Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- libs/vkd3d/device.c | 8 +++ libs/vkd3d/resource.c | 101 +++++++++++++++++++++++++++++++++++-- libs/vkd3d/vkd3d_private.h | 5 ++ 3 files changed, 109 insertions(+), 5 deletions(-)
diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c index bd471a72..0d2d1696 100644 --- a/libs/vkd3d/device.c +++ b/libs/vkd3d/device.c @@ -135,6 +135,7 @@ static const struct vkd3d_optional_extension_info optional_device_extensions[] = VK_EXTENSION(EXT_DEBUG_MARKER, EXT_debug_marker), VK_EXTENSION(EXT_DEPTH_CLIP_ENABLE, EXT_depth_clip_enable), VK_EXTENSION(EXT_DESCRIPTOR_INDEXING, EXT_descriptor_indexing), + VK_EXTENSION(EXT_ROBUSTNESS_2, EXT_robustness2), VK_EXTENSION(EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION, EXT_shader_demote_to_helper_invocation), VK_EXTENSION(EXT_SHADER_STENCIL_EXPORT, EXT_shader_stencil_export), VK_EXTENSION(EXT_TEXEL_BUFFER_ALIGNMENT, EXT_texel_buffer_alignment), @@ -797,6 +798,7 @@ struct vkd3d_physical_device_info VkPhysicalDeviceConditionalRenderingFeaturesEXT conditional_rendering_features; VkPhysicalDeviceDepthClipEnableFeaturesEXT depth_clip_features; VkPhysicalDeviceDescriptorIndexingFeaturesEXT descriptor_indexing_features; + VkPhysicalDeviceRobustness2FeaturesEXT robustness2_features; VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT demote_features; VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT texel_buffer_alignment_features; VkPhysicalDeviceTransformFeedbackFeaturesEXT xfb_features; @@ -813,6 +815,7 @@ static void vkd3d_physical_device_info_init(struct vkd3d_physical_device_info *i VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT *vertex_divisor_properties; VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT *buffer_alignment_properties; VkPhysicalDeviceDescriptorIndexingFeaturesEXT *descriptor_indexing_features; + VkPhysicalDeviceRobustness2FeaturesEXT *robustness2_features; VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT *vertex_divisor_features; VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT *buffer_alignment_features; VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT *demote_features; @@ -827,6 +830,7 @@ static void vkd3d_physical_device_info_init(struct vkd3d_physical_device_info *i conditional_rendering_features = &info->conditional_rendering_features; depth_clip_features = &info->depth_clip_features; descriptor_indexing_features = &info->descriptor_indexing_features; + robustness2_features = &info->robustness2_features; descriptor_indexing_properties = &info->descriptor_indexing_properties; maintenance3_properties = &info->maintenance3_properties; demote_features = &info->demote_features; @@ -845,6 +849,8 @@ static void vkd3d_physical_device_info_init(struct vkd3d_physical_device_info *i vk_prepend_struct(&info->features2, depth_clip_features); descriptor_indexing_features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES_EXT; vk_prepend_struct(&info->features2, descriptor_indexing_features); + robustness2_features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT; + vk_prepend_struct(&info->features2, robustness2_features); demote_features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES_EXT; vk_prepend_struct(&info->features2, demote_features); buffer_alignment_features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_FEATURES_EXT; @@ -1577,6 +1583,8 @@ static HRESULT vkd3d_init_device_caps(struct d3d12_device *device, vulkan_info->EXT_conditional_rendering = false; if (!physical_device_info->depth_clip_features.depthClipEnable) vulkan_info->EXT_depth_clip_enable = false; + if (!physical_device_info->robustness2_features.nullDescriptor) + vulkan_info->EXT_robustness2 = false; if (!physical_device_info->demote_features.shaderDemoteToHelperInvocation) vulkan_info->EXT_shader_demote_to_helper_invocation = false; if (!physical_device_info->texel_buffer_alignment_features.texelBufferAlignment) diff --git a/libs/vkd3d/resource.c b/libs/vkd3d/resource.c index cbbd4170..01e0b67a 100644 --- a/libs/vkd3d/resource.c +++ b/libs/vkd3d/resource.c @@ -2423,10 +2423,10 @@ bool vkd3d_create_buffer_view(struct d3d12_device *device, VkBuffer vk_buffer, c VkDeviceSize offset, VkDeviceSize size, struct vkd3d_view **view) { const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs; + VkBufferView vk_view = VK_NULL_HANDLE; struct vkd3d_view *object; - VkBufferView vk_view;
- if (!vkd3d_create_vk_buffer_view(device, vk_buffer, format, offset, size, &vk_view)) + if (vk_buffer && !vkd3d_create_vk_buffer_view(device, vk_buffer, format, offset, size, &vk_view)) return false;
if (!(object = vkd3d_view_create(VKD3D_VIEW_TYPE_BUFFER))) @@ -2782,7 +2782,7 @@ void d3d12_desc_create_cbv(struct d3d12_desc *descriptor, /* NULL descriptor */ buffer_info->buffer = device->null_resources.vk_buffer; buffer_info->offset = 0; - buffer_info->range = VKD3D_NULL_BUFFER_SIZE; + buffer_info->range = device->null_resources.vk_buffer ? VKD3D_NULL_BUFFER_SIZE : VK_WHOLE_SIZE; }
descriptor->magic = VKD3D_DESCRIPTOR_MAGIC_CBV; @@ -2864,6 +2864,55 @@ static void vkd3d_create_null_srv(struct d3d12_desc *descriptor, descriptor->u.view_info.written_serial_id = view->serial_id; }
+static bool vkd3d_create_null_texture_view(const struct d3d12_device *device, struct vkd3d_view **view) +{ + struct vkd3d_view *object; + + if (!(object = vkd3d_view_create(VKD3D_VIEW_TYPE_IMAGE))) + return false; + + object->u.vk_image_view = VK_NULL_HANDLE; + object->format = vkd3d_get_format(device, VKD3D_NULL_VIEW_FORMAT, false); + object->info.texture.vk_view_type = VK_IMAGE_VIEW_TYPE_2D; + object->info.texture.miplevel_idx = 0; + object->info.texture.layer_idx = 0; + object->info.texture.layer_count = 1; + *view = object; + return true; +} + +static void vkd3d_create_vk_null_srv(struct d3d12_desc *descriptor, struct d3d12_device *device, + const D3D12_SHADER_RESOURCE_VIEW_DESC *desc) +{ + struct vkd3d_view *view; + + if (!desc) + { + WARN("View desc is required for NULL view.\n"); + return; + } + + if (desc->ViewDimension == D3D12_SRV_DIMENSION_BUFFER) + { + if (!vkd3d_create_buffer_view(device, VK_NULL_HANDLE, vkd3d_get_format(device, DXGI_FORMAT_R32_UINT, false), + 0, VKD3D_NULL_BUFFER_SIZE, &view)) + { + return; + } + descriptor->vk_descriptor_type = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER; + } + else + { + if (!vkd3d_create_null_texture_view(device, &view)) + return; + descriptor->vk_descriptor_type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; + } + + descriptor->magic = VKD3D_DESCRIPTOR_MAGIC_SRV; + descriptor->u.view_info.view = view; + descriptor->u.view_info.written_serial_id = view->serial_id; +} + static void vkd3d_create_buffer_srv(struct d3d12_desc *descriptor, struct d3d12_device *device, struct d3d12_resource *resource, const D3D12_SHADER_RESOURCE_VIEW_DESC *desc) @@ -2925,7 +2974,7 @@ void d3d12_desc_create_srv(struct d3d12_desc *descriptor,
if (!resource) { - vkd3d_create_null_srv(descriptor, device, desc); + device->create_null_srv(descriptor, device, desc); return; }
@@ -3101,6 +3150,38 @@ static void vkd3d_create_null_uav(struct d3d12_desc *descriptor, descriptor->u.view_info.written_serial_id = view->serial_id; }
+static void vkd3d_create_vk_null_uav(struct d3d12_desc *descriptor, struct d3d12_device *device, + const D3D12_UNORDERED_ACCESS_VIEW_DESC *desc) +{ + struct vkd3d_view *view; + + if (!desc) + { + WARN("View desc is required for NULL view.\n"); + return; + } + + if (desc->ViewDimension == D3D12_UAV_DIMENSION_BUFFER) + { + if (!vkd3d_create_buffer_view(device, VK_NULL_HANDLE, vkd3d_get_format(device, DXGI_FORMAT_R32_UINT, false), + 0, VKD3D_NULL_BUFFER_SIZE, &view)) + { + return; + } + descriptor->vk_descriptor_type = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; + } + else + { + if (!vkd3d_create_null_texture_view(device, &view)) + return; + descriptor->vk_descriptor_type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; + } + + descriptor->magic = VKD3D_DESCRIPTOR_MAGIC_UAV; + descriptor->u.view_info.view = view; + descriptor->u.view_info.written_serial_id = view->serial_id; +} + static void vkd3d_create_buffer_uav(struct d3d12_desc *descriptor, struct d3d12_device *device, struct d3d12_resource *resource, struct d3d12_resource *counter_resource, const D3D12_UNORDERED_ACCESS_VIEW_DESC *desc) @@ -3216,7 +3297,7 @@ void d3d12_desc_create_uav(struct d3d12_desc *descriptor, struct d3d12_device *d { if (counter_resource) FIXME("Ignoring counter resource %p.\n", counter_resource); - vkd3d_create_null_uav(descriptor, device, desc); + device->create_null_uav(descriptor, device, desc); return; }
@@ -4421,6 +4502,16 @@ HRESULT vkd3d_init_null_resources(struct vkd3d_null_resources *null_resources,
memset(null_resources, 0, sizeof(*null_resources));
+ if (device->vk_info.EXT_robustness2) + { + device->create_null_srv = vkd3d_create_vk_null_srv; + device->create_null_uav = vkd3d_create_vk_null_uav; + return S_OK; + } + + device->create_null_srv = vkd3d_create_null_srv; + device->create_null_uav = vkd3d_create_null_uav; + memset(&heap_properties, 0, sizeof(heap_properties)); heap_properties.Type = D3D12_HEAP_TYPE_DEFAULT;
diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h index c28eb234..ef454fa1 100644 --- a/libs/vkd3d/vkd3d_private.h +++ b/libs/vkd3d/vkd3d_private.h @@ -131,6 +131,7 @@ struct vkd3d_vulkan_info bool EXT_debug_marker; bool EXT_depth_clip_enable; bool EXT_descriptor_indexing; + bool EXT_robustness2; bool EXT_shader_demote_to_helper_invocation; bool EXT_shader_stencil_export; bool EXT_texel_buffer_alignment; @@ -1450,6 +1451,10 @@ struct d3d12_device unsigned int format_compatibility_list_count; const struct vkd3d_format_compatibility_list *format_compatibility_lists; struct vkd3d_null_resources null_resources; + void (*create_null_srv)(struct d3d12_desc *descriptor, struct d3d12_device *device, + const D3D12_SHADER_RESOURCE_VIEW_DESC *desc); + void (*create_null_uav)(struct d3d12_desc *descriptor, struct d3d12_device *device, + const D3D12_UNORDERED_ACCESS_VIEW_DESC *desc); struct vkd3d_uav_clear_state uav_clear_state;
VkDescriptorPoolSize vk_pool_sizes[VKD3D_DESCRIPTOR_POOL_COUNT];
Binding a shader with the wrong null descriptor type works in Windows. The introduction of Vulkan-backed heaps may cause a regression in clients which do this, because the written index will remain unpopulated in all other sets, but a shader may access it in one of them.
Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- libs/vkd3d/resource.c | 55 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-)
diff --git a/libs/vkd3d/resource.c b/libs/vkd3d/resource.c index 01e0b67a..3c5024e3 100644 --- a/libs/vkd3d/resource.c +++ b/libs/vkd3d/resource.c @@ -2131,6 +2131,7 @@ void vkd3d_view_decref(struct vkd3d_view *view, struct d3d12_device *device) vkd3d_view_destroy(view, device); }
+/* TODO: write null descriptors to all applicable sets (invalid behaviour workaround). */ static void d3d12_descriptor_heap_write_vk_descriptor_range(struct d3d12_descriptor_heap_vk_set *descriptor_set, struct d3d12_desc_copy_location *locations, unsigned int write_count) { @@ -2178,6 +2179,47 @@ static void d3d12_descriptor_heap_write_vk_descriptor_range(struct d3d12_descrip } }
+static void d3d12_desc_write_vk_heap_null_descriptor(struct d3d12_descriptor_heap *descriptor_heap, + uint32_t dst_array_element, const struct d3d12_device *device) +{ + const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs; + struct d3d12_descriptor_heap_vk_set *descriptor_set; + VkBufferView vk_buffer_view = VK_NULL_HANDLE; + enum vkd3d_vk_descriptor_set_index i; + VkDescriptorBufferInfo vk_cbv_info; + + vk_cbv_info.buffer = VK_NULL_HANDLE; + vk_cbv_info.offset = 0; + vk_cbv_info.range = VK_WHOLE_SIZE; + + /* Binding a shader with the wrong null descriptor type works in Windows. + * To support that here we need to write one to all Vulkan sets. */ + for (i = VKD3D_SET_INDEX_UNIFORM_BUFFER; i <= VKD3D_SET_INDEX_STORAGE_IMAGE; ++i) + { + descriptor_set = &descriptor_heap->vk_descriptor_sets[i]; + descriptor_set->vk_descriptor_writes[0].dstArrayElement = dst_array_element; + descriptor_set->vk_descriptor_writes[0].descriptorCount = 1; + switch (i) + { + case VKD3D_SET_INDEX_UNIFORM_BUFFER: + descriptor_set->vk_descriptor_writes[0].pBufferInfo = &vk_cbv_info; + break; + case VKD3D_SET_INDEX_SAMPLED_IMAGE: + case VKD3D_SET_INDEX_STORAGE_IMAGE: + descriptor_set->vk_image_infos[0].imageView = VK_NULL_HANDLE; + break; + case VKD3D_SET_INDEX_UNIFORM_TEXEL_BUFFER: + case VKD3D_SET_INDEX_STORAGE_TEXEL_BUFFER: + descriptor_set->vk_descriptor_writes[0].pTexelBufferView = &vk_buffer_view; + break; + default: + assert(false); + break; + } + VK_CALL(vkUpdateDescriptorSets(device->vk_device, 1, descriptor_set->vk_descriptor_writes, 0, NULL)); + } +} + /* dst and src contain the same data unless another thread overwrites dst. The array index is * calculated from dst, and src is thread safe. */ static void d3d12_desc_write_vk_heap(const struct d3d12_desc *dst, const struct d3d12_desc *src, @@ -2186,6 +2228,7 @@ static void d3d12_desc_write_vk_heap(const struct d3d12_desc *dst, const struct struct d3d12_descriptor_heap_vk_set *descriptor_set; struct d3d12_descriptor_heap *descriptor_heap; const struct vkd3d_vk_device_procs *vk_procs; + bool is_null = false;
descriptor_heap = vkd3d_gpu_descriptor_allocator_heap_from_descriptor(&device->gpu_descriptor_allocator, dst); descriptor_set = &descriptor_heap->vk_descriptor_sets[vkd3d_vk_descriptor_set_index_from_vk_descriptor_type( @@ -2201,14 +2244,16 @@ static void d3d12_desc_write_vk_heap(const struct d3d12_desc *dst, const struct { case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: descriptor_set->vk_descriptor_writes[0].pBufferInfo = &src->u.vk_cbv_info; + is_null = !src->u.vk_cbv_info.buffer; break; case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: - descriptor_set->vk_image_infos[0].imageView = src->u.view_info.view->u.vk_image_view; + is_null = !(descriptor_set->vk_image_infos[0].imageView = src->u.view_info.view->u.vk_image_view); break; case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: descriptor_set->vk_descriptor_writes[0].pTexelBufferView = &src->u.view_info.view->u.vk_buffer_view; + is_null = !src->u.view_info.view->u.vk_buffer_view; break; case VK_DESCRIPTOR_TYPE_SAMPLER: descriptor_set->vk_image_infos[0].sampler = src->u.view_info.view->u.vk_sampler; @@ -2217,6 +2262,14 @@ static void d3d12_desc_write_vk_heap(const struct d3d12_desc *dst, const struct ERR("Unhandled descriptor type %#x.\n", src->vk_descriptor_type); break; } + if (is_null && device->vk_info.EXT_robustness2) + { + d3d12_desc_write_vk_heap_null_descriptor(descriptor_heap, + descriptor_set->vk_descriptor_writes[0].dstArrayElement, device); + vkd3d_mutex_unlock(&descriptor_heap->vk_sets_mutex); + return; + } + VK_CALL(vkUpdateDescriptorSets(device->vk_device, 1, descriptor_set->vk_descriptor_writes, 0, NULL));
if (src->magic == VKD3D_DESCRIPTOR_MAGIC_UAV && src->u.view_info.view->vk_counter_view)
On Mon, 21 Mar 2022 at 16:25, Conor McCarthy cmccarthy@codeweavers.com wrote:
Binding a shader with the wrong null descriptor type works in Windows. The introduction of Vulkan-backed heaps may cause a regression in clients which do this, because the written index will remain unpopulated in all other sets, but a shader may access it in one of them.
Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com
libs/vkd3d/resource.c | 55 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-)
Perhaps I'm just a bit "out of it", but it's not clear to me what "the wrong null descriptor type" means above. I gather from the contents of the patch that if we're writing a NULL descriptor at a particular index we should also clear other descriptor types at that same index; is that right? That would make sense, but I'd also imagine that would be the case if we're writing a non-NULL descriptor. A test demonstrating the issue would also be helpful, of course...
@@ -2217,6 +2262,14 @@ static void d3d12_desc_write_vk_heap(const struct d3d12_desc *dst, const struct ERR("Unhandled descriptor type %#x.\n", src->vk_descriptor_type); break; }
- if (is_null && device->vk_info.EXT_robustness2)
- {
d3d12_desc_write_vk_heap_null_descriptor(descriptor_heap,
descriptor_set->vk_descriptor_writes[0].dstArrayElement, device);
vkd3d_mutex_unlock(&descriptor_heap->vk_sets_mutex);
return;
- }
So at the risk that I'm just not understanding the issue very well, why does this need EXT_robustness2, and why is it limited to the case where a NULL descriptor is written?
March 22, 2022 3:14 AM, "Henri Verbeet" hverbeet@gmail.com wrote:
Perhaps I'm just a bit "out of it", but it's not clear to me what "the wrong null descriptor type" means above. I gather from the contents of the patch that if we're writing a NULL descriptor at a particular index we should also clear other descriptor types at that same index; is that right? That would make sense, but I'd also imagine that would be the case if we're writing a non-NULL descriptor. A test demonstrating the issue would also be helpful, of course...
A root signature descriptor range may declare, say, an SRV, and a shader may bind to it as such, but there's no constraint on what actually gets written there, so the client may write a UAV. This works if the descriptor is null, but with Vulkan-backed heaps, the UAV will be in a different set, and the shader accessing the SRV set will find an uninitialised descriptor.
This problem can also be eliminated by mutable descriptors, which all go in one set. The reduction in resource usage alone makes them worthwhile, so I intend to make a patch, but they are only available on RADV.
So at the risk that I'm just not understanding the issue very well, why does this need EXT_robustness2, and why is it limited to the case where a NULL descriptor is written?
It's much simpler with EXT_robustness2. Otherwise we'd need to create a set of null views. I assume the dimension won't matter much, e.g. if a null 3D SRV is written, a null 2D UAV will work in the UAV set. We could do that, but since the issue will only exist where descriptor indexing is available but EXT_robustness2 is not, I think it will show up rarely.
On Mon, 21 Mar 2022 at 16:25, Conor McCarthy cmccarthy@codeweavers.com wrote:
Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com
libs/vkd3d/device.c | 8 +++ libs/vkd3d/resource.c | 101 +++++++++++++++++++++++++++++++++++-- libs/vkd3d/vkd3d_private.h | 5 ++ 3 files changed, 109 insertions(+), 5 deletions(-)
So what does this get us over the current scheme? I could of course take some educated guesses, but ideally I wouldn't have to. Note also that the commit log may be read by fellow developers that may be a fair bit less familiar with Direct3D, Vulkan, vkd3d, or some combination of those.
@@ -2782,7 +2782,7 @@ void d3d12_desc_create_cbv(struct d3d12_desc *descriptor, /* NULL descriptor */ buffer_info->buffer = device->null_resources.vk_buffer; buffer_info->offset = 0;
buffer_info->range = VKD3D_NULL_BUFFER_SIZE;
}buffer_info->range = device->null_resources.vk_buffer ? VKD3D_NULL_BUFFER_SIZE : VK_WHOLE_SIZE;
Wouldn't VK_WHOLE_SIZE work in either case?
+static bool vkd3d_create_null_texture_view(const struct d3d12_device *device, struct vkd3d_view **view) +{
- struct vkd3d_view *object;
- if (!(object = vkd3d_view_create(VKD3D_VIEW_TYPE_IMAGE)))
return false;
- object->u.vk_image_view = VK_NULL_HANDLE;
- object->format = vkd3d_get_format(device, VKD3D_NULL_VIEW_FORMAT, false);
- object->info.texture.vk_view_type = VK_IMAGE_VIEW_TYPE_2D;
- object->info.texture.miplevel_idx = 0;
- object->info.texture.layer_idx = 0;
- object->info.texture.layer_count = 1;
- *view = object;
- return true;
+}
+static void vkd3d_create_vk_null_srv(struct d3d12_desc *descriptor, struct d3d12_device *device,
const D3D12_SHADER_RESOURCE_VIEW_DESC *desc)
+{
- struct vkd3d_view *view;
- if (!desc)
- {
WARN("View desc is required for NULL view.\n");
return;
- }
- if (desc->ViewDimension == D3D12_SRV_DIMENSION_BUFFER)
- {
if (!vkd3d_create_buffer_view(device, VK_NULL_HANDLE, vkd3d_get_format(device, DXGI_FORMAT_R32_UINT, false),
0, VKD3D_NULL_BUFFER_SIZE, &view))
{
return;
}
descriptor->vk_descriptor_type = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
- }
- else
- {
if (!vkd3d_create_null_texture_view(device, &view))
return;
descriptor->vk_descriptor_type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
- }
- descriptor->magic = VKD3D_DESCRIPTOR_MAGIC_SRV;
- descriptor->u.view_info.view = view;
- descriptor->u.view_info.written_serial_id = view->serial_id;
+}
This doesn't look all that different from the existing vkd3d_create_null_srv() path; the main difference appears to be passing VK_NULL_HANDLE instead one of the "null buffer" in the case of buffer views, and vkd3d_create_null_texture_view() looks fairly similar to calling vkd3d_create_texture_view() with VK_NULL_HANDLE as "vk_image" parameter. Could we just handle EXT_robustness2 support in vkd3d_create_buffer_view() and vkd3d_create_buffer_view() and avoid the function pointers?
+static void vkd3d_create_vk_null_uav(struct d3d12_desc *descriptor, struct d3d12_device *device,
const D3D12_UNORDERED_ACCESS_VIEW_DESC *desc)
+{
- struct vkd3d_view *view;
- if (!desc)
- {
WARN("View desc is required for NULL view.\n");
return;
- }
- if (desc->ViewDimension == D3D12_UAV_DIMENSION_BUFFER)
- {
if (!vkd3d_create_buffer_view(device, VK_NULL_HANDLE, vkd3d_get_format(device, DXGI_FORMAT_R32_UINT, false),
0, VKD3D_NULL_BUFFER_SIZE, &view))
{
return;
}
descriptor->vk_descriptor_type = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
- }
- else
- {
if (!vkd3d_create_null_texture_view(device, &view))
return;
descriptor->vk_descriptor_type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
- }
- descriptor->magic = VKD3D_DESCRIPTOR_MAGIC_UAV;
- descriptor->u.view_info.view = view;
- descriptor->u.view_info.written_serial_id = view->serial_id;
+}
And I think that would largely apply here as well.
@@ -4421,6 +4502,16 @@ HRESULT vkd3d_init_null_resources(struct vkd3d_null_resources *null_resources,
memset(null_resources, 0, sizeof(*null_resources));
- if (device->vk_info.EXT_robustness2)
- {
device->create_null_srv = vkd3d_create_vk_null_srv;
device->create_null_uav = vkd3d_create_vk_null_uav;
return S_OK;
- }
- device->create_null_srv = vkd3d_create_null_srv;
- device->create_null_uav = vkd3d_create_null_uav;
If we are going to have these function pointers though, I don't think the naming (e.g. vkd3d_create_null_srv() vs vkd3d_create_vk_null_srv()) is very descriptive. Also, we'd typically store these in an "ops" structure. The case for that perhaps isn't as obvious here as it would be in some other cases, but there's something to be said for consistency.