Correct robust buffer access behavior tests
[platform/upstream/VK-GL-CTS.git] / external / openglcts / modules / common / glcRobustBufferAccessBehaviorTests.hpp
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