2018-08-08 23:23:57 +01:00
|
|
|
/*
|
|
|
|
* 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
|
2019-01-09 22:16:01 +00:00
|
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
|
|
* DEALINGS IN THE SOFTWARE.
|
2018-08-08 23:23:57 +01:00
|
|
|
*/
|
2019-12-14 06:05:11 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @file
|
|
|
|
*
|
tu: Switch to the bindless descriptor model
Under the bindless model, there are 5 "base" registers programmed with a
64-bit address, and sam/ldib/ldc and so on each specify a base register
and an offset, in units of 16 dwords. The base registers correspond to
descriptor sets in Vulkan. We allocate a buffer at descriptor set
creation time, hopefully outside the main rendering loop, and then
switching descriptor sets is just a matter of programming the base
registers differently. Note, however, that some kinds of descriptors
need to be patched at command recording time, in particular dynamic
UBO's and SSBO's, which need to be patched at CmdBindDescriptorSets
time, and input attachments which need to be patched at draw time based
on the the pipeline that's bound. We reserve the fifth base register
(which seems to be unused by the blob driver) for these, creating a
descriptor set on-the-fly and combining all the dynamic descriptors from
all the different descriptor sets. This way, we never have to copy the
rest of the descriptor set at draw time like the blob seems to do. I
mostly chose to do this because the infrastructure was already there in
the form of dynamic_descriptors, and other drivers (at least radv) don't
cheat either when implementing this.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4358>
2020-03-16 10:49:19 +00:00
|
|
|
* We use the bindless descriptor model, which maps fairly closely to how
|
|
|
|
* Vulkan descriptor sets work. The two exceptions are input attachments and
|
|
|
|
* dynamic descriptors, which have to be patched when recording command
|
|
|
|
* buffers. We reserve an extra descriptor set for these. This descriptor set
|
|
|
|
* contains all the input attachments in the pipeline, in order, and then all
|
|
|
|
* the dynamic descriptors. The dynamic descriptors are stored in the CPU-side
|
|
|
|
* datastructure for each tu_descriptor_set, and then combined into one big
|
|
|
|
* descriptor set at CmdBindDescriptors time/draw time.
|
2019-12-14 06:05:11 +00:00
|
|
|
*/
|
|
|
|
|
2019-01-09 22:16:01 +00:00
|
|
|
#include "tu_private.h"
|
|
|
|
|
2018-08-08 23:23:57 +01:00
|
|
|
#include <assert.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <stdbool.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
|
|
|
|
#include "util/mesa-sha1.h"
|
2021-03-09 18:49:00 +00:00
|
|
|
#include "vk_descriptors.h"
|
2018-08-08 23:23:57 +01:00
|
|
|
#include "vk_util.h"
|
|
|
|
|
2021-07-27 05:49:56 +01:00
|
|
|
static inline uint8_t *
|
|
|
|
pool_base(struct tu_descriptor_pool *pool)
|
|
|
|
{
|
|
|
|
return pool->host_bo ?: pool->bo.map;
|
|
|
|
}
|
|
|
|
|
2019-09-26 04:00:16 +01:00
|
|
|
static uint32_t
|
tu: Switch to the bindless descriptor model
Under the bindless model, there are 5 "base" registers programmed with a
64-bit address, and sam/ldib/ldc and so on each specify a base register
and an offset, in units of 16 dwords. The base registers correspond to
descriptor sets in Vulkan. We allocate a buffer at descriptor set
creation time, hopefully outside the main rendering loop, and then
switching descriptor sets is just a matter of programming the base
registers differently. Note, however, that some kinds of descriptors
need to be patched at command recording time, in particular dynamic
UBO's and SSBO's, which need to be patched at CmdBindDescriptorSets
time, and input attachments which need to be patched at draw time based
on the the pipeline that's bound. We reserve the fifth base register
(which seems to be unused by the blob driver) for these, creating a
descriptor set on-the-fly and combining all the dynamic descriptors from
all the different descriptor sets. This way, we never have to copy the
rest of the descriptor set at draw time like the blob seems to do. I
mostly chose to do this because the infrastructure was already there in
the form of dynamic_descriptors, and other drivers (at least radv) don't
cheat either when implementing this.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4358>
2020-03-16 10:49:19 +00:00
|
|
|
descriptor_size(VkDescriptorType type)
|
2019-09-26 04:00:16 +01:00
|
|
|
{
|
|
|
|
switch (type) {
|
2019-10-07 02:42:27 +01:00
|
|
|
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
|
|
|
|
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
|
|
|
|
case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
|
tu: Switch to the bindless descriptor model
Under the bindless model, there are 5 "base" registers programmed with a
64-bit address, and sam/ldib/ldc and so on each specify a base register
and an offset, in units of 16 dwords. The base registers correspond to
descriptor sets in Vulkan. We allocate a buffer at descriptor set
creation time, hopefully outside the main rendering loop, and then
switching descriptor sets is just a matter of programming the base
registers differently. Note, however, that some kinds of descriptors
need to be patched at command recording time, in particular dynamic
UBO's and SSBO's, which need to be patched at CmdBindDescriptorSets
time, and input attachments which need to be patched at draw time based
on the the pipeline that's bound. We reserve the fifth base register
(which seems to be unused by the blob driver) for these, creating a
descriptor set on-the-fly and combining all the dynamic descriptors from
all the different descriptor sets. This way, we never have to copy the
rest of the descriptor set at draw time like the blob seems to do. I
mostly chose to do this because the infrastructure was already there in
the form of dynamic_descriptors, and other drivers (at least radv) don't
cheat either when implementing this.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4358>
2020-03-16 10:49:19 +00:00
|
|
|
/* These are remapped to the special driver-managed descriptor set,
|
|
|
|
* hence they don't take up any space in the original descriptor set:
|
2020-06-15 04:10:01 +01:00
|
|
|
* Input attachment doesn't use descriptor sets at all
|
tu: Switch to the bindless descriptor model
Under the bindless model, there are 5 "base" registers programmed with a
64-bit address, and sam/ldib/ldc and so on each specify a base register
and an offset, in units of 16 dwords. The base registers correspond to
descriptor sets in Vulkan. We allocate a buffer at descriptor set
creation time, hopefully outside the main rendering loop, and then
switching descriptor sets is just a matter of programming the base
registers differently. Note, however, that some kinds of descriptors
need to be patched at command recording time, in particular dynamic
UBO's and SSBO's, which need to be patched at CmdBindDescriptorSets
time, and input attachments which need to be patched at draw time based
on the the pipeline that's bound. We reserve the fifth base register
(which seems to be unused by the blob driver) for these, creating a
descriptor set on-the-fly and combining all the dynamic descriptors from
all the different descriptor sets. This way, we never have to copy the
rest of the descriptor set at draw time like the blob seems to do. I
mostly chose to do this because the infrastructure was already there in
the form of dynamic_descriptors, and other drivers (at least radv) don't
cheat either when implementing this.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4358>
2020-03-16 10:49:19 +00:00
|
|
|
*/
|
|
|
|
return 0;
|
2019-09-26 04:00:16 +01:00
|
|
|
case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
|
tu: Switch to the bindless descriptor model
Under the bindless model, there are 5 "base" registers programmed with a
64-bit address, and sam/ldib/ldc and so on each specify a base register
and an offset, in units of 16 dwords. The base registers correspond to
descriptor sets in Vulkan. We allocate a buffer at descriptor set
creation time, hopefully outside the main rendering loop, and then
switching descriptor sets is just a matter of programming the base
registers differently. Note, however, that some kinds of descriptors
need to be patched at command recording time, in particular dynamic
UBO's and SSBO's, which need to be patched at CmdBindDescriptorSets
time, and input attachments which need to be patched at draw time based
on the the pipeline that's bound. We reserve the fifth base register
(which seems to be unused by the blob driver) for these, creating a
descriptor set on-the-fly and combining all the dynamic descriptors from
all the different descriptor sets. This way, we never have to copy the
rest of the descriptor set at draw time like the blob seems to do. I
mostly chose to do this because the infrastructure was already there in
the form of dynamic_descriptors, and other drivers (at least radv) don't
cheat either when implementing this.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4358>
2020-03-16 10:49:19 +00:00
|
|
|
/* We make offsets and sizes all 16 dwords, to match how the hardware
|
|
|
|
* interprets indices passed to sample/load/store instructions in
|
|
|
|
* multiples of 16 dwords. This means that "normal" descriptors are all
|
|
|
|
* of size 16, with padding for smaller descriptors like uniform storage
|
|
|
|
* descriptors which are less than 16 dwords. However combined images
|
|
|
|
* and samplers are actually two descriptors, so they have size 2.
|
|
|
|
*/
|
|
|
|
return A6XX_TEX_CONST_DWORDS * 4 * 2;
|
2019-09-26 04:00:16 +01:00
|
|
|
default:
|
tu: Switch to the bindless descriptor model
Under the bindless model, there are 5 "base" registers programmed with a
64-bit address, and sam/ldib/ldc and so on each specify a base register
and an offset, in units of 16 dwords. The base registers correspond to
descriptor sets in Vulkan. We allocate a buffer at descriptor set
creation time, hopefully outside the main rendering loop, and then
switching descriptor sets is just a matter of programming the base
registers differently. Note, however, that some kinds of descriptors
need to be patched at command recording time, in particular dynamic
UBO's and SSBO's, which need to be patched at CmdBindDescriptorSets
time, and input attachments which need to be patched at draw time based
on the the pipeline that's bound. We reserve the fifth base register
(which seems to be unused by the blob driver) for these, creating a
descriptor set on-the-fly and combining all the dynamic descriptors from
all the different descriptor sets. This way, we never have to copy the
rest of the descriptor set at draw time like the blob seems to do. I
mostly chose to do this because the infrastructure was already there in
the form of dynamic_descriptors, and other drivers (at least radv) don't
cheat either when implementing this.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4358>
2020-03-16 10:49:19 +00:00
|
|
|
return A6XX_TEX_CONST_DWORDS * 4;
|
2019-09-26 04:00:16 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-27 05:49:56 +01:00
|
|
|
static uint32_t
|
|
|
|
mutable_descriptor_size(const VkMutableDescriptorTypeListVALVE *list)
|
|
|
|
{
|
|
|
|
uint32_t max_size = 0;
|
|
|
|
|
|
|
|
/* Since we don't support VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER for
|
|
|
|
* mutable descriptors, max_size should be always A6XX_TEX_CONST_DWORDS * 4.
|
|
|
|
* But we leave this as-is and add an assert.
|
|
|
|
*/
|
|
|
|
for (uint32_t i = 0; i < list->descriptorTypeCount; i++) {
|
|
|
|
uint32_t size = descriptor_size(list->pDescriptorTypes[i]);
|
|
|
|
max_size = MAX2(max_size, size);
|
|
|
|
}
|
|
|
|
|
|
|
|
assert(max_size == A6XX_TEX_CONST_DWORDS * 4);
|
|
|
|
|
|
|
|
return max_size;
|
|
|
|
}
|
|
|
|
|
2021-06-07 05:59:32 +01:00
|
|
|
VKAPI_ATTR VkResult VKAPI_CALL
|
2018-08-08 23:23:57 +01:00
|
|
|
tu_CreateDescriptorSetLayout(
|
2018-11-05 06:42:55 +00:00
|
|
|
VkDevice _device,
|
|
|
|
const VkDescriptorSetLayoutCreateInfo *pCreateInfo,
|
|
|
|
const VkAllocationCallbacks *pAllocator,
|
|
|
|
VkDescriptorSetLayout *pSetLayout)
|
2018-08-08 23:23:57 +01:00
|
|
|
{
|
|
|
|
TU_FROM_HANDLE(tu_device, device, _device);
|
|
|
|
struct tu_descriptor_set_layout *set_layout;
|
|
|
|
|
|
|
|
assert(pCreateInfo->sType ==
|
|
|
|
VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO);
|
|
|
|
const VkDescriptorSetLayoutBindingFlagsCreateInfoEXT *variable_flags =
|
2019-01-09 22:16:01 +00:00
|
|
|
vk_find_struct_const(
|
|
|
|
pCreateInfo->pNext,
|
|
|
|
DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO_EXT);
|
2021-07-27 05:49:56 +01:00
|
|
|
const VkMutableDescriptorTypeCreateInfoVALVE *mutable_info =
|
|
|
|
vk_find_struct_const(
|
|
|
|
pCreateInfo->pNext,
|
|
|
|
MUTABLE_DESCRIPTOR_TYPE_CREATE_INFO_VALVE);
|
2018-08-08 23:23:57 +01:00
|
|
|
|
2021-03-29 11:10:46 +01:00
|
|
|
uint32_t num_bindings = 0;
|
2019-10-07 02:42:27 +01:00
|
|
|
uint32_t immutable_sampler_count = 0;
|
2020-04-10 14:19:36 +01:00
|
|
|
uint32_t ycbcr_sampler_count = 0;
|
2019-10-07 02:42:27 +01:00
|
|
|
for (uint32_t j = 0; j < pCreateInfo->bindingCount; j++) {
|
2021-03-29 11:10:46 +01:00
|
|
|
num_bindings = MAX2(num_bindings, pCreateInfo->pBindings[j].binding + 1);
|
2019-10-07 02:42:27 +01:00
|
|
|
if ((pCreateInfo->pBindings[j].descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ||
|
|
|
|
pCreateInfo->pBindings[j].descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER) &&
|
|
|
|
pCreateInfo->pBindings[j].pImmutableSamplers) {
|
|
|
|
immutable_sampler_count += pCreateInfo->pBindings[j].descriptorCount;
|
2020-04-10 14:19:36 +01:00
|
|
|
|
|
|
|
bool has_ycbcr_sampler = false;
|
|
|
|
for (unsigned i = 0; i < pCreateInfo->pBindings[j].descriptorCount; ++i) {
|
|
|
|
if (tu_sampler_from_handle(pCreateInfo->pBindings[j].pImmutableSamplers[i])->ycbcr_sampler)
|
|
|
|
has_ycbcr_sampler = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (has_ycbcr_sampler)
|
|
|
|
ycbcr_sampler_count += pCreateInfo->pBindings[j].descriptorCount;
|
2019-10-07 02:42:27 +01:00
|
|
|
}
|
|
|
|
}
|
2018-08-08 23:23:57 +01:00
|
|
|
|
2020-07-01 04:13:40 +01:00
|
|
|
uint32_t samplers_offset =
|
2021-03-29 11:10:46 +01:00
|
|
|
offsetof(struct tu_descriptor_set_layout, binding[num_bindings]);
|
2020-07-01 04:13:40 +01:00
|
|
|
|
2020-04-10 14:19:36 +01:00
|
|
|
/* note: only need to store TEX_SAMP_DWORDS for immutable samples,
|
|
|
|
* but using struct tu_sampler makes things simpler */
|
|
|
|
uint32_t size = samplers_offset +
|
|
|
|
immutable_sampler_count * sizeof(struct tu_sampler) +
|
|
|
|
ycbcr_sampler_count * sizeof(struct tu_sampler_ycbcr_conversion);
|
2018-08-08 23:23:57 +01:00
|
|
|
|
2022-01-19 15:10:17 +00:00
|
|
|
set_layout = vk_object_zalloc(&device->vk, NULL, size,
|
2020-07-13 04:08:15 +01:00
|
|
|
VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT);
|
2018-08-08 23:23:57 +01:00
|
|
|
if (!set_layout)
|
2021-09-24 21:35:20 +01:00
|
|
|
return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
|
2018-08-08 23:23:57 +01:00
|
|
|
|
|
|
|
set_layout->flags = pCreateInfo->flags;
|
|
|
|
|
tu: Switch to the bindless descriptor model
Under the bindless model, there are 5 "base" registers programmed with a
64-bit address, and sam/ldib/ldc and so on each specify a base register
and an offset, in units of 16 dwords. The base registers correspond to
descriptor sets in Vulkan. We allocate a buffer at descriptor set
creation time, hopefully outside the main rendering loop, and then
switching descriptor sets is just a matter of programming the base
registers differently. Note, however, that some kinds of descriptors
need to be patched at command recording time, in particular dynamic
UBO's and SSBO's, which need to be patched at CmdBindDescriptorSets
time, and input attachments which need to be patched at draw time based
on the the pipeline that's bound. We reserve the fifth base register
(which seems to be unused by the blob driver) for these, creating a
descriptor set on-the-fly and combining all the dynamic descriptors from
all the different descriptor sets. This way, we never have to copy the
rest of the descriptor set at draw time like the blob seems to do. I
mostly chose to do this because the infrastructure was already there in
the form of dynamic_descriptors, and other drivers (at least radv) don't
cheat either when implementing this.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4358>
2020-03-16 10:49:19 +00:00
|
|
|
/* We just allocate all the immutable samplers at the end of the struct */
|
2021-03-29 11:10:46 +01:00
|
|
|
struct tu_sampler *samplers = (void*) &set_layout->binding[num_bindings];
|
2020-04-10 14:19:36 +01:00
|
|
|
struct tu_sampler_ycbcr_conversion *ycbcr_samplers =
|
|
|
|
(void*) &samplers[immutable_sampler_count];
|
2018-08-08 23:23:57 +01:00
|
|
|
|
2021-03-28 21:46:19 +01:00
|
|
|
VkDescriptorSetLayoutBinding *bindings = NULL;
|
|
|
|
VkResult result = vk_create_sorted_bindings(
|
|
|
|
pCreateInfo->pBindings, pCreateInfo->bindingCount, &bindings);
|
|
|
|
if (result != VK_SUCCESS) {
|
2020-07-13 04:08:15 +01:00
|
|
|
vk_object_free(&device->vk, pAllocator, set_layout);
|
2021-09-24 21:35:20 +01:00
|
|
|
return vk_error(device, result);
|
2018-08-08 23:23:57 +01:00
|
|
|
}
|
|
|
|
|
2022-01-19 15:10:17 +00:00
|
|
|
set_layout->ref_cnt = 1;
|
2021-03-29 11:10:46 +01:00
|
|
|
set_layout->binding_count = num_bindings;
|
2018-08-08 23:23:57 +01:00
|
|
|
set_layout->shader_stages = 0;
|
|
|
|
set_layout->has_immutable_samplers = false;
|
|
|
|
set_layout->size = 0;
|
tu: Switch to the bindless descriptor model
Under the bindless model, there are 5 "base" registers programmed with a
64-bit address, and sam/ldib/ldc and so on each specify a base register
and an offset, in units of 16 dwords. The base registers correspond to
descriptor sets in Vulkan. We allocate a buffer at descriptor set
creation time, hopefully outside the main rendering loop, and then
switching descriptor sets is just a matter of programming the base
registers differently. Note, however, that some kinds of descriptors
need to be patched at command recording time, in particular dynamic
UBO's and SSBO's, which need to be patched at CmdBindDescriptorSets
time, and input attachments which need to be patched at draw time based
on the the pipeline that's bound. We reserve the fifth base register
(which seems to be unused by the blob driver) for these, creating a
descriptor set on-the-fly and combining all the dynamic descriptors from
all the different descriptor sets. This way, we never have to copy the
rest of the descriptor set at draw time like the blob seems to do. I
mostly chose to do this because the infrastructure was already there in
the form of dynamic_descriptors, and other drivers (at least radv) don't
cheat either when implementing this.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4358>
2020-03-16 10:49:19 +00:00
|
|
|
set_layout->dynamic_ubo = 0;
|
2018-08-08 23:23:57 +01:00
|
|
|
|
|
|
|
uint32_t dynamic_offset_count = 0;
|
|
|
|
|
|
|
|
for (uint32_t j = 0; j < pCreateInfo->bindingCount; j++) {
|
|
|
|
const VkDescriptorSetLayoutBinding *binding = bindings + j;
|
|
|
|
uint32_t b = binding->binding;
|
2019-10-07 02:42:27 +01:00
|
|
|
|
2018-08-08 23:23:57 +01:00
|
|
|
set_layout->binding[b].type = binding->descriptorType;
|
|
|
|
set_layout->binding[b].array_size = binding->descriptorCount;
|
|
|
|
set_layout->binding[b].offset = set_layout->size;
|
|
|
|
set_layout->binding[b].dynamic_offset_offset = dynamic_offset_count;
|
2020-03-23 16:23:32 +00:00
|
|
|
set_layout->binding[b].shader_stages = binding->stageFlags;
|
2018-08-08 23:23:57 +01:00
|
|
|
|
2021-07-27 05:49:56 +01:00
|
|
|
if (binding->descriptorType == VK_DESCRIPTOR_TYPE_MUTABLE_VALVE) {
|
|
|
|
/* For mutable descriptor types we must allocate a size that fits the
|
|
|
|
* largest descriptor type that the binding can mutate to.
|
|
|
|
*/
|
|
|
|
set_layout->binding[b].size =
|
|
|
|
mutable_descriptor_size(&mutable_info->pMutableDescriptorTypeLists[j]);
|
|
|
|
} else {
|
|
|
|
set_layout->binding[b].size = descriptor_size(binding->descriptorType);
|
|
|
|
}
|
|
|
|
|
2018-08-08 23:23:57 +01:00
|
|
|
if (variable_flags && binding->binding < variable_flags->bindingCount &&
|
|
|
|
(variable_flags->pBindingFlags[binding->binding] &
|
|
|
|
VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT_EXT)) {
|
2019-01-09 22:16:01 +00:00
|
|
|
assert(!binding->pImmutableSamplers); /* Terribly ill defined how
|
|
|
|
many samplers are valid */
|
2021-03-29 11:10:46 +01:00
|
|
|
assert(binding->binding == num_bindings - 1);
|
2018-08-08 23:23:57 +01:00
|
|
|
|
|
|
|
set_layout->has_variable_descriptors = true;
|
|
|
|
}
|
|
|
|
|
2019-10-07 02:42:27 +01:00
|
|
|
if ((binding->descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ||
|
|
|
|
binding->descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER) &&
|
|
|
|
binding->pImmutableSamplers) {
|
|
|
|
set_layout->binding[b].immutable_samplers_offset = samplers_offset;
|
|
|
|
set_layout->has_immutable_samplers = true;
|
|
|
|
|
|
|
|
for (uint32_t i = 0; i < binding->descriptorCount; i++)
|
|
|
|
samplers[i] = *tu_sampler_from_handle(binding->pImmutableSamplers[i]);
|
|
|
|
|
|
|
|
samplers += binding->descriptorCount;
|
|
|
|
samplers_offset += sizeof(struct tu_sampler) * binding->descriptorCount;
|
2020-04-10 14:19:36 +01:00
|
|
|
|
|
|
|
bool has_ycbcr_sampler = false;
|
|
|
|
for (unsigned i = 0; i < pCreateInfo->pBindings[j].descriptorCount; ++i) {
|
|
|
|
if (tu_sampler_from_handle(binding->pImmutableSamplers[i])->ycbcr_sampler)
|
|
|
|
has_ycbcr_sampler = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (has_ycbcr_sampler) {
|
|
|
|
set_layout->binding[b].ycbcr_samplers_offset =
|
|
|
|
(const char*)ycbcr_samplers - (const char*)set_layout;
|
|
|
|
for (uint32_t i = 0; i < binding->descriptorCount; i++) {
|
|
|
|
struct tu_sampler *sampler = tu_sampler_from_handle(binding->pImmutableSamplers[i]);
|
|
|
|
if (sampler->ycbcr_sampler)
|
|
|
|
ycbcr_samplers[i] = *sampler->ycbcr_sampler;
|
|
|
|
else
|
|
|
|
ycbcr_samplers[i].ycbcr_model = VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY;
|
|
|
|
}
|
|
|
|
ycbcr_samplers += binding->descriptorCount;
|
|
|
|
} else {
|
|
|
|
set_layout->binding[b].ycbcr_samplers_offset = 0;
|
|
|
|
}
|
2019-10-07 02:42:27 +01:00
|
|
|
}
|
|
|
|
|
2018-08-08 23:23:57 +01:00
|
|
|
set_layout->size +=
|
2019-01-09 22:16:01 +00:00
|
|
|
binding->descriptorCount * set_layout->binding[b].size;
|
tu: Switch to the bindless descriptor model
Under the bindless model, there are 5 "base" registers programmed with a
64-bit address, and sam/ldib/ldc and so on each specify a base register
and an offset, in units of 16 dwords. The base registers correspond to
descriptor sets in Vulkan. We allocate a buffer at descriptor set
creation time, hopefully outside the main rendering loop, and then
switching descriptor sets is just a matter of programming the base
registers differently. Note, however, that some kinds of descriptors
need to be patched at command recording time, in particular dynamic
UBO's and SSBO's, which need to be patched at CmdBindDescriptorSets
time, and input attachments which need to be patched at draw time based
on the the pipeline that's bound. We reserve the fifth base register
(which seems to be unused by the blob driver) for these, creating a
descriptor set on-the-fly and combining all the dynamic descriptors from
all the different descriptor sets. This way, we never have to copy the
rest of the descriptor set at draw time like the blob seems to do. I
mostly chose to do this because the infrastructure was already there in
the form of dynamic_descriptors, and other drivers (at least radv) don't
cheat either when implementing this.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4358>
2020-03-16 10:49:19 +00:00
|
|
|
if (binding->descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC ||
|
|
|
|
binding->descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) {
|
|
|
|
if (binding->descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) {
|
|
|
|
STATIC_ASSERT(MAX_DYNAMIC_BUFFERS <= 8 * sizeof(set_layout->dynamic_ubo));
|
|
|
|
set_layout->dynamic_ubo |=
|
|
|
|
((1u << binding->descriptorCount) - 1) << dynamic_offset_count;
|
|
|
|
}
|
|
|
|
|
|
|
|
dynamic_offset_count += binding->descriptorCount;
|
|
|
|
}
|
2020-06-15 04:10:01 +01:00
|
|
|
|
2018-08-08 23:23:57 +01:00
|
|
|
set_layout->shader_stages |= binding->stageFlags;
|
|
|
|
}
|
|
|
|
|
|
|
|
free(bindings);
|
|
|
|
|
|
|
|
set_layout->dynamic_offset_count = dynamic_offset_count;
|
|
|
|
|
|
|
|
*pSetLayout = tu_descriptor_set_layout_to_handle(set_layout);
|
|
|
|
|
|
|
|
return VK_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2021-06-07 05:59:32 +01:00
|
|
|
VKAPI_ATTR void VKAPI_CALL
|
2018-08-08 23:23:57 +01:00
|
|
|
tu_DestroyDescriptorSetLayout(VkDevice _device,
|
2018-11-05 06:42:55 +00:00
|
|
|
VkDescriptorSetLayout _set_layout,
|
|
|
|
const VkAllocationCallbacks *pAllocator)
|
2018-08-08 23:23:57 +01:00
|
|
|
{
|
|
|
|
TU_FROM_HANDLE(tu_device, device, _device);
|
|
|
|
TU_FROM_HANDLE(tu_descriptor_set_layout, set_layout, _set_layout);
|
|
|
|
|
|
|
|
if (!set_layout)
|
|
|
|
return;
|
|
|
|
|
2022-01-19 15:10:17 +00:00
|
|
|
tu_descriptor_set_layout_unref(device, set_layout);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
tu_descriptor_set_layout_destroy(struct tu_device *device,
|
|
|
|
struct tu_descriptor_set_layout *layout)
|
|
|
|
{
|
|
|
|
assert(layout->ref_cnt == 0);
|
|
|
|
vk_object_free(&device->vk, NULL, layout);
|
2018-08-08 23:23:57 +01:00
|
|
|
}
|
|
|
|
|
2021-06-07 05:59:32 +01:00
|
|
|
VKAPI_ATTR void VKAPI_CALL
|
2018-08-08 23:23:57 +01:00
|
|
|
tu_GetDescriptorSetLayoutSupport(
|
2018-11-05 06:42:55 +00:00
|
|
|
VkDevice device,
|
|
|
|
const VkDescriptorSetLayoutCreateInfo *pCreateInfo,
|
|
|
|
VkDescriptorSetLayoutSupport *pSupport)
|
2018-08-08 23:23:57 +01:00
|
|
|
{
|
2021-03-28 21:46:19 +01:00
|
|
|
VkDescriptorSetLayoutBinding *bindings = NULL;
|
|
|
|
VkResult result = vk_create_sorted_bindings(
|
|
|
|
pCreateInfo->pBindings, pCreateInfo->bindingCount, &bindings);
|
|
|
|
if (result != VK_SUCCESS) {
|
2018-08-08 23:23:57 +01:00
|
|
|
pSupport->supported = false;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const VkDescriptorSetLayoutBindingFlagsCreateInfoEXT *variable_flags =
|
2019-01-09 22:16:01 +00:00
|
|
|
vk_find_struct_const(
|
|
|
|
pCreateInfo->pNext,
|
|
|
|
DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO_EXT);
|
2018-08-08 23:23:57 +01:00
|
|
|
VkDescriptorSetVariableDescriptorCountLayoutSupportEXT *variable_count =
|
2019-01-09 22:16:01 +00:00
|
|
|
vk_find_struct(
|
|
|
|
(void *) pCreateInfo->pNext,
|
|
|
|
DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_LAYOUT_SUPPORT_EXT);
|
2021-07-27 05:49:56 +01:00
|
|
|
const VkMutableDescriptorTypeCreateInfoVALVE *mutable_info =
|
|
|
|
vk_find_struct_const(
|
|
|
|
pCreateInfo->pNext,
|
|
|
|
MUTABLE_DESCRIPTOR_TYPE_CREATE_INFO_VALVE);
|
|
|
|
|
2018-08-08 23:23:57 +01:00
|
|
|
if (variable_count) {
|
|
|
|
variable_count->maxVariableDescriptorCount = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool supported = true;
|
|
|
|
uint64_t size = 0;
|
|
|
|
for (uint32_t i = 0; i < pCreateInfo->bindingCount; i++) {
|
|
|
|
const VkDescriptorSetLayoutBinding *binding = bindings + i;
|
|
|
|
|
2021-07-27 05:49:56 +01:00
|
|
|
uint64_t descriptor_sz;
|
|
|
|
|
|
|
|
if (binding->descriptorType == VK_DESCRIPTOR_TYPE_MUTABLE_VALVE) {
|
|
|
|
const VkMutableDescriptorTypeListVALVE *list =
|
|
|
|
&mutable_info->pMutableDescriptorTypeLists[i];
|
|
|
|
|
|
|
|
for (uint32_t j = 0; j < list->descriptorTypeCount; j++) {
|
|
|
|
/* Don't support the input attachement and combined image sampler type
|
|
|
|
* for mutable descriptors */
|
|
|
|
if (list->pDescriptorTypes[j] == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT ||
|
|
|
|
list->pDescriptorTypes[j] == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) {
|
|
|
|
supported = false;
|
2021-07-30 21:00:52 +01:00
|
|
|
goto out;
|
2021-07-27 05:49:56 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
descriptor_sz =
|
|
|
|
mutable_descriptor_size(&mutable_info->pMutableDescriptorTypeLists[i]);
|
|
|
|
} else {
|
|
|
|
descriptor_sz = descriptor_size(binding->descriptorType);
|
|
|
|
}
|
2019-09-26 04:00:16 +01:00
|
|
|
uint64_t descriptor_alignment = 8;
|
2018-08-08 23:23:57 +01:00
|
|
|
|
2020-04-16 20:44:06 +01:00
|
|
|
if (size && !ALIGN_POT(size, descriptor_alignment)) {
|
2018-08-08 23:23:57 +01:00
|
|
|
supported = false;
|
|
|
|
}
|
2020-04-16 20:44:06 +01:00
|
|
|
size = ALIGN_POT(size, descriptor_alignment);
|
2018-08-08 23:23:57 +01:00
|
|
|
|
|
|
|
uint64_t max_count = UINT64_MAX;
|
2019-09-26 04:00:16 +01:00
|
|
|
if (descriptor_sz)
|
|
|
|
max_count = (UINT64_MAX - size) / descriptor_sz;
|
2018-08-08 23:23:57 +01:00
|
|
|
|
|
|
|
if (max_count < binding->descriptorCount) {
|
|
|
|
supported = false;
|
|
|
|
}
|
2021-07-27 05:49:56 +01:00
|
|
|
|
2018-08-08 23:23:57 +01:00
|
|
|
if (variable_flags && binding->binding < variable_flags->bindingCount &&
|
|
|
|
variable_count &&
|
|
|
|
(variable_flags->pBindingFlags[binding->binding] &
|
|
|
|
VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT_EXT)) {
|
|
|
|
variable_count->maxVariableDescriptorCount =
|
2019-01-09 22:16:01 +00:00
|
|
|
MIN2(UINT32_MAX, max_count);
|
2018-08-08 23:23:57 +01:00
|
|
|
}
|
2019-09-26 04:00:16 +01:00
|
|
|
size += binding->descriptorCount * descriptor_sz;
|
2018-08-08 23:23:57 +01:00
|
|
|
}
|
|
|
|
|
2021-07-30 21:00:52 +01:00
|
|
|
out:
|
2018-08-08 23:23:57 +01:00
|
|
|
free(bindings);
|
|
|
|
|
|
|
|
pSupport->supported = supported;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Pipeline layouts. These have nothing to do with the pipeline. They are
|
|
|
|
* just multiple descriptor set layouts pasted together.
|
|
|
|
*/
|
|
|
|
|
2021-06-07 05:59:32 +01:00
|
|
|
VKAPI_ATTR VkResult VKAPI_CALL
|
2018-08-08 23:23:57 +01:00
|
|
|
tu_CreatePipelineLayout(VkDevice _device,
|
2018-11-05 06:42:55 +00:00
|
|
|
const VkPipelineLayoutCreateInfo *pCreateInfo,
|
|
|
|
const VkAllocationCallbacks *pAllocator,
|
|
|
|
VkPipelineLayout *pPipelineLayout)
|
2018-08-08 23:23:57 +01:00
|
|
|
{
|
|
|
|
TU_FROM_HANDLE(tu_device, device, _device);
|
|
|
|
struct tu_pipeline_layout *layout;
|
|
|
|
|
2019-01-09 22:16:01 +00:00
|
|
|
assert(pCreateInfo->sType ==
|
|
|
|
VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO);
|
2018-08-08 23:23:57 +01:00
|
|
|
|
2020-07-13 04:08:15 +01:00
|
|
|
layout = vk_object_alloc(&device->vk, pAllocator, sizeof(*layout),
|
|
|
|
VK_OBJECT_TYPE_PIPELINE_LAYOUT);
|
2018-08-08 23:23:57 +01:00
|
|
|
if (layout == NULL)
|
2021-09-24 21:35:20 +01:00
|
|
|
return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
|
2018-08-08 23:23:57 +01:00
|
|
|
|
|
|
|
layout->num_sets = pCreateInfo->setLayoutCount;
|
tu: Switch to the bindless descriptor model
Under the bindless model, there are 5 "base" registers programmed with a
64-bit address, and sam/ldib/ldc and so on each specify a base register
and an offset, in units of 16 dwords. The base registers correspond to
descriptor sets in Vulkan. We allocate a buffer at descriptor set
creation time, hopefully outside the main rendering loop, and then
switching descriptor sets is just a matter of programming the base
registers differently. Note, however, that some kinds of descriptors
need to be patched at command recording time, in particular dynamic
UBO's and SSBO's, which need to be patched at CmdBindDescriptorSets
time, and input attachments which need to be patched at draw time based
on the the pipeline that's bound. We reserve the fifth base register
(which seems to be unused by the blob driver) for these, creating a
descriptor set on-the-fly and combining all the dynamic descriptors from
all the different descriptor sets. This way, we never have to copy the
rest of the descriptor set at draw time like the blob seems to do. I
mostly chose to do this because the infrastructure was already there in
the form of dynamic_descriptors, and other drivers (at least radv) don't
cheat either when implementing this.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4358>
2020-03-16 10:49:19 +00:00
|
|
|
layout->dynamic_offset_count = 0;
|
2018-08-08 23:23:57 +01:00
|
|
|
|
2020-06-15 04:10:01 +01:00
|
|
|
unsigned dynamic_offset_count = 0;
|
2018-08-08 23:23:57 +01:00
|
|
|
|
|
|
|
for (uint32_t set = 0; set < pCreateInfo->setLayoutCount; set++) {
|
2019-01-09 22:16:01 +00:00
|
|
|
TU_FROM_HANDLE(tu_descriptor_set_layout, set_layout,
|
|
|
|
pCreateInfo->pSetLayouts[set]);
|
2018-08-08 23:23:57 +01:00
|
|
|
layout->set[set].layout = set_layout;
|
2022-01-19 15:10:17 +00:00
|
|
|
tu_descriptor_set_layout_ref(set_layout);
|
|
|
|
|
2018-08-08 23:23:57 +01:00
|
|
|
layout->set[set].dynamic_offset_start = dynamic_offset_count;
|
tu: Switch to the bindless descriptor model
Under the bindless model, there are 5 "base" registers programmed with a
64-bit address, and sam/ldib/ldc and so on each specify a base register
and an offset, in units of 16 dwords. The base registers correspond to
descriptor sets in Vulkan. We allocate a buffer at descriptor set
creation time, hopefully outside the main rendering loop, and then
switching descriptor sets is just a matter of programming the base
registers differently. Note, however, that some kinds of descriptors
need to be patched at command recording time, in particular dynamic
UBO's and SSBO's, which need to be patched at CmdBindDescriptorSets
time, and input attachments which need to be patched at draw time based
on the the pipeline that's bound. We reserve the fifth base register
(which seems to be unused by the blob driver) for these, creating a
descriptor set on-the-fly and combining all the dynamic descriptors from
all the different descriptor sets. This way, we never have to copy the
rest of the descriptor set at draw time like the blob seems to do. I
mostly chose to do this because the infrastructure was already there in
the form of dynamic_descriptors, and other drivers (at least radv) don't
cheat either when implementing this.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4358>
2020-03-16 10:49:19 +00:00
|
|
|
dynamic_offset_count += set_layout->dynamic_offset_count;
|
2018-08-08 23:23:57 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
layout->dynamic_offset_count = dynamic_offset_count;
|
|
|
|
layout->push_constant_size = 0;
|
|
|
|
|
|
|
|
for (unsigned i = 0; i < pCreateInfo->pushConstantRangeCount; ++i) {
|
|
|
|
const VkPushConstantRange *range = pCreateInfo->pPushConstantRanges + i;
|
|
|
|
layout->push_constant_size =
|
2019-01-09 22:16:01 +00:00
|
|
|
MAX2(layout->push_constant_size, range->offset + range->size);
|
2018-08-08 23:23:57 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
layout->push_constant_size = align(layout->push_constant_size, 16);
|
|
|
|
*pPipelineLayout = tu_pipeline_layout_to_handle(layout);
|
|
|
|
|
|
|
|
return VK_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2021-06-07 05:59:32 +01:00
|
|
|
VKAPI_ATTR void VKAPI_CALL
|
2018-08-08 23:23:57 +01:00
|
|
|
tu_DestroyPipelineLayout(VkDevice _device,
|
2018-11-05 06:42:55 +00:00
|
|
|
VkPipelineLayout _pipelineLayout,
|
|
|
|
const VkAllocationCallbacks *pAllocator)
|
2018-08-08 23:23:57 +01:00
|
|
|
{
|
|
|
|
TU_FROM_HANDLE(tu_device, device, _device);
|
|
|
|
TU_FROM_HANDLE(tu_pipeline_layout, pipeline_layout, _pipelineLayout);
|
|
|
|
|
|
|
|
if (!pipeline_layout)
|
|
|
|
return;
|
2020-07-13 04:08:15 +01:00
|
|
|
|
2022-01-19 15:10:17 +00:00
|
|
|
for (uint32_t i = 0; i < pipeline_layout->num_sets; i++)
|
|
|
|
tu_descriptor_set_layout_unref(device, pipeline_layout->set[i].layout);
|
|
|
|
|
2020-07-13 04:08:15 +01:00
|
|
|
vk_object_free(&device->vk, pAllocator, pipeline_layout);
|
2018-08-08 23:23:57 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#define EMPTY 1
|
|
|
|
|
2019-09-26 04:00:16 +01:00
|
|
|
static VkResult
|
|
|
|
tu_descriptor_set_create(struct tu_device *device,
|
|
|
|
struct tu_descriptor_pool *pool,
|
2022-01-19 15:10:17 +00:00
|
|
|
struct tu_descriptor_set_layout *layout,
|
2019-09-26 04:00:16 +01:00
|
|
|
const uint32_t *variable_count,
|
|
|
|
struct tu_descriptor_set **out_set)
|
|
|
|
{
|
|
|
|
struct tu_descriptor_set *set;
|
2020-09-11 15:26:40 +01:00
|
|
|
unsigned dynamic_offset = sizeof(struct tu_descriptor_set);
|
tu: Switch to the bindless descriptor model
Under the bindless model, there are 5 "base" registers programmed with a
64-bit address, and sam/ldib/ldc and so on each specify a base register
and an offset, in units of 16 dwords. The base registers correspond to
descriptor sets in Vulkan. We allocate a buffer at descriptor set
creation time, hopefully outside the main rendering loop, and then
switching descriptor sets is just a matter of programming the base
registers differently. Note, however, that some kinds of descriptors
need to be patched at command recording time, in particular dynamic
UBO's and SSBO's, which need to be patched at CmdBindDescriptorSets
time, and input attachments which need to be patched at draw time based
on the the pipeline that's bound. We reserve the fifth base register
(which seems to be unused by the blob driver) for these, creating a
descriptor set on-the-fly and combining all the dynamic descriptors from
all the different descriptor sets. This way, we never have to copy the
rest of the descriptor set at draw time like the blob seems to do. I
mostly chose to do this because the infrastructure was already there in
the form of dynamic_descriptors, and other drivers (at least radv) don't
cheat either when implementing this.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4358>
2020-03-16 10:49:19 +00:00
|
|
|
unsigned mem_size = dynamic_offset +
|
2020-06-15 04:10:01 +01:00
|
|
|
A6XX_TEX_CONST_DWORDS * 4 * layout->dynamic_offset_count;
|
2019-09-26 04:00:16 +01:00
|
|
|
|
|
|
|
if (pool->host_memory_base) {
|
|
|
|
if (pool->host_memory_end - pool->host_memory_ptr < mem_size)
|
2021-09-24 21:35:20 +01:00
|
|
|
return vk_error(device, VK_ERROR_OUT_OF_POOL_MEMORY);
|
2019-09-26 04:00:16 +01:00
|
|
|
|
|
|
|
set = (struct tu_descriptor_set*)pool->host_memory_ptr;
|
|
|
|
pool->host_memory_ptr += mem_size;
|
|
|
|
} else {
|
2020-07-13 04:08:15 +01:00
|
|
|
set = vk_alloc2(&device->vk.alloc, NULL, mem_size, 8,
|
2019-09-26 04:00:16 +01:00
|
|
|
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
|
|
|
|
|
|
|
|
if (!set)
|
2021-09-24 21:35:20 +01:00
|
|
|
return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
|
2019-09-26 04:00:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
memset(set, 0, mem_size);
|
2020-07-13 04:08:15 +01:00
|
|
|
vk_object_base_init(&device->vk, &set->base, VK_OBJECT_TYPE_DESCRIPTOR_SET);
|
2019-09-26 04:00:16 +01:00
|
|
|
|
2020-06-15 04:10:01 +01:00
|
|
|
if (layout->dynamic_offset_count) {
|
tu: Switch to the bindless descriptor model
Under the bindless model, there are 5 "base" registers programmed with a
64-bit address, and sam/ldib/ldc and so on each specify a base register
and an offset, in units of 16 dwords. The base registers correspond to
descriptor sets in Vulkan. We allocate a buffer at descriptor set
creation time, hopefully outside the main rendering loop, and then
switching descriptor sets is just a matter of programming the base
registers differently. Note, however, that some kinds of descriptors
need to be patched at command recording time, in particular dynamic
UBO's and SSBO's, which need to be patched at CmdBindDescriptorSets
time, and input attachments which need to be patched at draw time based
on the the pipeline that's bound. We reserve the fifth base register
(which seems to be unused by the blob driver) for these, creating a
descriptor set on-the-fly and combining all the dynamic descriptors from
all the different descriptor sets. This way, we never have to copy the
rest of the descriptor set at draw time like the blob seems to do. I
mostly chose to do this because the infrastructure was already there in
the form of dynamic_descriptors, and other drivers (at least radv) don't
cheat either when implementing this.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4358>
2020-03-16 10:49:19 +00:00
|
|
|
set->dynamic_descriptors = (uint32_t *)((uint8_t*)set + dynamic_offset);
|
2019-09-26 04:00:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
set->layout = layout;
|
tu: Switch to the bindless descriptor model
Under the bindless model, there are 5 "base" registers programmed with a
64-bit address, and sam/ldib/ldc and so on each specify a base register
and an offset, in units of 16 dwords. The base registers correspond to
descriptor sets in Vulkan. We allocate a buffer at descriptor set
creation time, hopefully outside the main rendering loop, and then
switching descriptor sets is just a matter of programming the base
registers differently. Note, however, that some kinds of descriptors
need to be patched at command recording time, in particular dynamic
UBO's and SSBO's, which need to be patched at CmdBindDescriptorSets
time, and input attachments which need to be patched at draw time based
on the the pipeline that's bound. We reserve the fifth base register
(which seems to be unused by the blob driver) for these, creating a
descriptor set on-the-fly and combining all the dynamic descriptors from
all the different descriptor sets. This way, we never have to copy the
rest of the descriptor set at draw time like the blob seems to do. I
mostly chose to do this because the infrastructure was already there in
the form of dynamic_descriptors, and other drivers (at least radv) don't
cheat either when implementing this.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4358>
2020-03-16 10:49:19 +00:00
|
|
|
set->pool = pool;
|
2019-09-26 04:00:16 +01:00
|
|
|
uint32_t layout_size = layout->size;
|
|
|
|
if (variable_count) {
|
|
|
|
assert(layout->has_variable_descriptors);
|
|
|
|
uint32_t stride = layout->binding[layout->binding_count - 1].size;
|
|
|
|
layout_size = layout->binding[layout->binding_count - 1].offset +
|
|
|
|
*variable_count * stride;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (layout_size) {
|
|
|
|
set->size = layout_size;
|
|
|
|
|
|
|
|
if (!pool->host_memory_base && pool->entry_count == pool->max_entry_count) {
|
2020-07-13 04:08:15 +01:00
|
|
|
vk_object_free(&device->vk, NULL, set);
|
2021-09-24 21:35:20 +01:00
|
|
|
return vk_error(device, VK_ERROR_OUT_OF_POOL_MEMORY);
|
2019-09-26 04:00:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* try to allocate linearly first, so that we don't spend
|
|
|
|
* time looking for gaps if the app only allocates &
|
|
|
|
* resets via the pool. */
|
|
|
|
if (pool->current_offset + layout_size <= pool->size) {
|
2021-07-27 05:49:56 +01:00
|
|
|
set->mapped_ptr = (uint32_t*)(pool_base(pool) + pool->current_offset);
|
|
|
|
set->va = pool->host_bo ? 0 : pool->bo.iova + pool->current_offset;
|
|
|
|
|
2019-09-26 04:00:16 +01:00
|
|
|
if (!pool->host_memory_base) {
|
|
|
|
pool->entries[pool->entry_count].offset = pool->current_offset;
|
|
|
|
pool->entries[pool->entry_count].size = layout_size;
|
|
|
|
pool->entries[pool->entry_count].set = set;
|
|
|
|
pool->entry_count++;
|
|
|
|
}
|
|
|
|
pool->current_offset += layout_size;
|
|
|
|
} else if (!pool->host_memory_base) {
|
|
|
|
uint64_t offset = 0;
|
|
|
|
int index;
|
|
|
|
|
|
|
|
for (index = 0; index < pool->entry_count; ++index) {
|
|
|
|
if (pool->entries[index].offset - offset >= layout_size)
|
|
|
|
break;
|
|
|
|
offset = pool->entries[index].offset + pool->entries[index].size;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pool->size - offset < layout_size) {
|
2020-07-13 04:08:15 +01:00
|
|
|
vk_object_free(&device->vk, NULL, set);
|
2021-09-24 21:35:20 +01:00
|
|
|
return vk_error(device, VK_ERROR_OUT_OF_POOL_MEMORY);
|
2019-09-26 04:00:16 +01:00
|
|
|
}
|
|
|
|
|
2021-07-27 05:49:56 +01:00
|
|
|
set->mapped_ptr = (uint32_t*)(pool_base(pool) + offset);
|
|
|
|
set->va = pool->host_bo ? 0 : pool->bo.iova + offset;
|
|
|
|
|
2019-09-26 04:00:16 +01:00
|
|
|
memmove(&pool->entries[index + 1], &pool->entries[index],
|
|
|
|
sizeof(pool->entries[0]) * (pool->entry_count - index));
|
|
|
|
pool->entries[index].offset = offset;
|
|
|
|
pool->entries[index].size = layout_size;
|
|
|
|
pool->entries[index].set = set;
|
|
|
|
pool->entry_count++;
|
|
|
|
} else
|
2021-09-24 21:35:20 +01:00
|
|
|
return vk_error(device, VK_ERROR_OUT_OF_POOL_MEMORY);
|
2019-09-26 04:00:16 +01:00
|
|
|
}
|
|
|
|
|
2020-03-24 17:00:21 +00:00
|
|
|
if (layout->has_immutable_samplers) {
|
|
|
|
for (unsigned i = 0; i < layout->binding_count; ++i) {
|
|
|
|
if (!layout->binding[i].immutable_samplers_offset)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
unsigned offset = layout->binding[i].offset / 4;
|
|
|
|
if (layout->binding[i].type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
|
|
|
|
offset += A6XX_TEX_CONST_DWORDS;
|
|
|
|
|
|
|
|
const struct tu_sampler *samplers =
|
|
|
|
(const struct tu_sampler *)((const char *)layout +
|
|
|
|
layout->binding[i].immutable_samplers_offset);
|
|
|
|
for (unsigned j = 0; j < layout->binding[i].array_size; ++j) {
|
2020-04-10 14:19:36 +01:00
|
|
|
memcpy(set->mapped_ptr + offset, samplers[j].descriptor,
|
|
|
|
sizeof(samplers[j].descriptor));
|
2020-03-24 17:00:21 +00:00
|
|
|
offset += layout->binding[i].size / 4;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-19 15:10:17 +00:00
|
|
|
tu_descriptor_set_layout_ref(layout);
|
2022-01-27 14:04:06 +00:00
|
|
|
list_addtail(&set->pool_link, &pool->desc_sets);
|
2022-01-19 15:10:17 +00:00
|
|
|
|
2019-09-26 04:00:16 +01:00
|
|
|
*out_set = set;
|
|
|
|
return VK_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
tu_descriptor_set_destroy(struct tu_device *device,
|
|
|
|
struct tu_descriptor_pool *pool,
|
|
|
|
struct tu_descriptor_set *set,
|
|
|
|
bool free_bo)
|
|
|
|
{
|
|
|
|
assert(!pool->host_memory_base);
|
|
|
|
|
|
|
|
if (free_bo && set->size && !pool->host_memory_base) {
|
2021-07-27 05:49:56 +01:00
|
|
|
uint32_t offset = (uint8_t*)set->mapped_ptr - pool_base(pool);
|
|
|
|
|
2019-09-26 04:00:16 +01:00
|
|
|
for (int i = 0; i < pool->entry_count; ++i) {
|
|
|
|
if (pool->entries[i].offset == offset) {
|
|
|
|
memmove(&pool->entries[i], &pool->entries[i+1],
|
|
|
|
sizeof(pool->entries[i]) * (pool->entry_count - i - 1));
|
|
|
|
--pool->entry_count;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-07-13 04:08:15 +01:00
|
|
|
|
2022-01-27 14:04:06 +00:00
|
|
|
list_del(&set->pool_link);
|
|
|
|
|
2020-07-13 04:08:15 +01:00
|
|
|
vk_object_free(&device->vk, NULL, set);
|
2019-09-26 04:00:16 +01:00
|
|
|
}
|
|
|
|
|
2021-06-07 05:59:32 +01:00
|
|
|
VKAPI_ATTR VkResult VKAPI_CALL
|
2018-08-08 23:23:57 +01:00
|
|
|
tu_CreateDescriptorPool(VkDevice _device,
|
2018-11-05 06:42:55 +00:00
|
|
|
const VkDescriptorPoolCreateInfo *pCreateInfo,
|
|
|
|
const VkAllocationCallbacks *pAllocator,
|
|
|
|
VkDescriptorPool *pDescriptorPool)
|
2018-08-08 23:23:57 +01:00
|
|
|
{
|
|
|
|
TU_FROM_HANDLE(tu_device, device, _device);
|
2019-09-26 04:00:16 +01:00
|
|
|
struct tu_descriptor_pool *pool;
|
|
|
|
uint64_t size = sizeof(struct tu_descriptor_pool);
|
tu: Switch to the bindless descriptor model
Under the bindless model, there are 5 "base" registers programmed with a
64-bit address, and sam/ldib/ldc and so on each specify a base register
and an offset, in units of 16 dwords. The base registers correspond to
descriptor sets in Vulkan. We allocate a buffer at descriptor set
creation time, hopefully outside the main rendering loop, and then
switching descriptor sets is just a matter of programming the base
registers differently. Note, however, that some kinds of descriptors
need to be patched at command recording time, in particular dynamic
UBO's and SSBO's, which need to be patched at CmdBindDescriptorSets
time, and input attachments which need to be patched at draw time based
on the the pipeline that's bound. We reserve the fifth base register
(which seems to be unused by the blob driver) for these, creating a
descriptor set on-the-fly and combining all the dynamic descriptors from
all the different descriptor sets. This way, we never have to copy the
rest of the descriptor set at draw time like the blob seems to do. I
mostly chose to do this because the infrastructure was already there in
the form of dynamic_descriptors, and other drivers (at least radv) don't
cheat either when implementing this.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4358>
2020-03-16 10:49:19 +00:00
|
|
|
uint64_t bo_size = 0, bo_count = 0, dynamic_count = 0;
|
2020-10-19 20:17:38 +01:00
|
|
|
VkResult ret;
|
2019-09-26 04:00:16 +01:00
|
|
|
|
2021-07-27 05:49:56 +01:00
|
|
|
const VkMutableDescriptorTypeCreateInfoVALVE *mutable_info =
|
|
|
|
vk_find_struct_const( pCreateInfo->pNext,
|
|
|
|
MUTABLE_DESCRIPTOR_TYPE_CREATE_INFO_VALVE);
|
|
|
|
|
2019-09-26 04:00:16 +01:00
|
|
|
for (unsigned i = 0; i < pCreateInfo->poolSizeCount; ++i) {
|
|
|
|
if (pCreateInfo->pPoolSizes[i].type != VK_DESCRIPTOR_TYPE_SAMPLER)
|
|
|
|
bo_count += pCreateInfo->pPoolSizes[i].descriptorCount;
|
|
|
|
|
2019-10-07 02:42:27 +01:00
|
|
|
switch(pCreateInfo->pPoolSizes[i].type) {
|
|
|
|
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
|
|
|
|
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
|
tu: Switch to the bindless descriptor model
Under the bindless model, there are 5 "base" registers programmed with a
64-bit address, and sam/ldib/ldc and so on each specify a base register
and an offset, in units of 16 dwords. The base registers correspond to
descriptor sets in Vulkan. We allocate a buffer at descriptor set
creation time, hopefully outside the main rendering loop, and then
switching descriptor sets is just a matter of programming the base
registers differently. Note, however, that some kinds of descriptors
need to be patched at command recording time, in particular dynamic
UBO's and SSBO's, which need to be patched at CmdBindDescriptorSets
time, and input attachments which need to be patched at draw time based
on the the pipeline that's bound. We reserve the fifth base register
(which seems to be unused by the blob driver) for these, creating a
descriptor set on-the-fly and combining all the dynamic descriptors from
all the different descriptor sets. This way, we never have to copy the
rest of the descriptor set at draw time like the blob seems to do. I
mostly chose to do this because the infrastructure was already there in
the form of dynamic_descriptors, and other drivers (at least radv) don't
cheat either when implementing this.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4358>
2020-03-16 10:49:19 +00:00
|
|
|
dynamic_count += pCreateInfo->pPoolSizes[i].descriptorCount;
|
2021-04-13 16:21:56 +01:00
|
|
|
break;
|
2021-07-27 05:49:56 +01:00
|
|
|
case VK_DESCRIPTOR_TYPE_MUTABLE_VALVE:
|
|
|
|
if (mutable_info && i < mutable_info->mutableDescriptorTypeListCount &&
|
|
|
|
mutable_info->pMutableDescriptorTypeLists[i].descriptorTypeCount > 0) {
|
|
|
|
bo_size +=
|
|
|
|
mutable_descriptor_size(&mutable_info->pMutableDescriptorTypeLists[i]) *
|
|
|
|
pCreateInfo->pPoolSizes[i].descriptorCount;
|
|
|
|
} else {
|
|
|
|
/* Allocate the maximum size possible.
|
|
|
|
* Since we don't support VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER for
|
|
|
|
* mutable descriptors, we can set the default size of descriptor types.
|
|
|
|
*/
|
|
|
|
bo_size += A6XX_TEX_CONST_DWORDS * 4 *
|
|
|
|
pCreateInfo->pPoolSizes[i].descriptorCount;
|
|
|
|
}
|
|
|
|
continue;
|
2019-10-07 02:42:27 +01:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2019-09-26 04:00:16 +01:00
|
|
|
bo_size += descriptor_size(pCreateInfo->pPoolSizes[i].type) *
|
|
|
|
pCreateInfo->pPoolSizes[i].descriptorCount;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(pCreateInfo->flags & VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT)) {
|
|
|
|
uint64_t host_size = pCreateInfo->maxSets * sizeof(struct tu_descriptor_set);
|
|
|
|
host_size += sizeof(struct tu_bo*) * bo_count;
|
tu: Switch to the bindless descriptor model
Under the bindless model, there are 5 "base" registers programmed with a
64-bit address, and sam/ldib/ldc and so on each specify a base register
and an offset, in units of 16 dwords. The base registers correspond to
descriptor sets in Vulkan. We allocate a buffer at descriptor set
creation time, hopefully outside the main rendering loop, and then
switching descriptor sets is just a matter of programming the base
registers differently. Note, however, that some kinds of descriptors
need to be patched at command recording time, in particular dynamic
UBO's and SSBO's, which need to be patched at CmdBindDescriptorSets
time, and input attachments which need to be patched at draw time based
on the the pipeline that's bound. We reserve the fifth base register
(which seems to be unused by the blob driver) for these, creating a
descriptor set on-the-fly and combining all the dynamic descriptors from
all the different descriptor sets. This way, we never have to copy the
rest of the descriptor set at draw time like the blob seems to do. I
mostly chose to do this because the infrastructure was already there in
the form of dynamic_descriptors, and other drivers (at least radv) don't
cheat either when implementing this.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4358>
2020-03-16 10:49:19 +00:00
|
|
|
host_size += A6XX_TEX_CONST_DWORDS * 4 * dynamic_count;
|
2019-09-26 04:00:16 +01:00
|
|
|
size += host_size;
|
|
|
|
} else {
|
|
|
|
size += sizeof(struct tu_descriptor_pool_entry) * pCreateInfo->maxSets;
|
|
|
|
}
|
|
|
|
|
2020-07-13 04:08:15 +01:00
|
|
|
pool = vk_object_zalloc(&device->vk, pAllocator, size,
|
|
|
|
VK_OBJECT_TYPE_DESCRIPTOR_POOL);
|
2019-09-26 04:00:16 +01:00
|
|
|
if (!pool)
|
2021-09-24 21:35:20 +01:00
|
|
|
return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
|
2019-09-26 04:00:16 +01:00
|
|
|
|
|
|
|
if (!(pCreateInfo->flags & VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT)) {
|
|
|
|
pool->host_memory_base = (uint8_t*)pool + sizeof(struct tu_descriptor_pool);
|
|
|
|
pool->host_memory_ptr = pool->host_memory_base;
|
|
|
|
pool->host_memory_end = (uint8_t*)pool + size;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bo_size) {
|
2021-07-27 05:49:56 +01:00
|
|
|
if (!(pCreateInfo->flags & VK_DESCRIPTOR_POOL_CREATE_HOST_ONLY_BIT_VALVE)) {
|
|
|
|
ret = tu_bo_init_new(device, &pool->bo, bo_size, TU_BO_ALLOC_ALLOW_DUMP);
|
|
|
|
if (ret)
|
|
|
|
goto fail_alloc;
|
|
|
|
|
|
|
|
ret = tu_bo_map(device, &pool->bo);
|
|
|
|
if (ret)
|
|
|
|
goto fail_map;
|
|
|
|
} else {
|
|
|
|
pool->host_bo = vk_alloc2(&device->vk.alloc, pAllocator, bo_size, 8,
|
|
|
|
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
|
|
|
|
if (!pool->host_bo) {
|
|
|
|
ret = VK_ERROR_OUT_OF_HOST_MEMORY;
|
|
|
|
goto fail_alloc;
|
|
|
|
}
|
|
|
|
}
|
2019-09-26 04:00:16 +01:00
|
|
|
}
|
|
|
|
pool->size = bo_size;
|
|
|
|
pool->max_entry_count = pCreateInfo->maxSets;
|
|
|
|
|
2022-01-27 14:04:06 +00:00
|
|
|
list_inithead(&pool->desc_sets);
|
|
|
|
|
2019-09-26 04:00:16 +01:00
|
|
|
*pDescriptorPool = tu_descriptor_pool_to_handle(pool);
|
2018-08-08 23:23:57 +01:00
|
|
|
return VK_SUCCESS;
|
2020-10-19 20:17:38 +01:00
|
|
|
|
|
|
|
fail_map:
|
|
|
|
tu_bo_finish(device, &pool->bo);
|
|
|
|
fail_alloc:
|
|
|
|
vk_object_free(&device->vk, pAllocator, pool);
|
|
|
|
return ret;
|
2018-08-08 23:23:57 +01:00
|
|
|
}
|
|
|
|
|
2021-06-07 05:59:32 +01:00
|
|
|
VKAPI_ATTR void VKAPI_CALL
|
2018-08-08 23:23:57 +01:00
|
|
|
tu_DestroyDescriptorPool(VkDevice _device,
|
2018-11-05 06:42:55 +00:00
|
|
|
VkDescriptorPool _pool,
|
|
|
|
const VkAllocationCallbacks *pAllocator)
|
2018-08-08 23:23:57 +01:00
|
|
|
{
|
2019-09-26 04:00:16 +01:00
|
|
|
TU_FROM_HANDLE(tu_device, device, _device);
|
|
|
|
TU_FROM_HANDLE(tu_descriptor_pool, pool, _pool);
|
|
|
|
|
|
|
|
if (!pool)
|
|
|
|
return;
|
|
|
|
|
2022-01-27 14:04:06 +00:00
|
|
|
list_for_each_entry_safe(struct tu_descriptor_set, set,
|
|
|
|
&pool->desc_sets, pool_link) {
|
|
|
|
tu_descriptor_set_layout_unref(device, set->layout);
|
2022-01-19 15:10:17 +00:00
|
|
|
}
|
|
|
|
|
2019-09-26 04:00:16 +01:00
|
|
|
if (!pool->host_memory_base) {
|
|
|
|
for(int i = 0; i < pool->entry_count; ++i) {
|
|
|
|
tu_descriptor_set_destroy(device, pool, pool->entries[i].set, false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-27 05:49:56 +01:00
|
|
|
if (pool->size) {
|
|
|
|
if (pool->host_bo)
|
|
|
|
vk_free2(&device->vk.alloc, pAllocator, pool->host_bo);
|
|
|
|
else
|
|
|
|
tu_bo_finish(device, &pool->bo);
|
|
|
|
}
|
2020-07-13 04:08:15 +01:00
|
|
|
|
|
|
|
vk_object_free(&device->vk, pAllocator, pool);
|
2018-08-08 23:23:57 +01:00
|
|
|
}
|
|
|
|
|
2021-06-07 05:59:32 +01:00
|
|
|
VKAPI_ATTR VkResult VKAPI_CALL
|
2018-08-08 23:23:57 +01:00
|
|
|
tu_ResetDescriptorPool(VkDevice _device,
|
2018-11-05 06:42:55 +00:00
|
|
|
VkDescriptorPool descriptorPool,
|
|
|
|
VkDescriptorPoolResetFlags flags)
|
2018-08-08 23:23:57 +01:00
|
|
|
{
|
|
|
|
TU_FROM_HANDLE(tu_device, device, _device);
|
|
|
|
TU_FROM_HANDLE(tu_descriptor_pool, pool, descriptorPool);
|
|
|
|
|
2022-01-27 14:04:06 +00:00
|
|
|
list_for_each_entry_safe(struct tu_descriptor_set, set,
|
|
|
|
&pool->desc_sets, pool_link) {
|
|
|
|
tu_descriptor_set_layout_unref(device, set->layout);
|
2022-01-19 15:10:17 +00:00
|
|
|
}
|
2022-01-27 14:04:06 +00:00
|
|
|
list_inithead(&pool->desc_sets);
|
2022-01-19 15:10:17 +00:00
|
|
|
|
2019-09-26 04:00:16 +01:00
|
|
|
if (!pool->host_memory_base) {
|
|
|
|
for(int i = 0; i < pool->entry_count; ++i) {
|
|
|
|
tu_descriptor_set_destroy(device, pool, pool->entries[i].set, false);
|
|
|
|
}
|
|
|
|
pool->entry_count = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
pool->current_offset = 0;
|
|
|
|
pool->host_memory_ptr = pool->host_memory_base;
|
|
|
|
|
2018-08-08 23:23:57 +01:00
|
|
|
return VK_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2021-06-07 05:59:32 +01:00
|
|
|
VKAPI_ATTR VkResult VKAPI_CALL
|
2018-08-08 23:23:57 +01:00
|
|
|
tu_AllocateDescriptorSets(VkDevice _device,
|
2018-11-05 06:42:55 +00:00
|
|
|
const VkDescriptorSetAllocateInfo *pAllocateInfo,
|
|
|
|
VkDescriptorSet *pDescriptorSets)
|
2018-08-08 23:23:57 +01:00
|
|
|
{
|
|
|
|
TU_FROM_HANDLE(tu_device, device, _device);
|
|
|
|
TU_FROM_HANDLE(tu_descriptor_pool, pool, pAllocateInfo->descriptorPool);
|
|
|
|
|
2019-09-26 04:00:16 +01:00
|
|
|
VkResult result = VK_SUCCESS;
|
|
|
|
uint32_t i;
|
|
|
|
struct tu_descriptor_set *set = NULL;
|
|
|
|
|
|
|
|
const VkDescriptorSetVariableDescriptorCountAllocateInfoEXT *variable_counts =
|
|
|
|
vk_find_struct_const(pAllocateInfo->pNext, DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO_EXT);
|
|
|
|
const uint32_t zero = 0;
|
|
|
|
|
|
|
|
/* allocate a set of buffers for each shader to contain descriptors */
|
|
|
|
for (i = 0; i < pAllocateInfo->descriptorSetCount; i++) {
|
|
|
|
TU_FROM_HANDLE(tu_descriptor_set_layout, layout,
|
|
|
|
pAllocateInfo->pSetLayouts[i]);
|
|
|
|
|
|
|
|
const uint32_t *variable_count = NULL;
|
|
|
|
if (variable_counts) {
|
|
|
|
if (i < variable_counts->descriptorSetCount)
|
|
|
|
variable_count = variable_counts->pDescriptorCounts + i;
|
|
|
|
else
|
|
|
|
variable_count = &zero;
|
|
|
|
}
|
|
|
|
|
|
|
|
assert(!(layout->flags & VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR));
|
|
|
|
|
|
|
|
result = tu_descriptor_set_create(device, pool, layout, variable_count, &set);
|
|
|
|
if (result != VK_SUCCESS)
|
|
|
|
break;
|
|
|
|
|
|
|
|
pDescriptorSets[i] = tu_descriptor_set_to_handle(set);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (result != VK_SUCCESS) {
|
|
|
|
tu_FreeDescriptorSets(_device, pAllocateInfo->descriptorPool,
|
|
|
|
i, pDescriptorSets);
|
|
|
|
for (i = 0; i < pAllocateInfo->descriptorSetCount; i++) {
|
|
|
|
pDescriptorSets[i] = VK_NULL_HANDLE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result;
|
2018-08-08 23:23:57 +01:00
|
|
|
}
|
|
|
|
|
2021-06-07 05:59:32 +01:00
|
|
|
VKAPI_ATTR VkResult VKAPI_CALL
|
2018-08-08 23:23:57 +01:00
|
|
|
tu_FreeDescriptorSets(VkDevice _device,
|
2018-11-05 06:42:55 +00:00
|
|
|
VkDescriptorPool descriptorPool,
|
|
|
|
uint32_t count,
|
|
|
|
const VkDescriptorSet *pDescriptorSets)
|
2018-08-08 23:23:57 +01:00
|
|
|
{
|
|
|
|
TU_FROM_HANDLE(tu_device, device, _device);
|
|
|
|
TU_FROM_HANDLE(tu_descriptor_pool, pool, descriptorPool);
|
|
|
|
|
2019-09-26 04:00:16 +01:00
|
|
|
for (uint32_t i = 0; i < count; i++) {
|
|
|
|
TU_FROM_HANDLE(tu_descriptor_set, set, pDescriptorSets[i]);
|
|
|
|
|
2022-01-19 15:10:17 +00:00
|
|
|
if (set)
|
|
|
|
tu_descriptor_set_layout_unref(device, set->layout);
|
|
|
|
|
2019-09-26 04:00:16 +01:00
|
|
|
if (set && !pool->host_memory_base)
|
|
|
|
tu_descriptor_set_destroy(device, pool, set, true);
|
|
|
|
}
|
2018-08-08 23:23:57 +01:00
|
|
|
return VK_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2020-09-16 15:56:36 +01:00
|
|
|
static void
|
|
|
|
write_texel_buffer_descriptor(uint32_t *dst, const VkBufferView buffer_view)
|
2019-10-07 02:42:27 +01:00
|
|
|
{
|
2020-11-10 16:41:55 +00:00
|
|
|
if (buffer_view == VK_NULL_HANDLE) {
|
|
|
|
memset(dst, 0, A6XX_TEX_CONST_DWORDS * sizeof(uint32_t));
|
|
|
|
} else {
|
|
|
|
TU_FROM_HANDLE(tu_buffer_view, view, buffer_view);
|
2020-01-22 20:25:10 +00:00
|
|
|
|
2020-11-10 16:41:55 +00:00
|
|
|
memcpy(dst, view->descriptor, sizeof(view->descriptor));
|
|
|
|
}
|
2019-10-07 02:42:27 +01:00
|
|
|
}
|
|
|
|
|
tu: Switch to the bindless descriptor model
Under the bindless model, there are 5 "base" registers programmed with a
64-bit address, and sam/ldib/ldc and so on each specify a base register
and an offset, in units of 16 dwords. The base registers correspond to
descriptor sets in Vulkan. We allocate a buffer at descriptor set
creation time, hopefully outside the main rendering loop, and then
switching descriptor sets is just a matter of programming the base
registers differently. Note, however, that some kinds of descriptors
need to be patched at command recording time, in particular dynamic
UBO's and SSBO's, which need to be patched at CmdBindDescriptorSets
time, and input attachments which need to be patched at draw time based
on the the pipeline that's bound. We reserve the fifth base register
(which seems to be unused by the blob driver) for these, creating a
descriptor set on-the-fly and combining all the dynamic descriptors from
all the different descriptor sets. This way, we never have to copy the
rest of the descriptor set at draw time like the blob seems to do. I
mostly chose to do this because the infrastructure was already there in
the form of dynamic_descriptors, and other drivers (at least radv) don't
cheat either when implementing this.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4358>
2020-03-16 10:49:19 +00:00
|
|
|
static uint32_t get_range(struct tu_buffer *buf, VkDeviceSize offset,
|
|
|
|
VkDeviceSize range)
|
|
|
|
{
|
|
|
|
if (range == VK_WHOLE_SIZE) {
|
|
|
|
return buf->size - offset;
|
|
|
|
} else {
|
|
|
|
return range;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-16 15:56:36 +01:00
|
|
|
static void
|
2021-03-23 16:39:32 +00:00
|
|
|
write_buffer_descriptor(const struct tu_device *device,
|
|
|
|
uint32_t *dst,
|
|
|
|
const VkDescriptorBufferInfo *buffer_info)
|
2019-09-26 04:00:16 +01:00
|
|
|
{
|
2020-11-10 16:41:55 +00:00
|
|
|
if (buffer_info->buffer == VK_NULL_HANDLE) {
|
|
|
|
memset(dst, 0, A6XX_TEX_CONST_DWORDS * sizeof(uint32_t));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-09-26 04:00:16 +01:00
|
|
|
TU_FROM_HANDLE(tu_buffer, buffer, buffer_info->buffer);
|
|
|
|
|
2020-11-17 21:19:36 +00:00
|
|
|
assert((buffer_info->offset & 63) == 0); /* minStorageBufferOffsetAlignment */
|
2022-02-01 05:24:54 +00:00
|
|
|
uint64_t va = buffer->iova + buffer_info->offset;
|
tu: Switch to the bindless descriptor model
Under the bindless model, there are 5 "base" registers programmed with a
64-bit address, and sam/ldib/ldc and so on each specify a base register
and an offset, in units of 16 dwords. The base registers correspond to
descriptor sets in Vulkan. We allocate a buffer at descriptor set
creation time, hopefully outside the main rendering loop, and then
switching descriptor sets is just a matter of programming the base
registers differently. Note, however, that some kinds of descriptors
need to be patched at command recording time, in particular dynamic
UBO's and SSBO's, which need to be patched at CmdBindDescriptorSets
time, and input attachments which need to be patched at draw time based
on the the pipeline that's bound. We reserve the fifth base register
(which seems to be unused by the blob driver) for these, creating a
descriptor set on-the-fly and combining all the dynamic descriptors from
all the different descriptor sets. This way, we never have to copy the
rest of the descriptor set at draw time like the blob seems to do. I
mostly chose to do this because the infrastructure was already there in
the form of dynamic_descriptors, and other drivers (at least radv) don't
cheat either when implementing this.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4358>
2020-03-16 10:49:19 +00:00
|
|
|
uint32_t range = get_range(buffer, buffer_info->offset, buffer_info->range);
|
2021-07-27 05:49:56 +01:00
|
|
|
|
2021-03-23 16:39:32 +00:00
|
|
|
/* newer a6xx allows using 16-bit descriptor for both 16-bit and 32-bit access */
|
2021-07-08 17:01:12 +01:00
|
|
|
if (device->physical_device->info->a6xx.storage_16bit) {
|
2021-03-23 16:39:32 +00:00
|
|
|
dst[0] = A6XX_IBO_0_TILE_MODE(TILE6_LINEAR) | A6XX_IBO_0_FMT(FMT6_16_UINT);
|
|
|
|
dst[1] = DIV_ROUND_UP(range, 2);
|
|
|
|
} else {
|
|
|
|
dst[0] = A6XX_IBO_0_TILE_MODE(TILE6_LINEAR) | A6XX_IBO_0_FMT(FMT6_32_UINT);
|
|
|
|
dst[1] = DIV_ROUND_UP(range, 4);
|
|
|
|
}
|
tu: Switch to the bindless descriptor model
Under the bindless model, there are 5 "base" registers programmed with a
64-bit address, and sam/ldib/ldc and so on each specify a base register
and an offset, in units of 16 dwords. The base registers correspond to
descriptor sets in Vulkan. We allocate a buffer at descriptor set
creation time, hopefully outside the main rendering loop, and then
switching descriptor sets is just a matter of programming the base
registers differently. Note, however, that some kinds of descriptors
need to be patched at command recording time, in particular dynamic
UBO's and SSBO's, which need to be patched at CmdBindDescriptorSets
time, and input attachments which need to be patched at draw time based
on the the pipeline that's bound. We reserve the fifth base register
(which seems to be unused by the blob driver) for these, creating a
descriptor set on-the-fly and combining all the dynamic descriptors from
all the different descriptor sets. This way, we never have to copy the
rest of the descriptor set at draw time like the blob seems to do. I
mostly chose to do this because the infrastructure was already there in
the form of dynamic_descriptors, and other drivers (at least radv) don't
cheat either when implementing this.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4358>
2020-03-16 10:49:19 +00:00
|
|
|
dst[2] =
|
|
|
|
A6XX_IBO_2_UNK4 | A6XX_IBO_2_TYPE(A6XX_TEX_1D) | A6XX_IBO_2_UNK31;
|
|
|
|
dst[3] = 0;
|
|
|
|
dst[4] = A6XX_IBO_4_BASE_LO(va);
|
|
|
|
dst[5] = A6XX_IBO_5_BASE_HI(va >> 32);
|
|
|
|
for (int i = 6; i < A6XX_TEX_CONST_DWORDS; i++)
|
|
|
|
dst[i] = 0;
|
2019-09-26 04:00:16 +01:00
|
|
|
}
|
|
|
|
|
2020-09-16 15:56:36 +01:00
|
|
|
static void
|
|
|
|
write_ubo_descriptor(uint32_t *dst, const VkDescriptorBufferInfo *buffer_info)
|
2019-10-07 02:42:27 +01:00
|
|
|
{
|
2020-11-10 16:41:55 +00:00
|
|
|
if (buffer_info->buffer == VK_NULL_HANDLE) {
|
|
|
|
dst[0] = dst[1] = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-10-07 02:42:27 +01:00
|
|
|
TU_FROM_HANDLE(tu_buffer, buffer, buffer_info->buffer);
|
|
|
|
|
tu: Switch to the bindless descriptor model
Under the bindless model, there are 5 "base" registers programmed with a
64-bit address, and sam/ldib/ldc and so on each specify a base register
and an offset, in units of 16 dwords. The base registers correspond to
descriptor sets in Vulkan. We allocate a buffer at descriptor set
creation time, hopefully outside the main rendering loop, and then
switching descriptor sets is just a matter of programming the base
registers differently. Note, however, that some kinds of descriptors
need to be patched at command recording time, in particular dynamic
UBO's and SSBO's, which need to be patched at CmdBindDescriptorSets
time, and input attachments which need to be patched at draw time based
on the the pipeline that's bound. We reserve the fifth base register
(which seems to be unused by the blob driver) for these, creating a
descriptor set on-the-fly and combining all the dynamic descriptors from
all the different descriptor sets. This way, we never have to copy the
rest of the descriptor set at draw time like the blob seems to do. I
mostly chose to do this because the infrastructure was already there in
the form of dynamic_descriptors, and other drivers (at least radv) don't
cheat either when implementing this.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4358>
2020-03-16 10:49:19 +00:00
|
|
|
uint32_t range = get_range(buffer, buffer_info->offset, buffer_info->range);
|
|
|
|
/* The HW range is in vec4 units */
|
|
|
|
range = ALIGN_POT(range, 16) / 16;
|
2022-02-01 05:24:54 +00:00
|
|
|
uint64_t va = buffer->iova + buffer_info->offset;
|
2020-11-10 16:41:55 +00:00
|
|
|
|
tu: Switch to the bindless descriptor model
Under the bindless model, there are 5 "base" registers programmed with a
64-bit address, and sam/ldib/ldc and so on each specify a base register
and an offset, in units of 16 dwords. The base registers correspond to
descriptor sets in Vulkan. We allocate a buffer at descriptor set
creation time, hopefully outside the main rendering loop, and then
switching descriptor sets is just a matter of programming the base
registers differently. Note, however, that some kinds of descriptors
need to be patched at command recording time, in particular dynamic
UBO's and SSBO's, which need to be patched at CmdBindDescriptorSets
time, and input attachments which need to be patched at draw time based
on the the pipeline that's bound. We reserve the fifth base register
(which seems to be unused by the blob driver) for these, creating a
descriptor set on-the-fly and combining all the dynamic descriptors from
all the different descriptor sets. This way, we never have to copy the
rest of the descriptor set at draw time like the blob seems to do. I
mostly chose to do this because the infrastructure was already there in
the form of dynamic_descriptors, and other drivers (at least radv) don't
cheat either when implementing this.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4358>
2020-03-16 10:49:19 +00:00
|
|
|
dst[0] = A6XX_UBO_0_BASE_LO(va);
|
|
|
|
dst[1] = A6XX_UBO_1_BASE_HI(va >> 32) | A6XX_UBO_1_SIZE(range);
|
2019-10-07 02:42:27 +01:00
|
|
|
}
|
|
|
|
|
2019-09-26 04:00:16 +01:00
|
|
|
static void
|
2020-09-16 15:56:36 +01:00
|
|
|
write_image_descriptor(uint32_t *dst,
|
|
|
|
VkDescriptorType descriptor_type,
|
|
|
|
const VkDescriptorImageInfo *image_info)
|
2019-09-26 04:00:16 +01:00
|
|
|
{
|
2020-11-10 16:41:55 +00:00
|
|
|
if (image_info->imageView == VK_NULL_HANDLE) {
|
|
|
|
memset(dst, 0, A6XX_TEX_CONST_DWORDS * sizeof(uint32_t));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-09-26 04:00:16 +01:00
|
|
|
TU_FROM_HANDLE(tu_image_view, iview, image_info->imageView);
|
|
|
|
|
|
|
|
if (descriptor_type == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) {
|
2021-10-13 16:51:13 +01:00
|
|
|
memcpy(dst, iview->view.storage_descriptor, sizeof(iview->view.storage_descriptor));
|
tu: Switch to the bindless descriptor model
Under the bindless model, there are 5 "base" registers programmed with a
64-bit address, and sam/ldib/ldc and so on each specify a base register
and an offset, in units of 16 dwords. The base registers correspond to
descriptor sets in Vulkan. We allocate a buffer at descriptor set
creation time, hopefully outside the main rendering loop, and then
switching descriptor sets is just a matter of programming the base
registers differently. Note, however, that some kinds of descriptors
need to be patched at command recording time, in particular dynamic
UBO's and SSBO's, which need to be patched at CmdBindDescriptorSets
time, and input attachments which need to be patched at draw time based
on the the pipeline that's bound. We reserve the fifth base register
(which seems to be unused by the blob driver) for these, creating a
descriptor set on-the-fly and combining all the dynamic descriptors from
all the different descriptor sets. This way, we never have to copy the
rest of the descriptor set at draw time like the blob seems to do. I
mostly chose to do this because the infrastructure was already there in
the form of dynamic_descriptors, and other drivers (at least radv) don't
cheat either when implementing this.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4358>
2020-03-16 10:49:19 +00:00
|
|
|
} else {
|
2021-10-13 16:51:13 +01:00
|
|
|
memcpy(dst, iview->view.descriptor, sizeof(iview->view.descriptor));
|
2019-09-26 04:00:16 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2020-09-16 15:56:36 +01:00
|
|
|
write_combined_image_sampler_descriptor(uint32_t *dst,
|
|
|
|
VkDescriptorType descriptor_type,
|
|
|
|
const VkDescriptorImageInfo *image_info,
|
|
|
|
bool has_sampler)
|
2019-09-26 04:00:16 +01:00
|
|
|
{
|
2020-09-16 15:56:36 +01:00
|
|
|
write_image_descriptor(dst, descriptor_type, image_info);
|
2019-09-26 04:00:16 +01:00
|
|
|
/* copy over sampler state */
|
|
|
|
if (has_sampler) {
|
2021-09-21 12:36:32 +01:00
|
|
|
TU_FROM_HANDLE(tu_sampler, sampler, image_info->sampler);
|
2020-07-14 01:47:30 +01:00
|
|
|
memcpy(dst + A6XX_TEX_CONST_DWORDS, sampler->descriptor, sizeof(sampler->descriptor));
|
2019-09-26 04:00:16 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-07 02:42:27 +01:00
|
|
|
static void
|
2020-09-16 15:56:36 +01:00
|
|
|
write_sampler_descriptor(uint32_t *dst, const VkDescriptorImageInfo *image_info)
|
2019-10-07 02:42:27 +01:00
|
|
|
{
|
|
|
|
TU_FROM_HANDLE(tu_sampler, sampler, image_info->sampler);
|
|
|
|
|
2020-07-14 01:47:30 +01:00
|
|
|
memcpy(dst, sampler->descriptor, sizeof(sampler->descriptor));
|
2019-10-07 02:42:27 +01:00
|
|
|
}
|
|
|
|
|
2020-09-17 01:12:52 +01:00
|
|
|
/* note: this is used with immutable samplers in push descriptors */
|
|
|
|
static void
|
|
|
|
write_sampler_push(uint32_t *dst, const struct tu_sampler *sampler)
|
|
|
|
{
|
|
|
|
memcpy(dst, sampler->descriptor, sizeof(sampler->descriptor));
|
|
|
|
}
|
|
|
|
|
2018-08-08 23:23:57 +01:00
|
|
|
void
|
2021-03-23 16:39:32 +00:00
|
|
|
tu_update_descriptor_sets(const struct tu_device *device,
|
|
|
|
VkDescriptorSet dstSetOverride,
|
2018-11-05 06:42:55 +00:00
|
|
|
uint32_t descriptorWriteCount,
|
|
|
|
const VkWriteDescriptorSet *pDescriptorWrites,
|
|
|
|
uint32_t descriptorCopyCount,
|
|
|
|
const VkCopyDescriptorSet *pDescriptorCopies)
|
2018-08-08 23:23:57 +01:00
|
|
|
{
|
2019-09-26 04:00:16 +01:00
|
|
|
uint32_t i, j;
|
|
|
|
for (i = 0; i < descriptorWriteCount; i++) {
|
|
|
|
const VkWriteDescriptorSet *writeset = &pDescriptorWrites[i];
|
2020-09-17 01:12:52 +01:00
|
|
|
TU_FROM_HANDLE(tu_descriptor_set, set, dstSetOverride ?: writeset->dstSet);
|
2019-09-26 04:00:16 +01:00
|
|
|
const struct tu_descriptor_set_binding_layout *binding_layout =
|
|
|
|
set->layout->binding + writeset->dstBinding;
|
|
|
|
uint32_t *ptr = set->mapped_ptr;
|
2020-09-17 01:12:52 +01:00
|
|
|
/* for immutable samplers with push descriptors: */
|
|
|
|
const bool copy_immutable_samplers =
|
|
|
|
dstSetOverride && binding_layout->immutable_samplers_offset;
|
|
|
|
const struct tu_sampler *samplers =
|
|
|
|
tu_immutable_samplers(set->layout, binding_layout);
|
2019-09-26 04:00:16 +01:00
|
|
|
|
|
|
|
ptr += binding_layout->offset / 4;
|
|
|
|
|
tu: Switch to the bindless descriptor model
Under the bindless model, there are 5 "base" registers programmed with a
64-bit address, and sam/ldib/ldc and so on each specify a base register
and an offset, in units of 16 dwords. The base registers correspond to
descriptor sets in Vulkan. We allocate a buffer at descriptor set
creation time, hopefully outside the main rendering loop, and then
switching descriptor sets is just a matter of programming the base
registers differently. Note, however, that some kinds of descriptors
need to be patched at command recording time, in particular dynamic
UBO's and SSBO's, which need to be patched at CmdBindDescriptorSets
time, and input attachments which need to be patched at draw time based
on the the pipeline that's bound. We reserve the fifth base register
(which seems to be unused by the blob driver) for these, creating a
descriptor set on-the-fly and combining all the dynamic descriptors from
all the different descriptor sets. This way, we never have to copy the
rest of the descriptor set at draw time like the blob seems to do. I
mostly chose to do this because the infrastructure was already there in
the form of dynamic_descriptors, and other drivers (at least radv) don't
cheat either when implementing this.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4358>
2020-03-16 10:49:19 +00:00
|
|
|
ptr += (binding_layout->size / 4) * writeset->dstArrayElement;
|
2019-09-26 04:00:16 +01:00
|
|
|
for (j = 0; j < writeset->descriptorCount; ++j) {
|
|
|
|
switch(writeset->descriptorType) {
|
tu: Switch to the bindless descriptor model
Under the bindless model, there are 5 "base" registers programmed with a
64-bit address, and sam/ldib/ldc and so on each specify a base register
and an offset, in units of 16 dwords. The base registers correspond to
descriptor sets in Vulkan. We allocate a buffer at descriptor set
creation time, hopefully outside the main rendering loop, and then
switching descriptor sets is just a matter of programming the base
registers differently. Note, however, that some kinds of descriptors
need to be patched at command recording time, in particular dynamic
UBO's and SSBO's, which need to be patched at CmdBindDescriptorSets
time, and input attachments which need to be patched at draw time based
on the the pipeline that's bound. We reserve the fifth base register
(which seems to be unused by the blob driver) for these, creating a
descriptor set on-the-fly and combining all the dynamic descriptors from
all the different descriptor sets. This way, we never have to copy the
rest of the descriptor set at draw time like the blob seems to do. I
mostly chose to do this because the infrastructure was already there in
the form of dynamic_descriptors, and other drivers (at least radv) don't
cheat either when implementing this.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4358>
2020-03-16 10:49:19 +00:00
|
|
|
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: {
|
2019-10-07 02:42:27 +01:00
|
|
|
assert(!(set->layout->flags & VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR));
|
tu: Switch to the bindless descriptor model
Under the bindless model, there are 5 "base" registers programmed with a
64-bit address, and sam/ldib/ldc and so on each specify a base register
and an offset, in units of 16 dwords. The base registers correspond to
descriptor sets in Vulkan. We allocate a buffer at descriptor set
creation time, hopefully outside the main rendering loop, and then
switching descriptor sets is just a matter of programming the base
registers differently. Note, however, that some kinds of descriptors
need to be patched at command recording time, in particular dynamic
UBO's and SSBO's, which need to be patched at CmdBindDescriptorSets
time, and input attachments which need to be patched at draw time based
on the the pipeline that's bound. We reserve the fifth base register
(which seems to be unused by the blob driver) for these, creating a
descriptor set on-the-fly and combining all the dynamic descriptors from
all the different descriptor sets. This way, we never have to copy the
rest of the descriptor set at draw time like the blob seems to do. I
mostly chose to do this because the infrastructure was already there in
the form of dynamic_descriptors, and other drivers (at least radv) don't
cheat either when implementing this.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4358>
2020-03-16 10:49:19 +00:00
|
|
|
unsigned idx = writeset->dstArrayElement + j;
|
2020-06-15 04:10:01 +01:00
|
|
|
idx += binding_layout->dynamic_offset_offset;
|
2020-09-16 15:56:36 +01:00
|
|
|
write_ubo_descriptor(set->dynamic_descriptors + A6XX_TEX_CONST_DWORDS * idx,
|
2020-09-11 15:26:40 +01:00
|
|
|
writeset->pBufferInfo + j);
|
2019-10-07 02:42:27 +01:00
|
|
|
break;
|
|
|
|
}
|
2019-09-26 04:00:16 +01:00
|
|
|
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
|
2020-09-16 15:56:36 +01:00
|
|
|
write_ubo_descriptor(ptr, writeset->pBufferInfo + j);
|
tu: Switch to the bindless descriptor model
Under the bindless model, there are 5 "base" registers programmed with a
64-bit address, and sam/ldib/ldc and so on each specify a base register
and an offset, in units of 16 dwords. The base registers correspond to
descriptor sets in Vulkan. We allocate a buffer at descriptor set
creation time, hopefully outside the main rendering loop, and then
switching descriptor sets is just a matter of programming the base
registers differently. Note, however, that some kinds of descriptors
need to be patched at command recording time, in particular dynamic
UBO's and SSBO's, which need to be patched at CmdBindDescriptorSets
time, and input attachments which need to be patched at draw time based
on the the pipeline that's bound. We reserve the fifth base register
(which seems to be unused by the blob driver) for these, creating a
descriptor set on-the-fly and combining all the dynamic descriptors from
all the different descriptor sets. This way, we never have to copy the
rest of the descriptor set at draw time like the blob seems to do. I
mostly chose to do this because the infrastructure was already there in
the form of dynamic_descriptors, and other drivers (at least radv) don't
cheat either when implementing this.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4358>
2020-03-16 10:49:19 +00:00
|
|
|
break;
|
|
|
|
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: {
|
|
|
|
assert(!(set->layout->flags & VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR));
|
|
|
|
unsigned idx = writeset->dstArrayElement + j;
|
2020-06-15 04:10:01 +01:00
|
|
|
idx += binding_layout->dynamic_offset_offset;
|
2021-03-23 16:39:32 +00:00
|
|
|
write_buffer_descriptor(device, set->dynamic_descriptors + A6XX_TEX_CONST_DWORDS * idx,
|
2020-09-11 15:26:40 +01:00
|
|
|
writeset->pBufferInfo + j);
|
tu: Switch to the bindless descriptor model
Under the bindless model, there are 5 "base" registers programmed with a
64-bit address, and sam/ldib/ldc and so on each specify a base register
and an offset, in units of 16 dwords. The base registers correspond to
descriptor sets in Vulkan. We allocate a buffer at descriptor set
creation time, hopefully outside the main rendering loop, and then
switching descriptor sets is just a matter of programming the base
registers differently. Note, however, that some kinds of descriptors
need to be patched at command recording time, in particular dynamic
UBO's and SSBO's, which need to be patched at CmdBindDescriptorSets
time, and input attachments which need to be patched at draw time based
on the the pipeline that's bound. We reserve the fifth base register
(which seems to be unused by the blob driver) for these, creating a
descriptor set on-the-fly and combining all the dynamic descriptors from
all the different descriptor sets. This way, we never have to copy the
rest of the descriptor set at draw time like the blob seems to do. I
mostly chose to do this because the infrastructure was already there in
the form of dynamic_descriptors, and other drivers (at least radv) don't
cheat either when implementing this.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4358>
2020-03-16 10:49:19 +00:00
|
|
|
break;
|
|
|
|
}
|
2019-10-07 02:42:27 +01:00
|
|
|
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
|
2021-03-23 16:39:32 +00:00
|
|
|
write_buffer_descriptor(device, ptr, writeset->pBufferInfo + j);
|
2019-09-26 04:00:16 +01:00
|
|
|
break;
|
2019-10-07 02:42:27 +01:00
|
|
|
case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
|
|
|
|
case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
|
2020-09-16 15:56:36 +01:00
|
|
|
write_texel_buffer_descriptor(ptr, writeset->pTexelBufferView[j]);
|
2019-10-07 02:42:27 +01:00
|
|
|
break;
|
|
|
|
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
|
|
|
|
case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
|
2020-09-16 15:56:36 +01:00
|
|
|
write_image_descriptor(ptr, writeset->descriptorType, writeset->pImageInfo + j);
|
2019-10-07 02:42:27 +01:00
|
|
|
break;
|
2019-09-26 04:00:16 +01:00
|
|
|
case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
|
2020-09-16 15:56:36 +01:00
|
|
|
write_combined_image_sampler_descriptor(ptr,
|
2019-09-26 04:00:16 +01:00
|
|
|
writeset->descriptorType,
|
|
|
|
writeset->pImageInfo + j,
|
|
|
|
!binding_layout->immutable_samplers_offset);
|
2020-09-17 01:12:52 +01:00
|
|
|
|
|
|
|
if (copy_immutable_samplers)
|
|
|
|
write_sampler_push(ptr + A6XX_TEX_CONST_DWORDS, &samplers[writeset->dstArrayElement + j]);
|
2019-10-07 02:42:27 +01:00
|
|
|
break;
|
|
|
|
case VK_DESCRIPTOR_TYPE_SAMPLER:
|
2020-09-17 01:12:52 +01:00
|
|
|
if (!binding_layout->immutable_samplers_offset)
|
|
|
|
write_sampler_descriptor(ptr, writeset->pImageInfo + j);
|
|
|
|
else if (copy_immutable_samplers)
|
|
|
|
write_sampler_push(ptr, &samplers[writeset->dstArrayElement + j]);
|
2019-09-26 04:00:16 +01:00
|
|
|
break;
|
2020-06-15 04:10:01 +01:00
|
|
|
case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
|
|
|
|
/* nothing in descriptor set - framebuffer state is used instead */
|
|
|
|
break;
|
2019-09-26 04:00:16 +01:00
|
|
|
default:
|
|
|
|
unreachable("unimplemented descriptor type");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
ptr += binding_layout->size / 4;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < descriptorCopyCount; i++) {
|
|
|
|
const VkCopyDescriptorSet *copyset = &pDescriptorCopies[i];
|
|
|
|
TU_FROM_HANDLE(tu_descriptor_set, src_set,
|
|
|
|
copyset->srcSet);
|
|
|
|
TU_FROM_HANDLE(tu_descriptor_set, dst_set,
|
|
|
|
copyset->dstSet);
|
|
|
|
const struct tu_descriptor_set_binding_layout *src_binding_layout =
|
|
|
|
src_set->layout->binding + copyset->srcBinding;
|
|
|
|
const struct tu_descriptor_set_binding_layout *dst_binding_layout =
|
|
|
|
dst_set->layout->binding + copyset->dstBinding;
|
|
|
|
uint32_t *src_ptr = src_set->mapped_ptr;
|
|
|
|
uint32_t *dst_ptr = dst_set->mapped_ptr;
|
|
|
|
|
|
|
|
src_ptr += src_binding_layout->offset / 4;
|
|
|
|
dst_ptr += dst_binding_layout->offset / 4;
|
|
|
|
|
|
|
|
src_ptr += src_binding_layout->size * copyset->srcArrayElement / 4;
|
|
|
|
dst_ptr += dst_binding_layout->size * copyset->dstArrayElement / 4;
|
|
|
|
|
2021-07-27 05:49:56 +01:00
|
|
|
/* In case of copies between mutable descriptor types
|
|
|
|
* and non-mutable descriptor types.
|
|
|
|
*/
|
|
|
|
uint32_t copy_size = MIN2(src_binding_layout->size, dst_binding_layout->size);
|
|
|
|
|
2019-09-26 04:00:16 +01:00
|
|
|
for (j = 0; j < copyset->descriptorCount; ++j) {
|
|
|
|
switch (src_binding_layout->type) {
|
|
|
|
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
|
|
|
|
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: {
|
|
|
|
unsigned src_idx = copyset->srcArrayElement + j;
|
|
|
|
unsigned dst_idx = copyset->dstArrayElement + j;
|
|
|
|
src_idx += src_binding_layout->dynamic_offset_offset;
|
|
|
|
dst_idx += dst_binding_layout->dynamic_offset_offset;
|
|
|
|
|
tu: Switch to the bindless descriptor model
Under the bindless model, there are 5 "base" registers programmed with a
64-bit address, and sam/ldib/ldc and so on each specify a base register
and an offset, in units of 16 dwords. The base registers correspond to
descriptor sets in Vulkan. We allocate a buffer at descriptor set
creation time, hopefully outside the main rendering loop, and then
switching descriptor sets is just a matter of programming the base
registers differently. Note, however, that some kinds of descriptors
need to be patched at command recording time, in particular dynamic
UBO's and SSBO's, which need to be patched at CmdBindDescriptorSets
time, and input attachments which need to be patched at draw time based
on the the pipeline that's bound. We reserve the fifth base register
(which seems to be unused by the blob driver) for these, creating a
descriptor set on-the-fly and combining all the dynamic descriptors from
all the different descriptor sets. This way, we never have to copy the
rest of the descriptor set at draw time like the blob seems to do. I
mostly chose to do this because the infrastructure was already there in
the form of dynamic_descriptors, and other drivers (at least radv) don't
cheat either when implementing this.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4358>
2020-03-16 10:49:19 +00:00
|
|
|
uint32_t *src_dynamic, *dst_dynamic;
|
|
|
|
src_dynamic = src_set->dynamic_descriptors + src_idx * A6XX_TEX_CONST_DWORDS;
|
|
|
|
dst_dynamic = dst_set->dynamic_descriptors + dst_idx * A6XX_TEX_CONST_DWORDS;
|
|
|
|
memcpy(dst_dynamic, src_dynamic, A6XX_TEX_CONST_DWORDS * 4);
|
|
|
|
break;
|
|
|
|
}
|
2019-09-26 04:00:16 +01:00
|
|
|
default:
|
2021-07-27 05:49:56 +01:00
|
|
|
memcpy(dst_ptr, src_ptr, copy_size);
|
2019-09-26 04:00:16 +01:00
|
|
|
}
|
tu: Switch to the bindless descriptor model
Under the bindless model, there are 5 "base" registers programmed with a
64-bit address, and sam/ldib/ldc and so on each specify a base register
and an offset, in units of 16 dwords. The base registers correspond to
descriptor sets in Vulkan. We allocate a buffer at descriptor set
creation time, hopefully outside the main rendering loop, and then
switching descriptor sets is just a matter of programming the base
registers differently. Note, however, that some kinds of descriptors
need to be patched at command recording time, in particular dynamic
UBO's and SSBO's, which need to be patched at CmdBindDescriptorSets
time, and input attachments which need to be patched at draw time based
on the the pipeline that's bound. We reserve the fifth base register
(which seems to be unused by the blob driver) for these, creating a
descriptor set on-the-fly and combining all the dynamic descriptors from
all the different descriptor sets. This way, we never have to copy the
rest of the descriptor set at draw time like the blob seems to do. I
mostly chose to do this because the infrastructure was already there in
the form of dynamic_descriptors, and other drivers (at least radv) don't
cheat either when implementing this.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4358>
2020-03-16 10:49:19 +00:00
|
|
|
|
2019-09-26 04:00:16 +01:00
|
|
|
src_ptr += src_binding_layout->size / 4;
|
|
|
|
dst_ptr += dst_binding_layout->size / 4;
|
|
|
|
}
|
|
|
|
}
|
2018-08-08 23:23:57 +01:00
|
|
|
}
|
|
|
|
|
2021-06-07 05:59:32 +01:00
|
|
|
VKAPI_ATTR void VKAPI_CALL
|
2018-08-08 23:23:57 +01:00
|
|
|
tu_UpdateDescriptorSets(VkDevice _device,
|
2018-11-05 06:42:55 +00:00
|
|
|
uint32_t descriptorWriteCount,
|
|
|
|
const VkWriteDescriptorSet *pDescriptorWrites,
|
|
|
|
uint32_t descriptorCopyCount,
|
|
|
|
const VkCopyDescriptorSet *pDescriptorCopies)
|
2018-08-08 23:23:57 +01:00
|
|
|
{
|
2021-03-23 16:39:32 +00:00
|
|
|
TU_FROM_HANDLE(tu_device, device, _device);
|
|
|
|
tu_update_descriptor_sets(device, VK_NULL_HANDLE,
|
2019-01-09 22:16:01 +00:00
|
|
|
descriptorWriteCount, pDescriptorWrites,
|
|
|
|
descriptorCopyCount, pDescriptorCopies);
|
2018-08-08 23:23:57 +01:00
|
|
|
}
|
|
|
|
|
2021-06-07 05:59:32 +01:00
|
|
|
VKAPI_ATTR VkResult VKAPI_CALL
|
2018-08-08 23:23:57 +01:00
|
|
|
tu_CreateDescriptorUpdateTemplate(
|
2018-11-05 06:42:55 +00:00
|
|
|
VkDevice _device,
|
2019-02-02 01:08:51 +00:00
|
|
|
const VkDescriptorUpdateTemplateCreateInfo *pCreateInfo,
|
2018-11-05 06:42:55 +00:00
|
|
|
const VkAllocationCallbacks *pAllocator,
|
2019-02-02 01:08:51 +00:00
|
|
|
VkDescriptorUpdateTemplate *pDescriptorUpdateTemplate)
|
2018-08-08 23:23:57 +01:00
|
|
|
{
|
|
|
|
TU_FROM_HANDLE(tu_device, device, _device);
|
2019-01-09 22:16:01 +00:00
|
|
|
TU_FROM_HANDLE(tu_descriptor_set_layout, set_layout,
|
|
|
|
pCreateInfo->descriptorSetLayout);
|
2018-08-08 23:23:57 +01:00
|
|
|
const uint32_t entry_count = pCreateInfo->descriptorUpdateEntryCount;
|
|
|
|
const size_t size =
|
2019-01-09 22:16:01 +00:00
|
|
|
sizeof(struct tu_descriptor_update_template) +
|
|
|
|
sizeof(struct tu_descriptor_update_template_entry) * entry_count;
|
2018-08-08 23:23:57 +01:00
|
|
|
struct tu_descriptor_update_template *templ;
|
|
|
|
|
2020-07-13 04:08:15 +01:00
|
|
|
templ = vk_object_alloc(&device->vk, pAllocator, size,
|
|
|
|
VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE);
|
2018-08-08 23:23:57 +01:00
|
|
|
if (!templ)
|
2021-09-24 21:35:20 +01:00
|
|
|
return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
|
2018-08-08 23:23:57 +01:00
|
|
|
|
2020-03-24 17:01:15 +00:00
|
|
|
templ->entry_count = entry_count;
|
|
|
|
|
|
|
|
if (pCreateInfo->templateType == VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR) {
|
|
|
|
TU_FROM_HANDLE(tu_pipeline_layout, pipeline_layout, pCreateInfo->pipelineLayout);
|
|
|
|
|
|
|
|
/* descriptorSetLayout should be ignored for push descriptors
|
|
|
|
* and instead it refers to pipelineLayout and set.
|
|
|
|
*/
|
|
|
|
assert(pCreateInfo->set < MAX_SETS);
|
|
|
|
set_layout = pipeline_layout->set[pCreateInfo->set].layout;
|
2020-09-17 01:12:52 +01:00
|
|
|
|
|
|
|
templ->bind_point = pCreateInfo->pipelineBindPoint;
|
2020-03-24 17:01:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for (uint32_t i = 0; i < entry_count; i++) {
|
|
|
|
const VkDescriptorUpdateTemplateEntry *entry = &pCreateInfo->pDescriptorUpdateEntries[i];
|
|
|
|
|
|
|
|
const struct tu_descriptor_set_binding_layout *binding_layout =
|
|
|
|
set_layout->binding + entry->dstBinding;
|
|
|
|
uint32_t dst_offset, dst_stride;
|
2020-09-17 01:12:52 +01:00
|
|
|
const struct tu_sampler *immutable_samplers = NULL;
|
2020-03-24 17:01:15 +00:00
|
|
|
|
|
|
|
/* dst_offset is an offset into dynamic_descriptors when the descriptor
|
|
|
|
* is dynamic, and an offset into mapped_ptr otherwise.
|
|
|
|
*/
|
|
|
|
switch (entry->descriptorType) {
|
|
|
|
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
|
|
|
|
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
|
2020-06-15 04:10:01 +01:00
|
|
|
dst_offset = (binding_layout->dynamic_offset_offset +
|
2020-03-24 17:01:15 +00:00
|
|
|
entry->dstArrayElement) * A6XX_TEX_CONST_DWORDS;
|
|
|
|
dst_stride = A6XX_TEX_CONST_DWORDS;
|
|
|
|
break;
|
2020-09-17 01:12:52 +01:00
|
|
|
case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
|
|
|
|
case VK_DESCRIPTOR_TYPE_SAMPLER:
|
|
|
|
if (pCreateInfo->templateType == VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR &&
|
|
|
|
binding_layout->immutable_samplers_offset) {
|
|
|
|
immutable_samplers =
|
|
|
|
tu_immutable_samplers(set_layout, binding_layout) + entry->dstArrayElement;
|
|
|
|
}
|
2021-04-10 16:11:58 +01:00
|
|
|
FALLTHROUGH;
|
2020-03-24 17:01:15 +00:00
|
|
|
default:
|
|
|
|
dst_offset = binding_layout->offset / 4;
|
|
|
|
dst_offset += (binding_layout->size * entry->dstArrayElement) / 4;
|
|
|
|
dst_stride = binding_layout->size / 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
templ->entry[i] = (struct tu_descriptor_update_template_entry) {
|
|
|
|
.descriptor_type = entry->descriptorType,
|
|
|
|
.descriptor_count = entry->descriptorCount,
|
|
|
|
.src_offset = entry->offset,
|
|
|
|
.src_stride = entry->stride,
|
|
|
|
.dst_offset = dst_offset,
|
|
|
|
.dst_stride = dst_stride,
|
|
|
|
.has_sampler = !binding_layout->immutable_samplers_offset,
|
2020-09-17 01:12:52 +01:00
|
|
|
.immutable_samplers = immutable_samplers,
|
2020-03-24 17:01:15 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2019-01-09 22:16:01 +00:00
|
|
|
*pDescriptorUpdateTemplate =
|
|
|
|
tu_descriptor_update_template_to_handle(templ);
|
2018-11-12 22:42:36 +00:00
|
|
|
|
2018-08-08 23:23:57 +01:00
|
|
|
return VK_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2021-06-07 05:59:32 +01:00
|
|
|
VKAPI_ATTR void VKAPI_CALL
|
2018-08-08 23:23:57 +01:00
|
|
|
tu_DestroyDescriptorUpdateTemplate(
|
2018-11-05 06:42:55 +00:00
|
|
|
VkDevice _device,
|
2019-02-02 01:08:51 +00:00
|
|
|
VkDescriptorUpdateTemplate descriptorUpdateTemplate,
|
2018-11-05 06:42:55 +00:00
|
|
|
const VkAllocationCallbacks *pAllocator)
|
2018-08-08 23:23:57 +01:00
|
|
|
{
|
|
|
|
TU_FROM_HANDLE(tu_device, device, _device);
|
2019-01-09 22:16:01 +00:00
|
|
|
TU_FROM_HANDLE(tu_descriptor_update_template, templ,
|
|
|
|
descriptorUpdateTemplate);
|
2018-08-08 23:23:57 +01:00
|
|
|
|
|
|
|
if (!templ)
|
|
|
|
return;
|
|
|
|
|
2020-07-13 04:08:15 +01:00
|
|
|
vk_object_free(&device->vk, pAllocator, templ);
|
2018-08-08 23:23:57 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
tu_update_descriptor_set_with_template(
|
2021-03-23 16:39:32 +00:00
|
|
|
const struct tu_device *device,
|
2018-11-05 06:42:55 +00:00
|
|
|
struct tu_descriptor_set *set,
|
2019-02-02 01:08:51 +00:00
|
|
|
VkDescriptorUpdateTemplate descriptorUpdateTemplate,
|
2018-11-05 06:42:55 +00:00
|
|
|
const void *pData)
|
2018-08-08 23:23:57 +01:00
|
|
|
{
|
2019-01-09 22:16:01 +00:00
|
|
|
TU_FROM_HANDLE(tu_descriptor_update_template, templ,
|
|
|
|
descriptorUpdateTemplate);
|
2020-03-24 17:01:15 +00:00
|
|
|
|
|
|
|
for (uint32_t i = 0; i < templ->entry_count; i++) {
|
|
|
|
uint32_t *ptr = set->mapped_ptr;
|
|
|
|
const void *src = ((const char *) pData) + templ->entry[i].src_offset;
|
2020-09-17 01:12:52 +01:00
|
|
|
const struct tu_sampler *samplers = templ->entry[i].immutable_samplers;
|
2020-03-24 17:01:15 +00:00
|
|
|
|
|
|
|
ptr += templ->entry[i].dst_offset;
|
|
|
|
unsigned dst_offset = templ->entry[i].dst_offset;
|
|
|
|
for (unsigned j = 0; j < templ->entry[i].descriptor_count; ++j) {
|
|
|
|
switch(templ->entry[i].descriptor_type) {
|
|
|
|
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: {
|
|
|
|
assert(!(set->layout->flags & VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR));
|
2020-09-16 15:56:36 +01:00
|
|
|
write_ubo_descriptor(set->dynamic_descriptors + dst_offset, src);
|
2020-03-24 17:01:15 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
|
2020-09-16 15:56:36 +01:00
|
|
|
write_ubo_descriptor(ptr, src);
|
2020-03-24 17:01:15 +00:00
|
|
|
break;
|
|
|
|
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: {
|
|
|
|
assert(!(set->layout->flags & VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR));
|
2021-03-23 16:39:32 +00:00
|
|
|
write_buffer_descriptor(device, set->dynamic_descriptors + dst_offset, src);
|
2020-03-24 17:01:15 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
|
2021-03-23 16:39:32 +00:00
|
|
|
write_buffer_descriptor(device, ptr, src);
|
2020-03-24 17:01:15 +00:00
|
|
|
break;
|
|
|
|
case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
|
|
|
|
case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
|
2020-09-16 15:56:36 +01:00
|
|
|
write_texel_buffer_descriptor(ptr, *(VkBufferView *) src);
|
2020-03-24 17:01:15 +00:00
|
|
|
break;
|
|
|
|
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
|
2020-07-27 12:17:42 +01:00
|
|
|
case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: {
|
2020-09-16 15:56:36 +01:00
|
|
|
write_image_descriptor(ptr, templ->entry[i].descriptor_type, src);
|
2020-03-24 17:01:15 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
|
2020-09-16 15:56:36 +01:00
|
|
|
write_combined_image_sampler_descriptor(ptr,
|
2020-03-24 17:01:15 +00:00
|
|
|
templ->entry[i].descriptor_type,
|
|
|
|
src,
|
|
|
|
templ->entry[i].has_sampler);
|
2020-09-17 01:12:52 +01:00
|
|
|
if (samplers)
|
|
|
|
write_sampler_push(ptr + A6XX_TEX_CONST_DWORDS, &samplers[j]);
|
2020-03-24 17:01:15 +00:00
|
|
|
break;
|
|
|
|
case VK_DESCRIPTOR_TYPE_SAMPLER:
|
2020-09-17 01:12:52 +01:00
|
|
|
if (templ->entry[i].has_sampler)
|
|
|
|
write_sampler_descriptor(ptr, src);
|
|
|
|
else if (samplers)
|
|
|
|
write_sampler_push(ptr, &samplers[j]);
|
2020-03-24 17:01:15 +00:00
|
|
|
break;
|
2020-07-27 12:17:42 +01:00
|
|
|
case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
|
|
|
|
/* nothing in descriptor set - framebuffer state is used instead */
|
|
|
|
break;
|
2020-03-24 17:01:15 +00:00
|
|
|
default:
|
|
|
|
unreachable("unimplemented descriptor type");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
src = (char *) src + templ->entry[i].src_stride;
|
|
|
|
ptr += templ->entry[i].dst_stride;
|
|
|
|
dst_offset += templ->entry[i].dst_stride;
|
|
|
|
}
|
|
|
|
}
|
2018-08-08 23:23:57 +01:00
|
|
|
}
|
|
|
|
|
2021-06-07 05:59:32 +01:00
|
|
|
VKAPI_ATTR void VKAPI_CALL
|
2018-08-08 23:23:57 +01:00
|
|
|
tu_UpdateDescriptorSetWithTemplate(
|
2018-11-05 06:42:55 +00:00
|
|
|
VkDevice _device,
|
|
|
|
VkDescriptorSet descriptorSet,
|
2019-02-02 01:08:51 +00:00
|
|
|
VkDescriptorUpdateTemplate descriptorUpdateTemplate,
|
2018-11-05 06:42:55 +00:00
|
|
|
const void *pData)
|
2018-08-08 23:23:57 +01:00
|
|
|
{
|
2021-03-23 16:39:32 +00:00
|
|
|
TU_FROM_HANDLE(tu_device, device, _device);
|
2018-08-08 23:23:57 +01:00
|
|
|
TU_FROM_HANDLE(tu_descriptor_set, set, descriptorSet);
|
|
|
|
|
2021-03-23 16:39:32 +00:00
|
|
|
tu_update_descriptor_set_with_template(device, set, descriptorUpdateTemplate, pData);
|
2018-08-08 23:23:57 +01:00
|
|
|
}
|
|
|
|
|
2021-06-07 05:59:32 +01:00
|
|
|
VKAPI_ATTR VkResult VKAPI_CALL
|
2018-08-08 23:23:57 +01:00
|
|
|
tu_CreateSamplerYcbcrConversion(
|
2020-04-10 14:19:36 +01:00
|
|
|
VkDevice _device,
|
2018-11-05 06:42:55 +00:00
|
|
|
const VkSamplerYcbcrConversionCreateInfo *pCreateInfo,
|
|
|
|
const VkAllocationCallbacks *pAllocator,
|
|
|
|
VkSamplerYcbcrConversion *pYcbcrConversion)
|
2018-08-08 23:23:57 +01:00
|
|
|
{
|
2020-04-10 14:19:36 +01:00
|
|
|
TU_FROM_HANDLE(tu_device, device, _device);
|
|
|
|
struct tu_sampler_ycbcr_conversion *conversion;
|
|
|
|
|
2020-07-13 04:08:15 +01:00
|
|
|
conversion = vk_object_alloc(&device->vk, pAllocator, sizeof(*conversion),
|
|
|
|
VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION);
|
2020-04-10 14:19:36 +01:00
|
|
|
if (!conversion)
|
2021-09-24 21:35:20 +01:00
|
|
|
return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
|
2020-04-10 14:19:36 +01:00
|
|
|
|
|
|
|
conversion->format = pCreateInfo->format;
|
|
|
|
conversion->ycbcr_model = pCreateInfo->ycbcrModel;
|
|
|
|
conversion->ycbcr_range = pCreateInfo->ycbcrRange;
|
|
|
|
conversion->components = pCreateInfo->components;
|
|
|
|
conversion->chroma_offsets[0] = pCreateInfo->xChromaOffset;
|
|
|
|
conversion->chroma_offsets[1] = pCreateInfo->yChromaOffset;
|
|
|
|
conversion->chroma_filter = pCreateInfo->chromaFilter;
|
|
|
|
|
|
|
|
*pYcbcrConversion = tu_sampler_ycbcr_conversion_to_handle(conversion);
|
2018-08-08 23:23:57 +01:00
|
|
|
return VK_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2021-06-07 05:59:32 +01:00
|
|
|
VKAPI_ATTR void VKAPI_CALL
|
2020-04-10 14:19:36 +01:00
|
|
|
tu_DestroySamplerYcbcrConversion(VkDevice _device,
|
2018-11-05 06:42:55 +00:00
|
|
|
VkSamplerYcbcrConversion ycbcrConversion,
|
|
|
|
const VkAllocationCallbacks *pAllocator)
|
2018-08-08 23:23:57 +01:00
|
|
|
{
|
2020-04-10 14:19:36 +01:00
|
|
|
TU_FROM_HANDLE(tu_device, device, _device);
|
|
|
|
TU_FROM_HANDLE(tu_sampler_ycbcr_conversion, ycbcr_conversion, ycbcrConversion);
|
|
|
|
|
2020-07-13 04:08:15 +01:00
|
|
|
if (!ycbcr_conversion)
|
|
|
|
return;
|
|
|
|
|
|
|
|
vk_object_free(&device->vk, pAllocator, ycbcr_conversion);
|
2018-08-08 23:23:57 +01:00
|
|
|
}
|