2021-06-24 13:09:35 +02:00
|
|
|
|
/*
|
|
|
|
|
|
* Copyright © Microsoft Corporation
|
|
|
|
|
|
*
|
|
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
|
|
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
|
|
|
|
* to deal in the Software without restriction, including without limitation
|
|
|
|
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
|
|
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
|
|
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
|
|
|
|
*
|
|
|
|
|
|
* The above copyright notice and this permission notice (including the next
|
|
|
|
|
|
* paragraph) shall be included in all copies or substantial portions of the
|
|
|
|
|
|
* Software.
|
|
|
|
|
|
*
|
|
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
|
|
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
|
|
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
|
|
|
|
* IN THE SOFTWARE.
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#include "dzn_private.h"
|
|
|
|
|
|
|
|
|
|
|
|
#include "vk_alloc.h"
|
|
|
|
|
|
#include "vk_descriptors.h"
|
|
|
|
|
|
#include "vk_util.h"
|
|
|
|
|
|
|
2023-03-02 19:58:09 -08:00
|
|
|
|
#include "dxil_spirv_nir.h"
|
|
|
|
|
|
|
2022-06-21 17:09:27 +02:00
|
|
|
|
#include "util/mesa-sha1.h"
|
|
|
|
|
|
|
|
|
|
|
|
static uint32_t
|
|
|
|
|
|
translate_desc_stages(VkShaderStageFlags in)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (in == VK_SHADER_STAGE_ALL)
|
|
|
|
|
|
in = VK_SHADER_STAGE_ALL_GRAPHICS | VK_SHADER_STAGE_COMPUTE_BIT;
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t out = 0;
|
|
|
|
|
|
|
|
|
|
|
|
u_foreach_bit(s, in)
|
|
|
|
|
|
out |= BITFIELD_BIT(vk_to_mesa_shader_stage(BITFIELD_BIT(s)));
|
|
|
|
|
|
|
|
|
|
|
|
return out;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2021-06-24 13:09:35 +02:00
|
|
|
|
static D3D12_SHADER_VISIBILITY
|
|
|
|
|
|
translate_desc_visibility(VkShaderStageFlags in)
|
|
|
|
|
|
{
|
|
|
|
|
|
switch (in) {
|
|
|
|
|
|
case VK_SHADER_STAGE_VERTEX_BIT: return D3D12_SHADER_VISIBILITY_VERTEX;
|
|
|
|
|
|
case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT: return D3D12_SHADER_VISIBILITY_HULL;
|
|
|
|
|
|
case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT: return D3D12_SHADER_VISIBILITY_DOMAIN;
|
|
|
|
|
|
case VK_SHADER_STAGE_GEOMETRY_BIT: return D3D12_SHADER_VISIBILITY_GEOMETRY;
|
|
|
|
|
|
case VK_SHADER_STAGE_FRAGMENT_BIT: return D3D12_SHADER_VISIBILITY_PIXEL;
|
|
|
|
|
|
default: return D3D12_SHADER_VISIBILITY_ALL;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static D3D12_DESCRIPTOR_RANGE_TYPE
|
|
|
|
|
|
desc_type_to_range_type(VkDescriptorType in, bool writeable)
|
|
|
|
|
|
{
|
|
|
|
|
|
switch (in) {
|
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_SAMPLER:
|
|
|
|
|
|
return D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER;
|
|
|
|
|
|
|
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
|
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
|
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
|
|
|
|
|
|
return D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
|
|
|
|
|
|
|
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
|
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
|
|
|
|
|
|
return D3D12_DESCRIPTOR_RANGE_TYPE_CBV;
|
|
|
|
|
|
|
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
|
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
|
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
|
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
|
|
|
|
|
|
return writeable ? D3D12_DESCRIPTOR_RANGE_TYPE_UAV : D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
|
|
|
|
|
|
default:
|
|
|
|
|
|
unreachable("Unsupported desc type");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static bool
|
|
|
|
|
|
is_dynamic_desc_type(VkDescriptorType desc_type)
|
|
|
|
|
|
{
|
|
|
|
|
|
return (desc_type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC ||
|
|
|
|
|
|
desc_type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-03-02 19:58:09 -08:00
|
|
|
|
static bool
|
|
|
|
|
|
is_buffer_desc_type_without_view(VkDescriptorType desc_type)
|
|
|
|
|
|
{
|
|
|
|
|
|
return (desc_type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER ||
|
|
|
|
|
|
desc_type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-03-28 09:41:17 +02:00
|
|
|
|
static bool
|
2023-03-02 13:06:22 -08:00
|
|
|
|
dzn_descriptor_type_depends_on_shader_usage(VkDescriptorType type, bool bindless)
|
2022-03-28 09:41:17 +02:00
|
|
|
|
{
|
2023-03-02 13:06:22 -08:00
|
|
|
|
if (bindless)
|
|
|
|
|
|
return false;
|
2022-03-28 09:41:17 +02:00
|
|
|
|
return type == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER ||
|
|
|
|
|
|
type == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE ||
|
|
|
|
|
|
type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER ||
|
|
|
|
|
|
type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-06-08 06:57:18 -07:00
|
|
|
|
static inline bool
|
|
|
|
|
|
dzn_desc_type_has_sampler(VkDescriptorType type)
|
|
|
|
|
|
{
|
|
|
|
|
|
return type == VK_DESCRIPTOR_TYPE_SAMPLER ||
|
|
|
|
|
|
type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2021-06-24 13:09:35 +02:00
|
|
|
|
static uint32_t
|
2023-03-02 13:06:22 -08:00
|
|
|
|
num_descs_for_type(VkDescriptorType type, bool static_sampler, bool bindless)
|
2021-06-24 13:09:35 +02:00
|
|
|
|
{
|
2023-03-02 13:06:22 -08:00
|
|
|
|
if (bindless)
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
2021-06-24 13:09:35 +02:00
|
|
|
|
unsigned num_descs = 1;
|
|
|
|
|
|
|
|
|
|
|
|
/* Some type map to an SRV or UAV depending on how the shaders is using the
|
|
|
|
|
|
* resource (NONWRITEABLE flag set or not), in that case we need to reserve
|
|
|
|
|
|
* slots for both the UAV and SRV descs.
|
|
|
|
|
|
*/
|
2023-03-02 13:06:22 -08:00
|
|
|
|
if (dzn_descriptor_type_depends_on_shader_usage(type, false))
|
2021-06-24 13:09:35 +02:00
|
|
|
|
num_descs++;
|
|
|
|
|
|
|
|
|
|
|
|
/* There's no combined SRV+SAMPLER type in d3d12, we need an descriptor
|
|
|
|
|
|
* for the sampler.
|
|
|
|
|
|
*/
|
|
|
|
|
|
if (type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
|
|
|
|
|
|
num_descs++;
|
|
|
|
|
|
|
|
|
|
|
|
/* Don't count immutable samplers, they have their own descriptor. */
|
2022-06-08 06:57:18 -07:00
|
|
|
|
if (static_sampler && dzn_desc_type_has_sampler(type))
|
2021-06-24 13:09:35 +02:00
|
|
|
|
num_descs--;
|
|
|
|
|
|
|
|
|
|
|
|
return num_descs;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static VkResult
|
2022-04-05 17:41:20 +02:00
|
|
|
|
dzn_descriptor_set_layout_create(struct dzn_device *device,
|
2021-06-24 13:09:35 +02:00
|
|
|
|
const VkDescriptorSetLayoutCreateInfo *pCreateInfo,
|
|
|
|
|
|
const VkAllocationCallbacks *pAllocator,
|
|
|
|
|
|
VkDescriptorSetLayout *out)
|
|
|
|
|
|
{
|
|
|
|
|
|
const VkDescriptorSetLayoutBinding *bindings = pCreateInfo->pBindings;
|
|
|
|
|
|
uint32_t binding_count = 0, static_sampler_count = 0, total_ranges = 0;
|
|
|
|
|
|
uint32_t dynamic_ranges_offset = 0, immutable_sampler_count = 0;
|
2023-03-02 19:58:09 -08:00
|
|
|
|
uint32_t dynamic_buffer_count = 0;
|
2022-04-06 15:04:34 +02:00
|
|
|
|
uint32_t range_count[MAX_SHADER_VISIBILITIES][NUM_POOL_TYPES] = { 0 };
|
2021-06-24 13:09:35 +02:00
|
|
|
|
|
2023-03-17 08:18:45 -07:00
|
|
|
|
const VkDescriptorSetLayoutBindingFlagsCreateInfo *binding_flags =
|
|
|
|
|
|
vk_find_struct_const(pCreateInfo->pNext, DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO);
|
|
|
|
|
|
bool has_variable_size = false;
|
|
|
|
|
|
|
2021-06-24 13:09:35 +02:00
|
|
|
|
for (uint32_t i = 0; i < pCreateInfo->bindingCount; i++) {
|
2022-04-11 04:46:31 -07:00
|
|
|
|
binding_count = MAX2(binding_count, bindings[i].binding + 1);
|
|
|
|
|
|
|
|
|
|
|
|
if (!bindings[i].descriptorCount)
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
2023-03-02 19:58:09 -08:00
|
|
|
|
D3D12_SHADER_VISIBILITY visibility = device->bindless ?
|
|
|
|
|
|
D3D12_SHADER_VISIBILITY_ALL :
|
2021-06-24 13:09:35 +02:00
|
|
|
|
translate_desc_visibility(bindings[i].stageFlags);
|
|
|
|
|
|
VkDescriptorType desc_type = bindings[i].descriptorType;
|
2022-06-08 06:57:18 -07:00
|
|
|
|
bool has_sampler = dzn_desc_type_has_sampler(desc_type);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
|
|
|
|
|
|
/* From the Vulkan 1.1.97 spec for VkDescriptorSetLayoutBinding:
|
|
|
|
|
|
*
|
|
|
|
|
|
* "If descriptorType specifies a VK_DESCRIPTOR_TYPE_SAMPLER or
|
|
|
|
|
|
* VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER type descriptor, then
|
|
|
|
|
|
* pImmutableSamplers can be used to initialize a set of immutable
|
|
|
|
|
|
* samplers. [...] If descriptorType is not one of these descriptor
|
|
|
|
|
|
* types, then pImmutableSamplers is ignored.
|
|
|
|
|
|
*
|
|
|
|
|
|
* We need to be careful here and only parse pImmutableSamplers if we
|
|
|
|
|
|
* have one of the right descriptor types.
|
|
|
|
|
|
*/
|
|
|
|
|
|
bool immutable_samplers =
|
|
|
|
|
|
has_sampler &&
|
|
|
|
|
|
bindings[i].pImmutableSamplers != NULL;
|
|
|
|
|
|
bool static_sampler = false;
|
|
|
|
|
|
|
2023-04-06 13:45:08 -07:00
|
|
|
|
if (device->support_static_samplers &&
|
|
|
|
|
|
immutable_samplers && bindings[i].descriptorCount == 1) {
|
2021-06-24 13:09:35 +02:00
|
|
|
|
VK_FROM_HANDLE(dzn_sampler, sampler, bindings[i].pImmutableSamplers[0]);
|
|
|
|
|
|
|
|
|
|
|
|
if (sampler->static_border_color != -1)
|
|
|
|
|
|
static_sampler = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (static_sampler) {
|
|
|
|
|
|
static_sampler_count += bindings[i].descriptorCount;
|
|
|
|
|
|
} else if (has_sampler) {
|
2023-03-02 19:58:09 -08:00
|
|
|
|
unsigned type = device->bindless ? D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV : D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER;
|
|
|
|
|
|
range_count[visibility][type]++;
|
2021-06-24 13:09:35 +02:00
|
|
|
|
total_ranges++;
|
|
|
|
|
|
|
|
|
|
|
|
if (immutable_samplers)
|
|
|
|
|
|
immutable_sampler_count += bindings[i].descriptorCount;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (desc_type != VK_DESCRIPTOR_TYPE_SAMPLER) {
|
|
|
|
|
|
range_count[visibility][D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV]++;
|
|
|
|
|
|
total_ranges++;
|
|
|
|
|
|
|
2023-03-02 13:06:22 -08:00
|
|
|
|
if (dzn_descriptor_type_depends_on_shader_usage(desc_type, device->bindless)) {
|
2021-06-24 13:09:35 +02:00
|
|
|
|
range_count[visibility][D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV]++;
|
|
|
|
|
|
total_ranges++;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-03-02 19:58:09 -08:00
|
|
|
|
uint32_t factor =
|
|
|
|
|
|
dzn_descriptor_type_depends_on_shader_usage(desc_type, device->bindless) ? 2 : 1;
|
|
|
|
|
|
if (is_dynamic_desc_type(desc_type))
|
|
|
|
|
|
dynamic_buffer_count += bindings[i].descriptorCount * factor;
|
|
|
|
|
|
else
|
2021-06-24 13:09:35 +02:00
|
|
|
|
dynamic_ranges_offset += bindings[i].descriptorCount * factor;
|
|
|
|
|
|
}
|
2023-03-17 08:18:45 -07:00
|
|
|
|
|
|
|
|
|
|
if (binding_flags && binding_flags->bindingCount &&
|
|
|
|
|
|
(binding_flags->pBindingFlags[i] & VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT))
|
|
|
|
|
|
has_variable_size = true;
|
2021-06-24 13:09:35 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-03-17 08:18:45 -07:00
|
|
|
|
assert(!has_variable_size || device->bindless);
|
|
|
|
|
|
|
2021-06-24 13:09:35 +02:00
|
|
|
|
/* We need to allocate decriptor set layouts off the device allocator
|
|
|
|
|
|
* with DEVICE scope because they are reference counted and may not be
|
|
|
|
|
|
* destroyed when vkDestroyDescriptorSetLayout is called.
|
|
|
|
|
|
*/
|
|
|
|
|
|
VK_MULTIALLOC(ma);
|
|
|
|
|
|
VK_MULTIALLOC_DECL(&ma, struct dzn_descriptor_set_layout, set_layout, 1);
|
|
|
|
|
|
VK_MULTIALLOC_DECL(&ma, D3D12_DESCRIPTOR_RANGE1,
|
|
|
|
|
|
ranges, total_ranges);
|
2023-01-09 12:43:16 -08:00
|
|
|
|
VK_MULTIALLOC_DECL(&ma, D3D12_STATIC_SAMPLER_DESC1, static_samplers,
|
2021-06-24 13:09:35 +02:00
|
|
|
|
static_sampler_count);
|
2022-04-05 17:41:20 +02:00
|
|
|
|
VK_MULTIALLOC_DECL(&ma, const struct dzn_sampler *, immutable_samplers,
|
2021-06-24 13:09:35 +02:00
|
|
|
|
immutable_sampler_count);
|
2022-04-05 17:41:20 +02:00
|
|
|
|
VK_MULTIALLOC_DECL(&ma, struct dzn_descriptor_set_layout_binding, binfos,
|
2021-06-24 13:09:35 +02:00
|
|
|
|
binding_count);
|
|
|
|
|
|
|
2022-06-29 04:37:43 -07:00
|
|
|
|
if (!vk_descriptor_set_layout_multizalloc(&device->vk, &ma))
|
2021-06-24 13:09:35 +02:00
|
|
|
|
return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
|
|
|
|
|
|
|
|
|
|
|
|
set_layout->static_samplers = static_samplers;
|
|
|
|
|
|
set_layout->static_sampler_count = static_sampler_count;
|
|
|
|
|
|
set_layout->immutable_samplers = immutable_samplers;
|
|
|
|
|
|
set_layout->immutable_sampler_count = immutable_sampler_count;
|
|
|
|
|
|
set_layout->bindings = binfos;
|
|
|
|
|
|
set_layout->binding_count = binding_count;
|
|
|
|
|
|
set_layout->dynamic_buffers.range_offset = dynamic_ranges_offset;
|
2023-03-02 19:58:09 -08:00
|
|
|
|
set_layout->buffer_count = dynamic_buffer_count;
|
2021-06-24 13:09:35 +02:00
|
|
|
|
|
|
|
|
|
|
for (uint32_t i = 0; i < MAX_SHADER_VISIBILITIES; i++) {
|
|
|
|
|
|
dzn_foreach_pool_type (type) {
|
|
|
|
|
|
if (range_count[i][type]) {
|
|
|
|
|
|
set_layout->ranges[i][type] = ranges;
|
|
|
|
|
|
set_layout->range_count[i][type] = range_count[i][type];
|
|
|
|
|
|
ranges += range_count[i][type];
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VkDescriptorSetLayoutBinding *ordered_bindings;
|
|
|
|
|
|
VkResult ret =
|
|
|
|
|
|
vk_create_sorted_bindings(pCreateInfo->pBindings,
|
|
|
|
|
|
pCreateInfo->bindingCount,
|
|
|
|
|
|
&ordered_bindings);
|
2023-03-01 15:47:20 -08:00
|
|
|
|
if (ret != VK_SUCCESS) {
|
|
|
|
|
|
vk_descriptor_set_layout_destroy(&device->vk, &set_layout->vk);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
return ret;
|
2023-03-01 15:47:20 -08:00
|
|
|
|
}
|
2021-06-24 13:09:35 +02:00
|
|
|
|
|
|
|
|
|
|
assert(binding_count ==
|
|
|
|
|
|
(pCreateInfo->bindingCount ?
|
|
|
|
|
|
(ordered_bindings[pCreateInfo->bindingCount - 1].binding + 1) : 0));
|
|
|
|
|
|
|
2022-04-06 15:04:34 +02:00
|
|
|
|
uint32_t range_idx[MAX_SHADER_VISIBILITIES][NUM_POOL_TYPES] = { 0 };
|
2021-06-24 13:09:35 +02:00
|
|
|
|
uint32_t static_sampler_idx = 0, immutable_sampler_idx = 0;
|
|
|
|
|
|
uint32_t dynamic_buffer_idx = 0;
|
|
|
|
|
|
uint32_t base_register = 0;
|
|
|
|
|
|
|
|
|
|
|
|
for (uint32_t i = 0; i < binding_count; i++) {
|
|
|
|
|
|
binfos[i].immutable_sampler_idx = ~0;
|
2023-03-02 19:58:09 -08:00
|
|
|
|
binfos[i].buffer_idx = ~0;
|
2021-06-24 13:09:35 +02:00
|
|
|
|
dzn_foreach_pool_type (type)
|
|
|
|
|
|
binfos[i].range_idx[type] = ~0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
for (uint32_t i = 0; i < pCreateInfo->bindingCount; i++) {
|
|
|
|
|
|
VkDescriptorType desc_type = ordered_bindings[i].descriptorType;
|
|
|
|
|
|
uint32_t binding = ordered_bindings[i].binding;
|
|
|
|
|
|
uint32_t desc_count = ordered_bindings[i].descriptorCount;
|
2022-06-08 06:57:18 -07:00
|
|
|
|
bool has_sampler = dzn_desc_type_has_sampler(desc_type);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
bool has_immutable_samplers =
|
|
|
|
|
|
has_sampler &&
|
|
|
|
|
|
ordered_bindings[i].pImmutableSamplers != NULL;
|
2023-04-06 13:45:08 -07:00
|
|
|
|
bool has_static_sampler = device->support_static_samplers &&
|
|
|
|
|
|
has_immutable_samplers && desc_count == 1;
|
2021-06-24 13:09:35 +02:00
|
|
|
|
bool is_dynamic = is_dynamic_desc_type(desc_type);
|
|
|
|
|
|
|
2023-03-02 19:58:09 -08:00
|
|
|
|
D3D12_SHADER_VISIBILITY visibility = device->bindless ?
|
|
|
|
|
|
D3D12_SHADER_VISIBILITY_ALL :
|
2021-06-24 13:09:35 +02:00
|
|
|
|
translate_desc_visibility(ordered_bindings[i].stageFlags);
|
|
|
|
|
|
binfos[binding].type = desc_type;
|
2022-06-21 17:09:27 +02:00
|
|
|
|
binfos[binding].stages =
|
|
|
|
|
|
translate_desc_stages(ordered_bindings[i].stageFlags);
|
|
|
|
|
|
set_layout->stages |= binfos[binding].stages;
|
2021-06-24 13:09:35 +02:00
|
|
|
|
binfos[binding].visibility = visibility;
|
2023-03-17 08:18:45 -07:00
|
|
|
|
/* Only the last binding can have variable size */
|
|
|
|
|
|
if (binding == binding_count - 1)
|
|
|
|
|
|
binfos[binding].variable_size = has_variable_size;
|
2023-03-13 12:43:45 -07:00
|
|
|
|
if (is_dynamic && device->bindless) {
|
|
|
|
|
|
/* Assign these into a separate 0->N space */
|
|
|
|
|
|
binfos[binding].base_shader_register = dynamic_buffer_idx;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
binfos[binding].base_shader_register = base_register;
|
|
|
|
|
|
assert(base_register + desc_count >= base_register);
|
|
|
|
|
|
base_register += desc_count;
|
|
|
|
|
|
}
|
2021-06-24 13:09:35 +02:00
|
|
|
|
|
|
|
|
|
|
if (has_static_sampler) {
|
|
|
|
|
|
VK_FROM_HANDLE(dzn_sampler, sampler, ordered_bindings[i].pImmutableSamplers[0]);
|
|
|
|
|
|
|
|
|
|
|
|
/* Not all border colors are supported. */
|
|
|
|
|
|
if (sampler->static_border_color != -1) {
|
2023-01-09 12:43:16 -08:00
|
|
|
|
D3D12_STATIC_SAMPLER_DESC1 *desc = (D3D12_STATIC_SAMPLER_DESC1 *)
|
2021-06-24 13:09:35 +02:00
|
|
|
|
&static_samplers[static_sampler_idx];
|
|
|
|
|
|
|
|
|
|
|
|
desc->Filter = sampler->desc.Filter;
|
|
|
|
|
|
desc->AddressU = sampler->desc.AddressU;
|
|
|
|
|
|
desc->AddressV = sampler->desc.AddressV;
|
|
|
|
|
|
desc->AddressW = sampler->desc.AddressW;
|
|
|
|
|
|
desc->MipLODBias = sampler->desc.MipLODBias;
|
|
|
|
|
|
desc->MaxAnisotropy = sampler->desc.MaxAnisotropy;
|
|
|
|
|
|
desc->ComparisonFunc = sampler->desc.ComparisonFunc;
|
|
|
|
|
|
desc->BorderColor = sampler->static_border_color;
|
|
|
|
|
|
desc->MinLOD = sampler->desc.MinLOD;
|
|
|
|
|
|
desc->MaxLOD = sampler->desc.MaxLOD;
|
|
|
|
|
|
desc->ShaderRegister = binfos[binding].base_shader_register;
|
|
|
|
|
|
desc->ShaderVisibility = translate_desc_visibility(ordered_bindings[i].stageFlags);
|
2023-01-09 12:43:16 -08:00
|
|
|
|
desc->Flags = sampler->desc.Flags;
|
2023-03-02 19:58:09 -08:00
|
|
|
|
if (device->bindless && desc_type == VK_DESCRIPTOR_TYPE_SAMPLER) {
|
|
|
|
|
|
/* Avoid using space in the descriptor set buffer for pure static samplers. The meaning
|
|
|
|
|
|
* of base register index is different for them - it's just an ID to map to the root
|
|
|
|
|
|
* signature, as opposed to all other bindings where it's an offset into the buffer. */
|
|
|
|
|
|
binfos[binding].base_shader_register = desc->ShaderRegister = static_sampler_idx;
|
|
|
|
|
|
base_register--;
|
|
|
|
|
|
}
|
2021-06-24 13:09:35 +02:00
|
|
|
|
static_sampler_idx++;
|
2022-04-20 12:50:14 +02:00
|
|
|
|
} else {
|
2021-06-24 13:09:35 +02:00
|
|
|
|
has_static_sampler = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-03-13 12:43:45 -07:00
|
|
|
|
if (has_static_sampler) {
|
|
|
|
|
|
binfos[binding].immutable_sampler_idx = STATIC_SAMPLER_TAG;
|
|
|
|
|
|
} else if (has_immutable_samplers) {
|
2021-06-24 13:09:35 +02:00
|
|
|
|
binfos[binding].immutable_sampler_idx = immutable_sampler_idx;
|
|
|
|
|
|
for (uint32_t s = 0; s < desc_count; s++) {
|
|
|
|
|
|
VK_FROM_HANDLE(dzn_sampler, sampler, ordered_bindings[i].pImmutableSamplers[s]);
|
|
|
|
|
|
|
|
|
|
|
|
immutable_samplers[immutable_sampler_idx++] = sampler;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (is_dynamic) {
|
2023-03-02 19:58:09 -08:00
|
|
|
|
binfos[binding].buffer_idx = dynamic_buffer_idx;
|
2021-06-24 13:09:35 +02:00
|
|
|
|
for (uint32_t d = 0; d < desc_count; d++)
|
|
|
|
|
|
set_layout->dynamic_buffers.bindings[dynamic_buffer_idx + d] = binding;
|
|
|
|
|
|
dynamic_buffer_idx += desc_count;
|
|
|
|
|
|
assert(dynamic_buffer_idx <= MAX_DYNAMIC_BUFFERS);
|
2023-03-02 19:58:09 -08:00
|
|
|
|
} else if (is_buffer_desc_type_without_view(desc_type)) {
|
|
|
|
|
|
binfos[binding].buffer_idx = set_layout->buffer_count;
|
|
|
|
|
|
set_layout->buffer_count += desc_count;
|
2021-06-24 13:09:35 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2022-04-11 04:46:31 -07:00
|
|
|
|
if (!ordered_bindings[i].descriptorCount)
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
2021-06-24 13:09:35 +02:00
|
|
|
|
unsigned num_descs =
|
2023-03-02 13:06:22 -08:00
|
|
|
|
num_descs_for_type(desc_type, has_static_sampler, device->bindless);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
if (!num_descs) continue;
|
|
|
|
|
|
|
|
|
|
|
|
assert(visibility < ARRAY_SIZE(set_layout->ranges));
|
|
|
|
|
|
|
2022-04-06 15:04:34 +02:00
|
|
|
|
bool has_range[NUM_POOL_TYPES] = { 0 };
|
2021-06-24 13:09:35 +02:00
|
|
|
|
has_range[D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER] =
|
2023-03-02 19:58:09 -08:00
|
|
|
|
has_sampler && !has_static_sampler && !device->bindless;
|
2021-06-24 13:09:35 +02:00
|
|
|
|
has_range[D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV] =
|
2023-03-02 19:58:09 -08:00
|
|
|
|
desc_type != VK_DESCRIPTOR_TYPE_SAMPLER || (device->bindless && !has_static_sampler);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
|
|
|
|
|
|
dzn_foreach_pool_type (type) {
|
|
|
|
|
|
if (!has_range[type]) continue;
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t idx = range_idx[visibility][type]++;
|
|
|
|
|
|
assert(idx < range_count[visibility][type]);
|
|
|
|
|
|
|
|
|
|
|
|
binfos[binding].range_idx[type] = idx;
|
|
|
|
|
|
D3D12_DESCRIPTOR_RANGE1 *range = (D3D12_DESCRIPTOR_RANGE1 *)
|
|
|
|
|
|
&set_layout->ranges[visibility][type][idx];
|
|
|
|
|
|
VkDescriptorType range_type = desc_type;
|
|
|
|
|
|
if (desc_type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) {
|
|
|
|
|
|
range_type = type == D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER ?
|
|
|
|
|
|
VK_DESCRIPTOR_TYPE_SAMPLER :
|
|
|
|
|
|
VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
|
|
|
|
|
|
}
|
2023-03-02 09:58:47 -08:00
|
|
|
|
range->RangeType = desc_type_to_range_type(range_type, true);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
range->NumDescriptors = desc_count;
|
|
|
|
|
|
range->BaseShaderRegister = binfos[binding].base_shader_register;
|
|
|
|
|
|
range->Flags = type == D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER ?
|
|
|
|
|
|
D3D12_DESCRIPTOR_RANGE_FLAG_NONE :
|
|
|
|
|
|
D3D12_DESCRIPTOR_RANGE_FLAG_DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS;
|
|
|
|
|
|
if (is_dynamic) {
|
|
|
|
|
|
range->OffsetInDescriptorsFromTableStart =
|
|
|
|
|
|
set_layout->dynamic_buffers.range_offset +
|
2023-05-24 10:41:40 -07:00
|
|
|
|
set_layout->dynamic_buffers.desc_count;
|
2021-06-24 13:09:35 +02:00
|
|
|
|
set_layout->dynamic_buffers.count += range->NumDescriptors;
|
2023-05-24 10:41:40 -07:00
|
|
|
|
set_layout->dynamic_buffers.desc_count += range->NumDescriptors;
|
2021-06-24 13:09:35 +02:00
|
|
|
|
} else {
|
|
|
|
|
|
range->OffsetInDescriptorsFromTableStart = set_layout->range_desc_count[type];
|
2023-03-17 08:18:45 -07:00
|
|
|
|
if (!binfos[binding].variable_size)
|
|
|
|
|
|
set_layout->range_desc_count[type] += range->NumDescriptors;
|
2021-06-24 13:09:35 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-03-02 13:06:22 -08:00
|
|
|
|
if (!dzn_descriptor_type_depends_on_shader_usage(desc_type, device->bindless))
|
2021-06-24 13:09:35 +02:00
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
|
|
assert(idx + 1 < range_count[visibility][type]);
|
|
|
|
|
|
range_idx[visibility][type]++;
|
|
|
|
|
|
range[1] = range[0];
|
|
|
|
|
|
range++;
|
2023-03-02 09:58:47 -08:00
|
|
|
|
range->RangeType = desc_type_to_range_type(range_type, false);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
if (is_dynamic) {
|
|
|
|
|
|
range->OffsetInDescriptorsFromTableStart =
|
|
|
|
|
|
set_layout->dynamic_buffers.range_offset +
|
2023-05-24 10:41:40 -07:00
|
|
|
|
set_layout->dynamic_buffers.desc_count;
|
|
|
|
|
|
set_layout->dynamic_buffers.desc_count += range->NumDescriptors;
|
2021-06-24 13:09:35 +02:00
|
|
|
|
} else {
|
|
|
|
|
|
range->OffsetInDescriptorsFromTableStart = set_layout->range_desc_count[type];
|
|
|
|
|
|
set_layout->range_desc_count[type] += range->NumDescriptors;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
free(ordered_bindings);
|
|
|
|
|
|
|
|
|
|
|
|
*out = dzn_descriptor_set_layout_to_handle(set_layout);
|
|
|
|
|
|
return VK_SUCCESS;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-03-28 09:41:17 +02:00
|
|
|
|
static uint32_t
|
2022-04-05 17:41:20 +02:00
|
|
|
|
dzn_descriptor_set_layout_get_heap_offset(const struct dzn_descriptor_set_layout *layout,
|
2021-06-24 13:09:35 +02:00
|
|
|
|
uint32_t b,
|
|
|
|
|
|
D3D12_DESCRIPTOR_HEAP_TYPE type,
|
2023-03-02 13:06:22 -08:00
|
|
|
|
bool alt,
|
|
|
|
|
|
bool bindless)
|
2021-06-24 13:09:35 +02:00
|
|
|
|
{
|
|
|
|
|
|
assert(b < layout->binding_count);
|
|
|
|
|
|
D3D12_SHADER_VISIBILITY visibility = layout->bindings[b].visibility;
|
|
|
|
|
|
assert(visibility < ARRAY_SIZE(layout->ranges));
|
|
|
|
|
|
assert(type < NUM_POOL_TYPES);
|
|
|
|
|
|
|
2023-03-02 19:58:09 -08:00
|
|
|
|
if (bindless)
|
|
|
|
|
|
type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
|
|
|
|
|
|
|
2021-06-24 13:09:35 +02:00
|
|
|
|
uint32_t range_idx = layout->bindings[b].range_idx[type];
|
|
|
|
|
|
|
|
|
|
|
|
if (range_idx == ~0)
|
|
|
|
|
|
return ~0;
|
|
|
|
|
|
|
2023-03-02 09:58:47 -08:00
|
|
|
|
if (alt &&
|
2023-03-02 13:06:22 -08:00
|
|
|
|
!dzn_descriptor_type_depends_on_shader_usage(layout->bindings[b].type, bindless))
|
2021-06-24 13:09:35 +02:00
|
|
|
|
return ~0;
|
|
|
|
|
|
|
2023-03-02 09:58:47 -08:00
|
|
|
|
if (alt)
|
2021-06-24 13:09:35 +02:00
|
|
|
|
range_idx++;
|
|
|
|
|
|
|
|
|
|
|
|
assert(range_idx < layout->range_count[visibility][type]);
|
|
|
|
|
|
return layout->ranges[visibility][type][range_idx].OffsetInDescriptorsFromTableStart;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-03-28 09:41:17 +02:00
|
|
|
|
static uint32_t
|
2022-04-05 17:41:20 +02:00
|
|
|
|
dzn_descriptor_set_layout_get_desc_count(const struct dzn_descriptor_set_layout *layout,
|
2021-06-24 13:09:35 +02:00
|
|
|
|
uint32_t b)
|
|
|
|
|
|
{
|
|
|
|
|
|
D3D12_SHADER_VISIBILITY visibility = layout->bindings[b].visibility;
|
|
|
|
|
|
assert(visibility < ARRAY_SIZE(layout->ranges));
|
|
|
|
|
|
|
|
|
|
|
|
dzn_foreach_pool_type (type) {
|
|
|
|
|
|
uint32_t range_idx = layout->bindings[b].range_idx[type];
|
|
|
|
|
|
assert(range_idx == ~0 || range_idx < layout->range_count[visibility][type]);
|
|
|
|
|
|
|
|
|
|
|
|
if (range_idx != ~0)
|
|
|
|
|
|
return layout->ranges[visibility][type][range_idx].NumDescriptors;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VKAPI_ATTR VkResult VKAPI_CALL
|
|
|
|
|
|
dzn_CreateDescriptorSetLayout(VkDevice device,
|
|
|
|
|
|
const VkDescriptorSetLayoutCreateInfo *pCreateInfo,
|
|
|
|
|
|
const VkAllocationCallbacks *pAllocator,
|
|
|
|
|
|
VkDescriptorSetLayout *pSetLayout)
|
|
|
|
|
|
{
|
|
|
|
|
|
return dzn_descriptor_set_layout_create(dzn_device_from_handle(device),
|
|
|
|
|
|
pCreateInfo, pAllocator, pSetLayout);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-04-19 11:43:22 +02:00
|
|
|
|
VKAPI_ATTR void VKAPI_CALL
|
2023-03-02 13:06:22 -08:00
|
|
|
|
dzn_GetDescriptorSetLayoutSupport(VkDevice _device,
|
2022-04-19 11:43:22 +02:00
|
|
|
|
const VkDescriptorSetLayoutCreateInfo *pCreateInfo,
|
|
|
|
|
|
VkDescriptorSetLayoutSupport *pSupport)
|
|
|
|
|
|
{
|
2023-03-02 13:06:22 -08:00
|
|
|
|
VK_FROM_HANDLE(dzn_device, device, _device);
|
2022-04-19 11:43:22 +02:00
|
|
|
|
const VkDescriptorSetLayoutBinding *bindings = pCreateInfo->pBindings;
|
|
|
|
|
|
uint32_t sampler_count = 0, other_desc_count = 0;
|
|
|
|
|
|
|
2024-01-22 16:21:37 -08:00
|
|
|
|
const VkDescriptorSetLayoutBindingFlagsCreateInfo *binding_flags =
|
|
|
|
|
|
vk_find_struct_const(pCreateInfo->pNext, DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO);
|
|
|
|
|
|
VkDescriptorSetVariableDescriptorCountLayoutSupport *variable_count =
|
|
|
|
|
|
vk_find_struct(pSupport->pNext, DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_LAYOUT_SUPPORT);
|
|
|
|
|
|
if (variable_count)
|
|
|
|
|
|
variable_count->maxVariableDescriptorCount = 0;
|
|
|
|
|
|
|
2022-04-19 11:43:22 +02:00
|
|
|
|
for (uint32_t i = 0; i < pCreateInfo->bindingCount; i++) {
|
|
|
|
|
|
VkDescriptorType desc_type = bindings[i].descriptorType;
|
|
|
|
|
|
bool has_sampler = dzn_desc_type_has_sampler(desc_type);
|
2024-01-22 16:21:37 -08:00
|
|
|
|
bool is_sampler = desc_type == VK_DESCRIPTOR_TYPE_SAMPLER;
|
|
|
|
|
|
|
|
|
|
|
|
UINT upper_bound = MAX_DESCS_PER_CBV_SRV_UAV_HEAP - other_desc_count;
|
|
|
|
|
|
if (has_sampler) {
|
|
|
|
|
|
UINT sampler_upper_bound = MAX_DESCS_PER_SAMPLER_HEAP - sampler_count;
|
|
|
|
|
|
upper_bound = is_sampler ? sampler_upper_bound : MIN2(sampler_upper_bound, upper_bound);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (binding_flags && binding_flags->bindingCount &&
|
|
|
|
|
|
(binding_flags->pBindingFlags[i] & VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT))
|
|
|
|
|
|
variable_count->maxVariableDescriptorCount = device->bindless ? INT32_MAX : upper_bound;
|
2022-04-19 11:43:22 +02:00
|
|
|
|
|
|
|
|
|
|
if (has_sampler)
|
|
|
|
|
|
sampler_count += bindings[i].descriptorCount;
|
2024-01-22 16:21:37 -08:00
|
|
|
|
if (!is_sampler)
|
2022-04-19 11:43:22 +02:00
|
|
|
|
other_desc_count += bindings[i].descriptorCount;
|
2023-03-02 13:06:22 -08:00
|
|
|
|
if (dzn_descriptor_type_depends_on_shader_usage(desc_type, device->bindless))
|
2022-04-19 11:43:22 +02:00
|
|
|
|
other_desc_count += bindings[i].descriptorCount;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-03-02 19:58:09 -08:00
|
|
|
|
pSupport->supported = device->bindless ||
|
|
|
|
|
|
(sampler_count <= MAX_DESCS_PER_SAMPLER_HEAP &&
|
|
|
|
|
|
other_desc_count <= MAX_DESCS_PER_CBV_SRV_UAV_HEAP);
|
2022-04-19 11:43:22 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2021-06-24 13:09:35 +02:00
|
|
|
|
static void
|
2022-06-29 05:10:10 -07:00
|
|
|
|
dzn_pipeline_layout_destroy(struct vk_device *vk_device,
|
|
|
|
|
|
struct vk_pipeline_layout *vk_layout)
|
2021-06-24 13:09:35 +02:00
|
|
|
|
{
|
2022-06-29 05:10:10 -07:00
|
|
|
|
struct dzn_pipeline_layout *layout =
|
|
|
|
|
|
container_of(vk_layout, struct dzn_pipeline_layout, vk);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
|
|
|
|
|
|
if (layout->root.sig)
|
2022-03-25 17:08:50 +01:00
|
|
|
|
ID3D12RootSignature_Release(layout->root.sig);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
|
2022-06-29 05:10:10 -07:00
|
|
|
|
vk_pipeline_layout_destroy(vk_device, &layout->vk);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Reserve two root parameters for the push constants and sysvals CBVs.
|
|
|
|
|
|
#define MAX_INTERNAL_ROOT_PARAMS 2
|
|
|
|
|
|
|
|
|
|
|
|
// One root parameter for samplers and the other one for views, multiplied by
|
|
|
|
|
|
// the number of visibility combinations, plus the internal root parameters.
|
|
|
|
|
|
#define MAX_ROOT_PARAMS ((MAX_SHADER_VISIBILITIES * 2) + MAX_INTERNAL_ROOT_PARAMS)
|
|
|
|
|
|
|
|
|
|
|
|
// Maximum number of DWORDS (32-bit words) that can be used for a root signature
|
|
|
|
|
|
#define MAX_ROOT_DWORDS 64
|
|
|
|
|
|
|
2022-06-21 17:09:27 +02:00
|
|
|
|
static void
|
|
|
|
|
|
dzn_pipeline_layout_hash_stages(struct dzn_pipeline_layout *layout,
|
|
|
|
|
|
const VkPipelineLayoutCreateInfo *info)
|
|
|
|
|
|
{
|
|
|
|
|
|
uint32_t stages = 0;
|
|
|
|
|
|
for (uint32_t stage = 0; stage < ARRAY_SIZE(layout->stages); stage++) {
|
|
|
|
|
|
for (uint32_t set = 0; set < info->setLayoutCount; set++) {
|
|
|
|
|
|
VK_FROM_HANDLE(dzn_descriptor_set_layout, set_layout, info->pSetLayouts[set]);
|
|
|
|
|
|
|
|
|
|
|
|
stages |= set_layout->stages;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
for (uint32_t stage = 0; stage < ARRAY_SIZE(layout->stages); stage++) {
|
|
|
|
|
|
if (!(stages & BITFIELD_BIT(stage)))
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
|
|
struct mesa_sha1 ctx;
|
|
|
|
|
|
|
|
|
|
|
|
_mesa_sha1_init(&ctx);
|
|
|
|
|
|
for (uint32_t set = 0; set < info->setLayoutCount; set++) {
|
|
|
|
|
|
VK_FROM_HANDLE(dzn_descriptor_set_layout, set_layout, info->pSetLayouts[set]);
|
|
|
|
|
|
if (!(BITFIELD_BIT(stage) & set_layout->stages))
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
|
|
for (uint32_t b = 0; b < set_layout->binding_count; b++) {
|
|
|
|
|
|
if (!(BITFIELD_BIT(stage) & set_layout->bindings[b].stages))
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
|
|
_mesa_sha1_update(&ctx, &b, sizeof(b));
|
|
|
|
|
|
_mesa_sha1_update(&ctx, &set_layout->bindings[b].base_shader_register,
|
|
|
|
|
|
sizeof(set_layout->bindings[b].base_shader_register));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
_mesa_sha1_final(&ctx, layout->stages[stage].hash);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2021-06-24 13:09:35 +02:00
|
|
|
|
static VkResult
|
2022-04-05 17:41:20 +02:00
|
|
|
|
dzn_pipeline_layout_create(struct dzn_device *device,
|
2021-06-24 13:09:35 +02:00
|
|
|
|
const VkPipelineLayoutCreateInfo *pCreateInfo,
|
|
|
|
|
|
const VkAllocationCallbacks *pAllocator,
|
|
|
|
|
|
VkPipelineLayout *out)
|
|
|
|
|
|
{
|
2023-01-09 12:43:16 -08:00
|
|
|
|
struct dzn_physical_device *pdev = container_of(device->vk.physical, struct dzn_physical_device, vk);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
uint32_t binding_count = 0;
|
|
|
|
|
|
|
|
|
|
|
|
for (uint32_t s = 0; s < pCreateInfo->setLayoutCount; s++) {
|
|
|
|
|
|
VK_FROM_HANDLE(dzn_descriptor_set_layout, set_layout, pCreateInfo->pSetLayouts[s]);
|
|
|
|
|
|
|
|
|
|
|
|
if (!set_layout)
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
|
|
binding_count += set_layout->binding_count;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VK_MULTIALLOC(ma);
|
2022-04-05 17:41:20 +02:00
|
|
|
|
VK_MULTIALLOC_DECL(&ma, struct dzn_pipeline_layout, layout, 1);
|
2022-06-21 02:53:05 -07:00
|
|
|
|
VK_MULTIALLOC_DECL(&ma, uint32_t, binding_translation, binding_count);
|
2023-03-13 12:43:45 -07:00
|
|
|
|
VK_MULTIALLOC_DECL(&ma, uint8_t, binding_class, binding_count);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
|
2022-06-29 05:10:10 -07:00
|
|
|
|
if (!vk_pipeline_layout_multizalloc(&device->vk, &ma, pCreateInfo))
|
2021-06-24 13:09:35 +02:00
|
|
|
|
return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
|
|
|
|
|
|
|
2022-06-29 05:10:10 -07:00
|
|
|
|
layout->vk.destroy = dzn_pipeline_layout_destroy;
|
2021-06-24 13:09:35 +02:00
|
|
|
|
|
|
|
|
|
|
for (uint32_t s = 0; s < pCreateInfo->setLayoutCount; s++) {
|
|
|
|
|
|
VK_FROM_HANDLE(dzn_descriptor_set_layout, set_layout, pCreateInfo->pSetLayouts[s]);
|
|
|
|
|
|
|
|
|
|
|
|
if (!set_layout || !set_layout->binding_count)
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
2022-06-21 02:53:05 -07:00
|
|
|
|
layout->binding_translation[s].base_reg = binding_translation;
|
2023-03-13 12:43:45 -07:00
|
|
|
|
layout->binding_translation[s].binding_class = binding_class;
|
2022-06-21 02:53:05 -07:00
|
|
|
|
binding_translation += set_layout->binding_count;
|
2023-03-13 12:43:45 -07:00
|
|
|
|
binding_class += set_layout->binding_count;
|
2021-06-24 13:09:35 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t range_count = 0, static_sampler_count = 0;
|
2023-03-13 12:43:45 -07:00
|
|
|
|
uint32_t dynamic_buffer_base = 0;
|
2021-06-24 13:09:35 +02:00
|
|
|
|
|
|
|
|
|
|
layout->root.param_count = 0;
|
|
|
|
|
|
dzn_foreach_pool_type (type)
|
|
|
|
|
|
layout->desc_count[type] = 0;
|
|
|
|
|
|
|
|
|
|
|
|
layout->set_count = pCreateInfo->setLayoutCount;
|
|
|
|
|
|
for (uint32_t j = 0; j < layout->set_count; j++) {
|
|
|
|
|
|
VK_FROM_HANDLE(dzn_descriptor_set_layout, set_layout, pCreateInfo->pSetLayouts[j]);
|
2022-06-21 02:53:05 -07:00
|
|
|
|
uint32_t *binding_trans = layout->binding_translation[j].base_reg;
|
2021-06-24 13:09:35 +02:00
|
|
|
|
|
|
|
|
|
|
layout->sets[j].dynamic_buffer_count = set_layout->dynamic_buffers.count;
|
|
|
|
|
|
memcpy(layout->sets[j].range_desc_count, set_layout->range_desc_count,
|
|
|
|
|
|
sizeof(layout->sets[j].range_desc_count));
|
|
|
|
|
|
layout->binding_translation[j].binding_count = set_layout->binding_count;
|
2023-03-13 12:43:45 -07:00
|
|
|
|
|
|
|
|
|
|
for (uint32_t b = 0; b < set_layout->binding_count; b++) {
|
2022-06-21 02:53:05 -07:00
|
|
|
|
binding_trans[b] = set_layout->bindings[b].base_shader_register;
|
2023-03-13 12:43:45 -07:00
|
|
|
|
if (is_dynamic_desc_type(set_layout->bindings[b].type)) {
|
|
|
|
|
|
layout->binding_translation[j].binding_class[b] = DZN_PIPELINE_BINDING_DYNAMIC_BUFFER;
|
|
|
|
|
|
if (device->bindless)
|
|
|
|
|
|
binding_trans[b] += dynamic_buffer_base;
|
|
|
|
|
|
} else if (dzn_desc_type_has_sampler(set_layout->bindings[b].type) &&
|
|
|
|
|
|
set_layout->bindings[b].immutable_sampler_idx == STATIC_SAMPLER_TAG)
|
|
|
|
|
|
layout->binding_translation[j].binding_class[b] = DZN_PIPELINE_BINDING_STATIC_SAMPLER;
|
|
|
|
|
|
else
|
|
|
|
|
|
layout->binding_translation[j].binding_class[b] = DZN_PIPELINE_BINDING_NORMAL;
|
|
|
|
|
|
}
|
2021-06-24 13:09:35 +02:00
|
|
|
|
|
|
|
|
|
|
static_sampler_count += set_layout->static_sampler_count;
|
|
|
|
|
|
dzn_foreach_pool_type (type) {
|
|
|
|
|
|
layout->sets[j].heap_offsets[type] = layout->desc_count[type];
|
|
|
|
|
|
layout->desc_count[type] += set_layout->range_desc_count[type];
|
|
|
|
|
|
for (uint32_t i = 0; i < MAX_SHADER_VISIBILITIES; i++)
|
|
|
|
|
|
range_count += set_layout->range_count[i][type];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-03-02 13:06:22 -08:00
|
|
|
|
if (!device->bindless)
|
2023-05-24 10:41:40 -07:00
|
|
|
|
layout->desc_count[D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV] += set_layout->dynamic_buffers.desc_count;
|
2023-03-02 13:06:22 -08:00
|
|
|
|
|
2023-03-13 12:43:45 -07:00
|
|
|
|
dynamic_buffer_base += set_layout->dynamic_buffers.count;
|
2021-06-24 13:09:35 +02:00
|
|
|
|
for (uint32_t o = 0, elem = 0; o < set_layout->dynamic_buffers.count; o++, elem++) {
|
2023-03-02 19:58:09 -08:00
|
|
|
|
if (device->bindless) {
|
|
|
|
|
|
layout->sets[j].dynamic_buffer_heap_offsets[o].primary = layout->dynamic_buffer_count++;
|
|
|
|
|
|
layout->sets[j].dynamic_buffer_heap_offsets[o].alt = ~0;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
uint32_t b = set_layout->dynamic_buffers.bindings[o];
|
2021-06-24 13:09:35 +02:00
|
|
|
|
|
2023-03-02 19:58:09 -08:00
|
|
|
|
if (o > 0 && set_layout->dynamic_buffers.bindings[o - 1] != b)
|
|
|
|
|
|
elem = 0;
|
2021-06-24 13:09:35 +02:00
|
|
|
|
|
2023-03-02 19:58:09 -08:00
|
|
|
|
uint32_t heap_offset =
|
|
|
|
|
|
dzn_descriptor_set_layout_get_heap_offset(set_layout, b, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
|
|
|
|
|
|
false, false);
|
|
|
|
|
|
uint32_t alt_heap_offset =
|
|
|
|
|
|
dzn_descriptor_set_layout_get_heap_offset(set_layout, b, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
|
|
|
|
|
|
true, false);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
|
2023-03-02 19:58:09 -08:00
|
|
|
|
layout->sets[j].dynamic_buffer_heap_offsets[o].primary = heap_offset != ~0 ? heap_offset + elem : ~0;
|
|
|
|
|
|
layout->sets[j].dynamic_buffer_heap_offsets[o].alt = alt_heap_offset != ~0 ? alt_heap_offset + elem : ~0;
|
|
|
|
|
|
}
|
2021-06-24 13:09:35 +02:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-04-08 11:11:21 +02:00
|
|
|
|
D3D12_DESCRIPTOR_RANGE1 *ranges =
|
2021-06-24 13:09:35 +02:00
|
|
|
|
vk_alloc2(&device->vk.alloc, pAllocator, sizeof(*ranges) * range_count, 8,
|
|
|
|
|
|
VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
|
|
|
|
|
|
if (range_count && !ranges) {
|
2022-06-29 05:10:10 -07:00
|
|
|
|
vk_pipeline_layout_unref(&device->vk, &layout->vk);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-01-09 12:43:16 -08:00
|
|
|
|
static_assert(sizeof(D3D12_STATIC_SAMPLER_DESC1) > sizeof(D3D12_STATIC_SAMPLER_DESC),
|
|
|
|
|
|
"Allocating larger array and re-using for smaller struct");
|
|
|
|
|
|
D3D12_STATIC_SAMPLER_DESC1 *static_sampler_descs =
|
2021-06-24 13:09:35 +02:00
|
|
|
|
vk_alloc2(&device->vk.alloc, pAllocator,
|
|
|
|
|
|
sizeof(*static_sampler_descs) * static_sampler_count, 8,
|
|
|
|
|
|
VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
|
|
|
|
|
|
if (static_sampler_count && !static_sampler_descs) {
|
|
|
|
|
|
vk_free2(&device->vk.alloc, pAllocator, ranges);
|
2022-06-29 05:10:10 -07:00
|
|
|
|
vk_pipeline_layout_unref(&device->vk, &layout->vk);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2022-04-06 15:04:34 +02:00
|
|
|
|
D3D12_ROOT_PARAMETER1 root_params[MAX_ROOT_PARAMS] = { 0 };
|
2021-06-24 13:09:35 +02:00
|
|
|
|
D3D12_DESCRIPTOR_RANGE1 *range_ptr = ranges;
|
|
|
|
|
|
D3D12_ROOT_PARAMETER1 *root_param;
|
2023-01-13 01:20:25 +08:00
|
|
|
|
ASSERTED uint32_t root_dwords = 0;
|
2021-06-24 13:09:35 +02:00
|
|
|
|
|
2023-03-02 19:58:09 -08:00
|
|
|
|
if (device->bindless) {
|
|
|
|
|
|
for (uint32_t j = 0; j < pCreateInfo->setLayoutCount; j++) {
|
|
|
|
|
|
root_param = &root_params[layout->root.param_count++];
|
|
|
|
|
|
root_param->ParameterType = D3D12_ROOT_PARAMETER_TYPE_SRV;
|
|
|
|
|
|
root_param->Descriptor.RegisterSpace = 0;
|
|
|
|
|
|
root_param->Descriptor.ShaderRegister = j;
|
|
|
|
|
|
root_param->Descriptor.Flags = D3D12_ROOT_DESCRIPTOR_FLAG_DATA_VOLATILE;
|
|
|
|
|
|
root_param->ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
|
|
|
|
|
|
root_dwords += 2;
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
for (uint32_t i = 0; i < MAX_SHADER_VISIBILITIES; i++) {
|
|
|
|
|
|
dzn_foreach_pool_type(type) {
|
|
|
|
|
|
root_param = &root_params[layout->root.param_count];
|
|
|
|
|
|
root_param->ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
|
|
|
|
|
|
root_param->DescriptorTable.pDescriptorRanges = range_ptr;
|
|
|
|
|
|
root_param->DescriptorTable.NumDescriptorRanges = 0;
|
|
|
|
|
|
root_param->ShaderVisibility = (D3D12_SHADER_VISIBILITY)i;
|
|
|
|
|
|
|
|
|
|
|
|
for (uint32_t j = 0; j < pCreateInfo->setLayoutCount; j++) {
|
|
|
|
|
|
VK_FROM_HANDLE(dzn_descriptor_set_layout, set_layout, pCreateInfo->pSetLayouts[j]);
|
|
|
|
|
|
uint32_t range_count = set_layout->range_count[i][type];
|
|
|
|
|
|
|
|
|
|
|
|
memcpy(range_ptr, set_layout->ranges[i][type],
|
|
|
|
|
|
range_count * sizeof(D3D12_DESCRIPTOR_RANGE1));
|
|
|
|
|
|
for (uint32_t k = 0; k < range_count; k++) {
|
|
|
|
|
|
range_ptr[k].RegisterSpace = j;
|
|
|
|
|
|
range_ptr[k].OffsetInDescriptorsFromTableStart +=
|
|
|
|
|
|
layout->sets[j].heap_offsets[type];
|
|
|
|
|
|
}
|
|
|
|
|
|
root_param->DescriptorTable.NumDescriptorRanges += range_count;
|
|
|
|
|
|
range_ptr += range_count;
|
2021-06-24 13:09:35 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-03-02 19:58:09 -08:00
|
|
|
|
if (root_param->DescriptorTable.NumDescriptorRanges) {
|
|
|
|
|
|
layout->root.type[layout->root.param_count++] = (D3D12_DESCRIPTOR_HEAP_TYPE)type;
|
|
|
|
|
|
root_dwords++;
|
|
|
|
|
|
}
|
2021-06-24 13:09:35 +02:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
layout->root.sets_param_count = layout->root.param_count;
|
|
|
|
|
|
|
2023-03-02 19:58:09 -08:00
|
|
|
|
if (layout->dynamic_buffer_count > 0 && device->bindless) {
|
|
|
|
|
|
layout->root.dynamic_buffer_bindless_param_idx = layout->root.param_count;
|
|
|
|
|
|
D3D12_ROOT_PARAMETER1 *root_param = &root_params[layout->root.param_count++];
|
|
|
|
|
|
|
|
|
|
|
|
root_param->ParameterType = D3D12_ROOT_PARAMETER_TYPE_SRV;
|
|
|
|
|
|
root_param->Descriptor.RegisterSpace = 0;
|
|
|
|
|
|
root_param->Descriptor.ShaderRegister = layout->root.sets_param_count;
|
|
|
|
|
|
root_param->Descriptor.Flags = D3D12_ROOT_DESCRIPTOR_FLAG_DATA_STATIC;
|
|
|
|
|
|
root_param->ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
|
|
|
|
|
|
root_dwords += 2;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2021-06-24 13:09:35 +02:00
|
|
|
|
/* Add our sysval CBV, and make it visible to all shaders */
|
|
|
|
|
|
layout->root.sysval_cbv_param_idx = layout->root.param_count;
|
|
|
|
|
|
root_param = &root_params[layout->root.param_count++];
|
|
|
|
|
|
root_param->ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS;
|
|
|
|
|
|
root_param->Descriptor.RegisterSpace = DZN_REGISTER_SPACE_SYSVALS;
|
|
|
|
|
|
root_param->Constants.ShaderRegister = 0;
|
|
|
|
|
|
root_param->Constants.Num32BitValues =
|
|
|
|
|
|
DIV_ROUND_UP(MAX2(sizeof(struct dxil_spirv_vertex_runtime_data),
|
|
|
|
|
|
sizeof(struct dxil_spirv_compute_runtime_data)),
|
|
|
|
|
|
4);
|
|
|
|
|
|
root_param->ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
|
|
|
|
|
|
root_dwords += root_param->Constants.Num32BitValues;
|
|
|
|
|
|
|
2023-01-09 12:43:16 -08:00
|
|
|
|
if (pdev->root_sig_version >= D3D_ROOT_SIGNATURE_VERSION_1_2) {
|
|
|
|
|
|
D3D12_STATIC_SAMPLER_DESC1 *static_sampler_ptr = static_sampler_descs;
|
|
|
|
|
|
for (uint32_t j = 0; j < pCreateInfo->setLayoutCount; j++) {
|
|
|
|
|
|
VK_FROM_HANDLE(dzn_descriptor_set_layout, set_layout, pCreateInfo->pSetLayouts[j]);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
|
2023-01-09 12:43:16 -08:00
|
|
|
|
memcpy(static_sampler_ptr, set_layout->static_samplers,
|
|
|
|
|
|
set_layout->static_sampler_count * sizeof(*set_layout->static_samplers));
|
|
|
|
|
|
if (j > 0) {
|
|
|
|
|
|
for (uint32_t k = 0; k < set_layout->static_sampler_count; k++)
|
|
|
|
|
|
static_sampler_ptr[k].RegisterSpace = j;
|
|
|
|
|
|
}
|
|
|
|
|
|
static_sampler_ptr += set_layout->static_sampler_count;
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
D3D12_STATIC_SAMPLER_DESC *static_sampler_ptr = (void *)static_sampler_descs;
|
|
|
|
|
|
for (uint32_t j = 0; j < pCreateInfo->setLayoutCount; j++) {
|
|
|
|
|
|
VK_FROM_HANDLE(dzn_descriptor_set_layout, set_layout, pCreateInfo->pSetLayouts[j]);
|
|
|
|
|
|
|
|
|
|
|
|
for (uint32_t k = 0; k < set_layout->static_sampler_count; k++) {
|
|
|
|
|
|
memcpy(static_sampler_ptr, &set_layout->static_samplers[k],
|
|
|
|
|
|
sizeof(*static_sampler_ptr));
|
|
|
|
|
|
static_sampler_ptr->RegisterSpace = j;
|
|
|
|
|
|
static_sampler_ptr++;
|
|
|
|
|
|
}
|
2021-06-24 13:09:35 +02:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t push_constant_size = 0;
|
|
|
|
|
|
uint32_t push_constant_flags = 0;
|
|
|
|
|
|
for (uint32_t j = 0; j < pCreateInfo->pushConstantRangeCount; j++) {
|
2022-04-12 16:50:21 +02:00
|
|
|
|
const VkPushConstantRange *range = pCreateInfo->pPushConstantRanges + j;
|
2021-06-24 13:09:35 +02:00
|
|
|
|
push_constant_size = MAX2(push_constant_size, range->offset + range->size);
|
|
|
|
|
|
push_constant_flags |= range->stageFlags;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (push_constant_size > 0) {
|
|
|
|
|
|
layout->root.push_constant_cbv_param_idx = layout->root.param_count;
|
|
|
|
|
|
D3D12_ROOT_PARAMETER1 *root_param = &root_params[layout->root.param_count++];
|
|
|
|
|
|
|
|
|
|
|
|
root_param->ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS;
|
|
|
|
|
|
root_param->Constants.ShaderRegister = 0;
|
|
|
|
|
|
root_param->Constants.Num32BitValues = ALIGN(push_constant_size, 4) / 4;
|
|
|
|
|
|
root_param->Constants.RegisterSpace = DZN_REGISTER_SPACE_PUSH_CONSTANT;
|
|
|
|
|
|
root_param->ShaderVisibility = translate_desc_visibility(push_constant_flags);
|
|
|
|
|
|
root_dwords += root_param->Constants.Num32BitValues;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
assert(layout->root.param_count <= ARRAY_SIZE(root_params));
|
|
|
|
|
|
assert(root_dwords <= MAX_ROOT_DWORDS);
|
|
|
|
|
|
|
|
|
|
|
|
D3D12_VERSIONED_ROOT_SIGNATURE_DESC root_sig_desc = {
|
2023-01-09 12:43:16 -08:00
|
|
|
|
.Version = pdev->root_sig_version,
|
|
|
|
|
|
};
|
|
|
|
|
|
/* TODO Only enable this flag when needed (optimization) */
|
|
|
|
|
|
D3D12_ROOT_SIGNATURE_FLAGS root_flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT;
|
2023-03-02 19:58:09 -08:00
|
|
|
|
if (device->bindless)
|
|
|
|
|
|
root_flags |= D3D12_ROOT_SIGNATURE_FLAG_SAMPLER_HEAP_DIRECTLY_INDEXED |
|
|
|
|
|
|
D3D12_ROOT_SIGNATURE_FLAG_CBV_SRV_UAV_HEAP_DIRECTLY_INDEXED;
|
2023-01-09 12:43:16 -08:00
|
|
|
|
if (pdev->root_sig_version >= D3D_ROOT_SIGNATURE_VERSION_1_2) {
|
|
|
|
|
|
root_sig_desc.Desc_1_2 = (D3D12_ROOT_SIGNATURE_DESC2){
|
2021-06-24 13:09:35 +02:00
|
|
|
|
.NumParameters = layout->root.param_count,
|
|
|
|
|
|
.pParameters = layout->root.param_count ? root_params : NULL,
|
2023-01-09 12:43:16 -08:00
|
|
|
|
.NumStaticSamplers = static_sampler_count,
|
2021-06-24 13:09:35 +02:00
|
|
|
|
.pStaticSamplers = static_sampler_descs,
|
2023-01-09 12:43:16 -08:00
|
|
|
|
.Flags = root_flags,
|
|
|
|
|
|
};
|
2023-04-14 09:21:26 -07:00
|
|
|
|
} else {
|
2023-01-09 12:43:16 -08:00
|
|
|
|
root_sig_desc.Desc_1_1 = (D3D12_ROOT_SIGNATURE_DESC1){
|
|
|
|
|
|
.NumParameters = layout->root.param_count,
|
|
|
|
|
|
.pParameters = layout->root.param_count ? root_params : NULL,
|
|
|
|
|
|
.NumStaticSamplers = static_sampler_count,
|
|
|
|
|
|
.pStaticSamplers = (void *)static_sampler_descs,
|
|
|
|
|
|
.Flags = root_flags,
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
2021-06-24 13:09:35 +02:00
|
|
|
|
|
|
|
|
|
|
layout->root.sig = dzn_device_create_root_sig(device, &root_sig_desc);
|
|
|
|
|
|
vk_free2(&device->vk.alloc, pAllocator, ranges);
|
|
|
|
|
|
vk_free2(&device->vk.alloc, pAllocator, static_sampler_descs);
|
|
|
|
|
|
|
|
|
|
|
|
if (!layout->root.sig) {
|
2022-06-29 05:10:10 -07:00
|
|
|
|
vk_pipeline_layout_unref(&device->vk, &layout->vk);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-06-21 17:09:27 +02:00
|
|
|
|
dzn_pipeline_layout_hash_stages(layout, pCreateInfo);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
*out = dzn_pipeline_layout_to_handle(layout);
|
|
|
|
|
|
return VK_SUCCESS;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VKAPI_ATTR VkResult VKAPI_CALL
|
|
|
|
|
|
dzn_CreatePipelineLayout(VkDevice device,
|
|
|
|
|
|
const VkPipelineLayoutCreateInfo *pCreateInfo,
|
|
|
|
|
|
const VkAllocationCallbacks *pAllocator,
|
|
|
|
|
|
VkPipelineLayout *pPipelineLayout)
|
|
|
|
|
|
{
|
|
|
|
|
|
return dzn_pipeline_layout_create(dzn_device_from_handle(device),
|
|
|
|
|
|
pCreateInfo, pAllocator, pPipelineLayout);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
dzn: Add initial bindless infrastructure
When operating in "bindless" mode, the device will own 2 descriptor
heaps, one for views, and one for samplers. Every time a view is
created (image view, buffer view), a slot is allocated for it out
of the device view heap for each usage type (sampled vs storage).
Then, in a future change, descriptor sets will just contain view/
sampler indices instead of actual descriptors. Instead of copying
these to a cmdbuf-owned descriptor heap, we can directly bind the
descriptor set as a buffer. We'll also modify shaders to perform
an indirection and index into the device heap.
Buffers also get views set up on creation. In a perfect world, we
could just put addresses/sizes in the descriptor set, but DXIL
doesn't support loading from addresses, we need descriptors. When
robust buffer access is disabled *or* descriptor set buffer views
reference the remainder of the buffer, we can just re-use a view
from the buffer and use an offset.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21913>
2023-03-02 10:06:13 -08:00
|
|
|
|
void
|
2022-04-05 17:41:20 +02:00
|
|
|
|
dzn_descriptor_heap_finish(struct dzn_descriptor_heap *heap)
|
2021-06-24 13:09:35 +02:00
|
|
|
|
{
|
|
|
|
|
|
if (heap->heap)
|
2022-03-25 17:08:50 +01:00
|
|
|
|
ID3D12DescriptorHeap_Release(heap->heap);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
dzn: Add initial bindless infrastructure
When operating in "bindless" mode, the device will own 2 descriptor
heaps, one for views, and one for samplers. Every time a view is
created (image view, buffer view), a slot is allocated for it out
of the device view heap for each usage type (sampled vs storage).
Then, in a future change, descriptor sets will just contain view/
sampler indices instead of actual descriptors. Instead of copying
these to a cmdbuf-owned descriptor heap, we can directly bind the
descriptor set as a buffer. We'll also modify shaders to perform
an indirection and index into the device heap.
Buffers also get views set up on creation. In a perfect world, we
could just put addresses/sizes in the descriptor set, but DXIL
doesn't support loading from addresses, we need descriptors. When
robust buffer access is disabled *or* descriptor set buffer views
reference the remainder of the buffer, we can just re-use a view
from the buffer and use an offset.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21913>
2023-03-02 10:06:13 -08:00
|
|
|
|
VkResult
|
2022-04-05 17:41:20 +02:00
|
|
|
|
dzn_descriptor_heap_init(struct dzn_descriptor_heap *heap,
|
|
|
|
|
|
struct dzn_device *device,
|
2021-06-24 13:09:35 +02:00
|
|
|
|
D3D12_DESCRIPTOR_HEAP_TYPE type,
|
|
|
|
|
|
uint32_t desc_count,
|
|
|
|
|
|
bool shader_visible)
|
|
|
|
|
|
{
|
|
|
|
|
|
heap->desc_count = desc_count;
|
2022-03-25 17:08:50 +01:00
|
|
|
|
heap->desc_sz = ID3D12Device1_GetDescriptorHandleIncrementSize(device->dev, type);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
|
|
|
|
|
|
D3D12_DESCRIPTOR_HEAP_DESC desc = {
|
|
|
|
|
|
.Type = type,
|
|
|
|
|
|
.NumDescriptors = desc_count,
|
|
|
|
|
|
.Flags = shader_visible ?
|
|
|
|
|
|
D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE :
|
|
|
|
|
|
D3D12_DESCRIPTOR_HEAP_FLAG_NONE,
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2022-03-25 17:08:50 +01:00
|
|
|
|
if (FAILED(ID3D12Device1_CreateDescriptorHeap(device->dev, &desc,
|
2022-04-06 15:04:34 +02:00
|
|
|
|
&IID_ID3D12DescriptorHeap,
|
2022-04-21 20:35:29 +08:00
|
|
|
|
(void **)&heap->heap))) {
|
2021-06-24 13:09:35 +02:00
|
|
|
|
return vk_error(device,
|
|
|
|
|
|
shader_visible ?
|
|
|
|
|
|
VK_ERROR_OUT_OF_DEVICE_MEMORY : VK_ERROR_OUT_OF_HOST_MEMORY);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-07-02 07:34:07 -07:00
|
|
|
|
D3D12_CPU_DESCRIPTOR_HANDLE cpu_handle = dzn_ID3D12DescriptorHeap_GetCPUDescriptorHandleForHeapStart(heap->heap);
|
2022-03-25 17:08:50 +01:00
|
|
|
|
heap->cpu_base = cpu_handle.ptr;
|
|
|
|
|
|
if (shader_visible) {
|
2022-07-02 07:34:07 -07:00
|
|
|
|
D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle = dzn_ID3D12DescriptorHeap_GetGPUDescriptorHandleForHeapStart(heap->heap);
|
2022-03-25 17:08:50 +01:00
|
|
|
|
heap->gpu_base = gpu_handle.ptr;
|
|
|
|
|
|
}
|
2021-06-24 13:09:35 +02:00
|
|
|
|
|
|
|
|
|
|
return VK_SUCCESS;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
D3D12_CPU_DESCRIPTOR_HANDLE
|
2022-04-05 17:41:20 +02:00
|
|
|
|
dzn_descriptor_heap_get_cpu_handle(const struct dzn_descriptor_heap *heap, uint32_t desc_offset)
|
2021-06-24 13:09:35 +02:00
|
|
|
|
{
|
2022-04-06 15:04:34 +02:00
|
|
|
|
return (D3D12_CPU_DESCRIPTOR_HANDLE) {
|
2021-06-24 13:09:35 +02:00
|
|
|
|
.ptr = heap->cpu_base + (desc_offset * heap->desc_sz),
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
D3D12_GPU_DESCRIPTOR_HANDLE
|
2022-04-05 17:41:20 +02:00
|
|
|
|
dzn_descriptor_heap_get_gpu_handle(const struct dzn_descriptor_heap *heap, uint32_t desc_offset)
|
2021-06-24 13:09:35 +02:00
|
|
|
|
{
|
2022-04-06 15:04:34 +02:00
|
|
|
|
return (D3D12_GPU_DESCRIPTOR_HANDLE) {
|
2021-06-24 13:09:35 +02:00
|
|
|
|
.ptr = heap->gpu_base ? heap->gpu_base + (desc_offset * heap->desc_sz) : 0,
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
|
dzn: Add initial bindless infrastructure
When operating in "bindless" mode, the device will own 2 descriptor
heaps, one for views, and one for samplers. Every time a view is
created (image view, buffer view), a slot is allocated for it out
of the device view heap for each usage type (sampled vs storage).
Then, in a future change, descriptor sets will just contain view/
sampler indices instead of actual descriptors. Instead of copying
these to a cmdbuf-owned descriptor heap, we can directly bind the
descriptor set as a buffer. We'll also modify shaders to perform
an indirection and index into the device heap.
Buffers also get views set up on creation. In a perfect world, we
could just put addresses/sizes in the descriptor set, but DXIL
doesn't support loading from addresses, we need descriptors. When
robust buffer access is disabled *or* descriptor set buffer views
reference the remainder of the buffer, we can just re-use a view
from the buffer and use an offset.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21913>
2023-03-02 10:06:13 -08:00
|
|
|
|
void
|
2023-02-28 13:54:18 -08:00
|
|
|
|
dzn_descriptor_heap_write_sampler_desc(struct dzn_device *device,
|
|
|
|
|
|
struct dzn_descriptor_heap *heap,
|
2021-06-24 13:09:35 +02:00
|
|
|
|
uint32_t desc_offset,
|
2022-04-05 17:41:20 +02:00
|
|
|
|
const struct dzn_sampler *sampler)
|
2021-06-24 13:09:35 +02:00
|
|
|
|
{
|
2023-02-28 13:54:18 -08:00
|
|
|
|
struct dzn_physical_device *pdev = container_of(device->vk.physical, struct dzn_physical_device, vk);
|
|
|
|
|
|
if (device->dev11 && pdev->options14.AdvancedTextureOpsSupported)
|
|
|
|
|
|
ID3D12Device11_CreateSampler2(device->dev11, &sampler->desc,
|
2023-01-05 15:39:16 -08:00
|
|
|
|
dzn_descriptor_heap_get_cpu_handle(heap, desc_offset));
|
|
|
|
|
|
else
|
2023-02-28 13:54:18 -08:00
|
|
|
|
ID3D12Device1_CreateSampler(device->dev, (D3D12_SAMPLER_DESC *)&sampler->desc,
|
2023-01-05 15:39:16 -08:00
|
|
|
|
dzn_descriptor_heap_get_cpu_handle(heap, desc_offset));
|
2021-06-24 13:09:35 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2023-02-28 13:54:18 -08:00
|
|
|
|
dzn_descriptor_heap_write_image_view_desc(struct dzn_device *device,
|
|
|
|
|
|
struct dzn_descriptor_heap *heap,
|
2021-06-24 13:09:35 +02:00
|
|
|
|
uint32_t desc_offset,
|
|
|
|
|
|
bool writeable, bool cube_as_2darray,
|
2022-04-05 17:41:20 +02:00
|
|
|
|
const struct dzn_image_view *iview)
|
2021-06-24 13:09:35 +02:00
|
|
|
|
{
|
|
|
|
|
|
D3D12_CPU_DESCRIPTOR_HANDLE view_handle =
|
|
|
|
|
|
dzn_descriptor_heap_get_cpu_handle(heap, desc_offset);
|
2022-04-05 17:41:20 +02:00
|
|
|
|
struct dzn_image *image = container_of(iview->vk.image, struct dzn_image, vk);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
|
|
|
|
|
|
if (writeable) {
|
2023-02-28 13:54:18 -08:00
|
|
|
|
ID3D12Device1_CreateUnorderedAccessView(device->dev, image->res, NULL, &iview->uav_desc, view_handle);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
} else if (cube_as_2darray &&
|
|
|
|
|
|
(iview->srv_desc.ViewDimension == D3D12_SRV_DIMENSION_TEXTURECUBEARRAY ||
|
|
|
|
|
|
iview->srv_desc.ViewDimension == D3D12_SRV_DIMENSION_TEXTURECUBE)) {
|
|
|
|
|
|
D3D12_SHADER_RESOURCE_VIEW_DESC srv_desc = iview->srv_desc;
|
|
|
|
|
|
srv_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DARRAY;
|
|
|
|
|
|
srv_desc.Texture2DArray.PlaneSlice = 0;
|
2022-11-04 13:01:08 -07:00
|
|
|
|
srv_desc.Texture2DArray.ResourceMinLODClamp = 0.0f;
|
2021-06-24 13:09:35 +02:00
|
|
|
|
if (iview->srv_desc.ViewDimension == D3D12_SRV_DIMENSION_TEXTURECUBEARRAY) {
|
|
|
|
|
|
srv_desc.Texture2DArray.MostDetailedMip =
|
|
|
|
|
|
iview->srv_desc.TextureCubeArray.MostDetailedMip;
|
|
|
|
|
|
srv_desc.Texture2DArray.MipLevels =
|
|
|
|
|
|
iview->srv_desc.TextureCubeArray.MipLevels;
|
|
|
|
|
|
srv_desc.Texture2DArray.FirstArraySlice =
|
|
|
|
|
|
iview->srv_desc.TextureCubeArray.First2DArrayFace;
|
|
|
|
|
|
srv_desc.Texture2DArray.ArraySize =
|
|
|
|
|
|
iview->srv_desc.TextureCubeArray.NumCubes * 6;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
srv_desc.Texture2DArray.MostDetailedMip =
|
|
|
|
|
|
iview->srv_desc.TextureCube.MostDetailedMip;
|
|
|
|
|
|
srv_desc.Texture2DArray.MipLevels =
|
|
|
|
|
|
iview->srv_desc.TextureCube.MipLevels;
|
|
|
|
|
|
srv_desc.Texture2DArray.FirstArraySlice = 0;
|
|
|
|
|
|
srv_desc.Texture2DArray.ArraySize = 6;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-02-28 13:54:18 -08:00
|
|
|
|
ID3D12Device1_CreateShaderResourceView(device->dev, image->res, &srv_desc, view_handle);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
} else {
|
2023-02-28 13:54:18 -08:00
|
|
|
|
ID3D12Device1_CreateShaderResourceView(device->dev, image->res, &iview->srv_desc, view_handle);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
dzn: Add initial bindless infrastructure
When operating in "bindless" mode, the device will own 2 descriptor
heaps, one for views, and one for samplers. Every time a view is
created (image view, buffer view), a slot is allocated for it out
of the device view heap for each usage type (sampled vs storage).
Then, in a future change, descriptor sets will just contain view/
sampler indices instead of actual descriptors. Instead of copying
these to a cmdbuf-owned descriptor heap, we can directly bind the
descriptor set as a buffer. We'll also modify shaders to perform
an indirection and index into the device heap.
Buffers also get views set up on creation. In a perfect world, we
could just put addresses/sizes in the descriptor set, but DXIL
doesn't support loading from addresses, we need descriptors. When
robust buffer access is disabled *or* descriptor set buffer views
reference the remainder of the buffer, we can just re-use a view
from the buffer and use an offset.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21913>
2023-03-02 10:06:13 -08:00
|
|
|
|
void
|
2023-02-28 13:54:18 -08:00
|
|
|
|
dzn_descriptor_heap_write_buffer_view_desc(struct dzn_device *device,
|
|
|
|
|
|
struct dzn_descriptor_heap *heap,
|
2021-06-24 13:09:35 +02:00
|
|
|
|
uint32_t desc_offset,
|
|
|
|
|
|
bool writeable,
|
2022-04-05 17:41:20 +02:00
|
|
|
|
const struct dzn_buffer_view *bview)
|
2021-06-24 13:09:35 +02:00
|
|
|
|
{
|
|
|
|
|
|
D3D12_CPU_DESCRIPTOR_HANDLE view_handle =
|
|
|
|
|
|
dzn_descriptor_heap_get_cpu_handle(heap, desc_offset);
|
|
|
|
|
|
|
|
|
|
|
|
if (writeable)
|
2023-02-28 13:54:18 -08:00
|
|
|
|
ID3D12Device1_CreateUnorderedAccessView(device->dev, bview->buffer->res, NULL, &bview->uav_desc, view_handle);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
else
|
2023-02-28 13:54:18 -08:00
|
|
|
|
ID3D12Device1_CreateShaderResourceView(device->dev, bview->buffer->res, &bview->srv_desc, view_handle);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2023-02-28 13:54:18 -08:00
|
|
|
|
dzn_descriptor_heap_write_buffer_desc(struct dzn_device *device,
|
|
|
|
|
|
struct dzn_descriptor_heap *heap,
|
2021-06-24 13:09:35 +02:00
|
|
|
|
uint32_t desc_offset,
|
|
|
|
|
|
bool writeable,
|
2022-04-05 17:41:20 +02:00
|
|
|
|
const struct dzn_buffer_desc *info)
|
2021-06-24 13:09:35 +02:00
|
|
|
|
{
|
|
|
|
|
|
D3D12_CPU_DESCRIPTOR_HANDLE view_handle =
|
|
|
|
|
|
dzn_descriptor_heap_get_cpu_handle(heap, desc_offset);
|
|
|
|
|
|
|
|
|
|
|
|
VkDeviceSize size =
|
|
|
|
|
|
info->range == VK_WHOLE_SIZE ?
|
|
|
|
|
|
info->buffer->size - info->offset :
|
|
|
|
|
|
info->range;
|
|
|
|
|
|
|
|
|
|
|
|
if (info->type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER ||
|
|
|
|
|
|
info->type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) {
|
|
|
|
|
|
assert(!writeable);
|
|
|
|
|
|
D3D12_CONSTANT_BUFFER_VIEW_DESC cbv_desc = {
|
2023-01-25 09:03:52 -08:00
|
|
|
|
.BufferLocation = info->buffer->gpuva + info->offset,
|
dzn: Add initial bindless infrastructure
When operating in "bindless" mode, the device will own 2 descriptor
heaps, one for views, and one for samplers. Every time a view is
created (image view, buffer view), a slot is allocated for it out
of the device view heap for each usage type (sampled vs storage).
Then, in a future change, descriptor sets will just contain view/
sampler indices instead of actual descriptors. Instead of copying
these to a cmdbuf-owned descriptor heap, we can directly bind the
descriptor set as a buffer. We'll also modify shaders to perform
an indirection and index into the device heap.
Buffers also get views set up on creation. In a perfect world, we
could just put addresses/sizes in the descriptor set, but DXIL
doesn't support loading from addresses, we need descriptors. When
robust buffer access is disabled *or* descriptor set buffer views
reference the remainder of the buffer, we can just re-use a view
from the buffer and use an offset.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21913>
2023-03-02 10:06:13 -08:00
|
|
|
|
.SizeInBytes = MIN2(ALIGN_POT(size, 256), D3D12_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * 4 * sizeof(float)),
|
2021-06-24 13:09:35 +02:00
|
|
|
|
};
|
2023-02-28 13:54:18 -08:00
|
|
|
|
ID3D12Device1_CreateConstantBufferView(device->dev, &cbv_desc, view_handle);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
} else if (writeable) {
|
|
|
|
|
|
D3D12_UNORDERED_ACCESS_VIEW_DESC uav_desc = {
|
|
|
|
|
|
.Format = DXGI_FORMAT_R32_TYPELESS,
|
|
|
|
|
|
.ViewDimension = D3D12_UAV_DIMENSION_BUFFER,
|
|
|
|
|
|
.Buffer = {
|
|
|
|
|
|
.FirstElement = info->offset / sizeof(uint32_t),
|
2023-01-06 13:17:10 -08:00
|
|
|
|
.NumElements = (UINT)DIV_ROUND_UP(size, sizeof(uint32_t)),
|
2021-06-24 13:09:35 +02:00
|
|
|
|
.Flags = D3D12_BUFFER_UAV_FLAG_RAW,
|
|
|
|
|
|
},
|
|
|
|
|
|
};
|
2023-02-28 13:54:18 -08:00
|
|
|
|
ID3D12Device1_CreateUnorderedAccessView(device->dev, info->buffer->res, NULL, &uav_desc, view_handle);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
} else {
|
|
|
|
|
|
D3D12_SHADER_RESOURCE_VIEW_DESC srv_desc = {
|
|
|
|
|
|
.Format = DXGI_FORMAT_R32_TYPELESS,
|
|
|
|
|
|
.ViewDimension = D3D12_SRV_DIMENSION_BUFFER,
|
|
|
|
|
|
.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING,
|
|
|
|
|
|
.Buffer = {
|
|
|
|
|
|
.FirstElement = info->offset / sizeof(uint32_t),
|
2023-01-06 13:17:10 -08:00
|
|
|
|
.NumElements = (UINT)DIV_ROUND_UP(size, sizeof(uint32_t)),
|
2021-06-24 13:09:35 +02:00
|
|
|
|
.Flags = D3D12_BUFFER_SRV_FLAG_RAW,
|
|
|
|
|
|
},
|
|
|
|
|
|
};
|
2023-02-28 13:54:18 -08:00
|
|
|
|
ID3D12Device1_CreateShaderResourceView(device->dev, info->buffer->res, &srv_desc, view_handle);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-03-02 19:58:09 -08:00
|
|
|
|
static void
|
dzn: Re-design custom buffer descriptors
Previously, custom buffer descriptors were owned by a descriptor set. Now,
custom buffer descriptors are owned by the buffer. Additionally, we respect
the app-provided sizes when they're smaller than the buffer size, even if
robustness is not enabled, so that size queries work correctly.
This new design fixes several issues:
* Descriptor set copies were broken when they involved custom descriptors,
because the original descriptor set owned the lifetime of the custom
descriptor, the new one was just borrowing it. If those lifetimes didn't
line up, problems would arise.
* A single buffer with the same sub-view placed in multiplel descriptor sets
would allocate multiple slots, when it only really needed one.
* Custom buffer descriptors now lower the base offset to 0 to allow merging
multiple overlapping (ending at the same upper bound) descriptors. Since
the shader is already doing an offset add, making it nonzero is free.
* Dynamic buffer descriptors were incorrect before. The size passed into the
descriptor set is supposed to be the size from the *dynamic* offset, not the
size from the static offset. By allocating/populating the descriptor when
placed into the set, it prevented larger offsets from working correctly. This
buffer-owned design prevents cmdbufs from having to own lifetime of custom
descriptors.
Fixes dEQP-VK.ssbo.unsized_array_length.float_offset_explicit_size
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/22639>
2023-04-21 11:48:16 -07:00
|
|
|
|
dzn_bindless_descriptor_set_write_sampler_desc(volatile struct dxil_spirv_bindless_entry *map,
|
2023-03-02 19:58:09 -08:00
|
|
|
|
uint32_t desc_offset,
|
|
|
|
|
|
const struct dzn_sampler *sampler)
|
|
|
|
|
|
{
|
|
|
|
|
|
map[desc_offset].sampler_idx = sampler->bindless_slot;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
dzn: Re-design custom buffer descriptors
Previously, custom buffer descriptors were owned by a descriptor set. Now,
custom buffer descriptors are owned by the buffer. Additionally, we respect
the app-provided sizes when they're smaller than the buffer size, even if
robustness is not enabled, so that size queries work correctly.
This new design fixes several issues:
* Descriptor set copies were broken when they involved custom descriptors,
because the original descriptor set owned the lifetime of the custom
descriptor, the new one was just borrowing it. If those lifetimes didn't
line up, problems would arise.
* A single buffer with the same sub-view placed in multiplel descriptor sets
would allocate multiple slots, when it only really needed one.
* Custom buffer descriptors now lower the base offset to 0 to allow merging
multiple overlapping (ending at the same upper bound) descriptors. Since
the shader is already doing an offset add, making it nonzero is free.
* Dynamic buffer descriptors were incorrect before. The size passed into the
descriptor set is supposed to be the size from the *dynamic* offset, not the
size from the static offset. By allocating/populating the descriptor when
placed into the set, it prevented larger offsets from working correctly. This
buffer-owned design prevents cmdbufs from having to own lifetime of custom
descriptors.
Fixes dEQP-VK.ssbo.unsized_array_length.float_offset_explicit_size
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/22639>
2023-04-21 11:48:16 -07:00
|
|
|
|
dzn_bindless_descriptor_set_write_image_view_desc(volatile struct dxil_spirv_bindless_entry *map,
|
2023-03-02 19:58:09 -08:00
|
|
|
|
VkDescriptorType type,
|
|
|
|
|
|
uint32_t desc_offset,
|
|
|
|
|
|
const struct dzn_image_view *iview)
|
|
|
|
|
|
{
|
|
|
|
|
|
switch (type) {
|
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
|
|
|
|
|
|
map[desc_offset].texture_idx = iview->uav_bindless_slot;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
|
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
|
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
|
|
|
|
|
|
map[desc_offset].texture_idx = iview->srv_bindless_slot;
|
|
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
|
|
unreachable("Unexpected descriptor type");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
dzn: Re-design custom buffer descriptors
Previously, custom buffer descriptors were owned by a descriptor set. Now,
custom buffer descriptors are owned by the buffer. Additionally, we respect
the app-provided sizes when they're smaller than the buffer size, even if
robustness is not enabled, so that size queries work correctly.
This new design fixes several issues:
* Descriptor set copies were broken when they involved custom descriptors,
because the original descriptor set owned the lifetime of the custom
descriptor, the new one was just borrowing it. If those lifetimes didn't
line up, problems would arise.
* A single buffer with the same sub-view placed in multiplel descriptor sets
would allocate multiple slots, when it only really needed one.
* Custom buffer descriptors now lower the base offset to 0 to allow merging
multiple overlapping (ending at the same upper bound) descriptors. Since
the shader is already doing an offset add, making it nonzero is free.
* Dynamic buffer descriptors were incorrect before. The size passed into the
descriptor set is supposed to be the size from the *dynamic* offset, not the
size from the static offset. By allocating/populating the descriptor when
placed into the set, it prevented larger offsets from working correctly. This
buffer-owned design prevents cmdbufs from having to own lifetime of custom
descriptors.
Fixes dEQP-VK.ssbo.unsized_array_length.float_offset_explicit_size
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/22639>
2023-04-21 11:48:16 -07:00
|
|
|
|
dzn_bindless_descriptor_set_write_buffer_view_desc(volatile struct dxil_spirv_bindless_entry *map,
|
2023-03-02 19:58:09 -08:00
|
|
|
|
VkDescriptorType type,
|
|
|
|
|
|
uint32_t desc_offset,
|
|
|
|
|
|
const struct dzn_buffer_view *bview)
|
|
|
|
|
|
{
|
|
|
|
|
|
switch (type) {
|
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
|
|
|
|
|
|
map[desc_offset].texture_idx = bview->srv_bindless_slot;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
|
|
|
|
|
|
map[desc_offset].texture_idx = bview->uav_bindless_slot;
|
|
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
|
|
unreachable("Unexpected descriptor type");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
dzn: Re-design custom buffer descriptors
Previously, custom buffer descriptors were owned by a descriptor set. Now,
custom buffer descriptors are owned by the buffer. Additionally, we respect
the app-provided sizes when they're smaller than the buffer size, even if
robustness is not enabled, so that size queries work correctly.
This new design fixes several issues:
* Descriptor set copies were broken when they involved custom descriptors,
because the original descriptor set owned the lifetime of the custom
descriptor, the new one was just borrowing it. If those lifetimes didn't
line up, problems would arise.
* A single buffer with the same sub-view placed in multiplel descriptor sets
would allocate multiple slots, when it only really needed one.
* Custom buffer descriptors now lower the base offset to 0 to allow merging
multiple overlapping (ending at the same upper bound) descriptors. Since
the shader is already doing an offset add, making it nonzero is free.
* Dynamic buffer descriptors were incorrect before. The size passed into the
descriptor set is supposed to be the size from the *dynamic* offset, not the
size from the static offset. By allocating/populating the descriptor when
placed into the set, it prevented larger offsets from working correctly. This
buffer-owned design prevents cmdbufs from having to own lifetime of custom
descriptors.
Fixes dEQP-VK.ssbo.unsized_array_length.float_offset_explicit_size
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/22639>
2023-04-21 11:48:16 -07:00
|
|
|
|
static void
|
|
|
|
|
|
dzn_bindless_descriptor_set_write_buffer_desc(struct dzn_device *device,
|
|
|
|
|
|
volatile struct dxil_spirv_bindless_entry *map,
|
|
|
|
|
|
uint32_t desc_offset,
|
|
|
|
|
|
const struct dzn_buffer_desc *info)
|
|
|
|
|
|
{
|
|
|
|
|
|
dzn_buffer_get_bindless_buffer_descriptor(device, info, &map[desc_offset]);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-03-02 19:58:09 -08:00
|
|
|
|
static bool
|
dzn: Re-design custom buffer descriptors
Previously, custom buffer descriptors were owned by a descriptor set. Now,
custom buffer descriptors are owned by the buffer. Additionally, we respect
the app-provided sizes when they're smaller than the buffer size, even if
robustness is not enabled, so that size queries work correctly.
This new design fixes several issues:
* Descriptor set copies were broken when they involved custom descriptors,
because the original descriptor set owned the lifetime of the custom
descriptor, the new one was just borrowing it. If those lifetimes didn't
line up, problems would arise.
* A single buffer with the same sub-view placed in multiplel descriptor sets
would allocate multiple slots, when it only really needed one.
* Custom buffer descriptors now lower the base offset to 0 to allow merging
multiple overlapping (ending at the same upper bound) descriptors. Since
the shader is already doing an offset add, making it nonzero is free.
* Dynamic buffer descriptors were incorrect before. The size passed into the
descriptor set is supposed to be the size from the *dynamic* offset, not the
size from the static offset. By allocating/populating the descriptor when
placed into the set, it prevented larger offsets from working correctly. This
buffer-owned design prevents cmdbufs from having to own lifetime of custom
descriptors.
Fixes dEQP-VK.ssbo.unsized_array_length.float_offset_explicit_size
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/22639>
2023-04-21 11:48:16 -07:00
|
|
|
|
need_custom_buffer_descriptor(struct dzn_device *device, const struct dzn_buffer_desc *info,
|
|
|
|
|
|
struct dzn_buffer_desc *out_desc)
|
2023-03-02 19:58:09 -08:00
|
|
|
|
{
|
dzn: Re-design custom buffer descriptors
Previously, custom buffer descriptors were owned by a descriptor set. Now,
custom buffer descriptors are owned by the buffer. Additionally, we respect
the app-provided sizes when they're smaller than the buffer size, even if
robustness is not enabled, so that size queries work correctly.
This new design fixes several issues:
* Descriptor set copies were broken when they involved custom descriptors,
because the original descriptor set owned the lifetime of the custom
descriptor, the new one was just borrowing it. If those lifetimes didn't
line up, problems would arise.
* A single buffer with the same sub-view placed in multiplel descriptor sets
would allocate multiple slots, when it only really needed one.
* Custom buffer descriptors now lower the base offset to 0 to allow merging
multiple overlapping (ending at the same upper bound) descriptors. Since
the shader is already doing an offset add, making it nonzero is free.
* Dynamic buffer descriptors were incorrect before. The size passed into the
descriptor set is supposed to be the size from the *dynamic* offset, not the
size from the static offset. By allocating/populating the descriptor when
placed into the set, it prevented larger offsets from working correctly. This
buffer-owned design prevents cmdbufs from having to own lifetime of custom
descriptors.
Fixes dEQP-VK.ssbo.unsized_array_length.float_offset_explicit_size
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/22639>
2023-04-21 11:48:16 -07:00
|
|
|
|
*out_desc = *info;
|
|
|
|
|
|
uint32_t upper_bound_default_descriptor;
|
|
|
|
|
|
uint32_t size_align, offset_align;
|
|
|
|
|
|
/* Canonicalize descriptor types for hash/compare, and get size/align info */
|
|
|
|
|
|
switch (info->type) {
|
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
|
|
|
|
|
|
out_desc->type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
|
|
|
|
|
FALLTHROUGH;
|
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
|
2023-05-02 11:21:00 -07:00
|
|
|
|
upper_bound_default_descriptor =
|
|
|
|
|
|
MIN2(D3D12_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * sizeof(float) * 4, info->buffer->size);
|
dzn: Re-design custom buffer descriptors
Previously, custom buffer descriptors were owned by a descriptor set. Now,
custom buffer descriptors are owned by the buffer. Additionally, we respect
the app-provided sizes when they're smaller than the buffer size, even if
robustness is not enabled, so that size queries work correctly.
This new design fixes several issues:
* Descriptor set copies were broken when they involved custom descriptors,
because the original descriptor set owned the lifetime of the custom
descriptor, the new one was just borrowing it. If those lifetimes didn't
line up, problems would arise.
* A single buffer with the same sub-view placed in multiplel descriptor sets
would allocate multiple slots, when it only really needed one.
* Custom buffer descriptors now lower the base offset to 0 to allow merging
multiple overlapping (ending at the same upper bound) descriptors. Since
the shader is already doing an offset add, making it nonzero is free.
* Dynamic buffer descriptors were incorrect before. The size passed into the
descriptor set is supposed to be the size from the *dynamic* offset, not the
size from the static offset. By allocating/populating the descriptor when
placed into the set, it prevented larger offsets from working correctly. This
buffer-owned design prevents cmdbufs from having to own lifetime of custom
descriptors.
Fixes dEQP-VK.ssbo.unsized_array_length.float_offset_explicit_size
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/22639>
2023-04-21 11:48:16 -07:00
|
|
|
|
size_align = offset_align = D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
|
|
|
|
|
|
out_desc->type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
|
|
|
|
|
|
FALLTHROUGH;
|
|
|
|
|
|
default:
|
2023-05-02 11:21:00 -07:00
|
|
|
|
upper_bound_default_descriptor = MIN2(UINT32_MAX, info->buffer->size);
|
dzn: Re-design custom buffer descriptors
Previously, custom buffer descriptors were owned by a descriptor set. Now,
custom buffer descriptors are owned by the buffer. Additionally, we respect
the app-provided sizes when they're smaller than the buffer size, even if
robustness is not enabled, so that size queries work correctly.
This new design fixes several issues:
* Descriptor set copies were broken when they involved custom descriptors,
because the original descriptor set owned the lifetime of the custom
descriptor, the new one was just borrowing it. If those lifetimes didn't
line up, problems would arise.
* A single buffer with the same sub-view placed in multiplel descriptor sets
would allocate multiple slots, when it only really needed one.
* Custom buffer descriptors now lower the base offset to 0 to allow merging
multiple overlapping (ending at the same upper bound) descriptors. Since
the shader is already doing an offset add, making it nonzero is free.
* Dynamic buffer descriptors were incorrect before. The size passed into the
descriptor set is supposed to be the size from the *dynamic* offset, not the
size from the static offset. By allocating/populating the descriptor when
placed into the set, it prevented larger offsets from working correctly. This
buffer-owned design prevents cmdbufs from having to own lifetime of custom
descriptors.
Fixes dEQP-VK.ssbo.unsized_array_length.float_offset_explicit_size
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/22639>
2023-04-21 11:48:16 -07:00
|
|
|
|
offset_align = D3D12_RAW_UAV_SRV_BYTE_ALIGNMENT;
|
|
|
|
|
|
size_align = 4;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-05-02 11:21:00 -07:00
|
|
|
|
uint64_t upper_bound = info->range == VK_WHOLE_SIZE ?
|
|
|
|
|
|
info->buffer->size :
|
|
|
|
|
|
info->offset + info->range;
|
|
|
|
|
|
/* Addressing the whole buffer, no custom descriptor needed. */
|
|
|
|
|
|
if (upper_bound == upper_bound_default_descriptor)
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
dzn: Re-design custom buffer descriptors
Previously, custom buffer descriptors were owned by a descriptor set. Now,
custom buffer descriptors are owned by the buffer. Additionally, we respect
the app-provided sizes when they're smaller than the buffer size, even if
robustness is not enabled, so that size queries work correctly.
This new design fixes several issues:
* Descriptor set copies were broken when they involved custom descriptors,
because the original descriptor set owned the lifetime of the custom
descriptor, the new one was just borrowing it. If those lifetimes didn't
line up, problems would arise.
* A single buffer with the same sub-view placed in multiplel descriptor sets
would allocate multiple slots, when it only really needed one.
* Custom buffer descriptors now lower the base offset to 0 to allow merging
multiple overlapping (ending at the same upper bound) descriptors. Since
the shader is already doing an offset add, making it nonzero is free.
* Dynamic buffer descriptors were incorrect before. The size passed into the
descriptor set is supposed to be the size from the *dynamic* offset, not the
size from the static offset. By allocating/populating the descriptor when
placed into the set, it prevented larger offsets from working correctly. This
buffer-owned design prevents cmdbufs from having to own lifetime of custom
descriptors.
Fixes dEQP-VK.ssbo.unsized_array_length.float_offset_explicit_size
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/22639>
2023-04-21 11:48:16 -07:00
|
|
|
|
out_desc->range = ALIGN_POT(upper_bound, size_align);
|
|
|
|
|
|
if (out_desc->range <= upper_bound_default_descriptor) {
|
|
|
|
|
|
/* Use a larger descriptor with the hope that we'll be more likely
|
|
|
|
|
|
* to be able to re-use it. The shader is already doing the offset
|
|
|
|
|
|
* add, so there's not really a cost to putting a nonzero value there. */
|
|
|
|
|
|
out_desc->offset = 0;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
/* At least align-down the base offset to ensure that's a valid view to create */
|
|
|
|
|
|
out_desc->offset = (out_desc->offset / offset_align) * offset_align;
|
|
|
|
|
|
out_desc->range -= out_desc->offset;
|
|
|
|
|
|
}
|
|
|
|
|
|
return true;
|
2023-03-02 19:58:09 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
dzn: Re-design custom buffer descriptors
Previously, custom buffer descriptors were owned by a descriptor set. Now,
custom buffer descriptors are owned by the buffer. Additionally, we respect
the app-provided sizes when they're smaller than the buffer size, even if
robustness is not enabled, so that size queries work correctly.
This new design fixes several issues:
* Descriptor set copies were broken when they involved custom descriptors,
because the original descriptor set owned the lifetime of the custom
descriptor, the new one was just borrowing it. If those lifetimes didn't
line up, problems would arise.
* A single buffer with the same sub-view placed in multiplel descriptor sets
would allocate multiple slots, when it only really needed one.
* Custom buffer descriptors now lower the base offset to 0 to allow merging
multiple overlapping (ending at the same upper bound) descriptors. Since
the shader is already doing an offset add, making it nonzero is free.
* Dynamic buffer descriptors were incorrect before. The size passed into the
descriptor set is supposed to be the size from the *dynamic* offset, not the
size from the static offset. By allocating/populating the descriptor when
placed into the set, it prevented larger offsets from working correctly. This
buffer-owned design prevents cmdbufs from having to own lifetime of custom
descriptors.
Fixes dEQP-VK.ssbo.unsized_array_length.float_offset_explicit_size
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/22639>
2023-04-21 11:48:16 -07:00
|
|
|
|
static uint32_t
|
|
|
|
|
|
hash_buffer_desc(const void *data)
|
2023-03-02 19:58:09 -08:00
|
|
|
|
{
|
dzn: Re-design custom buffer descriptors
Previously, custom buffer descriptors were owned by a descriptor set. Now,
custom buffer descriptors are owned by the buffer. Additionally, we respect
the app-provided sizes when they're smaller than the buffer size, even if
robustness is not enabled, so that size queries work correctly.
This new design fixes several issues:
* Descriptor set copies were broken when they involved custom descriptors,
because the original descriptor set owned the lifetime of the custom
descriptor, the new one was just borrowing it. If those lifetimes didn't
line up, problems would arise.
* A single buffer with the same sub-view placed in multiplel descriptor sets
would allocate multiple slots, when it only really needed one.
* Custom buffer descriptors now lower the base offset to 0 to allow merging
multiple overlapping (ending at the same upper bound) descriptors. Since
the shader is already doing an offset add, making it nonzero is free.
* Dynamic buffer descriptors were incorrect before. The size passed into the
descriptor set is supposed to be the size from the *dynamic* offset, not the
size from the static offset. By allocating/populating the descriptor when
placed into the set, it prevented larger offsets from working correctly. This
buffer-owned design prevents cmdbufs from having to own lifetime of custom
descriptors.
Fixes dEQP-VK.ssbo.unsized_array_length.float_offset_explicit_size
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/22639>
2023-04-21 11:48:16 -07:00
|
|
|
|
const struct dzn_buffer_desc *bdesc = data;
|
|
|
|
|
|
/* Avoid any potential padding in the struct */
|
|
|
|
|
|
uint32_t type_hash = _mesa_hash_data(&bdesc->type, sizeof(bdesc->type));
|
|
|
|
|
|
return _mesa_hash_data_with_seed(&bdesc->range, sizeof(bdesc->range) * 2, type_hash);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static bool
|
|
|
|
|
|
compare_buffer_desc(const void *_a, const void *_b)
|
|
|
|
|
|
{
|
|
|
|
|
|
const struct dzn_buffer_desc *a = _a, *b = _b;
|
|
|
|
|
|
assert(a->buffer == b->buffer);
|
|
|
|
|
|
/* Avoid any potential padding in the struct */
|
|
|
|
|
|
return a->type == b->type &&
|
|
|
|
|
|
a->range == b->range &&
|
|
|
|
|
|
a->offset == b->offset;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
|
handle_custom_descriptor_cache(struct dzn_device *device,
|
|
|
|
|
|
const struct dzn_buffer_desc *stack_desc)
|
|
|
|
|
|
{
|
|
|
|
|
|
/* Buffer lock is held */
|
|
|
|
|
|
|
|
|
|
|
|
/* Initialize hash map */
|
|
|
|
|
|
if (!stack_desc->buffer->custom_views)
|
|
|
|
|
|
stack_desc->buffer->custom_views = _mesa_hash_table_create(NULL, hash_buffer_desc, compare_buffer_desc);
|
|
|
|
|
|
|
|
|
|
|
|
if (!stack_desc->buffer->custom_views)
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t hash = hash_buffer_desc(stack_desc);
|
|
|
|
|
|
struct hash_entry *entry = _mesa_hash_table_search_pre_hashed(stack_desc->buffer->custom_views, hash, stack_desc);
|
|
|
|
|
|
if (entry)
|
|
|
|
|
|
return (int)(intptr_t)entry->data;
|
|
|
|
|
|
|
|
|
|
|
|
int slot = dzn_device_descriptor_heap_alloc_slot(device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
|
|
|
|
|
|
if (slot < 0)
|
|
|
|
|
|
return slot;
|
|
|
|
|
|
|
|
|
|
|
|
struct dzn_buffer_desc *key = malloc(sizeof(*stack_desc));
|
|
|
|
|
|
if (!key) {
|
|
|
|
|
|
dzn_device_descriptor_heap_free_slot(device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, slot);
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
*key = *stack_desc;
|
|
|
|
|
|
entry = _mesa_hash_table_insert_pre_hashed(stack_desc->buffer->custom_views, hash, key, (void *)(intptr_t)slot);
|
|
|
|
|
|
if (!entry) {
|
|
|
|
|
|
free(key);
|
|
|
|
|
|
dzn_device_descriptor_heap_free_slot(device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, slot);
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
dzn_descriptor_heap_write_buffer_desc(device, &device->device_heaps[D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV].heap,
|
|
|
|
|
|
slot, key->type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, key);
|
|
|
|
|
|
return slot;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
|
dzn_buffer_get_bindless_buffer_descriptor(struct dzn_device *device,
|
|
|
|
|
|
const struct dzn_buffer_desc *bdesc,
|
|
|
|
|
|
volatile struct dxil_spirv_bindless_entry *out)
|
|
|
|
|
|
{
|
|
|
|
|
|
int slot;
|
|
|
|
|
|
uint32_t offset = bdesc->offset;
|
|
|
|
|
|
switch (bdesc->type) {
|
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
|
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
|
|
|
|
|
|
slot = bdesc->buffer->cbv_bindless_slot;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
|
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
|
|
|
|
|
|
slot = bdesc->buffer->uav_bindless_slot;
|
|
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
|
|
unreachable("Unexpected descriptor type");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
struct dzn_buffer_desc local_desc;
|
|
|
|
|
|
if (need_custom_buffer_descriptor(device, bdesc, &local_desc)) {
|
|
|
|
|
|
mtx_lock(&bdesc->buffer->bindless_view_lock);
|
|
|
|
|
|
|
|
|
|
|
|
int new_slot = handle_custom_descriptor_cache(device, &local_desc);
|
|
|
|
|
|
if (new_slot >= 0) {
|
|
|
|
|
|
slot = new_slot;
|
|
|
|
|
|
offset = bdesc->offset - local_desc.offset;
|
2023-03-02 19:58:09 -08:00
|
|
|
|
}
|
dzn: Re-design custom buffer descriptors
Previously, custom buffer descriptors were owned by a descriptor set. Now,
custom buffer descriptors are owned by the buffer. Additionally, we respect
the app-provided sizes when they're smaller than the buffer size, even if
robustness is not enabled, so that size queries work correctly.
This new design fixes several issues:
* Descriptor set copies were broken when they involved custom descriptors,
because the original descriptor set owned the lifetime of the custom
descriptor, the new one was just borrowing it. If those lifetimes didn't
line up, problems would arise.
* A single buffer with the same sub-view placed in multiplel descriptor sets
would allocate multiple slots, when it only really needed one.
* Custom buffer descriptors now lower the base offset to 0 to allow merging
multiple overlapping (ending at the same upper bound) descriptors. Since
the shader is already doing an offset add, making it nonzero is free.
* Dynamic buffer descriptors were incorrect before. The size passed into the
descriptor set is supposed to be the size from the *dynamic* offset, not the
size from the static offset. By allocating/populating the descriptor when
placed into the set, it prevented larger offsets from working correctly. This
buffer-owned design prevents cmdbufs from having to own lifetime of custom
descriptors.
Fixes dEQP-VK.ssbo.unsized_array_length.float_offset_explicit_size
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/22639>
2023-04-21 11:48:16 -07:00
|
|
|
|
/* In the case of cache failure, just use the base view and try
|
|
|
|
|
|
* shader-based offsetting, it'll probably still work in most cases. */
|
|
|
|
|
|
|
|
|
|
|
|
mtx_unlock(&bdesc->buffer->bindless_view_lock);
|
2023-03-02 19:58:09 -08:00
|
|
|
|
}
|
dzn: Re-design custom buffer descriptors
Previously, custom buffer descriptors were owned by a descriptor set. Now,
custom buffer descriptors are owned by the buffer. Additionally, we respect
the app-provided sizes when they're smaller than the buffer size, even if
robustness is not enabled, so that size queries work correctly.
This new design fixes several issues:
* Descriptor set copies were broken when they involved custom descriptors,
because the original descriptor set owned the lifetime of the custom
descriptor, the new one was just borrowing it. If those lifetimes didn't
line up, problems would arise.
* A single buffer with the same sub-view placed in multiplel descriptor sets
would allocate multiple slots, when it only really needed one.
* Custom buffer descriptors now lower the base offset to 0 to allow merging
multiple overlapping (ending at the same upper bound) descriptors. Since
the shader is already doing an offset add, making it nonzero is free.
* Dynamic buffer descriptors were incorrect before. The size passed into the
descriptor set is supposed to be the size from the *dynamic* offset, not the
size from the static offset. By allocating/populating the descriptor when
placed into the set, it prevented larger offsets from working correctly. This
buffer-owned design prevents cmdbufs from having to own lifetime of custom
descriptors.
Fixes dEQP-VK.ssbo.unsized_array_length.float_offset_explicit_size
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/22639>
2023-04-21 11:48:16 -07:00
|
|
|
|
|
|
|
|
|
|
out->buffer_idx = slot;
|
|
|
|
|
|
out->buffer_offset = offset;
|
2023-03-02 19:58:09 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
2021-06-24 13:09:35 +02:00
|
|
|
|
void
|
2023-02-28 13:54:18 -08:00
|
|
|
|
dzn_descriptor_heap_copy(struct dzn_device *device,
|
|
|
|
|
|
struct dzn_descriptor_heap *dst_heap,
|
2021-06-24 13:09:35 +02:00
|
|
|
|
uint32_t dst_offset,
|
2022-04-05 17:41:20 +02:00
|
|
|
|
const struct dzn_descriptor_heap *src_heap,
|
2021-06-24 13:09:35 +02:00
|
|
|
|
uint32_t src_offset,
|
2023-03-01 13:59:33 -08:00
|
|
|
|
uint32_t desc_count,
|
|
|
|
|
|
D3D12_DESCRIPTOR_HEAP_TYPE type)
|
2021-06-24 13:09:35 +02:00
|
|
|
|
{
|
|
|
|
|
|
D3D12_CPU_DESCRIPTOR_HANDLE dst_handle =
|
|
|
|
|
|
dzn_descriptor_heap_get_cpu_handle(dst_heap, dst_offset);
|
|
|
|
|
|
D3D12_CPU_DESCRIPTOR_HANDLE src_handle =
|
|
|
|
|
|
dzn_descriptor_heap_get_cpu_handle(src_heap, src_offset);
|
|
|
|
|
|
|
2023-02-28 13:54:18 -08:00
|
|
|
|
ID3D12Device1_CopyDescriptorsSimple(device->dev, desc_count,
|
2022-03-25 17:08:50 +01:00
|
|
|
|
dst_handle,
|
|
|
|
|
|
src_handle,
|
2023-03-01 13:59:33 -08:00
|
|
|
|
type);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
struct dzn_descriptor_set_ptr {
|
|
|
|
|
|
uint32_t binding, elem;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
2022-04-14 11:37:45 +02:00
|
|
|
|
dzn_descriptor_set_ptr_validate(const struct dzn_descriptor_set_layout *layout,
|
2022-04-05 17:41:20 +02:00
|
|
|
|
struct dzn_descriptor_set_ptr *ptr)
|
2021-06-24 13:09:35 +02:00
|
|
|
|
{
|
|
|
|
|
|
|
2022-04-14 11:37:45 +02:00
|
|
|
|
if (ptr->binding >= layout->binding_count) {
|
2021-06-24 13:09:35 +02:00
|
|
|
|
ptr->binding = ~0;
|
|
|
|
|
|
ptr->elem = ~0;
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t desc_count =
|
2022-04-14 11:37:45 +02:00
|
|
|
|
dzn_descriptor_set_layout_get_desc_count(layout, ptr->binding);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
if (ptr->elem >= desc_count) {
|
|
|
|
|
|
ptr->binding = ~0;
|
|
|
|
|
|
ptr->elem = ~0;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
2022-04-14 11:37:45 +02:00
|
|
|
|
dzn_descriptor_set_ptr_init(const struct dzn_descriptor_set_layout *layout,
|
2022-04-05 17:41:20 +02:00
|
|
|
|
struct dzn_descriptor_set_ptr *ptr,
|
2021-06-24 13:09:35 +02:00
|
|
|
|
uint32_t binding, uint32_t elem)
|
|
|
|
|
|
{
|
|
|
|
|
|
ptr->binding = binding;
|
|
|
|
|
|
ptr->elem = elem;
|
2022-04-14 11:37:45 +02:00
|
|
|
|
dzn_descriptor_set_ptr_validate(layout, ptr);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
2022-04-14 11:37:45 +02:00
|
|
|
|
dzn_descriptor_set_ptr_move(const struct dzn_descriptor_set_layout *layout,
|
2022-04-05 17:41:20 +02:00
|
|
|
|
struct dzn_descriptor_set_ptr *ptr,
|
2021-06-24 13:09:35 +02:00
|
|
|
|
uint32_t count)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (ptr->binding == ~0)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
while (count) {
|
|
|
|
|
|
uint32_t desc_count =
|
2022-04-14 11:37:45 +02:00
|
|
|
|
dzn_descriptor_set_layout_get_desc_count(layout, ptr->binding);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
|
|
|
|
|
|
if (count >= desc_count - ptr->elem) {
|
|
|
|
|
|
count -= desc_count - ptr->elem;
|
|
|
|
|
|
ptr->binding++;
|
|
|
|
|
|
ptr->elem = 0;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
ptr->elem += count;
|
|
|
|
|
|
count = 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-04-14 11:37:45 +02:00
|
|
|
|
dzn_descriptor_set_ptr_validate(layout, ptr);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2022-03-28 09:41:17 +02:00
|
|
|
|
static bool
|
2022-04-05 17:41:20 +02:00
|
|
|
|
dzn_descriptor_set_ptr_is_valid(const struct dzn_descriptor_set_ptr *ptr)
|
2021-06-24 13:09:35 +02:00
|
|
|
|
{
|
|
|
|
|
|
return ptr->binding != ~0 && ptr->elem != ~0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-03-28 09:41:17 +02:00
|
|
|
|
static uint32_t
|
2022-04-14 11:37:45 +02:00
|
|
|
|
dzn_descriptor_set_remaining_descs_in_binding(const struct dzn_descriptor_set_layout *layout,
|
2022-04-05 17:41:20 +02:00
|
|
|
|
const struct dzn_descriptor_set_ptr *ptr)
|
2021-06-24 13:09:35 +02:00
|
|
|
|
{
|
2022-04-14 11:37:45 +02:00
|
|
|
|
if (ptr->binding >= layout->binding_count)
|
2021-06-24 13:09:35 +02:00
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t desc_count =
|
2022-04-14 11:37:45 +02:00
|
|
|
|
dzn_descriptor_set_layout_get_desc_count(layout, ptr->binding);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
|
|
|
|
|
|
return desc_count >= ptr->elem ? desc_count - ptr->elem : 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2022-03-28 09:41:17 +02:00
|
|
|
|
static uint32_t
|
2022-04-14 11:37:45 +02:00
|
|
|
|
dzn_descriptor_set_ptr_get_heap_offset(const struct dzn_descriptor_set_layout *layout,
|
2022-04-14 11:42:52 +02:00
|
|
|
|
D3D12_DESCRIPTOR_HEAP_TYPE type,
|
|
|
|
|
|
const struct dzn_descriptor_set_ptr *ptr,
|
2023-03-02 13:06:22 -08:00
|
|
|
|
bool alt,
|
|
|
|
|
|
bool bindless)
|
2021-06-24 13:09:35 +02:00
|
|
|
|
{
|
|
|
|
|
|
if (ptr->binding == ~0)
|
|
|
|
|
|
return ~0;
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t base =
|
2023-03-02 13:06:22 -08:00
|
|
|
|
dzn_descriptor_set_layout_get_heap_offset(layout, ptr->binding, type, alt, bindless);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
if (base == ~0)
|
|
|
|
|
|
return ~0;
|
|
|
|
|
|
|
|
|
|
|
|
return base + ptr->elem;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-04-14 14:34:19 +02:00
|
|
|
|
static void
|
2023-02-28 13:54:18 -08:00
|
|
|
|
dzn_descriptor_set_write_sampler_desc(struct dzn_device *device,
|
|
|
|
|
|
struct dzn_descriptor_set *set,
|
2022-04-14 14:34:19 +02:00
|
|
|
|
uint32_t heap_offset,
|
|
|
|
|
|
const struct dzn_sampler *sampler)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (heap_offset == ~0)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
D3D12_DESCRIPTOR_HEAP_TYPE type = D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER;
|
2023-03-02 19:58:09 -08:00
|
|
|
|
if (device->bindless) {
|
|
|
|
|
|
dzn_bindless_descriptor_set_write_sampler_desc(set->pool->bindless.map,
|
|
|
|
|
|
set->heap_offsets[0] + heap_offset,
|
|
|
|
|
|
sampler);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
dzn_descriptor_heap_write_sampler_desc(device,
|
|
|
|
|
|
&set->pool->heaps[type],
|
|
|
|
|
|
set->heap_offsets[type] + heap_offset,
|
|
|
|
|
|
sampler);
|
|
|
|
|
|
}
|
2022-04-14 14:34:19 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2022-03-28 09:41:17 +02:00
|
|
|
|
static void
|
2023-02-28 13:54:18 -08:00
|
|
|
|
dzn_descriptor_set_ptr_write_sampler_desc(struct dzn_device *device,
|
|
|
|
|
|
struct dzn_descriptor_set *set,
|
2022-04-14 11:42:52 +02:00
|
|
|
|
const struct dzn_descriptor_set_ptr *ptr,
|
|
|
|
|
|
const struct dzn_sampler *sampler)
|
2021-06-24 13:09:35 +02:00
|
|
|
|
{
|
|
|
|
|
|
D3D12_DESCRIPTOR_HEAP_TYPE type = D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER;
|
|
|
|
|
|
uint32_t heap_offset =
|
2023-03-02 13:06:22 -08:00
|
|
|
|
dzn_descriptor_set_ptr_get_heap_offset(set->layout, type, ptr, false, device->bindless);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
|
2023-02-28 13:54:18 -08:00
|
|
|
|
dzn_descriptor_set_write_sampler_desc(device, set, heap_offset, sampler);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2022-03-28 09:41:17 +02:00
|
|
|
|
static uint32_t
|
2023-03-02 19:58:09 -08:00
|
|
|
|
dzn_descriptor_set_ptr_get_buffer_idx(const struct dzn_descriptor_set_layout *layout,
|
|
|
|
|
|
const struct dzn_descriptor_set_ptr *ptr)
|
2021-06-24 13:09:35 +02:00
|
|
|
|
{
|
|
|
|
|
|
if (ptr->binding == ~0)
|
|
|
|
|
|
return ~0;
|
|
|
|
|
|
|
2023-03-02 19:58:09 -08:00
|
|
|
|
uint32_t base = layout->bindings[ptr->binding].buffer_idx;
|
2021-06-24 13:09:35 +02:00
|
|
|
|
|
|
|
|
|
|
if (base == ~0)
|
|
|
|
|
|
return ~0;
|
|
|
|
|
|
|
|
|
|
|
|
return base + ptr->elem;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-04-14 14:34:19 +02:00
|
|
|
|
static void
|
2023-03-02 19:58:09 -08:00
|
|
|
|
dzn_descriptor_set_write_dynamic_buffer_desc(struct dzn_device *device,
|
|
|
|
|
|
struct dzn_descriptor_set *set,
|
2022-04-14 14:34:19 +02:00
|
|
|
|
uint32_t dynamic_buffer_idx,
|
|
|
|
|
|
const struct dzn_buffer_desc *info)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (dynamic_buffer_idx == ~0)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
assert(dynamic_buffer_idx < set->layout->dynamic_buffers.count);
|
|
|
|
|
|
set->dynamic_buffers[dynamic_buffer_idx] = *info;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-03-28 09:41:17 +02:00
|
|
|
|
static void
|
2023-03-02 19:58:09 -08:00
|
|
|
|
dzn_descriptor_set_ptr_write_dynamic_buffer_desc(struct dzn_device *device,
|
|
|
|
|
|
struct dzn_descriptor_set *set,
|
2022-04-14 11:42:52 +02:00
|
|
|
|
const struct dzn_descriptor_set_ptr *ptr,
|
|
|
|
|
|
const struct dzn_buffer_desc *info)
|
2021-06-24 13:09:35 +02:00
|
|
|
|
{
|
|
|
|
|
|
uint32_t dynamic_buffer_idx =
|
2023-03-02 19:58:09 -08:00
|
|
|
|
dzn_descriptor_set_ptr_get_buffer_idx(set->layout, ptr);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
|
2023-03-02 19:58:09 -08:00
|
|
|
|
dzn_descriptor_set_write_dynamic_buffer_desc(device, set, dynamic_buffer_idx, info);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2022-03-28 09:41:17 +02:00
|
|
|
|
static VkDescriptorType
|
2022-04-14 11:37:45 +02:00
|
|
|
|
dzn_descriptor_set_ptr_get_vk_type(const struct dzn_descriptor_set_layout *layout,
|
2022-04-14 11:42:52 +02:00
|
|
|
|
const struct dzn_descriptor_set_ptr *ptr)
|
2021-06-24 13:09:35 +02:00
|
|
|
|
{
|
2022-04-14 11:37:45 +02:00
|
|
|
|
if (ptr->binding >= layout->binding_count)
|
2021-06-24 13:09:35 +02:00
|
|
|
|
return (VkDescriptorType)~0;
|
|
|
|
|
|
|
2022-04-14 11:37:45 +02:00
|
|
|
|
return layout->bindings[ptr->binding].type;
|
2021-06-24 13:09:35 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2022-03-28 09:41:17 +02:00
|
|
|
|
static void
|
2023-02-28 13:54:18 -08:00
|
|
|
|
dzn_descriptor_set_write_image_view_desc(struct dzn_device *device,
|
2023-03-02 09:58:47 -08:00
|
|
|
|
VkDescriptorType desc_type,
|
2023-02-28 13:54:18 -08:00
|
|
|
|
struct dzn_descriptor_set *set,
|
2022-04-14 14:34:19 +02:00
|
|
|
|
uint32_t heap_offset,
|
|
|
|
|
|
uint32_t alt_heap_offset,
|
|
|
|
|
|
bool cube_as_2darray,
|
|
|
|
|
|
const struct dzn_image_view *iview)
|
2021-06-24 13:09:35 +02:00
|
|
|
|
{
|
|
|
|
|
|
D3D12_DESCRIPTOR_HEAP_TYPE type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
|
2022-04-14 14:34:19 +02:00
|
|
|
|
|
2021-06-24 13:09:35 +02:00
|
|
|
|
if (heap_offset == ~0)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
2023-03-02 19:58:09 -08:00
|
|
|
|
if (device->bindless) {
|
|
|
|
|
|
dzn_bindless_descriptor_set_write_image_view_desc(set->pool->bindless.map,
|
|
|
|
|
|
desc_type,
|
|
|
|
|
|
set->heap_offsets[0] + heap_offset,
|
|
|
|
|
|
iview);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-03-02 09:58:47 -08:00
|
|
|
|
bool primary_writable = desc_type == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
|
|
|
|
|
|
|
2023-02-28 13:54:18 -08:00
|
|
|
|
dzn_descriptor_heap_write_image_view_desc(device,
|
|
|
|
|
|
&set->pool->heaps[type],
|
2021-06-24 13:09:35 +02:00
|
|
|
|
set->heap_offsets[type] + heap_offset,
|
2023-03-02 09:58:47 -08:00
|
|
|
|
primary_writable, cube_as_2darray,
|
2021-06-24 13:09:35 +02:00
|
|
|
|
iview);
|
|
|
|
|
|
|
2022-04-14 14:34:19 +02:00
|
|
|
|
if (alt_heap_offset != ~0) {
|
2023-03-02 09:58:47 -08:00
|
|
|
|
assert(primary_writable);
|
2023-02-28 13:54:18 -08:00
|
|
|
|
dzn_descriptor_heap_write_image_view_desc(device,
|
|
|
|
|
|
&set->pool->heaps[type],
|
2022-04-14 14:34:19 +02:00
|
|
|
|
set->heap_offsets[type] + alt_heap_offset,
|
2023-03-02 09:58:47 -08:00
|
|
|
|
false, cube_as_2darray,
|
2021-06-24 13:09:35 +02:00
|
|
|
|
iview);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-03-28 09:41:17 +02:00
|
|
|
|
static void
|
2023-02-28 13:54:18 -08:00
|
|
|
|
dzn_descriptor_set_ptr_write_image_view_desc(struct dzn_device *device,
|
2023-03-02 09:58:47 -08:00
|
|
|
|
VkDescriptorType desc_type,
|
2023-02-28 13:54:18 -08:00
|
|
|
|
struct dzn_descriptor_set *set,
|
2022-04-14 14:34:19 +02:00
|
|
|
|
const struct dzn_descriptor_set_ptr *ptr,
|
|
|
|
|
|
bool cube_as_2darray,
|
|
|
|
|
|
const struct dzn_image_view *iview)
|
2021-06-24 13:09:35 +02:00
|
|
|
|
{
|
|
|
|
|
|
D3D12_DESCRIPTOR_HEAP_TYPE type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
|
|
|
|
|
|
uint32_t heap_offset =
|
2023-03-02 13:06:22 -08:00
|
|
|
|
dzn_descriptor_set_ptr_get_heap_offset(set->layout, type, ptr, false, device->bindless);
|
2022-04-14 14:34:19 +02:00
|
|
|
|
uint32_t alt_heap_offset =
|
2023-03-02 13:06:22 -08:00
|
|
|
|
dzn_descriptor_set_ptr_get_heap_offset(set->layout, type, ptr, true, device->bindless);
|
2022-04-14 14:34:19 +02:00
|
|
|
|
|
2023-03-02 09:58:47 -08:00
|
|
|
|
dzn_descriptor_set_write_image_view_desc(device, desc_type, set, heap_offset, alt_heap_offset,
|
2022-04-14 14:34:19 +02:00
|
|
|
|
cube_as_2darray, iview);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
2023-02-28 13:54:18 -08:00
|
|
|
|
dzn_descriptor_set_write_buffer_view_desc(struct dzn_device *device,
|
2023-03-02 09:58:47 -08:00
|
|
|
|
VkDescriptorType desc_type,
|
2023-02-28 13:54:18 -08:00
|
|
|
|
struct dzn_descriptor_set *set,
|
2022-04-14 14:34:19 +02:00
|
|
|
|
uint32_t heap_offset,
|
|
|
|
|
|
uint32_t alt_heap_offset,
|
|
|
|
|
|
const struct dzn_buffer_view *bview)
|
|
|
|
|
|
{
|
2021-06-24 13:09:35 +02:00
|
|
|
|
if (heap_offset == ~0)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
2023-03-02 19:58:09 -08:00
|
|
|
|
if (device->bindless) {
|
|
|
|
|
|
dzn_bindless_descriptor_set_write_buffer_view_desc(set->pool->bindless.map,
|
|
|
|
|
|
desc_type,
|
|
|
|
|
|
set->heap_offsets[0] + heap_offset,
|
|
|
|
|
|
bview);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-04-14 14:34:19 +02:00
|
|
|
|
D3D12_DESCRIPTOR_HEAP_TYPE type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
|
2023-03-02 09:58:47 -08:00
|
|
|
|
bool primary_writable = desc_type == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
|
2022-04-14 14:34:19 +02:00
|
|
|
|
|
2023-02-28 13:54:18 -08:00
|
|
|
|
dzn_descriptor_heap_write_buffer_view_desc(device,
|
|
|
|
|
|
&set->pool->heaps[type],
|
2022-04-14 14:34:19 +02:00
|
|
|
|
set->heap_offsets[type] +
|
|
|
|
|
|
heap_offset,
|
2023-03-02 09:58:47 -08:00
|
|
|
|
primary_writable, bview);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
|
2022-04-14 14:34:19 +02:00
|
|
|
|
if (alt_heap_offset != ~0) {
|
2023-03-02 09:58:47 -08:00
|
|
|
|
assert(primary_writable);
|
2023-02-28 13:54:18 -08:00
|
|
|
|
dzn_descriptor_heap_write_buffer_view_desc(device,
|
|
|
|
|
|
&set->pool->heaps[type],
|
2022-04-14 14:34:19 +02:00
|
|
|
|
set->heap_offsets[type] +
|
|
|
|
|
|
alt_heap_offset,
|
2023-03-02 09:58:47 -08:00
|
|
|
|
false, bview);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-03-28 09:41:17 +02:00
|
|
|
|
static void
|
2023-02-28 13:54:18 -08:00
|
|
|
|
dzn_descriptor_set_ptr_write_buffer_view_desc(struct dzn_device *device,
|
2023-03-02 09:58:47 -08:00
|
|
|
|
VkDescriptorType desc_type,
|
2023-02-28 13:54:18 -08:00
|
|
|
|
struct dzn_descriptor_set *set,
|
2022-04-14 14:34:19 +02:00
|
|
|
|
const struct dzn_descriptor_set_ptr *ptr,
|
|
|
|
|
|
const struct dzn_buffer_view *bview)
|
2021-06-24 13:09:35 +02:00
|
|
|
|
{
|
|
|
|
|
|
D3D12_DESCRIPTOR_HEAP_TYPE type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
|
|
|
|
|
|
uint32_t heap_offset =
|
2023-03-02 13:06:22 -08:00
|
|
|
|
dzn_descriptor_set_ptr_get_heap_offset(set->layout, type, ptr, false, device->bindless);
|
2022-04-14 14:34:19 +02:00
|
|
|
|
uint32_t alt_heap_offset =
|
2023-03-02 13:06:22 -08:00
|
|
|
|
dzn_descriptor_set_ptr_get_heap_offset(set->layout, type, ptr, true, device->bindless);
|
2022-04-14 14:34:19 +02:00
|
|
|
|
|
2023-03-02 09:58:47 -08:00
|
|
|
|
dzn_descriptor_set_write_buffer_view_desc(device, desc_type, set, heap_offset, alt_heap_offset, bview);
|
2022-04-14 14:34:19 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
2023-02-28 13:54:18 -08:00
|
|
|
|
dzn_descriptor_set_write_buffer_desc(struct dzn_device *device,
|
2023-03-02 09:58:47 -08:00
|
|
|
|
VkDescriptorType desc_type,
|
2023-02-28 13:54:18 -08:00
|
|
|
|
struct dzn_descriptor_set *set,
|
2022-04-14 14:34:19 +02:00
|
|
|
|
uint32_t heap_offset,
|
|
|
|
|
|
uint32_t alt_heap_offset,
|
|
|
|
|
|
const struct dzn_buffer_desc *bdesc)
|
|
|
|
|
|
{
|
|
|
|
|
|
D3D12_DESCRIPTOR_HEAP_TYPE type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
|
2021-06-24 13:09:35 +02:00
|
|
|
|
if (heap_offset == ~0)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
2023-03-02 19:58:09 -08:00
|
|
|
|
if (device->bindless) {
|
|
|
|
|
|
dzn_bindless_descriptor_set_write_buffer_desc(device,
|
|
|
|
|
|
set->pool->bindless.map,
|
|
|
|
|
|
set->heap_offsets[0] + heap_offset,
|
|
|
|
|
|
bdesc);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-03-02 09:58:47 -08:00
|
|
|
|
bool primary_writable = desc_type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
|
|
|
|
|
|
|
2023-02-28 13:54:18 -08:00
|
|
|
|
dzn_descriptor_heap_write_buffer_desc(device, &set->pool->heaps[type],
|
2021-06-24 13:09:35 +02:00
|
|
|
|
set->heap_offsets[type] + heap_offset,
|
2023-03-02 09:58:47 -08:00
|
|
|
|
primary_writable, bdesc);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
|
2022-04-14 14:34:19 +02:00
|
|
|
|
if (alt_heap_offset != ~0) {
|
2023-03-02 09:58:47 -08:00
|
|
|
|
assert(primary_writable);
|
2023-02-28 13:54:18 -08:00
|
|
|
|
dzn_descriptor_heap_write_buffer_desc(device, &set->pool->heaps[type],
|
2022-04-14 14:34:19 +02:00
|
|
|
|
set->heap_offsets[type] +
|
|
|
|
|
|
alt_heap_offset,
|
2023-03-02 09:58:47 -08:00
|
|
|
|
false, bdesc);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-04-14 14:34:19 +02:00
|
|
|
|
static void
|
2023-02-28 13:54:18 -08:00
|
|
|
|
dzn_descriptor_set_ptr_write_buffer_desc(struct dzn_device *device,
|
2023-03-02 09:58:47 -08:00
|
|
|
|
VkDescriptorType desc_type,
|
2023-02-28 13:54:18 -08:00
|
|
|
|
struct dzn_descriptor_set *set,
|
2022-04-14 14:34:19 +02:00
|
|
|
|
const struct dzn_descriptor_set_ptr *ptr,
|
|
|
|
|
|
const struct dzn_buffer_desc *bdesc)
|
|
|
|
|
|
{
|
|
|
|
|
|
D3D12_DESCRIPTOR_HEAP_TYPE type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
|
|
|
|
|
|
uint32_t heap_offset =
|
2023-03-02 13:06:22 -08:00
|
|
|
|
dzn_descriptor_set_ptr_get_heap_offset(set->layout, type, ptr, false, device->bindless);
|
2022-04-14 14:34:19 +02:00
|
|
|
|
uint32_t alt_heap_offset =
|
2023-03-02 13:06:22 -08:00
|
|
|
|
dzn_descriptor_set_ptr_get_heap_offset(set->layout, type, ptr, true, device->bindless);
|
2022-04-14 14:34:19 +02:00
|
|
|
|
|
2023-03-02 09:58:47 -08:00
|
|
|
|
dzn_descriptor_set_write_buffer_desc(device, desc_type, set, heap_offset, alt_heap_offset, bdesc);
|
2022-04-14 14:34:19 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-03-02 19:58:09 -08:00
|
|
|
|
static VkResult
|
2022-04-05 17:41:20 +02:00
|
|
|
|
dzn_descriptor_set_init(struct dzn_descriptor_set *set,
|
|
|
|
|
|
struct dzn_device *device,
|
|
|
|
|
|
struct dzn_descriptor_pool *pool,
|
2023-03-02 15:14:29 -08:00
|
|
|
|
struct dzn_descriptor_set_layout *layout,
|
2023-03-17 08:18:45 -07:00
|
|
|
|
bool reuse,
|
|
|
|
|
|
uint32_t *variable_descriptor_count)
|
2021-06-24 13:09:35 +02:00
|
|
|
|
{
|
|
|
|
|
|
vk_object_base_init(&device->vk, &set->base, VK_OBJECT_TYPE_DESCRIPTOR_SET);
|
|
|
|
|
|
|
|
|
|
|
|
set->pool = pool;
|
|
|
|
|
|
set->layout = layout;
|
|
|
|
|
|
|
2023-03-02 15:14:29 -08:00
|
|
|
|
if (!reuse) {
|
|
|
|
|
|
dzn_foreach_pool_type(type) {
|
|
|
|
|
|
set->heap_offsets[type] = pool->free_offset[type];
|
2023-03-27 11:08:50 -07:00
|
|
|
|
if (device->bindless)
|
|
|
|
|
|
set->heap_offsets[type] = ALIGN(set->heap_offsets[type], 2);
|
2023-03-17 08:18:45 -07:00
|
|
|
|
set->heap_sizes[type] = layout->range_desc_count[type] + variable_descriptor_count[type];
|
2023-03-27 11:08:50 -07:00
|
|
|
|
set->pool->free_offset[type] = set->heap_offsets[type] + set->heap_sizes[type];
|
2023-03-02 15:14:29 -08:00
|
|
|
|
}
|
2021-06-24 13:09:35 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Pre-fill the immutable samplers */
|
|
|
|
|
|
if (layout->immutable_sampler_count) {
|
|
|
|
|
|
for (uint32_t b = 0; b < layout->binding_count; b++) {
|
|
|
|
|
|
bool has_samplers =
|
2022-06-08 06:57:18 -07:00
|
|
|
|
dzn_desc_type_has_sampler(layout->bindings[b].type);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
|
2023-03-13 12:43:45 -07:00
|
|
|
|
if (!has_samplers ||
|
|
|
|
|
|
layout->bindings[b].immutable_sampler_idx == ~0 ||
|
|
|
|
|
|
layout->bindings[b].immutable_sampler_idx == STATIC_SAMPLER_TAG)
|
2021-06-24 13:09:35 +02:00
|
|
|
|
continue;
|
|
|
|
|
|
|
2022-04-05 17:41:20 +02:00
|
|
|
|
struct dzn_descriptor_set_ptr ptr;
|
|
|
|
|
|
const struct dzn_sampler **sampler =
|
2021-06-24 13:09:35 +02:00
|
|
|
|
&layout->immutable_samplers[layout->bindings[b].immutable_sampler_idx];
|
2022-04-14 11:37:45 +02:00
|
|
|
|
for (dzn_descriptor_set_ptr_init(set->layout, &ptr, b, 0);
|
2024-01-26 11:15:20 -08:00
|
|
|
|
dzn_descriptor_set_ptr_is_valid(&ptr) && ptr.binding == b;
|
2022-04-14 11:37:45 +02:00
|
|
|
|
dzn_descriptor_set_ptr_move(set->layout, &ptr, 1)) {
|
2023-02-28 13:54:18 -08:00
|
|
|
|
dzn_descriptor_set_ptr_write_sampler_desc(device, set, &ptr, *sampler);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
sampler++;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2023-03-02 19:58:09 -08:00
|
|
|
|
return VK_SUCCESS;
|
2021-06-24 13:09:35 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
2022-04-05 17:41:20 +02:00
|
|
|
|
dzn_descriptor_set_finish(struct dzn_descriptor_set *set)
|
2021-06-24 13:09:35 +02:00
|
|
|
|
{
|
|
|
|
|
|
vk_object_base_finish(&set->base);
|
|
|
|
|
|
set->pool = NULL;
|
|
|
|
|
|
set->layout = NULL;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
2022-04-05 17:41:20 +02:00
|
|
|
|
dzn_descriptor_pool_destroy(struct dzn_descriptor_pool *pool,
|
2021-06-24 13:09:35 +02:00
|
|
|
|
const VkAllocationCallbacks *pAllocator)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!pool)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
2022-04-05 17:41:20 +02:00
|
|
|
|
struct dzn_device *device = container_of(pool->base.device, struct dzn_device, vk);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
|
2023-03-02 19:58:09 -08:00
|
|
|
|
if (device->bindless) {
|
|
|
|
|
|
if (pool->bindless.buf)
|
|
|
|
|
|
ID3D12Resource_Release(pool->bindless.buf);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
dzn_foreach_pool_type(type) {
|
|
|
|
|
|
if (pool->desc_count[type])
|
|
|
|
|
|
dzn_descriptor_heap_finish(&pool->heaps[type]);
|
|
|
|
|
|
}
|
2021-06-24 13:09:35 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
vk_object_base_finish(&pool->base);
|
|
|
|
|
|
vk_free2(&device->vk.alloc, pAllocator, pool);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static VkResult
|
2022-04-05 17:41:20 +02:00
|
|
|
|
dzn_descriptor_pool_create(struct dzn_device *device,
|
2021-06-24 13:09:35 +02:00
|
|
|
|
const VkDescriptorPoolCreateInfo *pCreateInfo,
|
|
|
|
|
|
const VkAllocationCallbacks *pAllocator,
|
|
|
|
|
|
VkDescriptorPool *out)
|
|
|
|
|
|
{
|
|
|
|
|
|
VK_MULTIALLOC(ma);
|
2022-04-05 17:41:20 +02:00
|
|
|
|
VK_MULTIALLOC_DECL(&ma, struct dzn_descriptor_pool, pool, 1);
|
|
|
|
|
|
VK_MULTIALLOC_DECL(&ma, struct dzn_descriptor_set, sets, pCreateInfo->maxSets);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
|
|
|
|
|
|
if (!vk_multialloc_zalloc2(&ma, &device->vk.alloc, pAllocator,
|
|
|
|
|
|
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT))
|
|
|
|
|
|
return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
|
|
|
|
|
|
|
|
|
|
|
|
pool->alloc = pAllocator ? *pAllocator : device->vk.alloc;
|
|
|
|
|
|
pool->sets = sets;
|
|
|
|
|
|
pool->set_count = pCreateInfo->maxSets;
|
|
|
|
|
|
|
|
|
|
|
|
vk_object_base_init(&device->vk, &pool->base, VK_OBJECT_TYPE_DESCRIPTOR_POOL);
|
|
|
|
|
|
|
|
|
|
|
|
for (uint32_t p = 0; p < pCreateInfo->poolSizeCount; p++) {
|
|
|
|
|
|
VkDescriptorType type = pCreateInfo->pPoolSizes[p].type;
|
|
|
|
|
|
uint32_t num_desc = pCreateInfo->pPoolSizes[p].descriptorCount;
|
|
|
|
|
|
|
2023-03-02 19:58:09 -08:00
|
|
|
|
if (device->bindless) {
|
|
|
|
|
|
switch (type) {
|
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
|
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
|
|
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
|
|
pool->desc_count[0] += num_desc;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
switch (type) {
|
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_SAMPLER:
|
|
|
|
|
|
pool->desc_count[D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER] += num_desc;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
|
|
|
|
|
|
pool->desc_count[D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV] += num_desc;
|
|
|
|
|
|
pool->desc_count[D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER] += num_desc;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
|
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
|
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
|
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
|
|
|
|
|
|
pool->desc_count[D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV] += num_desc;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
|
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
|
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
|
|
|
|
|
|
/* Reserve one UAV and one SRV slot for those. */
|
|
|
|
|
|
pool->desc_count[D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV] += num_desc * 2;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
|
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
|
|
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
|
|
unreachable("Unsupported desc type");
|
|
|
|
|
|
}
|
2021-06-24 13:09:35 +02:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-03-02 19:58:09 -08:00
|
|
|
|
if (device->bindless) {
|
|
|
|
|
|
if (pool->desc_count[0]) {
|
2023-03-27 11:08:50 -07:00
|
|
|
|
/* Include extra descriptors so that we can align each allocated descriptor set to a 16-byte boundary */
|
|
|
|
|
|
static_assert(D3D12_RAW_UAV_SRV_BYTE_ALIGNMENT / sizeof(struct dxil_spirv_bindless_entry) == 2,
|
|
|
|
|
|
"Ensure only one extra descriptor is needed to produce correct alignments");
|
|
|
|
|
|
uint32_t extra_descriptors = pool->set_count - 1;
|
|
|
|
|
|
pool->desc_count[0] += extra_descriptors;
|
|
|
|
|
|
|
2023-03-02 19:58:09 -08:00
|
|
|
|
/* Going to raw APIs to avoid allocating descriptors for this */
|
|
|
|
|
|
D3D12_RESOURCE_DESC buf_desc = {
|
|
|
|
|
|
.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER,
|
|
|
|
|
|
.Width = pool->desc_count[0] * sizeof(struct dxil_spirv_bindless_entry),
|
|
|
|
|
|
.Height = 1, .DepthOrArraySize = 1,
|
|
|
|
|
|
.MipLevels = 1, .SampleDesc = {.Count = 1},
|
|
|
|
|
|
.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR
|
|
|
|
|
|
};
|
|
|
|
|
|
D3D12_HEAP_PROPERTIES heap_props = { .Type = D3D12_HEAP_TYPE_UPLOAD };
|
|
|
|
|
|
if (FAILED(ID3D12Device_CreateCommittedResource(device->dev, &heap_props, 0, &buf_desc, D3D12_RESOURCE_STATE_GENERIC_READ,
|
|
|
|
|
|
NULL, &IID_ID3D12Resource, (void **)&pool->bindless.buf))) {
|
|
|
|
|
|
dzn_descriptor_pool_destroy(pool, pAllocator);
|
|
|
|
|
|
return vk_error(device, VK_ERROR_OUT_OF_DEVICE_MEMORY);
|
|
|
|
|
|
}
|
|
|
|
|
|
pool->bindless.gpuva = ID3D12Resource_GetGPUVirtualAddress(pool->bindless.buf);
|
|
|
|
|
|
ID3D12Resource_Map(pool->bindless.buf, 0, NULL, (void **)&pool->bindless.map);
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
dzn_foreach_pool_type(type) {
|
|
|
|
|
|
if (!pool->desc_count[type])
|
|
|
|
|
|
continue;
|
2021-06-24 13:09:35 +02:00
|
|
|
|
|
2023-03-02 19:58:09 -08:00
|
|
|
|
VkResult result =
|
|
|
|
|
|
dzn_descriptor_heap_init(&pool->heaps[type], device, type, pool->desc_count[type], false);
|
|
|
|
|
|
if (result != VK_SUCCESS) {
|
|
|
|
|
|
dzn_descriptor_pool_destroy(pool, pAllocator);
|
|
|
|
|
|
return result;
|
|
|
|
|
|
}
|
2021-06-24 13:09:35 +02:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
*out = dzn_descriptor_pool_to_handle(pool);
|
|
|
|
|
|
return VK_SUCCESS;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VKAPI_ATTR VkResult VKAPI_CALL
|
|
|
|
|
|
dzn_CreateDescriptorPool(VkDevice device,
|
|
|
|
|
|
const VkDescriptorPoolCreateInfo *pCreateInfo,
|
|
|
|
|
|
const VkAllocationCallbacks *pAllocator,
|
|
|
|
|
|
VkDescriptorPool *pDescriptorPool)
|
|
|
|
|
|
{
|
|
|
|
|
|
return dzn_descriptor_pool_create(dzn_device_from_handle(device),
|
|
|
|
|
|
pCreateInfo, pAllocator, pDescriptorPool);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VKAPI_ATTR void VKAPI_CALL
|
|
|
|
|
|
dzn_DestroyDescriptorPool(VkDevice device,
|
|
|
|
|
|
VkDescriptorPool descriptorPool,
|
|
|
|
|
|
const VkAllocationCallbacks *pAllocator)
|
|
|
|
|
|
{
|
2022-04-07 14:02:57 +02:00
|
|
|
|
dzn_descriptor_pool_destroy(dzn_descriptor_pool_from_handle(descriptorPool),
|
|
|
|
|
|
pAllocator);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VKAPI_ATTR VkResult VKAPI_CALL
|
|
|
|
|
|
dzn_ResetDescriptorPool(VkDevice device,
|
|
|
|
|
|
VkDescriptorPool descriptorPool,
|
|
|
|
|
|
VkDescriptorPoolResetFlags flags)
|
|
|
|
|
|
{
|
|
|
|
|
|
VK_FROM_HANDLE(dzn_descriptor_pool, pool, descriptorPool);
|
|
|
|
|
|
|
|
|
|
|
|
for (uint32_t s = 0; s < pool->set_count; s++)
|
|
|
|
|
|
dzn_descriptor_set_finish(&pool->sets[s]);
|
|
|
|
|
|
|
2023-03-02 15:14:29 -08:00
|
|
|
|
dzn_foreach_pool_type(type) {
|
2021-06-24 13:09:35 +02:00
|
|
|
|
pool->free_offset[type] = 0;
|
2023-03-02 15:14:29 -08:00
|
|
|
|
pool->used_desc_count[type] = 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
pool->used_set_count = 0;
|
2021-06-24 13:09:35 +02:00
|
|
|
|
|
|
|
|
|
|
return VK_SUCCESS;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2022-04-05 17:41:20 +02:00
|
|
|
|
dzn_descriptor_heap_pool_finish(struct dzn_descriptor_heap_pool *pool)
|
2021-06-24 13:09:35 +02:00
|
|
|
|
{
|
|
|
|
|
|
list_splicetail(&pool->active_heaps, &pool->free_heaps);
|
2022-04-05 17:41:20 +02:00
|
|
|
|
list_for_each_entry_safe(struct dzn_descriptor_heap_pool_entry, entry, &pool->free_heaps, link) {
|
2021-06-24 13:09:35 +02:00
|
|
|
|
list_del(&entry->link);
|
|
|
|
|
|
dzn_descriptor_heap_finish(&entry->heap);
|
|
|
|
|
|
vk_free(pool->alloc, entry);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2022-04-05 17:41:20 +02:00
|
|
|
|
dzn_descriptor_heap_pool_init(struct dzn_descriptor_heap_pool *pool,
|
|
|
|
|
|
struct dzn_device *device,
|
2021-06-24 13:09:35 +02:00
|
|
|
|
D3D12_DESCRIPTOR_HEAP_TYPE type,
|
|
|
|
|
|
bool shader_visible,
|
|
|
|
|
|
const VkAllocationCallbacks *alloc)
|
|
|
|
|
|
{
|
|
|
|
|
|
assert(!shader_visible ||
|
|
|
|
|
|
type == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV ||
|
|
|
|
|
|
type == D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER);
|
|
|
|
|
|
|
|
|
|
|
|
pool->alloc = alloc;
|
|
|
|
|
|
pool->type = type;
|
|
|
|
|
|
pool->shader_visible = shader_visible;
|
|
|
|
|
|
list_inithead(&pool->active_heaps);
|
|
|
|
|
|
list_inithead(&pool->free_heaps);
|
|
|
|
|
|
pool->offset = 0;
|
2022-03-25 17:08:50 +01:00
|
|
|
|
pool->desc_sz = ID3D12Device1_GetDescriptorHandleIncrementSize(device->dev, type);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VkResult
|
2022-04-05 17:41:20 +02:00
|
|
|
|
dzn_descriptor_heap_pool_alloc_slots(struct dzn_descriptor_heap_pool *pool,
|
|
|
|
|
|
struct dzn_device *device, uint32_t desc_count,
|
|
|
|
|
|
struct dzn_descriptor_heap **heap,
|
2021-06-24 13:09:35 +02:00
|
|
|
|
uint32_t *first_slot)
|
|
|
|
|
|
{
|
2022-04-05 17:41:20 +02:00
|
|
|
|
struct dzn_descriptor_heap *last_heap =
|
2021-06-24 13:09:35 +02:00
|
|
|
|
list_is_empty(&pool->active_heaps) ?
|
|
|
|
|
|
NULL :
|
2022-04-05 17:41:20 +02:00
|
|
|
|
&(list_last_entry(&pool->active_heaps, struct dzn_descriptor_heap_pool_entry, link)->heap);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
uint32_t last_heap_desc_count =
|
|
|
|
|
|
last_heap ? last_heap->desc_count : 0;
|
|
|
|
|
|
|
|
|
|
|
|
if (pool->offset + desc_count > last_heap_desc_count) {
|
|
|
|
|
|
uint32_t granularity =
|
|
|
|
|
|
(pool->type == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV ||
|
|
|
|
|
|
pool->type == D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER) ?
|
|
|
|
|
|
64 * 1024 : 4 * 1024;
|
|
|
|
|
|
uint32_t alloc_step = ALIGN_POT(desc_count * pool->desc_sz, granularity);
|
|
|
|
|
|
uint32_t heap_desc_count = MAX2(alloc_step / pool->desc_sz, 16);
|
2022-04-11 05:20:04 -07:00
|
|
|
|
|
|
|
|
|
|
/* Maximum of 2048 samplers per heap when shader_visible is true. */
|
|
|
|
|
|
if (pool->shader_visible &&
|
|
|
|
|
|
pool->type == D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER) {
|
2022-04-04 06:13:44 -07:00
|
|
|
|
assert(desc_count <= MAX_DESCS_PER_SAMPLER_HEAP);
|
|
|
|
|
|
heap_desc_count = MIN2(heap_desc_count, MAX_DESCS_PER_SAMPLER_HEAP);
|
2022-04-11 05:20:04 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
2022-04-05 17:41:20 +02:00
|
|
|
|
struct dzn_descriptor_heap_pool_entry *new_heap = NULL;
|
2021-06-24 13:09:35 +02:00
|
|
|
|
|
2022-04-05 17:41:20 +02:00
|
|
|
|
list_for_each_entry_safe(struct dzn_descriptor_heap_pool_entry, entry, &pool->free_heaps, link) {
|
2021-06-24 13:09:35 +02:00
|
|
|
|
if (entry->heap.desc_count >= heap_desc_count) {
|
|
|
|
|
|
new_heap = entry;
|
|
|
|
|
|
list_del(&entry->link);
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!new_heap) {
|
2022-04-08 11:11:21 +02:00
|
|
|
|
new_heap =
|
2021-06-24 13:09:35 +02:00
|
|
|
|
vk_zalloc(pool->alloc, sizeof(*new_heap), 8,
|
|
|
|
|
|
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
|
|
|
|
|
|
if (!new_heap)
|
|
|
|
|
|
return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
|
|
|
|
|
|
|
|
|
|
|
|
VkResult result =
|
|
|
|
|
|
dzn_descriptor_heap_init(&new_heap->heap, device, pool->type,
|
|
|
|
|
|
heap_desc_count, pool->shader_visible);
|
|
|
|
|
|
if (result != VK_SUCCESS) {
|
|
|
|
|
|
vk_free(&device->vk.alloc, new_heap);
|
|
|
|
|
|
return result;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
list_addtail(&new_heap->link, &pool->active_heaps);
|
|
|
|
|
|
pool->offset = 0;
|
|
|
|
|
|
last_heap = &new_heap->heap;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
*heap = last_heap;
|
|
|
|
|
|
*first_slot = pool->offset;
|
|
|
|
|
|
pool->offset += desc_count;
|
|
|
|
|
|
return VK_SUCCESS;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2022-04-05 17:41:20 +02:00
|
|
|
|
dzn_descriptor_heap_pool_reset(struct dzn_descriptor_heap_pool *pool)
|
2021-06-24 13:09:35 +02:00
|
|
|
|
{
|
|
|
|
|
|
pool->offset = 0;
|
|
|
|
|
|
list_splicetail(&pool->active_heaps, &pool->free_heaps);
|
2022-05-15 11:46:05 +02:00
|
|
|
|
list_inithead(&pool->active_heaps);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VKAPI_ATTR VkResult VKAPI_CALL
|
|
|
|
|
|
dzn_AllocateDescriptorSets(VkDevice dev,
|
|
|
|
|
|
const VkDescriptorSetAllocateInfo *pAllocateInfo,
|
|
|
|
|
|
VkDescriptorSet *pDescriptorSets)
|
|
|
|
|
|
{
|
|
|
|
|
|
VK_FROM_HANDLE(dzn_descriptor_pool, pool, pAllocateInfo->descriptorPool);
|
|
|
|
|
|
VK_FROM_HANDLE(dzn_device, device, dev);
|
|
|
|
|
|
|
2023-03-17 08:18:45 -07:00
|
|
|
|
const struct VkDescriptorSetVariableDescriptorCountAllocateInfo *variable_counts =
|
|
|
|
|
|
vk_find_struct_const(pAllocateInfo->pNext, DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO);
|
|
|
|
|
|
|
2021-06-24 13:09:35 +02:00
|
|
|
|
uint32_t set_idx = 0;
|
2023-03-02 15:14:29 -08:00
|
|
|
|
for (unsigned i = 0; i < pAllocateInfo->descriptorSetCount; i++) {
|
2021-06-24 13:09:35 +02:00
|
|
|
|
VK_FROM_HANDLE(dzn_descriptor_set_layout, layout, pAllocateInfo->pSetLayouts[i]);
|
2023-03-17 08:18:45 -07:00
|
|
|
|
uint32_t additional_desc_counts[NUM_POOL_TYPES];
|
|
|
|
|
|
additional_desc_counts[D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV] =
|
|
|
|
|
|
variable_counts && variable_counts->descriptorSetCount ?
|
|
|
|
|
|
variable_counts->pDescriptorCounts[i] : 0;
|
|
|
|
|
|
additional_desc_counts[D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER] = 0;
|
|
|
|
|
|
uint32_t total_desc_count[NUM_POOL_TYPES];
|
2021-06-24 13:09:35 +02:00
|
|
|
|
|
|
|
|
|
|
dzn_foreach_pool_type(type) {
|
2023-03-17 08:18:45 -07:00
|
|
|
|
total_desc_count[type] = layout->range_desc_count[type] + additional_desc_counts[type];
|
|
|
|
|
|
if (pool->used_desc_count[type] + total_desc_count[type] > pool->desc_count[type]) {
|
2021-06-24 13:09:35 +02:00
|
|
|
|
dzn_FreeDescriptorSets(dev, pAllocateInfo->descriptorPool, i, pDescriptorSets);
|
|
|
|
|
|
return vk_error(device, VK_ERROR_OUT_OF_POOL_MEMORY);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-04-05 17:41:20 +02:00
|
|
|
|
struct dzn_descriptor_set *set = NULL;
|
2023-03-02 15:14:29 -08:00
|
|
|
|
bool is_reuse = false;
|
|
|
|
|
|
bool found_any_unused = false;
|
2021-06-24 13:09:35 +02:00
|
|
|
|
for (; set_idx < pool->set_count; set_idx++) {
|
2023-03-02 15:14:29 -08:00
|
|
|
|
/* Find a free set */
|
2021-06-24 13:09:35 +02:00
|
|
|
|
if (!pool->sets[set_idx].layout) {
|
2023-03-02 15:14:29 -08:00
|
|
|
|
/* Found one. If it's re-use, check if it has enough space */
|
|
|
|
|
|
if (set_idx < pool->used_set_count) {
|
|
|
|
|
|
is_reuse = true;
|
|
|
|
|
|
found_any_unused = true;
|
|
|
|
|
|
dzn_foreach_pool_type(type) {
|
2023-03-17 08:18:45 -07:00
|
|
|
|
if (pool->sets[set_idx].heap_sizes[type] < total_desc_count[type]) {
|
2023-03-02 15:14:29 -08:00
|
|
|
|
/* No, not enough space */
|
|
|
|
|
|
is_reuse = false;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!is_reuse)
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
2021-06-24 13:09:35 +02:00
|
|
|
|
set = &pool->sets[set_idx];
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-03-02 15:14:29 -08:00
|
|
|
|
/* Either all occupied, or no free space large enough */
|
|
|
|
|
|
if (!set) {
|
|
|
|
|
|
dzn_FreeDescriptorSets(dev, pAllocateInfo->descriptorPool, i, pDescriptorSets);
|
|
|
|
|
|
return vk_error(device, found_any_unused ? VK_ERROR_FRAGMENTED_POOL : VK_ERROR_OUT_OF_POOL_MEMORY);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Couldn't find one for re-use, check if there's enough space at the end */
|
|
|
|
|
|
if (!is_reuse) {
|
|
|
|
|
|
dzn_foreach_pool_type(type) {
|
2023-03-17 08:18:45 -07:00
|
|
|
|
if (pool->free_offset[type] + total_desc_count[type] > pool->desc_count[type]) {
|
2023-03-02 15:14:29 -08:00
|
|
|
|
dzn_FreeDescriptorSets(dev, pAllocateInfo->descriptorPool, i, pDescriptorSets);
|
|
|
|
|
|
return vk_error(device, VK_ERROR_FRAGMENTED_POOL);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-03-17 08:18:45 -07:00
|
|
|
|
VkResult result = dzn_descriptor_set_init(set, device, pool, layout, is_reuse, additional_desc_counts);
|
2023-03-02 19:58:09 -08:00
|
|
|
|
if (result != VK_SUCCESS) {
|
|
|
|
|
|
dzn_FreeDescriptorSets(dev, pAllocateInfo->descriptorPool, i, pDescriptorSets);
|
|
|
|
|
|
return result;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-03-02 15:14:29 -08:00
|
|
|
|
pool->used_set_count = MAX2(pool->used_set_count, set_idx + 1);
|
|
|
|
|
|
dzn_foreach_pool_type(type)
|
2023-03-17 08:18:45 -07:00
|
|
|
|
pool->used_desc_count[type] += total_desc_count[type];
|
2021-06-24 13:09:35 +02:00
|
|
|
|
pDescriptorSets[i] = dzn_descriptor_set_to_handle(set);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return VK_SUCCESS;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VKAPI_ATTR VkResult VKAPI_CALL
|
|
|
|
|
|
dzn_FreeDescriptorSets(VkDevice dev,
|
|
|
|
|
|
VkDescriptorPool descriptorPool,
|
|
|
|
|
|
uint32_t count,
|
|
|
|
|
|
const VkDescriptorSet *pDescriptorSets)
|
|
|
|
|
|
{
|
|
|
|
|
|
VK_FROM_HANDLE(dzn_descriptor_pool, pool, descriptorPool);
|
|
|
|
|
|
|
|
|
|
|
|
for (uint32_t s = 0; s < count; s++) {
|
|
|
|
|
|
VK_FROM_HANDLE(dzn_descriptor_set, set, pDescriptorSets[s]);
|
|
|
|
|
|
|
|
|
|
|
|
if (!set)
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
|
|
assert(set->pool == pool);
|
2023-03-02 15:14:29 -08:00
|
|
|
|
dzn_foreach_pool_type(type)
|
2023-03-17 08:18:45 -07:00
|
|
|
|
pool->used_desc_count[type] -= set->heap_sizes[type];
|
2021-06-24 13:09:35 +02:00
|
|
|
|
|
|
|
|
|
|
dzn_descriptor_set_finish(set);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-03-02 15:14:29 -08:00
|
|
|
|
pool->used_set_count = 0;
|
2021-06-24 13:09:35 +02:00
|
|
|
|
dzn_foreach_pool_type(type)
|
|
|
|
|
|
pool->free_offset[type] = 0;
|
|
|
|
|
|
|
|
|
|
|
|
for (uint32_t s = 0; s < pool->set_count; s++) {
|
2022-04-05 17:41:20 +02:00
|
|
|
|
const struct dzn_descriptor_set *set = &pool->sets[s];
|
2021-06-24 13:09:35 +02:00
|
|
|
|
|
|
|
|
|
|
if (set->layout) {
|
2023-03-02 15:14:29 -08:00
|
|
|
|
pool->used_set_count = MAX2(pool->used_set_count, s + 1);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
dzn_foreach_pool_type (type) {
|
|
|
|
|
|
pool->free_offset[type] =
|
|
|
|
|
|
MAX2(pool->free_offset[type],
|
|
|
|
|
|
set->heap_offsets[type] +
|
2023-03-02 15:14:29 -08:00
|
|
|
|
set->heap_sizes[type]);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return VK_SUCCESS;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
2023-02-28 13:54:18 -08:00
|
|
|
|
dzn_descriptor_set_write(struct dzn_device *device,
|
|
|
|
|
|
const VkWriteDescriptorSet *pDescriptorWrite)
|
2021-06-24 13:09:35 +02:00
|
|
|
|
{
|
|
|
|
|
|
VK_FROM_HANDLE(dzn_descriptor_set, set, pDescriptorWrite->dstSet);
|
|
|
|
|
|
|
2022-04-05 17:41:20 +02:00
|
|
|
|
struct dzn_descriptor_set_ptr ptr;
|
2021-06-24 13:09:35 +02:00
|
|
|
|
|
2022-04-14 11:37:45 +02:00
|
|
|
|
dzn_descriptor_set_ptr_init(set->layout, &ptr,
|
2021-06-24 13:09:35 +02:00
|
|
|
|
pDescriptorWrite->dstBinding,
|
|
|
|
|
|
pDescriptorWrite->dstArrayElement);
|
|
|
|
|
|
uint32_t desc_count = pDescriptorWrite->descriptorCount;
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t d = 0;
|
|
|
|
|
|
bool cube_as_2darray =
|
|
|
|
|
|
pDescriptorWrite->descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
|
|
|
|
|
|
|
|
|
|
|
|
switch (pDescriptorWrite->descriptorType) {
|
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_SAMPLER:
|
|
|
|
|
|
for (; dzn_descriptor_set_ptr_is_valid(&ptr) && d < desc_count;
|
2022-04-14 11:37:45 +02:00
|
|
|
|
dzn_descriptor_set_ptr_move(set->layout, &ptr, 1)) {
|
|
|
|
|
|
assert(dzn_descriptor_set_ptr_get_vk_type(set->layout, &ptr) == pDescriptorWrite->descriptorType);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
const VkDescriptorImageInfo *pImageInfo = pDescriptorWrite->pImageInfo + d;
|
|
|
|
|
|
VK_FROM_HANDLE(dzn_sampler, sampler, pImageInfo->sampler);
|
|
|
|
|
|
|
|
|
|
|
|
if (sampler)
|
2023-02-28 13:54:18 -08:00
|
|
|
|
dzn_descriptor_set_ptr_write_sampler_desc(device, set, &ptr, sampler);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
|
|
|
|
|
|
d++;
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
|
|
|
|
|
|
for (; dzn_descriptor_set_ptr_is_valid(&ptr) && d < desc_count;
|
2022-04-14 11:37:45 +02:00
|
|
|
|
dzn_descriptor_set_ptr_move(set->layout, &ptr, 1)) {
|
|
|
|
|
|
assert(dzn_descriptor_set_ptr_get_vk_type(set->layout, &ptr) == pDescriptorWrite->descriptorType);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
const VkDescriptorImageInfo *pImageInfo = pDescriptorWrite->pImageInfo + d;
|
|
|
|
|
|
VK_FROM_HANDLE(dzn_sampler, sampler, pImageInfo->sampler);
|
|
|
|
|
|
VK_FROM_HANDLE(dzn_image_view, iview, pImageInfo->imageView);
|
|
|
|
|
|
|
|
|
|
|
|
if (sampler)
|
2023-02-28 13:54:18 -08:00
|
|
|
|
dzn_descriptor_set_ptr_write_sampler_desc(device, set, &ptr, sampler);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
|
|
|
|
|
|
if (iview)
|
2023-03-02 09:58:47 -08:00
|
|
|
|
dzn_descriptor_set_ptr_write_image_view_desc(device, pDescriptorWrite->descriptorType,
|
|
|
|
|
|
set, &ptr, cube_as_2darray, iview);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
|
|
|
|
|
|
d++;
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
|
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
|
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
|
|
|
|
|
|
for (; dzn_descriptor_set_ptr_is_valid(&ptr) && d < desc_count;
|
2022-04-14 11:37:45 +02:00
|
|
|
|
dzn_descriptor_set_ptr_move(set->layout, &ptr, 1)) {
|
|
|
|
|
|
assert(dzn_descriptor_set_ptr_get_vk_type(set->layout, &ptr) == pDescriptorWrite->descriptorType);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
const VkDescriptorImageInfo *pImageInfo = pDescriptorWrite->pImageInfo + d;
|
|
|
|
|
|
VK_FROM_HANDLE(dzn_image_view, iview, pImageInfo->imageView);
|
|
|
|
|
|
|
|
|
|
|
|
if (iview)
|
2023-03-02 09:58:47 -08:00
|
|
|
|
dzn_descriptor_set_ptr_write_image_view_desc(device, pDescriptorWrite->descriptorType,
|
|
|
|
|
|
set, &ptr, cube_as_2darray, iview);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
|
|
|
|
|
|
d++;
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
|
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
|
|
|
|
|
|
for (; dzn_descriptor_set_ptr_is_valid(&ptr) && d < desc_count;
|
2022-04-14 11:37:45 +02:00
|
|
|
|
dzn_descriptor_set_ptr_move(set->layout, &ptr, 1)) {
|
|
|
|
|
|
assert(dzn_descriptor_set_ptr_get_vk_type(set->layout, &ptr) == pDescriptorWrite->descriptorType);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
const VkDescriptorBufferInfo *binfo = &pDescriptorWrite->pBufferInfo[d];
|
2022-04-06 15:09:09 +02:00
|
|
|
|
struct dzn_buffer_desc desc = {
|
2021-06-24 13:09:35 +02:00
|
|
|
|
pDescriptorWrite->descriptorType,
|
|
|
|
|
|
dzn_buffer_from_handle(binfo->buffer),
|
dzn: Re-design custom buffer descriptors
Previously, custom buffer descriptors were owned by a descriptor set. Now,
custom buffer descriptors are owned by the buffer. Additionally, we respect
the app-provided sizes when they're smaller than the buffer size, even if
robustness is not enabled, so that size queries work correctly.
This new design fixes several issues:
* Descriptor set copies were broken when they involved custom descriptors,
because the original descriptor set owned the lifetime of the custom
descriptor, the new one was just borrowing it. If those lifetimes didn't
line up, problems would arise.
* A single buffer with the same sub-view placed in multiplel descriptor sets
would allocate multiple slots, when it only really needed one.
* Custom buffer descriptors now lower the base offset to 0 to allow merging
multiple overlapping (ending at the same upper bound) descriptors. Since
the shader is already doing an offset add, making it nonzero is free.
* Dynamic buffer descriptors were incorrect before. The size passed into the
descriptor set is supposed to be the size from the *dynamic* offset, not the
size from the static offset. By allocating/populating the descriptor when
placed into the set, it prevented larger offsets from working correctly. This
buffer-owned design prevents cmdbufs from having to own lifetime of custom
descriptors.
Fixes dEQP-VK.ssbo.unsized_array_length.float_offset_explicit_size
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/22639>
2023-04-21 11:48:16 -07:00
|
|
|
|
binfo->range, binfo->offset
|
2022-03-25 15:09:00 +01:00
|
|
|
|
};
|
2021-06-24 13:09:35 +02:00
|
|
|
|
|
|
|
|
|
|
if (desc.buffer)
|
2023-03-02 09:58:47 -08:00
|
|
|
|
dzn_descriptor_set_ptr_write_buffer_desc(device, pDescriptorWrite->descriptorType, set, &ptr, &desc);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
|
|
|
|
|
|
d++;
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
|
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
|
|
|
|
|
|
for (; dzn_descriptor_set_ptr_is_valid(&ptr) && d < desc_count;
|
2022-04-14 11:37:45 +02:00
|
|
|
|
dzn_descriptor_set_ptr_move(set->layout, &ptr, 1)) {
|
|
|
|
|
|
assert(dzn_descriptor_set_ptr_get_vk_type(set->layout, &ptr) == pDescriptorWrite->descriptorType);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
const VkDescriptorBufferInfo *binfo = &pDescriptorWrite->pBufferInfo[d];
|
2022-04-06 15:09:09 +02:00
|
|
|
|
struct dzn_buffer_desc desc = {
|
2021-06-24 13:09:35 +02:00
|
|
|
|
pDescriptorWrite->descriptorType,
|
|
|
|
|
|
dzn_buffer_from_handle(binfo->buffer),
|
dzn: Re-design custom buffer descriptors
Previously, custom buffer descriptors were owned by a descriptor set. Now,
custom buffer descriptors are owned by the buffer. Additionally, we respect
the app-provided sizes when they're smaller than the buffer size, even if
robustness is not enabled, so that size queries work correctly.
This new design fixes several issues:
* Descriptor set copies were broken when they involved custom descriptors,
because the original descriptor set owned the lifetime of the custom
descriptor, the new one was just borrowing it. If those lifetimes didn't
line up, problems would arise.
* A single buffer with the same sub-view placed in multiplel descriptor sets
would allocate multiple slots, when it only really needed one.
* Custom buffer descriptors now lower the base offset to 0 to allow merging
multiple overlapping (ending at the same upper bound) descriptors. Since
the shader is already doing an offset add, making it nonzero is free.
* Dynamic buffer descriptors were incorrect before. The size passed into the
descriptor set is supposed to be the size from the *dynamic* offset, not the
size from the static offset. By allocating/populating the descriptor when
placed into the set, it prevented larger offsets from working correctly. This
buffer-owned design prevents cmdbufs from having to own lifetime of custom
descriptors.
Fixes dEQP-VK.ssbo.unsized_array_length.float_offset_explicit_size
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/22639>
2023-04-21 11:48:16 -07:00
|
|
|
|
binfo->range, binfo->offset
|
2022-04-20 12:50:14 +02:00
|
|
|
|
};
|
2021-06-24 13:09:35 +02:00
|
|
|
|
|
|
|
|
|
|
if (desc.buffer)
|
2023-03-02 19:58:09 -08:00
|
|
|
|
dzn_descriptor_set_ptr_write_dynamic_buffer_desc(device, set, &ptr, &desc);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
|
|
|
|
|
|
d++;
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
|
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
|
|
|
|
|
|
for (; dzn_descriptor_set_ptr_is_valid(&ptr) && d < desc_count;
|
2022-04-14 11:37:45 +02:00
|
|
|
|
dzn_descriptor_set_ptr_move(set->layout, &ptr, 1)) {
|
|
|
|
|
|
assert(dzn_descriptor_set_ptr_get_vk_type(set->layout, &ptr) == pDescriptorWrite->descriptorType);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
VK_FROM_HANDLE(dzn_buffer_view, bview, pDescriptorWrite->pTexelBufferView[d]);
|
|
|
|
|
|
|
|
|
|
|
|
if (bview)
|
2023-03-02 09:58:47 -08:00
|
|
|
|
dzn_descriptor_set_ptr_write_buffer_view_desc(device, pDescriptorWrite->descriptorType,
|
|
|
|
|
|
set, &ptr, bview);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
|
|
|
|
|
|
d++;
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
|
unreachable("invalid descriptor type");
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
assert(d == pDescriptorWrite->descriptorCount);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
2023-02-28 13:54:18 -08:00
|
|
|
|
dzn_descriptor_set_copy(struct dzn_device *device,
|
|
|
|
|
|
const VkCopyDescriptorSet *pDescriptorCopy)
|
2021-06-24 13:09:35 +02:00
|
|
|
|
{
|
|
|
|
|
|
VK_FROM_HANDLE(dzn_descriptor_set, src_set, pDescriptorCopy->srcSet);
|
|
|
|
|
|
VK_FROM_HANDLE(dzn_descriptor_set, dst_set, pDescriptorCopy->dstSet);
|
2022-04-05 17:41:20 +02:00
|
|
|
|
struct dzn_descriptor_set_ptr src_ptr, dst_ptr;
|
2021-06-24 13:09:35 +02:00
|
|
|
|
|
2022-04-14 11:37:45 +02:00
|
|
|
|
dzn_descriptor_set_ptr_init(src_set->layout, &src_ptr,
|
2021-06-24 13:09:35 +02:00
|
|
|
|
pDescriptorCopy->srcBinding,
|
|
|
|
|
|
pDescriptorCopy->srcArrayElement);
|
2022-04-14 11:37:45 +02:00
|
|
|
|
dzn_descriptor_set_ptr_init(dst_set->layout, &dst_ptr,
|
2021-06-24 13:09:35 +02:00
|
|
|
|
pDescriptorCopy->dstBinding,
|
|
|
|
|
|
pDescriptorCopy->dstArrayElement);
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t copied_count = 0;
|
|
|
|
|
|
|
|
|
|
|
|
while (dzn_descriptor_set_ptr_is_valid(&src_ptr) &&
|
2022-04-08 12:02:56 -07:00
|
|
|
|
dzn_descriptor_set_ptr_is_valid(&dst_ptr) &&
|
|
|
|
|
|
copied_count < pDescriptorCopy->descriptorCount) {
|
2021-06-24 13:09:35 +02:00
|
|
|
|
VkDescriptorType src_type =
|
2022-04-14 11:37:45 +02:00
|
|
|
|
dzn_descriptor_set_ptr_get_vk_type(src_set->layout, &src_ptr);
|
2022-06-30 20:49:43 -07:00
|
|
|
|
ASSERTED VkDescriptorType dst_type =
|
2022-04-14 11:37:45 +02:00
|
|
|
|
dzn_descriptor_set_ptr_get_vk_type(dst_set->layout, &dst_ptr);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
|
|
|
|
|
|
assert(src_type == dst_type);
|
|
|
|
|
|
uint32_t count =
|
2022-04-14 11:37:45 +02:00
|
|
|
|
MIN2(dzn_descriptor_set_remaining_descs_in_binding(src_set->layout, &src_ptr),
|
|
|
|
|
|
dzn_descriptor_set_remaining_descs_in_binding(dst_set->layout, &dst_ptr));
|
2021-06-24 13:09:35 +02:00
|
|
|
|
|
|
|
|
|
|
if (src_type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC ||
|
|
|
|
|
|
src_type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC) {
|
|
|
|
|
|
uint32_t src_idx =
|
2023-03-02 19:58:09 -08:00
|
|
|
|
dzn_descriptor_set_ptr_get_buffer_idx(src_set->layout, &src_ptr);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
uint32_t dst_idx =
|
2023-03-02 19:58:09 -08:00
|
|
|
|
dzn_descriptor_set_ptr_get_buffer_idx(dst_set->layout, &dst_ptr);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
|
|
|
|
|
|
memcpy(&dst_set->dynamic_buffers[dst_idx],
|
|
|
|
|
|
&src_set->dynamic_buffers[src_idx],
|
|
|
|
|
|
sizeof(*dst_set->dynamic_buffers) * count);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
dzn_foreach_pool_type(type) {
|
|
|
|
|
|
uint32_t src_heap_offset =
|
2023-03-02 13:06:22 -08:00
|
|
|
|
dzn_descriptor_set_ptr_get_heap_offset(src_set->layout, type, &src_ptr, false, device->bindless);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
uint32_t dst_heap_offset =
|
2023-03-02 13:06:22 -08:00
|
|
|
|
dzn_descriptor_set_ptr_get_heap_offset(dst_set->layout, type, &dst_ptr, false, device->bindless);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
|
|
|
|
|
|
if (src_heap_offset == ~0) {
|
|
|
|
|
|
assert(dst_heap_offset == ~0);
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-03-02 19:58:09 -08:00
|
|
|
|
src_heap_offset += src_set->heap_offsets[type];
|
|
|
|
|
|
dst_heap_offset += dst_set->heap_offsets[type];
|
|
|
|
|
|
|
|
|
|
|
|
if (device->bindless) {
|
dzn: Re-design custom buffer descriptors
Previously, custom buffer descriptors were owned by a descriptor set. Now,
custom buffer descriptors are owned by the buffer. Additionally, we respect
the app-provided sizes when they're smaller than the buffer size, even if
robustness is not enabled, so that size queries work correctly.
This new design fixes several issues:
* Descriptor set copies were broken when they involved custom descriptors,
because the original descriptor set owned the lifetime of the custom
descriptor, the new one was just borrowing it. If those lifetimes didn't
line up, problems would arise.
* A single buffer with the same sub-view placed in multiplel descriptor sets
would allocate multiple slots, when it only really needed one.
* Custom buffer descriptors now lower the base offset to 0 to allow merging
multiple overlapping (ending at the same upper bound) descriptors. Since
the shader is already doing an offset add, making it nonzero is free.
* Dynamic buffer descriptors were incorrect before. The size passed into the
descriptor set is supposed to be the size from the *dynamic* offset, not the
size from the static offset. By allocating/populating the descriptor when
placed into the set, it prevented larger offsets from working correctly. This
buffer-owned design prevents cmdbufs from having to own lifetime of custom
descriptors.
Fixes dEQP-VK.ssbo.unsized_array_length.float_offset_explicit_size
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/22639>
2023-04-21 11:48:16 -07:00
|
|
|
|
memcpy((void *)&dst_set->pool->bindless.map[dst_heap_offset],
|
|
|
|
|
|
(const void *)&src_set->pool->bindless.map[src_heap_offset],
|
2023-03-02 19:58:09 -08:00
|
|
|
|
sizeof(src_set->pool->bindless.map[0]) * count);
|
|
|
|
|
|
/* There's never a reason to loop and memcpy again for bindless */
|
|
|
|
|
|
break;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
dzn_descriptor_heap_copy(device,
|
|
|
|
|
|
&dst_set->pool->heaps[type],
|
|
|
|
|
|
dst_heap_offset,
|
|
|
|
|
|
&src_set->pool->heaps[type],
|
|
|
|
|
|
src_heap_offset,
|
|
|
|
|
|
count, type);
|
|
|
|
|
|
}
|
2021-06-24 13:09:35 +02:00
|
|
|
|
|
2023-03-02 13:06:22 -08:00
|
|
|
|
if (dzn_descriptor_type_depends_on_shader_usage(src_type, device->bindless)) {
|
2023-05-24 11:11:58 -07:00
|
|
|
|
src_heap_offset = src_set->heap_offsets[type] +
|
2023-03-02 13:06:22 -08:00
|
|
|
|
dzn_descriptor_set_ptr_get_heap_offset(src_set->layout, type, &src_ptr, true, device->bindless);
|
2023-05-24 11:11:58 -07:00
|
|
|
|
dst_heap_offset = dst_set->heap_offsets[type] +
|
2023-03-02 13:06:22 -08:00
|
|
|
|
dzn_descriptor_set_ptr_get_heap_offset(dst_set->layout, type, &dst_ptr, true, device->bindless);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
assert(src_heap_offset != ~0);
|
|
|
|
|
|
assert(dst_heap_offset != ~0);
|
2023-02-28 13:54:18 -08:00
|
|
|
|
dzn_descriptor_heap_copy(device,
|
|
|
|
|
|
&dst_set->pool->heaps[type],
|
2023-03-02 19:58:09 -08:00
|
|
|
|
dst_heap_offset,
|
2021-06-24 13:09:35 +02:00
|
|
|
|
&src_set->pool->heaps[type],
|
2023-03-02 19:58:09 -08:00
|
|
|
|
src_heap_offset,
|
2023-03-01 13:59:33 -08:00
|
|
|
|
count, type);
|
2022-04-20 12:50:14 +02:00
|
|
|
|
}
|
2021-06-24 13:09:35 +02:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-04-14 11:37:45 +02:00
|
|
|
|
dzn_descriptor_set_ptr_move(src_set->layout, &src_ptr, count);
|
|
|
|
|
|
dzn_descriptor_set_ptr_move(dst_set->layout, &dst_ptr, count);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
copied_count += count;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
assert(copied_count == pDescriptorCopy->descriptorCount);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VKAPI_ATTR void VKAPI_CALL
|
|
|
|
|
|
dzn_UpdateDescriptorSets(VkDevice _device,
|
|
|
|
|
|
uint32_t descriptorWriteCount,
|
|
|
|
|
|
const VkWriteDescriptorSet *pDescriptorWrites,
|
|
|
|
|
|
uint32_t descriptorCopyCount,
|
|
|
|
|
|
const VkCopyDescriptorSet *pDescriptorCopies)
|
|
|
|
|
|
{
|
2023-02-28 13:54:18 -08:00
|
|
|
|
VK_FROM_HANDLE(dzn_device, device, _device);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
for (unsigned i = 0; i < descriptorWriteCount; i++)
|
2023-02-28 13:54:18 -08:00
|
|
|
|
dzn_descriptor_set_write(device, &pDescriptorWrites[i]);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
|
|
|
|
|
|
for (unsigned i = 0; i < descriptorCopyCount; i++)
|
2023-02-28 13:54:18 -08:00
|
|
|
|
dzn_descriptor_set_copy(device, &pDescriptorCopies[i]);
|
2021-06-24 13:09:35 +02:00
|
|
|
|
}
|
2022-03-28 10:12:57 +02:00
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
|
dzn_descriptor_update_template_destroy(struct dzn_descriptor_update_template *templ,
|
|
|
|
|
|
const VkAllocationCallbacks *alloc)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!templ)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
struct dzn_device *device =
|
|
|
|
|
|
container_of(templ->base.device, struct dzn_device, vk);
|
|
|
|
|
|
|
|
|
|
|
|
vk_object_base_finish(&templ->base);
|
|
|
|
|
|
vk_free2(&device->vk.alloc, alloc, templ);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static VkResult
|
|
|
|
|
|
dzn_descriptor_update_template_create(struct dzn_device *device,
|
|
|
|
|
|
const VkDescriptorUpdateTemplateCreateInfo *info,
|
|
|
|
|
|
const VkAllocationCallbacks *alloc,
|
|
|
|
|
|
VkDescriptorUpdateTemplate *out)
|
|
|
|
|
|
{
|
|
|
|
|
|
assert(info->templateType == VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET);
|
|
|
|
|
|
|
|
|
|
|
|
VK_FROM_HANDLE(dzn_descriptor_set_layout, set_layout, info->descriptorSetLayout);
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t entry_count = 0;
|
|
|
|
|
|
for (uint32_t e = 0; e < info->descriptorUpdateEntryCount; e++) {
|
|
|
|
|
|
struct dzn_descriptor_set_ptr ptr;
|
|
|
|
|
|
dzn_descriptor_set_ptr_init(set_layout, &ptr,
|
|
|
|
|
|
info->pDescriptorUpdateEntries[e].dstBinding,
|
|
|
|
|
|
info->pDescriptorUpdateEntries[e].dstArrayElement);
|
|
|
|
|
|
uint32_t desc_count = info->pDescriptorUpdateEntries[e].descriptorCount;
|
2022-06-30 20:49:43 -07:00
|
|
|
|
ASSERTED VkDescriptorType type = info->pDescriptorUpdateEntries[e].descriptorType;
|
2022-03-28 10:12:57 +02:00
|
|
|
|
uint32_t d = 0;
|
|
|
|
|
|
|
|
|
|
|
|
while (dzn_descriptor_set_ptr_is_valid(&ptr) && d < desc_count) {
|
|
|
|
|
|
uint32_t ndescs = dzn_descriptor_set_remaining_descs_in_binding(set_layout, &ptr);
|
|
|
|
|
|
|
|
|
|
|
|
assert(dzn_descriptor_set_ptr_get_vk_type(set_layout, &ptr) == type);
|
|
|
|
|
|
d += ndescs;
|
|
|
|
|
|
dzn_descriptor_set_ptr_move(set_layout, &ptr, ndescs);
|
|
|
|
|
|
entry_count++;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
assert(d >= desc_count);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VK_MULTIALLOC(ma);
|
|
|
|
|
|
VK_MULTIALLOC_DECL(&ma, struct dzn_descriptor_update_template, templ, 1);
|
|
|
|
|
|
VK_MULTIALLOC_DECL(&ma, struct dzn_descriptor_update_template_entry, entries, entry_count);
|
|
|
|
|
|
|
|
|
|
|
|
if (!vk_multialloc_zalloc2(&ma, &device->vk.alloc, alloc,
|
|
|
|
|
|
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT))
|
|
|
|
|
|
return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
|
|
|
|
|
|
|
|
|
|
|
|
vk_object_base_init(&device->vk, &templ->base, VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE);
|
|
|
|
|
|
templ->entry_count = entry_count;
|
|
|
|
|
|
templ->entries = entries;
|
|
|
|
|
|
|
|
|
|
|
|
struct dzn_descriptor_update_template_entry *entry = entries;
|
|
|
|
|
|
|
|
|
|
|
|
for (uint32_t e = 0; e < info->descriptorUpdateEntryCount; e++) {
|
|
|
|
|
|
struct dzn_descriptor_set_ptr ptr;
|
|
|
|
|
|
dzn_descriptor_set_ptr_init(set_layout, &ptr,
|
|
|
|
|
|
info->pDescriptorUpdateEntries[e].dstBinding,
|
|
|
|
|
|
info->pDescriptorUpdateEntries[e].dstArrayElement);
|
|
|
|
|
|
uint32_t desc_count = info->pDescriptorUpdateEntries[e].descriptorCount;
|
|
|
|
|
|
VkDescriptorType type = info->pDescriptorUpdateEntries[e].descriptorType;
|
|
|
|
|
|
size_t user_data_offset = info->pDescriptorUpdateEntries[e].offset;
|
|
|
|
|
|
size_t user_data_stride = info->pDescriptorUpdateEntries[e].stride;
|
|
|
|
|
|
uint32_t d = 0;
|
|
|
|
|
|
|
|
|
|
|
|
while (dzn_descriptor_set_ptr_is_valid(&ptr) && d < desc_count) {
|
|
|
|
|
|
uint32_t ndescs = dzn_descriptor_set_remaining_descs_in_binding(set_layout, &ptr);
|
|
|
|
|
|
|
|
|
|
|
|
entry->type = type;
|
|
|
|
|
|
entry->desc_count = MIN2(desc_count - d, ndescs);
|
2022-06-20 13:52:14 +02:00
|
|
|
|
entry->user_data.stride = user_data_stride;
|
2022-03-28 10:12:57 +02:00
|
|
|
|
entry->user_data.offset = user_data_offset;
|
|
|
|
|
|
memset(&entry->heap_offsets, ~0, sizeof(entry->heap_offsets));
|
|
|
|
|
|
|
|
|
|
|
|
assert(dzn_descriptor_set_ptr_get_vk_type(set_layout, &ptr) == type);
|
2022-06-08 06:57:18 -07:00
|
|
|
|
if (dzn_desc_type_has_sampler(type)) {
|
2022-03-28 10:12:57 +02:00
|
|
|
|
entry->heap_offsets.sampler =
|
|
|
|
|
|
dzn_descriptor_set_ptr_get_heap_offset(set_layout,
|
|
|
|
|
|
D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER,
|
2023-03-02 13:06:22 -08:00
|
|
|
|
&ptr, false, device->bindless);
|
2022-03-28 10:12:57 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-03-02 19:58:09 -08:00
|
|
|
|
if (is_dynamic_desc_type(type)) {
|
|
|
|
|
|
entry->buffer_idx = dzn_descriptor_set_ptr_get_buffer_idx(set_layout, &ptr);
|
2022-03-28 10:12:57 +02:00
|
|
|
|
} else if (type != VK_DESCRIPTOR_TYPE_SAMPLER) {
|
2023-03-02 19:58:09 -08:00
|
|
|
|
if (is_buffer_desc_type_without_view(type))
|
|
|
|
|
|
entry->buffer_idx = dzn_descriptor_set_ptr_get_buffer_idx(set_layout, &ptr);
|
|
|
|
|
|
|
2022-03-28 10:12:57 +02:00
|
|
|
|
entry->heap_offsets.cbv_srv_uav =
|
|
|
|
|
|
dzn_descriptor_set_ptr_get_heap_offset(set_layout,
|
|
|
|
|
|
D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
|
2023-03-02 13:06:22 -08:00
|
|
|
|
&ptr, false, device->bindless);
|
|
|
|
|
|
if (dzn_descriptor_type_depends_on_shader_usage(type, device->bindless)) {
|
2023-03-02 09:58:47 -08:00
|
|
|
|
entry->heap_offsets.extra_srv =
|
2022-03-28 10:12:57 +02:00
|
|
|
|
dzn_descriptor_set_ptr_get_heap_offset(set_layout,
|
|
|
|
|
|
D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
|
2023-03-02 13:06:22 -08:00
|
|
|
|
&ptr, true, device->bindless);
|
2022-03-28 10:12:57 +02:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
d += ndescs;
|
|
|
|
|
|
dzn_descriptor_set_ptr_move(set_layout, &ptr, ndescs);
|
|
|
|
|
|
user_data_offset += user_data_stride * ndescs;
|
|
|
|
|
|
++entry;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
*out = dzn_descriptor_update_template_to_handle(templ);
|
|
|
|
|
|
return VK_SUCCESS;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VKAPI_ATTR VkResult VKAPI_CALL
|
|
|
|
|
|
dzn_CreateDescriptorUpdateTemplate(VkDevice device,
|
|
|
|
|
|
const VkDescriptorUpdateTemplateCreateInfo *pCreateInfo,
|
|
|
|
|
|
const VkAllocationCallbacks *pAllocator,
|
|
|
|
|
|
VkDescriptorUpdateTemplate *pDescriptorUpdateTemplate)
|
|
|
|
|
|
{
|
|
|
|
|
|
return dzn_descriptor_update_template_create(dzn_device_from_handle(device),
|
|
|
|
|
|
pCreateInfo, pAllocator,
|
|
|
|
|
|
pDescriptorUpdateTemplate);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VKAPI_ATTR void VKAPI_CALL
|
|
|
|
|
|
dzn_DestroyDescriptorUpdateTemplate(VkDevice device,
|
|
|
|
|
|
VkDescriptorUpdateTemplate descriptorUpdateTemplate,
|
|
|
|
|
|
const VkAllocationCallbacks *pAllocator)
|
|
|
|
|
|
{
|
|
|
|
|
|
dzn_descriptor_update_template_destroy(dzn_descriptor_update_template_from_handle(descriptorUpdateTemplate),
|
|
|
|
|
|
pAllocator);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static const void *
|
|
|
|
|
|
dzn_descriptor_update_template_get_desc_data(const struct dzn_descriptor_update_template *templ,
|
|
|
|
|
|
uint32_t e, uint32_t d,
|
|
|
|
|
|
const void *user_data)
|
|
|
|
|
|
{
|
|
|
|
|
|
return (const void *)((const uint8_t *)user_data +
|
|
|
|
|
|
templ->entries[e].user_data.offset +
|
|
|
|
|
|
(d * templ->entries[e].user_data.stride));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VKAPI_ATTR void VKAPI_CALL
|
2023-02-28 13:54:18 -08:00
|
|
|
|
dzn_UpdateDescriptorSetWithTemplate(VkDevice _device,
|
2022-03-28 10:12:57 +02:00
|
|
|
|
VkDescriptorSet descriptorSet,
|
|
|
|
|
|
VkDescriptorUpdateTemplate descriptorUpdateTemplate,
|
|
|
|
|
|
const void *pData)
|
|
|
|
|
|
{
|
2023-02-28 13:54:18 -08:00
|
|
|
|
VK_FROM_HANDLE(dzn_device, device, _device);
|
2022-03-28 10:12:57 +02:00
|
|
|
|
VK_FROM_HANDLE(dzn_descriptor_set, set, descriptorSet);
|
|
|
|
|
|
VK_FROM_HANDLE(dzn_descriptor_update_template, templ, descriptorUpdateTemplate);
|
|
|
|
|
|
|
|
|
|
|
|
for (uint32_t e = 0; e < templ->entry_count; e++) {
|
|
|
|
|
|
const struct dzn_descriptor_update_template_entry *entry = &templ->entries[e];
|
|
|
|
|
|
bool cube_as_2darray =
|
|
|
|
|
|
entry->type == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
|
|
|
|
|
|
|
|
|
|
|
|
switch (entry->type) {
|
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_SAMPLER:
|
|
|
|
|
|
for (uint32_t d = 0; d < entry->desc_count; d++) {
|
|
|
|
|
|
const VkDescriptorImageInfo *info = (const VkDescriptorImageInfo *)
|
|
|
|
|
|
dzn_descriptor_update_template_get_desc_data(templ, e, d, pData);
|
|
|
|
|
|
VK_FROM_HANDLE(dzn_sampler, sampler, info->sampler);
|
|
|
|
|
|
|
|
|
|
|
|
if (sampler)
|
2023-02-28 13:54:18 -08:00
|
|
|
|
dzn_descriptor_set_write_sampler_desc(device, set, entry->heap_offsets.sampler + d, sampler);
|
2022-03-28 10:12:57 +02:00
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
|
|
|
|
|
|
for (uint32_t d = 0; d < entry->desc_count; d++) {
|
|
|
|
|
|
const VkDescriptorImageInfo *info = (const VkDescriptorImageInfo *)
|
|
|
|
|
|
dzn_descriptor_update_template_get_desc_data(templ, e, d, pData);
|
|
|
|
|
|
VK_FROM_HANDLE(dzn_sampler, sampler, info->sampler);
|
|
|
|
|
|
VK_FROM_HANDLE(dzn_image_view, iview, info->imageView);
|
|
|
|
|
|
|
|
|
|
|
|
if (sampler)
|
2023-02-28 13:54:18 -08:00
|
|
|
|
dzn_descriptor_set_write_sampler_desc(device, set, entry->heap_offsets.sampler + d, sampler);
|
2022-03-28 10:12:57 +02:00
|
|
|
|
|
|
|
|
|
|
if (iview)
|
2023-03-02 09:58:47 -08:00
|
|
|
|
dzn_descriptor_set_write_image_view_desc(device, entry->type, set,
|
|
|
|
|
|
entry->heap_offsets.cbv_srv_uav + d, ~0,
|
|
|
|
|
|
cube_as_2darray, iview);
|
2022-03-28 10:12:57 +02:00
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
|
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
|
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
|
|
|
|
|
|
for (uint32_t d = 0; d < entry->desc_count; d++) {
|
|
|
|
|
|
const VkDescriptorImageInfo *info = (const VkDescriptorImageInfo *)
|
|
|
|
|
|
dzn_descriptor_update_template_get_desc_data(templ, e, d, pData);
|
2023-03-02 09:58:47 -08:00
|
|
|
|
uint32_t heap_offset = entry->heap_offsets.cbv_srv_uav + d;
|
|
|
|
|
|
uint32_t alt_heap_offset =
|
2023-03-02 13:06:22 -08:00
|
|
|
|
dzn_descriptor_type_depends_on_shader_usage(entry->type, device->bindless) ?
|
2023-03-02 09:58:47 -08:00
|
|
|
|
entry->heap_offsets.extra_srv + d : ~0;
|
2022-03-28 10:12:57 +02:00
|
|
|
|
VK_FROM_HANDLE(dzn_image_view, iview, info->imageView);
|
|
|
|
|
|
|
|
|
|
|
|
if (iview)
|
2023-03-02 09:58:47 -08:00
|
|
|
|
dzn_descriptor_set_write_image_view_desc(device, entry->type, set,
|
|
|
|
|
|
heap_offset, alt_heap_offset,
|
|
|
|
|
|
cube_as_2darray, iview);
|
2022-03-28 10:12:57 +02:00
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
|
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
|
|
|
|
|
|
for (uint32_t d = 0; d < entry->desc_count; d++) {
|
|
|
|
|
|
const VkDescriptorBufferInfo *info = (const VkDescriptorBufferInfo *)
|
|
|
|
|
|
dzn_descriptor_update_template_get_desc_data(templ, e, d, pData);
|
2023-03-02 09:58:47 -08:00
|
|
|
|
uint32_t heap_offset = entry->heap_offsets.cbv_srv_uav + d;
|
|
|
|
|
|
uint32_t alt_heap_offset =
|
2023-03-02 13:06:22 -08:00
|
|
|
|
dzn_descriptor_type_depends_on_shader_usage(entry->type, device->bindless) ?
|
2023-03-02 09:58:47 -08:00
|
|
|
|
entry->heap_offsets.extra_srv + d : ~0;
|
2022-03-28 10:12:57 +02:00
|
|
|
|
|
|
|
|
|
|
struct dzn_buffer_desc desc = {
|
|
|
|
|
|
entry->type,
|
|
|
|
|
|
dzn_buffer_from_handle(info->buffer),
|
dzn: Re-design custom buffer descriptors
Previously, custom buffer descriptors were owned by a descriptor set. Now,
custom buffer descriptors are owned by the buffer. Additionally, we respect
the app-provided sizes when they're smaller than the buffer size, even if
robustness is not enabled, so that size queries work correctly.
This new design fixes several issues:
* Descriptor set copies were broken when they involved custom descriptors,
because the original descriptor set owned the lifetime of the custom
descriptor, the new one was just borrowing it. If those lifetimes didn't
line up, problems would arise.
* A single buffer with the same sub-view placed in multiplel descriptor sets
would allocate multiple slots, when it only really needed one.
* Custom buffer descriptors now lower the base offset to 0 to allow merging
multiple overlapping (ending at the same upper bound) descriptors. Since
the shader is already doing an offset add, making it nonzero is free.
* Dynamic buffer descriptors were incorrect before. The size passed into the
descriptor set is supposed to be the size from the *dynamic* offset, not the
size from the static offset. By allocating/populating the descriptor when
placed into the set, it prevented larger offsets from working correctly. This
buffer-owned design prevents cmdbufs from having to own lifetime of custom
descriptors.
Fixes dEQP-VK.ssbo.unsized_array_length.float_offset_explicit_size
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/22639>
2023-04-21 11:48:16 -07:00
|
|
|
|
info->range, info->offset
|
2022-03-28 10:12:57 +02:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
if (desc.buffer)
|
2023-03-02 19:58:09 -08:00
|
|
|
|
dzn_descriptor_set_write_buffer_desc(device, entry->type, set, heap_offset,
|
|
|
|
|
|
alt_heap_offset, &desc);
|
2022-03-28 10:12:57 +02:00
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
|
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
|
|
|
|
|
|
for (uint32_t d = 0; d < entry->desc_count; d++) {
|
|
|
|
|
|
const VkDescriptorBufferInfo *info = (const VkDescriptorBufferInfo *)
|
|
|
|
|
|
dzn_descriptor_update_template_get_desc_data(templ, e, d, pData);
|
2023-03-02 19:58:09 -08:00
|
|
|
|
uint32_t dyn_buf_idx = entry->buffer_idx + d;
|
2022-03-28 10:12:57 +02:00
|
|
|
|
|
|
|
|
|
|
struct dzn_buffer_desc desc = {
|
|
|
|
|
|
entry->type,
|
|
|
|
|
|
dzn_buffer_from_handle(info->buffer),
|
dzn: Re-design custom buffer descriptors
Previously, custom buffer descriptors were owned by a descriptor set. Now,
custom buffer descriptors are owned by the buffer. Additionally, we respect
the app-provided sizes when they're smaller than the buffer size, even if
robustness is not enabled, so that size queries work correctly.
This new design fixes several issues:
* Descriptor set copies were broken when they involved custom descriptors,
because the original descriptor set owned the lifetime of the custom
descriptor, the new one was just borrowing it. If those lifetimes didn't
line up, problems would arise.
* A single buffer with the same sub-view placed in multiplel descriptor sets
would allocate multiple slots, when it only really needed one.
* Custom buffer descriptors now lower the base offset to 0 to allow merging
multiple overlapping (ending at the same upper bound) descriptors. Since
the shader is already doing an offset add, making it nonzero is free.
* Dynamic buffer descriptors were incorrect before. The size passed into the
descriptor set is supposed to be the size from the *dynamic* offset, not the
size from the static offset. By allocating/populating the descriptor when
placed into the set, it prevented larger offsets from working correctly. This
buffer-owned design prevents cmdbufs from having to own lifetime of custom
descriptors.
Fixes dEQP-VK.ssbo.unsized_array_length.float_offset_explicit_size
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/22639>
2023-04-21 11:48:16 -07:00
|
|
|
|
info->range, info->offset
|
2022-03-28 10:12:57 +02:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
if (desc.buffer)
|
2023-03-02 19:58:09 -08:00
|
|
|
|
dzn_descriptor_set_write_dynamic_buffer_desc(device, set, dyn_buf_idx, &desc);
|
2022-03-28 10:12:57 +02:00
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
|
|
|
|
|
|
case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
|
|
|
|
|
|
for (uint32_t d = 0; d < entry->desc_count; d++) {
|
|
|
|
|
|
VkBufferView *info = (VkBufferView *)
|
|
|
|
|
|
dzn_descriptor_update_template_get_desc_data(templ, e, d, pData);
|
|
|
|
|
|
VK_FROM_HANDLE(dzn_buffer_view, bview, *info);
|
2023-03-02 09:58:47 -08:00
|
|
|
|
uint32_t heap_offset = entry->heap_offsets.cbv_srv_uav + d;
|
|
|
|
|
|
uint32_t alt_heap_offset =
|
2023-03-02 13:06:22 -08:00
|
|
|
|
dzn_descriptor_type_depends_on_shader_usage(entry->type, device->bindless) ?
|
2023-03-02 09:58:47 -08:00
|
|
|
|
entry->heap_offsets.extra_srv + d : ~0;
|
2022-03-28 10:12:57 +02:00
|
|
|
|
|
|
|
|
|
|
if (bview)
|
2023-03-02 09:58:47 -08:00
|
|
|
|
dzn_descriptor_set_write_buffer_view_desc(device, entry->type, set, heap_offset, alt_heap_offset, bview);
|
2022-03-28 10:12:57 +02:00
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
|
unreachable("invalid descriptor type");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|