[PATCH vkd3d 4/5] tests: Add a test for texture load instructions.

Zebediah Figura zfigura at codeweavers.com
Sun Oct 3 19:19:08 CDT 2021


Signed-off-by: Zebediah Figura <zfigura at codeweavers.com>
---
 Makefile.am                    |   2 +
 tests/d3d12.c                  |  89 -----------------
 tests/d3d12_test_utils.h       |  89 +++++++++++++++++
 tests/shader_runner_d3d12.c    | 175 ++++++++++++++++++++++++++++++++-
 tests/texture-load.shader_test |  19 ++++
 5 files changed, 281 insertions(+), 93 deletions(-)
 create mode 100644 tests/texture-load.shader_test

diff --git a/Makefile.am b/Makefile.am
index bc33e0f60..921bb7964 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -99,6 +99,7 @@ vkd3d_shader_tests = \
 	tests/swizzle-5.shader_test \
 	tests/swizzle-6.shader_test \
 	tests/swizzle-7.shader_test \
+	tests/texture-load.shader_test \
 	tests/trigonometry.shader_test \
 	tests/writemask-assignop-0.shader_test \
 	tests/writemask-assignop-1.shader_test \
@@ -299,6 +300,7 @@ XFAIL_TESTS = \
 	tests/hlsl-vector-indexing-uniform.shader_test \
 	tests/math.shader_test \
 	tests/max.shader_test \
+	tests/texture-load.shader_test \
 	tests/trigonometry.shader_test \
 	tests/writemask-assignop-1.shader_test
 endif
diff --git a/tests/d3d12.c b/tests/d3d12.c
index b4c136137..3ef93e911 100644
--- a/tests/d3d12.c
+++ b/tests/d3d12.c
@@ -155,22 +155,6 @@ static void uav_barrier(ID3D12GraphicsCommandList *list, ID3D12Resource *resourc
     ID3D12GraphicsCommandList_ResourceBarrier(list, 1, &barrier);
 }
 
-static void copy_sub_resource_data(const D3D12_MEMCPY_DEST *dst, const D3D12_SUBRESOURCE_DATA *src,
-        unsigned int row_count, unsigned int slice_count, size_t row_size)
-{
-    const BYTE *src_slice_ptr;
-    BYTE *dst_slice_ptr;
-    unsigned int z, y;
-
-    for (z = 0; z < slice_count; ++z)
-    {
-        dst_slice_ptr = (BYTE *)dst->pData + z * dst->SlicePitch;
-        src_slice_ptr = (const BYTE*)src->pData + z * src->SlicePitch;
-        for (y = 0; y < row_count; ++y)
-            memcpy(dst_slice_ptr + y * dst->RowPitch, src_slice_ptr + y * src->RowPitch, row_size);
-    }
-}
-
 #define upload_buffer_data(a, b, c, d, e, f) upload_buffer_data_(__LINE__, a, b, c, d, e, f)
 static void upload_buffer_data_(unsigned int line, ID3D12Resource *buffer, size_t offset,
         size_t size, const void *data, ID3D12CommandQueue *queue, ID3D12GraphicsCommandList *command_list)
@@ -196,79 +180,6 @@ static void upload_buffer_data_(unsigned int line, ID3D12Resource *buffer, size_
     ID3D12Device_Release(device);
 }
 
