| // |
| // 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 defaultUniforms\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)); |
| } |