summaryrefslogtreecommitdiffstats
path: root/src/compiler
diff options
context:
space:
mode:
authorIago Toral Quiroga <[email protected]>2016-11-17 09:36:36 +0100
committerIago Toral Quiroga <[email protected]>2016-11-23 08:07:44 +0100
commite062eb6415de3aa51b43f30d638ce8215efc0511 (patch)
treea59835d862f2fe53ff57702651a141fc08decea1 /src/compiler
parent9ce592647682b1d27c313c4f72713046fc86cbe4 (diff)
nir/spirv: implement ordered / unordered floating point comparisons properly
Besides the logical operation involved, these also require that we test if the operands are ordered / unordered. For ordered operations, both operands must be ordered (and they must pass the conditional test) while for unordered operations it is sufficient if only one of the operands is unordered (or they pass the logical test). Fixes the following Vulkan CTS tests: dEQP-VK.spirv_assembly.instruction.compute.opfunord.equal dEQP-VK.spirv_assembly.instruction.compute.opfunord.greater dEQP-VK.spirv_assembly.instruction.compute.opfunord.greaterequal dEQP-VK.spirv_assembly.instruction.compute.opfunord.less dEQP-VK.spirv_assembly.instruction.compute.opfunord.lessequal v2: Fixed typo: s/nir_eq/nir_feq Reviewed-by: Lionel Landwerlin <[email protected]>
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/spirv/vtn_alu.c53
1 files changed, 52 insertions, 1 deletions
diff --git a/src/compiler/spirv/vtn_alu.c b/src/compiler/spirv/vtn_alu.c
index 6d98a62ab97..95ff2b1aafe 100644
--- a/src/compiler/spirv/vtn_alu.c
+++ b/src/compiler/spirv/vtn_alu.c
@@ -257,7 +257,10 @@ vtn_nir_alu_op_for_spirv_opcode(SpvOp opcode, bool *swap)
case SpvOpBitReverse: return nir_op_bitfield_reverse;
case SpvOpBitCount: return nir_op_bit_count;
- /* Comparisons: (TODO: How do we want to handled ordered/unordered?) */
+ /* The ordered / unordered operators need special implementation besides
+ * the logical operator to use since they also need to check if operands are
+ * ordered.
+ */
case SpvOpFOrdEqual: return nir_op_feq;
case SpvOpFUnordEqual: return nir_op_feq;
case SpvOpINotEqual: return nir_op_ine;
@@ -447,6 +450,54 @@ vtn_handle_alu(struct vtn_builder *b, SpvOp opcode,
nir_imm_float(&b->nb, INFINITY));
break;
+ case SpvOpFUnordEqual:
+ case SpvOpFUnordNotEqual:
+ case SpvOpFUnordLessThan:
+ case SpvOpFUnordGreaterThan:
+ case SpvOpFUnordLessThanEqual:
+ case SpvOpFUnordGreaterThanEqual: {
+ bool swap;
+ nir_op op = vtn_nir_alu_op_for_spirv_opcode(opcode, &swap);
+
+ if (swap) {
+ nir_ssa_def *tmp = src[0];
+ src[0] = src[1];
+ src[1] = tmp;
+ }
+
+ val->ssa->def =
+ nir_ior(&b->nb,
+ nir_build_alu(&b->nb, op, src[0], src[1], NULL, NULL),
+ nir_ior(&b->nb,
+ nir_fne(&b->nb, src[0], src[0]),
+ nir_fne(&b->nb, src[1], src[1])));
+ break;
+ }
+
+ case SpvOpFOrdEqual:
+ case SpvOpFOrdNotEqual:
+ case SpvOpFOrdLessThan:
+ case SpvOpFOrdGreaterThan:
+ case SpvOpFOrdLessThanEqual:
+ case SpvOpFOrdGreaterThanEqual: {
+ bool swap;
+ nir_op op = vtn_nir_alu_op_for_spirv_opcode(opcode, &swap);
+
+ if (swap) {
+ nir_ssa_def *tmp = src[0];
+ src[0] = src[1];
+ src[1] = tmp;
+ }
+
+ val->ssa->def =
+ nir_iand(&b->nb,
+ nir_build_alu(&b->nb, op, src[0], src[1], NULL, NULL),
+ nir_iand(&b->nb,
+ nir_feq(&b->nb, src[0], src[0]),
+ nir_feq(&b->nb, src[1], src[1])));
+ break;
+ }
+
default: {
bool swap;
nir_op op = vtn_nir_alu_op_for_spirv_opcode(opcode, &swap);