xref: /aosp_15_r20/external/deqp/external/openglcts/modules/gl/gl4cGlSpirvTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*-------------------------------------------------------------------------
2  * OpenGL Conformance Test Suite
3  * -----------------------------
4  *
5  * Copyright (c) 2017 The Khronos Group Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  */ /*!
20  * \file
21  * \brief
22  */ /*-------------------------------------------------------------------*/
23 
24 /**
25  */ /*!
26  * \file  gl4cGlSpirvTests.cpp
27  * \brief Conformance tests for the GL_ARB_gl_spirv functionality.
28  */ /*-------------------------------------------------------------------*/
29 
30 #include "gl4cGlSpirvTests.hpp"
31 #include "deArrayUtil.hpp"
32 #include "deSingleton.h"
33 #include "deStringUtil.hpp"
34 #include "gluContextInfo.hpp"
35 #include "gluDefs.hpp"
36 #include "gluShaderProgram.hpp"
37 #include "gluStrUtil.hpp"
38 #include "glwEnums.hpp"
39 #include "glwFunctions.hpp"
40 #include "tcuRenderTarget.hpp"
41 #include "tcuResource.hpp"
42 #include "tcuTestLog.hpp"
43 
44 using namespace glu;
45 using namespace glw;
46 
47 namespace gl4cts
48 {
49 
50 namespace commonUtils
51 {
52 
writeSpirV(const char * filename,ShaderBinary binary)53 void writeSpirV(const char *filename, ShaderBinary binary)
54 {
55     FILE *file = fopen(filename, "wb");
56     if (file)
57     {
58         // As one binary could be associated with many shader objects it should be stored either a type of each shader
59         // This will be extended in the future
60         uint8_t count = (uint8_t)binary.shaderTypes.size();
61         fwrite((void *)&count, 1, 1, file);
62         for (int i = 0; i < (signed)binary.shaderTypes.size(); ++i)
63         {
64             fwrite((void *)&binary.shaderTypes[i], 1, sizeof(ShaderType), file);
65 
66             if (count > 1)
67             {
68                 uint8_t strLen = (uint8_t)binary.shaderEntryPoints[i].size();
69                 fwrite((void *)&strLen, 1, 1, file);
70                 fwrite((void *)binary.shaderEntryPoints[i].data(), 1, strLen, file);
71             }
72         }
73 
74         fwrite((void *)binary.binary.data(), 1, binary.binary.size() * 4, file);
75         fclose(file);
76     }
77 }
78 
readSpirV(tcu::Resource * resource)79 ShaderBinary readSpirV(tcu::Resource *resource)
80 {
81     ShaderBinary binary;
82     if (!resource)
83         return binary;
84 
85     // As one binary could be associated with many shader objects it should be stored either a type of each shader
86     uint8_t count;
87     resource->read(&count, 1);
88     binary.shaderTypes.resize(count);
89     binary.shaderEntryPoints.resize(count);
90     for (int i = 0; i < (signed)binary.shaderTypes.size(); ++i)
91     {
92         resource->read((uint8_t *)&binary.shaderTypes[i], sizeof(ShaderType));
93 
94         if (count > 1)
95         {
96             uint8_t strLen;
97             resource->read(&strLen, 1);
98 
99             binary.shaderEntryPoints[i].resize(strLen);
100             resource->read((uint8_t *)binary.shaderEntryPoints[i].data(), strLen);
101         }
102         else
103             binary.shaderEntryPoints[i] = "main";
104     }
105 
106     binary.binary.resize((resource->getSize() - resource->getPosition()) / sizeof(uint32_t));
107     resource->read((uint8_t *)binary.binary.data(), static_cast<uint32_t>(binary.binary.size()) * sizeof(uint32_t));
108 
109     return binary;
110 }
111 
112 /** Replace all occurance of <token> with <text> in <string>
113  *
114  * @param token           Token string
115  * @param text            String th at will be used as replacement for <token>
116  * @param string          String to work on
117  **/
replaceToken(const GLchar * token,const GLchar * text,std::string & string)118 void replaceToken(const GLchar *token, const GLchar *text, std::string &string)
119 {
120     const size_t text_length  = strlen(text);
121     const size_t token_length = strlen(token);
122 
123     size_t token_position;
124     while ((token_position = string.find(token, 0)) != std::string::npos)
125     {
126         string.replace(token_position, token_length, text, text_length);
127     }
128 }
129 
compareUintColors(const GLuint inColor,const GLuint refColor,const int epsilon)130 bool compareUintColors(const GLuint inColor, const GLuint refColor, const int epsilon)
131 {
132     int r1 = (inColor & 0xFF);
133     int g1 = ((inColor >> 8) & 0xFF);
134     int b1 = ((inColor >> 16) & 0xFF);
135     int a1 = ((inColor >> 24) & 0xFF);
136 
137     int r2 = (refColor & 0xFF);
138     int g2 = ((refColor >> 8) & 0xFF);
139     int b2 = ((refColor >> 16) & 0xFF);
140     int a2 = ((refColor >> 24) & 0xFF);
141 
142     if (r1 >= r2 - epsilon && r1 <= r2 + epsilon && g1 >= g2 - epsilon && g1 <= g2 + epsilon && b1 >= b2 - epsilon &&
143         b1 <= b2 + epsilon && a1 >= a2 - epsilon && a1 <= a2 + epsilon)
144     {
145         return true;
146     }
147 
148     return false;
149 }
150 
151 } // namespace commonUtils
152 
153 /** Constructor.
154  *
155  *  @param context     Rendering context
156  *  @param name        Test name
157  *  @param description Test description
158  */
SpirvModulesPositiveTest(deqp::Context & context)159 SpirvModulesPositiveTest::SpirvModulesPositiveTest(deqp::Context &context)
160     : TestCase(context, "spirv_modules_positive_test",
161                "Test verifies if using SPIR-V modules for each shader stage works as expected")
162 {
163     /* Left blank intentionally */
164 }
165 
166 /** Stub init method */
init()167 void SpirvModulesPositiveTest::init()
168 {
169     spirvUtils::checkGlSpirvSupported(m_context);
170 
171     m_vertex = "#version 450\n"
172                "\n"
173                "layout (location = 0) in vec3 position;\n"
174                "\n"
175                "layout (location = 1) out vec4 vColor;\n"
176                "\n"
177                "void main()\n"
178                "{\n"
179                "    gl_Position = vec4(position, 1.0);\n"
180                "    vColor = vec4(0.0, 0.0, 0.0, 1.0);\n"
181                "}\n";
182 
183     m_tesselationCtrl = "#version 450\n"
184                         "\n"
185                         "layout (vertices = 3) out;\n"
186                         "\n"
187                         "layout (location = 1) in vec4 vColor[];\n"
188                         "layout (location = 2) out vec4 tcColor[];\n"
189                         "\n"
190                         "void main()\n"
191                         "{\n"
192                         "    tcColor[gl_InvocationID] = vColor[gl_InvocationID];\n"
193                         "    tcColor[gl_InvocationID].r = 1.0;\n"
194                         "\n"
195                         "    if (gl_InvocationID == 0) {\n"
196                         "        gl_TessLevelOuter[0] = 1.0;\n"
197                         "        gl_TessLevelOuter[1] = 1.0;\n"
198                         "        gl_TessLevelOuter[2] = 1.0;\n"
199                         "        gl_TessLevelInner[0] = 1.0;\n"
200                         "    }\n"
201                         "\n"
202                         "    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
203                         "}\n";
204 
205     m_tesselationEval = "#version 450\n"
206                         "\n"
207                         "layout (triangles) in;\n"
208                         "\n"
209                         "layout (location = 2) in vec4 tcColor[];\n"
210                         "layout (location = 3) out vec4 teColor;\n"
211                         "\n"
212                         "void main()\n"
213                         "{\n"
214                         "    teColor = tcColor[0];\n"
215                         "    teColor.g = 1.0;\n"
216                         "\n"
217                         "    gl_Position = gl_TessCoord.x * gl_in[0].gl_Position +\n"
218                         "                  gl_TessCoord.y * gl_in[1].gl_Position +\n"
219                         "                  gl_TessCoord.z * gl_in[2].gl_Position;\n"
220                         "}\n";
221 
222     m_geometry = "#version 450\n"
223                  "\n"
224                  "layout (triangles) in;\n"
225                  "layout (triangle_strip, max_vertices = 3) out;\n"
226                  "\n"
227                  "layout (location = 3) in vec4 teColor[];\n"
228                  "layout (location = 4) out vec4 gColor;\n"
229                  "\n"
230                  "void main()\n"
231                  "{\n"
232                  "    gColor = teColor[0];\n"
233                  "    gColor.b = 1.0;\n"
234                  "\n"
235                  "    for (int i = 0; i < 3; ++i) {\n"
236                  "        gl_Position = gl_in[i].gl_Position;\n"
237                  "        EmitVertex();\n"
238                  "    }\n"
239                  "    EndPrimitive();\n"
240                  "}\n";
241 
242     m_fragment = "#version 450\n"
243                  "\n"
244                  "layout (location = 4) in vec4 gColor;\n"
245                  "layout (location = 0) out vec4 fColor;\n"
246                  "\n"
247                  "void main()\n"
248                  "{\n"
249                  "    fColor = gColor;\n"
250                  "}\n";
251 
252     const Functions &gl = m_context.getRenderContext().getFunctions();
253 
254     gl.genTextures(1, &m_texture);
255     GLU_EXPECT_NO_ERROR(gl.getError(), "genTextures");
256     gl.bindTexture(GL_TEXTURE_2D, m_texture);
257     GLU_EXPECT_NO_ERROR(gl.getError(), "bindTexture");
258     gl.texStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 32, 32);
259     GLU_EXPECT_NO_ERROR(gl.getError(), "texStorage2D");
260 
261     gl.genFramebuffers(1, &m_fbo);
262     GLU_EXPECT_NO_ERROR(gl.getError(), "genFramenuffers");
263     gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo);
264     GLU_EXPECT_NO_ERROR(gl.getError(), "bindFramebuffer");
265     gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture, 0);
266     GLU_EXPECT_NO_ERROR(gl.getError(), "framebufferTexture2D");
267 
268     gl.viewport(0, 0, 32, 32);
269     GLU_EXPECT_NO_ERROR(gl.getError(), "viewport");
270 }
271 
272 /** Stub de-init method */
deinit()273 void SpirvModulesPositiveTest::deinit()
274 {
275     if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gl_spirv"))
276         return;
277     const Functions &gl = m_context.getRenderContext().getFunctions();
278 
279     if (m_fbo)
280     {
281         gl.deleteFramebuffers(1, &m_fbo);
282         GLU_EXPECT_NO_ERROR(gl.getError(), "deleteFramebuffers");
283     }
284     if (m_texture)
285     {
286         gl.deleteTextures(1, &m_texture);
287         GLU_EXPECT_NO_ERROR(gl.getError(), "deleteTextures");
288     }
289 }
290 
291 /** Executes test iteration.
292  *
293  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
294  */
iterate()295 tcu::TestNode::IterateResult SpirvModulesPositiveTest::iterate()
296 {
297     const Functions &gl = m_context.getRenderContext().getFunctions();
298 
299     const GLfloat vertices[] = {-1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f};
300 
301     GLuint vao;
302     gl.genVertexArrays(1, &vao);
303     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays");
304     gl.bindVertexArray(vao);
305     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray");
306 
307     GLuint vbo;
308     gl.genBuffers(1, &vbo);
309     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers");
310     gl.bindBuffer(GL_ARRAY_BUFFER, vbo);
311     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer");
312 
313     gl.bufferData(GL_ARRAY_BUFFER, 9 * sizeof(GLfloat), (GLvoid *)vertices, GL_DYNAMIC_DRAW);
314     GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData");
315 
316     enum Iterates
317     {
318         ITERATE_GLSL,
319         ITERATE_SPIRV,
320         ITERATE_LAST
321     };
322 
323     uint32_t outputs[ITERATE_LAST];
324     for (int it = ITERATE_GLSL; it < ITERATE_LAST; ++it)
325     {
326         ShaderProgram *program = DE_NULL;
327         if (it == ITERATE_GLSL)
328         {
329             ProgramSources sources;
330             sources << VertexSource(m_vertex);
331             sources << TessellationControlSource(m_tesselationCtrl);
332             sources << TessellationEvaluationSource(m_tesselationEval);
333             sources << GeometrySource(m_geometry);
334             sources << FragmentSource(m_fragment);
335             program = new ShaderProgram(gl, sources);
336         }
337         else if (it == ITERATE_SPIRV)
338         {
339             ProgramBinaries binaries;
340             binaries << spirvUtils::makeSpirV(m_context.getTestContext().getLog(), VertexSource(m_vertex));
341             binaries << spirvUtils::makeSpirV(m_context.getTestContext().getLog(),
342                                               TessellationControlSource(m_tesselationCtrl));
343             binaries << spirvUtils::makeSpirV(m_context.getTestContext().getLog(),
344                                               TessellationEvaluationSource(m_tesselationEval));
345             binaries << spirvUtils::makeSpirV(m_context.getTestContext().getLog(), GeometrySource(m_geometry));
346             binaries << spirvUtils::makeSpirV(m_context.getTestContext().getLog(), FragmentSource(m_fragment));
347             program = new ShaderProgram(gl, binaries);
348         }
349 
350         if (!program->isOk())
351         {
352             m_testCtx.getLog() << tcu::TestLog::Message << "Shader build failed.\n"
353                                << "Vertex: " << program->getShaderInfo(SHADERTYPE_VERTEX).infoLog << "\n"
354                                << m_vertex << "\n"
355                                << "TesselationCtrl: " << program->getShaderInfo(SHADERTYPE_TESSELLATION_CONTROL).infoLog
356                                << "\n"
357                                << m_tesselationCtrl << "\n"
358                                << "TesselationEval: "
359                                << program->getShaderInfo(SHADERTYPE_TESSELLATION_EVALUATION).infoLog << "\n"
360                                << m_tesselationEval << "\n"
361                                << "Geometry: " << program->getShaderInfo(SHADERTYPE_GEOMETRY).infoLog << "\n"
362                                << m_geometry << "\n"
363                                << "Fragment: " << program->getShaderInfo(SHADERTYPE_FRAGMENT).infoLog << "\n"
364                                << m_fragment << "\n"
365                                << "Program: " << program->getProgramInfo().infoLog << tcu::TestLog::EndMessage;
366 
367             m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
368             return STOP;
369         }
370 
371         gl.useProgram(program->getProgram());
372         GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram");
373 
374         gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
375         GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor");
376         gl.clear(GL_COLOR_BUFFER_BIT);
377         GLU_EXPECT_NO_ERROR(gl.getError(), "glClear");
378 
379         gl.enableVertexAttribArray(0);
380         GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray");
381 
382         gl.vertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, DE_NULL);
383         GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer");
384 
385         gl.patchParameteri(GL_PATCH_VERTICES, 3);
386         gl.drawArrays(GL_PATCHES, 0, 3);
387         GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArray");
388 
389         gl.disableVertexAttribArray(0);
390         GLU_EXPECT_NO_ERROR(gl.getError(), "glDisableVertexAttribArray");
391 
392         gl.readPixels(16, 16, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid *)&outputs[it]);
393         GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels");
394 
395         if (program)
396             delete program;
397     }
398 
399     if (vbo)
400     {
401         gl.deleteBuffers(1, &vbo);
402         GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteBuffers");
403     }
404 
405     if (vao)
406     {
407         gl.deleteVertexArrays(1, &vao);
408         GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteVertexArrays");
409     }
410 
411     if ((outputs[ITERATE_GLSL] & outputs[ITERATE_SPIRV]) != 0xFFFFFFFF)
412     {
413         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
414         m_testCtx.getLog() << tcu::TestLog::Message << "Wrong output color read from framebuffer.\n"
415                            << "GLSL: " << outputs[ITERATE_GLSL] << ", SPIR-V: " << outputs[ITERATE_SPIRV]
416                            << "Expected: " << (uint32_t)0xFFFFFFFF << tcu::TestLog::EndMessage;
417         return STOP;
418     }
419 
420     m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
421     return STOP;
422 }
423 
424 /** Constructor.
425  *
426  *  @param context     Rendering context
427  *  @param name        Test name
428  *  @param description Test description
429  */
SpirvShaderBinaryMultipleShaderObjectsTest(deqp::Context & context)430 SpirvShaderBinaryMultipleShaderObjectsTest::SpirvShaderBinaryMultipleShaderObjectsTest(deqp::Context &context)
431     : TestCase(context, "spirv_modules_shader_binary_multiple_shader_objects_test",
432                "Test verifies if one binary module can be associated with multiple shader objects.")
433 {
434     /* Left blank intentionally */
435 }
436 
437 /** Stub init method */
init()438 void SpirvShaderBinaryMultipleShaderObjectsTest::init()
439 {
440     spirvUtils::checkGlSpirvSupported(m_context);
441 
442     m_spirv = "OpCapability Shader\n"
443               "%1 = OpExtInstImport \"GLSL.std.450\"\n"
444               "OpMemoryModel Logical GLSL450\n"
445               "OpEntryPoint Vertex %mainv \"mainv\" %_ %position %gl_VertexID %gl_InstanceID\n"
446               "OpEntryPoint Fragment %mainf \"mainf\" %fColor\n"
447               "OpExecutionMode %mainf OriginLowerLeft\n"
448               "OpSource GLSL 450\n"
449               "OpName %mainv \"mainv\"\n"
450               "OpName %mainf \"mainf\"\n"
451               "OpName %gl_PerVertex \"gl_PerVertex\"\n"
452               "OpMemberName %gl_PerVertex 0 \"gl_Position\"\n"
453               "OpMemberName %gl_PerVertex 1 \"gl_PointSize\"\n"
454               "OpMemberName %gl_PerVertex 2 \"gl_ClipDistance\"\n"
455               "OpMemberName %gl_PerVertex 3 \"gl_CullDistance\"\n"
456               "OpName %_ \"\"\n"
457               "OpName %position \"position\"\n"
458               "OpName %gl_VertexID \"gl_VertexID\"\n"
459               "OpName %gl_InstanceID \"gl_InstanceID\"\n"
460               "OpMemberDecorate %gl_PerVertex 0 BuiltIn Position\n"
461               "OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize\n"
462               "OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance\n"
463               "OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance\n"
464               "OpDecorate %gl_PerVertex Block\n"
465               "OpDecorate %position Location 0\n"
466               "OpDecorate %gl_VertexID BuiltIn VertexId\n"
467               "OpDecorate %gl_InstanceID BuiltIn InstanceId\n"
468               "OpDecorate %fColor Location 0\n"
469               "%void = OpTypeVoid\n"
470               "%3 = OpTypeFunction %void\n"
471               "%float = OpTypeFloat 32\n"
472               "%v4float = OpTypeVector %float 4\n"
473               "%uint = OpTypeInt 32 0\n"
474               "%uint_1 = OpConstant %uint 1\n"
475               "%_arr_float_uint_1 = OpTypeArray %float %uint_1\n"
476               "%gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1\n"
477               "%_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex\n"
478               "%_ = OpVariable %_ptr_Output_gl_PerVertex Output\n"
479               "%int = OpTypeInt 32 1\n"
480               "%int_0 = OpConstant %int 0\n"
481               "%v3float = OpTypeVector %float 3\n"
482               "%_ptr_Input_v3float = OpTypePointer Input %v3float\n"
483               "%position = OpVariable %_ptr_Input_v3float Input\n"
484               "%float_1 = OpConstant %float 1\n"
485               "%_ptr_Output_v4float = OpTypePointer Output %v4float\n"
486               "%_ptr_Input_int = OpTypePointer Input %int\n"
487               "%gl_VertexID = OpVariable %_ptr_Input_int Input\n"
488               "%gl_InstanceID = OpVariable %_ptr_Input_int Input\n"
489               "%fColor = OpVariable %_ptr_Output_v4float Output\n"
490               "%fVec4_1 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1\n"
491               "\n"
492               "%mainv = OpFunction %void None %3\n"
493               "%5 = OpLabel\n"
494               "%19 = OpLoad %v3float %position\n"
495               "%21 = OpCompositeExtract %float %19 0\n"
496               "%22 = OpCompositeExtract %float %19 1\n"
497               "%23 = OpCompositeExtract %float %19 2\n"
498               "%24 = OpCompositeConstruct %v4float %21 %22 %23 %float_1\n"
499               "%26 = OpAccessChain %_ptr_Output_v4float %_ %int_0\n"
500               "OpStore %26 %24\n"
501               "OpReturn\n"
502               "OpFunctionEnd\n"
503               "\n"
504               "%mainf = OpFunction %void None %3\n"
505               "%32 = OpLabel\n"
506               "OpStore %fColor %fVec4_1\n"
507               "OpReturn\n"
508               "OpFunctionEnd\n";
509 }
510 
511 /** Stub init method */
deinit()512 void SpirvShaderBinaryMultipleShaderObjectsTest::deinit()
513 {
514 }
515 
516 /** Executes test iteration.
517  *
518  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
519  */
iterate()520 tcu::TestNode::IterateResult SpirvShaderBinaryMultipleShaderObjectsTest::iterate()
521 {
522     const Functions &gl = m_context.getRenderContext().getFunctions();
523 
524     const GLfloat vertices[] = {-1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f};
525 
526     GLuint texture;
527     GLuint fbo;
528 
529     gl.genTextures(1, &texture);
530     GLU_EXPECT_NO_ERROR(gl.getError(), "genTextures");
531     gl.bindTexture(GL_TEXTURE_2D, texture);
532     GLU_EXPECT_NO_ERROR(gl.getError(), "bindTexture");
533     gl.texStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 32, 32);
534     GLU_EXPECT_NO_ERROR(gl.getError(), "texStorage2D");
535 
536     gl.genFramebuffers(1, &fbo);
537     GLU_EXPECT_NO_ERROR(gl.getError(), "genFramenuffers");
538     gl.bindFramebuffer(GL_FRAMEBUFFER, fbo);
539     GLU_EXPECT_NO_ERROR(gl.getError(), "bindFramebuffer");
540     gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
541     GLU_EXPECT_NO_ERROR(gl.getError(), "framebufferTexture2D");
542 
543     GLuint vao;
544     gl.genVertexArrays(1, &vao);
545     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays");
546     gl.bindVertexArray(vao);
547     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray");
548 
549     GLuint vbo;
550     gl.genBuffers(1, &vbo);
551     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers");
552     gl.bindBuffer(GL_ARRAY_BUFFER, vbo);
553     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer");
554 
555     gl.bufferData(GL_ARRAY_BUFFER, 9 * sizeof(GLfloat), (GLvoid *)vertices, GL_DYNAMIC_DRAW);
556     GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData");
557 
558     ShaderBinary binary;
559     binary << SHADERTYPE_VERTEX << "mainv";
560     binary << SHADERTYPE_FRAGMENT << "mainf";
561 
562     spirvUtils::spirvAssemble(binary.binary, m_spirv);
563     spirvUtils::spirvValidate(binary.binary, true);
564 
565     ProgramBinaries binaries;
566     binaries << binary;
567     ShaderProgram program(gl, binaries);
568 
569     if (!program.isOk())
570     {
571         m_testCtx.getLog() << tcu::TestLog::Message << "Shader build failed.\n"
572                            << "Vertex: " << program.getShaderInfo(SHADERTYPE_VERTEX).infoLog << "\n"
573                            << "Fragment: " << program.getShaderInfo(SHADERTYPE_FRAGMENT).infoLog << "\n"
574                            << "Program: " << program.getProgramInfo().infoLog << tcu::TestLog::EndMessage;
575 
576         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
577         return STOP;
578     }
579 
580     gl.viewport(0, 0, 32, 32);
581     GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport");
582 
583     gl.useProgram(program.getProgram());
584     GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram");
585 
586     gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
587     GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor");
588     gl.clear(GL_COLOR_BUFFER_BIT);
589     GLU_EXPECT_NO_ERROR(gl.getError(), "glClear");
590 
591     gl.enableVertexAttribArray(0);
592     GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray");
593 
594     gl.vertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, DE_NULL);
595     GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer");
596 
597     gl.drawArrays(GL_TRIANGLE_STRIP, 0, 3);
598     GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArray");
599 
600     gl.disableVertexAttribArray(0);
601     GLU_EXPECT_NO_ERROR(gl.getError(), "glDisableVertexAttribArray");
602 
603     GLuint insidePixel;
604     GLuint outsidePixel;
605     gl.readPixels(16, 16, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid *)&insidePixel);
606     GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels");
607     gl.readPixels(2, 30, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid *)&outsidePixel);
608     GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels");
609 
610     if (vbo)
611     {
612         gl.deleteBuffers(1, &vbo);
613         GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteBuffers");
614     }
615 
616     if (vao)
617     {
618         gl.deleteVertexArrays(1, &vao);
619         GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteVertexArrays");
620     }
621 
622     if (fbo)
623     {
624         gl.deleteFramebuffers(1, &fbo);
625         GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteFramebuffers");
626     }
627 
628     if (texture)
629     {
630         gl.deleteTextures(1, &texture);
631         GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteTextures");
632     }
633 
634     if (insidePixel == 0xFFFFFFFF && outsidePixel == 0xFF000000)
635         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
636     else
637     {
638         m_testCtx.getLog() << tcu::TestLog::Message << "Wrong pixels color read.\n"
639                            << "Expected (inside/outside): " << 0xFFFFFFFF << "/" << 0xFF000000 << "\n"
640                            << "Read: " << insidePixel << "/" << outsidePixel << tcu::TestLog::EndMessage;
641 
642         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
643     }
644 
645     return STOP;
646 }
647 
648 /** Constructor.
649  *
650  *  @param context     Rendering context
651  *  @param name        Test name
652  *  @param description Test description
653  */
SpirvModulesStateQueriesTest(deqp::Context & context)654 SpirvModulesStateQueriesTest::SpirvModulesStateQueriesTest(deqp::Context &context)
655     : TestCase(context, "spirv_modules_state_queries_test",
656                "Test verifies if state queries for new features added by ARB_gl_spirv works as expected.")
657 {
658     /* Left blank intentionally */
659 }
660 
661 /** Stub init method */
init()662 void SpirvModulesStateQueriesTest::init()
663 {
664     spirvUtils::checkGlSpirvSupported(m_context);
665 
666     m_vertex = "#version 450\n"
667                "\n"
668                "layout (location = 0) in vec4 position;\n"
669                "layout (location = 20) uniform vec4 extPosition;\n"
670                "layout (binding = 5) uniform ComponentsBlock\n"
671                "{\n"
672                "    vec4 c1;\n"
673                "    vec2 c2;\n"
674                "} components;\n"
675                "layout (xfb_buffer = 0, xfb_offset = 16) out gl_PerVertex\n"
676                "{\n"
677                "    vec4 gl_Position;\n"
678                "};\n"
679                "\n"
680                "void main()\n"
681                "{\n"
682                "    gl_Position = position + extPosition + components.c1 + vec4(components.c2, 0.0, 0.0);\n"
683                "}\n";
684 }
685 
686 /** Stub de-init method */
deinit()687 void SpirvModulesStateQueriesTest::deinit()
688 {
689 }
690 
691 /** Executes test iteration.
692  *
693  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
694  */
iterate()695 tcu::TestNode::IterateResult SpirvModulesStateQueriesTest::iterate()
696 {
697     const Functions &gl = m_context.getRenderContext().getFunctions();
698 
699     ProgramBinaries binaries;
700     ShaderBinary vertexBinary;
701 
702     {
703         vertexBinary = spirvUtils::makeSpirV(m_context.getTestContext().getLog(), VertexSource(m_vertex));
704 
705         // Disassemble Spir-V module
706         std::string output;
707         spirvUtils::spirvDisassemble(output, vertexBinary.binary);
708 
709         // Remove name reflection for defined variables
710         std::vector<std::string> lines = de::splitString(output, '\n');
711         std::string input;
712         for (int i = 0; i < (signed)lines.size(); ++i)
713         {
714             if (lines[i].find("OpName") != std::string::npos)
715                 continue;
716 
717             if (lines[i].find("OpMemberName") != std::string::npos)
718                 continue;
719 
720             input.append(lines[i] + "\n");
721         }
722 
723         // Assemble Spir-V module
724         vertexBinary.binary.clear();
725         spirvUtils::spirvAssemble(vertexBinary.binary, input);
726         spirvUtils::spirvValidate(vertexBinary.binary, true);
727     }
728 
729     binaries << vertexBinary;
730     ShaderProgram program(gl, binaries);
731 
732     Shader *shader = program.getShader(SHADERTYPE_VERTEX);
733 
734     // 1) Check compile status
735     if (!program.getShaderInfo(SHADERTYPE_VERTEX).compileOk)
736     {
737         m_testCtx.getLog() << tcu::TestLog::Message << "Check compile status failed.\n"
738                            << "Vertex: " << program.getShaderInfo(SHADERTYPE_VERTEX).infoLog << "\n"
739                            << m_vertex << "\n"
740                            << "Program: " << program.getProgramInfo().infoLog << tcu::TestLog::EndMessage;
741 
742         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
743         return STOP;
744     }
745 
746     // 2) Check if SPIR_V_BINARY_ARB state is TRUE
747     GLint shaderState;
748     gl.getShaderiv(shader->getShader(), GL_SPIR_V_BINARY_ARB, &shaderState);
749     GLU_EXPECT_NO_ERROR(gl.getError(), "getShaderiv");
750     if (shaderState != GL_TRUE)
751     {
752         m_testCtx.getLog() << tcu::TestLog::Message << "SPIR_V_BINARY_ARB state set to FALSE. Expected TRUE."
753                            << tcu::TestLog::EndMessage;
754 
755         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
756         return STOP;
757     }
758 
759     // 3) Check if queries for ACTIVE_ATTRIBUTE_MAX_LENGTH, ACTIVE_UNIFORM_MAX_LENGTH,
760     //    ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH and TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH return
761     //    value equal to 1
762     GLint programState[4];
763     GLint expectedValues[4] = {1, 1, 1, 1};
764     gl.getProgramiv(program.getProgram(), GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &programState[0]);
765     GLU_EXPECT_NO_ERROR(gl.getError(), "getProgramiv");
766 
767     gl.getProgramiv(program.getProgram(), GL_ACTIVE_UNIFORM_MAX_LENGTH, &programState[1]);
768     GLU_EXPECT_NO_ERROR(gl.getError(), "getProgramiv");
769 
770     gl.getProgramiv(program.getProgram(), GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH, &programState[2]);
771     GLU_EXPECT_NO_ERROR(gl.getError(), "getProgramiv");
772 
773     gl.getProgramiv(program.getProgram(), GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &programState[3]);
774     GLU_EXPECT_NO_ERROR(gl.getError(), "getProgramiv");
775 
776     bool programStateResult = true;
777     for (int i = 0; i < 4; ++i)
778     {
779         if (programState[i] != expectedValues[i])
780         {
781             m_testCtx.getLog() << tcu::TestLog::Message << "Check max name length [" << i << "] failed. "
782                                << "Expected: " << expectedValues[i] << ", Queried: " << programState[i] << "\n"
783                                << tcu::TestLog::EndMessage;
784             programStateResult = false;
785         }
786     }
787 
788     if (!programStateResult)
789     {
790         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
791         return STOP;
792     }
793 
794     // 4) Check if ShaderSource command usage on Spir-V binary shader will change SPIR_V_BINARY_ARB state to FALSE
795     const char *source = m_vertex.c_str();
796     const int length   = static_cast<int>(m_vertex.length());
797     gl.shaderSource(shader->getShader(), 1, &source, &length);
798     GLU_EXPECT_NO_ERROR(gl.getError(), "shaderSource");
799 
800     gl.getShaderiv(shader->getShader(), GL_SPIR_V_BINARY_ARB, &shaderState);
801     GLU_EXPECT_NO_ERROR(gl.getError(), "getShaderiv");
802     if (shaderState != GL_FALSE)
803     {
804         m_testCtx.getLog() << tcu::TestLog::Message << "SPIR_V_BINARY_ARB state set to TRUE. Expected FALSE."
805                            << tcu::TestLog::EndMessage;
806 
807         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
808         return STOP;
809     }
810 
811     m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
812     return STOP;
813 }
814 
815 /** Constructor.
816  *
817  *  @param context     Rendering context
818  *  @param name        Test name
819  *  @param description Test description
820  */
SpirvModulesErrorVerificationTest(deqp::Context & context)821 SpirvModulesErrorVerificationTest::SpirvModulesErrorVerificationTest(deqp::Context &context)
822     : TestCase(context, "spirv_modules_error_verification_test",
823                "Test verifies if new features added by ARB_gl_spirv generate error messages as expected.")
824 {
825     /* Left blank intentionally */
826 }
827 
828 /** Stub init method */
init()829 void SpirvModulesErrorVerificationTest::init()
830 {
831     spirvUtils::checkGlSpirvSupported(m_context);
832 
833     const Functions &gl = m_context.getRenderContext().getFunctions();
834 
835     m_vertex = "#version 450\n"
836                "\n"
837                "layout (location = 0) in vec4 position;\n"
838                "\n"
839                "void main()\n"
840                "{\n"
841                "    gl_Position = position;\n"
842                "}\n";
843 
844     m_glslShaderId = gl.createShader(GL_VERTEX_SHADER);
845     GLU_EXPECT_NO_ERROR(gl.getError(), "createShader");
846 
847     m_spirvShaderId = gl.createShader(GL_VERTEX_SHADER);
848     GLU_EXPECT_NO_ERROR(gl.getError(), "createShader");
849 
850     m_programId = gl.createProgram();
851     GLU_EXPECT_NO_ERROR(gl.getError(), "createProgram");
852 
853     gl.genTextures(1, &m_textureId);
854     GLU_EXPECT_NO_ERROR(gl.getError(), "genTextures");
855 }
856 
857 /** Stub de-init method */
deinit()858 void SpirvModulesErrorVerificationTest::deinit()
859 {
860     if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gl_spirv"))
861         return;
862 
863     const Functions &gl = m_context.getRenderContext().getFunctions();
864 
865     gl.deleteTextures(1, &m_textureId);
866     GLU_EXPECT_NO_ERROR(gl.getError(), "deleteTextures");
867 
868     gl.deleteProgram(m_programId);
869     GLU_EXPECT_NO_ERROR(gl.getError(), "deleteProgram");
870 
871     gl.deleteShader(m_glslShaderId);
872     GLU_EXPECT_NO_ERROR(gl.getError(), "deleteShader");
873 
874     gl.deleteShader(m_spirvShaderId);
875     GLU_EXPECT_NO_ERROR(gl.getError(), "deleteShader");
876 }
877 
878 /** Executes test iteration.
879  *
880  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
881  */
iterate()882 tcu::TestNode::IterateResult SpirvModulesErrorVerificationTest::iterate()
883 {
884     const Functions &gl = m_context.getRenderContext().getFunctions();
885 
886     const char *shaderSrc = m_vertex.c_str();
887     const int shaderLen   = static_cast<int>(m_vertex.length());
888 
889     ShaderBinary vertexBinary;
890 
891     vertexBinary = spirvUtils::makeSpirV(m_context.getTestContext().getLog(), VertexSource(m_vertex));
892 
893     gl.shaderSource(m_glslShaderId, 1, &shaderSrc, &shaderLen);
894     GLU_EXPECT_NO_ERROR(gl.getError(), "shaderSource");
895 
896     gl.shaderBinary(1, &m_spirvShaderId, GL_SHADER_BINARY_FORMAT_SPIR_V_ARB, (GLvoid *)vertexBinary.binary.data(),
897                     static_cast<uint32_t>(vertexBinary.binary.size()) * sizeof(uint32_t));
898     GLU_EXPECT_NO_ERROR(gl.getError(), "shaderBinary");
899 
900     gl.attachShader(m_programId, m_spirvShaderId);
901     GLU_EXPECT_NO_ERROR(gl.getError(), "attachShader");
902 
903     GLint err;
904 
905     // 1) Verify if CompileShader function used on shader with SPIR_V_BINARY_ARB state
906     //    will result in generating INVALID_OPERATION error.
907     gl.compileShader(m_spirvShaderId);
908     err = gl.getError();
909     if (err != GL_INVALID_OPERATION)
910     {
911         m_testCtx.getLog()
912             << tcu::TestLog::Message
913             << "Unexpected error code generated by CompileShader [1]. Expected INVALID_OPERATION, generated: "
914             << glu::getErrorName(err) << tcu::TestLog::EndMessage;
915 
916         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
917         return STOP;
918     }
919 
920     // 2) Verify if SpecializeShader function generate INVALID_VALUE error when
921     //    <shader> is not the name of either a program or shader object.
922     gl.specializeShader(0xFFFF, "main", 0, DE_NULL, DE_NULL);
923     err = gl.getError();
924     if (err != GL_INVALID_VALUE)
925     {
926         m_testCtx.getLog()
927             << tcu::TestLog::Message
928             << "Unexpected error code generated by SpecializeShader [2]. Expected INVALID_VALUE, generated: "
929             << glu::getErrorName(err) << tcu::TestLog::EndMessage;
930 
931         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
932         return STOP;
933     }
934 
935     // 3) Verify if SpecializeShader function generate INVALID_OPERATION error when
936     //    <shader> is the name of a program object.
937     gl.specializeShader(m_programId, "main", 0, DE_NULL, DE_NULL);
938     err = gl.getError();
939     if (err != GL_INVALID_OPERATION)
940     {
941         m_testCtx.getLog()
942             << tcu::TestLog::Message
943             << "Unexpected error code generated by SpecializeShader [3]. Expected INVALID_OPERATION, generated: "
944             << glu::getErrorName(err) << tcu::TestLog::EndMessage;
945 
946         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
947         return STOP;
948     }
949 
950     // 4) Verify if SpecializeShader function generate INVALID_OPERATION error when
951     //    SPIR_V_BINARY_ARB state for <shader> is not TRUE.
952     gl.specializeShader(m_glslShaderId, "main", 0, DE_NULL, DE_NULL);
953     err = gl.getError();
954     if (err != GL_INVALID_OPERATION)
955     {
956         m_testCtx.getLog()
957             << tcu::TestLog::Message
958             << "Unexpected error code generated by SpecializeShader [4]. Expected INVALID_OPERATION, generated: "
959             << glu::getErrorName(err) << tcu::TestLog::EndMessage;
960 
961         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
962         return STOP;
963     }
964 
965     // 5) Verify if SpecializeShader function generate INVALID_VALUE when <pEntryPoint>
966     //    does not name a valid entry point for <shader>.
967     gl.specializeShader(m_spirvShaderId, "entry", 0, DE_NULL, DE_NULL);
968     err = gl.getError();
969     if (err != GL_INVALID_VALUE)
970     {
971         m_testCtx.getLog()
972             << tcu::TestLog::Message
973             << "Unexpected error code generated by SpecializeShader [5]. Expected INVALID_VALUE, generated: "
974             << glu::getErrorName(err) << tcu::TestLog::EndMessage;
975 
976         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
977         return STOP;
978     }
979 
980     // 6) Verify if SpecializeShader function generate INVALID_VALUE when any element
981     //    of <pConstantIndex> refers to a specialization constant that does not exist
982     //    in the shader module contained in <shader>.
983     const GLuint specID    = 10;
984     const GLuint specValue = 10;
985     gl.specializeShader(m_spirvShaderId, "main", 1, &specID, &specValue);
986     err = gl.getError();
987     if (err != GL_INVALID_VALUE)
988     {
989         m_testCtx.getLog()
990             << tcu::TestLog::Message
991             << "Unexpected error code generated by SpecializeShader [6]. Expected INVALID_VALUE, generated: "
992             << glu::getErrorName(err) << tcu::TestLog::EndMessage;
993 
994         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
995         return STOP;
996     }
997 
998     // 7) Verify if LinkProgram fail when one or more of the shader objects attached to
999     //    <program> are not specialized.
1000     gl.linkProgram(m_programId);
1001     err = gl.getError();
1002     if (err == GL_NO_ERROR)
1003     {
1004         GLint linkStatus;
1005         gl.getProgramiv(m_programId, GL_LINK_STATUS, &linkStatus);
1006         GLU_EXPECT_NO_ERROR(gl.getError(), "getProgramiv");
1007 
1008         if (linkStatus != 0)
1009         {
1010             m_testCtx.getLog() << tcu::TestLog::Message << "Unexpected result of LinkProgram [7]."
1011                                << tcu::TestLog::EndMessage;
1012 
1013             m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1014             return STOP;
1015         }
1016     }
1017 
1018     // 8) Verify if SpecializeShader function generate INVALID_OPERATION error if the
1019     //    shader has already been specialized.
1020     gl.specializeShader(m_spirvShaderId, "main", 0, DE_NULL, DE_NULL);
1021     GLU_EXPECT_NO_ERROR(gl.getError(), "specializeShader");
1022 
1023     gl.specializeShader(m_spirvShaderId, "main", 0, DE_NULL, DE_NULL);
1024     err = gl.getError();
1025     if (err != GL_INVALID_OPERATION)
1026     {
1027         m_testCtx.getLog()
1028             << tcu::TestLog::Message
1029             << "Unexpected error code generated by SpecializeShader [8]. Expected INVALID_OPERATION, generated: "
1030             << glu::getErrorName(err) << tcu::TestLog::EndMessage;
1031 
1032         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1033         return STOP;
1034     }
1035 
1036     // 9) Verify if LinkProgram fail when not all of shaders attached to <program> have
1037     //    the same value for the SPIR_V_BINARY_ARB state.
1038     gl.compileShader(m_glslShaderId);
1039     GLU_EXPECT_NO_ERROR(gl.getError(), "compileShader");
1040 
1041     gl.attachShader(m_programId, m_glslShaderId);
1042     GLU_EXPECT_NO_ERROR(gl.getError(), "attachShader");
1043 
1044     gl.linkProgram(m_programId);
1045     err = gl.getError();
1046     if (err == GL_NO_ERROR)
1047     {
1048         GLint linkStatus;
1049         gl.getProgramiv(m_programId, GL_LINK_STATUS, &linkStatus);
1050         GLU_EXPECT_NO_ERROR(gl.getError(), "getProgramiv");
1051 
1052         if (linkStatus != 0)
1053         {
1054             m_testCtx.getLog() << tcu::TestLog::Message << "Unexpected result of LinkProgram [9]."
1055                                << tcu::TestLog::EndMessage;
1056 
1057             m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1058             return STOP;
1059         }
1060     }
1061 
1062     m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1063     return STOP;
1064 }
1065 
1066 /** Constructor.
1067  *
1068  *  @param context     Rendering context
1069  *  @param name        Test name
1070  *  @param description Test description
1071  */
SpirvGlslToSpirVEnableTest(deqp::Context & context)1072 SpirvGlslToSpirVEnableTest::SpirvGlslToSpirVEnableTest(deqp::Context &context)
1073     : TestCase(context, "spirv_glsl_to_spirv_enable_test", "Test verifies if glsl supports Spir-V features.")
1074 {
1075     /* Left blank intentionally */
1076 }
1077 
1078 /** Stub init method */
init()1079 void SpirvGlslToSpirVEnableTest::init()
1080 {
1081     spirvUtils::checkGlSpirvSupported(m_context);
1082 
1083     m_vertex = "#version 450\n"
1084                "\n"
1085                "#ifdef GL_SPIRV\n"
1086                "  layout (location = 0) in vec4 enabled;\n"
1087                "#else\n"
1088                "  layout (location = 0) in vec4 notEnabled;\n"
1089                "#endif // GL_SPIRV\n"
1090                "\n"
1091                "void main()\n"
1092                "{\n"
1093                "    gl_Position = vec4(0.0, 0.0, 0.0, 0.0);\n"
1094                "}\n";
1095 }
1096 
1097 /** Stub de-init method */
deinit()1098 void SpirvGlslToSpirVEnableTest::deinit()
1099 {
1100 }
1101 
1102 /** Executes test iteration.
1103  *
1104  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
1105  */
iterate()1106 tcu::TestNode::IterateResult SpirvGlslToSpirVEnableTest::iterate()
1107 {
1108 
1109     {
1110         const Functions &gl = m_context.getRenderContext().getFunctions();
1111 
1112         ProgramBinaries binaries;
1113         ShaderBinary vertexBinary = spirvUtils::makeSpirV(m_context.getTestContext().getLog(), VertexSource(m_vertex));
1114         binaries << vertexBinary;
1115         ShaderProgram spirvProgram(gl, binaries);
1116 
1117         std::string spirvSource;
1118         spirvUtils::spirvDisassemble(spirvSource, vertexBinary.binary);
1119 
1120         if (spirvSource.find("OpName %enabled") == std::string::npos)
1121         {
1122             m_testCtx.getLog() << tcu::TestLog::Message << "GL_SPIRV not defined. Spir-V source:\n"
1123                                << spirvSource.c_str() << tcu::TestLog::EndMessage;
1124 
1125             m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1126             return STOP;
1127         }
1128 
1129         if (!spirvProgram.isOk())
1130         {
1131             m_testCtx.getLog() << tcu::TestLog::Message << "Shader compilation failed. Source:\n"
1132                                << spirvSource.c_str() << "InfoLog:\n"
1133                                << spirvProgram.getShaderInfo(SHADERTYPE_VERTEX).infoLog << "\n"
1134                                << tcu::TestLog::EndMessage;
1135 
1136             m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1137             return STOP;
1138         }
1139 
1140         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1141     }
1142 
1143     return STOP;
1144 }
1145 
1146 enum EShaderTemplate
1147 {
1148     COMPUTE_TEMPLATE,
1149     TESSCTRL_TEMPLATE,
1150     GEOMETRY_TEMPLATE,
1151     FRAGMENT_TEMPLATE
1152 };
1153 
1154 struct FunctionMapping
1155 {
1156     EShaderTemplate shaderTemplate;
1157     std::string glslFunc;
1158     std::string glslArgs;
1159     std::string spirVFunc;
1160 
FunctionMappinggl4cts::FunctionMapping1161     FunctionMapping() : shaderTemplate(COMPUTE_TEMPLATE), glslFunc(""), glslArgs(""), spirVFunc("")
1162     {
1163     }
1164 
FunctionMappinggl4cts::FunctionMapping1165     FunctionMapping(EShaderTemplate shaderTemplate_, std::string glslFunc_, std::string glslArgs_,
1166                     std::string spirVFunc_)
1167         : shaderTemplate(shaderTemplate_)
1168         , glslFunc(glslFunc_)
1169         , glslArgs(glslArgs_)
1170         , spirVFunc(spirVFunc_)
1171     {
1172     }
1173 };
1174 
1175 /** Constructor.
1176  *
1177  *  @param context     Rendering context
1178  *  @param name        Test name
1179  *  @param description Test description
1180  */
SpirvGlslToSpirVBuiltInFunctionsTest(deqp::Context & context)1181 SpirvGlslToSpirVBuiltInFunctionsTest::SpirvGlslToSpirVBuiltInFunctionsTest(deqp::Context &context)
1182     : TestCase(context, "spirv_glsl_to_spirv_builtin_functions_test",
1183                "Test verifies if GLSL built-in functions are supported by Spir-V.")
1184 {
1185     /* Left blank intentionally */
1186 }
1187 
1188 /** Stub init method */
init()1189 void SpirvGlslToSpirVBuiltInFunctionsTest::init()
1190 {
1191     spirvUtils::checkGlSpirvSupported(m_context);
1192 
1193     initMappings();
1194 
1195     m_commonVertex = "#version 450\n"
1196                      "\n"
1197                      "layout (location = 0) in vec3 position;\n"
1198                      "layout (location = 1) out vec2 texCoord;\n"
1199                      "\n"
1200                      "void main()\n"
1201                      "{\n"
1202                      "    texCoord = vec2(0.0, 0.0);\n"
1203                      "    gl_Position = vec4(position, 1.0);\n"
1204                      "}\n";
1205 
1206     m_commonTessEval = "#version 450\n"
1207                        "\n"
1208                        "layout (triangles) in;\n"
1209                        "\n"
1210                        "void main()\n"
1211                        "{\n"
1212                        "    gl_Position = gl_TessCoord.x * gl_in[0].gl_Position +\n"
1213                        "                  gl_TessCoord.y * gl_in[1].gl_Position +\n"
1214                        "                  gl_TessCoord.z * gl_in[2].gl_Position;\n"
1215                        "}\n";
1216 
1217     m_sources.clear();
1218 
1219     // Angle Trigonometry
1220     m_sources.push_back(ComputeSource("#version 450\n"
1221                                       "\n"
1222                                       "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
1223                                       "\n"
1224                                       "void main()\n"
1225                                       "{\n"
1226                                       "    float tmp0 = 0.5;\n"
1227                                       "    float value;\n"
1228                                       "    value = radians(tmp0) +\n"
1229                                       "            degrees(tmp0) +\n"
1230                                       "            sin(tmp0) +\n"
1231                                       "            cos(tmp0) +\n"
1232                                       "            tan(tmp0) +\n"
1233                                       "            asin(tmp0) +\n"
1234                                       "            acos(tmp0) +\n"
1235                                       "            atan(tmp0) +\n"
1236                                       "            atan(tmp0) +\n"
1237                                       "            sinh(tmp0) +\n"
1238                                       "            cosh(tmp0) +\n"
1239                                       "            tanh(tmp0) +\n"
1240                                       "            asinh(tmp0) +\n"
1241                                       "            acosh(tmp0) +\n"
1242                                       "            atanh(tmp0);\n"
1243                                       "}\n"));
1244 
1245     // To avoid duplicated mappings create additional shaders for specific functions
1246     const std::string strAnlgeVariants = "#version 450\n"
1247                                          "\n"
1248                                          "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
1249                                          "\n"
1250                                          "void main()\n"
1251                                          "{\n"
1252                                          "    float tmp0 = 0.5;\n"
1253                                          "    float value = <ATANGENT>;\n"
1254                                          "}\n";
1255     std::string strATan                = strAnlgeVariants;
1256     std::string strATan2               = strAnlgeVariants;
1257     commonUtils::replaceToken("<ATANGENT>", "atan(tmp0, tmp0)", strATan);
1258     commonUtils::replaceToken("<ATANGENT>", "atan(tmp0)", strATan2);
1259 
1260     m_sources.push_back(ComputeSource(strATan));
1261     m_sources.push_back(ComputeSource(strATan2));
1262 
1263     // Exponential
1264     m_sources.push_back(ComputeSource("#version 450\n"
1265                                       "\n"
1266                                       "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
1267                                       "\n"
1268                                       "void main()\n"
1269                                       "{\n"
1270                                       "    float tmp0;\n"
1271                                       "    float tmp1;\n"
1272                                       "    float value;\n"
1273                                       "    value = pow(tmp1, tmp0) +\n"
1274                                       "            exp(tmp0) +\n"
1275                                       "            log(tmp1) +\n"
1276                                       "            exp2(tmp0) +\n"
1277                                       "            log2(tmp1) +\n"
1278                                       "            sqrt(tmp1) +\n"
1279                                       "            inversesqrt(tmp1);\n"
1280                                       "}\n"));
1281 
1282     // Common (without bit operations)
1283     m_sources.push_back(ComputeSource("#version 450\n"
1284                                       "\n"
1285                                       "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
1286                                       "\n"
1287                                       "void main()\n"
1288                                       "{\n"
1289                                       "    float value;\n"
1290                                       "    float outval;\n"
1291                                       "    float fpval = 0.5;\n"
1292                                       "    float fnval = -0.5;\n"
1293                                       "    int ival = 0x43800000;\n"
1294                                       "    uint uival= 0xC3800000;\n"
1295                                       "    value = abs(fnval) +\n"
1296                                       "            sign(fpval) +\n"
1297                                       "            floor(fpval) +\n"
1298                                       "            trunc(fpval) +\n"
1299                                       "            round(fpval) +\n"
1300                                       "            roundEven(fpval) +\n"
1301                                       "            ceil(fpval) +\n"
1302                                       "            fract(fpval) +\n"
1303                                       "            mod(fpval, 2.0) +\n"
1304                                       "            modf(fpval, outval) +\n"
1305                                       "            min(fpval, 0.2) +\n"
1306                                       "            max(fpval, 0.2) +\n"
1307                                       "            clamp(fpval, 0.8, 2.0) +\n"
1308                                       "            mix(fnval, fpval, 0.5) +\n"
1309                                       "            step(1.0, fpval) +\n"
1310                                       "            smoothstep(0.0, 1.0, fpval) +\n"
1311                                       "            float( isnan(fpval)) +\n"
1312                                       "            float( isinf(fpval)) +\n"
1313                                       "            fma(fpval, 1.0, fnval) +\n"
1314                                       "            frexp(4.0, ival) +\n"
1315                                       "            ldexp(4.0, ival);\n"
1316                                       "}\n"));
1317 
1318     // To avoid duplicated mappings create additional shaders for specific functions
1319     const std::string strBitsOpsVariants = "#version 450\n"
1320                                            "\n"
1321                                            "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
1322                                            "\n"
1323                                            "void main()\n"
1324                                            "{\n"
1325                                            "    float value;\n"
1326                                            "    int ival = 0x43800000;\n"
1327                                            "    uint uval = 0x43800000;\n"
1328                                            "    value = <BITS_TO_FLOAT>;\n"
1329                                            "}\n";
1330     std::string strIntBits               = strBitsOpsVariants;
1331     std::string strUIntBits              = strBitsOpsVariants;
1332     commonUtils::replaceToken("<BITS_TO_FLOAT>", "intBitsToFloat(ival)", strIntBits);
1333     commonUtils::replaceToken("<BITS_TO_FLOAT>", "uintBitsToFloat(uval)", strUIntBits);
1334 
1335     m_sources.push_back(ComputeSource(strIntBits));
1336     m_sources.push_back(ComputeSource(strUIntBits));
1337 
1338     // Float Pack Unpack
1339     m_sources.push_back(ComputeSource("#version 450\n"
1340                                       "\n"
1341                                       "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
1342                                       "\n"
1343                                       "void main()\n"
1344                                       "{\n"
1345                                       "    vec2 v2val = vec2(0.1, 0.2);\n"
1346                                       "    vec4 v4val = vec4(0.1, 0.2, 0.3, 0.4);\n"
1347                                       "    uint uival1 = packUnorm2x16(v2val);\n"
1348                                       "    uint uival2 = packSnorm2x16(v2val);\n"
1349                                       "    uint uival3 = packUnorm4x8(v4val);\n"
1350                                       "    uint uival4 = packSnorm4x8(v4val);\n"
1351                                       "    v2val = unpackUnorm2x16(uival1);\n"
1352                                       "    v2val = unpackSnorm2x16(uival2);\n"
1353                                       "    v4val = unpackUnorm4x8(uival3);\n"
1354                                       "    v4val = unpackSnorm4x8(uival4);\n"
1355                                       "    uvec2 uv2val = uvec2(10, 20);\n"
1356                                       "    double dval = packDouble2x32(uv2val);\n"
1357                                       "    uv2val = unpackDouble2x32(dval);\n"
1358                                       "    uint uival5 = packHalf2x16(v2val);\n"
1359                                       "    v2val = unpackHalf2x16(uival5);\n"
1360                                       "}\n"));
1361 
1362     // Geometric
1363     m_sources.push_back(ComputeSource("#version 450\n"
1364                                       "\n"
1365                                       "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
1366                                       "\n"
1367                                       "void main()\n"
1368                                       "{\n"
1369                                       "    vec3 v3val1 = vec3(0.1, 0.5, 1.0);\n"
1370                                       "    vec3 v3val2 = vec3(0.5, 0.3, 0.9);\n"
1371                                       "    vec3 v3val3 = vec3(1.0, 0.0, 0.0);\n"
1372                                       "    float fval = length(v3val1) +\n"
1373                                       "                 distance(v3val1, v3val2) +\n"
1374                                       "                 dot(v3val1, v3val2);\n"
1375                                       "    vec3 crossp = cross(v3val1, v3val2);\n"
1376                                       "    vec3 norm = normalize(crossp);\n"
1377                                       "    vec3 facef = faceforward(v3val1, v3val2, v3val3);\n"
1378                                       "    vec3 refl = reflect(v3val1, v3val2);\n"
1379                                       "    float eta = 0.1;\n"
1380                                       "    vec3 refr = refract(v3val1, v3val2, eta);"
1381                                       "}\n"));
1382 
1383     // Matrix
1384     m_sources.push_back(ComputeSource("#version 450\n"
1385                                       "\n"
1386                                       "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
1387                                       "\n"
1388                                       "void main()\n"
1389                                       "{\n"
1390                                       "    mat2 m2val1 = mat2(\n"
1391                                       "        0.1, 0.5,\n"
1392                                       "        0.2, 0.4\n"
1393                                       "    );\n"
1394                                       "    mat2 m2val2 = mat2(\n"
1395                                       "        0.8, 0.2,\n"
1396                                       "        0.9, 0.1\n"
1397                                       "    );\n"
1398                                       "    vec2 v2val1 = vec2(0.3, 0.4);\n"
1399                                       "    vec2 v2val2 = vec2(0.5, 0.6);\n"
1400                                       "\n"
1401                                       "    mat2 m2comp = matrixCompMult(m2val1, m2val2);\n"
1402                                       "    mat2 m2outerp = outerProduct(v2val1, v2val2);\n"
1403                                       "    mat2 m2trans = transpose(m2val1);\n"
1404                                       "    float fdet = determinant(m2val2);\n"
1405                                       "    mat2 m2inv = inverse(m2trans);\n"
1406                                       "}\n"));
1407 
1408     // Vector Relational
1409     m_sources.push_back(ComputeSource("#version 450\n"
1410                                       "\n"
1411                                       "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
1412                                       "\n"
1413                                       "void main()\n"
1414                                       "{\n"
1415                                       "    vec2 v2val1 = vec2(0.5, 0.2);\n"
1416                                       "    vec2 v2val2 = vec2(0.1, 0.8);\n"
1417                                       "    bvec2 bv2val1 = lessThan(v2val1, v2val2);\n"
1418                                       "    bvec2 bv2val2 = lessThanEqual(v2val1, v2val2);\n"
1419                                       "    bvec2 bv2val3 = greaterThan(v2val1, v2val2);\n"
1420                                       "    bvec2 bv2val4 = greaterThanEqual(v2val1, v2val2);\n"
1421                                       "    bvec2 bv2val5 = equal(v2val1, v2val2);\n"
1422                                       "    bvec2 bv2val6 = notEqual(v2val1, v2val2);\n"
1423                                       "    bool bval1 = any(bv2val1);\n"
1424                                       "    bool bval2 = all(bv2val1);\n"
1425                                       "    bvec2 bv2val7 = not(bv2val1);\n"
1426                                       "}\n"));
1427 
1428     // Integer
1429     m_sources.push_back(ComputeSource("#version 450\n"
1430                                       "\n"
1431                                       "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
1432                                       "\n"
1433                                       "void main()\n"
1434                                       "{\n"
1435                                       "    int ival = 0;\n"
1436                                       "    uint uival = 200;\n"
1437                                       "    uint uivalRet1;\n"
1438                                       "    uint uivalRet2;\n"
1439                                       "    uivalRet2 = uaddCarry(uival, 0xFFFFFFFF, uivalRet1);\n"
1440                                       "    uivalRet2 = usubBorrow(uival, 0xFFFFFFFF, uivalRet1);\n"
1441                                       "    umulExtended(uival, 0xFFFFFFFF, uivalRet1, uivalRet2);\n"
1442                                       "    uivalRet1 = bitfieldExtract(uival, 3, 8);\n"
1443                                       "    uivalRet1 = bitfieldInsert(uival, 0xFFFFFFFF, 3, 8);\n"
1444                                       "    uivalRet1 = bitfieldReverse(uival);\n"
1445                                       "    ival = bitCount(uival);\n"
1446                                       "    ival = findLSB(uival);\n"
1447                                       "    ival = findMSB(uival);\n"
1448                                       "}\n"));
1449 
1450     // Texture
1451     m_sources.push_back(
1452         FragmentSource("#version 450\n"
1453                        "\n"
1454                        "layout (location = 0) out vec4 fragColor;\n"
1455                        "\n"
1456                        "layout (location = 1) uniform sampler2D tex2D;\n"
1457                        "layout (location = 2) uniform sampler2DMS tex2DMS;\n"
1458                        "\n"
1459                        "void main()\n"
1460                        "{\n"
1461                        "    ivec2 iv2size = textureSize(tex2D, 0);\n"
1462                        "    vec2 v2lod = textureQueryLod(tex2D, vec2(0.0));\n"
1463                        "    int ilev = textureQueryLevels(tex2D);\n"
1464                        "    int isamp = textureSamples(tex2DMS);\n"
1465                        "    vec4 v4pix = textureLod(tex2D, vec2(0.0), 0.0) +\n"
1466                        "                 textureOffset(tex2D, vec2(0.0), ivec2(2)) +\n"
1467                        "                 texelFetch(tex2D, ivec2(2), 0) +\n"
1468                        "                 texelFetchOffset(tex2D, ivec2(2), 0, ivec2(2)) +\n"
1469                        "                 textureProjOffset(tex2D, vec3(0.0), ivec2(2)) +\n"
1470                        "                 textureLodOffset(tex2D, vec2(0.0), 0.0, ivec2(2)) +\n"
1471                        "                 textureProjLod(tex2D, vec3(0.0), 0.0) +\n"
1472                        "                 textureProjLodOffset(tex2D, vec3(0.0), 0.0, ivec2(2)) +\n"
1473                        "                 textureGrad(tex2D, vec2(0.0), vec2(0.2), vec2(0.5)) +\n"
1474                        "                 textureGradOffset(tex2D, vec2(0.0), vec2(0.2), vec2(0.5), ivec2(2)) +\n"
1475                        "                 textureProjGrad(tex2D, vec3(0.0), vec2(0.2), vec2(0.5)) +\n"
1476                        "                 textureProjGradOffset(tex2D, vec3(0.0), vec2(0.2), vec2(0.5), ivec2(2)) +\n"
1477                        "                 textureGatherOffset(tex2D, vec2(0.0), ivec2(2), 0);\n"
1478                        "    fragColor = vec4(0.0);\n"
1479                        "}\n"));
1480 
1481     // To avoid duplicated mappings create additional shaders for specific functions
1482     const std::string strTextureVariants = "#version 450\n"
1483                                            "\n"
1484                                            "layout (location = 0) out vec4 fragColor;\n"
1485                                            "\n"
1486                                            "layout (location = 1) uniform sampler2D tex2D;\n"
1487                                            "\n"
1488                                            "void main()\n"
1489                                            "{\n"
1490                                            "    fragColor = <TEXTURE>;\n"
1491                                            "}\n";
1492     std::string strTexture               = strTextureVariants;
1493     std::string strTextureProj           = strTextureVariants;
1494     std::string strTextureGather         = strTextureVariants;
1495     commonUtils::replaceToken("<TEXTURE>", "texture(tex2D, vec2(0.0))", strTexture);
1496     commonUtils::replaceToken("<TEXTURE>", "textureProj(tex2D, vec3(0.0))", strTextureProj);
1497     commonUtils::replaceToken("<TEXTURE>", "textureGather(tex2D, vec2(0.0), 0)", strTextureGather);
1498 
1499     m_sources.push_back(FragmentSource(strTexture));
1500     m_sources.push_back(FragmentSource(strTextureProj));
1501     m_sources.push_back(FragmentSource(strTextureGather));
1502 
1503     // Atomic Counter
1504     m_sources.push_back(ComputeSource("#version 450\n"
1505                                       "\n"
1506                                       "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
1507                                       "\n"
1508                                       "layout (binding = 0) uniform atomic_uint auival;\n"
1509                                       "\n"
1510                                       "void main()\n"
1511                                       "{\n"
1512                                       "    uint uival = atomicCounterIncrement(auival) +\n"
1513                                       "                 atomicCounterDecrement(auival) +\n"
1514                                       "                 atomicCounter(auival);\n"
1515                                       "}\n"));
1516 
1517     // Atomic Memory
1518     m_sources.push_back(ComputeSource("#version 450\n"
1519                                       "\n"
1520                                       "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
1521                                       "\n"
1522                                       "shared uint uishared;\n"
1523                                       "\n"
1524                                       "void main()\n"
1525                                       "{\n"
1526                                       "    uint uival2 = 5;\n"
1527                                       "    uint uivalRet = atomicAdd(uishared, uival2) +\n"
1528                                       "                    atomicMin(uishared, uival2) +\n"
1529                                       "                    atomicMax(uishared, uival2) +\n"
1530                                       "                    atomicAnd(uishared, uival2) +\n"
1531                                       "                    atomicOr(uishared, uival2) +\n"
1532                                       "                    atomicXor(uishared, uival2) +\n"
1533                                       "                    atomicExchange(uishared, uival2) +\n"
1534                                       "                    atomicCompSwap(uishared, uishared, uival2);\n"
1535                                       "}\n"));
1536 
1537     // Image
1538     m_sources.push_back(ComputeSource("#version 450\n"
1539                                       "\n"
1540                                       "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
1541                                       "\n"
1542                                       "layout (location = 1, rgba8ui) uniform readonly uimage2D rimg2D;\n"
1543                                       "layout (location = 2, rgba8ui) uniform readonly uimage2DMS rimg2DMS;\n"
1544                                       "layout (location = 3, rgba8ui) uniform writeonly uimage2D wimg2D;\n"
1545                                       "layout (location = 4, r32ui) uniform uimage2D aimg2D;\n"
1546                                       "\n"
1547                                       "void main()\n"
1548                                       "{\n"
1549                                       "    ivec2 size = imageSize(rimg2D);\n"
1550                                       "    int samp = imageSamples(rimg2DMS);\n"
1551                                       "    uvec4 v4pix = imageLoad(rimg2D, ivec2(0));\n"
1552                                       "    imageStore(wimg2D, ivec2(0), uvec4(255));\n"
1553                                       "    uint uivalRet = imageAtomicAdd(aimg2D, ivec2(0), 1) +\n"
1554                                       "                    imageAtomicMin(aimg2D, ivec2(0), 1) +\n"
1555                                       "                    imageAtomicMax(aimg2D, ivec2(0), 1) +\n"
1556                                       "                    imageAtomicAnd(aimg2D, ivec2(0), 1) +\n"
1557                                       "                    imageAtomicOr(aimg2D, ivec2(0), 1) +\n"
1558                                       "                    imageAtomicXor(aimg2D, ivec2(0), 1) +\n"
1559                                       "                    imageAtomicExchange(aimg2D, ivec2(0), 1) +\n"
1560                                       "                    imageAtomicCompSwap(aimg2D, ivec2(0), 1, 2);\n"
1561                                       "}\n"));
1562 
1563     // Fragment Processing
1564     m_sources.push_back(FragmentSource("#version 450\n"
1565                                        "\n"
1566                                        "layout (location = 0) out vec4 fragColor;\n"
1567                                        "layout (location = 1) in vec2 texCoord;\n"
1568                                        "\n"
1569                                        "void main()\n"
1570                                        "{\n"
1571                                        "    vec2 p = vec2(0.0);\n"
1572                                        "    vec2 dx = dFdx(p);\n"
1573                                        "    vec2 dy = dFdy(p);\n"
1574                                        "    dx = dFdxFine(p);\n"
1575                                        "    dy = dFdyFine(p);\n"
1576                                        "    dx = dFdxCoarse(p);\n"
1577                                        "    dy = dFdyCoarse(p);\n"
1578                                        "    vec2 fw = fwidth(p);\n"
1579                                        "    fw = fwidthFine(p);\n"
1580                                        "    fw = fwidthCoarse(p);\n"
1581                                        "    vec2 interp = interpolateAtCentroid(texCoord) +\n"
1582                                        "                  interpolateAtSample(texCoord, 0) +\n"
1583                                        "                  interpolateAtOffset(texCoord, vec2(0.0));\n"
1584                                        "    fragColor = vec4(1.0);\n"
1585                                        "}\n"));
1586 
1587     // To avoid duplicated mappings create additional shaders for specific functions
1588     const std::string strEmitVariants = "#version 450\n"
1589                                         "\n"
1590                                         "layout (points) in;\n"
1591                                         "layout (points, max_vertices = 3) out;\n"
1592                                         "\n"
1593                                         "void main()\n"
1594                                         "{\n"
1595                                         "    gl_Position = vec4(0.0);\n"
1596                                         "    <EMIT>;\n"
1597                                         "    <END>;\n"
1598                                         "}\n";
1599     std::string strEmit               = strEmitVariants;
1600     std::string strEmitStream         = strEmitVariants;
1601     commonUtils::replaceToken("<EMIT>", "EmitVertex()", strEmit);
1602     commonUtils::replaceToken("<EMIT>", "EmitStreamVertex(0)", strEmitStream);
1603     commonUtils::replaceToken("<END>", "EndPrimitive()", strEmit);
1604     commonUtils::replaceToken("<END>", "EndStreamPrimitive(0)", strEmitStream);
1605 
1606     m_sources.push_back(GeometrySource(strEmit));
1607     m_sources.push_back(GeometrySource(strEmitStream));
1608 
1609     // Shader Invocation Control
1610     m_sources.push_back(
1611         TessellationControlSource("#version 450\n"
1612                                   "\n"
1613                                   "layout (vertices = 3) out;\n"
1614                                   "\n"
1615                                   "void main()\n"
1616                                   "{\n"
1617                                   "    barrier();\n"
1618                                   "\n"
1619                                   "    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
1620                                   "}\n"));
1621 
1622     // Shared Memory Control
1623     // To avoid duplicated mappings create additional shaders for specific functions
1624     const std::string strMemoryBarrierSource  = "#version 450\n"
1625                                                 "\n"
1626                                                 "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
1627                                                 "\n"
1628                                                 "void main()\n"
1629                                                 "{\n"
1630                                                 "    <MEMORY_BARRIER>;\n"
1631                                                 "}\n";
1632     std::string strMemoryBarrier              = strMemoryBarrierSource;
1633     std::string strMemoryBarrierAtomicCounter = strMemoryBarrierSource;
1634     std::string strMemoryBarrierBuffer        = strMemoryBarrierSource;
1635     std::string strMemoryBarrierShared        = strMemoryBarrierSource;
1636     std::string strMemoryBarrierImage         = strMemoryBarrierSource;
1637     std::string strGroupMemoryBarrier         = strMemoryBarrierSource;
1638     commonUtils::replaceToken("<MEMORY_BARRIER>", "memoryBarrier()", strMemoryBarrier);
1639     commonUtils::replaceToken("<MEMORY_BARRIER>", "memoryBarrierAtomicCounter()", strMemoryBarrierAtomicCounter);
1640     commonUtils::replaceToken("<MEMORY_BARRIER>", "memoryBarrierBuffer()", strMemoryBarrierBuffer);
1641     commonUtils::replaceToken("<MEMORY_BARRIER>", "memoryBarrierShared()", strMemoryBarrierShared);
1642     commonUtils::replaceToken("<MEMORY_BARRIER>", "memoryBarrierImage()", strMemoryBarrierImage);
1643     commonUtils::replaceToken("<MEMORY_BARRIER>", "groupMemoryBarrier()", strGroupMemoryBarrier);
1644 
1645     m_sources.push_back(ComputeSource(strMemoryBarrier));
1646     m_sources.push_back(ComputeSource(strMemoryBarrierAtomicCounter));
1647     m_sources.push_back(ComputeSource(strMemoryBarrierBuffer));
1648     m_sources.push_back(ComputeSource(strMemoryBarrierShared));
1649     m_sources.push_back(ComputeSource(strMemoryBarrierImage));
1650     m_sources.push_back(ComputeSource(strGroupMemoryBarrier));
1651 }
1652 
1653 /** Stub de-init method */
deinit()1654 void SpirvGlslToSpirVBuiltInFunctionsTest::deinit()
1655 {
1656 }
1657 
1658 /** Executes test iteration.
1659  *
1660  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
1661  */
iterate()1662 tcu::TestNode::IterateResult SpirvGlslToSpirVBuiltInFunctionsTest::iterate()
1663 {
1664     const Functions &gl = m_context.getRenderContext().getFunctions();
1665 
1666     for (int i = 0; i < (signed)m_sources.size(); ++i)
1667     {
1668         ShaderSource shaderSource = m_sources[i];
1669 
1670         ProgramSources sources;
1671         ProgramBinaries binaries;
1672 
1673         if (shaderSource.shaderType != glu::SHADERTYPE_COMPUTE)
1674         {
1675             ShaderSource vertexSource(glu::SHADERTYPE_VERTEX, m_commonVertex);
1676 
1677             sources << vertexSource;
1678             ShaderBinary vertexBinary;
1679             vertexBinary = spirvUtils::makeSpirV(m_context.getTestContext().getLog(), vertexSource);
1680             binaries << vertexBinary;
1681         }
1682 
1683         sources << shaderSource;
1684         ShaderBinary shaderBinary;
1685         std::string spirvSource;
1686 
1687         shaderBinary = spirvUtils::makeSpirV(m_context.getTestContext().getLog(), shaderSource);
1688 
1689         {
1690             spirvUtils::spirvDisassemble(spirvSource, shaderBinary.binary);
1691 
1692             if (!spirvUtils::verifyMappings(shaderSource.source, spirvSource, m_mappings, false))
1693             {
1694                 m_testCtx.getLog() << tcu::TestLog::Message << "Mappings for shader failed.\n"
1695                                    << "GLSL source:\n"
1696                                    << shaderSource.source.c_str() << "\n"
1697                                    << "SpirV source:\n"
1698                                    << spirvSource.c_str() << tcu::TestLog::EndMessage;
1699 
1700                 TCU_THROW(InternalError, "Mappings for shader failed.");
1701             }
1702         }
1703 
1704         binaries << shaderBinary;
1705 
1706         if (shaderSource.shaderType == glu::SHADERTYPE_TESSELLATION_CONTROL)
1707         {
1708             ShaderSource tessEvalSource(glu::SHADERTYPE_TESSELLATION_EVALUATION, m_commonTessEval);
1709 
1710             sources << tessEvalSource;
1711             ShaderBinary tessEvalBinary;
1712             tessEvalBinary = spirvUtils::makeSpirV(m_context.getTestContext().getLog(), tessEvalSource);
1713             binaries << tessEvalBinary;
1714         }
1715 
1716         ShaderProgram glslProgram(gl, sources);
1717         if (!glslProgram.isOk())
1718         {
1719             m_testCtx.getLog() << tcu::TestLog::Message << "GLSL shader compilation failed. Source:\n"
1720                                << shaderSource.source.c_str() << "InfoLog:\n"
1721                                << glslProgram.getShaderInfo(shaderSource.shaderType).infoLog << "\n"
1722                                << tcu::TestLog::EndMessage;
1723 
1724             m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1725             return STOP;
1726         }
1727 
1728         ShaderProgram spirvProgram(gl, binaries);
1729         if (!spirvProgram.isOk())
1730         {
1731             m_testCtx.getLog() << tcu::TestLog::Message << "SpirV shader compilation failed. Source:\n"
1732                                << spirvSource.c_str() << "InfoLog:\n"
1733                                << spirvProgram.getShaderInfo(shaderSource.shaderType).infoLog << "\n"
1734                                << tcu::TestLog::EndMessage;
1735 
1736             m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1737             return STOP;
1738         }
1739     }
1740 
1741     m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1742     return STOP;
1743 }
1744 
1745 /** Mappings init method */
initMappings()1746 void SpirvGlslToSpirVBuiltInFunctionsTest::initMappings()
1747 {
1748     m_mappings.clear();
1749     m_mappings["radians"].push_back("OpExtInst Radians");
1750     m_mappings["degrees"].push_back("OpExtInst Degrees");
1751     m_mappings["sin"].push_back("OpExtInst Sin");
1752     m_mappings["cos"].push_back("OpExtInst Cos");
1753     m_mappings["tan"].push_back("OpExtInst Tan");
1754     m_mappings["asin"].push_back("OpExtInst Asin");
1755     m_mappings["acos"].push_back("OpExtInst Acos");
1756     m_mappings["atan"].push_back("OpExtInst Atan2");
1757     m_mappings["atan"].push_back("OpExtInst Atan");
1758     m_mappings["sinh"].push_back("OpExtInst Sinh");
1759     m_mappings["cosh"].push_back("OpExtInst Cosh");
1760     m_mappings["tanh"].push_back("OpExtInst Tanh");
1761     m_mappings["asinh"].push_back("OpExtInst Asinh");
1762     m_mappings["acosh"].push_back("OpExtInst Acosh");
1763     m_mappings["atanh"].push_back("OpExtInst Atanh");
1764     m_mappings["pow"].push_back("OpExtInst Pow");
1765     m_mappings["exp"].push_back("OpExtInst Exp");
1766     m_mappings["log"].push_back("OpExtInst Log");
1767     m_mappings["exp2"].push_back("OpExtInst Exp2");
1768     m_mappings["log2"].push_back("OpExtInst Log2");
1769     m_mappings["sqrt"].push_back("OpExtInst Sqrt");
1770     m_mappings["inversesqrt"].push_back("OpExtInst InverseSqrt");
1771     m_mappings["abs"].push_back("OpExtInst FAbs");
1772     m_mappings["sign"].push_back("OpExtInst FSign");
1773     m_mappings["floor"].push_back("OpExtInst Floor");
1774     m_mappings["trunc"].push_back("OpExtInst Trunc");
1775     m_mappings["round"].push_back("OpExtInst Round");
1776     m_mappings["roundEven"].push_back("OpExtInst RoundEven");
1777     m_mappings["ceil"].push_back("OpExtInst Ceil");
1778     m_mappings["fract"].push_back("OpExtInst Fract");
1779     m_mappings["mod"].push_back("OpFMod");
1780     m_mappings["modf"].push_back("OpExtInst Modf");
1781     m_mappings["min"].push_back("OpExtInst FMin");
1782     m_mappings["max"].push_back("OpExtInst FMax");
1783     m_mappings["clamp"].push_back("OpExtInst FClamp");
1784     m_mappings["mix"].push_back("OpExtInst FMix");
1785     m_mappings["step"].push_back("OpExtInst Step");
1786     m_mappings["smoothstep"].push_back("OpExtInst SmoothStep");
1787     m_mappings["intBitsToFloat"].push_back("OpBitcast");
1788     m_mappings["uintBitsToFloat"].push_back("OpBitcast");
1789     m_mappings["isnan"].push_back("OpIsNan");
1790     m_mappings["isinf"].push_back("OpIsInf");
1791     m_mappings["fma"].push_back("OpExtInst Fma");
1792     m_mappings["frexp"].push_back("OpExtInst FrexpStruct");
1793     m_mappings["ldexp"].push_back("OpExtInst Ldexp");
1794     m_mappings["packUnorm2x16"].push_back("OpExtInst PackUnorm2x16");
1795     m_mappings["packSnorm2x16"].push_back("OpExtInst PackSnorm2x16");
1796     m_mappings["packUnorm4x8"].push_back("OpExtInst PackUnorm4x8");
1797     m_mappings["packSnorm4x8"].push_back("OpExtInst PackSnorm4x8");
1798     m_mappings["unpackUnorm2x16"].push_back("OpExtInst UnpackUnorm2x16");
1799     m_mappings["unpackSnorm2x16"].push_back("OpExtInst UnpackSnorm2x16");
1800     m_mappings["unpackUnorm4x8"].push_back("OpExtInst UnpackUnorm4x8");
1801     m_mappings["unpackSnorm4x8"].push_back("OpExtInst UnpackSnorm4x8");
1802     m_mappings["packDouble2x32"].push_back("OpExtInst PackDouble2x32");
1803     m_mappings["unpackDouble2x32"].push_back("OpExtInst UnpackDouble2x32");
1804     m_mappings["packHalf2x16"].push_back("OpExtInst PackHalf2x16");
1805     m_mappings["unpackHalf2x16"].push_back("OpExtInst UnpackHalf2x16");
1806     m_mappings["length"].push_back("OpExtInst Length");
1807     m_mappings["distance"].push_back("OpExtInst Distance");
1808     m_mappings["dot"].push_back("OpDot");
1809     m_mappings["cross"].push_back("OpExtInst Cross");
1810     m_mappings["normalize"].push_back("OpExtInst Normalize");
1811     m_mappings["faceforward"].push_back("OpExtInst FaceForward");
1812     m_mappings["reflect"].push_back("OpExtInst Reflect");
1813     m_mappings["refract"].push_back("OpExtInst Refract");
1814     // This one could not be mapped as Spir-V equivalent need more steps
1815     // m_mappings["matrixCompMult"].push_back("");
1816     m_mappings["outerProduct"].push_back("OpOuterProduct");
1817     m_mappings["transpose"].push_back("OpTranspose");
1818     m_mappings["determinant"].push_back("OpExtInst Determinant");
1819     m_mappings["inverse"].push_back("OpExtInst MatrixInverse");
1820     m_mappings["lessThan"].push_back("OpFOrdLessThan");
1821     m_mappings["lessThanEqual"].push_back("OpFOrdLessThanEqual");
1822     m_mappings["greaterThan"].push_back("OpFOrdGreaterThan");
1823     m_mappings["greaterThanEqual"].push_back("OpFOrdGreaterThanEqual");
1824     m_mappings["equal"].push_back("OpFOrdEqual");
1825     m_mappings["notEqual"].push_back("OpFUnordNotEqual");
1826     m_mappings["any"].push_back("OpAny");
1827     m_mappings["all"].push_back("OpAll");
1828     m_mappings["not"].push_back("OpLogicalNot");
1829     m_mappings["uaddCarry"].push_back("OpIAddCarry");
1830     m_mappings["usubBorrow"].push_back("OpISubBorrow");
1831     m_mappings["umulExtended"].push_back("OpUMulExtended");
1832     m_mappings["bitfieldExtract"].push_back("OpBitFieldUExtract");
1833     m_mappings["bitfieldInsert"].push_back("OpBitFieldInsert");
1834     m_mappings["bitfieldReverse"].push_back("OpBitReverse");
1835     m_mappings["bitCount"].push_back("OpBitCount");
1836     m_mappings["findLSB"].push_back("OpExtInst FindILsb");
1837     m_mappings["findMSB"].push_back("OpExtInst FindUMsb");
1838     m_mappings["textureSize"].push_back("OpImageQuerySizeLod");
1839     m_mappings["textureQueryLod"].push_back("OpImageQueryLod");
1840     m_mappings["textureQueryLevels"].push_back("OpImageQueryLevels");
1841     m_mappings["textureSamples"].push_back("OpImageQuerySamples");
1842     m_mappings["texture"].push_back("OpImageSampleImplicitLod");
1843     m_mappings["textureProj"].push_back("OpImageSampleProjImplicitLod");
1844     m_mappings["textureLod"].push_back("OpImageSampleExplicitLod Lod");
1845     m_mappings["textureOffset"].push_back("OpImageSampleImplicitLod ConstOffset");
1846     m_mappings["texelFetch"].push_back("OpImageFetch Lod");
1847     m_mappings["texelFetchOffset"].push_back("OpImageFetch Lod|ConstOffset");
1848     m_mappings["textureProjOffset"].push_back("OpImageSampleProjImplicitLod ConstOffset");
1849     m_mappings["textureLodOffset"].push_back("OpImageSampleExplicitLod Lod|ConstOffset");
1850     m_mappings["textureProjLod"].push_back("OpImageSampleProjExplicitLod Lod");
1851     m_mappings["textureProjLodOffset"].push_back("OpImageSampleProjExplicitLod Lod|ConstOffset");
1852     m_mappings["textureGrad"].push_back("OpImageSampleExplicitLod Grad");
1853     m_mappings["textureGradOffset"].push_back("OpImageSampleExplicitLod Grad|ConstOffset");
1854     m_mappings["textureProjGrad"].push_back("OpImageSampleProjExplicitLod Grad");
1855     m_mappings["textureProjGradOffset"].push_back("OpImageSampleProjExplicitLod Grad|ConstOffset");
1856     m_mappings["textureGather"].push_back("OpImageGather");
1857     m_mappings["textureGatherOffset"].push_back("OpImageGather ConstOffset");
1858     m_mappings["atomicCounterIncrement"].push_back("OpAtomicIIncrement");
1859     m_mappings["atomicCounterDecrement"].push_back("OpAtomicIDecrement");
1860     m_mappings["atomicCounter"].push_back("OpAtomicLoad");
1861     m_mappings["atomicAdd"].push_back("OpAtomicIAdd");
1862     m_mappings["atomicMin"].push_back("OpAtomicUMin");
1863     m_mappings["atomicMax"].push_back("OpAtomicUMax");
1864     m_mappings["atomicAnd"].push_back("OpAtomicAnd");
1865     m_mappings["atomicOr"].push_back("OpAtomicOr");
1866     m_mappings["atomicXor"].push_back("OpAtomicXor");
1867     m_mappings["atomicExchange"].push_back("OpAtomicExchange");
1868     m_mappings["atomicCompSwap"].push_back("OpAtomicCompareExchange");
1869     m_mappings["imageSize"].push_back("OpImageQuerySize");
1870     m_mappings["imageSamples"].push_back("OpImageQuerySamples");
1871     m_mappings["imageLoad"].push_back("OpImageRead");
1872     m_mappings["imageStore"].push_back("OpImageWrite");
1873     m_mappings["imageAtomicAdd"].push_back("OpAtomicIAdd");
1874     m_mappings["imageAtomicMin"].push_back("OpAtomicUMin");
1875     m_mappings["imageAtomicMax"].push_back("OpAtomicUMax");
1876     m_mappings["imageAtomicAnd"].push_back("OpAtomicAnd");
1877     m_mappings["imageAtomicOr"].push_back("OpAtomicOr");
1878     m_mappings["imageAtomicXor"].push_back("OpAtomicXor");
1879     m_mappings["imageAtomicExchange"].push_back("OpAtomicExchange");
1880     m_mappings["imageAtomicCompSwap"].push_back("OpAtomicCompareExchange");
1881     m_mappings["dFdx"].push_back("OpDPdx");
1882     m_mappings["dFdy"].push_back("OpDPdy");
1883     m_mappings["dFdxFine"].push_back("OpDPdxFine");
1884     m_mappings["dFdyFine"].push_back("OpDPdyFine");
1885     m_mappings["dFdxCoarse"].push_back("OpDPdxCoarse");
1886     m_mappings["dFdyCoarse"].push_back("OpDPdyCoarse");
1887     m_mappings["fwidth"].push_back("OpFwidth");
1888     m_mappings["fwidthFine"].push_back("OpFwidthFine");
1889     m_mappings["fwidthCoarse"].push_back("OpFwidthCoarse");
1890     m_mappings["interpolateAtCentroid"].push_back("OpExtInst InterpolateAtCentroid");
1891     m_mappings["interpolateAtSample"].push_back("OpExtInst InterpolateAtSample");
1892     m_mappings["interpolateAtOffset"].push_back("OpExtInst InterpolateAtOffset");
1893     m_mappings["EmitStreamVertex"].push_back("OpEmitStreamVertex");
1894     m_mappings["EndStreamPrimitive"].push_back("OpEndStreamPrimitive");
1895     m_mappings["EmitVertex"].push_back("OpEmitVertex");
1896     m_mappings["EndPrimitive"].push_back("OpEndPrimitive");
1897     m_mappings["barrier"].push_back("OpControlBarrier");
1898     m_mappings["memoryBarrier"].push_back("OpMemoryBarrier");
1899     m_mappings["memoryBarrierAtomicCounter"].push_back("OpMemoryBarrier");
1900     m_mappings["memoryBarrierBuffer"].push_back("OpMemoryBarrier");
1901     m_mappings["memoryBarrierShared"].push_back("OpMemoryBarrier");
1902     m_mappings["memoryBarrierImage"].push_back("OpMemoryBarrier");
1903     m_mappings["groupMemoryBarrier"].push_back("OpMemoryBarrier");
1904 
1905     // Add a space prefix and parenthesis sufix to avoid searching for similar names
1906     SpirVMapping tempMappings;
1907     SpirVMapping::iterator it;
1908     for (it = m_mappings.begin(); it != m_mappings.end(); ++it)
1909     {
1910         tempMappings[std::string(" ") + it->first + "("] = it->second;
1911     }
1912 
1913     m_mappings = tempMappings;
1914 }
1915 
1916 /** Constructor.
1917  *
1918  *  @param context     Rendering context
1919  *  @param name        Test name
1920  *  @param description Test description
1921  */
SpirvGlslToSpirVSpecializationConstantsTest(deqp::Context & context)1922 SpirvGlslToSpirVSpecializationConstantsTest::SpirvGlslToSpirVSpecializationConstantsTest(deqp::Context &context)
1923     : TestCase(context, "spirv_glsl_to_spirv_specialization_constants_test",
1924                "Test verifies if constant specialization feature works as expected.")
1925 {
1926     /* Left blank intentionally */
1927 }
1928 
1929 /** Stub init method */
init()1930 void SpirvGlslToSpirVSpecializationConstantsTest::init()
1931 {
1932     spirvUtils::checkGlSpirvSupported(m_context);
1933 
1934     const Functions &gl = m_context.getRenderContext().getFunctions();
1935 
1936     m_vertex = "#version 450\n"
1937                "\n"
1938                "layout (location = 0) in vec3 position;\n"
1939                "\n"
1940                "void main()\n"
1941                "{\n"
1942                "    gl_Position = vec4(position, 1.0);\n"
1943                "}\n";
1944 
1945     m_fragment = "#version 450\n"
1946                  "\n"
1947                  "layout (constant_id = 10) const int red = 255;\n"
1948                  "\n"
1949                  "layout (location = 0) out vec4 fragColor;\n"
1950                  "\n"
1951                  "void main()\n"
1952                  "{\n"
1953                  "    fragColor = vec4(float(red) / 255, 0.0, 1.0, 1.0);\n"
1954                  "}\n";
1955 
1956     gl.genTextures(1, &m_texture);
1957     GLU_EXPECT_NO_ERROR(gl.getError(), "genTextures");
1958     gl.bindTexture(GL_TEXTURE_2D, m_texture);
1959     GLU_EXPECT_NO_ERROR(gl.getError(), "bindTexture");
1960     gl.texStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 32, 32);
1961     GLU_EXPECT_NO_ERROR(gl.getError(), "texStorage2D");
1962 
1963     gl.genFramebuffers(1, &m_fbo);
1964     GLU_EXPECT_NO_ERROR(gl.getError(), "genFramenuffers");
1965     gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo);
1966     GLU_EXPECT_NO_ERROR(gl.getError(), "bindFramebuffer");
1967     gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture, 0);
1968     GLU_EXPECT_NO_ERROR(gl.getError(), "framebufferTexture2D");
1969 
1970     gl.viewport(0, 0, 32, 32);
1971     GLU_EXPECT_NO_ERROR(gl.getError(), "viewport");
1972 }
1973 
1974 /** Stub de-init method */
deinit()1975 void SpirvGlslToSpirVSpecializationConstantsTest::deinit()
1976 {
1977     if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gl_spirv"))
1978         return;
1979     const Functions &gl = m_context.getRenderContext().getFunctions();
1980 
1981     if (m_fbo)
1982     {
1983         gl.deleteFramebuffers(1, &m_fbo);
1984         GLU_EXPECT_NO_ERROR(gl.getError(), "deleteFramebuffers");
1985     }
1986     if (m_texture)
1987     {
1988         gl.deleteTextures(1, &m_texture);
1989         GLU_EXPECT_NO_ERROR(gl.getError(), "deleteTextures");
1990     }
1991 }
1992 
1993 /** Executes test iteration.
1994  *
1995  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
1996  */
iterate()1997 tcu::TestNode::IterateResult SpirvGlslToSpirVSpecializationConstantsTest::iterate()
1998 {
1999     const Functions &gl = m_context.getRenderContext().getFunctions();
2000 
2001     const GLfloat vertices[] = {-1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f};
2002 
2003     GLuint vao;
2004     gl.genVertexArrays(1, &vao);
2005     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays");
2006     gl.bindVertexArray(vao);
2007     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray");
2008 
2009     GLuint vbo;
2010     gl.genBuffers(1, &vbo);
2011     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers");
2012     gl.bindBuffer(GL_ARRAY_BUFFER, vbo);
2013     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer");
2014 
2015     gl.bufferData(GL_ARRAY_BUFFER, 9 * sizeof(GLfloat), (GLvoid *)vertices, GL_DYNAMIC_DRAW);
2016     GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData");
2017 
2018     ShaderBinary vertexBinary;
2019     ShaderBinary fragmentBinary;
2020     {
2021         vertexBinary   = spirvUtils::makeSpirV(m_context.getTestContext().getLog(), VertexSource(m_vertex));
2022         fragmentBinary = spirvUtils::makeSpirV(m_context.getTestContext().getLog(), FragmentSource(m_fragment));
2023     }
2024     fragmentBinary << SpecializationData(10, 128);
2025 
2026     ProgramBinaries binaries;
2027     binaries << vertexBinary;
2028     binaries << fragmentBinary;
2029     ShaderProgram spirvProgram(gl, binaries);
2030 
2031     if (!spirvProgram.isOk())
2032     {
2033         m_testCtx.getLog() << tcu::TestLog::Message << "Shader compilation failed.\n"
2034                            << "Vertex:\n"
2035                            << m_vertex.c_str() << "Fragment:\n"
2036                            << m_fragment.c_str() << "InfoLog:\n"
2037                            << spirvProgram.getShaderInfo(SHADERTYPE_VERTEX).infoLog << tcu::TestLog::EndMessage;
2038 
2039         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2040         return STOP;
2041     }
2042 
2043     gl.useProgram(spirvProgram.getProgram());
2044     GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram");
2045 
2046     gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
2047     GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor");
2048     gl.clear(GL_COLOR_BUFFER_BIT);
2049     GLU_EXPECT_NO_ERROR(gl.getError(), "glClear");
2050 
2051     gl.enableVertexAttribArray(0);
2052     GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray");
2053 
2054     gl.vertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, DE_NULL);
2055     GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer");
2056 
2057     gl.drawArrays(GL_TRIANGLES, 0, 3);
2058     GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArray");
2059 
2060     gl.disableVertexAttribArray(0);
2061     GLU_EXPECT_NO_ERROR(gl.getError(), "glDisableVertexAttribArray");
2062 
2063     GLuint output;
2064 
2065     gl.readPixels(16, 16, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid *)&output);
2066     GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels");
2067 
2068     if (output != 0xFFFF0080)
2069     {
2070         m_testCtx.getLog() << tcu::TestLog::Message
2071                            << "Color value read from framebuffer is wrong. Expected: " << 0xFFFF0080
2072                            << ", Read: " << output << tcu::TestLog::EndMessage;
2073 
2074         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2075         return STOP;
2076     }
2077 
2078     m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2079     return STOP;
2080 }
2081 
2082 /** Constructor.
2083  *
2084  *  @param context     Rendering context
2085  *  @param name        Test name
2086  *  @param description Test description
2087  */
SpirvValidationBuiltInVariableDecorationsTest(deqp::Context & context)2088 SpirvValidationBuiltInVariableDecorationsTest::SpirvValidationBuiltInVariableDecorationsTest(deqp::Context &context)
2089     : TestCase(context, "spirv_validation_builtin_variable_decorations_test",
2090                "Test verifies if Spir-V built in variable decorations works as expected.")
2091 {
2092     /* Left blank intentionally */
2093 }
2094 
2095 /** Stub init method */
init()2096 void SpirvValidationBuiltInVariableDecorationsTest::init()
2097 {
2098     spirvUtils::checkGlSpirvSupported(m_context);
2099 
2100     m_compute = "#version 450\n"
2101                 "\n"
2102                 "layout (local_size_x = 1, local_size_y = 2, local_size_z = 1) in;\n"
2103                 "\n"
2104                 "layout (location = 0, rgba8ui) uniform uimage2D img0;\n"
2105                 "layout (location = 1, rgba8ui) uniform uimage2D img1;\n"
2106                 "layout (location = 2, rgba8ui) uniform uimage2D img2;\n"
2107                 "layout (location = 3, rgba8ui) uniform uimage2D img3;\n"
2108                 "layout (location = 4, rgba8ui) uniform uimage2D img4;\n"
2109                 "\n"
2110                 "void main()\n"
2111                 "{\n"
2112                 "    ivec3 point = ivec3(gl_GlobalInvocationID);\n"
2113                 "    uvec3 color0 = uvec3(gl_NumWorkGroups);\n"
2114                 "    uvec3 color1 = uvec3(gl_WorkGroupSize);\n"
2115                 "    uvec3 color2 = uvec3(gl_WorkGroupID);\n"
2116                 "    uvec3 color3 = uvec3(gl_LocalInvocationID);\n"
2117                 "    uvec3 color4 = uvec3(gl_LocalInvocationIndex);\n"
2118                 "    imageStore(img0, point.xy, uvec4(color0, 0xFF));\n"
2119                 "    imageStore(img1, point.xy, uvec4(color1, 0xFF));\n"
2120                 "    imageStore(img2, point.xy, uvec4(color2, 0xFF));\n"
2121                 "    imageStore(img3, point.xy, uvec4(color3, 0xFF));\n"
2122                 "    imageStore(img4, point.xy, uvec4(color4, 0xFF));\n"
2123                 "    memoryBarrier();\n"
2124                 "}\n";
2125 
2126     m_vertex = "#version 450\n"
2127                "\n"
2128                "layout (location = 0) in vec3 position;\n"
2129                "\n"
2130                "layout (location = 1) out vec4 vColor;\n"
2131                "\n"
2132                "void main()\n"
2133                "{\n"
2134                "    gl_PointSize = 10.0f;\n"
2135                "    gl_Position = vec4(position.x, position.y + 0.3 * gl_InstanceID, position.z, 1.0);\n"
2136                "    gl_ClipDistance[0] = <CLIP_DISTANCE>;\n"
2137                "    gl_CullDistance[0] = <CULL_DISTANCE>;\n"
2138                "    vColor = <VERTEX_COLOR>;\n"
2139                "}\n";
2140 
2141     m_tesselationCtrl = "#version 450\n"
2142                         "\n"
2143                         "layout (vertices = 3) out;\n"
2144                         "\n"
2145                         "layout (location = 1) in vec4 vColor[];\n"
2146                         "layout (location = 2) out vec4 tcColor[];\n"
2147                         "\n"
2148                         "void main()\n"
2149                         "{\n"
2150                         "    tcColor[gl_InvocationID] = vColor[gl_InvocationID];\n"
2151                         "    tcColor[gl_InvocationID].r = float(gl_PatchVerticesIn) / 3;\n"
2152                         "\n"
2153                         "    if (gl_InvocationID == 0) {\n"
2154                         "        gl_TessLevelOuter[0] = 1.0;\n"
2155                         "        gl_TessLevelOuter[1] = 1.0;\n"
2156                         "        gl_TessLevelOuter[2] = 1.0;\n"
2157                         "        gl_TessLevelInner[0] = 1.0;\n"
2158                         "    }\n"
2159                         "\n"
2160                         "    gl_out[gl_InvocationID].gl_ClipDistance[0] = gl_in[gl_InvocationID].gl_ClipDistance[0];\n"
2161                         "    gl_out[gl_InvocationID].gl_CullDistance[0] = gl_in[gl_InvocationID].gl_CullDistance[0];\n"
2162                         "    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
2163                         "}\n";
2164 
2165     m_tesselationEval = "#version 450\n"
2166                         "\n"
2167                         "layout (triangles) in;\n"
2168                         "\n"
2169                         "layout (location = 2) in vec4 tcColor[];\n"
2170                         "layout (location = 3) out vec4 teColor;\n"
2171                         "\n"
2172                         "void main()\n"
2173                         "{\n"
2174                         "    teColor = tcColor[0];\n"
2175                         "\n"
2176                         "    gl_ClipDistance[0] = gl_in[0].gl_ClipDistance[0];\n"
2177                         "    gl_CullDistance[0] = gl_in[0].gl_CullDistance[0];\n"
2178                         "    gl_Position = gl_TessCoord.x * gl_in[0].gl_Position +\n"
2179                         "                  gl_TessCoord.y * gl_in[1].gl_Position +\n"
2180                         "                  gl_TessCoord.z * gl_in[2].gl_Position;\n"
2181                         "}\n";
2182 
2183     m_geometry = "#version 450\n"
2184                  "\n"
2185                  "layout (triangles) in;\n"
2186                  "layout (triangle_strip, max_vertices = 3) out;\n"
2187                  "\n"
2188                  "layout (location = 3) in vec4 teColor[];\n"
2189                  "layout (location = 4) out vec4 gColor;\n"
2190                  "\n"
2191                  "void main()\n"
2192                  "{\n"
2193                  "    gColor = teColor[0];\n"
2194                  "    gColor.b = float(gl_PrimitiveIDIn);\n"
2195                  "\n"
2196                  "    gl_Layer = 1;\n"
2197                  "    gl_ViewportIndex = 1;\n"
2198                  "\n"
2199                  "    for (int i = 0; i < 3; ++i) {\n"
2200                  "        gl_ClipDistance[0] = gl_in[i].gl_ClipDistance[0];\n"
2201                  "        gl_CullDistance[0] = gl_in[i].gl_CullDistance[0];\n"
2202                  "        gl_Position = gl_in[i].gl_Position;\n"
2203                  "        EmitVertex();\n"
2204                  "    }\n"
2205                  "    EndPrimitive();\n"
2206                  "}\n";
2207 
2208     m_fragment = "#version 450\n"
2209                  "\n"
2210                  "layout (location = <INPUT_LOCATION>) in vec4 <INPUT_NAME>;\n"
2211                  "layout (location = 0) out vec4 fColor;\n"
2212                  "\n"
2213                  "void main()\n"
2214                  "{\n"
2215                  "    vec4 color = <INPUT_NAME>;\n"
2216                  "    <ADDITIONAL_CODE>\n"
2217                  "    fColor = color;\n"
2218                  "}\n";
2219 
2220     ValidationStruct validationCompute(&SpirvValidationBuiltInVariableDecorationsTest::validComputeFunc);
2221     validationCompute.shaders.push_back(ComputeSource(m_compute));
2222     m_validations.push_back(validationCompute);
2223 
2224     std::string clipNegativeVertex   = m_vertex;
2225     std::string clipNegativeFragment = m_fragment;
2226     commonUtils::replaceToken("<CLIP_DISTANCE>", "-1.0", clipNegativeVertex);
2227     commonUtils::replaceToken("<CULL_DISTANCE>", "1.0", clipNegativeVertex);
2228     commonUtils::replaceToken("<VERTEX_COLOR>", "vec4(1.0, 1.0, 1.0, 1.0)", clipNegativeVertex);
2229     commonUtils::replaceToken("<INPUT_LOCATION>", "1", clipNegativeFragment);
2230     commonUtils::replaceToken("<INPUT_NAME>", "vColor", clipNegativeFragment);
2231     commonUtils::replaceToken("<ADDITIONAL_CODE>", "", clipNegativeFragment);
2232     ValidationStruct validationClipNegative(&SpirvValidationBuiltInVariableDecorationsTest::validPerVertexFragFunc);
2233     validationClipNegative.shaders.push_back(VertexSource(clipNegativeVertex));
2234     validationClipNegative.shaders.push_back(FragmentSource(clipNegativeFragment));
2235     validationClipNegative.outputs.push_back(ValidationOutputStruct(32, 32, 0xFF000000));
2236     m_validations.push_back(validationClipNegative);
2237 
2238     std::string perVertexFragVertex   = m_vertex;
2239     std::string perVertexFragFragment = m_fragment;
2240     std::string fragCode              = "vec4 coord = gl_FragCoord;\n"
2241                                         "color = vec4(0.0, coord.s / 64, coord.t / 64, 1.0);\n";
2242     commonUtils::replaceToken("<CLIP_DISTANCE>", "1.0", perVertexFragVertex);
2243     commonUtils::replaceToken("<CULL_DISTANCE>", "1.0", perVertexFragVertex);
2244     commonUtils::replaceToken("<VERTEX_COLOR>", "vec4(1.0, 1.0, 1.0, 1.0)", perVertexFragVertex);
2245     commonUtils::replaceToken("<INPUT_LOCATION>", "1", perVertexFragFragment);
2246     commonUtils::replaceToken("<INPUT_NAME>", "vColor", perVertexFragFragment);
2247     commonUtils::replaceToken("<ADDITIONAL_CODE>", fragCode.c_str(), perVertexFragFragment);
2248     ValidationStruct validationFrag(&SpirvValidationBuiltInVariableDecorationsTest::validPerVertexFragFunc);
2249     validationFrag.shaders.push_back(VertexSource(perVertexFragVertex));
2250     validationFrag.shaders.push_back(FragmentSource(perVertexFragFragment));
2251     validationFrag.outputs.push_back(ValidationOutputStruct(32, 32, 0xFF7F7F00));
2252     m_validations.push_back(validationFrag);
2253 
2254     std::string perVertexPointVertex   = m_vertex;
2255     std::string perVertexPointFragment = m_fragment;
2256     std::string pointCode              = "vec2 coord = gl_PointCoord;\n"
2257                                          "color.b = coord.s * coord.t;\n";
2258     commonUtils::replaceToken("<CLIP_DISTANCE>", "1.0", perVertexPointVertex);
2259     commonUtils::replaceToken("<CULL_DISTANCE>", "1.0", perVertexPointVertex);
2260     commonUtils::replaceToken("<VERTEX_COLOR>", "vec4(float(gl_VertexID) / 3, 0.0, 0.0, 1.0)", perVertexPointVertex);
2261     commonUtils::replaceToken("<INPUT_LOCATION>", "1", perVertexPointFragment);
2262     commonUtils::replaceToken("<INPUT_NAME>", "vColor", perVertexPointFragment);
2263     commonUtils::replaceToken("<ADDITIONAL_CODE>", pointCode.c_str(), perVertexPointFragment);
2264     ValidationStruct validationPoint(&SpirvValidationBuiltInVariableDecorationsTest::validPerVertexPointFunc);
2265     validationPoint.shaders.push_back(VertexSource(perVertexPointVertex));
2266     validationPoint.shaders.push_back(FragmentSource(perVertexPointFragment));
2267     validationPoint.outputs.push_back(ValidationOutputStruct(64, 64, 0xFF3F0055));
2268     validationPoint.outputs.push_back(ValidationOutputStruct(45, 45, 0xFF3F0000));
2269     validationPoint.outputs.push_back(ValidationOutputStruct(83, 83, 0xFF3F00AA));
2270     m_validations.push_back(validationPoint);
2271 
2272     std::string tessGeomVertex   = m_vertex;
2273     std::string tessGeomFragment = m_fragment;
2274     commonUtils::replaceToken("<CLIP_DISTANCE>", "1.0", tessGeomVertex);
2275     commonUtils::replaceToken("<CULL_DISTANCE>", "1.0", tessGeomVertex);
2276     commonUtils::replaceToken("<VERTEX_COLOR>", "vec4(1.0, 1.0, 1.0, 1.0)", tessGeomVertex);
2277     commonUtils::replaceToken("<INPUT_LOCATION>", "4", tessGeomFragment);
2278     commonUtils::replaceToken("<INPUT_NAME>", "gColor", tessGeomFragment);
2279     commonUtils::replaceToken("<ADDITIONAL_CODE>", "", tessGeomFragment);
2280     ValidationStruct validationTessGeom(&SpirvValidationBuiltInVariableDecorationsTest::validTesselationGeometryFunc);
2281     validationTessGeom.shaders.push_back(VertexSource(tessGeomVertex));
2282     validationTessGeom.shaders.push_back(TessellationControlSource(m_tesselationCtrl));
2283     validationTessGeom.shaders.push_back(TessellationEvaluationSource(m_tesselationEval));
2284     validationTessGeom.shaders.push_back(GeometrySource(m_geometry));
2285     validationTessGeom.shaders.push_back(FragmentSource(tessGeomFragment));
2286     validationTessGeom.outputs.push_back(ValidationOutputStruct(48, 32, 1, 0xFF00FFFF));
2287     m_validations.push_back(validationTessGeom);
2288 
2289     std::string multisampleVertex   = m_vertex;
2290     std::string multisampleFragment = m_fragment;
2291     std::string samplingCode        = "if (gl_SampleID == 0)\n"
2292                                       "{\n"
2293                                       "   vec2 sampPos = gl_SamplePosition;\n"
2294                                       "    color = vec4(1.0, sampPos.x, sampPos.y, 1.0);\n"
2295                                       "}\n"
2296                                       "else\n"
2297                                       "{\n"
2298                                       "    color = vec4(0.0, 1.0, 0.0, 1.0);\n"
2299                                       "}\n"
2300                                       "gl_SampleMask[0] = 0x02;";
2301     commonUtils::replaceToken("<CLIP_DISTANCE>", "1.0", multisampleVertex);
2302     commonUtils::replaceToken("<CULL_DISTANCE>", "1.0", multisampleVertex);
2303     commonUtils::replaceToken("<VERTEX_COLOR>", "vec4(1.0, 1.0, 1.0, 1.0)", multisampleVertex);
2304     commonUtils::replaceToken("<INPUT_LOCATION>", "1", multisampleFragment);
2305     commonUtils::replaceToken("<INPUT_NAME>", "vColor", multisampleFragment);
2306     commonUtils::replaceToken("<ADDITIONAL_CODE>", samplingCode.c_str(), multisampleFragment);
2307     ValidationStruct validationMultisample(&SpirvValidationBuiltInVariableDecorationsTest::validMultiSamplingFunc);
2308     validationMultisample.shaders.push_back(VertexSource(multisampleVertex));
2309     validationMultisample.shaders.push_back(FragmentSource(multisampleFragment));
2310     validationMultisample.outputs.push_back(ValidationOutputStruct(16, 16, 0xFF00BC00));
2311     m_validations.push_back(validationMultisample);
2312 
2313     m_mappings["gl_NumWorkGroups"].push_back("BuiltIn NumWorkgroups");
2314     m_mappings["gl_WorkGroupSize"].push_back("BuiltIn WorkgroupSize");
2315     m_mappings["gl_WorkGroupID"].push_back("BuiltIn WorkgroupId");
2316     m_mappings["gl_LocalInvocationID"].push_back("BuiltIn LocalInvocationId");
2317     m_mappings["gl_GlobalInvocationID"].push_back("BuiltIn GlobalInvocationId");
2318     m_mappings["gl_LocalInvocationIndex"].push_back("BuiltIn LocalInvocationIndex");
2319     m_mappings["gl_VertexID"].push_back("BuiltIn VertexId");
2320     m_mappings["gl_InstanceID"].push_back("BuiltIn InstanceId");
2321     m_mappings["gl_Position"].push_back("BuiltIn Position");
2322     m_mappings["gl_PointSize"].push_back("BuiltIn PointSize");
2323     m_mappings["gl_ClipDistance"].push_back("BuiltIn ClipDistance");
2324     m_mappings["gl_CullDistance"].push_back("BuiltIn CullDistance");
2325     m_mappings["gl_PrimitiveIDIn"].push_back("BuiltIn PrimitiveId");
2326     m_mappings["gl_InvocationID"].push_back("BuiltIn InvocationId");
2327     m_mappings["gl_Layer"].push_back("BuiltIn Layer");
2328     m_mappings["gl_ViewportIndex"].push_back("BuiltIn ViewportIndex");
2329     m_mappings["gl_PatchVerticesIn"].push_back("BuiltIn PatchVertices");
2330     m_mappings["gl_TessLevelOuter"].push_back("BuiltIn TessLevelOuter");
2331     m_mappings["gl_TessLevelInner"].push_back("BuiltIn TessLevelInner");
2332     m_mappings["gl_TessCoord"].push_back("BuiltIn TessCoord");
2333     m_mappings["gl_FragCoord"].push_back("BuiltIn FragCoord");
2334     m_mappings["gl_FrontFacing"].push_back("BuiltIn FrontFacing");
2335     m_mappings["gl_PointCoord"].push_back("BuiltIn PointCoord");
2336     m_mappings["gl_SampleId"].push_back("BuiltIn SampleId");
2337     m_mappings["gl_SamplePosition"].push_back("BuiltIn SamplePosition");
2338     m_mappings["gl_SampleMask"].push_back("BuiltIn SampleMask");
2339 }
2340 
2341 /** Stub de-init method */
deinit()2342 void SpirvValidationBuiltInVariableDecorationsTest::deinit()
2343 {
2344 }
2345 
2346 /** Executes test iteration.
2347  *
2348  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
2349  */
iterate()2350 tcu::TestNode::IterateResult SpirvValidationBuiltInVariableDecorationsTest::iterate()
2351 {
2352     const Functions &gl = m_context.getRenderContext().getFunctions();
2353 
2354     GLuint vao;
2355     gl.genVertexArrays(1, &vao);
2356     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays");
2357     gl.bindVertexArray(vao);
2358     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray");
2359 
2360     GLuint vbo;
2361     gl.genBuffers(1, &vbo);
2362     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers");
2363     gl.bindBuffer(GL_ARRAY_BUFFER, vbo);
2364     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer");
2365 
2366     enum Iterates
2367     {
2368         ITERATE_GLSL,
2369         ITERATE_SPIRV,
2370         ITERATE_LAST
2371     };
2372 
2373     bool result = true;
2374 
2375     for (int v = 0; v < (signed)m_validations.size(); ++v)
2376     {
2377         for (int it = ITERATE_GLSL; it < ITERATE_LAST; ++it)
2378         {
2379             ShaderProgram *program = DE_NULL;
2380             if (it == ITERATE_GLSL)
2381             {
2382                 ProgramSources sources;
2383                 for (int s = 0; s < (signed)m_validations[v].shaders.size(); ++s)
2384                     sources << m_validations[v].shaders[s];
2385 
2386                 program = new ShaderProgram(gl, sources);
2387             }
2388             else if (it == ITERATE_SPIRV)
2389             {
2390                 std::vector<ShaderBinary> binariesVec;
2391 
2392                 ProgramBinaries binaries;
2393                 for (int s = 0; s < (signed)m_validations[v].shaders.size(); ++s)
2394                 {
2395                     ShaderBinary shaderBinary =
2396                         spirvUtils::makeSpirV(m_context.getTestContext().getLog(), m_validations[v].shaders[s]);
2397                     binariesVec.push_back(shaderBinary);
2398                     binaries << shaderBinary;
2399                 }
2400                 program = new ShaderProgram(gl, binaries);
2401 
2402                 std::string spirvSource;
2403 
2404                 for (int s = 0; s < (signed)m_validations[v].shaders.size(); ++s)
2405                 {
2406                     ShaderSource shaderSource = m_validations[v].shaders[s];
2407 
2408                     spirvUtils::spirvDisassemble(spirvSource, binariesVec[s].binary);
2409 
2410                     if (!spirvUtils::verifyMappings(shaderSource.source, spirvSource, m_mappings, true))
2411                     {
2412                         m_testCtx.getLog() << tcu::TestLog::Message << "Mappings for shader failed.\n"
2413                                            << "GLSL source:\n"
2414                                            << shaderSource.source.c_str() << "\n"
2415                                            << "SpirV source:\n"
2416                                            << spirvSource.c_str() << tcu::TestLog::EndMessage;
2417 
2418                         TCU_THROW(InternalError, "Mappings for shader failed.");
2419                     }
2420                 }
2421             }
2422 
2423             if (!program->isOk())
2424             {
2425                 std::stringstream message;
2426                 message << "Shader build failed.\n";
2427 
2428                 if (program->hasShader(SHADERTYPE_COMPUTE))
2429                     message << "ComputeInfo: " << program->getShaderInfo(SHADERTYPE_COMPUTE).infoLog << "\n"
2430                             << "ComputeSource: " << program->getShader(SHADERTYPE_COMPUTE)->getSource() << "\n";
2431                 if (program->hasShader(SHADERTYPE_VERTEX))
2432                     message << "VertexInfo: " << program->getShaderInfo(SHADERTYPE_VERTEX).infoLog << "\n"
2433                             << "VertexSource: " << program->getShader(SHADERTYPE_VERTEX)->getSource() << "\n";
2434                 if (program->hasShader(SHADERTYPE_TESSELLATION_CONTROL))
2435                     message << "TesselationCtrlInfo: "
2436                             << program->getShaderInfo(SHADERTYPE_TESSELLATION_CONTROL).infoLog << "\n"
2437                             << "TesselationCtrlSource: "
2438                             << program->getShader(SHADERTYPE_TESSELLATION_CONTROL)->getSource() << "\n";
2439                 if (program->hasShader(SHADERTYPE_TESSELLATION_EVALUATION))
2440                     message << "TesselationEvalInfo: "
2441                             << program->getShaderInfo(SHADERTYPE_TESSELLATION_EVALUATION).infoLog << "\n"
2442                             << "TesselationEvalSource: "
2443                             << program->getShader(SHADERTYPE_TESSELLATION_EVALUATION)->getSource() << "\n";
2444                 if (program->hasShader(SHADERTYPE_GEOMETRY))
2445                     message << "GeometryInfo: " << program->getShaderInfo(SHADERTYPE_GEOMETRY).infoLog << "\n"
2446                             << "GeometrySource: " << program->getShader(SHADERTYPE_GEOMETRY)->getSource() << "\n";
2447                 if (program->hasShader(SHADERTYPE_FRAGMENT))
2448                     message << "FragmentInfo: " << program->getShaderInfo(SHADERTYPE_FRAGMENT).infoLog << "\n"
2449                             << "FragmentSource: " << program->getShader(SHADERTYPE_FRAGMENT)->getSource() << "\n";
2450 
2451                 message << "ProgramInfo: " << program->getProgramInfo().infoLog;
2452 
2453                 m_testCtx.getLog() << tcu::TestLog::Message << message.str() << tcu::TestLog::EndMessage;
2454 
2455                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2456                 return STOP;
2457             }
2458 
2459             gl.useProgram(program->getProgram());
2460             GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram");
2461 
2462             ValidationFuncPtr funcPtr = m_validations[v].validationFuncPtr;
2463             result                    = (this->*funcPtr)(m_validations[v].outputs);
2464 
2465             if (program)
2466                 delete program;
2467 
2468             if (!result)
2469             {
2470                 m_testCtx.getLog() << tcu::TestLog::Message << "Validation " << v << " failed!"
2471                                    << tcu::TestLog::EndMessage;
2472 
2473                 break;
2474             }
2475         }
2476     }
2477 
2478     if (vbo)
2479     {
2480         gl.deleteBuffers(1, &vbo);
2481         GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteBuffers");
2482     }
2483 
2484     if (vao)
2485     {
2486         gl.deleteVertexArrays(1, &vao);
2487         GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteVertexArrays");
2488     }
2489 
2490     if (result)
2491         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2492     else
2493         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2494     return STOP;
2495 }
2496 
validComputeFunc(ValidationOutputVec & outputs)2497 bool SpirvValidationBuiltInVariableDecorationsTest::validComputeFunc(ValidationOutputVec &outputs)
2498 {
2499     DE_UNREF(outputs);
2500 
2501     const Functions &gl = m_context.getRenderContext().getFunctions();
2502 
2503     GLuint textures[5];
2504 
2505     gl.genTextures(5, textures);
2506     GLU_EXPECT_NO_ERROR(gl.getError(), "genTextures");
2507     for (int i = 0; i < 5; ++i)
2508     {
2509         gl.bindTexture(GL_TEXTURE_2D, textures[i]);
2510         GLU_EXPECT_NO_ERROR(gl.getError(), "bindTexture");
2511         gl.texStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8UI, 4, 4);
2512         GLU_EXPECT_NO_ERROR(gl.getError(), "texStorage2D");
2513     }
2514 
2515     gl.bindImageTexture(0, textures[0], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8UI);
2516     GLU_EXPECT_NO_ERROR(gl.getError(), "bindImageTexture");
2517     gl.bindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8UI);
2518     GLU_EXPECT_NO_ERROR(gl.getError(), "bindImageTexture");
2519     gl.bindImageTexture(2, textures[2], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8UI);
2520     GLU_EXPECT_NO_ERROR(gl.getError(), "bindImageTexture");
2521     gl.bindImageTexture(3, textures[3], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8UI);
2522     GLU_EXPECT_NO_ERROR(gl.getError(), "bindImageTexture");
2523     gl.bindImageTexture(4, textures[4], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8UI);
2524     GLU_EXPECT_NO_ERROR(gl.getError(), "bindImageTexture");
2525     gl.uniform1i(0, 0);
2526     GLU_EXPECT_NO_ERROR(gl.getError(), "uniform1i");
2527     gl.uniform1i(1, 1);
2528     GLU_EXPECT_NO_ERROR(gl.getError(), "uniform1i");
2529     gl.uniform1i(2, 2);
2530     GLU_EXPECT_NO_ERROR(gl.getError(), "uniform1i");
2531     gl.uniform1i(3, 3);
2532     GLU_EXPECT_NO_ERROR(gl.getError(), "uniform1i");
2533     gl.uniform1i(4, 4);
2534     GLU_EXPECT_NO_ERROR(gl.getError(), "uniform1i");
2535     gl.dispatchCompute(4, 2, 1);
2536     GLU_EXPECT_NO_ERROR(gl.getError(), "dispatchCompute");
2537 
2538     gl.memoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
2539     GLU_EXPECT_NO_ERROR(gl.getError(), "memoryBarrier");
2540 
2541     std::vector<GLubyte> expectedResults[5];
2542     for (int i = 0; i < 5; ++i)
2543     {
2544         for (int y = 0; y < 4; ++y)
2545         {
2546             for (int x = 0; x < 4; ++x)
2547             {
2548                 //"uvec3 color0 = uvec3(gl_NumWorkGroups);"
2549                 if (i == 0)
2550                 {
2551                     expectedResults[i].push_back(4);
2552                     expectedResults[i].push_back(2);
2553                     expectedResults[i].push_back(1);
2554                     expectedResults[i].push_back(0xFF);
2555                 }
2556                 //"uvec3 color1 = uvec3(gl_WorkGroupSize);"
2557                 else if (i == 1)
2558                 {
2559                     expectedResults[i].push_back(1);
2560                     expectedResults[i].push_back(2);
2561                     expectedResults[i].push_back(1);
2562                     expectedResults[i].push_back(0xFF);
2563                 }
2564                 //"uvec3 color2 = uvec3(gl_WorkGroupID);"
2565                 else if (i == 2)
2566                 {
2567                     expectedResults[i].push_back(x);
2568                     expectedResults[i].push_back(y / 2);
2569                     expectedResults[i].push_back(0);
2570                     expectedResults[i].push_back(0xFF);
2571                 }
2572                 //"uvec3 color3 = uvec3(gl_LocalInvocationID);"
2573                 else if (i == 3)
2574                 {
2575                     expectedResults[i].push_back(0);
2576                     expectedResults[i].push_back(y % 2);
2577                     expectedResults[i].push_back(0);
2578                     expectedResults[i].push_back(0xFF);
2579                 }
2580                 //"uvec3 color4 = uvec3(gl_LocalInvocationIndex);"
2581                 else if (i == 4)
2582                 {
2583                     expectedResults[i].push_back(y % 2);
2584                     expectedResults[i].push_back(y % 2);
2585                     expectedResults[i].push_back(y % 2);
2586                     expectedResults[i].push_back(0xFF);
2587                 }
2588             }
2589         }
2590     }
2591 
2592     bool result = true;
2593     for (int i = 0; i < 5; ++i)
2594     {
2595         gl.bindTexture(GL_TEXTURE_2D, textures[i]);
2596         GLU_EXPECT_NO_ERROR(gl.getError(), "bindTexture");
2597 
2598         std::vector<GLubyte> pixels;
2599         pixels.resize(4 * 4 * 4);
2600         gl.getTexImage(GL_TEXTURE_2D, 0, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, (GLvoid *)pixels.data());
2601         GLU_EXPECT_NO_ERROR(gl.getError(), "getTexImage");
2602 
2603         if (pixels != expectedResults[i])
2604         {
2605             m_testCtx.getLog() << tcu::TestLog::Message << "Invalid image computed [" << i << "]."
2606                                << tcu::TestLog::EndMessage;
2607 
2608             result = false;
2609         }
2610     }
2611 
2612     gl.deleteTextures(5, textures);
2613     GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteTextures");
2614 
2615     return result;
2616 }
2617 
validPerVertexFragFunc(ValidationOutputVec & outputs)2618 bool SpirvValidationBuiltInVariableDecorationsTest::validPerVertexFragFunc(ValidationOutputVec &outputs)
2619 {
2620     const Functions &gl = m_context.getRenderContext().getFunctions();
2621 
2622     const GLfloat vertices[] = {-1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f};
2623 
2624     GLuint texture;
2625     GLuint fbo;
2626 
2627     gl.genTextures(1, &texture);
2628     GLU_EXPECT_NO_ERROR(gl.getError(), "genTextures");
2629     gl.bindTexture(GL_TEXTURE_2D, texture);
2630     GLU_EXPECT_NO_ERROR(gl.getError(), "bindTexture");
2631     gl.texStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 64, 64);
2632     GLU_EXPECT_NO_ERROR(gl.getError(), "texStorage2D");
2633 
2634     gl.genFramebuffers(1, &fbo);
2635     GLU_EXPECT_NO_ERROR(gl.getError(), "genFramenuffers");
2636     gl.bindFramebuffer(GL_FRAMEBUFFER, fbo);
2637     GLU_EXPECT_NO_ERROR(gl.getError(), "bindFramebuffer");
2638     gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
2639     GLU_EXPECT_NO_ERROR(gl.getError(), "framebufferTexture2D");
2640 
2641     gl.viewport(0, 0, 64, 64);
2642     GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport");
2643 
2644     gl.bufferData(GL_ARRAY_BUFFER, 9 * sizeof(GLfloat), (GLvoid *)vertices, GL_DYNAMIC_DRAW);
2645     GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData");
2646 
2647     gl.enable(GL_CLIP_DISTANCE0);
2648 
2649     gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
2650     GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor");
2651     gl.clear(GL_COLOR_BUFFER_BIT);
2652     GLU_EXPECT_NO_ERROR(gl.getError(), "glClear");
2653 
2654     gl.enableVertexAttribArray(0);
2655     GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray");
2656 
2657     gl.vertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, DE_NULL);
2658     GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer");
2659 
2660     gl.drawArrays(GL_TRIANGLES, 0, 3);
2661     GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArray");
2662 
2663     gl.disableVertexAttribArray(0);
2664     GLU_EXPECT_NO_ERROR(gl.getError(), "glDisableVertexAttribArray");
2665 
2666     gl.disable(GL_CLIP_DISTANCE0);
2667 
2668     bool result = true;
2669     for (int o = 0; o < (signed)outputs.size(); ++o)
2670     {
2671         GLuint output;
2672         gl.readPixels(outputs[o].x, outputs[o].y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid *)&output);
2673         GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels");
2674 
2675         if (!commonUtils::compareUintColors(output, outputs[o].value, 2))
2676         {
2677             m_testCtx.getLog() << tcu::TestLog::Message << "Invalid output color read at [" << (int)outputs[o].x << "/"
2678                                << (int)outputs[o].y << "]. Expected: " << outputs[o].value << ", "
2679                                << "Read: " << output << tcu::TestLog::EndMessage;
2680 
2681             result = false;
2682         }
2683     }
2684 
2685     if (fbo)
2686     {
2687         gl.deleteFramebuffers(1, &fbo);
2688         GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteFramebuffers");
2689     }
2690 
2691     if (texture)
2692     {
2693         gl.deleteTextures(1, &texture);
2694         GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteTextures");
2695     }
2696 
2697     return result;
2698 }
2699 
validPerVertexPointFunc(ValidationOutputVec & outputs)2700 bool SpirvValidationBuiltInVariableDecorationsTest::validPerVertexPointFunc(ValidationOutputVec &outputs)
2701 {
2702     const Functions &gl = m_context.getRenderContext().getFunctions();
2703 
2704     const GLfloat vertices[] = {-0.3f, -0.3f, 0.0f, 0.0f, -0.3f, 0.0f, 0.3f, -0.3f, 0.0f};
2705 
2706     GLuint texture;
2707     GLuint fbo;
2708 
2709     gl.genTextures(1, &texture);
2710     GLU_EXPECT_NO_ERROR(gl.getError(), "genTextures");
2711     gl.bindTexture(GL_TEXTURE_2D, texture);
2712     GLU_EXPECT_NO_ERROR(gl.getError(), "bindTexture");
2713     gl.texStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 128, 128);
2714     GLU_EXPECT_NO_ERROR(gl.getError(), "texStorage2D");
2715 
2716     gl.genFramebuffers(1, &fbo);
2717     GLU_EXPECT_NO_ERROR(gl.getError(), "genFramenuffers");
2718     gl.bindFramebuffer(GL_FRAMEBUFFER, fbo);
2719     GLU_EXPECT_NO_ERROR(gl.getError(), "bindFramebuffer");
2720     gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
2721     GLU_EXPECT_NO_ERROR(gl.getError(), "framebufferTexture2D");
2722 
2723     gl.viewport(0, 0, 128, 128);
2724     GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport");
2725 
2726     gl.bufferData(GL_ARRAY_BUFFER, 9 * sizeof(GLfloat), (GLvoid *)vertices, GL_DYNAMIC_DRAW);
2727     GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData");
2728 
2729     gl.enable(GL_CLIP_DISTANCE0);
2730     gl.enable(GL_PROGRAM_POINT_SIZE);
2731 
2732     gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
2733     GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor");
2734     gl.clear(GL_COLOR_BUFFER_BIT);
2735     GLU_EXPECT_NO_ERROR(gl.getError(), "glClear");
2736 
2737     gl.enableVertexAttribArray(0);
2738     GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray");
2739 
2740     gl.vertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, DE_NULL);
2741     GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer");
2742 
2743     gl.drawArraysInstanced(GL_POINTS, 0, 3, 3);
2744     GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArray");
2745 
2746     gl.disableVertexAttribArray(0);
2747     GLU_EXPECT_NO_ERROR(gl.getError(), "glDisableVertexAttribArray");
2748 
2749     gl.disable(GL_PROGRAM_POINT_SIZE);
2750     gl.disable(GL_CLIP_DISTANCE0);
2751 
2752     bool result = true;
2753     for (int o = 0; o < (signed)outputs.size(); ++o)
2754     {
2755         GLuint output;
2756         gl.readPixels(outputs[o].x, outputs[o].y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid *)&output);
2757         GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels");
2758 
2759         if (!commonUtils::compareUintColors(output, outputs[o].value, 2))
2760         {
2761             m_testCtx.getLog() << tcu::TestLog::Message << "Invalid output color read at [" << (int)outputs[o].x << "/"
2762                                << (int)outputs[o].y << "]. Expected: " << outputs[o].value << ", "
2763                                << "Read: " << output << tcu::TestLog::EndMessage;
2764 
2765             result = false;
2766         }
2767     }
2768 
2769     if (fbo)
2770     {
2771         gl.deleteFramebuffers(1, &fbo);
2772         GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteFramebuffers");
2773     }
2774 
2775     if (texture)
2776     {
2777         gl.deleteTextures(1, &texture);
2778         GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteTextures");
2779     }
2780 
2781     return result;
2782 }
2783 
validTesselationGeometryFunc(ValidationOutputVec & outputs)2784 bool SpirvValidationBuiltInVariableDecorationsTest::validTesselationGeometryFunc(ValidationOutputVec &outputs)
2785 {
2786     const Functions &gl = m_context.getRenderContext().getFunctions();
2787 
2788     const GLfloat vertices[] = {-1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f};
2789 
2790     GLuint texture;
2791     GLuint fbo;
2792 
2793     gl.genTextures(1, &texture);
2794     GLU_EXPECT_NO_ERROR(gl.getError(), "genTextures");
2795     gl.bindTexture(GL_TEXTURE_2D_ARRAY, texture);
2796     GLU_EXPECT_NO_ERROR(gl.getError(), "bindTexture");
2797     gl.texStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, 64, 64, 2);
2798     GLU_EXPECT_NO_ERROR(gl.getError(), "texStorage2D");
2799 
2800     gl.genFramebuffers(1, &fbo);
2801     GLU_EXPECT_NO_ERROR(gl.getError(), "genFramenuffers");
2802     gl.bindFramebuffer(GL_FRAMEBUFFER, fbo);
2803     GLU_EXPECT_NO_ERROR(gl.getError(), "bindFramebuffer");
2804     gl.framebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture, 0);
2805     GLU_EXPECT_NO_ERROR(gl.getError(), "framebufferTexture2D");
2806 
2807     gl.viewportIndexedf(0, 0.0f, 0.0f, 32.0f, 64.0f);
2808     GLU_EXPECT_NO_ERROR(gl.getError(), "glViewportIndexed");
2809 
2810     gl.viewportIndexedf(1, 32.0f, 0.0f, 32.0f, 64.0f);
2811     GLU_EXPECT_NO_ERROR(gl.getError(), "glViewportIndexed");
2812 
2813     gl.bufferData(GL_ARRAY_BUFFER, 9 * sizeof(GLfloat), (GLvoid *)vertices, GL_DYNAMIC_DRAW);
2814     GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData");
2815 
2816     gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
2817     GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor");
2818     gl.clear(GL_COLOR_BUFFER_BIT);
2819     GLU_EXPECT_NO_ERROR(gl.getError(), "glClear");
2820 
2821     gl.enableVertexAttribArray(0);
2822     GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray");
2823 
2824     gl.vertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, DE_NULL);
2825     GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer");
2826 
2827     gl.patchParameteri(GL_PATCH_VERTICES, 3);
2828     gl.drawArrays(GL_PATCHES, 0, 3);
2829     GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArray");
2830 
2831     gl.disableVertexAttribArray(0);
2832     GLU_EXPECT_NO_ERROR(gl.getError(), "glDisableVertexAttribArray");
2833 
2834     gl.viewport(0, 0, 128, 64);
2835     GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport");
2836 
2837     std::vector<GLuint> pixels;
2838     pixels.resize(64 * 64 * 2);
2839     gl.getTexImage(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid *)pixels.data());
2840     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexImage");
2841 
2842     bool result = true;
2843     for (int o = 0; o < (signed)outputs.size(); ++o)
2844     {
2845         GLuint output = pixels[(outputs[o].x + outputs[o].y * 64) + outputs[o].z * 64 * 64];
2846 
2847         if (!commonUtils::compareUintColors(output, outputs[o].value, 2))
2848         {
2849             m_testCtx.getLog() << tcu::TestLog::Message << "Invalid output color read at [" << (int)outputs[o].x << "/"
2850                                << (int)outputs[o].y << "/" << (int)outputs[o].z << "]. Expected: " << outputs[o].value
2851                                << ", "
2852                                << "Read: " << output << tcu::TestLog::EndMessage;
2853 
2854             result = false;
2855         }
2856     }
2857 
2858     if (fbo)
2859     {
2860         gl.deleteFramebuffers(1, &fbo);
2861         GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteFramebuffers");
2862     }
2863 
2864     if (texture)
2865     {
2866         gl.deleteTextures(1, &texture);
2867         GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteTextures");
2868     }
2869 
2870     return result;
2871 }
2872 
validMultiSamplingFunc(ValidationOutputVec & outputs)2873 bool SpirvValidationBuiltInVariableDecorationsTest::validMultiSamplingFunc(ValidationOutputVec &outputs)
2874 {
2875     const Functions &gl = m_context.getRenderContext().getFunctions();
2876 
2877     const GLfloat vertices[] = {-1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f};
2878 
2879     GLuint textureMS;
2880     GLuint texture;
2881     GLuint fboMS;
2882     GLuint fbo;
2883 
2884     gl.genTextures(1, &textureMS);
2885     GLU_EXPECT_NO_ERROR(gl.getError(), "genTextures");
2886     gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, textureMS);
2887     GLU_EXPECT_NO_ERROR(gl.getError(), "bindTexture");
2888     gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 2, GL_RGBA8, 32, 32, GL_TRUE);
2889     GLU_EXPECT_NO_ERROR(gl.getError(), "texStorage2DMultisample");
2890 
2891     gl.genTextures(1, &texture);
2892     GLU_EXPECT_NO_ERROR(gl.getError(), "genTextures");
2893     gl.bindTexture(GL_TEXTURE_2D, texture);
2894     GLU_EXPECT_NO_ERROR(gl.getError(), "bindTexture");
2895     gl.texStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 32, 32);
2896     GLU_EXPECT_NO_ERROR(gl.getError(), "texStorage2D");
2897 
2898     gl.genFramebuffers(1, &fboMS);
2899     GLU_EXPECT_NO_ERROR(gl.getError(), "genFramenuffers");
2900     gl.bindFramebuffer(GL_FRAMEBUFFER, fboMS);
2901     GLU_EXPECT_NO_ERROR(gl.getError(), "bindFramebuffer");
2902     gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, textureMS, 0);
2903     GLU_EXPECT_NO_ERROR(gl.getError(), "framebufferTexture2D");
2904 
2905     gl.genFramebuffers(1, &fbo);
2906     GLU_EXPECT_NO_ERROR(gl.getError(), "genFramenuffers");
2907     gl.bindFramebuffer(GL_FRAMEBUFFER, fbo);
2908     GLU_EXPECT_NO_ERROR(gl.getError(), "bindFramebuffer");
2909     gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
2910     GLU_EXPECT_NO_ERROR(gl.getError(), "framebufferTexture2D");
2911 
2912     gl.bindFramebuffer(GL_FRAMEBUFFER, fboMS);
2913     GLU_EXPECT_NO_ERROR(gl.getError(), "bindFramebuffer");
2914 
2915     gl.viewport(0, 0, 32, 32);
2916     GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport");
2917 
2918     gl.bufferData(GL_ARRAY_BUFFER, 9 * sizeof(GLfloat), (GLvoid *)vertices, GL_DYNAMIC_DRAW);
2919     GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData");
2920 
2921     gl.enable(GL_CLIP_DISTANCE0);
2922 
2923     gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
2924     GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor");
2925     gl.clear(GL_COLOR_BUFFER_BIT);
2926     GLU_EXPECT_NO_ERROR(gl.getError(), "glClear");
2927 
2928     gl.enableVertexAttribArray(0);
2929     GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray");
2930 
2931     gl.vertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, DE_NULL);
2932     GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer");
2933 
2934     gl.drawArrays(GL_TRIANGLES, 0, 3);
2935     GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArray");
2936 
2937     gl.disableVertexAttribArray(0);
2938     GLU_EXPECT_NO_ERROR(gl.getError(), "glDisableVertexAttribArray");
2939 
2940     gl.disable(GL_CLIP_DISTANCE0);
2941 
2942     gl.bindFramebuffer(GL_READ_FRAMEBUFFER, fboMS);
2943     GLU_EXPECT_NO_ERROR(gl.getError(), "bindFramebuffer");
2944     gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
2945     GLU_EXPECT_NO_ERROR(gl.getError(), "bindFramebuffer");
2946 
2947     gl.blitFramebuffer(0, 0, 32, 32, 0, 0, 32, 32, GL_COLOR_BUFFER_BIT, GL_NEAREST);
2948     GLU_EXPECT_NO_ERROR(gl.getError(), "blitFramebuffer");
2949 
2950     gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
2951     GLU_EXPECT_NO_ERROR(gl.getError(), "bindFramebuffer");
2952 
2953     const int epsilon = 2;
2954     bool result       = true;
2955     for (int o = 0; o < (signed)outputs.size(); ++o)
2956     {
2957         GLuint output;
2958         gl.readPixels(outputs[o].x, outputs[o].y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid *)&output);
2959         GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels");
2960 
2961         // The fragment shader for this case is rendering to a 2-sample FBO discarding
2962         // sample 0 and rendering 100% green to sample 1, so we expect a green output.
2963         // However, because sample locations may not be the same across implementations,
2964         // and that can influence their weights during the multisample resolve,
2965         // we can only check that there has to be some green in the output (since we know
2966         // that we have a green sample being selected) and that the level of green is not
2967         // 100% (since we know that pixel coverage is not 100% because we are
2968         // discarding one of the samples).
2969 
2970         int r1 = (output & 0xFF);
2971         int g1 = ((output >> 8) & 0xFF);
2972         int b1 = ((output >> 16) & 0xFF);
2973         int a1 = ((output >> 24) & 0xFF);
2974 
2975         int r2 = (outputs[o].value & 0xFF);
2976         int b2 = ((outputs[o].value >> 16) & 0xFF);
2977         int a2 = ((outputs[o].value >> 24) & 0xFF);
2978 
2979         if (r1 < r2 - epsilon || r1 > r2 + epsilon || g1 == 0x00 || g1 == 0xFF || b1 < b2 - epsilon ||
2980             b1 > b2 + epsilon || a1 < a2 - epsilon || a1 > a2 + epsilon)
2981         {
2982             m_testCtx.getLog() << tcu::TestLog::Message << "Invalid output color read at [" << (int)outputs[o].x << "/"
2983                                << (int)outputs[o].y << "]. Expected 0xff00xx00, with xx anything but ff or 00. "
2984                                << "Read: " << std::hex << output << tcu::TestLog::EndMessage;
2985 
2986             result = false;
2987         }
2988     }
2989 
2990     if (fboMS)
2991     {
2992         gl.deleteFramebuffers(1, &fboMS);
2993         GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteFramebuffers");
2994     }
2995 
2996     if (fbo)
2997     {
2998         gl.deleteFramebuffers(1, &fbo);
2999         GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteFramebuffers");
3000     }
3001 
3002     if (textureMS)
3003     {
3004         gl.deleteTextures(1, &texture);
3005         GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteTextures");
3006     }
3007 
3008     if (texture)
3009     {
3010         gl.deleteTextures(1, &texture);
3011         GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteTextures");
3012     }
3013 
3014     return result;
3015 }
3016 
3017 /** Constructor.
3018  *
3019  *  @param context     Rendering context
3020  *  @param name        Test name
3021  *  @param description Test description
3022  */
SpirvValidationCapabilitiesTest(deqp::Context & context)3023 SpirvValidationCapabilitiesTest::SpirvValidationCapabilitiesTest(deqp::Context &context)
3024     : TestCase(context, "spirv_validation_capabilities_test", "Test verifies if Spir-V capabilities works as expected.")
3025 {
3026     /* Left blank intentionally */
3027 }
3028 
3029 /** Stub init method */
init()3030 void SpirvValidationCapabilitiesTest::init()
3031 {
3032     ShaderStage computeStage;
3033     computeStage.source = ComputeSource("#version 450\n"
3034                                         "\n"
3035                                         "layout (local_size_x = 1, local_size_y = 2, local_size_z = 1) in;\n"
3036                                         "\n"
3037                                         "layout (location = 0, rgba8) uniform image2DMS img0;\n"
3038                                         "layout (location = 1, rgba8) uniform image2DMSArray img1;\n"
3039                                         "layout (location = 2, rgba8) uniform image2DRect img2;\n"
3040                                         "layout (location = 3, rgba8) uniform imageCube img3;\n"
3041                                         "layout (location = 4, rgba8) uniform imageCubeArray img4;\n"
3042                                         "layout (location = 5, rgba8) uniform imageBuffer img5;\n"
3043                                         "layout (location = 6, rgba8) uniform image2D img6;\n"
3044                                         "layout (location = 7, rgba8) uniform image1D img7;\n"
3045                                         "layout (location = 8) uniform writeonly image1D img8;\n"
3046                                         "layout (location = 9, rg32f) uniform image1D img9;\n"
3047                                         "layout (location = 10) uniform sampler2DRect img10;\n"
3048                                         "layout (location = 11) uniform samplerCubeArray img11;\n"
3049                                         "layout (location = 12) uniform samplerBuffer img12;\n"
3050                                         "layout (location = 13) uniform sampler1D img13;\n"
3051                                         "layout (location = 14) uniform sampler2D img14;\n"
3052                                         "\n"
3053                                         "layout (binding = 0) uniform atomic_uint atCounter;\n"
3054                                         "\n"
3055                                         "void main()\n"
3056                                         "{\n"
3057                                         "    ivec2 size = imageSize(img6);\n"
3058                                         "    ivec3 point = ivec3(gl_GlobalInvocationID);\n"
3059                                         "    imageStore(img0, point.xy, 0, vec4(0));\n"
3060                                         "    imageStore(img1, point, 0, vec4(0));\n"
3061                                         "    imageStore(img2, point.xy, vec4(0));\n"
3062                                         "    imageStore(img3, point, vec4(0));\n"
3063                                         "    imageStore(img4, point, vec4(0));\n"
3064                                         "    imageStore(img5, point.x, vec4(0));\n"
3065                                         "    imageStore(img6, point.xy, vec4(0));\n"
3066                                         "    imageStore(img7, point.x, vec4(0));\n"
3067                                         "    imageStore(img8, point.x, vec4(0));\n"
3068                                         "\n"
3069                                         "    vec3 coord = vec3(0);\n"
3070                                         "    ivec2 offset = ivec2(gl_GlobalInvocationID.xy);\n"
3071                                         "    vec4 color;\n"
3072                                         "    color = textureGather(img10, coord.xy);\n"
3073                                         "    color = textureGather(img11, vec4(0));\n"
3074                                         "    color = texelFetch(img12, point.x);\n"
3075                                         "    color = textureGatherOffset(img14, coord.xy, offset);\n"
3076                                         "    memoryBarrier();\n"
3077                                         "}\n");
3078 
3079     computeStage.caps.push_back("Shader");
3080     computeStage.caps.push_back("SampledRect Shader");
3081     computeStage.caps.push_back("SampledCubeArray Shader");
3082     computeStage.caps.push_back("SampledBuffer Shader");
3083     computeStage.caps.push_back("Sampled1D");
3084     computeStage.caps.push_back("ImageRect SampledRect Shader");
3085     computeStage.caps.push_back("Image1D Sampled1D");
3086     computeStage.caps.push_back("ImageCubeArray SampledCubeArray Shader");
3087     computeStage.caps.push_back("ImageBuffer SampledBuffer");
3088     computeStage.caps.push_back("ImageMSArray Shader");
3089     computeStage.caps.push_back("ImageQuery Shader");
3090     computeStage.caps.push_back("ImageGatherExtended Shader");
3091     computeStage.caps.push_back("StorageImageExtendedFormats Shader");
3092     computeStage.caps.push_back("StorageImageWriteWithoutFormat Shader");
3093     computeStage.caps.push_back("AtomicStorage Shader");
3094 
3095     ShaderStage vertexStage;
3096     vertexStage.source = VertexSource("#version 450\n"
3097                                       "\n"
3098                                       "layout (location = 0) in vec3 position;\n"
3099                                       "layout (location = 1) in mat4 projMatrix;\n"
3100                                       "\n"
3101                                       "layout (location = 2, xfb_buffer = 0) out float xfbVal;\n"
3102                                       "layout (location = 3) out vec2 texCoord;\n"
3103                                       "\n"
3104                                       "void main()\n"
3105                                       "{\n"
3106                                       "    double dval = double(position.x);\n"
3107                                       "    gl_Position = vec4(position, 1.0) * projMatrix;\n"
3108                                       "    gl_ClipDistance[0] = 0.0;\n"
3109                                       "    gl_CullDistance[0] = 0.0;\n"
3110                                       "\n"
3111                                       "    xfbVal = 1.0;\n"
3112                                       "    texCoord = vec2(0, 0);\n"
3113                                       "}\n");
3114 
3115     vertexStage.caps.push_back("Matrix");
3116     vertexStage.caps.push_back("Shader Matrix");
3117     vertexStage.caps.push_back("Float64");
3118     vertexStage.caps.push_back("ClipDistance Shader");
3119     vertexStage.caps.push_back("CullDistance Shader");
3120     vertexStage.caps.push_back("TransformFeedback Shader");
3121 
3122     ShaderStage tessCtrlStage;
3123     tessCtrlStage.source =
3124         TessellationControlSource("#version 450\n"
3125                                   "\n"
3126                                   "layout (vertices = 3) out;\n"
3127                                   "layout (location = 3) in vec2 texCoordIn[];\n"
3128                                   "layout (location = 3) out vec2 texCoordOut[];\n"
3129                                   "\n"
3130                                   "void main()\n"
3131                                   "{\n"
3132                                   "    if (gl_InvocationID == 0) {\n"
3133                                   "        gl_TessLevelOuter[0] = 1.0;\n"
3134                                   "        gl_TessLevelOuter[1] = 1.0;\n"
3135                                   "        gl_TessLevelOuter[2] = 1.0;\n"
3136                                   "        gl_TessLevelInner[0] = 1.0;\n"
3137                                   "    }\n"
3138                                   "\n"
3139                                   "    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
3140                                   "    gl_out[gl_InvocationID].gl_PointSize = gl_in[gl_InvocationID].gl_PointSize;\n"
3141                                   "    texCoordOut[gl_InvocationID] = texCoordIn[gl_InvocationID];\n"
3142                                   "}\n");
3143 
3144     tessCtrlStage.caps.push_back("Tessellation Shader");
3145     tessCtrlStage.caps.push_back("TessellationPointSize Tessellation");
3146 
3147     ShaderStage tessEvalStage;
3148     tessEvalStage.source = TessellationEvaluationSource("#version 450\n"
3149                                                         "\n"
3150                                                         "layout (triangles) in;\n"
3151                                                         "layout (location = 3) in vec2 texCoordIn[];\n"
3152                                                         "layout (location = 3) out vec2 texCoordOut;\n"
3153                                                         "\n"
3154                                                         "void main()\n"
3155                                                         "{\n"
3156                                                         "    gl_Position = gl_TessCoord.x * gl_in[0].gl_Position +\n"
3157                                                         "                  gl_TessCoord.y * gl_in[1].gl_Position +\n"
3158                                                         "                  gl_TessCoord.z * gl_in[2].gl_Position;\n"
3159                                                         "    texCoordOut = texCoordIn[0];\n"
3160                                                         "}\n");
3161 
3162     ShaderStage geometryStage;
3163     geometryStage.source = GeometrySource("#version 450\n"
3164                                           "\n"
3165                                           "layout (triangles) in;\n"
3166                                           "layout (triangle_strip, max_vertices = 3) out;\n"
3167                                           "layout (location = 3) in vec2 texCoordIn[];\n"
3168                                           "layout (location = 3) out vec2 texCoordOut;\n"
3169                                           "\n"
3170                                           "void main()\n"
3171                                           "{\n"
3172                                           "    gl_ViewportIndex = 0;\n"
3173                                           "    for (int i = 0; i < 3; ++i) {\n"
3174                                           "        gl_Position = gl_in[i].gl_Position;\n"
3175                                           "        gl_PointSize = gl_in[i].gl_PointSize;\n"
3176                                           "        texCoordOut = texCoordIn[i];\n"
3177                                           "        EmitStreamVertex(0);\n"
3178                                           "    }\n"
3179                                           "    EndStreamPrimitive(0);\n"
3180                                           "}\n");
3181 
3182     geometryStage.caps.push_back("Geometry Shader");
3183     geometryStage.caps.push_back("GeometryPointSize Geometry");
3184     geometryStage.caps.push_back("GeometryStreams Geometry");
3185     geometryStage.caps.push_back("MultiViewport Geometry");
3186 
3187     ShaderStage fragmentStage;
3188     fragmentStage.source = FragmentSource("#version 450\n"
3189                                           "\n"
3190                                           "layout (location = 3) in vec2 texCoord;\n"
3191                                           "\n"
3192                                           "layout (location = 0) out vec4 fColor;\n"
3193                                           "\n"
3194                                           "layout (location = 1) uniform sampler2D tex;\n"
3195                                           "\n"
3196                                           "void main()\n"
3197                                           "{\n"
3198                                           "    vec2 p = vec2(gl_SampleID);\n"
3199                                           "    vec2 dx = dFdxFine(p);\n"
3200                                           "\n"
3201                                           "    interpolateAtCentroid(texCoord);"
3202                                           "\n"
3203                                           "    fColor = vec4(1.0);\n"
3204                                           "}\n");
3205 
3206     fragmentStage.caps.push_back("Shader");
3207     fragmentStage.caps.push_back("DerivativeControl Shader");
3208     fragmentStage.caps.push_back("SampleRateShading");
3209     fragmentStage.caps.push_back("InterpolationFunction");
3210 
3211     ShaderStage dynamicIndexingStage;
3212     dynamicIndexingStage.source = ComputeSource("#version 450\n"
3213                                                 "\n"
3214                                                 "layout (location = 0) uniform sampler2D uniSamp[10];\n"
3215                                                 "layout (location = 10, rgba8) uniform image2D uniImg[10];\n"
3216                                                 "layout (binding = 5) uniform UniData\n"
3217                                                 "{\n"
3218                                                 "   int a[10];\n"
3219                                                 "} uniBuff[10];\n"
3220                                                 "layout (binding = 5) buffer StorageData\n"
3221                                                 "{\n"
3222                                                 "   int a[10];\n"
3223                                                 "} storageBuff[10];\n"
3224                                                 "\n"
3225                                                 "void main()\n"
3226                                                 "{\n"
3227                                                 "    vec2 coord = vec2(0.0);\n"
3228                                                 "    ivec2 point = ivec2(0);\n"
3229                                                 "\n"
3230                                                 "    int ret = 0;\n"
3231                                                 "    for (int i = 0; i < 10; ++i)"
3232                                                 "    {\n"
3233                                                 "        ret = ret + uniBuff[i].a[i] + storageBuff[i].a[i];\n"
3234                                                 "        textureGather(uniSamp[i], coord);\n"
3235                                                 "        imageLoad(uniImg[i], point);\n"
3236                                                 "    }\n"
3237                                                 "    memoryBarrier();\n"
3238                                                 "}\n");
3239 
3240     dynamicIndexingStage.caps.push_back("UniformBufferArrayDynamicIndexing");
3241     dynamicIndexingStage.caps.push_back("SampledImageArrayDynamicIndexing");
3242     dynamicIndexingStage.caps.push_back("StorageBufferArrayDynamicIndexing");
3243     dynamicIndexingStage.caps.push_back("StorageImageArrayDynamicIndexing");
3244 
3245     Pipeline computePipeline;
3246     computePipeline.push_back(computeStage);
3247 
3248     Pipeline standardPipeline;
3249     standardPipeline.push_back(vertexStage);
3250     standardPipeline.push_back(tessCtrlStage);
3251     standardPipeline.push_back(tessEvalStage);
3252     standardPipeline.push_back(geometryStage);
3253     standardPipeline.push_back(fragmentStage);
3254 
3255     Pipeline dynamicIndexingPipeline;
3256     dynamicIndexingPipeline.push_back(dynamicIndexingStage);
3257 
3258     m_pipelines.push_back(computePipeline);
3259     m_pipelines.push_back(standardPipeline);
3260     m_pipelines.push_back(dynamicIndexingPipeline);
3261 
3262     if (m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_int64"))
3263     {
3264         ShaderStage computeStageExt("GL_ARB_gpu_shader_int64");
3265         computeStageExt.source = ComputeSource("#version 450\n"
3266                                                "\n"
3267                                                "#extension GL_ARB_gpu_shader_int64 : require\n"
3268                                                "\n"
3269                                                "void main()\n"
3270                                                "{\n"
3271                                                "    int64_t ival = int64_t(gl_GlobalInvocationID.x);\n"
3272                                                "}\n");
3273         computeStageExt.caps.push_back("Int64");
3274 
3275         Pipeline extPipeline;
3276         extPipeline.push_back(computeStageExt);
3277 
3278         m_pipelines.push_back(extPipeline);
3279     }
3280 
3281     if (m_context.getContextInfo().isExtensionSupported("GL_ARB_sparse_texture2"))
3282     {
3283         {
3284             ShaderStage computeStageExt("GL_ARB_sparse_texture2");
3285             computeStageExt.source = ComputeSource("#version 450\n"
3286                                                    "\n"
3287                                                    "#extension GL_ARB_sparse_texture2 : require\n"
3288                                                    "\n"
3289                                                    "layout (location = 0) uniform sampler2D tex;\n"
3290                                                    "\n"
3291                                                    "void main()\n"
3292                                                    "{\n"
3293                                                    "    vec2 p = vec2(0.0);\n"
3294                                                    "\n"
3295                                                    "    vec4 spCol;\n"
3296                                                    "    sparseTextureARB(tex, p, spCol);\n"
3297                                                    "}\n");
3298 
3299             computeStageExt.caps.push_back("SparseResidency");
3300 
3301             Pipeline extPipeline;
3302             extPipeline.push_back(computeStageExt);
3303 
3304             m_pipelines.push_back(extPipeline);
3305         }
3306 
3307         if (m_context.getContextInfo().isExtensionSupported("GL_ARB_sparse_texture_clamp"))
3308         {
3309             ShaderStage vertexStageExt("GL_ARB_sparse_texture_clamp_vert");
3310             vertexStageExt.source = VertexSource("#version 450\n"
3311                                                  "\n"
3312                                                  "layout (location = 0) in vec4 pos;\n"
3313                                                  "\n"
3314                                                  "void main()\n"
3315                                                  "{\n"
3316                                                  "    gl_Position = pos;\n"
3317                                                  "}\n");
3318 
3319             ShaderStage fragmentStageExt("GL_ARB_sparse_texture_clamp_frag");
3320             fragmentStageExt.source = FragmentSource("#version 450\n"
3321                                                      "\n"
3322                                                      "#extension GL_ARB_sparse_texture2 : require\n"
3323                                                      "#extension GL_ARB_sparse_texture_clamp : require\n"
3324                                                      "\n"
3325                                                      "uniform sampler2D tex;\n"
3326                                                      "\n"
3327                                                      "layout (location = 0) out vec4 spCol;\n"
3328                                                      "\n"
3329                                                      "void main()\n"
3330                                                      "{\n"
3331                                                      "    vec2 p = vec2(0.0);\n"
3332                                                      "\n"
3333                                                      "    sparseTextureClampARB(tex, p, 0.5, spCol);\n"
3334                                                      "}\n");
3335 
3336             fragmentStageExt.caps.push_back("MinLod");
3337 
3338             Pipeline extPipeline;
3339             extPipeline.push_back(vertexStageExt);
3340             extPipeline.push_back(fragmentStageExt);
3341 
3342             m_pipelines.push_back(extPipeline);
3343         }
3344     }
3345 
3346     if (m_context.getContextInfo().isExtensionSupported("GL_EXT_shader_image_load_formatted"))
3347     {
3348         ShaderStage computeStageExt("GL_EXT_shader_image_load_formatted");
3349         computeStageExt.source = ComputeSource("#version 450\n"
3350                                                "\n"
3351                                                "#extension GL_EXT_shader_image_load_formatted : require\n"
3352                                                "\n"
3353                                                "layout (location = 0) uniform image2D img;\n"
3354                                                "\n"
3355                                                "void main()\n"
3356                                                "{\n"
3357                                                "    ivec3 point = ivec3(gl_GlobalInvocationID);\n"
3358                                                "    vec4 color = imageLoad(img, point.xy);\n"
3359                                                "}\n");
3360 
3361         computeStageExt.caps.push_back("StorageImageReadWithoutFormat");
3362 
3363         Pipeline extPipeline;
3364         extPipeline.push_back(computeStageExt);
3365 
3366         m_pipelines.push_back(extPipeline);
3367     }
3368 }
3369 
3370 /** Stub de-init method */
deinit()3371 void SpirvValidationCapabilitiesTest::deinit()
3372 {
3373 }
3374 
3375 /** Executes test iteration.
3376  *
3377  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
3378  */
iterate()3379 tcu::TestNode::IterateResult SpirvValidationCapabilitiesTest::iterate()
3380 {
3381     const Functions &gl = m_context.getRenderContext().getFunctions();
3382 
3383     for (int p = 0; p < (signed)m_pipelines.size(); ++p)
3384     {
3385         ProgramBinaries programBinaries;
3386 
3387         Pipeline &pipeline = m_pipelines[p];
3388         for (int s = 0; s < (signed)pipeline.size(); ++s)
3389         {
3390             ShaderStage &stage = pipeline[s];
3391             stage.binary       = spirvUtils::makeSpirV(m_context.getTestContext().getLog(), stage.source);
3392             std::stringstream ssw;
3393             if (stage.name.empty())
3394                 ssw << "gl_cts/data/spirv/spirv_validation_capabilities/binary_p" << p << "s" << s << ".nspv";
3395             else
3396                 ssw << "gl_cts/data/spirv/spirv_validation_capabilities/" << stage.name << ".nspv";
3397             commonUtils::writeSpirV(ssw.str().c_str(), stage.binary);
3398             programBinaries << stage.binary;
3399         }
3400 
3401         ShaderProgram program(gl, programBinaries);
3402         if (!program.isOk())
3403         {
3404             std::stringstream ssLog;
3405 
3406             ssLog << "Program build failed [" << p << "].\n";
3407             if (program.hasShader(SHADERTYPE_COMPUTE))
3408                 ssLog << "Compute: " << program.getShaderInfo(SHADERTYPE_COMPUTE).infoLog << "\n";
3409             if (program.hasShader(SHADERTYPE_VERTEX))
3410                 ssLog << "Vertex: " << program.getShaderInfo(SHADERTYPE_VERTEX).infoLog << "\n";
3411             if (program.hasShader(SHADERTYPE_TESSELLATION_CONTROL))
3412                 ssLog << "TessellationCtrl: " << program.getShaderInfo(SHADERTYPE_TESSELLATION_CONTROL).infoLog << "\n";
3413             if (program.hasShader(SHADERTYPE_TESSELLATION_EVALUATION))
3414                 ssLog << "TessellationEval: " << program.getShaderInfo(SHADERTYPE_TESSELLATION_EVALUATION).infoLog
3415                       << "\n";
3416             if (program.hasShader(SHADERTYPE_GEOMETRY))
3417                 ssLog << "Geometry: " << program.getShaderInfo(SHADERTYPE_GEOMETRY).infoLog << "\n";
3418             if (program.hasShader(SHADERTYPE_FRAGMENT))
3419                 ssLog << "Fragment: " << program.getShaderInfo(SHADERTYPE_FRAGMENT).infoLog << "\n";
3420             ssLog << "Program: " << program.getProgramInfo().infoLog;
3421 
3422             m_testCtx.getLog() << tcu::TestLog::Message << ssLog.str() << tcu::TestLog::EndMessage;
3423 
3424             m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
3425             return STOP;
3426         }
3427 
3428         for (int s = 0; s < (signed)pipeline.size(); ++s)
3429         {
3430             ShaderStage stage   = pipeline[s];
3431             ShaderBinary binary = stage.binary;
3432 
3433             std::string spirVSource;
3434             spirvUtils::spirvDisassemble(spirVSource, binary.binary);
3435 
3436             for (int c = 0; c < (signed)stage.caps.size(); ++c)
3437             {
3438                 std::string spirVSourceCut;
3439                 int foundCount = spirVCapabilityCutOff(spirVSource, spirVSourceCut, stage.caps, c);
3440 
3441                 if (foundCount == 0)
3442                 {
3443                     m_testCtx.getLog()
3444                         << tcu::TestLog::Message << "OpCapability (" << stage.caps[c] << ") [" << p << "/" << s
3445                         << "].\n"
3446                         << "Neither capability nor capabilities that depends on this capability has been found."
3447                         << tcu::TestLog::EndMessage;
3448                 }
3449                 else
3450                 {
3451                     // Assemble and validate cut off SpirV source
3452                     spirvUtils::spirvAssemble(binary.binary, spirVSourceCut);
3453                     if (spirvUtils::spirvValidate(binary.binary, false))
3454                     {
3455                         m_testCtx.getLog() << tcu::TestLog::Message << "OpCapability (" << stage.caps[c] << ") [" << p
3456                                            << "/" << s << "].\n"
3457                                            << "Validation passed without corresponding OpCapability declared."
3458                                            << tcu::TestLog::EndMessage;
3459                     }
3460                 }
3461             }
3462         }
3463     }
3464 
3465     m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
3466     return STOP;
3467 }
3468 
spirVCapabilityCutOff(std::string spirVSrcInput,std::string & spirVSrcOutput,CapabilitiesVec & capabilities,int & currentCapability)3469 int SpirvValidationCapabilitiesTest::spirVCapabilityCutOff(std::string spirVSrcInput, std::string &spirVSrcOutput,
3470                                                            CapabilitiesVec &capabilities, int &currentCapability)
3471 {
3472     std::vector<std::string> current = de::splitString(capabilities[currentCapability], ' ');
3473 
3474     CapabilitiesVec toDisable;
3475     toDisable.push_back(current[0]);
3476 
3477     // Search for capabilities that depends on current one as it should be removed either
3478     for (int cr = 0; cr < (signed)capabilities.size(); ++cr)
3479     {
3480         std::vector<std::string> split = de::splitString(capabilities[cr], ' ');
3481 
3482         if (split[0] == current[0])
3483             continue;
3484 
3485         for (int s = 1; s < (signed)split.size(); ++s)
3486         {
3487             if (split[s] == current[0])
3488                 toDisable.push_back(split[0]);
3489         }
3490     }
3491 
3492     // Disable current capability and capabilities that depends on it
3493     int foundCount = 0;
3494     spirVSrcOutput = spirVSrcInput;
3495     for (int d = 0; d < (signed)toDisable.size(); ++d)
3496     {
3497         std::string searchString = std::string("OpCapability ") + toDisable[d];
3498 
3499         size_t pos = spirVSrcOutput.find(searchString);
3500 
3501         if (pos != std::string::npos)
3502         {
3503             foundCount++;
3504             spirVSrcOutput.erase(pos, searchString.length());
3505         }
3506     }
3507 
3508     return foundCount;
3509 }
3510 
3511 /** Constructor.
3512  *
3513  *  @param context Rendering context.
3514  */
GlSpirvTests(deqp::Context & context)3515 GlSpirvTests::GlSpirvTests(deqp::Context &context)
3516     : TestCaseGroup(context, "gl_spirv", "Verify conformance of ARB_gl_spirv implementation")
3517 {
3518 }
3519 
3520 /** Initializes the test group contents. */
init()3521 void GlSpirvTests::init()
3522 {
3523     addChild(new SpirvModulesPositiveTest(m_context));
3524     addChild(new SpirvShaderBinaryMultipleShaderObjectsTest(m_context));
3525     addChild(new SpirvModulesStateQueriesTest(m_context));
3526     addChild(new SpirvModulesErrorVerificationTest(m_context));
3527     addChild(new SpirvGlslToSpirVEnableTest(m_context));
3528     addChild(new SpirvGlslToSpirVBuiltInFunctionsTest(m_context));
3529     addChild(new SpirvGlslToSpirVSpecializationConstantsTest(m_context));
3530     addChild(new SpirvValidationBuiltInVariableDecorationsTest(m_context));
3531     addChild(new SpirvValidationCapabilitiesTest(m_context));
3532 }
3533 
3534 } // namespace gl4cts
3535