Home | History | Annotate | Download | only in functional
      1 /*-------------------------------------------------------------------------
      2  * drawElements Quality Program OpenGL ES 3.0 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 Indexed State Query tests.
     22  *//*--------------------------------------------------------------------*/
     23 
     24 #include "es3fIndexedStateQueryTests.hpp"
     25 #include "es3fApiCase.hpp"
     26 #include "glsStateQueryUtil.hpp"
     27 #include "tcuRenderTarget.hpp"
     28 #include "glwEnums.hpp"
     29 
     30 using namespace glw; // GLint and other GL types
     31 using deqp::gls::StateQueryUtil::StateQueryMemoryWriteGuard;
     32 
     33 namespace deqp
     34 {
     35 namespace gles3
     36 {
     37 namespace Functional
     38 {
     39 namespace
     40 {
     41 
     42 void checkIntEquals (tcu::TestContext& testCtx, GLint got, GLint expected)
     43 {
     44 	using tcu::TestLog;
     45 
     46 	if (got != expected)
     47 	{
     48 		testCtx.getLog() << TestLog::Message << "// ERROR: Expected " << expected << "; got " << got << TestLog::EndMessage;
     49 		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
     50 			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid value");
     51 	}
     52 }
     53 
     54 void checkIntEquals (tcu::TestContext& testCtx, GLint64 got, GLint64 expected)
     55 {
     56 	using tcu::TestLog;
     57 
     58 	if (got != expected)
     59 	{
     60 		testCtx.getLog() << TestLog::Message << "// ERROR: Expected " << expected << "; got " << got << TestLog::EndMessage;
     61 		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
     62 			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid value");
     63 	}
     64 }
     65 
     66 class TransformFeedbackCase : public ApiCase
     67 {
     68 public:
     69 	TransformFeedbackCase (Context& context, const char* name, const char* description)
     70 		: ApiCase(context, name, description)
     71 	{
     72 	}
     73 
     74 	virtual void testTransformFeedback (void) = DE_NULL;
     75 
     76 	void test (void)
     77 	{
     78 		static const char* transformFeedbackTestVertSource	=	"#version 300 es\n"
     79 																"out highp vec4 anotherOutput;\n"
     80 																"void main (void)\n"
     81 																"{\n"
     82 																"	gl_Position = vec4(0.0);\n"
     83 																"	anotherOutput = vec4(0.0);\n"
     84 																"}\n\0";
     85 		static const char* transformFeedbackTestFragSource	=	"#version 300 es\n"
     86 																"layout(location = 0) out mediump vec4 fragColor;"
     87 																"void main (void)\n"
     88 																"{\n"
     89 																"	fragColor = vec4(0.0);\n"
     90 																"}\n\0";
     91 
     92 		GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
     93 		GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
     94 
     95 		glShaderSource(shaderVert, 1, &transformFeedbackTestVertSource, DE_NULL);
     96 		glShaderSource(shaderFrag, 1, &transformFeedbackTestFragSource, DE_NULL);
     97 
     98 		glCompileShader(shaderVert);
     99 		glCompileShader(shaderFrag);
    100 		expectError(GL_NO_ERROR);
    101 
    102 		GLuint shaderProg = glCreateProgram();
    103 		glAttachShader(shaderProg, shaderVert);
    104 		glAttachShader(shaderProg, shaderFrag);
    105 
    106 		const char* transformFeedbackOutputs[] =
    107 		{
    108 			"gl_Position",
    109 			"anotherOutput"
    110 		};
    111 
    112 		glTransformFeedbackVaryings(shaderProg, 2, transformFeedbackOutputs, GL_INTERLEAVED_ATTRIBS);
    113 		glLinkProgram(shaderProg);
    114 		expectError(GL_NO_ERROR);
    115 
    116 		GLuint transformFeedbackId = 0;
    117 		glGenTransformFeedbacks(1, &transformFeedbackId);
    118 		glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, transformFeedbackId);
    119 		expectError(GL_NO_ERROR);
    120 
    121 		testTransformFeedback();
    122 
    123 		// cleanup
    124 
    125 		glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
    126 
    127 		glDeleteTransformFeedbacks(1, &transformFeedbackId);
    128 		glDeleteShader(shaderVert);
    129 		glDeleteShader(shaderFrag);
    130 		glDeleteProgram(shaderProg);
    131 		expectError(GL_NO_ERROR);
    132 	}
    133 };
    134 
    135 class TransformFeedbackBufferBindingCase : public TransformFeedbackCase
    136 {
    137 public:
    138 	TransformFeedbackBufferBindingCase (Context& context, const char* name, const char* description)
    139 		: TransformFeedbackCase(context, name, description)
    140 	{
    141 	}
    142 
    143 	void testTransformFeedback (void)
    144 	{
    145 		const int feedbackPositionIndex = 0;
    146 		const int feedbackOutputIndex = 1;
    147 		const int feedbackIndex[2] = {feedbackPositionIndex, feedbackOutputIndex};
    148 
    149 		// bind bffers
    150 
    151 		GLuint feedbackBuffers[2];
    152 		glGenBuffers(2, feedbackBuffers);
    153 		expectError(GL_NO_ERROR);
    154 
    155 		for (int ndx = 0; ndx < 2; ++ndx)
    156 		{
    157 			glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, feedbackBuffers[ndx]);
    158 			glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 16, NULL, GL_DYNAMIC_READ);
    159 			glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, feedbackIndex[ndx], feedbackBuffers[ndx]);
    160 			expectError(GL_NO_ERROR);
    161 		}
    162 
    163 		// test TRANSFORM_FEEDBACK_BUFFER_BINDING
    164 
    165 		for (int ndx = 0; ndx < 2; ++ndx)
    166 		{
    167 			StateQueryMemoryWriteGuard<GLint> boundBuffer;
    168 			glGetIntegeri_v(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, feedbackIndex[ndx], &boundBuffer);
    169 			boundBuffer.verifyValidity(m_testCtx);
    170 			checkIntEquals(m_testCtx, boundBuffer, feedbackBuffers[ndx]);
    171 		}
    172 
    173 
    174 		// cleanup
    175 
    176 		glDeleteBuffers(2, feedbackBuffers);
    177 	}
    178 };
    179 
    180 class TransformFeedbackBufferBufferCase : public TransformFeedbackCase
    181 {
    182 public:
    183 	TransformFeedbackBufferBufferCase (Context& context, const char* name, const char* description)
    184 		: TransformFeedbackCase(context, name, description)
    185 	{
    186 	}
    187 
    188 	void testTransformFeedback (void)
    189 	{
    190 		const int feedbackPositionIndex = 0;
    191 		const int feedbackOutputIndex = 1;
    192 
    193 		const int rangeBufferOffset = 4;
    194 		const int rangeBufferSize = 8;
    195 
    196 		// bind buffers
    197 
    198 		GLuint feedbackBuffers[2];
    199 		glGenBuffers(2, feedbackBuffers);
    200 		expectError(GL_NO_ERROR);
    201 
    202 		glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, feedbackBuffers[0]);
    203 		glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 16, NULL, GL_DYNAMIC_READ);
    204 		glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, feedbackPositionIndex, feedbackBuffers[0]);
    205 		expectError(GL_NO_ERROR);
    206 
    207 		glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, feedbackBuffers[1]);
    208 		glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 16, NULL, GL_DYNAMIC_READ);
    209 		glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, feedbackOutputIndex, feedbackBuffers[1], rangeBufferOffset, rangeBufferSize);
    210 		expectError(GL_NO_ERROR);
    211 
    212 		// test TRANSFORM_FEEDBACK_BUFFER_START and TRANSFORM_FEEDBACK_BUFFER_SIZE
    213 
    214 		const struct BufferRequirements
    215 		{
    216 			GLint	index;
    217 			GLenum	pname;
    218 			GLint64 value;
    219 		} requirements[] =
    220 		{
    221 			{ feedbackPositionIndex,	GL_TRANSFORM_FEEDBACK_BUFFER_START, 0					},
    222 			{ feedbackPositionIndex,	GL_TRANSFORM_FEEDBACK_BUFFER_SIZE,	0					},
    223 			{ feedbackOutputIndex,		GL_TRANSFORM_FEEDBACK_BUFFER_START, rangeBufferOffset	},
    224 			{ feedbackOutputIndex,		GL_TRANSFORM_FEEDBACK_BUFFER_SIZE,	rangeBufferSize		}
    225 		};
    226 
    227 		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(requirements); ++ndx)
    228 		{
    229 			StateQueryMemoryWriteGuard<GLint64> state;
    230 			glGetInteger64i_v(requirements[ndx].pname, requirements[ndx].index, &state);
    231 
    232 			if (state.verifyValidity(m_testCtx))
    233 				checkIntEquals(m_testCtx, state, requirements[ndx].value);
    234 		}
    235 
    236 		// cleanup
    237 
    238 		glDeleteBuffers(2, feedbackBuffers);
    239 	}
    240 };
    241 
    242 class UniformBufferCase : public ApiCase
    243 {
    244 public:
    245 	UniformBufferCase (Context& context, const char* name, const char* description)
    246 		: ApiCase	(context, name, description)
    247 		, m_program	(0)
    248 	{
    249 	}
    250 
    251 	virtual void testUniformBuffers (void) = DE_NULL;
    252 
    253 	void test (void)
    254 	{
    255 		static const char* testVertSource	=	"#version 300 es\n"
    256 												"uniform highp vec4 input1;\n"
    257 												"uniform highp vec4 input2;\n"
    258 												"void main (void)\n"
    259 												"{\n"
    260 												"	gl_Position = input1 + input2;\n"
    261 												"}\n\0";
    262 		static const char* testFragSource	=	"#version 300 es\n"
    263 												"layout(location = 0) out mediump vec4 fragColor;"
    264 												"void main (void)\n"
    265 												"{\n"
    266 												"	fragColor = vec4(0.0);\n"
    267 												"}\n\0";
    268 
    269 		GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
    270 		GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
    271 
    272 		glShaderSource(shaderVert, 1, &testVertSource, DE_NULL);
    273 		glShaderSource(shaderFrag, 1, &testFragSource, DE_NULL);
    274 
    275 		glCompileShader(shaderVert);
    276 		glCompileShader(shaderFrag);
    277 		expectError(GL_NO_ERROR);
    278 
    279 		m_program = glCreateProgram();
    280 		glAttachShader(m_program, shaderVert);
    281 		glAttachShader(m_program, shaderFrag);
    282 		glLinkProgram(m_program);
    283 		glUseProgram(m_program);
    284 		expectError(GL_NO_ERROR);
    285 
    286 		testUniformBuffers();
    287 
    288 		glUseProgram(0);
    289 		glDeleteShader(shaderVert);
    290 		glDeleteShader(shaderFrag);
    291 		glDeleteProgram(m_program);
    292 		expectError(GL_NO_ERROR);
    293 	}
    294 
    295 protected:
    296 	GLuint	m_program;
    297 };
    298 
    299 class UniformBufferBindingCase : public UniformBufferCase
    300 {
    301 public:
    302 	UniformBufferBindingCase (Context& context, const char* name, const char* description)
    303 		: UniformBufferCase(context, name, description)
    304 	{
    305 	}
    306 
    307 	void testUniformBuffers (void)
    308 	{
    309 		const char* uniformNames[] =
    310 		{
    311 			"input1",
    312 			"input2"
    313 		};
    314 		GLuint uniformIndices[2] = {0};
    315 		glGetUniformIndices(m_program, 2, uniformNames, uniformIndices);
    316 
    317 		GLuint buffers[2];
    318 		glGenBuffers(2, buffers);
    319 
    320 		for (int ndx = 0; ndx < 2; ++ndx)
    321 		{
    322 			glBindBuffer(GL_UNIFORM_BUFFER, buffers[ndx]);
    323 			glBufferData(GL_UNIFORM_BUFFER, 32, DE_NULL, GL_DYNAMIC_DRAW);
    324 			glBindBufferBase(GL_UNIFORM_BUFFER, uniformIndices[ndx], buffers[ndx]);
    325 			expectError(GL_NO_ERROR);
    326 		}
    327 
    328 		for (int ndx = 0; ndx < 2; ++ndx)
    329 		{
    330 			StateQueryMemoryWriteGuard<GLint> boundBuffer;
    331 			glGetIntegeri_v(GL_UNIFORM_BUFFER_BINDING, uniformIndices[ndx], &boundBuffer);
    332 
    333 			if (boundBuffer.verifyValidity(m_testCtx))
    334 				checkIntEquals(m_testCtx, boundBuffer, buffers[ndx]);
    335 			expectError(GL_NO_ERROR);
    336 		}
    337 
    338 		glDeleteBuffers(2, buffers);
    339 	}
    340 };
    341 
    342 class UniformBufferBufferCase : public UniformBufferCase
    343 {
    344 public:
    345 	UniformBufferBufferCase (Context& context, const char* name, const char* description)
    346 		: UniformBufferCase(context, name, description)
    347 	{
    348 	}
    349 
    350 	void testUniformBuffers (void)
    351 	{
    352 		const char* uniformNames[] =
    353 		{
    354 			"input1",
    355 			"input2"
    356 		};
    357 		GLuint uniformIndices[2] = {0};
    358 		glGetUniformIndices(m_program, 2, uniformNames, uniformIndices);
    359 
    360 		const GLint alignment = GetAlignment();
    361 		if (alignment == -1) // cannot continue without this
    362 			return;
    363 
    364 		m_testCtx.getLog() << tcu::TestLog::Message << "Alignment is " << alignment << tcu::TestLog::EndMessage;
    365 
    366 		int rangeBufferOffset		= alignment;
    367 		int rangeBufferSize			= alignment * 2;
    368 		int rangeBufferTotalSize	= rangeBufferOffset + rangeBufferSize + 8; // + 8 has no special meaning, just to make it != with the size of the range
    369 
    370 		GLuint buffers[2];
    371 		glGenBuffers(2, buffers);
    372 
    373 		glBindBuffer(GL_UNIFORM_BUFFER, buffers[0]);
    374 		glBufferData(GL_UNIFORM_BUFFER, 32, DE_NULL, GL_DYNAMIC_DRAW);
    375 		glBindBufferBase(GL_UNIFORM_BUFFER, uniformIndices[0], buffers[0]);
    376 		expectError(GL_NO_ERROR);
    377 
    378 		glBindBuffer(GL_UNIFORM_BUFFER, buffers[1]);
    379 		glBufferData(GL_UNIFORM_BUFFER, rangeBufferTotalSize, DE_NULL, GL_DYNAMIC_DRAW);
    380 		glBindBufferRange(GL_UNIFORM_BUFFER, uniformIndices[1], buffers[1], rangeBufferOffset, rangeBufferSize);
    381 		expectError(GL_NO_ERROR);
    382 
    383 		// test UNIFORM_BUFFER_START and UNIFORM_BUFFER_SIZE
    384 
    385 		const struct BufferRequirements
    386 		{
    387 			GLuint	index;
    388 			GLenum	pname;
    389 			GLint64 value;
    390 		} requirements[] =
    391 		{
    392 			{ uniformIndices[0], GL_UNIFORM_BUFFER_START,	0					},
    393 			{ uniformIndices[0], GL_UNIFORM_BUFFER_SIZE,	0					},
    394 			{ uniformIndices[1], GL_UNIFORM_BUFFER_START,	rangeBufferOffset	},
    395 			{ uniformIndices[1], GL_UNIFORM_BUFFER_SIZE,	rangeBufferSize		}
    396 		};
    397 
    398 		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(requirements); ++ndx)
    399 		{
    400 			StateQueryMemoryWriteGuard<GLint64> state;
    401 			glGetInteger64i_v(requirements[ndx].pname, requirements[ndx].index, &state);
    402 
    403 			if (state.verifyValidity(m_testCtx))
    404 				checkIntEquals(m_testCtx, state, requirements[ndx].value);
    405 			expectError(GL_NO_ERROR);
    406 		}
    407 
    408 		glDeleteBuffers(2, buffers);
    409 	}
    410 
    411 	int GetAlignment()
    412 	{
    413 		StateQueryMemoryWriteGuard<GLint> state;
    414 		glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &state);
    415 
    416 		if (!state.verifyValidity(m_testCtx))
    417 			return -1;
    418 
    419 		if (state <= 256)
    420 			return state;
    421 
    422 		m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: UNIFORM_BUFFER_OFFSET_ALIGNMENT has a maximum value of 256." << tcu::TestLog::EndMessage;
    423 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "invalid UNIFORM_BUFFER_OFFSET_ALIGNMENT value");
    424 
    425 		return -1;
    426 	}
    427 };
    428 
    429 } // anonymous
    430 
    431 IndexedStateQueryTests::IndexedStateQueryTests (Context& context)
    432 	: TestCaseGroup(context, "indexed", "Indexed Integer Values")
    433 {
    434 }
    435 
    436 void IndexedStateQueryTests::init (void)
    437 {
    438 	// transform feedback
    439 	addChild(new TransformFeedbackBufferBindingCase(m_context, "transform_feedback_buffer_binding", "TRANSFORM_FEEDBACK_BUFFER_BINDING"));
    440 	addChild(new TransformFeedbackBufferBufferCase(m_context, "transform_feedback_buffer_start_size", "TRANSFORM_FEEDBACK_BUFFER_START and TRANSFORM_FEEDBACK_BUFFER_SIZE"));
    441 
    442 	// uniform buffers
    443 	addChild(new UniformBufferBindingCase(m_context, "uniform_buffer_binding", "UNIFORM_BUFFER_BINDING"));
    444 	addChild(new UniformBufferBufferCase(m_context, "uniform_buffer_start_size", "UNIFORM_BUFFER_START and UNIFORM_BUFFER_SIZE"));
    445 }
    446 
    447 } // Functional
    448 } // gles3
    449 } // deqp
    450