Goes atop !601. The last three commits belong to this MR.
From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d-shader/dxil.c | 143 +++++++++++++++++- tests/hlsl/cbuffer.shader_test | 4 +- tests/hlsl/initializer-objects.shader_test | 4 +- tests/hlsl/load-level.shader_test | 6 +- tests/hlsl/object-references.shader_test | 4 +- ...egister-reservations-resources.shader_test | 32 ++-- tests/hlsl/swizzle-constant-prop.shader_test | 6 +- tests/hlsl/texture-load-offset.shader_test | 4 +- tests/hlsl/texture-load.shader_test | 6 +- 9 files changed, 182 insertions(+), 27 deletions(-)
diff --git a/libs/vkd3d-shader/dxil.c b/libs/vkd3d-shader/dxil.c index 3e1ba3911..c48665edb 100644 --- a/libs/vkd3d-shader/dxil.c +++ b/libs/vkd3d-shader/dxil.c @@ -33,6 +33,7 @@ static const uint64_t ALLOCA_FLAG_IN_ALLOCA = 0x20; static const uint64_t ALLOCA_FLAG_EXPLICIT_TYPE = 0x40; static const uint64_t ALLOCA_ALIGNMENT_MASK = ALLOCA_FLAG_IN_ALLOCA - 1; static const unsigned int SHADER_DESCRIPTOR_TYPE_COUNT = 4; +static const size_t MAX_IR_INSTRUCTIONS_PER_DXIL_INSTRUCTION = 5;
static const unsigned int dx_max_thread_group_size[3] = {1024, 1024, 64};
@@ -362,6 +363,7 @@ enum dx_intrinsic_opcode DX_UBFE = 52, DX_CREATE_HANDLE = 57, DX_CBUFFER_LOAD_LEGACY = 59, + DX_TEXTURE_LOAD = 66, DX_BUFFER_LOAD = 68, DX_DERIV_COARSEX = 83, DX_DERIV_COARSEY = 84, @@ -2369,6 +2371,26 @@ static bool sm6_value_validate_is_handle(const struct sm6_value *value, struct s return true; }
+static bool sm6_value_validate_is_texture_handle(const struct sm6_value *value, enum dx_intrinsic_opcode op, + struct sm6_parser *sm6) +{ + enum dxil_resource_kind kind; + + if (!sm6_value_validate_is_handle(value, sm6)) + return false; + + kind = value->u.handle.d->kind; + if (kind < RESOURCE_KIND_TEXTURE1D || kind > RESOURCE_KIND_TEXTURECUBEARRAY) + { + WARN("Resource kind %u for op %u is not a texture.\n", kind, op); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_RESOURCE_HANDLE, + "Resource kind %u for texture operation %u is not a texture.", kind, op); + return false; + } + + return true; +} + static bool sm6_value_validate_is_pointer(const struct sm6_value *value, struct sm6_parser *sm6) { if (!sm6_type_is_pointer(value->type)) @@ -3197,6 +3219,7 @@ struct function_emission_state { struct sm6_block *code_block; struct vkd3d_shader_instruction *ins; + unsigned int temp_idx; };
static void sm6_parser_emit_alloca(struct sm6_parser *sm6, const struct dxil_record *record, @@ -3516,6 +3539,60 @@ static void sm6_parser_emit_br(struct sm6_parser *sm6, const struct dxil_record ins->handler_idx = VKD3DSIH_NOP; }
+static bool sm6_parser_emit_coordinate_construct(struct sm6_parser *sm6, const struct sm6_value **operands, + const struct sm6_value *z_operand, struct function_emission_state *state, + struct vkd3d_shader_register *reg) +{ + struct vkd3d_shader_instruction *ins = state->ins; + unsigned int i, component_count, src_count; + struct vkd3d_shader_src_param *src_params; + struct vkd3d_shader_dst_param *dst_param; + const unsigned int max_operands = 3; + + if (z_operand) + { + component_count = max_operands; + } + else + { + for (component_count = 0; component_count < max_operands; ++component_count) + if (operands[component_count]->is_undefined) + break; + } + + if (component_count == 1) + { + *reg = operands[0]->u.reg; + return true; + } + + register_init_with_id(reg, VKD3DSPR_TEMP, operands[0]->u.reg.data_type, state->temp_idx++); + reg->dimension = VSIR_DIMENSION_VEC4; + + src_count = component_count + !!z_operand; + for (i = 0; i < src_count; ++i, ++ins) + { + vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_MOV); + + if (!(src_params = instruction_src_params_alloc(ins, 1, sm6))) + return false; + + src_param_init(&src_params[0]); + src_params[0].reg = (i < component_count) ? operands[i]->u.reg : z_operand->u.reg; + + if (!(dst_param = instruction_dst_params_alloc(ins, 1, sm6))) + return false; + + dst_param_init_scalar(dst_param, i); + dst_param->reg = *reg; + } + + state->ins = ins; + state->code_block->instruction_count += src_count; + + return true; +} + static enum vkd3d_shader_opcode map_dx_unary_op(enum dx_intrinsic_opcode op) { switch (op) @@ -3856,6 +3933,19 @@ static void sm6_parser_emit_dx_buffer_load(struct sm6_parser *sm6, enum dx_intri instruction_dst_param_init_ssa_vector(ins, VKD3D_VEC4_SIZE, sm6); }
+static unsigned int sm6_value_get_texel_offset(const struct sm6_value *value) +{ + return sm6_value_is_undef(value) ? 0 : sm6_value_get_constant_uint(value); +} + +static void instruction_set_texel_offset(struct vkd3d_shader_instruction *ins, + const struct sm6_value **operands, struct sm6_parser *sm6) +{ + ins->texel_offset.u = sm6_value_get_texel_offset(operands[0]); + ins->texel_offset.v = sm6_value_get_texel_offset(operands[1]); + ins->texel_offset.w = sm6_value_get_texel_offset(operands[2]); +} + static void sm6_parser_emit_dx_sincos(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, const struct sm6_value **operands, struct function_emission_state *state) { @@ -3932,6 +4022,50 @@ static void sm6_parser_emit_dx_store_output(struct sm6_parser *sm6, enum dx_intr src_param_init_from_value(src_param, value); }
+static void sm6_parser_emit_dx_texture_load(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, + const struct sm6_value **operands, struct function_emission_state *state) +{ + const struct sm6_value *resource, *mip_level_or_sample_count; + enum vkd3d_shader_resource_type resource_type; + struct vkd3d_shader_src_param *src_params; + struct vkd3d_shader_instruction *ins; + struct vkd3d_shader_register coord; + bool is_multisample, is_uav; + unsigned int i; + + resource = operands[0]; + if (!sm6_value_validate_is_texture_handle(resource, op, sm6)) + return; + + resource_type = resource->u.handle.d->resource_type; + is_multisample = resource_type == VKD3D_SHADER_RESOURCE_TEXTURE_2DMS + || resource_type == VKD3D_SHADER_RESOURCE_TEXTURE_2DMSARRAY; + is_uav = resource->u.handle.d->type == VKD3D_SHADER_DESCRIPTOR_TYPE_UAV; + + mip_level_or_sample_count = (resource_type != VKD3D_SHADER_RESOURCE_BUFFER) ? operands[1] : NULL; + if (!sm6_parser_emit_coordinate_construct(sm6, &operands[2], + is_multisample ? NULL : mip_level_or_sample_count, state, &coord)) + { + return; + } + + ins = state->ins; + instruction_init_with_resource(ins, is_uav ? VKD3DSIH_LD_UAV_TYPED + : is_multisample ? VKD3DSIH_LD2DMS : VKD3DSIH_LD, resource, sm6); + instruction_set_texel_offset(ins, &operands[5], sm6); + + for (i = 0; i < VKD3D_VEC4_SIZE; ++i) + ins->resource_data_type[i] = resource->u.handle.d->resource_data_type; + + src_params = instruction_src_params_alloc(ins, 2 + is_multisample, sm6); + src_param_init_vector_from_reg(&src_params[0], &coord); + src_param_init_vector_from_reg(&src_params[1], &resource->u.handle.reg); + if (is_multisample) + src_param_init_from_value(&src_params[2], mip_level_or_sample_count); + + instruction_dst_param_init_ssa_vector(ins, VKD3D_VEC4_SIZE, sm6); +} + struct sm6_dx_opcode_info { const char *ret_type; @@ -3945,6 +4079,7 @@ struct sm6_dx_opcode_info 8 -> int8 b -> constant int1 c -> constant int8/16/32 + C -> constant or undefined int8/16/32 i -> int32 m -> int16/32/64 f -> float @@ -3994,6 +4129,7 @@ static const struct sm6_dx_opcode_info sm6_dx_op_table[] = [DX_SQRT ] = {"g", "R", sm6_parser_emit_dx_unary}, [DX_STORE_OUTPUT ] = {"v", "ii8o", sm6_parser_emit_dx_store_output}, [DX_TAN ] = {"g", "R", sm6_parser_emit_dx_unary}, + [DX_TEXTURE_LOAD ] = {"o", "HiiiiCCC", sm6_parser_emit_dx_texture_load}, [DX_UBFE ] = {"m", "iiR", sm6_parser_emit_dx_tertiary}, [DX_UMAX ] = {"m", "RR", sm6_parser_emit_dx_binary}, [DX_UMIN ] = {"m", "RR", sm6_parser_emit_dx_binary}, @@ -4021,6 +4157,9 @@ static bool sm6_parser_validate_operand_type(struct sm6_parser *sm6, const struc case 'c': return sm6_value_is_constant(value) && sm6_type_is_integer(type) && type->u.width >= 8 && type->u.width <= 32; + case 'C': + return (sm6_value_is_constant(value) || sm6_value_is_undef(value)) + && sm6_type_is_integer(type) && type->u.width >= 8 && type->u.width <= 32; case 'i': return sm6_type_is_i32(type); case 'm': @@ -5378,7 +5517,8 @@ static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const
/* Some instructions can emit >1 IR instruction, so extra may be used. */ if (!vkd3d_array_reserve((void **)&code_block->instructions, &code_block->instruction_capacity, - code_block->instruction_count + 1, sizeof(*code_block->instructions))) + code_block->instruction_count + MAX_IR_INSTRUCTIONS_PER_DXIL_INSTRUCTION, + sizeof(*code_block->instructions))) { ERR("Failed to allocate instructions.\n"); return VKD3D_ERROR_OUT_OF_MEMORY; @@ -5409,6 +5549,7 @@ static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const { struct function_emission_state state = {code_block, ins}; sm6_parser_emit_call(sm6, record, &state, dst); + sm6->p.program.temp_count = max(sm6->p.program.temp_count, state.temp_idx); break; } case FUNC_CODE_INST_CAST: diff --git a/tests/hlsl/cbuffer.shader_test b/tests/hlsl/cbuffer.shader_test index b4dc01edd..62f1cd28c 100644 --- a/tests/hlsl/cbuffer.shader_test +++ b/tests/hlsl/cbuffer.shader_test @@ -549,7 +549,7 @@ float4 main() : sv_target }
[test] -todo(sm>=6) draw quad +draw quad probe all rgba (1.0, 1.0, 1.0, 1.0)
@@ -726,5 +726,5 @@ uniform 0 float4 0.0 1.0 2.0 3.0 uniform 4 float4 4.0 5.0 6.0 7.0 uniform 8 float4 8.0 9.0 10.0 11.0 uniform 12 float4 12.0 13.0 14.0 15.0 -todo(sm>=6) draw quad +draw quad probe all rgba (124.0, 135.0, 146.0, 150.5) diff --git a/tests/hlsl/initializer-objects.shader_test b/tests/hlsl/initializer-objects.shader_test index 514a7cebb..d9c0bc91c 100644 --- a/tests/hlsl/initializer-objects.shader_test +++ b/tests/hlsl/initializer-objects.shader_test @@ -25,7 +25,7 @@ float4 main() : sv_target }
[test] -todo(sm>=6) draw quad +draw quad probe all rgba (0.2, 0.2, 0.2, 0.1)
@@ -48,7 +48,7 @@ float4 main() : sv_target }
[test] -todo(sm>=6) draw quad +draw quad probe all rgba (31.1, 41.1, 51.1, 61.1) 1
diff --git a/tests/hlsl/load-level.shader_test b/tests/hlsl/load-level.shader_test index 9df2f01fb..0f64bd5d5 100644 --- a/tests/hlsl/load-level.shader_test +++ b/tests/hlsl/load-level.shader_test @@ -22,10 +22,10 @@ float4 main() : sv_target
[test] uniform 0 uint 0 -todo(sm>=6) draw quad +draw quad probe all rgba (1.0, 0.0, 1.0, 0.0) uniform 0 uint 1 -todo(sm>=6) draw quad +draw quad probe all rgba (0.0, 0.0, 1.0, 0.0)
[pixel shader fail] @@ -47,5 +47,5 @@ float4 main() : sv_target }
[test] -todo(sm>=6) draw quad +draw quad probe all rgba (1.0, 0.0, 1.0, 0.0) diff --git a/tests/hlsl/object-references.shader_test b/tests/hlsl/object-references.shader_test index c857f3885..5c8070946 100644 --- a/tests/hlsl/object-references.shader_test +++ b/tests/hlsl/object-references.shader_test @@ -73,7 +73,7 @@ float4 main(float4 pos : sv_position) : sv_target }
[test] -todo(sm>=6) draw quad +draw quad probe (0, 0) rgba (0.1, 0.2, 0.3, 0.4) probe (1, 0) rgba (0.5, 0.7, 0.6, 0.8) probe (0, 1) rgba (0.6, 0.5, 0.2, 0.1) @@ -134,7 +134,7 @@ float4 main() : sv_target }
[test] -todo(sm>=6) draw quad +draw quad probe all rgba (2132, 2132, 2132, 1111)
diff --git a/tests/hlsl/register-reservations-resources.shader_test b/tests/hlsl/register-reservations-resources.shader_test index 9539b05ff..22a441026 100644 --- a/tests/hlsl/register-reservations-resources.shader_test +++ b/tests/hlsl/register-reservations-resources.shader_test @@ -50,7 +50,7 @@ float4 main() : sv_target }
[test] -todo(sm>=6) draw quad +draw quad probe all rgba (0.0, 0.0, 0.0, 99.0)
@@ -65,7 +65,7 @@ float4 main() : sv_target }
[test] -todo(sm>=6) draw quad +draw quad probe all rgba (1.0, 1.0, 1.0, 99.0)
@@ -79,10 +79,24 @@ float4 main() : sv_target return tex.Load(int3(0, 0, 0)); }
+[require] +shader model >= 4.0 +shader model < 6.0 + [test] -todo(sm>=6) draw quad +draw quad probe all rgba (0.0, 0.0, 0.0, 99.0)
+[require] +shader model >= 6.0 + +[test] +draw quad +probe all rgba (1.0, 1.0, 1.0, 99.0) + +[require] +shader model >= 4.0 +
% Register reservation with incorrect register type. [pixel shader fail(sm>=6)] @@ -109,7 +123,7 @@ float4 main() : sv_target }
[test] -todo(sm>=6) draw quad +draw quad probe all rgba (4.0, 4.0, 4.0, 99.0)
@@ -125,7 +139,7 @@ float4 main() : sv_target }
[test] -todo(sm>=6) draw quad +draw quad probe all rgba (1.0, 1.0, 1.0, 99.0)
@@ -140,7 +154,7 @@ float4 main() : sv_target }
[test] -todo(sm>=6) draw quad +draw quad probe all rgba (2.0, 2.0, 2.0, 99.0)
@@ -154,7 +168,7 @@ float4 main() : sv_target }
[test] -todo(sm>=6) draw quad +draw quad probe all rgba (2.0, 2.0, 2.0, 99.0)
@@ -227,5 +241,5 @@ float4 main() : sv_target }
[test] -todo(sm>=6) draw quad -todo probe all rgba (1.0, 1.0, 1.0, 99.0) +draw quad +todo(sm<6) probe all rgba (1.0, 1.0, 1.0, 99.0) diff --git a/tests/hlsl/swizzle-constant-prop.shader_test b/tests/hlsl/swizzle-constant-prop.shader_test index a0ec18e45..357a3496e 100644 --- a/tests/hlsl/swizzle-constant-prop.shader_test +++ b/tests/hlsl/swizzle-constant-prop.shader_test @@ -25,7 +25,7 @@ float4 main() : sv_target
[test] uniform 0 int 4 -todo(sm>=6) draw quad +draw quad probe all rgba (110, 210, 410, 410)
@@ -43,7 +43,7 @@ float4 main() : sv_target
[test] uniform 0 int 3 -todo(sm>=6) draw quad +draw quad probe all rgba (105, 5, 305, 305)
@@ -59,5 +59,5 @@ float4 main() : sv_target
[test] uniform 0 int 1 -todo(sm>=6) draw quad +draw quad probe all rgba (14.0, 14.0, 14.0, 14.0) diff --git a/tests/hlsl/texture-load-offset.shader_test b/tests/hlsl/texture-load-offset.shader_test index f32b2191f..52b6a5f93 100644 --- a/tests/hlsl/texture-load-offset.shader_test +++ b/tests/hlsl/texture-load-offset.shader_test @@ -18,7 +18,7 @@ float4 main(float4 pos : sv_position) : sv_target
[test] -todo(sm>=6) draw quad +draw quad probe (0, 0) rgba (0, 1, 0, 1) probe (1, 0) rgba (1, 1, 0, 1) probe (0, 1) rgba (0, 2, 0, 1) @@ -35,7 +35,7 @@ float4 main(float4 pos : sv_position) : sv_target
[test] -todo(sm>=6) draw quad +draw quad probe (3, 0) rgba (1, 0, 0, 1) probe (4, 0) rgba (2, 0, 0, 1) probe (3, 1) rgba (1, 1, 0, 1) diff --git a/tests/hlsl/texture-load.shader_test b/tests/hlsl/texture-load.shader_test index 30a33a4a4..0723c1384 100644 --- a/tests/hlsl/texture-load.shader_test +++ b/tests/hlsl/texture-load.shader_test @@ -15,7 +15,7 @@ float4 main(float4 pos : sv_position) : sv_target }
[test] -todo(sm>=6) draw quad +draw quad probe (0, 0) rgba (0.1, 0.2, 0.3, 0.4) probe (1, 0) rgba (0.5, 0.7, 0.6, 0.8) probe (0, 1) rgba (0.6, 0.5, 0.2, 0.1) @@ -30,7 +30,7 @@ float4 main(float4 pos : sv_position) : sv_target }
[test] -todo(sm>=6) draw quad +draw quad probe (0, 0) rgba (0.1, 0.2, 0.3, 0.4) probe (1, 0) rgba (0.6, 0.5, 0.2, 0.1) probe (0, 1) rgba (0.5, 0.7, 0.6, 0.8) @@ -46,7 +46,7 @@ float4 main(float4 pos : sv_position) : sv_target }
[test] -todo(sm>=6) draw quad +draw quad probe (0, 0) rgba (0.1, 0.2, 0.3, 0.4) probe (1, 0) rgba (0.6, 0.5, 0.2, 0.1) probe (0, 1) rgba (0.5, 0.7, 0.6, 0.8)
From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d-shader/spirv.c | 11 ++++++++++- tests/hlsl/texture-load-typed.shader_test | 2 +- 2 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index 298ad31d9..d76ba6f96 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -3894,9 +3894,10 @@ static uint32_t spirv_compiler_emit_load_ssa_reg(struct spirv_compiler *compiler } assert(vkd3d_swizzle_is_scalar(swizzle, reg));
+ reg_component_type = vkd3d_component_type_from_data_type(ssa->data_type); + if (reg->dimension == VSIR_DIMENSION_SCALAR) { - reg_component_type = vkd3d_component_type_from_data_type(ssa->data_type); if (component_type != reg_component_type) { type_id = vkd3d_spirv_get_type_id(builder, component_type, 1); @@ -3906,6 +3907,14 @@ static uint32_t spirv_compiler_emit_load_ssa_reg(struct spirv_compiler *compiler return val_id; }
+ if (component_type != reg_component_type) + { + /* Required for resource loads with sampled type int, because DXIL has no signedness. + * Only 128-bit vector sizes are used. */ + type_id = vkd3d_spirv_get_type_id(builder, component_type, VKD3D_VEC4_SIZE); + val_id = vkd3d_spirv_build_op_bitcast(builder, type_id, val_id); + } + type_id = vkd3d_spirv_get_type_id(builder, component_type, 1); component_idx = vsir_swizzle_get_component(swizzle, 0); return vkd3d_spirv_build_op_composite_extract1(builder, type_id, val_id, component_idx); diff --git a/tests/hlsl/texture-load-typed.shader_test b/tests/hlsl/texture-load-typed.shader_test index 67a13f10d..736b4ae1e 100644 --- a/tests/hlsl/texture-load-typed.shader_test +++ b/tests/hlsl/texture-load-typed.shader_test @@ -48,7 +48,7 @@ float4 main() : sv_target }
[test] -todo(sm>=6) draw quad +draw quad probe all rgba (0.8, -3.0, 4294967295.0, 123.0)
% lowercase 'texture2D'
From: Conor McCarthy cmccarthy@codeweavers.com
Shader models >= 5.1 support descriptor indexing, and emit arrayed resource declarations. --- tests/hlsl/object-references.shader_test | 2 +- ...egister-reservations-resources.shader_test | 2 +- tests/shader_runner_d3d12.c | 33 ++++++++++++++----- 3 files changed, 27 insertions(+), 10 deletions(-)
diff --git a/tests/hlsl/object-references.shader_test b/tests/hlsl/object-references.shader_test index 5c8070946..698df0117 100644 --- a/tests/hlsl/object-references.shader_test +++ b/tests/hlsl/object-references.shader_test @@ -111,7 +111,7 @@ float4 main() : sv_target }
[test] -todo(sm>=6) draw quad +draw quad probe all rgba (312, 312, 312, 111)
diff --git a/tests/hlsl/register-reservations-resources.shader_test b/tests/hlsl/register-reservations-resources.shader_test index 22a441026..1fa1e9163 100644 --- a/tests/hlsl/register-reservations-resources.shader_test +++ b/tests/hlsl/register-reservations-resources.shader_test @@ -34,7 +34,7 @@ float4 main() : sv_target }
[test] -todo(sm>=6) draw quad +draw quad probe all rgba (41.0, 41.0, 41.0, 1089.0)
diff --git a/tests/shader_runner_d3d12.c b/tests/shader_runner_d3d12.c index c6154cd1e..16cfec1ba 100644 --- a/tests/shader_runner_d3d12.c +++ b/tests/shader_runner_d3d12.c @@ -241,7 +241,9 @@ static ID3D12RootSignature *d3d12_runner_create_root_signature(struct d3d12_shad D3D12_ROOT_SIGNATURE_DESC root_signature_desc = {0}; D3D12_ROOT_PARAMETER root_params[17], *root_param; D3D12_STATIC_SAMPLER_DESC static_samplers[7]; + struct d3d12_resource *base_resource = NULL; ID3D12RootSignature *root_signature; + unsigned int slot; HRESULT hr; size_t i;
@@ -274,6 +276,14 @@ static ID3D12RootSignature *d3d12_runner_create_root_signature(struct d3d12_shad case RESOURCE_TYPE_BUFFER_UAV: range = &resource->descriptor_range;
+ if (base_resource && resource->r.type == base_resource->r.type && resource->r.slot == slot + 1) + { + ++base_resource->descriptor_range.NumDescriptors; + resource->descriptor_range.NumDescriptors = 0; + ++slot; + continue; + } + resource->root_index = root_signature_desc.NumParameters++; root_param = &root_params[resource->root_index]; root_param->ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; @@ -289,6 +299,9 @@ static ID3D12RootSignature *d3d12_runner_create_root_signature(struct d3d12_shad range->BaseShaderRegister = resource->r.slot; range->RegisterSpace = 0; range->OffsetInDescriptorsFromTableStart = 0; + + base_resource = resource; + slot = resource->r.slot; break;
case RESOURCE_TYPE_RENDER_TARGET: @@ -376,14 +389,16 @@ static bool d3d12_runner_dispatch(struct shader_runner *r, unsigned int x, unsig switch (resource->r.type) { case RESOURCE_TYPE_TEXTURE: - ID3D12GraphicsCommandList_SetComputeRootDescriptorTable(command_list, resource->root_index, - get_gpu_descriptor_handle(test_context, runner->heap, resource->r.slot)); + if (resource->descriptor_range.NumDescriptors) + ID3D12GraphicsCommandList_SetComputeRootDescriptorTable(command_list, resource->root_index, + get_gpu_descriptor_handle(test_context, runner->heap, resource->r.slot)); break;
case RESOURCE_TYPE_UAV: case RESOURCE_TYPE_BUFFER_UAV: - ID3D12GraphicsCommandList_SetComputeRootDescriptorTable(command_list, resource->root_index, - get_gpu_descriptor_handle(test_context, runner->heap, resource->r.slot + MAX_RESOURCES)); + if (resource->descriptor_range.NumDescriptors) + ID3D12GraphicsCommandList_SetComputeRootDescriptorTable(command_list, resource->root_index, + get_gpu_descriptor_handle(test_context, runner->heap, resource->r.slot + MAX_RESOURCES)); break;
case RESOURCE_TYPE_RENDER_TARGET: @@ -517,14 +532,16 @@ static bool d3d12_runner_draw(struct shader_runner *r, break;
case RESOURCE_TYPE_TEXTURE: - ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(command_list, resource->root_index, - get_gpu_descriptor_handle(test_context, runner->heap, resource->r.slot)); + if (resource->descriptor_range.NumDescriptors) + ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(command_list, resource->root_index, + get_gpu_descriptor_handle(test_context, runner->heap, resource->r.slot)); break;
case RESOURCE_TYPE_UAV: case RESOURCE_TYPE_BUFFER_UAV: - ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(command_list, resource->root_index, - get_gpu_descriptor_handle(test_context, runner->heap, resource->r.slot + MAX_RESOURCES)); + if (resource->descriptor_range.NumDescriptors) + ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(command_list, resource->root_index, + get_gpu_descriptor_handle(test_context, runner->heap, resource->r.slot + MAX_RESOURCES)); break;
case RESOURCE_TYPE_VERTEX_BUFFER:
From: Conor McCarthy cmccarthy@codeweavers.com
The UAV default register allocation rules changed with SM 5.1. --- Makefile.am | 1 + tests/hlsl/sm6-uav-rwtexture.shader_test | 321 +++++++++++++++++++++++ tests/hlsl/uav-rwtexture.shader_test | 17 +- 3 files changed, 331 insertions(+), 8 deletions(-) create mode 100644 tests/hlsl/sm6-uav-rwtexture.shader_test
diff --git a/Makefile.am b/Makefile.am index 90e7dcfcc..20efa5f79 100644 --- a/Makefile.am +++ b/Makefile.am @@ -169,6 +169,7 @@ vkd3d_shader_tests = \ tests/hlsl/sign.shader_test \ tests/hlsl/single-numeric-initializer.shader_test \ tests/hlsl/sm6-ternary.shader_test \ + tests/hlsl/sm6-uav-rwtexture.shader_test \ tests/hlsl/smoothstep.shader_test \ tests/hlsl/sqrt.shader_test \ tests/hlsl/state-block-syntax.shader_test \ diff --git a/tests/hlsl/sm6-uav-rwtexture.shader_test b/tests/hlsl/sm6-uav-rwtexture.shader_test new file mode 100644 index 000000000..e2f4361f6 --- /dev/null +++ b/tests/hlsl/sm6-uav-rwtexture.shader_test @@ -0,0 +1,321 @@ +[require] +shader model >= 6.0 + +[pixel shader] +RWTexture2D<float4> u; + +float4 main() : sv_target +{ + /* Unlike SM < 6.0, all four components are not required to be written in a single statement. */ + u[uint2(0, 0)].xy = float2(1, 2); + u[uint2(0, 0)].zw = float2(3, 4); + return 0; +} + +[pixel shader fail] +Texture2D<float4> u; + +float4 main() : sv_target +{ + /* SRVs are not writable. */ + u[uint2(0, 0)].xyzw = float4(1, 2, 3, 4); + return 0; +} + + +[uav 0] +format r32 float +size (2, 2) + +0.1 0.2 +0.3 0.4 + +[uav 1] +size (1, 1) + +0.5 0.6 0.7 0.8 + +[pixel shader] +RWTexture2D<float> u; +RWTexture2D<float4> v; + +float4 main() : sv_target +{ + u[uint2(0, 0)] = 0.5; + u[uint2(0, 1)].x = 0.6; + u[uint2(1, 1)] = 0.7; + v[uint2(0, 0)].yxwz = float4(1, 2, 3, 4); + return 0; +} + +[test] +todo draw quad +probe uav 0 (0, 0) r (0.5) +probe uav 0 (0, 1) r (0.6) +probe uav 0 (1, 0) r (0.2) +probe uav 0 (1, 1) r (0.7) +probe uav 1 (0, 0) rgba (2.0, 1.0, 4.0, 3.0) + + +[uav 2] +size (1, 1) + +0.1 0.2 0.3 0.4 + +[pixel shader] +RWTexture2D<float4> u : register(u2); + +float4 main() : sv_target1 +{ + u[uint2(0, 0)] = float4(0.9, 0.8, 0.7, 0.6); + return 0; +} + +[test] +todo draw quad +probe uav 2 (0, 0) rgba (0.9, 0.8, 0.7, 0.6) + +% Uppercase register set name +[pixel shader] +RWTexture2D<float4> u : register(U2); + +float4 main() : sv_target1 +{ + u[uint2(0, 0)] = float4(0.9, 0.8, 0.7, 0.6); + return 0; +} + +[test] +todo draw quad +probe uav 2 (0, 0) rgba (0.9, 0.8, 0.7, 0.6) + +% Test that we can declare and use an array of UAVs. + +[uav 1] +size (1, 1) + +0.1 0.2 0.3 0.4 + +[uav 2] +size (1, 1) + +0.5 0.6 0.7 0.8 + +[pixel shader] +RWTexture2D<float4> u[2] : register(u1); + +float4 main() : sv_target1 +{ + u[0][uint2(0, 0)] = float4(1.1, 1.2, 1.3, 1.4); + u[1][uint2(0, 0)] = float4(2.1, 2.2, 2.3, 2.4); + return 0; +} + +[test] +todo draw quad +probe uav 1 (0, 0) rgba (1.1, 1.2, 1.3, 1.4) +probe uav 2 (0, 0) rgba (2.1, 2.2, 2.3, 2.4) + +% RWTexture1D types +[pixel shader] + +RWTexture1D<float4> u : register(u1); +RWTexture1D<float> u0; + +float4 main() : sv_target1 +{ + u[0] = float4(11.1, 12.2, 13.3, 14.4); + return 0; +} + +% RWTexture1DArray types +[pixel shader] + +RWTexture1DArray<float4> u : register(u1); +RWTexture1DArray<float> u0; + +float4 main() : sv_target1 +{ + u[int2(0, 0)] = float4(11.1, 12.2, 13.3, 14.4); + return 0; +} + +% RWTexture2D types +[pixel shader] + +RWTexture2D<float4> u : register(u1); +RWTexture2D<float> u0; + +float4 main() : sv_target1 +{ + u[int2(0, 0)] = float4(11.1, 12.2, 13.3, 14.4); + return 0; +} + +% RWTexture2DArray types +[pixel shader] + +RWTexture2DArray<float4> u : register(u1); +RWTexture2DArray<float> u0; + +float4 main() : sv_target1 +{ + u[int3(0, 0, 0)] = float4(11.1, 12.2, 13.3, 14.4); + return 0; +} + +% RWTexture3D types +[pixel shader] + +RWTexture3D<float4> u : register(u1); +RWTexture3D<float> u0; + +float4 main() : sv_target1 +{ + u[int3(0, 0, 0)] = float4(11.1, 12.2, 13.3, 14.4); + return 0; +} + +% Structs are invalid in SM 6. +[pixel shader fail] +struct s +{ + float4 a; +}; + +RWTexture2D<float4> u : register(u1); +RWTexture2D<struct s> u0; + +float4 main() : sv_target1 +{ + u[int2(0, 0)] = float4(11.1, 12.2, 13.3, 14.4); + return 0; +} + +% Matrices are invalid in SM 6. +[pixel shader fail] + +RWTexture2D<float4> u : register(u1); +RWTexture2D<float2x2> u0; + +float4 main() : sv_target1 +{ + u[int2(0, 0)] = float4(11.1, 12.2, 13.3, 14.4); + return 0; +} + +% Array type +[pixel shader fail] +typedef float arr[2]; +RWTexture1D<arr> u; + +float4 main() : sv_target1 +{ + return 0; +} + +% Object types +[pixel shader fail] +RWTexture1D<Texture2D> u; + +float4 main() : sv_target1 +{ + return 0; +} + +[pixel shader fail] +RWTexture1DArray<Texture2D> u; + +float4 main() : sv_target1 +{ + return 0; +} + +[pixel shader fail] +RWTexture2D<Texture2D> u; + +float4 main() : sv_target1 +{ + return 0; +} + +[pixel shader fail] +RWTexture2DArray<Texture2D> u; + +float4 main() : sv_target1 +{ + return 0; +} + +[pixel shader fail] +RWTexture3D<Texture2D> u; + +float4 main() : sv_target1 +{ + return 0; +} + +[pixel shader fail] +struct s +{ + Texture2D t; +}; + +RWTexture1D<struct s> u; + +float4 main() : sv_target1 +{ + return 0; +} + +[pixel shader fail] +struct s +{ + Texture2D t; +}; + +RWTexture1DArray<struct s> u; + +float4 main() : sv_target1 +{ + return 0; +} + +[pixel shader fail] +struct s +{ + Texture2D t; +}; + +RWTexture2D<struct s> u; + +float4 main() : sv_target1 +{ + return 0; +} + +[pixel shader fail] +struct s +{ + Texture2D t; +}; + +RWTexture2DArray<struct s> u; + +float4 main() : sv_target1 +{ + return 0; +} + +[pixel shader fail] +struct s +{ + Texture2D t; +}; + +RWTexture3D<struct s> u; + +float4 main() : sv_target1 +{ + return 0; +} diff --git a/tests/hlsl/uav-rwtexture.shader_test b/tests/hlsl/uav-rwtexture.shader_test index 76535bd59..266dcf8a6 100644 --- a/tests/hlsl/uav-rwtexture.shader_test +++ b/tests/hlsl/uav-rwtexture.shader_test @@ -1,7 +1,8 @@ [require] shader model >= 5.0 +shader model < 6.0
-[pixel shader fail(sm<6)] +[pixel shader fail] RWTexture2D<float4> u;
float4 main() : sv_target @@ -49,7 +50,7 @@ float4 main() : sv_target }
[test] -todo(sm>=6) draw quad +draw quad probe uav 1 (0, 0) r (0.5) probe uav 1 (0, 1) r (0.6) probe uav 1 (1, 0) r (0.2) @@ -71,7 +72,7 @@ size (1, 1)
0.1 0.2 0.3 0.4
-[pixel shader fail(sm<6)] +[pixel shader fail] RWTexture2D<float4> u : register(u0);
float4 main() : sv_target1 @@ -80,7 +81,7 @@ float4 main() : sv_target1 return 0; }
-[pixel shader fail(sm<6)] +[pixel shader fail] RWTexture2D<float4> u : register(u1);
float4 main() : sv_target1 @@ -99,7 +100,7 @@ float4 main() : sv_target1 }
[test] -todo(sm>=6) draw quad +draw quad probe uav 2 (0, 0) rgba (0.9, 0.8, 0.7, 0.6)
@@ -118,7 +119,7 @@ float4 main() : sv_target1 }
[test] -todo(sm>=6) draw quad +draw quad probe uav 3 (0, 0) rgba (0.9, 0.8, 0.7, 0.6)
% Uppercase register set name @@ -132,7 +133,7 @@ float4 main() : sv_target1 }
[test] -todo(sm>=6) draw quad +draw quad probe uav 3 (0, 0) rgba (0.9, 0.8, 0.7, 0.6)
% Test that we can declare and use an array of UAVs. @@ -158,7 +159,7 @@ float4 main() : sv_target1 }
[test] -todo(sm>=6) draw quad +draw quad probe uav 2 (0, 0) rgba (1.1, 1.2, 1.3, 1.4) probe uav 3 (0, 0) rgba (2.1, 2.2, 2.3, 2.4)
From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d-shader/dxil.c | 99 ++++++++++++++++++++++++ tests/hlsl/compute.shader_test | 2 +- tests/hlsl/sm6-uav-rwtexture.shader_test | 8 +- tests/hlsl/uav-load.shader_test | 2 +- tests/hlsl/uav-out-param.shader_test | 4 +- 5 files changed, 107 insertions(+), 8 deletions(-)
diff --git a/libs/vkd3d-shader/dxil.c b/libs/vkd3d-shader/dxil.c index c48665edb..172b99e03 100644 --- a/libs/vkd3d-shader/dxil.c +++ b/libs/vkd3d-shader/dxil.c @@ -364,6 +364,7 @@ enum dx_intrinsic_opcode DX_CREATE_HANDLE = 57, DX_CBUFFER_LOAD_LEGACY = 59, DX_TEXTURE_LOAD = 66, + DX_TEXTURE_STORE = 67, DX_BUFFER_LOAD = 68, DX_DERIV_COARSEX = 83, DX_DERIV_COARSEY = 84, @@ -2192,6 +2193,13 @@ static void dst_param_init(struct vkd3d_shader_dst_param *param) param->shift = 0; }
+static void dst_param_init_with_mask(struct vkd3d_shader_dst_param *param, unsigned int mask) +{ + param->write_mask = mask; + param->modifiers = 0; + param->shift = 0; +} + static inline void dst_param_init_scalar(struct vkd3d_shader_dst_param *param, unsigned int component_idx) { param->write_mask = 1u << component_idx; @@ -3222,6 +3230,46 @@ struct function_emission_state unsigned int temp_idx; };
+static bool sm6_parser_emit_composite_construct(struct sm6_parser *sm6, const struct sm6_value **operands, + unsigned int component_count, struct function_emission_state *state, struct vkd3d_shader_register *reg) +{ + struct vkd3d_shader_instruction *ins = state->ins; + struct vkd3d_shader_src_param *src_params; + struct vkd3d_shader_dst_param *dst_param; + unsigned int i; + + if (component_count == 1) + { + *reg = operands[0]->u.reg; + return true; + } + + register_init_with_id(reg, VKD3DSPR_TEMP, operands[0]->u.reg.data_type, state->temp_idx++); + reg->dimension = VSIR_DIMENSION_VEC4; + + for (i = 0; i < component_count; ++i, ++ins) + { + vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_MOV); + + if (!(src_params = instruction_src_params_alloc(ins, 1, sm6))) + return false; + + src_param_init(&src_params[0]); + src_params[0].reg = operands[i]->u.reg; + + if (!(dst_param = instruction_dst_params_alloc(ins, 1, sm6))) + return false; + + dst_param_init_scalar(dst_param, i); + dst_param->reg = *reg; + } + + state->ins += component_count; + state->code_block->instruction_count += component_count; + + return true; +} + static void sm6_parser_emit_alloca(struct sm6_parser *sm6, const struct dxil_record *record, struct vkd3d_shader_instruction *ins, struct sm6_value *dst) { @@ -4066,6 +4114,56 @@ static void sm6_parser_emit_dx_texture_load(struct sm6_parser *sm6, enum dx_intr instruction_dst_param_init_ssa_vector(ins, VKD3D_VEC4_SIZE, sm6); }
+static void sm6_parser_emit_dx_texture_store(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, + const struct sm6_value **operands, struct function_emission_state *state) +{ + struct vkd3d_shader_register coord, texel; + struct vkd3d_shader_src_param *src_params; + struct vkd3d_shader_dst_param *dst_param; + unsigned int write_mask, component_count; + struct vkd3d_shader_instruction *ins; + const struct sm6_value *resource; + + resource = operands[0]; + if (!sm6_value_validate_is_texture_handle(resource, op, sm6)) + return; + + if (!sm6_parser_emit_coordinate_construct(sm6, &operands[1], NULL, state, &coord)) + return; + + write_mask = sm6_value_get_constant_uint(operands[8]); + if (!write_mask || write_mask > VKD3DSP_WRITEMASK_ALL) + { + WARN("Invalid write mask %#x.\n", write_mask); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "Write mask %#x for a texture store operation is invalid.", write_mask); + return; + } + else if (write_mask & (write_mask + 1)) + { + /* In this case, it is unclear which source operands will be defined unless we encounter it in a shader. */ + FIXME("Unhandled write mask %#x.\n", write_mask); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "Write mask %#x for a texture store operation is unhandled.", write_mask); + } + component_count = vsir_write_mask_component_count(write_mask); + + if (!sm6_parser_emit_composite_construct(sm6, &operands[4], component_count, state, &texel)) + return; + + ins = state->ins; + vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_STORE_UAV_TYPED); + + if (!(src_params = instruction_src_params_alloc(ins, 2, sm6))) + return; + src_param_init_vector_from_reg(&src_params[0], &coord); + src_param_init_vector_from_reg(&src_params[1], &texel); + + dst_param = instruction_dst_params_alloc(ins, 1, sm6); + dst_param_init_with_mask(dst_param, write_mask); + dst_param->reg = resource->u.handle.reg; +} + struct sm6_dx_opcode_info { const char *ret_type; @@ -4130,6 +4228,7 @@ static const struct sm6_dx_opcode_info sm6_dx_op_table[] = [DX_STORE_OUTPUT ] = {"v", "ii8o", sm6_parser_emit_dx_store_output}, [DX_TAN ] = {"g", "R", sm6_parser_emit_dx_unary}, [DX_TEXTURE_LOAD ] = {"o", "HiiiiCCC", sm6_parser_emit_dx_texture_load}, + [DX_TEXTURE_STORE ] = {"v", "Hiiiooooc", sm6_parser_emit_dx_texture_store}, [DX_UBFE ] = {"m", "iiR", sm6_parser_emit_dx_tertiary}, [DX_UMAX ] = {"m", "RR", sm6_parser_emit_dx_binary}, [DX_UMIN ] = {"m", "RR", sm6_parser_emit_dx_binary}, diff --git a/tests/hlsl/compute.shader_test b/tests/hlsl/compute.shader_test index 2f2af9fc8..6d2f698c7 100644 --- a/tests/hlsl/compute.shader_test +++ b/tests/hlsl/compute.shader_test @@ -17,5 +17,5 @@ void main() }
[test] -todo(sm>=6) dispatch 1 1 1 +dispatch 1 1 1 probe uav 0 (0, 0) r (-123.0) diff --git a/tests/hlsl/sm6-uav-rwtexture.shader_test b/tests/hlsl/sm6-uav-rwtexture.shader_test index e2f4361f6..0597bf504 100644 --- a/tests/hlsl/sm6-uav-rwtexture.shader_test +++ b/tests/hlsl/sm6-uav-rwtexture.shader_test @@ -49,7 +49,7 @@ float4 main() : sv_target }
[test] -todo draw quad +draw quad probe uav 0 (0, 0) r (0.5) probe uav 0 (0, 1) r (0.6) probe uav 0 (1, 0) r (0.2) @@ -72,7 +72,7 @@ float4 main() : sv_target1 }
[test] -todo draw quad +draw quad probe uav 2 (0, 0) rgba (0.9, 0.8, 0.7, 0.6)
% Uppercase register set name @@ -86,7 +86,7 @@ float4 main() : sv_target1 }
[test] -todo draw quad +draw quad probe uav 2 (0, 0) rgba (0.9, 0.8, 0.7, 0.6)
% Test that we can declare and use an array of UAVs. @@ -112,7 +112,7 @@ float4 main() : sv_target1 }
[test] -todo draw quad +draw quad probe uav 1 (0, 0) rgba (1.1, 1.2, 1.3, 1.4) probe uav 2 (0, 0) rgba (2.1, 2.2, 2.3, 2.4)
diff --git a/tests/hlsl/uav-load.shader_test b/tests/hlsl/uav-load.shader_test index 9088ffa0d..fe6350e0c 100644 --- a/tests/hlsl/uav-load.shader_test +++ b/tests/hlsl/uav-load.shader_test @@ -23,7 +23,7 @@ void main() }
[test] -todo(sm>=6) dispatch 1 1 1 +dispatch 1 1 1 probe uav 0 (0, 0) r (0.6) probe uav 0 (1, 0) r (0.6) probe uav 0 (2, 0) r (0.6) diff --git a/tests/hlsl/uav-out-param.shader_test b/tests/hlsl/uav-out-param.shader_test index 796c4bf1f..f31344748 100644 --- a/tests/hlsl/uav-out-param.shader_test +++ b/tests/hlsl/uav-out-param.shader_test @@ -26,7 +26,7 @@ void main() }
[test] -todo(sm>=6) dispatch 1 1 1 +dispatch 1 1 1 probe uav 0 (0, 0) rgba (0.4, 0.1, 0.2, 0.3)
[uav 0] @@ -51,5 +51,5 @@ void main() }
[test] -todo(sm>=6) dispatch 1 1 1 +dispatch 1 1 1 probe uav 0 (0, 0) r (0.2)