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