// // Copyright 2018 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // // ANGLE_draw_id.cpp: // Test for ANGLE_draw_id extension // #include "GLSLANG/ShaderLang.h" #include "angle_gl.h" #include "compiler/translator/tree_ops/EmulateMultiDrawShaderBuiltins.h" #include "gtest/gtest.h" #include "tests/test_utils/compiler_test.h" using namespace sh; class EmulateGLDrawIDTest : public MatchOutputCodeTest { public: EmulateGLDrawIDTest() : MatchOutputCodeTest(GL_VERTEX_SHADER, SH_VARIABLES, SH_GLSL_COMPATIBILITY_OUTPUT) { getResources()->ANGLE_multi_draw = 1; } protected: void CheckCompileFailure(const std::string &shaderString, const char *expectedError = nullptr) { std::string translatedCode; std::string infoLog; bool success = compileTestShader(GL_VERTEX_SHADER, SH_GLES2_SPEC, SH_GLSL_COMPATIBILITY_OUTPUT, shaderString, getResources(), SH_VARIABLES, &translatedCode, &infoLog); EXPECT_FALSE(success); if (expectedError) { EXPECT_TRUE(infoLog.find(expectedError) != std::string::npos); } } }; // Check that compilation fails if the compile option to emulate gl_DrawID // is not set TEST_F(EmulateGLDrawIDTest, RequiresEmulation) { CheckCompileFailure( "#extension GL_ANGLE_multi_draw : require\n" "void main() {\n" " gl_Position = vec4(float(gl_DrawID), 0.0, 0.0, 1.0);\n" "}\n", "extension is not supported"); } // Check that compiling with emulation with gl_DrawID works with different shader versions TEST_F(EmulateGLDrawIDTest, CheckCompile) { const std::string shaderString = "#extension GL_ANGLE_multi_draw : require\n" "void main() {\n" " gl_Position = vec4(float(gl_DrawID), 0.0, 0.0, 1.0);\n" "}\n"; compile(shaderString, SH_OBJECT_CODE | SH_VARIABLES | SH_EMULATE_GL_DRAW_ID); compile("#version 100\n" + shaderString, SH_OBJECT_CODE | SH_VARIABLES | SH_EMULATE_GL_DRAW_ID); compile("#version 300 es\n" + shaderString, SH_OBJECT_CODE | SH_VARIABLES | SH_EMULATE_GL_DRAW_ID); } // Check that gl_DrawID is properly emulated TEST_F(EmulateGLDrawIDTest, EmulatesUniform) { addOutputType(SH_GLSL_COMPATIBILITY_OUTPUT); addOutputType(SH_ESSL_OUTPUT); #ifdef ANGLE_ENABLE_VULKAN addOutputType(SH_GLSL_VULKAN_OUTPUT); #endif #ifdef ANGLE_ENABLE_HLSL addOutputType(SH_HLSL_3_0_OUTPUT); addOutputType(SH_HLSL_3_0_OUTPUT); #endif const std::string &shaderString = "#extension GL_ANGLE_multi_draw : require\n" "void main() {\n" " gl_Position = vec4(float(gl_DrawID), 0.0, 0.0, 1.0);\n" "}\n"; compile(shaderString, SH_OBJECT_CODE | SH_VARIABLES | SH_EMULATE_GL_DRAW_ID); EXPECT_TRUE(notFoundInCode("gl_DrawID")); EXPECT_TRUE(foundInCode("angle_DrawID")); EXPECT_TRUE(notFoundInCode("GL_ANGLE_multi_draw")); EXPECT_TRUE(foundInCode(SH_GLSL_COMPATIBILITY_OUTPUT, "uniform int angle_DrawID")); EXPECT_TRUE(foundInCode(SH_ESSL_OUTPUT, "uniform highp int angle_DrawID")); #ifdef ANGLE_ENABLE_VULKAN EXPECT_TRUE( foundInCode(SH_GLSL_VULKAN_OUTPUT, "uniform defaultUniformsVS\n{\n int angle_DrawID;")); #endif #ifdef ANGLE_ENABLE_HLSL EXPECT_TRUE(foundInCode(SH_HLSL_3_0_OUTPUT, "uniform int angle_DrawID : register")); EXPECT_TRUE(foundInCode(SH_HLSL_3_0_OUTPUT, "uniform int angle_DrawID : register")); #endif } // Check that a user-defined "gl_DrawID" is not permitted TEST_F(EmulateGLDrawIDTest, DisallowsUserDefinedGLDrawID) { // Check that it is not permitted without the extension CheckCompileFailure( "uniform int gl_DrawID;\n" "void main() {\n" " gl_Position = vec4(float(gl_DrawID), 0.0, 0.0, 1.0);\n" "}\n", "reserved built-in name"); CheckCompileFailure( "void main() {\n" " int gl_DrawID = 0;\n" " gl_Position = vec4(float(gl_DrawID), 0.0, 0.0, 1.0);\n" "}\n", "reserved built-in name"); // Check that it is not permitted with the extension CheckCompileFailure( "#extension GL_ANGLE_multi_draw : require\n" "uniform int gl_DrawID;\n" "void main() {\n" " gl_Position = vec4(float(gl_DrawID), 0.0, 0.0, 1.0);\n" "}\n", "reserved built-in name"); CheckCompileFailure( "#extension GL_ANGLE_multi_draw : require\n" "void main() {\n" " int gl_DrawID = 0;\n" " gl_Position = vec4(float(gl_DrawID), 0.0, 0.0, 1.0);\n" "}\n", "reserved built-in name"); } // gl_DrawID is translated to angle_DrawID internally. Check that a user-defined // angle_DrawID is permitted TEST_F(EmulateGLDrawIDTest, AllowsUserDefinedANGLEDrawID) { addOutputType(SH_GLSL_COMPATIBILITY_OUTPUT); addOutputType(SH_ESSL_OUTPUT); #ifdef ANGLE_ENABLE_VULKAN addOutputType(SH_GLSL_VULKAN_OUTPUT); #endif #ifdef ANGLE_ENABLE_HLSL addOutputType(SH_HLSL_3_0_OUTPUT); addOutputType(SH_HLSL_3_0_OUTPUT); #endif const std::string &shaderString = "#extension GL_ANGLE_multi_draw : require\n" "uniform int angle_DrawID;\n" "void main() {\n" " gl_Position = vec4(float(angle_DrawID + gl_DrawID), 0.0, 0.0, 1.0);\n" "}\n"; compile(shaderString, SH_OBJECT_CODE | SH_VARIABLES | SH_EMULATE_GL_DRAW_ID); // " angle_DrawID" (note the space) should appear exactly twice: // once in the declaration and once in the body. // The user-defined angle_DrawID should be decorated EXPECT_TRUE(foundInCode(" angle_DrawID", 2)); }