From 59303584e3186d0cd4bb018822c0041b81d34f4b Mon Sep 17 00:00:00 2001 From: Faith Ekstrand Date: Fri, 7 Jun 2024 20:05:55 -0500 Subject: [PATCH] nvk: Align buffer descriptors In theory, the app is supposed to do this for us but this gives us a bit of protection against potential GPU faults. Part-of: --- src/nouveau/vulkan/nvk_cmd_buffer.c | 6 ++- src/nouveau/vulkan/nvk_cmd_draw.c | 4 -- src/nouveau/vulkan/nvk_descriptor_set.c | 66 +++++++++++++++++-------- src/nouveau/vulkan/nvk_descriptor_set.h | 4 +- 4 files changed, 52 insertions(+), 28 deletions(-) diff --git a/src/nouveau/vulkan/nvk_cmd_buffer.c b/src/nouveau/vulkan/nvk_cmd_buffer.c index 72c17da6d5e..c61f6a9a163 100644 --- a/src/nouveau/vulkan/nvk_cmd_buffer.c +++ b/src/nouveau/vulkan/nvk_cmd_buffer.c @@ -731,6 +731,7 @@ nvk_push_descriptor_set(struct nvk_cmd_buffer *cmd, struct nvk_descriptor_state *desc, const VkPushDescriptorSetInfoKHR *info) { + struct nvk_device *dev = nvk_cmd_buffer_device(cmd); VK_FROM_HANDLE(vk_pipeline_layout, pipeline_layout, info->layout); struct nvk_push_descriptor_set *push_set = @@ -741,7 +742,7 @@ nvk_push_descriptor_set(struct nvk_cmd_buffer *cmd, struct nvk_descriptor_set_layout *set_layout = vk_to_nvk_descriptor_set_layout(pipeline_layout->set_layouts[info->set]); - nvk_push_descriptor_set_update(push_set, set_layout, + nvk_push_descriptor_set_update(dev, push_set, set_layout, info->descriptorWriteCount, info->pDescriptorWrites); } @@ -887,6 +888,7 @@ nvk_CmdPushDescriptorSetWithTemplate2KHR( const VkPushDescriptorSetWithTemplateInfoKHR *pPushDescriptorSetWithTemplateInfo) { VK_FROM_HANDLE(nvk_cmd_buffer, cmd, commandBuffer); + struct nvk_device *dev = nvk_cmd_buffer_device(cmd); VK_FROM_HANDLE(vk_descriptor_update_template, template, pPushDescriptorSetWithTemplateInfo->descriptorUpdateTemplate); VK_FROM_HANDLE(vk_pipeline_layout, pipeline_layout, @@ -902,6 +904,6 @@ nvk_CmdPushDescriptorSetWithTemplate2KHR( struct nvk_descriptor_set_layout *set_layout = vk_to_nvk_descriptor_set_layout(pipeline_layout->set_layouts[pPushDescriptorSetWithTemplateInfo->set]); - nvk_push_descriptor_set_update_template(push_set, set_layout, template, + nvk_push_descriptor_set_update_template(dev, push_set, set_layout, template, pPushDescriptorSetWithTemplateInfo->pData); } diff --git a/src/nouveau/vulkan/nvk_cmd_draw.c b/src/nouveau/vulkan/nvk_cmd_draw.c index a1894b24cdc..648792aea04 100644 --- a/src/nouveau/vulkan/nvk_cmd_draw.c +++ b/src/nouveau/vulkan/nvk_cmd_draw.c @@ -2272,10 +2272,6 @@ nvk_mme_bind_cbuf_desc(struct mme_builder *b) } mme_if(b, ine, size, mme_zero()) { - uint32_t alignment = nvk_min_cbuf_alignment(b->devinfo); - mme_add_to(b, size, size, mme_imm(alignment - 1)); - mme_and_to(b, size, size, mme_imm(~(alignment - 1))); - /* size = max(size, NVK_MAX_CBUF_SIZE) */ assert(util_is_power_of_two_nonzero(NVK_MAX_CBUF_SIZE)); struct mme_value is_large = diff --git a/src/nouveau/vulkan/nvk_descriptor_set.c b/src/nouveau/vulkan/nvk_descriptor_set.c index c9cf2da6de2..2d14ceedbf8 100644 --- a/src/nouveau/vulkan/nvk_descriptor_set.c +++ b/src/nouveau/vulkan/nvk_descriptor_set.c @@ -125,39 +125,47 @@ write_storage_image_view_desc(struct nvk_descriptor_set *set, } static struct nvk_buffer_address -ubo_desc(const VkDescriptorBufferInfo *const info, +ubo_desc(struct nvk_physical_device *pdev, + const VkDescriptorBufferInfo *const info, uint32_t binding, uint32_t elem) { VK_FROM_HANDLE(nvk_buffer, buffer, info->buffer); + const uint32_t min_cbuf_alignment = nvk_min_cbuf_alignment(&pdev->info); - const struct nvk_addr_range addr_range = + struct nvk_addr_range addr_range = nvk_buffer_addr_range(buffer, info->offset, info->range); - assert(addr_range.range <= UINT32_MAX); + assert(addr_range.addr % min_cbuf_alignment == 0); + assert(addr_range.range <= NVK_MAX_CBUF_SIZE); + + addr_range.addr = align64(addr_range.addr, min_cbuf_alignment); + addr_range.range = align(addr_range.range, min_cbuf_alignment); return (struct nvk_buffer_address) { - .base_addr = addr_range.addr, - .size = addr_range.range, + .base_addr = align64(addr_range.addr, min_cbuf_alignment), + .size = align(addr_range.range, min_cbuf_alignment), }; } static void -write_ubo_desc(struct nvk_descriptor_set *set, +write_ubo_desc(struct nvk_physical_device *pdev, + struct nvk_descriptor_set *set, const VkDescriptorBufferInfo *const info, uint32_t binding, uint32_t elem) { - const struct nvk_buffer_address desc = ubo_desc(info, binding, elem); + const struct nvk_buffer_address desc = ubo_desc(pdev, info, binding, elem); write_desc(set, binding, elem, &desc, sizeof(desc)); } static void -write_dynamic_ubo_desc(struct nvk_descriptor_set *set, +write_dynamic_ubo_desc(struct nvk_physical_device *pdev, + struct nvk_descriptor_set *set, const VkDescriptorBufferInfo *const info, uint32_t binding, uint32_t elem) { const struct nvk_descriptor_set_binding_layout *binding_layout = &set->layout->binding[binding]; set->dynamic_buffers[binding_layout->dynamic_buffer_index + elem] = - ubo_desc(info, binding, elem); + ubo_desc(pdev, info, binding, elem); } static struct nvk_buffer_address @@ -166,16 +174,21 @@ ssbo_desc(const VkDescriptorBufferInfo *const info, { VK_FROM_HANDLE(nvk_buffer, buffer, info->buffer); - const struct nvk_addr_range addr_range = + struct nvk_addr_range addr_range = nvk_buffer_addr_range(buffer, info->offset, info->range); + assert(addr_range.addr % NVK_MIN_SSBO_ALIGNMENT == 0); assert(addr_range.range <= UINT32_MAX); + addr_range.addr = align64(addr_range.addr, NVK_MIN_SSBO_ALIGNMENT); + addr_range.range = align(addr_range.range, NVK_SSBO_BOUNDS_CHECK_ALIGNMENT); + return (struct nvk_buffer_address) { - .base_addr = addr_range.addr, - .size = addr_range.range, + .base_addr = align64(addr_range.addr, NVK_MIN_SSBO_ALIGNMENT), + .size = align(addr_range.range, NVK_SSBO_BOUNDS_CHECK_ALIGNMENT), }; } + static void write_ssbo_desc(struct nvk_descriptor_set *set, const VkDescriptorBufferInfo *const info, @@ -227,6 +240,9 @@ nvk_UpdateDescriptorSets(VkDevice device, uint32_t descriptorCopyCount, const VkCopyDescriptorSet *pDescriptorCopies) { + VK_FROM_HANDLE(nvk_device, dev, device); + struct nvk_physical_device *pdev = nvk_device_physical(dev); + for (uint32_t w = 0; w < descriptorWriteCount; w++) { const VkWriteDescriptorSet *write = &pDescriptorWrites[w]; VK_FROM_HANDLE(nvk_descriptor_set, set, write->dstSet); @@ -262,7 +278,7 @@ nvk_UpdateDescriptorSets(VkDevice device, case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: for (uint32_t j = 0; j < write->descriptorCount; j++) { - write_ubo_desc(set, write->pBufferInfo + j, + write_ubo_desc(pdev, set, write->pBufferInfo + j, write->dstBinding, write->dstArrayElement + j); } @@ -278,7 +294,7 @@ nvk_UpdateDescriptorSets(VkDevice device, case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: for (uint32_t j = 0; j < write->descriptorCount; j++) { - write_dynamic_ubo_desc(set, write->pBufferInfo + j, + write_dynamic_ubo_desc(pdev, set, write->pBufferInfo + j, write->dstBinding, write->dstArrayElement + j); } @@ -352,11 +368,14 @@ nvk_UpdateDescriptorSets(VkDevice device, } void -nvk_push_descriptor_set_update(struct nvk_push_descriptor_set *push_set, +nvk_push_descriptor_set_update(struct nvk_device *dev, + struct nvk_push_descriptor_set *push_set, struct nvk_descriptor_set_layout *layout, uint32_t write_count, const VkWriteDescriptorSet *writes) { + struct nvk_physical_device *pdev = nvk_device_physical(dev); + assert(layout->non_variable_descriptor_buffer_size < sizeof(push_set->data)); struct nvk_descriptor_set set = { .layout = layout, @@ -399,7 +418,7 @@ nvk_push_descriptor_set_update(struct nvk_push_descriptor_set *push_set, case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: for (uint32_t j = 0; j < write->descriptorCount; j++) { - write_ubo_desc(&set, write->pBufferInfo + j, + write_ubo_desc(pdev, &set, write->pBufferInfo + j, write->dstBinding, write->dstArrayElement + j); } @@ -732,10 +751,13 @@ nvk_ResetDescriptorPool(VkDevice device, } static void -nvk_descriptor_set_write_template(struct nvk_descriptor_set *set, +nvk_descriptor_set_write_template(struct nvk_device *dev, + struct nvk_descriptor_set *set, const struct vk_descriptor_update_template *template, const void *data) { + struct nvk_physical_device *pdev = nvk_device_physical(dev); + for (uint32_t i = 0; i < template->entry_count; i++) { const struct vk_descriptor_template_entry *entry = &template->entries[i]; @@ -784,7 +806,7 @@ nvk_descriptor_set_write_template(struct nvk_descriptor_set *set, const VkDescriptorBufferInfo *info = data + entry->offset + j * entry->stride; - write_ubo_desc(set, info, + write_ubo_desc(pdev, set, info, entry->binding, entry->array_element + j); } @@ -806,7 +828,7 @@ nvk_descriptor_set_write_template(struct nvk_descriptor_set *set, const VkDescriptorBufferInfo *info = data + entry->offset + j * entry->stride; - write_dynamic_ubo_desc(set, info, + write_dynamic_ubo_desc(pdev, set, info, entry->binding, entry->array_element + j); } @@ -843,15 +865,17 @@ nvk_UpdateDescriptorSetWithTemplate(VkDevice device, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const void *pData) { + VK_FROM_HANDLE(nvk_device, dev, device); VK_FROM_HANDLE(nvk_descriptor_set, set, descriptorSet); VK_FROM_HANDLE(vk_descriptor_update_template, template, descriptorUpdateTemplate); - nvk_descriptor_set_write_template(set, template, pData); + nvk_descriptor_set_write_template(dev, set, template, pData); } void nvk_push_descriptor_set_update_template( + struct nvk_device *dev, struct nvk_push_descriptor_set *push_set, struct nvk_descriptor_set_layout *layout, const struct vk_descriptor_update_template *template, @@ -862,5 +886,5 @@ nvk_push_descriptor_set_update_template( .size = sizeof(push_set->data), .mapped_ptr = push_set->data, }; - nvk_descriptor_set_write_template(&tmp_set, template, data); + nvk_descriptor_set_write_template(dev, &tmp_set, template, data); } diff --git a/src/nouveau/vulkan/nvk_descriptor_set.h b/src/nouveau/vulkan/nvk_descriptor_set.h index c02c83c71ae..c0af30a912d 100644 --- a/src/nouveau/vulkan/nvk_descriptor_set.h +++ b/src/nouveau/vulkan/nvk_descriptor_set.h @@ -110,13 +110,15 @@ struct nvk_push_descriptor_set { }; void -nvk_push_descriptor_set_update(struct nvk_push_descriptor_set *push_set, +nvk_push_descriptor_set_update(struct nvk_device *dev, + struct nvk_push_descriptor_set *push_set, struct nvk_descriptor_set_layout *layout, uint32_t write_count, const VkWriteDescriptorSet *writes); void nvk_push_descriptor_set_update_template( + struct nvk_device *dev, struct nvk_push_descriptor_set *push_set, struct nvk_descriptor_set_layout *layout, const struct vk_descriptor_update_template *template,