-#define upload_texture_data(a, b, c, d, e) upload_texture_data_(__LINE__, a, b, c, d, e)
-static void upload_texture_data_(unsigned int line, ID3D12Resource *texture,
-        const D3D12_SUBRESOURCE_DATA *data, unsigned int sub_resource_count,
-        ID3D12CommandQueue *queue, ID3D12GraphicsCommandList *command_list)
-{
-    D3D12_TEXTURE_COPY_LOCATION dst_location, src_location;
-    D3D12_PLACED_SUBRESOURCE_FOOTPRINT *layouts;
-    uint64_t *row_sizes, required_size;
-    D3D12_RESOURCE_DESC resource_desc;
-    ID3D12Resource *upload_buffer;
-    D3D12_MEMCPY_DEST dst_data;
-    ID3D12Device *device;
-    UINT *row_counts;
-    unsigned int i;
-    HRESULT hr;
-    void *ptr;
-
-    layouts = calloc(sub_resource_count, sizeof(*layouts));
-    ok(layouts, "Failed to allocate memory.\n");
-    row_counts = calloc(sub_resource_count, sizeof(*row_counts));
-    ok(row_counts, "Failed to allocate memory.\n");
-    row_sizes = calloc(sub_resource_count, sizeof(*row_sizes));
-    ok(row_sizes, "Failed to allocate memory.\n");
-
-    resource_desc = ID3D12Resource_GetDesc(texture);
-    hr = ID3D12Resource_GetDevice(texture, &IID_ID3D12Device, (void **)&device);
-    ok_(line)(SUCCEEDED(hr), "Failed to get device, hr %#x.\n", hr);
-
-    ID3D12Device_GetCopyableFootprints(device, &resource_desc, 0, sub_resource_count,
-            0, layouts, row_counts, row_sizes, &required_size);
-
-    upload_buffer = create_upload_buffer_(line, device, required_size, NULL);
-
-    hr = ID3D12Resource_Map(upload_buffer, 0, NULL, (void **)&ptr);
-    ok_(line)(SUCCEEDED(hr), "Failed to map upload buffer, hr %#x.\n", hr);
-    for (i = 0; i < sub_resource_count; ++i)
-    {
-        dst_data.pData = (BYTE *)ptr + layouts[i].Offset;
-        dst_data.RowPitch = layouts[i].Footprint.RowPitch;
-        dst_data.SlicePitch = layouts[i].Footprint.RowPitch * row_counts[i];
-        copy_sub_resource_data(&dst_data, &data[i],
-                row_counts[i], layouts[i].Footprint.Depth, row_sizes[i]);
-    }
-    ID3D12Resource_Unmap(upload_buffer, 0, NULL);
-
-    for (i = 0; i < sub_resource_count; ++i)
-    {
-        dst_location.pResource = texture;
-        dst_location.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
-        dst_location.SubresourceIndex = i;
-
-        src_location.pResource = upload_buffer;
-        src_location.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
-        src_location.PlacedFootprint = layouts[i];
-
-        ID3D12GraphicsCommandList_CopyTextureRegion(command_list,
-                &dst_location, 0, 0, 0, &src_location, NULL);
-    }
-
-    hr = ID3D12GraphicsCommandList_Close(command_list);
-    ok_(line)(SUCCEEDED(hr), "Failed to close command list, hr %#x.\n", hr);
-
-    exec_command_list(queue, command_list);
-    wait_queue_idle(device, queue);
-
-    ID3D12Resource_Release(upload_buffer);
-    ID3D12Device_Release(device);
-
-    free(layouts);
-    free(row_counts);
-    free(row_sizes);
-}
-
 static const DXGI_FORMAT depth_stencil_formats[] =
 {
     DXGI_FORMAT_R32G8X24_TYPELESS,
diff --git a/tests/d3d12_test_utils.h b/tests/d3d12_test_utils.h
index 0374d8d11..5d900f891 100644
--- a/tests/d3d12_test_utils.h
+++ b/tests/d3d12_test_utils.h
@@ -697,6 +697,95 @@ static inline ID3D12Resource *create_default_texture3d_(unsigned int line, ID3D1
             width, height, depth, miplevel_count, format, flags, initial_state);
 }
 
