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