From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d-shader/dxil.c | 172 ++++++++++++++++++ tests/hlsl/arithmetic-int-uniform.shader_test | 14 +- tests/hlsl/asfloat.shader_test | 2 +- tests/hlsl/asuint.shader_test | 4 +- tests/hlsl/d3dcolor-to-ubyte4.shader_test | 4 +- tests/hlsl/function-cast.shader_test | 4 +- tests/hlsl/lerp.shader_test | 2 +- tests/hlsl/non-const-indexing.shader_test | 16 +- .../shader-interstage-interface.shader_test | 2 +- 9 files changed, 196 insertions(+), 24 deletions(-)
diff --git a/libs/vkd3d-shader/dxil.c b/libs/vkd3d-shader/dxil.c index b29877106..17521d3ef 100644 --- a/libs/vkd3d-shader/dxil.c +++ b/libs/vkd3d-shader/dxil.c @@ -289,6 +289,23 @@ enum dx_intrinsic_opcode DX_CBUFFER_LOAD_LEGACY = 59, };
+enum dxil_cast_code +{ + CAST_TRUNC = 0, + CAST_ZEXT = 1, + CAST_SEXT = 2, + CAST_FPTOUI = 3, + CAST_FPTOSI = 4, + CAST_UITOFP = 5, + CAST_SITOFP = 6, + CAST_FPTRUNC = 7, + CAST_FPEXT = 8, + CAST_PTRTOINT = 9, + CAST_INTTOPTR = 10, + CAST_BITCAST = 11, + CAST_ADDRSPACECAST = 12, +}; + struct sm6_pointer_info { const struct sm6_type *type; @@ -3249,6 +3266,158 @@ static void sm6_parser_emit_call(struct sm6_parser *sm6, const struct dxil_recor fn_value->u.function.name, &operands[1], operand_count - 1, ins, dst); }
+static enum vkd3d_shader_opcode sm6_map_cast_op(uint64_t code, const struct sm6_type *from, + const struct sm6_type *to, struct sm6_parser *sm6) +{ + enum vkd3d_shader_opcode op = VKD3DSIH_INVALID; + bool from_int, to_int; + bool is_valid = false; + + /* NOTE: DXIL currently doesn't use vectors here. */ + if (!sm6_type_is_scalar(from) || !sm6_type_is_scalar(to)) + { + FIXME("Unhandled non-scalar type class %u and/or %u.\n", from->class, to->class); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "Cast of non-scalar types is not implemented."); + /* width is not available for non-scalar types so we can't attempt to compile it. */ + return VKD3DSIH_INVALID; + } + if (to->u.width == 8 || from->u.width == 8) + { + FIXME("Unhandled 8-bit value.\n"); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "Cast to/from an 8-bit type is not implemented."); + return VKD3DSIH_INVALID; + } + + from_int = sm6_type_is_integer(from); + to_int = sm6_type_is_integer(to); + + /* DXC emits minimum precision types as 16-bit. These must be emitted + * as 32-bit in VSIR, so all width extensions to 32 bits are no-ops. */ + switch (code) + { + case CAST_TRUNC: + /* nop or min precision. TODO: native 16-bit */ + if (to->u.width == from->u.width || (to->u.width == 16 && from->u.width == 32)) + op = VKD3DSIH_NOP; + else + op = VKD3DSIH_UTOU; + is_valid = from_int && to_int && to->u.width <= from->u.width; + break; + case CAST_ZEXT: + case CAST_SEXT: + /* nop or min precision. TODO: native 16-bit */ + if (to->u.width == from->u.width || (to->u.width == 32 && from->u.width == 16)) + { + op = VKD3DSIH_NOP; + is_valid = from_int && to_int; + } + else if (to->u.width > from->u.width) + { + op = (code == CAST_ZEXT) ? VKD3DSIH_UTOU : VKD3DSIH_ITOI; + assert(from->u.width == 1 || to->u.width == 64); + is_valid = from_int && to_int; + } + break; + case CAST_FPTOUI: + op = VKD3DSIH_FTOU; + is_valid = !from_int && to_int && to->u.width > 1; + break; + case CAST_FPTOSI: + op = VKD3DSIH_FTOI; + is_valid = !from_int && to_int && to->u.width > 1; + break; + case CAST_UITOFP: + op = VKD3DSIH_UTOF; + is_valid = from_int && !to_int; + break; + case CAST_SITOFP: + op = VKD3DSIH_ITOF; + is_valid = from_int && !to_int; + break; + case CAST_FPTRUNC: + /* TODO: native 16-bit */ + op = (from->u.width == 64) ? VKD3DSIH_DTOF : VKD3DSIH_NOP; + is_valid = !from_int && !to_int; + break; + case CAST_FPEXT: + /* TODO: native 16-bit */ + op = (to->u.width == 64) ? VKD3DSIH_FTOD : VKD3DSIH_NOP; + is_valid = !from_int && !to_int; + break; + case CAST_BITCAST: + op = VKD3DSIH_MOV; + is_valid = to->u.width == from->u.width; + break; + default: + FIXME("Unhandled cast op %"PRIu64".\n", code); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "Cast operation %"PRIu64" is unhandled.\n", code); + return VKD3DSIH_INVALID; + } + + if (!is_valid) + { + FIXME("Invalid types %u and/or %u for op %"PRIu64".\n", from->class, to->class, code); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "Cast operation %"PRIu64" from type class %u, width %u to type class %u, width %u is invalid.\n", + code, from->class, from->u.width, to->class, to->u.width); + return VKD3DSIH_INVALID; + } + + return op; +} + +static void sm6_parser_emit_cast(struct sm6_parser *sm6, const struct dxil_record *record, + struct vkd3d_shader_instruction *ins, struct sm6_value *dst) +{ + struct vkd3d_shader_src_param *src_param; + enum vkd3d_shader_opcode handler_idx; + const struct sm6_value *value; + const struct sm6_type *type; + unsigned int i = 0; + + if (!(value = sm6_parser_get_value_by_ref(sm6, record, NULL, &i))) + return; + + if (!dxil_record_validate_operand_count(record, i + 2, i + 2, sm6)) + return; + + if (!(type = sm6_parser_get_type(sm6, record->operands[i++]))) + return; + + dst->type = type; + + if (sm6_type_is_pointer(type)) + { + *dst = *value; + dst->type = type; + ins->handler_idx = VKD3DSIH_NOP; + return; + } + + if ((handler_idx = sm6_map_cast_op(record->operands[i], value->type, type, sm6)) == VKD3DSIH_INVALID) + return; + + vsir_instruction_init(ins, &sm6->p.location, handler_idx); + + if (handler_idx == VKD3DSIH_NOP) + { + dst->u.reg = value->u.reg; + return; + } + + src_param = instruction_src_params_alloc(ins, 1, sm6); + src_param_init_from_value(src_param, value); + + instruction_dst_param_init_ssa_scalar(ins, sm6); + + /* bitcast */ + if (handler_idx == VKD3DSIH_MOV) + src_param->reg.data_type = dst->u.reg.data_type; +} + static void sm6_parser_emit_extractval(struct sm6_parser *sm6, const struct dxil_record *record, struct vkd3d_shader_instruction *ins, struct sm6_value *dst) { @@ -3465,6 +3634,9 @@ static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const case FUNC_CODE_INST_CALL: sm6_parser_emit_call(sm6, record, code_block, ins, dst); break; + case FUNC_CODE_INST_CAST: + sm6_parser_emit_cast(sm6, record, ins, dst); + break; case FUNC_CODE_INST_EXTRACTVAL: sm6_parser_emit_extractval(sm6, record, ins, dst); break; diff --git a/tests/hlsl/arithmetic-int-uniform.shader_test b/tests/hlsl/arithmetic-int-uniform.shader_test index 726a191a7..7f5cdaaa6 100644 --- a/tests/hlsl/arithmetic-int-uniform.shader_test +++ b/tests/hlsl/arithmetic-int-uniform.shader_test @@ -10,7 +10,7 @@ float4 main() : SV_TARGET
[test] uniform 0 float4 5.0 16.0 0.0 0.0 -todo(sm>=6) draw quad +draw quad probe all rgba (21.0, -11.0, 80.0, 0.0)
[pixel shader] @@ -25,7 +25,7 @@ float4 main() : SV_TARGET
[test] uniform 0 float4 5.0 16.0 0.0 0.0 -todo(sm>=6) draw quad +draw quad probe all rgba (5.0, 5.0, -5.0, 3.0)
[pixel shader] @@ -40,7 +40,7 @@ float4 main() : SV_TARGET
[test] uniform 0 float4 42.0 5.0 0.0 0.0 -todo(sm>=6) draw quad +draw quad probe all rgba (8.0, -8.0, -8.0, 8.0)
[pixel shader] @@ -55,7 +55,7 @@ float4 main() : SV_TARGET
[test] uniform 0 float4 42.0 5.0 0.0 0.0 -todo(sm>=6) draw quad +draw quad probe all rgba (2.0, -2.0, 2.0, -2.0)
[pixel shader] @@ -70,7 +70,7 @@ float4 main() : SV_TARGET
[test] uniform 0 float4 45.0 5.0 0.0 0.0 -todo(sm>=6) draw quad +draw quad probe all rgba (9.0, -9.0, -9.0, 9.0)
[pixel shader] @@ -85,7 +85,7 @@ float4 main() : SV_TARGET
[test] uniform 0 float4 45.0 5.0 0.0 0.0 -todo(sm>=6) draw quad +draw quad probe all rgba (0.0, 0.0, 0.0, 0.0)
[pixel shader] @@ -117,5 +117,5 @@ float4 main() : sv_target [test] uniform 0 float4 45.0 5.0 50.0 10.0 uniform 4 float4 3.0 8.0 2.0 5.0 -todo(sm>=6) draw quad +draw quad probe all rgba (9.0, 5.0, 1.0, 3.0) diff --git a/tests/hlsl/asfloat.shader_test b/tests/hlsl/asfloat.shader_test index f43f2fdff..2184c1869 100644 --- a/tests/hlsl/asfloat.shader_test +++ b/tests/hlsl/asfloat.shader_test @@ -20,7 +20,7 @@ float4 main() : sv_target
[test] uniform 0 float4 123.0 -2.0 456 0.01 -todo(sm>=6) draw quad +draw quad probe (320,240) rgba (123.0, -2.0, 456.0, 0.01)
[pixel shader] diff --git a/tests/hlsl/asuint.shader_test b/tests/hlsl/asuint.shader_test index 0a2e39e53..50b0895e9 100644 --- a/tests/hlsl/asuint.shader_test +++ b/tests/hlsl/asuint.shader_test @@ -20,7 +20,7 @@ float4 main() : sv_target
[test] uniform 0 uint4 123 0xc0000000 456 0x7fd69345 -todo(sm>=6) draw quad +draw quad probe (320,240) rgba (123.0, 3221225472.0, 456.0, 2144768896.0)
@@ -37,7 +37,7 @@ float4 main() : sv_target uniform 0 uint4 11 12 0 0 uniform 4 uint4 13 14 0 0 uniform 8 uint4 20 21 22 23 -todo(sm>=6) draw quad +draw quad probe (320,240) rgba (13.0, 21.0, 0.0, 0.0)
diff --git a/tests/hlsl/d3dcolor-to-ubyte4.shader_test b/tests/hlsl/d3dcolor-to-ubyte4.shader_test index 01b7f2f64..dca307cdb 100644 --- a/tests/hlsl/d3dcolor-to-ubyte4.shader_test +++ b/tests/hlsl/d3dcolor-to-ubyte4.shader_test @@ -11,7 +11,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 (1912.0, 1657.0, -127.0, 867.0) 1
[pixel shader] @@ -24,5 +24,5 @@ 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 (-127.0, -127.0, -127.0, -127.0) 1 diff --git a/tests/hlsl/function-cast.shader_test b/tests/hlsl/function-cast.shader_test index a2b9cf4f4..c92289863 100644 --- a/tests/hlsl/function-cast.shader_test +++ b/tests/hlsl/function-cast.shader_test @@ -18,7 +18,7 @@ float4 main() : sv_target
[test] uniform 0 float4 -1.9 -1.0 2.9 4.0 -todo draw quad +todo(sm<6) draw quad probe all rgba (-1.0, -1.0, 2.0, 4.0)
% As above, but cast "x" to float4 first. @@ -89,5 +89,5 @@ float4 main() : sv_target
[test] uniform 0 int4 -2 0 1 -3000000 -todo draw quad +todo(sm<6) draw quad probe all rgba (-1.0, 0.0, 1.0, -3000000.0) diff --git a/tests/hlsl/lerp.shader_test b/tests/hlsl/lerp.shader_test index 413bfe833..15e90cef9 100644 --- a/tests/hlsl/lerp.shader_test +++ b/tests/hlsl/lerp.shader_test @@ -32,7 +32,7 @@ float4 main() : SV_TARGET uniform 0 int4 2 3 4 0 uniform 4 int4 0 -10 10 1000000 uniform 8 int4 0 1 -1 1000000 -todo(sm>=6) draw quad +draw quad probe all rgba (2.0, -10.0, -2.0, 1e12)
diff --git a/tests/hlsl/non-const-indexing.shader_test b/tests/hlsl/non-const-indexing.shader_test index bc550738c..3a1e12acc 100644 --- a/tests/hlsl/non-const-indexing.shader_test +++ b/tests/hlsl/non-const-indexing.shader_test @@ -12,17 +12,17 @@ uniform 0 float4 1.0 2.0 3.0 4.0 uniform 4 float4 5.0 6.0 7.0 8.0 uniform 8 float4 9.0 10.0 11.0 12.0 uniform 12 float4 0 0 0 0 -todo(sm>=6) draw quad -todo(sm>=6) probe all rgba (1.0, 2.0, 3.0, 4.0) +draw quad +probe all rgba (1.0, 2.0, 3.0, 4.0) uniform 12 float4 1 0 0 0 -todo(sm>=6) draw quad -todo(sm>=6) probe all rgba (5.0, 6.0, 7.0, 8.0) +draw quad +probe all rgba (5.0, 6.0, 7.0, 8.0) uniform 12 float4 0 1 0 0 -todo(sm>=6) draw quad -todo(sm>=6) probe all rgba (5.0, 6.0, 7.0, 8.0) +draw quad +probe all rgba (5.0, 6.0, 7.0, 8.0) uniform 12 float4 1 1 0 0 -todo(sm>=6) draw quad -todo(sm>=6) probe all rgba (9.0, 10.0, 11.0, 12.0) +draw quad +probe all rgba (9.0, 10.0, 11.0, 12.0)
[pixel shader] diff --git a/tests/hlsl/shader-interstage-interface.shader_test b/tests/hlsl/shader-interstage-interface.shader_test index 271eb3bbe..584b88cf9 100644 --- a/tests/hlsl/shader-interstage-interface.shader_test +++ b/tests/hlsl/shader-interstage-interface.shader_test @@ -52,5 +52,5 @@ void main(float4 position : SV_Position, float2 t0 : TEXCOORD0, }
[test] -todo(sm>=6) draw triangle strip 4 +draw triangle strip 4 probe all rgba (10.0, 8.0, 7.0, 3.0)