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