diff --git a/src/tests/compiler_tests/HLSLOutput_test.cpp b/src/tests/compiler_tests/HLSLOutput_test.cpp index 47a6c975fe..4a8a8394f6 100644 --- a/src/tests/compiler_tests/HLSLOutput_test.cpp +++ b/src/tests/compiler_tests/HLSLOutput_test.cpp @@ -33,6 +33,55 @@ class HLSL41VertexOutputTest : public MatchOutputCodeTest HLSL41VertexOutputTest() : MatchOutputCodeTest(GL_VERTEX_SHADER, SH_HLSL_4_1_OUTPUT) {} }; +// Test that an && whose RHS contains an indirect array index is unfolded into an +// if-statement, even though the RHS has no GLSL "side effects". HLSL && does NOT +// short-circuit, so emitting it as a raw && causes data[idx] to be evaluated +// unconditionally with an unclamped index. GLSL ES 3.0 ยง5.9 mandates short-circuit +// semantics; failing to unfold here is a spec violation that exposes driver-dependent +// OOB reads of D3D11 indexable-temp registers. +// +// This is the HLSL counterpart of the SPIR-V fix that introduced +// IsSafeToExecuteInShortCircuit() (angleproject:465831139). +TEST_F(HLSLOutputTest, ShortCircuitAndWithIndirectArrayIndexOnRHS) +{ + const std::string &shaderString = + "#version 300 es\n" + "precision highp float;\n" + "uniform int idx;\n" + "uniform bool safe;\n" + "out vec4 color;\n" + "void main() {\n" + " float data[4] = float[4](1.0, 2.0, 3.0, 4.0);\n" + " bool b = safe && (data[idx] > 0.0);\n" + " color = vec4(b ? 1.0 : 0.0);\n" + "}\n"; + compile(shaderString); + // The && must NOT survive into HLSL: it must be unfolded into an if() because + // HLSL evaluates both operands of &&. If "&&" appears in the output, data[idx] + // is executed unconditionally with an unclamped index. + EXPECT_TRUE(notFoundInCode("&&")) << "Generated HLSL:\n" + << outputCode(SH_HLSL_4_1_OUTPUT); +} + +// Same as above but for ||. +TEST_F(HLSLOutputTest, ShortCircuitOrWithIndirectArrayIndexOnRHS) +{ + const std::string &shaderString = + "#version 300 es\n" + "precision highp float;\n" + "uniform int idx;\n" + "uniform bool safe;\n" + "out vec4 color;\n" + "void main() {\n" + " float data[4] = float[4](1.0, 2.0, 3.0, 4.0);\n" + " bool b = safe || (data[idx] > 0.0);\n" + " color = vec4(b ? 1.0 : 0.0);\n" + "}\n"; + compile(shaderString); + EXPECT_TRUE(notFoundInCode("||")) << "Generated HLSL:\n" + << outputCode(SH_HLSL_4_1_OUTPUT); +} + // Test that having dynamic indexing of a vector inside the right hand side of logical or doesn't // trigger asserts in HLSL output. TEST_F(HLSLOutputTest, DynamicIndexingOfVectorOnRightSideOfLogicalOr)