summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Romanick <ian.d.romanick@intel.com>2021-10-29 08:15:18 -0700
committerEric Engestrom <eric@engestrom.ch>2022-02-23 17:55:55 +0000
commit724acc7bd62effd1c84f7ce64cf284d906232630 (patch)
treef51043a47ea00aed76b3f9a851ebc2440836e864
parent062e7ee38c435f8994e92b7ec2cb5800e3a149aa (diff)
spirv: Produce correct result for GLSLstd450Modf with Inf
GLSLstd450ModfStruct too. No shader-db or fossil-db changes on any Intel platform. v2: Fix handling 16-bit (and presumably 64-bit) values. Reviewed-by: Caio Oliveira <caio.oliveira@intel.com> Fixes: f92a35d831c ("vtn: Fix Modf.") Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/13999> (cherry picked from commit e442b9d79296ad9322af61fdadbc81d680466f57)
-rw-r--r--.pick_status.json2
-rw-r--r--src/compiler/spirv/vtn_glsl450.c26
2 files changed, 25 insertions, 3 deletions
diff --git a/.pick_status.json b/.pick_status.json
index 2313ba5811e..3cc6f7baf19 100644
--- a/.pick_status.json
+++ b/.pick_status.json
@@ -3820,7 +3820,7 @@
"description": "spirv: Produce correct result for GLSLstd450Modf with Inf",
"nominated": true,
"nomination_type": 1,
- "resolution": 0,
+ "resolution": 1,
"main_sha": null,
"because_sha": "f92a35d831cf54f2244d5510932fd17c97b02ce4"
},
diff --git a/src/compiler/spirv/vtn_glsl450.c b/src/compiler/spirv/vtn_glsl450.c
index d596c251548..21f5fa80973 100644
--- a/src/compiler/spirv/vtn_glsl450.c
+++ b/src/compiler/spirv/vtn_glsl450.c
@@ -332,9 +332,22 @@ handle_glsl450_alu(struct vtn_builder *b, enum GLSLstd450 entrypoint,
break;
case GLSLstd450Modf: {
+ nir_ssa_def *inf = nir_imm_floatN_t(&b->nb, INFINITY, src[0]->bit_size);
+ nir_ssa_def *sign_bit =
+ nir_imm_intN_t(&b->nb, (uint64_t)1 << (src[0]->bit_size - 1),
+ src[0]->bit_size);
nir_ssa_def *sign = nir_fsign(nb, src[0]);
nir_ssa_def *abs = nir_fabs(nb, src[0]);
- dest->def = nir_fmul(nb, sign, nir_ffract(nb, abs));
+
+ /* NaN input should produce a NaN results, and ±Inf input should provide
+ * ±0 result. The fmul(sign(x), ffract(x)) calculation will already
+ * produce the expected NaN. To get ±0, directly compare for equality
+ * with Inf instead of using fisfinite (which is false for NaN).
+ */
+ dest->def = nir_bcsel(nb,
+ nir_ieq(nb, abs, inf),
+ nir_iand(nb, src[0], sign_bit),
+ nir_fmul(nb, sign, nir_ffract(nb, abs)));
struct vtn_pointer *i_ptr = vtn_value(b, w[6], vtn_value_type_pointer)->pointer;
struct vtn_ssa_value *whole = vtn_create_ssa_value(b, i_ptr->type->type);
@@ -344,10 +357,19 @@ handle_glsl450_alu(struct vtn_builder *b, enum GLSLstd450 entrypoint,
}
case GLSLstd450ModfStruct: {
+ nir_ssa_def *inf = nir_imm_floatN_t(&b->nb, INFINITY, src[0]->bit_size);
+ nir_ssa_def *sign_bit =
+ nir_imm_intN_t(&b->nb, (uint64_t)1 << (src[0]->bit_size - 1),
+ src[0]->bit_size);
nir_ssa_def *sign = nir_fsign(nb, src[0]);
nir_ssa_def *abs = nir_fabs(nb, src[0]);
vtn_assert(glsl_type_is_struct_or_ifc(dest_type));
- dest->elems[0]->def = nir_fmul(nb, sign, nir_ffract(nb, abs));
+
+ /* See GLSLstd450Modf for explanation of the Inf and NaN handling. */
+ dest->elems[0]->def = nir_bcsel(nb,
+ nir_ieq(nb, abs, inf),
+ nir_iand(nb, src[0], sign_bit),
+ nir_fmul(nb, sign, nir_ffract(nb, abs)));
dest->elems[1]->def = nir_fmul(nb, sign, nir_ffloor(nb, abs));
break;
}