tests: Add a shader test for texture sampling.

Signed-off-by: Zebediah Figura <zfigura@codeweavers.com>
Signed-off-by: Matteo Bruni <mbruni@codeweavers.com>
Signed-off-by: Henri Verbeet <hverbeet@codeweavers.com>
Signed-off-by: Giovanni Mascellani <gmascellani@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Zebediah Figura 2021-11-05 19:35:49 +01:00 committed by Alexandre Julliard
parent 9c645bb1f6
commit 3ca8f52b0b
3 changed files with 177 additions and 0 deletions

View File

@ -90,6 +90,7 @@ vkd3d_shader_tests = \
tests/preproc-invalid.shader_test \ tests/preproc-invalid.shader_test \
tests/preproc-macro.shader_test \ tests/preproc-macro.shader_test \
tests/preproc-misc.shader_test \ tests/preproc-misc.shader_test \
tests/sampler.shader_test \
tests/saturate.shader_test \ tests/saturate.shader_test \
tests/swizzle-0.shader_test \ tests/swizzle-0.shader_test \
tests/swizzle-1.shader_test \ tests/swizzle-1.shader_test \
@ -302,6 +303,7 @@ XFAIL_TESTS = \
tests/hlsl-vector-indexing-uniform.shader_test \ tests/hlsl-vector-indexing-uniform.shader_test \
tests/math.shader_test \ tests/math.shader_test \
tests/max.shader_test \ tests/max.shader_test \
tests/sampler.shader_test \
tests/texture-load.shader_test \ tests/texture-load.shader_test \
tests/texture-load-typed.shader_test \ tests/texture-load-typed.shader_test \
tests/trigonometry.shader_test \ tests/trigonometry.shader_test \

34
tests/sampler.shader_test Normal file
View File

@ -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)

View File

@ -80,6 +80,14 @@ enum texture_data_type
TEXTURE_DATA_UINT, TEXTURE_DATA_UINT,
}; };
struct sampler
{
unsigned int slot;
D3D12_FILTER filter;
D3D12_TEXTURE_ADDRESS_MODE u_address, v_address, w_address;
};
struct texture struct texture
{ {
unsigned int slot; unsigned int slot;
@ -108,6 +116,9 @@ struct shader_context
struct texture *textures; struct texture *textures;
size_t texture_count; size_t texture_count;
struct sampler *samplers;
size_t sampler_count;
}; };
static ID3D10Blob *compile_shader(const char *source, const char *target) static ID3D10Blob *compile_shader(const char *source, const char *target)
@ -139,6 +150,7 @@ enum parse_state
STATE_NONE, STATE_NONE,
STATE_PREPROC, STATE_PREPROC,
STATE_PREPROC_INVALID, STATE_PREPROC_INVALID,
STATE_SAMPLER,
STATE_SHADER_INVALID_PIXEL, STATE_SHADER_INVALID_PIXEL,
STATE_SHADER_PIXEL, STATE_SHADER_PIXEL,
STATE_TEXTURE, STATE_TEXTURE,
@ -195,6 +207,74 @@ static void parse_texture_format(struct texture *texture, const char *line)
texture->texel_size = 16; 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;
break;
}
}
if (i == ARRAY_SIZE(filters))
goto err;
}
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) static void parse_texture_directive(struct texture *texture, const char *line)
{ {
const char *const orig_line = line; const char *const orig_line = line;
@ -266,6 +346,7 @@ static void parse_test_directive(struct shader_context *context, const char *lin
ID3D12GraphicsCommandList *command_list = context->c.list; ID3D12GraphicsCommandList *command_list = context->c.list;
D3D12_ROOT_SIGNATURE_DESC root_signature_desc = {0}; D3D12_ROOT_SIGNATURE_DESC root_signature_desc = {0};
D3D12_ROOT_PARAMETER root_params[3], *root_param; D3D12_ROOT_PARAMETER root_params[3], *root_param;
D3D12_STATIC_SAMPLER_DESC static_samplers[1];
static const float clear_color[4]; static const float clear_color[4];
unsigned int uniform_index; unsigned int uniform_index;
ID3D12PipelineState *pso; ID3D12PipelineState *pso;
@ -274,6 +355,8 @@ static void parse_test_directive(struct shader_context *context, const char *lin
root_signature_desc.NumParameters = 0; root_signature_desc.NumParameters = 0;
root_signature_desc.pParameters = root_params; root_signature_desc.pParameters = root_params;
root_signature_desc.NumStaticSamplers = 0;
root_signature_desc.pStaticSamplers = static_samplers;
if (context->uniform_count) if (context->uniform_count)
{ {
@ -324,6 +407,21 @@ static void parse_test_directive(struct shader_context *context, const char *lin
assert(root_signature_desc.NumParameters <= ARRAY_SIZE(root_params)); 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) if (context->c.root_signature)
ID3D12RootSignature_Release(context->c.root_signature); ID3D12RootSignature_Release(context->c.root_signature);
hr = create_root_signature(context->c.device, &root_signature_desc, &context->c.root_signature); hr = create_root_signature(context->c.device, &root_signature_desc, &context->c.root_signature);
@ -486,6 +584,22 @@ err:
fprintf(stderr, "Ignoring malformed line '%s'.\n", orig_line); 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) static struct texture *get_texture(struct shader_context *context, unsigned int slot)
{ {
struct texture *texture; struct texture *texture;
@ -511,6 +625,7 @@ START_TEST(shader_runner_d3d12)
.rt_format = DXGI_FORMAT_R32G32B32A32_FLOAT, .rt_format = DXGI_FORMAT_R32G32B32A32_FLOAT,
}; };
size_t shader_source_size = 0, shader_source_len = 0; size_t shader_source_size = 0, shader_source_len = 0;
struct sampler *current_sampler = NULL;
struct texture *current_texture = NULL; struct texture *current_texture = NULL;
enum parse_state state = STATE_NONE; enum parse_state state = STATE_NONE;
unsigned int i, line_number = 0; unsigned int i, line_number = 0;
@ -559,6 +674,7 @@ START_TEST(shader_runner_d3d12)
switch (state) switch (state)
{ {
case STATE_NONE: case STATE_NONE:
case STATE_SAMPLER:
case STATE_TEST: case STATE_TEST:
case STATE_TEXTURE: case STATE_TEXTURE:
break; break;
@ -663,6 +779,27 @@ START_TEST(shader_runner_d3d12)
{ {
state = STATE_SHADER_INVALID_PIXEL; 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)) else if (sscanf(line, "[texture %u]\n", &index))
{ {
state = STATE_TEXTURE; state = STATE_TEXTURE;
@ -719,6 +856,10 @@ START_TEST(shader_runner_d3d12)
break; break;
} }
case STATE_SAMPLER:
parse_sampler_directive(current_sampler, line);
break;
case STATE_TEXTURE: case STATE_TEXTURE:
parse_texture_directive(current_texture, line); parse_texture_directive(current_texture, line);
break; break;