Merge vk-gl-cts/vulkan-cts-1.1.5 into vk-gl-cts/vulkan-cts-1.1.6
[platform/upstream/VK-GL-CTS.git] / external / openglcts / modules / gl / gl4cShaderBallotTests.cpp
1 /*-------------------------------------------------------------------------
2 * OpenGL Conformance Test Suite
3 * -----------------------------
4 *
5 * Copyright (c) 2014-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  gl4cShaderBallotTests.cpp
21 * \brief Conformance tests for the ARB_shader_ballot functionality.
22 */ /*-------------------------------------------------------------------*/
23
24 #include "gl4cShaderBallotTests.hpp"
25
26 #include "glcContext.hpp"
27 #include "gluContextInfo.hpp"
28 #include "gluDefs.hpp"
29 #include "gluDrawUtil.hpp"
30 #include "gluObjectWrapper.hpp"
31 #include "gluProgramInterfaceQuery.hpp"
32 #include "gluShaderProgram.hpp"
33 #include "glwEnums.hpp"
34 #include "glwFunctions.hpp"
35 #include "tcuRenderTarget.hpp"
36
37 namespace gl4cts
38 {
39
40 ShaderBallotBaseTestCase::ShaderPipeline::ShaderPipeline(glu::ShaderType        testedShader,
41                                                                                                                  const std::string& contentSnippet,
42                                                                                                                  std::map<std::string, std::string> specMap)
43         : m_programRender(NULL), m_programCompute(NULL), m_testedShader(testedShader), m_specializationMap(specMap)
44 {
45         std::string testedHeadPart = "#extension GL_ARB_shader_ballot : enable\n"
46                                                                  "#extension GL_ARB_gpu_shader_int64 : enable\n";
47
48         std::string testedContentPart = contentSnippet;
49
50         // vertex shader parts
51
52         m_shaders[glu::SHADERTYPE_VERTEX].push_back("#version 450 core\n");
53         m_shaders[glu::SHADERTYPE_VERTEX].push_back(m_testedShader == glu::SHADERTYPE_VERTEX ? testedHeadPart : "");
54         m_shaders[glu::SHADERTYPE_VERTEX].push_back("in highp vec2 inPosition;\n"
55                                                                                                 "in highp vec4 inColor;\n"
56                                                                                                 "out highp vec3 vsPosition;\n"
57                                                                                                 "out highp vec4 vsColor;\n"
58                                                                                                 "void main()\n"
59                                                                                                 "{\n"
60                                                                                                 "       gl_Position = vec4(inPosition, 0.0, 1.0);\n"
61                                                                                                 "       vsPosition = vec3(inPosition, 0.0);\n"
62                                                                                                 "       vec4 outColor = vec4(0.0); \n");
63         m_shaders[glu::SHADERTYPE_VERTEX].push_back(m_testedShader == glu::SHADERTYPE_VERTEX ? testedContentPart :
64                                                                                                                                                                                    "    outColor = inColor;\n");
65         m_shaders[glu::SHADERTYPE_VERTEX].push_back("   vsColor = outColor;\n"
66                                                                                                 "}\n");
67
68         // fragment shader parts
69
70         m_shaders[glu::SHADERTYPE_FRAGMENT].push_back("#version 450 core\n");
71         m_shaders[glu::SHADERTYPE_FRAGMENT].push_back(m_testedShader == glu::SHADERTYPE_FRAGMENT ? testedHeadPart : "");
72         m_shaders[glu::SHADERTYPE_FRAGMENT].push_back("in highp vec4 gsColor;\n"
73                                                                                                   "out highp vec4 fsColor;\n"
74                                                                                                   "void main()\n"
75                                                                                                   "{\n"
76                                                                                                   "     vec4 outColor = vec4(0.0); \n");
77         m_shaders[glu::SHADERTYPE_FRAGMENT].push_back(
78                 m_testedShader == glu::SHADERTYPE_FRAGMENT ? testedContentPart : "      outColor = gsColor;\n");
79         m_shaders[glu::SHADERTYPE_FRAGMENT].push_back(" fsColor = outColor;\n"
80                                                                                                   "}\n");
81
82         // tessellation control shader parts
83
84         m_shaders[glu::SHADERTYPE_TESSELLATION_CONTROL].push_back("#version 450 core\n");
85         m_shaders[glu::SHADERTYPE_TESSELLATION_CONTROL].push_back(
86                 m_testedShader == glu::SHADERTYPE_TESSELLATION_CONTROL ? testedHeadPart : "");
87         m_shaders[glu::SHADERTYPE_TESSELLATION_CONTROL].push_back(
88                 "layout(vertices = 3) out;\n"
89                 "in highp vec4 vsColor[];\n"
90                 "in highp vec3 vsPosition[];\n"
91                 "out highp vec3 tcsPosition[];\n"
92                 "out highp vec4 tcsColor[];\n"
93                 "void main()\n"
94                 "{\n"
95                 "       tcsPosition[gl_InvocationID] = vsPosition[gl_InvocationID];\n"
96                 "       vec4 outColor = vec4(0.0);\n");
97         m_shaders[glu::SHADERTYPE_TESSELLATION_CONTROL].push_back(m_testedShader == glu::SHADERTYPE_TESSELLATION_CONTROL ?
98                                                                                                                                   testedContentPart :
99                                                                                                                                   "     outColor = vsColor[gl_InvocationID];\n");
100         m_shaders[glu::SHADERTYPE_TESSELLATION_CONTROL].push_back("     tcsColor[gl_InvocationID] = outColor;\n"
101                                                                                                                           "     gl_TessLevelInner[0] = 3;\n"
102                                                                                                                           "     gl_TessLevelOuter[0] = 3;\n"
103                                                                                                                           "     gl_TessLevelOuter[1] = 3;\n"
104                                                                                                                           "     gl_TessLevelOuter[2] = 3;\n"
105                                                                                                                           "}\n");
106
107         // tessellation evaluation shader parts
108
109         m_shaders[glu::SHADERTYPE_TESSELLATION_EVALUATION].push_back("#version 450 core\n");
110         m_shaders[glu::SHADERTYPE_TESSELLATION_EVALUATION].push_back(
111                 m_testedShader == glu::SHADERTYPE_TESSELLATION_EVALUATION ? testedHeadPart : "");
112         m_shaders[glu::SHADERTYPE_TESSELLATION_EVALUATION].push_back("layout(triangles, equal_spacing, cw) in;\n"
113                                                                                                                                  "in highp vec3 tcsPosition[];\n"
114                                                                                                                                  "in highp vec4 tcsColor[];\n"
115                                                                                                                                  "out highp vec4 tesColor;\n"
116                                                                                                                                  "void main()\n"
117                                                                                                                                  "{\n"
118                                                                                                                                  "      vec3 p0 = gl_TessCoord.x * tcsPosition[0];\n"
119                                                                                                                                  "      vec3 p1 = gl_TessCoord.y * tcsPosition[1];\n"
120                                                                                                                                  "      vec3 p2 = gl_TessCoord.z * tcsPosition[2];\n"
121                                                                                                                                  "      vec4 outColor = vec4(0.0);\n");
122         m_shaders[glu::SHADERTYPE_TESSELLATION_EVALUATION].push_back(
123                 m_testedShader == glu::SHADERTYPE_TESSELLATION_EVALUATION ? testedContentPart : "       outColor = tcsColor[0];\n");
124         m_shaders[glu::SHADERTYPE_TESSELLATION_EVALUATION].push_back("  tesColor = outColor;\n"
125                                                                                                                                  "      gl_Position = vec4(normalize(p0 + p1 + p2), 1.0);\n"
126                                                                                                                                  "}\n");
127
128         // geometry shader parts
129
130         m_shaders[glu::SHADERTYPE_GEOMETRY].push_back("#version 450 core\n");
131         m_shaders[glu::SHADERTYPE_GEOMETRY].push_back(m_testedShader == glu::SHADERTYPE_GEOMETRY ? testedHeadPart : "");
132         m_shaders[glu::SHADERTYPE_GEOMETRY].push_back("layout(triangles) in;\n"
133                                                                                                   "layout(triangle_strip, max_vertices = 3) out;\n"
134                                                                                                   "in highp vec4 tesColor[];\n"
135                                                                                                   "out highp vec4 gsColor;\n"
136                                                                                                   "void main()\n"
137                                                                                                   "{\n"
138                                                                                                   "     for (int i = 0; i<3; i++)\n"
139                                                                                                   "     {\n"
140                                                                                                   "             gl_Position = gl_in[i].gl_Position;\n"
141                                                                                                   "             vec4 outColor = vec4(0.0);\n");
142         m_shaders[glu::SHADERTYPE_GEOMETRY].push_back(
143                 m_testedShader == glu::SHADERTYPE_GEOMETRY ? testedContentPart : "              outColor = tesColor[i];\n");
144         m_shaders[glu::SHADERTYPE_GEOMETRY].push_back("         gsColor = outColor;\n"
145                                                                                                   "             EmitVertex();\n"
146                                                                                                   "     }\n"
147                                                                                                   "     EndPrimitive();\n"
148                                                                                                   "}\n");
149
150         // compute shader parts
151
152         m_shaders[glu::SHADERTYPE_COMPUTE].push_back("#version 450 core\n");
153         m_shaders[glu::SHADERTYPE_COMPUTE].push_back(m_testedShader == glu::SHADERTYPE_COMPUTE ? testedHeadPart : "");
154         m_shaders[glu::SHADERTYPE_COMPUTE].push_back(
155                 "layout(rgba32f, binding = 1) writeonly uniform highp image2D destImage;\n"
156                 "layout (local_size_x = 16, local_size_y = 16) in;\n"
157                 "void main (void)\n"
158                 "{\n"
159                 "vec4 outColor = vec4(0.0);\n");
160         m_shaders[glu::SHADERTYPE_COMPUTE].push_back(m_testedShader == glu::SHADERTYPE_COMPUTE ? testedContentPart : "");
161         m_shaders[glu::SHADERTYPE_COMPUTE].push_back("imageStore(destImage, ivec2(gl_GlobalInvocationID.xy), outColor);\n"
162                                                                                                  "}\n");
163
164         // create shader chunks
165
166         for (unsigned int shaderType = 0; shaderType <= glu::SHADERTYPE_COMPUTE; ++shaderType)
167         {
168                 m_shaderChunks[shaderType] = new char*[m_shaders[shaderType].size()];
169                 for (unsigned int i = 0; i < m_shaders[i].size(); ++i)
170                 {
171                         m_shaderChunks[shaderType][i] = (char*)m_shaders[shaderType][i].data();
172                 }
173         }
174 }
175
176 ShaderBallotBaseTestCase::ShaderPipeline::~ShaderPipeline()
177 {
178         if (m_programRender)
179         {
180                 delete m_programRender;
181         }
182
183         if (m_programCompute)
184         {
185                 delete m_programCompute;
186         }
187
188         for (unsigned int shaderType = 0; shaderType <= glu::SHADERTYPE_COMPUTE; ++shaderType)
189         {
190                 delete[] m_shaderChunks[shaderType];
191         }
192 }
193
194 const char* const* ShaderBallotBaseTestCase::ShaderPipeline::getShaderParts(glu::ShaderType shaderType) const
195 {
196         return m_shaderChunks[shaderType];
197 }
198
199 unsigned int ShaderBallotBaseTestCase::ShaderPipeline::getShaderPartsCount(glu::ShaderType shaderType) const
200 {
201         return m_shaders[shaderType].size();
202 }
203
204 void ShaderBallotBaseTestCase::ShaderPipeline::renderQuad(deqp::Context& context)
205 {
206         const glw::Functions& gl = context.getRenderContext().getFunctions();
207
208         deUint16 const quadIndices[] = { 0, 1, 2, 2, 1, 3 };
209
210         float const position[] = { -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f };
211
212         glu::VertexArrayBinding vertexArrays[] = { glu::va::Float("inPosition", 2, 4, 0, position) };
213
214         this->use(context);
215
216         glu::PrimitiveList primitiveList = glu::pr::Patches(DE_LENGTH_OF_ARRAY(quadIndices), quadIndices);
217
218         glu::draw(context.getRenderContext(), m_programRender->getProgram(), DE_LENGTH_OF_ARRAY(vertexArrays), vertexArrays,
219                           primitiveList);
220
221         GLU_EXPECT_NO_ERROR(gl.getError(), "glu::draw error");
222 }
223
224 void ShaderBallotBaseTestCase::ShaderPipeline::executeComputeShader(deqp::Context& context)
225 {
226         const glw::Functions& gl = context.getRenderContext().getFunctions();
227
228         const glu::Texture outputTexture(context.getRenderContext());
229
230         gl.useProgram(m_programCompute->getProgram());
231
232         // output image
233         gl.bindTexture(GL_TEXTURE_2D, *outputTexture);
234         gl.texStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32UI, 16, 16);
235         gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
236         gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
237         GLU_EXPECT_NO_ERROR(gl.getError(), "Uploading image data failed");
238
239         // bind image
240         gl.bindImageTexture(1, *outputTexture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32UI);
241         GLU_EXPECT_NO_ERROR(gl.getError(), "Image setup failed");
242
243         // dispatch compute
244         gl.dispatchCompute(1, 1, 1);
245         GLU_EXPECT_NO_ERROR(gl.getError(), "glDispatchCompute()");
246
247         gl.memoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
248         GLU_EXPECT_NO_ERROR(gl.getError(), "glMemoryBarrier()");
249
250         // render output texture
251
252         std::string vs = "#version 450 core\n"
253                                          "in highp vec2 position;\n"
254                                          "in vec2 inTexcoord;\n"
255                                          "out vec2 texcoord;\n"
256                                          "void main()\n"
257                                          "{\n"
258                                          "      texcoord = inTexcoord;\n"
259                                          "      gl_Position = vec4(position, 0.0, 1.0);\n"
260                                          "}\n";
261
262         std::string fs = "#version 450 core\n"
263                                          "uniform sampler2D sampler;\n"
264                                          "in vec2 texcoord;\n"
265                                          "out vec4 color;\n"
266                                          "void main()\n"
267                                          "{\n"
268                                          "      color = texture(sampler, texcoord);\n"
269                                          "}\n";
270
271         glu::ProgramSources sources;
272         sources.sources[glu::SHADERTYPE_VERTEX].push_back(vs);
273         sources.sources[glu::SHADERTYPE_FRAGMENT].push_back(fs);
274         glu::ShaderProgram renderShader(context.getRenderContext(), sources);
275
276         if (!m_programRender->isOk())
277         {
278                 TCU_FAIL("Shader compilation failed");
279         }
280
281         gl.bindTexture(GL_TEXTURE_2D, *outputTexture);
282         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
283
284         gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
285         gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
286
287         gl.useProgram(renderShader.getProgram());
288
289         gl.uniform1i(gl.getUniformLocation(renderShader.getProgram(), "sampler"), 0);
290         GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i failed");
291
292         deUint16 const quadIndices[] = { 0, 1, 2, 2, 1, 3 };
293
294         float const position[] = { -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f };
295
296         float const texCoord[] = { 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f };
297
298         glu::VertexArrayBinding vertexArrays[] = { glu::va::Float("position", 2, 4, 0, position),
299                                                                                            glu::va::Float("inTexcoord", 2, 4, 0, texCoord) };
300
301         glu::draw(context.getRenderContext(), renderShader.getProgram(), DE_LENGTH_OF_ARRAY(vertexArrays), vertexArrays,
302                           glu::pr::TriangleStrip(DE_LENGTH_OF_ARRAY(quadIndices), quadIndices));
303
304         GLU_EXPECT_NO_ERROR(gl.getError(), "glu::draw error");
305 }
306
307 void ShaderBallotBaseTestCase::ShaderPipeline::use(deqp::Context& context)
308 {
309         const glw::Functions& gl = context.getRenderContext().getFunctions();
310         gl.useProgram(m_programRender->getProgram());
311         GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram failed");
312 }
313
314 void ShaderBallotBaseTestCase::ShaderPipeline::test(deqp::Context& context)
315 {
316         if (m_testedShader == glu::SHADERTYPE_COMPUTE)
317         {
318                 executeComputeShader(context);
319         }
320         else
321         {
322                 renderQuad(context);
323         }
324 }
325
326 void ShaderBallotBaseTestCase::createShaderPrograms(ShaderPipeline& pipeline)
327 {
328         glu::ProgramSources sourcesRender;
329
330         for (unsigned int i = 0; i < glu::SHADERTYPE_COMPUTE; ++i)
331         {
332                 glu::ShaderType shaderType = (glu::ShaderType)i;
333
334                 std::map<std::string, std::string>::const_iterator mapIter;
335                 for (mapIter = pipeline.getSpecializationMap().begin(); mapIter != pipeline.getSpecializationMap().end();
336                          mapIter++)
337                         m_specializationMap[mapIter->first] = mapIter->second;
338
339                 std::string shader =
340                         specializeShader(pipeline.getShaderPartsCount(shaderType), pipeline.getShaderParts(shaderType));
341                 sourcesRender.sources[i].push_back(shader);
342         }
343
344         glu::ShaderProgram* programRender = new glu::ShaderProgram(m_context.getRenderContext(), sourcesRender);
345
346         if (!programRender->isOk())
347         {
348                 TCU_FAIL("Shader compilation failed");
349         }
350
351         glu::ProgramSources sourcesCompute;
352
353         m_specializationMap.insert(pipeline.getSpecializationMap().begin(), pipeline.getSpecializationMap().end());
354         std::string shaderCompute = specializeShader(pipeline.getShaderPartsCount(glu::SHADERTYPE_COMPUTE),
355                                                                                                  pipeline.getShaderParts(glu::SHADERTYPE_COMPUTE));
356         sourcesCompute.sources[glu::SHADERTYPE_COMPUTE].push_back(shaderCompute);
357
358         glu::ShaderProgram* programCompute = new glu::ShaderProgram(m_context.getRenderContext(), sourcesCompute);
359
360         if (!programCompute->isOk())
361         {
362                 TCU_FAIL("Shader compilation failed");
363         }
364
365         pipeline.setShaderPrograms(programRender, programCompute);
366 }
367
368 ShaderBallotBaseTestCase::~ShaderBallotBaseTestCase()
369 {
370         for (ShaderPipelineIter iter = m_shaderPipelines.begin(); iter != m_shaderPipelines.end(); ++iter)
371         {
372                 delete *iter;
373         }
374 }
375
376 bool ShaderBallotBaseTestCase::validateScreenPixels(deqp::Context& context, tcu::Vec4 desiredColor,
377                                                                                                         tcu::Vec4 ignoredColor)
378 {
379         const glw::Functions&   gl                       = context.getRenderContext().getFunctions();
380         const tcu::RenderTarget renderTarget = context.getRenderContext().getRenderTarget();
381         tcu::IVec2                              size(renderTarget.getWidth(), renderTarget.getHeight());
382
383         glw::GLfloat* pixels = new glw::GLfloat[size.x() * size.y() * 4];
384
385         // clear buffer
386         for (int x = 0; x < size.x(); ++x)
387         {
388                 for (int y = 0; y < size.y(); ++y)
389                 {
390                         int mappedPixelPosition = y * size.x() + x;
391
392                         pixels[mappedPixelPosition * 4 + 0] = -1.0f;
393                         pixels[mappedPixelPosition * 4 + 1] = -1.0f;
394                         pixels[mappedPixelPosition * 4 + 2] = -1.0f;
395                         pixels[mappedPixelPosition * 4 + 3] = -1.0f;
396                 }
397         }
398
399         // read pixels
400         gl.readPixels(0, 0, size.x(), size.y(), GL_RGBA, GL_FLOAT, pixels);
401
402         // validate pixels
403         bool rendered = false;
404         for (int x = 0; x < size.x(); ++x)
405         {
406                 for (int y = 0; y < size.y(); ++y)
407                 {
408                         int mappedPixelPosition = y * size.x() + x;
409
410                         tcu::Vec4 color(pixels[mappedPixelPosition * 4 + 0], pixels[mappedPixelPosition * 4 + 1],
411                                                         pixels[mappedPixelPosition * 4 + 2], pixels[mappedPixelPosition * 4 + 3]);
412
413                         if (!ShaderBallotBaseTestCase::validateColor(color, ignoredColor))
414                         {
415                                 rendered = true;
416                                 if (!ShaderBallotBaseTestCase::validateColor(color, desiredColor))
417                                 {
418                                         return false;
419                                 }
420                         }
421                 }
422         }
423
424         delete[] pixels;
425
426         return rendered;
427 }
428
429 bool ShaderBallotBaseTestCase::validateScreenPixelsSameColor(deqp::Context& context, tcu::Vec4 ignoredColor)
430 {
431         const glw::Functions&   gl                       = context.getRenderContext().getFunctions();
432         const tcu::RenderTarget renderTarget = context.getRenderContext().getRenderTarget();
433         tcu::IVec2                              size(renderTarget.getWidth(), renderTarget.getHeight());
434
435         glw::GLfloat* centerPixel = new glw::GLfloat[4];
436         centerPixel[0]                    = -1.0f;
437         centerPixel[1]                    = -1.0f;
438         centerPixel[2]                    = -1.0f;
439         centerPixel[3]                    = -1.0f;
440
441         // read pixel
442         gl.readPixels(size.x() / 2, size.y() / 2, 1, 1, GL_RGBA, GL_FLOAT, centerPixel);
443
444         tcu::Vec4 desiredColor(centerPixel[0], centerPixel[1], centerPixel[2], centerPixel[3]);
445
446         delete[] centerPixel;
447
448         // validation
449         return ShaderBallotBaseTestCase::validateScreenPixels(context, desiredColor, ignoredColor);
450 }
451
452 bool ShaderBallotBaseTestCase::validateColor(tcu::Vec4 testedColor, tcu::Vec4 desiredColor)
453 {
454         const float epsilon = 0.008f;
455         return de::abs(testedColor.x() - desiredColor.x()) < epsilon &&
456                    de::abs(testedColor.y() - desiredColor.y()) < epsilon &&
457                    de::abs(testedColor.z() - desiredColor.z()) < epsilon &&
458                    de::abs(testedColor.w() - desiredColor.w()) < epsilon;
459 }
460
461 /** Constructor.
462 *
463 *  @param context Rendering context
464 */
465 ShaderBallotAvailabilityTestCase::ShaderBallotAvailabilityTestCase(deqp::Context& context)
466         : ShaderBallotBaseTestCase(context, "ShaderBallotAvailability",
467                                                            "Implements verification of availability for new build-in features")
468 {
469         std::string colorShaderSnippet =
470                 "       float red = gl_SubGroupSizeARB / 64.0f;\n"
471                 "       float green = 1.0f - (gl_SubGroupInvocationARB / float(gl_SubGroupSizeARB));\n"
472                 "       float blue = float(ballotARB(true) % 256) / 256.0f;\n"
473                 "       outColor = readInvocationARB(vec4(red, green, blue, 1.0f), gl_SubGroupInvocationARB);\n";
474
475         for (unsigned int i = 0; i <= glu::SHADERTYPE_COMPUTE; ++i)
476         {
477                 m_shaderPipelines.push_back(new ShaderPipeline((glu::ShaderType)i, colorShaderSnippet));
478         }
479 }
480
481 /** Initializes the test
482 */
483 void ShaderBallotAvailabilityTestCase::init()
484 {
485 }
486
487 /** Executes test iteration.
488 *
489 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
490 */
491 tcu::TestNode::IterateResult ShaderBallotAvailabilityTestCase::iterate()
492 {
493         if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_ballot") ||
494                 !m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_int64"))
495         {
496                 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not supported");
497                 return STOP;
498         }
499
500         for (ShaderPipelineIter iter = m_shaderPipelines.begin(); iter != m_shaderPipelines.end(); ++iter)
501         {
502                 createShaderPrograms(**iter);
503         }
504
505         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
506
507         for (ShaderPipelineIter pipelineIter = m_shaderPipelines.begin(); pipelineIter != m_shaderPipelines.end();
508                  ++pipelineIter)
509         {
510                 gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
511                 gl.clear(GL_COLOR_BUFFER_BIT);
512
513                 (*pipelineIter)->test(m_context);
514
515                 gl.flush();
516         }
517
518         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
519         return STOP;
520 }
521
522 /** Constructor.
523 *
524 *  @param context Rendering context
525 */
526 ShaderBallotBitmasksTestCase::ShaderBallotBitmasksTestCase(deqp::Context& context)
527         : ShaderBallotBaseTestCase(context, "ShaderBallotBitmasks",
528                                                            "Implements verification of values of gl_SubGroup*MaskARB variables")
529 {
530         m_maskVars["gl_SubGroupEqMaskARB"] = "==";
531         m_maskVars["gl_SubGroupGeMaskARB"] = ">=";
532         m_maskVars["gl_SubGroupGtMaskARB"] = ">";
533         m_maskVars["gl_SubGroupLeMaskARB"] = "<=";
534         m_maskVars["gl_SubGroupLtMaskARB"] = "<";
535
536         std::string colorShaderSnippet = "      uint64_t mask = 0;\n"
537                                                                          "      for(uint i = 0; i < gl_SubGroupSizeARB; ++i)\n"
538                                                                          "      {\n"
539                                                                          "              if(i ${MASK_OPERATOR} gl_SubGroupInvocationARB)\n"
540                                                                          "                      mask = mask | (1ul << i);\n"
541                                                                          "      }\n"
542                                                                          "      float color = (${MASK_VAR} ^ mask) == 0ul ? 1.0 : 0.0;\n"
543                                                                          "      outColor = vec4(color, color, color, 1.0);\n";
544
545         for (MaskVarIter maskIter = m_maskVars.begin(); maskIter != m_maskVars.end(); maskIter++)
546         {
547                 for (unsigned int i = 0; i <= glu::SHADERTYPE_COMPUTE; ++i)
548                 {
549                         std::map<std::string, std::string> specMap;
550                         specMap["MASK_VAR"]              = maskIter->first;
551                         specMap["MASK_OPERATOR"] = maskIter->second;
552                         m_shaderPipelines.push_back(new ShaderPipeline((glu::ShaderType)i, colorShaderSnippet, specMap));
553                 }
554         }
555 }
556
557 /** Initializes the test
558 */
559 void ShaderBallotBitmasksTestCase::init()
560 {
561 }
562
563 /** Executes test iteration.
564 *
565 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
566 */
567 tcu::TestNode::IterateResult ShaderBallotBitmasksTestCase::iterate()
568 {
569         if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_ballot") ||
570                 !m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_int64"))
571         {
572                 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not supported");
573                 return STOP;
574         }
575
576         for (ShaderPipelineIter iter = m_shaderPipelines.begin(); iter != m_shaderPipelines.end(); ++iter)
577         {
578                 createShaderPrograms(**iter);
579         }
580
581         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
582
583         for (ShaderPipelineIter pipelineIter = m_shaderPipelines.begin(); pipelineIter != m_shaderPipelines.end();
584                  ++pipelineIter)
585         {
586                 gl.clearColor(1.0f, 0.0f, 0.0f, 1.0f);
587                 gl.clear(GL_COLOR_BUFFER_BIT);
588
589                 (*pipelineIter)->test(m_context);
590
591                 gl.flush();
592
593                 bool validationResult = ShaderBallotBaseTestCase::validateScreenPixels(
594                         m_context, tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f), tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f));
595                 TCU_CHECK_MSG(validationResult, "Bitmask value is not correct");
596         }
597
598         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
599         return STOP;
600 }
601
602 /** Constructor.
603 *
604 *  @param context Rendering context
605 */
606 ShaderBallotFunctionBallotTestCase::ShaderBallotFunctionBallotTestCase(deqp::Context& context)
607         : ShaderBallotBaseTestCase(context, "ShaderBallotFunctionBallot",
608                                                            "Implements verification of ballotARB calls and returned results")
609 {
610         std::string ballotFalseSnippet = "      uint64_t result = ballotARB(false);\n"
611                                                                          "      float color = result == 0ul ? 1.0 : 0.0;\n"
612                                                                          "      outColor = vec4(color, color, color, 1.0);\n";
613
614         std::string ballotTrueSnippet = "       uint64_t result = ballotARB(true);\n"
615                                                                         "       float color = result != 0ul ? 1.0 : 0.0;\n"
616                                                                         "       uint64_t invocationBit = 1ul << gl_SubGroupInvocationARB;\n"
617                                                                         "       color *= float(invocationBit & result);\n"
618                                                                         "       outColor = vec4(color, color, color, 1.0);\n";
619
620         std::string ballotMixedSnippet = "      bool param = (gl_SubGroupInvocationARB % 2) == 0ul;\n"
621                                                                          "      uint64_t result = ballotARB(param);\n"
622                                                                          "      float color = (param && result != 0ul) || !param ? 1.0 : 0.0;\n"
623                                                                          "      outColor = vec4(color, color, color, 1.0);\n";
624
625         for (unsigned int i = 0; i <= glu::SHADERTYPE_COMPUTE; ++i)
626         {
627                 m_shaderPipelines.push_back(new ShaderPipeline((glu::ShaderType)i, ballotFalseSnippet));
628                 m_shaderPipelines.push_back(new ShaderPipeline((glu::ShaderType)i, ballotTrueSnippet));
629                 m_shaderPipelines.push_back(new ShaderPipeline((glu::ShaderType)i, ballotMixedSnippet));
630         }
631 }
632
633 /** Initializes the test
634 */
635 void ShaderBallotFunctionBallotTestCase::init()
636 {
637 }
638
639 /** Executes test iteration.
640 *
641 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
642 */
643 tcu::TestNode::IterateResult ShaderBallotFunctionBallotTestCase::iterate()
644 {
645         if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_ballot") ||
646                 !m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_int64"))
647         {
648                 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not supported");
649                 return STOP;
650         }
651
652         for (ShaderPipelineIter iter = m_shaderPipelines.begin(); iter != m_shaderPipelines.end(); ++iter)
653         {
654                 createShaderPrograms(**iter);
655         }
656
657         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
658
659         for (ShaderPipelineIter pipelineIter = m_shaderPipelines.begin(); pipelineIter != m_shaderPipelines.end();
660                  ++pipelineIter)
661         {
662                 gl.clearColor(1.0f, 0.0f, 0.0f, 1.0f);
663                 gl.clear(GL_COLOR_BUFFER_BIT);
664
665                 (*pipelineIter)->test(m_context);
666
667                 gl.flush();
668
669                 bool validationResult = ShaderBallotBaseTestCase::validateScreenPixels(
670                         m_context, tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f), tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f));
671                 TCU_CHECK_MSG(validationResult, "Value returned from ballotARB function is not correct");
672         }
673
674         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
675         return STOP;
676 }
677
678 /** Constructor.
679 *
680 *  @param context Rendering context
681 */
682 ShaderBallotFunctionReadTestCase::ShaderBallotFunctionReadTestCase(deqp::Context& context)
683         : ShaderBallotBaseTestCase(context, "ShaderBallotFunctionRead",
684                                                            "Implements verification of readInvocationARB and readFirstInvocationARB function calls")
685 {
686         std::string readFirstInvSnippet = "float color = 1.0f - (gl_SubGroupInvocationARB / float(gl_SubGroupSizeARB));\n"
687                                                                           "outColor = readFirstInvocationARB(vec4(color, color, color, 1.0f));\n";
688
689         std::string readInvSnippet = "float color = 1.0 - (gl_SubGroupInvocationARB / float(gl_SubGroupSizeARB));\n"
690                                                                  "uvec2 parts = unpackUint2x32(ballotARB(true));\n"
691                                                                  "uint invocation;\n"
692                                                                  "if (parts.x != 0) {\n"
693                                                                  "    invocation = findLSB(parts.x);\n"
694                                                                  "} else {\n"
695                                                                  "    invocation = findLSB(parts.y) + 32;\n"
696                                                                  "}\n"
697                                                                  "outColor = readInvocationARB(vec4(color, color, color, 1.0f), invocation);\n";
698
699         for (unsigned int i = 0; i <= glu::SHADERTYPE_COMPUTE; ++i)
700         {
701                 m_shaderPipelines.push_back(new ShaderPipeline((glu::ShaderType)i, readFirstInvSnippet));
702                 m_shaderPipelines.push_back(new ShaderPipeline((glu::ShaderType)i, readInvSnippet));
703         }
704 }
705
706 /** Initializes the test
707 */
708 void ShaderBallotFunctionReadTestCase::init()
709 {
710 }
711
712 /** Executes test iteration.
713 *
714 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
715 */
716 tcu::TestNode::IterateResult ShaderBallotFunctionReadTestCase::iterate()
717 {
718         if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_ballot") ||
719                 !m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_int64"))
720         {
721                 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not supported");
722                 return STOP;
723         }
724
725         for (ShaderPipelineIter iter = m_shaderPipelines.begin(); iter != m_shaderPipelines.end(); ++iter)
726         {
727                 createShaderPrograms(**iter);
728         }
729
730         const glw::Functions&   gl                       = m_context.getRenderContext().getFunctions();
731         const tcu::RenderTarget renderTarget = m_context.getRenderContext().getRenderTarget();
732
733         gl.clearColor(1.0f, 0.0f, 0.0f, 1.0f);
734         gl.viewport(renderTarget.getWidth() / 2 - 1, renderTarget.getHeight() / 2 - 1, 2, 2);
735
736         for (ShaderPipelineIter pipelineIter = m_shaderPipelines.begin(); pipelineIter != m_shaderPipelines.end();
737                  ++pipelineIter)
738         {
739                 gl.clear(GL_COLOR_BUFFER_BIT);
740
741                 (*pipelineIter)->test(m_context);
742
743                 gl.flush();
744
745                 bool validationResult =
746                         ShaderBallotBaseTestCase::validateScreenPixelsSameColor(m_context, tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f));
747                 TCU_CHECK_MSG(validationResult, "Read functions result is not correct");
748         }
749
750         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
751         return STOP;
752 }
753
754 /** Constructor.
755 *
756 *  @param context Rendering context.
757 **/
758 ShaderBallotTests::ShaderBallotTests(deqp::Context& context)
759         : TestCaseGroup(context, "shader_ballot_tests", "Verify conformance of CTS_ARB_shader_ballot implementation")
760 {
761 }
762
763 /** Initializes the shader_ballot test group.
764 *
765 **/
766 void ShaderBallotTests::init(void)
767 {
768         addChild(new ShaderBallotAvailabilityTestCase(m_context));
769         addChild(new ShaderBallotBitmasksTestCase(m_context));
770         addChild(new ShaderBallotFunctionBallotTestCase(m_context));
771         addChild(new ShaderBallotFunctionReadTestCase(m_context));
772 }
773 } /* glcts namespace */