blob: 371cf4fa0488a428c1712e3a4e2a5efa5ecbfef3 [file] [log] [blame]
/*
* Copyright © 2021 Collabora Ltd.
*
* Derived from:
* Copyright © 2016 Red Hat.
* Copyright © 2016 Bas Nieuwenhuizen
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include "genxml/gen_macros.h"
#include "panvk_private.h"
#include <assert.h>
#include <fcntl.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
#include "util/mesa-sha1.h"
#include "vk_descriptors.h"
#include "vk_descriptor_update_template.h"
#include "vk_util.h"
#include "pan_bo.h"
#include "panvk_cs.h"
#define PANVK_DESCRIPTOR_ALIGN 8
struct panvk_bview_desc {
uint32_t elems;
};
static void
panvk_fill_bview_desc(struct panvk_bview_desc *desc,
struct panvk_buffer_view *view)
{
desc->elems = view->elems;
}
struct panvk_image_desc {
uint16_t width;
uint16_t height;
uint16_t depth;
uint8_t levels;
uint8_t samples;
};
static void
panvk_fill_image_desc(struct panvk_image_desc *desc,
struct panvk_image_view *view)
{
desc->width = view->vk.extent.width - 1;
desc->height = view->vk.extent.height - 1;
desc->depth = view->vk.extent.depth - 1;
desc->levels = view->vk.level_count;
desc->samples = view->vk.image->samples;
/* Stick array layer count after the last valid size component */
if (view->vk.image->image_type == VK_IMAGE_TYPE_1D)
desc->height = view->vk.layer_count - 1;
else if (view->vk.image->image_type == VK_IMAGE_TYPE_2D)
desc->depth = view->vk.layer_count - 1;
}
VkResult
panvk_per_arch(CreateDescriptorSetLayout)(VkDevice _device,
const VkDescriptorSetLayoutCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
VkDescriptorSetLayout *pSetLayout)
{
VK_FROM_HANDLE(panvk_device, device, _device);
struct panvk_descriptor_set_layout *set_layout;
VkDescriptorSetLayoutBinding *bindings = NULL;
unsigned num_bindings = 0;
VkResult result;
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;
}
unsigned num_immutable_samplers = 0;
for (unsigned i = 0; i < pCreateInfo->bindingCount; i++) {
if (bindings[i].pImmutableSamplers)
num_immutable_samplers += bindings[i].descriptorCount;
}
size_t size = sizeof(*set_layout) +
(sizeof(struct panvk_descriptor_set_binding_layout) *
num_bindings) +
(sizeof(struct panvk_sampler *) * num_immutable_samplers);
set_layout = vk_descriptor_set_layout_zalloc(&device->vk, size);
if (!set_layout) {
result = VK_ERROR_OUT_OF_HOST_MEMORY;
goto err_free_bindings;
}
struct panvk_sampler **immutable_samplers =
(struct panvk_sampler **)((uint8_t *)set_layout + sizeof(*set_layout) +
(sizeof(struct panvk_descriptor_set_binding_layout) *
num_bindings));
set_layout->binding_count = num_bindings;
unsigned sampler_idx = 0, tex_idx = 0, ubo_idx = 0;
unsigned dyn_ubo_idx = 0, dyn_ssbo_idx = 0, img_idx = 0;
uint32_t desc_ubo_size = 0;
for (unsigned i = 0; i < pCreateInfo->bindingCount; i++) {
const VkDescriptorSetLayoutBinding *binding = &bindings[i];
struct panvk_descriptor_set_binding_layout *binding_layout =
&set_layout->bindings[binding->binding];
binding_layout->type = binding->descriptorType;
binding_layout->array_size = binding->descriptorCount;
binding_layout->shader_stages = binding->stageFlags;
binding_layout->desc_ubo_stride = 0;
if (binding->pImmutableSamplers) {
binding_layout->immutable_samplers = immutable_samplers;
immutable_samplers += binding_layout->array_size;
for (unsigned j = 0; j < binding_layout->array_size; j++) {
VK_FROM_HANDLE(panvk_sampler, sampler, binding->pImmutableSamplers[j]);
binding_layout->immutable_samplers[j] = sampler;
}
}
switch (binding_layout->type) {
case VK_DESCRIPTOR_TYPE_SAMPLER:
binding_layout->sampler_idx = sampler_idx;
sampler_idx += binding_layout->array_size;
break;
case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
binding_layout->sampler_idx = sampler_idx;
binding_layout->tex_idx = tex_idx;
sampler_idx += binding_layout->array_size;
tex_idx += binding_layout->array_size;
binding_layout->desc_ubo_stride = sizeof(struct panvk_image_desc);
break;
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
binding_layout->tex_idx = tex_idx;
tex_idx += binding_layout->array_size;
binding_layout->desc_ubo_stride = sizeof(struct panvk_image_desc);
break;
case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
binding_layout->tex_idx = tex_idx;
tex_idx += binding_layout->array_size;
binding_layout->desc_ubo_stride = sizeof(struct panvk_bview_desc);
break;
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
binding_layout->dyn_ubo_idx = dyn_ubo_idx;
dyn_ubo_idx += binding_layout->array_size;
break;
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
binding_layout->ubo_idx = ubo_idx;
ubo_idx += binding_layout->array_size;
break;
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
binding_layout->dyn_ssbo_idx = dyn_ssbo_idx;
dyn_ssbo_idx += binding_layout->array_size;
break;
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
binding_layout->desc_ubo_stride = sizeof(struct panvk_ssbo_addr);
break;
case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
binding_layout->img_idx = img_idx;
img_idx += binding_layout->array_size;
binding_layout->desc_ubo_stride = sizeof(struct panvk_image_desc);
break;
case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
binding_layout->img_idx = img_idx;
img_idx += binding_layout->array_size;
binding_layout->desc_ubo_stride = sizeof(struct panvk_bview_desc);
break;
default:
unreachable("Invalid descriptor type");
}
desc_ubo_size = ALIGN_POT(desc_ubo_size, PANVK_DESCRIPTOR_ALIGN);
binding_layout->desc_ubo_offset = desc_ubo_size;
desc_ubo_size += binding_layout->desc_ubo_stride *
binding_layout->array_size;
}
set_layout->desc_ubo_size = desc_ubo_size;
if (desc_ubo_size > 0)
set_layout->desc_ubo_index = ubo_idx++;
set_layout->num_samplers = sampler_idx;
set_layout->num_textures = tex_idx;
set_layout->num_ubos = ubo_idx;
set_layout->num_dyn_ubos = dyn_ubo_idx;
set_layout->num_dyn_ssbos = dyn_ssbo_idx;
set_layout->num_imgs = img_idx;
free(bindings);
*pSetLayout = panvk_descriptor_set_layout_to_handle(set_layout);
return VK_SUCCESS;
err_free_bindings:
free(bindings);
return vk_error(device, result);
}
static void
panvk_write_sampler_desc_raw(struct panvk_descriptor_set *set,
uint32_t binding, uint32_t elem,
struct panvk_sampler *sampler);
static VkResult
panvk_per_arch(descriptor_set_create)(struct panvk_device *device,
struct panvk_descriptor_pool *pool,
const struct panvk_descriptor_set_layout *layout,
struct panvk_descriptor_set **out_set)
{
struct panvk_descriptor_set *set;
/* TODO: Allocate from the pool! */
set = vk_object_zalloc(&device->vk, NULL,
sizeof(struct panvk_descriptor_set),
VK_OBJECT_TYPE_DESCRIPTOR_SET);
if (!set)
return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
set->layout = layout;
if (layout->num_ubos) {
set->ubos = vk_zalloc(&device->vk.alloc,
pan_size(UNIFORM_BUFFER) * layout->num_ubos, 8,
VK_OBJECT_TYPE_DESCRIPTOR_SET);
if (!set->ubos)
goto err_free_set;
}
if (layout->num_dyn_ubos) {
set->dyn_ubos = vk_zalloc(&device->vk.alloc,
sizeof(*set->dyn_ubos) * layout->num_dyn_ubos, 8,
VK_OBJECT_TYPE_DESCRIPTOR_SET);
if (!set->dyn_ubos)
goto err_free_set;
}
if (layout->num_dyn_ssbos) {
set->dyn_ssbos = vk_zalloc(&device->vk.alloc,
sizeof(*set->dyn_ssbos) * layout->num_dyn_ssbos, 8,
VK_OBJECT_TYPE_DESCRIPTOR_SET);
if (!set->dyn_ssbos)
goto err_free_set;
}
if (layout->num_samplers) {
set->samplers = vk_zalloc(&device->vk.alloc,
pan_size(SAMPLER) * layout->num_samplers, 8,
VK_OBJECT_TYPE_DESCRIPTOR_SET);
if (!set->samplers)
goto err_free_set;
}
if (layout->num_textures) {
set->textures =
vk_zalloc(&device->vk.alloc, pan_size(TEXTURE) * layout->num_textures,
8, VK_OBJECT_TYPE_DESCRIPTOR_SET);
if (!set->textures)
goto err_free_set;
}
if (layout->num_imgs) {
set->img_fmts =
vk_zalloc(&device->vk.alloc,
sizeof(*set->img_fmts) * layout->num_imgs,
8, VK_OBJECT_TYPE_DESCRIPTOR_SET);
if (!set->img_fmts)
goto err_free_set;
set->img_attrib_bufs =
vk_zalloc(&device->vk.alloc,
pan_size(ATTRIBUTE_BUFFER) * 2 * layout->num_imgs,
8, VK_OBJECT_TYPE_DESCRIPTOR_SET);
if (!set->img_attrib_bufs)
goto err_free_set;
}
if (layout->desc_ubo_size) {
set->desc_bo = panfrost_bo_create(&device->physical_device->pdev,
layout->desc_ubo_size,
0, "Descriptor set");
if (!set->desc_bo)
goto err_free_set;
struct mali_uniform_buffer_packed *ubos = set->ubos;
panvk_per_arch(emit_ubo)(set->desc_bo->ptr.gpu,
layout->desc_ubo_size,
&ubos[layout->desc_ubo_index]);
}
for (unsigned i = 0; i < layout->binding_count; i++) {
if (!layout->bindings[i].immutable_samplers)
continue;
for (unsigned j = 0; j < layout->bindings[i].array_size; j++) {
struct panvk_sampler *sampler =
layout->bindings[i].immutable_samplers[j];
panvk_write_sampler_desc_raw(set, i, j, sampler);
}
}
*out_set = set;
return VK_SUCCESS;
err_free_set:
vk_free(&device->vk.alloc, set->textures);
vk_free(&device->vk.alloc, set->samplers);
vk_free(&device->vk.alloc, set->ubos);
vk_free(&device->vk.alloc, set->dyn_ubos);
vk_free(&device->vk.alloc, set->dyn_ssbos);
vk_free(&device->vk.alloc, set->img_fmts);
vk_free(&device->vk.alloc, set->img_attrib_bufs);
if (set->desc_bo)
panfrost_bo_unreference(set->desc_bo);
vk_object_free(&device->vk, NULL, set);
return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
}
VkResult
panvk_per_arch(AllocateDescriptorSets)(VkDevice _device,
const VkDescriptorSetAllocateInfo *pAllocateInfo,
VkDescriptorSet *pDescriptorSets)
{
VK_FROM_HANDLE(panvk_device, device, _device);
VK_FROM_HANDLE(panvk_descriptor_pool, pool, pAllocateInfo->descriptorPool);
VkResult result;
unsigned i;
for (i = 0; i < pAllocateInfo->descriptorSetCount; i++) {
VK_FROM_HANDLE(panvk_descriptor_set_layout, layout,
pAllocateInfo->pSetLayouts[i]);
struct panvk_descriptor_set *set = NULL;
result = panvk_per_arch(descriptor_set_create)(device, pool, layout, &set);
if (result != VK_SUCCESS)
goto err_free_sets;
pDescriptorSets[i] = panvk_descriptor_set_to_handle(set);
}
return VK_SUCCESS;
err_free_sets:
panvk_FreeDescriptorSets(_device, pAllocateInfo->descriptorPool, i, pDescriptorSets);
for (i = 0; i < pAllocateInfo->descriptorSetCount; i++)
pDescriptorSets[i] = VK_NULL_HANDLE;
return result;
}
static void *
panvk_desc_ubo_data(struct panvk_descriptor_set *set,
uint32_t binding, uint32_t elem)
{
const struct panvk_descriptor_set_binding_layout *binding_layout =
&set->layout->bindings[binding];
return (char *)set->desc_bo->ptr.cpu +
binding_layout->desc_ubo_offset +
elem * binding_layout->desc_ubo_stride;
}
static struct mali_sampler_packed *
panvk_sampler_desc(struct panvk_descriptor_set *set,
uint32_t binding, uint32_t elem)
{
const struct panvk_descriptor_set_binding_layout *binding_layout =
&set->layout->bindings[binding];
uint32_t sampler_idx = binding_layout->sampler_idx + elem;
return &((struct mali_sampler_packed *)set->samplers)[sampler_idx];
}
static void
panvk_write_sampler_desc_raw(struct panvk_descriptor_set *set,
uint32_t binding, uint32_t elem,
struct panvk_sampler *sampler)
{
memcpy(panvk_sampler_desc(set, binding, elem),
&sampler->desc, sizeof(sampler->desc));
}
static void
panvk_write_sampler_desc(UNUSED struct panvk_device *dev,
struct panvk_descriptor_set *set,
uint32_t binding, uint32_t elem,
const VkDescriptorImageInfo * const pImageInfo)
{
const struct panvk_descriptor_set_binding_layout *binding_layout =
&set->layout->bindings[binding];
if (binding_layout->immutable_samplers)
return;
VK_FROM_HANDLE(panvk_sampler, sampler, pImageInfo->sampler);
panvk_write_sampler_desc_raw(set, binding, elem, sampler);
}
static void
panvk_copy_sampler_desc(struct panvk_descriptor_set *dst_set,
uint32_t dst_binding, uint32_t dst_elem,
struct panvk_descriptor_set *src_set,
uint32_t src_binding, uint32_t src_elem)
{
const struct panvk_descriptor_set_binding_layout *dst_binding_layout =
&dst_set->layout->bindings[dst_binding];
if (dst_binding_layout->immutable_samplers)
return;
memcpy(panvk_sampler_desc(dst_set, dst_binding, dst_elem),
panvk_sampler_desc(src_set, src_binding, src_elem),
sizeof(struct mali_sampler_packed));
}
static struct mali_texture_packed *
panvk_tex_desc(struct panvk_descriptor_set *set,
uint32_t binding, uint32_t elem)
{
const struct panvk_descriptor_set_binding_layout *binding_layout =
&set->layout->bindings[binding];
unsigned tex_idx = binding_layout->tex_idx + elem;
return &((struct mali_texture_packed *)set->textures)[tex_idx];
}
static void
panvk_write_tex_desc(UNUSED struct panvk_device *dev,
struct panvk_descriptor_set *set,
uint32_t binding, uint32_t elem,
const VkDescriptorImageInfo * const pImageInfo)
{
VK_FROM_HANDLE(panvk_image_view, view, pImageInfo->imageView);
memcpy(panvk_tex_desc(set, binding, elem),
view->descs.tex, pan_size(TEXTURE));
panvk_fill_image_desc(panvk_desc_ubo_data(set, binding, elem), view);
}
static void
panvk_copy_tex_desc(struct panvk_descriptor_set *dst_set,
uint32_t dst_binding, uint32_t dst_elem,
struct panvk_descriptor_set *src_set,
uint32_t src_binding, uint32_t src_elem)
{
*panvk_tex_desc(dst_set, dst_binding, dst_elem) =
*panvk_tex_desc(src_set, src_binding, src_elem);
/* Descriptor UBO data gets copied automatically */
}
static void
panvk_write_tex_buf_desc(UNUSED struct panvk_device *dev,
struct panvk_descriptor_set *set,
uint32_t binding, uint32_t elem,
const VkBufferView bufferView)
{
VK_FROM_HANDLE(panvk_buffer_view, view, bufferView);
memcpy(panvk_tex_desc(set, binding, elem),
view->descs.tex, pan_size(TEXTURE));
panvk_fill_bview_desc(panvk_desc_ubo_data(set, binding, elem), view);
}
static uint32_t
panvk_img_idx(struct panvk_descriptor_set *set,
uint32_t binding, uint32_t elem)
{
const struct panvk_descriptor_set_binding_layout *binding_layout =
&set->layout->bindings[binding];
return binding_layout->img_idx + elem;
}
static void
panvk_write_img_desc(struct panvk_device *dev,
struct panvk_descriptor_set *set,
uint32_t binding, uint32_t elem,
const VkDescriptorImageInfo *pImageInfo)
{
const struct panfrost_device *pdev = &dev->physical_device->pdev;
VK_FROM_HANDLE(panvk_image_view, view, pImageInfo->imageView);
unsigned img_idx = panvk_img_idx(set, binding, elem);
void *attrib_buf = (uint8_t *)set->img_attrib_bufs +
(pan_size(ATTRIBUTE_BUFFER) * 2 * img_idx);
set->img_fmts[img_idx] = pdev->formats[view->pview.format].hw;
memcpy(attrib_buf, view->descs.img_attrib_buf, pan_size(ATTRIBUTE_BUFFER) * 2);
panvk_fill_image_desc(panvk_desc_ubo_data(set, binding, elem), view);
}
static void
panvk_copy_img_desc(struct panvk_descriptor_set *dst_set,
uint32_t dst_binding, uint32_t dst_elem,
struct panvk_descriptor_set *src_set,
uint32_t src_binding, uint32_t src_elem)
{
unsigned dst_img_idx = panvk_img_idx(dst_set, dst_binding, dst_elem);
unsigned src_img_idx = panvk_img_idx(src_set, src_binding, src_elem);
void *dst_attrib_buf = (uint8_t *)dst_set->img_attrib_bufs +
(pan_size(ATTRIBUTE_BUFFER) * 2 * dst_img_idx);
void *src_attrib_buf = (uint8_t *)src_set->img_attrib_bufs +
(pan_size(ATTRIBUTE_BUFFER) * 2 * src_img_idx);
dst_set->img_fmts[dst_img_idx] = src_set->img_fmts[src_img_idx];
memcpy(dst_attrib_buf, src_attrib_buf, pan_size(ATTRIBUTE_BUFFER) * 2);
/* Descriptor UBO data gets copied automatically */
}
static void
panvk_write_img_buf_desc(struct panvk_device *dev,
struct panvk_descriptor_set *set,
uint32_t binding, uint32_t elem,
const VkBufferView bufferView)
{
const struct panfrost_device *pdev = &dev->physical_device->pdev;
VK_FROM_HANDLE(panvk_buffer_view, view, bufferView);
unsigned img_idx = panvk_img_idx(set, binding, elem);
void *attrib_buf = (uint8_t *)set->img_attrib_bufs +
(pan_size(ATTRIBUTE_BUFFER) * 2 * img_idx);
set->img_fmts[img_idx] = pdev->formats[view->fmt].hw;
memcpy(attrib_buf, view->descs.img_attrib_buf, pan_size(ATTRIBUTE_BUFFER) * 2);
panvk_fill_bview_desc(panvk_desc_ubo_data(set, binding, elem), view);
}
static struct mali_uniform_buffer_packed *
panvk_ubo_desc(struct panvk_descriptor_set *set,
uint32_t binding, uint32_t elem)
{
const struct panvk_descriptor_set_binding_layout *binding_layout =
&set->layout->bindings[binding];
unsigned ubo_idx = binding_layout->ubo_idx + elem;
return &((struct mali_uniform_buffer_packed *)set->ubos)[ubo_idx];
}
static void
panvk_write_ubo_desc(UNUSED struct panvk_device *dev,
struct panvk_descriptor_set *set,
uint32_t binding, uint32_t elem,
const VkDescriptorBufferInfo *pBufferInfo)
{
VK_FROM_HANDLE(panvk_buffer, buffer, pBufferInfo->buffer);
mali_ptr ptr = panvk_buffer_gpu_ptr(buffer, pBufferInfo->offset);
size_t size = panvk_buffer_range(buffer, pBufferInfo->offset,
pBufferInfo->range);
panvk_per_arch(emit_ubo)(ptr, size, panvk_ubo_desc(set, binding, elem));
}
static void
panvk_copy_ubo_desc(struct panvk_descriptor_set *dst_set,
uint32_t dst_binding, uint32_t dst_elem,
struct panvk_descriptor_set *src_set,
uint32_t src_binding, uint32_t src_elem)
{
*panvk_ubo_desc(dst_set, dst_binding, dst_elem) =
*panvk_ubo_desc(src_set, src_binding, src_elem);
}
static struct panvk_buffer_desc *
panvk_dyn_ubo_desc(struct panvk_descriptor_set *set,
uint32_t binding, uint32_t elem)
{
const struct panvk_descriptor_set_binding_layout *binding_layout =
&set->layout->bindings[binding];
return &set->dyn_ubos[binding_layout->dyn_ubo_idx + elem];
}
static void
panvk_write_dyn_ubo_desc(UNUSED struct panvk_device *dev,
struct panvk_descriptor_set *set,
uint32_t binding, uint32_t elem,
const VkDescriptorBufferInfo *pBufferInfo)
{
VK_FROM_HANDLE(panvk_buffer, buffer, pBufferInfo->buffer);
*panvk_dyn_ubo_desc(set, binding, elem) = (struct panvk_buffer_desc) {
.buffer = buffer,
.offset = pBufferInfo->offset,
.size = pBufferInfo->range,
};
}
static void
panvk_copy_dyn_ubo_desc(struct panvk_descriptor_set *dst_set,
uint32_t dst_binding, uint32_t dst_elem,
struct panvk_descriptor_set *src_set,
uint32_t src_binding, uint32_t src_elem)
{
*panvk_dyn_ubo_desc(dst_set, dst_binding, dst_elem) =
*panvk_dyn_ubo_desc(src_set, src_binding, src_elem);
}
static void
panvk_write_ssbo_desc(UNUSED struct panvk_device *dev,
struct panvk_descriptor_set *set,
uint32_t binding, uint32_t elem,
const VkDescriptorBufferInfo *pBufferInfo)
{
VK_FROM_HANDLE(panvk_buffer, buffer, pBufferInfo->buffer);
struct panvk_ssbo_addr *desc = panvk_desc_ubo_data(set, binding, elem);
*desc = (struct panvk_ssbo_addr) {
.base_addr = panvk_buffer_gpu_ptr(buffer, pBufferInfo->offset),
.size = panvk_buffer_range(buffer, pBufferInfo->offset,
pBufferInfo->range),
};
}
static void
panvk_copy_ssbo_desc(struct panvk_descriptor_set *dst_set,
uint32_t dst_binding, uint32_t dst_elem,
struct panvk_descriptor_set *src_set,
uint32_t src_binding, uint32_t src_elem)
{
/* Descriptor UBO data gets copied automatically */
}
static struct panvk_buffer_desc *
panvk_dyn_ssbo_desc(struct panvk_descriptor_set *set,
uint32_t binding, uint32_t elem)
{
const struct panvk_descriptor_set_binding_layout *binding_layout =
&set->layout->bindings[binding];
return &set->dyn_ssbos[binding_layout->dyn_ssbo_idx + elem];
}
static void
panvk_write_dyn_ssbo_desc(UNUSED struct panvk_device *dev,
struct panvk_descriptor_set *set,
uint32_t binding, uint32_t elem,
const VkDescriptorBufferInfo *pBufferInfo)
{
VK_FROM_HANDLE(panvk_buffer, buffer, pBufferInfo->buffer);
*panvk_dyn_ssbo_desc(set, binding, elem) = (struct panvk_buffer_desc) {
.buffer = buffer,
.offset = pBufferInfo->offset,
.size = pBufferInfo->range,
};
}
static void
panvk_copy_dyn_ssbo_desc(struct panvk_descriptor_set *dst_set,
uint32_t dst_binding, uint32_t dst_elem,
struct panvk_descriptor_set *src_set,
uint32_t src_binding, uint32_t src_elem)
{
*panvk_dyn_ssbo_desc(dst_set, dst_binding, dst_elem) =
*panvk_dyn_ssbo_desc(src_set, src_binding, src_elem);
}
void
panvk_per_arch(UpdateDescriptorSets)(VkDevice _device,
uint32_t descriptorWriteCount,
const VkWriteDescriptorSet *pDescriptorWrites,
uint32_t descriptorCopyCount,
const VkCopyDescriptorSet *pDescriptorCopies)
{
VK_FROM_HANDLE(panvk_device, dev, _device);
for (unsigned i = 0; i < descriptorWriteCount; i++) {
const VkWriteDescriptorSet *write = &pDescriptorWrites[i];
VK_FROM_HANDLE(panvk_descriptor_set, set, write->dstSet);
switch (write->descriptorType) {
case VK_DESCRIPTOR_TYPE_SAMPLER:
for (uint32_t j = 0; j < write->descriptorCount; j++) {
panvk_write_sampler_desc(dev, set,
write->dstBinding,
write->dstArrayElement + j,
&write->pImageInfo[j]);
}
break;
case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
for (uint32_t j = 0; j < write->descriptorCount; j++) {
panvk_write_sampler_desc(dev, set,
write->dstBinding,
write->dstArrayElement + j,
&write->pImageInfo[j]);
panvk_write_tex_desc(dev, set,
write->dstBinding,
write->dstArrayElement + j,
&write->pImageInfo[j]);
}
break;
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
for (uint32_t j = 0; j < write->descriptorCount; j++) {
panvk_write_tex_desc(dev, set,
write->dstBinding,
write->dstArrayElement + j,
&write->pImageInfo[j]);
}
break;
case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
for (uint32_t j = 0; j < write->descriptorCount; j++) {
panvk_write_img_desc(dev, set,
write->dstBinding,
write->dstArrayElement + j,
&write->pImageInfo[j]);
}
break;
case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
for (uint32_t j = 0; j < write->descriptorCount; j++) {
panvk_write_tex_buf_desc(dev, set,
write->dstBinding,
write->dstArrayElement + j,
write->pTexelBufferView[j]);
}
break;
case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
for (uint32_t j = 0; j < write->descriptorCount; j++) {
panvk_write_img_buf_desc(dev, set,
write->dstBinding,
write->dstArrayElement + j,
write->pTexelBufferView[j]);
}
break;
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
for (uint32_t j = 0; j < write->descriptorCount; j++) {
panvk_write_ubo_desc(dev, set,
write->dstBinding,
write->dstArrayElement + j,
&write->pBufferInfo[j]);
}
break;
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
for (uint32_t j = 0; j < write->descriptorCount; j++) {
panvk_write_dyn_ubo_desc(dev, set,
write->dstBinding,
write->dstArrayElement + j,
&write->pBufferInfo[j]);
}
break;
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
for (uint32_t j = 0; j < write->descriptorCount; j++) {
panvk_write_ssbo_desc(dev, set,
write->dstBinding,
write->dstArrayElement + j,
&write->pBufferInfo[j]);
}
break;
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
for (uint32_t j = 0; j < write->descriptorCount; j++) {
panvk_write_dyn_ssbo_desc(dev, set,
write->dstBinding,
write->dstArrayElement + j,
&write->pBufferInfo[j]);
}
break;
default:
unreachable("Unsupported descriptor type");
}
}
for (unsigned i = 0; i < descriptorCopyCount; i++) {
const VkCopyDescriptorSet *copy = &pDescriptorCopies[i];
VK_FROM_HANDLE(panvk_descriptor_set, src_set, copy->srcSet);
VK_FROM_HANDLE(panvk_descriptor_set, dst_set, copy->dstSet);
const struct panvk_descriptor_set_binding_layout *dst_binding_layout =
&dst_set->layout->bindings[copy->dstBinding];
const struct panvk_descriptor_set_binding_layout *src_binding_layout =
&src_set->layout->bindings[copy->srcBinding];
assert(dst_binding_layout->type == src_binding_layout->type);
if (dst_binding_layout->desc_ubo_stride > 0 &&
src_binding_layout->desc_ubo_stride > 0) {
for (uint32_t j = 0; j < copy->descriptorCount; j++) {
memcpy(panvk_desc_ubo_data(dst_set, copy->dstBinding,
copy->dstArrayElement + j),
panvk_desc_ubo_data(src_set, copy->srcBinding,
copy->srcArrayElement + j),
MIN2(dst_binding_layout->desc_ubo_stride,
src_binding_layout->desc_ubo_stride));
}
}
switch (src_binding_layout->type) {
case VK_DESCRIPTOR_TYPE_SAMPLER:
for (uint32_t j = 0; j < copy->descriptorCount; j++) {
panvk_copy_sampler_desc(dst_set, copy->dstBinding,
copy->dstArrayElement + j,
src_set, copy->srcBinding,
copy->srcArrayElement + j);
}
break;
case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
for (uint32_t j = 0; j < copy->descriptorCount; j++) {
panvk_copy_sampler_desc(dst_set, copy->dstBinding,
copy->dstArrayElement + j,
src_set, copy->srcBinding,
copy->srcArrayElement + j);
panvk_copy_tex_desc(dst_set, copy->dstBinding,
copy->dstArrayElement + j,
src_set, copy->srcBinding,
copy->srcArrayElement + j);
}
break;
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
for (uint32_t j = 0; j < copy->descriptorCount; j++) {
panvk_copy_tex_desc(dst_set, copy->dstBinding,
copy->dstArrayElement + j,
src_set, copy->srcBinding,
copy->srcArrayElement + j);
}
break;
case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
for (uint32_t j = 0; j < copy->descriptorCount; j++) {
panvk_copy_img_desc(dst_set, copy->dstBinding,
copy->dstArrayElement + j,
src_set, copy->srcBinding,
copy->srcArrayElement + j);
}
break;
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
for (uint32_t j = 0; j < copy->descriptorCount; j++) {
panvk_copy_ubo_desc(dst_set, copy->dstBinding,
copy->dstArrayElement + j,
src_set, copy->srcBinding,
copy->srcArrayElement + j);
}
break;
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
for (uint32_t j = 0; j < copy->descriptorCount; j++) {
panvk_copy_dyn_ubo_desc(dst_set, copy->dstBinding,
copy->dstArrayElement + j,
src_set, copy->srcBinding,
copy->srcArrayElement + j);
}
break;
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
for (uint32_t j = 0; j < copy->descriptorCount; j++) {
panvk_copy_ssbo_desc(dst_set, copy->dstBinding,
copy->dstArrayElement + j,
src_set, copy->srcBinding,
copy->srcArrayElement + j);
}
break;
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
for (uint32_t j = 0; j < copy->descriptorCount; j++) {
panvk_copy_dyn_ssbo_desc(dst_set, copy->dstBinding,
copy->dstArrayElement + j,
src_set, copy->srcBinding,
copy->srcArrayElement + j);
}
break;
default:
unreachable("Unsupported descriptor type");
}
}
}
void
panvk_per_arch(UpdateDescriptorSetWithTemplate)(VkDevice _device,
VkDescriptorSet descriptorSet,
VkDescriptorUpdateTemplate descriptorUpdateTemplate,
const void *data)
{
VK_FROM_HANDLE(panvk_device, dev, _device);
VK_FROM_HANDLE(panvk_descriptor_set, set, descriptorSet);
VK_FROM_HANDLE(vk_descriptor_update_template, template,
descriptorUpdateTemplate);
const struct panvk_descriptor_set_layout *layout = set->layout;
for (uint32_t i = 0; i < template->entry_count; i++) {
const struct vk_descriptor_template_entry *entry =
&template->entries[i];
const struct panvk_descriptor_set_binding_layout *binding_layout =
&layout->bindings[entry->binding];
switch (entry->type) {
case VK_DESCRIPTOR_TYPE_SAMPLER:
case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
for (unsigned j = 0; j < entry->array_count; j++) {
const VkDescriptorImageInfo *info =
data + entry->offset + j * entry->stride;
if ((entry->type == VK_DESCRIPTOR_TYPE_SAMPLER ||
entry->type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) &&
!binding_layout->immutable_samplers) {
panvk_write_sampler_desc(dev, set,
entry->binding,
entry->array_element + j,
info);
}
if (entry->type == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ||
entry->type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) {
panvk_write_tex_desc(dev, set,
entry->binding,
entry->array_element + j,
info);
}
}
break;
case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
for (unsigned j = 0; j < entry->array_count; j++) {
const VkDescriptorImageInfo *info =
data + entry->offset + j * entry->stride;
panvk_write_img_desc(dev, set,
entry->binding,
entry->array_element + j,
info);
}
break;
case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
for (unsigned j = 0; j < entry->array_count; j++) {
const VkBufferView *view =
data + entry->offset + j * entry->stride;
panvk_write_tex_buf_desc(dev, set,
entry->binding,
entry->array_element + j,
*view);
}
break;
case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
for (unsigned j = 0; j < entry->array_count; j++) {
const VkBufferView *view =
data + entry->offset + j * entry->stride;
panvk_write_img_buf_desc(dev, set,
entry->binding,
entry->array_element + j,
*view);
}
break;
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
for (unsigned j = 0; j < entry->array_count; j++) {
const VkDescriptorBufferInfo *info =
data + entry->offset + j * entry->stride;
panvk_write_ubo_desc(dev, set,
entry->binding,
entry->array_element + j,
info);
}
break;
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
for (unsigned j = 0; j < entry->array_count; j++) {
const VkDescriptorBufferInfo *info =
data + entry->offset + j * entry->stride;
panvk_write_dyn_ubo_desc(dev, set,
entry->binding,
entry->array_element + j,
info);
}
break;
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
for (unsigned j = 0; j < entry->array_count; j++) {
const VkDescriptorBufferInfo *info =
data + entry->offset + j * entry->stride;
panvk_write_ssbo_desc(dev, set,
entry->binding,
entry->array_element + j,
info);
}
break;
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
for (unsigned j = 0; j < entry->array_count; j++) {
const VkDescriptorBufferInfo *info =
data + entry->offset + j * entry->stride;
panvk_write_dyn_ssbo_desc(dev, set,
entry->binding,
entry->array_element + j,
info);
}
break;
default:
unreachable("Invalid type");
}
}
}