Merge "Fix extension support checks in negative api tests" into nougat-cts-dev am...
[platform/upstream/VK-GL-CTS.git] / modules / gles3 / functional / es3fImplementationLimitTests.cpp
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES 3.0 Module
3  * -------------------------------------------------
4  *
5  * Copyright 2014 The Android Open Source Project
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Implementation-defined limit tests.
22  *//*--------------------------------------------------------------------*/
23
24 #include "es3fImplementationLimitTests.hpp"
25 #include "tcuTestLog.hpp"
26 #include "gluDefs.hpp"
27 #include "gluStrUtil.hpp"
28 #include "gluRenderContext.hpp"
29
30 #include <vector>
31 #include <set>
32 #include <algorithm>
33 #include <iterator>
34 #include <limits>
35
36 #include "glwEnums.hpp"
37 #include "glwFunctions.hpp"
38
39 namespace deqp
40 {
41 namespace gles3
42 {
43 namespace Functional
44 {
45
46 using std::vector;
47 using std::string;
48 using std::set;
49 using namespace glw; // GL types
50
51 namespace LimitQuery
52 {
53
54 // Query function template.
55 template<typename T>
56 T query (const glw::Functions& gl, deUint32 param);
57
58 // Compare template.
59 template<typename T>
60 inline bool compare (const T& min, const T& reported) { return min <= reported; }
61
62 // Types for queries
63
64 struct NegInt
65 {
66         GLint value;
67         NegInt (GLint value_) : value(value_) {}
68 };
69
70 std::ostream& operator<< (std::ostream& str, const NegInt& v) { return str << v.value; }
71
72 struct FloatRange
73 {
74         float min;
75         float max;
76         FloatRange (float min_, float max_) : min(min_), max(max_) {}
77 };
78
79 std::ostream& operator<< (std::ostream& str, const FloatRange& range) { return str << range.min << ", " << range.max; }
80
81 struct AlignmentInt
82 {
83         GLint value;
84         AlignmentInt (GLint value_) : value(value_) {}
85 };
86
87 std::ostream& operator<< (std::ostream& str, const AlignmentInt& v) { return str << v.value; }
88
89 // For custom formatting
90 struct Boolean
91 {
92         GLboolean value;
93         Boolean (GLboolean value_) : value(value_) {}
94 };
95
96 std::ostream& operator<< (std::ostream& str, const Boolean& boolean) { return str << (boolean.value ? "GL_TRUE" : "GL_FALSE"); }
97
98 // Query function implementations.
99 template<>
100 GLint query<GLint> (const glw::Functions& gl, deUint32 param)
101 {
102         GLint val = -1;
103         gl.getIntegerv(param, &val);
104         return val;
105 }
106
107 template<>
108 GLint64 query<GLint64> (const glw::Functions& gl, deUint32 param)
109 {
110         GLint64 val = -1;
111         gl.getInteger64v(param, &val);
112         return val;
113 }
114
115 template<>
116 GLuint64 query<GLuint64> (const glw::Functions& gl, deUint32 param)
117 {
118         GLint64 val = 0;
119         gl.getInteger64v(param, &val);
120         return (GLuint64)val;
121 }
122
123 template<>
124 GLfloat query<GLfloat> (const glw::Functions& gl,deUint32 param)
125 {
126         GLfloat val = -1000.f;
127         gl.getFloatv(param, &val);
128         return val;
129 }
130
131 template<>
132 NegInt query<NegInt> (const glw::Functions& gl, deUint32 param)
133 {
134         return NegInt(query<GLint>(gl, param));
135 }
136
137 template<>
138 Boolean query<Boolean> (const glw::Functions& gl, deUint32 param)
139 {
140         GLboolean val = GL_FALSE;
141         gl.getBooleanv(param, &val);
142         return Boolean(val);
143 }
144
145 template<>
146 FloatRange query<FloatRange> (const glw::Functions& gl, deUint32 param)
147 {
148         float v[2] = { -1.0f, -1.0f };
149         gl.getFloatv(param, &v[0]);
150         return FloatRange(v[0], v[1]);
151 }
152
153 template<>
154 AlignmentInt query<AlignmentInt> (const glw::Functions& gl, deUint32 param)
155 {
156         return AlignmentInt(query<GLint>(gl, param));
157 }
158
159 // Special comparison operators
160 template<>
161 bool compare<Boolean> (const Boolean& min, const Boolean& reported)
162 {
163         return !min.value || (min.value && reported.value);
164 }
165
166 template<>
167 bool compare<NegInt> (const NegInt& min, const NegInt& reported)
168 {
169         // Reverse comparison.
170         return reported.value <= min.value;
171 }
172
173 template<>
174 bool compare<FloatRange> (const FloatRange& min, const FloatRange& reported)
175 {
176         return reported.min <= min.min && min.max <= reported.max;
177 }
178
179 template<>
180 bool compare<AlignmentInt> (const AlignmentInt& min, const AlignmentInt& reported)
181 {
182         // Reverse comparison.
183         return reported.value <= min.value;
184 }
185
186 // Special error descriptions
187
188 enum QueryClass
189 {
190         CLASS_VALUE = 0,
191         CLASS_RANGE,
192         CLASS_ALIGNMENT,
193 };
194
195 template <QueryClass Class>
196 struct QueryClassTraits
197 {
198         static const char* const s_errorDescription;
199 };
200
201 template <>
202 const char* const QueryClassTraits<CLASS_VALUE>::s_errorDescription = "reported value is less than minimum required value!";
203
204 template <>
205 const char* const QueryClassTraits<CLASS_RANGE>::s_errorDescription = "reported range does not contain the minimum required range!";
206
207 template <>
208 const char* const QueryClassTraits<CLASS_ALIGNMENT>::s_errorDescription = "reported alignment is larger than minimum required aligmnent!";
209
210 template <typename T>
211 struct QueryTypeTraits
212 {
213 };
214
215 template <> struct QueryTypeTraits<GLint>                       {       enum { CLASS = CLASS_VALUE };           };
216 template <> struct QueryTypeTraits<GLint64>                     {       enum { CLASS = CLASS_VALUE };           };
217 template <> struct QueryTypeTraits<GLuint64>            {       enum { CLASS = CLASS_VALUE };           };
218 template <> struct QueryTypeTraits<GLfloat>                     {       enum { CLASS = CLASS_VALUE };           };
219 template <> struct QueryTypeTraits<Boolean>                     {       enum { CLASS = CLASS_VALUE };           };
220 template <> struct QueryTypeTraits<NegInt>                      {       enum { CLASS = CLASS_VALUE };           };
221 template <> struct QueryTypeTraits<FloatRange>          {       enum { CLASS = CLASS_RANGE };           };
222 template <> struct QueryTypeTraits<AlignmentInt>        {       enum { CLASS = CLASS_ALIGNMENT };       };
223
224 } // LimitQuery
225
226 using namespace LimitQuery;
227 using tcu::TestLog;
228
229 template<typename T>
230 class LimitQueryCase : public TestCase
231 {
232 public:
233         LimitQueryCase (Context& context, const char* name, const char* description, deUint32 limit, const T& minRequiredValue)
234                 : TestCase                              (context, name, description)
235                 , m_limit                               (limit)
236                 , m_minRequiredValue    (minRequiredValue)
237         {
238         }
239
240         IterateResult iterate (void)
241         {
242                 const glw::Functions&   gl              = m_context.getRenderContext().getFunctions();
243                 const T                                 value   = query<T>(m_context.getRenderContext().getFunctions(), m_limit);
244                 GLU_EXPECT_NO_ERROR(gl.getError(), "Query failed");
245
246                 const bool isOk = compare<T>(m_minRequiredValue, value);
247
248                 m_testCtx.getLog() << TestLog::Message << "Reported: " << value << TestLog::EndMessage;
249                 m_testCtx.getLog() << TestLog::Message << "Minimum required: " << m_minRequiredValue << TestLog::EndMessage;
250
251                 if (!isOk)
252                         m_testCtx.getLog() << TestLog::Message << "FAIL: " << QueryClassTraits<(QueryClass)QueryTypeTraits<T>::CLASS>::s_errorDescription << TestLog::EndMessage;
253
254                 m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS      : QP_TEST_RESULT_FAIL,
255                                                                 isOk ? "Pass"                           : "Requirement not satisfied");
256                 return STOP;
257         }
258
259 private:
260         deUint32        m_limit;
261         T                       m_minRequiredValue;
262 };
263
264 static const deUint32 s_requiredCompressedTexFormats[] =
265 {
266         GL_COMPRESSED_R11_EAC,
267         GL_COMPRESSED_SIGNED_R11_EAC,
268         GL_COMPRESSED_RG11_EAC,
269         GL_COMPRESSED_SIGNED_RG11_EAC,
270         GL_COMPRESSED_RGB8_ETC2,
271         GL_COMPRESSED_SRGB8_ETC2,
272         GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2,
273         GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2,
274         GL_COMPRESSED_RGBA8_ETC2_EAC,
275         GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC
276 };
277
278 class CompressedTextureFormatsQueryCase : public TestCase
279 {
280 public:
281         CompressedTextureFormatsQueryCase (Context& context)
282                 : TestCase(context, "compressed_texture_formats", "GL_COMPRESSED_TEXTURE_FORMATS")
283         {
284         }
285
286         IterateResult iterate (void)
287         {
288                 const glw::Functions&   gl                              = m_context.getRenderContext().getFunctions();
289                 const GLint                             numFormats              = query<GLint>(gl, GL_NUM_COMPRESSED_TEXTURE_FORMATS);
290                 vector<GLint>                   formats                 (numFormats);
291                 bool                                    allFormatsOk    = true;
292
293                 if (numFormats > 0)
294                         gl.getIntegerv(GL_COMPRESSED_TEXTURE_FORMATS, &formats[0]);
295
296                 GLU_EXPECT_NO_ERROR(gl.getError(), "Query failed");
297
298                 // Log formats.
299                 m_testCtx.getLog() << TestLog::Message << "Reported:" << TestLog::EndMessage;
300                 for (vector<GLint>::const_iterator fmt = formats.begin(); fmt != formats.end(); fmt++)
301                         m_testCtx.getLog() << TestLog::Message << glu::getCompressedTextureFormatStr(*fmt) << TestLog::EndMessage;
302
303                 // Check that all required formats are in list.
304                 {
305                         set<GLint> formatSet(formats.begin(), formats.end());
306
307                         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_requiredCompressedTexFormats); ndx++)
308                         {
309                                 const deUint32  fmt             = s_requiredCompressedTexFormats[ndx];
310                                 const bool              found   = formatSet.find(fmt) != formatSet.end();
311
312                                 if (!found)
313                                 {
314                                         m_testCtx.getLog() << TestLog::Message << "ERROR: " << glu::getCompressedTextureFormatStr(fmt) << " is missing!" << TestLog::EndMessage;
315                                         allFormatsOk = false;
316                                 }
317                         }
318                 }
319
320                 m_testCtx.setTestResult(allFormatsOk ? QP_TEST_RESULT_PASS      : QP_TEST_RESULT_FAIL,
321                                                                 allFormatsOk ? "Pass"                           : "Requirement not satisfied");
322                 return STOP;
323         }
324 };
325
326 static vector<string> queryExtensionsNonIndexed (const glw::Functions& gl)
327 {
328         const string    extensionStr    = (const char*)gl.getString(GL_EXTENSIONS);
329         vector<string>  extensionList;
330         size_t                  pos                             = 0;
331
332         for (;;)
333         {
334                 const size_t    nextPos = extensionStr.find(' ', pos);
335                 const size_t    len             = nextPos == string::npos ? extensionStr.length()-pos : nextPos-pos;
336
337                 if (len > 0)
338                         extensionList.push_back(extensionStr.substr(pos, len));
339
340                 if (nextPos == string::npos)
341                         break;
342                 else
343                         pos = nextPos+1;
344         }
345
346         return extensionList;
347 }
348
349 static vector<string> queryExtensionsIndexed (const glw::Functions& gl)
350 {
351         const int               numExtensions           = query<GLint>(gl, GL_NUM_EXTENSIONS);
352         vector<string>  extensions                      (numExtensions);
353
354         GLU_EXPECT_NO_ERROR(gl.getError(), "GL_NUM_EXTENSIONS query failed");
355
356         for (int ndx = 0; ndx < numExtensions; ndx++)
357                 extensions[ndx] = (const char*)gl.getStringi(GL_EXTENSIONS, (GLuint)ndx);
358
359         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetStringi(GL_EXTENSIONS) failed");
360
361         return extensions;
362 }
363
364 static bool compareExtensionLists (const vector<string>& a, const vector<string>& b)
365 {
366         if (a.size() != b.size())
367                 return false;
368
369         set<string> extsInB(b.begin(), b.end());
370
371         for (vector<string>::const_iterator i = a.begin(); i != a.end(); ++i)
372         {
373                 if (extsInB.find(*i) == extsInB.end())
374                         return false;
375         }
376
377         return true;
378 }
379
380 class ExtensionQueryCase : public TestCase
381 {
382 public:
383         ExtensionQueryCase (Context& context)
384                 : TestCase(context, "extensions", "GL_EXTENSIONS")
385         {
386         }
387
388         IterateResult iterate (void)
389         {
390                 const glw::Functions&   gl                                      = m_context.getRenderContext().getFunctions();
391                 const vector<string>    nonIndexedExts          = queryExtensionsNonIndexed(gl);
392                 const vector<string>    indexedExts                     = queryExtensionsIndexed(gl);
393                 const bool                              isOk                            = compareExtensionLists(nonIndexedExts, indexedExts);
394
395                 m_testCtx.getLog() << TestLog::Message << "Extensions as reported by glGetStringi(GL_EXTENSIONS):" << TestLog::EndMessage;
396                 for (vector<string>::const_iterator ext = indexedExts.begin(); ext != indexedExts.end(); ++ext)
397                         m_testCtx.getLog() << TestLog::Message << *ext << TestLog::EndMessage;
398
399                 if (!isOk)
400                 {
401                         m_testCtx.getLog() << TestLog::Message << "Extensions as reported by glGetString(GL_EXTENSIONS):" << TestLog::EndMessage;
402                         for (vector<string>::const_iterator ext = nonIndexedExts.begin(); ext != nonIndexedExts.end(); ++ext)
403                                 m_testCtx.getLog() << TestLog::Message << *ext << TestLog::EndMessage;
404
405                         m_testCtx.getLog() << TestLog::Message << "ERROR: Extension lists do not match!" << TestLog::EndMessage;
406                 }
407
408                 m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS      : QP_TEST_RESULT_FAIL,
409                                                                 isOk ? "Pass"                           : "Invalid extension list");
410                 return STOP;
411         }
412 };
413
414 ImplementationLimitTests::ImplementationLimitTests (Context& context)
415         : TestCaseGroup(context, "implementation_limits", "Implementation-defined limits")
416 {
417 }
418
419 ImplementationLimitTests::~ImplementationLimitTests (void)
420 {
421 }
422
423 void ImplementationLimitTests::init (void)
424 {
425         const int       minVertexUniformBlocks                                  = 12;
426         const int       minVertexUniformComponents                              = 1024;
427
428         const int       minFragmentUniformBlocks                                = 12;
429         const int       minFragmentUniformComponents                    = 896;
430
431         const int       minUniformBlockSize                                             = 16384;
432         const int       minCombinedVertexUniformComponents              = (minVertexUniformBlocks*minUniformBlockSize)/4 + minVertexUniformComponents;
433         const int       minCombinedFragmentUniformComponents    = (minFragmentUniformBlocks*minUniformBlockSize)/4 + minFragmentUniformComponents;
434
435 #define LIMIT_CASE(NAME, PARAM, TYPE, MIN_VAL)  \
436         addChild(new LimitQueryCase<TYPE>(m_context, #NAME, #PARAM, PARAM, MIN_VAL))
437
438         LIMIT_CASE(max_element_index,                           GL_MAX_ELEMENT_INDEX,                                   GLint64,        (1<<24)-1);
439         LIMIT_CASE(subpixel_bits,                                       GL_SUBPIXEL_BITS,                                               GLint,          4);
440         LIMIT_CASE(max_3d_texture_size,                         GL_MAX_3D_TEXTURE_SIZE,                                 GLint,          256);
441         LIMIT_CASE(max_texture_size,                            GL_MAX_TEXTURE_SIZE,                                    GLint,          2048);
442         LIMIT_CASE(max_array_texture_layers,            GL_MAX_ARRAY_TEXTURE_LAYERS,                    GLint,          256);
443         LIMIT_CASE(max_texture_lod_bias,                        GL_MAX_TEXTURE_LOD_BIAS,                                GLfloat,        2.0f);
444         LIMIT_CASE(max_cube_map_texture_size,           GL_MAX_CUBE_MAP_TEXTURE_SIZE,                   GLint,          2048);
445         LIMIT_CASE(max_renderbuffer_size,                       GL_MAX_RENDERBUFFER_SIZE,                               GLint,          2048);
446         LIMIT_CASE(max_draw_buffers,                            GL_MAX_DRAW_BUFFERS,                                    GLint,          4);
447         LIMIT_CASE(max_color_attachments,                       GL_MAX_COLOR_ATTACHMENTS,                               GLint,          4);
448         // GL_MAX_VIEWPORT_DIMS
449         LIMIT_CASE(aliased_point_size_range,            GL_ALIASED_POINT_SIZE_RANGE,                    FloatRange,     FloatRange(1,1));
450         LIMIT_CASE(aliased_line_width_range,            GL_ALIASED_LINE_WIDTH_RANGE,                    FloatRange,     FloatRange(1,1));
451         LIMIT_CASE(max_elements_indices,                        GL_MAX_ELEMENTS_INDICES,                                GLint,          0);
452         LIMIT_CASE(max_elements_vertices,                       GL_MAX_ELEMENTS_VERTICES,                               GLint,          0);
453         LIMIT_CASE(num_compressed_texture_formats,      GL_NUM_COMPRESSED_TEXTURE_FORMATS,              GLint,          DE_LENGTH_OF_ARRAY(s_requiredCompressedTexFormats));
454         addChild(new CompressedTextureFormatsQueryCase(m_context)); // GL_COMPRESSED_TEXTURE_FORMATS
455         // GL_PROGRAM_BINARY_FORMATS
456         LIMIT_CASE(num_program_binary_formats,          GL_NUM_PROGRAM_BINARY_FORMATS,                  GLint,          0);
457         // GL_SHADER_BINARY_FORMATS
458         LIMIT_CASE(num_shader_binary_formats,           GL_NUM_SHADER_BINARY_FORMATS,                   GLint,          0);
459         LIMIT_CASE(shader_compiler,                                     GL_SHADER_COMPILER,                                             Boolean,        GL_TRUE);
460         // Shader data type ranges & precisions
461         LIMIT_CASE(max_server_wait_timeout,                     GL_MAX_SERVER_WAIT_TIMEOUT,                             GLuint64,       0);
462
463         // Version and extension support
464         addChild(new ExtensionQueryCase(m_context)); // GL_EXTENSIONS + consistency validation
465         LIMIT_CASE(num_extensions,                                      GL_NUM_EXTENSIONS,                                              GLint,          0);
466         LIMIT_CASE(major_version,                                       GL_MAJOR_VERSION,                                               GLint,          3);
467         LIMIT_CASE(minor_version,                                       GL_MINOR_VERSION,                                               GLint,          0);
468         // GL_RENDERER
469         // GL_SHADING_LANGUAGE_VERSION
470         // GL_VENDOR
471         // GL_VERSION
472
473         // Vertex shader limits
474         LIMIT_CASE(max_vertex_attribs,                          GL_MAX_VERTEX_ATTRIBS,                                  GLint,          16);
475         LIMIT_CASE(max_vertex_uniform_components,       GL_MAX_VERTEX_UNIFORM_COMPONENTS,               GLint,          minVertexUniformComponents);
476         LIMIT_CASE(max_vertex_uniform_vectors,          GL_MAX_VERTEX_UNIFORM_VECTORS,                  GLint,          minVertexUniformComponents/4);
477         LIMIT_CASE(max_vertex_uniform_blocks,           GL_MAX_VERTEX_UNIFORM_BLOCKS,                   GLint,          minVertexUniformBlocks);
478         LIMIT_CASE(max_vertex_output_components,        GL_MAX_VERTEX_OUTPUT_COMPONENTS,                GLint,          64);
479         LIMIT_CASE(max_vertex_texture_image_units,      GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS,              GLint,          16);
480
481         // Fragment shader limits
482         LIMIT_CASE(max_fragment_uniform_components,     GL_MAX_FRAGMENT_UNIFORM_COMPONENTS,             GLint,          minFragmentUniformComponents);
483         LIMIT_CASE(max_fragment_uniform_vectors,        GL_MAX_FRAGMENT_UNIFORM_VECTORS,                GLint,          minFragmentUniformComponents/4);
484         LIMIT_CASE(max_fragment_uniform_blocks,         GL_MAX_FRAGMENT_UNIFORM_BLOCKS,                 GLint,          minFragmentUniformBlocks);
485         LIMIT_CASE(max_fragment_input_components,       GL_MAX_FRAGMENT_INPUT_COMPONENTS,               GLint,          60);
486         LIMIT_CASE(max_texture_image_units,                     GL_MAX_TEXTURE_IMAGE_UNITS,                             GLint,          16);
487         LIMIT_CASE(min_program_texel_offset,            GL_MIN_PROGRAM_TEXEL_OFFSET,                    NegInt,         -8);
488         LIMIT_CASE(max_program_texel_offset,            GL_MAX_PROGRAM_TEXEL_OFFSET,                    GLint,          7);
489
490         // Aggregate shader limits
491         LIMIT_CASE(max_uniform_buffer_bindings,                                         GL_MAX_UNIFORM_BUFFER_BINDINGS,                                         GLint,                          24);
492         LIMIT_CASE(max_uniform_block_size,                                                      GL_MAX_UNIFORM_BLOCK_SIZE,                                                      GLint64,                        minUniformBlockSize);
493         LIMIT_CASE(uniform_buffer_offset_alignment,                                     GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT,                                     AlignmentInt,           256);
494         LIMIT_CASE(max_combined_uniform_blocks,                                         GL_MAX_COMBINED_UNIFORM_BLOCKS,                                         GLint,                          24);
495         LIMIT_CASE(max_combined_vertex_uniform_components,                      GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS,                      GLint64,                        minCombinedVertexUniformComponents);
496         LIMIT_CASE(max_combined_fragment_uniform_components,            GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS,            GLint64,                        minCombinedFragmentUniformComponents);
497         LIMIT_CASE(max_varying_components,                                                      GL_MAX_VARYING_COMPONENTS,                                                      GLint,                          60);
498         LIMIT_CASE(max_varying_vectors,                                                         GL_MAX_VARYING_VECTORS,                                                         GLint,                          15);
499         LIMIT_CASE(max_combined_texture_image_units,                            GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS,                            GLint,                          32);
500
501         // Transform feedback limits
502         LIMIT_CASE(max_transform_feedback_interleaved_components,       GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS,       GLint,                          64);
503         LIMIT_CASE(max_transform_feedback_separate_attribs,                     GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS,                     GLint,                          4);
504         LIMIT_CASE(max_transform_feedback_separate_components,          GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS,          GLint,                          4);
505 }
506
507 } // Functional
508 } // gles3
509 } // deqp