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), 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
~ShaderPipeline()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
getShaderParts(glu::ShaderType shaderType) const194 const char* const* ShaderBallotBaseTestCase::ShaderPipeline::getShaderParts(glu::ShaderType shaderType) const
195 {
196 return m_shaderChunks[shaderType];
197 }
198
getShaderPartsCount(glu::ShaderType shaderType) const199 unsigned int ShaderBallotBaseTestCase::ShaderPipeline::getShaderPartsCount(glu::ShaderType shaderType) const
200 {
201 return static_cast<unsigned int>(m_shaders[shaderType].size());
202 }
203
renderQuad(deqp::Context & context)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
executeComputeShader(deqp::Context & context)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
use(deqp::Context & context)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
test(deqp::Context & context)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
createShaderPrograms(ShaderPipeline & pipeline)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
~ShaderBallotBaseTestCase()368 ShaderBallotBaseTestCase::~ShaderBallotBaseTestCase()
369 {
370 for (ShaderPipelineIter iter = m_shaderPipelines.begin(); iter != m_shaderPipelines.end(); ++iter)
371 {
372 delete *iter;
373 }
374 }
375
validateScreenPixels(deqp::Context & context,tcu::Vec4 desiredColor,tcu::Vec4 ignoredColor)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
validateScreenPixelsSameColor(deqp::Context & context,tcu::Vec4 ignoredColor)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
434 glw::GLfloat* topLeftPixel = new glw::GLfloat[4];
435 topLeftPixel[0] = -1.0f;
436 topLeftPixel[1] = -1.0f;
437 topLeftPixel[2] = -1.0f;
438 topLeftPixel[3] = -1.0f;
439
440 // read pixel
441 gl.readPixels(0, 0, 1, 1, GL_RGBA, GL_FLOAT, topLeftPixel);
442
443 tcu::Vec4 desiredColor(topLeftPixel[0], topLeftPixel[1], topLeftPixel[2], topLeftPixel[3]);
444
445 delete[] topLeftPixel;
446
447 // validation
448 return ShaderBallotBaseTestCase::validateScreenPixels(context, desiredColor, ignoredColor);
449 }
450
validateColor(tcu::Vec4 testedColor,tcu::Vec4 desiredColor)451 bool ShaderBallotBaseTestCase::validateColor(tcu::Vec4 testedColor, tcu::Vec4 desiredColor)
452 {
453 const float epsilon = 0.008f;
454 return de::abs(testedColor.x() - desiredColor.x()) < epsilon &&
455 de::abs(testedColor.y() - desiredColor.y()) < epsilon &&
456 de::abs(testedColor.z() - desiredColor.z()) < epsilon &&
457 de::abs(testedColor.w() - desiredColor.w()) < epsilon;
458 }
459
460 /** Constructor.
461 *
462 * @param context Rendering context
463 */
ShaderBallotAvailabilityTestCase(deqp::Context & context)464 ShaderBallotAvailabilityTestCase::ShaderBallotAvailabilityTestCase(deqp::Context& context)
465 : ShaderBallotBaseTestCase(context, "ShaderBallotAvailability",
466 "Implements verification of availability for new build-in features")
467 {
468 std::string colorShaderSnippet =
469 " float red = gl_SubGroupSizeARB / 64.0f;\n"
470 " float green = 1.0f - (gl_SubGroupInvocationARB / float(gl_SubGroupSizeARB));\n"
471 " float blue = float(ballotARB(true) % 256) / 256.0f;\n"
472 " outColor = readInvocationARB(vec4(red, green, blue, 1.0f), gl_SubGroupInvocationARB);\n";
473
474 for (unsigned int i = 0; i <= glu::SHADERTYPE_COMPUTE; ++i)
475 {
476 m_shaderPipelines.push_back(new ShaderPipeline((glu::ShaderType)i, colorShaderSnippet));
477 }
478 }
479
480 /** Initializes the test
481 */
init()482 void ShaderBallotAvailabilityTestCase::init()
483 {
484 }
485
486 /** Executes test iteration.
487 *
488 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
489 */
iterate()490 tcu::TestNode::IterateResult ShaderBallotAvailabilityTestCase::iterate()
491 {
492 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_ballot") ||
493 !m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_int64"))
494 {
495 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not supported");
496 return STOP;
497 }
498
499 for (ShaderPipelineIter iter = m_shaderPipelines.begin(); iter != m_shaderPipelines.end(); ++iter)
500 {
501 createShaderPrograms(**iter);
502 }
503
504 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
505
506 for (ShaderPipelineIter pipelineIter = m_shaderPipelines.begin(); pipelineIter != m_shaderPipelines.end();
507 ++pipelineIter)
508 {
509 gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
510 gl.clear(GL_COLOR_BUFFER_BIT);
511
512 (*pipelineIter)->test(m_context);
513
514 gl.flush();
515 }
516
517 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
518 return STOP;
519 }
520
521 /** Constructor.
522 *
523 * @param context Rendering context
524 */
ShaderBallotBitmasksTestCase(deqp::Context & context)525 ShaderBallotBitmasksTestCase::ShaderBallotBitmasksTestCase(deqp::Context& context)
526 : ShaderBallotBaseTestCase(context, "ShaderBallotBitmasks",
527 "Implements verification of values of gl_SubGroup*MaskARB variables")
528 {
529 m_maskVars["gl_SubGroupEqMaskARB"] = "==";
530 m_maskVars["gl_SubGroupGeMaskARB"] = ">=";
531 m_maskVars["gl_SubGroupGtMaskARB"] = ">";
532 m_maskVars["gl_SubGroupLeMaskARB"] = "<=";
533 m_maskVars["gl_SubGroupLtMaskARB"] = "<";
534
535 std::string colorShaderSnippet = " uint64_t mask = 0;\n"
536 " for(uint i = 0; i < gl_SubGroupSizeARB; ++i)\n"
537 " {\n"
538 " if(i ${MASK_OPERATOR} gl_SubGroupInvocationARB)\n"
539 " mask = mask | (1ul << i);\n"
540 " }\n"
541 " float color = (${MASK_VAR} ^ mask) == 0ul ? 1.0 : 0.0;\n"
542 " outColor = vec4(color, color, color, 1.0);\n";
543
544 for (MaskVarIter maskIter = m_maskVars.begin(); maskIter != m_maskVars.end(); maskIter++)
545 {
546 for (unsigned int i = 0; i <= glu::SHADERTYPE_COMPUTE; ++i)
547 {
548 std::map<std::string, std::string> specMap;
549 specMap["MASK_VAR"] = maskIter->first;
550 specMap["MASK_OPERATOR"] = maskIter->second;
551 m_shaderPipelines.push_back(new ShaderPipeline((glu::ShaderType)i, colorShaderSnippet, specMap));
552 }
553 }
554 }
555
556 /** Initializes the test
557 */
init()558 void ShaderBallotBitmasksTestCase::init()
559 {
560 }
561
562 /** Executes test iteration.
563 *
564 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
565 */
iterate()566 tcu::TestNode::IterateResult ShaderBallotBitmasksTestCase::iterate()
567 {
568 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_ballot") ||
569 !m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_int64"))
570 {
571 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not supported");
572 return STOP;
573 }
574
575 for (ShaderPipelineIter iter = m_shaderPipelines.begin(); iter != m_shaderPipelines.end(); ++iter)
576 {
577 createShaderPrograms(**iter);
578 }
579
580 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
581
582 for (ShaderPipelineIter pipelineIter = m_shaderPipelines.begin(); pipelineIter != m_shaderPipelines.end();
583 ++pipelineIter)
584 {
585 gl.clearColor(1.0f, 0.0f, 0.0f, 1.0f);
586 gl.clear(GL_COLOR_BUFFER_BIT);
587
588 (*pipelineIter)->test(m_context);
589
590 gl.flush();
591
592 bool validationResult = ShaderBallotBaseTestCase::validateScreenPixels(
593 m_context, tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f), tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f));
594 TCU_CHECK_MSG(validationResult, "Bitmask value is not correct");
595 }
596
597 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
598 return STOP;
599 }
600
601 /** Constructor.
602 *
603 * @param context Rendering context
604 */
ShaderBallotFunctionBallotTestCase(deqp::Context & context)605 ShaderBallotFunctionBallotTestCase::ShaderBallotFunctionBallotTestCase(deqp::Context& context)
606 : ShaderBallotBaseTestCase(context, "ShaderBallotFunctionBallot",
607 "Implements verification of ballotARB calls and returned results")
608 {
609 std::string ballotFalseSnippet = " uint64_t result = ballotARB(false);\n"
610 " float color = result == 0ul ? 1.0 : 0.0;\n"
611 " outColor = vec4(color, color, color, 1.0);\n";
612
613 std::string ballotTrueSnippet = " uint64_t result = ballotARB(true);\n"
614 " float color = result != 0ul ? 1.0 : 0.0;\n"
615 " uint64_t invocationBit = 1ul << gl_SubGroupInvocationARB;\n"
616 " color *= float(invocationBit & result);\n"
617 " outColor = vec4(color, color, color, 1.0);\n";
618
619 std::string ballotMixedSnippet = " bool param = (gl_SubGroupInvocationARB % 2) == 0ul;\n"
620 " uint64_t result = ballotARB(param);\n"
621 " float color = (param && result != 0ul) || !param ? 1.0 : 0.0;\n"
622 " outColor = vec4(color, color, color, 1.0);\n";
623
624 for (unsigned int i = 0; i <= glu::SHADERTYPE_COMPUTE; ++i)
625 {
626 m_shaderPipelines.push_back(new ShaderPipeline((glu::ShaderType)i, ballotFalseSnippet));
627 m_shaderPipelines.push_back(new ShaderPipeline((glu::ShaderType)i, ballotTrueSnippet));
628 m_shaderPipelines.push_back(new ShaderPipeline((glu::ShaderType)i, ballotMixedSnippet));
629 }
630 }
631
632 /** Initializes the test
633 */
init()634 void ShaderBallotFunctionBallotTestCase::init()
635 {
636 }
637
638 /** Executes test iteration.
639 *
640 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
641 */
iterate()642 tcu::TestNode::IterateResult ShaderBallotFunctionBallotTestCase::iterate()
643 {
644 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_ballot") ||
645 !m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_int64"))
646 {
647 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not supported");
648 return STOP;
649 }
650
651 for (ShaderPipelineIter iter = m_shaderPipelines.begin(); iter != m_shaderPipelines.end(); ++iter)
652 {
653 createShaderPrograms(**iter);
654 }
655
656 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
657
658 for (ShaderPipelineIter pipelineIter = m_shaderPipelines.begin(); pipelineIter != m_shaderPipelines.end();
659 ++pipelineIter)
660 {
661 gl.clearColor(1.0f, 0.0f, 0.0f, 1.0f);
662 gl.clear(GL_COLOR_BUFFER_BIT);
663
664 (*pipelineIter)->test(m_context);
665
666 gl.flush();
667
668 bool validationResult = ShaderBallotBaseTestCase::validateScreenPixels(
669 m_context, tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f), tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f));
670 TCU_CHECK_MSG(validationResult, "Value returned from ballotARB function is not correct");
671 }
672
673 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
674 return STOP;
675 }
676
677 /** Constructor.
678 *
679 * @param context Rendering context
680 */
ShaderBallotFunctionReadTestCase(deqp::Context & context)681 ShaderBallotFunctionReadTestCase::ShaderBallotFunctionReadTestCase(deqp::Context& context)
682 : ShaderBallotBaseTestCase(context, "ShaderBallotFunctionRead",
683 "Implements verification of readInvocationARB and readFirstInvocationARB function calls")
684 {
685 std::string readFirstInvSnippet = "float color = 1.0f - (gl_SubGroupInvocationARB / float(gl_SubGroupSizeARB));\n"
686 "outColor = readFirstInvocationARB(vec4(color, color, color, 1.0f));\n";
687
688 std::string readInvSnippet = "float color = 1.0 - (gl_SubGroupInvocationARB / float(gl_SubGroupSizeARB));\n"
689 "uvec2 parts = unpackUint2x32(ballotARB(true));\n"
690 "uint invocation;\n"
691 "if (parts.x != 0) {\n"
692 " invocation = findLSB(parts.x);\n"
693 "} else {\n"
694 " invocation = findLSB(parts.y) + 32;\n"
695 "}\n"
696 "outColor = readInvocationARB(vec4(color, color, color, 1.0f), invocation);\n";
697
698 for (unsigned int i = 0; i <= glu::SHADERTYPE_COMPUTE; ++i)
699 {
700 m_shaderPipelines.push_back(new ShaderPipeline((glu::ShaderType)i, readFirstInvSnippet));
701 m_shaderPipelines.push_back(new ShaderPipeline((glu::ShaderType)i, readInvSnippet));
702 }
703 }
704
705 /** Initializes the test
706 */
init()707 void ShaderBallotFunctionReadTestCase::init()
708 {
709 }
710
711 /** Executes test iteration.
712 *
713 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
714 */
iterate()715 tcu::TestNode::IterateResult ShaderBallotFunctionReadTestCase::iterate()
716 {
717 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_ballot") ||
718 !m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_int64"))
719 {
720 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not supported");
721 return STOP;
722 }
723
724 for (ShaderPipelineIter iter = m_shaderPipelines.begin(); iter != m_shaderPipelines.end(); ++iter)
725 {
726 createShaderPrograms(**iter);
727 }
728
729 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
730 const tcu::RenderTarget renderTarget = m_context.getRenderContext().getRenderTarget();
731
732 gl.clearColor(1.0f, 0.0f, 0.0f, 1.0f);
733 gl.viewport(0, 0, 2, 2);
734
735 for (ShaderPipelineIter pipelineIter = m_shaderPipelines.begin(); pipelineIter != m_shaderPipelines.end();
736 ++pipelineIter)
737 {
738 gl.clear(GL_COLOR_BUFFER_BIT);
739
740 (*pipelineIter)->test(m_context);
741
742 gl.flush();
743
744 bool validationResult =
745 ShaderBallotBaseTestCase::validateScreenPixelsSameColor(m_context, tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f));
746 TCU_CHECK_MSG(validationResult, "Read functions result is not correct");
747 }
748
749 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
750 return STOP;
751 }
752
753 /** Constructor.
754 *
755 * @param context Rendering context.
756 **/
ShaderBallotTests(deqp::Context & context)757 ShaderBallotTests::ShaderBallotTests(deqp::Context& context)
758 : TestCaseGroup(context, "shader_ballot_tests", "Verify conformance of CTS_ARB_shader_ballot implementation")
759 {
760 }
761
762 /** Initializes the shader_ballot test group.
763 *
764 **/
init(void)765 void ShaderBallotTests::init(void)
766 {
767 addChild(new ShaderBallotAvailabilityTestCase(m_context));
768 addChild(new ShaderBallotBitmasksTestCase(m_context));
769 addChild(new ShaderBallotFunctionBallotTestCase(m_context));
770 addChild(new ShaderBallotFunctionReadTestCase(m_context));
771 }
772 } /* glcts namespace */
773