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