1 //
2 // Copyright 2018 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // ANGLE_draw_id.cpp:
7 // Test for ANGLE_draw_id extension
8 //
9
10 #include "GLSLANG/ShaderLang.h"
11 #include "angle_gl.h"
12 #include "compiler/translator/tree_ops/EmulateMultiDrawShaderBuiltins.h"
13 #include "gtest/gtest.h"
14 #include "tests/test_utils/compiler_test.h"
15
16 using namespace sh;
17
18 class EmulateGLDrawIDTest : public MatchOutputCodeTest
19 {
20 public:
EmulateGLDrawIDTest()21 EmulateGLDrawIDTest()
22 : MatchOutputCodeTest(GL_VERTEX_SHADER, SH_VARIABLES, SH_GLSL_COMPATIBILITY_OUTPUT)
23 {
24 getResources()->ANGLE_multi_draw = 1;
25 }
26
27 protected:
CheckCompileFailure(const std::string & shaderString,const char * expectedError=nullptr)28 void CheckCompileFailure(const std::string &shaderString, const char *expectedError = nullptr)
29 {
30 std::string translatedCode;
31 std::string infoLog;
32 bool success = compileTestShader(GL_VERTEX_SHADER, SH_GLES2_SPEC,
33 SH_GLSL_COMPATIBILITY_OUTPUT, shaderString, getResources(),
34 SH_VARIABLES, &translatedCode, &infoLog);
35 EXPECT_FALSE(success);
36 if (expectedError)
37 {
38 EXPECT_TRUE(infoLog.find(expectedError) != std::string::npos);
39 }
40 }
41 };
42
43 // Check that compilation fails if the compile option to emulate gl_DrawID
44 // is not set
TEST_F(EmulateGLDrawIDTest,RequiresEmulation)45 TEST_F(EmulateGLDrawIDTest, RequiresEmulation)
46 {
47 CheckCompileFailure(
48 "#extension GL_ANGLE_multi_draw : require\n"
49 "void main() {\n"
50 " gl_Position = vec4(float(gl_DrawID), 0.0, 0.0, 1.0);\n"
51 "}\n",
52 "extension is not supported");
53 }
54
55 // Check that compiling with emulation with gl_DrawID works with different shader versions
TEST_F(EmulateGLDrawIDTest,CheckCompile)56 TEST_F(EmulateGLDrawIDTest, CheckCompile)
57 {
58 const std::string shaderString =
59 "#extension GL_ANGLE_multi_draw : require\n"
60 "void main() {\n"
61 " gl_Position = vec4(float(gl_DrawID), 0.0, 0.0, 1.0);\n"
62 "}\n";
63
64 compile(shaderString, SH_OBJECT_CODE | SH_VARIABLES | SH_EMULATE_GL_DRAW_ID);
65 compile("#version 100\n" + shaderString, SH_OBJECT_CODE | SH_VARIABLES | SH_EMULATE_GL_DRAW_ID);
66 compile("#version 300 es\n" + shaderString,
67 SH_OBJECT_CODE | SH_VARIABLES | SH_EMULATE_GL_DRAW_ID);
68 }
69
70 // Check that gl_DrawID is properly emulated
TEST_F(EmulateGLDrawIDTest,EmulatesUniform)71 TEST_F(EmulateGLDrawIDTest, EmulatesUniform)
72 {
73 addOutputType(SH_GLSL_COMPATIBILITY_OUTPUT);
74 addOutputType(SH_ESSL_OUTPUT);
75 #ifdef ANGLE_ENABLE_VULKAN
76 addOutputType(SH_SPIRV_VULKAN_OUTPUT);
77 #endif
78 #ifdef ANGLE_ENABLE_HLSL
79 addOutputType(SH_HLSL_3_0_OUTPUT);
80 addOutputType(SH_HLSL_3_0_OUTPUT);
81 #endif
82
83 const std::string &shaderString =
84 "#extension GL_ANGLE_multi_draw : require\n"
85 "void main() {\n"
86 " gl_Position = vec4(float(gl_DrawID), 0.0, 0.0, 1.0);\n"
87 "}\n";
88
89 compile(shaderString, SH_OBJECT_CODE | SH_VARIABLES | SH_EMULATE_GL_DRAW_ID);
90
91 EXPECT_TRUE(notFoundInCode("gl_DrawID"));
92 EXPECT_TRUE(foundInCode("angle_DrawID"));
93 EXPECT_TRUE(notFoundInCode("GL_ANGLE_multi_draw"));
94
95 EXPECT_TRUE(foundInCode(SH_GLSL_COMPATIBILITY_OUTPUT, "uniform int angle_DrawID"));
96 EXPECT_TRUE(foundInCode(SH_ESSL_OUTPUT, "uniform highp int angle_DrawID"));
97
98 #ifdef ANGLE_ENABLE_HLSL
99 EXPECT_TRUE(foundInCode(SH_HLSL_3_0_OUTPUT, "uniform int angle_DrawID : register"));
100 EXPECT_TRUE(foundInCode(SH_HLSL_3_0_OUTPUT, "uniform int angle_DrawID : register"));
101 #endif
102 }
103
104 // Check that a user-defined "gl_DrawID" is not permitted
TEST_F(EmulateGLDrawIDTest,DisallowsUserDefinedGLDrawID)105 TEST_F(EmulateGLDrawIDTest, DisallowsUserDefinedGLDrawID)
106 {
107 // Check that it is not permitted without the extension
108 CheckCompileFailure(
109 "uniform int gl_DrawID;\n"
110 "void main() {\n"
111 " gl_Position = vec4(float(gl_DrawID), 0.0, 0.0, 1.0);\n"
112 "}\n",
113 "reserved built-in name");
114
115 CheckCompileFailure(
116 "void main() {\n"
117 " int gl_DrawID = 0;\n"
118 " gl_Position = vec4(float(gl_DrawID), 0.0, 0.0, 1.0);\n"
119 "}\n",
120 "reserved built-in name");
121
122 // Check that it is not permitted with the extension
123 CheckCompileFailure(
124 "#extension GL_ANGLE_multi_draw : require\n"
125 "uniform int gl_DrawID;\n"
126 "void main() {\n"
127 " gl_Position = vec4(float(gl_DrawID), 0.0, 0.0, 1.0);\n"
128 "}\n",
129 "reserved built-in name");
130
131 CheckCompileFailure(
132 "#extension GL_ANGLE_multi_draw : require\n"
133 "void main() {\n"
134 " int gl_DrawID = 0;\n"
135 " gl_Position = vec4(float(gl_DrawID), 0.0, 0.0, 1.0);\n"
136 "}\n",
137 "reserved built-in name");
138 }
139
140 // gl_DrawID is translated to angle_DrawID internally. Check that a user-defined
141 // angle_DrawID is permitted
TEST_F(EmulateGLDrawIDTest,AllowsUserDefinedANGLEDrawID)142 TEST_F(EmulateGLDrawIDTest, AllowsUserDefinedANGLEDrawID)
143 {
144 addOutputType(SH_GLSL_COMPATIBILITY_OUTPUT);
145 addOutputType(SH_ESSL_OUTPUT);
146 #ifdef ANGLE_ENABLE_VULKAN
147 addOutputType(SH_SPIRV_VULKAN_OUTPUT);
148 #endif
149 #ifdef ANGLE_ENABLE_HLSL
150 addOutputType(SH_HLSL_3_0_OUTPUT);
151 addOutputType(SH_HLSL_3_0_OUTPUT);
152 #endif
153
154 const std::string &shaderString =
155 "#extension GL_ANGLE_multi_draw : require\n"
156 "uniform int angle_DrawID;\n"
157 "void main() {\n"
158 " gl_Position = vec4(float(angle_DrawID + gl_DrawID), 0.0, 0.0, 1.0);\n"
159 "}\n";
160
161 compile(shaderString, SH_OBJECT_CODE | SH_VARIABLES | SH_EMULATE_GL_DRAW_ID);
162
163 // " angle_DrawID" (note the space) should appear exactly twice:
164 // once in the declaration and once in the body.
165 // The user-defined angle_DrawID should be decorated
166 EXPECT_TRUE(foundInCode(" angle_DrawID", 2));
167 }
168