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 <rebecca.mckeever@collabora.com>
Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/32563>
This commit is contained in:
Rebecca Mckeever 2025-01-28 14:23:29 -08:00 committed by Marge Bot
parent 45657fb70f
commit cdf24f067e
9 changed files with 343 additions and 110 deletions

View file

@ -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 */

View file

@ -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;

View file

@ -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,

View file

@ -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};
}

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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:

View file

@ -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;
}