-- v2: vkd3d-shader/dxil: Apply metadata attachments to instructions. vkd3d-shader/dxil: Implement DX intrinsic Unary.
From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d-shader/dxil.c | 148 +++++++++++++++++++++++++++++-- tests/hlsl/ceil.shader_test | 6 +- tests/hlsl/ddxddy.shader_test | 8 +- tests/hlsl/distance.shader_test | 2 +- tests/hlsl/exp.shader_test | 4 +- tests/hlsl/floor.shader_test | 6 +- tests/hlsl/frac.shader_test | 2 +- tests/hlsl/ldexp.shader_test | 4 +- tests/hlsl/length.shader_test | 6 +- tests/hlsl/lit.shader_test | 8 +- tests/hlsl/log.shader_test | 6 +- tests/hlsl/normalize.shader_test | 4 +- tests/hlsl/pow.shader_test | 2 +- tests/hlsl/round.shader_test | 6 +- tests/hlsl/sqrt.shader_test | 4 +- tests/hlsl/trunc.shader_test | 8 +- 16 files changed, 180 insertions(+), 44 deletions(-)
diff --git a/libs/vkd3d-shader/dxil.c b/libs/vkd3d-shader/dxil.c index 1709212fa..7d646cba2 100644 --- a/libs/vkd3d-shader/dxil.c +++ b/libs/vkd3d-shader/dxil.c @@ -296,8 +296,28 @@ enum dx_intrinsic_opcode { DX_LOAD_INPUT = 4, DX_STORE_OUTPUT = 5, + DX_EXP = 21, + DX_FRC = 22, + DX_LOG = 23, + DX_SQRT = 24, + DX_RSQRT = 25, + DX_ROUND_NE = 26, + DX_ROUND_NI = 27, + DX_ROUND_PI = 28, + DX_ROUND_Z = 29, + DX_BFREV = 30, + DX_COUNT_BITS = 31, + DX_FIRST_BIT_LO = 32, + DX_FIRST_BIT_HI = 33, + DX_FIRST_BIT_SHI = 34, DX_CREATE_HANDLE = 57, DX_CBUFFER_LOAD_LEGACY = 59, + DX_DERIV_COARSEX = 83, + DX_DERIV_COARSEY = 84, + DX_DERIV_FINEX = 85, + DX_DERIV_FINEY = 86, + DX_LEGACY_F32TOF16 = 130, + DX_LEGACY_F16TOF32 = 131, };
enum dxil_cast_code @@ -1587,6 +1607,16 @@ static inline bool sm6_type_is_i32(const struct sm6_type *type) return type->class == TYPE_CLASS_INTEGER && type->u.width == 32; }
+static bool sm6_type_is_float(const struct sm6_type *type) +{ + return type->class == TYPE_CLASS_FLOAT && type->u.width == 32; +} + +static bool sm6_type_is_f16_f32(const struct sm6_type *type) +{ + return type->class == TYPE_CLASS_FLOAT && (type->u.width == 16 || type->u.width == 32); +} + static inline bool sm6_type_is_floating_point(const struct sm6_type *type) { return type->class == TYPE_CLASS_FLOAT; @@ -3170,6 +3200,67 @@ static void sm6_parser_emit_binop(struct sm6_parser *sm6, const struct dxil_reco } }
+static enum vkd3d_shader_opcode map_dx_unary_op(enum dx_intrinsic_opcode op) +{ + switch (op) + { + case DX_EXP: + return VKD3DSIH_EXP; + case DX_FRC: + return VKD3DSIH_FRC; + case DX_LOG: + return VKD3DSIH_LOG; + case DX_SQRT: + return VKD3DSIH_SQRT; + case DX_RSQRT: + return VKD3DSIH_RSQ; + case DX_ROUND_NE: + return VKD3DSIH_ROUND_NE; + case DX_ROUND_NI: + return VKD3DSIH_ROUND_NI; + case DX_ROUND_PI: + return VKD3DSIH_ROUND_PI; + case DX_ROUND_Z: + return VKD3DSIH_ROUND_Z; + case DX_BFREV: + return VKD3DSIH_BFREV; + case DX_COUNT_BITS: + return VKD3DSIH_COUNTBITS; + case DX_FIRST_BIT_LO: + return VKD3DSIH_FIRSTBIT_LO; + case DX_FIRST_BIT_HI: + return VKD3DSIH_FIRSTBIT_HI; + case DX_FIRST_BIT_SHI: + return VKD3DSIH_FIRSTBIT_SHI; + case DX_DERIV_COARSEX: + return VKD3DSIH_DSX_COARSE; + case DX_DERIV_COARSEY: + return VKD3DSIH_DSY_COARSE; + case DX_DERIV_FINEX: + return VKD3DSIH_DSX_FINE; + case DX_DERIV_FINEY: + return VKD3DSIH_DSY_FINE; + case DX_LEGACY_F32TOF16: + return VKD3DSIH_F32TOF16; + case DX_LEGACY_F16TOF32: + return VKD3DSIH_F16TOF32; + default: + vkd3d_unreachable(); + } +} + +static void sm6_parser_emit_dx_unary(struct sm6_parser *sm6, struct sm6_block *code_block, + enum dx_intrinsic_opcode op, const struct sm6_value **operands, struct vkd3d_shader_instruction *ins) +{ + struct vkd3d_shader_src_param *src_param; + + vsir_instruction_init(ins, &sm6->p.location, map_dx_unary_op(op)); + src_param = instruction_src_params_alloc(ins, 1, sm6); + src_param_init_from_value(src_param, operands[0]); + + instruction_dst_param_init_ssa_scalar(ins, sm6); +} + static void sm6_parser_emit_dx_cbuffer_load(struct sm6_parser *sm6, struct sm6_block *code_block, enum dx_intrinsic_opcode op, const struct sm6_value **operands, struct vkd3d_shader_instruction *ins) { @@ -3343,7 +3434,7 @@ static void sm6_parser_emit_dx_store_output(struct sm6_parser *sm6, struct sm6_b
struct sm6_dx_opcode_info { - const char ret_type; + const char *ret_type; const char *operand_info; void (*handler)(struct sm6_parser *, struct sm6_block *, enum dx_intrinsic_opcode, const struct sm6_value **, struct vkd3d_shader_instruction *); @@ -3354,16 +3445,40 @@ struct sm6_dx_opcode_info b -> constant int1 c -> constant int8/16/32 i -> int32 + m -> int16/32/64 + f -> float + e -> half/float + g -> half/float/double H -> handle v -> void o -> overloaded */ static const struct sm6_dx_opcode_info sm6_dx_op_table[] = { - [DX_CBUFFER_LOAD_LEGACY ] = {'o', "Hi", sm6_parser_emit_dx_cbuffer_load}, - [DX_CREATE_HANDLE ] = {'H', "ccib", sm6_parser_emit_dx_create_handle}, - [DX_LOAD_INPUT ] = {'o', "ii8i", sm6_parser_emit_dx_load_input}, - [DX_STORE_OUTPUT ] = {'v', "ii8o", sm6_parser_emit_dx_store_output}, + [DX_BFREV ] = {"m0", "m", sm6_parser_emit_dx_unary}, + [DX_CBUFFER_LOAD_LEGACY ] = {"o", "Hi", sm6_parser_emit_dx_cbuffer_load}, + [DX_COUNT_BITS ] = {"i", "m", sm6_parser_emit_dx_unary}, + [DX_CREATE_HANDLE ] = {"H", "ccib", sm6_parser_emit_dx_create_handle}, + [DX_DERIV_COARSEX ] = {"e0", "e", sm6_parser_emit_dx_unary}, + [DX_DERIV_COARSEY ] = {"e0", "e", sm6_parser_emit_dx_unary}, + [DX_DERIV_FINEX ] = {"e0", "e", sm6_parser_emit_dx_unary}, + [DX_DERIV_FINEY ] = {"e0", "e", sm6_parser_emit_dx_unary}, + [DX_EXP ] = {"g0", "g", sm6_parser_emit_dx_unary}, + [DX_FIRST_BIT_HI ] = {"i", "m", sm6_parser_emit_dx_unary}, + [DX_FIRST_BIT_LO ] = {"i", "m", sm6_parser_emit_dx_unary}, + [DX_FIRST_BIT_SHI ] = {"i", "m", sm6_parser_emit_dx_unary}, + [DX_FRC ] = {"g0", "g", sm6_parser_emit_dx_unary}, + [DX_LEGACY_F16TOF32 ] = {"f", "i", sm6_parser_emit_dx_unary}, + [DX_LEGACY_F32TOF16 ] = {"i", "f", sm6_parser_emit_dx_unary}, + [DX_LOAD_INPUT ] = {"o", "ii8i", sm6_parser_emit_dx_load_input}, + [DX_LOG ] = {"g0", "g", sm6_parser_emit_dx_unary}, + [DX_ROUND_NE ] = {"g0", "g", sm6_parser_emit_dx_unary}, + [DX_ROUND_NI ] = {"g0", "g", sm6_parser_emit_dx_unary}, + [DX_ROUND_PI ] = {"g0", "g", sm6_parser_emit_dx_unary}, + [DX_ROUND_Z ] = {"g0", "g", sm6_parser_emit_dx_unary}, + [DX_RSQRT ] = {"g0", "g", sm6_parser_emit_dx_unary}, + [DX_SQRT ] = {"g0", "g", sm6_parser_emit_dx_unary}, + [DX_STORE_OUTPUT ] = {"v", "ii8o", sm6_parser_emit_dx_store_output}, };
static bool sm6_parser_validate_operand_type(struct sm6_parser *sm6, const struct sm6_value *value, char info_type, @@ -3388,6 +3503,14 @@ static bool sm6_parser_validate_operand_type(struct sm6_parser *sm6, const struc && type->u.width <= 32; case 'i': return sm6_type_is_i32(type); + case 'm': + return sm6_type_is_bool_i16_i32_i64(type); + case 'f': + return sm6_type_is_float(type); + case 'e': + return sm6_type_is_f16_f32(type); + case 'g': + return sm6_type_is_floating_point(type); case 'H': return (is_return || sm6_value_is_handle(value)) && type == sm6->handle_type; case 'v': @@ -3401,6 +3524,17 @@ static bool sm6_parser_validate_operand_type(struct sm6_parser *sm6, const struc } }
+static bool operand_types_match(struct sm6_value *dst, const struct sm6_value **operands, unsigned int operand_count, + char index_char) +{ + unsigned int i = index_char - '0'; + + assert(i < 10); + if (i >= operand_count) + return false; + return dst->type == operands[i]->type; +} + static bool sm6_parser_validate_dx_op(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, const char *name, const struct sm6_value **operands, unsigned int operand_count, struct sm6_value *dst) { @@ -3409,7 +3543,9 @@ static bool sm6_parser_validate_dx_op(struct sm6_parser *sm6, enum dx_intrinsic_
info = &sm6_dx_op_table[op];
- if (!sm6_parser_validate_operand_type(sm6, dst, info->ret_type, true)) + assert(info->ret_type[0]); + if (!sm6_parser_validate_operand_type(sm6, dst, info->ret_type[0], true) + || (info->ret_type[1] && !operand_types_match(dst, operands, operand_count, info->ret_type[1]))) { WARN("Failed to validate return type for dx intrinsic id %u, '%s'.\n", op, name); /* Return type validation failure is not so critical. We only need to set diff --git a/tests/hlsl/ceil.shader_test b/tests/hlsl/ceil.shader_test index 0ff9938b9..ef26cc8ef 100644 --- a/tests/hlsl/ceil.shader_test +++ b/tests/hlsl/ceil.shader_test @@ -18,7 +18,7 @@ float4 main() : sv_target
[test] uniform 0 float4 -0.5 6.5 7.5 3.4 -todo(sm>=6) draw quad +draw quad probe all rgba (0.0, 7.0, 8.0, 4.0) 4
[pixel shader] @@ -34,7 +34,7 @@ float4 main() : sv_target
[test] uniform 0 float4 -0.5 6.5 7.5 3.4 -todo(sm>=6) draw quad +draw quad probe all rgba (7.0, 8.0, 0.0, 4.0) 4
[require] @@ -53,5 +53,5 @@ float4 main() : sv_target
[test] uniform 0 int4 -1 6 7 3 -todo(sm>=6) draw quad +draw quad probe all rgba (6.0, 7.0, -1.0, 3.0) 4 diff --git a/tests/hlsl/ddxddy.shader_test b/tests/hlsl/ddxddy.shader_test index ba7215ca0..4986c233f 100644 --- a/tests/hlsl/ddxddy.shader_test +++ b/tests/hlsl/ddxddy.shader_test @@ -8,7 +8,7 @@ float4 main(float4 pos : sv_position) : sv_target }
[test] -todo(sm>=6) draw quad +draw quad probe all rgba (1.0, 1.0, 0.0, 0.0)
@@ -29,7 +29,7 @@ float4 main(float4 pos : sv_position) : sv_target }
[test] -todo(sm>=6) draw quad +draw quad probe (10, 10) rgba (-16.0, -5.0, 3.0, 0.0) probe (11, 10) rgba (-21.0, -5.0, 3.0, 0.0) probe (10, 11) rgba (-13.0, -5.0, 3.0, 0.0) @@ -55,7 +55,7 @@ float4 main(float4 pos : sv_position) : sv_target }
[test] -todo(sm>=6) draw quad +draw quad probe (10, 10) rgba (-16.0, -5.0, 3.0, 0.0) probe (11, 10) rgba (-21.0, -5.0, 3.0, 0.0) probe (10, 11) rgba (-13.0, -5.0, 3.0, 0.0) @@ -74,7 +74,7 @@ float4 main(float4 pos : sv_position) : sv_target }
[test] -todo(sm>=6) draw quad +draw quad probe (10, 10) rgba (-0.524999976, -0.164999843, 0.104999900, 0.0) 16 probe (11, 10) rgba (-0.689999819, -0.164999843, 0.114999890, 0.0) 32 probe (10, 11) rgba (-0.420000076, -0.154999852, 0.104999900, 0.0) 32 diff --git a/tests/hlsl/distance.shader_test b/tests/hlsl/distance.shader_test index 6527c218a..3f5446451 100644 --- a/tests/hlsl/distance.shader_test +++ b/tests/hlsl/distance.shader_test @@ -10,7 +10,7 @@ float4 main() : sv_target [test] uniform 0 float4 -2.0 3.0 4.0 0.1 uniform 4 float4 2.0 -1.0 4.0 5.0 -todo(sm>=6) draw quad +draw quad probe all rgba (7.483983, 7.483983, 7.483983, 7.483983) 1
[pixel shader] diff --git a/tests/hlsl/exp.shader_test b/tests/hlsl/exp.shader_test index 38f8750fd..1d1889977 100644 --- a/tests/hlsl/exp.shader_test +++ b/tests/hlsl/exp.shader_test @@ -8,7 +8,7 @@ float4 main() : sv_target
[test] uniform 0 float4 -1.0 0.0 1.0 2.0 -todo(sm>=6) draw quad +draw quad probe all rgba (0.5, 1.0, 2.0, 4.0) 2
[pixel shader] @@ -21,5 +21,5 @@ float4 main() : sv_target
[test] uniform 0 float4 -1.0 0.0 1.0 2.0 -todo(sm>=6) draw quad +draw quad probe all rgba (0.36787948, 1.0, 2.7182815, 7.38905573) 2 diff --git a/tests/hlsl/floor.shader_test b/tests/hlsl/floor.shader_test index e6562c4aa..19f9437a9 100644 --- a/tests/hlsl/floor.shader_test +++ b/tests/hlsl/floor.shader_test @@ -18,7 +18,7 @@ float4 main() : sv_target
[test] uniform 0 float4 -0.5 6.5 7.5 3.4 -todo(sm>=6) draw quad +draw quad probe all rgba (-1.0, 6.0, 7.0, 3.0) 4
[pixel shader] @@ -34,7 +34,7 @@ float4 main() : sv_target
[test] uniform 0 float4 -0.5 6.5 7.5 3.4 -todo(sm>=6) draw quad +draw quad probe all rgba (6.0, 7.0, -1.0, 3.0) 4
[require] @@ -53,5 +53,5 @@ float4 main() : sv_target
[test] uniform 0 int4 -1 6 7 3 -todo(sm>=6) draw quad +draw quad probe all rgba (6.0, 7.0, -1.0, 3.0) 4 diff --git a/tests/hlsl/frac.shader_test b/tests/hlsl/frac.shader_test index 2ac9b530d..f54f3fe88 100644 --- a/tests/hlsl/frac.shader_test +++ b/tests/hlsl/frac.shader_test @@ -8,5 +8,5 @@ float4 main() : sv_target
[test] uniform 0 float4 -1.1 1.6 1.3 0.5 -todo(sm>=6) draw quad +draw quad probe all rgba (0.9, 0.6, 0.3, 0.5) 2 diff --git a/tests/hlsl/ldexp.shader_test b/tests/hlsl/ldexp.shader_test index 2db624067..f8ad40d8e 100644 --- a/tests/hlsl/ldexp.shader_test +++ b/tests/hlsl/ldexp.shader_test @@ -10,7 +10,7 @@ float4 main() : SV_TARGET [test] uniform 0 float4 2.0 3.0 4.0 5.0 uniform 4 float4 0.0 -10.0 10.0 100.0 -todo(sm>=6) draw quad +draw quad probe all rgba (2.0, 0.00292968750, 4096.0, 6.33825300e+030) 2
[require] @@ -28,7 +28,7 @@ float4 main() : SV_TARGET [test] uniform 0 int4 2 3 4 5 uniform 4 int4 0 -10 10 100 -todo(sm>=6) draw quad +draw quad probe all rgba (2.0, 0.00292968750, 4096.0, 6.33825300e+030) 2
diff --git a/tests/hlsl/length.shader_test b/tests/hlsl/length.shader_test index 8653942e0..44b4e5254 100644 --- a/tests/hlsl/length.shader_test +++ b/tests/hlsl/length.shader_test @@ -8,7 +8,7 @@ float4 main() : SV_TARGET
[test] uniform 0 float4 2.0 3.0 4.0 5.0 -todo(sm>=6) draw quad +draw quad probe all rgba (7.34846926, 7.34846926, 7.34846926, 7.34846926) 1
[pixel shader] @@ -21,7 +21,7 @@ float4 main() : SV_TARGET
[test] uniform 0 float4 2.0 3.0 4.0 0.0 -todo(sm>=6) draw quad +draw quad probe all rgba (5.38516474, 5.38516474, 5.38516474, 5.38516474) 1
[pixel shader] @@ -34,7 +34,7 @@ float4 main() : SV_TARGET
[test] uniform 0 float4 2.0 3.0 0.0 0.0 -todo(sm>=6) draw quad +draw quad probe all rgba (3.60555124, 3.60555124, 3.60555124, 3.60555124) 1
[pixel shader] diff --git a/tests/hlsl/lit.shader_test b/tests/hlsl/lit.shader_test index 5014c1ed0..fcf37d78b 100644 --- a/tests/hlsl/lit.shader_test +++ b/tests/hlsl/lit.shader_test @@ -8,17 +8,17 @@ float4 main() : sv_target
[test] uniform 0 float4 -0.1 10.0 0.0 0.0 -todo(sm>=6) draw quad +draw quad probe all rgba (1.0, 0.0, 0.0, 1.0)
[test] uniform 0 float4 1.2 -0.1 0.0 0.0 -todo(sm>=6) draw quad +draw quad probe all rgba (1.0, 1.2, 0.0, 1.0)
[test] uniform 0 float4 1.2 2.0 3.0 0.0 -todo(sm>=6) draw quad +draw quad probe all rgba (1.0, 1.2, 8.0, 1.0)
[pixel shader] @@ -31,7 +31,7 @@ float4 main() : sv_target
[test] uniform 0 float4 1.2 2.0 3.0 0.0 -todo(sm>=6) draw quad +draw quad probe all rgba (2.0, 2.4, 16.0, 2.0)
[pixel shader fail] diff --git a/tests/hlsl/log.shader_test b/tests/hlsl/log.shader_test index 2f7d5c7c0..b0f405d11 100644 --- a/tests/hlsl/log.shader_test +++ b/tests/hlsl/log.shader_test @@ -8,7 +8,7 @@ float4 main() : sv_target
[test] uniform 0 float4 2.0 4.0 5.0 0.4 -todo(sm>=6) draw quad +draw quad probe all rgba (1.0, 2.0, 2.32192802, -1.32192802) 1
[pixel shader] @@ -21,7 +21,7 @@ float4 main() : sv_target
[test] uniform 0 float4 10.0 100.0 1.0 0.1 -todo(sm>=6) draw quad +draw quad probe all rgba (1.0, 2.0, 0.0, -1.0) 1
[pixel shader] @@ -34,5 +34,5 @@ float4 main() : sv_target
[test] uniform 0 float4 3.0 10.0 1.0 0.1 -todo(sm>=6) draw quad +draw quad probe all rgba (1.0986123, 2.302585, 0.0, -2.302585) 2 diff --git a/tests/hlsl/normalize.shader_test b/tests/hlsl/normalize.shader_test index 0fe0dea3c..8b181dfa5 100644 --- a/tests/hlsl/normalize.shader_test +++ b/tests/hlsl/normalize.shader_test @@ -47,7 +47,7 @@ float4 main() : SV_TARGET
[test] uniform 0 float4 2.0 0.0 0.0 0.0 -todo(sm>=6) draw quad +draw quad probe all rgba (1.0, 1.0, 1.0, 1.0)
[pixel shader] @@ -60,7 +60,7 @@ float4 main() : SV_TARGET
[test] uniform 0 float4 2.0 0.0 0.0 0.0 -todo(sm>=6) draw quad +draw quad probe all rgba (1.0, 1.0, 1.0, 1.0)
[pixel shader fail] diff --git a/tests/hlsl/pow.shader_test b/tests/hlsl/pow.shader_test index d8f5eec9f..1c9394f06 100644 --- a/tests/hlsl/pow.shader_test +++ b/tests/hlsl/pow.shader_test @@ -8,7 +8,7 @@ float4 main() : sv_target
[test] uniform 0 float4 0.4 0.8 2.5 2.0 -todo(sm>=6) draw quad +draw quad probe all rgba (0.512, 0.101192884, 0.64, 0.25) 4
diff --git a/tests/hlsl/round.shader_test b/tests/hlsl/round.shader_test index 2a32b3ec2..b9234b010 100644 --- a/tests/hlsl/round.shader_test +++ b/tests/hlsl/round.shader_test @@ -8,7 +8,7 @@ float4 main() : sv_target
[test] uniform 0 float4 -0.4 -6.6 7.6 3.4 -todo(sm>=6) draw quad +draw quad probe all rgba (0.0, -7.0, 8.0, 3.0) 4
@@ -26,7 +26,7 @@ float4 main() : sv_target
[test] uniform 0 float4 -0.4 -6.6 7.6 3.4 -todo(sm>=6) draw quad +draw quad probe all rgba (-7.0, 8.0, 0.0, 3.0) 4
@@ -42,5 +42,5 @@ float4 main() : sv_target
[test] uniform 0 float4 -1 0 2 10 -todo(sm>=6) draw quad +draw quad probe all rgba (-1.0, 0.0, 2.0, 10.0) 4 diff --git a/tests/hlsl/sqrt.shader_test b/tests/hlsl/sqrt.shader_test index 73ecba899..78d89d38f 100644 --- a/tests/hlsl/sqrt.shader_test +++ b/tests/hlsl/sqrt.shader_test @@ -8,7 +8,7 @@ float4 main() : sv_target
[test] uniform 0 float4 1.0 9.0 32.3 46.5 -todo(sm>=6) draw quad +draw quad probe all rgba (1.0, 3.0, 5.683309, 6.819091) 1
[pixel shader] @@ -21,5 +21,5 @@ float4 main() : sv_target
[test] uniform 0 float4 1.0 9.0 4.0 16.0 -todo(sm>=6) draw quad +draw quad probe all rgba (1.0, 0.33333333, 0.5, 0.25) 1 diff --git a/tests/hlsl/trunc.shader_test b/tests/hlsl/trunc.shader_test index a359cd03a..76ffdbbad 100644 --- a/tests/hlsl/trunc.shader_test +++ b/tests/hlsl/trunc.shader_test @@ -8,10 +8,10 @@ float4 main() : sv_target
[test] uniform 0 float4 -0.5 6.5 7.5 3.4 -todo(sm>=6) draw quad +draw quad probe all rgba (0.0, 6.0, 7.0, 3.0) uniform 0 float4 -1.5 6.5 7.5 3.4 -todo(sm>=6) draw quad +draw quad probe all rgba (-1.0, 6.0, 7.0, 3.0)
[pixel shader] @@ -27,7 +27,7 @@ float4 main() : sv_target
[test] uniform 0 float4 -0.5 6.5 7.5 3.4 -todo(sm>=6) draw quad +draw quad probe all rgba (6.0, 7.0, 0.0, 3.0)
[require] @@ -46,5 +46,5 @@ float4 main() : sv_target
[test] uniform 0 int4 -1 6 7 3 -todo(sm>=6) draw quad +draw quad probe all rgba (6.0, 7.0, -1.0, 3.0)
From: Conor McCarthy cmccarthy@codeweavers.com
These are apperently only used for 'dx.op' intrinsics, because the instructions based on native LLVM ones have their own way to apply attributes. --- libs/vkd3d-shader/dxil.c | 204 +++++++++++++++++++++++ libs/vkd3d-shader/vkd3d_shader_private.h | 1 + 2 files changed, 205 insertions(+)
diff --git a/libs/vkd3d-shader/dxil.c b/libs/vkd3d-shader/dxil.c index 7d646cba2..3109da717 100644 --- a/libs/vkd3d-shader/dxil.c +++ b/libs/vkd3d-shader/dxil.c @@ -459,6 +459,7 @@ struct dxil_record { unsigned int code; unsigned int operand_count; + const struct dxil_record *attachment; uint64_t operands[]; };
@@ -816,6 +817,7 @@ static enum vkd3d_result sm6_parser_read_unabbrev_record(struct sm6_parser *sm6)
record->code = code; record->operand_count = count; + record->attachment = NULL;
for (i = 0; i < count; ++i) record->operands[i] = sm6_parser_read_vbr(sm6, 6); @@ -1032,6 +1034,7 @@ static enum vkd3d_result sm6_parser_read_abbrev_record(struct sm6_parser *sm6, u if (!abbrev->operands[i + 1].read_operand(sm6, abbrev->operands[i + 1].context, &record->operands[i])) goto fail; record->operand_count = count; + record->attachment = NULL;
/* An array can occur only as the last operand. */ if (abbrev->is_array) @@ -2618,6 +2621,13 @@ static enum vkd3d_result sm6_parser_constants_init(struct sm6_parser *sm6, const break; }
+ if (record->attachment) + { + WARN("Ignoring metadata attachment.\n"); + vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, + "Ignoring a metadata attachment for a constant."); + } + ++sm6->value_count; }
@@ -4288,6 +4298,195 @@ static bool sm6_metadata_get_uint64_value(const struct sm6_parser *sm6, return true; }
+static void sm6_parser_metadata_attachment_block_init(struct sm6_parser *sm6, const struct dxil_block *target_block, + const struct dxil_block *block) +{ + const struct dxil_record *record; + unsigned int i; + uint64_t index; + + for (i = 0; i < block->record_count; ++i) + { + record = block->records[i]; + if (record->code != METADATA_ATTACHMENT) + { + WARN("Ignoring record with code %u.\n", record->code); + vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, + "Ignoring a metadata attachment record with code %u.", record->code); + continue; + } + if (!(record->operand_count & 1)) + { + WARN("Ignoring function attachment.\n"); + vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, + "Ignoring a metadata function attachment."); + continue; + } + + index = record->operands[0]; + if (!target_block->record_count || index >= target_block->record_count - 1) + { + WARN("Invalid record index %"PRIu64".\n", index); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "Invalid record index %"PRIu64" for a metadata attachment.", index); + continue; + } + /* 'index' is an instruction index, but records[0] is DECLAREBLOCKS, not an instruction. */ + target_block->records[index + 1]->attachment = record; + } +} + +static void sm6_parser_metadata_attachments_init(struct sm6_parser *sm6, const struct dxil_block *block) +{ + unsigned int i; + + for (i = 0; i < block->child_block_count; ++i) + { + if (block->child_blocks[i]->id == METADATA_ATTACHMENT_BLOCK) + sm6_parser_metadata_attachment_block_init(sm6, block, block->child_blocks[i]); + } +} + +static const struct sm6_metadata_value *sm6_parser_find_metadata_kind(const struct sm6_parser *sm6, uint64_t id) +{ + unsigned int i, j; + + for (i = 0; i < ARRAY_SIZE(sm6->metadata_tables); ++i) + { + for (j = 0; j < sm6->metadata_tables[i].count; ++j) + { + if (sm6->metadata_tables[i].values[j].type == VKD3D_METADATA_KIND + && sm6->metadata_tables[i].values[j].u.kind.id == id) + return &sm6->metadata_tables[i].values[j]; + } + } + + return NULL; +} + +static const struct sm6_metadata_value *sm6_parser_metadata_get_value(const struct sm6_parser *sm6, uint64_t index) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(sm6->metadata_tables); ++i) + { + if (sm6->metadata_tables[i].count > index) + break; + index -= sm6->metadata_tables[i].count; + } + + return (index < sm6->metadata_tables[i].count) ? &sm6->metadata_tables[i].values[index] : NULL; +} + +static bool metadata_node_get_unary_uint(const struct sm6_metadata_node *node, unsigned int *operand, + struct sm6_parser *sm6) +{ + if (node->operand_count != 1) + { + FIXME("Ignoring node with %u operands.\n", node->operand_count); + vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, + "Ignoring metadata attachment node with %u operands; expected unary.", node->operand_count); + return false; + } + if (!sm6_metadata_value_is_value(node->operands[0]) + || !sm6_metadata_get_uint_value(sm6, node->operands[0], operand)) + { + WARN("Failed to get operand value.\n"); + vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, + "Failed to get a metadata attachment operand value; ignoring the attachment."); + return false; + } + + return true; +} + +static void metadata_attachment_record_apply(const struct dxil_record *record, + struct vkd3d_shader_instruction *ins, struct sm6_value *dst, struct sm6_parser *sm6) +{ + static const char *ignored_names[] = + { + "alias.scope", + "dx.controlflow.hints", + "llvm.loop", + "noalias", + "tbaa", + "range", + }; + const struct sm6_metadata_node *node; + const struct sm6_metadata_value *m; + unsigned int i, j, operand; + const char *name; + + if (record->attachment) + { + WARN("Ignoring nested metadata attachment.\n"); + vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, + "Ignoring a nested metadata attachment."); + } + + assert(record->operand_count & 1); + for (i = 1; i < record->operand_count; i += 2) + { + if (!(m = sm6_parser_find_metadata_kind(sm6, record->operands[i]))) + { + WARN("Failed to find metadata kind %"PRIx64".\n", record->operands[i]); + vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, + "Failed to find metadata kind %"PRIx64" for an attachment.", record->operands[i]); + continue; + } + name = m->u.kind.name; + + m = sm6_parser_metadata_get_value(sm6, record->operands[i + 1]); + if (!m || !sm6_metadata_value_is_node(m)) + { + WARN("Failed to retrieve metadata attachment node.\n"); + vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, + "Failed to retrieve a metadata attachment node."); + continue; + } + node = m->u.node; + + if (!strcmp(name, "dx.precise")) + { + if (!sm6_value_is_register(dst)) + { + WARN("Precise value is not a register.\n"); + vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, + "A value marked as precise is not a register."); + } + else if (metadata_node_get_unary_uint(node, &operand, sm6) && operand) + { + ins->flags |= sm6_type_is_scalar(dst->type) ? VKD3DSI_PRECISE_X : VKD3DSI_PRECISE_XYZW; + } + } + else if (!strcmp(name, "dx.nonuniform")) + { + if (!sm6_value_is_register(dst)) + { + WARN("Non-uniform value is not a register.\n"); + vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, + "A value marked as non-uniform is not a register."); + } + else if (metadata_node_get_unary_uint(node, &operand, sm6)) + { + dst->u.reg.non_uniform = !!operand; + } + } + else + { + for (j = 0; j < ARRAY_SIZE(ignored_names); ++j) + if (!strcmp(name, ignored_names[j])) + break; + if (j == ARRAY_SIZE(ignored_names)) + { + WARN("Ignoring metadata attachment '%s'.\n", name); + vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, + "Ignoring a metadata attachment named '%s'.", name); + } + } + } +} + static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const struct dxil_block *block, struct sm6_function *function) { @@ -4413,6 +4612,9 @@ static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const return VKD3D_ERROR; assert(ins->handler_idx != VKD3DSIH_INVALID);
+ if (record->attachment) + metadata_attachment_record_apply(record->attachment, ins, dst, sm6); + if (is_terminator) { ++block_idx; @@ -4466,6 +4668,8 @@ static enum vkd3d_result sm6_parser_module_init(struct sm6_parser *sm6, const st sm6->p.location.line = block->id; sm6->p.location.column = 0;
+ sm6_parser_metadata_attachments_init(sm6, block); + switch (block->id) { case CONSTANTS_BLOCK: diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index d3989672b..08669520c 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -196,6 +196,7 @@ enum vkd3d_shader_error VKD3D_SHADER_WARNING_DXIL_ENTRY_POINT_MISMATCH = 8306, VKD3D_SHADER_WARNING_DXIL_INVALID_MASK = 8307, VKD3D_SHADER_WARNING_DXIL_INVALID_OPERATION = 8308, + VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT = 8309,
VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED = 9000, VKD3D_SHADER_ERROR_VSIR_INVALID_HANDLER = 9001,
Giovanni Mascellani (@giomasce) commented about libs/vkd3d-shader/dxil.c:
}
}
+static bool operand_types_match(struct sm6_value *dst, const struct sm6_value **operands, unsigned int operand_count,
char index_char)
+{
- unsigned int i = index_char - '0';
- assert(i < 10);
- if (i >= operand_count)
return false;
- return dst->type == operands[i]->type;
+}
That's fine for me, but I wonder whether using some dedicated char (like `R`, as in "return value") in `operand_info` can be more readable and flexible (just in case, in the future, you have to use it for more than one source operand). I'm not even sure that flexibility is useful for something, so that's just a random thought.
Giovanni Mascellani (@giomasce) commented about libs/vkd3d-shader/dxil.c:
- [DX_STORE_OUTPUT ] = {'v', "ii8o", sm6_parser_emit_dx_store_output},
- [DX_BFREV ] = {"m0", "m", sm6_parser_emit_dx_unary},
- [DX_CBUFFER_LOAD_LEGACY ] = {"o", "Hi", sm6_parser_emit_dx_cbuffer_load},
- [DX_COUNT_BITS ] = {"i", "m", sm6_parser_emit_dx_unary},
- [DX_CREATE_HANDLE ] = {"H", "ccib", sm6_parser_emit_dx_create_handle},
- [DX_DERIV_COARSEX ] = {"e0", "e", sm6_parser_emit_dx_unary},
- [DX_DERIV_COARSEY ] = {"e0", "e", sm6_parser_emit_dx_unary},
- [DX_DERIV_FINEX ] = {"e0", "e", sm6_parser_emit_dx_unary},
- [DX_DERIV_FINEY ] = {"e0", "e", sm6_parser_emit_dx_unary},
- [DX_EXP ] = {"g0", "g", sm6_parser_emit_dx_unary},
- [DX_FIRST_BIT_HI ] = {"i", "m", sm6_parser_emit_dx_unary},
- [DX_FIRST_BIT_LO ] = {"i", "m", sm6_parser_emit_dx_unary},
- [DX_FIRST_BIT_SHI ] = {"i", "m", sm6_parser_emit_dx_unary},
- [DX_FRC ] = {"g0", "g", sm6_parser_emit_dx_unary},
- [DX_LEGACY_F16TOF32 ] = {"f", "i", sm6_parser_emit_dx_unary},
- [DX_LEGACY_F32TOF16 ] = {"i", "f", sm6_parser_emit_dx_unary},
That means that even for dxcompiler F16 values are typed as integers, rather than `half`?
Giovanni Mascellani (@giomasce) commented about libs/vkd3d-shader/dxil.c:
WARN("Ignoring function attachment.\n");
vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT,
"Ignoring a metadata function attachment.");
continue;
}
index = record->operands[0];
if (!target_block->record_count || index >= target_block->record_count - 1)
{
WARN("Invalid record index %"PRIu64".\n", index);
vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND,
"Invalid record index %"PRIu64" for a metadata attachment.", index);
continue;
}
/* 'index' is an instruction index, but records[0] is DECLAREBLOCKS, not an instruction. */
target_block->records[index + 1]->attachment = record;
Maybe we could warn if that record already has an attachment.
Giovanni Mascellani (@giomasce) commented about libs/vkd3d-shader/dxil.c:
return VKD3D_ERROR; assert(ins->handler_idx != VKD3DSIH_INVALID);
if (record->attachment)
metadata_attachment_record_apply(record->attachment, ins, dst, sm6);
Since you mention that attachments only seem to make sense for `dx.op` intrinsics, maybe that could be validated?