[Mesa-dev] [PATCH] spirv: Accept doubles in FaceForward, Reflect and Refract
Neil Roberts
nroberts at igalia.com
Wed Mar 7 17:05:02 UTC 2018
The SPIR-V spec doesn’t specify a size requirement for these and the
equivalent functions in the GLSL spec have explicit alternatives for
doubles. Refract is a little bit more complicated due to the fact that
the final argument is always supposed to be a scalar 32-bit float
regardless of the other operands. However in practice it seems there
is a bug in glslang that makes it convert the argument to 64-bit if
you actually try to pass it a 32-bit value while the other arguments
are 32-bit. This adds an optional conversion of the final argument in
order to support either type.
These have been tested against the automatically generated tests of
glsl-4.00/execution/built-in-functions using the ARB_gl_spirv branch
which tests it with quite a large range of combinations.
The issue with glslang has been filed here:
https://github.com/KhronosGroup/glslang/issues/1279
---
src/compiler/spirv/vtn_glsl450.c | 17 +++++++++++++----
1 file changed, 13 insertions(+), 4 deletions(-)
diff --git a/src/compiler/spirv/vtn_glsl450.c b/src/compiler/spirv/vtn_glsl450.c
index 46ef40f5e3f..b098f082f3e 100644
--- a/src/compiler/spirv/vtn_glsl450.c
+++ b/src/compiler/spirv/vtn_glsl450.c
@@ -583,14 +583,14 @@ handle_glsl450_alu(struct vtn_builder *b, enum GLSLstd450 entrypoint,
case GLSLstd450FaceForward:
val->ssa->def =
nir_bcsel(nb, nir_flt(nb, nir_fdot(nb, src[2], src[1]),
- nir_imm_float(nb, 0.0)),
+ NIR_IMM_FP(nb, 0.0)),
src[0], nir_fneg(nb, src[0]));
return;
case GLSLstd450Reflect:
/* I - 2 * dot(N, I) * N */
val->ssa->def =
- nir_fsub(nb, src[0], nir_fmul(nb, nir_imm_float(nb, 2.0),
+ nir_fsub(nb, src[0], nir_fmul(nb, NIR_IMM_FP(nb, 2.0),
nir_fmul(nb, nir_fdot(nb, src[0], src[1]),
src[1])));
return;
@@ -600,8 +600,17 @@ handle_glsl450_alu(struct vtn_builder *b, enum GLSLstd450 entrypoint,
nir_ssa_def *N = src[1];
nir_ssa_def *eta = src[2];
nir_ssa_def *n_dot_i = nir_fdot(nb, N, I);
- nir_ssa_def *one = nir_imm_float(nb, 1.0);
- nir_ssa_def *zero = nir_imm_float(nb, 0.0);
+ nir_ssa_def *one = NIR_IMM_FP(nb, 1.0);
+ nir_ssa_def *zero = NIR_IMM_FP(nb, 0.0);
+ /* According to the SPIR-V and GLSL specs, eta is always a float
+ * regardless of the type of the other operands. However in practice it
+ * seems that if you try to pass it a float then glslang will just
+ * promote it to a double and generate invalid SPIR-V. In order to
+ * support a hypothetical fixed version of glslang we’ll promote eta to
+ * double if the other operands are double also.
+ */
+ if (I->bit_size > eta->bit_size)
+ eta = nir_build_alu(nb, nir_op_f2f64, eta, NULL, NULL, NULL);
/* k = 1.0 - eta * eta * (1.0 - dot(N, I) * dot(N, I)) */
nir_ssa_def *k =
nir_fsub(nb, one, nir_fmul(nb, eta, nir_fmul(nb, eta,
--
2.14.3
More information about the mesa-dev
mailing list