UINT_MAX is valid for specifying all remaining layers in all view types, although it's only documented for TEXTURE3D RTVs. If unhandled, UINT_MAX will be passed to vkd3d_compute_workgroup_count() during UAV clears, leading to nasty results in RADV.
Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- libs/vkd3d/resource.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+)
diff --git a/libs/vkd3d/resource.c b/libs/vkd3d/resource.c index 1ca23a90..16dd07db 100644 --- a/libs/vkd3d/resource.c +++ b/libs/vkd3d/resource.c @@ -2477,6 +2477,25 @@ static bool init_default_texture_view_desc(struct vkd3d_texture_view_desc *desc, return true; }
+static unsigned int vkd3d_get_texture_layer_count(unsigned int layer_idx, unsigned int layer_count, + const D3D12_RESOURCE_DESC *desc) +{ + if (desc->DepthOrArraySize > layer_idx) + { + unsigned int max_layer_count = desc->DepthOrArraySize - layer_idx; + + if (layer_count <= max_layer_count) + return layer_count; + + if (layer_count != UINT_MAX) + WARN("Layer count %u exceeds maximum %u.\n", layer_count, max_layer_count); + return max_layer_count; + } + + WARN("Layer index %u exceeds maximum available layer %u.\n", layer_idx, desc->DepthOrArraySize - 1); + return 1; +} + bool vkd3d_create_texture_view(struct d3d12_device *device, VkImage vk_image, const struct vkd3d_texture_view_desc *desc, struct vkd3d_view **view) { @@ -2758,6 +2777,7 @@ void d3d12_desc_create_srv(struct d3d12_desc *descriptor, default: FIXME("Unhandled view dimension %#x.\n", desc->ViewDimension); } + /* Allow a UINT_MAX layer count through as it equals VK_REMAINING_ARRAY_LAYERS. */ }
if (!vkd3d_create_texture_view(device, resource->u.vk_image, &vkd3d_desc, &view)) @@ -2931,6 +2951,9 @@ static void vkd3d_create_texture_uav(struct d3d12_desc *descriptor, default: FIXME("Unhandled view dimension %#x.\n", desc->ViewDimension); } + /* Prevent problems with UAV clears where the layer count is UINT_MAX. */ + vkd3d_desc.layer_count = vkd3d_get_texture_layer_count(vkd3d_desc.layer_idx, + vkd3d_desc.layer_count, &resource->desc); }
if (!vkd3d_create_texture_view(device, resource->u.vk_image, &vkd3d_desc, &view))
Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- libs/vkd3d/resource.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/libs/vkd3d/resource.c b/libs/vkd3d/resource.c index 16dd07db..c5666b67 100644 --- a/libs/vkd3d/resource.c +++ b/libs/vkd3d/resource.c @@ -3205,6 +3205,10 @@ void d3d12_rtv_desc_create_rtv(struct d3d12_rtv_desc *rtv_desc, struct d3d12_dev default: FIXME("Unhandled view dimension %#x.\n", desc->ViewDimension); } + /* ArraySize or WSize can be UINT_MAX. This is equal to VK_REMAINING_ARRAY_LAYERS, but it is not + * valid for TEXTURE3D or for Vulkan frame buffers. It is easiest to deal with UINT_MAX here. */ + vkd3d_desc.layer_count = vkd3d_get_texture_layer_count(vkd3d_desc.layer_idx, + vkd3d_desc.layer_count, &resource->desc); } else if (resource->desc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE3D) {
Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- libs/vkd3d/resource.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/libs/vkd3d/resource.c b/libs/vkd3d/resource.c index c5666b67..725ce34f 100644 --- a/libs/vkd3d/resource.c +++ b/libs/vkd3d/resource.c @@ -3298,6 +3298,9 @@ void d3d12_dsv_desc_create_dsv(struct d3d12_dsv_desc *dsv_desc, struct d3d12_dev default: FIXME("Unhandled view dimension %#x.\n", desc->ViewDimension); } + /* A UINT_MAX layer count is not compatible with Vulkan frame buffers. */ + vkd3d_desc.layer_count = vkd3d_get_texture_layer_count(vkd3d_desc.layer_idx, + vkd3d_desc.layer_count, &resource->desc); }
assert(d3d12_resource_is_texture(resource));
Testing without the fixes in vkd3d_create_texture_uav() has nasty results in RADV and possibly others.
Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- tests/d3d12.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/tests/d3d12.c b/tests/d3d12.c index 8dbced41..382fef51 100644 --- a/tests/d3d12.c +++ b/tests/d3d12.c @@ -4982,6 +4982,8 @@ static void test_clear_unordered_access_view_image(void) {0x3f000000, 0, 0, 0}, 0x3f000000, true}, {DXGI_FORMAT_R32_FLOAT, 1, IMAGE_SIZE, 0, 3, 2, 0, {}, {0x3f000000, 0, 0, 0}, 0x3f000000, true}, + /* Test clearing a UINT_MAX layer count. */ + {DXGI_FORMAT_R32_FLOAT, 1, IMAGE_SIZE, 0, 0, UINT_MAX, 0, {}, {1, 0, 0, 0}, 1}, /* Test a single clear rect. */ {DXGI_FORMAT_R32_FLOAT, 1, 1, 0, 0, 1, 1, {{1, 2, IMAGE_SIZE - 4, IMAGE_SIZE - 2}}, {1, 0, 0, 0}, 1},
Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- tests/d3d12.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-)
diff --git a/tests/d3d12.c b/tests/d3d12.c index 382fef51..aad15702 100644 --- a/tests/d3d12.c +++ b/tests/d3d12.c @@ -4640,7 +4640,7 @@ static void test_clear_render_target_view(void) rtv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; rtv_desc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2DARRAY; rtv_desc.Texture2DArray.FirstArraySlice = i; - rtv_desc.Texture2DArray.ArraySize = 1; + rtv_desc.Texture2DArray.ArraySize = (i == ARRAY_SIZE(array_colors) - 1) ? UINT_MAX : 1;
ID3D12Device_CreateRenderTargetView(device, resource, &rtv_desc, rtv_handle);
@@ -4671,7 +4671,7 @@ static void test_clear_render_target_view(void) rtv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; rtv_desc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2DMSARRAY; rtv_desc.Texture2DMSArray.FirstArraySlice = i; - rtv_desc.Texture2DMSArray.ArraySize = 1; + rtv_desc.Texture2DMSArray.ArraySize = (i == ARRAY_SIZE(array_colors) - 1) ? UINT_MAX : 1;
ID3D12Device_CreateRenderTargetView(device, resource, &rtv_desc, rtv_handle);
@@ -4727,6 +4727,23 @@ static void test_clear_render_target_view(void) check_readback_data_uint(&rb, &box, 0xbf4c7f19, 1); release_resource_readback(&rb);
+ rtv_desc.Texture3D.FirstWSlice = 30; + rtv_desc.Texture3D.WSize = UINT_MAX; + ID3D12Device_CreateRenderTargetView(device, resource, &rtv_desc, rtv_handle); + + reset_command_list(command_list, context.allocator); + transition_resource_state(command_list, resource, + D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET); + ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, rtv_handle, green, 0, NULL); + transition_resource_state(command_list, resource, + D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE); + get_texture_readback_with_command_list(resource, 0, &rb, queue, command_list); + set_box(&box, 0, 0, 4, 32, 32, 30); + check_readback_data_uint(&rb, &box, 0xbf4c7f19, 1); + set_box(&box, 0, 0, 30, 32, 32, 32); + check_readback_data_uint(&rb, &box, 0xff00ff00, 1); + release_resource_readback(&rb); + ID3D12Resource_Release(resource); ID3D12DescriptorHeap_Release(rtv_heap); destroy_test_context(&context);
Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- tests/d3d12.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
diff --git a/tests/d3d12.c b/tests/d3d12.c index aad15702..1699b3f8 100644 --- a/tests/d3d12.c +++ b/tests/d3d12.c @@ -4453,6 +4453,17 @@ static void test_clear_depth_stencil_view(void) reset_command_list(command_list, context.allocator); }
+ transition_resource_state(command_list, ds.texture, + D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_DEPTH_WRITE); + dsv_desc.Texture2DArray.ArraySize = UINT_MAX; + ID3D12Device_CreateDepthStencilView(device, ds.texture, &dsv_desc, ds.dsv_handle); + ID3D12GraphicsCommandList_ClearDepthStencilView(command_list, ds.dsv_handle, + D3D12_CLEAR_FLAG_DEPTH, expected_values[4], 0, 0, NULL); + + transition_resource_state(command_list, ds.texture, + D3D12_RESOURCE_STATE_DEPTH_WRITE, D3D12_RESOURCE_STATE_COPY_SOURCE); + check_sub_resource_float(ds.texture, 5, queue, command_list, expected_values[4], 1); + destroy_depth_stencil(&ds); destroy_test_context(&context); }