-- v6: vkd3d-shader/dxil: Implement DX intrinsic BufferUpdateCounter. tests/hlsl: Add UAV counter tests.
From: Conor McCarthy cmccarthy@codeweavers.com
--- Makefile.am | 1 + tests/hlsl/uav-counter.shader_test | 39 ++++++++++++++++++++++++++++++ tests/shader_runner.c | 9 +++++++ tests/shader_runner.h | 1 + tests/shader_runner_d3d11.c | 9 +++++-- tests/shader_runner_d3d12.c | 3 ++- 6 files changed, 59 insertions(+), 3 deletions(-) create mode 100644 tests/hlsl/uav-counter.shader_test
diff --git a/Makefile.am b/Makefile.am index 52e154fee..8abe08638 100644 --- a/Makefile.am +++ b/Makefile.am @@ -205,6 +205,7 @@ vkd3d_shader_tests = \ tests/hlsl/trunc.shader_test \ tests/hlsl/type-names.shader_test \ tests/hlsl/uav-atomics.shader_test \ + tests/hlsl/uav-counter.shader_test \ tests/hlsl/uav-load.shader_test \ tests/hlsl/uav-out-param.shader_test \ tests/hlsl/uav-rwbuffer.shader_test \ diff --git a/tests/hlsl/uav-counter.shader_test b/tests/hlsl/uav-counter.shader_test new file mode 100644 index 000000000..b008d52f8 --- /dev/null +++ b/tests/hlsl/uav-counter.shader_test @@ -0,0 +1,39 @@ +[require] +shader model >= 5.0 + +[uav 1] +format r32 uint +size (counter_buffer, 1) +0 + +[compute shader todo] +RWStructuredBuffer<uint> u : register(u1); + + [numthreads(4, 1, 1)] +void main() +{ + u.IncrementCounter(); +} + +[test] +todo dispatch 3 1 1 +probe uav 1 (0) rui (12) + + +[uav 1] +format r32 sint +size (counter_buffer, 1) +0 + +[compute shader todo] +RWStructuredBuffer<int> u : register(u1); + + [numthreads(4, 1, 1)] +void main() +{ + u.DecrementCounter(); +} + +[test] +todo dispatch 3 1 1 +probe uav 1 (0) ri (-12) diff --git a/tests/shader_runner.c b/tests/shader_runner.c index ccdda5b78..2f99eed99 100644 --- a/tests/shader_runner.c +++ b/tests/shader_runner.c @@ -481,6 +481,15 @@ static void parse_resource_directive(struct resource_params *resource, const cha resource->dimension = RESOURCE_DIMENSION_BUFFER; resource->height = 1; } + else if (sscanf(line, "( counter_buffer , %u ) ", &resource->width) == 1) + { + resource->dimension = RESOURCE_DIMENSION_BUFFER; + resource->height = 1; + resource->is_uav_counter = true; + resource->stride = sizeof(uint32_t); + resource->texel_size = resource->stride; + resource->format = DXGI_FORMAT_UNKNOWN; + } else if (sscanf(line, "( 2d , %u , %u ) ", &resource->width, &resource->height) == 2) { resource->dimension = RESOURCE_DIMENSION_2D; diff --git a/tests/shader_runner.h b/tests/shader_runner.h index 5666b2d59..7cba0a525 100644 --- a/tests/shader_runner.h +++ b/tests/shader_runner.h @@ -88,6 +88,7 @@ struct resource_params
DXGI_FORMAT format; bool is_shadow; + bool is_uav_counter; enum texture_data_type data_type; unsigned int texel_size; unsigned int stride; diff --git a/tests/shader_runner_d3d11.c b/tests/shader_runner_d3d11.c index ffc89085c..1285ca41f 100644 --- a/tests/shader_runner_d3d11.c +++ b/tests/shader_runner_d3d11.c @@ -49,6 +49,7 @@ struct d3d11_resource ID3D11RenderTargetView *rtv; ID3D11ShaderResourceView *srv; ID3D11UnorderedAccessView *uav; + bool is_uav_counter; };
static struct d3d11_resource *d3d11_resource(struct resource *r) @@ -438,12 +439,13 @@ static void init_resource_uav_buffer(struct d3d11_shader_runner *runner, struct
resource->buffer = create_buffer(device, D3D11_BIND_UNORDERED_ACCESS, params->data_size, params->stride, params->data); resource->resource = (ID3D11Resource *)resource->buffer; + resource->is_uav_counter = params->is_uav_counter;
uav_desc.Format = params->format; uav_desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER; uav_desc.Buffer.FirstElement = 0; uav_desc.Buffer.NumElements = params->data_size / params->texel_size; - uav_desc.Buffer.Flags = 0; + uav_desc.Buffer.Flags = params->is_uav_counter ? D3D11_BUFFER_UAV_FLAG_COUNTER : 0; hr = ID3D11Device_CreateUnorderedAccessView(device, resource->resource, &uav_desc, &resource->uav); ok(hr == S_OK, "Failed to create view, hr %#lx.\n", hr); } @@ -754,7 +756,10 @@ static struct resource_readback *d3d11_runner_get_resource_readback(struct shade assert(0); }
- ID3D11DeviceContext_CopyResource(runner->immediate_context, rb->resource, resource->resource); + if (resource->is_uav_counter) + ID3D11DeviceContext_CopyStructureCount(runner->immediate_context, (ID3D11Buffer *)rb->resource, 0, resource->uav); + else + ID3D11DeviceContext_CopyResource(runner->immediate_context, rb->resource, resource->resource); hr = ID3D11DeviceContext_Map(runner->immediate_context, rb->resource, 0, D3D11_MAP_READ, 0, &map_desc); ok(hr == S_OK, "Failed to map texture, hr %#lx.\n", hr);
diff --git a/tests/shader_runner_d3d12.c b/tests/shader_runner_d3d12.c index ce27ad22a..9bf7bb248 100644 --- a/tests/shader_runner_d3d12.c +++ b/tests/shader_runner_d3d12.c @@ -203,7 +203,8 @@ static struct resource *d3d12_runner_create_resource(struct shader_runner *r, co uav_desc.Buffer.StructureByteStride = params->stride;
ID3D12Device_CreateUnorderedAccessView(device, resource->resource, - NULL, &uav_desc, get_cpu_descriptor_handle(test_context, runner->heap, resource->r.slot + MAX_RESOURCES)); + params->is_uav_counter ? resource->resource : NULL, &uav_desc, + get_cpu_descriptor_handle(test_context, runner->heap, resource->r.slot + MAX_RESOURCES)); } else {
From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d-shader/dxil.c | 39 ++++++++++++++++++++++++++++++ tests/hlsl/uav-counter.shader_test | 4 +-- 2 files changed, 41 insertions(+), 2 deletions(-)
diff --git a/libs/vkd3d-shader/dxil.c b/libs/vkd3d-shader/dxil.c index 86671c07d..34615acbf 100644 --- a/libs/vkd3d-shader/dxil.c +++ b/libs/vkd3d-shader/dxil.c @@ -388,6 +388,7 @@ enum dx_intrinsic_opcode DX_TEXTURE_STORE = 67, DX_BUFFER_LOAD = 68, DX_BUFFER_STORE = 69, + DX_BUFFER_UPDATE_COUNTER = 70, DX_GET_DIMENSIONS = 72, DX_TEXTURE_GATHER = 73, DX_TEXTURE_GATHER_CMP = 74, @@ -4134,6 +4135,43 @@ static void sm6_parser_emit_dx_barrier(struct sm6_parser *sm6, enum dx_intrinsic } }
+static void sm6_parser_emit_dx_buffer_update_counter(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, + const struct sm6_value **operands, struct function_emission_state *state) +{ + struct vkd3d_shader_instruction *ins = state->ins; + struct vkd3d_shader_src_param *src_params; + const struct sm6_value *resource; + unsigned int i; + int8_t inc; + + resource = operands[0]; + if (!sm6_value_validate_is_handle(resource, sm6)) + return; + + if (!sm6_value_is_constant(operands[1])) + { + FIXME("Unsupported dynamic update operand.\n"); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "A dynamic update value for a UAV counter operation is not supported."); + return; + } + i = sm6_value_get_constant_uint(operands[1]); + if (i != 1 && i != 255) + { + WARN("Unexpected update value %#x.\n", i); + vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_OPERANDS, + "Update value %#x for a UAV counter operation is not supported.", i); + } + inc = i; + + vsir_instruction_init(ins, &sm6->p.location, (inc < 0) ? VKD3DSIH_IMM_ATOMIC_CONSUME : VKD3DSIH_IMM_ATOMIC_ALLOC); + if (!(src_params = instruction_src_params_alloc(ins, 1, sm6))) + return; + src_param_init_vector_from_reg(&src_params[0], &resource->u.handle.reg); + + instruction_dst_param_init_ssa_scalar(ins, sm6); +} + static void sm6_parser_emit_dx_cbuffer_load(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, const struct sm6_value **operands, struct function_emission_state *state) { @@ -4967,6 +5005,7 @@ static const struct sm6_dx_opcode_info sm6_dx_op_table[] = [DX_BFREV ] = {"m", "R", sm6_parser_emit_dx_unary}, [DX_BUFFER_LOAD ] = {"o", "Hii", sm6_parser_emit_dx_buffer_load}, [DX_BUFFER_STORE ] = {"v", "Hiiooooc", sm6_parser_emit_dx_buffer_store}, + [DX_BUFFER_UPDATE_COUNTER ] = {"i", "H8", sm6_parser_emit_dx_buffer_update_counter}, [DX_CBUFFER_LOAD_LEGACY ] = {"o", "Hi", sm6_parser_emit_dx_cbuffer_load}, [DX_COS ] = {"g", "R", sm6_parser_emit_dx_sincos}, [DX_COUNT_BITS ] = {"i", "m", sm6_parser_emit_dx_unary}, diff --git a/tests/hlsl/uav-counter.shader_test b/tests/hlsl/uav-counter.shader_test index b008d52f8..0f05e1a58 100644 --- a/tests/hlsl/uav-counter.shader_test +++ b/tests/hlsl/uav-counter.shader_test @@ -16,7 +16,7 @@ void main() }
[test] -todo dispatch 3 1 1 +todo(sm<6) dispatch 3 1 1 probe uav 1 (0) rui (12)
@@ -35,5 +35,5 @@ void main() }
[test] -todo dispatch 3 1 1 +todo(sm<6) dispatch 3 1 1 probe uav 1 (0) ri (-12)
I left it out because it would be untested dead code. The GL and Vulkan tests can't run until the compiler supports UAV counters.
Oh right, the Vulkan runner doesn't run the DXIL tests, even though in principle it could.
This merge request was approved by Henri Verbeet.