[PATCH vkd3d 3/8] tests: Allow specifying a custom input layout.

Zebediah Figura zfigura at codeweavers.com
Mon Mar 21 20:42:16 CDT 2022


Signed-off-by: Zebediah Figura <zfigura at codeweavers.com>
---
 tests/shader_runner.c       | 63 ++++++++++++++++++++++++++++++++-----
 tests/shader_runner.h       | 12 +++++++
 tests/shader_runner_d3d11.c | 41 +++++++++++++++++++-----
 tests/shader_runner_d3d12.c | 23 +++++++++++++-
 4 files changed, 124 insertions(+), 15 deletions(-)

diff --git a/tests/shader_runner.c b/tests/shader_runner.c
index a2aecf9f9..383a61fb3 100644
--- a/tests/shader_runner.c
+++ b/tests/shader_runner.c
@@ -54,6 +54,7 @@ typedef int HRESULT;
 #include <errno.h>
 #include <stdbool.h>
 #include <stdio.h>
+#include <string.h>
 #include "vkd3d_windows.h"
 #include "vkd3d_d3dcommon.h"
 #include "vkd3d_d3dcompiler.h"
@@ -74,6 +75,7 @@ void fatal_error(const char *format, ...)
 enum parse_state
 {
     STATE_NONE,
+    STATE_INPUT_LAYOUT,
     STATE_PREPROC,
     STATE_PREPROC_INVALID,
     STATE_REQUIRE,
@@ -89,6 +91,9 @@ static bool match_string(const char *line, const char *token, const char **const
 {
     size_t len = strlen(token);
 
+    while (isspace(*line))
+        ++line;
+
     if (strncmp(line, token, len) || !isspace(line[len]))
         return false;
     if (rest)
@@ -131,7 +136,7 @@ static void parse_require_directive(struct shader_runner *runner, const char *li
     }
 }
 
-static void parse_texture_format(struct texture_params *texture, const char *line)
+static DXGI_FORMAT parse_format(const char *line, enum texture_data_type *data_type, unsigned int *texel_size, const char **rest)
 {
     static const struct
     {
@@ -151,12 +156,12 @@ static void parse_texture_format(struct texture_params *texture, const char *lin
 
     for (i = 0; i < ARRAY_SIZE(formats); ++i)
     {
-        if (match_string(line, formats[i].string, &line))
+        if (match_string(line, formats[i].string, rest))
         {
-            texture->format = formats[i].format;
-            texture->data_type = formats[i].data_type;
-            texture->texel_size = formats[i].texel_size;
-            return;
+            if (data_type)
+                *data_type = formats[i].data_type;
+            *texel_size = formats[i].texel_size;
+            return formats[i].format;
         }
     }
 
@@ -230,7 +235,7 @@ static void parse_texture_directive(struct texture_params *texture, const char *
 
     if (match_string(line, "format", &line))
     {
-        parse_texture_format(texture, line);
+        texture->format = parse_format(line, &texture->data_type, &texture->texel_size, &line);
     }
     else if (match_string(line, "size", &line))
     {
@@ -278,6 +283,34 @@ static void parse_texture_directive(struct texture_params *texture, const char *
     }
 }
 
+static void parse_input_layout_directive(struct shader_runner *runner, const char *line)
+{
+    struct input_element *element;
+    const char *rest;
+
+    vkd3d_array_reserve((void **)&runner->input_elements, &runner->input_element_capacity,
+            runner->input_element_count + 1, sizeof(*runner->input_elements));
+    element = &runner->input_elements[runner->input_element_count++];
+
+    element->slot = strtoul(line, (char **)&rest, 10);
+    if (rest == line)
+        fatal_error("Malformed input layout directive '%s'.\n", line);
+    line = rest;
+
+    element->format = parse_format(line, NULL, &element->texel_size, &line);
+
+    if (!(rest = strpbrk(line, " \n")))
+        rest = line + strlen(line);
+    element->name = malloc(rest - line + 1);
+    memcpy(element->name, line, rest - line);
+    element->name[rest - line] = 0;
+    line = rest;
+
+    element->index = strtoul(line, (char **)&rest, 10);
+    if (rest == line)
+        element->index = 0;
+}
+
 static void set_uniforms(struct shader_runner *runner, size_t offset, size_t count, const void *uniforms)
 {
     runner->uniform_count = align(max(runner->uniform_count, offset + count), 4);
@@ -493,6 +526,7 @@ void run_shader_tests(struct shader_runner *runner, int argc, char **argv, const
         {
             switch (state)
             {
+                case STATE_INPUT_LAYOUT:
                 case STATE_NONE:
                 case STATE_REQUIRE:
                 case STATE_SAMPLER:
@@ -662,6 +696,14 @@ void run_shader_tests(struct shader_runner *runner, int argc, char **argv, const
             {
                 state = STATE_SHADER_VERTEX;
             }
+            else if (!strcmp(line, "[input layout]\n"))
+            {
+                state = STATE_INPUT_LAYOUT;
+
+                for (i = 0; i < runner->input_element_count; ++i)
+                    free(runner->input_elements[i].name);
+                runner->input_element_count = 0;
+            }
 
             vkd3d_test_set_context("Section %.*s, line %u", strlen(line) - 1, line, line_number);
         }
@@ -673,6 +715,10 @@ void run_shader_tests(struct shader_runner *runner, int argc, char **argv, const
                     fatal_error("Malformed line '%s'.\n", line);
                     break;
 
+                case STATE_INPUT_LAYOUT:
+                    parse_input_layout_directive(runner, line);
+                    break;
+
                 case STATE_PREPROC:
                 case STATE_PREPROC_INVALID:
                 case STATE_SHADER_INVALID_PIXEL:
@@ -706,6 +752,9 @@ void run_shader_tests(struct shader_runner *runner, int argc, char **argv, const
         }
     }
 
+    for (i = 0; i < runner->input_element_count; ++i)
+        free(runner->input_elements[i].name);
+    free(runner->input_elements);
     free(runner->vs_source);
     free(runner->ps_source);
     for (i = 0; i < runner->texture_count; ++i)
diff --git a/tests/shader_runner.h b/tests/shader_runner.h
index 43ded8534..8e2ca20e7 100644
--- a/tests/shader_runner.h
+++ b/tests/shader_runner.h
@@ -68,6 +68,15 @@ struct texture
     unsigned int slot;
 };
 
+struct input_element
+{
+    char *name;
+    unsigned int slot;
+    DXGI_FORMAT format;
+    unsigned int texel_size;
+    unsigned int index;
+};
+
 struct shader_runner
 {
     const struct shader_runner_ops *ops;
@@ -84,6 +93,9 @@ struct shader_runner
 
     struct sampler *samplers;
     size_t sampler_count;
+
+    struct input_element *input_elements;
+    size_t input_element_count, input_element_capacity;
 };
 
 struct shader_runner_ops
diff --git a/tests/shader_runner_d3d11.c b/tests/shader_runner_d3d11.c
index f40494446..d419db2d8 100644
--- a/tests/shader_runner_d3d11.c
+++ b/tests/shader_runner_d3d11.c
@@ -412,6 +412,7 @@ static void d3d11_runner_destroy_texture(struct shader_runner *r, struct texture
 static void d3d11_runner_draw_quad(struct shader_runner *r)
 {
     struct d3d11_shader_runner *runner = d3d11_shader_runner(r);
+    ID3D11DeviceContext *context = runner->immediate_context;
     ID3D11Device *device = runner->device;
     ID3D10Blob *vs_code, *ps_code;
     ID3D11Buffer *cb = NULL;
@@ -441,14 +442,14 @@ static void d3d11_runner_draw_quad(struct shader_runner *r)
     {
         cb = create_buffer(device, D3D11_BIND_CONSTANT_BUFFER,
                 runner->r.uniform_count * sizeof(*runner->r.uniforms), runner->r.uniforms);
-        ID3D11DeviceContext_PSSetConstantBuffers(runner->immediate_context, 0, 1, &cb);
+        ID3D11DeviceContext_PSSetConstantBuffers(context, 0, 1, &cb);
     }
 
     for (i = 0; i < runner->r.texture_count; ++i)
     {
         struct d3d11_texture *texture = d3d11_texture(runner->r.textures[i]);
 
-        ID3D11DeviceContext_PSSetShaderResources(runner->immediate_context, texture->t.slot, 1, &texture->srv);
+        ID3D11DeviceContext_PSSetShaderResources(context, texture->t.slot, 1, &texture->srv);
     }
 
     for (i = 0; i < runner->r.sampler_count; ++i)
@@ -468,15 +469,41 @@ static void d3d11_runner_draw_quad(struct shader_runner *r)
 
         hr = ID3D11Device_CreateSamplerState(device, &desc, &d3d11_sampler);
         ok(hr == S_OK, "Failed to create sampler state, hr %#lx.\n", hr);
-        ID3D11DeviceContext_PSSetSamplers(runner->immediate_context, sampler->slot, 1, &d3d11_sampler);
+        ID3D11DeviceContext_PSSetSamplers(context, sampler->slot, 1, &d3d11_sampler);
         ID3D11SamplerState_Release(d3d11_sampler);
     }
 
-    ID3D11DeviceContext_IASetPrimitiveTopology(runner->immediate_context, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
-    ID3D11DeviceContext_VSSetShader(runner->immediate_context, vs, NULL, 0);
-    ID3D11DeviceContext_PSSetShader(runner->immediate_context, ps, NULL, 0);
+    if (runner->r.input_element_count)
+    {
+        D3D11_INPUT_ELEMENT_DESC *descs;
+        ID3D11InputLayout *input_layout;
 
-    ID3D11DeviceContext_Draw(runner->immediate_context, 3, 0);
+        descs = calloc(runner->r.input_element_count, sizeof(*descs));
+        for (i = 0; i < runner->r.input_element_count; ++i)
+        {
+            const struct input_element *element = &runner->r.input_elements[i];
+            D3D11_INPUT_ELEMENT_DESC *desc = &descs[i];
+
+            desc->SemanticName = element->name;
+            desc->SemanticIndex = element->index;
+            desc->Format = element->format;
+            desc->InputSlot = element->slot;
+            desc->AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT;
+            desc->InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
+        }
+
+        hr = ID3D11Device_CreateInputLayout(device, descs, runner->r.input_element_count,
+                ID3D10Blob_GetBufferPointer(vs_code), ID3D10Blob_GetBufferSize(vs_code), &input_layout);
+        ok(hr == S_OK, "Failed to create input layout, hr %#lx.\n", hr);
+        ID3D11DeviceContext_IASetInputLayout(context, input_layout);
+        ID3D11InputLayout_Release(input_layout);
+    }
+
+    ID3D11DeviceContext_IASetPrimitiveTopology(context, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
+    ID3D11DeviceContext_VSSetShader(context, vs, NULL, 0);
+    ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0);
+
+    ID3D11DeviceContext_Draw(context, 3, 0);
 
     ID3D11PixelShader_Release(ps);
     ID3D11VertexShader_Release(vs);
diff --git a/tests/shader_runner_d3d12.c b/tests/shader_runner_d3d12.c
index befa7f2f5..e442d16e1 100644
--- a/tests/shader_runner_d3d12.c
+++ b/tests/shader_runner_d3d12.c
@@ -131,8 +131,10 @@ static void d3d12_runner_draw_quad(struct shader_runner *r)
     D3D12_ROOT_SIGNATURE_DESC root_signature_desc = {0};
     D3D12_ROOT_PARAMETER root_params[3], *root_param;
     ID3D12CommandQueue *queue = test_context->queue;
+    D3D12_INPUT_ELEMENT_DESC *input_element_descs;
     D3D12_STATIC_SAMPLER_DESC static_samplers[1];
     ID3D12Device *device = test_context->device;
+    D3D12_INPUT_LAYOUT_DESC input_layout;
     static const float clear_color[4];
     ID3D10Blob *vs_code, *ps_code;
     D3D12_SHADER_BYTECODE vs, ps;
@@ -154,6 +156,7 @@ static void d3d12_runner_draw_quad(struct shader_runner *r)
     root_signature_desc.pParameters = root_params;
     root_signature_desc.NumStaticSamplers = 0;
     root_signature_desc.pStaticSamplers = static_samplers;
+    root_signature_desc.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT;
 
     if (runner->r.uniform_count)
     {
@@ -209,14 +212,32 @@ static void d3d12_runner_draw_quad(struct shader_runner *r)
     hr = create_root_signature(device, &root_signature_desc, &test_context->root_signature);
     ok(hr == S_OK, "Failed to create root signature, hr %#x.\n", hr);
 
+    input_element_descs = calloc(runner->r.input_element_count, sizeof(*input_element_descs));
+    for (i = 0; i < runner->r.input_element_count; ++i)
+    {
+        const struct input_element *element = &runner->r.input_elements[i];
+        D3D12_INPUT_ELEMENT_DESC *desc = &input_element_descs[i];
+
+        desc->SemanticName = element->name;
+        desc->SemanticIndex = element->index;
+        desc->Format = element->format;
+        desc->InputSlot = element->slot;
+        desc->AlignedByteOffset = D3D12_APPEND_ALIGNED_ELEMENT;
+        desc->InputSlotClass = D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA;
+    }
+
+    input_layout.pInputElementDescs = input_element_descs;
+    input_layout.NumElements = runner->r.input_element_count;
+
     vs.pShaderBytecode = ID3D10Blob_GetBufferPointer(vs_code);
     vs.BytecodeLength = ID3D10Blob_GetBufferSize(vs_code);
     ps.pShaderBytecode = ID3D10Blob_GetBufferPointer(ps_code);
     ps.BytecodeLength = ID3D10Blob_GetBufferSize(ps_code);
     pso = create_pipeline_state(device, test_context->root_signature,
-            test_context->render_target_desc.Format, &vs, &ps, NULL);
+            test_context->render_target_desc.Format, &vs, &ps, &input_layout);
     ID3D10Blob_Release(vs_code);
     ID3D10Blob_Release(ps_code);
+    free(input_element_descs);
     if (!pso)
         return;
     vkd3d_array_reserve((void **)&test_context->pso, &test_context->pso_capacity,
-- 
2.35.1




More information about the wine-devel mailing list