[PATCH vkd3d 4/5] tests: Add a test for texture load instructions.
Zebediah Figura
zfigura at codeweavers.com
Sun Oct 3 19:19:08 CDT 2021
Signed-off-by: Zebediah Figura <zfigura at codeweavers.com>
---
Makefile.am | 2 +
tests/d3d12.c | 89 -----------------
tests/d3d12_test_utils.h | 89 +++++++++++++++++
tests/shader_runner_d3d12.c | 175 ++++++++++++++++++++++++++++++++-
tests/texture-load.shader_test | 19 ++++
5 files changed, 281 insertions(+), 93 deletions(-)
create mode 100644 tests/texture-load.shader_test
diff --git a/Makefile.am b/Makefile.am
index bc33e0f60..921bb7964 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -99,6 +99,7 @@ vkd3d_shader_tests = \
tests/swizzle-5.shader_test \
tests/swizzle-6.shader_test \
tests/swizzle-7.shader_test \
+ tests/texture-load.shader_test \
tests/trigonometry.shader_test \
tests/writemask-assignop-0.shader_test \
tests/writemask-assignop-1.shader_test \
@@ -299,6 +300,7 @@ XFAIL_TESTS = \
tests/hlsl-vector-indexing-uniform.shader_test \
tests/math.shader_test \
tests/max.shader_test \
+ tests/texture-load.shader_test \
tests/trigonometry.shader_test \
tests/writemask-assignop-1.shader_test
endif
diff --git a/tests/d3d12.c b/tests/d3d12.c
index b4c136137..3ef93e911 100644
--- a/tests/d3d12.c
+++ b/tests/d3d12.c
@@ -155,22 +155,6 @@ static void uav_barrier(ID3D12GraphicsCommandList *list, ID3D12Resource *resourc
ID3D12GraphicsCommandList_ResourceBarrier(list, 1, &barrier);
}
-static void copy_sub_resource_data(const D3D12_MEMCPY_DEST *dst, const D3D12_SUBRESOURCE_DATA *src,
- unsigned int row_count, unsigned int slice_count, size_t row_size)
-{
- const BYTE *src_slice_ptr;
- BYTE *dst_slice_ptr;
- unsigned int z, y;
-
- for (z = 0; z < slice_count; ++z)
- {
- dst_slice_ptr = (BYTE *)dst->pData + z * dst->SlicePitch;
- src_slice_ptr = (const BYTE*)src->pData + z * src->SlicePitch;
- for (y = 0; y < row_count; ++y)
- memcpy(dst_slice_ptr + y * dst->RowPitch, src_slice_ptr + y * src->RowPitch, row_size);
- }
-}
-
#define upload_buffer_data(a, b, c, d, e, f) upload_buffer_data_(__LINE__, a, b, c, d, e, f)
static void upload_buffer_data_(unsigned int line, ID3D12Resource *buffer, size_t offset,
size_t size, const void *data, ID3D12CommandQueue *queue, ID3D12GraphicsCommandList *command_list)
@@ -196,79 +180,6 @@ static void upload_buffer_data_(unsigned int line, ID3D12Resource *buffer, size_
ID3D12Device_Release(device);
}
-#define upload_texture_data(a, b, c, d, e) upload_texture_data_(__LINE__, a, b, c, d, e)
-static void upload_texture_data_(unsigned int line, ID3D12Resource *texture,
- const D3D12_SUBRESOURCE_DATA *data, unsigned int sub_resource_count,
- ID3D12CommandQueue *queue, ID3D12GraphicsCommandList *command_list)
-{
- D3D12_TEXTURE_COPY_LOCATION dst_location, src_location;
- D3D12_PLACED_SUBRESOURCE_FOOTPRINT *layouts;
- uint64_t *row_sizes, required_size;
- D3D12_RESOURCE_DESC resource_desc;
- ID3D12Resource *upload_buffer;
- D3D12_MEMCPY_DEST dst_data;
- ID3D12Device *device;
- UINT *row_counts;
- unsigned int i;
- HRESULT hr;
- void *ptr;
-
- layouts = calloc(sub_resource_count, sizeof(*layouts));
- ok(layouts, "Failed to allocate memory.\n");
- row_counts = calloc(sub_resource_count, sizeof(*row_counts));
- ok(row_counts, "Failed to allocate memory.\n");
- row_sizes = calloc(sub_resource_count, sizeof(*row_sizes));
- ok(row_sizes, "Failed to allocate memory.\n");
-
- resource_desc = ID3D12Resource_GetDesc(texture);
- hr = ID3D12Resource_GetDevice(texture, &IID_ID3D12Device, (void **)&device);
- ok_(line)(SUCCEEDED(hr), "Failed to get device, hr %#x.\n", hr);
-
- ID3D12Device_GetCopyableFootprints(device, &resource_desc, 0, sub_resource_count,
- 0, layouts, row_counts, row_sizes, &required_size);
-
- upload_buffer = create_upload_buffer_(line, device, required_size, NULL);
-
- hr = ID3D12Resource_Map(upload_buffer, 0, NULL, (void **)&ptr);
- ok_(line)(SUCCEEDED(hr), "Failed to map upload buffer, hr %#x.\n", hr);
- for (i = 0; i < sub_resource_count; ++i)
- {
- dst_data.pData = (BYTE *)ptr + layouts[i].Offset;
- dst_data.RowPitch = layouts[i].Footprint.RowPitch;
- dst_data.SlicePitch = layouts[i].Footprint.RowPitch * row_counts[i];
- copy_sub_resource_data(&dst_data, &data[i],
- row_counts[i], layouts[i].Footprint.Depth, row_sizes[i]);
- }
- ID3D12Resource_Unmap(upload_buffer, 0, NULL);
-
- for (i = 0; i < sub_resource_count; ++i)
- {
- dst_location.pResource = texture;
- dst_location.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
- dst_location.SubresourceIndex = i;
-
- src_location.pResource = upload_buffer;
- src_location.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
- src_location.PlacedFootprint = layouts[i];
-
- ID3D12GraphicsCommandList_CopyTextureRegion(command_list,
- &dst_location, 0, 0, 0, &src_location, NULL);
- }
-
- hr = ID3D12GraphicsCommandList_Close(command_list);
- ok_(line)(SUCCEEDED(hr), "Failed to close command list, hr %#x.\n", hr);
-
- exec_command_list(queue, command_list);
- wait_queue_idle(device, queue);
-
- ID3D12Resource_Release(upload_buffer);
- ID3D12Device_Release(device);
-
- free(layouts);
- free(row_counts);
- free(row_sizes);
-}
-
static const DXGI_FORMAT depth_stencil_formats[] =
{
DXGI_FORMAT_R32G8X24_TYPELESS,
diff --git a/tests/d3d12_test_utils.h b/tests/d3d12_test_utils.h
index 0374d8d11..5d900f891 100644
--- a/tests/d3d12_test_utils.h
+++ b/tests/d3d12_test_utils.h
@@ -697,6 +697,95 @@ static inline ID3D12Resource *create_default_texture3d_(unsigned int line, ID3D1
width, height, depth, miplevel_count, format, flags, initial_state);
}
+static void copy_sub_resource_data(const D3D12_MEMCPY_DEST *dst, const D3D12_SUBRESOURCE_DATA *src,
+ unsigned int row_count, unsigned int slice_count, size_t row_size)
+{
+ const BYTE *src_slice_ptr;
+ BYTE *dst_slice_ptr;
+ unsigned int z, y;
+
+ for (z = 0; z < slice_count; ++z)
+ {
+ dst_slice_ptr = (BYTE *)dst->pData + z * dst->SlicePitch;
+ src_slice_ptr = (const BYTE*)src->pData + z * src->SlicePitch;
+ for (y = 0; y < row_count; ++y)
+ memcpy(dst_slice_ptr + y * dst->RowPitch, src_slice_ptr + y * src->RowPitch, row_size);
+ }
+}
+
+#define upload_texture_data(a, b, c, d, e) upload_texture_data_(__LINE__, a, b, c, d, e)
+static inline void upload_texture_data_(unsigned int line, ID3D12Resource *texture,
+ const D3D12_SUBRESOURCE_DATA *data, unsigned int sub_resource_count,
+ ID3D12CommandQueue *queue, ID3D12GraphicsCommandList *command_list)
+{
+ D3D12_TEXTURE_COPY_LOCATION dst_location, src_location;
+ D3D12_PLACED_SUBRESOURCE_FOOTPRINT *layouts;
+ uint64_t *row_sizes, required_size;
+ D3D12_RESOURCE_DESC resource_desc;
+ ID3D12Resource *upload_buffer;
+ D3D12_MEMCPY_DEST dst_data;
+ ID3D12Device *device;
+ UINT *row_counts;
+ unsigned int i;
+ HRESULT hr;
+ void *ptr;
+
+ layouts = calloc(sub_resource_count, sizeof(*layouts));
+ ok(layouts, "Failed to allocate memory.\n");
+ row_counts = calloc(sub_resource_count, sizeof(*row_counts));
+ ok(row_counts, "Failed to allocate memory.\n");
+ row_sizes = calloc(sub_resource_count, sizeof(*row_sizes));
+ ok(row_sizes, "Failed to allocate memory.\n");
+
+ resource_desc = ID3D12Resource_GetDesc(texture);
+ hr = ID3D12Resource_GetDevice(texture, &IID_ID3D12Device, (void **)&device);
+ ok_(line)(SUCCEEDED(hr), "Failed to get device, hr %#x.\n", hr);
+
+ ID3D12Device_GetCopyableFootprints(device, &resource_desc, 0, sub_resource_count,
+ 0, layouts, row_counts, row_sizes, &required_size);
+
+ upload_buffer = create_upload_buffer_(line, device, required_size, NULL);
+
+ hr = ID3D12Resource_Map(upload_buffer, 0, NULL, (void **)&ptr);
+ ok_(line)(SUCCEEDED(hr), "Failed to map upload buffer, hr %#x.\n", hr);
+ for (i = 0; i < sub_resource_count; ++i)
+ {
+ dst_data.pData = (BYTE *)ptr + layouts[i].Offset;
+ dst_data.RowPitch = layouts[i].Footprint.RowPitch;
+ dst_data.SlicePitch = layouts[i].Footprint.RowPitch * row_counts[i];
+ copy_sub_resource_data(&dst_data, &data[i],
+ row_counts[i], layouts[i].Footprint.Depth, row_sizes[i]);
+ }
+ ID3D12Resource_Unmap(upload_buffer, 0, NULL);
+
+ for (i = 0; i < sub_resource_count; ++i)
+ {
+ dst_location.pResource = texture;
+ dst_location.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
+ dst_location.SubresourceIndex = i;
+
+ src_location.pResource = upload_buffer;
+ src_location.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
+ src_location.PlacedFootprint = layouts[i];
+
+ ID3D12GraphicsCommandList_CopyTextureRegion(command_list,
+ &dst_location, 0, 0, 0, &src_location, NULL);
+ }
+
+ hr = ID3D12GraphicsCommandList_Close(command_list);
+ ok_(line)(SUCCEEDED(hr), "Failed to close command list, hr %#x.\n", hr);
+
+ exec_command_list(queue, command_list);
+ wait_queue_idle(device, queue);
+
+ ID3D12Resource_Release(upload_buffer);
+ ID3D12Device_Release(device);
+
+ free(layouts);
+ free(row_counts);
+ free(row_sizes);
+}
+
static HRESULT create_root_signature(ID3D12Device *device, const D3D12_ROOT_SIGNATURE_DESC *desc,
ID3D12RootSignature **root_signature)
{
diff --git a/tests/shader_runner_d3d12.c b/tests/shader_runner_d3d12.c
index a0cdc5b38..171a855f1 100644
--- a/tests/shader_runner_d3d12.c
+++ b/tests/shader_runner_d3d12.c
@@ -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);
diff --git a/tests/texture-load.shader_test b/tests/texture-load.shader_test
new file mode 100644
index 000000000..86b36af49
--- /dev/null
+++ b/tests/texture-load.shader_test
@@ -0,0 +1,19 @@
+[texture 0]
+size (2, 2)
+0.1 0.2 0.3 0.4 0.5 0.7 0.6 0.8
+0.6 0.5 0.2 0.1 0.8 0.0 0.7 1.0
+
+[pixel shader]
+Texture2D t;
+
+float4 main(float4 pos : sv_position) : sv_target
+{
+ return t.Load(int3(pos.xy, 0));
+}
+
+[test]
+draw quad
+probe rgba (0, 0) (0.1, 0.2, 0.3, 0.4)
+probe rgba (1, 0) (0.5, 0.7, 0.6, 0.8)
+probe rgba (0, 1) (0.6, 0.5, 0.2, 0.1)
+probe rgba (1, 1) (0.8, 0.0, 0.7, 1.0)
--
2.33.0
More information about the wine-devel
mailing list