1 /*------------------------------------------------------------------------
2 * OpenGL Conformance Tests
3 * ------------------------
5 * Copyright (c) 2017-2019 The Khronos Group Inc.
6 * Copyright (c) 2017 Codeplay Software Ltd.
7 * Copyright (c) 2019 NVIDIA Corporation.
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
13 * http://www.apache.org/licenses/LICENSE-2.0
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.
23 * \brief Subgroups Tests Utils
24 */ /*--------------------------------------------------------------------*/
26 #include "glcSubgroupsTestsUtils.hpp"
27 #include "deRandom.hpp"
28 #include "tcuCommandLine.hpp"
29 #include "tcuStringTemplate.hpp"
30 #include "gluContextInfo.hpp"
31 #include "gluShaderUtil.hpp"
40 // debug callback function
42 // gl.enable(GL_DEBUG_OUTPUT);
43 // gl.debugMessageCallback(debugCallback, &context);
45 void debugCallback(GLenum source, GLenum type, GLuint id, GLenum severity,
46 GLsizei length, const char * message, const void * userParam)
48 glc::Context *context = (glc::Context *)userParam;
50 tcu::TestLog& log = context->getDeqpContext().getTestContext().getLog();
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;
61 // returns the stride in bytes
62 deUint32 getFormatReadInfo(const subgroups::Format format, GLenum &readFormat, GLenum &readType)
64 using namespace subgroups;
68 DE_FATAL("Unhandled format!");
70 case FORMAT_R32G32B32A32_SFLOAT:
74 case FORMAT_R32G32_SFLOAT:
79 readFormat = GL_RED_INTEGER;
80 readType = GL_UNSIGNED_INT;
82 case FORMAT_R32G32B32A32_UINT:
83 readFormat = GL_RGBA_INTEGER;
84 readType = GL_UNSIGNED_INT;
88 deUint32 getFormatSizeInBytes(const subgroups::Format format)
90 using namespace subgroups;
94 DE_FATAL("Unhandled format!");
98 return sizeof(deInt32);
99 case FORMAT_R32G32_SINT:
100 case FORMAT_R32G32_UINT:
101 return static_cast<deUint32>(sizeof(deInt32) * 2);
102 case FORMAT_R32G32B32_SINT:
103 case FORMAT_R32G32B32_UINT:
104 case FORMAT_R32G32B32A32_SINT:
105 case FORMAT_R32G32B32A32_UINT:
106 return static_cast<deUint32>(sizeof(deInt32) * 4);
107 case FORMAT_R32_SFLOAT:
109 case FORMAT_R32G32_SFLOAT:
111 case FORMAT_R32G32B32_SFLOAT:
113 case FORMAT_R32G32B32A32_SFLOAT:
115 case FORMAT_R64_SFLOAT:
117 case FORMAT_R64G64_SFLOAT:
119 case FORMAT_R64G64B64_SFLOAT:
121 case FORMAT_R64G64B64A64_SFLOAT:
123 // The below formats are used to represent bool and bvec* types. These
124 // types are passed to the shader as int and ivec* types, before the
125 // calculations are done as booleans. We need a distinct type here so
126 // that the shader generators can switch on it and generate the correct
127 // shader source for testing.
128 case FORMAT_R32_BOOL:
129 return sizeof(deInt32);
130 case FORMAT_R32G32_BOOL:
131 return static_cast<deUint32>(sizeof(deInt32) * 2);
132 case FORMAT_R32G32B32_BOOL:
133 case FORMAT_R32G32B32A32_BOOL:
134 return static_cast<deUint32>(sizeof(deInt32) * 4);
138 de::MovePtr<glu::ShaderProgram> makeGraphicsPipeline(glc::Context& context,
139 const subgroups::ShaderStageFlags stages,
140 const GlslSource * vshader,
141 const GlslSource * fshader,
142 const GlslSource * gshader,
143 const GlslSource * tcshader,
144 const GlslSource * teshader)
146 tcu::TestLog& log = context.getDeqpContext().getTestContext().getLog();
147 const bool doShaderLog = log.isShaderLoggingEnabled();
148 DE_UNREF(stages); // only used for asserts
150 map<string, string> templateArgs;
151 // string versionDecl(getGLSLVersionDeclaration(context.getGLSLVersion()));
152 // templateArgs.insert(pair<string, string>("VERSION_DECL", versionDecl));
154 string vertSource, tescSource, teseSource, geomSource, fragSource;
157 DE_ASSERT(stages & subgroups::SHADER_STAGE_VERTEX_BIT);
158 tcu::StringTemplate shaderTemplate(vshader->sources[glu::SHADERTYPE_VERTEX][0]);
159 string shaderSource(shaderTemplate.specialize(templateArgs));
162 log << tcu::TestLog::Message << "vertex shader:\n"
163 << shaderSource << "\n:end:" << tcu::TestLog::EndMessage;
165 vertSource = shaderSource;
169 DE_ASSERT(stages & subgroups::SHADER_STAGE_TESS_CONTROL_BIT);
170 tcu::StringTemplate shaderTemplate(tcshader->sources[glu::SHADERTYPE_TESSELLATION_CONTROL][0]);
171 string shaderSource(shaderTemplate.specialize(templateArgs));
174 log << tcu::TestLog::Message << "tess control shader:\n"
175 << shaderSource << "\n:end:" << tcu::TestLog::EndMessage;
177 tescSource = shaderSource;
181 DE_ASSERT(stages & subgroups::SHADER_STAGE_TESS_EVALUATION_BIT);
182 tcu::StringTemplate shaderTemplate(teshader->sources[glu::SHADERTYPE_TESSELLATION_EVALUATION][0]);
183 string shaderSource(shaderTemplate.specialize(templateArgs));
186 log << tcu::TestLog::Message << "tess eval shader:\n"
187 << shaderSource << "\n:end:" << tcu::TestLog::EndMessage;
189 teseSource = shaderSource;
193 DE_ASSERT(stages & subgroups::SHADER_STAGE_GEOMETRY_BIT);
194 tcu::StringTemplate shaderTemplate(gshader->sources[glu::SHADERTYPE_GEOMETRY][0]);
195 string shaderSource(shaderTemplate.specialize(templateArgs));
198 log << tcu::TestLog::Message << "geometry shader:\n"
199 << shaderSource << "\n:end:" << tcu::TestLog::EndMessage;
201 geomSource = shaderSource;
205 DE_ASSERT(stages & subgroups::SHADER_STAGE_FRAGMENT_BIT);
206 tcu::StringTemplate shaderTemplate(fshader->sources[glu::SHADERTYPE_FRAGMENT][0]);
207 string shaderSource(shaderTemplate.specialize(templateArgs));
210 log << tcu::TestLog::Message << "fragment shader:\n"
211 << shaderSource << "\n:end:" << tcu::TestLog::EndMessage;
213 fragSource = shaderSource;
216 glu::ShaderProgram *program = DE_NULL;
217 if(context.getShaderType() == SHADER_TYPE_GLSL)
219 glu::ProgramSources sources;
221 sources << glu::VertexSource(vertSource);
223 sources << glu::TessellationControlSource(tescSource);
225 sources << glu::TessellationEvaluationSource(teseSource);
227 sources << glu::GeometrySource(geomSource);
229 sources << glu::FragmentSource(fragSource);
231 program = new glu::ShaderProgram(context.getDeqpContext().getRenderContext().getFunctions(), sources);
233 DE_ASSERT(context.getShaderType() == SHADER_TYPE_SPIRV);
235 glu::ProgramBinaries binaries;
237 binaries << spirvUtils::makeSpirV(log, glu::VertexSource(vertSource), spirvUtils::SPIRV_VERSION_1_3);
239 binaries << spirvUtils::makeSpirV(log, glu::TessellationControlSource(tescSource), spirvUtils::SPIRV_VERSION_1_3);
241 binaries << spirvUtils::makeSpirV(log, glu::TessellationEvaluationSource(teseSource), spirvUtils::SPIRV_VERSION_1_3);
243 binaries << spirvUtils::makeSpirV(log, glu::GeometrySource(geomSource), spirvUtils::SPIRV_VERSION_1_3);
245 binaries << spirvUtils::makeSpirV(log, glu::FragmentSource(fragSource), spirvUtils::SPIRV_VERSION_1_3);
247 program = new glu::ShaderProgram(context.getDeqpContext().getRenderContext().getFunctions(), binaries);
250 if (!program->isOk())
252 log << tcu::TestLog::Message << "Shader build failed.\n"
253 << "Vertex: " << (vshader ? program->getShaderInfo(glu::SHADERTYPE_VERTEX).infoLog : "n/a") << "\n"
254 << "Tess Cont: " << (tcshader ? program->getShaderInfo(glu::SHADERTYPE_TESSELLATION_CONTROL).infoLog : "n/a") << "\n"
255 << "Tess Eval: " << (teshader ? program->getShaderInfo(glu::SHADERTYPE_TESSELLATION_EVALUATION).infoLog : "n/a") << "\n"
256 << "Geometry: " << (gshader ? program->getShaderInfo(glu::SHADERTYPE_GEOMETRY).infoLog : "n/a") << "\n"
257 << "Fragment: " << (fshader ? program->getShaderInfo(glu::SHADERTYPE_FRAGMENT).infoLog : "n/a") << "\n"
258 << "Program: " << program->getProgramInfo().infoLog << tcu::TestLog::EndMessage;
260 return de::MovePtr<glu::ShaderProgram>(program);
263 de::MovePtr<glu::ShaderProgram> makeComputePipeline(glc::Context& context, const GlslSource &glslTemplate,
264 deUint32 localSizeX, deUint32 localSizeY, deUint32 localSizeZ)
267 tcu::TestLog& log = context.getDeqpContext().getTestContext().getLog();
268 const bool doShaderLog = log.isShaderLoggingEnabled();
270 tcu::StringTemplate computeTemplate(glslTemplate.sources[glu::SHADERTYPE_COMPUTE][0]);
272 map<string, string> localSizeParams;
274 stringstream localSize;
275 localSize << "local_size_x = " << localSizeX;
276 localSizeParams.insert(pair<string, string>("LOCAL_SIZE_X", localSize.str()));
279 stringstream localSize;
280 localSize << "local_size_y = " << localSizeY;
281 localSizeParams.insert(pair<string, string>("LOCAL_SIZE_Y", localSize.str()));
284 stringstream localSize;
285 localSize << "local_size_z = " << localSizeZ;
286 localSizeParams.insert(pair<string, string>("LOCAL_SIZE_Z", localSize.str()));
289 glu::ComputeSource cshader(glu::ComputeSource(computeTemplate.specialize(localSizeParams)));
293 log << tcu::TestLog::Message << "compute shader specialized source:\n"
294 << cshader.source << "\n:end:" << tcu::TestLog::EndMessage;
297 glu::ShaderProgram *program = DE_NULL;
298 if(context.getShaderType() == SHADER_TYPE_GLSL)
300 glu::ProgramSources sources;
302 program = new glu::ShaderProgram(context.getDeqpContext().getRenderContext().getFunctions(), sources);
304 DE_ASSERT(context.getShaderType() == SHADER_TYPE_SPIRV);
306 glu::ProgramBinaries binaries;
307 binaries << spirvUtils::makeSpirV(log, cshader, spirvUtils::SPIRV_VERSION_1_3);
309 program = new glu::ShaderProgram(context.getDeqpContext().getRenderContext().getFunctions(), binaries);
312 if (!program->isOk())
314 log << tcu::TestLog::Message << "Shader build failed.\n"
315 << "Compute: " << program->getShaderInfo(glu::SHADERTYPE_COMPUTE).infoLog << "\n"
316 << "Program: " << program->getProgramInfo().infoLog << tcu::TestLog::EndMessage;
318 return de::MovePtr<glu::ShaderProgram>(program);
331 Buffer* getAsBuffer()
333 if (m_isImage) DE_FATAL("Trying to get a buffer as an image!");
334 return reinterpret_cast<Buffer* >(this);
339 if (!m_isImage) DE_FATAL("Trying to get an image as a buffer!");
340 return reinterpret_cast<Image*>(this);
343 virtual subgroups::DescriptorType getType() const
347 return subgroups::DESCRIPTOR_TYPE_STORAGE_IMAGE;
351 return subgroups::DESCRIPTOR_TYPE_STORAGE_BUFFER;
360 virtual ~BufferOrImage() {}
363 explicit BufferOrImage(glc::Context& context, bool image)
364 : m_gl(context.getDeqpContext().getRenderContext().getFunctions())
368 const glw::Functions & m_gl;
373 struct Buffer : public BufferOrImage
376 glc::Context& context, deUint64 sizeInBytes, GLenum target = GL_SHADER_STORAGE_BUFFER)
377 : BufferOrImage (context, false)
378 // HACK overpad to account for the size for std140 UBOs
379 , m_sizeInBytes (sizeInBytes * 4)
382 m_gl.genBuffers(1, &m_objectId);
383 GLU_EXPECT_NO_ERROR(m_gl.getError(), "genBuffers");
384 m_gl.bindBuffer(m_target, m_objectId);
385 GLU_EXPECT_NO_ERROR(m_gl.getError(), "bindBuffer");
386 m_gl.bufferData(m_target, m_sizeInBytes, NULL, GL_DYNAMIC_DRAW);
387 GLU_EXPECT_NO_ERROR(m_gl.getError(), "bufferData");
388 m_gl.bindBuffer(m_target, 0);
389 GLU_EXPECT_NO_ERROR(m_gl.getError(), "bindBuffer(0)");
396 m_gl.deleteBuffers(1, &m_objectId);
397 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glDeleteBuffers");
401 virtual subgroups::DescriptorType getType() const
403 if (GL_UNIFORM_BUFFER == m_target)
405 return subgroups::DESCRIPTOR_TYPE_UNIFORM_BUFFER;
407 return subgroups::DESCRIPTOR_TYPE_STORAGE_BUFFER;
410 glw::GLvoid* mapBufferPtr() {
413 m_gl.bindBuffer(m_target, m_objectId);
414 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer");
416 ptr = m_gl.mapBuffer(m_target, GL_READ_WRITE);
417 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glMapBuffer");
419 m_gl.bindBuffer(m_target, 0);
420 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer(0)");
425 void unmapBufferPtr() {
426 m_gl.bindBuffer(m_target, m_objectId);
427 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer");
429 m_gl.unmapBuffer(m_target);
430 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glUnmapBuffer");
432 m_gl.bindBuffer(m_target, 0);
433 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer(0)");
436 deUint64 getSize() const {
437 return m_sizeInBytes;
441 deUint64 m_sizeInBytes;
442 const GLenum m_target;
445 struct Image : public BufferOrImage
447 explicit Image(glc::Context& context, deUint32 width, deUint32 height,
448 subgroups::Format format)
449 : BufferOrImage(context, true)
451 m_gl.genTextures(1, &m_objectId);
452 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGenTextures");
453 m_gl.bindTexture(GL_TEXTURE_2D, m_objectId);
454 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindTexture");
455 m_gl.texStorage2D(GL_TEXTURE_2D, 1, format, width, height);
456 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glTexStorage2D");
463 m_gl.deleteTextures(1, &m_objectId);
464 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glDeleteTextures");
473 explicit Vao(glc::Context& context)
474 : m_gl(context.getDeqpContext().getRenderContext().getFunctions())
477 m_gl.genVertexArrays(1, &m_objectId);
478 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGenVertexArrays");
479 m_gl.bindVertexArray(m_objectId);
480 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindVertexArray");
487 m_gl.deleteVertexArrays(1, &m_objectId);
488 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glDeleteVertexArrays");
493 const glw::Functions & m_gl;
499 explicit Fbo(glc::Context& context)
500 : m_gl(context.getDeqpContext().getRenderContext().getFunctions())
503 m_gl.genFramebuffers(1, &m_objectId);
504 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGenFramebuffers");
505 m_gl.bindFramebuffer(GL_FRAMEBUFFER, m_objectId);
506 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindFramebuffer");
513 m_gl.deleteFramebuffers(1, &m_objectId);
514 GLU_EXPECT_NO_ERROR(m_gl.getError(), "deleteFramebuffers");
518 void bind2D(Image &img)
520 m_gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, img.getId(), 0);
521 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glFramebufferTexture2D");
525 const glw::Functions & m_gl;
531 std::string glc::subgroups::getSharedMemoryBallotHelper()
533 return "shared uvec4 superSecretComputeShaderHelper[gl_WorkGroupSize.x * gl_WorkGroupSize.y * gl_WorkGroupSize.z];\n"
534 "uvec4 sharedMemoryBallot(bool vote)\n"
536 " uint groupOffset = gl_SubgroupID;\n"
537 " // One invocation in the group 0's the whole group's data\n"
538 " if (subgroupElect())\n"
540 " superSecretComputeShaderHelper[groupOffset] = uvec4(0);\n"
542 " subgroupMemoryBarrierShared();\n"
545 " const highp uint invocationId = gl_SubgroupInvocationID % 32;\n"
546 " const highp uint bitToSet = 1u << invocationId;\n"
547 " switch (gl_SubgroupInvocationID / 32)\n"
549 " case 0: atomicOr(superSecretComputeShaderHelper[groupOffset].x, bitToSet); break;\n"
550 " case 1: atomicOr(superSecretComputeShaderHelper[groupOffset].y, bitToSet); break;\n"
551 " case 2: atomicOr(superSecretComputeShaderHelper[groupOffset].z, bitToSet); break;\n"
552 " case 3: atomicOr(superSecretComputeShaderHelper[groupOffset].w, bitToSet); break;\n"
555 " subgroupMemoryBarrierShared();\n"
556 " return superSecretComputeShaderHelper[groupOffset];\n"
560 deUint32 glc::subgroups::getSubgroupSize(Context& context)
562 int subgroupSize = context.getDeqpContext().getContextInfo().getInt(GL_SUBGROUP_SIZE_KHR);
567 deUint32 glc::subgroups::maxSupportedSubgroupSize() {
571 std::string glc::subgroups::getShaderStageName(ShaderStageFlags stage)
573 DE_ASSERT(stage & SHADER_STAGE_ALL_VALID);
577 DE_FATAL("Unhandled stage!");
579 case SHADER_STAGE_COMPUTE_BIT:
581 case SHADER_STAGE_FRAGMENT_BIT:
583 case SHADER_STAGE_VERTEX_BIT:
585 case SHADER_STAGE_GEOMETRY_BIT:
587 case SHADER_STAGE_TESS_CONTROL_BIT:
588 return "tess_control";
589 case SHADER_STAGE_TESS_EVALUATION_BIT:
594 std::string glc::subgroups::getSubgroupFeatureName(SubgroupFeatureFlags bit)
596 DE_ASSERT(bit & SUBGROUP_FEATURE_ALL_VALID);
600 DE_FATAL("Unknown subgroup feature category!");
602 case SUBGROUP_FEATURE_BASIC_BIT:
603 return "GL_SUBGROUP_FEATURE_BASIC_BIT_KHR";
604 case SUBGROUP_FEATURE_VOTE_BIT:
605 return "GL_SUBGROUP_FEATURE_VOTE_BIT_KHR";
606 case SUBGROUP_FEATURE_ARITHMETIC_BIT:
607 return "GL_SUBGROUP_FEATURE_ARITHMETIC_BIT_KHR";
608 case SUBGROUP_FEATURE_BALLOT_BIT:
609 return "GL_SUBGROUP_FEATURE_BALLOT_BIT_KHR";
610 case SUBGROUP_FEATURE_SHUFFLE_BIT:
611 return "GL_SUBGROUP_FEATURE_SHUFFLE_BIT_KHR";
612 case SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT:
613 return "GL_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT_KHR";
614 case SUBGROUP_FEATURE_CLUSTERED_BIT:
615 return "GL_SUBGROUP_FEATURE_CLUSTERED_BIT_KHR";
616 case SUBGROUP_FEATURE_QUAD_BIT:
617 return "GL_SUBGROUP_FEATURE_QUAD_BIT_KHR";
618 case SUBGROUP_FEATURE_PARTITIONED_BIT_NV:
619 return "GL_SUBGROUP_FEATURE_PARTITIONED_BIT_NV";
623 void glc::subgroups::addNoSubgroupShader (SourceCollections& programCollection)
626 const std::string vertNoSubgroupGLSL =
630 " float pixelSize = 2.0f/1024.0f;\n"
631 " float pixelPosition = pixelSize/2.0f - 1.0f;\n"
632 " gl_Position = vec4(float(gl_VertexID) * pixelSize + pixelPosition, 0.0f, 0.0f, 1.0f);\n"
633 " gl_PointSize = 1.0f;\n"
635 programCollection.add("vert_noSubgroup") << glu::VertexSource(vertNoSubgroupGLSL);
639 const std::string tescNoSubgroupGLSL =
641 "layout(vertices=1) out;\n"
645 " if (gl_InvocationID == 0)\n"
647 " gl_TessLevelOuter[0] = 1.0f;\n"
648 " gl_TessLevelOuter[1] = 1.0f;\n"
650 " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
652 programCollection.add("tesc_noSubgroup") << glu::TessellationControlSource(tescNoSubgroupGLSL);
656 const std::string teseNoSubgroupGLSL =
658 "layout(isolines) in;\n"
662 " float pixelSize = 2.0f/1024.0f;\n"
663 " gl_Position = gl_in[0].gl_Position + gl_TessCoord.x * pixelSize / 2.0f;\n"
665 programCollection.add("tese_noSubgroup") << glu::TessellationEvaluationSource(teseNoSubgroupGLSL);
670 std::string glc::subgroups::getVertShaderForStage(const ShaderStageFlags stage)
672 DE_ASSERT(stage & SHADER_STAGE_ALL_VALID);
676 DE_FATAL("Unhandled stage!");
678 case SHADER_STAGE_FRAGMENT_BIT:
683 " float pixelSize = 2.0f/1024.0f;\n"
684 " float pixelPosition = pixelSize/2.0f - 1.0f;\n"
685 " gl_Position = vec4(float(gl_VertexID) * pixelSize + pixelPosition, 0.0f, 0.0f, 1.0f);\n"
687 case SHADER_STAGE_GEOMETRY_BIT:
693 case SHADER_STAGE_TESS_CONTROL_BIT:
694 case SHADER_STAGE_TESS_EVALUATION_BIT:
703 bool glc::subgroups::isSubgroupSupported(Context& context)
705 return context.getDeqpContext().getContextInfo().isExtensionSupported("GL_KHR_shader_subgroup");
708 bool glc::subgroups::areSubgroupOperationsSupportedForStage(
709 Context& context, const ShaderStageFlags stage)
711 DE_ASSERT(stage & SHADER_STAGE_ALL_VALID);
712 int supportedStages = context.getDeqpContext().getContextInfo().getInt(GL_SUBGROUP_SUPPORTED_STAGES_KHR);
714 return (stage & supportedStages) ? true : false;
717 bool glc::subgroups::areSubgroupOperationsRequiredForStage(
718 const ShaderStageFlags stage)
720 DE_ASSERT(stage & SHADER_STAGE_ALL_VALID);
725 case SHADER_STAGE_COMPUTE_BIT:
730 bool glc::subgroups::isSubgroupFeatureSupportedForDevice(
732 const SubgroupFeatureFlags bit)
734 DE_ASSERT(bit & SUBGROUP_FEATURE_ALL_VALID);
736 int supportedOperations = context.getDeqpContext().getContextInfo().getInt(GL_SUBGROUP_SUPPORTED_FEATURES_KHR);
738 return (bit & supportedOperations) ? true : false;
741 bool glc::subgroups::isFragmentSSBOSupportedForDevice(Context& context)
743 int numFragmentSSBOs = context.getDeqpContext().getContextInfo().getInt(GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS);
745 return (numFragmentSSBOs > 0) ? true : false;
748 bool glc::subgroups::isVertexSSBOSupportedForDevice(Context& context)
750 int numVertexSSBOs = context.getDeqpContext().getContextInfo().getInt(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS);
752 return (numVertexSSBOs > 0) ? true : false;
755 bool glc::subgroups::isDoubleSupportedForDevice(Context& context)
757 glu::ContextType contextType = context.getDeqpContext().getRenderContext().getType();
758 return (glu::contextSupports(contextType, glu::ApiType::core(4, 0)) ||
759 context.getDeqpContext().getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"));
762 bool glc::subgroups::isDoubleFormat(Format format)
768 case FORMAT_R64_SFLOAT:
769 case FORMAT_R64G64_SFLOAT:
770 case FORMAT_R64G64B64_SFLOAT:
771 case FORMAT_R64G64B64A64_SFLOAT:
776 std::string glc::subgroups::getFormatNameForGLSL (Format format)
781 DE_FATAL("Unhandled format!");
783 case FORMAT_R32_SINT:
785 case FORMAT_R32G32_SINT:
787 case FORMAT_R32G32B32_SINT:
789 case FORMAT_R32G32B32A32_SINT:
791 case FORMAT_R32_UINT:
793 case FORMAT_R32G32_UINT:
795 case FORMAT_R32G32B32_UINT:
797 case FORMAT_R32G32B32A32_UINT:
799 case FORMAT_R32_SFLOAT:
801 case FORMAT_R32G32_SFLOAT:
803 case FORMAT_R32G32B32_SFLOAT:
805 case FORMAT_R32G32B32A32_SFLOAT:
807 case FORMAT_R64_SFLOAT:
809 case FORMAT_R64G64_SFLOAT:
811 case FORMAT_R64G64B64_SFLOAT:
813 case FORMAT_R64G64B64A64_SFLOAT:
815 case FORMAT_R32_BOOL:
817 case FORMAT_R32G32_BOOL:
819 case FORMAT_R32G32B32_BOOL:
821 case FORMAT_R32G32B32A32_BOOL:
826 void glc::subgroups::setVertexShaderFrameBuffer (SourceCollections& programCollection)
828 programCollection.add("vert") << glu::VertexSource(
830 "layout(location = 0) in highp vec4 in_position;\n"
833 " gl_Position = in_position;\n"
837 void glc::subgroups::setFragmentShaderFrameBuffer (SourceCollections& programCollection)
839 programCollection.add("fragment") << glu::FragmentSource(
841 "layout(location = 0) in float in_color;\n"
842 "layout(location = 0) out uint out_color;\n"
845 " out_color = uint(in_color);\n"
849 void glc::subgroups::setTesCtrlShaderFrameBuffer (SourceCollections& programCollection)
851 programCollection.add("tesc") << glu::TessellationControlSource(
853 "#extension GL_KHR_shader_subgroup_basic: enable\n"
854 "#extension GL_EXT_tessellation_shader : require\n"
855 "layout(vertices = 2) out;\n"
858 " if (gl_InvocationID == 0)\n"
860 " gl_TessLevelOuter[0] = 1.0f;\n"
861 " gl_TessLevelOuter[1] = 1.0f;\n"
863 " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
867 void glc::subgroups::setTesEvalShaderFrameBuffer (SourceCollections& programCollection)
869 programCollection.add("tese") << glu::TessellationEvaluationSource(
871 "#extension GL_KHR_shader_subgroup_ballot: enable\n"
872 "#extension GL_EXT_tessellation_shader : require\n"
873 "layout(isolines, equal_spacing, ccw ) in;\n"
874 "layout(location = 0) in float in_color[];\n"
875 "layout(location = 0) out float out_color;\n"
879 " gl_Position = mix(gl_in[0].gl_Position, gl_in[1].gl_Position, gl_TessCoord.x);\n"
880 " out_color = in_color[0];\n"
884 void glc::subgroups::addGeometryShadersFromTemplate (const std::string& glslTemplate, SourceCollections& collection)
886 tcu::StringTemplate geometryTemplate(glslTemplate);
888 map<string, string> linesParams;
889 linesParams.insert(pair<string, string>("TOPOLOGY", "lines"));
891 map<string, string> pointsParams;
892 pointsParams.insert(pair<string, string>("TOPOLOGY", "points"));
894 collection.add("geometry_lines") << glu::GeometrySource(geometryTemplate.specialize(linesParams));
895 collection.add("geometry_points") << glu::GeometrySource(geometryTemplate.specialize(pointsParams));
898 void initializeMemory(deqp::Context& context, glw::GLvoid *hostPtr, subgroups::SSBOData& data)
900 using namespace subgroups;
901 const Format format = data.format;
902 const deUint64 size = getFormatSizeInBytes(format) * data.numElements;
903 if (subgroups::SSBOData::InitializeNonZero == data.initializeType)
905 de::Random rnd(context.getTestContext().getCommandLine().getBaseSeed());
909 DE_FATAL("Illegal buffer format");
911 case FORMAT_R32_BOOL:
912 case FORMAT_R32G32_BOOL:
913 case FORMAT_R32G32B32_BOOL:
914 case FORMAT_R32G32B32A32_BOOL:
915 case FORMAT_R32_SINT:
916 case FORMAT_R32G32_SINT:
917 case FORMAT_R32G32B32_SINT:
918 case FORMAT_R32G32B32A32_SINT:
919 case FORMAT_R32_UINT:
920 case FORMAT_R32G32_UINT:
921 case FORMAT_R32G32B32_UINT:
922 case FORMAT_R32G32B32A32_UINT:
924 deUint32* ptr = reinterpret_cast<deUint32*>(hostPtr);
926 for (deUint64 k = 0; k < (size / sizeof(deUint32)); k++)
928 ptr[k] = rnd.getUint32();
932 case FORMAT_R32_SFLOAT:
933 case FORMAT_R32G32_SFLOAT:
934 case FORMAT_R32G32B32_SFLOAT:
935 case FORMAT_R32G32B32A32_SFLOAT:
937 float* ptr = reinterpret_cast<float*>(hostPtr);
939 for (deUint64 k = 0; k < (size / sizeof(float)); k++)
941 ptr[k] = rnd.getFloat();
945 case FORMAT_R64_SFLOAT:
946 case FORMAT_R64G64_SFLOAT:
947 case FORMAT_R64G64B64_SFLOAT:
948 case FORMAT_R64G64B64A64_SFLOAT:
950 double* ptr = reinterpret_cast<double*>(hostPtr);
952 for (deUint64 k = 0; k < (size / sizeof(double)); k++)
954 ptr[k] = rnd.getDouble();
960 else if (subgroups::SSBOData::InitializeZero == data.initializeType)
962 deUint32* ptr = reinterpret_cast<deUint32*>(hostPtr);
964 for (deUint64 k = 0; k < size / 4; k++)
970 if (subgroups::SSBOData::InitializeNone != data.initializeType)
972 // nothing to do for GL
976 deUint32 getResultBinding (const glc::subgroups::ShaderStageFlags shaderStage)
978 using namespace glc::subgroups;
981 case SHADER_STAGE_VERTEX_BIT:
984 case SHADER_STAGE_TESS_CONTROL_BIT:
987 case SHADER_STAGE_TESS_EVALUATION_BIT:
990 case SHADER_STAGE_GEOMETRY_BIT:
1001 tcu::TestStatus glc::subgroups::makeTessellationEvaluationFrameBufferTest(
1002 Context& context, Format format, SSBOData* extraData,
1003 deUint32 extraDataCount,
1004 bool (*checkResult)(std::vector<const void*> datas, deUint32 width, deUint32 subgroupSize),
1005 const ShaderStageFlags shaderStage)
1007 tcu::TestLog& log = context.getDeqpContext().getTestContext().getLog();
1008 const glw::Functions& gl = context.getDeqpContext().getRenderContext().getFunctions();
1010 const deUint32 maxWidth = 1024u;
1011 vector<de::SharedPtr<BufferOrImage> > inputBuffers (extraDataCount);
1013 const GlslSource& vshader = context.getSourceCollection().get("vert");
1014 const GlslSource& tcshader = context.getSourceCollection().get("tesc");
1015 const GlslSource& teshader = context.getSourceCollection().get("tese");
1016 const GlslSource& fshader = context.getSourceCollection().get("fragment");
1018 for (deUint32 i = 0u; i < extraDataCount; i++)
1020 if (extraData[i].isImage)
1022 inputBuffers[i] = de::SharedPtr<BufferOrImage>(new Image(context, static_cast<deUint32>(extraData[i].numElements), 1u, extraData[i].format));
1023 // haven't implemented init for images yet
1024 DE_ASSERT(extraData[i].initializeType == subgroups::SSBOData::InitializeNone);
1028 deUint64 size = getFormatSizeInBytes(extraData[i].format) * extraData[i].numElements;
1029 inputBuffers[i] = de::SharedPtr<BufferOrImage>(new Buffer(context, size, GL_UNIFORM_BUFFER));
1031 glw::GLvoid *ptr = inputBuffers[i]->getAsBuffer()->mapBufferPtr();
1032 initializeMemory(context.getDeqpContext(), ptr, extraData[i]);
1033 inputBuffers[i]->getAsBuffer()->unmapBufferPtr();
1037 for (deUint32 ndx = 0u; ndx < extraDataCount; ndx++)
1039 log << tcu::TestLog::Message
1040 << "binding inputBuffers[" << ndx << "](" << inputBuffers[ndx]->getType() << ", " << inputBuffers[ndx]->getId() << " ), "
1041 << "stage = " << shaderStage << " , binding = " << extraData[ndx].binding << "\n"
1042 << tcu::TestLog::EndMessage;
1044 if (inputBuffers[ndx]->isImage())
1046 gl.bindImageTexture(extraData[ndx].binding, inputBuffers[ndx]->getId(),
1047 0, GL_FALSE, 0, GL_READ_ONLY, extraData[ndx].format);
1048 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindImageTexture()");
1051 gl.bindBufferBase(inputBuffers[ndx]->getType(), extraData[ndx].binding, inputBuffers[ndx]->getId());
1052 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase()");
1056 de::MovePtr<glu::ShaderProgram> pipeline(
1057 makeGraphicsPipeline(context, (ShaderStageFlags)(SHADER_STAGE_VERTEX_BIT | SHADER_STAGE_FRAGMENT_BIT | SHADER_STAGE_TESS_CONTROL_BIT | SHADER_STAGE_TESS_EVALUATION_BIT),
1058 &vshader, &fshader, DE_NULL, &tcshader, &teshader));
1059 if (!pipeline->isOk())
1061 return tcu::TestStatus::fail("tese graphics program build failed");
1064 const deUint32 subgroupSize = getSubgroupSize(context);
1065 const deUint64 vertexBufferSize = 2ull * maxWidth * sizeof(tcu::Vec4);
1066 Buffer vertexBuffer (context, vertexBufferSize, GL_ARRAY_BUFFER);
1067 unsigned totalIterations = 0u;
1068 unsigned failedIterations = 0u;
1069 Image discardableImage (context, maxWidth, 1u, format);
1072 glw::GLvoid * bufferPtr = vertexBuffer.mapBufferPtr();
1073 std::vector<tcu::Vec4> data (2u * maxWidth, tcu::Vec4(1.0f, 0.0f, 1.0f, 1.0f));
1074 const float pixelSize = 2.0f / static_cast<float>(maxWidth);
1075 float leftHandPosition = -1.0f;
1077 for(deUint32 ndx = 0u; ndx < data.size(); ndx+=2u)
1079 data[ndx][0] = leftHandPosition;
1080 leftHandPosition += pixelSize;
1081 data[ndx+1][0] = leftHandPosition;
1084 deMemcpy(bufferPtr, &data[0], data.size() * sizeof(tcu::Vec4));
1085 vertexBuffer.unmapBufferPtr();
1090 fbo.bind2D(discardableImage);
1092 gl.viewport(0, 0, maxWidth, 1u);
1093 GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport");
1095 for (deUint32 width = 1u; width < maxWidth; ++width)
1097 const deUint64 imageResultSize = getFormatSizeInBytes(format) * maxWidth;
1098 vector<glw::GLubyte> imageBufferResult(imageResultSize);
1099 const deUint64 vertexBufferOffset = 0u;
1104 gl.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
1105 GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor");
1106 gl.clear(GL_COLOR_BUFFER_BIT);
1107 GLU_EXPECT_NO_ERROR(gl.getError(), "glClear");
1109 gl.useProgram(pipeline->getProgram());
1110 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram");
1112 gl.enableVertexAttribArray(0);
1113 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray");
1115 gl.bindBuffer(GL_ARRAY_BUFFER, vertexBuffer.getId());
1116 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer");
1118 gl.vertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(tcu::Vec4), vertexBufferOffset);
1119 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer");
1121 gl.patchParameteri(GL_PATCH_VERTICES, 2u);
1122 GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameter(PATCH_VERTICES)");
1124 gl.drawArrays(GL_PATCHES, 0, 2 * width);
1125 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays");
1127 gl.disableVertexAttribArray(0);
1131 getFormatReadInfo(format, readFormat, readType);
1133 gl.readPixels(0, 0, width, 1, readFormat, readType, (GLvoid*)&imageBufferResult[0]);
1134 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels");
1138 std::vector<const void*> datas;
1139 datas.push_back(&imageBufferResult[0]);
1140 if (!checkResult(datas, width/2u, subgroupSize))
1145 if (0 < failedIterations)
1147 log << tcu::TestLog::Message << (totalIterations - failedIterations) << " / "
1148 << totalIterations << " values passed" << tcu::TestLog::EndMessage;
1149 return tcu::TestStatus::fail("Failed!");
1152 log << tcu::TestLog::Message << (totalIterations - failedIterations) << " / "
1153 <<totalIterations << " values passed" << tcu::TestLog::EndMessage;
1156 return tcu::TestStatus::pass("OK");
1159 bool glc::subgroups::check(std::vector<const void*> datas,
1160 deUint32 width, deUint32 ref)
1162 const deUint32* data = reinterpret_cast<const deUint32*>(datas[0]);
1164 for (deUint32 n = 0; n < width; ++n)
1175 bool glc::subgroups::checkCompute(std::vector<const void*> datas,
1176 const deUint32 numWorkgroups[3], const deUint32 localSize[3],
1179 const deUint32 globalSizeX = numWorkgroups[0] * localSize[0];
1180 const deUint32 globalSizeY = numWorkgroups[1] * localSize[1];
1181 const deUint32 globalSizeZ = numWorkgroups[2] * localSize[2];
1183 return check(datas, globalSizeX * globalSizeY * globalSizeZ, ref);
1187 tcu::TestStatus glc::subgroups::makeGeometryFrameBufferTest(
1188 Context& context, Format format, SSBOData* extraData,
1189 deUint32 extraDataCount,
1190 bool (*checkResult)(std::vector<const void*> datas, deUint32 width, deUint32 subgroupSize))
1192 tcu::TestLog& log = context.getDeqpContext().getTestContext().getLog();
1193 const glw::Functions& gl = context.getDeqpContext().getRenderContext().getFunctions();
1195 const deUint32 maxWidth = 1024u;
1196 vector<de::SharedPtr<BufferOrImage> > inputBuffers (extraDataCount);
1198 const GlslSource& vshader = context.getSourceCollection().get("vert");
1199 const GlslSource& gshader = context.getSourceCollection().get("geometry");
1200 const GlslSource& fshader = context.getSourceCollection().get("fragment");
1202 for (deUint32 i = 0u; i < extraDataCount; i++)
1204 if (extraData[i].isImage)
1206 inputBuffers[i] = de::SharedPtr<BufferOrImage>(new Image(context, static_cast<deUint32>(extraData[i].numElements), 1u, extraData[i].format));
1207 // haven't implemented init for images yet
1208 DE_ASSERT(extraData[i].initializeType == subgroups::SSBOData::InitializeNone);
1212 deUint64 size = getFormatSizeInBytes(extraData[i].format) * extraData[i].numElements;
1213 inputBuffers[i] = de::SharedPtr<BufferOrImage>(new Buffer(context, size, GL_UNIFORM_BUFFER));
1215 glw::GLvoid *ptr = inputBuffers[i]->getAsBuffer()->mapBufferPtr();
1216 initializeMemory(context.getDeqpContext(), ptr, extraData[i]);
1217 inputBuffers[i]->getAsBuffer()->unmapBufferPtr();
1221 for (deUint32 ndx = 0u; ndx < extraDataCount; ndx++)
1223 log << tcu::TestLog::Message
1224 << "binding inputBuffers[" << ndx << "](" << inputBuffers[ndx]->getType() << ", " << inputBuffers[ndx]->getId() << " ), "
1225 << "GEOMETRY, binding = " << extraData[ndx].binding << "\n"
1226 << tcu::TestLog::EndMessage;
1228 if (inputBuffers[ndx]->isImage())
1230 gl.bindImageTexture(extraData[ndx].binding, inputBuffers[ndx]->getId(),
1231 0, GL_FALSE, 0, GL_READ_ONLY, extraData[ndx].format);
1232 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindImageTexture()");
1235 gl.bindBufferBase(inputBuffers[ndx]->getType(), extraData[ndx].binding, inputBuffers[ndx]->getId());
1236 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase()");
1240 de::MovePtr<glu::ShaderProgram> pipeline(
1241 makeGraphicsPipeline(context, (ShaderStageFlags)(SHADER_STAGE_VERTEX_BIT | SHADER_STAGE_FRAGMENT_BIT | SHADER_STAGE_GEOMETRY_BIT),
1242 &vshader, &fshader, &gshader, DE_NULL, DE_NULL));
1243 if (!pipeline->isOk())
1245 return tcu::TestStatus::fail("geom graphics program build failed");
1248 const deUint32 subgroupSize = getSubgroupSize(context);
1249 const deUint64 vertexBufferSize = maxWidth * sizeof(tcu::Vec4);
1250 Buffer vertexBuffer (context, vertexBufferSize, GL_ARRAY_BUFFER);
1251 unsigned totalIterations = 0u;
1252 unsigned failedIterations = 0u;
1253 Image discardableImage (context, maxWidth, 1u, format);
1256 glw::GLvoid * bufferPtr = vertexBuffer.mapBufferPtr();
1257 std::vector<tcu::Vec4> data (maxWidth, tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
1258 const float pixelSize = 2.0f / static_cast<float>(maxWidth);
1259 float leftHandPosition = -1.0f;
1261 for(deUint32 ndx = 0u; ndx < maxWidth; ++ndx)
1263 data[ndx][0] = leftHandPosition + pixelSize / 2.0f;
1264 leftHandPosition += pixelSize;
1267 deMemcpy(bufferPtr, &data[0], maxWidth * sizeof(tcu::Vec4));
1268 vertexBuffer.unmapBufferPtr();
1273 fbo.bind2D(discardableImage);
1275 gl.viewport(0, 0, maxWidth, 1u);
1276 GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport");
1278 for (deUint32 width = 1u; width < maxWidth; width++)
1281 const deUint64 imageResultSize = getFormatSizeInBytes(format) * maxWidth;
1282 vector<glw::GLubyte> imageBufferResult(imageResultSize);
1283 const deUint64 vertexBufferOffset = 0u;
1285 for (deUint32 ndx = 0u; ndx < inputBuffers.size(); ndx++)
1287 if (inputBuffers[ndx]->isImage())
1289 DE_ASSERT(extraData[ndx].initializeType == subgroups::SSBOData::InitializeNone);
1292 glw::GLvoid *ptr = inputBuffers[ndx]->getAsBuffer()->mapBufferPtr();
1293 initializeMemory(context.getDeqpContext(), ptr, extraData[ndx]);
1294 inputBuffers[ndx]->getAsBuffer()->unmapBufferPtr();
1299 gl.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
1300 GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor");
1301 gl.clear(GL_COLOR_BUFFER_BIT);
1302 GLU_EXPECT_NO_ERROR(gl.getError(), "glClear");
1304 gl.useProgram(pipeline->getProgram());
1305 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram");
1307 gl.enableVertexAttribArray(0);
1308 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray");
1310 gl.bindBuffer(GL_ARRAY_BUFFER, vertexBuffer.getId());
1311 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer");
1313 gl.vertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(tcu::Vec4), vertexBufferOffset);
1314 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer");
1316 gl.drawArrays(GL_POINTS, 0, width);
1317 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays");
1319 gl.disableVertexAttribArray(0);
1320 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisableVertexAttribArray");
1324 getFormatReadInfo(format, readFormat, readType);
1326 gl.readPixels(0, 0, width, 1, readFormat, readType, (GLvoid*)&imageBufferResult[0]);
1327 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels");
1331 std::vector<const void*> datas;
1332 datas.push_back(&imageBufferResult[0]);
1333 if (!checkResult(datas, width, subgroupSize))
1338 if (0 < failedIterations)
1340 log << tcu::TestLog::Message << (totalIterations - failedIterations) << " / "
1341 << totalIterations << " values passed" << tcu::TestLog::EndMessage;
1342 return tcu::TestStatus::fail("Failed!");
1345 log << tcu::TestLog::Message << (totalIterations - failedIterations) << " / "
1346 <<totalIterations << " values passed" << tcu::TestLog::EndMessage;
1349 return tcu::TestStatus::pass("OK");
1352 tcu::TestStatus glc::subgroups::allStages(
1353 Context& context, Format format, SSBOData* extraDatas,
1354 deUint32 extraDatasCount,
1355 bool (*checkResult)(std::vector<const void*> datas, deUint32 width, deUint32 subgroupSize),
1356 const ShaderStageFlags shaderStageTested)
1358 const deUint32 maxWidth = 1024u;
1359 vector<ShaderStageFlags> stagesVector;
1360 ShaderStageFlags shaderStageRequired = (ShaderStageFlags)0ull;
1361 tcu::TestLog& log = context.getDeqpContext().getTestContext().getLog();
1362 const glw::Functions& gl = context.getDeqpContext().getRenderContext().getFunctions();
1364 if (shaderStageTested & SHADER_STAGE_VERTEX_BIT)
1366 stagesVector.push_back(SHADER_STAGE_VERTEX_BIT);
1368 if (shaderStageTested & SHADER_STAGE_TESS_CONTROL_BIT)
1370 stagesVector.push_back(SHADER_STAGE_TESS_CONTROL_BIT);
1371 shaderStageRequired = (ShaderStageFlags)((deUint32)shaderStageRequired | ((deUint32)(shaderStageTested & SHADER_STAGE_TESS_EVALUATION_BIT) ? 0u : (deUint32)SHADER_STAGE_TESS_EVALUATION_BIT));
1372 shaderStageRequired = (ShaderStageFlags)((deUint32)shaderStageRequired | ((deUint32)(shaderStageTested & SHADER_STAGE_VERTEX_BIT) ? 0u : (deUint32)SHADER_STAGE_VERTEX_BIT));
1374 if (shaderStageTested & SHADER_STAGE_TESS_EVALUATION_BIT)
1376 stagesVector.push_back(SHADER_STAGE_TESS_EVALUATION_BIT);
1377 shaderStageRequired = (ShaderStageFlags)((deUint32)shaderStageRequired | ((deUint32)(shaderStageTested & SHADER_STAGE_VERTEX_BIT) ? 0u : (deUint32)SHADER_STAGE_VERTEX_BIT));
1378 shaderStageRequired = (ShaderStageFlags)((deUint32)shaderStageRequired | ((deUint32)(shaderStageTested & SHADER_STAGE_TESS_CONTROL_BIT) ? 0u : (deUint32)SHADER_STAGE_TESS_CONTROL_BIT));
1380 if (shaderStageTested & SHADER_STAGE_GEOMETRY_BIT)
1382 stagesVector.push_back(SHADER_STAGE_GEOMETRY_BIT);
1383 const ShaderStageFlags required = SHADER_STAGE_VERTEX_BIT;
1384 shaderStageRequired = (ShaderStageFlags)((deUint32)shaderStageRequired | ((deUint32)(shaderStageTested & required) ? 0u : (deUint32)required));
1386 if (shaderStageTested & SHADER_STAGE_FRAGMENT_BIT)
1388 const ShaderStageFlags required = SHADER_STAGE_VERTEX_BIT;
1389 shaderStageRequired = (ShaderStageFlags)((deUint32)shaderStageRequired | ((deUint32)(shaderStageTested & required) ? 0u : (deUint32)required));
1392 const deUint32 stagesCount = static_cast<deUint32>(stagesVector.size());
1393 const string vert = (shaderStageRequired & SHADER_STAGE_VERTEX_BIT) ? "vert_noSubgroup" : "vert";
1394 const string tesc = (shaderStageRequired & SHADER_STAGE_TESS_CONTROL_BIT) ? "tesc_noSubgroup" : "tesc";
1395 const string tese = (shaderStageRequired & SHADER_STAGE_TESS_EVALUATION_BIT) ? "tese_noSubgroup" : "tese";
1397 shaderStageRequired = (ShaderStageFlags)(shaderStageTested | shaderStageRequired);
1399 const GlslSource *vshader = &context.getSourceCollection().get(vert);
1400 const GlslSource *fshader = DE_NULL;
1401 const GlslSource *gshader = DE_NULL;
1402 const GlslSource *tcshader = DE_NULL;
1403 const GlslSource *teshader = DE_NULL;
1405 if (shaderStageRequired & SHADER_STAGE_TESS_CONTROL_BIT)
1407 tcshader = &context.getSourceCollection().get(tesc);
1408 teshader = &context.getSourceCollection().get(tese);
1410 if (shaderStageRequired & SHADER_STAGE_GEOMETRY_BIT)
1412 if (shaderStageRequired & SHADER_STAGE_TESS_EVALUATION_BIT)
1414 // tessellation shaders output line primitives
1415 gshader = &context.getSourceCollection().get("geometry_lines");
1419 // otherwise points are processed by geometry shader
1420 gshader = &context.getSourceCollection().get("geometry_points");
1423 if (shaderStageRequired & SHADER_STAGE_FRAGMENT_BIT)
1425 fshader = &context.getSourceCollection().get("fragment");
1428 std::vector< de::SharedPtr<BufferOrImage> > inputBuffers(stagesCount + extraDatasCount);
1430 // The implicit result SSBO we use to store our outputs from the shader
1431 for (deUint32 ndx = 0u; ndx < stagesCount; ++ndx)
1433 const deUint64 shaderSize = (stagesVector[ndx] == SHADER_STAGE_TESS_EVALUATION_BIT) ? maxWidth * 2 : maxWidth;
1434 const deUint64 size = getFormatSizeInBytes(format) * shaderSize;
1435 inputBuffers[ndx] = de::SharedPtr<BufferOrImage>(new Buffer(context, size));
1437 log << tcu::TestLog::Message
1438 << "binding inputBuffers[" << ndx << "](" << inputBuffers[ndx]->getType() << ", " << inputBuffers[ndx]->getId() << " ), "
1439 << "inputstage[" << ndx << "] = " << stagesVector[ndx] << " binding = " << getResultBinding(stagesVector[ndx])
1440 << tcu::TestLog::EndMessage;
1442 gl.bindBufferBase(inputBuffers[ndx]->getType(), getResultBinding(stagesVector[ndx]), inputBuffers[ndx]->getId());
1443 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase(ndx, inputBuffers[ndx])");
1446 for (deUint32 ndx = stagesCount; ndx < stagesCount + extraDatasCount; ++ndx)
1448 const deUint32 datasNdx = ndx - stagesCount;
1449 if (extraDatas[datasNdx].isImage)
1451 inputBuffers[ndx] = de::SharedPtr<BufferOrImage>(new Image(context, static_cast<deUint32>(extraDatas[datasNdx].numElements), 1, extraDatas[datasNdx].format));
1453 // haven't implemented init for images yet
1454 DE_ASSERT(extraDatas[datasNdx].initializeType == subgroups::SSBOData::InitializeNone);
1458 const deUint64 size = getFormatSizeInBytes(extraDatas[datasNdx].format) * extraDatas[datasNdx].numElements;
1459 inputBuffers[ndx] = de::SharedPtr<BufferOrImage>(new Buffer(context, size));
1461 glw::GLvoid *ptr = inputBuffers[ndx]->getAsBuffer()->mapBufferPtr();
1462 initializeMemory(context.getDeqpContext(), ptr, extraDatas[datasNdx]);
1463 inputBuffers[ndx]->getAsBuffer()->unmapBufferPtr();
1466 log << tcu::TestLog::Message
1467 << "binding inputBuffers[" << ndx << "](" << inputBuffers[ndx]->getType() << ", " << inputBuffers[ndx]->getId() << " ), "
1468 << "extrastage[" << datasNdx << "] = " << extraDatas[datasNdx].stages << " binding = " << extraDatas[datasNdx].binding
1469 << tcu::TestLog::EndMessage;
1471 if (inputBuffers[ndx]->isImage())
1473 gl.bindImageTexture(extraDatas[datasNdx].binding, inputBuffers[ndx]->getId(),
1474 0, GL_FALSE, 0, GL_READ_WRITE, extraDatas[datasNdx].format);
1475 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindImageTexture(extraDatas[datasNdx])");
1478 gl.bindBufferBase(inputBuffers[ndx]->getType(), extraDatas[datasNdx].binding, inputBuffers[ndx]->getId());
1479 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase(extraDatas[datasNdx])");
1483 de::MovePtr<glu::ShaderProgram> pipeline(
1484 makeGraphicsPipeline(context, shaderStageRequired, vshader, fshader, gshader, tcshader, teshader));
1486 if (!pipeline->isOk())
1488 return tcu::TestStatus::fail("allstages graphics program build failed");
1492 const deUint32 subgroupSize = getSubgroupSize(context);
1493 unsigned totalIterations = 0u;
1494 unsigned failedIterations = 0u;
1495 Image resultImage (context, maxWidth, 1, format);
1496 const deUint64 imageResultSize = getFormatSizeInBytes(format) * maxWidth;
1497 vector<glw::GLubyte> imageBufferResult(imageResultSize);
1501 fbo.bind2D(resultImage);
1503 gl.viewport(0, 0, maxWidth, 1u);
1504 GLU_EXPECT_NO_ERROR(gl.getError(), "viewport");
1506 for (deUint32 width = 1u; width < maxWidth; width++)
1508 for (deUint32 ndx = stagesCount; ndx < stagesCount + extraDatasCount; ++ndx)
1511 if (extraDatas[ndx - stagesCount].isImage)
1513 // haven't implemented init for images yet
1514 DE_ASSERT(extraDatas[ndx - stagesCount].initializeType == subgroups::SSBOData::InitializeNone);
1517 glw::GLvoid *ptr = inputBuffers[ndx]->getAsBuffer()->mapBufferPtr();
1518 initializeMemory(context.getDeqpContext(), ptr, extraDatas[ndx - stagesCount]);
1519 inputBuffers[ndx]->getAsBuffer()->unmapBufferPtr();
1525 gl.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
1526 GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor");
1527 gl.clear(GL_COLOR_BUFFER_BIT);
1528 GLU_EXPECT_NO_ERROR(gl.getError(), "glClear");
1530 gl.useProgram(pipeline->getProgram());
1531 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram");
1533 glw::GLenum drawType;
1534 if (shaderStageRequired & SHADER_STAGE_TESS_CONTROL_BIT)
1536 drawType = GL_PATCHES;
1537 gl.patchParameteri(GL_PATCH_VERTICES, 1u);
1538 GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameter(PATCH_VERTICES)");
1541 drawType = GL_POINTS;
1544 gl.drawArrays(drawType, 0, width);
1545 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays");
1549 getFormatReadInfo(format, readFormat, readType);
1551 gl.readPixels(0, 0, width, 1, readFormat, readType, (GLvoid*)&imageBufferResult[0]);
1552 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels");
1554 for (deUint32 ndx = 0u; ndx < stagesCount; ++ndx)
1556 std::vector<const void*> datas;
1557 std::vector<Buffer *> buffersToUnmap;
1559 if (!inputBuffers[ndx]->isImage())
1561 glw::GLvoid * resultData = inputBuffers[ndx]->getAsBuffer()->mapBufferPtr();
1562 buffersToUnmap.push_back(inputBuffers[ndx]->getAsBuffer());
1563 // we always have our result data first
1564 datas.push_back(resultData);
1567 for (deUint32 index = stagesCount; index < stagesCount + extraDatasCount; ++index)
1569 const deUint32 datasNdx = index - stagesCount;
1570 if ((stagesVector[ndx] & extraDatas[datasNdx].stages) && (!inputBuffers[index]->isImage()))
1572 glw::GLvoid * resultData = inputBuffers[index]->getAsBuffer()->mapBufferPtr();
1573 buffersToUnmap.push_back(inputBuffers[index]->getAsBuffer());
1574 // we always have our result data first
1575 datas.push_back(resultData);
1579 if (!checkResult(datas, (stagesVector[ndx] == SHADER_STAGE_TESS_EVALUATION_BIT) ? width * 2 : width , subgroupSize))
1582 while( !buffersToUnmap.empty() )
1584 Buffer * buf = buffersToUnmap.back();
1585 buf->unmapBufferPtr();
1586 buffersToUnmap.pop_back();
1589 if (shaderStageTested & SHADER_STAGE_FRAGMENT_BIT)
1591 std::vector<const void*> datas;
1592 std::vector<Buffer *> buffersToUnmap;
1594 // we always have our result data first
1595 datas.push_back(&imageBufferResult[0]);
1597 for (deUint32 index = stagesCount; index < stagesCount + extraDatasCount; ++index)
1599 const deUint32 datasNdx = index - stagesCount;
1600 if (SHADER_STAGE_FRAGMENT_BIT & extraDatas[datasNdx].stages && (!inputBuffers[index]->isImage()))
1602 glw::GLvoid * resultData = inputBuffers[index]->getAsBuffer()->mapBufferPtr();
1603 buffersToUnmap.push_back(inputBuffers[index]->getAsBuffer());
1604 // we always have our result data first
1605 datas.push_back(resultData);
1609 if (!checkResult(datas, width , subgroupSize))
1612 while( !buffersToUnmap.empty() )
1614 Buffer * buf = buffersToUnmap.back();
1615 buf->unmapBufferPtr();
1616 buffersToUnmap.pop_back();
1622 if (0 < failedIterations)
1624 log << tcu::TestLog::Message << (totalIterations - failedIterations) << " / "
1625 << totalIterations << " values passed" << tcu::TestLog::EndMessage;
1626 return tcu::TestStatus::fail("Failed!");
1629 log << tcu::TestLog::Message << (totalIterations - failedIterations) << " / "
1630 << totalIterations << " values passed" << tcu::TestLog::EndMessage;
1633 return tcu::TestStatus::pass("OK");
1636 tcu::TestStatus glc::subgroups::makeVertexFrameBufferTest(Context& context, Format format,
1637 SSBOData* extraData, deUint32 extraDataCount,
1638 bool (*checkResult)(std::vector<const void*> datas, deUint32 width, deUint32 subgroupSize))
1640 tcu::TestLog& log = context.getDeqpContext().getTestContext().getLog();
1641 const glw::Functions& gl = context.getDeqpContext().getRenderContext().getFunctions();
1643 const deUint32 maxWidth = 1024u;
1644 vector<de::SharedPtr<BufferOrImage> > inputBuffers (extraDataCount);
1646 const GlslSource& vshader = context.getSourceCollection().get("vert");
1647 const GlslSource& fshader = context.getSourceCollection().get("fragment");
1649 for (deUint32 i = 0u; i < extraDataCount; i++)
1651 if (extraData[i].isImage)
1653 inputBuffers[i] = de::SharedPtr<BufferOrImage>(new Image(context, static_cast<deUint32>(extraData[i].numElements), 1u, extraData[i].format));
1655 // haven't implemented init for images yet
1656 DE_ASSERT(extraData[i].initializeType == subgroups::SSBOData::InitializeNone);
1660 deUint64 size = getFormatSizeInBytes(extraData[i].format) * extraData[i].numElements;
1661 inputBuffers[i] = de::SharedPtr<BufferOrImage>(new Buffer(context, size, GL_UNIFORM_BUFFER));
1663 glw::GLvoid *ptr = inputBuffers[i]->getAsBuffer()->mapBufferPtr();
1664 initializeMemory(context.getDeqpContext(), ptr, extraData[i]);
1665 inputBuffers[i]->getAsBuffer()->unmapBufferPtr();
1669 for (deUint32 ndx = 0u; ndx < extraDataCount; ndx++)
1671 log << tcu::TestLog::Message
1672 << "binding inputBuffers[" << ndx << "](" << inputBuffers[ndx]->getType() << ", " << inputBuffers[ndx]->getId() << " ), "
1673 << "VERTEX, binding = " << extraData[ndx].binding << "\n"
1674 << tcu::TestLog::EndMessage;
1676 if (inputBuffers[ndx]->isImage())
1678 gl.bindImageTexture(extraData[ndx].binding, inputBuffers[ndx]->getId(),
1679 0, GL_FALSE, 0, GL_READ_ONLY, extraData[ndx].format);
1680 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindImageTexture()");
1683 gl.bindBufferBase(inputBuffers[ndx]->getType(), extraData[ndx].binding, inputBuffers[ndx]->getId());
1684 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase()");
1688 de::MovePtr<glu::ShaderProgram> pipeline(
1689 makeGraphicsPipeline(context, (ShaderStageFlags)(SHADER_STAGE_VERTEX_BIT | SHADER_STAGE_FRAGMENT_BIT),
1690 &vshader, &fshader, DE_NULL, DE_NULL, DE_NULL));
1692 if (!pipeline->isOk())
1694 return tcu::TestStatus::fail("vert graphics program build failed");
1697 const deUint32 subgroupSize = getSubgroupSize(context);
1699 const deUint64 vertexBufferSize = maxWidth * sizeof(tcu::Vec4);
1700 Buffer vertexBuffer (context, vertexBufferSize, GL_ARRAY_BUFFER);
1702 unsigned totalIterations = 0u;
1703 unsigned failedIterations = 0u;
1705 Image discardableImage (context, maxWidth, 1u, format);
1708 glw::GLvoid * bufferPtr = vertexBuffer.mapBufferPtr();
1709 std::vector<tcu::Vec4> data (maxWidth, tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
1710 const float pixelSize = 2.0f / static_cast<float>(maxWidth);
1711 float leftHandPosition = -1.0f;
1713 for(deUint32 ndx = 0u; ndx < maxWidth; ++ndx)
1715 data[ndx][0] = leftHandPosition + pixelSize / 2.0f;
1716 leftHandPosition += pixelSize;
1719 deMemcpy(bufferPtr, &data[0], maxWidth * sizeof(tcu::Vec4));
1720 vertexBuffer.unmapBufferPtr();
1725 fbo.bind2D(discardableImage);
1727 gl.viewport(0, 0, maxWidth, 1u);
1728 GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport");
1730 for (deUint32 width = 1u; width < maxWidth; width++)
1733 const deUint64 imageResultSize = getFormatSizeInBytes(format) * maxWidth;
1734 vector<glw::GLubyte> imageBufferResult(imageResultSize);
1735 const deUint64 vertexBufferOffset = 0u;
1737 for (deUint32 ndx = 0u; ndx < inputBuffers.size(); ndx++)
1739 if (inputBuffers[ndx]->isImage())
1741 DE_ASSERT(extraData[ndx].initializeType == subgroups::SSBOData::InitializeNone);
1744 glw::GLvoid *ptr = inputBuffers[ndx]->getAsBuffer()->mapBufferPtr();
1745 initializeMemory(context.getDeqpContext(), ptr, extraData[ndx]);
1746 inputBuffers[ndx]->getAsBuffer()->unmapBufferPtr();
1751 gl.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
1752 GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor");
1753 gl.clear(GL_COLOR_BUFFER_BIT);
1754 GLU_EXPECT_NO_ERROR(gl.getError(), "glClear");
1756 gl.useProgram(pipeline->getProgram());
1757 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram");
1759 gl.enableVertexAttribArray(0);
1760 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray");
1762 gl.bindBuffer(GL_ARRAY_BUFFER, vertexBuffer.getId());
1763 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer");
1765 gl.vertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(tcu::Vec4), vertexBufferOffset);
1766 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer");
1768 gl.drawArrays(GL_POINTS, 0, width);
1769 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays");
1771 gl.disableVertexAttribArray(0);
1772 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisableVertexAttribArray");
1776 getFormatReadInfo(format, readFormat, readType);
1778 gl.readPixels(0, 0, width, 1, readFormat, readType, (GLvoid*)&imageBufferResult[0]);
1779 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels");
1783 std::vector<const void*> datas;
1784 datas.push_back(&imageBufferResult[0]);
1785 if (!checkResult(datas, width, subgroupSize))
1790 if (0 < failedIterations)
1792 log << tcu::TestLog::Message << (totalIterations - failedIterations) << " / "
1793 << totalIterations << " values passed" << tcu::TestLog::EndMessage;
1794 return tcu::TestStatus::fail("Failed!");
1797 log << tcu::TestLog::Message << (totalIterations - failedIterations) << " / "
1798 <<totalIterations << " values passed" << tcu::TestLog::EndMessage;
1801 return tcu::TestStatus::pass("OK");
1805 tcu::TestStatus glc::subgroups::makeFragmentFrameBufferTest (Context& context, Format format, SSBOData* extraDatas,
1806 deUint32 extraDatasCount,
1807 bool (*checkResult)(std::vector<const void*> datas, deUint32 width,
1808 deUint32 height, deUint32 subgroupSize))
1810 tcu::TestLog& log = context.getDeqpContext().getTestContext().getLog();
1811 const glw::Functions& gl = context.getDeqpContext().getRenderContext().getFunctions();
1813 const GlslSource& vshader = context.getSourceCollection().get("vert");
1814 const GlslSource& fshader = context.getSourceCollection().get("fragment");
1816 std::vector< de::SharedPtr<BufferOrImage> > inputBuffers(extraDatasCount);
1818 for (deUint32 i = 0; i < extraDatasCount; i++)
1820 if (extraDatas[i].isImage)
1822 inputBuffers[i] = de::SharedPtr<BufferOrImage>(new Image(context,
1823 static_cast<deUint32>(extraDatas[i].numElements), 1, extraDatas[i].format));
1825 // haven't implemented init for images yet
1826 DE_ASSERT(extraDatas[i].initializeType == subgroups::SSBOData::InitializeNone);
1831 getFormatSizeInBytes(extraDatas[i].format) * extraDatas[i].numElements;
1832 inputBuffers[i] = de::SharedPtr<BufferOrImage>(new Buffer(context, size, GL_UNIFORM_BUFFER));
1834 glw::GLvoid *ptr = inputBuffers[i]->getAsBuffer()->mapBufferPtr();
1835 initializeMemory(context.getDeqpContext(), ptr, extraDatas[i]);
1836 inputBuffers[i]->getAsBuffer()->unmapBufferPtr();
1840 for (deUint32 i = 0; i < extraDatasCount; i++)
1842 log << tcu::TestLog::Message
1843 << "binding inputBuffers[" << i << "](" << inputBuffers[i]->getType() << ", " << inputBuffers[i]->getId() << " ), "
1844 << "FRAGMENT, binding = " << extraDatas[i].binding << "\n"
1845 << tcu::TestLog::EndMessage;
1847 if (inputBuffers[i]->isImage())
1849 gl.bindImageTexture(extraDatas[i].binding, inputBuffers[i]->getId(),
1850 0, GL_FALSE, 0, GL_READ_ONLY, extraDatas[i].format);
1851 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindImageTexture()");
1854 gl.bindBufferBase(inputBuffers[i]->getType(), extraDatas[i].binding, inputBuffers[i]->getId());
1855 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase()");
1859 de::MovePtr<glu::ShaderProgram> pipeline(
1860 makeGraphicsPipeline(context, (ShaderStageFlags)(SHADER_STAGE_VERTEX_BIT | SHADER_STAGE_FRAGMENT_BIT),
1861 &vshader, &fshader, DE_NULL, DE_NULL, DE_NULL));
1863 if (!pipeline->isOk())
1865 return tcu::TestStatus::fail("frag graphics program build failed");
1868 const deUint32 subgroupSize = getSubgroupSize(context);
1870 unsigned totalIterations = 0;
1871 unsigned failedIterations = 0;
1876 for (deUint32 width = 8; width <= subgroupSize; width *= 2)
1878 for (deUint32 height = 8; height <= subgroupSize; height *= 2)
1883 for (deUint32 i = 0; i < extraDatasCount; i++)
1885 if (inputBuffers[i]->isImage())
1887 DE_ASSERT(extraDatas[i].initializeType == subgroups::SSBOData::InitializeNone);
1890 glw::GLvoid *ptr = inputBuffers[i]->getAsBuffer()->mapBufferPtr();
1891 initializeMemory(context.getDeqpContext(), ptr, extraDatas[i]);
1892 inputBuffers[i]->getAsBuffer()->unmapBufferPtr();
1896 deUint64 formatSize = getFormatSizeInBytes(format);
1897 const deUint64 resultImageSizeInBytes =
1898 width * height * formatSize;
1900 Image resultImage(context, width, height, format);
1902 vector<glw::GLubyte> resultBuffer(resultImageSizeInBytes);
1904 fbo.bind2D(resultImage);
1906 gl.viewport(0, 0, width, height);
1907 GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport");
1909 gl.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
1910 GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor");
1911 gl.clear(GL_COLOR_BUFFER_BIT);
1912 GLU_EXPECT_NO_ERROR(gl.getError(), "glClear");
1914 gl.useProgram(pipeline->getProgram());
1915 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram");
1917 gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4);
1918 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays");
1922 getFormatReadInfo(format, readFormat, readType);
1924 gl.readPixels(0, 0, width, height, readFormat, readType, (GLvoid*)&resultBuffer[0]);
1925 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels");
1927 std::vector<const void*> datas;
1929 // we always have our result data first
1930 datas.push_back(&resultBuffer[0]);
1933 if (!checkResult(datas, width, height, subgroupSize))
1940 if (0 < failedIterations)
1942 log << tcu::TestLog::Message << (totalIterations - failedIterations) << " / "
1943 << totalIterations << " values passed" << tcu::TestLog::EndMessage;
1944 return tcu::TestStatus::fail("Failed!");
1947 log << tcu::TestLog::Message << (totalIterations - failedIterations) << " / "
1948 <<totalIterations << " values passed" << tcu::TestLog::EndMessage;
1950 return tcu::TestStatus::pass("OK");
1953 tcu::TestStatus glc::subgroups::makeComputeTest(
1954 Context& context, Format format, SSBOData* inputs, deUint32 inputsCount,
1955 bool (*checkResult)(std::vector<const void*> datas,
1956 const deUint32 numWorkgroups[3], const deUint32 localSize[3],
1957 deUint32 subgroupSize))
1959 const glw::Functions& gl = context.getDeqpContext().getRenderContext().getFunctions();
1960 deUint64 elementSize = getFormatSizeInBytes(format);
1962 const deUint64 resultBufferSize = maxSupportedSubgroupSize() *
1963 maxSupportedSubgroupSize() *
1964 maxSupportedSubgroupSize();
1965 const deUint64 resultBufferSizeInBytes = resultBufferSize * elementSize;
1967 Buffer resultBuffer(
1968 context, resultBufferSizeInBytes);
1970 std::vector< de::SharedPtr<BufferOrImage> > inputBuffers(inputsCount);
1972 for (deUint32 i = 0; i < inputsCount; i++)
1974 if (inputs[i].isImage)
1976 inputBuffers[i] = de::SharedPtr<BufferOrImage>(new Image(context,
1977 static_cast<deUint32>(inputs[i].numElements), 1, inputs[i].format));
1978 // haven't implemented init for images yet
1979 DE_ASSERT(inputs[i].initializeType == subgroups::SSBOData::InitializeNone);
1984 getFormatSizeInBytes(inputs[i].format) * inputs[i].numElements;
1985 inputBuffers[i] = de::SharedPtr<BufferOrImage>(new Buffer(context, size));
1987 glw::GLvoid *ptr = inputBuffers[i]->getAsBuffer()->mapBufferPtr();
1988 initializeMemory(context.getDeqpContext(), ptr, inputs[i]);
1989 inputBuffers[i]->getAsBuffer()->unmapBufferPtr();
1994 tcu::TestLog& log = context.getDeqpContext().getTestContext().getLog();
1995 log << tcu::TestLog::Message
1996 << "binding resultbuffer(type=" << resultBuffer.getType()
1997 << ", id=" << resultBuffer.getId() << ", binding=0), COMPUTE"
1998 << tcu::TestLog::EndMessage;
2000 gl.bindBufferBase(resultBuffer.getType(), 0, resultBuffer.getId());
2001 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase(0, resultBuffer)");
2003 for (deUint32 i = 0; i < inputsCount; i++)
2005 log << tcu::TestLog::Message
2006 << "binding inputBuffers[" << i << "](type=" << inputBuffers[i]->getType()
2007 << ", id=" << inputBuffers[i]->getId() << ", binding="
2008 << inputs[i].binding << "), 1, COMPUTE"
2009 << tcu::TestLog::EndMessage;
2011 if (inputBuffers[i]->isImage())
2013 gl.bindImageTexture(inputs[i].binding, inputBuffers[i]->getId(),
2014 0, GL_FALSE, 0, GL_READ_WRITE, inputs[i].format);
2015 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindImageTexture(inputBuffer[i]");
2018 gl.bindBufferBase(inputBuffers[i]->getType(), inputs[i].binding, inputBuffers[i]->getId());
2019 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase(inputBuffer[i])");
2023 const GlslSource &cshader = context.getSourceCollection().get("comp");
2025 unsigned totalIterations = 0;
2026 unsigned failedIterations = 0;
2028 const deUint32 subgroupSize = getSubgroupSize(context);
2030 const deUint32 numWorkgroups[3] = {4, 2, 2};
2032 const deUint32 localSizesToTestCount = 15;
2033 deUint32 localSizesToTest[localSizesToTestCount][3] =
2042 {subgroupSize, 1, 1},
2043 {1, subgroupSize, 1},
2044 {1, 1, subgroupSize},
2049 {1, 1, 1} // Isn't used, just here to make double buffering checks easier
2053 de::MovePtr<glu::ShaderProgram> lastPipeline(
2054 makeComputePipeline(context, cshader,
2055 localSizesToTest[0][0], localSizesToTest[0][1], localSizesToTest[0][2]));
2057 for (deUint32 index = 0; index < (localSizesToTestCount - 1); index++)
2059 const deUint32 nextX = localSizesToTest[index + 1][0];
2060 const deUint32 nextY = localSizesToTest[index + 1][1];
2061 const deUint32 nextZ = localSizesToTest[index + 1][2];
2063 // we are running one test
2066 if (!lastPipeline->isOk())
2068 return tcu::TestStatus::fail("compute shaders build failed");
2071 gl.useProgram(lastPipeline->getProgram());
2072 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram");
2074 gl.dispatchCompute(numWorkgroups[0], numWorkgroups[1], numWorkgroups[2]);
2075 GLU_EXPECT_NO_ERROR(gl.getError(), "glDispatchCompute");
2077 de::MovePtr<glu::ShaderProgram> nextPipeline(
2078 makeComputePipeline(context, cshader, nextX, nextY, nextZ));
2080 std::vector<const void*> datas;
2083 glw::GLvoid * resultData = resultBuffer.mapBufferPtr();
2085 // we always have our result data first
2086 datas.push_back(resultData);
2089 for (deUint32 i = 0; i < inputsCount; i++)
2091 if (!inputBuffers[i]->isImage())
2093 glw::GLvoid *resultData = inputBuffers[i]->getAsBuffer()->mapBufferPtr();
2095 // we always have our result data first
2096 datas.push_back(resultData);
2100 if (!checkResult(datas, numWorkgroups, localSizesToTest[index], subgroupSize))
2105 resultBuffer.unmapBufferPtr();
2106 for (deUint32 i = 0; i < inputsCount; i++)
2108 if (!inputBuffers[i]->isImage())
2110 inputBuffers[i]->getAsBuffer()->unmapBufferPtr();
2114 lastPipeline = nextPipeline;
2117 if (0 < failedIterations)
2119 log << tcu::TestLog::Message << (totalIterations - failedIterations) << " / "
2120 << totalIterations << " values passed" << tcu::TestLog::EndMessage;
2121 return tcu::TestStatus::fail("Failed!");
2124 log << tcu::TestLog::Message << (totalIterations - failedIterations) << " / "
2125 << totalIterations << " values passed" << tcu::TestLog::EndMessage;
2128 return tcu::TestStatus::pass("OK");