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"
|
|
|
|
#include "vk_util.h"
|
|
|
|
|
|
|
|
static int
|
|
|
|
binding_compare(const void *av, const void *bv)
|
|
|
|
{
|
|
|
|
const VkDescriptorSetLayoutBinding *a =
|
2019-01-09 22:16:01 +00:00
|
|
|
(const VkDescriptorSetLayoutBinding *) av;
|
2018-08-08 23:23:57 +01:00
|
|
|
const VkDescriptorSetLayoutBinding *b =
|
2019-01-09 22:16:01 +00:00
|
|
|
(const VkDescriptorSetLayoutBinding *) bv;
|
2018-08-08 23:23:57 +01:00
|
|
|
|
|
|
|
return (a->binding < b->binding) ? -1 : (a->binding > b->binding) ? 1 : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static VkDescriptorSetLayoutBinding *
|
|
|
|
create_sorted_bindings(const VkDescriptorSetLayoutBinding *bindings,
|
|
|
|
unsigned count)
|
|
|
|
{
|
|
|
|
VkDescriptorSetLayoutBinding *sorted_bindings =
|
2019-01-09 22:16:01 +00:00
|
|
|
malloc(count * sizeof(VkDescriptorSetLayoutBinding));
|
2018-08-08 23:23:57 +01:00
|
|
|
if (!sorted_bindings)
|
|
|
|
return NULL;
|
|
|
|
|
2019-01-09 22:16:01 +00:00
|
|
|
memcpy(sorted_bindings, bindings,
|
|
|
|
count * sizeof(VkDescriptorSetLayoutBinding));
|
2018-08-08 23:23:57 +01:00
|
|
|
|
2019-01-09 22:16:01 +00:00
|
|
|
qsort(sorted_bindings, count, sizeof(VkDescriptorSetLayoutBinding),
|
2018-08-08 23:23:57 +01:00
|
|
|
binding_compare);
|
|
|
|
|
|
|
|
return sorted_bindings;
|
|
|
|
}
|
|
|
|
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-08 23:23:57 +01:00
|
|
|
VkResult
|
|
|
|
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);
|
2018-08-08 23:23:57 +01:00
|
|
|
|
|
|
|
uint32_t max_binding = 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++) {
|
2018-08-08 23:23:57 +01:00
|
|
|
max_binding = MAX2(max_binding, pCreateInfo->pBindings[j].binding);
|
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 =
|
|
|
|
offsetof(struct tu_descriptor_set_layout, binding[max_binding + 1]);
|
|
|
|
|
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
|
|
|
|
2020-07-13 04:08:15 +01:00
|
|
|
set_layout = vk_object_zalloc(&device->vk, pAllocator, size,
|
|
|
|
VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT);
|
2018-08-08 23:23:57 +01:00
|
|
|
if (!set_layout)
|
|
|
|
return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
|
|
|
|
|
|
|
|
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 */
|
2019-10-07 02:42:27 +01:00
|
|
|
struct tu_sampler *samplers = (void*) &set_layout->binding[max_binding + 1];
|
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
|
|
|
|
2019-01-09 22:16:01 +00:00
|
|
|
VkDescriptorSetLayoutBinding *bindings = create_sorted_bindings(
|
|
|
|
pCreateInfo->pBindings, pCreateInfo->bindingCount);
|
2018-08-08 23:23:57 +01:00
|
|
|
if (!bindings) {
|
2020-07-13 04:08:15 +01:00
|
|
|
vk_object_free(&device->vk, pAllocator, set_layout);
|
2018-08-08 23:23:57 +01:00
|
|
|
return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
|
|
|
|
}
|
|
|
|
|
|
|
|
set_layout->binding_count = max_binding + 1;
|
|
|
|
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;
|
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 buffer_count = 0;
|
2018-08-08 23:23:57 +01:00
|
|
|
|
|
|
|
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].buffer_offset = buffer_count;
|
|
|
|
set_layout->binding[b].dynamic_offset_offset = dynamic_offset_count;
|
2019-09-26 04:00:16 +01:00
|
|
|
set_layout->binding[b].size = descriptor_size(binding->descriptorType);
|
2020-03-23 16:23:32 +00:00
|
|
|
set_layout->binding[b].shader_stages = binding->stageFlags;
|
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 */
|
2018-08-08 23:23:57 +01:00
|
|
|
assert(binding->binding == max_binding);
|
|
|
|
|
|
|
|
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_SAMPLER &&
|
|
|
|
binding->descriptorType != VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT)
|
|
|
|
buffer_count += binding->descriptorCount;
|
|
|
|
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;
|
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->buffer_count = buffer_count;
|
2018-08-08 23:23:57 +01:00
|
|
|
|
|
|
|
*pSetLayout = tu_descriptor_set_layout_to_handle(set_layout);
|
|
|
|
|
|
|
|
return VK_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
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;
|
|
|
|
|
2020-07-13 04:08:15 +01:00
|
|
|
vk_object_free(&device->vk, pAllocator, set_layout);
|
2018-08-08 23:23:57 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
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
|
|
|
{
|
2019-01-09 22:16:01 +00:00
|
|
|
VkDescriptorSetLayoutBinding *bindings = create_sorted_bindings(
|
|
|
|
pCreateInfo->pBindings, pCreateInfo->bindingCount);
|
2018-08-08 23:23:57 +01:00
|
|
|
if (!bindings) {
|
|
|
|
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);
|
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;
|
|
|
|
|
2019-09-26 04:00:16 +01:00
|
|
|
uint64_t descriptor_sz = descriptor_size(binding->descriptorType);
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
free(bindings);
|
|
|
|
|
|
|
|
pSupport->supported = supported;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Pipeline layouts. These have nothing to do with the pipeline. They are
|
|
|
|
* just multiple descriptor set layouts pasted together.
|
|
|
|
*/
|
|
|
|
|
|
|
|
VkResult
|
|
|
|
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;
|
|
|
|
struct mesa_sha1 ctx;
|
|
|
|
|
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)
|
|
|
|
return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
_mesa_sha1_init(&ctx);
|
|
|
|
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;
|
|
|
|
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
|
|
|
for (uint32_t b = 0; b < set_layout->binding_count; b++) {
|
|
|
|
if (set_layout->binding[b].immutable_samplers_offset)
|
|
|
|
_mesa_sha1_update(
|
2019-01-09 22:16:01 +00:00
|
|
|
&ctx,
|
|
|
|
tu_immutable_samplers(set_layout, set_layout->binding + b),
|
|
|
|
set_layout->binding[b].array_size * 4 * sizeof(uint32_t));
|
2018-08-08 23:23:57 +01:00
|
|
|
}
|
2019-01-09 22:16:01 +00:00
|
|
|
_mesa_sha1_update(
|
|
|
|
&ctx, set_layout->binding,
|
|
|
|
sizeof(set_layout->binding[0]) * set_layout->binding_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);
|
2019-01-09 22:16:01 +00:00
|
|
|
_mesa_sha1_update(&ctx, &layout->push_constant_size,
|
|
|
|
sizeof(layout->push_constant_size));
|
2018-08-08 23:23:57 +01:00
|
|
|
_mesa_sha1_final(&ctx, layout->sha1);
|
|
|
|
*pPipelineLayout = tu_pipeline_layout_to_handle(layout);
|
|
|
|
|
|
|
|
return VK_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
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
|
|
|
|
|
|
|
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,
|
|
|
|
const struct tu_descriptor_set_layout *layout,
|
|
|
|
const uint32_t *variable_count,
|
|
|
|
struct tu_descriptor_set **out_set)
|
|
|
|
{
|
|
|
|
struct tu_descriptor_set *set;
|
|
|
|
uint32_t buffer_count = layout->buffer_count;
|
|
|
|
if (variable_count) {
|
|
|
|
unsigned stride = 1;
|
|
|
|
if (layout->binding[layout->binding_count - 1].type == VK_DESCRIPTOR_TYPE_SAMPLER ||
|
|
|
|
layout->binding[layout->binding_count - 1].type == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT)
|
|
|
|
stride = 0;
|
|
|
|
buffer_count = layout->binding[layout->binding_count - 1].buffer_offset +
|
|
|
|
*variable_count * stride;
|
|
|
|
}
|
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 dynamic_offset = sizeof(struct tu_descriptor_set) +
|
2019-09-26 04:00:16 +01:00
|
|
|
sizeof(struct tu_bo *) * buffer_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
|
|
|
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)
|
|
|
|
return vk_error(device->instance, VK_ERROR_OUT_OF_POOL_MEMORY);
|
|
|
|
|
|
|
|
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)
|
|
|
|
return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
2019-09-26 04:00:16 +01:00
|
|
|
return vk_error(device->instance, VK_ERROR_OUT_OF_POOL_MEMORY);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* 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) {
|
|
|
|
set->mapped_ptr = (uint32_t*)(pool->bo.map + pool->current_offset);
|
|
|
|
set->va = pool->bo.iova + pool->current_offset;
|
|
|
|
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);
|
2019-09-26 04:00:16 +01:00
|
|
|
return vk_error(device->instance, VK_ERROR_OUT_OF_POOL_MEMORY);
|
|
|
|
}
|
|
|
|
|
|
|
|
set->mapped_ptr = (uint32_t*)(pool->bo.map + offset);
|
|
|
|
set->va = pool->bo.iova + offset;
|
|
|
|
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
|
|
|
|
return vk_error(device->instance, VK_ERROR_OUT_OF_POOL_MEMORY);
|
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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) {
|
|
|
|
uint32_t offset = (uint8_t*)set->mapped_ptr - (uint8_t*)pool->bo.map;
|
|
|
|
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
|
|
|
|
|
|
|
vk_object_free(&device->vk, NULL, set);
|
2019-09-26 04:00:16 +01:00
|
|
|
}
|
|
|
|
|
2018-08-08 23:23:57 +01:00
|
|
|
VkResult
|
|
|
|
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;
|
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;
|
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)
|
|
|
|
return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
|
|
|
|
|
|
|
|
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) {
|
|
|
|
VkResult ret;
|
|
|
|
|
|
|
|
ret = tu_bo_init_new(device, &pool->bo, bo_size);
|
|
|
|
assert(ret == VK_SUCCESS);
|
|
|
|
|
|
|
|
ret = tu_bo_map(device, &pool->bo);
|
|
|
|
assert(ret == VK_SUCCESS);
|
|
|
|
}
|
|
|
|
pool->size = bo_size;
|
|
|
|
pool->max_entry_count = pCreateInfo->maxSets;
|
|
|
|
|
|
|
|
*pDescriptorPool = tu_descriptor_pool_to_handle(pool);
|
2018-08-08 23:23:57 +01:00
|
|
|
return VK_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
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;
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pool->size)
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
VkResult
|
|
|
|
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);
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
VkResult
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
VkResult
|
|
|
|
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]);
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2019-10-07 02:42:27 +01:00
|
|
|
static void write_texel_buffer_descriptor(struct tu_device *device,
|
|
|
|
struct tu_cmd_buffer *cmd_buffer,
|
|
|
|
unsigned *dst,
|
|
|
|
struct tu_bo **buffer_list,
|
2020-01-22 20:25:10 +00:00
|
|
|
const VkBufferView buffer_view)
|
2019-10-07 02:42:27 +01:00
|
|
|
{
|
2020-01-22 20:25:10 +00:00
|
|
|
TU_FROM_HANDLE(tu_buffer_view, view, buffer_view);
|
|
|
|
|
|
|
|
memcpy(dst, view->descriptor, sizeof(view->descriptor));
|
|
|
|
|
|
|
|
if (cmd_buffer)
|
|
|
|
tu_bo_list_add(&cmd_buffer->bo_list, view->buffer->bo, MSM_SUBMIT_BO_READ);
|
|
|
|
else
|
|
|
|
*buffer_list = view->buffer->bo;
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-26 04:00:16 +01:00
|
|
|
static void write_buffer_descriptor(struct tu_device *device,
|
|
|
|
struct tu_cmd_buffer *cmd_buffer,
|
|
|
|
unsigned *dst,
|
|
|
|
struct tu_bo **buffer_list,
|
|
|
|
const VkDescriptorBufferInfo *buffer_info)
|
|
|
|
{
|
|
|
|
TU_FROM_HANDLE(tu_buffer, buffer, buffer_info->buffer);
|
|
|
|
|
2019-12-04 21:13:16 +00:00
|
|
|
uint64_t va = tu_buffer_iova(buffer) + 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);
|
|
|
|
range = ALIGN_POT(range, 4) / 4;
|
|
|
|
dst[0] =
|
|
|
|
A6XX_IBO_0_TILE_MODE(TILE6_LINEAR) | A6XX_IBO_0_FMT(FMT6_32_UINT);
|
|
|
|
dst[1] = range;
|
|
|
|
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
|
|
|
|
|
|
|
if (cmd_buffer)
|
|
|
|
tu_bo_list_add(&cmd_buffer->bo_list, buffer->bo, MSM_SUBMIT_BO_READ);
|
|
|
|
else
|
|
|
|
*buffer_list = buffer->bo;
|
|
|
|
}
|
|
|
|
|
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 void write_ubo_descriptor(struct tu_device *device,
|
|
|
|
struct tu_cmd_buffer *cmd_buffer,
|
|
|
|
unsigned *dst,
|
|
|
|
struct tu_bo **buffer_list,
|
|
|
|
const VkDescriptorBufferInfo *buffer_info)
|
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;
|
|
|
|
uint64_t va = tu_buffer_iova(buffer) + buffer_info->offset;
|
|
|
|
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
|
|
|
|
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 (cmd_buffer)
|
|
|
|
tu_bo_list_add(&cmd_buffer->bo_list, buffer->bo, MSM_SUBMIT_BO_READ);
|
|
|
|
else
|
|
|
|
*buffer_list = buffer->bo;
|
2019-10-07 02:42:27 +01:00
|
|
|
}
|
|
|
|
|
2019-09-26 04:00:16 +01:00
|
|
|
static void
|
|
|
|
write_image_descriptor(struct tu_device *device,
|
|
|
|
struct tu_cmd_buffer *cmd_buffer,
|
2019-10-07 02:42:27 +01:00
|
|
|
unsigned *dst,
|
2019-09-26 04:00:16 +01:00
|
|
|
struct tu_bo **buffer_list,
|
|
|
|
VkDescriptorType descriptor_type,
|
|
|
|
const VkDescriptorImageInfo *image_info)
|
|
|
|
{
|
|
|
|
TU_FROM_HANDLE(tu_image_view, iview, image_info->imageView);
|
|
|
|
|
|
|
|
if (descriptor_type == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) {
|
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
|
|
|
memcpy(dst, iview->storage_descriptor, sizeof(iview->storage_descriptor));
|
|
|
|
} else {
|
|
|
|
memcpy(dst, iview->descriptor, sizeof(iview->descriptor));
|
2019-09-26 04:00:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (cmd_buffer)
|
|
|
|
tu_bo_list_add(&cmd_buffer->bo_list, iview->image->bo, MSM_SUBMIT_BO_READ);
|
|
|
|
else
|
|
|
|
*buffer_list = iview->image->bo;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
write_combined_image_sampler_descriptor(struct tu_device *device,
|
|
|
|
struct tu_cmd_buffer *cmd_buffer,
|
|
|
|
unsigned sampler_offset,
|
|
|
|
unsigned *dst,
|
|
|
|
struct tu_bo **buffer_list,
|
|
|
|
VkDescriptorType descriptor_type,
|
|
|
|
const VkDescriptorImageInfo *image_info,
|
|
|
|
bool has_sampler)
|
|
|
|
{
|
|
|
|
TU_FROM_HANDLE(tu_sampler, sampler, image_info->sampler);
|
|
|
|
|
2019-10-07 02:42:27 +01:00
|
|
|
write_image_descriptor(device, cmd_buffer, dst, buffer_list,
|
2019-09-26 04:00:16 +01:00
|
|
|
descriptor_type, image_info);
|
|
|
|
/* copy over sampler state */
|
|
|
|
if (has_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
|
|
|
|
write_sampler_descriptor(struct tu_device *device,
|
|
|
|
unsigned *dst,
|
|
|
|
const VkDescriptorImageInfo *image_info)
|
|
|
|
{
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2018-08-08 23:23:57 +01:00
|
|
|
void
|
|
|
|
tu_update_descriptor_sets(struct tu_device *device,
|
2018-11-05 06:42:55 +00:00
|
|
|
struct tu_cmd_buffer *cmd_buffer,
|
|
|
|
VkDescriptorSet dstSetOverride,
|
|
|
|
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];
|
|
|
|
TU_FROM_HANDLE(tu_descriptor_set, set,
|
|
|
|
dstSetOverride ? dstSetOverride : writeset->dstSet);
|
|
|
|
const struct tu_descriptor_set_binding_layout *binding_layout =
|
|
|
|
set->layout->binding + writeset->dstBinding;
|
|
|
|
uint32_t *ptr = set->mapped_ptr;
|
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
|
|
|
struct tu_bo **buffer_list = set->buffers;
|
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
|
|
|
buffer_list += binding_layout->buffer_offset;
|
|
|
|
buffer_list += writeset->dstArrayElement;
|
|
|
|
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;
|
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
|
|
|
write_ubo_descriptor(device, cmd_buffer,
|
|
|
|
set->dynamic_descriptors + A6XX_TEX_CONST_DWORDS * idx,
|
|
|
|
buffer_list, 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:
|
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
|
|
|
write_ubo_descriptor(device, cmd_buffer, ptr, buffer_list,
|
|
|
|
writeset->pBufferInfo + j);
|
|
|
|
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;
|
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
|
|
|
write_buffer_descriptor(device, cmd_buffer,
|
|
|
|
set->dynamic_descriptors + A6XX_TEX_CONST_DWORDS * idx,
|
|
|
|
buffer_list, writeset->pBufferInfo + j);
|
|
|
|
break;
|
|
|
|
}
|
2019-10-07 02:42:27 +01:00
|
|
|
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
|
2019-09-26 04:00:16 +01:00
|
|
|
write_buffer_descriptor(device, cmd_buffer, ptr, buffer_list,
|
|
|
|
writeset->pBufferInfo + j);
|
|
|
|
break;
|
2019-10-07 02:42:27 +01:00
|
|
|
case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
|
|
|
|
case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
|
|
|
|
write_texel_buffer_descriptor(device, cmd_buffer, ptr, buffer_list,
|
|
|
|
writeset->pTexelBufferView[j]);
|
|
|
|
break;
|
|
|
|
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
|
|
|
|
case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
|
|
|
|
write_image_descriptor(device, cmd_buffer, ptr, buffer_list,
|
|
|
|
writeset->descriptorType,
|
|
|
|
writeset->pImageInfo + j);
|
|
|
|
break;
|
2019-09-26 04:00:16 +01:00
|
|
|
case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
|
|
|
|
write_combined_image_sampler_descriptor(device, cmd_buffer,
|
2019-12-20 00:47:08 +00:00
|
|
|
A6XX_TEX_CONST_DWORDS * 4,
|
2019-09-26 04:00:16 +01:00
|
|
|
ptr, buffer_list,
|
|
|
|
writeset->descriptorType,
|
|
|
|
writeset->pImageInfo + j,
|
|
|
|
!binding_layout->immutable_samplers_offset);
|
2019-10-07 02:42:27 +01:00
|
|
|
break;
|
|
|
|
case VK_DESCRIPTOR_TYPE_SAMPLER:
|
|
|
|
write_sampler_descriptor(device, ptr, writeset->pImageInfo + 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;
|
|
|
|
++buffer_list;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
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
|
|
|
struct tu_bo **src_buffer_list = src_set->buffers;
|
|
|
|
struct tu_bo **dst_buffer_list = dst_set->buffers;
|
2019-09-26 04:00:16 +01:00
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
src_buffer_list += src_binding_layout->buffer_offset;
|
|
|
|
src_buffer_list += copyset->srcArrayElement;
|
|
|
|
|
|
|
|
dst_buffer_list += dst_binding_layout->buffer_offset;
|
|
|
|
dst_buffer_list += copyset->dstArrayElement;
|
|
|
|
|
|
|
|
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:
|
|
|
|
memcpy(dst_ptr, src_ptr, src_binding_layout->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
|
|
|
|
2019-09-26 04:00:16 +01:00
|
|
|
src_ptr += src_binding_layout->size / 4;
|
|
|
|
dst_ptr += dst_binding_layout->size / 4;
|
|
|
|
|
|
|
|
if (src_binding_layout->type != VK_DESCRIPTOR_TYPE_SAMPLER) {
|
|
|
|
/* Sampler descriptors don't have a buffer list. */
|
|
|
|
dst_buffer_list[j] = src_buffer_list[j];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-08-08 23:23:57 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
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
|
|
|
{
|
|
|
|
TU_FROM_HANDLE(tu_device, device, _device);
|
|
|
|
|
2019-01-09 22:16:01 +00:00
|
|
|
tu_update_descriptor_sets(device, NULL, VK_NULL_HANDLE,
|
|
|
|
descriptorWriteCount, pDescriptorWrites,
|
|
|
|
descriptorCopyCount, pDescriptorCopies);
|
2018-08-08 23:23:57 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
VkResult
|
|
|
|
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)
|
|
|
|
return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
const uint32_t buffer_offset = binding_layout->buffer_offset +
|
|
|
|
entry->dstArrayElement;
|
|
|
|
uint32_t dst_offset, dst_stride;
|
|
|
|
|
|
|
|
/* 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;
|
|
|
|
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,
|
|
|
|
.buffer_offset = buffer_offset,
|
|
|
|
.has_sampler = !binding_layout->immutable_samplers_offset,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
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(
|
2018-11-05 06:42:55 +00:00
|
|
|
struct tu_device *device,
|
|
|
|
struct tu_cmd_buffer *cmd_buffer,
|
|
|
|
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;
|
|
|
|
struct tu_bo **buffer_list = set->buffers;
|
|
|
|
|
|
|
|
ptr += templ->entry[i].dst_offset;
|
|
|
|
buffer_list += templ->entry[i].buffer_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));
|
|
|
|
write_ubo_descriptor(device, cmd_buffer,
|
|
|
|
set->dynamic_descriptors + dst_offset,
|
|
|
|
buffer_list, src);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
|
|
|
|
write_ubo_descriptor(device, cmd_buffer, ptr, buffer_list, src);
|
|
|
|
break;
|
|
|
|
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: {
|
|
|
|
assert(!(set->layout->flags & VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR));
|
|
|
|
write_buffer_descriptor(device, cmd_buffer,
|
|
|
|
set->dynamic_descriptors + dst_offset,
|
|
|
|
buffer_list, src);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
|
|
|
|
write_buffer_descriptor(device, cmd_buffer, ptr, buffer_list, src);
|
|
|
|
break;
|
|
|
|
case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
|
|
|
|
case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
|
|
|
|
write_texel_buffer_descriptor(device, cmd_buffer, ptr,
|
|
|
|
buffer_list, *(VkBufferView *) src);
|
|
|
|
break;
|
|
|
|
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
|
|
|
|
case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
|
2020-06-15 04:10:01 +01:00
|
|
|
case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: {
|
2020-03-24 17:01:15 +00:00
|
|
|
write_image_descriptor(device, cmd_buffer, ptr, buffer_list,
|
|
|
|
templ->entry[i].descriptor_type,
|
|
|
|
src);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
|
|
|
|
write_combined_image_sampler_descriptor(device, cmd_buffer,
|
|
|
|
A6XX_TEX_CONST_DWORDS * 4,
|
|
|
|
ptr, buffer_list,
|
|
|
|
templ->entry[i].descriptor_type,
|
|
|
|
src,
|
|
|
|
templ->entry[i].has_sampler);
|
|
|
|
break;
|
|
|
|
case VK_DESCRIPTOR_TYPE_SAMPLER:
|
|
|
|
write_sampler_descriptor(device, ptr, src);
|
|
|
|
break;
|
|
|
|
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;
|
|
|
|
++buffer_list;
|
|
|
|
}
|
|
|
|
}
|
2018-08-08 23:23:57 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
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
|
|
|
{
|
|
|
|
TU_FROM_HANDLE(tu_device, device, _device);
|
|
|
|
TU_FROM_HANDLE(tu_descriptor_set, set, descriptorSet);
|
|
|
|
|
2019-01-09 22:16:01 +00:00
|
|
|
tu_update_descriptor_set_with_template(device, NULL, set,
|
|
|
|
descriptorUpdateTemplate, pData);
|
2018-08-08 23:23:57 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
VkResult
|
|
|
|
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)
|
|
|
|
return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
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
|
|
|
}
|