1 /*------------------------------------------------------------------------
2 * OpenGL Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2017-2019 The Khronos Group Inc.
6 * Copyright (c) 2017 Codeplay Software Ltd.
7 * Copyright (c) 2019 NVIDIA Corporation.
8 *
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
12 *
13 * http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 *
21 */ /*!
22 * \file
23 * \brief Subgroups Tests Utils
24 */ /*--------------------------------------------------------------------*/
25
26 #include "glcSubgroupsTestsUtils.hpp"
27 #include "deRandom.hpp"
28 #include "tcuCommandLine.hpp"
29 #include "tcuStringTemplate.hpp"
30 #include "gluContextInfo.hpp"
31 #include "gluShaderUtil.hpp"
32
33 using namespace deqp;
34 using namespace std;
35 using namespace glc;
36 using namespace glw;
37
38 namespace
39 {
40 // debug callback function
41 // To use:
42 // gl.enable(GL_DEBUG_OUTPUT);
43 // gl.debugMessageCallback(debugCallback, &context);
44 //
debugCallback(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const char * message,const void * userParam)45 void debugCallback(GLenum source, GLenum type, GLuint id, GLenum severity,
46 GLsizei length, const char * message, const void * userParam)
47 {
48 glc::Context *context = (glc::Context *)userParam;
49
50 tcu::TestLog& log = context->getDeqpContext().getTestContext().getLog();
51
52 log << tcu::TestLog::Message
53 << "DEBUG: source = " << source << ", type= " << type << ", id = " << id << ", severity = " << severity
54 << ", length = " << length << "\n"
55 << "DEBUG: `" << message << "`"
56 << tcu::TestLog::EndMessage;
57
58 }
59
60 // getFormatReadInfo
61 // returns the stride in bytes
getFormatReadInfo(const subgroups::Format format,GLenum & readFormat,GLenum & readType)62 deUint32 getFormatReadInfo(const subgroups::Format format, GLenum &readFormat, GLenum &readType)
63 {
64 using namespace subgroups;
65 switch (format)
66 {
67 default:
68 DE_FATAL("Unhandled format!");
69 // fall-through
70 case FORMAT_R32G32B32A32_SFLOAT:
71 readFormat = GL_RGBA;
72 readType = GL_FLOAT;
73 return 4u;
74 case FORMAT_R32G32_SFLOAT:
75 readFormat = GL_RG;
76 readType = GL_FLOAT;
77 return 2u;
78 case FORMAT_R32_UINT:
79 readFormat = GL_RED_INTEGER;
80 readType = GL_UNSIGNED_INT;
81 return 1u;
82 case FORMAT_R32G32B32A32_UINT:
83 readFormat = GL_RGBA_INTEGER;
84 readType = GL_UNSIGNED_INT;
85 return 4u;
86 }
87 }
88
getMaxWidth()89 deUint32 getMaxWidth ()
90 {
91 return 1024u;
92 }
93
getNextWidth(const deUint32 width)94 deUint32 getNextWidth (const deUint32 width)
95 {
96 if (width < 128)
97 {
98 // This ensures we test every value up to 128 (the max subgroup size).
99 return width + 1;
100 }
101 else
102 {
103 // And once we hit 128 we increment to only power of 2's to reduce testing time.
104 return width * 2;
105 }
106 }
107
getFormatSizeInBytes(const subgroups::Format format)108 deUint32 getFormatSizeInBytes(const subgroups::Format format)
109 {
110 using namespace subgroups;
111 switch (format)
112 {
113 default:
114 DE_FATAL("Unhandled format!");
115 return 0;
116 case FORMAT_R32_SINT:
117 case FORMAT_R32_UINT:
118 return sizeof(deInt32);
119 case FORMAT_R32G32_SINT:
120 case FORMAT_R32G32_UINT:
121 return static_cast<deUint32>(sizeof(deInt32) * 2);
122 case FORMAT_R32G32B32_SINT:
123 case FORMAT_R32G32B32_UINT:
124 case FORMAT_R32G32B32A32_SINT:
125 case FORMAT_R32G32B32A32_UINT:
126 return static_cast<deUint32>(sizeof(deInt32) * 4);
127 case FORMAT_R32_SFLOAT:
128 return 4;
129 case FORMAT_R32G32_SFLOAT:
130 return 8;
131 case FORMAT_R32G32B32_SFLOAT:
132 return 16;
133 case FORMAT_R32G32B32A32_SFLOAT:
134 return 16;
135 case FORMAT_R64_SFLOAT:
136 return 8;
137 case FORMAT_R64G64_SFLOAT:
138 return 16;
139 case FORMAT_R64G64B64_SFLOAT:
140 return 32;
141 case FORMAT_R64G64B64A64_SFLOAT:
142 return 32;
143 // The below formats are used to represent bool and bvec* types. These
144 // types are passed to the shader as int and ivec* types, before the
145 // calculations are done as booleans. We need a distinct type here so
146 // that the shader generators can switch on it and generate the correct
147 // shader source for testing.
148 case FORMAT_R32_BOOL:
149 return sizeof(deInt32);
150 case FORMAT_R32G32_BOOL:
151 return static_cast<deUint32>(sizeof(deInt32) * 2);
152 case FORMAT_R32G32B32_BOOL:
153 case FORMAT_R32G32B32A32_BOOL:
154 return static_cast<deUint32>(sizeof(deInt32) * 4);
155 }
156 }
157
getElementSizeInBytes(const subgroups::Format format,const subgroups::SSBOData::InputDataLayoutType layout)158 deUint32 getElementSizeInBytes(
159 const subgroups::Format format,
160 const subgroups::SSBOData::InputDataLayoutType layout)
161 {
162 deUint32 bytes = getFormatSizeInBytes(format);
163 if (layout == subgroups::SSBOData::LayoutStd140)
164 return bytes < 16 ? 16 : bytes;
165 else
166 return bytes;
167 }
168
169
makeGraphicsPipeline(glc::Context & context,const subgroups::ShaderStageFlags stages,const GlslSource * vshader,const GlslSource * fshader,const GlslSource * gshader,const GlslSource * tcshader,const GlslSource * teshader)170 de::MovePtr<glu::ShaderProgram> makeGraphicsPipeline(glc::Context& context,
171 const subgroups::ShaderStageFlags stages,
172 const GlslSource * vshader,
173 const GlslSource * fshader,
174 const GlslSource * gshader,
175 const GlslSource * tcshader,
176 const GlslSource * teshader)
177 {
178 tcu::TestLog& log = context.getDeqpContext().getTestContext().getLog();
179 const bool doShaderLog = log.isShaderLoggingEnabled();
180 DE_UNREF(stages); // only used for asserts
181
182 map<string, string> templateArgs;
183 string versionDecl(getGLSLVersionDeclaration(context.getGLSLVersion()));
184 templateArgs.insert(pair<string, string>("VERSION_DECL", versionDecl));
185
186 string vertSource, tescSource, teseSource, geomSource, fragSource;
187 if (vshader)
188 {
189 DE_ASSERT(stages & subgroups::SHADER_STAGE_VERTEX_BIT);
190 tcu::StringTemplate shaderTemplate(vshader->sources[glu::SHADERTYPE_VERTEX][0]);
191 string shaderSource(shaderTemplate.specialize(templateArgs));
192 if (doShaderLog)
193 {
194 log << tcu::TestLog::Message << "vertex shader:\n"
195 << shaderSource << "\n:end:" << tcu::TestLog::EndMessage;
196 }
197 vertSource = shaderSource;
198 }
199 if (tcshader)
200 {
201 DE_ASSERT(stages & subgroups::SHADER_STAGE_TESS_CONTROL_BIT);
202 tcu::StringTemplate shaderTemplate(tcshader->sources[glu::SHADERTYPE_TESSELLATION_CONTROL][0]);
203 string shaderSource(shaderTemplate.specialize(templateArgs));
204 if (doShaderLog)
205 {
206 log << tcu::TestLog::Message << "tess control shader:\n"
207 << shaderSource << "\n:end:" << tcu::TestLog::EndMessage;
208 }
209 tescSource = shaderSource;
210 }
211 if (teshader)
212 {
213 DE_ASSERT(stages & subgroups::SHADER_STAGE_TESS_EVALUATION_BIT);
214 tcu::StringTemplate shaderTemplate(teshader->sources[glu::SHADERTYPE_TESSELLATION_EVALUATION][0]);
215 string shaderSource(shaderTemplate.specialize(templateArgs));
216 if (doShaderLog)
217 {
218 log << tcu::TestLog::Message << "tess eval shader:\n"
219 << shaderSource << "\n:end:" << tcu::TestLog::EndMessage;
220 }
221 teseSource = shaderSource;
222 }
223 if (gshader)
224 {
225 DE_ASSERT(stages & subgroups::SHADER_STAGE_GEOMETRY_BIT);
226 tcu::StringTemplate shaderTemplate(gshader->sources[glu::SHADERTYPE_GEOMETRY][0]);
227 string shaderSource(shaderTemplate.specialize(templateArgs));
228 if (doShaderLog)
229 {
230 log << tcu::TestLog::Message << "geometry shader:\n"
231 << shaderSource << "\n:end:" << tcu::TestLog::EndMessage;
232 }
233 geomSource = shaderSource;
234 }
235 if (fshader)
236 {
237 DE_ASSERT(stages & subgroups::SHADER_STAGE_FRAGMENT_BIT);
238 tcu::StringTemplate shaderTemplate(fshader->sources[glu::SHADERTYPE_FRAGMENT][0]);
239 string shaderSource(shaderTemplate.specialize(templateArgs));
240 if (doShaderLog)
241 {
242 log << tcu::TestLog::Message << "fragment shader:\n"
243 << shaderSource << "\n:end:" << tcu::TestLog::EndMessage;
244 }
245 fragSource = shaderSource;
246 }
247
248 glu::ShaderProgram *program = DE_NULL;
249 if(context.getShaderType() == SHADER_TYPE_GLSL)
250 {
251 glu::ProgramSources sources;
252 if (vshader)
253 sources << glu::VertexSource(vertSource);
254 if (tcshader)
255 sources << glu::TessellationControlSource(tescSource);
256 if (teshader)
257 sources << glu::TessellationEvaluationSource(teseSource);
258 if (gshader)
259 sources << glu::GeometrySource(geomSource);
260 if (fshader)
261 sources << glu::FragmentSource(fragSource);
262
263 program = new glu::ShaderProgram(context.getDeqpContext().getRenderContext().getFunctions(), sources);
264 } else {
265 DE_ASSERT(context.getShaderType() == SHADER_TYPE_SPIRV);
266
267 glu::ProgramBinaries binaries;
268 if (vshader)
269 binaries << spirvUtils::makeSpirV(log, glu::VertexSource(vertSource), spirvUtils::SPIRV_VERSION_1_3);
270 if (tcshader)
271 binaries << spirvUtils::makeSpirV(log, glu::TessellationControlSource(tescSource), spirvUtils::SPIRV_VERSION_1_3);
272 if (teshader)
273 binaries << spirvUtils::makeSpirV(log, glu::TessellationEvaluationSource(teseSource), spirvUtils::SPIRV_VERSION_1_3);
274 if (gshader)
275 binaries << spirvUtils::makeSpirV(log, glu::GeometrySource(geomSource), spirvUtils::SPIRV_VERSION_1_3);
276 if (fshader)
277 binaries << spirvUtils::makeSpirV(log, glu::FragmentSource(fragSource), spirvUtils::SPIRV_VERSION_1_3);
278
279 program = new glu::ShaderProgram(context.getDeqpContext().getRenderContext().getFunctions(), binaries);
280 }
281
282 if (!program->isOk())
283 {
284 log << tcu::TestLog::Message << "Shader build failed.\n"
285 << "Vertex: " << (vshader ? program->getShaderInfo(glu::SHADERTYPE_VERTEX).infoLog : "n/a") << "\n"
286 << "Tess Cont: " << (tcshader ? program->getShaderInfo(glu::SHADERTYPE_TESSELLATION_CONTROL).infoLog : "n/a") << "\n"
287 << "Tess Eval: " << (teshader ? program->getShaderInfo(glu::SHADERTYPE_TESSELLATION_EVALUATION).infoLog : "n/a") << "\n"
288 << "Geometry: " << (gshader ? program->getShaderInfo(glu::SHADERTYPE_GEOMETRY).infoLog : "n/a") << "\n"
289 << "Fragment: " << (fshader ? program->getShaderInfo(glu::SHADERTYPE_FRAGMENT).infoLog : "n/a") << "\n"
290 << "Program: " << program->getProgramInfo().infoLog << tcu::TestLog::EndMessage;
291 }
292 return de::MovePtr<glu::ShaderProgram>(program);
293 }
294
makeComputePipeline(glc::Context & context,const GlslSource & glslTemplate,deUint32 localSizeX,deUint32 localSizeY,deUint32 localSizeZ)295 de::MovePtr<glu::ShaderProgram> makeComputePipeline(glc::Context& context, const GlslSource &glslTemplate,
296 deUint32 localSizeX, deUint32 localSizeY, deUint32 localSizeZ)
297 {
298
299 tcu::TestLog& log = context.getDeqpContext().getTestContext().getLog();
300 const bool doShaderLog = log.isShaderLoggingEnabled();
301
302 tcu::StringTemplate computeTemplate(glslTemplate.sources[glu::SHADERTYPE_COMPUTE][0]);
303
304 map<string, string> templateArgs;
305 {
306 stringstream localSize;
307 localSize << "local_size_x = " << localSizeX;
308 templateArgs.insert(pair<string, string>("LOCAL_SIZE_X", localSize.str()));
309 }
310 {
311 stringstream localSize;
312 localSize << "local_size_y = " << localSizeY;
313 templateArgs.insert(pair<string, string>("LOCAL_SIZE_Y", localSize.str()));
314 }
315 {
316 stringstream localSize;
317 localSize << "local_size_z = " << localSizeZ;
318 templateArgs.insert(pair<string, string>("LOCAL_SIZE_Z", localSize.str()));
319 }
320 string versionDecl(getGLSLVersionDeclaration(context.getGLSLVersion()));
321 templateArgs.insert(pair<string, string>("VERSION_DECL", versionDecl));
322
323 glu::ComputeSource cshader(glu::ComputeSource(computeTemplate.specialize(templateArgs)));
324
325 if (doShaderLog)
326 {
327 log << tcu::TestLog::Message << "compute shader specialized source:\n"
328 << cshader.source << "\n:end:" << tcu::TestLog::EndMessage;
329 }
330
331 glu::ShaderProgram *program = DE_NULL;
332 if(context.getShaderType() == SHADER_TYPE_GLSL)
333 {
334 glu::ProgramSources sources;
335 sources << cshader;
336 program = new glu::ShaderProgram(context.getDeqpContext().getRenderContext().getFunctions(), sources);
337 } else {
338 DE_ASSERT(context.getShaderType() == SHADER_TYPE_SPIRV);
339
340 glu::ProgramBinaries binaries;
341 binaries << spirvUtils::makeSpirV(log, cshader, spirvUtils::SPIRV_VERSION_1_3);
342
343 program = new glu::ShaderProgram(context.getDeqpContext().getRenderContext().getFunctions(), binaries);
344 }
345
346 if (!program->isOk())
347 {
348 log << tcu::TestLog::Message << "Shader build failed.\n"
349 << "Compute: " << program->getShaderInfo(glu::SHADERTYPE_COMPUTE).infoLog << "\n"
350 << "Program: " << program->getProgramInfo().infoLog << tcu::TestLog::EndMessage;
351 }
352 return de::MovePtr<glu::ShaderProgram>(program);
353 }
354
355 struct Buffer;
356 struct Image;
357
358 struct BufferOrImage
359 {
isImage__anon5dfb49870111::BufferOrImage360 bool isImage() const
361 {
362 return m_isImage;
363 }
364
getAsBuffer__anon5dfb49870111::BufferOrImage365 Buffer* getAsBuffer()
366 {
367 if (m_isImage) DE_FATAL("Trying to get a buffer as an image!");
368 return reinterpret_cast<Buffer* >(this);
369 }
370
getAsImage__anon5dfb49870111::BufferOrImage371 Image* getAsImage()
372 {
373 if (!m_isImage) DE_FATAL("Trying to get an image as a buffer!");
374 return reinterpret_cast<Image*>(this);
375 }
376
getType__anon5dfb49870111::BufferOrImage377 virtual subgroups::DescriptorType getType() const
378 {
379 if (m_isImage)
380 {
381 return subgroups::DESCRIPTOR_TYPE_STORAGE_IMAGE;
382 }
383 else
384 {
385 return subgroups::DESCRIPTOR_TYPE_STORAGE_BUFFER;
386 }
387 }
388
getId__anon5dfb49870111::BufferOrImage389 GLuint getId()
390 {
391 return m_objectId;
392 }
393
~BufferOrImage__anon5dfb49870111::BufferOrImage394 virtual ~BufferOrImage() {}
395
396 protected:
BufferOrImage__anon5dfb49870111::BufferOrImage397 explicit BufferOrImage(glc::Context& context, bool image)
398 : m_gl(context.getDeqpContext().getRenderContext().getFunctions())
399 , m_isImage(image)
400 , m_objectId(0) {}
401
402 const glw::Functions & m_gl;
403 bool m_isImage;
404 GLuint m_objectId;
405 };
406
407 struct Buffer : public BufferOrImage
408 {
Buffer__anon5dfb49870111::Buffer409 explicit Buffer(
410 glc::Context& context, deUint64 sizeInBytes, GLenum target = GL_SHADER_STORAGE_BUFFER)
411 : BufferOrImage (context, false)
412 , m_sizeInBytes (sizeInBytes)
413 , m_target (target)
414 {
415 m_gl.genBuffers(1, &m_objectId);
416 GLU_EXPECT_NO_ERROR(m_gl.getError(), "genBuffers");
417 m_gl.bindBuffer(m_target, m_objectId);
418 GLU_EXPECT_NO_ERROR(m_gl.getError(), "bindBuffer");
419 m_gl.bufferData(m_target, m_sizeInBytes, NULL, GL_DYNAMIC_DRAW);
420 GLU_EXPECT_NO_ERROR(m_gl.getError(), "bufferData");
421 m_gl.bindBuffer(m_target, 0);
422 GLU_EXPECT_NO_ERROR(m_gl.getError(), "bindBuffer(0)");
423 }
424
~Buffer__anon5dfb49870111::Buffer425 virtual ~Buffer()
426 {
427 if (m_objectId != 0)
428 {
429 m_gl.deleteBuffers(1, &m_objectId);
430 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glDeleteBuffers");
431 }
432 }
433
getType__anon5dfb49870111::Buffer434 virtual subgroups::DescriptorType getType() const
435 {
436 if (GL_UNIFORM_BUFFER == m_target)
437 {
438 return subgroups::DESCRIPTOR_TYPE_UNIFORM_BUFFER;
439 }
440 return subgroups::DESCRIPTOR_TYPE_STORAGE_BUFFER;
441 }
442
mapBufferPtr__anon5dfb49870111::Buffer443 glw::GLvoid* mapBufferPtr() {
444 glw::GLvoid *ptr;
445
446 m_gl.bindBuffer(m_target, m_objectId);
447 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer");
448
449 ptr = m_gl.mapBufferRange(m_target, 0, m_sizeInBytes, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT);
450 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glMapBuffer");
451
452 m_gl.bindBuffer(m_target, 0);
453 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer(0)");
454
455 return ptr;
456 }
457
unmapBufferPtr__anon5dfb49870111::Buffer458 void unmapBufferPtr() {
459 m_gl.bindBuffer(m_target, m_objectId);
460 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer");
461
462 m_gl.unmapBuffer(m_target);
463 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glUnmapBuffer");
464
465 m_gl.bindBuffer(m_target, 0);
466 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer(0)");
467 }
468
getSize__anon5dfb49870111::Buffer469 deUint64 getSize() const {
470 return m_sizeInBytes;
471 }
472
473 private:
474 deUint64 m_sizeInBytes;
475 const GLenum m_target;
476 };
477
478 struct Image : public BufferOrImage
479 {
Image__anon5dfb49870111::Image480 explicit Image(glc::Context& context, deUint32 width, deUint32 height,
481 subgroups::Format format)
482 : BufferOrImage(context, true)
483 {
484 m_gl.genTextures(1, &m_objectId);
485 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGenTextures");
486 m_gl.bindTexture(GL_TEXTURE_2D, m_objectId);
487 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindTexture");
488 m_gl.texStorage2D(GL_TEXTURE_2D, 1, format, width, height);
489 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glTexStorage2D");
490 }
491
~Image__anon5dfb49870111::Image492 virtual ~Image()
493 {
494 if (m_objectId != 0)
495 {
496 m_gl.deleteTextures(1, &m_objectId);
497 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glDeleteTextures");
498 }
499 }
500
501 private:
502 };
503
504 struct Vao
505 {
Vao__anon5dfb49870111::Vao506 explicit Vao(glc::Context& context)
507 : m_gl(context.getDeqpContext().getRenderContext().getFunctions())
508 , m_objectId(0)
509 {
510 m_gl.genVertexArrays(1, &m_objectId);
511 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGenVertexArrays");
512 m_gl.bindVertexArray(m_objectId);
513 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindVertexArray");
514 }
515
~Vao__anon5dfb49870111::Vao516 ~Vao()
517 {
518 if (m_objectId != 0)
519 {
520 m_gl.deleteVertexArrays(1, &m_objectId);
521 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glDeleteVertexArrays");
522 }
523 }
524
525 private:
526 const glw::Functions & m_gl;
527 GLuint m_objectId;
528 };
529
530 struct Fbo
531 {
Fbo__anon5dfb49870111::Fbo532 explicit Fbo(glc::Context& context)
533 : m_gl(context.getDeqpContext().getRenderContext().getFunctions())
534 , m_objectId(0)
535 {
536 m_gl.genFramebuffers(1, &m_objectId);
537 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGenFramebuffers");
538 m_gl.bindFramebuffer(GL_FRAMEBUFFER, m_objectId);
539 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindFramebuffer");
540 }
541
~Fbo__anon5dfb49870111::Fbo542 ~Fbo()
543 {
544 if (m_objectId != 0)
545 {
546 m_gl.deleteFramebuffers(1, &m_objectId);
547 GLU_EXPECT_NO_ERROR(m_gl.getError(), "deleteFramebuffers");
548 }
549 }
550
bind2D__anon5dfb49870111::Fbo551 void bind2D(Image &img)
552 {
553 m_gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, img.getId(), 0);
554 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glFramebufferTexture2D");
555 }
556
557 private:
558 const glw::Functions & m_gl;
559 GLuint m_objectId;
560
561 };
562 }
563
getSharedMemoryBallotHelper()564 std::string glc::subgroups::getSharedMemoryBallotHelper()
565 {
566 return "shared uvec4 superSecretComputeShaderHelper[gl_WorkGroupSize.x * gl_WorkGroupSize.y * gl_WorkGroupSize.z];\n"
567 "uvec4 sharedMemoryBallot(bool vote)\n"
568 "{\n"
569 " uint groupOffset = gl_SubgroupID;\n"
570 " // One invocation in the group 0's the whole group's data\n"
571 " if (subgroupElect())\n"
572 " {\n"
573 " superSecretComputeShaderHelper[groupOffset] = uvec4(0);\n"
574 " }\n"
575 " subgroupMemoryBarrierShared();\n"
576 " if (vote)\n"
577 " {\n"
578 " highp uint invocationId = gl_SubgroupInvocationID % 32u;\n"
579 " highp uint bitToSet = 1u << invocationId;\n"
580 " switch (gl_SubgroupInvocationID / 32u)\n"
581 " {\n"
582 " case 0u: atomicOr(superSecretComputeShaderHelper[groupOffset].x, bitToSet); break;\n"
583 " case 1u: atomicOr(superSecretComputeShaderHelper[groupOffset].y, bitToSet); break;\n"
584 " case 2u: atomicOr(superSecretComputeShaderHelper[groupOffset].z, bitToSet); break;\n"
585 " case 3u: atomicOr(superSecretComputeShaderHelper[groupOffset].w, bitToSet); break;\n"
586 " }\n"
587 " }\n"
588 " subgroupMemoryBarrierShared();\n"
589 " return superSecretComputeShaderHelper[groupOffset];\n"
590 "}\n";
591 }
592
getSubgroupSize(Context & context)593 deUint32 glc::subgroups::getSubgroupSize(Context& context)
594 {
595 int subgroupSize = context.getDeqpContext().getContextInfo().getInt(GL_SUBGROUP_SIZE_KHR);
596
597 return subgroupSize;
598 }
599
maxSupportedSubgroupSize()600 deUint32 glc::subgroups::maxSupportedSubgroupSize() {
601 return 128u;
602 }
603
getShaderStageName(ShaderStageFlags stage)604 std::string glc::subgroups::getShaderStageName(ShaderStageFlags stage)
605 {
606 DE_ASSERT(stage & SHADER_STAGE_ALL_VALID);
607 switch (stage)
608 {
609 default:
610 DE_FATAL("Unhandled stage!");
611 return "";
612 case SHADER_STAGE_COMPUTE_BIT:
613 return "compute";
614 case SHADER_STAGE_FRAGMENT_BIT:
615 return "fragment";
616 case SHADER_STAGE_VERTEX_BIT:
617 return "vertex";
618 case SHADER_STAGE_GEOMETRY_BIT:
619 return "geometry";
620 case SHADER_STAGE_TESS_CONTROL_BIT:
621 return "tess_control";
622 case SHADER_STAGE_TESS_EVALUATION_BIT:
623 return "tess_eval";
624 }
625 }
626
getSubgroupFeatureName(SubgroupFeatureFlags bit)627 std::string glc::subgroups::getSubgroupFeatureName(SubgroupFeatureFlags bit)
628 {
629 DE_ASSERT(bit & SUBGROUP_FEATURE_ALL_VALID);
630 switch (bit)
631 {
632 default:
633 DE_FATAL("Unknown subgroup feature category!");
634 return "";
635 case SUBGROUP_FEATURE_BASIC_BIT:
636 return "GL_SUBGROUP_FEATURE_BASIC_BIT_KHR";
637 case SUBGROUP_FEATURE_VOTE_BIT:
638 return "GL_SUBGROUP_FEATURE_VOTE_BIT_KHR";
639 case SUBGROUP_FEATURE_ARITHMETIC_BIT:
640 return "GL_SUBGROUP_FEATURE_ARITHMETIC_BIT_KHR";
641 case SUBGROUP_FEATURE_BALLOT_BIT:
642 return "GL_SUBGROUP_FEATURE_BALLOT_BIT_KHR";
643 case SUBGROUP_FEATURE_SHUFFLE_BIT:
644 return "GL_SUBGROUP_FEATURE_SHUFFLE_BIT_KHR";
645 case SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT:
646 return "GL_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT_KHR";
647 case SUBGROUP_FEATURE_CLUSTERED_BIT:
648 return "GL_SUBGROUP_FEATURE_CLUSTERED_BIT_KHR";
649 case SUBGROUP_FEATURE_QUAD_BIT:
650 return "GL_SUBGROUP_FEATURE_QUAD_BIT_KHR";
651 case SUBGROUP_FEATURE_PARTITIONED_BIT_NV:
652 return "GL_SUBGROUP_FEATURE_PARTITIONED_BIT_NV";
653 }
654 }
655
addNoSubgroupShader(SourceCollections & programCollection)656 void glc::subgroups::addNoSubgroupShader (SourceCollections& programCollection)
657 {
658 {
659 const std::string vertNoSubgroupGLSL =
660 "${VERSION_DECL}\n"
661 "void main (void)\n"
662 "{\n"
663 " float pixelSize = 2.0f/1024.0f;\n"
664 " float pixelPosition = pixelSize/2.0f - 1.0f;\n"
665 " gl_Position = vec4(float(gl_VertexID) * pixelSize + pixelPosition, 0.0f, 0.0f, 1.0f);\n"
666 " gl_PointSize = 1.0f;\n"
667 "}\n";
668 programCollection.add("vert_noSubgroup") << glu::VertexSource(vertNoSubgroupGLSL);
669 }
670
671 {
672 const std::string tescNoSubgroupGLSL =
673 "${VERSION_DECL}\n"
674 "layout(vertices=1) out;\n"
675 "\n"
676 "void main (void)\n"
677 "{\n"
678 " if (gl_InvocationID == 0)\n"
679 " {\n"
680 " gl_TessLevelOuter[0] = 1.0f;\n"
681 " gl_TessLevelOuter[1] = 1.0f;\n"
682 " }\n"
683 " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
684 "}\n";
685 programCollection.add("tesc_noSubgroup") << glu::TessellationControlSource(tescNoSubgroupGLSL);
686 }
687
688 {
689 const std::string teseNoSubgroupGLSL =
690 "${VERSION_DECL}\n"
691 "layout(isolines) in;\n"
692 "\n"
693 "void main (void)\n"
694 "{\n"
695 " float pixelSize = 2.0f/1024.0f;\n"
696 " gl_Position = gl_in[0].gl_Position + gl_TessCoord.x * pixelSize / 2.0f;\n"
697 "}\n";
698 programCollection.add("tese_noSubgroup") << glu::TessellationEvaluationSource(teseNoSubgroupGLSL);
699 }
700
701 }
702
getVertShaderForStage(const ShaderStageFlags stage)703 std::string glc::subgroups::getVertShaderForStage(const ShaderStageFlags stage)
704 {
705 DE_ASSERT(stage & SHADER_STAGE_ALL_VALID);
706 switch (stage)
707 {
708 default:
709 DE_FATAL("Unhandled stage!");
710 return "";
711 case SHADER_STAGE_FRAGMENT_BIT:
712 return
713 "${VERSION_DECL}\n"
714 "void main (void)\n"
715 "{\n"
716 " float pixelSize = 2.0f/1024.0f;\n"
717 " float pixelPosition = pixelSize/2.0f - 1.0f;\n"
718 " gl_Position = vec4(float(gl_VertexID) * pixelSize + pixelPosition, 0.0f, 0.0f, 1.0f);\n"
719 "}\n";
720 case SHADER_STAGE_GEOMETRY_BIT:
721 return
722 "${VERSION_DECL}\n"
723 "void main (void)\n"
724 "{\n"
725 "}\n";
726 case SHADER_STAGE_TESS_CONTROL_BIT:
727 case SHADER_STAGE_TESS_EVALUATION_BIT:
728 return
729 "${VERSION_DECL}\n"
730 "void main (void)\n"
731 "{\n"
732 "}\n";
733 }
734 }
735
isSubgroupSupported(Context & context)736 bool glc::subgroups::isSubgroupSupported(Context& context)
737 {
738 return context.getDeqpContext().getContextInfo().isExtensionSupported("GL_KHR_shader_subgroup");
739 }
740
areSubgroupOperationsSupportedForStage(Context & context,const ShaderStageFlags stage)741 bool glc::subgroups::areSubgroupOperationsSupportedForStage(
742 Context& context, const ShaderStageFlags stage)
743 {
744 DE_ASSERT(stage & SHADER_STAGE_ALL_VALID);
745 int supportedStages = context.getDeqpContext().getContextInfo().getInt(GL_SUBGROUP_SUPPORTED_STAGES_KHR);
746
747 return (stage & supportedStages) ? true : false;
748 }
749
areSubgroupOperationsRequiredForStage(const ShaderStageFlags stage)750 bool glc::subgroups::areSubgroupOperationsRequiredForStage(
751 const ShaderStageFlags stage)
752 {
753 DE_ASSERT(stage & SHADER_STAGE_ALL_VALID);
754 switch (stage)
755 {
756 default:
757 return false;
758 case SHADER_STAGE_COMPUTE_BIT:
759 return true;
760 }
761 }
762
isSubgroupFeatureSupportedForDevice(Context & context,const SubgroupFeatureFlags bit)763 bool glc::subgroups::isSubgroupFeatureSupportedForDevice(
764 Context& context,
765 const SubgroupFeatureFlags bit)
766 {
767 DE_ASSERT(bit & SUBGROUP_FEATURE_ALL_VALID);
768
769 int supportedOperations = context.getDeqpContext().getContextInfo().getInt(GL_SUBGROUP_SUPPORTED_FEATURES_KHR);
770
771 return (bit & supportedOperations) ? true : false;
772 }
773
isFragmentSSBOSupportedForDevice(Context & context)774 bool glc::subgroups::isFragmentSSBOSupportedForDevice(Context& context)
775 {
776 int numFragmentSSBOs = context.getDeqpContext().getContextInfo().getInt(GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS);
777
778 return (numFragmentSSBOs > 0) ? true : false;
779 }
780
isVertexSSBOSupportedForDevice(Context & context)781 bool glc::subgroups::isVertexSSBOSupportedForDevice(Context& context)
782 {
783 int numVertexSSBOs = context.getDeqpContext().getContextInfo().getInt(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS);
784
785 return (numVertexSSBOs > 0) ? true : false;
786 }
787
isImageSupportedForStageOnDevice(Context & context,const ShaderStageFlags stage)788 bool glc::subgroups::isImageSupportedForStageOnDevice(Context& context, const ShaderStageFlags stage)
789 {
790 glw::GLint stageQuery;
791 DE_ASSERT(stage & SHADER_STAGE_ALL_VALID);
792
793 // image uniforms are optional in VTG stages
794 switch (stage)
795 {
796 case SHADER_STAGE_FRAGMENT_BIT:
797 case SHADER_STAGE_COMPUTE_BIT:
798 default:
799 return true;
800 case SHADER_STAGE_VERTEX_BIT:
801 stageQuery = GL_MAX_VERTEX_IMAGE_UNIFORMS;
802 break;
803 case SHADER_STAGE_TESS_CONTROL_BIT:
804 stageQuery = GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS;
805 break;
806 case SHADER_STAGE_TESS_EVALUATION_BIT:
807 stageQuery = GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS;
808 break;
809 case SHADER_STAGE_GEOMETRY_BIT:
810 stageQuery = GL_MAX_GEOMETRY_IMAGE_UNIFORMS;
811 break;
812 }
813
814 int numImages = context.getDeqpContext().getContextInfo().getInt(stageQuery);
815
816 return (numImages > 0) ? true : false;
817 }
818
isDoubleSupportedForDevice(Context & context)819 bool glc::subgroups::isDoubleSupportedForDevice(Context& context)
820 {
821 glu::ContextType contextType = context.getDeqpContext().getRenderContext().getType();
822 return (glu::contextSupports(contextType, glu::ApiType::core(4, 0)) ||
823 context.getDeqpContext().getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"));
824 }
825
isDoubleFormat(Format format)826 bool glc::subgroups::isDoubleFormat(Format format)
827 {
828 switch (format)
829 {
830 default:
831 return false;
832 case FORMAT_R64_SFLOAT:
833 case FORMAT_R64G64_SFLOAT:
834 case FORMAT_R64G64B64_SFLOAT:
835 case FORMAT_R64G64B64A64_SFLOAT:
836 return true;
837 }
838 }
839
getFormatNameForGLSL(Format format)840 std::string glc::subgroups::getFormatNameForGLSL (Format format)
841 {
842 switch (format)
843 {
844 default:
845 DE_FATAL("Unhandled format!");
846 return "";
847 case FORMAT_R32_SINT:
848 return "int";
849 case FORMAT_R32G32_SINT:
850 return "ivec2";
851 case FORMAT_R32G32B32_SINT:
852 return "ivec3";
853 case FORMAT_R32G32B32A32_SINT:
854 return "ivec4";
855 case FORMAT_R32_UINT:
856 return "uint";
857 case FORMAT_R32G32_UINT:
858 return "uvec2";
859 case FORMAT_R32G32B32_UINT:
860 return "uvec3";
861 case FORMAT_R32G32B32A32_UINT:
862 return "uvec4";
863 case FORMAT_R32_SFLOAT:
864 return "float";
865 case FORMAT_R32G32_SFLOAT:
866 return "vec2";
867 case FORMAT_R32G32B32_SFLOAT:
868 return "vec3";
869 case FORMAT_R32G32B32A32_SFLOAT:
870 return "vec4";
871 case FORMAT_R64_SFLOAT:
872 return "double";
873 case FORMAT_R64G64_SFLOAT:
874 return "dvec2";
875 case FORMAT_R64G64B64_SFLOAT:
876 return "dvec3";
877 case FORMAT_R64G64B64A64_SFLOAT:
878 return "dvec4";
879 case FORMAT_R32_BOOL:
880 return "bool";
881 case FORMAT_R32G32_BOOL:
882 return "bvec2";
883 case FORMAT_R32G32B32_BOOL:
884 return "bvec3";
885 case FORMAT_R32G32B32A32_BOOL:
886 return "bvec4";
887 }
888 }
889
setVertexShaderFrameBuffer(SourceCollections & programCollection)890 void glc::subgroups::setVertexShaderFrameBuffer (SourceCollections& programCollection)
891 {
892 programCollection.add("vert") << glu::VertexSource(
893 "${VERSION_DECL}\n"
894 "layout(location = 0) in highp vec4 in_position;\n"
895 "void main (void)\n"
896 "{\n"
897 " gl_Position = in_position;\n"
898 "}\n");
899 }
900
setFragmentShaderFrameBuffer(SourceCollections & programCollection)901 void glc::subgroups::setFragmentShaderFrameBuffer (SourceCollections& programCollection)
902 {
903 programCollection.add("fragment") << glu::FragmentSource(
904 "${VERSION_DECL}\n"
905 "precision highp int;\n"
906 "layout(location = 0) in highp float in_color;\n"
907 "layout(location = 0) out uint out_color;\n"
908 "void main()\n"
909 "{\n"
910 " out_color = uint(in_color);\n"
911 "}\n");
912 }
913
setTesCtrlShaderFrameBuffer(SourceCollections & programCollection)914 void glc::subgroups::setTesCtrlShaderFrameBuffer (SourceCollections& programCollection)
915 {
916 programCollection.add("tesc") << glu::TessellationControlSource(
917 "${VERSION_DECL}\n"
918 "#extension GL_KHR_shader_subgroup_basic: enable\n"
919 "#extension GL_EXT_tessellation_shader : require\n"
920 "layout(vertices = 2) out;\n"
921 "void main (void)\n"
922 "{\n"
923 " if (gl_InvocationID == 0)\n"
924 " {\n"
925 " gl_TessLevelOuter[0] = 1.0f;\n"
926 " gl_TessLevelOuter[1] = 1.0f;\n"
927 " }\n"
928 " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
929 "}\n");
930 }
931
setTesEvalShaderFrameBuffer(SourceCollections & programCollection)932 void glc::subgroups::setTesEvalShaderFrameBuffer (SourceCollections& programCollection)
933 {
934 programCollection.add("tese") << glu::TessellationEvaluationSource(
935 "${VERSION_DECL}\n"
936 "#extension GL_KHR_shader_subgroup_ballot: enable\n"
937 "#extension GL_EXT_tessellation_shader : require\n"
938 "layout(isolines, equal_spacing, ccw ) in;\n"
939 "layout(location = 0) in float in_color[];\n"
940 "layout(location = 0) out float out_color;\n"
941 "\n"
942 "void main (void)\n"
943 "{\n"
944 " gl_Position = mix(gl_in[0].gl_Position, gl_in[1].gl_Position, gl_TessCoord.x);\n"
945 " out_color = in_color[0];\n"
946 "}\n");
947 }
948
addGeometryShadersFromTemplate(const std::string & glslTemplate,SourceCollections & collection)949 void glc::subgroups::addGeometryShadersFromTemplate (const std::string& glslTemplate, SourceCollections& collection)
950 {
951 tcu::StringTemplate geometryTemplate(glslTemplate);
952
953 map<string, string> linesParams;
954 linesParams.insert(pair<string, string>("TOPOLOGY", "lines"));
955
956 map<string, string> pointsParams;
957 pointsParams.insert(pair<string, string>("TOPOLOGY", "points"));
958
959 collection.add("geometry_lines") << glu::GeometrySource("${VERSION_DECL}\n" + geometryTemplate.specialize(linesParams));
960 collection.add("geometry_points") << glu::GeometrySource("${VERSION_DECL}\n" + geometryTemplate.specialize(pointsParams));
961 }
962
initializeMemory(deqp::Context & context,glw::GLvoid * hostPtr,subgroups::SSBOData & data)963 void initializeMemory(deqp::Context& context, glw::GLvoid *hostPtr, subgroups::SSBOData& data)
964 {
965 using namespace subgroups;
966 const Format format = data.format;
967 const deUint64 size = data.numElements *
968 (data.isImage ? getFormatSizeInBytes(format) : getElementSizeInBytes(format, data.layout));
969 if (subgroups::SSBOData::InitializeNonZero == data.initializeType)
970 {
971 de::Random rnd(context.getTestContext().getCommandLine().getBaseSeed());
972 switch (format)
973 {
974 default:
975 DE_FATAL("Illegal buffer format");
976 break;
977 case FORMAT_R32_BOOL:
978 case FORMAT_R32G32_BOOL:
979 case FORMAT_R32G32B32_BOOL:
980 case FORMAT_R32G32B32A32_BOOL:
981 {
982 deUint32* ptr = reinterpret_cast<deUint32*>(hostPtr);
983
984 for (deUint64 k = 0; k < (size / sizeof(deUint32)); k++)
985 {
986 deUint32 r = rnd.getUint32();
987 ptr[k] = (r & 1) ? r : 0;
988 }
989 }
990 break;
991 case FORMAT_R32_SINT:
992 case FORMAT_R32G32_SINT:
993 case FORMAT_R32G32B32_SINT:
994 case FORMAT_R32G32B32A32_SINT:
995 case FORMAT_R32_UINT:
996 case FORMAT_R32G32_UINT:
997 case FORMAT_R32G32B32_UINT:
998 case FORMAT_R32G32B32A32_UINT:
999 {
1000 deUint32* ptr = reinterpret_cast<deUint32*>(hostPtr);
1001
1002 for (deUint64 k = 0; k < (size / sizeof(deUint32)); k++)
1003 {
1004 ptr[k] = rnd.getUint32();
1005 }
1006 }
1007 break;
1008 case FORMAT_R32_SFLOAT:
1009 case FORMAT_R32G32_SFLOAT:
1010 case FORMAT_R32G32B32_SFLOAT:
1011 case FORMAT_R32G32B32A32_SFLOAT:
1012 {
1013 float* ptr = reinterpret_cast<float*>(hostPtr);
1014
1015 for (deUint64 k = 0; k < (size / sizeof(float)); k++)
1016 {
1017 ptr[k] = rnd.getFloat();
1018 }
1019 }
1020 break;
1021 case FORMAT_R64_SFLOAT:
1022 case FORMAT_R64G64_SFLOAT:
1023 case FORMAT_R64G64B64_SFLOAT:
1024 case FORMAT_R64G64B64A64_SFLOAT:
1025 {
1026 double* ptr = reinterpret_cast<double*>(hostPtr);
1027
1028 for (deUint64 k = 0; k < (size / sizeof(double)); k++)
1029 {
1030 ptr[k] = rnd.getDouble();
1031 }
1032 }
1033 break;
1034 }
1035 }
1036 else if (subgroups::SSBOData::InitializeZero == data.initializeType)
1037 {
1038 deUint32* ptr = reinterpret_cast<deUint32*>(hostPtr);
1039
1040 for (deUint64 k = 0; k < size / 4; k++)
1041 {
1042 ptr[k] = 0;
1043 }
1044 }
1045
1046 if (subgroups::SSBOData::InitializeNone != data.initializeType)
1047 {
1048 // nothing to do for GL
1049 }
1050 }
1051
getResultBinding(const glc::subgroups::ShaderStageFlags shaderStage)1052 deUint32 getResultBinding (const glc::subgroups::ShaderStageFlags shaderStage)
1053 {
1054 using namespace glc::subgroups;
1055 switch(shaderStage)
1056 {
1057 case SHADER_STAGE_VERTEX_BIT:
1058 return 0u;
1059 case SHADER_STAGE_TESS_CONTROL_BIT:
1060 return 1u;
1061 case SHADER_STAGE_TESS_EVALUATION_BIT:
1062 return 2u;
1063 case SHADER_STAGE_GEOMETRY_BIT:
1064 return 3u;
1065 default:
1066 DE_ASSERT(0);
1067 return -1;
1068 }
1069 DE_ASSERT(0);
1070 return -1;
1071 }
1072
makeTessellationEvaluationFrameBufferTest(Context & context,Format format,SSBOData * extraData,deUint32 extraDataCount,bool (* checkResult)(std::vector<const void * > datas,deUint32 width,deUint32 subgroupSize),const ShaderStageFlags shaderStage)1073 tcu::TestStatus glc::subgroups::makeTessellationEvaluationFrameBufferTest(
1074 Context& context, Format format, SSBOData* extraData,
1075 deUint32 extraDataCount,
1076 bool (*checkResult)(std::vector<const void*> datas, deUint32 width, deUint32 subgroupSize),
1077 const ShaderStageFlags shaderStage)
1078 {
1079 tcu::TestLog& log = context.getDeqpContext().getTestContext().getLog();
1080 const glw::Functions& gl = context.getDeqpContext().getRenderContext().getFunctions();
1081
1082 const deUint32 maxWidth = getMaxWidth();
1083 vector<de::SharedPtr<BufferOrImage> > inputBuffers (extraDataCount);
1084
1085 const GlslSource& vshader = context.getSourceCollection().get("vert");
1086 const GlslSource& tcshader = context.getSourceCollection().get("tesc");
1087 const GlslSource& teshader = context.getSourceCollection().get("tese");
1088 const GlslSource& fshader = context.getSourceCollection().get("fragment");
1089
1090 for (deUint32 i = 0u; i < extraDataCount; i++)
1091 {
1092 if (extraData[i].isImage)
1093 {
1094 inputBuffers[i] = de::SharedPtr<BufferOrImage>(new Image(context, static_cast<deUint32>(extraData[i].numElements), 1u, extraData[i].format));
1095 // haven't implemented init for images yet
1096 DE_ASSERT(extraData[i].initializeType == subgroups::SSBOData::InitializeNone);
1097 }
1098 else
1099 {
1100 deUint64 size = getElementSizeInBytes(extraData[i].format, extraData[i].layout) * extraData[i].numElements;
1101 inputBuffers[i] = de::SharedPtr<BufferOrImage>(new Buffer(context, size, GL_UNIFORM_BUFFER));
1102
1103 glw::GLvoid *ptr = inputBuffers[i]->getAsBuffer()->mapBufferPtr();
1104 initializeMemory(context.getDeqpContext(), ptr, extraData[i]);
1105 inputBuffers[i]->getAsBuffer()->unmapBufferPtr();
1106 }
1107 }
1108
1109 for (deUint32 ndx = 0u; ndx < extraDataCount; ndx++)
1110 {
1111 log << tcu::TestLog::Message
1112 << "binding inputBuffers[" << ndx << "](" << inputBuffers[ndx]->getType() << ", " << inputBuffers[ndx]->getId() << " ), "
1113 << "stage = " << shaderStage << " , binding = " << extraData[ndx].binding << "\n"
1114 << tcu::TestLog::EndMessage;
1115
1116 if (inputBuffers[ndx]->isImage())
1117 {
1118 gl.bindImageTexture(extraData[ndx].binding, inputBuffers[ndx]->getId(),
1119 0, GL_FALSE, 0, GL_READ_ONLY, extraData[ndx].format);
1120 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindImageTexture()");
1121 } else
1122 {
1123 gl.bindBufferBase(inputBuffers[ndx]->getType(), extraData[ndx].binding, inputBuffers[ndx]->getId());
1124 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase()");
1125 }
1126 }
1127
1128 de::MovePtr<glu::ShaderProgram> pipeline(
1129 makeGraphicsPipeline(context, (ShaderStageFlags)(SHADER_STAGE_VERTEX_BIT | SHADER_STAGE_FRAGMENT_BIT | SHADER_STAGE_TESS_CONTROL_BIT | SHADER_STAGE_TESS_EVALUATION_BIT),
1130 &vshader, &fshader, DE_NULL, &tcshader, &teshader));
1131 if (!pipeline->isOk())
1132 {
1133 return tcu::TestStatus::fail("tese graphics program build failed");
1134 }
1135
1136 const deUint32 subgroupSize = getSubgroupSize(context);
1137 const deUint64 vertexBufferSize = 2ull * maxWidth * sizeof(tcu::Vec4);
1138 Buffer vertexBuffer (context, vertexBufferSize, GL_ARRAY_BUFFER);
1139 unsigned totalIterations = 0u;
1140 unsigned failedIterations = 0u;
1141 Image discardableImage (context, maxWidth, 1u, format);
1142
1143 {
1144 glw::GLvoid * bufferPtr = vertexBuffer.mapBufferPtr();
1145 std::vector<tcu::Vec4> data (2u * maxWidth, tcu::Vec4(1.0f, 0.0f, 1.0f, 1.0f));
1146 const float pixelSize = 2.0f / static_cast<float>(maxWidth);
1147 float leftHandPosition = -1.0f;
1148
1149 for(deUint32 ndx = 0u; ndx < data.size(); ndx+=2u)
1150 {
1151 data[ndx][0] = leftHandPosition;
1152 leftHandPosition += pixelSize;
1153 data[ndx+1][0] = leftHandPosition;
1154 }
1155
1156 deMemcpy(bufferPtr, &data[0], data.size() * sizeof(tcu::Vec4));
1157 vertexBuffer.unmapBufferPtr();
1158 }
1159
1160 Vao vao(context);
1161 Fbo fbo(context);
1162 fbo.bind2D(discardableImage);
1163
1164 gl.viewport(0, 0, maxWidth, 1u);
1165 GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport");
1166
1167 const deUint64 imageResultSize = getFormatSizeInBytes(format) * maxWidth;
1168 vector<glw::GLubyte> imageBufferResult(imageResultSize);
1169 const deUint64 vertexBufferOffset = 0u;
1170
1171 for (deUint32 width = 1u; width < maxWidth; width = getNextWidth(width))
1172 {
1173 totalIterations++;
1174
1175 {
1176 gl.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
1177 GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor");
1178 gl.clear(GL_COLOR_BUFFER_BIT);
1179 GLU_EXPECT_NO_ERROR(gl.getError(), "glClear");
1180
1181 gl.useProgram(pipeline->getProgram());
1182 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram");
1183
1184 gl.enableVertexAttribArray(0);
1185 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray");
1186
1187 gl.bindBuffer(GL_ARRAY_BUFFER, vertexBuffer.getId());
1188 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer");
1189
1190 gl.vertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(tcu::Vec4), glu::BufferOffsetAsPointer(vertexBufferOffset));
1191 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer");
1192
1193 gl.patchParameteri(GL_PATCH_VERTICES, 2u);
1194 GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameter(PATCH_VERTICES)");
1195
1196 gl.drawArrays(GL_PATCHES, 0, 2 * width);
1197 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays");
1198
1199 gl.disableVertexAttribArray(0);
1200
1201 GLenum readFormat;
1202 GLenum readType;
1203 getFormatReadInfo(format, readFormat, readType);
1204
1205 gl.readPixels(0, 0, width, 1, readFormat, readType, (GLvoid*)&imageBufferResult[0]);
1206 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels");
1207 }
1208
1209 {
1210 std::vector<const void*> datas;
1211 datas.push_back(&imageBufferResult[0]);
1212 if (!checkResult(datas, width/2u, subgroupSize))
1213 failedIterations++;
1214 }
1215 }
1216
1217 if (0 < failedIterations)
1218 {
1219 log << tcu::TestLog::Message << (totalIterations - failedIterations) << " / "
1220 << totalIterations << " values passed" << tcu::TestLog::EndMessage;
1221 return tcu::TestStatus::fail("Failed!");
1222 } else
1223 {
1224 log << tcu::TestLog::Message << (totalIterations - failedIterations) << " / "
1225 <<totalIterations << " values passed" << tcu::TestLog::EndMessage;
1226 }
1227
1228 return tcu::TestStatus::pass("OK");
1229 }
1230
check(std::vector<const void * > datas,deUint32 width,deUint32 ref)1231 bool glc::subgroups::check(std::vector<const void*> datas,
1232 deUint32 width, deUint32 ref)
1233 {
1234 const deUint32* data = reinterpret_cast<const deUint32*>(datas[0]);
1235
1236 for (deUint32 n = 0; n < width; ++n)
1237 {
1238 if (data[n] != ref)
1239 {
1240 return false;
1241 }
1242 }
1243
1244 return true;
1245 }
1246
checkCompute(std::vector<const void * > datas,const deUint32 numWorkgroups[3],const deUint32 localSize[3],deUint32 ref)1247 bool glc::subgroups::checkCompute(std::vector<const void*> datas,
1248 const deUint32 numWorkgroups[3], const deUint32 localSize[3],
1249 deUint32 ref)
1250 {
1251 const deUint32 globalSizeX = numWorkgroups[0] * localSize[0];
1252 const deUint32 globalSizeY = numWorkgroups[1] * localSize[1];
1253 const deUint32 globalSizeZ = numWorkgroups[2] * localSize[2];
1254
1255 return check(datas, globalSizeX * globalSizeY * globalSizeZ, ref);
1256 }
1257
1258
makeGeometryFrameBufferTest(Context & context,Format format,SSBOData * extraData,deUint32 extraDataCount,bool (* checkResult)(std::vector<const void * > datas,deUint32 width,deUint32 subgroupSize))1259 tcu::TestStatus glc::subgroups::makeGeometryFrameBufferTest(
1260 Context& context, Format format, SSBOData* extraData,
1261 deUint32 extraDataCount,
1262 bool (*checkResult)(std::vector<const void*> datas, deUint32 width, deUint32 subgroupSize))
1263 {
1264 tcu::TestLog& log = context.getDeqpContext().getTestContext().getLog();
1265 const glw::Functions& gl = context.getDeqpContext().getRenderContext().getFunctions();
1266
1267 const deUint32 maxWidth = getMaxWidth();
1268 vector<de::SharedPtr<BufferOrImage> > inputBuffers (extraDataCount);
1269
1270 const GlslSource& vshader = context.getSourceCollection().get("vert");
1271 const GlslSource& gshader = context.getSourceCollection().get("geometry");
1272 const GlslSource& fshader = context.getSourceCollection().get("fragment");
1273
1274 for (deUint32 i = 0u; i < extraDataCount; i++)
1275 {
1276 if (extraData[i].isImage)
1277 {
1278 inputBuffers[i] = de::SharedPtr<BufferOrImage>(new Image(context, static_cast<deUint32>(extraData[i].numElements), 1u, extraData[i].format));
1279 // haven't implemented init for images yet
1280 DE_ASSERT(extraData[i].initializeType == subgroups::SSBOData::InitializeNone);
1281 }
1282 else
1283 {
1284 deUint64 size = getElementSizeInBytes(extraData[i].format, extraData[i].layout) * extraData[i].numElements;
1285 inputBuffers[i] = de::SharedPtr<BufferOrImage>(new Buffer(context, size, GL_UNIFORM_BUFFER));
1286
1287 glw::GLvoid *ptr = inputBuffers[i]->getAsBuffer()->mapBufferPtr();
1288 initializeMemory(context.getDeqpContext(), ptr, extraData[i]);
1289 inputBuffers[i]->getAsBuffer()->unmapBufferPtr();
1290 }
1291 }
1292
1293 for (deUint32 ndx = 0u; ndx < extraDataCount; ndx++)
1294 {
1295 log << tcu::TestLog::Message
1296 << "binding inputBuffers[" << ndx << "](" << inputBuffers[ndx]->getType() << ", " << inputBuffers[ndx]->getId() << " ), "
1297 << "GEOMETRY, binding = " << extraData[ndx].binding << "\n"
1298 << tcu::TestLog::EndMessage;
1299
1300 if (inputBuffers[ndx]->isImage())
1301 {
1302 gl.bindImageTexture(extraData[ndx].binding, inputBuffers[ndx]->getId(),
1303 0, GL_FALSE, 0, GL_READ_ONLY, extraData[ndx].format);
1304 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindImageTexture()");
1305 } else
1306 {
1307 gl.bindBufferBase(inputBuffers[ndx]->getType(), extraData[ndx].binding, inputBuffers[ndx]->getId());
1308 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase()");
1309 }
1310 }
1311
1312 de::MovePtr<glu::ShaderProgram> pipeline(
1313 makeGraphicsPipeline(context, (ShaderStageFlags)(SHADER_STAGE_VERTEX_BIT | SHADER_STAGE_FRAGMENT_BIT | SHADER_STAGE_GEOMETRY_BIT),
1314 &vshader, &fshader, &gshader, DE_NULL, DE_NULL));
1315 if (!pipeline->isOk())
1316 {
1317 return tcu::TestStatus::fail("geom graphics program build failed");
1318 }
1319
1320 const deUint32 subgroupSize = getSubgroupSize(context);
1321 const deUint64 vertexBufferSize = maxWidth * sizeof(tcu::Vec4);
1322 Buffer vertexBuffer (context, vertexBufferSize, GL_ARRAY_BUFFER);
1323 unsigned totalIterations = 0u;
1324 unsigned failedIterations = 0u;
1325 Image discardableImage (context, maxWidth, 1u, format);
1326
1327 {
1328 glw::GLvoid * bufferPtr = vertexBuffer.mapBufferPtr();
1329 std::vector<tcu::Vec4> data (maxWidth, tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
1330 const float pixelSize = 2.0f / static_cast<float>(maxWidth);
1331 float leftHandPosition = -1.0f;
1332
1333 for(deUint32 ndx = 0u; ndx < maxWidth; ++ndx)
1334 {
1335 data[ndx][0] = leftHandPosition + pixelSize / 2.0f;
1336 leftHandPosition += pixelSize;
1337 }
1338
1339 deMemcpy(bufferPtr, &data[0], maxWidth * sizeof(tcu::Vec4));
1340 vertexBuffer.unmapBufferPtr();
1341 }
1342
1343 Vao vao(context);
1344 Fbo fbo(context);
1345 fbo.bind2D(discardableImage);
1346
1347 gl.viewport(0, 0, maxWidth, 1u);
1348 GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport");
1349
1350 const deUint64 imageResultSize = getFormatSizeInBytes(format) * maxWidth;
1351 vector<glw::GLubyte> imageBufferResult(imageResultSize);
1352 const deUint64 vertexBufferOffset = 0u;
1353
1354 for (deUint32 width = 1u; width < maxWidth; width = getNextWidth(width))
1355 {
1356 totalIterations++;
1357
1358 for (deUint32 ndx = 0u; ndx < inputBuffers.size(); ndx++)
1359 {
1360 if (inputBuffers[ndx]->isImage())
1361 {
1362 DE_ASSERT(extraData[ndx].initializeType == subgroups::SSBOData::InitializeNone);
1363 } else
1364 {
1365 glw::GLvoid *ptr = inputBuffers[ndx]->getAsBuffer()->mapBufferPtr();
1366 initializeMemory(context.getDeqpContext(), ptr, extraData[ndx]);
1367 inputBuffers[ndx]->getAsBuffer()->unmapBufferPtr();
1368 }
1369 }
1370
1371 {
1372 gl.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
1373 GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor");
1374 gl.clear(GL_COLOR_BUFFER_BIT);
1375 GLU_EXPECT_NO_ERROR(gl.getError(), "glClear");
1376
1377 gl.useProgram(pipeline->getProgram());
1378 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram");
1379
1380 gl.enableVertexAttribArray(0);
1381 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray");
1382
1383 gl.bindBuffer(GL_ARRAY_BUFFER, vertexBuffer.getId());
1384 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer");
1385
1386 gl.vertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(tcu::Vec4), glu::BufferOffsetAsPointer(vertexBufferOffset));
1387 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer");
1388
1389 gl.drawArrays(GL_POINTS, 0, width);
1390 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays");
1391
1392 gl.disableVertexAttribArray(0);
1393 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisableVertexAttribArray");
1394
1395 GLenum readFormat;
1396 GLenum readType;
1397 getFormatReadInfo(format, readFormat, readType);
1398
1399 gl.readPixels(0, 0, width, 1, readFormat, readType, (GLvoid*)&imageBufferResult[0]);
1400 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels");
1401 }
1402
1403 {
1404 std::vector<const void*> datas;
1405 datas.push_back(&imageBufferResult[0]);
1406 if (!checkResult(datas, width, subgroupSize))
1407 failedIterations++;
1408 }
1409 }
1410
1411 if (0 < failedIterations)
1412 {
1413 log << tcu::TestLog::Message << (totalIterations - failedIterations) << " / "
1414 << totalIterations << " values passed" << tcu::TestLog::EndMessage;
1415 return tcu::TestStatus::fail("Failed!");
1416 } else
1417 {
1418 log << tcu::TestLog::Message << (totalIterations - failedIterations) << " / "
1419 <<totalIterations << " values passed" << tcu::TestLog::EndMessage;
1420 }
1421
1422 return tcu::TestStatus::pass("OK");
1423 }
1424
allStages(Context & context,Format format,SSBOData * extraDatas,deUint32 extraDatasCount,bool (* checkResult)(std::vector<const void * > datas,deUint32 width,deUint32 subgroupSize),const ShaderStageFlags shaderStageTested)1425 tcu::TestStatus glc::subgroups::allStages(
1426 Context& context, Format format, SSBOData* extraDatas,
1427 deUint32 extraDatasCount,
1428 bool (*checkResult)(std::vector<const void*> datas, deUint32 width, deUint32 subgroupSize),
1429 const ShaderStageFlags shaderStageTested)
1430 {
1431 const deUint32 maxWidth = getMaxWidth();
1432 vector<ShaderStageFlags> stagesVector;
1433 ShaderStageFlags shaderStageRequired = (ShaderStageFlags)0ull;
1434 tcu::TestLog& log = context.getDeqpContext().getTestContext().getLog();
1435 const glw::Functions& gl = context.getDeqpContext().getRenderContext().getFunctions();
1436
1437 if (shaderStageTested & SHADER_STAGE_VERTEX_BIT)
1438 {
1439 stagesVector.push_back(SHADER_STAGE_VERTEX_BIT);
1440 }
1441 if (shaderStageTested & SHADER_STAGE_TESS_CONTROL_BIT)
1442 {
1443 stagesVector.push_back(SHADER_STAGE_TESS_CONTROL_BIT);
1444 shaderStageRequired = (ShaderStageFlags)((deUint32)shaderStageRequired | ((deUint32)(shaderStageTested & SHADER_STAGE_TESS_EVALUATION_BIT) ? 0u : (deUint32)SHADER_STAGE_TESS_EVALUATION_BIT));
1445 shaderStageRequired = (ShaderStageFlags)((deUint32)shaderStageRequired | ((deUint32)(shaderStageTested & SHADER_STAGE_VERTEX_BIT) ? 0u : (deUint32)SHADER_STAGE_VERTEX_BIT));
1446 }
1447 if (shaderStageTested & SHADER_STAGE_TESS_EVALUATION_BIT)
1448 {
1449 stagesVector.push_back(SHADER_STAGE_TESS_EVALUATION_BIT);
1450 shaderStageRequired = (ShaderStageFlags)((deUint32)shaderStageRequired | ((deUint32)(shaderStageTested & SHADER_STAGE_VERTEX_BIT) ? 0u : (deUint32)SHADER_STAGE_VERTEX_BIT));
1451 shaderStageRequired = (ShaderStageFlags)((deUint32)shaderStageRequired | ((deUint32)(shaderStageTested & SHADER_STAGE_TESS_CONTROL_BIT) ? 0u : (deUint32)SHADER_STAGE_TESS_CONTROL_BIT));
1452 }
1453 if (shaderStageTested & SHADER_STAGE_GEOMETRY_BIT)
1454 {
1455 stagesVector.push_back(SHADER_STAGE_GEOMETRY_BIT);
1456 const ShaderStageFlags required = SHADER_STAGE_VERTEX_BIT;
1457 shaderStageRequired = (ShaderStageFlags)((deUint32)shaderStageRequired | ((deUint32)(shaderStageTested & required) ? 0u : (deUint32)required));
1458 }
1459 if (shaderStageTested & SHADER_STAGE_FRAGMENT_BIT)
1460 {
1461 const ShaderStageFlags required = SHADER_STAGE_VERTEX_BIT;
1462 shaderStageRequired = (ShaderStageFlags)((deUint32)shaderStageRequired | ((deUint32)(shaderStageTested & required) ? 0u : (deUint32)required));
1463 }
1464
1465 const deUint32 stagesCount = static_cast<deUint32>(stagesVector.size());
1466 const string vert = (shaderStageRequired & SHADER_STAGE_VERTEX_BIT) ? "vert_noSubgroup" : "vert";
1467 const string tesc = (shaderStageRequired & SHADER_STAGE_TESS_CONTROL_BIT) ? "tesc_noSubgroup" : "tesc";
1468 const string tese = (shaderStageRequired & SHADER_STAGE_TESS_EVALUATION_BIT) ? "tese_noSubgroup" : "tese";
1469
1470 shaderStageRequired = (ShaderStageFlags)(shaderStageTested | shaderStageRequired);
1471
1472 const GlslSource *vshader = &context.getSourceCollection().get(vert);
1473 const GlslSource *fshader = DE_NULL;
1474 const GlslSource *gshader = DE_NULL;
1475 const GlslSource *tcshader = DE_NULL;
1476 const GlslSource *teshader = DE_NULL;
1477
1478 if (shaderStageRequired & SHADER_STAGE_TESS_CONTROL_BIT)
1479 {
1480 tcshader = &context.getSourceCollection().get(tesc);
1481 teshader = &context.getSourceCollection().get(tese);
1482 }
1483 if (shaderStageRequired & SHADER_STAGE_GEOMETRY_BIT)
1484 {
1485 if (shaderStageRequired & SHADER_STAGE_TESS_EVALUATION_BIT)
1486 {
1487 // tessellation shaders output line primitives
1488 gshader = &context.getSourceCollection().get("geometry_lines");
1489 }
1490 else
1491 {
1492 // otherwise points are processed by geometry shader
1493 gshader = &context.getSourceCollection().get("geometry_points");
1494 }
1495 }
1496 if (shaderStageRequired & SHADER_STAGE_FRAGMENT_BIT)
1497 {
1498 fshader = &context.getSourceCollection().get("fragment");
1499 }
1500
1501 std::vector< de::SharedPtr<BufferOrImage> > inputBuffers(stagesCount + extraDatasCount);
1502
1503 // The implicit result SSBO we use to store our outputs from the shader
1504 for (deUint32 ndx = 0u; ndx < stagesCount; ++ndx)
1505 {
1506 const deUint64 shaderSize = (stagesVector[ndx] == SHADER_STAGE_TESS_EVALUATION_BIT) ? maxWidth * 2 : maxWidth;
1507 const deUint64 size = getElementSizeInBytes(format, SSBOData::LayoutStd430) * shaderSize;
1508 inputBuffers[ndx] = de::SharedPtr<BufferOrImage>(new Buffer(context, size));
1509
1510 log << tcu::TestLog::Message
1511 << "binding inputBuffers[" << ndx << "](" << inputBuffers[ndx]->getType() << ", "
1512 << inputBuffers[ndx]->getId() << ", " << size << "), "
1513 << "inputstage[" << ndx << "] = " << stagesVector[ndx] << " binding = " << getResultBinding(stagesVector[ndx])
1514 << tcu::TestLog::EndMessage;
1515
1516 gl.bindBufferBase(inputBuffers[ndx]->getType(), getResultBinding(stagesVector[ndx]), inputBuffers[ndx]->getId());
1517 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase(ndx, inputBuffers[ndx])");
1518 }
1519
1520 for (deUint32 ndx = stagesCount; ndx < stagesCount + extraDatasCount; ++ndx)
1521 {
1522 const deUint32 datasNdx = ndx - stagesCount;
1523 if (extraDatas[datasNdx].isImage)
1524 {
1525 inputBuffers[ndx] = de::SharedPtr<BufferOrImage>(new Image(context, static_cast<deUint32>(extraDatas[datasNdx].numElements), 1, extraDatas[datasNdx].format));
1526
1527 // haven't implemented init for images yet
1528 DE_ASSERT(extraDatas[datasNdx].initializeType == subgroups::SSBOData::InitializeNone);
1529 }
1530 else
1531 {
1532 const deUint64 size = getElementSizeInBytes(extraDatas[datasNdx].format, extraDatas[datasNdx].layout) * extraDatas[datasNdx].numElements;
1533 inputBuffers[ndx] = de::SharedPtr<BufferOrImage>(new Buffer(context, size));
1534
1535 glw::GLvoid *ptr = inputBuffers[ndx]->getAsBuffer()->mapBufferPtr();
1536 initializeMemory(context.getDeqpContext(), ptr, extraDatas[datasNdx]);
1537 inputBuffers[ndx]->getAsBuffer()->unmapBufferPtr();
1538 }
1539
1540 log << tcu::TestLog::Message
1541 << "binding inputBuffers[" << ndx << "](" << inputBuffers[ndx]->getType() << ", "
1542 << inputBuffers[ndx]->getId() << ", " << extraDatas[datasNdx].numElements << " els), "
1543 << "extrastage[" << datasNdx << "] = " << extraDatas[datasNdx].stages << " binding = " << extraDatas[datasNdx].binding
1544 << tcu::TestLog::EndMessage;
1545
1546 if (inputBuffers[ndx]->isImage())
1547 {
1548 gl.bindImageTexture(extraDatas[datasNdx].binding, inputBuffers[ndx]->getId(),
1549 0, GL_FALSE, 0, GL_READ_WRITE, extraDatas[datasNdx].format);
1550 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindImageTexture(extraDatas[datasNdx])");
1551 } else
1552 {
1553 gl.bindBufferBase(inputBuffers[ndx]->getType(), extraDatas[datasNdx].binding, inputBuffers[ndx]->getId());
1554 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase(extraDatas[datasNdx])");
1555 }
1556 }
1557
1558 de::MovePtr<glu::ShaderProgram> pipeline(
1559 makeGraphicsPipeline(context, shaderStageRequired, vshader, fshader, gshader, tcshader, teshader));
1560
1561 if (!pipeline->isOk())
1562 {
1563 return tcu::TestStatus::fail("allstages graphics program build failed");
1564 }
1565
1566 {
1567 const deUint32 subgroupSize = getSubgroupSize(context);
1568 unsigned totalIterations = 0u;
1569 unsigned failedIterations = 0u;
1570 Image resultImage (context, maxWidth, 1, format);
1571 const deUint64 imageResultSize = getFormatSizeInBytes(format) * maxWidth;
1572 vector<glw::GLubyte> imageBufferResult(imageResultSize);
1573
1574 Vao vao(context);
1575 Fbo fbo(context);
1576 fbo.bind2D(resultImage);
1577
1578 gl.viewport(0, 0, maxWidth, 1u);
1579 GLU_EXPECT_NO_ERROR(gl.getError(), "viewport");
1580
1581 for (deUint32 width = 1u; width < maxWidth; width = getNextWidth(width))
1582 {
1583 for (deUint32 ndx = stagesCount; ndx < stagesCount + extraDatasCount; ++ndx)
1584 {
1585 // re-init the data
1586 if (extraDatas[ndx - stagesCount].isImage)
1587 {
1588 // haven't implemented init for images yet
1589 DE_ASSERT(extraDatas[ndx - stagesCount].initializeType == subgroups::SSBOData::InitializeNone);
1590 } else
1591 {
1592 glw::GLvoid *ptr = inputBuffers[ndx]->getAsBuffer()->mapBufferPtr();
1593 initializeMemory(context.getDeqpContext(), ptr, extraDatas[ndx - stagesCount]);
1594 inputBuffers[ndx]->getAsBuffer()->unmapBufferPtr();
1595 }
1596 }
1597
1598 totalIterations++;
1599
1600 gl.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
1601 GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor");
1602 gl.clear(GL_COLOR_BUFFER_BIT);
1603 GLU_EXPECT_NO_ERROR(gl.getError(), "glClear");
1604
1605 gl.useProgram(pipeline->getProgram());
1606 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram");
1607
1608 glw::GLenum drawType;
1609 if (shaderStageRequired & SHADER_STAGE_TESS_CONTROL_BIT)
1610 {
1611 drawType = GL_PATCHES;
1612 gl.patchParameteri(GL_PATCH_VERTICES, 1u);
1613 GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameter(PATCH_VERTICES)");
1614 } else
1615 {
1616 drawType = GL_POINTS;
1617 }
1618
1619 gl.drawArrays(drawType, 0, width);
1620 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays");
1621
1622 GLenum readFormat;
1623 GLenum readType;
1624 getFormatReadInfo(format, readFormat, readType);
1625
1626 gl.readPixels(0, 0, width, 1, readFormat, readType, (GLvoid*)&imageBufferResult[0]);
1627 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels");
1628
1629 for (deUint32 ndx = 0u; ndx < stagesCount; ++ndx)
1630 {
1631 std::vector<const void*> datas;
1632 std::vector<Buffer *> buffersToUnmap;
1633
1634 if (!inputBuffers[ndx]->isImage())
1635 {
1636 glw::GLvoid * resultData = inputBuffers[ndx]->getAsBuffer()->mapBufferPtr();
1637 buffersToUnmap.push_back(inputBuffers[ndx]->getAsBuffer());
1638 // we always have our result data first
1639 datas.push_back(resultData);
1640 }
1641
1642 for (deUint32 index = stagesCount; index < stagesCount + extraDatasCount; ++index)
1643 {
1644 const deUint32 datasNdx = index - stagesCount;
1645 if ((stagesVector[ndx] & extraDatas[datasNdx].stages) && (!inputBuffers[index]->isImage()))
1646 {
1647 glw::GLvoid * resultData = inputBuffers[index]->getAsBuffer()->mapBufferPtr();
1648 buffersToUnmap.push_back(inputBuffers[index]->getAsBuffer());
1649 datas.push_back(resultData);
1650 }
1651 }
1652
1653 if (!checkResult(datas, (stagesVector[ndx] == SHADER_STAGE_TESS_EVALUATION_BIT) ? width * 2 : width , subgroupSize))
1654 failedIterations++;
1655
1656 while( !buffersToUnmap.empty() )
1657 {
1658 Buffer * buf = buffersToUnmap.back();
1659 buf->unmapBufferPtr();
1660 buffersToUnmap.pop_back();
1661 }
1662 }
1663 if (shaderStageTested & SHADER_STAGE_FRAGMENT_BIT)
1664 {
1665 std::vector<const void*> datas;
1666 std::vector<Buffer *> buffersToUnmap;
1667
1668 // we always have our result data first
1669 datas.push_back(&imageBufferResult[0]);
1670
1671 for (deUint32 index = stagesCount; index < stagesCount + extraDatasCount; ++index)
1672 {
1673 const deUint32 datasNdx = index - stagesCount;
1674 if (SHADER_STAGE_FRAGMENT_BIT & extraDatas[datasNdx].stages && (!inputBuffers[index]->isImage()))
1675 {
1676 glw::GLvoid * resultData = inputBuffers[index]->getAsBuffer()->mapBufferPtr();
1677 buffersToUnmap.push_back(inputBuffers[index]->getAsBuffer());
1678 // we always have our result data first
1679 datas.push_back(resultData);
1680 }
1681 }
1682
1683 if (!checkResult(datas, width, subgroupSize))
1684 failedIterations++;
1685
1686 while( !buffersToUnmap.empty() )
1687 {
1688 Buffer * buf = buffersToUnmap.back();
1689 buf->unmapBufferPtr();
1690 buffersToUnmap.pop_back();
1691 }
1692 }
1693
1694 }
1695
1696 if (0 < failedIterations)
1697 {
1698 log << tcu::TestLog::Message << (totalIterations - failedIterations) << " / "
1699 << totalIterations << " values passed" << tcu::TestLog::EndMessage;
1700 return tcu::TestStatus::fail("Failed!");
1701 } else
1702 {
1703 log << tcu::TestLog::Message << (totalIterations - failedIterations) << " / "
1704 << totalIterations << " values passed" << tcu::TestLog::EndMessage;
1705 }
1706 }
1707 return tcu::TestStatus::pass("OK");
1708 }
1709
makeVertexFrameBufferTest(Context & context,Format format,SSBOData * extraData,deUint32 extraDataCount,bool (* checkResult)(std::vector<const void * > datas,deUint32 width,deUint32 subgroupSize))1710 tcu::TestStatus glc::subgroups::makeVertexFrameBufferTest(Context& context, Format format,
1711 SSBOData* extraData, deUint32 extraDataCount,
1712 bool (*checkResult)(std::vector<const void*> datas, deUint32 width, deUint32 subgroupSize))
1713 {
1714 tcu::TestLog& log = context.getDeqpContext().getTestContext().getLog();
1715 const glw::Functions& gl = context.getDeqpContext().getRenderContext().getFunctions();
1716
1717 const deUint32 maxWidth = getMaxWidth();
1718 vector<de::SharedPtr<BufferOrImage> > inputBuffers (extraDataCount);
1719
1720 const GlslSource& vshader = context.getSourceCollection().get("vert");
1721 const GlslSource& fshader = context.getSourceCollection().get("fragment");
1722
1723 for (deUint32 i = 0u; i < extraDataCount; i++)
1724 {
1725 if (extraData[i].isImage)
1726 {
1727 inputBuffers[i] = de::SharedPtr<BufferOrImage>(new Image(context, static_cast<deUint32>(extraData[i].numElements), 1u, extraData[i].format));
1728
1729 // haven't implemented init for images yet
1730 DE_ASSERT(extraData[i].initializeType == subgroups::SSBOData::InitializeNone);
1731 }
1732 else
1733 {
1734 deUint64 size = getElementSizeInBytes(extraData[i].format, extraData[i].layout) * extraData[i].numElements;
1735 inputBuffers[i] = de::SharedPtr<BufferOrImage>(new Buffer(context, size, GL_UNIFORM_BUFFER));
1736
1737 glw::GLvoid *ptr = inputBuffers[i]->getAsBuffer()->mapBufferPtr();
1738 initializeMemory(context.getDeqpContext(), ptr, extraData[i]);
1739 inputBuffers[i]->getAsBuffer()->unmapBufferPtr();
1740 }
1741 }
1742
1743 for (deUint32 ndx = 0u; ndx < extraDataCount; ndx++)
1744 {
1745 log << tcu::TestLog::Message
1746 << "binding inputBuffers[" << ndx << "](" << inputBuffers[ndx]->getType() << ", " << inputBuffers[ndx]->getId() << " ), "
1747 << "VERTEX, binding = " << extraData[ndx].binding << "\n"
1748 << tcu::TestLog::EndMessage;
1749
1750 if (inputBuffers[ndx]->isImage())
1751 {
1752 gl.bindImageTexture(extraData[ndx].binding, inputBuffers[ndx]->getId(),
1753 0, GL_FALSE, 0, GL_READ_ONLY, extraData[ndx].format);
1754 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindImageTexture()");
1755 } else
1756 {
1757 gl.bindBufferBase(inputBuffers[ndx]->getType(), extraData[ndx].binding, inputBuffers[ndx]->getId());
1758 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase()");
1759 }
1760 }
1761
1762 de::MovePtr<glu::ShaderProgram> pipeline(
1763 makeGraphicsPipeline(context, (ShaderStageFlags)(SHADER_STAGE_VERTEX_BIT | SHADER_STAGE_FRAGMENT_BIT),
1764 &vshader, &fshader, DE_NULL, DE_NULL, DE_NULL));
1765
1766 if (!pipeline->isOk())
1767 {
1768 return tcu::TestStatus::fail("vert graphics program build failed");
1769 }
1770
1771 const deUint32 subgroupSize = getSubgroupSize(context);
1772
1773 const deUint64 vertexBufferSize = maxWidth * sizeof(tcu::Vec4);
1774 Buffer vertexBuffer (context, vertexBufferSize, GL_ARRAY_BUFFER);
1775
1776 unsigned totalIterations = 0u;
1777 unsigned failedIterations = 0u;
1778
1779 Image discardableImage (context, maxWidth, 1u, format);
1780
1781 {
1782 glw::GLvoid * bufferPtr = vertexBuffer.mapBufferPtr();
1783 std::vector<tcu::Vec4> data (maxWidth, tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
1784 const float pixelSize = 2.0f / static_cast<float>(maxWidth);
1785 float leftHandPosition = -1.0f;
1786
1787 for(deUint32 ndx = 0u; ndx < maxWidth; ++ndx)
1788 {
1789 data[ndx][0] = leftHandPosition + pixelSize / 2.0f;
1790 leftHandPosition += pixelSize;
1791 }
1792
1793 deMemcpy(bufferPtr, &data[0], maxWidth * sizeof(tcu::Vec4));
1794 vertexBuffer.unmapBufferPtr();
1795 }
1796
1797 Vao vao(context);
1798 Fbo fbo(context);
1799 fbo.bind2D(discardableImage);
1800
1801 gl.viewport(0, 0, maxWidth, 1u);
1802 GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport");
1803
1804 const deUint64 imageResultSize = getFormatSizeInBytes(format) * maxWidth;
1805 vector<glw::GLubyte> imageBufferResult(imageResultSize);
1806 const deUint64 vertexBufferOffset = 0u;
1807
1808 for (deUint32 width = 1u; width < maxWidth; width = getNextWidth(width))
1809 {
1810 totalIterations++;
1811
1812 for (deUint32 ndx = 0u; ndx < inputBuffers.size(); ndx++)
1813 {
1814 if (inputBuffers[ndx]->isImage())
1815 {
1816 DE_ASSERT(extraData[ndx].initializeType == subgroups::SSBOData::InitializeNone);
1817 } else
1818 {
1819 glw::GLvoid *ptr = inputBuffers[ndx]->getAsBuffer()->mapBufferPtr();
1820 initializeMemory(context.getDeqpContext(), ptr, extraData[ndx]);
1821 inputBuffers[ndx]->getAsBuffer()->unmapBufferPtr();
1822 }
1823 }
1824
1825 {
1826 gl.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
1827 GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor");
1828 gl.clear(GL_COLOR_BUFFER_BIT);
1829 GLU_EXPECT_NO_ERROR(gl.getError(), "glClear");
1830
1831 gl.useProgram(pipeline->getProgram());
1832 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram");
1833
1834 gl.enableVertexAttribArray(0);
1835 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray");
1836
1837 gl.bindBuffer(GL_ARRAY_BUFFER, vertexBuffer.getId());
1838 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer");
1839
1840 gl.vertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(tcu::Vec4), glu::BufferOffsetAsPointer(vertexBufferOffset));
1841 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer");
1842
1843 gl.drawArrays(GL_POINTS, 0, width);
1844 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays");
1845
1846 gl.disableVertexAttribArray(0);
1847 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisableVertexAttribArray");
1848
1849 GLenum readFormat;
1850 GLenum readType;
1851 getFormatReadInfo(format, readFormat, readType);
1852
1853 gl.readPixels(0, 0, width, 1, readFormat, readType, (GLvoid*)&imageBufferResult[0]);
1854 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels");
1855 }
1856
1857 {
1858 std::vector<const void*> datas;
1859 datas.push_back(&imageBufferResult[0]);
1860 if (!checkResult(datas, width, subgroupSize))
1861 failedIterations++;
1862 }
1863 }
1864
1865 if (0 < failedIterations)
1866 {
1867 log << tcu::TestLog::Message << (totalIterations - failedIterations) << " / "
1868 << totalIterations << " values passed" << tcu::TestLog::EndMessage;
1869 return tcu::TestStatus::fail("Failed!");
1870 } else
1871 {
1872 log << tcu::TestLog::Message << (totalIterations - failedIterations) << " / "
1873 <<totalIterations << " values passed" << tcu::TestLog::EndMessage;
1874 }
1875
1876 return tcu::TestStatus::pass("OK");
1877 }
1878
1879
makeFragmentFrameBufferTest(Context & context,Format format,SSBOData * extraDatas,deUint32 extraDatasCount,bool (* checkResult)(std::vector<const void * > datas,deUint32 width,deUint32 height,deUint32 subgroupSize))1880 tcu::TestStatus glc::subgroups::makeFragmentFrameBufferTest (Context& context, Format format, SSBOData* extraDatas,
1881 deUint32 extraDatasCount,
1882 bool (*checkResult)(std::vector<const void*> datas, deUint32 width,
1883 deUint32 height, deUint32 subgroupSize))
1884 {
1885 tcu::TestLog& log = context.getDeqpContext().getTestContext().getLog();
1886 const glw::Functions& gl = context.getDeqpContext().getRenderContext().getFunctions();
1887
1888 const GlslSource& vshader = context.getSourceCollection().get("vert");
1889 const GlslSource& fshader = context.getSourceCollection().get("fragment");
1890
1891 std::vector< de::SharedPtr<BufferOrImage> > inputBuffers(extraDatasCount);
1892
1893 for (deUint32 i = 0; i < extraDatasCount; i++)
1894 {
1895 if (extraDatas[i].isImage)
1896 {
1897 inputBuffers[i] = de::SharedPtr<BufferOrImage>(new Image(context,
1898 static_cast<deUint32>(extraDatas[i].numElements), 1, extraDatas[i].format));
1899
1900 // haven't implemented init for images yet
1901 DE_ASSERT(extraDatas[i].initializeType == subgroups::SSBOData::InitializeNone);
1902 }
1903 else
1904 {
1905 deUint64 size =
1906 getElementSizeInBytes(extraDatas[i].format, extraDatas[i].layout) * extraDatas[i].numElements;
1907 inputBuffers[i] = de::SharedPtr<BufferOrImage>(new Buffer(context, size, GL_UNIFORM_BUFFER));
1908
1909 glw::GLvoid *ptr = inputBuffers[i]->getAsBuffer()->mapBufferPtr();
1910 initializeMemory(context.getDeqpContext(), ptr, extraDatas[i]);
1911 inputBuffers[i]->getAsBuffer()->unmapBufferPtr();
1912 }
1913 }
1914
1915 for (deUint32 i = 0; i < extraDatasCount; i++)
1916 {
1917 log << tcu::TestLog::Message
1918 << "binding inputBuffers[" << i << "](" << inputBuffers[i]->getType() << ", " << inputBuffers[i]->getId() << " ), "
1919 << "FRAGMENT, binding = " << extraDatas[i].binding << "\n"
1920 << tcu::TestLog::EndMessage;
1921
1922 if (inputBuffers[i]->isImage())
1923 {
1924 gl.bindImageTexture(extraDatas[i].binding, inputBuffers[i]->getId(),
1925 0, GL_FALSE, 0, GL_READ_ONLY, extraDatas[i].format);
1926 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindImageTexture()");
1927 } else
1928 {
1929 gl.bindBufferBase(inputBuffers[i]->getType(), extraDatas[i].binding, inputBuffers[i]->getId());
1930 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase()");
1931 }
1932 }
1933
1934 de::MovePtr<glu::ShaderProgram> pipeline(
1935 makeGraphicsPipeline(context, (ShaderStageFlags)(SHADER_STAGE_VERTEX_BIT | SHADER_STAGE_FRAGMENT_BIT),
1936 &vshader, &fshader, DE_NULL, DE_NULL, DE_NULL));
1937
1938 if (!pipeline->isOk())
1939 {
1940 return tcu::TestStatus::fail("frag graphics program build failed");
1941 }
1942
1943 const deUint32 subgroupSize = getSubgroupSize(context);
1944
1945 unsigned totalIterations = 0;
1946 unsigned failedIterations = 0;
1947
1948 Vao vao(context);
1949 Fbo fbo(context);
1950
1951 for (deUint32 width = 8; width <= subgroupSize; width *= 2)
1952 {
1953 for (deUint32 height = 8; height <= subgroupSize; height *= 2)
1954 {
1955 totalIterations++;
1956
1957 // re-init the data
1958 for (deUint32 i = 0; i < extraDatasCount; i++)
1959 {
1960 if (inputBuffers[i]->isImage())
1961 {
1962 DE_ASSERT(extraDatas[i].initializeType == subgroups::SSBOData::InitializeNone);
1963 } else
1964 {
1965 glw::GLvoid *ptr = inputBuffers[i]->getAsBuffer()->mapBufferPtr();
1966 initializeMemory(context.getDeqpContext(), ptr, extraDatas[i]);
1967 inputBuffers[i]->getAsBuffer()->unmapBufferPtr();
1968 }
1969 }
1970
1971 deUint64 formatSize = getFormatSizeInBytes(format);
1972 const deUint64 resultImageSizeInBytes =
1973 width * height * formatSize;
1974
1975 Image resultImage(context, width, height, format);
1976
1977 vector<glw::GLubyte> resultBuffer(resultImageSizeInBytes);
1978
1979 fbo.bind2D(resultImage);
1980
1981 gl.viewport(0, 0, width, height);
1982 GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport");
1983
1984 gl.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
1985 GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor");
1986 gl.clear(GL_COLOR_BUFFER_BIT);
1987 GLU_EXPECT_NO_ERROR(gl.getError(), "glClear");
1988
1989 gl.useProgram(pipeline->getProgram());
1990 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram");
1991
1992 gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4);
1993 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays");
1994
1995 GLenum readFormat;
1996 GLenum readType;
1997 getFormatReadInfo(format, readFormat, readType);
1998
1999 gl.readPixels(0, 0, width, height, readFormat, readType, (GLvoid*)&resultBuffer[0]);
2000 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels");
2001
2002 std::vector<const void*> datas;
2003 {
2004 // we always have our result data first
2005 datas.push_back(&resultBuffer[0]);
2006 }
2007
2008 if (!checkResult(datas, width, height, subgroupSize))
2009 {
2010 failedIterations++;
2011 }
2012 }
2013 }
2014
2015 if (0 < failedIterations)
2016 {
2017 log << tcu::TestLog::Message << (totalIterations - failedIterations) << " / "
2018 << totalIterations << " values passed" << tcu::TestLog::EndMessage;
2019 return tcu::TestStatus::fail("Failed!");
2020 } else
2021 {
2022 log << tcu::TestLog::Message << (totalIterations - failedIterations) << " / "
2023 <<totalIterations << " values passed" << tcu::TestLog::EndMessage;
2024 }
2025 return tcu::TestStatus::pass("OK");
2026 }
2027
makeComputeTest(Context & context,Format format,SSBOData * inputs,deUint32 inputsCount,bool (* checkResult)(std::vector<const void * > datas,const deUint32 numWorkgroups[3],const deUint32 localSize[3],deUint32 subgroupSize))2028 tcu::TestStatus glc::subgroups::makeComputeTest(
2029 Context& context, Format format, SSBOData* inputs, deUint32 inputsCount,
2030 bool (*checkResult)(std::vector<const void*> datas,
2031 const deUint32 numWorkgroups[3], const deUint32 localSize[3],
2032 deUint32 subgroupSize))
2033 {
2034 const glw::Functions& gl = context.getDeqpContext().getRenderContext().getFunctions();
2035 deUint64 elementSize = getFormatSizeInBytes(format);
2036
2037 const deUint64 resultBufferSize = maxSupportedSubgroupSize() *
2038 maxSupportedSubgroupSize() *
2039 maxSupportedSubgroupSize();
2040 const deUint64 resultBufferSizeInBytes = resultBufferSize * elementSize;
2041
2042 Buffer resultBuffer(
2043 context, resultBufferSizeInBytes);
2044
2045 std::vector< de::SharedPtr<BufferOrImage> > inputBuffers(inputsCount);
2046
2047 for (deUint32 i = 0; i < inputsCount; i++)
2048 {
2049 if (inputs[i].isImage)
2050 {
2051 inputBuffers[i] = de::SharedPtr<BufferOrImage>(new Image(context,
2052 static_cast<deUint32>(inputs[i].numElements), 1, inputs[i].format));
2053 // haven't implemented init for images yet
2054 DE_ASSERT(inputs[i].initializeType == subgroups::SSBOData::InitializeNone);
2055 }
2056 else
2057 {
2058 deUint64 size =
2059 getElementSizeInBytes(inputs[i].format, inputs[i].layout) * inputs[i].numElements;
2060 inputBuffers[i] = de::SharedPtr<BufferOrImage>(new Buffer(context, size));
2061
2062 glw::GLvoid *ptr = inputBuffers[i]->getAsBuffer()->mapBufferPtr();
2063 initializeMemory(context.getDeqpContext(), ptr, inputs[i]);
2064 inputBuffers[i]->getAsBuffer()->unmapBufferPtr();
2065 }
2066
2067 }
2068
2069 tcu::TestLog& log = context.getDeqpContext().getTestContext().getLog();
2070 log << tcu::TestLog::Message
2071 << "binding resultbuffer(type=" << resultBuffer.getType()
2072 << ", id=" << resultBuffer.getId() << ", binding=0), COMPUTE"
2073 << tcu::TestLog::EndMessage;
2074
2075 gl.bindBufferBase(resultBuffer.getType(), 0, resultBuffer.getId());
2076 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase(0, resultBuffer)");
2077
2078 for (deUint32 i = 0; i < inputsCount; i++)
2079 {
2080 log << tcu::TestLog::Message
2081 << "binding inputBuffers[" << i << "](type=" << inputBuffers[i]->getType()
2082 << ", id=" << inputBuffers[i]->getId() << ", binding="
2083 << inputs[i].binding << "), 1, COMPUTE"
2084 << tcu::TestLog::EndMessage;
2085
2086 if (inputBuffers[i]->isImage())
2087 {
2088 gl.bindImageTexture(inputs[i].binding, inputBuffers[i]->getId(),
2089 0, GL_FALSE, 0, GL_READ_WRITE, inputs[i].format);
2090 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindImageTexture(inputBuffer[i]");
2091 } else
2092 {
2093 gl.bindBufferBase(inputBuffers[i]->getType(), inputs[i].binding, inputBuffers[i]->getId());
2094 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase(inputBuffer[i])");
2095 }
2096 }
2097
2098 const GlslSource &cshader = context.getSourceCollection().get("comp");
2099
2100 unsigned totalIterations = 0;
2101 unsigned failedIterations = 0;
2102
2103 const deUint32 subgroupSize = getSubgroupSize(context);
2104
2105 const deUint32 numWorkgroups[3] = {4, 2, 2};
2106
2107 const deUint32 localSizesToTestCount = 15;
2108 deUint32 localSizesToTest[localSizesToTestCount][3] =
2109 {
2110 {1, 1, 1},
2111 {32, 4, 1},
2112 {32, 1, 4},
2113 {1, 32, 4},
2114 {1, 4, 32},
2115 {4, 1, 32},
2116 {4, 32, 1},
2117 {subgroupSize, 1, 1},
2118 {1, subgroupSize, 1},
2119 {1, 1, subgroupSize},
2120 {3, 5, 7},
2121 {128, 1, 1},
2122 {1, 128, 1},
2123 {1, 1, 64},
2124 {1, 1, 1} // Isn't used, just here to make double buffering checks easier
2125 };
2126
2127
2128 de::MovePtr<glu::ShaderProgram> lastPipeline(
2129 makeComputePipeline(context, cshader,
2130 localSizesToTest[0][0], localSizesToTest[0][1], localSizesToTest[0][2]));
2131
2132 for (deUint32 index = 0; index < (localSizesToTestCount - 1); index++)
2133 {
2134 const deUint32 nextX = localSizesToTest[index + 1][0];
2135 const deUint32 nextY = localSizesToTest[index + 1][1];
2136 const deUint32 nextZ = localSizesToTest[index + 1][2];
2137
2138 // we are running one test
2139 totalIterations++;
2140
2141 if (!lastPipeline->isOk())
2142 {
2143 return tcu::TestStatus::fail("compute shaders build failed");
2144 }
2145
2146 gl.useProgram(lastPipeline->getProgram());
2147 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram");
2148
2149 gl.dispatchCompute(numWorkgroups[0], numWorkgroups[1], numWorkgroups[2]);
2150 GLU_EXPECT_NO_ERROR(gl.getError(), "glDispatchCompute");
2151
2152 de::MovePtr<glu::ShaderProgram> nextPipeline(
2153 makeComputePipeline(context, cshader, nextX, nextY, nextZ));
2154
2155 std::vector<const void*> datas;
2156
2157 {
2158 glw::GLvoid * resultData = resultBuffer.mapBufferPtr();
2159
2160 // we always have our result data first
2161 datas.push_back(resultData);
2162 }
2163
2164 for (deUint32 i = 0; i < inputsCount; i++)
2165 {
2166 if (!inputBuffers[i]->isImage())
2167 {
2168 glw::GLvoid *resultData = inputBuffers[i]->getAsBuffer()->mapBufferPtr();
2169
2170 // we always have our result data first
2171 datas.push_back(resultData);
2172 }
2173 }
2174
2175 if (!checkResult(datas, numWorkgroups, localSizesToTest[index], subgroupSize))
2176 {
2177 failedIterations++;
2178 }
2179
2180 resultBuffer.unmapBufferPtr();
2181 for (deUint32 i = 0; i < inputsCount; i++)
2182 {
2183 if (!inputBuffers[i]->isImage())
2184 {
2185 inputBuffers[i]->getAsBuffer()->unmapBufferPtr();
2186 }
2187 }
2188
2189 lastPipeline = nextPipeline;
2190 }
2191
2192 if (0 < failedIterations)
2193 {
2194 log << tcu::TestLog::Message << (totalIterations - failedIterations) << " / "
2195 << totalIterations << " values passed" << tcu::TestLog::EndMessage;
2196 return tcu::TestStatus::fail("Failed!");
2197 } else
2198 {
2199 log << tcu::TestLog::Message << (totalIterations - failedIterations) << " / "
2200 << totalIterations << " values passed" << tcu::TestLog::EndMessage;
2201 }
2202
2203 return tcu::TestStatus::pass("OK");
2204 }
2205