With no compiler support, there's no easy way to verify shader runner support for d3d11 UAV counters works, so I've left it out for now.
-- v4: 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 | 2 +- tests/shader_runner_d3d12.c | 3 ++- 6 files changed, 53 insertions(+), 2 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..059b9f2b4 100644 --- a/tests/shader_runner_d3d11.c +++ b/tests/shader_runner_d3d11.c @@ -443,7 +443,7 @@ static void init_resource_uav_buffer(struct d3d11_shader_runner *runner, struct 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); } 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 de51588b5..eeb0ac83b 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, @@ -3989,6 +3990,43 @@ static void sm6_parser_emit_dx_atomic_binop(struct sm6_parser *sm6, enum dx_intr dst->u.reg = dst_params[0].reg; }
+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) { @@ -4821,6 +4859,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)