1 //
2 // Copyright 2019 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_base_vertex_base_instance.cpp:
7 //   Test for ANGLE_base_vertex_base_instance 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 EmulateGLBaseVertexBaseInstanceTest : public MatchOutputCodeTest
19 {
20   public:
EmulateGLBaseVertexBaseInstanceTest()21     EmulateGLBaseVertexBaseInstanceTest()
22         : MatchOutputCodeTest(GL_VERTEX_SHADER, SH_VARIABLES, SH_GLSL_COMPATIBILITY_OUTPUT)
23     {
24         getResources()->ANGLE_base_vertex_base_instance = 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_GLES3_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_BaseVertex and gl_BaseInstance
44 // is not set
TEST_F(EmulateGLBaseVertexBaseInstanceTest,RequiresEmulation)45 TEST_F(EmulateGLBaseVertexBaseInstanceTest, RequiresEmulation)
46 {
47     CheckCompileFailure(
48         "#extension GL_ANGLE_base_vertex_base_instance : require\n"
49         "void main() {\n"
50         "   gl_Position = vec4(float(gl_BaseVertex), float(gl_BaseInstance), 0.0, 1.0);\n"
51         "}\n",
52         "extension is not supported");
53 }
54 
55 // Check that compiling with emulation with gl_BaseVertex and gl_BaseInstance works with different
56 // shader versions
TEST_F(EmulateGLBaseVertexBaseInstanceTest,CheckCompile)57 TEST_F(EmulateGLBaseVertexBaseInstanceTest, CheckCompile)
58 {
59     const std::string shaderString =
60         "#extension GL_ANGLE_base_vertex_base_instance : require\n"
61         "void main() {\n"
62         "   gl_Position = vec4(float(gl_BaseVertex), float(gl_BaseInstance), 0.0, 1.0);\n"
63         "}\n";
64 
65     compile("#version 300 es\n" + shaderString,
66             SH_OBJECT_CODE | SH_VARIABLES | SH_EMULATE_GL_BASE_VERTEX_BASE_INSTANCE);
67 }
68 
69 // Check that gl_BaseVertex and gl_BaseInstance is properly emulated
TEST_F(EmulateGLBaseVertexBaseInstanceTest,EmulatesUniform)70 TEST_F(EmulateGLBaseVertexBaseInstanceTest, EmulatesUniform)
71 {
72     addOutputType(SH_GLSL_COMPATIBILITY_OUTPUT);
73     addOutputType(SH_ESSL_OUTPUT);
74 #ifdef ANGLE_ENABLE_VULKAN
75     addOutputType(SH_GLSL_VULKAN_OUTPUT);
76 #endif
77 #ifdef ANGLE_ENABLE_HLSL
78     addOutputType(SH_HLSL_3_0_OUTPUT);
79     addOutputType(SH_HLSL_3_0_OUTPUT);
80 #endif
81 
82     const std::string &shaderString =
83         "#version 300 es\n"
84         "#extension GL_ANGLE_base_vertex_base_instance : require\n"
85         "void main() {\n"
86         "   gl_Position = vec4(float(gl_BaseVertex), float(gl_BaseInstance), 0.0, 1.0);\n"
87         "}\n";
88 
89     compile(shaderString, SH_OBJECT_CODE | SH_VARIABLES | SH_EMULATE_GL_BASE_VERTEX_BASE_INSTANCE);
90 
91     EXPECT_TRUE(notFoundInCode("gl_BaseVertex"));
92     EXPECT_TRUE(foundInCode("angle_BaseVertex"));
93     EXPECT_TRUE(notFoundInCode("gl_BaseInstance"));
94     EXPECT_TRUE(foundInCode("angle_BaseInstance"));
95     EXPECT_TRUE(notFoundInCode("GL_ANGLE_base_vertex_base_instance"));
96 
97     EXPECT_TRUE(foundInCode(SH_GLSL_COMPATIBILITY_OUTPUT, "uniform int angle_BaseVertex"));
98     EXPECT_TRUE(foundInCode(SH_GLSL_COMPATIBILITY_OUTPUT, "uniform int angle_BaseInstance"));
99     EXPECT_TRUE(foundInCode(SH_ESSL_OUTPUT, "uniform highp int angle_BaseVertex"));
100     EXPECT_TRUE(foundInCode(SH_ESSL_OUTPUT, "uniform highp int angle_BaseInstance"));
101 
102 #ifdef ANGLE_ENABLE_VULKAN
103     EXPECT_TRUE(foundInCode(
104         SH_GLSL_VULKAN_OUTPUT,
105         "uniform defaultUniformsVS\n{\n    int angle_BaseInstance;\n    int angle_BaseVertex;"));
106 #endif
107 #ifdef ANGLE_ENABLE_HLSL
108     EXPECT_TRUE(foundInCode(SH_HLSL_3_0_OUTPUT, "uniform int angle_BaseVertex : register"));
109     EXPECT_TRUE(foundInCode(SH_HLSL_3_0_OUTPUT, "uniform int angle_BaseInstance : register"));
110 #endif
111 }
112 
113 // Check that a user-defined "gl_BaseVertex" or "gl_BaseInstance" is not permitted
TEST_F(EmulateGLBaseVertexBaseInstanceTest,DisallowsUserDefinedGLDrawID)114 TEST_F(EmulateGLBaseVertexBaseInstanceTest, DisallowsUserDefinedGLDrawID)
115 {
116     // Check that it is not permitted without the extension
117     CheckCompileFailure(
118         "#version 300 es\n"
119         "uniform int gl_BaseVertex;\n"
120         "void main() {\n"
121         "   gl_Position = vec4(float(gl_BaseVertex), 0.0, 0.0, 1.0);\n"
122         "}\n",
123         "reserved built-in name");
124 
125     CheckCompileFailure(
126         "#version 300 es\n"
127         "uniform int gl_BaseInstance;\n"
128         "void main() {\n"
129         "   gl_Position = vec4(float(gl_BaseInstance), 0.0, 0.0, 1.0);\n"
130         "}\n",
131         "reserved built-in name");
132 
133     CheckCompileFailure(
134         "#version 300 es\n"
135         "void main() {\n"
136         "   int gl_BaseVertex = 0;\n"
137         "   gl_Position = vec4(float(gl_BaseVertex), 0.0, 0.0, 1.0);\n"
138         "}\n",
139         "reserved built-in name");
140 
141     CheckCompileFailure(
142         "#version 300 es\n"
143         "void main() {\n"
144         "   int gl_BaseInstance = 0;\n"
145         "   gl_Position = vec4(float(gl_BaseInstance), 0.0, 0.0, 1.0);\n"
146         "}\n",
147         "reserved built-in name");
148 
149     // Check that it is not permitted with the extension
150     CheckCompileFailure(
151         "#version 300 es\n"
152         "#extension GL_ANGLE_base_vertex_base_instance : require\n"
153         "uniform int gl_BaseVertex;\n"
154         "void main() {\n"
155         "   gl_Position = vec4(float(gl_BaseVertex), 0.0, 0.0, 1.0);\n"
156         "}\n",
157         "reserved built-in name");
158 
159     CheckCompileFailure(
160         "#version 300 es\n"
161         "#extension GL_ANGLE_base_vertex_base_instance : require\n"
162         "uniform int gl_BaseInstance;\n"
163         "void main() {\n"
164         "   gl_Position = vec4(float(gl_BaseInstance), 0.0, 0.0, 1.0);\n"
165         "}\n",
166         "reserved built-in name");
167 
168     CheckCompileFailure(
169         "#version 300 es\n"
170         "#extension GL_ANGLE_base_vertex_base_instance : require\n"
171         "void main() {\n"
172         "   int gl_BaseVertex = 0;\n"
173         "   gl_Position = vec4(float(gl_BaseVertex), 0.0, 0.0, 1.0);\n"
174         "}\n",
175         "reserved built-in name");
176 
177     CheckCompileFailure(
178         "#version 300 es\n"
179         "#extension GL_ANGLE_base_vertex_base_instance : require\n"
180         "void main() {\n"
181         "   int gl_BaseInstance = 0;\n"
182         "   gl_Position = vec4(float(gl_BaseInstance), 0.0, 0.0, 1.0);\n"
183         "}\n",
184         "reserved built-in name");
185 }
186 
187 // gl_BaseVertex and gl_BaseInstance are translated to angle_BaseVertex and angle_BaseInstance
188 // internally. Check that a user-defined angle_BaseVertex or angle_BaseInstance is permitted
TEST_F(EmulateGLBaseVertexBaseInstanceTest,AllowsUserDefinedANGLEDrawID)189 TEST_F(EmulateGLBaseVertexBaseInstanceTest, AllowsUserDefinedANGLEDrawID)
190 {
191     addOutputType(SH_GLSL_COMPATIBILITY_OUTPUT);
192     addOutputType(SH_ESSL_OUTPUT);
193 #ifdef ANGLE_ENABLE_VULKAN
194     addOutputType(SH_GLSL_VULKAN_OUTPUT);
195 #endif
196 #ifdef ANGLE_ENABLE_HLSL
197     addOutputType(SH_HLSL_3_0_OUTPUT);
198     addOutputType(SH_HLSL_3_0_OUTPUT);
199 #endif
200 
201     const std::string &shaderString =
202         "#version 300 es\n"
203         "#extension GL_ANGLE_base_vertex_base_instance : require\n"
204         "uniform int angle_BaseVertex;\n"
205         "uniform int angle_BaseInstance;\n"
206         "void main() {\n"
207         "   gl_Position = vec4(\n"
208         "           float(angle_BaseVertex + gl_BaseVertex),\n"
209         "           float(angle_BaseInstance + gl_BaseInstance),\n"
210         "           0.0, 1.0);\n"
211         "}\n";
212 
213     compile(shaderString, SH_OBJECT_CODE | SH_VARIABLES | SH_EMULATE_GL_BASE_VERTEX_BASE_INSTANCE);
214 
215     // " angle_BaseVertex" (note the space) should appear exactly twice:
216     //    once in the declaration and once in the body.
217     // The user-defined angle_BaseVertex should be decorated
218     EXPECT_TRUE(foundInCode(" angle_BaseVertex", 2));
219     EXPECT_TRUE(foundInCode(" angle_BaseInstance", 2));
220 }
221