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