From 3ed4c6fe23a07424b3d421af1265b32eb29fb9bb Mon Sep 17 00:00:00 2001 From: Zebediah Figura Date: Mon, 21 Mar 2022 20:42:16 -0500 Subject: [PATCH] tests: Allow specifying a custom input layout. Signed-off-by: Zebediah Figura Signed-off-by: Henri Verbeet Signed-off-by: Alexandre Julliard --- 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 a2aecf9f..383a61fb 100644 --- a/tests/shader_runner.c +++ b/tests/shader_runner.c @@ -54,6 +54,7 @@ typedef int HRESULT; #include #include #include +#include #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 43ded853..8e2ca20e 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 f4049444..d419db2d 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 befa7f2f..e442d16e 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,