• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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), m_shader(shader), m_program(NULL), m_compileOnly(true)
57 {
58 }
59 
ComputeShader(const std::string & name,const std::string & shader,const tcu::IVec4 & desiredColor)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 
~ComputeShader()66 ShaderGroupVoteTestCaseBase::ComputeShader::~ComputeShader()
67 {
68 	if (m_program)
69 	{
70 		delete m_program;
71 	}
72 }
73 
create(deqp::Context & context)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 
execute(deqp::Context & context)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 
validate(deqp::Context & context)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 
validateScreenPixels(deqp::Context & context,tcu::IVec4 desiredColor)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 */
ShaderGroupVoteTestCaseBase(deqp::Context & context,ExtParameters & extParam,const char * name,const char * description)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 
init()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 
deinit()269 void ShaderGroupVoteTestCaseBase::deinit()
270 {
271 	for (ComputeShaderIter iter = m_shaders.begin(); iter != m_shaders.end(); ++iter)
272 	{
273 		delete (*iter);
274 	}
275 }
276 
iterate()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 */
ShaderGroupVoteAvailabilityTestCase(deqp::Context & context,ExtParameters & extParam)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 */
ShaderGroupVoteFunctionTestCaseBase(deqp::Context & context,ExtParameters & extParam,const char * name,const char * description)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 */
ShaderGroupVoteAllInvocationsTestCase(deqp::Context & context,ExtParameters & extParam)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 */
ShaderGroupVoteAnyInvocationTestCase(deqp::Context & context,ExtParameters & extParam)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 */
ShaderGroupVoteAllInvocationsEqualTestCase(deqp::Context & context,ExtParameters & extParam)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 */
ShaderGroupVoteWithVariablesTestCase(deqp::Context & context,ExtParameters & extParam)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 */
ShaderGroupVote(deqp::Context & context)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. */
init()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 */
455