1 #ifndef _ESEXTCTEXTUREBUFFEROPERATIONS_HPP 2 #define _ESEXTCTEXTUREBUFFEROPERATIONS_HPP 3 /*------------------------------------------------------------------------- 4 * OpenGL Conformance Test Suite 5 * ----------------------------- 6 * 7 * Copyright (c) 2014-2016 The Khronos Group Inc. 8 * 9 * Licensed under the Apache License, Version 2.0 (the "License"); 10 * you may not use this file except in compliance with the License. 11 * You may obtain a copy of the License at 12 * 13 * http://www.apache.org/licenses/LICENSE-2.0 14 * 15 * Unless required by applicable law or agreed to in writing, software 16 * distributed under the License is distributed on an "AS IS" BASIS, 17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 * See the License for the specific language governing permissions and 19 * limitations under the License. 20 * 21 */ /*! 22 * \file 23 * \brief 24 */ /*-------------------------------------------------------------------*/ 25 26 /*! 27 * \file esextcTextureBufferOperations.hpp 28 * \brief Texture Buffer Operations (Test 1) 29 */ /*-------------------------------------------------------------------*/ 30 31 #include "../esextcTestCaseBase.hpp" 32 33 namespace glcts 34 { 35 36 /** Implementation of (Test 1) from CTS_EXT_texture_buffer. Description follows 37 * 38 * Check whether texture data for the texture buffer can be specified in a number 39 * of different ways: 40 * 41 * 1. via buffer object loads 42 * 2. via direct CPU writes 43 * 3. via framebuffer readbacks to pixel buffer objects 44 * 4. via transform feedback 45 * 5. via image store 46 * 6. via ssbo writes 47 * 48 * Category: API, Functional Test. 49 * 50 * The test should create a texture object and bind it to GL_TEXTURE_BUFFER_EXT 51 * texture target at texture unit 0. It should also create buffer object 52 * and bind it to TEXTURE_BUFFER_EXT target. Call glBufferData with NULL data 53 * pointer to allocate storage for the buffer object. The size of the storage 54 * should be equal to value(GL_MAX_COMPUTE_WORK_GROUP_SIZE, X axis) * 55 * sizeof(GLint) * 4. 56 * 57 * The buffer object should be used as texture buffer's data store by calling 58 * 59 * TexBufferExt(TEXTURE_BUFFER_EXT, GL_RGBA32I, buffer_id ); 60 * 61 * The data for the buffer object should be specified in the following ways: 62 * 63 * --------------------------------------------------------------------------- 64 * 65 * 1. Use glBufferSubData to fill buffer object's data store. 66 * glBufferSubData should be given a pointer to data that will be copied into 67 * the data store for initialization. 68 * 69 * --------------------------------------------------------------------------- 70 * 71 * 2. Map the buffer object's data store to client's address space by using 72 * glMapBufferRange function (map the whole data store). The data store should 73 * then be filled with values up to the size of the data store. 74 * The data store should be unmapped using glUnmapBuffer function. 75 * 76 * --------------------------------------------------------------------------- 77 * 78 * 3. Create a framebuffer object and bind it to GL_DRAW_FRAMEBUFFER target. 79 * Create a 2d texture object with size 80 * value(GL_MAX_COMPUTE_WORK_GROUP_SIZE, X axis) x 1 and RGBA32I internal 81 * format. Attach the texture object to framebuffer's GL_COLOR_ATTACHMENT0 82 * attachment. Render to texture filling it completely with some predefined 83 * integer values. 84 * 85 * Bind the framebuffer object to GL_READ_FRAMEBUFFER target. 86 * 87 * Bind the buffer object to GL_PIXEL_PACK_BUFFER target. 88 * 89 * Set the alignment requirements by calling glPixelStorei(GL_UNPACK_ALIGNMENT,1) 90 * and glPixelStorei(GL_PACK_ALIGNMENT,1). 91 * 92 * Call glReadPixels(0, 0, value(GL_MAX_COMPUTE_WORK_GROUP_SIZE, X axis), 93 * 1, GL_RGBA, GL_INT, 0). 94 * 95 * Bind the buffer object once again to TEXTURE_BUFFER_EXT target. 96 * 97 * --------------------------------------------------------------------------- 98 * 99 * 4. Write a vertex shader that declares in ivec4 inPosition and 100 * out ivec4 outPosition variables and a matching fragment shader. The vertex 101 * shader should assign the value of inPosition to outPosition. The buffer object 102 * being a data source for the inPosition attribute should be filled with some 103 * integer values. Configure transform feedback to capture value of outPosition. 104 * Bind our texture buffer's buffer object as destination buffer for transform 105 * feedback operations. 106 * 107 * Execute a draw call. 108 * 109 * --------------------------------------------------------------------------- 110 * 111 * 5. Write a compute shader that defines 112 * 113 * layout(rgba32i, binding = 0) uniform highp iimageBuffer image_buffer; 114 * 115 * The work group size should be equal to 116 * value(GL_MAX_COMPUTE_WORK_GROUP_SIZE, X axis) x 1 x 1. 117 * 118 * Bind the texture buffer to image unit 0. 119 * 120 * In the compute shader execute: 121 * 122 * imageStore(image_buffer, gl_LocalInvocationID.x, ivec4(gl_LocalInvocationID.x) ); 123 * 124 * Call: 125 * 126 * glDispatchCompute(1, 1, 1); 127 * glMemoryBarrier(TEXTURE_FETCH_BARRIER_BIT); 128 * 129 * --------------------------------------------------------------------------- 130 * 131 * 6. Write a compute shader that defines 132 * 133 * buffer ComputeSSBO 134 * { 135 * ivec4 value[]; 136 * 137 * } computeSSBO; 138 * 139 * Work group size should be equal to 140 * value(GL_MAX_COMPUTE_WORK_GROUP_SIZE, X axis) x 1 x 1. 141 * 142 * Bind the buffer object to GL_SHADER_STORAGE_BUFFER target. 143 * 144 * In the compute shader execute: 145 * 146 * computeSSBO.value[gl_LocalInvocationID.x] = vec4(gl_LocalInvocationID.x); 147 * 148 * Call: 149 * 150 * glDispatchCompute(1, 1, 1); 151 * glMemoryBarrier(TEXTURE_FETCH_BARRIER_BIT); 152 * 153 * Bind the buffer object once again to TEXTURE_BUFFER_EXT target. 154 * 155 * --------------------------------------------------------------------------- 156 * 157 * The test checks whether data for the texture buffer has been correctly 158 * specified in the above 6 different ways and if it can be accessed via imageLoad 159 * and texelFetch. In the first phase we try to access the data via imageLoad in 160 * a compute shader and in the second phase we try to access the same data 161 * via texelFetch in a vertex shader. 162 * 163 * For the first phase write a compute shader that defines 164 * 165 * layout(rgba32i, binding = 0) uniform highp iimageBuffer image_buffer; 166 * 167 * Bind the texture buffer to image unit 0. 168 * 169 * Work group size should be equal to 170 * value(GL_MAX_COMPUTE_WORK_GROUP_SIZE, X axis) x 1 x 1. 171 * 172 * The shader should also define a shader storage buffer object 173 * 174 * buffer ComputeSSBO 175 * { 176 * ivec4 value[]; 177 * 178 * } computeSSBO; 179 * 180 * Initialize a buffer object to be assigned as ssbo data store. The size of 181 * this buffer object's data store should be equal to the size of 182 * the data store of the buffer object associated with texture buffer. 183 * 184 * In the compute shader execute: 185 * 186 * int index = int(gl_LocalInvocationID.x); 187 * 188 * computeSSBO.value[index] = imageLoad( image_buffer, index); 189 * 190 * Call: 191 * 192 * glDispatchCompute(1, 1, 1); 193 * glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); 194 * 195 * For each case compare the contents of the data store of ssbo's buffer object 196 * with the values that this case should have written to the data store of the 197 * texture buffer. This phase of the test passes if for each case we get equality. 198 * 199 * For the second phase of the test write a vertex shader that defines 200 * 201 * in vec4 vs_position; 202 * in float vs_index; 203 * out float fs_index; 204 * 205 * The shader should execute the following operations: 206 * 207 * gl_Position = vs_position; 208 * fs_index = vs_index; 209 * 210 * Configure buffer object as data source for the vs_position attribute. 211 * The buffer object should be filled with data: 212 * (-1,-1,0,1), (1,-1,0,1), (-1,1,0,1), (1,1,0,1). 213 * 214 * Configure buffer object as data source for the vs_index attribute. 215 * The buffer object should be filled with data: 216 * 0.0f , 0.0f , value(GL_MAX_COMPUTE_WORK_GROUP_SIZE, X axis), 217 * value(GL_MAX_COMPUTE_WORK_GROUP_SIZE, X axis). 218 * 219 * Write a fragment shader that defines; 220 * 221 * in float fs_index; 222 * 223 * uniform highp isamplerBuffer sampler_buffer; 224 * 225 * layout(location = 0) out ivec4 color; 226 * 227 * The shader should execute the following operations: 228 * 229 * color = texelFetch( sampler_buffer, int(fs_index) ); 230 * 231 * Create a program from the above vertex shader and fragment shader and use it. 232 * 233 * Bind the sampler_buffer location to texture unit 0. 234 * 235 * The test should set up a FBO. A 2D texture of 236 * value(GL_MAX_COMPUTE_WORK_GROUP_SIZE, X axis) x 1 resolution using 237 * GL_RGBA32I internal format and GL_NEAREST magnification and 238 * minification filter should be attached to its color attachment 0. 239 * 240 * Execute a draw call glDrawArrays(GL_TRIANGLE_STRIP, 0, 4). 241 * 242 * Use glReadPixels to read the texel data from the texture attached to color 243 * attachment 0. 244 * 245 * For each case compare the contents of retrieved texel data with the values 246 * that this case should have written to the data store of the texture buffer. 247 * This phase of the test passes if for each case we get equality. 248 */ 249 250 /* Base Class */ 251 class TextureBufferOperations : public TestCaseBase 252 { 253 public: 254 /* Public methods */ 255 TextureBufferOperations(Context& context, const ExtParameters& extParams, const char* name, 256 const char* description); 257 ~TextureBufferOperations()258 virtual ~TextureBufferOperations() 259 { 260 } 261 262 virtual void deinit(void); 263 virtual IterateResult iterate(void); 264 265 protected: 266 /* Protected methods */ 267 void checkFramebufferStatus(glw::GLenum framebuffer); 268 virtual void initTest(void); 269 virtual void initializeBufferObjectData(void) = 0; 270 virtual void fillBufferWithData(glw::GLint* buffer, glw::GLuint bufferLength); 271 272 /* Protected static constants */ 273 static const glw::GLuint m_n_vector_components; 274 275 /* Protected variables */ 276 glw::GLint m_n_vectors_in_buffer_texture; 277 278 glw::GLuint m_tb_bo_id; 279 glw::GLuint m_texbuff_id; 280 281 private: 282 std::string getComputeShaderCode(void) const; 283 std::string getFragmentShaderCode(void) const; 284 std::string getVertexShaderCode(void) const; 285 286 void initFirstPhase(void); 287 void initSecondPhase(void); 288 void iterateFirstPhase(glw::GLint* result, glw::GLuint size); 289 void iterateSecondPhase(glw::GLint* result); 290 void deinitFirstPhase(void); 291 void deinitSecondPhase(void); 292 293 glw::GLboolean verifyResults(glw::GLint* reference, glw::GLint* result, glw::GLuint size, const char* message); 294 295 /* Private variables */ 296 glw::GLuint m_cs_id; 297 glw::GLuint m_po_cs_id; 298 glw::GLuint m_ssbo_bo_id; 299 300 glw::GLuint m_fbo_id; 301 glw::GLuint m_fs_id; 302 glw::GLuint m_po_vs_fs_id; 303 glw::GLuint m_to_id; 304 glw::GLuint m_vao_id; 305 glw::GLuint m_vbo_id; 306 glw::GLuint m_vbo_indicies_id; 307 glw::GLuint m_vs_id; 308 glw::GLint m_vertex_location; 309 glw::GLint m_index_location; 310 }; 311 312 /* Test Case 1 - buffer object loads */ 313 class TextureBufferOperationsViaBufferObjectLoad : public TextureBufferOperations 314 { 315 public: 316 /* Public methods */ 317 TextureBufferOperationsViaBufferObjectLoad(Context& context, const ExtParameters& extParams, const char* name, 318 const char* description); 319 ~TextureBufferOperationsViaBufferObjectLoad()320 virtual ~TextureBufferOperationsViaBufferObjectLoad() 321 { 322 } 323 324 protected: 325 /* Protected methods */ 326 virtual void initializeBufferObjectData(void); 327 }; 328 329 /* Test Case 2 - direct CPU writes */ 330 class TextureBufferOperationsViaCPUWrites : public TextureBufferOperations 331 { 332 public: 333 /* Public methods */ 334 TextureBufferOperationsViaCPUWrites(Context& context, const ExtParameters& extParams, const char* name, 335 const char* description); 336 ~TextureBufferOperationsViaCPUWrites()337 virtual ~TextureBufferOperationsViaCPUWrites() 338 { 339 } 340 341 protected: 342 /* Protected methods */ 343 virtual void initializeBufferObjectData(void); 344 }; 345 346 /* Test Case 3 - framebuffer readbacks to pixel buffer objects */ 347 class TextureBufferOperationsViaFrambufferReadBack : public TextureBufferOperations 348 { 349 public: 350 /* Public methods */ 351 TextureBufferOperationsViaFrambufferReadBack(Context& context, const ExtParameters& extParams, const char* name, 352 const char* description); 353 ~TextureBufferOperationsViaFrambufferReadBack()354 virtual ~TextureBufferOperationsViaFrambufferReadBack() 355 { 356 } 357 358 virtual void deinit(void); 359 360 private: 361 /* Private methods */ 362 virtual void initializeBufferObjectData(void); 363 virtual void fillBufferWithData(glw::GLint* buffer, glw::GLuint bufferLength); 364 365 std::string getFBFragmentShaderCode() const; 366 std::string getFBVertexShaderCode() const; 367 368 glw::GLuint m_fb_fbo_id; 369 glw::GLuint m_fb_fs_id; 370 glw::GLuint m_fb_po_id; 371 glw::GLuint m_fb_to_id; 372 glw::GLuint m_fb_vao_id; 373 glw::GLuint m_fb_vbo_id; 374 glw::GLuint m_fb_vs_id; 375 glw::GLint m_position_location; 376 }; 377 378 /* Test Case 4 - transform feedback */ 379 class TextureBufferOperationsViaTransformFeedback : public TextureBufferOperations 380 { 381 public: 382 /* Public methods */ 383 TextureBufferOperationsViaTransformFeedback(Context& context, const ExtParameters& extParams, const char* name, 384 const char* description); 385 ~TextureBufferOperationsViaTransformFeedback()386 virtual ~TextureBufferOperationsViaTransformFeedback() 387 { 388 } 389 390 virtual void deinit(void); 391 392 private: 393 /* Private methods */ 394 virtual void initializeBufferObjectData(void); 395 396 std::string getTFVertexShaderCode() const; 397 std::string getTFFragmentShaderCode() const; 398 399 /* Private variables */ 400 glw::GLuint m_tf_fs_id; 401 glw::GLuint m_tf_po_id; 402 glw::GLuint m_tf_vao_id; 403 glw::GLuint m_tf_vbo_id; 404 glw::GLuint m_tf_vs_id; 405 glw::GLint m_position_location; 406 }; 407 408 /* Test Case 5 - image store */ 409 class TextureBufferOperationsViaImageStore : public TextureBufferOperations 410 { 411 public: 412 /* Public methods */ 413 TextureBufferOperationsViaImageStore(Context& context, const ExtParameters& extParams, const char* name, 414 const char* description); 415 ~TextureBufferOperationsViaImageStore()416 virtual ~TextureBufferOperationsViaImageStore() 417 { 418 } 419 420 virtual void deinit(void); 421 422 private: 423 /* Private methods */ 424 virtual void initializeBufferObjectData(void); 425 virtual void fillBufferWithData(glw::GLint* buffer, glw::GLuint bufferLength); 426 427 std::string getISComputeShaderCode() const; 428 429 /* Private Variables */ 430 glw::GLuint m_is_cs_id; 431 glw::GLuint m_is_po_id; 432 433 /* Private static constants */ 434 static const glw::GLuint m_image_unit; 435 }; 436 437 /* Test Case 6 - ssbo writes */ 438 class TextureBufferOperationsViaSSBOWrites : public TextureBufferOperations 439 { 440 public: 441 /* Public methods */ 442 TextureBufferOperationsViaSSBOWrites(Context& context, const ExtParameters& extParams, const char* name, 443 const char* description); 444 ~TextureBufferOperationsViaSSBOWrites()445 virtual ~TextureBufferOperationsViaSSBOWrites() 446 { 447 } 448 449 virtual void deinit(void); 450 451 private: 452 /* Private methods */ 453 virtual void initializeBufferObjectData(void); 454 virtual void fillBufferWithData(glw::GLint* buffer, glw::GLuint bufferLength); 455 456 std::string getSSBOComputeShaderCode() const; 457 458 /* Private variables */ 459 glw::GLuint m_ssbo_cs_id; 460 glw::GLuint m_ssbo_po_id; 461 }; 462 463 } // namespace glcts 464 465 #endif // _ESEXTCTEXTUREBUFFEROPERATIONS_HPP 466