From 73518dc169fc8d2b3cf8221d9244cba3d0e4bb16 Mon Sep 17 00:00:00 2001 From: Rebecca Mckeever Date: Sun, 9 Jun 2024 15:35:10 +0200 Subject: [PATCH] panvk: Add Valhall DescriptorSetLayout implementation Valhall descriptor model was loosely based on the Vulkan descriptor model. Provide a new implementation for the VkDescriptorSetLayout object that matches this new model. Co-developed-by: Mary Guillemard Co-developed-by: Boris Brezillon Reviewed-by: Boris Brezillon Reviewed-by: Mary Guillemard Part-of: --- src/panfrost/vulkan/meson.build | 4 +- .../valhall/panvk_descriptor_set_layout.h | 91 +++++++ .../valhall/panvk_vX_descriptor_set_layout.c | 225 ++++++++++++++++++ 3 files changed, 319 insertions(+), 1 deletion(-) create mode 100644 src/panfrost/vulkan/valhall/panvk_descriptor_set_layout.h create mode 100644 src/panfrost/vulkan/valhall/panvk_vX_descriptor_set_layout.c diff --git a/src/panfrost/vulkan/meson.build b/src/panfrost/vulkan/meson.build index 3a0f270d51b..2f413b6e792 100644 --- a/src/panfrost/vulkan/meson.build +++ b/src/panfrost/vulkan/meson.build @@ -66,7 +66,9 @@ bifrost_files = [ valhall_archs = [9, 10] valhall_inc_dir = ['valhall'] -valhall_files = [] +valhall_files = [ + 'valhall/panvk_vX_descriptor_set_layout.c', +] jm_archs = [6, 7] jm_inc_dir = ['jm'] diff --git a/src/panfrost/vulkan/valhall/panvk_descriptor_set_layout.h b/src/panfrost/vulkan/valhall/panvk_descriptor_set_layout.h new file mode 100644 index 00000000000..e29ed877c0c --- /dev/null +++ b/src/panfrost/vulkan/valhall/panvk_descriptor_set_layout.h @@ -0,0 +1,91 @@ +/* + * Copyright © 2024 Collabora Ltd. + * SPDX-License-Identifier: MIT + */ + +#ifndef PANVK_DESCRIPTOR_SET_LAYOUT_H +#define PANVK_DESCRIPTOR_SET_LAYOUT_H + +#ifndef PAN_ARCH +#error "PAN_ARCH must be defined" +#endif + +#include + +#include "vk_descriptor_set_layout.h" + +#include "util/mesa-blake3.h" + +#include "genxml/gen_macros.h" + +#define PANVK_DESCRIPTOR_SIZE 32 +#define MAX_SETS 4 +#define MAX_DYNAMIC_UNIFORM_BUFFERS 16 +#define MAX_DYNAMIC_STORAGE_BUFFERS 8 +#define MAX_PUSH_DESCS 32 +#define MAX_DYNAMIC_BUFFERS \ + (MAX_DYNAMIC_UNIFORM_BUFFERS + MAX_DYNAMIC_STORAGE_BUFFERS) + +struct panvk_descriptor_set_binding_layout { + VkDescriptorType type; + VkDescriptorBindingFlags flags; + unsigned desc_count; + unsigned desc_idx; + struct mali_sampler_packed *immutable_samplers; +}; + +struct panvk_descriptor_set_layout { + struct vk_descriptor_set_layout vk; + VkDescriptorSetLayoutCreateFlagBits flags; + blake3_hash hash; + unsigned desc_count; + unsigned dyn_buf_count; + + /* Number of bindings in this descriptor set */ + uint32_t binding_count; + + /* Bindings in this descriptor set */ + struct panvk_descriptor_set_binding_layout *bindings; +}; + +VK_DEFINE_NONDISP_HANDLE_CASTS(panvk_descriptor_set_layout, vk.base, + VkDescriptorSetLayout, + VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT) + +static inline const struct panvk_descriptor_set_layout * +to_panvk_descriptor_set_layout(const struct vk_descriptor_set_layout *layout) +{ + return container_of(layout, const struct panvk_descriptor_set_layout, vk); +} + +static inline const uint32_t +panvk_get_desc_stride(VkDescriptorType type) +{ + /* One descriptor for the sampler, and one for the texture. */ + return type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ? 2 : 1; +} + +static inline uint32_t +panvk_get_desc_index(const struct panvk_descriptor_set_binding_layout *layout, + uint32_t elem, VkDescriptorType type) +{ + assert(layout->type == type || + (layout->type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER && + (type == VK_DESCRIPTOR_TYPE_SAMPLER || + type == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE))); + + assert(layout->type != VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC && + layout->type != VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC); + + uint32_t desc_idx = + layout->desc_idx + elem * panvk_get_desc_stride(layout->type); + + /* In case of combined image-sampler, we put the texture first. */ + if (layout->type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER && + type == VK_DESCRIPTOR_TYPE_SAMPLER) + desc_idx++; + + return desc_idx; +} + +#endif /* PANVK_VX_DESCRIPTOR_SET_LAYOUT_H */ diff --git a/src/panfrost/vulkan/valhall/panvk_vX_descriptor_set_layout.c b/src/panfrost/vulkan/valhall/panvk_vX_descriptor_set_layout.c new file mode 100644 index 00000000000..e2e4b1c712c --- /dev/null +++ b/src/panfrost/vulkan/valhall/panvk_vX_descriptor_set_layout.c @@ -0,0 +1,225 @@ +/* + * Copyright © 2024 Collabora Ltd. + * SPDX-License-Identifier: MIT + */ + +#include +#include +#include +#include +#include + +#include "util/mesa-blake3.h" + +#include "vk_descriptor_update_template.h" +#include "vk_descriptors.h" +#include "vk_format.h" +#include "vk_log.h" +#include "vk_util.h" + +#include "util/bitset.h" + +#include "genxml/gen_macros.h" + +#include "panvk_descriptor_set_layout.h" +#include "panvk_device.h" +#include "panvk_entrypoints.h" +#include "panvk_macros.h" +#include "panvk_sampler.h" + +#define PANVK_MAX_DESCS_PER_SET (1 << 24) + +static bool +binding_has_immutable_samplers(const VkDescriptorSetLayoutBinding *binding) +{ + switch (binding->descriptorType) { + case VK_DESCRIPTOR_TYPE_SAMPLER: + case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: + return binding->pImmutableSamplers != NULL; + + default: + return false; + } +} + +static bool +is_sampler(const VkDescriptorSetLayoutBinding *binding) +{ + switch (binding->descriptorType) { + case VK_DESCRIPTOR_TYPE_SAMPLER: + case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: + return true; + default: + return false; + } +} + +static bool +is_texture(const VkDescriptorSetLayoutBinding *binding) +{ + switch (binding->descriptorType) { + case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: + case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: + case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: + case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: + return true; + default: + return false; + } +} + +VkResult +panvk_per_arch(CreateDescriptorSetLayout)( + VkDevice _device, const VkDescriptorSetLayoutCreateInfo *pCreateInfo, + const VkAllocationCallbacks *pAllocator, VkDescriptorSetLayout *pSetLayout) +{ + VK_FROM_HANDLE(panvk_device, device, _device); + VkDescriptorSetLayoutBinding *bindings = NULL; + unsigned num_bindings = 0; + VkResult result; + + unsigned immutable_sampler_count = 0; + for (uint32_t j = 0; j < pCreateInfo->bindingCount; j++) { + const VkDescriptorSetLayoutBinding *binding = &pCreateInfo->pBindings[j]; + num_bindings = MAX2(num_bindings, binding->binding + 1); + + /* From the Vulkan 1.1.97 spec for VkDescriptorSetLayoutBinding: + * + * "If descriptorType specifies a VK_DESCRIPTOR_TYPE_SAMPLER or + * VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER type descriptor, then + * pImmutableSamplers can be used to initialize a set of immutable + * samplers. [...] If descriptorType is not one of these descriptor + * types, then pImmutableSamplers is ignored. + * + * We need to be careful here and only parse pImmutableSamplers if we + * have one of the right descriptor types. + */ + if (binding_has_immutable_samplers(binding)) + immutable_sampler_count += binding->descriptorCount; + } + + if (pCreateInfo->bindingCount) { + result = vk_create_sorted_bindings(pCreateInfo->pBindings, + pCreateInfo->bindingCount, &bindings); + if (result != VK_SUCCESS) + return vk_error(device, result); + + num_bindings = bindings[pCreateInfo->bindingCount - 1].binding + 1; + } + + VK_MULTIALLOC(ma); + VK_MULTIALLOC_DECL(&ma, struct panvk_descriptor_set_layout, layout, 1); + VK_MULTIALLOC_DECL(&ma, struct panvk_descriptor_set_binding_layout, + binding_layouts, num_bindings); + VK_MULTIALLOC_DECL(&ma, struct mali_sampler_packed, samplers, + immutable_sampler_count); + + if (!vk_descriptor_set_layout_multizalloc(&device->vk, &ma)) { + free(bindings); + return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); + } + + layout->flags = pCreateInfo->flags; + layout->bindings = binding_layouts; + layout->binding_count = num_bindings; + + const VkDescriptorSetLayoutBindingFlagsCreateInfo *binding_flags_info = + vk_find_struct_const(pCreateInfo->pNext, + DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO); + + unsigned desc_idx = 0; + unsigned dyn_buf_idx = 0; + for (unsigned i = 0; i < pCreateInfo->bindingCount; i++) { + const VkDescriptorSetLayoutBinding *binding = &bindings[i]; + struct panvk_descriptor_set_binding_layout *binding_layout = + &layout->bindings[binding->binding]; + + if (binding->descriptorCount == 0) + continue; + + binding_layout->type = binding->descriptorType; + + if (binding_flags_info && binding_flags_info->bindingCount > 0) { + assert(binding_flags_info->bindingCount == pCreateInfo->bindingCount); + binding_layout->flags = binding_flags_info->pBindingFlags[i]; + } + + binding_layout->desc_count = binding->descriptorCount; + + if (binding_has_immutable_samplers(binding)) { + binding_layout->immutable_samplers = samplers; + samplers += binding->descriptorCount; + for (uint32_t j = 0; j < binding->descriptorCount; j++) { + VK_FROM_HANDLE(panvk_sampler, sampler, + binding->pImmutableSamplers[j]); + binding_layout->immutable_samplers[j] = sampler->desc; + } + } + + if (binding_layout->type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC || + binding_layout->type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC) { + binding_layout->desc_idx = dyn_buf_idx; + dyn_buf_idx += binding_layout->desc_count; + } else { + binding_layout->desc_idx = desc_idx; + desc_idx += panvk_get_desc_stride(binding_layout->type) * + binding_layout->desc_count; + } + } + + layout->desc_count = desc_idx; + layout->dyn_buf_count = dyn_buf_idx; + + struct mesa_blake3 hash_ctx; + _mesa_blake3_init(&hash_ctx); + + _mesa_blake3_update(&hash_ctx, &layout->binding_count, + sizeof(layout->binding_count)); + _mesa_blake3_update(&hash_ctx, &layout->desc_count, + sizeof(layout->desc_count)); + _mesa_blake3_update(&hash_ctx, &layout->dyn_buf_count, + sizeof(layout->dyn_buf_count)); + + for (uint32_t b = 0; b < num_bindings; b++) { + _mesa_blake3_update(&hash_ctx, &layout->bindings[b].type, + sizeof(layout->bindings[b].type)); + _mesa_blake3_update(&hash_ctx, &layout->bindings[b].flags, + sizeof(layout->bindings[b].flags)); + _mesa_blake3_update(&hash_ctx, &layout->bindings[b].desc_count, + sizeof(layout->bindings[b].desc_count)); + /* Immutable samplers are ignored for now */ + } + + _mesa_blake3_final(&hash_ctx, layout->hash); + + free(bindings); + *pSetLayout = panvk_descriptor_set_layout_to_handle(layout); + + return VK_SUCCESS; +} + +void +panvk_per_arch(GetDescriptorSetLayoutSupport)( + VkDevice _device, const VkDescriptorSetLayoutCreateInfo *pCreateInfo, + VkDescriptorSetLayoutSupport *pSupport) +{ + pSupport->supported = false; + + unsigned desc_count = 0, dyn_buf_count = 0; + for (unsigned i = 0; i < pCreateInfo->bindingCount; i++) { + const VkDescriptorSetLayoutBinding *binding = &pCreateInfo->pBindings[i]; + VkDescriptorType type = binding->descriptorType; + + if (type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC || + type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC) + dyn_buf_count += binding->descriptorCount; + else + desc_count += panvk_get_desc_stride(type) * binding->descriptorCount; + } + + if (desc_count > PANVK_MAX_DESCS_PER_SET || + dyn_buf_count > MAX_DYNAMIC_BUFFERS) + return; + + pSupport->supported = true; +}