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