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 ¤tCapability)
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