From: Philip Rebohle philip.rebohle@tu-dortmund.de
Addresses the following limitations of the previous implementation: - Only R32_{UINT,TYPELESS} were supported for buffers. - Clearing an image UAV did not behave correctly for images with non-UINT formats. - Due to the use of transfer operations, extra memory barriers were needed.
If necessary, this will create a temporary view with a bit-compatible UINT format for the resource in order to perform a bit-exact clear.
Signed-off-by: Philip Rebohle philip.rebohle@tu-dortmund.de Signed-off-by: Henri Verbeet hverbeet@codeweavers.com --- This supersedes patches 173346, 173347 and 173324.
libs/vkd3d/command.c | 116 ++++++++++++++++----------------------------- libs/vkd3d/resource.c | 20 ++------ libs/vkd3d/utils.c | 31 ++++++++++++ libs/vkd3d/vkd3d_private.h | 19 ++++++++ tests/d3d12.c | 22 ++++----- 5 files changed, 104 insertions(+), 104 deletions(-)
diff --git a/libs/vkd3d/command.c b/libs/vkd3d/command.c index ade51ba..e3810e2 100644 --- a/libs/vkd3d/command.c +++ b/libs/vkd3d/command.c @@ -4984,96 +4984,60 @@ static void STDMETHODCALLTYPE d3d12_command_list_ClearUnorderedAccessViewUint(ID const UINT values[4], UINT rect_count, const D3D12_RECT *rects) { struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList1(iface); - const struct vkd3d_vk_device_procs *vk_procs; - const struct vkd3d_vulkan_info *vk_info; - const struct d3d12_desc *cpu_descriptor; + struct d3d12_device *device = list->device; + struct vkd3d_view *view, *uint_view = NULL; + struct vkd3d_texture_view_desc view_desc; + const struct vkd3d_format *uint_format; struct d3d12_resource *resource_impl; - VkBufferMemoryBarrier buffer_barrier; - VkImageMemoryBarrier image_barrier; - VkPipelineStageFlags stage_mask; - VkImageSubresourceRange range; - VkClearColorValue color; + VkClearColorValue colour;
TRACE("iface %p, gpu_handle %#"PRIx64", cpu_handle %lx, resource %p, values %p, rect_count %u, rects %p.\n", iface, gpu_handle.ptr, cpu_handle.ptr, resource, values, rect_count, rects);
- vk_procs = &list->device->vk_procs; - vk_info = &list->device->vk_info; - resource_impl = unsafe_impl_from_ID3D12Resource(resource); + view = d3d12_desc_from_cpu_handle(cpu_handle)->u.view; + memcpy(colour.uint32, values, sizeof(colour.uint32));
- d3d12_command_list_track_resource_usage(list, resource_impl); - - if (rect_count) - { - FIXME("Clear rects not supported.\n"); - return; - } - - d3d12_command_list_end_current_render_pass(list); - - cpu_descriptor = d3d12_desc_from_cpu_handle(cpu_handle); - - if (d3d12_resource_is_buffer(resource_impl)) + if (view->format->type != VKD3D_FORMAT_TYPE_UINT) { - if (cpu_descriptor->u.view->format->vk_format != VK_FORMAT_R32_UINT) + if (!(uint_format = vkd3d_find_uint_format(device, view->format->dxgi_format))) { - FIXME("Not supported for UAV descriptor %p.\n", cpu_descriptor); + ERR("Unhandled format %#x.\n", view->format->dxgi_format); return; }
- VK_CALL(vkCmdFillBuffer(list->vk_command_buffer, resource_impl->u.vk_buffer, - cpu_descriptor->u.view->info.buffer.offset, cpu_descriptor->u.view->info.buffer.size, values[0])); - - buffer_barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; - buffer_barrier.pNext = NULL; - buffer_barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - buffer_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - buffer_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - buffer_barrier.buffer = resource_impl->u.vk_buffer; - buffer_barrier.offset = cpu_descriptor->u.view->info.buffer.offset; - buffer_barrier.size = cpu_descriptor->u.view->info.buffer.size; - - vk_barrier_parameters_from_d3d12_resource_state(D3D12_RESOURCE_STATE_UNORDERED_ACCESS, 0, - resource_impl, list->vk_queue_flags, vk_info, &buffer_barrier.dstAccessMask, &stage_mask, NULL); - - VK_CALL(vkCmdPipelineBarrier(list->vk_command_buffer, - VK_PIPELINE_STAGE_TRANSFER_BIT, stage_mask, 0, - 0, NULL, 1, &buffer_barrier, 0, NULL)); + if (d3d12_resource_is_buffer(resource_impl)) + { + if (!vkd3d_create_buffer_view(device, resource_impl->u.vk_buffer, uint_format, + view->info.buffer.offset, view->info.buffer.size, &uint_view)) + { + ERR("Failed to create buffer view.\n"); + return; + } + } + else + { + memset(&view_desc, 0, sizeof(view_desc)); + view_desc.view_type = view->info.texture.vk_view_type; + view_desc.format = uint_format; + view_desc.miplevel_idx = view->info.texture.miplevel_idx; + view_desc.miplevel_count = 1; + view_desc.layer_idx = view->info.texture.layer_idx; + view_desc.layer_count = view->info.texture.layer_count; + + if (!vkd3d_create_texture_view(device, resource_impl->u.vk_image, &view_desc, &uint_view)) + { + ERR("Failed to create image view.\n"); + return; + } + } + view = uint_view; } - else - { - color.uint32[0] = values[0]; - color.uint32[1] = values[1]; - color.uint32[2] = values[2]; - color.uint32[3] = values[3]; - - range.aspectMask = cpu_descriptor->u.view->format->vk_aspect_mask; - range.baseMipLevel = cpu_descriptor->u.view->info.texture.miplevel_idx; - range.levelCount = 1; - range.baseArrayLayer = cpu_descriptor->u.view->info.texture.layer_idx; - range.layerCount = cpu_descriptor->u.view->info.texture.layer_count; - - VK_CALL(vkCmdClearColorImage(list->vk_command_buffer, - resource_impl->u.vk_image, VK_IMAGE_LAYOUT_GENERAL, &color, 1, &range)); - - image_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - image_barrier.pNext = NULL; - image_barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - image_barrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL; - image_barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL; - image_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - image_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - image_barrier.image = resource_impl->u.vk_image; - image_barrier.subresourceRange = range; - - vk_barrier_parameters_from_d3d12_resource_state(D3D12_RESOURCE_STATE_UNORDERED_ACCESS, 0, - resource_impl, list->vk_queue_flags, vk_info, &image_barrier.dstAccessMask, &stage_mask, NULL);
- VK_CALL(vkCmdPipelineBarrier(list->vk_command_buffer, - VK_PIPELINE_STAGE_TRANSFER_BIT, stage_mask, 0, - 0, NULL, 0, NULL, 1, &image_barrier)); - } + d3d12_command_list_clear_uav(list, resource_impl, view, &colour, rect_count, rects); + + if (uint_view) + vkd3d_view_decref(uint_view, device); }
static void STDMETHODCALLTYPE d3d12_command_list_ClearUnorderedAccessViewFloat(ID3D12GraphicsCommandList1 *iface, diff --git a/libs/vkd3d/resource.c b/libs/vkd3d/resource.c index 7d22ba4..89733ce 100644 --- a/libs/vkd3d/resource.c +++ b/libs/vkd3d/resource.c @@ -2150,8 +2150,7 @@ static bool vkd3d_create_vk_buffer_view(struct d3d12_device *device, return vr == VK_SUCCESS; }
-static bool vkd3d_create_buffer_view(struct d3d12_device *device, - VkBuffer vk_buffer, const struct vkd3d_format *format, +bool vkd3d_create_buffer_view(struct d3d12_device *device, VkBuffer vk_buffer, const struct vkd3d_format *format, VkDeviceSize offset, VkDeviceSize size, struct vkd3d_view **view) { const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs; @@ -2350,18 +2349,6 @@ static void vk_component_mapping_compose(VkComponentMapping *dst, const VkCompon dst->a = swizzle_vk_component(&a, a.a, b->a); }
-struct vkd3d_texture_view_desc -{ - VkImageViewType view_type; - const struct vkd3d_format *format; - unsigned int miplevel_idx; - unsigned int miplevel_count; - unsigned int layer_idx; - unsigned int layer_count; - VkComponentMapping components; - bool allowed_swizzle; -}; - static bool init_default_texture_view_desc(struct vkd3d_texture_view_desc *desc, struct d3d12_resource *resource, DXGI_FORMAT view_format) { @@ -2409,9 +2396,8 @@ static bool init_default_texture_view_desc(struct vkd3d_texture_view_desc *desc, return true; }
-static bool vkd3d_create_texture_view(struct d3d12_device *device, - VkImage vk_image, const struct vkd3d_texture_view_desc *desc, - struct vkd3d_view **view) +bool vkd3d_create_texture_view(struct d3d12_device *device, VkImage vk_image, + const struct vkd3d_texture_view_desc *desc, struct vkd3d_view **view) { const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs; const struct vkd3d_format *format = desc->format; diff --git a/libs/vkd3d/utils.c b/libs/vkd3d/utils.c index cf0448d..7abfd42 100644 --- a/libs/vkd3d/utils.c +++ b/libs/vkd3d/utils.c @@ -451,6 +451,37 @@ const struct vkd3d_format *vkd3d_get_format(const struct d3d12_device *device, return NULL; }
+const struct vkd3d_format *vkd3d_find_uint_format(const struct d3d12_device *device, DXGI_FORMAT dxgi_format) +{ + DXGI_FORMAT typeless_format = DXGI_FORMAT_UNKNOWN; + const struct vkd3d_format *vkd3d_format; + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(vkd3d_format_compatibility_info); ++i) + { + if (vkd3d_format_compatibility_info[i].format == dxgi_format) + { + typeless_format = vkd3d_format_compatibility_info[i].typeless_format; + break; + } + } + + if (!typeless_format) + return NULL; + + for (i = 0; i < ARRAY_SIZE(vkd3d_format_compatibility_info); ++i) + { + if (vkd3d_format_compatibility_info[i].typeless_format != typeless_format) + continue; + + vkd3d_format = vkd3d_get_format(device, vkd3d_format_compatibility_info[i].format, false); + if (vkd3d_format->type == VKD3D_FORMAT_TYPE_UINT) + return vkd3d_format; + } + + return NULL; +} + void vkd3d_format_copy_data(const struct vkd3d_format *format, const uint8_t *src, unsigned int src_row_pitch, unsigned int src_slice_pitch, uint8_t *dst, unsigned int dst_row_pitch, unsigned int dst_slice_pitch, unsigned int w, unsigned int h, unsigned int d) diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h index 933c7c4..df8d1a1 100644 --- a/libs/vkd3d/vkd3d_private.h +++ b/libs/vkd3d/vkd3d_private.h @@ -497,6 +497,23 @@ struct vkd3d_view void vkd3d_view_decref(struct vkd3d_view *view, struct d3d12_device *device) DECLSPEC_HIDDEN; void vkd3d_view_incref(struct vkd3d_view *view) DECLSPEC_HIDDEN;
+struct vkd3d_texture_view_desc +{ + VkImageViewType view_type; + const struct vkd3d_format *format; + unsigned int miplevel_idx; + unsigned int miplevel_count; + unsigned int layer_idx; + unsigned int layer_count; + VkComponentMapping components; + bool allowed_swizzle; +}; + +bool vkd3d_create_buffer_view(struct d3d12_device *device, VkBuffer vk_buffer, const struct vkd3d_format *format, + VkDeviceSize offset, VkDeviceSize size, struct vkd3d_view **view) DECLSPEC_HIDDEN; +bool vkd3d_create_texture_view(struct d3d12_device *device, VkImage vk_image, + const struct vkd3d_texture_view_desc *desc, struct vkd3d_view **view) DECLSPEC_HIDDEN; + struct d3d12_desc { uint32_t magic; @@ -1225,6 +1242,8 @@ void vkd3d_format_copy_data(const struct vkd3d_format *format, const uint8_t *sr
const struct vkd3d_format *vkd3d_get_format(const struct d3d12_device *device, DXGI_FORMAT dxgi_format, bool depth_stencil) DECLSPEC_HIDDEN; +const struct vkd3d_format *vkd3d_find_uint_format(const struct d3d12_device *device, + DXGI_FORMAT dxgi_format) DECLSPEC_HIDDEN;
HRESULT vkd3d_init_format_info(struct d3d12_device *device) DECLSPEC_HIDDEN; void vkd3d_cleanup_format_info(struct d3d12_device *device) DECLSPEC_HIDDEN; diff --git a/tests/d3d12.c b/tests/d3d12.c index 3b5264f..5d549e2 100644 --- a/tests/d3d12.c +++ b/tests/d3d12.c @@ -4808,19 +4808,19 @@ static void test_clear_unordered_access_view_buffer(void) {11, 0, 0, 0}, 11},
{DXGI_FORMAT_R32_FLOAT, { 0, BUFFER_SIZE / sizeof(uint32_t), 0, 0, D3D12_BUFFER_UAV_FLAG_NONE}, - {0, 0, 0, 0}, 0, false, true}, + {0, 0, 0, 0}, 0}, {DXGI_FORMAT_R32_FLOAT, { 0, BUFFER_SIZE / sizeof(uint32_t), 0, 0, D3D12_BUFFER_UAV_FLAG_NONE}, - {1, 0, 0, 0}, 1, false, true}, + {1, 0, 0, 0}, 1}, {DXGI_FORMAT_R32_FLOAT, { 0, BUFFER_SIZE / sizeof(uint32_t), 0, 0, D3D12_BUFFER_UAV_FLAG_NONE}, {0x3f800000 /* 1.0f */, 0, 0, 0}, 0x3f800000 /* 1.0f */, true},
{DXGI_FORMAT_R16G16_UINT, { 0, BUFFER_SIZE / sizeof(uint32_t), 0, 0, D3D12_BUFFER_UAV_FLAG_NONE}, - {0x1234, 0xabcd, 0, 0}, 0xabcd1234, false, true}, + {0x1234, 0xabcd, 0, 0}, 0xabcd1234}, {DXGI_FORMAT_R16G16_UINT, { 0, BUFFER_SIZE / sizeof(uint32_t), 0, 0, D3D12_BUFFER_UAV_FLAG_NONE}, {0x10000, 0, 0, 0}, 0, false, true},
{DXGI_FORMAT_R16G16_UNORM, { 0, BUFFER_SIZE / sizeof(uint32_t), 0, 0, D3D12_BUFFER_UAV_FLAG_NONE}, - {0x1234, 0xabcd, 0, 0}, 0xabcd1234, false, true}, + {0x1234, 0xabcd, 0, 0}, 0xabcd1234}, {DXGI_FORMAT_R16G16_UNORM, { 0, BUFFER_SIZE / sizeof(uint32_t), 0, 0, D3D12_BUFFER_UAV_FLAG_NONE}, {0x3f000000 /* 0.5f */, 0x3f800000 /* 1.0f */, 0, 0}, 0xffff8000, true}, {DXGI_FORMAT_R16G16_UNORM, { 0, BUFFER_SIZE / sizeof(uint32_t), 0, 0, D3D12_BUFFER_UAV_FLAG_NONE}, @@ -4829,12 +4829,12 @@ static void test_clear_unordered_access_view_buffer(void) {0xbf800000 /* -1.0f */, 0 /* 0.0f */, 0x3f000000 /* 1.0f */, 0x3f000000 /* 1.0f */}, 0, true},
{DXGI_FORMAT_R16G16_FLOAT, { 0, BUFFER_SIZE / sizeof(uint32_t), 0, 0, D3D12_BUFFER_UAV_FLAG_NONE}, - {0x1234, 0xabcd, 0, 0}, 0xabcd1234, false, true}, + {0x1234, 0xabcd, 0, 0}, 0xabcd1234}, {DXGI_FORMAT_R16G16_FLOAT, { 0, BUFFER_SIZE / sizeof(uint32_t), 0, 0, D3D12_BUFFER_UAV_FLAG_NONE}, {0x3f000000 /* 0.5f */, 0x3f800000 /* 1.0f */, 0, 0}, 0x3c003800, true},
{DXGI_FORMAT_R8G8B8A8_UINT, { 0, BUFFER_SIZE / sizeof(uint32_t), 0, 0, D3D12_BUFFER_UAV_FLAG_NONE}, - {0x11, 0x22, 0x33, 0x44}, 0x44332211, false, true}, + {0x11, 0x22, 0x33, 0x44}, 0x44332211}, {DXGI_FORMAT_R8G8B8A8_UINT, { 0, BUFFER_SIZE / sizeof(uint32_t), 0, 0, D3D12_BUFFER_UAV_FLAG_NONE}, {0x100, 0, 0, 0}, 0, false, true},
@@ -4995,22 +4995,22 @@ static void test_clear_unordered_access_view_image(void) {0x3f000000, 0, 0, 0}, 0x3f000000, true}, /* 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, false, true}, + {1, 0, 0, 0}, 1}, {DXGI_FORMAT_R32_FLOAT, 1, 1, 0, 0, 1, 1, {{1, 2, IMAGE_SIZE - 4, IMAGE_SIZE - 2}}, {0x3f000000, 0, 0, 0}, 0x3f000000, true}, /* Test multiple clear rects. */ {DXGI_FORMAT_R32_FLOAT, 1, 1, 0, 0, 1, 2, {{1, 2, 3, 4}, {5, 6, 7, 8}}, - {1, 0, 0, 0}, 1, false, true}, + {1, 0, 0, 0}, 1}, {DXGI_FORMAT_R32_FLOAT, 1, 1, 0, 0, 1, 2, {{1, 2, 3, 4}, {5, 6, 7, 8}}, {0x3f000000, 0, 0, 0}, 0x3f000000, true}, /* Test uint clears with formats. */ {DXGI_FORMAT_R16G16_UINT, 1, 1, 0, 0, 1, 0, {}, {1, 2, 3, 4}, 0x00020001}, {DXGI_FORMAT_R16G16_UINT, 1, 1, 0, 0, 1, 0, {}, {0x12345, 0, 0, 0}, 0x00002345, false, true}, - {DXGI_FORMAT_R16G16_UNORM, 1, 1, 0, 0, 1, 0, {}, {1, 2, 3, 4}, 0x00020001, false, true}, - {DXGI_FORMAT_R16G16_FLOAT, 1, 1, 0, 0, 1, 0, {}, {1, 2, 3, 4}, 0x00020001, false, true}, + {DXGI_FORMAT_R16G16_UNORM, 1, 1, 0, 0, 1, 0, {}, {1, 2, 3, 4}, 0x00020001}, + {DXGI_FORMAT_R16G16_FLOAT, 1, 1, 0, 0, 1, 0, {}, {1, 2, 3, 4}, 0x00020001}, {DXGI_FORMAT_R8G8B8A8_UINT, 1, 1, 0, 0, 1, 0, {}, {1, 2, 3, 4}, 0x04030201}, {DXGI_FORMAT_R8G8B8A8_UINT, 1, 1, 0, 0, 1, 0, {}, {0x123, 0, 0, 0}, 0x00000023, false, true}, - {DXGI_FORMAT_R8G8B8A8_UNORM, 1, 1, 0, 0, 1, 0, {}, {1, 2, 3, 4}, 0x04030201, false, true}, + {DXGI_FORMAT_R8G8B8A8_UNORM, 1, 1, 0, 0, 1, 0, {}, {1, 2, 3, 4}, 0x04030201}, {DXGI_FORMAT_R11G11B10_FLOAT, 1, 1, 0, 0, 1, 0, {}, {1, 2, 3, 4}, 0x00c01001, false, true}, /* Test float clears with formats. */ {DXGI_FORMAT_R16G16_UNORM, 1, 1, 0, 0, 1, 0, {},