+static void copy_sub_resource_data(const D3D12_MEMCPY_DEST *dst, const D3D12_SUBRESOURCE_DATA *src,
+        unsigned int row_count, unsigned int slice_count, size_t row_size)
+{
+    const BYTE *src_slice_ptr;
+    BYTE *dst_slice_ptr;
+    unsigned int z, y;
+
+    for (z = 0; z < slice_count; ++z)
+    {
+        dst_slice_ptr = (BYTE *)dst->pData + z * dst->SlicePitch;
+        src_slice_ptr = (const BYTE*)src->pData + z * src->SlicePitch;
+        for (y = 0; y < row_count; ++y)
+            memcpy(dst_slice_ptr + y * dst->RowPitch, src_slice_ptr + y * src->RowPitch, row_size);
+    }
+}
+
+#define upload_texture_data(a, b, c, d, e) upload_texture_data_(__LINE__, a, b, c, d, e)
+static inline void upload_texture_data_(unsigned int line, ID3D12Resource *texture,
+        const D3D12_SUBRESOURCE_DATA *data, unsigned int sub_resource_count,
+        ID3D12CommandQueue *queue, ID3D12GraphicsCommandList *command_list)
+{
+    D3D12_TEXTURE_COPY_LOCATION dst_location, src_location;
+    D3D12_PLACED_SUBRESOURCE_FOOTPRINT *layouts;
+    uint64_t *row_sizes, required_size;
+    D3D12_RESOURCE_DESC resource_desc;
+    ID3D12Resource *upload_buffer;
+    D3D12_MEMCPY_DEST dst_data;
+    ID3D12Device *device;
+    UINT *row_counts;
+    unsigned int i;
+    HRESULT hr;
+    void *ptr;
+
+    layouts = calloc(sub_resource_count, sizeof(*layouts));
+    ok(layouts, "Failed to allocate memory.\n");
+    row_counts = calloc(sub_resource_count, sizeof(*row_counts));
+    ok(row_counts, "Failed to allocate memory.\n");
+    row_sizes = calloc(sub_resource_count, sizeof(*row_sizes));
+    ok(row_sizes, "Failed to allocate memory.\n");
+
+    resource_desc = ID3D12Resource_GetDesc(texture);
+    hr = ID3D12Resource_GetDevice(texture, &IID_ID3D12Device, (void **)&device);
+    ok_(line)(SUCCEEDED(hr), "Failed to get device, hr %#x.\n", hr);
+
+    ID3D12Device_GetCopyableFootprints(device, &resource_desc, 0, sub_resource_count,
+            0, layouts, row_counts, row_sizes, &required_size);
+
+    upload_buffer = create_upload_buffer_(line, device, required_size, NULL);
+
+    hr = ID3D12Resource_Map(upload_buffer, 0, NULL, (void **)&ptr);
+    ok_(line)(SUCCEEDED(hr), "Failed to map upload buffer, hr %#x.\n", hr);
+    for (i = 0; i < sub_resource_count; ++i)
+    {
+        dst_data.pData = (BYTE *)ptr + layouts[i].Offset;
+        dst_data.RowPitch = layouts[i].Footprint.RowPitch;
+        dst_data.SlicePitch = layouts[i].Footprint.RowPitch * row_counts[i];
+        copy_sub_resource_data(&dst_data, &data[i],
+                row_counts[i], layouts[i].Footprint.Depth, row_sizes[i]);
+    }
+    ID3D12Resource_Unmap(upload_buffer, 0, NULL);
+
+    for (i = 0; i < sub_resource_count; ++i)
+    {
+        dst_location.pResource = texture;
+        dst_location.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
+        dst_location.SubresourceIndex = i;
+
+        src_location.pResource = upload_buffer;
+        src_location.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
+        src_location.PlacedFootprint = layouts[i];
+
+        ID3D12GraphicsCommandList_CopyTextureRegion(command_list,
+                &dst_location, 0, 0, 0, &src_location, NULL);
+    }
+
+    hr = ID3D12GraphicsCommandList_Close(command_list);
+    ok_(line)(SUCCEEDED(hr), "Failed to close command list, hr %#x.\n", hr);
+
+    exec_command_list(queue, command_list);
+    wait_queue_idle(device, queue);
+
+    ID3D12Resource_Release(upload_buffer);
+    ID3D12Device_Release(device);
+
+    free(layouts);
+    free(row_counts);
+    free(row_sizes);
+}
+
 static HRESULT create_root_signature(ID3D12Device *device, const D3D12_ROOT_SIGNATURE_DESC *desc,
         ID3D12RootSignature **root_signature)
 {
diff --git a/tests/shader_runner_d3d12.c b/tests/shader_runner_d3d12.c
index a0cdc5b38..171a855f1 100644
--- a/tests/shader_runner_d3d12.c
+++ b/tests/shader_runner_d3d12.c
@@ -73,6 +73,20 @@ static bool vkd3d_array_reserve(void **elements, size_t *capacity, size_t elemen
     return true;
 }
 
+struct texture
+{
+    unsigned int slot;
+
+    unsigned int width, height;
+    uint8_t *data;
+    size_t data_size, data_capacity;
+
+    D3D12_DESCRIPTOR_RANGE descriptor_range;
+    ID3D12DescriptorHeap *heap;
+    ID3D12Resource *resource;
+    unsigned int root_index;
+};
+
 struct shader_context
 {
     struct test_context c;
@@ -81,6 +95,9 @@ struct shader_context
 
     uint32_t *uniforms;
     size_t uniform_count;
+
+    struct texture *textures;
+    size_t texture_count;
 };
 
 static ID3D10Blob *compile_shader(const char *source, const char *target)
@@ -99,6 +116,14 @@ static ID3D10Blob *compile_shader(const char *source, const char *target)
     return blob;
 }
 
