radv: implement VK_KHR_descriptor_update_template
authorFredrik Höglund <fredrik@kde.org>
Wed, 29 Mar 2017 17:19:47 +0000 (19:19 +0200)
committerFredrik Höglund <fredrik@kde.org>
Thu, 6 Apr 2017 22:54:46 +0000 (00:54 +0200)
All offsets and strides are precomputed by
radv_CreateDescriptorUpdateTemplateKHR and stored in the template.

v2: Move the new struct declarations from radv_descriptor_set.h
    to radv_private.h (Bas)

Signed-off-by: Fredrik Höglund <fredrik@kde.org>
Reviewed-by: Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
src/amd/vulkan/radv_cmd_buffer.c
src/amd/vulkan/radv_descriptor_set.c
src/amd/vulkan/radv_device.c
src/amd/vulkan/radv_entrypoints_gen.py
src/amd/vulkan/radv_private.h

index 46c139a8fcbc5f9c3465ab892b5bb22e31252c76..992dc123a21a5380c117f364851b081c1bbc91e1 100644 (file)
@@ -1988,6 +1988,30 @@ void radv_CmdPushDescriptorSetKHR(
        cmd_buffer->state.push_descriptors_dirty = true;
 }
 
+void radv_CmdPushDescriptorSetWithTemplateKHR(
+       VkCommandBuffer                             commandBuffer,
+       VkDescriptorUpdateTemplateKHR               descriptorUpdateTemplate,
+       VkPipelineLayout                            _layout,
+       uint32_t                                    set,
+       const void*                                 pData)
+{
+       RADV_FROM_HANDLE(radv_cmd_buffer, cmd_buffer, commandBuffer);
+       RADV_FROM_HANDLE(radv_pipeline_layout, layout, _layout);
+       struct radv_descriptor_set *push_set = &cmd_buffer->push_descriptors.set;
+
+       assert(layout->set[set].layout->flags & VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR);
+
+       if (!radv_init_push_descriptor_set(cmd_buffer, push_set, layout->set[set].layout))
+               return;
+
+       radv_update_descriptor_set_with_template(cmd_buffer->device, cmd_buffer, push_set,
+                                                descriptorUpdateTemplate, pData);
+
+       cmd_buffer->state.descriptors[set] = push_set;
+       cmd_buffer->state.descriptors_dirty |= (1 << set);
+       cmd_buffer->state.push_descriptors_dirty = true;
+}
+
 void radv_CmdPushConstants(VkCommandBuffer commandBuffer,
                           VkPipelineLayout layout,
                           VkShaderStageFlags stageFlags,
index 0ff9aa206d2d4a1e2ab323f8070627285e42b272..c2bf006f34298a4bf60177858d9f0b7230c19478 100644 (file)
@@ -742,3 +742,166 @@ void radv_UpdateDescriptorSets(
        radv_update_descriptor_sets(device, NULL, VK_NULL_HANDLE, descriptorWriteCount, pDescriptorWrites,
                                    descriptorCopyCount, pDescriptorCopies);
 }
+
+VkResult radv_CreateDescriptorUpdateTemplateKHR(VkDevice _device,
+                                                const VkDescriptorUpdateTemplateCreateInfoKHR *pCreateInfo,
+                                                const VkAllocationCallbacks *pAllocator,
+                                                VkDescriptorUpdateTemplateKHR *pDescriptorUpdateTemplate)
+{
+       RADV_FROM_HANDLE(radv_device, device, _device);
+       RADV_FROM_HANDLE(radv_descriptor_set_layout, set_layout, pCreateInfo->descriptorSetLayout);
+       const uint32_t entry_count = pCreateInfo->descriptorUpdateEntryCount;
+       const size_t size = sizeof(struct radv_descriptor_update_template) +
+               sizeof(struct radv_descriptor_update_template_entry) * entry_count;
+       struct radv_descriptor_update_template *templ;
+       uint32_t i;
+
+       templ = vk_alloc2(&device->alloc, pAllocator, size, 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+       if (!templ)
+               return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
+
+       templ->entry_count = entry_count;
+
+       for (i = 0; i < entry_count; i++) {
+               const VkDescriptorUpdateTemplateEntryKHR *entry = &pCreateInfo->pDescriptorUpdateEntries[i];
+               const struct radv_descriptor_set_binding_layout *binding_layout =
+                       set_layout->binding + entry->dstBinding;
+               const uint32_t buffer_offset = binding_layout->buffer_offset +
+                       binding_layout->buffer_count * entry->dstArrayElement;
+               uint32_t *immutable_samplers = NULL;
+               uint16_t dst_offset;
+               uint16_t dst_stride;
+
+               /* dst_offset is an offset into dynamic_descriptors when the descriptor
+                  is dynamic, and an offset into mapped_ptr otherwise */
+               switch (entry->descriptorType) {
+               case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
+               case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
+                       assert(pCreateInfo->templateType == VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR);
+                       dst_offset = binding_layout->dynamic_offset_offset + entry->dstArrayElement;
+                       dst_stride = 0; /* Not used */
+                       break;
+               default:
+                       switch (entry->descriptorType) {
+                       case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
+                       case VK_DESCRIPTOR_TYPE_SAMPLER:
+                               /* Immutable samplers are copied into push descriptors when they are pushed */
+                               if (pCreateInfo->templateType == VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR &&
+                                   binding_layout->immutable_samplers && !binding_layout->immutable_samplers_equal)
+                                       immutable_samplers = binding_layout->immutable_samplers + entry->dstArrayElement * 4;
+                               break;
+                       default:
+                               break;
+                       }
+                       dst_offset = binding_layout->offset / 4 + binding_layout->size * entry->dstArrayElement / 4;
+                       dst_stride = binding_layout->size / 4;
+                       break;
+               }
+
+               templ->entry[i] = (struct radv_descriptor_update_template_entry) {
+                       .descriptor_type = entry->descriptorType,
+                       .descriptor_count = entry->descriptorCount,
+                       .src_offset = entry->offset,
+                       .src_stride = entry->stride,
+                       .dst_offset = dst_offset,
+                       .dst_stride = dst_stride,
+                       .buffer_offset = buffer_offset,
+                       .buffer_count = binding_layout->buffer_count,
+                       .has_sampler = !binding_layout->immutable_samplers,
+                       .immutable_samplers = immutable_samplers
+               };
+       }
+
+       *pDescriptorUpdateTemplate = radv_descriptor_update_template_to_handle(templ);
+       return VK_SUCCESS;
+}
+
+void radv_DestroyDescriptorUpdateTemplateKHR(VkDevice _device,
+                                             VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate,
+                                             const VkAllocationCallbacks *pAllocator)
+{
+       RADV_FROM_HANDLE(radv_device, device, _device);
+       RADV_FROM_HANDLE(radv_descriptor_update_template, templ, descriptorUpdateTemplate);
+
+       if (!templ)
+               return;
+
+       vk_free2(&device->alloc, pAllocator, templ);
+}
+
+void radv_update_descriptor_set_with_template(struct radv_device *device,
+                                              struct radv_cmd_buffer *cmd_buffer,
+                                              struct radv_descriptor_set *set,
+                                              VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate,
+                                              const void *pData)
+{
+       RADV_FROM_HANDLE(radv_descriptor_update_template, templ, descriptorUpdateTemplate);
+       uint32_t i;
+
+       for (i = 0; i < templ->entry_count; ++i) {
+               struct radeon_winsys_bo **buffer_list = set->descriptors + templ->entry[i].buffer_offset;
+               uint32_t *pDst = set->mapped_ptr + templ->entry[i].dst_offset;
+               const uint8_t *pSrc = ((const uint8_t *) pData) + templ->entry[i].src_offset;
+               uint32_t j;
+
+               for (j = 0; j < templ->entry[i].descriptor_count; ++j) {
+                       switch (templ->entry[i].descriptor_type) {
+                       case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
+                       case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: {
+                               const unsigned idx = templ->entry[i].dst_offset + j;
+                               assert(!(set->layout->flags & VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR));
+                               write_dynamic_buffer_descriptor(device, set->dynamic_descriptors + idx,
+                                                               buffer_list, (struct VkDescriptorBufferInfo *) pSrc);
+                               break;
+                       }
+                       case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
+                       case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
+                               write_buffer_descriptor(device, cmd_buffer, pDst, buffer_list,
+                                                       (struct VkDescriptorBufferInfo *) pSrc);
+                               break;
+                       case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
+                       case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
+                               write_texel_buffer_descriptor(device, cmd_buffer, pDst, buffer_list,
+                                                             *(VkBufferView *) pSrc);
+                               break;
+                       case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
+                       case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
+                       case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
+                               write_image_descriptor(device, cmd_buffer, pDst, buffer_list,
+                                                      (struct VkDescriptorImageInfo *) pSrc);
+                               break;
+                       case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
+                               write_combined_image_sampler_descriptor(device, cmd_buffer, pDst, buffer_list,
+                                                                       (struct VkDescriptorImageInfo *) pSrc,
+                                                                       templ->entry[i].has_sampler);
+                               if (templ->entry[i].immutable_samplers)
+                                       memcpy(pDst + 16, templ->entry[i].immutable_samplers + 4 * j, 16);
+                               break;
+                       case VK_DESCRIPTOR_TYPE_SAMPLER:
+                               if (templ->entry[i].has_sampler)
+                                       write_sampler_descriptor(device, pDst,
+                                                                (struct VkDescriptorImageInfo *) pSrc);
+                               else if (templ->entry[i].immutable_samplers)
+                                       memcpy(pDst, templ->entry[i].immutable_samplers + 4 * j, 16);
+                               break;
+                       default:
+                               unreachable("unimplemented descriptor type");
+                               break;
+                       }
+                       pSrc += templ->entry[i].src_stride;
+                       pDst += templ->entry[i].dst_stride;
+                       buffer_list += templ->entry[i].buffer_count;
+               }
+       }
+}
+
+void radv_UpdateDescriptorSetWithTemplateKHR(VkDevice _device,
+                                             VkDescriptorSet descriptorSet,
+                                             VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate,
+                                             const void *pData)
+{
+       RADV_FROM_HANDLE(radv_device, device, _device);
+       RADV_FROM_HANDLE(radv_descriptor_set, set, descriptorSet);
+
+       radv_update_descriptor_set_with_template(device, NULL, set, descriptorUpdateTemplate, pData);
+}
index 059c013f3599346b6f3e5a362bebe25ed29ca6ef..9e8faa3da9aba5c69f3a6a08ac060bd41da1095a 100644 (file)
@@ -91,6 +91,10 @@ static const VkExtensionProperties instance_extensions[] = {
 };
 
 static const VkExtensionProperties common_device_extensions[] = {
+       {
+               .extensionName = VK_KHR_DESCRIPTOR_UPDATE_TEMPLATE_EXTENSION_NAME,
+               .specVersion = 1,
+       },
        {
                .extensionName = VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME,
                .specVersion = 1,
index 4651c63dcf84e3b6a71d6abee6fb1651dabce773..3474c789ea830abe791cf317e01969ad642e698b 100644 (file)
@@ -30,6 +30,7 @@ max_api_version = 1.0
 supported_extensions = [
    'VK_AMD_draw_indirect_count',
    'VK_NV_dedicated_allocation',
+   'VK_KHR_descriptor_update_template',
    'VK_KHR_get_physical_device_properties2',
    'VK_KHR_incremental_present',
    'VK_KHR_maintenance1',
index e39819fff3e18035f568f0607895f5fb44871c4f..580c1197e64f9adb974a2c493b0c41984cdb7e5e 100644 (file)
@@ -565,6 +565,37 @@ struct radv_descriptor_pool {
        struct list_head vram_list;
 };
 
+struct radv_descriptor_update_template_entry {
+       VkDescriptorType descriptor_type;
+
+       /* The number of descriptors to update */
+       uint16_t descriptor_count;
+
+       /* Into mapped_ptr or dynamic_descriptors, in units of the respective array */
+       uint16_t dst_offset;
+
+       /* In dwords. Not valid/used for dynamic descriptors */
+       uint16_t dst_stride;
+
+       uint16_t buffer_offset;
+       uint16_t buffer_count;
+
+       /* Only valid for combined image samplers and samplers */
+       uint16_t has_sampler;
+
+       /* In bytes */
+       size_t src_offset;
+       size_t src_stride;
+
+       /* For push descriptors */
+       uint32_t *immutable_samplers;
+};
+
+struct radv_descriptor_update_template {
+       uint32_t entry_count;
+       struct radv_descriptor_update_template_entry entry[0];
+};
+
 struct radv_buffer {
        struct radv_device *                          device;
        VkDeviceSize                                 size;
@@ -1363,6 +1394,13 @@ radv_update_descriptor_sets(struct radv_device *device,
                             uint32_t descriptorCopyCount,
                             const VkCopyDescriptorSet *pDescriptorCopies);
 
+void
+radv_update_descriptor_set_with_template(struct radv_device *device,
+                                         struct radv_cmd_buffer *cmd_buffer,
+                                         struct radv_descriptor_set *set,
+                                         VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate,
+                                         const void *pData);
+
 void radv_initialise_cmask(struct radv_cmd_buffer *cmd_buffer,
                           struct radv_image *image, uint32_t value);
 void radv_initialize_dcc(struct radv_cmd_buffer *cmd_buffer,
@@ -1419,6 +1457,7 @@ RADV_DEFINE_NONDISP_HANDLE_CASTS(radv_buffer_view, VkBufferView)
 RADV_DEFINE_NONDISP_HANDLE_CASTS(radv_descriptor_pool, VkDescriptorPool)
 RADV_DEFINE_NONDISP_HANDLE_CASTS(radv_descriptor_set, VkDescriptorSet)
 RADV_DEFINE_NONDISP_HANDLE_CASTS(radv_descriptor_set_layout, VkDescriptorSetLayout)
+RADV_DEFINE_NONDISP_HANDLE_CASTS(radv_descriptor_update_template, VkDescriptorUpdateTemplateKHR)
 RADV_DEFINE_NONDISP_HANDLE_CASTS(radv_device_memory, VkDeviceMemory)
 RADV_DEFINE_NONDISP_HANDLE_CASTS(radv_fence, VkFence)
 RADV_DEFINE_NONDISP_HANDLE_CASTS(radv_event, VkEvent)