mirror of
https://gitlab.winehq.org/wine/vkd3d.git
synced 2024-11-21 16:46:41 -08:00
tests: Add a test for compute thread IDs.
This commit is contained in:
parent
404a2d6a3d
commit
809a43f06b
Notes:
Alexandre Julliard
2023-01-25 22:44:06 +01:00
Approved-by: Giovanni Mascellani (@giomasce) Approved-by: Henri Verbeet (@hverbeet) Approved-by: Alexandre Julliard (@julliard) Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/64
@ -26,11 +26,6 @@
|
|||||||
static PFN_D3D12_CREATE_VERSIONED_ROOT_SIGNATURE_DESERIALIZER pfn_D3D12CreateVersionedRootSignatureDeserializer;
|
static PFN_D3D12_CREATE_VERSIONED_ROOT_SIGNATURE_DESERIALIZER pfn_D3D12CreateVersionedRootSignatureDeserializer;
|
||||||
static PFN_D3D12_SERIALIZE_VERSIONED_ROOT_SIGNATURE pfn_D3D12SerializeVersionedRootSignature;
|
static PFN_D3D12_SERIALIZE_VERSIONED_ROOT_SIGNATURE pfn_D3D12SerializeVersionedRootSignature;
|
||||||
|
|
||||||
struct uvec4
|
|
||||||
{
|
|
||||||
unsigned int x, y, z, w;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ivec4
|
struct ivec4
|
||||||
{
|
{
|
||||||
int x, y, z, w;
|
int x, y, z, w;
|
||||||
@ -41,11 +36,6 @@ struct dvec2
|
|||||||
double x, y;
|
double x, y;
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool compare_uvec4(const struct uvec4* v1, const struct uvec4 *v2)
|
|
||||||
{
|
|
||||||
return v1->x == v2->x && v1->y == v2->y && v1->z == v2->z && v1->w == v2->w;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool compare_uint8(uint8_t a, uint8_t b, unsigned int max_diff)
|
static bool compare_uint8(uint8_t a, uint8_t b, unsigned int max_diff)
|
||||||
{
|
{
|
||||||
return abs(a - b) <= max_diff;
|
return abs(a - b) <= max_diff;
|
||||||
@ -725,35 +715,6 @@ static ID3D12CommandSignature *create_command_signature_(unsigned int line,
|
|||||||
return command_signature;
|
return command_signature;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define init_compute_test_context(context) init_compute_test_context_(__LINE__, context)
|
|
||||||
static bool init_compute_test_context_(unsigned int line, struct test_context *context)
|
|
||||||
{
|
|
||||||
ID3D12Device *device;
|
|
||||||
HRESULT hr;
|
|
||||||
|
|
||||||
memset(context, 0, sizeof(*context));
|
|
||||||
|
|
||||||
if (!(context->device = create_device()))
|
|
||||||
{
|
|
||||||
skip_(line)("Failed to create device.\n");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
device = context->device;
|
|
||||||
|
|
||||||
context->queue = create_command_queue_(line, device,
|
|
||||||
D3D12_COMMAND_LIST_TYPE_COMPUTE, D3D12_COMMAND_QUEUE_PRIORITY_NORMAL);
|
|
||||||
|
|
||||||
hr = ID3D12Device_CreateCommandAllocator(device, D3D12_COMMAND_LIST_TYPE_COMPUTE,
|
|
||||||
&IID_ID3D12CommandAllocator, (void **)&context->allocator);
|
|
||||||
ok_(line)(hr == S_OK, "Failed to create command allocator, hr %#x.\n", hr);
|
|
||||||
|
|
||||||
hr = ID3D12Device_CreateCommandList(device, 0, D3D12_COMMAND_LIST_TYPE_COMPUTE,
|
|
||||||
context->allocator, NULL, &IID_ID3D12GraphicsCommandList, (void **)&context->list);
|
|
||||||
ok_(line)(hr == S_OK, "Failed to create command list, hr %#x.\n", hr);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct depth_stencil_resource
|
struct depth_stencil_resource
|
||||||
{
|
{
|
||||||
ID3D12Resource *texture;
|
ID3D12Resource *texture;
|
||||||
|
@ -1034,6 +1034,35 @@ static inline bool init_test_context_(unsigned int line, struct test_context *co
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define init_compute_test_context(context) init_compute_test_context_(__LINE__, context)
|
||||||
|
static inline bool init_compute_test_context_(unsigned int line, struct test_context *context)
|
||||||
|
{
|
||||||
|
ID3D12Device *device;
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
memset(context, 0, sizeof(*context));
|
||||||
|
|
||||||
|
if (!(context->device = create_device()))
|
||||||
|
{
|
||||||
|
skip_(line)("Failed to create device.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
device = context->device;
|
||||||
|
|
||||||
|
context->queue = create_command_queue_(line, device,
|
||||||
|
D3D12_COMMAND_LIST_TYPE_COMPUTE, D3D12_COMMAND_QUEUE_PRIORITY_NORMAL);
|
||||||
|
|
||||||
|
hr = ID3D12Device_CreateCommandAllocator(device, D3D12_COMMAND_LIST_TYPE_COMPUTE,
|
||||||
|
&IID_ID3D12CommandAllocator, (void **)&context->allocator);
|
||||||
|
ok_(line)(hr == S_OK, "Failed to create command allocator, hr %#x.\n", hr);
|
||||||
|
|
||||||
|
hr = ID3D12Device_CreateCommandList(device, 0, D3D12_COMMAND_LIST_TYPE_COMPUTE,
|
||||||
|
context->allocator, NULL, &IID_ID3D12GraphicsCommandList, (void **)&context->list);
|
||||||
|
ok_(line)(hr == S_OK, "Failed to create command list, hr %#x.\n", hr);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static inline void destroy_pipeline_state_objects(struct test_context *context)
|
static inline void destroy_pipeline_state_objects(struct test_context *context)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
|
@ -416,6 +416,166 @@ static void test_preprocess(void)
|
|||||||
ID3D10Blob_Release(errors);
|
ID3D10Blob_Release(errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define compile_shader(a, b) compile_shader_(__LINE__, a, b, 0)
|
||||||
|
#define compile_shader_flags(a, b, c) compile_shader_(__LINE__, a, b, c)
|
||||||
|
static ID3D10Blob *compile_shader_(unsigned int line, const char *source, const char *target, UINT flags)
|
||||||
|
{
|
||||||
|
ID3D10Blob *blob = NULL, *errors = NULL;
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
hr = D3DCompile(source, strlen(source), NULL, NULL, NULL, "main", target, flags, 0, &blob, &errors);
|
||||||
|
ok_(line)(hr == S_OK, "Failed to compile shader, hr %#x.\n", hr);
|
||||||
|
if (errors)
|
||||||
|
{
|
||||||
|
if (vkd3d_test_state.debug_level)
|
||||||
|
trace_(line)("%s\n", (char *)ID3D10Blob_GetBufferPointer(errors));
|
||||||
|
ID3D10Blob_Release(errors);
|
||||||
|
}
|
||||||
|
return blob;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_thread_id(void)
|
||||||
|
{
|
||||||
|
ID3D12GraphicsCommandList *command_list;
|
||||||
|
struct d3d12_resource_readback rb;
|
||||||
|
struct test_context context;
|
||||||
|
ID3D12Resource *textures[3];
|
||||||
|
ID3D12DescriptorHeap *heap;
|
||||||
|
unsigned int i, x, y, z;
|
||||||
|
ID3D12Device *device;
|
||||||
|
ID3D10Blob *cs_code;
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
static const char cs_source[] =
|
||||||
|
"RWTexture3D<uint4> group_uav, thread_uav, dispatch_uav;\n"
|
||||||
|
"[numthreads(5, 3, 2)]\n"
|
||||||
|
"void main(uint3 group : sv_groupid, uint3 thread : sv_groupthreadid, uint3 dispatch : sv_dispatchthreadid)\n"
|
||||||
|
"{\n"
|
||||||
|
" group_uav[dispatch] = uint4(group, 1);\n"
|
||||||
|
" thread_uav[dispatch] = uint4(thread, 2);\n"
|
||||||
|
" dispatch_uav[dispatch] = uint4(dispatch, 3);\n"
|
||||||
|
"}";
|
||||||
|
|
||||||
|
static const D3D12_DESCRIPTOR_RANGE descriptor_range = {D3D12_DESCRIPTOR_RANGE_TYPE_UAV, 3, 0, 0, 0};
|
||||||
|
|
||||||
|
static const D3D12_ROOT_PARAMETER root_parameter =
|
||||||
|
{
|
||||||
|
.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE,
|
||||||
|
.DescriptorTable = {1, &descriptor_range},
|
||||||
|
};
|
||||||
|
|
||||||
|
static const D3D12_ROOT_SIGNATURE_DESC root_signature_desc =
|
||||||
|
{
|
||||||
|
.NumParameters = 1,
|
||||||
|
.pParameters = &root_parameter,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!init_compute_test_context(&context))
|
||||||
|
return;
|
||||||
|
command_list = context.list;
|
||||||
|
device = context.device;
|
||||||
|
|
||||||
|
hr = create_root_signature(device, &root_signature_desc, &context.root_signature);
|
||||||
|
ok(hr == S_OK, "Failed to create root signature, hr %#x.\n", hr);
|
||||||
|
|
||||||
|
heap = create_gpu_descriptor_heap(device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, 3);
|
||||||
|
|
||||||
|
for (i = 0; i < 3; ++i)
|
||||||
|
{
|
||||||
|
textures[i] = create_default_texture3d(device, 16, 8, 8, 1, DXGI_FORMAT_R32G32B32A32_UINT,
|
||||||
|
D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);
|
||||||
|
ID3D12Device_CreateUnorderedAccessView(device, textures[i], NULL, NULL,
|
||||||
|
get_cpu_descriptor_handle(&context, heap, i));
|
||||||
|
}
|
||||||
|
|
||||||
|
todo cs_code = compile_shader(cs_source, "cs_5_0");
|
||||||
|
if (cs_code)
|
||||||
|
{
|
||||||
|
context.pipeline_state = create_compute_pipeline_state(device, context.root_signature,
|
||||||
|
shader_bytecode(ID3D10Blob_GetBufferPointer(cs_code), ID3D10Blob_GetBufferSize(cs_code)));
|
||||||
|
|
||||||
|
ID3D12GraphicsCommandList_SetPipelineState(command_list, context.pipeline_state);
|
||||||
|
ID3D12GraphicsCommandList_SetComputeRootSignature(command_list, context.root_signature);
|
||||||
|
ID3D12GraphicsCommandList_SetComputeRootDescriptorTable(command_list,
|
||||||
|
0, get_gpu_descriptor_handle(&context, heap, 0));
|
||||||
|
ID3D12GraphicsCommandList_Dispatch(command_list, 2, 2, 2);
|
||||||
|
|
||||||
|
transition_resource_state(command_list, textures[0],
|
||||||
|
D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_COPY_SOURCE);
|
||||||
|
get_texture_readback_with_command_list(textures[0], 0, &rb, context.queue, command_list);
|
||||||
|
for (x = 0; x < 16; ++x)
|
||||||
|
{
|
||||||
|
for (y = 0; y < 8; ++y)
|
||||||
|
{
|
||||||
|
for (z = 0; z < 8; ++z)
|
||||||
|
{
|
||||||
|
const struct uvec4 *v = get_readback_data(&rb.rb, x, y, z, sizeof(struct uvec4));
|
||||||
|
struct uvec4 expect = {x / 5, y / 3, z / 2, 1};
|
||||||
|
|
||||||
|
if (x >= 10 || y >= 6 || z >= 4)
|
||||||
|
memset(&expect, 0, sizeof(expect));
|
||||||
|
|
||||||
|
ok(compare_uvec4(v, &expect), "Got {%u, %u, %u, %u} at (%u, %u, %u).\n",
|
||||||
|
v->x, v->y, v->z, v->w, x, y, z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
release_resource_readback(&rb);
|
||||||
|
reset_command_list(command_list, context.allocator);
|
||||||
|
|
||||||
|
transition_resource_state(command_list, textures[1],
|
||||||
|
D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_COPY_SOURCE);
|
||||||
|
get_texture_readback_with_command_list(textures[1], 0, &rb, context.queue, command_list);
|
||||||
|
for (x = 0; x < 16; ++x)
|
||||||
|
{
|
||||||
|
for (y = 0; y < 8; ++y)
|
||||||
|
{
|
||||||
|
for (z = 0; z < 8; ++z)
|
||||||
|
{
|
||||||
|
const struct uvec4 *v = get_readback_data(&rb.rb, x, y, z, sizeof(struct uvec4));
|
||||||
|
struct uvec4 expect = {x % 5, y % 3, z % 2, 2};
|
||||||
|
|
||||||
|
if (x >= 10 || y >= 6 || z >= 4)
|
||||||
|
memset(&expect, 0, sizeof(expect));
|
||||||
|
|
||||||
|
ok(compare_uvec4(v, &expect), "Got {%u, %u, %u, %u} at (%u, %u, %u).\n",
|
||||||
|
v->x, v->y, v->z, v->w, x, y, z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
release_resource_readback(&rb);
|
||||||
|
reset_command_list(command_list, context.allocator);
|
||||||
|
|
||||||
|
transition_resource_state(command_list, textures[2],
|
||||||
|
D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_COPY_SOURCE);
|
||||||
|
get_texture_readback_with_command_list(textures[2], 0, &rb, context.queue, command_list);
|
||||||
|
for (x = 0; x < 16; ++x)
|
||||||
|
{
|
||||||
|
for (y = 0; y < 8; ++y)
|
||||||
|
{
|
||||||
|
for (z = 0; z < 8; ++z)
|
||||||
|
{
|
||||||
|
const struct uvec4 *v = get_readback_data(&rb.rb, x, y, z, sizeof(struct uvec4));
|
||||||
|
struct uvec4 expect = {x, y, z, 3};
|
||||||
|
|
||||||
|
if (x >= 10 || y >= 6 || z >= 4)
|
||||||
|
memset(&expect, 0, sizeof(expect));
|
||||||
|
|
||||||
|
ok(compare_uvec4(v, &expect), "Got {%u, %u, %u, %u} at (%u, %u, %u).\n",
|
||||||
|
v->x, v->y, v->z, v->w, x, y, z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
release_resource_readback(&rb);
|
||||||
|
reset_command_list(command_list, context.allocator);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < 3; ++i)
|
||||||
|
ID3D12Resource_Release(textures[i]);
|
||||||
|
ID3D12DescriptorHeap_Release(heap);
|
||||||
|
destroy_test_context(&context);
|
||||||
|
}
|
||||||
|
|
||||||
START_TEST(hlsl_d3d12)
|
START_TEST(hlsl_d3d12)
|
||||||
{
|
{
|
||||||
parse_args(argc, argv);
|
parse_args(argc, argv);
|
||||||
@ -423,4 +583,5 @@ START_TEST(hlsl_d3d12)
|
|||||||
init_adapter_info();
|
init_adapter_info();
|
||||||
|
|
||||||
run_test(test_preprocess);
|
run_test(test_preprocess);
|
||||||
|
run_test(test_thread_id);
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,11 @@ struct vec4
|
|||||||
float x, y, z, w;
|
float x, y, z, w;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct uvec4
|
||||||
|
{
|
||||||
|
unsigned int x, y, z, w;
|
||||||
|
};
|
||||||
|
|
||||||
struct resource_readback
|
struct resource_readback
|
||||||
{
|
{
|
||||||
uint64_t width;
|
uint64_t width;
|
||||||
@ -97,6 +102,11 @@ static bool compare_float(float f, float g, unsigned int ulps)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool compare_uvec4(const struct uvec4 *v1, const struct uvec4 *v2)
|
||||||
|
{
|
||||||
|
return v1->x == v2->x && v1->y == v2->y && v1->z == v2->z && v1->w == v2->w;
|
||||||
|
}
|
||||||
|
|
||||||
static inline bool compare_vec4(const struct vec4 *v1, const struct vec4 *v2, unsigned int ulps)
|
static inline bool compare_vec4(const struct vec4 *v1, const struct vec4 *v2, unsigned int ulps)
|
||||||
{
|
{
|
||||||
return compare_float(v1->x, v2->x, ulps)
|
return compare_float(v1->x, v2->x, ulps)
|
||||||
|
Loading…
Reference in New Issue
Block a user