1 /*------------------------------------------------------------------------- 2 * OpenGL Conformance Test Suite 3 * ----------------------------- 4 * 5 * Copyright (c) 2014-2016 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 21 * \brief 22 */ /*-------------------------------------------------------------------*/ 23 24 /*! 25 * \file esextcGPUShader5UniformBlocksArrayIndexing.cpp 26 * \brief GPUShader5 Uniform Blocks Array Indexing Test (Test Group 4) 27 */ /*-------------------------------------------------------------------*/ 28 29 #include "esextcGPUShader5UniformBlocksArrayIndexing.hpp" 30 #include "gluContextInfo.hpp" 31 #include "gluDefs.hpp" 32 #include "glwEnums.hpp" 33 #include "glwFunctions.hpp" 34 #include "tcuTestLog.hpp" 35 #include <cstring> 36 37 namespace glcts 38 { 39 40 const glw::GLuint GPUShader5UniformBlocksArrayIndexing::m_n_array_size = 4; 41 const glw::GLuint GPUShader5UniformBlocksArrayIndexing::m_n_position_components = 4; 42 43 /* Data to fill in the buffer object associated with positionBlocks uniform array */ 44 const glw::GLfloat GPUShader5UniformBlocksArrayIndexing::m_position_data[] = { -1.0, -1.0, 0.0, 1.0, -1.0, 1.0, 45 0.0, 1.0, 1.0, -1.0, 0.0, 1.0, 46 1.0, 1.0, 0.0, 1.0 }; 47 48 /* Fragment Shader code */ 49 const char* GPUShader5UniformBlocksArrayIndexing::m_fragment_shader_code = "${VERSION}\n" 50 "\n" 51 "${GPU_SHADER5_REQUIRE}\n" 52 "\n" 53 "precision highp float;\n" 54 "\n" 55 "out vec4 color;\n" 56 "\n" 57 "void main()\n" 58 "{\n" 59 " color = vec4(1, 1, 1, 1);\n" 60 "}\n"; 61 62 /* Vertex Shader code */ 63 const char* GPUShader5UniformBlocksArrayIndexing::m_vertex_shader_code = 64 "${VERSION}\n" 65 "\n" 66 "${GPU_SHADER5_REQUIRE}\n" 67 "\n" 68 "precision highp float;\n" 69 "\n" 70 "uniform PositionBlock\n" 71 "{\n" 72 " vec4 position;\n" 73 "} positionBlocks[4];\n" 74 "\n" 75 "uniform uint index;\n" 76 "\n" 77 "void main()\n" 78 "{\n" 79 " gl_Position = positionBlocks[index].position;\n" 80 "}\n"; 81 82 /** Constructor 83 * 84 * @param context Test context 85 * @param name Test case's name 86 * @param description Test case's description 87 **/ 88 GPUShader5UniformBlocksArrayIndexing::GPUShader5UniformBlocksArrayIndexing(Context& context, 89 const ExtParameters& extParams, 90 const char* name, const char* description) 91 : TestCaseBase(context, extParams, name, description) 92 , m_fragment_shader_id(0) 93 , m_program_id(0) 94 , m_tf_buffer_id(0) 95 , m_uniform_buffer_ids(DE_NULL) 96 , m_vertex_shader_id(0) 97 , m_vao_id(0) 98 { 99 /* Nothing to be done here */ 100 } 101 102 /** Initializes GLES objects used during the test. 103 * 104 **/ 105 void GPUShader5UniformBlocksArrayIndexing::initTest(void) 106 { 107 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 108 109 /* Check if gpu_shader5 extension is supported */ 110 if (!m_is_gpu_shader5_supported) 111 { 112 throw tcu::NotSupportedError(GPU_SHADER5_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__); 113 } 114 115 /* Feedback varyings */ 116 const char* feedbackVaryings[] = { "gl_Position" }; 117 const unsigned int nVaryings = sizeof(feedbackVaryings) / sizeof(char*); 118 119 /* Generate and bind VAO */ 120 gl.genVertexArrays(1, &m_vao_id); 121 gl.bindVertexArray(m_vao_id); 122 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create vertex array object"); 123 124 /* Create program object */ 125 m_program_id = gl.createProgram(); 126 GLU_EXPECT_NO_ERROR(gl.getError(), "Creating program object failed!"); 127 128 gl.transformFeedbackVaryings(m_program_id, nVaryings, feedbackVaryings, GL_INTERLEAVED_ATTRIBS); 129 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set transform feedback varyings!"); 130 131 /* Create shader objects */ 132 m_vertex_shader_id = gl.createShader(GL_VERTEX_SHADER); 133 m_fragment_shader_id = gl.createShader(GL_FRAGMENT_SHADER); 134 GLU_EXPECT_NO_ERROR(gl.getError(), "Creating shader objects failed!"); 135 136 /* Build program */ 137 if (!buildProgram(m_program_id, m_fragment_shader_id, 1, &m_fragment_shader_code, m_vertex_shader_id, 1, 138 &m_vertex_shader_code)) 139 { 140 TCU_FAIL("Program could not have been created sucessfully from a valid vertex/fragment shader!"); 141 } 142 143 /* Create a buffer object */ 144 gl.genBuffers(1, &m_tf_buffer_id); 145 gl.bindBuffer(GL_ARRAY_BUFFER, m_tf_buffer_id); 146 gl.bufferData(GL_ARRAY_BUFFER, m_n_position_components * sizeof(glw::GLfloat) * nVaryings, DE_NULL, 147 GL_DYNAMIC_COPY); 148 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create and initialize a buffer object to be used for XFB!"); 149 150 /* Bind buffer object to transform feedback binding point */ 151 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, /* index */ 152 m_tf_buffer_id); 153 154 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not bind buffer object to transform feedback binding point!"); 155 } 156 157 /** Executes the test. 158 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise. 159 * 160 * Note the function throws exception should an error occur! 161 * 162 * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again. 163 * 164 **/ 165 tcu::TestNode::IterateResult GPUShader5UniformBlocksArrayIndexing::iterate(void) 166 { 167 initTest(); 168 169 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 170 171 /* Use the test program object */ 172 gl.useProgram(m_program_id); 173 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not use program object!"); 174 175 /* Set up uniform buffer bindings */ 176 m_uniform_buffer_ids = new glw::GLuint[m_n_array_size]; 177 memset(m_uniform_buffer_ids, 0, m_n_array_size * sizeof(glw::GLuint)); 178 179 gl.genBuffers(m_n_array_size, m_uniform_buffer_ids); 180 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() failed"); 181 182 for (glw::GLuint index_value = 0; index_value < m_n_array_size; ++index_value) 183 { 184 glw::GLuint blockIndex = 0; 185 std::stringstream positionBlock; 186 187 positionBlock << "PositionBlock[" << index_value << "]"; 188 189 blockIndex = gl.getUniformBlockIndex(m_program_id, positionBlock.str().c_str()); 190 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not get uniform block index"); 191 192 gl.uniformBlockBinding(m_program_id, blockIndex, index_value); 193 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not assign uniform block binding"); 194 195 gl.bindBuffer(GL_UNIFORM_BUFFER, m_uniform_buffer_ids[index_value]); 196 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not bind buffer object"); 197 198 gl.bufferData(GL_UNIFORM_BUFFER, m_n_position_components * sizeof(float), 199 m_position_data + m_n_position_components * index_value, GL_STATIC_READ); 200 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set buffer object data"); 201 202 gl.bindBufferBase(GL_UNIFORM_BUFFER, index_value, m_uniform_buffer_ids[index_value]); 203 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not bind buffer object to uniform block binding point"); 204 } 205 206 /* Retrieve 'index' uniform location. */ 207 glw::GLint index_uniform_location = gl.getUniformLocation(m_program_id, "index"); 208 209 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation() call failed."); 210 211 if (index_uniform_location == -1) 212 { 213 TCU_FAIL("Could not get index uniform location!"); 214 } 215 216 /* Run the test */ 217 bool testFailed = false; 218 219 for (glw::GLuint index_value = 0; index_value < m_n_array_size; ++index_value) 220 { 221 if (!drawAndCheckResult(index_uniform_location, index_value)) 222 { 223 testFailed = true; 224 225 break; 226 } 227 } 228 229 if (testFailed) 230 { 231 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 232 } 233 else 234 { 235 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 236 } 237 238 return STOP; 239 } 240 241 /** Draws and checks result data fetched via transform feedback 242 * 243 * @param index_value value to be set for the index uniform variable. 244 * 245 * @return true if the result data is correct, false otherwise 246 */ 247 bool GPUShader5UniformBlocksArrayIndexing::drawAndCheckResult(glw::GLuint index_location, glw::GLuint index_value) 248 { 249 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 250 bool result = true; 251 252 gl.uniform1ui(index_location, index_value); 253 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1ui() call failed"); 254 255 gl.enable(GL_RASTERIZER_DISCARD); 256 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable(GL_RASTERIZER_DISCARD) call failed"); 257 258 gl.beginTransformFeedback(GL_POINTS); 259 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback(GL_POINTS) call failed"); 260 261 gl.drawArrays(GL_POINTS, 0, /* first */ 262 1); /* count */ 263 GLU_EXPECT_NO_ERROR(gl.getError(), "Rendering failed!"); 264 265 gl.endTransformFeedback(); 266 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed"); 267 268 gl.disable(GL_RASTERIZER_DISCARD); 269 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable(GL_RASTERIZER_DISCARD) call failed"); 270 271 /* Fetch the results via transform feedback */ 272 const glw::GLfloat* feedback_result = 273 (glw::GLfloat*)gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, /* offset */ 274 sizeof(float) * m_n_position_components, GL_MAP_READ_BIT); 275 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not map buffer to process space"); 276 277 if (de::abs(feedback_result[0] - m_position_data[index_value * m_n_position_components + 0]) > m_epsilon_float || 278 de::abs(feedback_result[1] - m_position_data[index_value * m_n_position_components + 1]) > m_epsilon_float || 279 de::abs(feedback_result[2] - m_position_data[index_value * m_n_position_components + 2]) > m_epsilon_float || 280 de::abs(feedback_result[3] - m_position_data[index_value * m_n_position_components + 3]) > m_epsilon_float) 281 { 282 m_testCtx.getLog() << tcu::TestLog::Message << "Expected Data (" 283 << m_position_data[index_value * m_n_position_components + 0] << ", " 284 << m_position_data[index_value * m_n_position_components + 1] << ", " 285 << m_position_data[index_value * m_n_position_components + 2] << ", " 286 << m_position_data[index_value * m_n_position_components + 3] << ") Result Data (" 287 << feedback_result[0] << ", " << feedback_result[1] << ", " << feedback_result[2] << ", " 288 << feedback_result[3] << ")" << tcu::TestLog::EndMessage; 289 result = false; 290 } 291 292 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); 293 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed"); 294 295 return result; 296 } 297 298 /** Deinitializes GLES objects created during the test. 299 * 300 */ 301 void GPUShader5UniformBlocksArrayIndexing::deinit(void) 302 { 303 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 304 305 /* Reset OpenGL ES state */ 306 gl.useProgram(0); 307 gl.bindBuffer(GL_ARRAY_BUFFER, 0); 308 gl.bindBuffer(GL_UNIFORM_BUFFER, 0); 309 gl.bindVertexArray(0); 310 311 /* Delete program object and shaders */ 312 if (m_program_id != 0) 313 { 314 gl.deleteProgram(m_program_id); 315 316 m_program_id = 0; 317 } 318 319 if (m_vertex_shader_id != 0) 320 { 321 gl.deleteShader(m_vertex_shader_id); 322 323 m_vertex_shader_id = 0; 324 } 325 326 if (m_fragment_shader_id != 0) 327 { 328 gl.deleteShader(m_fragment_shader_id); 329 330 m_fragment_shader_id = 0; 331 } 332 333 if (m_tf_buffer_id != 0) 334 { 335 gl.deleteBuffers(1, &m_tf_buffer_id); 336 337 m_tf_buffer_id = 0; 338 } 339 340 if (m_uniform_buffer_ids != DE_NULL) 341 { 342 gl.deleteBuffers(m_n_array_size, m_uniform_buffer_ids); 343 344 delete[] m_uniform_buffer_ids; 345 m_uniform_buffer_ids = DE_NULL; 346 } 347 348 if (m_vao_id != 0) 349 { 350 gl.deleteVertexArrays(1, &m_vao_id); 351 352 m_vao_id = 0; 353 } 354 355 /* Call base class' deinit() */ 356 TestCaseBase::deinit(); 357 } 358 359 } // namespace glcts 360