From cdf24f067e9ada5651e08634d0d315b5f1e068fd Mon Sep 17 00:00:00 2001 From: Rebecca Mckeever Date: Tue, 28 Jan 2025 14:23:29 -0800 Subject: [PATCH] panvk: Use multiple sampler planes and one texture descriptor per plane Multiple sampler planes (one for luma, one for chroma) are needed to support CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT. Multiple texture descriptors (one per plane) are needed for the downsampling in nir_vk_lower_ycbcr_tex() to work in panvk. Signed-off-by: Rebecca Mckeever Reviewed-by: Boris Brezillon Part-of: --- .../vulkan/panvk_descriptor_set_layout.h | 87 ++++++++++--- src/panfrost/vulkan/panvk_image_view.h | 3 +- src/panfrost/vulkan/panvk_sampler.h | 8 +- src/panfrost/vulkan/panvk_vX_cmd_fb_preload.c | 2 +- src/panfrost/vulkan/panvk_vX_descriptor_set.c | 80 +++++++----- .../vulkan/panvk_vX_descriptor_set_layout.c | 91 ++++++++++++- src/panfrost/vulkan/panvk_vX_image_view.c | 37 +++++- .../vulkan/panvk_vX_nir_lower_descriptors.c | 123 ++++++++++++------ src/panfrost/vulkan/panvk_vX_sampler.c | 22 +++- 9 files changed, 343 insertions(+), 110 deletions(-) diff --git a/src/panfrost/vulkan/panvk_descriptor_set_layout.h b/src/panfrost/vulkan/panvk_descriptor_set_layout.h index b17bdde78f3..6ce810943f0 100644 --- a/src/panfrost/vulkan/panvk_descriptor_set_layout.h +++ b/src/panfrost/vulkan/panvk_descriptor_set_layout.h @@ -37,6 +37,17 @@ struct panvk_descriptor_set_binding_layout { VkDescriptorBindingFlags flags; unsigned desc_count; unsigned desc_idx; + + /* if textures are present, maximum number of planes required per texture; + * 0 otherwise + */ + unsigned textures_per_desc; + + /* if samplers are present, maximum number of planes required per sampler; + * 0 otherwise + */ + unsigned samplers_per_desc; + struct panvk_sampler **immutable_samplers; }; @@ -66,30 +77,72 @@ to_panvk_descriptor_set_layout(const struct vk_descriptor_set_layout *layout) static inline const uint32_t panvk_get_desc_stride(const struct panvk_descriptor_set_binding_layout *layout) { - /* One descriptor for the sampler, and one for the texture. */ - return layout->type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ? 2 : 1; + /* One descriptor for each sampler plane, and one for each texture. */ + return layout->type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER + ? layout->textures_per_desc + layout->samplers_per_desc : 1; +} + +struct panvk_subdesc_info { + VkDescriptorType type; + uint8_t plane; +}; + +#define IMPLICIT_SUBDESC_TYPE (VkDescriptorType)-1 +#define NO_SUBDESC (struct panvk_subdesc_info){ \ + .type = IMPLICIT_SUBDESC_TYPE, \ +} +#define TEX_SUBDESC(__plane) (struct panvk_subdesc_info){ \ + .type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, \ + .plane = __plane, \ +} +#define SAMPLER_SUBDESC(__plane) (struct panvk_subdesc_info){ \ + .type = VK_DESCRIPTOR_TYPE_SAMPLER, \ + .plane = __plane, \ +} + +static inline struct panvk_subdesc_info +get_tex_subdesc_info(VkDescriptorType type, uint8_t plane) +{ + return (type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) + ? TEX_SUBDESC(plane) : NO_SUBDESC; +} + +static inline struct panvk_subdesc_info +get_sampler_subdesc_info(VkDescriptorType type, uint8_t plane) +{ + return (type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) + ? SAMPLER_SUBDESC(plane) : NO_SUBDESC; +} + +static inline uint32_t +get_subdesc_idx(const struct panvk_descriptor_set_binding_layout *layout, + struct panvk_subdesc_info subdesc) +{ + assert((subdesc.type == IMPLICIT_SUBDESC_TYPE) || + (layout->type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER && + (subdesc.type == VK_DESCRIPTOR_TYPE_SAMPLER || + subdesc.type == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE))); + + uint32_t subdesc_idx = 0; + + /* In case of combined image-sampler, we put the texture first. */ + if (subdesc.type == VK_DESCRIPTOR_TYPE_SAMPLER) + subdesc_idx += layout->textures_per_desc + + MIN2(subdesc.plane, layout->samplers_per_desc - 1); + else if (subdesc.type == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE) + subdesc_idx += MIN2(subdesc.plane, layout->textures_per_desc - 1); + + return subdesc_idx; } static inline uint32_t panvk_get_desc_index(const struct panvk_descriptor_set_binding_layout *layout, - uint32_t elem, VkDescriptorType type) + uint32_t elem, struct panvk_subdesc_info subdesc) { - assert(layout->type == type || - (layout->type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER && - (type == VK_DESCRIPTOR_TYPE_SAMPLER || - type == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE))); - assert(!vk_descriptor_type_is_dynamic(layout->type)); - uint32_t desc_idx = - layout->desc_idx + elem * panvk_get_desc_stride(layout); - - /* 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; + return layout->desc_idx + elem * panvk_get_desc_stride(layout) + + get_subdesc_idx(layout, subdesc); } #endif /* PANVK_VX_DESCRIPTOR_SET_LAYOUT_H */ diff --git a/src/panfrost/vulkan/panvk_image_view.h b/src/panfrost/vulkan/panvk_image_view.h index 5613d3bfef6..07e22b86d9c 100644 --- a/src/panfrost/vulkan/panvk_image_view.h +++ b/src/panfrost/vulkan/panvk_image_view.h @@ -17,6 +17,7 @@ #include "pan_texture.h" #include "genxml/gen_macros.h" +#include "panvk_image.h" struct panvk_priv_bo; @@ -29,7 +30,7 @@ struct panvk_image_view { struct { union { - struct mali_texture_packed tex; + struct mali_texture_packed tex[PANVK_MAX_PLANES]; struct { struct mali_texture_packed tex; struct mali_texture_packed other_aspect_tex; diff --git a/src/panfrost/vulkan/panvk_sampler.h b/src/panfrost/vulkan/panvk_sampler.h index 4b653516bb9..78c3c4387a4 100644 --- a/src/panfrost/vulkan/panvk_sampler.h +++ b/src/panfrost/vulkan/panvk_sampler.h @@ -14,9 +14,15 @@ #include "vk_sampler.h" +/* We use 2 sampler planes for YCbCr conversion with different filters for + * the Y and CbCr components. + */ +#define PANVK_MAX_DESCS_PER_SAMPLER 2 + struct panvk_sampler { struct vk_sampler vk; - struct mali_sampler_packed desc; + struct mali_sampler_packed descs[PANVK_MAX_DESCS_PER_SAMPLER]; + uint8_t desc_count; }; VK_DEFINE_NONDISP_HANDLE_CASTS(panvk_sampler, vk.base, VkSampler, diff --git a/src/panfrost/vulkan/panvk_vX_cmd_fb_preload.c b/src/panfrost/vulkan/panvk_vX_cmd_fb_preload.c index c400f17b71b..6302f1c240a 100644 --- a/src/panfrost/vulkan/panvk_vX_cmd_fb_preload.c +++ b/src/panfrost/vulkan/panvk_vX_cmd_fb_preload.c @@ -254,7 +254,7 @@ fill_textures(struct panvk_cmd_buffer *cmdbuf, struct pan_fb_info *fbinfo, cmdbuf->state.gfx.render.color_attachments.iviews[i]; if (iview) - textures[i] = iview->descs.tex; + textures[i] = iview->descs.tex[0]; else textures[i] = (struct mali_texture_packed){0}; } diff --git a/src/panfrost/vulkan/panvk_vX_descriptor_set.c b/src/panfrost/vulkan/panvk_vX_descriptor_set.c index 4945c436657..92232548e90 100644 --- a/src/panfrost/vulkan/panvk_vX_descriptor_set.c +++ b/src/panfrost/vulkan/panvk_vX_descriptor_set.c @@ -35,23 +35,23 @@ static void * get_desc_slot_ptr(struct panvk_descriptor_set *set, uint32_t binding, - uint32_t elem, VkDescriptorType type) + uint32_t elem, struct panvk_subdesc_info subdesc) { const struct panvk_descriptor_set_binding_layout *binding_layout = &set->layout->bindings[binding]; - uint32_t offset = panvk_get_desc_index(binding_layout, elem, type); + uint32_t offset = panvk_get_desc_index(binding_layout, elem, subdesc); assert(offset < set->layout->desc_count); return (char *)set->descs.host + offset * PANVK_DESCRIPTOR_SIZE; } -#define write_desc(set, binding, elem, desc, type) \ +#define write_desc(set, binding, elem, desc, subdesc) \ do { \ static_assert(sizeof(*(desc)) == PANVK_DESCRIPTOR_SIZE, \ "wrong descriptor size"); \ - void *__dst = get_desc_slot_ptr(set, binding, elem, type); \ + void *__dst = get_desc_slot_ptr(set, binding, elem, subdesc); \ memcpy(__dst, (desc), PANVK_DESCRIPTOR_SIZE); \ } while (0) @@ -66,19 +66,22 @@ write_sampler_desc(struct panvk_descriptor_set *set, if (binding_layout->immutable_samplers && !write_immutable) return; - const struct mali_sampler_packed *sampler_desc; + struct panvk_sampler *sampler; if (binding_layout->immutable_samplers) { - sampler_desc = &binding_layout->immutable_samplers[elem]->desc; + sampler = binding_layout->immutable_samplers[elem]; } else { - struct panvk_sampler *sampler = panvk_sampler_from_handle( + sampler = panvk_sampler_from_handle( pImageInfo ? pImageInfo->sampler : VK_NULL_HANDLE); - - sampler_desc = sampler ? &sampler->desc : NULL; } - if (sampler_desc) - write_desc(set, binding, elem, sampler_desc, VK_DESCRIPTOR_TYPE_SAMPLER); + if (!sampler) + return; + + for (uint8_t plane = 0; plane < sampler->desc_count; plane++) { + write_desc(set, binding, elem, &sampler->descs[plane], + get_sampler_subdesc_info(binding_layout->type, plane)); + } } static void @@ -89,14 +92,19 @@ write_image_view_desc(struct panvk_descriptor_set *set, if (pImageInfo && pImageInfo->imageView != VK_NULL_HANDLE) { VK_FROM_HANDLE(panvk_image_view, view, pImageInfo->imageView); + uint8_t plane_count = vk_format_get_plane_count(view->vk.format); + for (uint8_t plane = 0; plane < plane_count; plane++) { + struct panvk_subdesc_info subdesc = get_tex_subdesc_info(type, plane); #if PAN_ARCH <= 7 - if (type == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) - write_desc(set, binding, elem, &view->descs.img_attrib_buf, type); - else - write_desc(set, binding, elem, &view->descs.tex, type); + if (type == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) + write_desc(set, binding, elem, &view->descs.img_attrib_buf, + NO_SUBDESC); + else + write_desc(set, binding, elem, &view->descs.tex[plane], subdesc); #else - write_desc(set, binding, elem, &view->descs.tex, type); + write_desc(set, binding, elem, &view->descs.tex[plane], subdesc); #endif + } } } @@ -116,7 +124,7 @@ write_buffer_desc(struct panvk_descriptor_set *set, .size = range, }; - write_desc(set, binding, elem, &desc, type); + write_desc(set, binding, elem, &desc, NO_SUBDESC); } else { struct { struct mali_uniform_buffer_packed ubo; @@ -128,7 +136,7 @@ write_buffer_desc(struct panvk_descriptor_set *set, cfg.entries = DIV_ROUND_UP(range, 16); } - write_desc(set, binding, elem, &padded_desc, type); + write_desc(set, binding, elem, &padded_desc, NO_SUBDESC); } #else struct mali_buffer_packed desc; @@ -137,7 +145,7 @@ write_buffer_desc(struct panvk_descriptor_set *set, cfg.address = panvk_buffer_gpu_ptr(buffer, info->offset); cfg.size = range; } - write_desc(set, binding, elem, &desc, type); + write_desc(set, binding, elem, &desc, NO_SUBDESC); #endif } @@ -170,11 +178,12 @@ write_buffer_view_desc(struct panvk_descriptor_set *set, #if PAN_ARCH <= 7 if (type == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER) - write_desc(set, binding, elem, &view->descs.img_attrib_buf, type); + write_desc(set, binding, elem, &view->descs.img_attrib_buf, + NO_SUBDESC); else - write_desc(set, binding, elem, &view->descs.tex, type); + write_desc(set, binding, elem, &view->descs.tex, NO_SUBDESC); #else - write_desc(set, binding, elem, &view->descs.tex, type); + write_desc(set, binding, elem, &view->descs.tex, NO_SUBDESC); #endif } } @@ -242,6 +251,8 @@ panvk_per_arch(CreateDescriptorPool)( if (!vk_descriptor_type_is_dynamic(pCreateInfo->pPoolSizes[i].type)) { const struct panvk_descriptor_set_binding_layout layout = { .type = pCreateInfo->pPoolSizes[i].type, + .textures_per_desc = PANVK_MAX_PLANES, + .samplers_per_desc = PANVK_MAX_DESCS_PER_SAMPLER, }; desc_count += panvk_get_desc_stride(&layout) * pCreateInfo->pPoolSizes[i].descriptorCount; @@ -307,8 +318,14 @@ desc_set_write_immutable_samplers(struct panvk_descriptor_set *set, array_size = variable_count; for (uint32_t j = 0; j < array_size; j++) { - write_desc(set, b, j, &layout->bindings[b].immutable_samplers[j]->desc, - VK_DESCRIPTOR_TYPE_SAMPLER); + struct panvk_sampler *sampler = + layout->bindings[b].immutable_samplers[j]; + for (uint8_t plane = 0; plane < sampler->desc_count; plane++) { + write_desc(set, b, j, + &sampler->descs[plane], + get_sampler_subdesc_info(layout->bindings[b].type, + plane)); + } } } } @@ -459,12 +476,12 @@ panvk_per_arch(descriptor_set_write)(struct panvk_descriptor_set *set, case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: for (uint32_t j = 0; j < write->descriptorCount; j++) { + write_image_view_desc(set, write->pImageInfo + j, write->dstBinding, + write->dstArrayElement + j, + write->descriptorType); write_sampler_desc(set, write->pImageInfo + j, write->dstBinding, write->dstArrayElement + j, write_immutable_samplers); - write_image_view_desc(set, write->pImageInfo + j, write->dstBinding, - write->dstArrayElement + j, - VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE); } break; @@ -536,10 +553,10 @@ panvk_descriptor_set_copy(const VkCopyDescriptorSet *copy) for (uint32_t i = 0; i < copy->descriptorCount; i++) { void *dst = get_desc_slot_ptr(dst_set, copy->dstBinding, copy->dstArrayElement + i, - dst_binding_layout->type); + NO_SUBDESC); const void *src = get_desc_slot_ptr(src_set, copy->srcBinding, copy->srcArrayElement + i, - src_binding_layout->type); + NO_SUBDESC); memcpy(dst, src, PANVK_DESCRIPTOR_SIZE * @@ -609,12 +626,11 @@ panvk_per_arch(descriptor_set_write_template)( for (uint32_t j = 0; j < entry->array_count; j++) { const VkDescriptorImageInfo *info = data + entry->offset + j * entry->stride; + write_image_view_desc(set, info, entry->binding, + entry->array_element + j, entry->type); write_sampler_desc(set, info, entry->binding, entry->array_element + j, write_immutable_samplers); - write_image_view_desc(set, info, entry->binding, - entry->array_element + j, - VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE); } break; diff --git a/src/panfrost/vulkan/panvk_vX_descriptor_set_layout.c b/src/panfrost/vulkan/panvk_vX_descriptor_set_layout.c index 6dc06bb13b0..6b366460aeb 100644 --- a/src/panfrost/vulkan/panvk_vX_descriptor_set_layout.c +++ b/src/panfrost/vulkan/panvk_vX_descriptor_set_layout.c @@ -16,6 +16,7 @@ #include "vk_format.h" #include "vk_log.h" #include "vk_util.h" +#include "vk_ycbcr_conversion.h" #include "util/bitset.h" @@ -30,18 +31,55 @@ #define PANVK_MAX_DESCS_PER_SET (1 << 24) static bool -binding_has_immutable_samplers(const VkDescriptorSetLayoutBinding *binding) +is_texture(VkDescriptorType type) { - switch (binding->descriptorType) { - case VK_DESCRIPTOR_TYPE_SAMPLER: + switch (type) { + case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: + case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: + case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: - return binding->pImmutableSamplers != NULL; + return true; default: return false; } } +static bool +is_sampler(VkDescriptorType type) +{ + switch (type) { + case VK_DESCRIPTOR_TYPE_SAMPLER: + case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: + return true; + + default: + return false; + } +} + +static bool +binding_has_immutable_samplers(const VkDescriptorSetLayoutBinding *binding) +{ + return is_sampler(binding->descriptorType) && + binding->pImmutableSamplers != NULL; +} + +static void +set_immutable_sampler(struct panvk_descriptor_set_binding_layout *binding_layout, + uint32_t index, struct panvk_sampler *sampler) +{ + binding_layout->immutable_samplers[index] = sampler; + if (!sampler->vk.ycbcr_conversion) + return; + + binding_layout->textures_per_desc = + MAX2(vk_format_get_plane_count(sampler->vk.ycbcr_conversion->state.format), + binding_layout->textures_per_desc); + binding_layout->samplers_per_desc = + MAX2(sampler->desc_count, binding_layout->samplers_per_desc); +} + VkResult panvk_per_arch(CreateDescriptorSetLayout)( VkDevice _device, const VkDescriptorSetLayoutCreateInfo *pCreateInfo, @@ -119,6 +157,11 @@ panvk_per_arch(CreateDescriptorSetLayout)( } binding_layout->desc_count = binding->descriptorCount; + if (is_texture(binding_layout->type)) + binding_layout->textures_per_desc = 1; + + if (is_sampler(binding_layout->type)) + binding_layout->samplers_per_desc = 1; if (binding_has_immutable_samplers(binding)) { binding_layout->immutable_samplers = samplers; @@ -126,7 +169,7 @@ panvk_per_arch(CreateDescriptorSetLayout)( for (uint32_t j = 0; j < binding->descriptorCount; j++) { VK_FROM_HANDLE(panvk_sampler, sampler, binding->pImmutableSamplers[j]); - binding_layout->immutable_samplers[j] = sampler; + set_immutable_sampler(binding_layout, j, sampler); } } @@ -160,7 +203,23 @@ panvk_per_arch(CreateDescriptorSetLayout)( 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_update(&hash_ctx, &layout->bindings[b].textures_per_desc, + sizeof(layout->bindings[b].textures_per_desc)); + _mesa_blake3_update(&hash_ctx, &layout->bindings[b].samplers_per_desc, + sizeof(layout->bindings[b].samplers_per_desc)); + + if (layout->bindings[b].immutable_samplers != NULL) { + for (uint32_t i = 0; i < layout->bindings[b].desc_count; i++) { + const struct panvk_sampler *sampler = + layout->bindings[b].immutable_samplers[i]; + + /* We zalloc the object, so it's safe to hash the whole thing */ + if (sampler != NULL && sampler->vk.ycbcr_conversion != NULL) + _mesa_blake3_update(&hash_ctx, + &sampler->vk.ycbcr_conversion->state, + sizeof(sampler->vk.ycbcr_conversion->state)); + } + } } _mesa_blake3_final(&hash_ctx, layout->vk.blake3); @@ -188,8 +247,28 @@ panvk_per_arch(GetDescriptorSetLayoutSupport)( continue; } + unsigned textures_per_desc = is_texture(type) ? 1 : 0; + unsigned samplers_per_desc = is_sampler(type) ? 1 : 0; + if (binding_has_immutable_samplers(binding)) { + for (uint32_t j = 0; j < binding->descriptorCount; j++) { + VK_FROM_HANDLE(panvk_sampler, sampler, + binding->pImmutableSamplers[j]); + if (!sampler->vk.ycbcr_conversion) + continue; + + textures_per_desc = + MAX2(vk_format_get_plane_count( + sampler->vk.ycbcr_conversion->state.format), + textures_per_desc); + samplers_per_desc = + MAX2(sampler->desc_count, samplers_per_desc); + } + } + const struct panvk_descriptor_set_binding_layout layout = { .type = type, + .textures_per_desc = textures_per_desc, + .samplers_per_desc = samplers_per_desc, }; desc_count += panvk_get_desc_stride(&layout) * binding->descriptorCount; diff --git a/src/panfrost/vulkan/panvk_vX_image_view.c b/src/panfrost/vulkan/panvk_vX_image_view.c index c66bccb5b99..23553d714cb 100644 --- a/src/panfrost/vulkan/panvk_vX_image_view.c +++ b/src/panfrost/vulkan/panvk_vX_image_view.c @@ -113,17 +113,22 @@ prepare_tex_descs(struct panvk_image_view *view) if (pview.format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT) pview.format = PIPE_FORMAT_Z32_FLOAT; + uint32_t plane_count = vk_format_get_plane_count(view->vk.format); + uint32_t tex_payload_size = + GENX(panfrost_estimate_texture_payload_size)(&pview); + struct panvk_pool_alloc_info alloc_info = { #if PAN_ARCH == 6 .alignment = pan_alignment(SURFACE_WITH_STRIDE), #elif PAN_ARCH == 7 - .alignment = pan_alignment(MULTIPLANAR_SURFACE), + .alignment = (plane_count > 1) + ? pan_alignment(MULTIPLANAR_SURFACE) + : pan_alignment(SURFACE_WITH_STRIDE), #else - .alignment = pan_alignment(PLANE), + .alignment = pan_alignment(PLANE) * (plane_count > 1 ? 2 : 1), #endif - .size = GENX(panfrost_estimate_texture_payload_size)(&pview) * - (can_preload_other_aspect ? 2 : 1), + .size = tex_payload_size * (can_preload_other_aspect ? 2 : plane_count), }; view->mem = panvk_pool_alloc_mem(&dev->mempools.rw, alloc_info); @@ -135,7 +140,25 @@ prepare_tex_descs(struct panvk_image_view *view) .cpu = panvk_priv_mem_host_addr(view->mem), }; - GENX(panfrost_new_texture)(&pview, &view->descs.tex, &ptr); + if (plane_count > 1) { + memset(pview.planes, 0, sizeof(pview.planes)); + + for (uint32_t plane = 0; plane < plane_count; plane++) { + VkFormat plane_format = + vk_format_get_plane_format(view->vk.view_format, plane); + + /* We need a per-plane pview. */ + pview.planes[0] = view->pview.planes[plane]; + pview.format = vk_format_to_pipe_format(plane_format); + + GENX(panfrost_new_texture)(&pview, &view->descs.tex[plane], &ptr); + + ptr.cpu += tex_payload_size; + ptr.gpu += tex_payload_size; + } + } else { + GENX(panfrost_new_texture)(&pview, &view->descs.tex[0], &ptr); + } if (!can_preload_other_aspect) return VK_SUCCESS; @@ -158,8 +181,8 @@ prepare_tex_descs(struct panvk_image_view *view) assert(!"Invalid format"); } - ptr.cpu += alloc_info.size / 2; - ptr.gpu += alloc_info.size / 2; + ptr.cpu += tex_payload_size; + ptr.gpu += tex_payload_size; GENX(panfrost_new_texture)(&pview, &view->descs.zs.other_aspect_tex, &ptr); return VK_SUCCESS; diff --git a/src/panfrost/vulkan/panvk_vX_nir_lower_descriptors.c b/src/panfrost/vulkan/panvk_vX_nir_lower_descriptors.c index f56ef55210a..61fa9b769f9 100644 --- a/src/panfrost/vulkan/panvk_vX_nir_lower_descriptors.c +++ b/src/panfrost/vulkan/panvk_vX_nir_lower_descriptors.c @@ -110,8 +110,8 @@ struct desc_id { struct { uint32_t binding; uint32_t set : 4; - uint32_t subdesc : 1; - uint32_t pad : 27; + uint32_t subdesc : 3; + uint32_t pad : 25; }; uint64_t ht_key; }; @@ -119,12 +119,15 @@ struct desc_id { #if PAN_ARCH <= 7 static enum panvk_bifrost_desc_table_type -desc_type_to_table_type(VkDescriptorType type, unsigned subdesc_idx) +desc_type_to_table_type( + const struct panvk_descriptor_set_binding_layout *binding_layout, + unsigned subdesc_idx) { - switch (type) { + switch (binding_layout->type) { case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: - return subdesc_idx == 1 ? PANVK_BIFROST_DESC_TABLE_SAMPLER - : PANVK_BIFROST_DESC_TABLE_TEXTURE; + return subdesc_idx >= MAX2(1, binding_layout->textures_per_desc) + ? PANVK_BIFROST_DESC_TABLE_SAMPLER + : PANVK_BIFROST_DESC_TABLE_TEXTURE; case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: @@ -143,27 +146,15 @@ desc_type_to_table_type(VkDescriptorType type, unsigned subdesc_idx) #endif static uint32_t -get_subdesc_idx(const struct panvk_descriptor_set_binding_layout *bind_layout, - VkDescriptorType subdesc_type) -{ - if (bind_layout->type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) { - assert(subdesc_type == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE || - subdesc_type == VK_DESCRIPTOR_TYPE_SAMPLER); - return subdesc_type == VK_DESCRIPTOR_TYPE_SAMPLER ? 1 : 0; - } - - return 0; -} - -static uint32_t -shader_desc_idx(uint32_t set, uint32_t binding, VkDescriptorType subdesc_type, +shader_desc_idx(uint32_t set, uint32_t binding, + struct panvk_subdesc_info subdesc, const struct lower_desc_ctx *ctx) { const struct panvk_descriptor_set_layout *set_layout = get_set_layout(set, ctx); const struct panvk_descriptor_set_binding_layout *bind_layout = &set_layout->bindings[binding]; - uint32_t subdesc_idx = get_subdesc_idx(bind_layout, subdesc_type); + uint32_t subdesc_idx = get_subdesc_idx(bind_layout, subdesc); /* On Valhall, all non-dynamic descriptors are accessed directly through * their set. The vertex attribute table always comes first, so we always @@ -193,7 +184,7 @@ shader_desc_idx(uint32_t set, uint32_t binding, VkDescriptorType subdesc_type, } else if (bind_layout->type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC) { map = &ctx->desc_info.dyn_ssbos; } else { - uint32_t table = desc_type_to_table_type(bind_layout->type, src.subdesc); + uint32_t table = desc_type_to_table_type(bind_layout, src.subdesc); assert(table < PANVK_BIFROST_DESC_TABLE_COUNT); map = &ctx->desc_info.others[table]; @@ -300,7 +291,7 @@ build_res_index(nir_builder *b, uint32_t set, uint32_t binding, &set_layout->bindings[binding]; uint32_t array_size = bind_layout->desc_count; nir_address_format addr_fmt = addr_format_for_type(bind_layout->type, ctx); - uint32_t desc_idx = shader_desc_idx(set, binding, bind_layout->type, ctx); + uint32_t desc_idx = shader_desc_idx(set, binding, NO_SUBDESC, ctx); switch (addr_fmt) { #if PAN_ARCH <= 7 @@ -524,7 +515,14 @@ load_resource_deref_desc(nir_builder *b, nir_deref_instr *deref, get_set_layout(set, ctx); const struct panvk_descriptor_set_binding_layout *bind_layout = &set_layout->bindings[binding]; - unsigned subdesc_idx = get_subdesc_idx(bind_layout, subdesc_type); + struct panvk_subdesc_info subdesc = + subdesc_type == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE + ? get_tex_subdesc_info(bind_layout->type, 0) + : subdesc_type == VK_DESCRIPTOR_TYPE_SAMPLER + ? get_sampler_subdesc_info(bind_layout->type, 0) + : NO_SUBDESC; + + unsigned subdesc_idx = get_subdesc_idx(bind_layout, subdesc); assert(index_ssa == NULL || index_imm == 0); if (index_ssa == NULL) @@ -677,12 +675,24 @@ load_img_samples(nir_builder *b, nir_deref_instr *deref, } static uint32_t -get_desc_array_stride(const struct panvk_descriptor_set_binding_layout *layout) +get_desc_array_stride(const struct panvk_descriptor_set_binding_layout *layout, + VkDescriptorType type) { + if (PAN_ARCH >= 9) + return panvk_get_desc_stride(layout); + /* On Bifrost, descriptors are copied from the sets to the final - * descriptor tables which are per-type, making the stride one in - * this context. */ - return PAN_ARCH >= 9 ? panvk_get_desc_stride(layout) : 1; + * descriptor tables which are per-type. For combined image-sampler, + * the stride is {textures/samplers}_per_desc in this context; + * otherwise the stride is one. */ + switch(type) { + case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: + return layout->textures_per_desc; + case VK_DESCRIPTOR_TYPE_SAMPLER: + return layout->samplers_per_desc; + default: + return 1; + } } static bool @@ -722,9 +732,14 @@ lower_tex(nir_builder *b, nir_tex_instr *tex, const struct lower_desc_ctx *ctx) return true; } + uint32_t plane = 0; int sampler_src_idx = nir_tex_instr_src_index(tex, nir_tex_src_sampler_deref); if (sampler_src_idx >= 0) { + nir_def *plane_ssa = nir_steal_tex_src(tex, nir_tex_src_plane); + plane = + plane_ssa ? nir_src_as_uint(nir_src_for_ssa(plane_ssa)) : 0; + nir_deref_instr *deref = nir_src_as_deref(tex->src[sampler_src_idx].src); nir_tex_instr_remove_src(tex, sampler_src_idx); @@ -736,10 +751,12 @@ lower_tex(nir_builder *b, nir_tex_instr *tex, const struct lower_desc_ctx *ctx) get_set_layout(set, ctx); const struct panvk_descriptor_set_binding_layout *bind_layout = &set_layout->bindings[binding]; - uint32_t desc_stride = get_desc_array_stride(bind_layout); + struct panvk_subdesc_info subdesc = + get_sampler_subdesc_info(bind_layout->type, plane); + uint32_t desc_stride = get_desc_array_stride(bind_layout, subdesc.type); tex->sampler_index = - shader_desc_idx(set, binding, VK_DESCRIPTOR_TYPE_SAMPLER, ctx) + + shader_desc_idx(set, binding, subdesc, ctx) + index_imm * desc_stride; if (index_ssa != NULL) { @@ -767,10 +784,12 @@ lower_tex(nir_builder *b, nir_tex_instr *tex, const struct lower_desc_ctx *ctx) get_set_layout(set, ctx); const struct panvk_descriptor_set_binding_layout *bind_layout = &set_layout->bindings[binding]; - uint32_t desc_stride = get_desc_array_stride(bind_layout); + struct panvk_subdesc_info subdesc = + get_tex_subdesc_info(bind_layout->type, plane); + uint32_t desc_stride = get_desc_array_stride(bind_layout, subdesc.type); tex->texture_index = - shader_desc_idx(set, binding, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, ctx) + + shader_desc_idx(set, binding, subdesc, ctx) + index_imm * desc_stride; if (index_ssa != NULL) { @@ -798,7 +817,7 @@ get_img_index(nir_builder *b, nir_deref_instr *deref, bind_layout->type == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER || bind_layout->type == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER); - unsigned img_offset = shader_desc_idx(set, binding, bind_layout->type, ctx); + unsigned img_offset = shader_desc_idx(set, binding, NO_SUBDESC, ctx); if (index_ssa == NULL) { return nir_imm_int(b, img_offset + index_imm); @@ -879,15 +898,17 @@ lower_descriptors_instr(nir_builder *b, nir_instr *instr, void *data) static void record_binding(struct lower_desc_ctx *ctx, unsigned set, unsigned binding, - VkDescriptorType subdesc_type, uint32_t max_idx) + struct panvk_subdesc_info subdesc, uint32_t max_idx) { const struct panvk_descriptor_set_layout *set_layout = ctx->set_layouts[set]; const struct panvk_descriptor_set_binding_layout *binding_layout = &set_layout->bindings[binding]; - uint32_t subdesc_idx = get_subdesc_idx(binding_layout, subdesc_type); + uint32_t subdesc_idx = get_subdesc_idx(binding_layout, subdesc); uint32_t desc_stride = panvk_get_desc_stride(binding_layout); + uint32_t max_desc_stride = MAX2( + binding_layout->samplers_per_desc + binding_layout->textures_per_desc, 1); - assert(desc_stride == 1 || desc_stride == 2); + assert(desc_stride >= 1 && desc_stride <= max_desc_stride); ctx->desc_info.used_set_mask |= BITFIELD_BIT(set); /* On valhall, we only record dynamic bindings, others are accessed directly @@ -931,7 +952,7 @@ record_binding(struct lower_desc_ctx *ctx, unsigned set, unsigned binding, ctx->desc_info.dyn_ssbos.count += desc_count_diff; } else { uint32_t table = - desc_type_to_table_type(binding_layout->type, subdesc_idx); + desc_type_to_table_type(binding_layout, subdesc_idx); assert(table < PANVK_BIFROST_DESC_TABLE_COUNT); ctx->desc_info.others[table].count += desc_count_diff; @@ -969,7 +990,7 @@ fill_copy_descs_for_binding(struct lower_desc_ctx *ctx, unsigned set, map = &ctx->desc_info.dyn_ssbos; } else { uint32_t dst_table = - desc_type_to_table_type(binding_layout->type, subdesc_idx); + desc_type_to_table_type(binding_layout, subdesc_idx); assert(dst_table < PANVK_BIFROST_DESC_TABLE_COUNT); map = &ctx->desc_info.others[dst_table]; @@ -1069,17 +1090,28 @@ collect_tex_desc_access(nir_builder *b, nir_tex_instr *tex, struct lower_desc_ctx *ctx) { bool recorded = false; + uint32_t plane = 0; int sampler_src_idx = nir_tex_instr_src_index(tex, nir_tex_src_sampler_deref); if (sampler_src_idx >= 0) { + int plane_src_idx = nir_tex_instr_src_index(tex, nir_tex_src_plane); + if (plane_src_idx >= 0) + plane = nir_src_as_uint(tex->src[plane_src_idx].src); + nir_deref_instr *deref = nir_src_as_deref(tex->src[sampler_src_idx].src); uint32_t set, binding, index_imm, max_idx; nir_def *index_ssa; get_resource_deref_binding(deref, &set, &binding, &index_imm, &index_ssa, &max_idx); + const struct panvk_descriptor_set_layout *set_layout = + ctx->set_layouts[set]; + const struct panvk_descriptor_set_binding_layout *binding_layout = + &set_layout->bindings[binding]; + struct panvk_subdesc_info subdesc = + get_sampler_subdesc_info(binding_layout->type, plane); - record_binding(ctx, set, binding, VK_DESCRIPTOR_TYPE_SAMPLER, max_idx); + record_binding(ctx, set, binding, subdesc, max_idx); recorded = true; } @@ -1091,9 +1123,14 @@ collect_tex_desc_access(nir_builder *b, nir_tex_instr *tex, nir_def *index_ssa; get_resource_deref_binding(deref, &set, &binding, &index_imm, &index_ssa, &max_idx); + const struct panvk_descriptor_set_layout *set_layout = + ctx->set_layouts[set]; + const struct panvk_descriptor_set_binding_layout *binding_layout = + &set_layout->bindings[binding]; + struct panvk_subdesc_info subdesc = + get_tex_subdesc_info(binding_layout->type, plane); - record_binding(ctx, set, binding, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, - max_idx); + record_binding(ctx, set, binding, subdesc, max_idx); recorded = true; } @@ -1113,7 +1150,7 @@ collect_intr_desc_access(nir_builder *b, nir_intrinsic_instr *intrin, /* TODO: walk the reindex chain from load_vulkan_descriptor() to try and * guess the max index. */ - record_binding(ctx, set, binding, ~0, UINT32_MAX); + record_binding(ctx, set, binding, NO_SUBDESC, UINT32_MAX); return true; } @@ -1129,7 +1166,7 @@ collect_intr_desc_access(nir_builder *b, nir_intrinsic_instr *intrin, get_resource_deref_binding(deref, &set, &binding, &index_imm, &index_ssa, &max_idx); - record_binding(ctx, set, binding, ~0, max_idx); + record_binding(ctx, set, binding, NO_SUBDESC, max_idx); return true; } default: diff --git a/src/panfrost/vulkan/panvk_vX_sampler.c b/src/panfrost/vulkan/panvk_vX_sampler.c index c458e9e0d1b..87e49332af4 100644 --- a/src/panfrost/vulkan/panvk_vX_sampler.c +++ b/src/panfrost/vulkan/panvk_vX_sampler.c @@ -14,6 +14,7 @@ #include "vk_format.h" #include "vk_log.h" +#include "vk_ycbcr_conversion.h" static enum mali_mipmap_mode panvk_translate_sampler_mipmap_mode(VkSamplerMipmapMode mode) @@ -185,7 +186,7 @@ panvk_per_arch(CreateSampler)(VkDevice _device, if (!sampler) return panvk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); - STATIC_ASSERT(sizeof(sampler->desc) >= pan_size(SAMPLER)); + STATIC_ASSERT(sizeof(sampler->descs[0]) >= pan_size(SAMPLER)); VkFormat fmt; VkClearColorValue border_color = @@ -195,10 +196,27 @@ panvk_per_arch(CreateSampler)(VkDevice _device, panvk_afbc_reswizzle_border_color(&border_color, fmt); #endif - panvk_sampler_fill_desc(pCreateInfo, &sampler->desc, border_color, + sampler->desc_count = 1; + panvk_sampler_fill_desc(pCreateInfo, &sampler->descs[0], border_color, pCreateInfo->minFilter, pCreateInfo->magFilter, sampler->vk.reduction_mode); + /* In order to support CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT, + * we need multiple sampler planes: at minimum we will need one for + * luminance (the default), and one for chroma. + */ + if (sampler->vk.ycbcr_conversion) { + const VkFilter chroma_filter = + sampler->vk.ycbcr_conversion->state.chroma_filter; + if (pCreateInfo->magFilter != chroma_filter || + pCreateInfo->minFilter != chroma_filter) { + sampler->desc_count = 2; + panvk_sampler_fill_desc(pCreateInfo, &sampler->descs[1], + border_color, chroma_filter, chroma_filter, + sampler->vk.reduction_mode); + } + } + *pSampler = panvk_sampler_to_handle(sampler); return VK_SUCCESS; }