1 #ifndef _GLCROBUSTBUFFERACCESSBEHAVIORTESTS_HPP 2 #define _GLCROBUSTBUFFERACCESSBEHAVIORTESTS_HPP 3 /*------------------------------------------------------------------------- 4 * OpenGL Conformance Test Suite 5 * ----------------------------- 6 * 7 * Copyright (c) 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 glcRobustBufferAccessBehaviorTests.hpp 23 * \brief Declares test classes for "Robust Buffer Access Behavior" functionality. 24 */ /*-------------------------------------------------------------------*/ 25 26 #include "glcRobustnessTests.hpp" 27 #include "glcTestCase.hpp" 28 #include "glwDefs.hpp" 29 #include "glwEnums.hpp" 30 31 #include <map> 32 33 namespace glcts 34 { 35 namespace RobustBufferAccessBehavior 36 { 37 /** Replace first occurance of <token> with <text> in <string> starting at <search_posistion> 38 **/ 39 void replaceToken(const glw::GLchar* token, size_t& search_position, const glw::GLchar* text, std::string& string); 40 41 /** Represents buffer instance 42 * Provides basic buffer functionality 43 **/ 44 class Buffer 45 { 46 public: 47 /* Public methods */ 48 /* Ctr & Dtr */ 49 Buffer(const glw::Functions& gl); 50 ~Buffer(); 51 52 /* Init & Release */ 53 void InitData(glw::GLenum target, glw::GLenum usage, glw::GLsizeiptr size, const glw::GLvoid* data); 54 void Release(); 55 56 /* Functionality */ 57 void Bind() const; 58 void BindBase(glw::GLuint index) const; 59 60 /* Public static routines */ 61 /* Functionality */ 62 static void Bind(const glw::Functions& gl, glw::GLuint id, glw::GLenum target); 63 static void BindBase(const glw::Functions& gl, glw::GLuint id, glw::GLenum target, glw::GLuint index); 64 static void Data(const glw::Functions& gl, glw::GLenum target, glw::GLenum usage, glw::GLsizeiptr size, 65 const glw::GLvoid* data); 66 static void Generate(const glw::Functions& gl, glw::GLuint& out_id); 67 static void SubData(const glw::Functions& gl, glw::GLenum target, glw::GLintptr offset, glw::GLsizeiptr size, 68 glw::GLvoid* data); 69 70 /* Public fields */ 71 glw::GLuint m_id; 72 73 /* Public constants */ 74 static const glw::GLuint m_invalid_id; 75 static const glw::GLuint m_n_targets = 13; 76 static const glw::GLenum m_targets[m_n_targets]; 77 78 private: 79 /* Private enums */ 80 81 /* Private fields */ 82 const glw::Functions& m_gl; 83 glw::GLenum m_target; 84 }; 85 86 /** Represents framebuffer 87 * Provides basic functionality 88 **/ 89 class Framebuffer 90 { 91 public: 92 /* Public methods */ 93 /* Ctr & Dtr */ 94 Framebuffer(const glw::Functions& gl); 95 ~Framebuffer(); 96 97 /* Init & Release */ 98 void Release(); 99 100 /* Public static routines */ 101 static void AttachTexture(const glw::Functions& gl, glw::GLenum target, glw::GLenum attachment, 102 glw::GLuint texture_id, glw::GLint level, glw::GLuint width, glw::GLuint height); 103 104 static void Bind(const glw::Functions& gl, glw::GLenum target, glw::GLuint id); 105 static void Generate(const glw::Functions& gl, glw::GLuint& out_id); 106 107 /* Public fields */ 108 glw::GLuint m_id; 109 110 /* Public constants */ 111 static const glw::GLuint m_invalid_id; 112 113 private: 114 /* Private fields */ 115 const glw::Functions& m_gl; 116 }; 117 118 /** Represents shader instance. 119 * Provides basic functionality for shaders. 120 **/ 121 class Shader 122 { 123 public: 124 /* Public methods */ 125 /* Ctr & Dtr */ 126 Shader(const glw::Functions& gl); 127 ~Shader(); 128 129 /* Init & Realese */ 130 void Init(glw::GLenum stage, const std::string& source); 131 void Release(); 132 133 /* Public static routines */ 134 /* Functionality */ 135 static void Compile(const glw::Functions& gl, glw::GLuint id); 136 static void Create(const glw::Functions& gl, glw::GLenum stage, glw::GLuint& out_id); 137 static void Source(const glw::Functions& gl, glw::GLuint id, const std::string& source); 138 139 /* Public fields */ 140 glw::GLuint m_id; 141 142 /* Public constants */ 143 static const glw::GLuint m_invalid_id; 144 145 private: 146 /* Private fields */ 147 const glw::Functions& m_gl; 148 }; 149 150 /** Represents program instance. 151 * Provides basic functionality 152 **/ 153 class Program 154 { 155 public: 156 /* Public methods */ 157 /* Ctr & Dtr */ 158 Program(const glw::Functions& gl); 159 ~Program(); 160 161 /* Init & Release */ 162 void Init(const std::string& compute_shader, const std::string& fragment_shader, const std::string& geometry_shader, 163 const std::string& tesselation_control_shader, const std::string& tesselation_evaluation_shader, 164 const std::string& vertex_shader); 165 166 void Release(); 167 168 /* Functionality */ 169 void Use() const; 170 171 /* Public static routines */ 172 /* Functionality */ 173 static void Attach(const glw::Functions& gl, glw::GLuint program_id, glw::GLuint shader_id); 174 static void Create(const glw::Functions& gl, glw::GLuint& out_id); 175 static void Link(const glw::Functions& gl, glw::GLuint id); 176 static void Use(const glw::Functions& gl, glw::GLuint id); 177 178 /* Public fields */ 179 glw::GLuint m_id; 180 181 Shader m_compute; 182 Shader m_fragment; 183 Shader m_geometry; 184 Shader m_tess_ctrl; 185 Shader m_tess_eval; 186 Shader m_vertex; 187 188 /* Public constants */ 189 static const glw::GLuint m_invalid_id; 190 191 private: 192 /* Private fields */ 193 const glw::Functions& m_gl; 194 }; 195 196 /** Represents texture instance 197 **/ 198 class Texture 199 { 200 public: 201 /* Public methods */ 202 /* Ctr & Dtr */ 203 Texture(const glw::Functions& gl); 204 ~Texture(); 205 206 /* Init & Release */ 207 void Release(); 208 209 /* Public static routines */ 210 /* Functionality */ 211 static void Bind(const glw::Functions& gl, glw::GLuint id, glw::GLenum target); 212 213 static void CompressedImage(const glw::Functions& gl, glw::GLenum target, glw::GLint level, 214 glw::GLenum internal_format, glw::GLuint width, glw::GLuint height, glw::GLuint depth, 215 glw::GLsizei image_size, const glw::GLvoid* data); 216 217 static void Generate(const glw::Functions& gl, glw::GLuint& out_id); 218 219 static void GetData(const glw::Functions& gl, glw::GLint level, glw::GLenum target, glw::GLenum format, 220 glw::GLenum type, glw::GLvoid* out_data); 221 222 static void GetData(const glw::Functions& gl, glw::GLuint id, glw::GLint level, glw::GLuint width, 223 glw::GLuint height, glw::GLenum format, glw::GLenum type, glw::GLvoid* out_data); 224 225 static void GetLevelParameter(const glw::Functions& gl, glw::GLenum target, glw::GLint level, glw::GLenum pname, 226 glw::GLint* param); 227 228 static void Image(const glw::Functions& gl, glw::GLenum target, glw::GLint level, glw::GLenum internal_format, 229 glw::GLuint width, glw::GLuint height, glw::GLuint depth, glw::GLenum format, glw::GLenum type, 230 const glw::GLvoid* data); 231 232 static void Storage(const glw::Functions& gl, glw::GLenum target, glw::GLsizei levels, glw::GLenum internal_format, 233 glw::GLuint width, glw::GLuint height, glw::GLuint depth); 234 235 static void SubImage(const glw::Functions& gl, glw::GLenum target, glw::GLint level, glw::GLint x, glw::GLint y, 236 glw::GLint z, glw::GLsizei width, glw::GLsizei height, glw::GLsizei depth, glw::GLenum format, 237 glw::GLenum type, const glw::GLvoid* pixels); 238 239 /* Public fields */ 240 glw::GLuint m_id; 241 242 /* Public constants */ 243 static const glw::GLuint m_invalid_id; 244 245 private: 246 /* Private fields */ 247 const glw::Functions& m_gl; 248 }; 249 250 /** Represents Vertex array object 251 * Provides basic functionality 252 **/ 253 class VertexArray 254 { 255 public: 256 /* Public methods */ 257 /* Ctr & Dtr */ 258 VertexArray(const glw::Functions& gl); 259 ~VertexArray(); 260 261 /* Init & Release */ 262 void Release(); 263 264 /* Public static methods */ 265 static void Bind(const glw::Functions& gl, glw::GLuint id); 266 static void Generate(const glw::Functions& gl, glw::GLuint& out_id); 267 268 /* Public fields */ 269 glw::GLuint m_id; 270 271 /* Public constants */ 272 static const glw::GLuint m_invalid_id; 273 274 private: 275 /* Private fields */ 276 const glw::Functions& m_gl; 277 }; 278 279 class RobustnessBase : public tcu::TestCase 280 { 281 public: 282 RobustnessBase(tcu::TestContext& testCtx, const char* name, const char* description, glu::ApiType apiType); 283 284 glu::RenderContext* createRobustContext( 285 glu::ResetNotificationStrategy reset = glu::RESET_NOTIFICATION_STRATEGY_NO_RESET_NOTIFICATION); 286 287 protected: 288 glu::ApiType m_api_type; 289 bool m_context_is_es; 290 bool m_has_khr_robust_buffer_access; 291 292 std::map<std::string, std::string> m_specializationMap; 293 }; 294 295 /** Implementation of test VertexBufferObjects. Description follows: 296 * 297 * This test verifies that any "out-of-bound" read from vertex buffer result with abnormal program exit 298 * 299 * Steps: 300 * - prepare vertex buffer with the following vertices: 301 * * 0 - [ 0, 0, 0], 302 * * 1 - [-1, 0, 0], 303 * * 2 - [-1, 1, 0], 304 * * 3 - [ 0, 1, 0], 305 * * 4 - [ 1, 1, 0], 306 * * 5 - [ 1, 0, 0], 307 * * 6 - [ 1, -1, 0], 308 * * 7 - [ 0, -1, 0], 309 * * 8 - [-1, -1, 0]; 310 * - prepare element buffer: 311 * * valid: 312 * 0, 1, 2, 313 * 0, 2, 3, 314 * 0, 3, 4, 315 * 0, 4, 5, 316 * 0, 5, 6, 317 * 0, 6, 7, 318 * 0, 7, 8, 319 * 0, 8, 1; 320 * * invalid: 321 * 9, 1, 2, 322 * 10, 2, 3, 323 * 11, 3, 4, 324 * 12, 4, 5, 325 * 13, 5, 6, 326 * 14, 6, 7, 327 * 15, 7, 8, 328 * 16, 8, 1; 329 * - prepare program consisting of vertex and fragment shader that will output 330 * value 1; 331 * - prepare framebuffer with R8UI texture attached as color 0, filled with 332 * value 128; 333 * - execute draw call with invalid element buffer; 334 * - inspect contents of framebuffer, it is expected that it is filled with 335 * value 1; 336 * - clean framebuffer to value 128; 337 * - execute draw call with valid element buffer; 338 * - inspect contents of framebuffer, it is expected that it is filled with 339 * value 1. 340 **/ 341 class VertexBufferObjectsTest : public RobustnessBase 342 { 343 public: 344 /* Public methods */ 345 VertexBufferObjectsTest(tcu::TestContext& testCtx, glu::ApiType apiType); ~VertexBufferObjectsTest()346 virtual ~VertexBufferObjectsTest() 347 { 348 } 349 350 /* Public methods inherited from TestCase */ 351 virtual tcu::TestNode::IterateResult iterate(void); 352 353 protected: 354 /* Protected methods */ 355 std::string getFragmentShader(); 356 std::string getVertexShader(); 357 void cleanTexture(const glw::Functions& gl, glw::GLuint texture_id); 358 bool verifyInvalidResults(const glw::Functions& gl, glw::GLuint texture_id); 359 bool verifyValidResults(const glw::Functions& gl, glw::GLuint texture_id); 360 bool verifyResults(const glw::Functions& gl, glw::GLuint texture_id); 361 }; 362 363 /** Implementation of test TexelFetch. Description follows: 364 * 365 * This test verifies that any "out-of-bound" fetch from texture result in 366 * "zero". 367 * 368 * Steps: 369 * - prepare program consisting of vertex, geometry and fragment shader that 370 * will output full-screen quad; Each fragment should receive value of 371 * corresponding texel from source texture; Use texelFetch function; 372 * - prepare 16x16 2D R8UI source texture filled with unique values; 373 * - prepare framebuffer with 16x16 R8UI texture as color attachment, filled 374 * with value 0; 375 * - execute draw call; 376 * - inspect contents of framebuffer, it is expected to match source texture; 377 * - modify program so it will fetch invalid texels; 378 * - execute draw call; 379 * - inspect contents of framebuffer, it is expected that it will be filled 380 * with value 0 for RGB channels and with 0, 1 or the biggest representable 381 * integral number for alpha channel. 382 * 383 * Repeat steps for: 384 * - R8 texture; 385 * - RG8_SNORM texture; 386 * - RGBA32F texture; 387 * - mipmap at level 1; 388 * - a texture with 4 samples. 389 **/ 390 class TexelFetchTest : public RobustnessBase 391 { 392 public: 393 /* Public methods */ 394 TexelFetchTest(tcu::TestContext& testCtx, glu::ApiType apiType); 395 TexelFetchTest(tcu::TestContext& testCtx, const char* name, const char* description, glu::ApiType apiType); ~TexelFetchTest()396 virtual ~TexelFetchTest() 397 { 398 } 399 400 /* Public methods inherited from TestCase */ 401 virtual tcu::TestNode::IterateResult iterate(void); 402 403 protected: 404 /* Protected enums */ 405 enum TEST_CASES 406 { 407 R8, 408 RG8_SNORM, 409 R32UI_MULTISAMPLE, 410 RGBA32F, 411 R32UI_MIPMAP, 412 /* */ 413 LAST 414 }; 415 416 enum VERSION 417 { 418 VALID, 419 SOURCE_INVALID, 420 DESTINATION_INVALID, 421 }; 422 423 /* Protected methods */ 424 const glw::GLchar* getTestCaseName() const; 425 void prepareTexture(const glw::Functions& gl, bool is_source, glw::GLuint texture_id); 426 427 /* Protected fields */ 428 TEST_CASES m_test_case; 429 430 protected: 431 /* Protected methods */ 432 std::string getFragmentShader(const glu::ContextType& contextType, bool is_case_valid, 433 glw::GLuint fetch_offset = 0); 434 std::string getGeometryShader(); 435 std::string getVertexShader(); 436 virtual bool verifyInvalidResults(const glw::Functions& gl, glw::GLuint texture_id); 437 virtual bool verifyValidResults(const glw::Functions& gl, glw::GLuint texture_id); 438 }; 439 440 /** Implementation of test ImageLoadStore. Description follows: 441 * 442 * This test verifies that any "out-of-bound" access to image result in "zero" 443 * or is discarded. 444 * 445 * Modify TexelFetch test in the following aspects: 446 * - use compute shader instead of "draw" pipeline; 447 * - use imageLoad instead of texelFetch; 448 * - use destination image instead of framebuffer; Store texel with imageStore; 449 * - for each case from TexelFetch verify: 450 * * valid coordinates for source and destination images; 451 * * invalid coordinates for destination and valid ones for source image; 452 * * valid coordinates for destination and invalid ones for source image. 453 **/ 454 class ImageLoadStoreTest : public TexelFetchTest 455 { 456 public: 457 /* Public methods */ 458 ImageLoadStoreTest(tcu::TestContext& testCtx, glu::ApiType apiType); ~ImageLoadStoreTest()459 virtual ~ImageLoadStoreTest() 460 { 461 } 462 463 /* Public methods inherited from TestCase */ 464 virtual tcu::TestNode::IterateResult iterate(void); 465 466 protected: 467 /* Protected methods */ 468 std::string getComputeShader(VERSION version, glw::GLuint coord_offset = 0, glw::GLuint sample_offset = 0); 469 void setTextures(const glw::Functions& gl, glw::GLuint id_destination, glw::GLuint id_source); 470 bool verifyInvalidResults(const glw::Functions& gl, glw::GLuint texture_id); 471 bool verifyValidResults(const glw::Functions& gl, glw::GLuint texture_id); 472 }; 473 474 /** Implementation of test StorageBuffer. Description follows: 475 * 476 * This test verifies that any "out-of-bound" access to buffer result in zero 477 * or is discarded. 478 * 479 * Steps: 480 * - prepare compute shader based on the following code snippet: 481 * 482 * uint dst_index = gl_LocalInvocationID.x; 483 * uint src_index = gl_LocalInvocationID.x; 484 * destination[dst_index] = source[src_index]; 485 * 486 * where source and destination are storage buffers, defined as unsized arrays 487 * of floats; 488 * - prepare two buffers of 4 floats: 489 * * destination filled with value 1; 490 * * source filled with unique values; 491 * - dispatch program to copy all 4 values; 492 * - inspect program to verify that contents of source buffer were copied to 493 * destination; 494 * - repeat steps for the following cases: 495 * * value of dst_index is equal to gl_LocalInvocationID.x + 16; It is 496 * expected that destination buffer will not be modified; 497 * * value of src_index is equal to gl_LocalInvocationID.x + 16; It is 498 * expected that destination buffer will be filled with value 0. 499 **/ 500 class StorageBufferTest : public RobustnessBase 501 { 502 public: 503 /* Public methods */ 504 StorageBufferTest(tcu::TestContext& testCtx, glu::ApiType apiType); ~StorageBufferTest()505 virtual ~StorageBufferTest() 506 { 507 } 508 509 /* Public methods inherited from TestCase */ 510 virtual tcu::TestNode::IterateResult iterate(void); 511 512 protected: 513 /* Protected enums */ 514 enum VERSION 515 { 516 VALID, 517 SOURCE_INVALID, 518 DESTINATION_INVALID, 519 /* */ 520 LAST 521 }; 522 523 /* Private methods */ 524 std::string getComputeShader(glw::GLuint offset); 525 bool verifyResults(glw::GLfloat* buffer_data); 526 527 /* Protected fields */ 528 VERSION m_test_case; 529 530 /* Protected constants */ 531 static const glw::GLfloat m_destination_data[4]; 532 static const glw::GLfloat m_source_data[4]; 533 }; 534 535 /** Implementation of test UniformBuffer. Description follows: 536 * 537 * This test verifies that any "out-of-bound" read from uniform buffer result 538 * in zero; 539 * 540 * Modify StorageBuffer test in the following aspects: 541 * - use uniform buffer for source instead of storage buffer; 542 * - ignore the case with invalid value of dst_index. 543 **/ 544 class UniformBufferTest : public RobustnessBase 545 { 546 public: 547 /* Public methods */ 548 UniformBufferTest(tcu::TestContext& testCtx, glu::ApiType apiType); ~UniformBufferTest()549 virtual ~UniformBufferTest() 550 { 551 } 552 553 /* Public methods inherited from TestCase */ 554 virtual tcu::TestNode::IterateResult iterate(void); 555 556 protected: 557 /* Protected enums */ 558 enum VERSION 559 { 560 VALID, 561 SOURCE_INVALID, 562 /* */ 563 LAST 564 }; 565 566 /* Protected methods */ 567 std::string getComputeShader(glw::GLuint offset); 568 bool verifyResults(glw::GLfloat* buffer_data); 569 570 /* Protected fields */ 571 VERSION m_test_case; 572 }; 573 } /* RobustBufferAccessBehavior */ 574 575 /** Group class for multi bind conformance tests */ 576 class RobustBufferAccessBehaviorTests : public tcu::TestCaseGroup 577 { 578 public: 579 /* Public methods */ 580 RobustBufferAccessBehaviorTests(tcu::TestContext& testCtx, glu::ApiType apiType); ~RobustBufferAccessBehaviorTests(void)581 virtual ~RobustBufferAccessBehaviorTests(void) 582 { 583 } 584 585 virtual void init(void); 586 587 private: 588 /* Private methods */ 589 RobustBufferAccessBehaviorTests(const RobustBufferAccessBehaviorTests& other); 590 RobustBufferAccessBehaviorTests& operator=(const RobustBufferAccessBehaviorTests& other); 591 592 glu::ApiType m_ApiType; 593 }; 594 595 } /* glcts */ 596 597 #endif // _GLCROBUSTBUFFERACCESSBEHAVIORTESTS_HPP 598