Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- Makefile.am | 2 + tests/sampler.shader_test | 34 +++++++++ tests/shader_runner_d3d12.c | 136 ++++++++++++++++++++++++++++++++++++ 3 files changed, 172 insertions(+) create mode 100644 tests/sampler.shader_test
diff --git a/Makefile.am b/Makefile.am index eaa4f8168..d6e14cf14 100644 --- a/Makefile.am +++ b/Makefile.am @@ -90,6 +90,7 @@ vkd3d_shader_tests = \ tests/preproc-invalid.shader_test \ tests/preproc-macro.shader_test \ tests/preproc-misc.shader_test \ + tests/sampler.shader_test \ tests/saturate.shader_test \ tests/swizzle-0.shader_test \ tests/swizzle-1.shader_test \ @@ -302,6 +303,7 @@ XFAIL_TESTS = \ tests/hlsl-vector-indexing-uniform.shader_test \ tests/math.shader_test \ tests/max.shader_test \ + tests/sampler.shader_test \ tests/texture-load.shader_test \ tests/texture-load-typed.shader_test \ tests/trigonometry.shader_test \ diff --git a/tests/sampler.shader_test b/tests/sampler.shader_test new file mode 100644 index 000000000..3970fb510 --- /dev/null +++ b/tests/sampler.shader_test @@ -0,0 +1,34 @@ +[sampler 0] +filter linear linear linear +address clamp clamp clamp + +[texture 0] +size (2, 2) +0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +0.0 0.0 0.0 0.0 1.0 0.0 1.0 0.0 + +[pixel shader] +sampler s; +Texture2D t; + +float4 main() : sv_target +{ + return t.Sample(s, float2(0.5, 0.5)); +} + +[test] +draw quad +probe all rgba (0.25, 0, 0.25, 0) + +[pixel shader] +SamplerState s; +Texture2D t; + +float4 main() : sv_target +{ + return t.Sample(s, float2(0.5, 0.5)); +} + +[test] +draw quad +probe all rgba (0.25, 0, 0.25, 0) diff --git a/tests/shader_runner_d3d12.c b/tests/shader_runner_d3d12.c index a17a171ef..d52382978 100644 --- a/tests/shader_runner_d3d12.c +++ b/tests/shader_runner_d3d12.c @@ -80,6 +80,14 @@ enum texture_data_type TEXTURE_DATA_UINT, };
+struct sampler +{ + unsigned int slot; + + D3D12_FILTER filter; + D3D12_TEXTURE_ADDRESS_MODE u_address, v_address, w_address; +}; + struct texture { unsigned int slot; @@ -108,6 +116,9 @@ struct shader_context
struct texture *textures; size_t texture_count; + + struct sampler *samplers; + size_t sampler_count; };
static ID3D10Blob *compile_shader(const char *source, const char *target) @@ -139,6 +150,7 @@ enum parse_state STATE_NONE, STATE_PREPROC, STATE_PREPROC_INVALID, + STATE_SAMPLER, STATE_SHADER_INVALID_PIXEL, STATE_SHADER_PIXEL, STATE_TEXTURE, @@ -195,6 +207,69 @@ static void parse_texture_format(struct texture *texture, const char *line) texture->texel_size = 16; }
+static D3D12_TEXTURE_ADDRESS_MODE parse_sampler_address_mode(const char *line, const char **rest) +{ + if (match_string(line, "border", rest)) + return D3D12_TEXTURE_ADDRESS_MODE_BORDER; + if (match_string(line, "clamp", rest)) + return D3D12_TEXTURE_ADDRESS_MODE_CLAMP; + if (match_string(line, "mirror_once", rest)) + return D3D12_TEXTURE_ADDRESS_MODE_MIRROR_ONCE; + if (match_string(line, "mirror", rest)) + return D3D12_TEXTURE_ADDRESS_MODE_MIRROR; + if (match_string(line, "wrap", rest)) + return D3D12_TEXTURE_ADDRESS_MODE_WRAP; + fprintf(stderr, "Malformed address mode '%s'.\n", line); + return D3D12_TEXTURE_ADDRESS_MODE_WRAP; +} + +static void parse_sampler_directive(struct sampler *sampler, const char *line) +{ + const char *const orig_line = line; + + if (match_string(line, "address", &line)) + { + sampler->u_address = parse_sampler_address_mode(line, &line); + sampler->v_address = parse_sampler_address_mode(line, &line); + sampler->w_address = parse_sampler_address_mode(line, &line); + } + else if (match_string(line, "filter", &line)) + { + static const struct + { + const char *string; + D3D12_FILTER filter; + } + filters[] = + { + {"point point point", D3D12_FILTER_MIN_MAG_MIP_POINT}, + {"point point linear", D3D12_FILTER_MIN_MAG_POINT_MIP_LINEAR}, + {"point linear point", D3D12_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT}, + {"point linear linear", D3D12_FILTER_MIN_POINT_MAG_MIP_LINEAR}, + {"linear point point", D3D12_FILTER_MIN_LINEAR_MAG_MIP_POINT}, + {"linear point linear", D3D12_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR}, + {"linear linear point", D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT}, + {"linear linear linear", D3D12_FILTER_MIN_MAG_MIP_LINEAR}, + }; + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(filters); ++i) + { + if (match_string(line, filters[i].string, &line)) + sampler->filter = filters[i].filter; + } + } + else + { + goto err; + } + + return; + +err: + fprintf(stderr, "Ignoring malformed line '%s'.\n", orig_line); +} + static void parse_texture_directive(struct texture *texture, const char *line) { const char *const orig_line = line; @@ -266,6 +341,7 @@ static void parse_test_directive(struct shader_context *context, const char *lin ID3D12GraphicsCommandList *command_list = context->c.list; D3D12_ROOT_SIGNATURE_DESC root_signature_desc = {0}; D3D12_ROOT_PARAMETER root_params[3], *root_param; + D3D12_STATIC_SAMPLER_DESC static_samplers[1]; static const float clear_color[4]; unsigned int uniform_index; ID3D12PipelineState *pso; @@ -274,6 +350,8 @@ static void parse_test_directive(struct shader_context *context, const char *lin
root_signature_desc.NumParameters = 0; root_signature_desc.pParameters = root_params; + root_signature_desc.NumStaticSamplers = 0; + root_signature_desc.pStaticSamplers = static_samplers;
if (context->uniform_count) { @@ -324,6 +402,21 @@ static void parse_test_directive(struct shader_context *context, const char *lin
assert(root_signature_desc.NumParameters <= ARRAY_SIZE(root_params));
+ for (i = 0; i < context->sampler_count; ++i) + { + D3D12_STATIC_SAMPLER_DESC *sampler_desc = &static_samplers[root_signature_desc.NumStaticSamplers++]; + const struct sampler *sampler = &context->samplers[i]; + + memset(sampler_desc, 0, sizeof(*sampler_desc)); + sampler_desc->Filter = sampler->filter; + sampler_desc->AddressU = sampler->u_address; + sampler_desc->AddressV = sampler->v_address; + sampler_desc->AddressW = sampler->w_address; + sampler_desc->ShaderRegister = sampler->slot; + sampler_desc->RegisterSpace = 0; + sampler_desc->ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; + } + if (context->c.root_signature) ID3D12RootSignature_Release(context->c.root_signature); hr = create_root_signature(context->c.device, &root_signature_desc, &context->c.root_signature); @@ -486,6 +579,22 @@ err: fprintf(stderr, "Ignoring malformed line '%s'.\n", orig_line); }
+static struct sampler *get_sampler(struct shader_context *context, unsigned int slot) +{ + struct sampler *sampler; + size_t i; + + for (i = 0; i < context->sampler_count; ++i) + { + sampler = &context->samplers[i]; + + if (sampler->slot == slot) + return sampler; + } + + return NULL; +} + static struct texture *get_texture(struct shader_context *context, unsigned int slot) { struct texture *texture; @@ -513,6 +622,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 sampler *current_sampler; struct texture *current_texture; struct shader_context context; const char *filename = NULL; @@ -559,6 +669,7 @@ START_TEST(shader_runner_d3d12) switch (state) { case STATE_NONE: + case STATE_SAMPLER: case STATE_TEST: case STATE_TEXTURE: break; @@ -663,6 +774,27 @@ START_TEST(shader_runner_d3d12) { state = STATE_SHADER_INVALID_PIXEL; } + else if (sscanf(line, "[sampler %u]\n", &index)) + { + state = STATE_SAMPLER; + + if ((current_sampler = get_sampler(&context, index))) + { + memset(current_sampler, 0, sizeof(*current_sampler)); + } + else + { + context.samplers = realloc(context.samplers, + ++context.sampler_count * sizeof(*context.samplers)); + current_sampler = &context.samplers[context.sampler_count - 1]; + memset(current_sampler, 0, sizeof(*current_sampler)); + } + current_sampler->slot = index; + current_sampler->filter = D3D12_FILTER_MIN_MAG_MIP_POINT; + current_sampler->u_address = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; + current_sampler->v_address = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; + current_sampler->w_address = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; + } else if (sscanf(line, "[texture %u]\n", &index)) { state = STATE_TEXTURE; @@ -719,6 +851,10 @@ START_TEST(shader_runner_d3d12) break; }
+ case STATE_SAMPLER: + parse_sampler_directive(current_sampler, line); + break; + case STATE_TEXTURE: parse_texture_directive(current_texture, line); break;