tests: Add a test for texture load instructions.

Signed-off-by: Zebediah Figura <zfigura@codeweavers.com>
Signed-off-by: Giovanni Mascellani <gmascellani@codeweavers.com>
Signed-off-by: Matteo Bruni <mbruni@codeweavers.com>
Signed-off-by: Henri Verbeet <hverbeet@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Zebediah Figura
2021-10-03 19:19:08 -05:00
committed by Alexandre Julliard
parent 5f8becada4
commit b1889215ee
5 changed files with 281 additions and 93 deletions

View File

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