Home | History | Annotate | Download | only in functional
      1 /*-------------------------------------------------------------------------
      2  * drawElements Quality Program OpenGL ES 3.1 Module
      3  * -------------------------------------------------
      4  *
      5  * Copyright 2014 The Android Open Source Project
      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
     21  * \brief GLSL Shared variable tests.
     22  *//*--------------------------------------------------------------------*/
     23 
     24 #include "es31fShaderSharedVarTests.hpp"
     25 #include "es31fShaderAtomicOpTests.hpp"
     26 #include "gluShaderProgram.hpp"
     27 #include "gluShaderUtil.hpp"
     28 #include "gluRenderContext.hpp"
     29 #include "gluObjectWrapper.hpp"
     30 #include "gluProgramInterfaceQuery.hpp"
     31 #include "tcuVector.hpp"
     32 #include "tcuTestLog.hpp"
     33 #include "tcuVectorUtil.hpp"
     34 #include "tcuFormatUtil.hpp"
     35 #include "deRandom.hpp"
     36 #include "glwFunctions.hpp"
     37 #include "glwEnums.hpp"
     38 
     39 #include <algorithm>
     40 #include <set>
     41 
     42 namespace deqp
     43 {
     44 namespace gles31
     45 {
     46 namespace Functional
     47 {
     48 
     49 using std::string;
     50 using std::vector;
     51 using tcu::TestLog;
     52 using tcu::UVec3;
     53 using std::set;
     54 using namespace glu;
     55 
     56 enum
     57 {
     58 	MAX_VALUE_ARRAY_LENGTH	= 15	// * 2 * sizeof(mat4) + sizeof(int) = 481 uniform components (limit 512)
     59 };
     60 
     61 template<typename T, int Size>
     62 static inline T product (const tcu::Vector<T, Size>& v)
     63 {
     64 	T res = v[0];
     65 	for (int ndx = 1; ndx < Size; ndx++)
     66 		res *= v[ndx];
     67 	return res;
     68 }
     69 
     70 class SharedBasicVarCase : public TestCase
     71 {
     72 public:
     73 							SharedBasicVarCase		(Context& context, const char* name, DataType basicType, Precision precision, const tcu::UVec3& workGroupSize);
     74 							~SharedBasicVarCase		(void);
     75 
     76 	void					init					(void);
     77 	void					deinit					(void);
     78 	IterateResult			iterate					(void);
     79 
     80 private:
     81 							SharedBasicVarCase		(const SharedBasicVarCase& other);
     82 	SharedBasicVarCase&		operator=				(const SharedBasicVarCase& other);
     83 
     84 	const DataType			m_basicType;
     85 	const Precision			m_precision;
     86 	const tcu::UVec3		m_workGroupSize;
     87 
     88 	ShaderProgram*			m_program;
     89 };
     90 
     91 static std::string getBasicCaseDescription (DataType basicType, Precision precision, const tcu::UVec3& workGroupSize)
     92 {
     93 	std::ostringstream str;
     94 	if (precision != PRECISION_LAST)
     95 		str << getPrecisionName(precision) << " ";
     96 	str << getDataTypeName(basicType) << ", work group size = " << workGroupSize;
     97 	return str.str();
     98 }
     99 
    100 SharedBasicVarCase::SharedBasicVarCase (Context& context, const char* name, DataType basicType, Precision precision, const tcu::UVec3& workGroupSize)
    101 	: TestCase			(context, name, getBasicCaseDescription(basicType, precision, workGroupSize).c_str())
    102 	, m_basicType		(basicType)
    103 	, m_precision		(precision)
    104 	, m_workGroupSize	(workGroupSize)
    105 	, m_program			(DE_NULL)
    106 {
    107 }
    108 
    109 SharedBasicVarCase::~SharedBasicVarCase (void)
    110 {
    111 	SharedBasicVarCase::deinit();
    112 }
    113 
    114 void SharedBasicVarCase::init (void)
    115 {
    116 	const int			valArrayLength	= de::min<int>(MAX_VALUE_ARRAY_LENGTH, product(m_workGroupSize));
    117 	const char*			precName		= m_precision != glu::PRECISION_LAST ? getPrecisionName(m_precision) : "";
    118 	const char*			typeName		= getDataTypeName(m_basicType);
    119 	std::ostringstream	src;
    120 
    121 	src << "#version 310 es\n"
    122 		<< "layout (local_size_x = " << m_workGroupSize[0]
    123 		<< ", local_size_y = " << m_workGroupSize[1]
    124 		<< ", local_size_z = " << m_workGroupSize[2]
    125 		<< ") in;\n"
    126 		<< "const uint LOCAL_SIZE = gl_WorkGroupSize.x*gl_WorkGroupSize.y*gl_WorkGroupSize.z;\n"
    127 		<< "shared " << precName << " " << typeName << " s_var;\n"
    128 		<< "uniform " << precName << " " << typeName << " u_val[" << valArrayLength << "];\n"
    129 		<< "uniform " << precName << " " << typeName << " u_ref[" << valArrayLength << "];\n"
    130 		<< "uniform uint u_numIters;\n"
    131 		<< "layout(binding = 0) buffer Result\n"
    132 		<< "{\n"
    133 		<< "	bool isOk[LOCAL_SIZE];\n"
    134 		<< "};\n"
    135 		<< "\n"
    136 		<< "void main (void)\n"
    137 		<< "{\n"
    138 		<< "	bool allOk = true;\n"
    139 		<< "	for (uint ndx = 0u; ndx < u_numIters; ndx++)\n"
    140 		<< "	{\n"
    141 		<< "		if (ndx == gl_LocalInvocationIndex)\n"
    142 		<< "			s_var = u_val[ndx%uint(u_val.length())];\n"
    143 		<< "\n"
    144 		<< "		barrier();\n"
    145 		<< "\n"
    146 		<< "		if (s_var != u_ref[ndx%uint(u_ref.length())])\n"
    147 		<< "			allOk = false;\n"
    148 		<< "\n"
    149 		<< "		barrier();\n"
    150 		<< "	}\n"
    151 		<< "\n"
    152 		<< "	isOk[gl_LocalInvocationIndex] = allOk;\n"
    153 		<< "}\n";
    154 
    155 	DE_ASSERT(!m_program);
    156 	m_program = new ShaderProgram(m_context.getRenderContext(), ProgramSources() << ComputeSource(src.str()));
    157 
    158 	m_testCtx.getLog() << *m_program;
    159 
    160 	if (!m_program->isOk())
    161 	{
    162 		delete m_program;
    163 		m_program = DE_NULL;
    164 		throw tcu::TestError("Compile failed");
    165 	}
    166 }
    167 
    168 void SharedBasicVarCase::deinit (void)
    169 {
    170 	delete m_program;
    171 	m_program = DE_NULL;
    172 }
    173 
    174 SharedBasicVarCase::IterateResult SharedBasicVarCase::iterate (void)
    175 {
    176 	const glw::Functions&		gl				= m_context.getRenderContext().getFunctions();
    177 	const deUint32				program			= m_program->getProgram();
    178 	Buffer						outputBuffer	(m_context.getRenderContext());
    179 	const deUint32				outBlockNdx		= gl.getProgramResourceIndex(program, GL_SHADER_STORAGE_BLOCK, "Result");
    180 	const InterfaceBlockInfo	outBlockInfo	= getProgramInterfaceBlockInfo(gl, program, GL_SHADER_STORAGE_BLOCK, outBlockNdx);
    181 
    182 	gl.useProgram(program);
    183 
    184 	// Setup input values.
    185 	{
    186 		const int		numValues		= (int)product(m_workGroupSize);
    187 		const int		valLoc			= gl.getUniformLocation(program, "u_val[0]");
    188 		const int		refLoc			= gl.getUniformLocation(program, "u_ref[0]");
    189 		const int		iterCountLoc	= gl.getUniformLocation(program, "u_numIters");
    190 		const int		scalarSize		= getDataTypeScalarSize(m_basicType);
    191 
    192 		if (isDataTypeFloatOrVec(m_basicType))
    193 		{
    194 			const int		maxInt			= m_precision == glu::PRECISION_LOWP ? 2 : 1024;
    195 			const int		minInt			= -de::min(numValues/2, maxInt);
    196 			vector<float>	values			(numValues*scalarSize);
    197 
    198 			for (int ndx = 0; ndx < (int)values.size(); ndx++)
    199 				values[ndx] = float(minInt + (ndx % (maxInt-minInt+1)));
    200 
    201 			for (int uNdx = 0; uNdx < 2; uNdx++)
    202 			{
    203 				const int location = uNdx == 1 ? refLoc : valLoc;
    204 
    205 				if (scalarSize == 1)		gl.uniform1fv(location, numValues, &values[0]);
    206 				else if (scalarSize == 2)	gl.uniform2fv(location, numValues, &values[0]);
    207 				else if (scalarSize == 3)	gl.uniform3fv(location, numValues, &values[0]);
    208 				else if (scalarSize == 4)	gl.uniform4fv(location, numValues, &values[0]);
    209 			}
    210 		}
    211 		else if (isDataTypeIntOrIVec(m_basicType))
    212 		{
    213 			const int		maxInt			= m_precision == glu::PRECISION_LOWP ? 64 : 1024;
    214 			const int		minInt			= -de::min(numValues/2, maxInt);
    215 			vector<int>		values			(numValues*scalarSize);
    216 
    217 			for (int ndx = 0; ndx < (int)values.size(); ndx++)
    218 				values[ndx] = minInt + (ndx % (maxInt-minInt+1));
    219 
    220 			for (int uNdx = 0; uNdx < 2; uNdx++)
    221 			{
    222 				const int location = uNdx == 1 ? refLoc : valLoc;
    223 
    224 				if (scalarSize == 1)		gl.uniform1iv(location, numValues, &values[0]);
    225 				else if (scalarSize == 2)	gl.uniform2iv(location, numValues, &values[0]);
    226 				else if (scalarSize == 3)	gl.uniform3iv(location, numValues, &values[0]);
    227 				else if (scalarSize == 4)	gl.uniform4iv(location, numValues, &values[0]);
    228 			}
    229 		}
    230 		else if (isDataTypeUintOrUVec(m_basicType))
    231 		{
    232 			const deUint32		maxInt		= m_precision == glu::PRECISION_LOWP ? 128 : 1024;
    233 			vector<deUint32>	values		(numValues*scalarSize);
    234 
    235 			for (int ndx = 0; ndx < (int)values.size(); ndx++)
    236 				values[ndx] = ndx % (maxInt+1);
    237 
    238 			for (int uNdx = 0; uNdx < 2; uNdx++)
    239 			{
    240 				const int location = uNdx == 1 ? refLoc : valLoc;
    241 
    242 				if (scalarSize == 1)		gl.uniform1uiv(location, numValues, &values[0]);
    243 				else if (scalarSize == 2)	gl.uniform2uiv(location, numValues, &values[0]);
    244 				else if (scalarSize == 3)	gl.uniform3uiv(location, numValues, &values[0]);
    245 				else if (scalarSize == 4)	gl.uniform4uiv(location, numValues, &values[0]);
    246 			}
    247 		}
    248 		else if (isDataTypeBoolOrBVec(m_basicType))
    249 		{
    250 			de::Random		rnd				(0x324f);
    251 			vector<int>		values			(numValues*scalarSize);
    252 
    253 			for (int ndx = 0; ndx < (int)values.size(); ndx++)
    254 				values[ndx] = rnd.getBool() ? 1 : 0;
    255 
    256 			for (int uNdx = 0; uNdx < 2; uNdx++)
    257 			{
    258 				const int location = uNdx == 1 ? refLoc : valLoc;
    259 
    260 				if (scalarSize == 1)		gl.uniform1iv(location, numValues, &values[0]);
    261 				else if (scalarSize == 2)	gl.uniform2iv(location, numValues, &values[0]);
    262 				else if (scalarSize == 3)	gl.uniform3iv(location, numValues, &values[0]);
    263 				else if (scalarSize == 4)	gl.uniform4iv(location, numValues, &values[0]);
    264 			}
    265 		}
    266 		else if (isDataTypeMatrix(m_basicType))
    267 		{
    268 			const int		maxInt			= m_precision == glu::PRECISION_LOWP ? 2 : 1024;
    269 			const int		minInt			= -de::min(numValues/2, maxInt);
    270 			vector<float>	values			(numValues*scalarSize);
    271 
    272 			for (int ndx = 0; ndx < (int)values.size(); ndx++)
    273 				values[ndx] = float(minInt + (ndx % (maxInt-minInt+1)));
    274 
    275 			for (int uNdx = 0; uNdx < 2; uNdx++)
    276 			{
    277 				const int location = uNdx == 1 ? refLoc : valLoc;
    278 
    279 				switch (m_basicType)
    280 				{
    281 					case TYPE_FLOAT_MAT2:	gl.uniformMatrix2fv  (location, numValues, DE_FALSE, &values[0]);	break;
    282 					case TYPE_FLOAT_MAT2X3:	gl.uniformMatrix2x3fv(location, numValues, DE_FALSE, &values[0]);	break;
    283 					case TYPE_FLOAT_MAT2X4:	gl.uniformMatrix2x4fv(location, numValues, DE_FALSE, &values[0]);	break;
    284 					case TYPE_FLOAT_MAT3X2:	gl.uniformMatrix3x2fv(location, numValues, DE_FALSE, &values[0]);	break;
    285 					case TYPE_FLOAT_MAT3:	gl.uniformMatrix3fv  (location, numValues, DE_FALSE, &values[0]);	break;
    286 					case TYPE_FLOAT_MAT3X4:	gl.uniformMatrix3x4fv(location, numValues, DE_FALSE, &values[0]);	break;
    287 					case TYPE_FLOAT_MAT4X2:	gl.uniformMatrix4x2fv(location, numValues, DE_FALSE, &values[0]);	break;
    288 					case TYPE_FLOAT_MAT4X3:	gl.uniformMatrix4x3fv(location, numValues, DE_FALSE, &values[0]);	break;
    289 					case TYPE_FLOAT_MAT4:	gl.uniformMatrix4fv  (location, numValues, DE_FALSE, &values[0]);	break;
    290 					default:
    291 						DE_ASSERT(false);
    292 				}
    293 			}
    294 		}
    295 
    296 		gl.uniform1ui(iterCountLoc, product(m_workGroupSize));
    297 		GLU_EXPECT_NO_ERROR(gl.getError(), "Input value setup failed");
    298 	}
    299 
    300 	// Setup output buffer.
    301 	{
    302 		vector<deUint8> emptyData(outBlockInfo.dataSize);
    303 		std::fill(emptyData.begin(), emptyData.end(), 0);
    304 
    305 		gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, *outputBuffer);
    306 		gl.bufferData(GL_SHADER_STORAGE_BUFFER, outBlockInfo.dataSize, &emptyData[0], GL_STATIC_READ);
    307 		gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, *outputBuffer);
    308 		GLU_EXPECT_NO_ERROR(gl.getError(), "Output buffer setup failed");
    309 	}
    310 
    311 	gl.dispatchCompute(1, 1, 1);
    312 
    313 	// Read back and compare
    314 	{
    315 		const deUint32				numValues	= product(m_workGroupSize);
    316 		const InterfaceVariableInfo	outVarInfo	= getProgramInterfaceVariableInfo(gl, program, GL_BUFFER_VARIABLE, outBlockInfo.activeVariables[0]);
    317 		const void*					resPtr		= gl.mapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, outBlockInfo.dataSize, GL_MAP_READ_BIT);
    318 		const int					maxErrMsg	= 10;
    319 		int							numFailed	= 0;
    320 
    321 		GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange()");
    322 		TCU_CHECK(resPtr);
    323 
    324 		for (deUint32 ndx = 0; ndx < numValues; ndx++)
    325 		{
    326 			const int resVal = *((const int*)((const deUint8*)resPtr + outVarInfo.offset + outVarInfo.arrayStride*ndx));
    327 
    328 			if (resVal == 0)
    329 			{
    330 				if (numFailed < maxErrMsg)
    331 					m_testCtx.getLog() << TestLog::Message << "ERROR: isOk[" << ndx << "] = " << resVal << " != true" << TestLog::EndMessage;
    332 				else if (numFailed == maxErrMsg)
    333 					m_testCtx.getLog() << TestLog::Message << "..." << TestLog::EndMessage;
    334 
    335 				numFailed += 1;
    336 			}
    337 		}
    338 
    339 		gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER);
    340 		GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer()");
    341 
    342 		m_testCtx.getLog() << TestLog::Message << (numValues-numFailed) << " / " << numValues << " values passed" << TestLog::EndMessage;
    343 
    344 		m_testCtx.setTestResult(numFailed == 0 ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
    345 								numFailed == 0 ? "Pass"					: "Comparison failed");
    346 	}
    347 
    348 	return STOP;
    349 }
    350 
    351 ShaderSharedVarTests::ShaderSharedVarTests (Context& context)
    352 	: TestCaseGroup(context, "shared_var", "Shared Variable Tests")
    353 {
    354 }
    355 
    356 ShaderSharedVarTests::~ShaderSharedVarTests (void)
    357 {
    358 }
    359 
    360 void ShaderSharedVarTests::init (void)
    361 {
    362 	// .basic_type
    363 	{
    364 		tcu::TestCaseGroup *const basicTypeGroup = new tcu::TestCaseGroup(m_testCtx, "basic_type", "Basic Types");
    365 		addChild(basicTypeGroup);
    366 
    367 		for (int basicType = TYPE_FLOAT; basicType <= TYPE_BOOL_VEC4; basicType++)
    368 		{
    369 			if (glu::isDataTypeBoolOrBVec(DataType(basicType)))
    370 			{
    371 				const tcu::UVec3	workGroupSize	(2,1,3);
    372 				basicTypeGroup->addChild(new SharedBasicVarCase(m_context, getDataTypeName(DataType(basicType)), DataType(basicType), PRECISION_LAST, workGroupSize));
    373 			}
    374 			else
    375 			{
    376 				for (int precision = 0; precision < PRECISION_LAST; precision++)
    377 				{
    378 					const tcu::UVec3	workGroupSize	(2,1,3);
    379 					const string		name			= string(getDataTypeName(DataType(basicType))) + "_" + getPrecisionName(Precision(precision));
    380 
    381 					basicTypeGroup->addChild(new SharedBasicVarCase(m_context, name.c_str(), DataType(basicType), Precision(precision), workGroupSize));
    382 				}
    383 			}
    384 		}
    385 	}
    386 
    387 	// .work_group_size
    388 	{
    389 		tcu::TestCaseGroup *const workGroupSizeGroup = new tcu::TestCaseGroup(m_testCtx, "work_group_size", "Shared Variables with Various Work Group Sizes");
    390 		addChild(workGroupSizeGroup);
    391 
    392 		workGroupSizeGroup->addChild(new SharedBasicVarCase(m_context, "float_1_1_1",		TYPE_FLOAT,			PRECISION_HIGHP,	tcu::UVec3(1,1,1)));
    393 		workGroupSizeGroup->addChild(new SharedBasicVarCase(m_context, "float_64_1_1",		TYPE_FLOAT,			PRECISION_HIGHP,	tcu::UVec3(64,1,1)));
    394 		workGroupSizeGroup->addChild(new SharedBasicVarCase(m_context, "float_1_64_1",		TYPE_FLOAT,			PRECISION_HIGHP,	tcu::UVec3(1,64,1)));
    395 		workGroupSizeGroup->addChild(new SharedBasicVarCase(m_context, "float_1_1_64",		TYPE_FLOAT,			PRECISION_HIGHP,	tcu::UVec3(1,1,64)));
    396 		workGroupSizeGroup->addChild(new SharedBasicVarCase(m_context, "float_128_1_1",		TYPE_FLOAT,			PRECISION_HIGHP,	tcu::UVec3(128,1,1)));
    397 		workGroupSizeGroup->addChild(new SharedBasicVarCase(m_context, "float_1_128_1",		TYPE_FLOAT,			PRECISION_HIGHP,	tcu::UVec3(1,128,1)));
    398 		workGroupSizeGroup->addChild(new SharedBasicVarCase(m_context, "float_13_2_4",		TYPE_FLOAT,			PRECISION_HIGHP,	tcu::UVec3(13,2,4)));
    399 
    400 		workGroupSizeGroup->addChild(new SharedBasicVarCase(m_context, "vec4_1_1_1",		TYPE_FLOAT_VEC4,	PRECISION_HIGHP,	tcu::UVec3(1,1,1)));
    401 		workGroupSizeGroup->addChild(new SharedBasicVarCase(m_context, "vec4_64_1_1",		TYPE_FLOAT_VEC4,	PRECISION_HIGHP,	tcu::UVec3(64,1,1)));
    402 		workGroupSizeGroup->addChild(new SharedBasicVarCase(m_context, "vec4_1_64_1",		TYPE_FLOAT_VEC4,	PRECISION_HIGHP,	tcu::UVec3(1,64,1)));
    403 		workGroupSizeGroup->addChild(new SharedBasicVarCase(m_context, "vec4_1_1_64",		TYPE_FLOAT_VEC4,	PRECISION_HIGHP,	tcu::UVec3(1,1,64)));
    404 		workGroupSizeGroup->addChild(new SharedBasicVarCase(m_context, "vec4_128_1_1",		TYPE_FLOAT_VEC4,	PRECISION_HIGHP,	tcu::UVec3(128,1,1)));
    405 		workGroupSizeGroup->addChild(new SharedBasicVarCase(m_context, "vec4_1_128_1",		TYPE_FLOAT_VEC4,	PRECISION_HIGHP,	tcu::UVec3(1,128,1)));
    406 		workGroupSizeGroup->addChild(new SharedBasicVarCase(m_context, "vec4_13_2_4",		TYPE_FLOAT_VEC4,	PRECISION_HIGHP,	tcu::UVec3(13,2,4)));
    407 
    408 		workGroupSizeGroup->addChild(new SharedBasicVarCase(m_context, "mat4_1_1_1",		TYPE_FLOAT_MAT4,	PRECISION_HIGHP,	tcu::UVec3(1,1,1)));
    409 		workGroupSizeGroup->addChild(new SharedBasicVarCase(m_context, "mat4_64_1_1",		TYPE_FLOAT_MAT4,	PRECISION_HIGHP,	tcu::UVec3(64,1,1)));
    410 		workGroupSizeGroup->addChild(new SharedBasicVarCase(m_context, "mat4_1_64_1",		TYPE_FLOAT_MAT4,	PRECISION_HIGHP,	tcu::UVec3(1,64,1)));
    411 		workGroupSizeGroup->addChild(new SharedBasicVarCase(m_context, "mat4_1_1_64",		TYPE_FLOAT_MAT4,	PRECISION_HIGHP,	tcu::UVec3(1,1,64)));
    412 		workGroupSizeGroup->addChild(new SharedBasicVarCase(m_context, "mat4_128_1_1",		TYPE_FLOAT_MAT4,	PRECISION_HIGHP,	tcu::UVec3(128,1,1)));
    413 		workGroupSizeGroup->addChild(new SharedBasicVarCase(m_context, "mat4_1_128_1",		TYPE_FLOAT_MAT4,	PRECISION_HIGHP,	tcu::UVec3(1,128,1)));
    414 		workGroupSizeGroup->addChild(new SharedBasicVarCase(m_context, "mat4_13_2_4",		TYPE_FLOAT_MAT4,	PRECISION_HIGHP,	tcu::UVec3(13,2,4)));
    415 	}
    416 
    417 	// .atomic
    418 	addChild(new ShaderAtomicOpTests(m_context, "atomic", ATOMIC_OPERAND_SHARED_VARIABLE));
    419 }
    420 
    421 } // Functional
    422 } // gles31
    423 } // deqp
    424