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 <mary.guillemard@collabora.com>
Co-developed-by: Boris Brezillon <boris.brezillon@collabora.com>
Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
Reviewed-by: Mary Guillemard <mary.guillemard@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/29654>
This commit is contained in:
Rebecca Mckeever
2024-06-09 15:35:10 +02:00
committed by Marge Bot
parent 3796bfbb76
commit 73518dc169
3 changed files with 319 additions and 1 deletions

View File

@@ -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']

View File

@@ -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 <stdint.h>
#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 */

View File

@@ -0,0 +1,225 @@
/*
* Copyright © 2024 Collabora Ltd.
* SPDX-License-Identifier: MIT
*/
#include <assert.h>
#include <fcntl.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
#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;
}