Home | History | Annotate | Download | only in common
      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);
    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);
    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);
    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);
    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);
    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);
    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