Signed-off-by: Nikolay Sivov nsivov@codeweavers.com
-- v2: vkd3d-shader/hlsl: Add refract() function.
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)
On Wed Nov 8 00:46:20 2023 +0000, Zebediah Figura wrote:
This still has review that needs to be addressed.
It's still not clear to me where argument conversion needs to happen. I don't see any 'itof's for example when called with int vectors. Unrelated to that, one thing we need to check is that dimensions for 'r' and 'n' are the same.
On Wed Nov 8 00:46:19 2023 +0000, Nikolay Sivov wrote:
It's still not clear to me where argument conversion needs to happen. I don't see any 'itof's for example when called with int vectors. Unrelated to that, one thing we need to check is that dimensions for 'r' and 'n' are the same.
I see itof for all three arguments with the following shader:
``` int a, b, c;
float4 main() : sv_target { return refract(a, b, c); } ```
What are you testing?
On Wed Nov 8 01:05:15 2023 +0000, Zebediah Figura wrote:
I see itof for all three arguments with the following shader:
int a, b, c; float4 main() : sv_target { return refract(a, b, c); }
What are you testing?
That's a good question, I think I confused my test files. Contrary to what documentation suggests, this function only seems to support scalars/float1's or float4 vectors, nothing in between. Last argument is simply cast to a scalar. I'll update accordingly.
On Wed Nov 8 11:33:35 2023 +0000, Nikolay Sivov wrote:
That's a good question, I think I confused my test files. Contrary to what documentation suggests, this function only seems to support scalars/float1's or float4 vectors, nothing in between. Last argument is simply cast to a scalar. I'll update accordingly.
Wrong again. The failure was about implicit cast of return value, it does accept any vector size.