1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 3.0 Module
3 * -------------------------------------------------
5 * Copyright 2014 The Android Open Source Project
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 * \brief Indexed State Query tests.
22 *//*--------------------------------------------------------------------*/
24 #include "es3fIndexedStateQueryTests.hpp"
25 #include "es3fApiCase.hpp"
26 #include "glsStateQueryUtil.hpp"
27 #include "tcuRenderTarget.hpp"
28 #include "glwEnums.hpp"
30 using namespace glw; // GLint and other GL types
31 using deqp::gls::StateQueryUtil::StateQueryMemoryWriteGuard;
42 void checkIntEquals (tcu::TestContext& testCtx, GLint got, GLint expected)
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");
54 void checkIntEquals (tcu::TestContext& testCtx, GLint64 got, GLint64 expected)
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");
66 class TransformFeedbackCase : public ApiCase
69 TransformFeedbackCase (Context& context, const char* name, const char* description)
70 : ApiCase(context, name, description)
74 virtual void testTransformFeedback (void) = DE_NULL;
78 static const char* transformFeedbackTestVertSource = "#version 300 es\n"
79 "out highp vec4 anotherOutput;\n"
82 " gl_Position = vec4(0.0);\n"
83 " anotherOutput = vec4(0.0);\n"
85 static const char* transformFeedbackTestFragSource = "#version 300 es\n"
86 "layout(location = 0) out mediump vec4 fragColor;"
89 " fragColor = vec4(0.0);\n"
92 GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
93 GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
95 glShaderSource(shaderVert, 1, &transformFeedbackTestVertSource, DE_NULL);
96 glShaderSource(shaderFrag, 1, &transformFeedbackTestFragSource, DE_NULL);
98 glCompileShader(shaderVert);
99 glCompileShader(shaderFrag);
100 expectError(GL_NO_ERROR);
102 GLuint shaderProg = glCreateProgram();
103 glAttachShader(shaderProg, shaderVert);
104 glAttachShader(shaderProg, shaderFrag);
106 const char* transformFeedbackOutputs[] =
112 glTransformFeedbackVaryings(shaderProg, 2, transformFeedbackOutputs, GL_INTERLEAVED_ATTRIBS);
113 glLinkProgram(shaderProg);
114 expectError(GL_NO_ERROR);
116 GLuint transformFeedbackId = 0;
117 glGenTransformFeedbacks(1, &transformFeedbackId);
118 glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, transformFeedbackId);
119 expectError(GL_NO_ERROR);
121 testTransformFeedback();
125 glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
127 glDeleteTransformFeedbacks(1, &transformFeedbackId);
128 glDeleteShader(shaderVert);
129 glDeleteShader(shaderFrag);
130 glDeleteProgram(shaderProg);
131 expectError(GL_NO_ERROR);
135 class TransformFeedbackBufferBindingCase : public TransformFeedbackCase
138 TransformFeedbackBufferBindingCase (Context& context, const char* name, const char* description)
139 : TransformFeedbackCase(context, name, description)
143 void testTransformFeedback (void)
145 const int feedbackPositionIndex = 0;
146 const int feedbackOutputIndex = 1;
147 const int feedbackIndex[2] = {feedbackPositionIndex, feedbackOutputIndex};
151 GLuint feedbackBuffers[2];
152 glGenBuffers(2, feedbackBuffers);
153 expectError(GL_NO_ERROR);
155 for (int ndx = 0; ndx < 2; ++ndx)
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);
163 // test TRANSFORM_FEEDBACK_BUFFER_BINDING
165 for (int ndx = 0; ndx < 2; ++ndx)
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]);
176 glDeleteBuffers(2, feedbackBuffers);
180 class TransformFeedbackBufferBufferCase : public TransformFeedbackCase
183 TransformFeedbackBufferBufferCase (Context& context, const char* name, const char* description)
184 : TransformFeedbackCase(context, name, description)
188 void testTransformFeedback (void)
190 const int feedbackPositionIndex = 0;
191 const int feedbackOutputIndex = 1;
193 const int rangeBufferOffset = 4;
194 const int rangeBufferSize = 8;
198 GLuint feedbackBuffers[2];
199 glGenBuffers(2, feedbackBuffers);
200 expectError(GL_NO_ERROR);
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);
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);
212 // test TRANSFORM_FEEDBACK_BUFFER_START and TRANSFORM_FEEDBACK_BUFFER_SIZE
214 const struct BufferRequirements
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 }
227 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(requirements); ++ndx)
229 StateQueryMemoryWriteGuard<GLint64> state;
230 glGetInteger64i_v(requirements[ndx].pname, requirements[ndx].index, &state);
232 if (state.verifyValidity(m_testCtx))
233 checkIntEquals(m_testCtx, state, requirements[ndx].value);
238 glDeleteBuffers(2, feedbackBuffers);
242 class UniformBufferCase : public ApiCase
245 UniformBufferCase (Context& context, const char* name, const char* description)
246 : ApiCase (context, name, description)
251 virtual void testUniformBuffers (void) = DE_NULL;
255 static const char* testVertSource = "#version 300 es\n"
256 "uniform highp vec4 input1;\n"
257 "uniform highp vec4 input2;\n"
260 " gl_Position = input1 + input2;\n"
262 static const char* testFragSource = "#version 300 es\n"
263 "layout(location = 0) out mediump vec4 fragColor;"
266 " fragColor = vec4(0.0);\n"
269 GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
270 GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
272 glShaderSource(shaderVert, 1, &testVertSource, DE_NULL);
273 glShaderSource(shaderFrag, 1, &testFragSource, DE_NULL);
275 glCompileShader(shaderVert);
276 glCompileShader(shaderFrag);
277 expectError(GL_NO_ERROR);
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);
286 testUniformBuffers();
289 glDeleteShader(shaderVert);
290 glDeleteShader(shaderFrag);
291 glDeleteProgram(m_program);
292 expectError(GL_NO_ERROR);
299 class UniformBufferBindingCase : public UniformBufferCase
302 UniformBufferBindingCase (Context& context, const char* name, const char* description)
303 : UniformBufferCase(context, name, description)
307 void testUniformBuffers (void)
309 const char* uniformNames[] =
314 GLuint uniformIndices[2] = {0};
315 glGetUniformIndices(m_program, 2, uniformNames, uniformIndices);
318 glGenBuffers(2, buffers);
320 for (int ndx = 0; ndx < 2; ++ndx)
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);
328 for (int ndx = 0; ndx < 2; ++ndx)
330 StateQueryMemoryWriteGuard<GLint> boundBuffer;
331 glGetIntegeri_v(GL_UNIFORM_BUFFER_BINDING, uniformIndices[ndx], &boundBuffer);
333 if (boundBuffer.verifyValidity(m_testCtx))
334 checkIntEquals(m_testCtx, boundBuffer, buffers[ndx]);
335 expectError(GL_NO_ERROR);
338 glDeleteBuffers(2, buffers);
342 class UniformBufferBufferCase : public UniformBufferCase
345 UniformBufferBufferCase (Context& context, const char* name, const char* description)
346 : UniformBufferCase(context, name, description)
350 void testUniformBuffers (void)
352 const char* uniformNames[] =
357 GLuint uniformIndices[2] = {0};
358 glGetUniformIndices(m_program, 2, uniformNames, uniformIndices);
360 const GLint alignment = GetAlignment();
361 if (alignment == -1) // cannot continue without this
364 m_testCtx.getLog() << tcu::TestLog::Message << "Alignment is " << alignment << tcu::TestLog::EndMessage;
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
371 glGenBuffers(2, buffers);
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);
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);
383 // test UNIFORM_BUFFER_START and UNIFORM_BUFFER_SIZE
385 const struct BufferRequirements
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 }
398 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(requirements); ++ndx)
400 StateQueryMemoryWriteGuard<GLint64> state;
401 glGetInteger64i_v(requirements[ndx].pname, requirements[ndx].index, &state);
403 if (state.verifyValidity(m_testCtx))
404 checkIntEquals(m_testCtx, state, requirements[ndx].value);
405 expectError(GL_NO_ERROR);
408 glDeleteBuffers(2, buffers);
413 StateQueryMemoryWriteGuard<GLint> state;
414 glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &state);
416 if (!state.verifyValidity(m_testCtx))
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");
431 IndexedStateQueryTests::IndexedStateQueryTests (Context& context)
432 : TestCaseGroup(context, "indexed", "Indexed Integer Values")
436 void IndexedStateQueryTests::init (void)
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"));
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"));