diff options
| author | jsmall-nvidia <jsmall@nvidia.com> | 2019-02-08 09:02:55 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-02-08 09:02:55 -0500 |
| commit | c34a5e7ed2da03c9ceaddd167e4b0421246b0c25 (patch) | |
| tree | 078851510f93a4fdd62d819f30a86483a4165075 | |
| parent | 23b36c5cb10c820c0b0f66000711d1013bc009f3 (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.cpp | 71 | ||||
| -rw-r--r-- | tests/bugs/vec-compare.slang | 80 | ||||
| -rw-r--r-- | tests/bugs/vec-compare.slang.expected.txt | 17 |
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 + |
