Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- libs/vkd3d/command.c | 13 ++----------- libs/vkd3d/device.c | 39 ++++++++++++++++++++++++++++++++++++++ libs/vkd3d/vkd3d_private.h | 18 ++++++++++++++++++ 3 files changed, 59 insertions(+), 11 deletions(-)
diff --git a/libs/vkd3d/command.c b/libs/vkd3d/command.c index f1ec6be3..0973b204 100644 --- a/libs/vkd3d/command.c +++ b/libs/vkd3d/command.c @@ -1351,15 +1351,6 @@ static bool d3d12_command_allocator_add_transfer_buffer(struct d3d12_command_all static VkDescriptorPool d3d12_command_allocator_allocate_descriptor_pool( struct d3d12_command_allocator *allocator) { - static const VkDescriptorPoolSize pool_sizes[] = - { - {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1024}, - {VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1024}, - {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1024}, - {VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1024}, - {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1024}, - {VK_DESCRIPTOR_TYPE_SAMPLER, 1024}, - }; struct d3d12_device *device = allocator->device; const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs; struct VkDescriptorPoolCreateInfo pool_desc; @@ -1379,8 +1370,8 @@ static VkDescriptorPool d3d12_command_allocator_allocate_descriptor_pool( pool_desc.pNext = NULL; pool_desc.flags = 0; pool_desc.maxSets = 512; - pool_desc.poolSizeCount = ARRAY_SIZE(pool_sizes); - pool_desc.pPoolSizes = pool_sizes; + pool_desc.poolSizeCount = ARRAY_SIZE(device->vk_pool_sizes); + pool_desc.pPoolSizes = device->vk_pool_sizes; if ((vr = VK_CALL(vkCreateDescriptorPool(vk_device, &pool_desc, NULL, &vk_pool))) < 0) { ERR("Failed to create descriptor pool, vr %d.\n", vr); diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c index 4bcb5efc..212b0b74 100644 --- a/libs/vkd3d/device.c +++ b/libs/vkd3d/device.c @@ -1277,6 +1277,16 @@ static void vkd3d_init_feature_level(struct vkd3d_vulkan_info *vk_info, TRACE("Max feature level: %#x.\n", vk_info->max_feature_level); }
+static void vkd3d_device_descriptor_limits_init(struct vkd3d_device_descriptor_limits *limits, + const VkPhysicalDeviceLimits *device_limits) +{ + limits->uniform_buffer_max_descriptors = device_limits->maxDescriptorSetUniformBuffers; + limits->sampled_image_max_descriptors = device_limits->maxDescriptorSetSampledImages; + limits->storage_buffer_max_descriptors = device_limits->maxDescriptorSetStorageBuffers; + limits->storage_image_max_descriptors = device_limits->maxDescriptorSetStorageImages; + limits->sampler_max_descriptors = min(device_limits->maxDescriptorSetSamplers, VKD3D_MAX_DESCRIPTOR_SET_SAMPLERS); +} + static HRESULT vkd3d_init_device_caps(struct d3d12_device *device, const struct vkd3d_device_create_info *create_info, struct vkd3d_physical_device_info *physical_device_info, @@ -1504,6 +1514,9 @@ static HRESULT vkd3d_init_device_caps(struct d3d12_device *device, features->robustBufferAccess = VK_FALSE; }
+ vkd3d_device_descriptor_limits_init(&vulkan_info->descriptor_limits, + &physical_device_info->properties2.properties.limits); + return S_OK; }
@@ -2419,6 +2432,29 @@ static void vkd3d_time_domains_init(struct d3d12_device *device) WARN("Found no acceptable host time domain. Calibrated timestamps will not be available.\n"); }
+static void vkd3d_init_descriptor_pool_sizes(VkDescriptorPoolSize *pool_sizes, unsigned int count, + const struct vkd3d_device_descriptor_limits *limits) +{ + assert(count == 6); + + pool_sizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + pool_sizes[0].descriptorCount = min(limits->uniform_buffer_max_descriptors, + VKD3D_MAX_VIRTUAL_HEAP_DESCRIPTORS_PER_TYPE); + pool_sizes[1].type = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER; + pool_sizes[1].descriptorCount = min(limits->sampled_image_max_descriptors, + VKD3D_MAX_VIRTUAL_HEAP_DESCRIPTORS_PER_TYPE); + pool_sizes[2].type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; + pool_sizes[2].descriptorCount = pool_sizes[1].descriptorCount; + pool_sizes[3].type = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; + pool_sizes[3].descriptorCount = min(limits->storage_image_max_descriptors, + VKD3D_MAX_VIRTUAL_HEAP_DESCRIPTORS_PER_TYPE); + pool_sizes[4].type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; + pool_sizes[4].descriptorCount = pool_sizes[3].descriptorCount; + pool_sizes[5].type = VK_DESCRIPTOR_TYPE_SAMPLER; + pool_sizes[5].descriptorCount = min(limits->sampler_max_descriptors, + VKD3D_MAX_VIRTUAL_HEAP_DESCRIPTORS_PER_TYPE); +}; + /* ID3D12Device */ static inline struct d3d12_device *impl_from_ID3D12Device(ID3D12Device *iface) { @@ -3979,6 +4015,9 @@ static HRESULT d3d12_device_init(struct d3d12_device *device, for (i = 0; i < ARRAY_SIZE(device->desc_mutex); ++i) pthread_mutex_init(&device->desc_mutex[i], NULL);
+ vkd3d_init_descriptor_pool_sizes(device->vk_pool_sizes, ARRAY_SIZE(device->vk_pool_sizes), + &device->vk_info.descriptor_limits); + if ((device->parent = create_info->parent)) IUnknown_AddRef(device->parent);
diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h index d21cd411..5da00685 100644 --- a/libs/vkd3d/vkd3d_private.h +++ b/libs/vkd3d/vkd3d_private.h @@ -59,6 +59,12 @@ #define VKD3D_MAX_SHADER_STAGES 5u #define VKD3D_MAX_VK_SYNC_OBJECTS 4u #define VKD3D_MAX_DESCRIPTOR_SETS 64u +/* D3D12 binding tier 3 has a limit of 2048 samplers. */ +#define VKD3D_MAX_DESCRIPTOR_SET_SAMPLERS 2048u +/* The main limitation here is the simple descriptor pool recycling scheme + * requiring each pool to contain all descriptor types used by vkd3d. Limit + * this number to prevent excessive pool memory use. */ +#define VKD3D_MAX_VIRTUAL_HEAP_DESCRIPTORS_PER_TYPE (16 * 1024u)
struct d3d12_command_list; struct d3d12_device; @@ -92,6 +98,15 @@ HRESULT hresult_from_errno(int rc); HRESULT hresult_from_vk_result(VkResult vr); HRESULT hresult_from_vkd3d_result(int vkd3d_result);
+struct vkd3d_device_descriptor_limits +{ + unsigned int uniform_buffer_max_descriptors; + unsigned int sampled_image_max_descriptors; + unsigned int storage_buffer_max_descriptors; + unsigned int storage_image_max_descriptors; + unsigned int sampler_max_descriptors; +}; + struct vkd3d_vulkan_info { /* KHR instance extensions */ @@ -127,6 +142,7 @@ struct vkd3d_vulkan_info
VkPhysicalDeviceLimits device_limits; VkPhysicalDeviceSparseProperties sparse_properties; + struct vkd3d_device_descriptor_limits descriptor_limits;
VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT texel_buffer_alignment_properties;
@@ -1218,6 +1234,8 @@ struct d3d12_device const struct vkd3d_format_compatibility_list *format_compatibility_lists; struct vkd3d_null_resources null_resources; struct vkd3d_uav_clear_state uav_clear_state; + + VkDescriptorPoolSize vk_pool_sizes[6]; };
HRESULT d3d12_device_create(struct vkd3d_instance *instance,
Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- libs/vkd3d/state.c | 81 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 73 insertions(+), 8 deletions(-)
diff --git a/libs/vkd3d/state.c b/libs/vkd3d/state.c index b54a6527..fa4de634 100644 --- a/libs/vkd3d/state.c +++ b/libs/vkd3d/state.c @@ -331,14 +331,25 @@ struct d3d12_root_signature_info size_t root_constant_count; size_t root_descriptor_count;
+ unsigned int cbv_count; + unsigned int srv_count; + unsigned int uav_count; + unsigned int sampler_count; + unsigned int cbv_unbounded_range_count; + unsigned int srv_unbounded_range_count; + unsigned int uav_unbounded_range_count; + unsigned int sampler_unbounded_range_count; + size_t cost; };
static HRESULT d3d12_root_signature_info_count_descriptors(struct d3d12_root_signature_info *info, const D3D12_ROOT_DESCRIPTOR_TABLE *table, bool use_array) { + bool cbv_unbounded_range = false, srv_unbounded_range = false, uav_unbounded_range = false; + bool sampler_unbounded_range = false; bool unbounded = false; - unsigned int i; + unsigned int i, count;
for (i = 0; i < table->NumDescriptorRanges; ++i) { @@ -365,8 +376,12 @@ static HRESULT d3d12_root_signature_info_count_descriptors(struct d3d12_root_sig return E_INVALIDARG; }
+ count = range->NumDescriptors; if (range->NumDescriptors == UINT_MAX) + { unbounded = true; + count = 0; + }
binding_count = use_array ? 1 : range->NumDescriptors;
@@ -378,14 +393,22 @@ static HRESULT d3d12_root_signature_info_count_descriptors(struct d3d12_root_sig * root signature, we create descriptor set layouts with two bindings for * each SRV and UAV. */ info->binding_count += binding_count; + info->srv_count += count * 2u; + srv_unbounded_range |= unbounded; break; case D3D12_DESCRIPTOR_RANGE_TYPE_UAV: /* As above. */ info->binding_count += binding_count; + info->uav_count += count * 2u; + uav_unbounded_range |= unbounded; break; case D3D12_DESCRIPTOR_RANGE_TYPE_CBV: + info->cbv_count += count; + cbv_unbounded_range |= unbounded; break; case D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER: + info->sampler_count += count; + sampler_unbounded_range |= unbounded; break; default: FIXME("Unhandled descriptor type %#x.\n", range->RangeType); @@ -401,6 +424,11 @@ static HRESULT d3d12_root_signature_info_count_descriptors(struct d3d12_root_sig return E_FAIL; }
+ info->srv_unbounded_range_count += srv_unbounded_range * 2u; + info->uav_unbounded_range_count += uav_unbounded_range * 2u; + info->cbv_unbounded_range_count += cbv_unbounded_range; + info->sampler_unbounded_range_count += sampler_unbounded_range; + return S_OK; }
@@ -427,16 +455,19 @@ static HRESULT d3d12_root_signature_info_from_desc(struct d3d12_root_signature_i
case D3D12_ROOT_PARAMETER_TYPE_CBV: ++info->root_descriptor_count; + ++info->cbv_count; ++info->binding_count; info->cost += 2; break; case D3D12_ROOT_PARAMETER_TYPE_SRV: ++info->root_descriptor_count; + ++info->srv_count; ++info->binding_count; info->cost += 2; break; case D3D12_ROOT_PARAMETER_TYPE_UAV: ++info->root_descriptor_count; + ++info->uav_count; ++info->binding_count; info->cost += 2; break; @@ -453,6 +484,7 @@ static HRESULT d3d12_root_signature_info_from_desc(struct d3d12_root_signature_i }
info->binding_count += desc->NumStaticSamplers; + info->sampler_count += desc->NumStaticSamplers;
return S_OK; } @@ -675,14 +707,44 @@ static uint32_t vkd3d_descriptor_magic_from_d3d12(D3D12_DESCRIPTOR_RANGE_TYPE ty } }
-static unsigned int vk_binding_count_from_descriptor_range(const struct d3d12_root_descriptor_table_range *range) +static unsigned int vk_binding_count_from_descriptor_range(const struct d3d12_root_descriptor_table_range *range, + const struct d3d12_root_signature_info *info, const struct vkd3d_device_descriptor_limits *limits) { + unsigned int count, limit; + if (range->descriptor_count != UINT_MAX) return range->descriptor_count;
- /* TODO: Calculate an upper bound from unbounded set counts and Vulkan - * device limits. */ - return 1024; + switch (range->type) + { + case VKD3D_SHADER_DESCRIPTOR_TYPE_CBV: + limit = limits->uniform_buffer_max_descriptors; + count = (limit - min(info->cbv_count, limit)) / info->cbv_unbounded_range_count; + break; + case VKD3D_SHADER_DESCRIPTOR_TYPE_SRV: + limit = limits->sampled_image_max_descriptors; + count = (limit - min(info->srv_count, limit)) / info->srv_unbounded_range_count; + break; + case VKD3D_SHADER_DESCRIPTOR_TYPE_UAV: + limit = limits->storage_image_max_descriptors; + count = (limit - min(info->uav_count, limit)) / info->uav_unbounded_range_count; + break; + case VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER: + limit = limits->sampler_max_descriptors; + count = (limit - min(info->sampler_count, limit)) / info->sampler_unbounded_range_count; + break; + default: + ERR("Unhandled type %#x.\n", range->type); + return 1; + } + + if (!count) + { + WARN("Descriptor table exceeds type %#x limit of %u.\n", range->type, limit); + count = 1; + } + + return min(count, VKD3D_MAX_VIRTUAL_HEAP_DESCRIPTORS_PER_TYPE); }
static HRESULT d3d12_root_signature_init_descriptor_array_binding(struct d3d12_root_signature *root_signature, @@ -802,8 +864,10 @@ static HRESULT validate_descriptor_register_ranges(const struct d3d12_root_descr }
static HRESULT d3d12_root_signature_init_root_descriptor_tables(struct d3d12_root_signature *root_signature, - const D3D12_ROOT_SIGNATURE_DESC *desc, struct vkd3d_descriptor_set_context *context) + const D3D12_ROOT_SIGNATURE_DESC *desc, const struct d3d12_root_signature_info *info, + struct vkd3d_descriptor_set_context *context) { + const struct d3d12_device *device = root_signature->device; struct d3d12_root_descriptor_table *table; unsigned int i, j, k, range_count; uint32_t vk_binding; @@ -904,7 +968,8 @@ static HRESULT d3d12_root_signature_init_root_descriptor_tables(struct d3d12_roo }
range->binding = context->descriptor_binding; - range->vk_binding_count = vk_binding_count_from_descriptor_range(range); + range->vk_binding_count = vk_binding_count_from_descriptor_range(range, + info, &device->vk_info.descriptor_limits);
if (FAILED(hr = d3d12_root_signature_init_descriptor_array_binding(root_signature, range, p->ShaderVisibility, context))) @@ -1213,7 +1278,7 @@ static HRESULT d3d12_root_signature_init(struct d3d12_root_signature *root_signa goto fail; if (FAILED(hr = d3d12_root_signature_init_static_samplers(root_signature, device, desc, &context))) goto fail; - if (FAILED(hr = d3d12_root_signature_init_root_descriptor_tables(root_signature, desc, &context))) + if (FAILED(hr = d3d12_root_signature_init_root_descriptor_tables(root_signature, desc, &info, &context))) goto fail;
if (FAILED(hr = d3d12_root_signature_append_descriptor_set_layout(root_signature, &context, 0)))