From 608d70bc02a968ee2b21a5db0f54247d877c8196 Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Wed, 21 Mar 2018 20:34:40 +0100 Subject: [PATCH] spirv: Accept doubles in FaceForward, Reflect and Refract MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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- or 16- 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 64-bit. This adds an optional conversion of the final argument in order to support any 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 v2: Convert the eta operand of Refract from any size in order to make it eventually cope with 16-bit floats. Reviewed-by: Jason Ekstrand --- src/compiler/spirv/vtn_glsl450.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/compiler/spirv/vtn_glsl450.c b/src/compiler/spirv/vtn_glsl450.c index c74476a48d7..6fa759b1bba 100644 --- a/src/compiler/spirv/vtn_glsl450.c +++ b/src/compiler/spirv/vtn_glsl450.c @@ -629,14 +629,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; @@ -646,8 +646,22 @@ 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) { + nir_op conversion_op = + nir_type_conversion_op(nir_type_float | eta->bit_size, + nir_type_float | I->bit_size, + nir_rounding_mode_undef); + eta = nir_build_alu(nb, conversion_op, 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.30.2