[PATCH vkd3d 4/7] vkd3d: Re-implement d3d12_command_list_ClearUnorderedAccessViewUint().

Henri Verbeet hverbeet at codeweavers.com
Mon Nov 25 08:05:39 CST 2019


From: Philip Rebohle <philip.rebohle at 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 at tu-dortmund.de>
Signed-off-by: Henri Verbeet <hverbeet at 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, {},
-- 
2.11.0




More information about the wine-devel mailing list