summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjsmall-nvidia <jsmall@nvidia.com>2019-02-08 09:02:55 -0500
committerGitHub <noreply@github.com>2019-02-08 09:02:55 -0500
commitc34a5e7ed2da03c9ceaddd167e4b0421246b0c25 (patch)
tree078851510f93a4fdd62d819f30a86483a4165075
parent23b36c5cb10c820c0b0f66000711d1013bc009f3 (diff)
Fix vector compares on GLSL targets (#833)
* * Make vector comparisons out correct functions on glsl * Test for vector comparisons * Typo fixes * Glsl vector comparisons use functions. * Added a coercion test.
-rw-r--r--source/slang/emit.cpp71
-rw-r--r--tests/bugs/vec-compare.slang80
-rw-r--r--tests/bugs/vec-compare.slang.expected.txt17
3 files changed, 158 insertions, 10 deletions
diff --git a/source/slang/emit.cpp b/source/slang/emit.cpp
index d551ba1b9..38ea79206 100644
--- a/source/slang/emit.cpp
+++ b/source/slang/emit.cpp
@@ -101,7 +101,7 @@ struct SharedEmitContext
HumaneSourceLoc nextSourceLocation;
bool needToUpdateSourceLocation;
- // For GLSL output, we can't emit traidtional `#line` directives
+ // For GLSL output, we can't emit traditional `#line` directives
// with a file path in them, so we maintain a map that associates
// each path with a unique integer, and then we output those
// instead.
@@ -508,7 +508,7 @@ struct EmitVisitor
{
// There are a few different requirements here that we need to deal with:
//
- // 1) We need to print somethign that is valid syntax in the target language
+ // 1) We need to print something that is valid syntax in the target language
// (this means that hex floats are off the table for now)
//
// 2) We need our printing to be independent of the current global locale in C,
@@ -1608,7 +1608,7 @@ struct EmitVisitor
return space;
}
- // Emit a single `regsiter` semantic, as appropriate for a given resource-type-specific layout info
+ // Emit a single `register` semantic, as appropriate for a given resource-type-specific layout info
void emitHLSLRegisterSemantic(
LayoutResourceKind kind,
EmitVarChain* chain,
@@ -1779,7 +1779,7 @@ struct EmitVisitor
// Explicit offsets require a GLSL extension (which
// is not universally supported, it seems) or a new
// enough GLSL version (which we don't want to
- // universall require), so for right now we
+ // universally require), so for right now we
// won't actually output explicit offsets for uniform
// shader parameters.
//
@@ -3597,6 +3597,51 @@ struct EmitVisitor
}
}
+ static const char* getGLSLVectorCompareFunctionName(IROp op)
+ {
+ // Glsl vector comparisons use functions...
+ // https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/equal.xhtml
+
+ switch (op)
+ {
+ case kIROp_Eql: return "equal";
+ case kIROp_Neq: return "notEqual";
+ case kIROp_Greater: return "greaterThan";
+ case kIROp_Less: return "lessThan";
+ case kIROp_Geq: return "greaterThanEqual";
+ case kIROp_Leq: return "lessThanEqual";
+ default: return nullptr;
+ }
+ }
+
+ void emitComparison(EmitContext* ctx, IRInst* inst, IREmitMode mode, EOpInfo& inOutOuterPrec, const EOpInfo& opPrec, bool* needCloseOut)
+ {
+ *needCloseOut = maybeEmitParens(inOutOuterPrec, opPrec);
+
+ if (getTarget(ctx) == CodeGenTarget::GLSL
+ && as<IRVectorType>(inst->getOperand(0)->getDataType())
+ && as<IRVectorType>(inst->getOperand(1)->getDataType()))
+ {
+ const char* funcName = getGLSLVectorCompareFunctionName(inst->op);
+ SLANG_ASSERT(funcName);
+
+ emit(funcName);
+ emit("(");
+ emitIROperand(ctx, inst->getOperand(0), mode, leftSide(inOutOuterPrec, opPrec));
+ emit(",");
+ emitIROperand(ctx, inst->getOperand(1), mode, rightSide(inOutOuterPrec, opPrec));
+ emit(")");
+ }
+ else
+ {
+ emitIROperand(ctx, inst->getOperand(0), mode, leftSide(inOutOuterPrec, opPrec));
+ emit(" ");
+ emit(opPrec.op);
+ emit(" ");
+ emitIROperand(ctx, inst->getOperand(1), mode, rightSide(inOutOuterPrec, opPrec));
+ }
+ }
+
void emitIRInstExpr(
EmitContext* ctx,
IRInst* inst,
@@ -3703,6 +3748,12 @@ struct EmitVisitor
}
break;
+
+#define CASE_COMPARE(OPCODE, PREC, OP) \
+ case OPCODE: \
+ emitComparison(ctx, inst, mode, outerPrec, kEOp_##PREC, &needClose); \
+ break
+
#define CASE(OPCODE, PREC, OP) \
case OPCODE: \
needClose = maybeEmitParens(outerPrec, kEOp_##PREC); \
@@ -3721,12 +3772,12 @@ struct EmitVisitor
// TODO: Need to pull out component-wise
// comparison cases for matrices/vectors
- CASE(kIROp_Eql, Eql, ==);
- CASE(kIROp_Neq, Neq, !=);
- CASE(kIROp_Greater, Greater, >);
- CASE(kIROp_Less, Less, <);
- CASE(kIROp_Geq, Geq, >=);
- CASE(kIROp_Leq, Leq, <=);
+ CASE_COMPARE(kIROp_Eql, Eql, ==);
+ CASE_COMPARE(kIROp_Neq, Neq, !=);
+ CASE_COMPARE(kIROp_Greater, Greater, >);
+ CASE_COMPARE(kIROp_Less, Less, <);
+ CASE_COMPARE(kIROp_Geq, Geq, >=);
+ CASE_COMPARE(kIROp_Leq, Leq, <=);
CASE(kIROp_BitAnd, BitAnd, &);
CASE(kIROp_BitXor, BitXor, ^);
diff --git a/tests/bugs/vec-compare.slang b/tests/bugs/vec-compare.slang
new file mode 100644
index 000000000..0eaec0191
--- /dev/null
+++ b/tests/bugs/vec-compare.slang
@@ -0,0 +1,80 @@
+//TEST(compute):COMPARE_COMPUTE_EX:-slang -compute
+//TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -dx12
+//TEST(compute, vulkan):COMPARE_COMPUTE_EX:-vk -compute
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0], stride=4):dxbinding(0),glbinding(0),out
+
+RWStructuredBuffer<int> outputBuffer;
+
+[numthreads(4,4,1)]
+void computeMain(uint3 pixelIndex : SV_DispatchThreadID)
+{
+
+ // We will test floats, uints, and int vectors
+ // We need all comparisons < > <= >= == !=
+
+ int x = pixelIndex.x;
+ int y = pixelIndex.y;
+
+ int uintBits;
+ {
+ uint2 v = { uint(x), uint(y) };
+ uint2 test = { 1, 3 };
+
+ int bits = 0;
+ bits |= any(v < test) ? 0x01 : 0;
+ bits |= any(v <= test) ? 0x02 : 0;
+ bits |= any(v == test) ? 0x04 : 0;
+ bits |= any(v > test) ? 0x08 : 0;
+ bits |= any(v >= test) ? 0x10 : 0;
+ bits |= any(v != test) ? 0x20 : 0;
+ uintBits = bits;
+ }
+
+ int intBits;
+ {
+ int2 v = { x, y };
+ int2 test = { 2, 0 };
+
+ int bits = 0;
+ bits |= any(v < test) ? 0x01 : 0;
+ bits |= any(v <= test) ? 0x02 : 0;
+ bits |= any(v == test) ? 0x04 : 0;
+ bits |= any(v > test) ? 0x08 : 0;
+ bits |= any(v >= test) ? 0x10 : 0;
+ bits |= any(v != test) ? 0x20 : 0;
+ intBits = bits;
+ }
+
+ int floatBits;
+ {
+ float2 v = { float(x), float(y) };
+ float2 test = { 1, 2 };
+
+ int bits = 0;
+ bits |= any(v < test) ? 0x01 : 0;
+ bits |= any(v <= test) ? 0x02 : 0;
+ bits |= any(v == test) ? 0x04 : 0;
+ bits |= any(v > test) ? 0x08 : 0;
+ bits |= any(v >= test) ? 0x10 : 0;
+ bits |= any(v != test) ? 0x20 : 0;
+ floatBits = bits;
+ }
+
+ int coerceBits;
+ {
+ float2 v = { float(x), float(y) };
+ int2 test = { 1, 2 };
+
+ int bits = 0;
+ bits |= any(v < test) ? 0x01 : 0;
+ bits |= any(v <= test) ? 0x02 : 0;
+ bits |= any(v == test) ? 0x04 : 0;
+ bits |= any(v > test) ? 0x08 : 0;
+ bits |= any(v >= test) ? 0x10 : 0;
+ bits |= any(v != test) ? 0x20 : 0;
+ coerceBits = bits;
+ }
+
+ outputBuffer[pixelIndex.x + pixelIndex.y * 4] = (coerceBits << 24) | (floatBits << 16) | (intBits << 8) | (uintBits);
+} \ No newline at end of file
diff --git a/tests/bugs/vec-compare.slang.expected.txt b/tests/bugs/vec-compare.slang.expected.txt
new file mode 100644
index 000000000..477414740
--- /dev/null
+++ b/tests/bugs/vec-compare.slang.expected.txt
@@ -0,0 +1,17 @@
+23233723
+37373737
+3B3B163B
+3B3B3E3B
+23233B23
+37373B37
+3B3B3E3B
+3B3B383B
+37373B23
+16163B37
+3E3E3E3B
+3E3E383B
+3B3B3B37
+3E3E3B16
+38383E3E
+3838383E
+