From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- Makefile.am | 1 + libs/vkd3d-shader/hlsl.y | 38 ++++++++++++++++++++++++++++++++++ tests/hlsl/refract.shader_test | 19 +++++++++++++++++ 3 files changed, 58 insertions(+) create mode 100644 tests/hlsl/refract.shader_test
diff --git a/Makefile.am b/Makefile.am index 14b5cf096..642e7d9df 100644 --- a/Makefile.am +++ b/Makefile.am @@ -143,6 +143,7 @@ vkd3d_shader_tests = \ tests/hlsl/object-references.shader_test \ tests/hlsl/pow.shader_test \ tests/hlsl/reflect.shader_test \ + tests/hlsl/refract.shader_test \ tests/hlsl/register-reservations.shader_test \ tests/hlsl/return-implicit-conversion.shader_test \ tests/hlsl/return.shader_test \ diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index 0e72a539e..f488ec047 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -3392,6 +3392,43 @@ static bool intrinsic_reflect(struct hlsl_ctx *ctx, return !!add_binary_arithmetic_expr(ctx, params->instrs, HLSL_OP2_ADD, i, neg, loc); }
+static bool intrinsic_refract(struct hlsl_ctx *ctx, + const struct parse_initializer *params, const struct vkd3d_shader_location *loc) +{ + struct hlsl_ir_node *r = params->args[0]; + struct hlsl_ir_node *n = params->args[1]; + struct hlsl_ir_function_decl *func; + struct hlsl_type *type; + char *body; + + static const char template[] = + "%s refract(%s r, %s n, float i)\n" + "{\n" + " float d = dot(r, n);\n" + " float t = 1 - i * i * (1 - d * d);\n" + " return t >= 0.0 ? i * r - (i * d + sqrt(t)) * n : 0;\n" + "}"; + + if (r->data_type->class == HLSL_CLASS_MATRIX + || n->data_type->class == HLSL_CLASS_MATRIX) + { + hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, "Invalid argument type."); + return false; + } + + type = hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, r->data_type->dimx); + + if (!(body = hlsl_sprintf_alloc(ctx, template, type->name, type->name, type->name))) + return false; + + func = hlsl_compile_internal_function(ctx, "refract", body); + vkd3d_free(body); + if (!func) + return false; + + return add_user_call(ctx, func, params, loc); +} + static bool intrinsic_round(struct hlsl_ctx *ctx, const struct parse_initializer *params, const struct vkd3d_shader_location *loc) { @@ -3811,6 +3848,7 @@ intrinsic_functions[] = {"normalize", 1, true, intrinsic_normalize}, {"pow", 2, true, intrinsic_pow}, {"reflect", 2, true, intrinsic_reflect}, + {"refract", 3, true, intrinsic_refract}, {"round", 1, true, intrinsic_round}, {"rsqrt", 1, true, intrinsic_rsqrt}, {"saturate", 1, true, intrinsic_saturate}, diff --git a/tests/hlsl/refract.shader_test b/tests/hlsl/refract.shader_test new file mode 100644 index 000000000..0ce84955c --- /dev/null +++ b/tests/hlsl/refract.shader_test @@ -0,0 +1,19 @@ +[pixel shader] +uniform float4 r; +uniform float4 n; +uniform float i; + +float4 main() : sv_target +{ + return refract(r, n, i); +} + +[test] +uniform 0 float4 0.5 -0.1 0.2 0.3 +uniform 4 float4 0.6 0.4 -0.3 1.0 +uniform 8 float 0.2 +todo(sm>=6) draw quad +probe all rgba (-0.550931, -0.453954, 0.3654653, -1.0248856) 32 +uniform 8 float 100.0 +todo(sm>=6) draw quad +probe all rgba (0.0, 0.0, 0.0, 0.0)