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