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