1 #ifndef _GL3CTRANSFORMFEEDBACKTESTS_HPP
2 #define _GL3CTRANSFORMFEEDBACKTESTS_HPP
3 /*-------------------------------------------------------------------------
4  * OpenGL Conformance Test Suite
5  * -----------------------------
6  *
7  * Copyright (c) 2015-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  */ /*!
28  * \file  gl3cTransformFeedback.hpp
29  * \brief Transform Feedback Test Suite Interface
30  */ /*-------------------------------------------------------------------*/
31 
32 #include "glcTestCase.hpp"
33 #include "glwDefs.hpp"
34 #include "tcuDefs.hpp"
35 
36 /* Includes. */
37 #include <map>
38 #include <string>
39 #include <typeinfo>
40 #include <vector>
41 
42 #include "glwEnums.hpp"
43 #include "glwFunctions.hpp"
44 
45 namespace gl3cts
46 {
47 namespace TransformFeedback
48 {
49 class Tests : public deqp::TestCaseGroup
50 {
51 public:
52 	Tests(deqp::Context& context);
53 	~Tests(void);
54 	virtual void init(void);
55 
56 private:
57 	Tests(const Tests& other);
58 	Tests& operator=(const Tests& other);
59 };
60 
61 /** APIErrors
62  *
63  *  Verifies if errors are generated as specified.
64  *  Four test shall be run:
65  *   - Test api errors defined in GL_EXT_transform_feedback.
66  *   - Test api errors defined in GL_ARB_transform_feedback2.
67  *   - Test api errors defined in GL_ARB_transform_feedback3.
68  *   - Test api errors defined in GL_ARB_transform_feedback_instanced.
69  */
70 class APIErrors : public deqp::TestCase
71 {
72 public:
73 	APIErrors(deqp::Context& context);
74 	~APIErrors(void);
75 	IterateResult iterate(void);
76 
77 private:
78 	deqp::Context& m_context;
79 
80 	static const glw::GLchar* m_tessellation_control_shader;
81 	static const glw::GLchar* m_tessellation_evaluation_shader;
82 	static const glw::GLchar* m_geometry_shader;
83 	static const glw::GLchar* s_vertex_shader_with_input_output;
84 	static const glw::GLchar* s_vertex_shader_with_output;
85 	static const glw::GLchar* s_vertex_shader_without_output;
86 	static const glw::GLchar* s_fragment_shader;
87 	static const glw::GLchar* m_varying_name;
88 
89 	static const glw::GLfloat m_buffer_1_data[];
90 	static const glw::GLsizei m_buffer_1_size;
91 
92 	glw::GLuint m_buffer_0;
93 	glw::GLuint m_buffer_1;
94 
95 	glw::GLuint m_vertex_array_object;
96 
97 	glw::GLuint m_transform_feedback_object_0;
98 	glw::GLuint m_transform_feedback_object_1;
99 
100 	glw::GLuint m_query_object;
101 
102 	glw::GLuint m_program_id_with_input_output;
103 	glw::GLuint m_program_id_with_output;
104 	glw::GLuint m_program_id_without_output;
105 	glw::GLuint m_program_id_with_geometry_shader;
106 	glw::GLuint m_program_id_with_tessellation_shaders;
107 
108 	/** Check the following if EXT_transform_feedback is supported or context is
109 	 *  at least 3.0:
110 	 *
111 	 *  - INVALID_VALUE is generated by BindBufferRange, BindBufferOffset and
112 	 *    BindBufferBase when <index> is greater or equal to
113 	 *    MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS;
114 	 *  - INVALID_VALUE is generated by BindBufferRange and BindBufferOffset
115 	 *    when <size> is less or equal to zero;
116 	 *  - INVALID_VALUE is generated by BindBufferRange and BindBufferOffset
117 	 *    when <offset> is not word-aligned;
118 	 *  - INVALID_VALUE is generated by BindBufferRange and BindBufferOffset
119 	 *    when <size> is not word-aligned;
120 	 *  - INVALID_OPERATION is generated by BindBufferRange, BindBufferOffset and
121 	 *    BindBufferBase when <target> is TRANSFORM_FEEDBACK_BUFFER and transform
122 	 *    feedback is active;
123 	 *  - INVALID_OPERATION is generated by UseProgram when transform feedback is
124 	 *    active;
125 	 *  - INVALID_OPERATION is generated by LinkProgram when <program> is currently
126 	 *    active and transform feedback is active;
127 	 *  - INVALID_OPERATION is generated by BeginTransformFeedback when transform
128 	 *    feedback is active;
129 	 *  - INVALID_OPERATION is generated by EndTransformFeedback when transform
130 	 *    feedback is inactive;
131 	 *  - INVALID_OPERATION is generated by draw command when generated primitives
132 	 *    type does not match <primitiveMode>;
133 	 *  - INVALID_OPERATION is generated by BeginTransformFeedback when any binding
134 	 *    point used by XFB does not have buffer bound;
135 	 *  - INVALID_OPERATION is generated by BeginTransformFeedback when no program
136 	 *    is active;
137 	 *  - INVALID_OPERATION is generated by BeginTransformFeedback when no variable
138 	 *    are specified to be captured in the active program;
139 	 *  - INVALID_VALUE is generated by TransformFeedbackVaryings when <program> is
140 	 *    not id of the program object;
141 	 *  - INVALID_VALUE is generated by TransformFeedbackVaryings when <bufferMode>
142 	 *    is SEPARATE_ATTRIBS and <count> is exceeds limits;
143 	 *  - IVALID_VALUE is generated by GetTransformFeedbackVarying when <index> is
144 	 *    greater than or equal to TRANSFORM_FEEDBACK_VARYINGS;
145 	 *  - INVALID_VALUE is generated by GetIntegerIndexdv when <index> exceeds the
146 	 *    limits of MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS and <param> is one of the
147 	 *    following:
148 	 *    * TRANSFORM_FEEDBACK_BUFFER_BINDING,
149 	 *    * TRANSFORM_FEEDBACK_BUFFER_START,
150 	 *    * TRANSFORM_FEEDBACK_BUFFER_SIZE;
151 	 *  - INVALID_VALUE is generated by GetBooleanIndexedv when <index> exceeds the
152 	 *    limits of MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS and <param> is
153 	 *    TRANSFORM_FEEDBACK_BUFFER_BINDING.
154 	 */
155 	bool testExtension1(void);
156 
157 	/** Check the following if ARB_transform_feedback2 is supported or context is
158 	 *  at least 4.0:
159 	 *
160 	 *  - INVALID_OPERATION is generated by BindTransformFeedback if current
161 	 *    transform feedback is active and not paused;
162 	 *  - INVALID_OPERATION is generated by DeleteTransformFeedbacks if any of <ids>
163 	 *    is active;
164 	 *  - INVALID_OPERATION is generated by PauseTransformFeedback if current
165 	 *    transform feedback is not active or paused;
166 	 *  - INVALID_OPERATION is generated by ResumeTransformFeedback if current
167 	 *    transform feedback is not active or not paused;
168 	 *  - No error is generated by draw command when transform feedback is paused
169 	 *    and primitive modes do not match;
170 	 *  - No error is generated by UseProgram when transform feedback is paused;
171 	 *  - INVALID_OPERATION is generated by LinkProgram when <program> is used by
172 	 *    some transform feedback object that is currently not active;
173 	 *  - INVALID_VALUE is generated by DrawTransformFeedback if <id> is not name of
174 	 *    transform feedback object;
175 	 *  - INVALID_OPERATION is generated by DrawTransformFeedback when
176 	 *    EndTransformFeedback was never called for the object named <id>.
177 	 */
178 	bool testExtension2(void);
179 
180 	/** Check the following if ARB_transform_feedback3 is supported or context is
181 	 *  at least 4.0:
182 	 *
183 	 *  - INVALID_VALUE is generated by BeginQueryIndexed, EndQueryIndexed and
184 	 *    GetQueryIndexediv when <target> is TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN and
185 	 *    <index> exceeds limits of MAX_VERTEX_STREAMS;
186 	 *  - INVALID_VALUE is generated by BeginQueryIndexed, EndQueryIndexed and
187 	 *    GetQueryIndexediv when <target> is PRIMITIVES_GENERATED and <index> exceeds
188 	 *    limits of MAX_VERTEX_STREAMS;
189 	 *  - INVALID_OPERATION is generated by EndQueryIndexed when name of active
190 	 *    query at <index> of <target> is zero;
191 	 *  - INVALID_VALUE is generated by DrawTransformFeedbackStream when <stream>
192 	 *    exceeds limits of MAX_VERTEX_STREAMS;
193 	 *  - INVALID_OPERATION is generated by TransformFeedbackVaryings when
194 	 *    <varyings> contains any of the special names while <bufferMode> is not
195 	 *    INTERLEAVED_ATTRIBS;
196 	 *  - INVALID_OPERATION is generated by TransformFeedbackVaryings when
197 	 *    <varyings> contains more "gl_NextBuffer" entries than allowed limit of
198 	 *    MAX_TRANSFORM_FEEDBACK_BUFFERS;
199 	 */
200 	bool testExtension3(void);
201 
202 	/** Check the following if ARB_transform_feedback_instanced is supported or
203 	 *  context is at least 4.2:
204 	 *
205 	 *  - INVALID_ENUM is generated by DrawTransformFeedbackInstanced and
206 	 *    DrawTransformFeedbackStreamInstanced if <mode> is invalid;
207 	 *  - INVALID_OPERATION is generated by DrawTransformFeedbackInstanced and
208 	 *    DrawTransformFeedbackStreamInstanced if <mode> does not match geometry
209 	 *    shader;
210 	 *  - INVALID_OPERATION is generated by DrawTransformFeedbackInstanced and
211 	 *    DrawTransformFeedbackStreamInstanced if <mode> does not match tessellation;
212 	 *  - INVALID_VALUE is generated by DrawTransformFeedbackStreamInstanced if
213 	 *    <stream> is greater than or equal to MAX_VERTEX_STREAMS;
214 	 *  - INVALID_VALUE is generated by DrawTransformFeedbackInstanced and
215 	 *    DrawTransformFeedbackStreamInstanced if <id> is not name of transform
216 	 *    feedback object;
217 	 *  - INVALID_OPERATION is generated by DrawTransformFeedbackInstanced and
218 	 *    DrawTransformFeedbackStreamInstanced if a non-zero buffer object name is
219 	 *    bound to an enabled array and the buffer object's data store is currently
220 	 *    mapped;
221 	 *  - INVALID_OPERATION is generated if by DrawTransformFeedbackStreamInstanced
222 	 *    if EndTransformFeedback was never called for the object named <id>.
223 	 */
224 	bool testInstanced(void);
225 
226 	typedef GLW_APICALL void (GLW_APIENTRY *BindBufferOffsetEXT_ProcAddress)(glw::GLenum target, glw::GLuint index, glw::GLuint buffer,
227 																			 glw::GLintptr offset);
228 	typedef GLW_APICALL void (GLW_APIENTRY *GetIntegerIndexedvEXT_ProcAddress)(glw::GLenum param, glw::GLuint index, glw::GLint* values);
229 	typedef GLW_APICALL void (GLW_APIENTRY *GetBooleanIndexedvEXT_ProcAddress)(glw::GLenum param, glw::GLuint index, glw::GLboolean* values);
230 
231 	BindBufferOffsetEXT_ProcAddress   m_glBindBufferOffsetEXT;
232 	GetIntegerIndexedvEXT_ProcAddress m_glGetIntegerIndexedvEXT;
233 	GetBooleanIndexedvEXT_ProcAddress m_glGetBooleanIndexedvEXT;
234 };
235 
236 /** LinkingErrors
237  *
238  *  Verifies that linker reports errors as specified.
239  *
240  *  Test should be run if EXT_transform_feedback is supported or context is
241  *  at least 3.0.
242  *
243  *  Check if link process fails under the following conditions:
244  *  - <count> specified by TransformFeedbackVaryings is non-zero and program has
245  *    neither vertex nor geometry shader;
246  *  - <varyings> specified by TransformFeedbackVaryings contains name of
247  *    variable that is not available for capture;
248  *  - <varyings> specified by TransformFeedbackVaryings contains name of
249  *    variable more than once;
250  *  - number of components specified to capture exceeds limits
251  *    MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS or
252  *    MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS.
253  */
254 class LinkingErrors : public deqp::TestCase
255 {
256 public:
257 	LinkingErrors(deqp::Context& context);
258 	~LinkingErrors(void);
259 	IterateResult iterate(void);
260 
261 private:
262 	deqp::Context& m_context;
263 
264 	static const glw::GLchar* s_fragment_shader;
265 	static const glw::GLchar* s_vertex_shader_template;
266 	static const glw::GLchar* s_valid_transform_feedback_varying;
267 	static const glw::GLchar* s_invalid_transform_feedback_varying;
268 	static const glw::GLchar* s_repeated_transform_feedback_varying[];
269 	static const glw::GLsizei s_repeated_transform_feedback_varying_count;
270 
271 	bool testNoVertexNoGeometry(void);
272 	bool testInvalidVarying(void);
273 	bool testRepeatedVarying(void);
274 	bool testTooManyVaryings(void);
275 };
276 
277 /** Limits
278  *
279  *  Verifies that limits reported by API are as expected.
280  *
281  *  Check the following if EXT_transform_feedback is supported or context is at
282  *  least 3.0:
283  *  - MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS is at least 64,
284  *  - MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS is at least 4,
285  *  - MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS is at least 4.
286  *
287  *  Check the following if ARB_transform_feedback3 is supported or context is at
288  *  least 4.0:
289  *  - MAX_TRANSFORM_FEEDBACK_BUFFERS is at least 4,
290  *  - MAX_VERTEX_STREAMS is at least 1.
291  */
292 class Limits : public deqp::TestCase
293 {
294 public:
295 	Limits(deqp::Context& context);
296 	~Limits(void);
297 	IterateResult iterate(void);
298 
299 private:
300 	deqp::Context& m_context;
301 
302 	static const glw::GLchar* s_fragment_shader;
303 	static const glw::GLchar* s_vertex_shader;
304 
305 	static const glw::GLint s_min_value_of_max_transform_feedback_interleaved_components;
306 	static const glw::GLint s_min_value_of_max_transform_feedback_separate_attribs;
307 	static const glw::GLint s_min_value_of_max_transform_feedback_separate_components;
308 	static const glw::GLint s_min_value_of_max_transform_feedback_buffers;
309 	static const glw::GLint s_min_value_of_max_vertex_streams;
310 
311 	bool test_max_transform_feedback_interleaved_components(void);
312 	bool test_max_transform_feedback_separate_attribs(void);
313 	bool test_max_transform_feedback_separate_components(void);
314 	bool test_max_transform_feedback_buffers(void);
315 	bool test_max_vertex_streams(void);
316 };
317 
318 /** CaptureVertexInterleaved
319  *
320  *  Verifies if geometry processed with vertex shader is captured as expected in
321  *  interleaved mode.
322  *
323  *  Test should be run if EXT_transform_feedback is supported or context is
324  *  at least 3.0.
325  *
326  *  Steps:
327  *  - prepare program consisting of vertex and fragment shader; Vertex shader
328  *    should assign all MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS components;
329  *    One of the variables must be a position; Position should be set to one of
330  *    corners, based on gl_VertexID: 0 - top left, 1 - top right, 2 - bottom left
331  *    and 3 - bottom right; Rest of components should be covered with output
332  *    variables of type vec4; Fragment shader should accept all outputs from
333  *    vertex shader as inputs and use them to calculate non-black output color;
334  *  - instruct implementation to capture all outputs defined by vertex shader;
335  *    Use interleaved mode;
336  *  - prepare and set buffer to store captured geometry;
337  *  - prepare, set and clean frame-buffer with black color;
338  *  - execute BeginTransformFeedback;
339  *  - execute DrawElements;
340  *  - execute EndTransformFeedback;
341  *  - inspect contents of frame-buffer to check if rasterization was done
342  *    correctly;
343  *  - inspect TRANSFORM_FEEDBACK_BUFFER_START and
344  *    TRANSFORM_FEEDBACK_BUFFER_SIZE;
345  *  - inspect contents of the buffer to check if geometry was captured
346  *    correctly.
347  *
348  *  Test the following BindBuffer routines:
349  *  - BindBufferRange - use non-zero offset,
350  *  - BindBufferOffset - use non-zero offset,
351  *  - BindBufferBase.
352  *
353  *  Test the following primitive types:
354  *  - GL_POINTS - use these indices: [0, 1, 2, 3]; All corner pixels should be
355  *    set to specific colors; XFB should contain four vertices;
356  *  - GL_LINES - use these indices: [0, 1, 2, 3]; Top and bottom edges should be
357  *    drawn; XFB should contain four vertices;
358  *  - GL_LINE_LOOP - use these indices: [0, 1, 3, 2]; All four edges should be
359  *    drawn; XFB should contain eight vertices;
360  *  - GL_LINE_STRIP - use these indices: [0, 1, 3, 2]; Top, right and bottom
361  *    edge should be drawn; XFB should contain six vertices;
362  *  - GL_TRIANGLES - use these indices: [2, 0, 1, 2, 1, 3]; Whole image should
363  *    be drawn; XFB should contain six vertices;
364  *  - GL_TRIANGLE_STRIP - use these indices: [0, 1, 2, 3]; Whole image should
365  *    be drawn; XFB should contain six vertices;
366  *  - GL_TRIANGLE_FAN - use these indices: [2, 0, 1, 3]; Whole image should
367  *    be drawn; XFB should contain six vertices.
368  *
369  *  Number of components that can be passed to rasterization must not exceed
370  *  MAX_VARYING_COMPONENTS.
371  */
372 class CaptureVertexInterleaved : public deqp::TestCase
373 {
374 public:
375 	CaptureVertexInterleaved(deqp::Context& context, const char* test_name, const char* test_description);
376 	~CaptureVertexInterleaved(void);
377 	virtual IterateResult iterate(void);
378 
379 protected:
380 	deqp::Context& m_context;
381 	glw::GLuint	m_program;
382 	glw::GLuint	m_framebuffer;
383 	glw::GLuint	m_renderbuffer;
384 	glw::GLuint	m_buffer;
385 	glw::GLuint	m_buffer_size;
386 	glw::GLuint	m_vertex_array_object;
387 	glw::GLint	 m_max_transform_feedback_components;
388 	glw::GLenum	m_attrib_type;
389 	glw::GLuint	m_max_vertices_drawn;
390 
391 	typedef GLW_APICALL void (GLW_APIENTRY *BindBufferOffsetEXT_ProcAddress)(glw::GLenum target, glw::GLuint index, glw::GLuint buffer,
392 																			 glw::GLintptr offset);
393 
394 	BindBufferOffsetEXT_ProcAddress m_glBindBufferOffsetEXT;
395 
396 	static const glw::GLchar* s_vertex_shader_source_code_template;
397 	static const glw::GLchar* s_fragment_shader_source_code;
398 
399 	static const glw::GLuint  s_max_element_indices_count = 6;
400 	static const glw::GLuint  s_element_indices[][s_max_element_indices_count];
401 	static const glw::GLuint  s_primitive_cases_count;
402 	static const glw::GLuint  s_element_indices_counts[];
403 	static const glw::GLenum  s_primitive_cases[];
404 	static const glw::GLenum  s_primitive_cases_xfb[];
405 	static const glw::GLuint  s_framebuffer_size;
406 	static const glw::GLfloat s_rasterization_epsilon;
407 	static const glw::GLuint  s_max_vertex_id = 4;
408 
409 	enum BindBufferCase
410 	{
411 		BIND_BUFFER_BASE_CASE,
412 		BIND_BUFFER_RANGE_CASE,
413 		BIND_BUFFER_OFFSET_CASE,
414 		BIND_BUFFER_CASES_COUNT
415 	};
416 
417 	virtual void fetchLimits(void);
418 	virtual void buildProgram(void);
419 	void		 createFramebuffer(void);
420 	virtual void createTransformFeedbackBuffer(void);
421 	void		 createVertexArrayObject(void);
422 	virtual void draw(glw::GLuint primitive_case);
423 	virtual bool checkFramebuffer(glw::GLuint primitive_case);
424 	virtual bool checkTransformFeedbackBuffer(BindBufferCase bind_case, glw::GLenum primitive_type);
425 	virtual void bindBuffer(BindBufferCase bind_case);
426 	virtual void clean(void);
427 	virtual void cleanBuffer(void);
428 };
429 
430 /** CaptureGeometryInterleaved
431  *
432  *  Verifies if geometry processed with geometry shader is captured as expected
433  *  in interleaved mode.
434  *
435  *  Test should be run if either EXT_transform_feedback is supported or context
436  *  is at least 3.0 and either ARB_geometry_shader4 is supported or context is
437  *  at least 3.2.
438  *
439  *  Modify CaptureVertexInterleaved test in the following aspects:
440  *  - outputs definition and assignment is done in geometry instead of
441  *    vertex shader;
442  *  - vertex shader can be blank;
443  *  - use DrawArrays instead of DrawElements, draw single vertex with GL_POINTS.
444  *
445  *  Test the following output primitive types for geometry shader:
446  *  - points - emit vertices as in GL_POINTS case;
447  *  - line_strip - emit vertices as in GL_LINE_STRIP case;
448  *  - triangle_strip - emit vertices as in GL_TRIANGLE_STRIP case.
449  *
450  *  Number of components written by geometry shader must not exceed
451  *  MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS.
452  */
453 class CaptureGeometryInterleaved : virtual public CaptureVertexInterleaved
454 {
455 public:
456 	CaptureGeometryInterleaved(deqp::Context& context, const char* test_name, const char* test_description);
457 	~CaptureGeometryInterleaved(void);
458 	virtual IterateResult iterate(void);
459 
460 protected:
461 	virtual void fetchLimits(void);
462 	using CaptureVertexInterleaved::buildProgram;
463 	virtual void buildProgram(glw::GLuint primitive_case);
464 	virtual void draw(glw::GLuint primitive_case);
465 
466 	static const glw::GLchar* s_geometry_shader_source_code_template;
467 	static const glw::GLchar* s_blank_vertex_shader_source_code;
468 
469 	static const glw::GLchar* s_geometry_interleaved_primitive_cases[];
470 	static const glw::GLenum  s_geometry_interleaved_primitive_cases_xfb[];
471 	static const glw::GLuint  s_geometry_interleaved_primitive_cases_count;
472 };
473 
474 /** CaptureVertexSeparate
475  *
476  *  Verifies if geometry processed with vertex shader is captured as expected in
477  *  separate mode.
478  *
479  *  Test should be run if EXT_transform_feedback is supported or context is
480  *  at least 3.0.
481  *
482  *  Modify CaptureVertexInterleaved test in the following aspects:
483  *  - use transform feedback in separate mode.
484  *
485  *  Separate mode require one buffer per captured variable.
486  *
487  *  Number of attributes and components that can be captured is limited by:
488  *  - MAX TRANSFORM FEEDBACK SEPARATE ATTRIBS,
489  *  - MAX TRANSFORM FEEDBACK SEPARATE COMPONENTS.
490  */
491 class CaptureVertexSeparate : virtual public CaptureVertexInterleaved
492 {
493 public:
494 	CaptureVertexSeparate(deqp::Context& context, const char* test_name, const char* test_description);
495 
496 protected:
497 	glw::GLuint* m_buffers;
498 	glw::GLint   m_max_transform_feedback_separate_attribs;
499 
500 	virtual void fetchLimits(void);
501 	virtual void createTransformFeedbackBuffer(void);
502 	virtual void bindBuffer(BindBufferCase bind_case);
503 	virtual void cleanBuffer(void);
504 	virtual bool checkTransformFeedbackBuffer(BindBufferCase bind_case, glw::GLenum primitive_type);
505 };
506 
507 /** CaptureGeometrySeparate
508  *
509  *  Verifies if geometry processed with geometry shader is captured as expected
510  *  in separate mode.
511  *
512  *  Test should be run if either EXT_transform_feedback is supported or context
513  *  is at least 3.0 and either ARB_geometry_shader4 is supported or context is
514  *  at least 3.2.
515  *
516  *  Modify CaptureGeometryInterleaved test in the following aspects:
517  *  - use transform feedback in separate mode.
518  *
519  *  Separate mode require one buffer per captured variable.
520  *
521  *  Number of attributes and components that can be captured is limited by:
522  *  - MAX TRANSFORM FEEDBACK SEPARATE ATTRIBS,
523  *  - MAX TRANSFORM FEEDBACK SEPARATE COMPONENTS.
524  */
525 class CaptureGeometrySeparate : public CaptureGeometryInterleaved, virtual public CaptureVertexSeparate
526 {
527 public:
528 	CaptureGeometrySeparate(deqp::Context& context, const char* test_name, const char* test_description);
iterate(void)529 	virtual IterateResult iterate(void)
530 	{
531 		return CaptureGeometryInterleaved::iterate();
532 	};
533 
534 protected:
535 	glw::GLuint* m_buffers;
536 	glw::GLint   m_max_transform_feedback_separate_attribs;
537 
draw(glw::GLenum primitive_type)538 	virtual void draw(glw::GLenum primitive_type)
539 	{
540 		CaptureGeometryInterleaved::draw(primitive_type);
541 	};
fetchLimits(void)542 	virtual void fetchLimits(void)
543 	{
544 		CaptureVertexSeparate::fetchLimits();
545 	};
createTransformFeedbackBuffer(void)546 	virtual void createTransformFeedbackBuffer(void)
547 	{
548 		CaptureVertexSeparate::createTransformFeedbackBuffer();
549 	};
bindBuffer(BindBufferCase bind_case)550 	virtual void bindBuffer(BindBufferCase bind_case)
551 	{
552 		CaptureVertexSeparate::bindBuffer(bind_case);
553 	};
cleanBuffer(void)554 	virtual void cleanBuffer(void)
555 	{
556 		CaptureVertexSeparate::cleanBuffer();
557 	};
checkTransformFeedbackBuffer(BindBufferCase bind_case,glw::GLenum primitive_type)558 	virtual bool checkTransformFeedbackBuffer(BindBufferCase bind_case, glw::GLenum primitive_type)
559 	{
560 		return CaptureVertexSeparate::checkTransformFeedbackBuffer(bind_case, primitive_type);
561 	};
562 };
563 
564 /** GetXFBVaryingVertexInterleaved
565  *
566  *  Verifies if varyings captured from vertex stage are correctly reported in
567  *  interleaved mode.
568  *
569  *  Test should be run if EXT_transform_feedback is supported or context is
570  *  at least 3.0.
571  *
572  *  Steps:
573  *  - prepare program consisting of vertex and fragment shader; Vertex shader
574  *    should define and assign maximum allowed number of varyings of tested type;
575  *    Fragment shader can be blank;
576  *  - instruct implementation to capture all outputs defined by vertex shader;
577  *    Use interleaved mode;
578  *  - inspect all captured varying with GetTransformFeedbackVarying;
579  *  - inspect TRANSFORM_FEEDBACK_VARYINGS;
580  *  - inspect TRANSFORM_FEEDBACK_BUFFER_MODE;
581  *  - inspect TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH.
582  *
583  *  Test all valid types.
584  *
585  *
586  *  GetXFBVaryingGeometryInterleaved
587  *
588  *  Verifies if varyings captured from geometry stage are correctly reported in
589  *  interleaved mode.
590  *
591  *  Test should be run if either EXT_transform_feedback is supported or context
592  *  is at least 3.0 and either ARB_geometry_shader4 is supported or context is
593  *  at least 3.2.
594  *
595  *  Modify GetXFBVaryingVertexInterleaved test in the following aspects:
596  *  - outputs definition and assignment is done in geometry instead of
597  *    vertex shader;
598  *  - vertex shader can be blank;
599  *
600  *
601  *  GetXFBVaryingVertexSeparate
602  *
603  *  Verifies if varyings captured from vertex stage are correctly reported in
604  *  separate mode.
605  *
606  *  Test should be run if EXT_transform_feedback is supported or context is
607  *  at least 3.0.
608  *
609  *  Modify CaptureGeometryInterleaved test in the following aspects:
610  *  - use transform feedback in separate mode.
611  *
612  *  Separate mode require one buffer per captured variable.
613  *
614  *
615  *  GetXFBVaryingGeometrySeparate
616  *
617  *  Verifies if varyings captured from geometry stage are correctly reported in
618  *  separate mode.
619  *
620  *  Test should be run if either EXT_transform_feedback is supported or context
621  *  is at least 3.0 and either ARB_geometry_shader4 is supported or context is
622  *  at least 3.2.
623  *
624  *  Modify GetXFBVaryingGeometryInterleaved test in the following aspects:
625  *  - use transform feedback in separate mode.
626  *
627  *  Separate mode require one buffer per captured variable.
628  */
629 class CheckGetXFBVarying : public deqp::TestCase
630 {
631 public:
632 	CheckGetXFBVarying(deqp::Context& context, const char* test_name, const char* test_description);
633 	~CheckGetXFBVarying(void);
634 	virtual IterateResult iterate(void);
635 
636 private:
637 	deqp::Context& m_context;
638 	glw::GLint	 m_max_xfb_interleaved_components;
639 	glw::GLint	 m_max_xfb_separate_attributes;
640 	glw::GLint	 m_max_xfb_separate_components;
641 	glw::GLint	 m_max_varying_components;
642 	glw::GLint	 m_max_varying_vectors;
643 	glw::GLint	 m_max_geometry_total_output_components;
644 
645 	void		fetchLimits(void);
646 	glw::GLuint numberOfAttributes(glw::GLuint capture_way, glw::GLuint shader_case, glw::GLuint varying_type);
647 
648 	glw::GLuint buildProgram(glw::GLuint capture_way, glw::GLuint shader_case, glw::GLuint varying_type,
649 							 glw::GLuint number_of_attributes);
650 
651 	bool check(glw::GLuint program, glw::GLuint capture_way, glw::GLuint shader_case, glw::GLuint varying_type,
652 			   glw::GLuint number_of_attributes);
653 
654 	static const glw::GLchar* s_generic_fragment_shader;
655 
656 	static const struct ShaderCase
657 	{
658 		const glw::GLchar* vertex_shader;
659 		const glw::GLchar* geometry_shader;
660 	} s_shader_cases[];
661 
662 	static const glw::GLuint s_shader_cases_count;
663 
664 	static const struct VaryingType
665 	{
666 		const glw::GLenum  type;
667 		const glw::GLchar* name;
668 		const glw::GLuint  components_count;
669 		const bool		   float_component;
670 	} s_varying_types[];
671 
672 	static const glw::GLuint s_varying_types_count;
673 
674 	static const glw::GLenum s_capture_ways[];
675 	static const glw::GLuint s_capture_ways_count;
676 };
677 
678 /** QueryVertexInterleaved
679  *
680  *  Verifies if queries are performed as expected when geometry is captured from
681  *  vertex stage in interleaved mode.
682  *
683  *  Test should be run if EXT_transform_feedback is supported or context is
684  *  at least 3.0.
685  *
686  *  Modify CaptureVertexInterleaved test in the following aspects:
687  *  - buffer used as storage for captured geometry should be too small to fit
688  *    all emitted vertices;
689  *  - execute BeginQuery for PRIMITIVES_GENERATED and
690  *    TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN before draw is executed; End queries
691  *    after draw call.
692  *
693  *  Test pass if results of queries are correct.
694  */
695 class QueryVertexInterleaved : public CaptureVertexInterleaved
696 {
697 public:
698 	QueryVertexInterleaved(deqp::Context& context, const char* test_name, const char* test_description);
699 
700 protected:
701 	glw::GLuint m_query_object;
702 
703 	virtual void createTransformFeedbackBuffer(void);
704 	virtual void draw(glw::GLuint primitive_case);
705 	virtual bool checkTransformFeedbackBuffer(BindBufferCase bind_case, glw::GLenum primitive_type);
706 	virtual void clean(void);
707 };
708 
709 /** QueryGeometryInterleaved
710  *
711  *  Verifies if queries are performed as expected when geometry is captured from
712  *  geometry stage in interleaved mode.
713  *
714  *  Test should be run if either EXT_transform_feedback is supported or context
715  *  is at least 3.0 and either ARB_geometry_shader4 is supported or context is
716  *  at least 3.2.
717  *
718  *  Modify CaptureGeometryInterleaved test in the following aspects:
719  *  - buffer used as storage for captured geometry should be too small to fit
720  *    all emitted vertices;
721  *  - execute BeginQuery for PRIMITIVES_GENERATED and
722  *    TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN before draw is executed; End queries
723  *    after draw call.
724  *
725  *  Test pass if results of queries are correct.
726  */
727 class QueryGeometryInterleaved : public CaptureGeometryInterleaved
728 {
729 public:
730 	QueryGeometryInterleaved(deqp::Context& context, const char* test_name, const char* test_description);
731 
732 protected:
733 	glw::GLuint m_query_object;
734 
735 	virtual void createTransformFeedbackBuffer(void);
736 	virtual void draw(glw::GLuint primitive_case);
737 	virtual bool checkTransformFeedbackBuffer(BindBufferCase bind_case, glw::GLenum primitive_type);
738 	virtual void clean(void);
739 };
740 
741 /** QueryVertexSeparate
742  *
743  *  Verifies if queries are performed as expected when geometry is captured from
744  *  vertex stage in separate mode.
745  *
746  *  Test should be run if EXT_transform_feedback is supported or context is
747  *  at least 3.0.
748  *
749  *  Modify CaptureVertexSeparate test in the following aspects:
750  *  - buffers used as storage for captured geometry should be too small to fit
751  *    all emitted vertices;
752  *  - execute BeginQuery for PRIMITIVES_GENERATED and
753  *    TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN before draw is executed; End queries
754  *    after draw call;
755  *  - use transform feedback in separate mode.
756  *
757  *  Separate mode require one buffer per captured variable.
758  *
759  *  Test pass if results of queries are correct.
760  */
761 class QueryVertexSeparate : public CaptureVertexSeparate
762 {
763 public:
764 	QueryVertexSeparate(deqp::Context& context, const char* test_name, const char* test_description);
765 
766 protected:
767 	glw::GLuint m_query_object;
768 
769 	virtual void createTransformFeedbackBuffer(void);
770 	virtual void draw(glw::GLuint primitive_case);
771 	virtual bool checkTransformFeedbackBuffer(BindBufferCase bind_case, glw::GLenum primitive_type);
772 	virtual void clean(void);
773 };
774 
775 /** QueryGeometrySeparate
776  *
777  *  Verifies if queries are performed as expected when geometry is captured from
778  *  geometry stage in separate mode.
779  *
780  *  Test should be run if either EXT_transform_feedback is supported or context
781  *  is at least 3.0 and either ARB_geometry_shader4 is supported or context is
782  *  at least 3.2.
783  *
784  *  Modify CaptureGeometrySeparate test in the following aspects:
785  *  - buffers used as storage for captured geometry should be too small to fit
786  *    all emitted vertices;
787  *  - execute BeginQuery for PRIMITIVES_GENERATED and
788  *    TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN before draw is executed; End queries
789  *    after draw call;
790  *  - use transform feedback in separate mode.
791  *
792  *  Separate mode require one buffer per captured variable.
793  *
794  *  Test pass if results of queries are correct.
795  */
796 class QueryGeometrySeparate : public CaptureGeometrySeparate
797 {
798 public:
799 	QueryGeometrySeparate(deqp::Context& context, const char* test_name, const char* test_description);
800 
801 protected:
802 	glw::GLuint m_query_object;
803 
804 	virtual void createTransformFeedbackBuffer(void);
805 	virtual void draw(glw::GLuint primitive_case);
806 	virtual bool checkTransformFeedbackBuffer(BindBufferCase bind_case, glw::GLenum primitive_type);
807 	virtual void clean(void);
808 };
809 
810 /** DiscardVertex
811  *
812  *  Verifies if rasterization is discarded when geometry is captured from vertex
813  *  stage.
814  *
815  *  Test should be run if EXT_transform_feedback is supported or context is
816  *  at least 3.0.
817  *
818  *  Modify CaptureVertexInterleaved test in the following aspects:
819  *  - disable rasterization before draw call;
820  *  - it is expected that framebuffer contents will not change, while XFB buffer
821  *  is modified.
822  */
823 class DiscardVertex : public CaptureVertexInterleaved
824 {
825 public:
826 	DiscardVertex(deqp::Context& context, const char* test_name, const char* test_description);
827 
828 protected:
829 	virtual void draw(glw::GLuint primitive_case);
830 	virtual bool checkFramebuffer(glw::GLuint primitive_case);
831 };
832 
833 /** DiscardGeometry
834  *
835  *  Verifies if rasterization is discarded when geometry is captured from
836  *  geometry stage.
837  *
838  *  Test should be run if EXT_transform_feedback is supported or context is at least 3.0.
839  *  Test should be run if ARB_geometry_shader4 is supported or context is at least 3.2.
840  *
841  *  Modify CaptureGeometryInterleaved test in the following aspects:
842  *  - disable rasterization before draw call;
843  *  - it is expected that framebuffer contents will not change, while XFB buffer
844  *    is modified.
845  */
846 class DiscardGeometry : public CaptureGeometryInterleaved
847 {
848 public:
849 	DiscardGeometry(deqp::Context& context, const char* test_name, const char* test_description);
850 
851 protected:
852 	virtual void draw(glw::GLuint primitive_case);
853 	virtual bool checkFramebuffer(glw::GLuint primitive_case);
854 };
855 
856 /** DrawXFB
857  *
858  *  Verifies that transform feedback objects can be used to draw.
859  *
860  *  Test should be executed if ARB_transform_feedback2 is supported or context
861  *  is at least 4.0.
862  *
863  *  Steps:
864  *  - prepare two programs consisting of vertex shader which will:
865  *     * output position based on gl_VertexID:
866  *     * output color by passing value of uniform;
867  *    First program should use the following positions:
868  *     ID |  X |  Y
869  *      0 | -1 | -1
870  *      1 | -1 |  1
871  *      2 |  1 |  1
872  *    Second program should use the following positions:
873  *      0 | -1 | -1
874  *      1 |  1 |  1
875  *      2 |  1 | -1
876  *  - prepare three XFB objects and corresponding buffers for captured geometry;
877  *    Each XFB should capture position and color from both programs;
878  *  - activate first program;
879  *  - for each XFB object:
880  *     * set uniform to color corresponding with XFB;
881  *     * activate XFB;
882  *     * execute DrawArrays to draw three points starting at 0;
883  *     * pause XFB;
884  *  - inspect TRANSFORM_FEEDBACK_BUFFER_PAUSED and
885  *    TRANSFORM_FEEDBACK_BUFFER_ACTIVE;
886  *  - activate second program;
887  *  - for each XFB object:
888  *     * set uniform to color corresponding with XFB;
889  *     * resume XFB;
890  *     * execute DrawArrays to draw three points starting at 0;
891  *     * end XFB;
892  *  - inspect TRANSFORM_FEEDBACK_BUFFER_PAUSED and
893  *    TRANSFORM_FEEDBACK_BUFFER_ACTIVE;
894  *  - prepare program consisting of vertex and fragment stage; Vertex shader
895  *    should pass position and color; Fragment stage should pass color;
896  *  - set program;
897  *  - set vertex array to match layout of XFB;
898  *  - for each XFB:
899  *     * prepare and clean framebuffer;
900  *     * execute DrawTransformFeedback to draw triangles;
901  *     * inspect contents of framebuffer;
902  *
903  *  It is expected that drawn images will be filled with color set via uniform
904  *  variables.
905  *
906  *  Repeat steps for both interleaved and separate modes.
907  */
908 class DrawXFB : public deqp::TestCase
909 {
910 public:
911 	DrawXFB(deqp::Context& context, const char* test_name, const char* test_description);
912 	~DrawXFB(void);
913 	virtual IterateResult iterate(void);
914 
915 protected:
916 	static const glw::GLchar* s_vertex_shader_xfb;
917 	static const glw::GLchar* s_vertex_shader_draw;
918 	static const glw::GLchar* s_fragment_shader;
919 
920 	static const glw::GLuint  s_xfb_varyings_count = 2;
921 	static const glw::GLchar* s_xfb_varyings[s_xfb_varyings_count];
922 	static const glw::GLuint  s_vertex_count = 3;
923 	static const glw::GLenum  s_capture_modes[];
924 	static const glw::GLuint  s_capture_modes_count;
925 	static const glw::GLuint  s_capture_size = s_vertex_count * sizeof(glw::GLfloat) * 4 /* number of components */ *
926 											  s_xfb_varyings_count * 2 /* number of programs */;
927 	static const glw::GLuint  s_view_size = 2;
928 	static const glw::GLuint  s_xfb_count = 3;
929 	static const glw::GLfloat s_colours[s_xfb_count][4];
930 
931 	deqp::Context& m_context;
932 	glw::GLuint	m_program_id_xfb;
933 	glw::GLuint	m_program_id_draw;
934 	glw::GLuint	m_xfb_id[s_xfb_count];
935 	glw::GLuint	m_bo_id[s_xfb_count];
936 	glw::GLuint	m_fbo_id;
937 	glw::GLuint	m_rbo_id;
938 	glw::GLuint	m_vao_id;
939 
940 	void prepare(glw::GLenum capture_mode);
941 	void bindXFB(glw::GLuint xfb_id);
942 	void bindVAO(glw::GLuint vao_id);
943 	void bindBOForXFB(glw::GLenum capture_mode, glw::GLuint bo_id);
944 	void bindBOForDraw(glw::GLuint program_id, glw::GLenum capture_mode, glw::GLuint bo_id);
945 	void useProgram(glw::GLuint program_id);
946 	void useColour(glw::GLuint program_id, glw::GLfloat r, glw::GLfloat g, glw::GLfloat b, glw::GLfloat a);
947 	void useGeometrySet(glw::GLuint program_id, bool invert_sign);
948 	void drawForCapture(bool begin_xfb, bool pause_xfb, bool resume_xfb, bool end_xfb);
949 	void drawToFramebuffer(glw::GLuint xfb_id);
950 	bool checkFramebuffer(glw::GLfloat r, glw::GLfloat g, glw::GLfloat b, glw::GLfloat a);
951 	bool inspectXFBState(bool shall_be_paused, bool shall_be_active);
952 	void clean();
953 };
954 
955 /** DrawXFBFeedback
956  *
957  *  Verifies that data captured with XFB can be used as source for next capture.
958  *
959  *  Test should be executed if ARB_transform_feedback2 is supported or context
960  *  is at least 4.0.
961  *
962  *  Steps:
963  *  - prepare program consisting of vertex shader which pass position from input
964  *    attribute to gl_Position multiplying it by 2.0;
965  *  - instruct implementation to capture geometry in interleaved mode;
966  *  - prepare source buffer;
967  *  - prepare buffer to capture geometry;
968  *  - begin transform feedback;
969  *  - draw one vertex using DrawArrays;
970  *  - end transform feedback;
971  *  - swap buffer
972  *  - begin transform feedback;
973  *  - draw using DrawTransformFeedback;
974  *  - end transform feedback;
975  *  - swap buffer
976  *  - begin transform feedback;
977  *  - draw using DrawTransformFeedback;
978  *  - end transform feedback;
979  *  - map last captured buffer, expect position vector multiplied by value 8;
980  */
981 class DrawXFBFeedback : public deqp::TestCase
982 {
983 public:
984 	DrawXFBFeedback(deqp::Context& context, const char* test_name, const char* test_description);
985 	~DrawXFBFeedback(void);
986 	virtual IterateResult iterate(void);
987 
988 protected:
989 	static const glw::GLchar* s_vertex_shader;
990 	static const glw::GLchar* s_fragment_shader;
991 	static const glw::GLchar* s_xfb_varying;
992 	static const glw::GLchar* s_attrib;
993 	static const glw::GLuint  s_draw_vertex_count;
994 	static const glw::GLfloat s_initial_data[];
995 	static const glw::GLuint  s_bo_count = 2;
996 	static const glw::GLuint  s_bo_size;
997 
998 	deqp::Context& m_context;
999 	glw::GLuint	m_program_id;
1000 	glw::GLuint	m_vao_id[s_bo_count];
1001 	glw::GLuint	m_xfb_id;
1002 	glw::GLuint	m_bo_id[s_bo_count];
1003 	glw::GLuint	m_source_bo_index;
1004 
1005 	void prepareAndBind();
1006 	void draw(bool is_first_draw);
1007 	void swapBuffers();
1008 	bool check();
1009 	void clean();
1010 };
1011 
1012 /** DrawXFBStream
1013  *
1014  *  Verifies that vertex stream captured with transform feedback can be used to
1015  *  draw.
1016  *
1017  *  Test should be executed if both ARB_transform_feedback3 and ARB_gpu_shader5
1018  *  are supported or context is at least 4.0.
1019  *  This test is not supported if MAX_VERTEX_STREAMS is less than 2.
1020  *
1021  *  Steps:
1022  *  - prepare program consisting of vertex and geometry shaders; Geometry shader
1023  *    should output full-screen quad made of two triangles; First triangle should
1024  *    be emitted to first vertex stream; Second triangle should be emitted to the
1025  *    second vertex stream; Vertex shader can be blank;
1026  *  - prepare buffers to capture geometry;
1027  *  - instruct implementation to capture geometry in interleaved mode;
1028  *  - begin XFB;
1029  *  - begin indexed query for PRIMITIVES_GENERATED and
1030  *    TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN for both vertex streams;
1031  *  - draw single vertex;
1032  *  - end queries;
1033  *  - end XFB;
1034  *  - inspect results of queries;
1035  *  - prepare program consisting of vertex and fragment shaders; Vertex stage
1036  *    should pass position from input to output; Fragment shader should output
1037  *    white color;
1038  *  - prepare and clean framebuffer;
1039  *  - set vertex array layout to match data captured by XFB;
1040  *  - execute DrawTransformFeedbackStream to draw triangle from first stream;
1041  *  - execute DrawTransformFeedbackStream to draw triangle from second stream;
1042  *  - inspect contents of framebuffer, it is expected to be filled with white
1043  *    color.
1044  */
1045 class DrawXFBStream : public deqp::TestCase
1046 {
1047 public:
1048 	DrawXFBStream(deqp::Context& context, const char* test_name, const char* test_description);
1049 	~DrawXFBStream(void);
1050 	virtual IterateResult iterate(void);
1051 
1052 private:
1053 	static const glw::GLchar* s_vertex_shader_pass;
1054 	static const glw::GLchar* s_vertex_shader_blank;
1055 	static const glw::GLchar* s_geometry_shader;
1056 	static const glw::GLchar* s_fragment_shader;
1057 	static const glw::GLchar* s_xfb_varyings[];
1058 	static const glw::GLuint  s_xfb_varyings_count;
1059 	static const glw::GLuint  s_bo_ids_count = 2;
1060 	static const glw::GLuint  s_qo_ids_count = 4;
1061 	static const glw::GLuint  s_bo_size;
1062 	static const glw::GLuint  s_view_size;
1063 
1064 	deqp::Context& m_context;
1065 	glw::GLuint	m_program_id_generate;
1066 	glw::GLuint	m_program_id_draw;
1067 	glw::GLuint	m_vao_id;
1068 	glw::GLuint	m_xfb_id;
1069 	glw::GLuint	m_bo_id[s_bo_ids_count];
1070 	glw::GLuint	m_fbo_id;
1071 	glw::GLuint	m_rbo_id;
1072 	glw::GLuint	m_qo_id[s_qo_ids_count];
1073 
1074 	void prepareObjects();
1075 	void setupVertexArray(glw::GLuint bo_id);
1076 	void useProgram(glw::GLuint program_id);
1077 	void drawForXFB();
1078 	bool inspectQueries();
1079 	void drawForFramebuffer(glw::GLuint stream);
1080 	bool check();
1081 	void clean();
1082 };
1083 
1084 /** CaptureSpecialInterleaved
1085  *
1086  *  Verifies that special variable names are respected.
1087  *
1088  *  Test should be executed if ARB_transform_feedback3 is supported or context
1089  *  is at least 4.0.
1090  *
1091  *  Steps:
1092  *  - prepare program consisting of vertex shader which outputs four variables;
1093  *  - set up XFB to capture the following <varyings>:
1094  *    * variable_1,
1095  *    * gl_SkipComponents4,
1096  *    * variable_2,
1097  *    * gl_NextBuffer,
1098  *    * variable_3,
1099  *    * gl_SkipComponents4,
1100  *    * variable_4;
1101  *  - begin XFB;
1102  *  - draw two vertices;
1103  *  - end XFB;
1104  *  - verify that captured geometry is correct.
1105  */
1106 class CaptureSpecialInterleaved : public deqp::TestCase
1107 {
1108 public:
1109 	CaptureSpecialInterleaved(deqp::Context& context, const char* test_name, const char* test_description);
1110 	~CaptureSpecialInterleaved(void);
1111 	virtual IterateResult iterate(void);
1112 
1113 private:
1114 	static const glw::GLchar* s_vertex_shader;
1115 	static const glw::GLchar* s_fragment_shader;
1116 	static const glw::GLchar* s_xfb_varyings[];
1117 	static const glw::GLuint  s_xfb_varyings_count;
1118 	static const glw::GLuint  s_bo_ids_count = 2;
1119 	static const glw::GLuint  s_bo_size;
1120 
1121 	deqp::Context& m_context;
1122 	glw::GLuint	m_program_id;
1123 	glw::GLuint	m_vao_id;
1124 	glw::GLuint	m_xfb_id;
1125 	glw::GLuint	m_bo_id[s_bo_ids_count];
1126 
1127 	void prepareAndBind();
1128 	void draw();
1129 	bool check();
1130 	void clean();
1131 };
1132 
1133 /** DrawXFBInstanced
1134  *
1135  *  Verifies that transform feedback objects can used with instanced draws.
1136  *
1137  *  Test should be executed if context is at least 3.1 and either
1138  *  ARB_transform_feedback_instanced is supported or context is at least 4.2.
1139  *
1140  *  Steps:
1141  *  - prepare program consisting of vertex shader which outputs positions of
1142  *    full-screen quad made of triangle strip based on gl_VertexID;
1143  *  - instruct implementation to capture geometry in interleaved mode;
1144  *  - prepare buffer to capture geometry;
1145  *  - begin transform feedback;
1146  *  - draw four vertices;
1147  *  - end transform feedback;
1148  *  - prepare program consisting of vertex and fragment shaders; Vertex stage
1149  *    should calculate position as follows:
1150  *
1151  *    gl_Position = in_position * uni_matrices[gl_InstanceID];
1152  *
1153  *  Fragment shader should output white color;
1154  *  - prepare UNIFORM_BUFFER filled with four mat4; Select data so matrices
1155  *    transforms quad [-1, -1] : [1, 1] as follows:
1156  *    * 0 - [-1,  0] : [0, 1] - left top,
1157  *    * 1 - [ 0,  0] : [1, 1] - right top,
1158  *    * 2 - [-1, -1] : [0, 0] - left bottom,
1159  *    * 3 - [ 0, -1] : [1, 0] - right bottom;
1160  *  - prepare and clean framebuffer;
1161  *  - set up layout of vertex data in XFB;
1162  *  - execute DrawTransformFeedbackInstanced to draw four instances of quad from XFB;
1163  *  - it is expected that framebuffer is filled with white color;
1164  */
1165 class DrawXFBInstanced : public deqp::TestCase
1166 {
1167 public:
1168 	DrawXFBInstanced(deqp::Context& context, const char* test_name, const char* test_description);
1169 	~DrawXFBInstanced(void);
1170 	virtual IterateResult iterate(void);
1171 
1172 private:
1173 	static const glw::GLchar* s_vertex_shader_generate;
1174 	static const glw::GLchar* s_vertex_shader_draw;
1175 	static const glw::GLchar* s_fragment_shader;
1176 	static const glw::GLchar* s_xfb_varying;
1177 	static const glw::GLchar* s_uniform;
1178 	static const glw::GLuint  s_bo_xfb_size;
1179 	static const glw::GLfloat s_bo_uniform_data[];
1180 	static const glw::GLuint  s_bo_uniform_size;
1181 	static const glw::GLuint  s_view_size;
1182 
1183 	deqp::Context& m_context;
1184 	glw::GLuint	m_program_id_generate;
1185 	glw::GLuint	m_program_id_draw;
1186 	glw::GLuint	m_vao_id;
1187 	glw::GLuint	m_xfb_id;
1188 	glw::GLuint	m_bo_id_xfb;
1189 	glw::GLuint	m_bo_id_uniform;
1190 	glw::GLuint	m_fbo_id;
1191 	glw::GLuint	m_rbo_id;
1192 
1193 	void prepareObjects();
1194 	void drawForXFB();
1195 	void drawInstanced();
1196 	bool check();
1197 	void clean();
1198 
1199 	typedef GLW_APICALL glw::GLuint (GLW_APIENTRY *GetUniformBlockIndex_ProcAddress)(glw::GLuint program, const glw::GLchar* uniformBlockName);
1200 	typedef GLW_APICALL void        (GLW_APIENTRY *UniformBlockBinding_ProcAddress)(glw::GLuint program,
1201 																					glw::GLuint uniformIndex,
1202 																					glw::GLuint uniformBlockBinding);
1203 
1204 	GetUniformBlockIndex_ProcAddress m_glGetUniformBlockIndex;
1205 	UniformBlockBinding_ProcAddress  m_glUniformBlockBinding;
1206 };
1207 
1208 /** DrawXFBStreamInstanced
1209  *
1210  *  Verifies that transform feedback objects can used with instanced draws.
1211  *
1212  *  Test should be executed if context is at least 3.1 and either
1213  *  ARB_gpu_shader5 is supported or context is at least 4.0 and either
1214  *  ARB_transform_feedback_instanced is supported or context is at least 4.2.
1215  *
1216  *  Steps:
1217  *  - prepare program consisting of vertex shader which based on gl_VertexID
1218  *    outputs:
1219  *     * to stream 0 - color,
1220  *     * to stream 1 - positions
1221  *    for a full-screen quad made of triangle strip;
1222  *  - instruct implementation to capture geometry in interleaved mode;
1223  *  - prepare buffers to capture geometry;
1224  *  - begin transform feedback;
1225  *  - draw four vertices;
1226  *  - end transform feedback;
1227  *  - prepare program consisting of vertex and fragment shaders; Vertex stage
1228  *    should calculate position as follows:
1229  *
1230  *      gl_Position = in_position * uni_matrices[gl_InstanceID];
1231  *
1232  *  Fragment shader should output white color;
1233  *  - prepare UNIFORM_BUFFER filled with four mat4; Select data so matrices
1234  *    transforms quad [-1, -1] : [1, 1] as follows:
1235  *     * 0 - [-1,  0] : [0, 1] - left top,
1236  *     * 1 - [ 0,  0] : [1, 1] - right top,
1237  *     * 2 - [-1, -1] : [0, 0] - left bottom,
1238  *     * 3 - [ 0, -1] : [1, 0] - right bottom;
1239  *  - prepare and clean framebuffer;
1240  *  - set up layout of vertex data in XFB;
1241  *  - execute DrawTransformFeedbackStreamInstanced to draw four instances of
1242  *    quad from XFB, stream 1;
1243  *  - it is expected that framebuffer is filled with white color;
1244  */
1245 class DrawXFBStreamInstanced : public deqp::TestCase
1246 {
1247 public:
1248 	DrawXFBStreamInstanced(deqp::Context& context, const char* test_name, const char* test_description);
1249 	~DrawXFBStreamInstanced(void);
1250 	virtual IterateResult iterate(void);
1251 
1252 private:
1253 	static const glw::GLchar* s_vertex_shader_blank;
1254 	static const glw::GLchar* s_geometry_shader_generate;
1255 	static const glw::GLchar* s_vertex_shader_draw;
1256 	static const glw::GLchar* s_fragment_shader_blank;
1257 	static const glw::GLchar* s_fragment_shader_draw;
1258 	static const glw::GLchar* s_xfb_varyings[];
1259 	static const glw::GLuint  s_xfb_varyings_count;
1260 	static const glw::GLchar* s_uniform;
1261 	static const glw::GLuint  s_bo_xfb_size;
1262 	static const glw::GLfloat s_bo_uniform_data[];
1263 	static const glw::GLuint  s_bo_uniform_size;
1264 	static const glw::GLuint  s_view_size;
1265 
1266 	deqp::Context& m_context;
1267 	glw::GLuint	m_program_id_generate;
1268 	glw::GLuint	m_program_id_draw;
1269 	glw::GLuint	m_vao_id;
1270 	glw::GLuint	m_xfb_id;
1271 	glw::GLuint	m_bo_id_xfb_position;
1272 	glw::GLuint	m_bo_id_xfb_color;
1273 	glw::GLuint	m_bo_id_uniform;
1274 	glw::GLuint	m_fbo_id;
1275 	glw::GLuint	m_rbo_id;
1276 
1277 	void prepareObjects();
1278 	void drawForXFB();
1279 	void drawStreamInstanced();
1280 	bool check();
1281 	void clean();
1282 
1283 	typedef GLW_APICALL glw::GLuint (GLW_APIENTRY *GetUniformBlockIndex_ProcAddress)(glw::GLuint program, const glw::GLchar* uniformBlockName);
1284 	typedef GLW_APICALL void        (GLW_APIENTRY *UniformBlockBinding_ProcAddress)(glw::GLuint program,
1285 																					glw::GLuint uniformIndex,
1286 																					glw::GLuint uniformBlockBinding);
1287 
1288 	GetUniformBlockIndex_ProcAddress m_glGetUniformBlockIndex;
1289 	UniformBlockBinding_ProcAddress  m_glUniformBlockBinding;
1290 };
1291 
1292 namespace Utilities
1293 {
1294 /** Build a GLSL program
1295  *
1296  *  @param [in]  gl                                     OpenGL Functions Access.
1297  *  @param [in]  log                                    Log outut.
1298  *  @param [in]  geometry_shader_source                 Pointer to C string of the geometry shader or NULL if not used.
1299  *  @param [in]  tessellation_control_shader_source     Pointer to C string of the tessellation control shader or NULL if not used.
1300  *  @param [in]  tessellation_evaluation_shader_source  Pointer to C string of the tessellation evaluation shader or NULL if not used.
1301  *  @param [in]  vertex_shader_source                   Pointer to C string of the vertex shader or NULL if not used.
1302  *  @param [in]  geometry_shader_source                 Pointer to C string of the fragment shader or NULL if not used.
1303  *  @param [in]  transform_feedback_varyings            C array of transform feedback varyings names.
1304  *  @param [in]  transform_feedback_varyings_count      Count of transform feedback varyings names.
1305  *  @param [in]  transform_feedback_varyings_mode       Transform feedback capture mode - GL_SEPARATE_ATTRIBS or GL_INTERLEAVED_ATTRIBS.
1306  *  @param [in]  do_not_detach                          Do not detach shaders - default is faulse.
1307  *  @param [out] linking_status                         Return pointer to store linking status or NULL if not needed.
1308  *
1309  *  @return OpenGL program shader ID or zero if error had occured.
1310  */
1311 glw::GLuint buildProgram(glw::Functions const& gl, tcu::TestLog& log, glw::GLchar const* const geometry_shader_source,
1312 						 glw::GLchar const* const tessellation_control_shader_source,
1313 						 glw::GLchar const* const tessellation_evaluation_shader_source,
1314 						 glw::GLchar const* const vertex_shader_source, glw::GLchar const* const fragment_shader_source,
1315 						 glw::GLchar const* const* const transform_feedback_varyings,
1316 						 glw::GLsizei const				 transform_feedback_varyings_count,
1317 						 glw::GLenum const transform_feedback_varyings_mode, bool const do_not_detach = false,
1318 						 glw::GLint* linking_status = DE_NULL);
1319 
1320 /** Preprocess source string by replacing key tokens with new values.
1321  *
1322  *  @param [in] source      Source string.
1323  *  @param [in] key         Key, substring to be replaced.
1324  *  @param [in] value       Value, substring to be substituted in place of key.
1325  *
1326  *  @return Preprocessed string.
1327  */
1328 std::string preprocessCode(std::string source, std::string key, std::string value);
1329 
1330 /** Change integer number to string
1331  *
1332  *  @param [in] i       Integer number.
1333  *
1334  *  @return String represnting integer number.
1335  */
1336 std::string itoa(glw::GLint i);
1337 
1338 /** Change floating point number to string
1339  *
1340  *  @param [in] f       Floating point number.
1341  *
1342  *  @return String represnting floating point number.
1343  */
1344 std::string ftoa(glw::GLfloat f);
1345 } /* Utilities namespace */
1346 } /* TransformFeedback namespace */
1347 
1348 } /* gl3cts namespace */
1349 
1350 #endif // _GL3CTRANSFORMFEEDBACKTESTS_HPP
1351