+static void free_texture(struct texture *texture)
+{
+    ID3D12DescriptorHeap_Release(texture->heap);
+    ID3D12Resource_Release(texture->resource);
+    free(texture->data);
+    memset(texture, 0, sizeof(*texture));
+}
+
 enum parse_state
 {
     STATE_NONE,
@@ -106,6 +131,7 @@ enum parse_state
     STATE_PREPROC_INVALID,
     STATE_SHADER_INVALID_PIXEL,
     STATE_SHADER_PIXEL,
+    STATE_TEXTURE,
     STATE_TEST,
 };
 
@@ -124,6 +150,37 @@ static bool match_string(const char *line, const char *token, const char **const
     return true;
 }
 
+static void parse_texture_directive(struct texture *texture, const char *line)
+{
+    const char *const orig_line = line;
+    int ret;
+
+    if (match_string(line, "size", &line))
+    {
+        ret = sscanf(line, "( %u , %u )", &texture->width, &texture->height);
+        if (ret < 2)
+            goto err;
+    }
+    else
+    {
+        char *rest;
+        float f;
+
+        while ((f = strtof(line, &rest)) || rest != line)
+        {
+            vkd3d_array_reserve((void **)&texture->data, &texture->data_capacity, texture->data_size + sizeof(f), 1);
+            memcpy(texture->data + texture->data_size, &f, sizeof(f));
+            texture->data_size += sizeof(f);
+            line = rest;
+        }
+    }
+
+    return;
+
+err:
+    fprintf(stderr, "Ignoring malformed line '%s'.\n", orig_line);
+}
+
 static void parse_test_directive(struct shader_context *context, const char *line)
 {
     const char *const orig_line = line;
@@ -133,13 +190,66 @@ static void parse_test_directive(struct shader_context *context, const char *lin
         D3D12_SHADER_BYTECODE ps
                 = {ID3D10Blob_GetBufferPointer(context->ps_code), ID3D10Blob_GetBufferSize(context->ps_code)};
         ID3D12GraphicsCommandList *command_list = context->c.list;
+        D3D12_ROOT_SIGNATURE_DESC root_signature_desc = {0};
+        D3D12_ROOT_PARAMETER root_params[2], *root_param;
         static const float clear_color[4];
+        unsigned int uniform_index;
         ID3D12PipelineState *pso;
+        HRESULT hr;
+        size_t i;
+
+        root_signature_desc.NumParameters = 0;
+        root_signature_desc.pParameters = root_params;
+
+        if (context->uniform_count)
+        {
+            uniform_index = root_signature_desc.NumParameters++;
+            root_param = &root_params[uniform_index];
+            root_param->ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS;
+            root_param->Constants.ShaderRegister = 0;
+            root_param->Constants.RegisterSpace = 0;
+            root_param->Constants.Num32BitValues = context->uniform_count;
+            root_param->ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
+        }
+
+        for (i = 0; i < context->texture_count; ++i)
+        {
+            struct texture *texture = &context->textures[i];
+            D3D12_DESCRIPTOR_RANGE *range = &texture->descriptor_range;
+            D3D12_SUBRESOURCE_DATA resource_data;
+
+            texture->root_index = root_signature_desc.NumParameters++;
+            root_param = &root_params[texture->root_index];
+            root_param->ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
+            root_param->DescriptorTable.NumDescriptorRanges = 1;
+            root_param->DescriptorTable.pDescriptorRanges = range;
+            root_param->ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
+
+            range->RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
+            range->NumDescriptors = 1;
+            range->BaseShaderRegister = texture->slot;
+            range->RegisterSpace = 0;
+            range->OffsetInDescriptorsFromTableStart = 0;
+
+            texture->heap = create_gpu_descriptor_heap(context->c.device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, 1);
+            texture->resource = create_default_texture(context->c.device, texture->width, texture->height,
+                    DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D12_RESOURCE_STATE_COPY_DEST);
+            resource_data.pData = texture->data;
+            resource_data.SlicePitch = resource_data.RowPitch = texture->width * sizeof(struct vec4);
+            upload_texture_data(texture->resource, &resource_data, 1, context->c.queue, command_list);
+            reset_command_list(command_list, context->c.allocator);
+            transition_resource_state(command_list, texture->resource, D3D12_RESOURCE_STATE_COPY_DEST,
+                    D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
+            ID3D12Device_CreateShaderResourceView(context->c.device, texture->resource,
+                    NULL, get_cpu_descriptor_handle(&context->c, texture->heap, 0));
+        }
+
+        assert(root_signature_desc.NumParameters <= ARRAY_SIZE(root_params));
 
         if (context->c.root_signature)
             ID3D12RootSignature_Release(context->c.root_signature);
-        context->c.root_signature = create_32bit_constants_root_signature(context->c.device,
-                0, context->uniform_count, D3D12_SHADER_VISIBILITY_ALL);
+        hr = create_root_signature(context->c.device, &root_signature_desc, &context->c.root_signature);
+        ok(hr == S_OK, "Failed to create root signature, hr %#x.\n", hr);
 
         pso = create_pipeline_state(context->c.device, context->c.root_signature,
                 context->c.render_target_desc.Format, NULL, &ps, NULL);
@@ -147,8 +257,13 @@ static void parse_test_directive(struct shader_context *context, const char *lin
             return;
 
         ID3D12GraphicsCommandList_SetGraphicsRootSignature(command_list, context->c.root_signature);
-        ID3D12GraphicsCommandList_SetGraphicsRoot32BitConstants(command_list, 0,
-                context->uniform_count, context->uniforms, 0);
+        if (context->uniform_count)
+            ID3D12GraphicsCommandList_SetGraphicsRoot32BitConstants(command_list, uniform_index,
+                    context->uniform_count, context->uniforms, 0);
+        for (i = 0; i < context->texture_count; ++i)
+            ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(command_list, context->textures[i].root_index,
+                    get_gpu_descriptor_handle(&context->c, context->textures[i].heap, 0));
+
         ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, 1, &context->c.rtv, false, NULL);
         ID3D12GraphicsCommandList_RSSetScissorRects(command_list, 1, &context->c.scissor_rect);
         ID3D12GraphicsCommandList_RSSetViewports(command_list, 1, &context->c.viewport);
@@ -293,6 +408,21 @@ err:
     fprintf(stderr, "Ignoring malformed line '%s'.\n", orig_line);
 }
 
+static struct texture *get_texture(struct shader_context *context, unsigned int slot)
+{
+    struct texture *texture;
+    size_t i;
+
+    for (i = 0; i < context->texture_count; ++i)
+    {
+        texture = &context->textures[i];
+        if (texture->slot == slot)
+            return texture;
+    }
+
+    return NULL;
+}
+
 START_TEST(shader_runner_d3d12)
 {
     static const struct test_context_desc desc =
@@ -305,6 +435,7 @@ START_TEST(shader_runner_d3d12)
     size_t shader_source_size = 0, shader_source_len = 0;
     enum parse_state state = STATE_NONE;
     unsigned int i, line_number = 0;
+    struct texture *current_texture;
     struct shader_context context;
     const char *filename = NULL;
     char *shader_source = NULL;
@@ -351,6 +482,7 @@ START_TEST(shader_runner_d3d12)
             {
                 case STATE_NONE:
                 case STATE_TEST:
+                case STATE_TEXTURE:
                     break;
 
                 case STATE_SHADER_PIXEL:
@@ -439,16 +571,45 @@ START_TEST(shader_runner_d3d12)
 
         if (line[0] == '[')
         {
+            unsigned int index;
+
             if (!strcmp(line, "[pixel shader]\n"))
+            {
                 state = STATE_SHADER_PIXEL;
+            }
             else if (!strcmp(line, "[pixel shader fail]\n"))
+            {
                 state = STATE_SHADER_INVALID_PIXEL;
+            }
+            else if (sscanf(line, "[texture %u]\n", &index))
+            {
+                state = STATE_TEXTURE;
+
+                if ((current_texture = get_texture(&context, index)))
+                {
+                    free_texture(current_texture);
+                }
+                else
+                {
+                    context.textures = realloc(context.textures,
+                            ++context.texture_count * sizeof(*context.textures));
+                    current_texture = &context.textures[context.texture_count - 1];
+                    memset(current_texture, 0, sizeof(*current_texture));
+                }
+                current_texture->slot = index;
+            }
             else if (!strcmp(line, "[test]\n"))
+            {
                 state = STATE_TEST;
+            }
             else if (!strcmp(line, "[preproc]\n"))
+            {
                 state = STATE_PREPROC;
+            }
             else if (!strcmp(line, "[preproc fail]\n"))
+            {
                 state = STATE_PREPROC_INVALID;
+            }
 
             vkd3d_test_set_context("Section %.*s, line %u", strlen(line) - 1, line, line_number);
         }
@@ -473,6 +634,10 @@ START_TEST(shader_runner_d3d12)
                     break;
                 }
 
+                case STATE_TEXTURE:
+                    parse_texture_directive(current_texture, line);
+                    break;
+
                 case STATE_TEST:
                     parse_test_directive(&context, line);
                     break;
@@ -482,6 +647,8 @@ START_TEST(shader_runner_d3d12)
 
     if (context.ps_code)
         ID3D10Blob_Release(context.ps_code);
+    for (i = 0; i < context.texture_count; ++i)
+        free_texture(&context.textures[i]);
     destroy_test_context(&context.c);
 
     fclose(f);
diff --git a/tests/texture-load.shader_test b/tests/texture-load.shader_test
new file mode 100644
index 000000000..86b36af49
--- /dev/null
+++ b/tests/texture-load.shader_test
@@ -0,0 +1,19 @@
+[texture 0]
+size (2, 2)
+0.1 0.2 0.3 0.4     0.5 0.7 0.6 0.8
+0.6 0.5 0.2 0.1     0.8 0.0 0.7 1.0
+
+[pixel shader]
+Texture2D t;
+
+float4 main(float4 pos : sv_position) : sv_target
+{
+    return t.Load(int3(pos.xy, 0));
+}
+
+[test]
+draw quad
+probe rgba (0, 0) (0.1, 0.2, 0.3, 0.4)
+probe rgba (1, 0) (0.5, 0.7, 0.6, 0.8)
+probe rgba (0, 1) (0.6, 0.5, 0.2, 0.1)
+probe rgba (1, 1) (0.8, 0.0, 0.7, 1.0)
-- 
2.33.0




More information about the wine-devel mailing list