xref: /aosp_15_r20/external/deqp/external/openglcts/modules/common/glcShaderGroupVoteTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*-------------------------------------------------------------------------
2  * OpenGL Conformance Test Suite
3  * -----------------------------
4  *
5  * Copyright (c) 2017 The Khronos Group Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  */ /*!
20 * \file  glcShaderGroupVoteTests.cpp
21 * \brief Conformance tests for the ARB_shader_group_vote functionality.
22 */ /*-------------------------------------------------------------------*/
23 
24 #include "glcShaderGroupVoteTests.hpp"
25 #include "gluContextInfo.hpp"
26 #include "gluDefs.hpp"
27 #include "gluDrawUtil.hpp"
28 #include "gluObjectWrapper.hpp"
29 #include "gluShaderProgram.hpp"
30 #include "glwEnums.hpp"
31 #include "glwFunctions.hpp"
32 #include "tcuRenderTarget.hpp"
33 #include "tcuTestLog.hpp"
34 
35 using namespace glw;
36 
37 namespace glcts
38 {
39 
40 // Helper structure that wpraps workgroup size
41 struct WorkGroupSize
42 {
WorkGroupSizeglcts::WorkGroupSize43     WorkGroupSize(deqp::Context &context)
44     {
45         width  = 16;
46         height = 16;
47         if (glu::isContextTypeES(context.getRenderContext().getType()))
48             height = 8;
49     }
50 
51     GLsizei width;
52     GLsizei height;
53 };
54 
ComputeShader(const std::string & name,const std::string & shader)55 ShaderGroupVoteTestCaseBase::ComputeShader::ComputeShader(const std::string &name, const std::string &shader)
56     : m_name(name)
57     , m_shader(shader)
58     , m_program(NULL)
59     , m_compileOnly(true)
60 {
61 }
62 
ComputeShader(const std::string & name,const std::string & shader,const tcu::IVec4 & desiredColor)63 ShaderGroupVoteTestCaseBase::ComputeShader::ComputeShader(const std::string &name, const std::string &shader,
64                                                           const tcu::IVec4 &desiredColor)
65     : m_name(name)
66     , m_shader(shader)
67     , m_program(NULL)
68     , m_desiredColor(desiredColor)
69     , m_compileOnly(false)
70 {
71 }
72 
~ComputeShader()73 ShaderGroupVoteTestCaseBase::ComputeShader::~ComputeShader()
74 {
75     if (m_program)
76     {
77         delete m_program;
78     }
79 }
80 
create(deqp::Context & context)81 void ShaderGroupVoteTestCaseBase::ComputeShader::create(deqp::Context &context)
82 {
83     glu::ProgramSources sourcesCompute;
84     sourcesCompute.sources[glu::SHADERTYPE_COMPUTE].push_back(m_shader);
85     m_program = new glu::ShaderProgram(context.getRenderContext(), sourcesCompute);
86 
87     if (!m_program->isOk())
88     {
89         context.getTestContext().getLog()
90             << tcu::TestLog::Message << m_shader << m_program->getShaderInfo(glu::SHADERTYPE_COMPUTE).infoLog
91             << m_program->getProgramInfo().infoLog << tcu::TestLog::EndMessage;
92         TCU_FAIL("Shader compilation failed");
93     }
94 }
95 
execute(deqp::Context & context)96 void ShaderGroupVoteTestCaseBase::ComputeShader::execute(deqp::Context &context)
97 {
98     if (m_compileOnly)
99     {
100         return;
101     }
102 
103     const glw::Functions &gl = context.getRenderContext().getFunctions();
104     const glu::Texture outputTexture(context.getRenderContext());
105     const WorkGroupSize renderSize(context);
106 
107     gl.clearColor(0.5f, 0.5f, 0.5f, 1.0f);
108     gl.clear(GL_COLOR_BUFFER_BIT);
109 
110     gl.useProgram(m_program->getProgram());
111     GLU_EXPECT_NO_ERROR(gl.getError(), "useProgram failed");
112 
113     // output image
114     gl.bindTexture(GL_TEXTURE_2D, *outputTexture);
115     gl.texStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, renderSize.width, renderSize.height);
116     gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
117     gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
118     GLU_EXPECT_NO_ERROR(gl.getError(), "Uploading image data failed");
119 
120     // bind image
121     gl.bindImageTexture(2, *outputTexture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8);
122     GLU_EXPECT_NO_ERROR(gl.getError(), "bindImageTexture failed");
123 
124     // dispatch compute
125     gl.dispatchCompute(1, 1, 1);
126     GLU_EXPECT_NO_ERROR(gl.getError(), "dispatchCompute failed");
127 
128     glu::GLSLVersion glslVersion   = glu::getContextTypeGLSLVersion(context.getRenderContext().getType());
129     const char *versionDeclaration = glu::getGLSLVersionDeclaration(glslVersion);
130 
131     // render output texture
132     std::string vs = versionDeclaration;
133     vs += "\n"
134           "in highp vec2 position;\n"
135           "in highp vec2 inTexcoord;\n"
136           "out highp vec2 texcoord;\n"
137           "void main()\n"
138           "{\n"
139           "    texcoord = inTexcoord;\n"
140           "    gl_Position = vec4(position, 0.0, 1.0);\n"
141           "}\n";
142 
143     std::string fs = versionDeclaration;
144     fs += "\n"
145           "uniform highp sampler2D sampler;\n"
146           "in highp vec2 texcoord;\n"
147           "out highp vec4 color;\n"
148           "void main()\n"
149           "{\n"
150           "    color = texture(sampler, texcoord);\n"
151           "}\n";
152 
153     glu::ProgramSources sources;
154     sources.sources[glu::SHADERTYPE_VERTEX].push_back(vs);
155     sources.sources[glu::SHADERTYPE_FRAGMENT].push_back(fs);
156     glu::ShaderProgram renderShader(context.getRenderContext(), sources);
157 
158     if (!m_program->isOk())
159     {
160         TCU_FAIL("Shader compilation failed");
161     }
162 
163     gl.bindTexture(GL_TEXTURE_2D, *outputTexture);
164     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
165 
166     gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
167     gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
168     GLU_EXPECT_NO_ERROR(gl.getError(), "texParameteri failed");
169 
170     gl.useProgram(renderShader.getProgram());
171     GLU_EXPECT_NO_ERROR(gl.getError(), "useProgram failed");
172 
173     gl.uniform1i(gl.getUniformLocation(renderShader.getProgram(), "sampler"), 0);
174     GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i failed");
175 
176     uint16_t const quadIndices[] = {0, 1, 2, 2, 1, 3};
177 
178     float const position[] = {-1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f};
179 
180     float const texCoord[] = {0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f};
181 
182     glu::VertexArrayBinding vertexArrays[] = {glu::va::Float("position", 2, 4, 0, position),
183                                               glu::va::Float("inTexcoord", 2, 4, 0, texCoord)};
184 
185     gl.viewport(0, 0, renderSize.width, renderSize.height);
186     glu::draw(context.getRenderContext(), renderShader.getProgram(), DE_LENGTH_OF_ARRAY(vertexArrays), vertexArrays,
187               glu::pr::TriangleStrip(DE_LENGTH_OF_ARRAY(quadIndices), quadIndices));
188 
189     GLU_EXPECT_NO_ERROR(gl.getError(), "glu::draw error");
190 
191     gl.flush();
192 }
193 
validate(deqp::Context & context)194 void ShaderGroupVoteTestCaseBase::ComputeShader::validate(deqp::Context &context)
195 {
196     if (m_compileOnly)
197     {
198         return;
199     }
200 
201     bool validationResult          = validateScreenPixels(context, m_desiredColor);
202     std::string validationErrorMsg = "Validation failed for " + m_name + " test";
203 
204     TCU_CHECK_MSG(validationResult, validationErrorMsg.c_str());
205 }
206 
validateScreenPixels(deqp::Context & context,tcu::IVec4 desiredColor)207 bool ShaderGroupVoteTestCaseBase::ComputeShader::validateScreenPixels(deqp::Context &context, tcu::IVec4 desiredColor)
208 {
209     const glw::Functions &gl = context.getRenderContext().getFunctions();
210     const WorkGroupSize renderSize(context);
211     std::size_t totalSize = renderSize.width * renderSize.height * 4;
212     std::vector<glw::GLubyte> pixels(totalSize, 128);
213 
214     // read pixels
215     gl.readPixels(0, 0, renderSize.width, renderSize.height, GL_RGBA, GL_UNSIGNED_BYTE, &pixels[0]);
216 
217     // compare pixels to desired color
218     for (std::size_t i = 0; i < totalSize; i += 4)
219     {
220         if ((pixels[i + 0] != desiredColor.x()) || (pixels[i + 1] != desiredColor.y()) ||
221             (pixels[i + 2] != desiredColor.z()))
222             return false;
223     }
224 
225     return true;
226 }
227 
228 /** Constructor.
229  *
230  *  @param context Rendering context
231  *  @param name Test name
232  *  @param description Test description
233  */
ShaderGroupVoteTestCaseBase(deqp::Context & context,ExtParameters & extParam,const char * name,const char * description)234 ShaderGroupVoteTestCaseBase::ShaderGroupVoteTestCaseBase(deqp::Context &context, ExtParameters &extParam,
235                                                          const char *name, const char *description)
236     : TestCaseBase(context, glcts::ExtParameters(glu::GLSL_VERSION_450, glcts::EXTENSIONTYPE_EXT), name, description)
237     , m_extensionSupported(true)
238 {
239     const WorkGroupSize workGroupSize(context);
240     glu::ContextType contextType   = m_context.getRenderContext().getType();
241     m_specializationMap["VERSION"] = glu::getGLSLVersionDeclaration(extParam.glslVersion);
242 
243     std::stringstream stream;
244     stream << workGroupSize.width << " " << workGroupSize.height;
245     stream >> m_specializationMap["SIZE_X"] >> m_specializationMap["SIZE_Y"];
246 
247     if (glu::contextSupports(contextType, glu::ApiType::core(4, 6)))
248     {
249         m_specializationMap["GROUP_VOTE_EXTENSION"] = "";
250         m_specializationMap["EXT_TYPE"]             = "";
251     }
252     else
253     {
254         bool isCoreGL             = glu::isContextTypeGLCore(contextType);
255         std::string extensionName = isCoreGL ? "GL_ARB_shader_group_vote" : "GL_EXT_shader_group_vote";
256         m_extensionSupported      = context.getContextInfo().isExtensionSupported(extensionName.c_str());
257         std::stringstream extensionString;
258         extensionString << "#extension " + extensionName + " : enable";
259 
260         m_specializationMap["GROUP_VOTE_EXTENSION"] = extensionString.str();
261         m_specializationMap["EXT_TYPE"]             = isCoreGL ? "ARB" : "EXT";
262     }
263 }
264 
init()265 void ShaderGroupVoteTestCaseBase::init()
266 {
267     if (m_extensionSupported)
268     {
269         for (ComputeShaderIter iter = m_shaders.begin(); iter != m_shaders.end(); ++iter)
270         {
271             (*iter)->create(m_context);
272         }
273     }
274 }
275 
deinit()276 void ShaderGroupVoteTestCaseBase::deinit()
277 {
278     for (ComputeShaderIter iter = m_shaders.begin(); iter != m_shaders.end(); ++iter)
279     {
280         delete (*iter);
281     }
282 }
283 
iterate()284 tcu::TestNode::IterateResult ShaderGroupVoteTestCaseBase::iterate()
285 {
286     if (!m_extensionSupported)
287     {
288         m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not supported");
289         return STOP;
290     }
291 
292     for (ComputeShaderIter iter = m_shaders.begin(); iter != m_shaders.end(); ++iter)
293     {
294         (*iter)->execute(m_context);
295         (*iter)->validate(m_context);
296     }
297 
298     m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
299     return STOP;
300 }
301 
302 /** Constructor.
303  *
304  *  @param context Rendering context
305  */
ShaderGroupVoteAvailabilityTestCase(deqp::Context & context,ExtParameters & extParam)306 ShaderGroupVoteAvailabilityTestCase::ShaderGroupVoteAvailabilityTestCase(deqp::Context &context,
307                                                                          ExtParameters &extParam)
308     : ShaderGroupVoteTestCaseBase(context, extParam, "availability", "Implements ...")
309 {
310     const char *shader = "${VERSION}\n"
311                          "${GROUP_VOTE_EXTENSION}\n"
312                          "layout(rgba8, binding = 2) writeonly uniform highp image2D destImage;\n"
313                          "layout(local_size_x = ${SIZE_X}, local_size_y = ${SIZE_Y}) in;\n"
314                          "void main (void)\n"
315                          "{\n"
316                          "    vec4 outColor = vec4(0.0);\n"
317                          "    outColor.r = allInvocations${EXT_TYPE}(true) ? 1.0 : 0.0;\n"
318                          "    outColor.g = anyInvocation${EXT_TYPE}(true) ? 1.0 : 0.0;\n"
319                          "    outColor.b = allInvocationsEqual${EXT_TYPE}(true) ? 1.0 : 0.0;\n"
320                          "    imageStore(destImage, ivec2(gl_GlobalInvocationID.xy), outColor);\n"
321                          "}\n";
322 
323     m_shaders.push_back(new ComputeShader("availability", specializeShader(1, &shader)));
324 }
325 
326 /** Constructor.
327  *
328  *  @param context Rendering context
329  *  @param name Test name
330  *  @param description Test description
331  */
ShaderGroupVoteFunctionTestCaseBase(deqp::Context & context,ExtParameters & extParam,const char * name,const char * description)332 ShaderGroupVoteFunctionTestCaseBase::ShaderGroupVoteFunctionTestCaseBase(deqp::Context &context,
333                                                                          ExtParameters &extParam, const char *name,
334                                                                          const char *description)
335     : ShaderGroupVoteTestCaseBase(context, extParam, name, description)
336 {
337     m_shaderBase += "${VERSION}\n"
338                     "${GROUP_VOTE_EXTENSION}\n"
339                     "layout(rgba8, binding = 2) writeonly uniform highp image2D destImage;\n"
340                     "layout(local_size_x = ${SIZE_X}, local_size_y = ${SIZE_Y}) in;\n"
341                     "void main (void)\n"
342                     "{\n"
343                     "    bool result = ${FUNC}${EXT_TYPE}(${FUNC_PARAMETER});\n"
344                     "    vec4 outColor = vec4(vec3(result ? 1.0 : 0.0), 1.0);\n"
345                     "    imageStore(destImage, ivec2(gl_GlobalInvocationID.xy), outColor);\n"
346                     "}\n";
347 }
348 
349 /** Constructor.
350  *
351  *  @param context Rendering context
352  */
ShaderGroupVoteAllInvocationsTestCase(deqp::Context & context,ExtParameters & extParam)353 ShaderGroupVoteAllInvocationsTestCase::ShaderGroupVoteAllInvocationsTestCase(deqp::Context &context,
354                                                                              ExtParameters &extParam)
355     : ShaderGroupVoteFunctionTestCaseBase(context, extParam, "all_invocations", "Implements ...")
356 {
357     const char *shaderBase                = m_shaderBase.c_str();
358     m_specializationMap["FUNC"]           = "allInvocations";
359     m_specializationMap["FUNC_PARAMETER"] = "true";
360 
361     m_shaders.push_back(
362         new ComputeShader("allInvocationsARB", specializeShader(1, &shaderBase), tcu::IVec4(255, 255, 255, 255)));
363 }
364 
365 /** Constructor.
366  *
367  *  @param context Rendering context
368  */
ShaderGroupVoteAnyInvocationTestCase(deqp::Context & context,ExtParameters & extParam)369 ShaderGroupVoteAnyInvocationTestCase::ShaderGroupVoteAnyInvocationTestCase(deqp::Context &context,
370                                                                            ExtParameters &extParam)
371     : ShaderGroupVoteFunctionTestCaseBase(context, extParam, "any_invocation", "Implements ...")
372 {
373     const char *shaderBase                = m_shaderBase.c_str();
374     m_specializationMap["FUNC"]           = "anyInvocation";
375     m_specializationMap["FUNC_PARAMETER"] = "false";
376 
377     m_shaders.push_back(
378         new ComputeShader("anyInvocationARB", specializeShader(1, &shaderBase), tcu::IVec4(0, 0, 0, 255)));
379 }
380 
381 /** Constructor.
382  *
383  *  @param context Rendering context
384  */
ShaderGroupVoteAllInvocationsEqualTestCase(deqp::Context & context,ExtParameters & extParam)385 ShaderGroupVoteAllInvocationsEqualTestCase::ShaderGroupVoteAllInvocationsEqualTestCase(deqp::Context &context,
386                                                                                        ExtParameters &extParam)
387     : ShaderGroupVoteFunctionTestCaseBase(context, extParam, "all_invocations_equal", "Implements ...")
388 {
389     const char *shaderBase                = m_shaderBase.c_str();
390     m_specializationMap["FUNC"]           = "allInvocationsEqual";
391     m_specializationMap["FUNC_PARAMETER"] = "true";
392     m_shaders.push_back(
393         new ComputeShader("allInvocationsEqualARB", specializeShader(1, &shaderBase), tcu::IVec4(255, 255, 255, 255)));
394 
395     m_specializationMap["FUNC"]           = "allInvocationsEqual";
396     m_specializationMap["FUNC_PARAMETER"] = "false";
397     m_shaders.push_back(
398         new ComputeShader("allInvocationsEqualARB", specializeShader(1, &shaderBase), tcu::IVec4(255, 255, 255, 255)));
399 }
400 
401 /** Constructor.
402  *
403  *  @param context Rendering context
404  */
ShaderGroupVoteWithVariablesTestCase(deqp::Context & context,ExtParameters & extParam)405 ShaderGroupVoteWithVariablesTestCase::ShaderGroupVoteWithVariablesTestCase(deqp::Context &context,
406                                                                            ExtParameters &extParam)
407     : ShaderGroupVoteTestCaseBase(context, extParam, "invocations_with_variables", "Implements ...")
408 {
409     const char *shaderBase = "${VERSION}\n"
410                              "${GROUP_VOTE_EXTENSION}\n"
411                              "layout(rgba8, binding = 2) writeonly uniform highp image2D destImage;\n"
412                              "layout(local_size_x = ${SIZE_X}, local_size_y = ${SIZE_Y}) in;\n"
413                              "void main (void)\n"
414                              "{\n"
415                              "    bool result = ${EXPRESSION};\n"
416                              "    vec4 outColor = vec4(vec3(result ? 1.0 : 0.0), 1.0);\n"
417                              "    imageStore(destImage, ivec2(gl_GlobalInvocationID.xy), outColor);\n"
418                              "}\n";
419 
420     // first specialization EXPRESSION and then whole shader
421     const char *expression1           = "allInvocations${EXT_TYPE}((gl_LocalInvocationIndex % 2u) == 1u) && "
422                                         "anyInvocation${EXT_TYPE}((gl_LocalInvocationIndex % 2u) == 0u) && "
423                                         "anyInvocation${EXT_TYPE}((gl_LocalInvocationIndex % 2u) == 1u)";
424     m_specializationMap["EXPRESSION"] = specializeShader(1, &expression1);
425     m_shaders.push_back(
426         new ComputeShader("allInvocations", specializeShader(1, &shaderBase), tcu::IVec4(0, 0, 0, 255)));
427 
428     const char *expression2           = "anyInvocation${EXT_TYPE}(gl_LocalInvocationIndex < 256u)";
429     m_specializationMap["EXPRESSION"] = specializeShader(1, &expression2);
430     m_shaders.push_back(
431         new ComputeShader("anyInvocation", specializeShader(1, &shaderBase), tcu::IVec4(255, 255, 255, 255)));
432 
433     const char *expression3           = "allInvocationsEqual${EXT_TYPE}(gl_WorkGroupID.x == 0u)";
434     m_specializationMap["EXPRESSION"] = specializeShader(1, &expression3);
435     m_shaders.push_back(
436         new ComputeShader("anyInvocation", specializeShader(1, &shaderBase), tcu::IVec4(255, 255, 255, 255)));
437 }
438 
439 /** Constructor.
440  *
441  *  @param context Rendering context.
442  */
ShaderGroupVote(deqp::Context & context)443 ShaderGroupVote::ShaderGroupVote(deqp::Context &context)
444     : TestCaseGroup(context, "shader_group_vote",
445                     "Verify conformance of shader_group_vote functionality implementation")
446 {
447 }
448 
449 /** Initializes the test group contents. */
init()450 void ShaderGroupVote::init()
451 {
452     glu::GLSLVersion glslVersion = getContextTypeGLSLVersion(m_context.getRenderContext().getType());
453     ExtParameters extParam       = glcts::ExtParameters(glslVersion, glcts::EXTENSIONTYPE_EXT);
454 
455     addChild(new ShaderGroupVoteAvailabilityTestCase(m_context, extParam));
456     addChild(new ShaderGroupVoteAllInvocationsTestCase(m_context, extParam));
457     addChild(new ShaderGroupVoteAnyInvocationTestCase(m_context, extParam));
458     addChild(new ShaderGroupVoteAllInvocationsEqualTestCase(m_context, extParam));
459     addChild(new ShaderGroupVoteWithVariablesTestCase(m_context, extParam));
460 }
461 } // namespace glcts
462