1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 3.1 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 Program interface query tests.
22 *//*--------------------------------------------------------------------*/
23
24 #include "es31fProgramInterfaceQueryTests.hpp"
25 #include "es31fProgramInterfaceQueryTestCase.hpp"
26 #include "es31fProgramInterfaceDefinition.hpp"
27 #include "es31fProgramInterfaceDefinitionUtil.hpp"
28 #include "tcuTestLog.hpp"
29 #include "tcuStringTemplate.hpp"
30 #include "gluShaderProgram.hpp"
31 #include "gluVarTypeUtil.hpp"
32 #include "gluStrUtil.hpp"
33 #include "gluContextInfo.hpp"
34 #include "glwFunctions.hpp"
35 #include "glwEnums.hpp"
36 #include "deRandom.hpp"
37 #include "deString.h"
38 #include "deStringUtil.hpp"
39 #include "deSharedPtr.hpp"
40 #include "deUniquePtr.hpp"
41 #include "deSTLUtil.hpp"
42 #include "deArrayUtil.hpp"
43
44 #include <set>
45 #include <map>
46
47 namespace deqp
48 {
49 namespace gles31
50 {
51 namespace Functional
52 {
53 namespace
54 {
55
getTypeSize(glu::DataType type)56 static int getTypeSize (glu::DataType type)
57 {
58 if (type == glu::TYPE_FLOAT)
59 return 4;
60 else if (type == glu::TYPE_INT || type == glu::TYPE_UINT)
61 return 4;
62 else if (type == glu::TYPE_BOOL)
63 return 4; // uint
64
65 DE_ASSERT(false);
66 return 0;
67 }
68
getVarTypeSize(const glu::VarType & type)69 static int getVarTypeSize (const glu::VarType& type)
70 {
71 if (type.isBasicType())
72 return glu::getDataTypeScalarSize(type.getBasicType()) * getTypeSize(glu::getDataTypeScalarType(type.getBasicType()));
73 else if (type.isStructType())
74 {
75 int size = 0;
76 for (int ndx = 0; ndx < type.getStructPtr()->getNumMembers(); ++ndx)
77 size += getVarTypeSize(type.getStructPtr()->getMember(ndx).getType());
78 return size;
79 }
80 else if (type.isArrayType())
81 {
82 if (type.getArraySize() == glu::VarType::UNSIZED_ARRAY)
83 return getVarTypeSize(type.getElementType());
84 else
85 return type.getArraySize() * getVarTypeSize(type.getElementType());
86 }
87 else
88 {
89 DE_ASSERT(false);
90 return 0;
91 }
92 }
93
convertGLTypeNameToTestName(const char * glName)94 static std::string convertGLTypeNameToTestName (const char* glName)
95 {
96 // vectors and matrices are fine as is
97 {
98 if (deStringBeginsWith(glName, "vec") == DE_TRUE ||
99 deStringBeginsWith(glName, "ivec") == DE_TRUE ||
100 deStringBeginsWith(glName, "uvec") == DE_TRUE ||
101 deStringBeginsWith(glName, "bvec") == DE_TRUE ||
102 deStringBeginsWith(glName, "mat") == DE_TRUE)
103 return std::string(glName);
104 }
105
106 // convert camel case to use underscore
107 {
108 std::ostringstream buf;
109 std::istringstream name (glName);
110 bool mergeNextToken = false;
111 bool previousTokenWasDigit = false;
112
113 while (!name.eof())
114 {
115 std::ostringstream token;
116
117 while (name.peek() != EOF)
118 {
119 if ((de::isDigit((char)name.peek()) || de::isUpper((char)name.peek())) && token.tellp())
120 break;
121
122 token << de::toLower((char)name.get());
123 }
124
125 if (buf.str().empty() || mergeNextToken)
126 buf << token.str();
127 else
128 buf << '_' << token.str();
129
130 // Single char causes next char to be merged (don't split initialisms or acronyms) unless it is 'D' after a number (split to ..._2d_acronym_aa
131 mergeNextToken = false;
132 if (token.tellp() == (std::streamoff)1)
133 {
134 if (!previousTokenWasDigit || token.str()[0] != 'd')
135 mergeNextToken = true;
136
137 previousTokenWasDigit = de::isDigit(token.str()[0]);
138 }
139 else
140 previousTokenWasDigit = false;
141 }
142
143 return buf.str();
144 }
145 }
146
getProgramInterfaceGLEnum(ProgramInterface interface)147 static glw::GLenum getProgramInterfaceGLEnum (ProgramInterface interface)
148 {
149 static const glw::GLenum s_enums[] =
150 {
151 GL_UNIFORM, // PROGRAMINTERFACE_UNIFORM
152 GL_UNIFORM_BLOCK, // PROGRAMINTERFACE_UNIFORM_BLOCK
153 GL_ATOMIC_COUNTER_BUFFER, // PROGRAMINTERFACE_ATOMIC_COUNTER_BUFFER
154 GL_PROGRAM_INPUT, // PROGRAMINTERFACE_PROGRAM_INPUT
155 GL_PROGRAM_OUTPUT, // PROGRAMINTERFACE_PROGRAM_OUTPUT
156 GL_TRANSFORM_FEEDBACK_VARYING, // PROGRAMINTERFACE_TRANSFORM_FEEDBACK_VARYING
157 GL_BUFFER_VARIABLE, // PROGRAMINTERFACE_BUFFER_VARIABLE
158 GL_SHADER_STORAGE_BLOCK, // PROGRAMINTERFACE_SHADER_STORAGE_BLOCK
159 };
160
161 return de::getSizedArrayElement<PROGRAMINTERFACE_LAST>(s_enums, interface);
162 }
163
getShaderMaskFirstStage(deUint32 mask)164 static glu::ShaderType getShaderMaskFirstStage (deUint32 mask)
165 {
166 if (mask & (1u << glu::SHADERTYPE_COMPUTE))
167 return glu::SHADERTYPE_COMPUTE;
168
169 if (mask & (1u << glu::SHADERTYPE_VERTEX))
170 return glu::SHADERTYPE_VERTEX;
171
172 if (mask & (1u << glu::SHADERTYPE_TESSELLATION_CONTROL))
173 return glu::SHADERTYPE_TESSELLATION_CONTROL;
174
175 if (mask & (1u << glu::SHADERTYPE_TESSELLATION_EVALUATION))
176 return glu::SHADERTYPE_TESSELLATION_EVALUATION;
177
178 if (mask & (1u << glu::SHADERTYPE_GEOMETRY))
179 return glu::SHADERTYPE_GEOMETRY;
180
181 if (mask & (1u << glu::SHADERTYPE_FRAGMENT))
182 return glu::SHADERTYPE_FRAGMENT;
183
184 DE_ASSERT(false);
185 return glu::SHADERTYPE_LAST;
186 }
187
getShaderMaskLastStage(deUint32 mask)188 static glu::ShaderType getShaderMaskLastStage (deUint32 mask)
189 {
190 if (mask & (1u << glu::SHADERTYPE_FRAGMENT))
191 return glu::SHADERTYPE_FRAGMENT;
192
193 if (mask & (1u << glu::SHADERTYPE_GEOMETRY))
194 return glu::SHADERTYPE_GEOMETRY;
195
196 if (mask & (1u << glu::SHADERTYPE_TESSELLATION_EVALUATION))
197 return glu::SHADERTYPE_TESSELLATION_EVALUATION;
198
199 if (mask & (1u << glu::SHADERTYPE_TESSELLATION_CONTROL))
200 return glu::SHADERTYPE_TESSELLATION_CONTROL;
201
202 if (mask & (1u << glu::SHADERTYPE_VERTEX))
203 return glu::SHADERTYPE_VERTEX;
204
205 if (mask & (1u << glu::SHADERTYPE_COMPUTE))
206 return glu::SHADERTYPE_COMPUTE;
207
208 DE_ASSERT(false);
209 return glu::SHADERTYPE_LAST;
210 }
211
specializeShader(Context & context,const char * code)212 static std::string specializeShader(Context& context, const char* code)
213 {
214 const glu::GLSLVersion glslVersion = glu::getContextTypeGLSLVersion(context.getRenderContext().getType());
215 std::map<std::string, std::string> specializationMap;
216
217 specializationMap["GLSL_VERSION_DECL"] = glu::getGLSLVersionDeclaration(glslVersion);
218
219 return tcu::StringTemplate(code).specialize(specializationMap);
220 }
221
222 namespace ResourceDefinition
223 {
224
225 class Node
226 {
227 public:
228 enum NodeType
229 {
230 TYPE_PROGRAM = 0,
231 TYPE_SHADER,
232 TYPE_DEFAULT_BLOCK,
233 TYPE_VARIABLE,
234 TYPE_INTERFACE_BLOCK,
235 TYPE_ARRAY_ELEMENT,
236 TYPE_STRUCT_MEMBER,
237 TYPE_STORAGE_QUALIFIER,
238 TYPE_LAYOUT_QUALIFIER,
239 TYPE_SHADER_SET,
240 TYPE_INTERPOLATION_QUALIFIER,
241 TYPE_TRANSFORM_FEEDBACK_TARGET,
242
243 TYPE_LAST
244 };
245
246 typedef de::SharedPtr<const Node> SharedPtr;
247
Node(NodeType type,const SharedPtr & enclosingNode)248 Node (NodeType type, const SharedPtr& enclosingNode) : m_type(type), m_enclosingNode(enclosingNode) { DE_ASSERT(type < TYPE_LAST); }
~Node(void)249 virtual ~Node (void) { }
250
getEnclosingNode(void) const251 inline const Node* getEnclosingNode (void) const { return m_enclosingNode.get(); }
getType(void) const252 inline NodeType getType (void) const { return m_type; }
253
254 private:
255 const NodeType m_type;
256 const SharedPtr m_enclosingNode;
257 };
258
259 class Program : public Node
260 {
261 public:
Program(bool separable=false)262 Program (bool separable = false)
263 : Node (TYPE_PROGRAM, SharedPtr())
264 , m_separable (separable)
265 {
266 }
267
268 const bool m_separable;
269 };
270
271 class Shader : public Node
272 {
273 public:
Shader(const SharedPtr & enclosingNode,glu::ShaderType type,glu::GLSLVersion version)274 Shader (const SharedPtr& enclosingNode, glu::ShaderType type, glu::GLSLVersion version)
275 : Node (TYPE_SHADER, enclosingNode)
276 , m_type (type)
277 , m_version (version)
278 {
279 DE_ASSERT(enclosingNode->getType() == TYPE_PROGRAM);
280 DE_ASSERT(type < glu::SHADERTYPE_LAST);
281 }
282
283 const glu::ShaderType m_type;
284 const glu::GLSLVersion m_version;
285 };
286
287 class DefaultBlock : public Node
288 {
289 public:
DefaultBlock(const SharedPtr & enclosing)290 DefaultBlock (const SharedPtr& enclosing)
291 : Node(TYPE_DEFAULT_BLOCK, enclosing)
292 {
293 // enclosed by the shader
294 DE_ASSERT(enclosing->getType() == TYPE_SHADER ||
295 enclosing->getType() == TYPE_SHADER_SET);
296 }
297 };
298
299 class StorageQualifier : public Node
300 {
301 public:
StorageQualifier(const SharedPtr & enclosing,glu::Storage storage)302 StorageQualifier (const SharedPtr& enclosing, glu::Storage storage)
303 : Node (TYPE_STORAGE_QUALIFIER, enclosing)
304 , m_storage (storage)
305 {
306 // not a part of any block
307 DE_ASSERT(enclosing->getType() == TYPE_DEFAULT_BLOCK);
308 }
309
310 const glu::Storage m_storage;
311 };
312
313 class Variable : public Node
314 {
315 public:
Variable(const SharedPtr & enclosing,glu::DataType dataType)316 Variable (const SharedPtr& enclosing, glu::DataType dataType)
317 : Node (TYPE_VARIABLE, enclosing)
318 , m_dataType (dataType)
319 {
320 DE_ASSERT(enclosing->getType() == TYPE_STORAGE_QUALIFIER ||
321 enclosing->getType() == TYPE_LAYOUT_QUALIFIER ||
322 enclosing->getType() == TYPE_INTERPOLATION_QUALIFIER ||
323 enclosing->getType() == TYPE_INTERFACE_BLOCK ||
324 enclosing->getType() == TYPE_ARRAY_ELEMENT ||
325 enclosing->getType() == TYPE_STRUCT_MEMBER ||
326 enclosing->getType() == TYPE_TRANSFORM_FEEDBACK_TARGET);
327 }
328
329 const glu::DataType m_dataType;
330 };
331
332 class InterfaceBlock : public Node
333 {
334 public:
InterfaceBlock(const SharedPtr & enclosing,bool named)335 InterfaceBlock (const SharedPtr& enclosing, bool named)
336 : Node (TYPE_INTERFACE_BLOCK, enclosing)
337 , m_named (named)
338 {
339 // Must be storage qualified
340 const Node* storageNode = enclosing.get();
341 while (storageNode->getType() == TYPE_ARRAY_ELEMENT ||
342 storageNode->getType() == TYPE_LAYOUT_QUALIFIER)
343 {
344 storageNode = storageNode->getEnclosingNode();
345 }
346
347 DE_ASSERT(storageNode->getType() == TYPE_STORAGE_QUALIFIER);
348 DE_UNREF(storageNode);
349 }
350
351 const bool m_named;
352 };
353
354 class ArrayElement : public Node
355 {
356 public:
ArrayElement(const SharedPtr & enclosing,int arraySize=DEFAULT_SIZE)357 ArrayElement (const SharedPtr& enclosing, int arraySize = DEFAULT_SIZE)
358 : Node (TYPE_ARRAY_ELEMENT, enclosing)
359 , m_arraySize (arraySize)
360 {
361 DE_ASSERT(enclosing->getType() == TYPE_STORAGE_QUALIFIER ||
362 enclosing->getType() == TYPE_LAYOUT_QUALIFIER ||
363 enclosing->getType() == TYPE_INTERPOLATION_QUALIFIER ||
364 enclosing->getType() == TYPE_INTERFACE_BLOCK ||
365 enclosing->getType() == TYPE_ARRAY_ELEMENT ||
366 enclosing->getType() == TYPE_STRUCT_MEMBER ||
367 enclosing->getType() == TYPE_TRANSFORM_FEEDBACK_TARGET);
368 }
369
370 const int m_arraySize;
371
372 enum
373 {
374 DEFAULT_SIZE = -1,
375 UNSIZED_ARRAY = -2,
376 };
377 };
378
379 class StructMember : public Node
380 {
381 public:
StructMember(const SharedPtr & enclosing)382 StructMember (const SharedPtr& enclosing)
383 : Node(TYPE_STRUCT_MEMBER, enclosing)
384 {
385 DE_ASSERT(enclosing->getType() == TYPE_STORAGE_QUALIFIER ||
386 enclosing->getType() == TYPE_LAYOUT_QUALIFIER ||
387 enclosing->getType() == TYPE_INTERPOLATION_QUALIFIER ||
388 enclosing->getType() == TYPE_INTERFACE_BLOCK ||
389 enclosing->getType() == TYPE_ARRAY_ELEMENT ||
390 enclosing->getType() == TYPE_STRUCT_MEMBER ||
391 enclosing->getType() == TYPE_TRANSFORM_FEEDBACK_TARGET);
392 }
393 };
394
395 class LayoutQualifier : public Node
396 {
397 public:
LayoutQualifier(const SharedPtr & enclosing,const glu::Layout & layout)398 LayoutQualifier (const SharedPtr& enclosing, const glu::Layout& layout)
399 : Node (TYPE_LAYOUT_QUALIFIER, enclosing)
400 , m_layout (layout)
401 {
402 DE_ASSERT(enclosing->getType() == TYPE_STORAGE_QUALIFIER ||
403 enclosing->getType() == TYPE_LAYOUT_QUALIFIER ||
404 enclosing->getType() == TYPE_INTERPOLATION_QUALIFIER ||
405 enclosing->getType() == TYPE_DEFAULT_BLOCK ||
406 enclosing->getType() == TYPE_INTERFACE_BLOCK);
407 }
408
409 const glu::Layout m_layout;
410 };
411
412 class InterpolationQualifier : public Node
413 {
414 public:
InterpolationQualifier(const SharedPtr & enclosing,const glu::Interpolation & interpolation)415 InterpolationQualifier (const SharedPtr& enclosing, const glu::Interpolation& interpolation)
416 : Node (TYPE_INTERPOLATION_QUALIFIER, enclosing)
417 , m_interpolation (interpolation)
418 {
419 DE_ASSERT(enclosing->getType() == TYPE_STORAGE_QUALIFIER ||
420 enclosing->getType() == TYPE_LAYOUT_QUALIFIER ||
421 enclosing->getType() == TYPE_INTERPOLATION_QUALIFIER ||
422 enclosing->getType() == TYPE_DEFAULT_BLOCK ||
423 enclosing->getType() == TYPE_INTERFACE_BLOCK);
424 }
425
426 const glu::Interpolation m_interpolation;
427 };
428
429 class ShaderSet : public Node
430 {
431 public:
432 ShaderSet (const SharedPtr& enclosing, glu::GLSLVersion version);
433 ShaderSet (const SharedPtr& enclosing, glu::GLSLVersion version, deUint32 stagesPresentBits, deUint32 stagesReferencingBits);
434
435 void setStage (glu::ShaderType type, bool referencing);
436 bool isStagePresent (glu::ShaderType stage) const;
437 bool isStageReferencing (glu::ShaderType stage) const;
438
439 deUint32 getReferencingMask (void) const;
440
441 const glu::GLSLVersion m_version;
442 private:
443 bool m_stagePresent[glu::SHADERTYPE_LAST];
444 bool m_stageReferencing[glu::SHADERTYPE_LAST];
445 };
446
ShaderSet(const SharedPtr & enclosing,glu::GLSLVersion version)447 ShaderSet::ShaderSet (const SharedPtr& enclosing, glu::GLSLVersion version)
448 : Node (TYPE_SHADER_SET, enclosing)
449 , m_version (version)
450 {
451 DE_ASSERT(enclosing->getType() == TYPE_PROGRAM);
452
453 deMemset(m_stagePresent, 0, sizeof(m_stagePresent));
454 deMemset(m_stageReferencing, 0, sizeof(m_stageReferencing));
455 }
456
ShaderSet(const SharedPtr & enclosing,glu::GLSLVersion version,deUint32 stagesPresentBits,deUint32 stagesReferencingBits)457 ShaderSet::ShaderSet (const SharedPtr& enclosing,
458 glu::GLSLVersion version,
459 deUint32 stagesPresentBits,
460 deUint32 stagesReferencingBits)
461 : Node (TYPE_SHADER_SET, enclosing)
462 , m_version (version)
463 {
464 for (deUint32 stageNdx = 0; stageNdx < glu::SHADERTYPE_LAST; ++stageNdx)
465 {
466 const deUint32 stageMask = (1u << stageNdx);
467 const bool stagePresent = (stagesPresentBits & stageMask) != 0;
468 const bool stageReferencing = (stagesReferencingBits & stageMask) != 0;
469
470 DE_ASSERT(stagePresent || !stageReferencing);
471
472 m_stagePresent[stageNdx] = stagePresent;
473 m_stageReferencing[stageNdx] = stageReferencing;
474 }
475 }
476
setStage(glu::ShaderType type,bool referencing)477 void ShaderSet::setStage (glu::ShaderType type, bool referencing)
478 {
479 DE_ASSERT(type < glu::SHADERTYPE_LAST);
480 m_stagePresent[type] = true;
481 m_stageReferencing[type] = referencing;
482 }
483
isStagePresent(glu::ShaderType stage) const484 bool ShaderSet::isStagePresent (glu::ShaderType stage) const
485 {
486 DE_ASSERT(stage < glu::SHADERTYPE_LAST);
487 return m_stagePresent[stage];
488 }
489
isStageReferencing(glu::ShaderType stage) const490 bool ShaderSet::isStageReferencing (glu::ShaderType stage) const
491 {
492 DE_ASSERT(stage < glu::SHADERTYPE_LAST);
493 return m_stageReferencing[stage];
494 }
495
getReferencingMask(void) const496 deUint32 ShaderSet::getReferencingMask (void) const
497 {
498 deUint32 mask = 0;
499 for (deUint32 stage = 0; stage < glu::SHADERTYPE_LAST; ++stage)
500 {
501 if (m_stageReferencing[stage])
502 mask |= (1u << stage);
503 }
504 return mask;
505 }
506
507 class TransformFeedbackTarget : public Node
508 {
509 public:
TransformFeedbackTarget(const SharedPtr & enclosing,const char * builtinVarName=DE_NULL)510 TransformFeedbackTarget (const SharedPtr& enclosing, const char* builtinVarName = DE_NULL)
511 : Node (TYPE_TRANSFORM_FEEDBACK_TARGET, enclosing)
512 , m_builtinVarName (builtinVarName)
513 {
514 }
515
516 const char* const m_builtinVarName;
517 };
518
519 } // ResourceDefinition
520
getDataTypeDefaultPrecision(const glu::DataType & type)521 static glu::Precision getDataTypeDefaultPrecision (const glu::DataType& type)
522 {
523 if (glu::isDataTypeBoolOrBVec(type))
524 return glu::PRECISION_LAST;
525 else if (glu::isDataTypeScalarOrVector(type) || glu::isDataTypeMatrix(type))
526 return glu::PRECISION_HIGHP;
527 else if (glu::isDataTypeSampler(type))
528 return glu::PRECISION_HIGHP;
529 else if (glu::isDataTypeImage(type))
530 return glu::PRECISION_HIGHP;
531 else if (type == glu::TYPE_UINT_ATOMIC_COUNTER)
532 return glu::PRECISION_HIGHP;
533
534 DE_ASSERT(false);
535 return glu::PRECISION_LAST;
536 }
537
generateProgramDefinitionFromResource(const ResourceDefinition::Node * resource)538 static de::MovePtr<ProgramInterfaceDefinition::Program> generateProgramDefinitionFromResource (const ResourceDefinition::Node* resource)
539 {
540 de::MovePtr<ProgramInterfaceDefinition::Program> program (new ProgramInterfaceDefinition::Program());
541 const ResourceDefinition::Node* head = resource;
542
543 if (head->getType() == ResourceDefinition::Node::TYPE_VARIABLE)
544 {
545 DE_ASSERT(dynamic_cast<const ResourceDefinition::Variable*>(resource));
546
547 enum BindingType
548 {
549 BINDING_VARIABLE,
550 BINDING_INTERFACE_BLOCK,
551 BINDING_DEFAULT_BLOCK
552 };
553
554 int structNdx = 0;
555 int autoAssignArraySize = 0;
556 const glu::DataType basicType = static_cast<const ResourceDefinition::Variable*>(resource)->m_dataType;
557 BindingType boundObject = BINDING_VARIABLE;
558 glu::VariableDeclaration variable (glu::VarType(basicType, getDataTypeDefaultPrecision(basicType)), "target");
559 glu::InterfaceBlock interfaceBlock;
560 ProgramInterfaceDefinition::DefaultBlock defaultBlock;
561 std::vector<std::string> feedbackTargetVaryingPath;
562 bool feedbackTargetSet = false;
563
564 // image specific
565 if (glu::isDataTypeImage(basicType))
566 {
567 variable.memoryAccessQualifierBits |= glu::MEMORYACCESSQUALIFIER_READONLY_BIT;
568 variable.layout.binding = 1;
569
570 if (basicType >= glu::TYPE_IMAGE_2D && basicType <= glu::TYPE_IMAGE_3D)
571 variable.layout.format = glu::FORMATLAYOUT_RGBA8;
572 else if (basicType >= glu::TYPE_INT_IMAGE_2D && basicType <= glu::TYPE_INT_IMAGE_3D)
573 variable.layout.format = glu::FORMATLAYOUT_RGBA8I;
574 else if (basicType >= glu::TYPE_UINT_IMAGE_2D && basicType <= glu::TYPE_UINT_IMAGE_3D)
575 variable.layout.format = glu::FORMATLAYOUT_RGBA8UI;
576 else
577 DE_ASSERT(false);
578 }
579
580 // atomic counter specific
581 if (basicType == glu::TYPE_UINT_ATOMIC_COUNTER)
582 variable.layout.binding = 1;
583
584 for (head = head->getEnclosingNode(); head; head = head->getEnclosingNode())
585 {
586 if (head->getType() == ResourceDefinition::Node::TYPE_STORAGE_QUALIFIER)
587 {
588 const ResourceDefinition::StorageQualifier* qualifier = static_cast<const ResourceDefinition::StorageQualifier*>(head);
589
590 DE_ASSERT(dynamic_cast<const ResourceDefinition::StorageQualifier*>(head));
591
592 if (boundObject == BINDING_VARIABLE)
593 {
594 DE_ASSERT(variable.storage == glu::STORAGE_LAST);
595 variable.storage = qualifier->m_storage;
596 }
597 else if (boundObject == BINDING_INTERFACE_BLOCK)
598 {
599 DE_ASSERT(interfaceBlock.storage == glu::STORAGE_LAST);
600 interfaceBlock.storage = qualifier->m_storage;
601 }
602 else
603 DE_ASSERT(false);
604 }
605 else if (head->getType() == ResourceDefinition::Node::TYPE_LAYOUT_QUALIFIER)
606 {
607 const ResourceDefinition::LayoutQualifier* qualifier = static_cast<const ResourceDefinition::LayoutQualifier*>(head);
608 glu::Layout* targetLayout = DE_NULL;
609
610 DE_ASSERT(dynamic_cast<const ResourceDefinition::LayoutQualifier*>(head));
611
612 if (boundObject == BINDING_VARIABLE)
613 targetLayout = &variable.layout;
614 else if (boundObject == BINDING_INTERFACE_BLOCK)
615 targetLayout = &interfaceBlock.layout;
616 else
617 DE_ASSERT(false);
618
619 if (qualifier->m_layout.location != -1)
620 targetLayout->location = qualifier->m_layout.location;
621
622 if (qualifier->m_layout.binding != -1)
623 targetLayout->binding = qualifier->m_layout.binding;
624
625 if (qualifier->m_layout.offset != -1)
626 targetLayout->offset = qualifier->m_layout.offset;
627
628 if (qualifier->m_layout.format != glu::FORMATLAYOUT_LAST)
629 targetLayout->format = qualifier->m_layout.format;
630
631 if (qualifier->m_layout.matrixOrder != glu::MATRIXORDER_LAST)
632 targetLayout->matrixOrder = qualifier->m_layout.matrixOrder;
633 }
634 else if (head->getType() == ResourceDefinition::Node::TYPE_INTERPOLATION_QUALIFIER)
635 {
636 const ResourceDefinition::InterpolationQualifier* qualifier = static_cast<const ResourceDefinition::InterpolationQualifier*>(head);
637
638 DE_ASSERT(dynamic_cast<const ResourceDefinition::InterpolationQualifier*>(head));
639
640 if (boundObject == BINDING_VARIABLE)
641 variable.interpolation = qualifier->m_interpolation;
642 else
643 DE_ASSERT(false);
644 }
645 else if (head->getType() == ResourceDefinition::Node::TYPE_ARRAY_ELEMENT)
646 {
647 DE_ASSERT(dynamic_cast<const ResourceDefinition::ArrayElement*>(head));
648
649 const ResourceDefinition::ArrayElement* arrayElement = static_cast<const ResourceDefinition::ArrayElement*>(head);
650 int arraySize;
651
652 // Vary array size per level
653 if (arrayElement->m_arraySize == ResourceDefinition::ArrayElement::DEFAULT_SIZE)
654 {
655 if (--autoAssignArraySize <= 1)
656 autoAssignArraySize = 3;
657
658 arraySize = autoAssignArraySize;
659 }
660 else if (arrayElement->m_arraySize == ResourceDefinition::ArrayElement::UNSIZED_ARRAY)
661 arraySize = glu::VarType::UNSIZED_ARRAY;
662 else
663 arraySize = arrayElement->m_arraySize;
664
665 if (boundObject == BINDING_VARIABLE)
666 variable.varType = glu::VarType(variable.varType, arraySize);
667 else if (boundObject == BINDING_INTERFACE_BLOCK)
668 interfaceBlock.dimensions.push_back(arraySize);
669 else
670 DE_ASSERT(false);
671
672 if (feedbackTargetSet)
673 feedbackTargetVaryingPath.back().append("[0]");
674 }
675 else if (head->getType() == ResourceDefinition::Node::TYPE_STRUCT_MEMBER)
676 {
677 DE_ASSERT(dynamic_cast<const ResourceDefinition::StructMember*>(head));
678 DE_ASSERT(boundObject == BINDING_VARIABLE);
679
680 // Struct members cannot contain any qualifiers except precision
681 DE_ASSERT(variable.interpolation == glu::INTERPOLATION_LAST);
682 DE_ASSERT(variable.layout == glu::Layout());
683 DE_ASSERT(variable.memoryAccessQualifierBits == 0);
684 DE_ASSERT(variable.storage == glu::STORAGE_LAST);
685
686 {
687 glu::StructType* structPtr = new glu::StructType(("StructType" + de::toString(structNdx++)).c_str());
688 structPtr->addMember(variable.name.c_str(), variable.varType);
689
690 variable = glu::VariableDeclaration(glu::VarType(structPtr), "target");
691 }
692
693 if (feedbackTargetSet)
694 feedbackTargetVaryingPath.push_back("target");
695 }
696 else if (head->getType() == ResourceDefinition::Node::TYPE_INTERFACE_BLOCK)
697 {
698 DE_ASSERT(dynamic_cast<const ResourceDefinition::InterfaceBlock*>(head));
699 DE_ASSERT(boundObject == BINDING_VARIABLE);
700
701 const bool named = static_cast<const ResourceDefinition::InterfaceBlock*>(head)->m_named;
702
703 boundObject = BINDING_INTERFACE_BLOCK;
704
705 interfaceBlock.interfaceName = "TargetInterface";
706 interfaceBlock.instanceName = (named) ? ("targetInstance") : ("");
707 interfaceBlock.variables.push_back(variable);
708
709 if (feedbackTargetSet && !interfaceBlock.instanceName.empty())
710 feedbackTargetVaryingPath.push_back(interfaceBlock.interfaceName);
711 }
712 else if (head->getType() == ResourceDefinition::Node::TYPE_DEFAULT_BLOCK)
713 {
714 DE_ASSERT(dynamic_cast<const ResourceDefinition::DefaultBlock*>(head));
715 DE_ASSERT(boundObject == BINDING_VARIABLE || boundObject == BINDING_INTERFACE_BLOCK);
716
717 if (boundObject == BINDING_VARIABLE)
718 defaultBlock.variables.push_back(variable);
719 else if (boundObject == BINDING_INTERFACE_BLOCK)
720 defaultBlock.interfaceBlocks.push_back(interfaceBlock);
721 else
722 DE_ASSERT(false);
723
724 boundObject = BINDING_DEFAULT_BLOCK;
725 }
726 else if (head->getType() == ResourceDefinition::Node::TYPE_SHADER)
727 {
728 DE_ASSERT(dynamic_cast<const ResourceDefinition::Shader*>(head));
729
730 const ResourceDefinition::Shader* shaderDef = static_cast<const ResourceDefinition::Shader*>(head);
731 ProgramInterfaceDefinition::Shader* shader = program->addShader(shaderDef->m_type, shaderDef->m_version);
732
733 shader->getDefaultBlock() = defaultBlock;
734 }
735 else if (head->getType() == ResourceDefinition::Node::TYPE_SHADER_SET)
736 {
737 DE_ASSERT(dynamic_cast<const ResourceDefinition::ShaderSet*>(head));
738
739 const ResourceDefinition::ShaderSet* shaderDef = static_cast<const ResourceDefinition::ShaderSet*>(head);
740
741 for (int shaderType = 0; shaderType < glu::SHADERTYPE_LAST; ++shaderType)
742 {
743 if (shaderDef->isStagePresent((glu::ShaderType)shaderType))
744 {
745 ProgramInterfaceDefinition::Shader* shader = program->addShader((glu::ShaderType)shaderType, shaderDef->m_version);
746
747 if (shaderDef->isStageReferencing((glu::ShaderType)shaderType))
748 shader->getDefaultBlock() = defaultBlock;
749 }
750 }
751 }
752 else if (head->getType() == ResourceDefinition::Node::TYPE_PROGRAM)
753 {
754 DE_ASSERT(dynamic_cast<const ResourceDefinition::Program*>(head));
755
756 const ResourceDefinition::Program* programDef = static_cast<const ResourceDefinition::Program*>(head);
757
758 program->setSeparable(programDef->m_separable);
759
760 DE_ASSERT(feedbackTargetSet == !feedbackTargetVaryingPath.empty());
761 if (!feedbackTargetVaryingPath.empty())
762 {
763 std::ostringstream buf;
764
765 for (std::vector<std::string>::reverse_iterator it = feedbackTargetVaryingPath.rbegin(); it != feedbackTargetVaryingPath.rend(); ++it)
766 {
767 if (it != feedbackTargetVaryingPath.rbegin())
768 buf << ".";
769 buf << *it;
770 }
771
772 program->addTransformFeedbackVarying(buf.str());
773 program->setTransformFeedbackMode(GL_INTERLEAVED_ATTRIBS);
774 }
775 break;
776 }
777 else if (head->getType() == ResourceDefinition::Node::TYPE_TRANSFORM_FEEDBACK_TARGET)
778 {
779 DE_ASSERT(dynamic_cast<const ResourceDefinition::TransformFeedbackTarget*>(head));
780
781 const ResourceDefinition::TransformFeedbackTarget* feedbackTarget = static_cast<const ResourceDefinition::TransformFeedbackTarget*>(head);
782
783 DE_ASSERT(feedbackTarget->m_builtinVarName == DE_NULL);
784 DE_UNREF(feedbackTarget);
785
786 feedbackTargetSet = true;
787 feedbackTargetVaryingPath.push_back(variable.name);
788 }
789 else
790 {
791 DE_ASSERT(DE_FALSE);
792 break;
793 }
794 }
795 }
796 else if (head->getType() == ResourceDefinition::Node::TYPE_DEFAULT_BLOCK ||
797 head->getType() == ResourceDefinition::Node::TYPE_TRANSFORM_FEEDBACK_TARGET)
798 {
799 const char* feedbackTargetVaryingName = DE_NULL;
800
801 // empty default block
802
803 for (; head; head = head->getEnclosingNode())
804 {
805 if (head->getType() == ResourceDefinition::Node::TYPE_SHADER)
806 {
807 DE_ASSERT(dynamic_cast<const ResourceDefinition::Shader*>(head));
808
809 const ResourceDefinition::Shader* shaderDef = static_cast<const ResourceDefinition::Shader*>(head);
810
811 program->addShader(shaderDef->m_type, shaderDef->m_version);
812 }
813 else if (head->getType() == ResourceDefinition::Node::TYPE_SHADER_SET)
814 {
815 DE_ASSERT(dynamic_cast<const ResourceDefinition::ShaderSet*>(head));
816
817 const ResourceDefinition::ShaderSet* shaderDef = static_cast<const ResourceDefinition::ShaderSet*>(head);
818
819 for (int shaderType = 0; shaderType < glu::SHADERTYPE_LAST; ++shaderType)
820 if (shaderDef->isStagePresent((glu::ShaderType)shaderType))
821 program->addShader((glu::ShaderType)shaderType, shaderDef->m_version);
822 }
823 else if (head->getType() == ResourceDefinition::Node::TYPE_PROGRAM)
824 {
825 DE_ASSERT(dynamic_cast<const ResourceDefinition::Program*>(head));
826
827 const ResourceDefinition::Program* programDef = static_cast<const ResourceDefinition::Program*>(head);
828
829 program->setSeparable(programDef->m_separable);
830 if (feedbackTargetVaryingName)
831 {
832 program->addTransformFeedbackVarying(std::string(feedbackTargetVaryingName));
833 program->setTransformFeedbackMode(GL_INTERLEAVED_ATTRIBS);
834 }
835 break;
836 }
837 else if (head->getType() == ResourceDefinition::Node::TYPE_TRANSFORM_FEEDBACK_TARGET)
838 {
839 DE_ASSERT(dynamic_cast<const ResourceDefinition::TransformFeedbackTarget*>(head));
840
841 const ResourceDefinition::TransformFeedbackTarget* feedbackTarget = static_cast<const ResourceDefinition::TransformFeedbackTarget*>(head);
842
843 DE_ASSERT(feedbackTarget->m_builtinVarName != DE_NULL);
844
845 feedbackTargetVaryingName = feedbackTarget->m_builtinVarName;
846 }
847 else if (head->getType() == ResourceDefinition::Node::TYPE_DEFAULT_BLOCK)
848 {
849 }
850 else
851 {
852 DE_ASSERT(DE_FALSE);
853 break;
854 }
855 }
856 }
857
858 if (program->hasStage(glu::SHADERTYPE_GEOMETRY))
859 program->setGeometryNumOutputVertices(1);
860 if (program->hasStage(glu::SHADERTYPE_TESSELLATION_CONTROL) || program->hasStage(glu::SHADERTYPE_TESSELLATION_EVALUATION))
861 program->setTessellationNumOutputPatchVertices(1);
862
863 return program;
864 }
865
checkAndLogProgram(const glu::ShaderProgram & program,const ProgramInterfaceDefinition::Program * programDefinition,const glw::Functions & gl,tcu::TestLog & log)866 static void checkAndLogProgram (const glu::ShaderProgram& program, const ProgramInterfaceDefinition::Program* programDefinition, const glw::Functions& gl, tcu::TestLog& log)
867 {
868 const tcu::ScopedLogSection section(log, "Program", "Program");
869
870 log << program;
871 if (!program.isOk())
872 {
873 log << tcu::TestLog::Message << "Program build failed, checking if program exceeded implementation limits" << tcu::TestLog::EndMessage;
874 checkProgramResourceUsage(programDefinition, gl, log);
875
876 // within limits
877 throw tcu::TestError("could not build program");
878 }
879 }
880
881 // Resource list query case
882
883 class ResourceListTestCase : public TestCase
884 {
885 public:
886 ResourceListTestCase (Context& context, const ResourceDefinition::Node::SharedPtr& targetResource, ProgramInterface interface, const char* name = DE_NULL);
887 ~ResourceListTestCase (void);
888
889 protected:
890 void init (void);
891 void deinit (void);
892 IterateResult iterate (void);
893
894 void queryResourceList (std::vector<std::string>& dst, glw::GLuint program);
895 bool verifyResourceList (const std::vector<std::string>& resourceList, const std::vector<std::string>& expectedResources);
896 bool verifyResourceIndexQuery (const std::vector<std::string>& resourceList, const std::vector<std::string>& referenceResources, glw::GLuint program);
897 bool verifyMaxNameLength (const std::vector<std::string>& referenceResourceList, glw::GLuint program);
898
899 static std::string genTestCaseName (ProgramInterface interface, const ResourceDefinition::Node*);
900 static bool isArrayedInterface (ProgramInterface interface, deUint32 stageBits);
901
902 const ProgramInterface m_programInterface;
903 ResourceDefinition::Node::SharedPtr m_targetResource;
904 ProgramInterfaceDefinition::Program* m_programDefinition;
905 };
906
ResourceListTestCase(Context & context,const ResourceDefinition::Node::SharedPtr & targetResource,ProgramInterface interface,const char * name)907 ResourceListTestCase::ResourceListTestCase (Context& context, const ResourceDefinition::Node::SharedPtr& targetResource, ProgramInterface interface, const char* name)
908 : TestCase (context, (name == DE_NULL) ? (genTestCaseName(interface, targetResource.get()).c_str()) : (name), "")
909 , m_programInterface (interface)
910 , m_targetResource (targetResource)
911 , m_programDefinition (DE_NULL)
912 {
913 // GL_ATOMIC_COUNTER_BUFFER: no resource names
914 DE_ASSERT(m_programInterface != PROGRAMINTERFACE_ATOMIC_COUNTER_BUFFER);
915 }
916
~ResourceListTestCase(void)917 ResourceListTestCase::~ResourceListTestCase (void)
918 {
919 deinit();
920 }
921
init(void)922 void ResourceListTestCase::init (void)
923 {
924 m_programDefinition = generateProgramDefinitionFromResource(m_targetResource.get()).release();
925 const bool supportsES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2));
926
927 if ((m_programDefinition->hasStage(glu::SHADERTYPE_TESSELLATION_CONTROL) || m_programDefinition->hasStage(glu::SHADERTYPE_TESSELLATION_EVALUATION)) &&
928 !supportsES32 && !m_context.getContextInfo().isExtensionSupported("GL_EXT_tessellation_shader"))
929 {
930 throw tcu::NotSupportedError("Test requires GL_EXT_tessellation_shader extension");
931 }
932 if (m_programDefinition->hasStage(glu::SHADERTYPE_GEOMETRY) &&
933 !supportsES32 && !m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader"))
934 {
935 throw tcu::NotSupportedError("Test requires GL_EXT_geometry_shader extension");
936 }
937 if (programContainsIOBlocks(m_programDefinition) &&
938 !supportsES32 && !m_context.getContextInfo().isExtensionSupported("GL_EXT_shader_io_blocks"))
939 {
940 throw tcu::NotSupportedError("Test requires GL_EXT_shader_io_blocks extension");
941 }
942 }
943
deinit(void)944 void ResourceListTestCase::deinit (void)
945 {
946 m_targetResource.clear();
947
948 delete m_programDefinition;
949 m_programDefinition = DE_NULL;
950 }
951
iterate(void)952 ResourceListTestCase::IterateResult ResourceListTestCase::iterate (void)
953 {
954 const glu::ShaderProgram program(m_context.getRenderContext(), generateProgramInterfaceProgramSources(m_programDefinition));
955
956 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
957 checkAndLogProgram(program, m_programDefinition, m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
958
959 // Check resource list
960 {
961 const tcu::ScopedLogSection section (m_testCtx.getLog(), "ResourceList", "Resource list");
962 std::vector<std::string> resourceList;
963 std::vector<std::string> expectedResources;
964
965 queryResourceList(resourceList, program.getProgram());
966 expectedResources = getProgramInterfaceResourceList(m_programDefinition, m_programInterface);
967
968 // verify the list and the expected list match
969
970 if (!verifyResourceList(resourceList, expectedResources))
971 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "invalid resource list");
972
973 // verify GetProgramResourceIndex() matches the indices of the list
974
975 if (!verifyResourceIndexQuery(resourceList, expectedResources, program.getProgram()))
976 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "GetProgramResourceIndex returned unexpected values");
977
978 // Verify MAX_NAME_LENGTH
979 if (!verifyMaxNameLength(resourceList, program.getProgram()))
980 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "MAX_NAME_LENGTH invalid");
981 }
982
983 return STOP;
984 }
985
queryResourceList(std::vector<std::string> & dst,glw::GLuint program)986 void ResourceListTestCase::queryResourceList (std::vector<std::string>& dst, glw::GLuint program)
987 {
988 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
989 const glw::GLenum programInterface = getProgramInterfaceGLEnum(m_programInterface);
990 glw::GLint numActiveResources = 0;
991 glw::GLint maxNameLength = 0;
992 std::vector<char> buffer;
993
994 m_testCtx.getLog() << tcu::TestLog::Message << "Querying " << glu::getProgramInterfaceName(programInterface) << " interface:" << tcu::TestLog::EndMessage;
995
996 gl.getProgramInterfaceiv(program, programInterface, GL_ACTIVE_RESOURCES, &numActiveResources);
997 gl.getProgramInterfaceiv(program, programInterface, GL_MAX_NAME_LENGTH, &maxNameLength);
998 GLU_EXPECT_NO_ERROR(gl.getError(), "query interface");
999
1000 m_testCtx.getLog() << tcu::TestLog::Message
1001 << "\tGL_ACTIVE_RESOURCES = " << numActiveResources << "\n"
1002 << "\tGL_MAX_NAME_LENGTH = " << maxNameLength
1003 << tcu::TestLog::EndMessage;
1004
1005 m_testCtx.getLog() << tcu::TestLog::Message << "Querying all active resources" << tcu::TestLog::EndMessage;
1006
1007 buffer.resize(maxNameLength+1, '\0');
1008
1009 for (int resourceNdx = 0; resourceNdx < numActiveResources; ++resourceNdx)
1010 {
1011 glw::GLint written = 0;
1012
1013 gl.getProgramResourceName(program, programInterface, resourceNdx, maxNameLength, &written, &buffer[0]);
1014 GLU_EXPECT_NO_ERROR(gl.getError(), "query resource name");
1015
1016 dst.push_back(std::string(&buffer[0], written));
1017 }
1018 }
1019
verifyResourceList(const std::vector<std::string> & resourceList,const std::vector<std::string> & expectedResources)1020 bool ResourceListTestCase::verifyResourceList (const std::vector<std::string>& resourceList, const std::vector<std::string>& expectedResources)
1021 {
1022 bool error = false;
1023
1024 // Log and compare resource lists
1025
1026 m_testCtx.getLog() << tcu::TestLog::Message << "GL returned resources:" << tcu::TestLog::EndMessage;
1027
1028 for (int ndx = 0; ndx < (int)resourceList.size(); ++ndx)
1029 {
1030 // dummyZero is a uniform that may be added by
1031 // generateProgramInterfaceProgramSources. Omit it here to avoid
1032 // confusion about the output.
1033 if (resourceList[ndx] != getDummyZeroUniformName())
1034 m_testCtx.getLog() << tcu::TestLog::Message << "\t" << ndx << ": " << resourceList[ndx] << tcu::TestLog::EndMessage;
1035 }
1036
1037 m_testCtx.getLog() << tcu::TestLog::Message << "Expected list of resources:" << tcu::TestLog::EndMessage;
1038
1039 for (int ndx = 0; ndx < (int)expectedResources.size(); ++ndx)
1040 m_testCtx.getLog() << tcu::TestLog::Message << "\t" << ndx << ": " << expectedResources[ndx] << tcu::TestLog::EndMessage;
1041
1042 m_testCtx.getLog() << tcu::TestLog::Message << "Verifying resource list contents." << tcu::TestLog::EndMessage;
1043
1044 for (int ndx = 0; ndx < (int)expectedResources.size(); ++ndx)
1045 {
1046 if (!de::contains(resourceList.begin(), resourceList.end(), expectedResources[ndx]))
1047 {
1048 m_testCtx.getLog() << tcu::TestLog::Message << "Error, resource list did not contain active resource " << expectedResources[ndx] << tcu::TestLog::EndMessage;
1049 error = true;
1050 }
1051 }
1052
1053 for (int ndx = 0; ndx < (int)resourceList.size(); ++ndx)
1054 {
1055 if (!de::contains(expectedResources.begin(), expectedResources.end(), resourceList[ndx]))
1056 {
1057 // Ignore all builtin variables or the variable dummyZero,
1058 // mismatch causes errors otherwise. dummyZero is a uniform that
1059 // may be added by generateProgramInterfaceProgramSources.
1060 if (deStringBeginsWith(resourceList[ndx].c_str(), "gl_") == DE_FALSE &&
1061 resourceList[ndx] != getDummyZeroUniformName())
1062 {
1063 m_testCtx.getLog() << tcu::TestLog::Message << "Error, resource list contains unexpected resource name " << resourceList[ndx] << tcu::TestLog::EndMessage;
1064 error = true;
1065 }
1066 else
1067 m_testCtx.getLog() << tcu::TestLog::Message << "Note, resource list contains unknown built-in " << resourceList[ndx] << ". This variable is ignored." << tcu::TestLog::EndMessage;
1068 }
1069 }
1070
1071 return !error;
1072 }
1073
verifyResourceIndexQuery(const std::vector<std::string> & resourceList,const std::vector<std::string> & referenceResources,glw::GLuint program)1074 bool ResourceListTestCase::verifyResourceIndexQuery (const std::vector<std::string>& resourceList, const std::vector<std::string>& referenceResources, glw::GLuint program)
1075 {
1076 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1077 const glw::GLenum programInterface = getProgramInterfaceGLEnum(m_programInterface);
1078 bool error = false;
1079
1080 m_testCtx.getLog() << tcu::TestLog::Message << "Verifying GetProgramResourceIndex returns correct indices for resource names." << tcu::TestLog::EndMessage;
1081
1082 for (int ndx = 0; ndx < (int)referenceResources.size(); ++ndx)
1083 {
1084 const glw::GLuint index = gl.getProgramResourceIndex(program, programInterface, referenceResources[ndx].c_str());
1085 GLU_EXPECT_NO_ERROR(gl.getError(), "query resource index");
1086
1087 if (index == GL_INVALID_INDEX)
1088 {
1089 m_testCtx.getLog() << tcu::TestLog::Message << "Error, for active resource \"" << referenceResources[ndx] << "\" got index GL_INVALID_INDEX." << tcu::TestLog::EndMessage;
1090 error = true;
1091 }
1092 else if ((int)index >= (int)resourceList.size())
1093 {
1094 m_testCtx.getLog() << tcu::TestLog::Message << "Error, for active resource \"" << referenceResources[ndx] << "\" got index " << index << " (larger or equal to GL_ACTIVE_RESOURCES)." << tcu::TestLog::EndMessage;
1095 error = true;
1096 }
1097 else if (resourceList[index] != referenceResources[ndx])
1098 {
1099 m_testCtx.getLog() << tcu::TestLog::Message << "Error, for active resource \"" << referenceResources[ndx] << "\" got index (index = " << index << ") of another resource (" << resourceList[index] << ")." << tcu::TestLog::EndMessage;
1100 error = true;
1101 }
1102 }
1103
1104 // Query for "name" should match "name[0]" except for XFB
1105
1106 if (m_programInterface != PROGRAMINTERFACE_TRANSFORM_FEEDBACK_VARYING)
1107 {
1108 for (int ndx = 0; ndx < (int)referenceResources.size(); ++ndx)
1109 {
1110 if (de::endsWith(referenceResources[ndx], "[0]"))
1111 {
1112 const std::string queryString = referenceResources[ndx].substr(0, referenceResources[ndx].length()-3);
1113 const glw::GLuint index = gl.getProgramResourceIndex(program, programInterface, queryString.c_str());
1114 GLU_EXPECT_NO_ERROR(gl.getError(), "query resource index");
1115
1116 if (index == GL_INVALID_INDEX)
1117 {
1118 m_testCtx.getLog() << tcu::TestLog::Message << "Error, query for \"" << queryString << "\" resulted in index GL_INVALID_INDEX." << tcu::TestLog::EndMessage;
1119 error = true;
1120 }
1121 else if ((int)index >= (int)resourceList.size())
1122 {
1123 m_testCtx.getLog() << tcu::TestLog::Message << "Error, query for \"" << queryString << "\" resulted in index " << index << " (larger or equal to GL_ACTIVE_RESOURCES)." << tcu::TestLog::EndMessage;
1124 error = true;
1125 }
1126 else if (resourceList[index] != queryString + "[0]")
1127 {
1128 m_testCtx.getLog() << tcu::TestLog::Message << "Error, query for \"" << queryString << "\" got index (index = " << index << ") of another resource (\"" << resourceList[index] << "\")." << tcu::TestLog::EndMessage;
1129 error = true;
1130 }
1131 }
1132 }
1133 }
1134
1135 return !error;
1136 }
1137
verifyMaxNameLength(const std::vector<std::string> & resourceList,glw::GLuint program)1138 bool ResourceListTestCase::verifyMaxNameLength (const std::vector<std::string>& resourceList, glw::GLuint program)
1139 {
1140 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1141 const glw::GLenum programInterface = getProgramInterfaceGLEnum(m_programInterface);
1142 glw::GLint maxNameLength = 0;
1143 glw::GLint expectedMaxNameLength = 0;
1144
1145 gl.getProgramInterfaceiv(program, programInterface, GL_MAX_NAME_LENGTH, &maxNameLength);
1146 GLU_EXPECT_NO_ERROR(gl.getError(), "query interface");
1147
1148 for (int ndx = 0; ndx < (int)resourceList.size(); ++ndx)
1149 expectedMaxNameLength = de::max(expectedMaxNameLength, (int)resourceList[ndx].size() + 1);
1150
1151 m_testCtx.getLog() << tcu::TestLog::Message << "Verifying MAX_NAME_LENGTH, expecting " << expectedMaxNameLength << " (i.e. consistent with the queried resource list)" << tcu::TestLog::EndMessage;
1152
1153 if (expectedMaxNameLength != maxNameLength)
1154 {
1155 m_testCtx.getLog() << tcu::TestLog::Message << "Error, got " << maxNameLength << tcu::TestLog::EndMessage;
1156 return false;
1157 }
1158
1159 return true;
1160 }
1161
genTestCaseName(ProgramInterface interface,const ResourceDefinition::Node * root)1162 std::string ResourceListTestCase::genTestCaseName (ProgramInterface interface, const ResourceDefinition::Node* root)
1163 {
1164 bool isImplicitlySizedArray = false;
1165 bool hasVariable = false;
1166 bool accumulateName = true;
1167 std::string buf = "var";
1168 std::string prefix;
1169
1170 for (const ResourceDefinition::Node* node = root; node; node = node->getEnclosingNode())
1171 {
1172 switch (node->getType())
1173 {
1174 case ResourceDefinition::Node::TYPE_VARIABLE:
1175 {
1176 hasVariable = true;
1177 break;
1178 }
1179
1180 case ResourceDefinition::Node::TYPE_STRUCT_MEMBER:
1181 {
1182 if (accumulateName)
1183 buf += "_struct";
1184 break;
1185 }
1186
1187 case ResourceDefinition::Node::TYPE_ARRAY_ELEMENT:
1188 {
1189 DE_ASSERT(dynamic_cast<const ResourceDefinition::ArrayElement*>(node));
1190 const ResourceDefinition::ArrayElement* arrayElement = static_cast<const ResourceDefinition::ArrayElement*>(node);
1191
1192 isImplicitlySizedArray = (arrayElement->m_arraySize == ResourceDefinition::ArrayElement::UNSIZED_ARRAY);
1193
1194 if (accumulateName)
1195 buf += "_array";
1196 break;
1197 }
1198
1199 case ResourceDefinition::Node::TYPE_STORAGE_QUALIFIER:
1200 {
1201 DE_ASSERT(dynamic_cast<const ResourceDefinition::StorageQualifier*>(node));
1202 const ResourceDefinition::StorageQualifier* storageDef = static_cast<const ResourceDefinition::StorageQualifier*>(node);
1203
1204 if (storageDef->m_storage == glu::STORAGE_PATCH_IN ||
1205 storageDef->m_storage == glu::STORAGE_PATCH_OUT)
1206 {
1207 if (accumulateName)
1208 prefix += "patch_";
1209 }
1210 break;
1211 }
1212
1213 case ResourceDefinition::Node::TYPE_SHADER:
1214 case ResourceDefinition::Node::TYPE_SHADER_SET:
1215 {
1216 bool arrayedInterface;
1217
1218 if (node->getType() == ResourceDefinition::Node::TYPE_SHADER)
1219 {
1220 DE_ASSERT(dynamic_cast<const ResourceDefinition::Shader*>(node));
1221 const ResourceDefinition::Shader* shaderDef = static_cast<const ResourceDefinition::Shader*>(node);
1222
1223 arrayedInterface = isArrayedInterface(interface, (1u << shaderDef->m_type));
1224 }
1225 else
1226 {
1227 DE_ASSERT(node->getType() == ResourceDefinition::Node::TYPE_SHADER_SET);
1228 DE_ASSERT(dynamic_cast<const ResourceDefinition::ShaderSet*>(node));
1229 const ResourceDefinition::ShaderSet* shaderDef = static_cast<const ResourceDefinition::ShaderSet*>(node);
1230
1231 arrayedInterface = isArrayedInterface(interface, shaderDef->getReferencingMask());
1232 }
1233
1234 if (arrayedInterface && isImplicitlySizedArray)
1235 {
1236 // omit implicit arrayness from name, i.e. remove trailing "_array"
1237 DE_ASSERT(de::endsWith(buf, "_array"));
1238 buf = buf.substr(0, buf.length() - 6);
1239 }
1240
1241 break;
1242 }
1243
1244 case ResourceDefinition::Node::TYPE_INTERFACE_BLOCK:
1245 {
1246 accumulateName = false;
1247 break;
1248 }
1249
1250 default:
1251 break;
1252 }
1253 }
1254
1255 if (!hasVariable)
1256 return prefix + "empty";
1257 else
1258 return prefix + buf;
1259 }
1260
isArrayedInterface(ProgramInterface interface,deUint32 stageBits)1261 bool ResourceListTestCase::isArrayedInterface (ProgramInterface interface, deUint32 stageBits)
1262 {
1263 if (interface == PROGRAMINTERFACE_PROGRAM_INPUT)
1264 {
1265 const glu::ShaderType firstStage = getShaderMaskFirstStage(stageBits);
1266 return firstStage == glu::SHADERTYPE_TESSELLATION_CONTROL ||
1267 firstStage == glu::SHADERTYPE_TESSELLATION_EVALUATION ||
1268 firstStage == glu::SHADERTYPE_GEOMETRY;
1269 }
1270 else if (interface == PROGRAMINTERFACE_PROGRAM_OUTPUT)
1271 {
1272 const glu::ShaderType lastStage = getShaderMaskLastStage(stageBits);
1273 return lastStage == glu::SHADERTYPE_TESSELLATION_CONTROL;
1274 }
1275 return false;
1276 }
1277
1278 // Resouce property query case
1279
1280 class ResourceTestCase : public ProgramInterfaceQueryTestCase
1281 {
1282 public:
1283 ResourceTestCase (Context& context, const ResourceDefinition::Node::SharedPtr& targetResource, const ProgramResourceQueryTestTarget& queryTarget, const char* name = DE_NULL);
1284 ~ResourceTestCase (void);
1285
1286 private:
1287 void init (void);
1288 void deinit (void);
1289 const ProgramInterfaceDefinition::Program* getProgramDefinition (void) const;
1290 std::vector<std::string> getQueryTargetResources (void) const;
1291
1292 static std::string genTestCaseName (const ResourceDefinition::Node*);
1293 static std::string genMultilineDescription (const ResourceDefinition::Node*);
1294
1295 ResourceDefinition::Node::SharedPtr m_targetResource;
1296 ProgramInterfaceDefinition::Program* m_program;
1297 std::vector<std::string> m_targetResources;
1298 };
1299
ResourceTestCase(Context & context,const ResourceDefinition::Node::SharedPtr & targetResource,const ProgramResourceQueryTestTarget & queryTarget,const char * name)1300 ResourceTestCase::ResourceTestCase (Context& context, const ResourceDefinition::Node::SharedPtr& targetResource, const ProgramResourceQueryTestTarget& queryTarget, const char* name)
1301 : ProgramInterfaceQueryTestCase (context, (name == DE_NULL) ? (genTestCaseName(targetResource.get()).c_str()) : (name), "", queryTarget)
1302 , m_targetResource (targetResource)
1303 , m_program (DE_NULL)
1304 {
1305 }
1306
~ResourceTestCase(void)1307 ResourceTestCase::~ResourceTestCase (void)
1308 {
1309 deinit();
1310 }
1311
init(void)1312 void ResourceTestCase::init (void)
1313 {
1314 m_testCtx.getLog()
1315 << tcu::TestLog::Message
1316 << genMultilineDescription(m_targetResource.get())
1317 << tcu::TestLog::EndMessage;
1318
1319 // Program
1320 {
1321 // Generate interface with target resource
1322 m_program = generateProgramDefinitionFromResource(m_targetResource.get()).release();
1323 m_targetResources = getProgramInterfaceResourceList(m_program, getTargetInterface());
1324 }
1325 }
1326
deinit(void)1327 void ResourceTestCase::deinit (void)
1328 {
1329 m_targetResource.clear();
1330
1331 delete m_program;
1332 m_program = DE_NULL;
1333
1334 m_targetResources = std::vector<std::string>();
1335 }
1336
getProgramDefinition(void) const1337 const ProgramInterfaceDefinition::Program* ResourceTestCase::getProgramDefinition (void) const
1338 {
1339 return m_program;
1340 }
1341
getQueryTargetResources(void) const1342 std::vector<std::string> ResourceTestCase::getQueryTargetResources (void) const
1343 {
1344 return m_targetResources;
1345 }
1346
genTestCaseName(const ResourceDefinition::Node * resource)1347 std::string ResourceTestCase::genTestCaseName (const ResourceDefinition::Node* resource)
1348 {
1349 if (resource->getType() == ResourceDefinition::Node::TYPE_VARIABLE)
1350 {
1351 DE_ASSERT(dynamic_cast<const ResourceDefinition::Variable*>(resource));
1352
1353 const ResourceDefinition::Variable* variable = static_cast<const ResourceDefinition::Variable*>(resource);
1354
1355 return convertGLTypeNameToTestName(glu::getDataTypeName(variable->m_dataType));
1356 }
1357
1358 DE_ASSERT(false);
1359 return "";
1360 }
1361
genMultilineDescription(const ResourceDefinition::Node * resource)1362 std::string ResourceTestCase::genMultilineDescription (const ResourceDefinition::Node* resource)
1363 {
1364 if (resource->getType() == ResourceDefinition::Node::TYPE_VARIABLE)
1365 {
1366 DE_ASSERT(dynamic_cast<const ResourceDefinition::Variable*>(resource));
1367
1368 const ResourceDefinition::Variable* varDef = static_cast<const ResourceDefinition::Variable*>(resource);
1369 std::ostringstream buf;
1370 std::ostringstream structureDescriptor;
1371 std::string uniformType;
1372
1373 for (const ResourceDefinition::Node* node = resource; node; node = node->getEnclosingNode())
1374 {
1375 if (node->getType() == ResourceDefinition::Node::TYPE_STORAGE_QUALIFIER)
1376 {
1377 DE_ASSERT(dynamic_cast<const ResourceDefinition::StorageQualifier*>(node));
1378
1379 const ResourceDefinition::StorageQualifier* storageDef = static_cast<const ResourceDefinition::StorageQualifier*>(node);
1380
1381 uniformType = std::string(" ") + glu::getStorageName(storageDef->m_storage);
1382 structureDescriptor << "\n\tdeclared as \"" << glu::getStorageName(storageDef->m_storage) << "\"";
1383 }
1384
1385 if (node->getType() == ResourceDefinition::Node::TYPE_ARRAY_ELEMENT)
1386 structureDescriptor << "\n\tarray";
1387
1388 if (node->getType() == ResourceDefinition::Node::TYPE_STRUCT_MEMBER)
1389 structureDescriptor << "\n\tin a struct";
1390
1391 if (node->getType() == ResourceDefinition::Node::TYPE_DEFAULT_BLOCK)
1392 structureDescriptor << "\n\tin the default block";
1393
1394 if (node->getType() == ResourceDefinition::Node::TYPE_INTERFACE_BLOCK)
1395 structureDescriptor << "\n\tin an interface block";
1396 }
1397
1398 buf << "Querying properties of " << glu::getDataTypeName(varDef->m_dataType) << uniformType << " variable.\n"
1399 << "Variable is:\n"
1400 << "\t" << glu::getDataTypeName(varDef->m_dataType)
1401 << structureDescriptor.str();
1402
1403 return buf.str();
1404 }
1405 else if (resource->getType() == ResourceDefinition::Node::TYPE_TRANSFORM_FEEDBACK_TARGET)
1406 {
1407 DE_ASSERT(dynamic_cast<const ResourceDefinition::TransformFeedbackTarget*>(resource));
1408
1409 const ResourceDefinition::TransformFeedbackTarget* xfbDef = static_cast<const ResourceDefinition::TransformFeedbackTarget*>(resource);
1410
1411 DE_ASSERT(xfbDef->m_builtinVarName);
1412
1413 return std::string("Querying properties of a builtin variable ") + xfbDef->m_builtinVarName;
1414 }
1415
1416 DE_ASSERT(false);
1417 return DE_NULL;
1418 }
1419
1420 class ResourceNameBufferLimitCase : public TestCase
1421 {
1422 public:
1423 ResourceNameBufferLimitCase (Context& context, const char* name, const char* description);
1424 ~ResourceNameBufferLimitCase (void);
1425
1426 private:
1427 IterateResult iterate (void);
1428 };
1429
ResourceNameBufferLimitCase(Context & context,const char * name,const char * description)1430 ResourceNameBufferLimitCase::ResourceNameBufferLimitCase (Context& context, const char* name, const char* description)
1431 : TestCase(context, name, description)
1432 {
1433 }
1434
~ResourceNameBufferLimitCase(void)1435 ResourceNameBufferLimitCase::~ResourceNameBufferLimitCase (void)
1436 {
1437 }
1438
iterate(void)1439 ResourceNameBufferLimitCase::IterateResult ResourceNameBufferLimitCase::iterate (void)
1440 {
1441 static const char* const computeSource = "${GLSL_VERSION_DECL}\n"
1442 "layout(local_size_x = 1) in;\n"
1443 "uniform highp int u_uniformWithALongName;\n"
1444 "writeonly buffer OutputBufferBlock { highp int b_output_int; };\n"
1445 "void main ()\n"
1446 "{\n"
1447 " b_output_int = u_uniformWithALongName;\n"
1448 "}\n";
1449
1450 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1451 const glu::ShaderProgram program (m_context.getRenderContext(), glu::ProgramSources() << glu::ComputeSource(specializeShader(m_context, computeSource)));
1452 glw::GLuint uniformIndex;
1453
1454 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1455
1456 // Log program
1457 {
1458 const tcu::ScopedLogSection section(m_testCtx.getLog(), "Program", "Program");
1459
1460 m_testCtx.getLog() << program;
1461 if (!program.isOk())
1462 throw tcu::TestError("could not build program");
1463 }
1464
1465 uniformIndex = gl.getProgramResourceIndex(program.getProgram(), GL_UNIFORM, "u_uniformWithALongName");
1466 GLU_EXPECT_NO_ERROR(gl.getError(), "query resource index");
1467
1468 if (uniformIndex == GL_INVALID_INDEX)
1469 throw tcu::TestError("Uniform u_uniformWithALongName resource index was GL_INVALID_INDEX");
1470
1471 // Query with different sized buffers, len("u_uniformWithALongName") == 22
1472
1473 {
1474 static const struct
1475 {
1476 const char* description;
1477 int querySize;
1478 bool returnLength;
1479 } querySizes[] =
1480 {
1481 { "Query to larger buffer", 24, true },
1482 { "Query to buffer the same size", 23, true },
1483 { "Query to one byte too small buffer", 22, true },
1484 { "Query to one byte buffer", 1, true },
1485 { "Query to zero sized buffer", 0, true },
1486 { "Query to one byte too small buffer, null length argument", 22, false },
1487 { "Query to one byte buffer, null length argument", 1, false },
1488 { "Query to zero sized buffer, null length argument", 0, false },
1489 };
1490
1491 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(querySizes); ++ndx)
1492 {
1493 const tcu::ScopedLogSection section (m_testCtx.getLog(), "Query", querySizes[ndx].description);
1494 const int uniformNameLen = 22;
1495 const int expectedWriteLen = (querySizes[ndx].querySize != 0) ? (de::min(uniformNameLen, (querySizes[ndx].querySize - 1))) : (0);
1496 char buffer [26];
1497 glw::GLsizei written = -1;
1498
1499 // One byte for guard
1500 DE_ASSERT((int)sizeof(buffer) > querySizes[ndx].querySize);
1501
1502 deMemset(buffer, 'x', sizeof(buffer));
1503
1504 if (querySizes[ndx].querySize)
1505 m_testCtx.getLog()
1506 << tcu::TestLog::Message
1507 << "Querying uniform name to a buffer of size " << querySizes[ndx].querySize
1508 << ", expecting query to write " << expectedWriteLen << " bytes followed by a null terminator"
1509 << tcu::TestLog::EndMessage;
1510 else
1511 m_testCtx.getLog()
1512 << tcu::TestLog::Message
1513 << "Querying uniform name to a buffer of size " << querySizes[ndx].querySize
1514 << ", expecting query to write 0 bytes"
1515 << tcu::TestLog::EndMessage;
1516
1517 gl.getProgramResourceName(program.getProgram(), GL_UNIFORM, uniformIndex, querySizes[ndx].querySize, (querySizes[ndx].returnLength) ? (&written) : (DE_NULL), buffer);
1518 GLU_EXPECT_NO_ERROR(gl.getError(), "query resource name");
1519
1520 if (querySizes[ndx].returnLength && written != expectedWriteLen)
1521 {
1522 m_testCtx.getLog() << tcu::TestLog::Message << "Error, expected write length of " << expectedWriteLen << ", got " << written << tcu::TestLog::EndMessage;
1523 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Unexpected write lenght");
1524 }
1525 else if (querySizes[ndx].querySize != 0 && buffer[expectedWriteLen] != 0)
1526 {
1527 m_testCtx.getLog() << tcu::TestLog::Message << "Error, expected null terminator at " << expectedWriteLen << ", got dec=" << (int)buffer[expectedWriteLen] << tcu::TestLog::EndMessage;
1528 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Missing null terminator");
1529 }
1530 else if (querySizes[ndx].querySize != 0 && buffer[expectedWriteLen+1] != 'x')
1531 {
1532 m_testCtx.getLog() << tcu::TestLog::Message << "Error, guard at index " << (expectedWriteLen+1) << " was modified, got dec=" << (int)buffer[expectedWriteLen+1] << tcu::TestLog::EndMessage;
1533 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Wrote over buffer size");
1534 }
1535 else if (querySizes[ndx].querySize == 0 && buffer[0] != 'x')
1536 {
1537 m_testCtx.getLog() << tcu::TestLog::Message << "Error, buffer size was 0 but buffer contents were modified. At index 0 got dec=" << (int)buffer[0] << tcu::TestLog::EndMessage;
1538 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Buffer contents were modified");
1539 }
1540 }
1541 }
1542
1543 return STOP;
1544 }
1545
1546 class ResourceQueryBufferLimitCase : public TestCase
1547 {
1548 public:
1549 ResourceQueryBufferLimitCase (Context& context, const char* name, const char* description);
1550 ~ResourceQueryBufferLimitCase (void);
1551
1552 private:
1553 IterateResult iterate (void);
1554 };
1555
ResourceQueryBufferLimitCase(Context & context,const char * name,const char * description)1556 ResourceQueryBufferLimitCase::ResourceQueryBufferLimitCase (Context& context, const char* name, const char* description)
1557 : TestCase(context, name, description)
1558 {
1559 }
1560
~ResourceQueryBufferLimitCase(void)1561 ResourceQueryBufferLimitCase::~ResourceQueryBufferLimitCase (void)
1562 {
1563 }
1564
iterate(void)1565 ResourceQueryBufferLimitCase::IterateResult ResourceQueryBufferLimitCase::iterate (void)
1566 {
1567 static const char* const computeSource = "${GLSL_VERSION_DECL}\n"
1568 "layout(local_size_x = 1) in;\n"
1569 "uniform highp int u_uniform;\n"
1570 "writeonly buffer OutputBufferBlock { highp int b_output_int; };\n"
1571 "void main ()\n"
1572 "{\n"
1573 " b_output_int = u_uniform;\n"
1574 "}\n";
1575
1576 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1577 const glu::ShaderProgram program (m_context.getRenderContext(), glu::ProgramSources() << glu::ComputeSource(specializeShader(m_context, computeSource)));
1578 glw::GLuint uniformIndex;
1579
1580 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1581
1582 // Log program
1583 {
1584 const tcu::ScopedLogSection section(m_testCtx.getLog(), "Program", "Program");
1585
1586 m_testCtx.getLog() << program;
1587 if (!program.isOk())
1588 throw tcu::TestError("could not build program");
1589 }
1590
1591 uniformIndex = gl.getProgramResourceIndex(program.getProgram(), GL_UNIFORM, "u_uniform");
1592 GLU_EXPECT_NO_ERROR(gl.getError(), "query resource index");
1593
1594 if (uniformIndex == GL_INVALID_INDEX)
1595 throw tcu::TestError("Uniform u_uniform resource index was GL_INVALID_INDEX");
1596
1597 // Query uniform properties
1598
1599 {
1600 static const struct
1601 {
1602 const char* description;
1603 int numProps;
1604 int bufferSize;
1605 bool returnLength;
1606 } querySizes[] =
1607 {
1608 { "Query to a larger buffer", 2, 3, true },
1609 { "Query to too small a buffer", 3, 2, true },
1610 { "Query to zero sized buffer", 3, 0, true },
1611 { "Query to a larger buffer, null length argument", 2, 3, false },
1612 { "Query to too small a buffer, null length argument", 3, 2, false },
1613 { "Query to zero sized buffer, null length argument", 3, 0, false },
1614 };
1615
1616 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(querySizes); ++ndx)
1617 {
1618 const tcu::ScopedLogSection section (m_testCtx.getLog(), "QueryToLarger", querySizes[ndx].description);
1619 const glw::GLenum props[] = { GL_LOCATION, GL_LOCATION, GL_LOCATION };
1620 const int expectedWriteLen = de::min(querySizes[ndx].bufferSize, querySizes[ndx].numProps);
1621 int params[] = { 255, 255, 255, 255 };
1622 glw::GLsizei written = -1;
1623
1624 DE_ASSERT(querySizes[ndx].numProps <= DE_LENGTH_OF_ARRAY(props));
1625 DE_ASSERT(querySizes[ndx].bufferSize < DE_LENGTH_OF_ARRAY(params)); // leave at least one element for overflow detection
1626
1627 m_testCtx.getLog()
1628 << tcu::TestLog::Message
1629 << "Querying " << querySizes[ndx].numProps << " uniform prop(s) to a buffer with size " << querySizes[ndx].bufferSize << ". Expecting query to return " << expectedWriteLen << " prop(s)"
1630 << tcu::TestLog::EndMessage;
1631
1632 gl.getProgramResourceiv(program.getProgram(), GL_UNIFORM, uniformIndex, querySizes[ndx].numProps, props, querySizes[ndx].bufferSize, (querySizes[ndx].returnLength) ? (&written) : (DE_NULL), params);
1633 GLU_EXPECT_NO_ERROR(gl.getError(), "query program resources");
1634
1635 if (querySizes[ndx].returnLength && written != expectedWriteLen)
1636 {
1637 m_testCtx.getLog() << tcu::TestLog::Message << "Error, expected write length of " << expectedWriteLen << ", got " << written << tcu::TestLog::EndMessage;
1638 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Unexpected write lenght");
1639 }
1640 else if (params[expectedWriteLen] != 255)
1641 {
1642 m_testCtx.getLog() << tcu::TestLog::Message << "Error, guard at index " << (expectedWriteLen) << " was modified. Was 255 before call, got dec=" << params[expectedWriteLen] << tcu::TestLog::EndMessage;
1643 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Wrote over buffer size");
1644 }
1645 }
1646 }
1647
1648 return STOP;
1649 }
1650
1651 class InterfaceBlockBaseCase : public TestCase
1652 {
1653 public:
1654 enum CaseType
1655 {
1656 CASE_NAMED_BLOCK = 0,
1657 CASE_UNNAMED_BLOCK,
1658 CASE_BLOCK_ARRAY,
1659
1660 CASE_LAST
1661 };
1662
1663 InterfaceBlockBaseCase (Context& context, const char* name, const char* description, glu::Storage storage, CaseType caseType);
1664 ~InterfaceBlockBaseCase (void);
1665
1666 private:
1667 void init (void);
1668 void deinit (void);
1669
1670 protected:
1671 const glu::Storage m_storage;
1672 const CaseType m_caseType;
1673 ProgramInterfaceDefinition::Program* m_program;
1674 };
1675
InterfaceBlockBaseCase(Context & context,const char * name,const char * description,glu::Storage storage,CaseType caseType)1676 InterfaceBlockBaseCase::InterfaceBlockBaseCase (Context& context, const char* name, const char* description, glu::Storage storage, CaseType caseType)
1677 : TestCase (context, name, description)
1678 , m_storage (storage)
1679 , m_caseType (caseType)
1680 , m_program (DE_NULL)
1681 {
1682 DE_ASSERT(storage == glu::STORAGE_UNIFORM || storage == glu::STORAGE_BUFFER);
1683 }
1684
~InterfaceBlockBaseCase(void)1685 InterfaceBlockBaseCase::~InterfaceBlockBaseCase (void)
1686 {
1687 deinit();
1688 }
1689
init(void)1690 void InterfaceBlockBaseCase::init (void)
1691 {
1692 const glu::GLSLVersion glslVersion = glu::getContextTypeGLSLVersion(m_context.getRenderContext().getType());
1693 ProgramInterfaceDefinition::Shader* shader;
1694
1695 m_program = new ProgramInterfaceDefinition::Program();
1696 shader = m_program->addShader(glu::SHADERTYPE_COMPUTE, glslVersion);
1697
1698 // PrecedingInterface
1699 {
1700 glu::InterfaceBlock precedingInterfaceBlock;
1701
1702 precedingInterfaceBlock.interfaceName = "PrecedingInterface";
1703 precedingInterfaceBlock.layout.binding = 0;
1704 precedingInterfaceBlock.storage = m_storage;
1705 precedingInterfaceBlock.instanceName = "precedingInstance";
1706
1707 precedingInterfaceBlock.variables.push_back(glu::VariableDeclaration(glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP), "precedingMember"));
1708
1709 // Unsized array type
1710 if (m_storage == glu::STORAGE_BUFFER)
1711 precedingInterfaceBlock.variables.push_back(glu::VariableDeclaration(glu::VarType(glu::VarType(glu::TYPE_FLOAT, glu::PRECISION_HIGHP), glu::VarType::UNSIZED_ARRAY), "precedingMemberUnsizedArray"));
1712 else
1713 precedingInterfaceBlock.variables.push_back(glu::VariableDeclaration(glu::VarType(glu::VarType(glu::TYPE_FLOAT, glu::PRECISION_HIGHP), 2), "precedingMemberArray"));
1714
1715 shader->getDefaultBlock().interfaceBlocks.push_back(precedingInterfaceBlock);
1716 }
1717
1718 // TargetInterface
1719 {
1720 glu::InterfaceBlock targetInterfaceBlock;
1721
1722 targetInterfaceBlock.interfaceName = "TargetInterface";
1723 targetInterfaceBlock.layout.binding = 1;
1724 targetInterfaceBlock.storage = m_storage;
1725
1726 if (m_caseType == CASE_UNNAMED_BLOCK)
1727 targetInterfaceBlock.instanceName = "";
1728 else
1729 targetInterfaceBlock.instanceName = "targetInstance";
1730
1731 if (m_caseType == CASE_BLOCK_ARRAY)
1732 targetInterfaceBlock.dimensions.push_back(2);
1733
1734 // Basic type
1735 {
1736 targetInterfaceBlock.variables.push_back(glu::VariableDeclaration(glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP), "blockMemberBasic"));
1737 }
1738
1739 // Array type
1740 {
1741 targetInterfaceBlock.variables.push_back(glu::VariableDeclaration(glu::VarType(glu::VarType(glu::TYPE_FLOAT, glu::PRECISION_HIGHP), 3), "blockMemberArray"));
1742 }
1743
1744 // Struct type
1745 {
1746 glu::StructType* structPtr = new glu::StructType("StructType");
1747 structPtr->addMember("structMemberBasic", glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP));
1748 structPtr->addMember("structMemberArray", glu::VarType(glu::VarType(glu::TYPE_FLOAT, glu::PRECISION_HIGHP), 2));
1749
1750 targetInterfaceBlock.variables.push_back(glu::VariableDeclaration(glu::VarType(glu::VarType(structPtr), 2), "blockMemberStruct"));
1751 }
1752
1753 // Unsized array type
1754 if (m_storage == glu::STORAGE_BUFFER)
1755 targetInterfaceBlock.variables.push_back(glu::VariableDeclaration(glu::VarType(glu::VarType(glu::TYPE_FLOAT, glu::PRECISION_HIGHP), glu::VarType::UNSIZED_ARRAY), "blockMemberUnsizedArray"));
1756
1757 shader->getDefaultBlock().interfaceBlocks.push_back(targetInterfaceBlock);
1758 }
1759
1760 // TrailingInterface
1761 {
1762 glu::InterfaceBlock trailingInterfaceBlock;
1763
1764 trailingInterfaceBlock.interfaceName = "TrailingInterface";
1765 trailingInterfaceBlock.layout.binding = 3;
1766 trailingInterfaceBlock.storage = m_storage;
1767 trailingInterfaceBlock.instanceName = "trailingInstance";
1768 trailingInterfaceBlock.variables.push_back(glu::VariableDeclaration(glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP), "trailingMember"));
1769
1770 shader->getDefaultBlock().interfaceBlocks.push_back(trailingInterfaceBlock);
1771 }
1772
1773 DE_ASSERT(m_program->isValid());
1774 }
1775
deinit(void)1776 void InterfaceBlockBaseCase::deinit (void)
1777 {
1778 delete m_program;
1779 m_program = DE_NULL;
1780 }
1781
1782 class InterfaceBlockActiveVariablesTestCase : public InterfaceBlockBaseCase
1783 {
1784 public:
1785 InterfaceBlockActiveVariablesTestCase (Context& context, const char* name, const char* description, glu::Storage storage, CaseType caseType);
1786
1787 private:
1788 IterateResult iterate (void);
1789 };
1790
InterfaceBlockActiveVariablesTestCase(Context & context,const char * name,const char * description,glu::Storage storage,CaseType caseType)1791 InterfaceBlockActiveVariablesTestCase::InterfaceBlockActiveVariablesTestCase (Context& context, const char* name, const char* description, glu::Storage storage, CaseType caseType)
1792 : InterfaceBlockBaseCase(context, name, description, storage, caseType)
1793 {
1794 }
1795
iterate(void)1796 InterfaceBlockActiveVariablesTestCase::IterateResult InterfaceBlockActiveVariablesTestCase::iterate (void)
1797 {
1798 const ProgramInterface programInterface = (m_storage == glu::STORAGE_UNIFORM) ? (PROGRAMINTERFACE_UNIFORM_BLOCK) :
1799 (m_storage == glu::STORAGE_BUFFER) ? (PROGRAMINTERFACE_SHADER_STORAGE_BLOCK) :
1800 (PROGRAMINTERFACE_LAST);
1801 const glw::GLenum programGLInterfaceValue = getProgramInterfaceGLEnum(programInterface);
1802 const glw::GLenum programMemberInterfaceValue = (m_storage == glu::STORAGE_UNIFORM) ? (GL_UNIFORM) :
1803 (m_storage == glu::STORAGE_BUFFER) ? (GL_BUFFER_VARIABLE) :
1804 (0);
1805 const std::vector<std::string> blockNames = getProgramInterfaceResourceList(m_program, programInterface);
1806 glu::ShaderProgram program (m_context.getRenderContext(), generateProgramInterfaceProgramSources(m_program));
1807 int expectedMaxNumActiveVariables = 0;
1808
1809 DE_ASSERT(programInterface != PROGRAMINTERFACE_LAST);
1810
1811 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1812 checkAndLogProgram(program, m_program, m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
1813
1814 // Verify all blocks
1815
1816 for (int blockNdx = 0; blockNdx < (int)blockNames.size(); ++blockNdx)
1817 {
1818 const tcu::ScopedLogSection section (m_testCtx.getLog(), "Block", "Block \"" + blockNames[blockNdx] + "\"");
1819 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1820 const glw::GLuint resourceNdx = gl.getProgramResourceIndex(program.getProgram(), programGLInterfaceValue, blockNames[blockNdx].c_str());
1821 glw::GLint numActiveResources;
1822 std::vector<std::string> activeResourceNames;
1823
1824 GLU_EXPECT_NO_ERROR(gl.getError(), "query resource index");
1825
1826 if (resourceNdx == GL_INVALID_INDEX)
1827 {
1828 m_testCtx.getLog() << tcu::TestLog::Message << "Error, getProgramResourceIndex returned GL_INVALID_INDEX for \"" << blockNames[blockNdx] << "\"" << tcu::TestLog::EndMessage;
1829 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Resource not found");
1830 continue;
1831 }
1832
1833 // query block information
1834
1835 {
1836 const glw::GLenum props[] = { GL_NUM_ACTIVE_VARIABLES };
1837 glw::GLint retBuffer[2] = { -1, -1 };
1838 glw::GLint written = -1;
1839
1840 gl.getProgramResourceiv(program.getProgram(), programGLInterfaceValue, resourceNdx, DE_LENGTH_OF_ARRAY(props), props, 1, &written, retBuffer);
1841 GLU_EXPECT_NO_ERROR(gl.getError(), "query GL_NUM_ACTIVE_VARIABLES");
1842
1843 numActiveResources = retBuffer[0];
1844 expectedMaxNumActiveVariables = de::max(expectedMaxNumActiveVariables, numActiveResources);
1845 m_testCtx.getLog() << tcu::TestLog::Message << "NUM_ACTIVE_VARIABLES = " << numActiveResources << tcu::TestLog::EndMessage;
1846
1847 if (written == -1 || retBuffer[0] == -1)
1848 {
1849 m_testCtx.getLog() << tcu::TestLog::Message << "Error, Query for NUM_ACTIVE_VARIABLES did not return a value" << tcu::TestLog::EndMessage;
1850 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Query for NUM_ACTIVE_VARIABLES failed");
1851 continue;
1852 }
1853 else if (retBuffer[1] != -1)
1854 {
1855 m_testCtx.getLog() << tcu::TestLog::Message << "Error, Query for NUM_ACTIVE_VARIABLES returned too many values" << tcu::TestLog::EndMessage;
1856 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Query for NUM_ACTIVE_VARIABLES returned too many values");
1857 continue;
1858 }
1859 else if (retBuffer[0] < 0)
1860 {
1861 m_testCtx.getLog() << tcu::TestLog::Message << "Error, NUM_ACTIVE_VARIABLES < 0" << tcu::TestLog::EndMessage;
1862 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "NUM_ACTIVE_VARIABLES < 0");
1863 continue;
1864 }
1865 }
1866
1867 // query block variable information
1868
1869 {
1870 const glw::GLenum props[] = { GL_ACTIVE_VARIABLES };
1871 std::vector<glw::GLint> activeVariableIndices (numActiveResources + 1, -1); // Allocate one extra trailing to detect wrong write lengths
1872 glw::GLint written = -1;
1873
1874 gl.getProgramResourceiv(program.getProgram(), programGLInterfaceValue, resourceNdx, DE_LENGTH_OF_ARRAY(props), props, (glw::GLsizei)activeVariableIndices.size(), &written, &activeVariableIndices[0]);
1875 GLU_EXPECT_NO_ERROR(gl.getError(), "query GL_ACTIVE_VARIABLES");
1876
1877 if (written == -1)
1878 {
1879 m_testCtx.getLog() << tcu::TestLog::Message << "Error, Query for GL_ACTIVE_VARIABLES did not return any values" << tcu::TestLog::EndMessage;
1880 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Query for GL_ACTIVE_VARIABLES failed");
1881 continue;
1882 }
1883 else if (written != numActiveResources)
1884 {
1885 m_testCtx.getLog() << tcu::TestLog::Message << "Error, Query for GL_ACTIVE_VARIABLES did not return NUM_ACTIVE_VARIABLES values" << tcu::TestLog::EndMessage;
1886 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Query for GL_ACTIVE_VARIABLES returned invalid number of values");
1887 continue;
1888 }
1889 else if (activeVariableIndices.back() != -1)
1890 {
1891 m_testCtx.getLog() << tcu::TestLog::Message << "Error, GL_ACTIVE_VARIABLES query return buffer trailing guard value was modified, getProgramResourceiv returned more than NUM_ACTIVE_VARIABLES values" << tcu::TestLog::EndMessage;
1892 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Query for GL_ACTIVE_VARIABLES returned too many values");
1893 continue;
1894 }
1895
1896 // log indices
1897 {
1898 tcu::MessageBuilder builder(&m_testCtx.getLog());
1899
1900 builder << "Active variable indices: {";
1901 for (int varNdx = 0; varNdx < numActiveResources; ++varNdx)
1902 {
1903 if (varNdx)
1904 builder << ", ";
1905 builder << activeVariableIndices[varNdx];
1906 }
1907 builder << "}" << tcu::TestLog::EndMessage;
1908 }
1909
1910 // collect names
1911
1912 activeResourceNames.resize(numActiveResources);
1913
1914 for (int varNdx = 0; varNdx < numActiveResources; ++varNdx)
1915 {
1916 const glw::GLenum nameProp = GL_NAME_LENGTH;
1917 glw::GLint nameLength = -1;
1918 std::vector<char> nameBuffer;
1919
1920 written = -1;
1921 gl.getProgramResourceiv(program.getProgram(), programMemberInterfaceValue, activeVariableIndices[varNdx], 1, &nameProp, 1, &written, &nameLength);
1922 GLU_EXPECT_NO_ERROR(gl.getError(), "query GL_NAME_LENGTH");
1923
1924 if (nameLength <= 0 || written <= 0)
1925 {
1926 m_testCtx.getLog() << tcu::TestLog::Message << "Error, GL_NAME_LENGTH query failed" << tcu::TestLog::EndMessage;
1927 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "GL_NAME_LENGTH query failed");
1928 continue;
1929 }
1930
1931 nameBuffer.resize(nameLength + 2, 'X'); // allocate more than required
1932 written = -1;
1933 gl.getProgramResourceName(program.getProgram(), programMemberInterfaceValue, activeVariableIndices[varNdx], nameLength+1, &written, &nameBuffer[0]);
1934 GLU_EXPECT_NO_ERROR(gl.getError(), "getProgramResourceName");
1935
1936 if (written <= 0)
1937 {
1938 m_testCtx.getLog() << tcu::TestLog::Message << "Error, name query failed, no data written" << tcu::TestLog::EndMessage;
1939 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "name query failed");
1940 continue;
1941 }
1942 else if (written > nameLength)
1943 {
1944 m_testCtx.getLog() << tcu::TestLog::Message << "Error, name query failed, query returned too much data" << tcu::TestLog::EndMessage;
1945 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "name query failed");
1946 continue;
1947 }
1948
1949 activeResourceNames[varNdx] = std::string(&nameBuffer[0], written);
1950 }
1951
1952 // log collected names
1953 {
1954 tcu::MessageBuilder builder(&m_testCtx.getLog());
1955
1956 builder << "Active variables:\n";
1957 for (int varNdx = 0; varNdx < numActiveResources; ++varNdx)
1958 builder << "\t" << activeResourceNames[varNdx] << "\n";
1959 builder << tcu::TestLog::EndMessage;
1960 }
1961 }
1962
1963 // verify names
1964 {
1965 glu::InterfaceBlock* block = DE_NULL;
1966 const std::string blockName = glu::parseVariableName(blockNames[blockNdx].c_str());
1967 std::vector<std::string> referenceList;
1968
1969 for (int interfaceNdx = 0; interfaceNdx < (int)m_program->getShaders()[0]->getDefaultBlock().interfaceBlocks.size(); ++interfaceNdx)
1970 {
1971 if (m_program->getShaders()[0]->getDefaultBlock().interfaceBlocks[interfaceNdx].interfaceName == blockName)
1972 {
1973 block = &m_program->getShaders()[0]->getDefaultBlock().interfaceBlocks[interfaceNdx];
1974 break;
1975 }
1976 }
1977
1978 if (!block)
1979 throw tcu::InternalError("could not find block referenced in the reference resource list");
1980
1981 // generate reference list
1982
1983 referenceList = getProgramInterfaceBlockMemberResourceList(*block);
1984 {
1985 tcu::MessageBuilder builder(&m_testCtx.getLog());
1986
1987 builder << "Expected variable names:\n";
1988 for (int varNdx = 0; varNdx < (int)referenceList.size(); ++varNdx)
1989 builder << "\t" << referenceList[varNdx] << "\n";
1990 builder << tcu::TestLog::EndMessage;
1991 }
1992
1993 // compare lists
1994 {
1995 bool listsIdentical = true;
1996
1997 for (int ndx = 0; ndx < (int)referenceList.size(); ++ndx)
1998 {
1999 if (!de::contains(activeResourceNames.begin(), activeResourceNames.end(), referenceList[ndx]))
2000 {
2001 m_testCtx.getLog() << tcu::TestLog::Message << "Error, variable name list did not contain active variable " << referenceList[ndx] << tcu::TestLog::EndMessage;
2002 listsIdentical = false;
2003 }
2004 }
2005
2006 for (int ndx = 0; ndx < (int)activeResourceNames.size(); ++ndx)
2007 {
2008 if (!de::contains(referenceList.begin(), referenceList.end(), activeResourceNames[ndx]))
2009 {
2010 m_testCtx.getLog() << tcu::TestLog::Message << "Error, variable name list contains unexpected resource \"" << activeResourceNames[ndx] << "\"" << tcu::TestLog::EndMessage;
2011 listsIdentical = false;
2012 }
2013 }
2014
2015 if (listsIdentical)
2016 m_testCtx.getLog() << tcu::TestLog::Message << "Lists identical" << tcu::TestLog::EndMessage;
2017 else
2018 {
2019 m_testCtx.getLog() << tcu::TestLog::Message << "Error, invalid active variable list" << tcu::TestLog::EndMessage;
2020 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "invalid active variable list");
2021 continue;
2022 }
2023 }
2024 }
2025 }
2026
2027 // Max num active variables
2028 {
2029 const tcu::ScopedLogSection section (m_testCtx.getLog(), "MaxNumActiveVariables", "MAX_NUM_ACTIVE_VARIABLES");
2030 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2031 glw::GLint maxNumActiveVariables = -1;
2032
2033 gl.getProgramInterfaceiv(program.getProgram(), programGLInterfaceValue, GL_MAX_NUM_ACTIVE_VARIABLES, &maxNumActiveVariables);
2034 GLU_EXPECT_NO_ERROR(gl.getError(), "query MAX_NUM_ACTIVE_VARIABLES");
2035
2036 m_testCtx.getLog() << tcu::TestLog::Message << "MAX_NUM_ACTIVE_VARIABLES = " << maxNumActiveVariables << tcu::TestLog::EndMessage;
2037
2038 if (expectedMaxNumActiveVariables != maxNumActiveVariables)
2039 {
2040 m_testCtx.getLog() << tcu::TestLog::Message << "Error, got unexpected MAX_NUM_ACTIVE_VARIABLES" << tcu::TestLog::EndMessage;
2041 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "unexpected MAX_NUM_ACTIVE_VARIABLES");
2042 }
2043 else
2044 m_testCtx.getLog() << tcu::TestLog::Message << "MAX_NUM_ACTIVE_VARIABLES valid" << tcu::TestLog::EndMessage;
2045 }
2046
2047 return STOP;
2048 }
2049
2050 class InterfaceBlockDataSizeTestCase : public InterfaceBlockBaseCase
2051 {
2052 public:
2053 InterfaceBlockDataSizeTestCase (Context& context, const char* name, const char* description, glu::Storage storage, CaseType caseType);
2054
2055 private:
2056 IterateResult iterate (void);
2057 int getBlockMinDataSize (const std::string& blockName) const;
2058 int getBlockMinDataSize (const glu::InterfaceBlock& block) const;
2059 };
2060
InterfaceBlockDataSizeTestCase(Context & context,const char * name,const char * description,glu::Storage storage,CaseType caseType)2061 InterfaceBlockDataSizeTestCase::InterfaceBlockDataSizeTestCase (Context& context, const char* name, const char* description, glu::Storage storage, CaseType caseType)
2062 : InterfaceBlockBaseCase(context, name, description, storage, caseType)
2063 {
2064 }
2065
iterate(void)2066 InterfaceBlockDataSizeTestCase::IterateResult InterfaceBlockDataSizeTestCase::iterate (void)
2067 {
2068 const ProgramInterface programInterface = (m_storage == glu::STORAGE_UNIFORM) ? (PROGRAMINTERFACE_UNIFORM_BLOCK) :
2069 (m_storage == glu::STORAGE_BUFFER) ? (PROGRAMINTERFACE_SHADER_STORAGE_BLOCK) :
2070 (PROGRAMINTERFACE_LAST);
2071 const glw::GLenum programGLInterfaceValue = getProgramInterfaceGLEnum(programInterface);
2072 const std::vector<std::string> blockNames = getProgramInterfaceResourceList(m_program, programInterface);
2073 glu::ShaderProgram program (m_context.getRenderContext(), generateProgramInterfaceProgramSources(m_program));
2074
2075 DE_ASSERT(programInterface != PROGRAMINTERFACE_LAST);
2076
2077 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2078 checkAndLogProgram(program, m_program, m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
2079
2080 // Verify all blocks
2081 for (int blockNdx = 0; blockNdx < (int)blockNames.size(); ++blockNdx)
2082 {
2083 const tcu::ScopedLogSection section (m_testCtx.getLog(), "Block", "Block \"" + blockNames[blockNdx] + "\"");
2084 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2085 const glw::GLuint resourceNdx = gl.getProgramResourceIndex(program.getProgram(), programGLInterfaceValue, blockNames[blockNdx].c_str());
2086 const int expectedMinDataSize = getBlockMinDataSize(blockNames[blockNdx]);
2087 glw::GLint queryDataSize = -1;
2088
2089 GLU_EXPECT_NO_ERROR(gl.getError(), "query resource index");
2090
2091 if (resourceNdx == GL_INVALID_INDEX)
2092 {
2093 m_testCtx.getLog() << tcu::TestLog::Message << "Error, getProgramResourceIndex returned GL_INVALID_INDEX for \"" << blockNames[blockNdx] << "\"" << tcu::TestLog::EndMessage;
2094 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Resource not found");
2095 continue;
2096 }
2097
2098 // query
2099 {
2100 const glw::GLenum prop = GL_BUFFER_DATA_SIZE;
2101
2102 gl.getProgramResourceiv(program.getProgram(), programGLInterfaceValue, resourceNdx, 1, &prop, 1, DE_NULL, &queryDataSize);
2103 GLU_EXPECT_NO_ERROR(gl.getError(), "query resource BUFFER_DATA_SIZE");
2104 }
2105
2106 m_testCtx.getLog()
2107 << tcu::TestLog::Message
2108 << "BUFFER_DATA_SIZE = " << queryDataSize << "\n"
2109 << "Buffer data size with tight packing: " << expectedMinDataSize
2110 << tcu::TestLog::EndMessage;
2111
2112 if (queryDataSize < expectedMinDataSize)
2113 {
2114 m_testCtx.getLog() << tcu::TestLog::Message << "Error, buffer size was less than minimum buffer data size" << tcu::TestLog::EndMessage;
2115 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Buffer data size invalid");
2116 continue;
2117 }
2118 else
2119 m_testCtx.getLog() << tcu::TestLog::Message << "Buffer size valid" << tcu::TestLog::EndMessage;
2120 }
2121
2122 return STOP;
2123 }
2124
getBlockMinDataSize(const std::string & blockFullName) const2125 int InterfaceBlockDataSizeTestCase::getBlockMinDataSize (const std::string& blockFullName) const
2126 {
2127 const std::string blockName = glu::parseVariableName(blockFullName.c_str());
2128
2129 for (int interfaceNdx = 0; interfaceNdx < (int)m_program->getShaders()[0]->getDefaultBlock().interfaceBlocks.size(); ++interfaceNdx)
2130 {
2131 if (m_program->getShaders()[0]->getDefaultBlock().interfaceBlocks[interfaceNdx].interfaceName == blockName &&
2132 m_program->getShaders()[0]->getDefaultBlock().interfaceBlocks[interfaceNdx].storage == m_storage)
2133 return getBlockMinDataSize(m_program->getShaders()[0]->getDefaultBlock().interfaceBlocks[interfaceNdx]);
2134 }
2135
2136 DE_ASSERT(false);
2137 return -1;
2138 }
2139
2140 class AtomicCounterCase : public TestCase
2141 {
2142 public:
2143 AtomicCounterCase (Context& context, const char* name, const char* description);
2144 ~AtomicCounterCase (void);
2145
2146 private:
2147 void init (void);
2148 void deinit (void);
2149
2150 protected:
2151 int getNumAtomicCounterBuffers (void) const;
2152 int getMaxNumActiveVariables (void) const;
2153 int getBufferVariableCount (int binding) const;
2154 int getBufferMinimumDataSize (int binding) const;
2155
2156 ProgramInterfaceDefinition::Program* m_program;
2157 };
2158
AtomicCounterCase(Context & context,const char * name,const char * description)2159 AtomicCounterCase::AtomicCounterCase (Context& context, const char* name, const char* description)
2160 : TestCase (context, name, description)
2161 , m_program (DE_NULL)
2162 {
2163 }
2164
~AtomicCounterCase(void)2165 AtomicCounterCase::~AtomicCounterCase (void)
2166 {
2167 deinit();
2168 }
2169
init(void)2170 void AtomicCounterCase::init (void)
2171 {
2172 ProgramInterfaceDefinition::Shader* shader;
2173 glu::GLSLVersion glslVersion = glu::getContextTypeGLSLVersion(m_context.getRenderContext().getType());
2174
2175 m_program = new ProgramInterfaceDefinition::Program();
2176 shader = m_program->addShader(glu::SHADERTYPE_COMPUTE, glslVersion);
2177
2178 {
2179 glu::VariableDeclaration decl(glu::VarType(glu::TYPE_UINT_ATOMIC_COUNTER, glu::PRECISION_LAST), "binding1_counter1", glu::STORAGE_UNIFORM);
2180 decl.layout.binding = 1;
2181 shader->getDefaultBlock().variables.push_back(decl);
2182 }
2183 {
2184 glu::VariableDeclaration decl(glu::VarType(glu::TYPE_UINT_ATOMIC_COUNTER, glu::PRECISION_LAST), "binding1_counter2", glu::STORAGE_UNIFORM);
2185 decl.layout.binding = 1;
2186 decl.layout.offset = 8;
2187
2188 shader->getDefaultBlock().variables.push_back(decl);
2189 }
2190 {
2191 glu::VariableDeclaration decl(glu::VarType(glu::TYPE_UINT_ATOMIC_COUNTER, glu::PRECISION_LAST), "binding2_counter1", glu::STORAGE_UNIFORM);
2192 decl.layout.binding = 2;
2193 shader->getDefaultBlock().variables.push_back(decl);
2194 }
2195
2196 DE_ASSERT(m_program->isValid());
2197 }
2198
deinit(void)2199 void AtomicCounterCase::deinit (void)
2200 {
2201 delete m_program;
2202 m_program = DE_NULL;
2203 }
2204
getNumAtomicCounterBuffers(void) const2205 int AtomicCounterCase::getNumAtomicCounterBuffers (void) const
2206 {
2207 std::set<int> buffers;
2208
2209 for (int ndx = 0; ndx < (int)m_program->getShaders()[0]->getDefaultBlock().variables.size(); ++ndx)
2210 {
2211 if (m_program->getShaders()[0]->getDefaultBlock().variables[ndx].varType.isBasicType() &&
2212 glu::isDataTypeAtomicCounter(m_program->getShaders()[0]->getDefaultBlock().variables[ndx].varType.getBasicType()))
2213 {
2214 buffers.insert(m_program->getShaders()[0]->getDefaultBlock().variables[ndx].layout.binding);
2215 }
2216 }
2217
2218 return (int)buffers.size();
2219 }
2220
getMaxNumActiveVariables(void) const2221 int AtomicCounterCase::getMaxNumActiveVariables (void) const
2222 {
2223 int maxVars = 0;
2224 std::map<int,int> numBufferVars;
2225
2226 for (int ndx = 0; ndx < (int)m_program->getShaders()[0]->getDefaultBlock().variables.size(); ++ndx)
2227 {
2228 if (m_program->getShaders()[0]->getDefaultBlock().variables[ndx].varType.isBasicType() &&
2229 glu::isDataTypeAtomicCounter(m_program->getShaders()[0]->getDefaultBlock().variables[ndx].varType.getBasicType()))
2230 {
2231 const int binding = m_program->getShaders()[0]->getDefaultBlock().variables[ndx].layout.binding;
2232
2233 if (numBufferVars.find(binding) == numBufferVars.end())
2234 numBufferVars[binding] = 1;
2235 else
2236 ++numBufferVars[binding];
2237 }
2238 }
2239
2240 for (std::map<int,int>::const_iterator it = numBufferVars.begin(); it != numBufferVars.end(); ++it)
2241 maxVars = de::max(maxVars, it->second);
2242
2243 return maxVars;
2244 }
2245
getBufferVariableCount(int binding) const2246 int AtomicCounterCase::getBufferVariableCount (int binding) const
2247 {
2248 int numVars = 0;
2249
2250 for (int ndx = 0; ndx < (int)m_program->getShaders()[0]->getDefaultBlock().variables.size(); ++ndx)
2251 {
2252 if (m_program->getShaders()[0]->getDefaultBlock().variables[ndx].varType.isBasicType() &&
2253 glu::isDataTypeAtomicCounter(m_program->getShaders()[0]->getDefaultBlock().variables[ndx].varType.getBasicType()) &&
2254 m_program->getShaders()[0]->getDefaultBlock().variables[ndx].layout.binding == binding)
2255 ++numVars;
2256 }
2257
2258 return numVars;
2259 }
2260
getBufferMinimumDataSize(int binding) const2261 int AtomicCounterCase::getBufferMinimumDataSize (int binding) const
2262 {
2263 int minSize = -1;
2264 int currentOffset = 0;
2265
2266 for (int ndx = 0; ndx < (int)m_program->getShaders()[0]->getDefaultBlock().variables.size(); ++ndx)
2267 {
2268 if (m_program->getShaders()[0]->getDefaultBlock().variables[ndx].varType.isBasicType() &&
2269 glu::isDataTypeAtomicCounter(m_program->getShaders()[0]->getDefaultBlock().variables[ndx].varType.getBasicType()) &&
2270 m_program->getShaders()[0]->getDefaultBlock().variables[ndx].layout.binding == binding)
2271 {
2272 const int thisOffset = (m_program->getShaders()[0]->getDefaultBlock().variables[ndx].layout.offset != -1) ? (m_program->getShaders()[0]->getDefaultBlock().variables[ndx].layout.offset) : (currentOffset);
2273 currentOffset = thisOffset + 4;
2274
2275 minSize = de::max(minSize, thisOffset + 4);
2276 }
2277 }
2278
2279 return minSize;
2280 }
2281
2282 class AtomicCounterResourceListCase : public AtomicCounterCase
2283 {
2284 public:
2285 AtomicCounterResourceListCase (Context& context, const char* name, const char* description);
2286
2287 private:
2288 IterateResult iterate (void);
2289 };
2290
AtomicCounterResourceListCase(Context & context,const char * name,const char * description)2291 AtomicCounterResourceListCase::AtomicCounterResourceListCase (Context& context, const char* name, const char* description)
2292 : AtomicCounterCase(context, name, description)
2293 {
2294 }
2295
iterate(void)2296 AtomicCounterResourceListCase::IterateResult AtomicCounterResourceListCase::iterate (void)
2297 {
2298 const glu::ShaderProgram program(m_context.getRenderContext(), generateProgramInterfaceProgramSources(m_program));
2299
2300 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2301 checkAndLogProgram(program, m_program, m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
2302
2303 {
2304 const tcu::ScopedLogSection section (m_testCtx.getLog(), "ActiveResources", "ACTIVE_RESOURCES");
2305 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2306 glw::GLint numActiveResources = -1;
2307 const int numExpectedActiveResources = 2; // 2 buffer bindings
2308
2309 m_testCtx.getLog() << tcu::TestLog::Message << "Verifying ACTIVE_RESOURCES, expecting " << numExpectedActiveResources << tcu::TestLog::EndMessage;
2310
2311 gl.getProgramInterfaceiv(program.getProgram(), GL_ATOMIC_COUNTER_BUFFER, GL_ACTIVE_RESOURCES, &numActiveResources);
2312 GLU_EXPECT_NO_ERROR(gl.getError(), "query GL_ACTIVE_RESOURCES");
2313
2314 m_testCtx.getLog() << tcu::TestLog::Message << "ACTIVE_RESOURCES = " << numActiveResources << tcu::TestLog::EndMessage;
2315
2316 if (numActiveResources != numExpectedActiveResources)
2317 {
2318 m_testCtx.getLog() << tcu::TestLog::Message << "Error, got unexpected ACTIVE_RESOURCES" << tcu::TestLog::EndMessage;
2319 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got unexpected ACTIVE_RESOURCES");
2320 }
2321 else
2322 m_testCtx.getLog() << tcu::TestLog::Message << "ACTIVE_RESOURCES valid" << tcu::TestLog::EndMessage;
2323 }
2324
2325 return STOP;
2326 }
2327
2328 class AtomicCounterActiveVariablesCase : public AtomicCounterCase
2329 {
2330 public:
2331 AtomicCounterActiveVariablesCase (Context& context, const char* name, const char* description);
2332
2333 private:
2334 IterateResult iterate (void);
2335 };
2336
AtomicCounterActiveVariablesCase(Context & context,const char * name,const char * description)2337 AtomicCounterActiveVariablesCase::AtomicCounterActiveVariablesCase (Context& context, const char* name, const char* description)
2338 : AtomicCounterCase(context, name, description)
2339 {
2340 }
2341
iterate(void)2342 AtomicCounterActiveVariablesCase::IterateResult AtomicCounterActiveVariablesCase::iterate (void)
2343 {
2344 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2345 const glu::ShaderProgram program (m_context.getRenderContext(), generateProgramInterfaceProgramSources(m_program));
2346 const int numAtomicBuffers = getNumAtomicCounterBuffers();
2347 const int expectedMaxNumActiveVariables = getMaxNumActiveVariables();
2348
2349 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2350 checkAndLogProgram(program, m_program, m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
2351
2352 // check active variables
2353 {
2354 const tcu::ScopedLogSection section (m_testCtx.getLog(), "Interface", "ATOMIC_COUNTER_BUFFER interface");
2355 glw::GLint queryActiveResources = -1;
2356 glw::GLint queryMaxNumActiveVariables = -1;
2357
2358 gl.getProgramInterfaceiv(program.getProgram(), GL_ATOMIC_COUNTER_BUFFER, GL_ACTIVE_RESOURCES, &queryActiveResources);
2359 gl.getProgramInterfaceiv(program.getProgram(), GL_ATOMIC_COUNTER_BUFFER, GL_MAX_NUM_ACTIVE_VARIABLES, &queryMaxNumActiveVariables);
2360 GLU_EXPECT_NO_ERROR(gl.getError(), "query interface");
2361
2362 m_testCtx.getLog()
2363 << tcu::TestLog::Message
2364 << "GL_ACTIVE_RESOURCES = " << queryActiveResources << "\n"
2365 << "GL_MAX_NUM_ACTIVE_VARIABLES = " << queryMaxNumActiveVariables << "\n"
2366 << tcu::TestLog::EndMessage;
2367
2368 if (queryActiveResources != numAtomicBuffers)
2369 {
2370 m_testCtx.getLog() << tcu::TestLog::Message << "Error, got unexpected GL_ACTIVE_RESOURCES, expected " << numAtomicBuffers << tcu::TestLog::EndMessage;
2371 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got unexpected GL_ACTIVE_RESOURCES");
2372 }
2373
2374 if (queryMaxNumActiveVariables != expectedMaxNumActiveVariables)
2375 {
2376 m_testCtx.getLog() << tcu::TestLog::Message << "Error, got unexpected GL_MAX_NUM_ACTIVE_VARIABLES, expected " << expectedMaxNumActiveVariables << tcu::TestLog::EndMessage;
2377 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got unexpected GL_MAX_NUM_ACTIVE_VARIABLES");
2378 }
2379 }
2380
2381 // Check each buffer
2382 for (int bufferNdx = 0; bufferNdx < numAtomicBuffers; ++bufferNdx)
2383 {
2384 const tcu::ScopedLogSection section (m_testCtx.getLog(), "Resource", "Resource index " + de::toString(bufferNdx));
2385 std::vector<glw::GLint> activeVariables;
2386 std::vector<std::string> memberNames;
2387
2388 // Find active variables
2389 {
2390 const glw::GLenum numActiveVariablesProp = GL_NUM_ACTIVE_VARIABLES;
2391 const glw::GLenum activeVariablesProp = GL_ACTIVE_VARIABLES;
2392 glw::GLint numActiveVariables = -2;
2393 glw::GLint written = -1;
2394
2395 gl.getProgramResourceiv(program.getProgram(), GL_ATOMIC_COUNTER_BUFFER, bufferNdx, 1, &numActiveVariablesProp, 1, &written, &numActiveVariables);
2396 GLU_EXPECT_NO_ERROR(gl.getError(), "query num active variables");
2397
2398 if (numActiveVariables <= 0)
2399 {
2400 m_testCtx.getLog() << tcu::TestLog::Message << "Error, got unexpected NUM_ACTIVE_VARIABLES: " << numActiveVariables << tcu::TestLog::EndMessage;
2401 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got unexpected NUM_ACTIVE_VARIABLES");
2402 continue;
2403 }
2404
2405 if (written <= 0)
2406 {
2407 m_testCtx.getLog() << tcu::TestLog::Message << "Error, query for NUM_ACTIVE_VARIABLES returned no values" << tcu::TestLog::EndMessage;
2408 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "NUM_ACTIVE_VARIABLES query failed");
2409 continue;
2410 }
2411
2412 m_testCtx.getLog() << tcu::TestLog::Message << "GL_NUM_ACTIVE_VARIABLES = " << numActiveVariables << tcu::TestLog::EndMessage;
2413
2414 written = -1;
2415 activeVariables.resize(numActiveVariables + 1, -2);
2416
2417 gl.getProgramResourceiv(program.getProgram(), GL_ATOMIC_COUNTER_BUFFER, bufferNdx, 1, &activeVariablesProp, numActiveVariables, &written, &activeVariables[0]);
2418 GLU_EXPECT_NO_ERROR(gl.getError(), "query active variables");
2419
2420 if (written != numActiveVariables)
2421 {
2422 m_testCtx.getLog() << tcu::TestLog::Message << "Error, unexpected number of ACTIVE_VARIABLES, NUM_ACTIVE_VARIABLES = " << numActiveVariables << ", query returned " << written << " values" << tcu::TestLog::EndMessage;
2423 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got unexpected ACTIVE_VARIABLES");
2424 continue;
2425 }
2426
2427 if (activeVariables.back() != -2)
2428 {
2429 m_testCtx.getLog() << tcu::TestLog::Message << "Error, query for ACTIVE_VARIABLES wrote over target buffer bounds" << tcu::TestLog::EndMessage;
2430 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "ACTIVE_VARIABLES query failed");
2431 continue;
2432 }
2433
2434 activeVariables.pop_back();
2435 }
2436
2437 // log indices
2438 {
2439 tcu::MessageBuilder builder(&m_testCtx.getLog());
2440
2441 builder << "Active variable indices: {";
2442 for (int varNdx = 0; varNdx < (int)activeVariables.size(); ++varNdx)
2443 {
2444 if (varNdx)
2445 builder << ", ";
2446 builder << activeVariables[varNdx];
2447 }
2448 builder << "}" << tcu::TestLog::EndMessage;
2449 }
2450
2451 // collect member names
2452 for (int ndx = 0; ndx < (int)activeVariables.size(); ++ndx)
2453 {
2454 const glw::GLenum nameLengthProp = GL_NAME_LENGTH;
2455 glw::GLint nameLength = -1;
2456 glw::GLint written = -1;
2457 std::vector<char> nameBuf;
2458
2459 gl.getProgramResourceiv(program.getProgram(), GL_UNIFORM, activeVariables[ndx], 1, &nameLengthProp, 1, &written, &nameLength);
2460 GLU_EXPECT_NO_ERROR(gl.getError(), "query buffer variable name length");
2461
2462 if (written <= 0 || nameLength == -1)
2463 {
2464 m_testCtx.getLog() << tcu::TestLog::Message << "Error, query for GL_NAME_LENGTH returned no values" << tcu::TestLog::EndMessage;
2465 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "GL_NAME_LENGTH query failed");
2466 continue;
2467 }
2468
2469 nameBuf.resize(nameLength + 2, 'X'); // +2 to tolerate potential off-by-ones in some implementations, name queries will check these cases better
2470 written = -1;
2471
2472 gl.getProgramResourceName(program.getProgram(), GL_UNIFORM, activeVariables[ndx], (int)nameBuf.size(), &written, &nameBuf[0]);
2473 GLU_EXPECT_NO_ERROR(gl.getError(), "query buffer variable name");
2474
2475 if (written <= 0)
2476 {
2477 m_testCtx.getLog() << tcu::TestLog::Message << "Error, query for resource name returned no name" << tcu::TestLog::EndMessage;
2478 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Name query failed");
2479 continue;
2480 }
2481
2482 memberNames.push_back(std::string(&nameBuf[0], written));
2483 }
2484
2485 // log names
2486 {
2487 tcu::MessageBuilder builder(&m_testCtx.getLog());
2488
2489 builder << "Active variables:\n";
2490 for (int varNdx = 0; varNdx < (int)memberNames.size(); ++varNdx)
2491 {
2492 builder << "\t" << memberNames[varNdx] << "\n";
2493 }
2494 builder << tcu::TestLog::EndMessage;
2495 }
2496
2497 // check names are all in the same buffer
2498 {
2499 bool bindingsValid = true;
2500
2501 m_testCtx.getLog() << tcu::TestLog::Message << "Verifying names" << tcu::TestLog::EndMessage;
2502
2503 for (int nameNdx = 0; nameNdx < (int)memberNames.size(); ++nameNdx)
2504 {
2505 int prevBinding = -1;
2506
2507 for (int varNdx = 0; varNdx < (int)m_program->getShaders()[0]->getDefaultBlock().variables.size(); ++varNdx)
2508 {
2509 if (m_program->getShaders()[0]->getDefaultBlock().variables[varNdx].name == memberNames[nameNdx])
2510 {
2511 const int varBinding = m_program->getShaders()[0]->getDefaultBlock().variables[varNdx].layout.binding;
2512
2513 if (prevBinding == -1 || prevBinding == varBinding)
2514 prevBinding = varBinding;
2515 else
2516 bindingsValid = false;
2517 }
2518 }
2519
2520 if (prevBinding == -1)
2521 {
2522 m_testCtx.getLog() << tcu::TestLog::Message << "Error, could not find variable with name \"" << memberNames[nameNdx] << "\"" << tcu::TestLog::EndMessage;
2523 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Variable name invalid");
2524 }
2525 else if (getBufferVariableCount(prevBinding) != (int)memberNames.size())
2526 {
2527 m_testCtx.getLog()
2528 << tcu::TestLog::Message
2529 << "Error, unexpected variable count for binding " << prevBinding
2530 << ". Expected " << getBufferVariableCount(prevBinding) << ", got " << (int)memberNames.size()
2531 << tcu::TestLog::EndMessage;
2532 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Variable names invalid");
2533 }
2534 }
2535
2536 if (!bindingsValid)
2537 {
2538 m_testCtx.getLog() << tcu::TestLog::Message << "Error, all resource do not share the same buffer" << tcu::TestLog::EndMessage;
2539 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Active variables invalid");
2540 continue;
2541 }
2542 }
2543 }
2544
2545 return STOP;
2546 }
2547
2548 class AtomicCounterBufferBindingCase : public AtomicCounterCase
2549 {
2550 public:
2551 AtomicCounterBufferBindingCase (Context& context, const char* name, const char* description);
2552
2553 private:
2554 IterateResult iterate (void);
2555 };
2556
AtomicCounterBufferBindingCase(Context & context,const char * name,const char * description)2557 AtomicCounterBufferBindingCase::AtomicCounterBufferBindingCase (Context& context, const char* name, const char* description)
2558 : AtomicCounterCase(context, name, description)
2559 {
2560 }
2561
iterate(void)2562 AtomicCounterBufferBindingCase::IterateResult AtomicCounterBufferBindingCase::iterate (void)
2563 {
2564 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2565 const glu::ShaderProgram program (m_context.getRenderContext(), generateProgramInterfaceProgramSources(m_program));
2566 const int numAtomicBuffers = getNumAtomicCounterBuffers();
2567
2568 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2569 checkAndLogProgram(program, m_program, m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
2570
2571 // check every buffer
2572 for (int bufferNdx = 0; bufferNdx < numAtomicBuffers; ++bufferNdx)
2573 {
2574 const tcu::ScopedLogSection section (m_testCtx.getLog(), "Resource", "Resource index " + de::toString(bufferNdx));
2575 const glw::GLenum bufferBindingProp = GL_BUFFER_BINDING;
2576 glw::GLint bufferBinding = -1;
2577 glw::GLint written = -1;
2578
2579 gl.getProgramResourceiv(program.getProgram(), GL_ATOMIC_COUNTER_BUFFER, bufferNdx, 1, &bufferBindingProp, 1, &written, &bufferBinding);
2580 GLU_EXPECT_NO_ERROR(gl.getError(), "query buffer binding");
2581
2582 if (written <= 0)
2583 {
2584 m_testCtx.getLog() << tcu::TestLog::Message << "Error, query for BUFFER_BINDING returned no values." << tcu::TestLog::EndMessage;
2585 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "BUFFER_BINDING query failed");
2586 }
2587
2588 m_testCtx.getLog() << tcu::TestLog::Message << "GL_BUFFER_BINDING = " << bufferBinding << tcu::TestLog::EndMessage;
2589
2590 // no such buffer binding?
2591 if (getBufferVariableCount(bufferBinding) == 0)
2592 {
2593 m_testCtx.getLog() << tcu::TestLog::Message << "Error, got buffer with BUFFER_BINDING = " << bufferBinding << ", but such buffer does not exist." << tcu::TestLog::EndMessage;
2594 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got unexpected BUFFER_BINDING");
2595 }
2596 }
2597
2598 return STOP;
2599 }
2600
2601 class AtomicCounterBufferDataSizeCase : public AtomicCounterCase
2602 {
2603 public:
2604 AtomicCounterBufferDataSizeCase (Context& context, const char* name, const char* description);
2605
2606 private:
2607 IterateResult iterate (void);
2608 };
2609
AtomicCounterBufferDataSizeCase(Context & context,const char * name,const char * description)2610 AtomicCounterBufferDataSizeCase::AtomicCounterBufferDataSizeCase (Context& context, const char* name, const char* description)
2611 : AtomicCounterCase(context, name, description)
2612 {
2613 }
2614
iterate(void)2615 AtomicCounterBufferDataSizeCase::IterateResult AtomicCounterBufferDataSizeCase::iterate (void)
2616 {
2617 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2618 const glu::ShaderProgram program (m_context.getRenderContext(), generateProgramInterfaceProgramSources(m_program));
2619 const int numAtomicBuffers = getNumAtomicCounterBuffers();
2620
2621 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2622 checkAndLogProgram(program, m_program, m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
2623
2624 // check every buffer
2625 for (int bufferNdx = 0; bufferNdx < numAtomicBuffers; ++bufferNdx)
2626 {
2627 const tcu::ScopedLogSection section (m_testCtx.getLog(), "Resource", "Resource index " + de::toString(bufferNdx));
2628 const glw::GLenum props[] = { GL_BUFFER_BINDING, GL_BUFFER_DATA_SIZE };
2629 glw::GLint values[] = { -1, -1 };
2630 glw::GLint written = -1;
2631 int bufferMinDataSize;
2632
2633 gl.getProgramResourceiv(program.getProgram(), GL_ATOMIC_COUNTER_BUFFER, bufferNdx, DE_LENGTH_OF_ARRAY(props), props, DE_LENGTH_OF_ARRAY(values), &written, values);
2634 GLU_EXPECT_NO_ERROR(gl.getError(), "query buffer binding");
2635
2636 if (written != 2)
2637 {
2638 m_testCtx.getLog() << tcu::TestLog::Message << "Error, query for (BUFFER_BINDING, BUFFER_DATA_SIZE) returned " << written << " value(s)." << tcu::TestLog::EndMessage;
2639 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "property query failed");
2640 continue;
2641 }
2642
2643 m_testCtx.getLog()
2644 << tcu::TestLog::Message
2645 << "GL_BUFFER_BINDING = " << values[0] << "\n"
2646 << "GL_BUFFER_DATA_SIZE = " << values[1]
2647 << tcu::TestLog::EndMessage;
2648
2649 bufferMinDataSize = getBufferMinimumDataSize(values[0]);
2650 m_testCtx.getLog() << tcu::TestLog::Message << "Verifying data size, expected greater than or equal to " << bufferMinDataSize << tcu::TestLog::EndMessage;
2651
2652 // no such buffer binding?
2653 if (bufferMinDataSize == -1)
2654 {
2655 m_testCtx.getLog() << tcu::TestLog::Message << "Error, got buffer with BUFFER_BINDING = " << values[0] << ", but such buffer does not exist." << tcu::TestLog::EndMessage;
2656 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got unexpected BUFFER_BINDING");
2657 }
2658 else if (values[1] < bufferMinDataSize)
2659 {
2660 m_testCtx.getLog() << tcu::TestLog::Message << "Error, got buffer with BUFFER_DATA_SIZE = " << values[1] << ", expected greater than or equal to " << bufferMinDataSize << tcu::TestLog::EndMessage;
2661 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got unexpected BUFFER_BINDING");
2662 }
2663 else
2664 m_testCtx.getLog() << tcu::TestLog::Message << "Data size valid" << tcu::TestLog::EndMessage;
2665 }
2666
2667 return STOP;
2668 }
2669
2670 class AtomicCounterReferencedByCase : public TestCase
2671 {
2672 public:
2673 AtomicCounterReferencedByCase (Context& context,
2674 const char* name,
2675 const char* description,
2676 bool separable,
2677 deUint32 presentStagesMask,
2678 deUint32 activeStagesMask);
2679 ~AtomicCounterReferencedByCase (void);
2680
2681 private:
2682 void init (void);
2683 void deinit (void);
2684 IterateResult iterate (void);
2685
2686 const bool m_separable;
2687 const deUint32 m_presentStagesMask;
2688 const deUint32 m_activeStagesMask;
2689 ProgramInterfaceDefinition::Program* m_program;
2690 };
2691
AtomicCounterReferencedByCase(Context & context,const char * name,const char * description,bool separable,deUint32 presentStagesMask,deUint32 activeStagesMask)2692 AtomicCounterReferencedByCase::AtomicCounterReferencedByCase (Context& context,
2693 const char* name,
2694 const char* description,
2695 bool separable,
2696 deUint32 presentStagesMask,
2697 deUint32 activeStagesMask)
2698 : TestCase (context, name, description)
2699 , m_separable (separable)
2700 , m_presentStagesMask (presentStagesMask)
2701 , m_activeStagesMask (activeStagesMask)
2702 , m_program (DE_NULL)
2703 {
2704 DE_ASSERT((activeStagesMask & presentStagesMask) == activeStagesMask);
2705 }
2706
~AtomicCounterReferencedByCase(void)2707 AtomicCounterReferencedByCase::~AtomicCounterReferencedByCase (void)
2708 {
2709 deinit();
2710 }
2711
init(void)2712 void AtomicCounterReferencedByCase::init (void)
2713 {
2714 const deUint32 geometryMask = (1 << glu::SHADERTYPE_GEOMETRY);
2715 const deUint32 tessellationMask = (1 << glu::SHADERTYPE_TESSELLATION_CONTROL) | (1 << glu::SHADERTYPE_TESSELLATION_EVALUATION);
2716 glu::VariableDeclaration atomicVar (glu::VarType(glu::TYPE_UINT_ATOMIC_COUNTER, glu::PRECISION_LAST), "targetCounter", glu::STORAGE_UNIFORM);
2717 const glu::GLSLVersion glslVersion = glu::getContextTypeGLSLVersion(m_context.getRenderContext().getType());
2718 const bool supportsES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2));
2719
2720 if ((m_presentStagesMask & tessellationMask) != 0 && !supportsES32 && !m_context.getContextInfo().isExtensionSupported("GL_EXT_tessellation_shader"))
2721 throw tcu::NotSupportedError("Test requires GL_EXT_tessellation_shader extension");
2722 if ((m_presentStagesMask & geometryMask) != 0 && !supportsES32 && !m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader"))
2723 throw tcu::NotSupportedError("Test requires GL_EXT_geometry_shader extension");
2724
2725 atomicVar.layout.binding = 1;
2726
2727 m_program = new ProgramInterfaceDefinition::Program();
2728 m_program->setSeparable(m_separable);
2729
2730 for (int shaderType = 0; shaderType < glu::SHADERTYPE_LAST; ++shaderType)
2731 {
2732 if (m_activeStagesMask & (1 << shaderType))
2733 m_program->addShader((glu::ShaderType)shaderType, glslVersion)->getDefaultBlock().variables.push_back(atomicVar);
2734 else if (m_presentStagesMask & (1 << shaderType))
2735 m_program->addShader((glu::ShaderType)shaderType, glslVersion);
2736 }
2737
2738 if (m_program->hasStage(glu::SHADERTYPE_GEOMETRY))
2739 m_program->setGeometryNumOutputVertices(1);
2740 if (m_program->hasStage(glu::SHADERTYPE_TESSELLATION_CONTROL) || m_program->hasStage(glu::SHADERTYPE_TESSELLATION_EVALUATION))
2741 m_program->setTessellationNumOutputPatchVertices(1);
2742
2743 DE_ASSERT(m_program->isValid());
2744 }
2745
deinit(void)2746 void AtomicCounterReferencedByCase::deinit (void)
2747 {
2748 delete m_program;
2749 m_program = DE_NULL;
2750 }
2751
iterate(void)2752 AtomicCounterReferencedByCase::IterateResult AtomicCounterReferencedByCase::iterate (void)
2753 {
2754 const bool supportsES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2));
2755
2756 const struct
2757 {
2758 glw::GLenum propName;
2759 glu::ShaderType shaderType;
2760 const char* extension;
2761 } targetProps[] =
2762 {
2763 { GL_REFERENCED_BY_VERTEX_SHADER, glu::SHADERTYPE_VERTEX, DE_NULL },
2764 { GL_REFERENCED_BY_FRAGMENT_SHADER, glu::SHADERTYPE_FRAGMENT, DE_NULL },
2765 { GL_REFERENCED_BY_COMPUTE_SHADER, glu::SHADERTYPE_COMPUTE, DE_NULL },
2766 { GL_REFERENCED_BY_TESS_CONTROL_SHADER, glu::SHADERTYPE_TESSELLATION_CONTROL, (supportsES32 ? DE_NULL : "GL_EXT_tessellation_shader") },
2767 { GL_REFERENCED_BY_TESS_EVALUATION_SHADER, glu::SHADERTYPE_TESSELLATION_EVALUATION, (supportsES32 ? DE_NULL : "GL_EXT_tessellation_shader") },
2768 { GL_REFERENCED_BY_GEOMETRY_SHADER, glu::SHADERTYPE_GEOMETRY, (supportsES32 ? DE_NULL : "GL_EXT_geometry_shader") },
2769 };
2770
2771 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2772 const glu::ShaderProgram program (m_context.getRenderContext(), generateProgramInterfaceProgramSources(m_program));
2773
2774 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2775 checkAndLogProgram(program, m_program, m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
2776
2777 // check props
2778 for (int propNdx = 0; propNdx < DE_LENGTH_OF_ARRAY(targetProps); ++propNdx)
2779 {
2780 if (targetProps[propNdx].extension == DE_NULL || m_context.getContextInfo().isExtensionSupported(targetProps[propNdx].extension))
2781 {
2782 const glw::GLenum prop = targetProps[propNdx].propName;
2783 const glw::GLint expected = ((m_activeStagesMask & (1 << targetProps[propNdx].shaderType)) != 0) ? (GL_TRUE) : (GL_FALSE);
2784 glw::GLint value = -1;
2785 glw::GLint written = -1;
2786
2787 m_testCtx.getLog() << tcu::TestLog::Message << "Verifying " << glu::getProgramResourcePropertyName(prop) << ", expecting " << glu::getBooleanName(expected) << tcu::TestLog::EndMessage;
2788
2789 gl.getProgramResourceiv(program.getProgram(), GL_ATOMIC_COUNTER_BUFFER, 0, 1, &prop, 1, &written, &value);
2790 GLU_EXPECT_NO_ERROR(gl.getError(), "query buffer binding");
2791
2792 if (written != 1)
2793 {
2794 m_testCtx.getLog() << tcu::TestLog::Message << "Error, query for referenced_by_* returned invalid number of values." << tcu::TestLog::EndMessage;
2795 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "property query failed");
2796 continue;
2797 }
2798
2799 m_testCtx.getLog() << tcu::TestLog::Message << glu::getProgramResourcePropertyName(prop) << " = " << glu::getBooleanStr(value) << tcu::TestLog::EndMessage;
2800
2801 if (value != expected)
2802 {
2803 m_testCtx.getLog() << tcu::TestLog::Message << "Error, got unexpected value" << tcu::TestLog::EndMessage;
2804 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "unexpected property value");
2805 continue;
2806 }
2807 }
2808 }
2809
2810 return STOP;
2811 }
2812
2813 class ProgramInputOutputReferencedByCase : public TestCase
2814 {
2815 public:
2816 enum CaseType
2817 {
2818 CASE_VERTEX_FRAGMENT = 0,
2819 CASE_VERTEX_GEO_FRAGMENT,
2820 CASE_VERTEX_TESS_FRAGMENT,
2821 CASE_VERTEX_TESS_GEO_FRAGMENT,
2822
2823 CASE_SEPARABLE_VERTEX,
2824 CASE_SEPARABLE_FRAGMENT,
2825 CASE_SEPARABLE_GEOMETRY,
2826 CASE_SEPARABLE_TESS_CTRL,
2827 CASE_SEPARABLE_TESS_EVAL,
2828
2829 CASE_LAST
2830 };
2831 ProgramInputOutputReferencedByCase (Context& context, const char* name, const char* description, glu::Storage targetStorage, CaseType caseType);
2832 ~ProgramInputOutputReferencedByCase (void);
2833
2834 private:
2835 void init (void);
2836 void deinit (void);
2837 IterateResult iterate (void);
2838
2839 const CaseType m_caseType;
2840 const glu::Storage m_targetStorage;
2841 ProgramInterfaceDefinition::Program* m_program;
2842 };
2843
ProgramInputOutputReferencedByCase(Context & context,const char * name,const char * description,glu::Storage targetStorage,CaseType caseType)2844 ProgramInputOutputReferencedByCase::ProgramInputOutputReferencedByCase (Context& context, const char* name, const char* description, glu::Storage targetStorage, CaseType caseType)
2845 : TestCase (context, name, description)
2846 , m_caseType (caseType)
2847 , m_targetStorage (targetStorage)
2848 , m_program (DE_NULL)
2849 {
2850 DE_ASSERT(caseType < CASE_LAST);
2851 }
2852
~ProgramInputOutputReferencedByCase(void)2853 ProgramInputOutputReferencedByCase::~ProgramInputOutputReferencedByCase (void)
2854 {
2855 deinit();
2856 }
2857
init(void)2858 void ProgramInputOutputReferencedByCase::init (void)
2859 {
2860 const bool hasTessellationShader = (m_caseType == CASE_VERTEX_TESS_FRAGMENT) ||
2861 (m_caseType == CASE_VERTEX_TESS_GEO_FRAGMENT) ||
2862 (m_caseType == CASE_SEPARABLE_TESS_CTRL) ||
2863 (m_caseType == CASE_SEPARABLE_TESS_EVAL);
2864 const bool hasGeometryShader = (m_caseType == CASE_VERTEX_GEO_FRAGMENT) ||
2865 (m_caseType == CASE_VERTEX_TESS_GEO_FRAGMENT) ||
2866 (m_caseType == CASE_SEPARABLE_GEOMETRY);
2867 const bool supportsES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2));
2868
2869 if (hasTessellationShader && !supportsES32 && !m_context.getContextInfo().isExtensionSupported("GL_EXT_tessellation_shader"))
2870 throw tcu::NotSupportedError("Test requires GL_EXT_tessellation_shader extension");
2871 if (hasGeometryShader && !supportsES32 && !m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader"))
2872 throw tcu::NotSupportedError("Test requires GL_EXT_geometry_shader extension");
2873
2874 glu::GLSLVersion glslVersion = glu::getContextTypeGLSLVersion(m_context.getRenderContext().getType());
2875 m_program = new ProgramInterfaceDefinition::Program();
2876
2877 if (m_caseType == CASE_SEPARABLE_VERTEX ||
2878 m_caseType == CASE_SEPARABLE_FRAGMENT ||
2879 m_caseType == CASE_SEPARABLE_GEOMETRY ||
2880 m_caseType == CASE_SEPARABLE_TESS_CTRL ||
2881 m_caseType == CASE_SEPARABLE_TESS_EVAL)
2882 {
2883 const bool isInputCase = (m_targetStorage == glu::STORAGE_IN || m_targetStorage == glu::STORAGE_PATCH_IN);
2884 const bool perPatchStorage = (m_targetStorage == glu::STORAGE_PATCH_IN || m_targetStorage == glu::STORAGE_PATCH_OUT);
2885 const char* varName = (isInputCase) ? ("shaderInput") : ("shaderOutput");
2886 const glu::VariableDeclaration targetDecl (glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP), varName, m_targetStorage);
2887 const glu::ShaderType shaderType = (m_caseType == CASE_SEPARABLE_VERTEX) ? (glu::SHADERTYPE_VERTEX)
2888 : (m_caseType == CASE_SEPARABLE_FRAGMENT) ? (glu::SHADERTYPE_FRAGMENT)
2889 : (m_caseType == CASE_SEPARABLE_GEOMETRY) ? (glu::SHADERTYPE_GEOMETRY)
2890 : (m_caseType == CASE_SEPARABLE_TESS_CTRL) ? (glu::SHADERTYPE_TESSELLATION_CONTROL)
2891 : (m_caseType == CASE_SEPARABLE_TESS_EVAL) ? (glu::SHADERTYPE_TESSELLATION_EVALUATION)
2892 : (glu::SHADERTYPE_LAST);
2893 const bool arrayedInterface = (isInputCase) ? ((shaderType == glu::SHADERTYPE_GEOMETRY) ||
2894 (shaderType == glu::SHADERTYPE_TESSELLATION_CONTROL) ||
2895 (shaderType == glu::SHADERTYPE_TESSELLATION_EVALUATION))
2896 : (shaderType == glu::SHADERTYPE_TESSELLATION_CONTROL);
2897
2898 m_program->setSeparable(true);
2899
2900 if (arrayedInterface && !perPatchStorage)
2901 {
2902 const glu::VariableDeclaration targetDeclArr(glu::VarType(targetDecl.varType, glu::VarType::UNSIZED_ARRAY), varName, m_targetStorage);
2903 m_program->addShader(shaderType, glslVersion)->getDefaultBlock().variables.push_back(targetDeclArr);
2904 }
2905 else
2906 {
2907 m_program->addShader(shaderType, glslVersion)->getDefaultBlock().variables.push_back(targetDecl);
2908 }
2909 }
2910 else if (m_caseType == CASE_VERTEX_FRAGMENT ||
2911 m_caseType == CASE_VERTEX_GEO_FRAGMENT ||
2912 m_caseType == CASE_VERTEX_TESS_FRAGMENT ||
2913 m_caseType == CASE_VERTEX_TESS_GEO_FRAGMENT)
2914 {
2915 ProgramInterfaceDefinition::Shader* vertex = m_program->addShader(glu::SHADERTYPE_VERTEX, glslVersion);
2916 ProgramInterfaceDefinition::Shader* fragment = m_program->addShader(glu::SHADERTYPE_FRAGMENT, glslVersion);
2917
2918 m_program->setSeparable(false);
2919
2920 vertex->getDefaultBlock().variables.push_back(glu::VariableDeclaration(glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP),
2921 "shaderInput",
2922 glu::STORAGE_IN));
2923 vertex->getDefaultBlock().variables.push_back(glu::VariableDeclaration(glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP),
2924 "shaderOutput",
2925 glu::STORAGE_OUT,
2926 glu::INTERPOLATION_LAST,
2927 glu::Layout(1)));
2928
2929 fragment->getDefaultBlock().variables.push_back(glu::VariableDeclaration(glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP),
2930 "shaderOutput",
2931 glu::STORAGE_OUT,
2932 glu::INTERPOLATION_LAST,
2933 glu::Layout(0)));
2934 fragment->getDefaultBlock().variables.push_back(glu::VariableDeclaration(glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP),
2935 "shaderInput",
2936 glu::STORAGE_IN,
2937 glu::INTERPOLATION_LAST,
2938 glu::Layout(1)));
2939
2940 if (m_caseType == CASE_VERTEX_TESS_FRAGMENT || m_caseType == CASE_VERTEX_TESS_GEO_FRAGMENT)
2941 {
2942 ProgramInterfaceDefinition::Shader* tessCtrl = m_program->addShader(glu::SHADERTYPE_TESSELLATION_CONTROL, glslVersion);
2943 ProgramInterfaceDefinition::Shader* tessEval = m_program->addShader(glu::SHADERTYPE_TESSELLATION_EVALUATION, glslVersion);
2944
2945 tessCtrl->getDefaultBlock().variables.push_back(glu::VariableDeclaration(glu::VarType(glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP), glu::VarType::UNSIZED_ARRAY),
2946 "shaderInput",
2947 glu::STORAGE_IN,
2948 glu::INTERPOLATION_LAST,
2949 glu::Layout(1)));
2950 tessCtrl->getDefaultBlock().variables.push_back(glu::VariableDeclaration(glu::VarType(glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP), glu::VarType::UNSIZED_ARRAY),
2951 "shaderOutput",
2952 glu::STORAGE_OUT,
2953 glu::INTERPOLATION_LAST,
2954 glu::Layout(1)));
2955
2956 tessEval->getDefaultBlock().variables.push_back(glu::VariableDeclaration(glu::VarType(glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP), glu::VarType::UNSIZED_ARRAY),
2957 "shaderInput",
2958 glu::STORAGE_IN,
2959 glu::INTERPOLATION_LAST,
2960 glu::Layout(1)));
2961 tessEval->getDefaultBlock().variables.push_back(glu::VariableDeclaration(glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP),
2962 "shaderOutput",
2963 glu::STORAGE_OUT,
2964 glu::INTERPOLATION_LAST,
2965 glu::Layout(1)));
2966 }
2967
2968 if (m_caseType == CASE_VERTEX_GEO_FRAGMENT || m_caseType == CASE_VERTEX_TESS_GEO_FRAGMENT)
2969 {
2970 ProgramInterfaceDefinition::Shader* geometry = m_program->addShader(glu::SHADERTYPE_GEOMETRY, glslVersion);
2971
2972 geometry->getDefaultBlock().variables.push_back(glu::VariableDeclaration(glu::VarType(glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP), glu::VarType::UNSIZED_ARRAY),
2973 "shaderInput",
2974 glu::STORAGE_IN,
2975 glu::INTERPOLATION_LAST,
2976 glu::Layout(1)));
2977 geometry->getDefaultBlock().variables.push_back(glu::VariableDeclaration(glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP),
2978 "shaderOutput",
2979 glu::STORAGE_OUT,
2980 glu::INTERPOLATION_LAST,
2981 glu::Layout(1)));
2982 }
2983 }
2984 else
2985 DE_ASSERT(false);
2986
2987 if (m_program->hasStage(glu::SHADERTYPE_GEOMETRY))
2988 m_program->setGeometryNumOutputVertices(1);
2989 if (m_program->hasStage(glu::SHADERTYPE_TESSELLATION_CONTROL) || m_program->hasStage(glu::SHADERTYPE_TESSELLATION_EVALUATION))
2990 m_program->setTessellationNumOutputPatchVertices(1);
2991
2992 DE_ASSERT(m_program->isValid());
2993 }
2994
deinit(void)2995 void ProgramInputOutputReferencedByCase::deinit (void)
2996 {
2997 delete m_program;
2998 m_program = DE_NULL;
2999 }
3000
iterate(void)3001 ProgramInputOutputReferencedByCase::IterateResult ProgramInputOutputReferencedByCase::iterate (void)
3002 {
3003 static const struct
3004 {
3005 glw::GLenum propName;
3006 glu::ShaderType shaderType;
3007 const char* extension;
3008 } targetProps[] =
3009 {
3010 { GL_REFERENCED_BY_VERTEX_SHADER, glu::SHADERTYPE_VERTEX, DE_NULL },
3011 { GL_REFERENCED_BY_FRAGMENT_SHADER, glu::SHADERTYPE_FRAGMENT, DE_NULL },
3012 { GL_REFERENCED_BY_COMPUTE_SHADER, glu::SHADERTYPE_COMPUTE, DE_NULL },
3013 { GL_REFERENCED_BY_TESS_CONTROL_SHADER, glu::SHADERTYPE_TESSELLATION_CONTROL, "GL_EXT_tessellation_shader" },
3014 { GL_REFERENCED_BY_TESS_EVALUATION_SHADER, glu::SHADERTYPE_TESSELLATION_EVALUATION, "GL_EXT_tessellation_shader" },
3015 { GL_REFERENCED_BY_GEOMETRY_SHADER, glu::SHADERTYPE_GEOMETRY, "GL_EXT_geometry_shader" },
3016 };
3017
3018 const bool isInputCase = (m_targetStorage == glu::STORAGE_IN || m_targetStorage == glu::STORAGE_PATCH_IN);
3019 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3020 const glu::ShaderProgram program (m_context.getRenderContext(), generateProgramInterfaceProgramSources(m_program));
3021 const std::string targetResourceName = (isInputCase) ? ("shaderInput") : ("shaderOutput");
3022 const glw::GLenum programGLInterface = (isInputCase) ? (GL_PROGRAM_INPUT) : (GL_PROGRAM_OUTPUT);
3023 glw::GLuint resourceIndex;
3024
3025 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
3026 checkAndLogProgram(program, m_program, m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
3027
3028 // find target resource index
3029
3030 resourceIndex = gl.getProgramResourceIndex(program.getProgram(), programGLInterface, targetResourceName.c_str());
3031 GLU_EXPECT_NO_ERROR(gl.getError(), "query resource index");
3032
3033 if (resourceIndex == GL_INVALID_INDEX)
3034 {
3035 m_testCtx.getLog() << tcu::TestLog::Message << "Error, query for resource \"" << targetResourceName << "\" index returned invalid index." << tcu::TestLog::EndMessage;
3036 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "could not find target resource");
3037 return STOP;
3038 }
3039
3040 // check props
3041 for (int propNdx = 0; propNdx < DE_LENGTH_OF_ARRAY(targetProps); ++propNdx)
3042 {
3043 if (targetProps[propNdx].extension == DE_NULL || m_context.getContextInfo().isExtensionSupported(targetProps[propNdx].extension))
3044 {
3045 const glw::GLenum prop = targetProps[propNdx].propName;
3046 const bool expected = (isInputCase) ? (targetProps[propNdx].shaderType == m_program->getFirstStage()) : (targetProps[propNdx].shaderType == m_program->getLastStage());
3047 glw::GLint value = -1;
3048 glw::GLint written = -1;
3049
3050 m_testCtx.getLog() << tcu::TestLog::Message << "Verifying " << glu::getProgramResourcePropertyName(prop) << ", expecting " << ((expected) ? ("TRUE") : ("FALSE")) << tcu::TestLog::EndMessage;
3051
3052 gl.getProgramResourceiv(program.getProgram(), programGLInterface, resourceIndex, 1, &prop, 1, &written, &value);
3053 GLU_EXPECT_NO_ERROR(gl.getError(), "query buffer binding");
3054
3055 if (written != 1)
3056 {
3057 m_testCtx.getLog() << tcu::TestLog::Message << "Error, query for referenced_by_* returned invalid number of values." << tcu::TestLog::EndMessage;
3058 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "property query failed");
3059 continue;
3060 }
3061
3062 m_testCtx.getLog() << tcu::TestLog::Message << glu::getProgramResourcePropertyName(prop) << " = " << glu::getBooleanStr(value) << tcu::TestLog::EndMessage;
3063
3064 if (value != ((expected) ? (GL_TRUE) : (GL_FALSE)))
3065 {
3066 m_testCtx.getLog() << tcu::TestLog::Message << "Error, got unexpected value" << tcu::TestLog::EndMessage;
3067 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "unexpected property value");
3068 continue;
3069 }
3070 }
3071 }
3072
3073 return STOP;
3074 }
3075
3076 class FeedbackResourceListTestCase : public ResourceListTestCase
3077 {
3078 public:
3079 FeedbackResourceListTestCase (Context& context, const ResourceDefinition::Node::SharedPtr& resource, const char* name);
3080 ~FeedbackResourceListTestCase (void);
3081
3082 private:
3083 IterateResult iterate (void);
3084 };
3085
FeedbackResourceListTestCase(Context & context,const ResourceDefinition::Node::SharedPtr & resource,const char * name)3086 FeedbackResourceListTestCase::FeedbackResourceListTestCase (Context& context, const ResourceDefinition::Node::SharedPtr& resource, const char* name)
3087 : ResourceListTestCase(context, resource, PROGRAMINTERFACE_TRANSFORM_FEEDBACK_VARYING, name)
3088 {
3089 }
3090
~FeedbackResourceListTestCase(void)3091 FeedbackResourceListTestCase::~FeedbackResourceListTestCase (void)
3092 {
3093 deinit();
3094 }
3095
iterate(void)3096 FeedbackResourceListTestCase::IterateResult FeedbackResourceListTestCase::iterate (void)
3097 {
3098 const glu::ShaderProgram program(m_context.getRenderContext(), generateProgramInterfaceProgramSources(m_programDefinition));
3099
3100 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
3101
3102 // Feedback varyings
3103 {
3104 tcu::MessageBuilder builder(&m_testCtx.getLog());
3105 builder << "Transform feedback varyings: {";
3106 for (int ndx = 0; ndx < (int)m_programDefinition->getTransformFeedbackVaryings().size(); ++ndx)
3107 {
3108 if (ndx)
3109 builder << ", ";
3110 builder << "\"" << m_programDefinition->getTransformFeedbackVaryings()[ndx] << "\"";
3111 }
3112 builder << "}" << tcu::TestLog::EndMessage;
3113 }
3114
3115 checkAndLogProgram(program, m_programDefinition, m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
3116
3117 // Check resource list
3118 {
3119 const tcu::ScopedLogSection section (m_testCtx.getLog(), "ResourceList", "Resource list");
3120 std::vector<std::string> resourceList;
3121 std::vector<std::string> expectedResources;
3122
3123 queryResourceList(resourceList, program.getProgram());
3124 expectedResources = getProgramInterfaceResourceList(m_programDefinition, m_programInterface);
3125
3126 // verify the list and the expected list match
3127
3128 if (!verifyResourceList(resourceList, expectedResources))
3129 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "invalid resource list");
3130
3131 // verify GetProgramResourceIndex() matches the indices of the list
3132
3133 if (!verifyResourceIndexQuery(resourceList, expectedResources, program.getProgram()))
3134 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "GetProgramResourceIndex returned unexpected values");
3135
3136 // Verify MAX_NAME_LENGTH
3137 if (!verifyMaxNameLength(resourceList, program.getProgram()))
3138 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "MAX_NAME_LENGTH invalid");
3139 }
3140
3141 return STOP;
3142 }
3143
getBlockMinDataSize(const glu::InterfaceBlock & block) const3144 int InterfaceBlockDataSizeTestCase::getBlockMinDataSize (const glu::InterfaceBlock& block) const
3145 {
3146 int dataSize = 0;
3147
3148 for (int ndx = 0; ndx < (int)block.variables.size(); ++ndx)
3149 dataSize += getVarTypeSize(block.variables[ndx].varType);
3150
3151 return dataSize;
3152 }
3153
isDataTypeLayoutQualified(glu::DataType type)3154 static bool isDataTypeLayoutQualified (glu::DataType type)
3155 {
3156 return glu::isDataTypeImage(type) || glu::isDataTypeAtomicCounter(type);
3157 }
3158
generateVariableCases(Context & context,const ResourceDefinition::Node::SharedPtr & parentStructure,tcu::TestCaseGroup * const targetGroup,const ProgramResourceQueryTestTarget & queryTarget,int expandLevel=3,bool createTestGroup=true)3159 static void generateVariableCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup, const ProgramResourceQueryTestTarget& queryTarget, int expandLevel = 3, bool createTestGroup = true)
3160 {
3161 static const struct
3162 {
3163 int level;
3164 glu::DataType dataType;
3165 } variableTypes[] =
3166 {
3167 { 0, glu::TYPE_FLOAT },
3168 { 1, glu::TYPE_INT },
3169 { 1, glu::TYPE_UINT },
3170 { 1, glu::TYPE_BOOL },
3171
3172 { 3, glu::TYPE_FLOAT_VEC2 },
3173 { 1, glu::TYPE_FLOAT_VEC3 },
3174 { 1, glu::TYPE_FLOAT_VEC4 },
3175
3176 { 3, glu::TYPE_INT_VEC2 },
3177 { 2, glu::TYPE_INT_VEC3 },
3178 { 3, glu::TYPE_INT_VEC4 },
3179
3180 { 3, glu::TYPE_UINT_VEC2 },
3181 { 2, glu::TYPE_UINT_VEC3 },
3182 { 3, glu::TYPE_UINT_VEC4 },
3183
3184 { 3, glu::TYPE_BOOL_VEC2 },
3185 { 2, glu::TYPE_BOOL_VEC3 },
3186 { 3, glu::TYPE_BOOL_VEC4 },
3187
3188 { 2, glu::TYPE_FLOAT_MAT2 },
3189 { 3, glu::TYPE_FLOAT_MAT2X3 },
3190 { 3, glu::TYPE_FLOAT_MAT2X4 },
3191 { 2, glu::TYPE_FLOAT_MAT3X2 },
3192 { 2, glu::TYPE_FLOAT_MAT3 },
3193 { 3, glu::TYPE_FLOAT_MAT3X4 },
3194 { 2, glu::TYPE_FLOAT_MAT4X2 },
3195 { 3, glu::TYPE_FLOAT_MAT4X3 },
3196 { 2, glu::TYPE_FLOAT_MAT4 },
3197 };
3198
3199 tcu::TestCaseGroup* group;
3200
3201 if (createTestGroup)
3202 {
3203 group = new tcu::TestCaseGroup(context.getTestContext(), "basic_type", "Basic variable");
3204 targetGroup->addChild(group);
3205 }
3206 else
3207 group = targetGroup;
3208
3209 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(variableTypes); ++ndx)
3210 {
3211 if (variableTypes[ndx].level <= expandLevel)
3212 {
3213 const ResourceDefinition::Node::SharedPtr variable(new ResourceDefinition::Variable(parentStructure, variableTypes[ndx].dataType));
3214 group->addChild(new ResourceTestCase(context, variable, queryTarget));
3215 }
3216 }
3217 }
3218
generateOpaqueTypeCases(Context & context,const ResourceDefinition::Node::SharedPtr & parentStructure,tcu::TestCaseGroup * const targetGroup,const ProgramResourceQueryTestTarget & queryTarget,int expandLevel=3,bool createTestGroup=true)3219 static void generateOpaqueTypeCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup, const ProgramResourceQueryTestTarget& queryTarget, int expandLevel = 3, bool createTestGroup = true)
3220 {
3221 static const struct
3222 {
3223 int level;
3224 glu::DataType dataType;
3225 } variableTypes[] =
3226 {
3227 { 0, glu::TYPE_SAMPLER_2D },
3228 { 2, glu::TYPE_SAMPLER_CUBE },
3229 { 1, glu::TYPE_SAMPLER_2D_ARRAY },
3230 { 1, glu::TYPE_SAMPLER_3D },
3231 { 2, glu::TYPE_SAMPLER_2D_SHADOW },
3232 { 3, glu::TYPE_SAMPLER_CUBE_SHADOW },
3233 { 3, glu::TYPE_SAMPLER_2D_ARRAY_SHADOW },
3234 { 1, glu::TYPE_INT_SAMPLER_2D },
3235 { 3, glu::TYPE_INT_SAMPLER_CUBE },
3236 { 3, glu::TYPE_INT_SAMPLER_2D_ARRAY },
3237 { 3, glu::TYPE_INT_SAMPLER_3D },
3238 { 2, glu::TYPE_UINT_SAMPLER_2D },
3239 { 3, glu::TYPE_UINT_SAMPLER_CUBE },
3240 { 3, glu::TYPE_UINT_SAMPLER_2D_ARRAY },
3241 { 3, glu::TYPE_UINT_SAMPLER_3D },
3242 { 2, glu::TYPE_SAMPLER_2D_MULTISAMPLE },
3243 { 2, glu::TYPE_INT_SAMPLER_2D_MULTISAMPLE },
3244 { 3, glu::TYPE_UINT_SAMPLER_2D_MULTISAMPLE },
3245 { 1, glu::TYPE_IMAGE_2D },
3246 { 3, glu::TYPE_IMAGE_CUBE },
3247 { 3, glu::TYPE_IMAGE_2D_ARRAY },
3248 { 3, glu::TYPE_IMAGE_3D },
3249 { 3, glu::TYPE_INT_IMAGE_2D },
3250 { 3, glu::TYPE_INT_IMAGE_CUBE },
3251 { 1, glu::TYPE_INT_IMAGE_2D_ARRAY },
3252 { 3, glu::TYPE_INT_IMAGE_3D },
3253 { 2, glu::TYPE_UINT_IMAGE_2D },
3254 { 3, glu::TYPE_UINT_IMAGE_CUBE },
3255 { 3, glu::TYPE_UINT_IMAGE_2D_ARRAY },
3256 { 3, glu::TYPE_UINT_IMAGE_3D },
3257 { 1, glu::TYPE_UINT_ATOMIC_COUNTER },
3258 };
3259
3260 bool isStructMember = false;
3261
3262 // Requirements
3263 for (const ResourceDefinition::Node* node = parentStructure.get(); node; node = node->getEnclosingNode())
3264 {
3265 // Don't insert inside a interface block
3266 if (node->getType() == ResourceDefinition::Node::TYPE_INTERFACE_BLOCK)
3267 return;
3268
3269 isStructMember |= (node->getType() == ResourceDefinition::Node::TYPE_STRUCT_MEMBER);
3270 }
3271
3272 // Add cases
3273 {
3274 tcu::TestCaseGroup* group;
3275
3276 if (createTestGroup)
3277 {
3278 group = new tcu::TestCaseGroup(context.getTestContext(), "opaque_type", "Opaque types");
3279 targetGroup->addChild(group);
3280 }
3281 else
3282 group = targetGroup;
3283
3284 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(variableTypes); ++ndx)
3285 {
3286 if (variableTypes[ndx].level > expandLevel)
3287 continue;
3288
3289 // Layout qualifiers are not allowed on struct members
3290 if (isDataTypeLayoutQualified(variableTypes[ndx].dataType) && isStructMember)
3291 continue;
3292
3293 {
3294 const ResourceDefinition::Node::SharedPtr variable(new ResourceDefinition::Variable(parentStructure, variableTypes[ndx].dataType));
3295 group->addChild(new ResourceTestCase(context, variable, queryTarget));
3296 }
3297 }
3298 }
3299 }
3300
3301 static void generateCompoundVariableCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup, const ProgramResourceQueryTestTarget& queryTarget, int expandLevel = 3);
3302
generateVariableArrayCases(Context & context,const ResourceDefinition::Node::SharedPtr & parentStructure,tcu::TestCaseGroup * const targetGroup,const ProgramResourceQueryTestTarget & queryTarget,int expandLevel=3)3303 static void generateVariableArrayCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup, const ProgramResourceQueryTestTarget& queryTarget, int expandLevel = 3)
3304 {
3305 if (expandLevel > 0)
3306 {
3307 const ResourceDefinition::Node::SharedPtr arrayElement (new ResourceDefinition::ArrayElement(parentStructure));
3308 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), "array", "Arrays");
3309
3310 targetGroup->addChild(blockGroup);
3311
3312 // Arrays of basic variables
3313 generateVariableCases(context, arrayElement, blockGroup, queryTarget, expandLevel, expandLevel != 1);
3314
3315 // Arrays of opaque types
3316 generateOpaqueTypeCases(context, arrayElement, blockGroup, queryTarget, expandLevel, expandLevel != 1);
3317
3318 // Arrays of arrays
3319 generateVariableArrayCases(context, arrayElement, blockGroup, queryTarget, expandLevel-1);
3320
3321 // Arrays of structs
3322 generateCompoundVariableCases(context, arrayElement, blockGroup, queryTarget, expandLevel-1);
3323 }
3324 }
3325
generateCompoundVariableCases(Context & context,const ResourceDefinition::Node::SharedPtr & parentStructure,tcu::TestCaseGroup * const targetGroup,const ProgramResourceQueryTestTarget & queryTarget,int expandLevel)3326 static void generateCompoundVariableCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup, const ProgramResourceQueryTestTarget& queryTarget, int expandLevel)
3327 {
3328 if (expandLevel > 0)
3329 {
3330 const ResourceDefinition::Node::SharedPtr structMember (new ResourceDefinition::StructMember(parentStructure));
3331 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), "struct", "Structs");
3332
3333 targetGroup->addChild(blockGroup);
3334
3335 // Struct containing basic variable
3336 generateVariableCases(context, structMember, blockGroup, queryTarget, expandLevel, expandLevel != 1);
3337
3338 // Struct containing opaque types
3339 generateOpaqueTypeCases(context, structMember, blockGroup, queryTarget, expandLevel, expandLevel != 1);
3340
3341 // Struct containing arrays
3342 generateVariableArrayCases(context, structMember, blockGroup, queryTarget, expandLevel-1);
3343
3344 // Struct containing struct
3345 generateCompoundVariableCases(context, structMember, blockGroup, queryTarget, expandLevel-1);
3346 }
3347 }
3348
3349 // Resource list cases
3350
3351 enum BlockFlags
3352 {
3353 BLOCKFLAG_DEFAULT = 0x01,
3354 BLOCKFLAG_NAMED = 0x02,
3355 BLOCKFLAG_UNNAMED = 0x04,
3356 BLOCKFLAG_ARRAY = 0x08,
3357
3358 BLOCKFLAG_ALL = 0x0F
3359 };
3360
generateUniformCaseBlocks(Context & context,const ResourceDefinition::Node::SharedPtr & parentStructure,tcu::TestCaseGroup * const targetGroup,deUint32 blockFlags,void (* blockContentGenerator)(Context &,const ResourceDefinition::Node::SharedPtr &,tcu::TestCaseGroup * const))3361 static void generateUniformCaseBlocks (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup, deUint32 blockFlags, void (*blockContentGenerator)(Context&, const ResourceDefinition::Node::SharedPtr&, tcu::TestCaseGroup* const))
3362 {
3363 const ResourceDefinition::Node::SharedPtr defaultBlock (new ResourceDefinition::DefaultBlock(parentStructure));
3364 const ResourceDefinition::Node::SharedPtr uniform (new ResourceDefinition::StorageQualifier(defaultBlock, glu::STORAGE_UNIFORM));
3365
3366 // .default_block
3367 if (blockFlags & BLOCKFLAG_DEFAULT)
3368 {
3369 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), "default_block", "Default block");
3370 targetGroup->addChild(blockGroup);
3371
3372 blockContentGenerator(context, uniform, blockGroup);
3373 }
3374
3375 // .named_block
3376 if (blockFlags & BLOCKFLAG_NAMED)
3377 {
3378 const ResourceDefinition::Node::SharedPtr block(new ResourceDefinition::InterfaceBlock(uniform, true));
3379
3380 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), "named_block", "Named uniform block");
3381 targetGroup->addChild(blockGroup);
3382
3383 blockContentGenerator(context, block, blockGroup);
3384 }
3385
3386 // .unnamed_block
3387 if (blockFlags & BLOCKFLAG_UNNAMED)
3388 {
3389 const ResourceDefinition::Node::SharedPtr block(new ResourceDefinition::InterfaceBlock(uniform, false));
3390
3391 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), "unnamed_block", "Unnamed uniform block");
3392 targetGroup->addChild(blockGroup);
3393
3394 blockContentGenerator(context, block, blockGroup);
3395 }
3396
3397 // .block_array
3398 if (blockFlags & BLOCKFLAG_ARRAY)
3399 {
3400 const ResourceDefinition::Node::SharedPtr arrayElement (new ResourceDefinition::ArrayElement(uniform));
3401 const ResourceDefinition::Node::SharedPtr block (new ResourceDefinition::InterfaceBlock(arrayElement, true));
3402
3403 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), "block_array", "Uniform block array");
3404 targetGroup->addChild(blockGroup);
3405
3406 blockContentGenerator(context, block, blockGroup);
3407 }
3408 }
3409
generateBufferBackedResourceListBlockContentCases(Context & context,const ResourceDefinition::Node::SharedPtr & parentStructure,tcu::TestCaseGroup * const targetGroup,ProgramInterface interface,int depth)3410 static void generateBufferBackedResourceListBlockContentCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup, ProgramInterface interface, int depth)
3411 {
3412 // variable
3413 {
3414 const ResourceDefinition::Node::SharedPtr variable(new ResourceDefinition::Variable(parentStructure, glu::TYPE_FLOAT_VEC4));
3415 targetGroup->addChild(new ResourceListTestCase(context, variable, interface));
3416 }
3417
3418 // struct
3419 if (depth > 0)
3420 {
3421 const ResourceDefinition::Node::SharedPtr structMember(new ResourceDefinition::StructMember(parentStructure));
3422 generateBufferBackedResourceListBlockContentCases(context, structMember, targetGroup, interface, depth - 1);
3423 }
3424
3425 // array
3426 if (depth > 0)
3427 {
3428 const ResourceDefinition::Node::SharedPtr arrayElement(new ResourceDefinition::ArrayElement(parentStructure));
3429 generateBufferBackedResourceListBlockContentCases(context, arrayElement, targetGroup, interface, depth - 1);
3430 }
3431 }
3432
generateBufferBackedVariableAggregateTypeCases(Context & context,const ResourceDefinition::Node::SharedPtr & parentStructure,tcu::TestCaseGroup * const targetGroup,ProgramInterface interface,ProgramResourcePropFlags targetProp,glu::DataType dataType,const std::string & nameSuffix,int depth)3433 static void generateBufferBackedVariableAggregateTypeCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup, ProgramInterface interface, ProgramResourcePropFlags targetProp, glu::DataType dataType, const std::string& nameSuffix, int depth)
3434 {
3435 // variable
3436 {
3437 const ResourceDefinition::Node::SharedPtr variable(new ResourceDefinition::Variable(parentStructure, dataType));
3438 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(interface, targetProp), ("var" + nameSuffix).c_str()));
3439 }
3440
3441 // struct
3442 if (depth > 0)
3443 {
3444 const ResourceDefinition::Node::SharedPtr structMember(new ResourceDefinition::StructMember(parentStructure));
3445 generateBufferBackedVariableAggregateTypeCases(context, structMember, targetGroup, interface, targetProp, dataType, "_struct" + nameSuffix, depth - 1);
3446 }
3447
3448 // array
3449 if (depth > 0)
3450 {
3451 const ResourceDefinition::Node::SharedPtr arrayElement(new ResourceDefinition::ArrayElement(parentStructure));
3452 generateBufferBackedVariableAggregateTypeCases(context, arrayElement, targetGroup, interface, targetProp, dataType, "_array" + nameSuffix, depth - 1);
3453 }
3454 }
3455
generateUniformResourceListBlockContents(Context & context,const ResourceDefinition::Node::SharedPtr & parentStructure,tcu::TestCaseGroup * const targetGroup)3456 static void generateUniformResourceListBlockContents (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup)
3457 {
3458 generateBufferBackedResourceListBlockContentCases(context, parentStructure, targetGroup, PROGRAMINTERFACE_UNIFORM, 4);
3459 }
3460
generateUniformBlockArraySizeContents(Context & context,const ResourceDefinition::Node::SharedPtr & parentStructure,tcu::TestCaseGroup * const targetGroup)3461 static void generateUniformBlockArraySizeContents (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup)
3462 {
3463 const ProgramResourceQueryTestTarget queryTarget (PROGRAMINTERFACE_UNIFORM, PROGRAMRESOURCEPROP_ARRAY_SIZE);
3464 const bool isInterfaceBlock = (parentStructure->getType() == ResourceDefinition::Node::TYPE_INTERFACE_BLOCK);
3465 const bool namedNonArrayBlock = isInterfaceBlock &&
3466 static_cast<const ResourceDefinition::InterfaceBlock*>(parentStructure.get())->m_named &&
3467 parentStructure->getEnclosingNode()->getType() != ResourceDefinition::Node::TYPE_ARRAY_ELEMENT;
3468
3469 if (!isInterfaceBlock || namedNonArrayBlock)
3470 {
3471 // .types
3472 {
3473 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), "types", "Types");
3474 targetGroup->addChild(blockGroup);
3475
3476 generateVariableCases(context, parentStructure, blockGroup, queryTarget, 2, false);
3477 generateOpaqueTypeCases(context, parentStructure, blockGroup, queryTarget, 2, false);
3478 }
3479
3480 // aggregates
3481 {
3482 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), "aggregates", "Aggregate types");
3483 targetGroup->addChild(blockGroup);
3484
3485 generateBufferBackedVariableAggregateTypeCases(context, parentStructure, blockGroup, queryTarget.interface, PROGRAMRESOURCEPROP_ARRAY_SIZE, glu::TYPE_FLOAT, "", 3);
3486 }
3487 }
3488 else
3489 {
3490 // aggregates
3491 generateBufferBackedVariableAggregateTypeCases(context, parentStructure, targetGroup, queryTarget.interface, PROGRAMRESOURCEPROP_ARRAY_SIZE, glu::TYPE_FLOAT, "", 2);
3492 }
3493 }
3494
generateBufferBackedArrayStrideTypeAggregateSubCases(Context & context,const ResourceDefinition::Node::SharedPtr & parentStructure,tcu::TestCaseGroup * const targetGroup,const std::string & namePrefix,ProgramInterface interface,glu::DataType type,int expandLevel)3495 static void generateBufferBackedArrayStrideTypeAggregateSubCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup, const std::string& namePrefix, ProgramInterface interface, glu::DataType type, int expandLevel)
3496 {
3497 // case
3498 {
3499 const ResourceDefinition::Node::SharedPtr variable(new ResourceDefinition::Variable(parentStructure, type));
3500 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(interface, PROGRAMRESOURCEPROP_ARRAY_STRIDE), namePrefix.c_str()));
3501 }
3502
3503 if (expandLevel > 0)
3504 {
3505 const ResourceDefinition::Node::SharedPtr structMember (new ResourceDefinition::StructMember(parentStructure));
3506 const ResourceDefinition::Node::SharedPtr arrayElement (new ResourceDefinition::ArrayElement(parentStructure));
3507
3508 // _struct
3509 generateBufferBackedArrayStrideTypeAggregateSubCases(context, structMember, targetGroup, namePrefix + "_struct", interface, type, expandLevel - 1);
3510
3511 // _array
3512 generateBufferBackedArrayStrideTypeAggregateSubCases(context, arrayElement, targetGroup, namePrefix + "_array", interface, type, expandLevel - 1);
3513 }
3514 }
3515
generateBufferBackedArrayStrideTypeAggregateCases(Context & context,const ResourceDefinition::Node::SharedPtr & parentStructure,tcu::TestCaseGroup * const targetGroup,ProgramInterface interface,glu::DataType type,int expandLevel,bool includeBaseCase)3516 static void generateBufferBackedArrayStrideTypeAggregateCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup, ProgramInterface interface, glu::DataType type, int expandLevel, bool includeBaseCase)
3517 {
3518 const ResourceDefinition::Node::SharedPtr structMember (new ResourceDefinition::StructMember(parentStructure));
3519 const ResourceDefinition::Node::SharedPtr arrayElement (new ResourceDefinition::ArrayElement(parentStructure));
3520 const std::string namePrefix = glu::getDataTypeName(type);
3521
3522 if (expandLevel == 0 || includeBaseCase)
3523 {
3524 const ResourceDefinition::Node::SharedPtr variable(new ResourceDefinition::Variable(parentStructure, type));
3525 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(interface, PROGRAMRESOURCEPROP_ARRAY_STRIDE), namePrefix.c_str()));
3526 }
3527 if (expandLevel >= 1)
3528 {
3529 // _struct
3530 if (!glu::isDataTypeAtomicCounter(type))
3531 generateBufferBackedArrayStrideTypeAggregateSubCases(context, structMember, targetGroup, namePrefix + "_struct", interface, type, expandLevel - 1);
3532
3533 // _array
3534 generateBufferBackedArrayStrideTypeAggregateSubCases(context, arrayElement, targetGroup, namePrefix + "_array", interface, type, expandLevel - 1);
3535 }
3536 }
3537
generateUniformBlockArrayStrideContents(Context & context,const ResourceDefinition::Node::SharedPtr & parentStructure,tcu::TestCaseGroup * const targetGroup)3538 static void generateUniformBlockArrayStrideContents (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup)
3539 {
3540 const ProgramResourceQueryTestTarget queryTarget (PROGRAMINTERFACE_UNIFORM, PROGRAMRESOURCEPROP_ARRAY_STRIDE);
3541 const bool isInterfaceBlock = (parentStructure->getType() == ResourceDefinition::Node::TYPE_INTERFACE_BLOCK);
3542 const bool namedNonArrayBlock = isInterfaceBlock &&
3543 static_cast<const ResourceDefinition::InterfaceBlock*>(parentStructure.get())->m_named &&
3544 parentStructure->getEnclosingNode()->getType() != ResourceDefinition::Node::TYPE_ARRAY_ELEMENT;
3545
3546 if (!isInterfaceBlock || namedNonArrayBlock)
3547 {
3548 // .types
3549 {
3550 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), "types", "Types");
3551 targetGroup->addChild(blockGroup);
3552
3553 generateVariableCases(context, parentStructure, blockGroup, queryTarget, 2, false);
3554 generateOpaqueTypeCases(context, parentStructure, blockGroup, queryTarget, 2, false);
3555 }
3556
3557 // .aggregates
3558 {
3559 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), "aggregates", "Aggregate types");
3560 targetGroup->addChild(blockGroup);
3561
3562 // .sampler_2d_*
3563 if (!isInterfaceBlock)
3564 generateBufferBackedArrayStrideTypeAggregateCases(context, parentStructure, blockGroup, queryTarget.interface, glu::TYPE_SAMPLER_2D, 1, false);
3565
3566 // .atomic_counter_*
3567 if (!isInterfaceBlock)
3568 {
3569 const ResourceDefinition::Node::SharedPtr layout(new ResourceDefinition::LayoutQualifier(parentStructure, glu::Layout(-1, 0)));
3570 generateBufferBackedArrayStrideTypeAggregateCases(context, layout, blockGroup, queryTarget.interface, glu::TYPE_UINT_ATOMIC_COUNTER, 1, false);
3571 }
3572
3573 // .float_*
3574 generateBufferBackedArrayStrideTypeAggregateCases(context, parentStructure, blockGroup, queryTarget.interface, glu::TYPE_FLOAT, 2, false);
3575
3576 // .bool_*
3577 generateBufferBackedArrayStrideTypeAggregateCases(context, parentStructure, blockGroup, queryTarget.interface, glu::TYPE_BOOL, 1, false);
3578
3579 // .bvec3_*
3580 generateBufferBackedArrayStrideTypeAggregateCases(context, parentStructure, blockGroup, queryTarget.interface, glu::TYPE_BOOL_VEC3, 2, false);
3581
3582 // .vec3_*
3583 generateBufferBackedArrayStrideTypeAggregateCases(context, parentStructure, blockGroup, queryTarget.interface, glu::TYPE_FLOAT_VEC3, 2, false);
3584
3585 // .ivec2_*
3586 generateBufferBackedArrayStrideTypeAggregateCases(context, parentStructure, blockGroup, queryTarget.interface, glu::TYPE_INT_VEC3, 2, false);
3587 }
3588 }
3589 else
3590 {
3591 generateVariableCases(context, parentStructure, targetGroup, queryTarget, 1);
3592 generateVariableArrayCases(context, parentStructure, targetGroup, queryTarget, 1);
3593 generateCompoundVariableCases(context, parentStructure, targetGroup, queryTarget, 1);
3594 }
3595 }
3596
generateUniformBlockLocationContents(Context & context,const ResourceDefinition::Node::SharedPtr & parentStructure,tcu::TestCaseGroup * const targetGroup)3597 static void generateUniformBlockLocationContents (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup)
3598 {
3599 const ProgramResourceQueryTestTarget queryTarget (PROGRAMINTERFACE_UNIFORM, PROGRAMRESOURCEPROP_LOCATION);
3600 const bool isInterfaceBlock = (parentStructure->getType() == ResourceDefinition::Node::TYPE_INTERFACE_BLOCK);
3601
3602 if (!isInterfaceBlock)
3603 {
3604 generateVariableCases(context, parentStructure, targetGroup, queryTarget, 3);
3605 generateOpaqueTypeCases(context, parentStructure, targetGroup, queryTarget, 3);
3606 generateVariableArrayCases(context, parentStructure, targetGroup, queryTarget, 2);
3607 generateCompoundVariableCases(context, parentStructure, targetGroup, queryTarget, 2);
3608 }
3609 else
3610 generateVariableCases(context, parentStructure, targetGroup, queryTarget, 1, false);
3611 }
3612
generateUniformBlockBlockIndexContents(Context & context,tcu::TestCaseGroup * const targetGroup,glu::GLSLVersion glslVersion)3613 static void generateUniformBlockBlockIndexContents (Context& context, tcu::TestCaseGroup* const targetGroup, glu::GLSLVersion glslVersion)
3614 {
3615 const ResourceDefinition::Node::SharedPtr program (new ResourceDefinition::Program());
3616 const ResourceDefinition::Node::SharedPtr shader (new ResourceDefinition::Shader(program, glu::SHADERTYPE_COMPUTE, glslVersion));
3617 const ResourceDefinition::Node::SharedPtr defaultBlock (new ResourceDefinition::DefaultBlock(shader));
3618 const ResourceDefinition::Node::SharedPtr uniform (new ResourceDefinition::StorageQualifier(defaultBlock, glu::STORAGE_UNIFORM));
3619 const ResourceDefinition::Node::SharedPtr binding (new ResourceDefinition::LayoutQualifier(uniform, glu::Layout(-1, 0)));
3620
3621 // .default_block
3622 {
3623 const ResourceDefinition::Node::SharedPtr variable(new ResourceDefinition::Variable(uniform, glu::TYPE_FLOAT_VEC4));
3624
3625 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_UNIFORM, PROGRAMRESOURCEPROP_BLOCK_INDEX), "default_block"));
3626 }
3627
3628 // .named_block
3629 {
3630 const ResourceDefinition::Node::SharedPtr buffer (new ResourceDefinition::InterfaceBlock(binding, true));
3631 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(buffer, glu::TYPE_FLOAT_VEC4));
3632
3633 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_UNIFORM, PROGRAMRESOURCEPROP_BLOCK_INDEX), "named_block"));
3634 }
3635
3636 // .unnamed_block
3637 {
3638 const ResourceDefinition::Node::SharedPtr buffer (new ResourceDefinition::InterfaceBlock(binding, false));
3639 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(buffer, glu::TYPE_FLOAT_VEC4));
3640
3641 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_UNIFORM, PROGRAMRESOURCEPROP_BLOCK_INDEX), "unnamed_block"));
3642 }
3643
3644 // .block_array
3645 {
3646 const ResourceDefinition::Node::SharedPtr arrayElement (new ResourceDefinition::ArrayElement(binding));
3647 const ResourceDefinition::Node::SharedPtr buffer (new ResourceDefinition::InterfaceBlock(arrayElement, true));
3648 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(buffer, glu::TYPE_FLOAT_VEC4));
3649
3650 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_UNIFORM, PROGRAMRESOURCEPROP_BLOCK_INDEX), "block_array"));
3651 }
3652 }
3653
generateUniformBlockAtomicCounterBufferIndexContents(Context & context,const ResourceDefinition::Node::SharedPtr & parentStructure,tcu::TestCaseGroup * const targetGroup)3654 static void generateUniformBlockAtomicCounterBufferIndexContents (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup)
3655 {
3656 const ProgramResourceQueryTestTarget queryTarget (PROGRAMINTERFACE_UNIFORM, PROGRAMRESOURCEPROP_ATOMIC_COUNTER_BUFFER_INDEX);
3657 const bool isInterfaceBlock = (parentStructure->getType() == ResourceDefinition::Node::TYPE_INTERFACE_BLOCK);
3658
3659 if (!isInterfaceBlock)
3660 {
3661 generateVariableCases(context, parentStructure, targetGroup, queryTarget, 3);
3662 generateOpaqueTypeCases(context, parentStructure, targetGroup, queryTarget, 3);
3663
3664 // .array
3665 {
3666 const ResourceDefinition::Node::SharedPtr arrayElement (new ResourceDefinition::ArrayElement(parentStructure));
3667 const ResourceDefinition::Node::SharedPtr arrayArrayElement (new ResourceDefinition::ArrayElement(arrayElement));
3668 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(arrayElement, glu::TYPE_UINT_ATOMIC_COUNTER));
3669 const ResourceDefinition::Node::SharedPtr elementvariable (new ResourceDefinition::Variable(arrayArrayElement, glu::TYPE_UINT_ATOMIC_COUNTER));
3670 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), "array", "Arrays");
3671
3672 targetGroup->addChild(blockGroup);
3673
3674 blockGroup->addChild(new ResourceTestCase(context, variable, queryTarget, "var_array"));
3675 blockGroup->addChild(new ResourceTestCase(context, elementvariable, queryTarget, "var_array_array"));
3676 }
3677 }
3678 else
3679 generateVariableCases(context, parentStructure, targetGroup, queryTarget, 1, false);
3680 }
3681
generateUniformBlockNameLengthContents(Context & context,const ResourceDefinition::Node::SharedPtr & parentStructure,tcu::TestCaseGroup * const targetGroup)3682 static void generateUniformBlockNameLengthContents (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup)
3683 {
3684 const bool isInterfaceBlock = (parentStructure->getType() == ResourceDefinition::Node::TYPE_INTERFACE_BLOCK);
3685 const bool namedNonArrayBlock = isInterfaceBlock &&
3686 static_cast<const ResourceDefinition::InterfaceBlock*>(parentStructure.get())->m_named &&
3687 parentStructure->getEnclosingNode()->getType() != ResourceDefinition::Node::TYPE_ARRAY_ELEMENT;
3688
3689 if (!isInterfaceBlock || namedNonArrayBlock)
3690 generateBufferBackedVariableAggregateTypeCases(context, parentStructure, targetGroup, PROGRAMINTERFACE_UNIFORM, PROGRAMRESOURCEPROP_NAME_LENGTH, glu::TYPE_FLOAT, "", 2);
3691 else
3692 generateBufferBackedVariableAggregateTypeCases(context, parentStructure, targetGroup, PROGRAMINTERFACE_UNIFORM, PROGRAMRESOURCEPROP_NAME_LENGTH, glu::TYPE_FLOAT, "", 1);
3693 }
3694
generateUniformBlockTypeContents(Context & context,const ResourceDefinition::Node::SharedPtr & parentStructure,tcu::TestCaseGroup * const targetGroup)3695 static void generateUniformBlockTypeContents (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup)
3696 {
3697 const ProgramResourceQueryTestTarget queryTarget (PROGRAMINTERFACE_UNIFORM, PROGRAMRESOURCEPROP_TYPE);
3698 const bool isInterfaceBlock = (parentStructure->getType() == ResourceDefinition::Node::TYPE_INTERFACE_BLOCK);
3699 const bool namedNonArrayBlock = isInterfaceBlock &&
3700 static_cast<const ResourceDefinition::InterfaceBlock*>(parentStructure.get())->m_named &&
3701 parentStructure->getEnclosingNode()->getType() != ResourceDefinition::Node::TYPE_ARRAY_ELEMENT;
3702
3703 if (!isInterfaceBlock || namedNonArrayBlock)
3704 {
3705 // .types
3706 {
3707 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), "types", "Types");
3708 targetGroup->addChild(blockGroup);
3709
3710 generateVariableCases(context, parentStructure, blockGroup, queryTarget, 3, false);
3711 generateOpaqueTypeCases(context, parentStructure, blockGroup, queryTarget, 3, false);
3712 }
3713
3714 generateVariableArrayCases(context, parentStructure, targetGroup, queryTarget, 1);
3715 generateCompoundVariableCases(context, parentStructure, targetGroup, queryTarget, 1);
3716
3717 }
3718 else
3719 {
3720 generateVariableCases(context, parentStructure, targetGroup, queryTarget, 1);
3721 generateVariableArrayCases(context, parentStructure, targetGroup, queryTarget, 1);
3722 generateCompoundVariableCases(context, parentStructure, targetGroup, queryTarget, 1);
3723 }
3724 }
3725
generateUniformBlockOffsetContents(Context & context,const ResourceDefinition::Node::SharedPtr & parentStructure,tcu::TestCaseGroup * const targetGroup)3726 static void generateUniformBlockOffsetContents (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup)
3727 {
3728 const ProgramResourceQueryTestTarget queryTarget (PROGRAMINTERFACE_UNIFORM, PROGRAMRESOURCEPROP_OFFSET);
3729 const bool isInterfaceBlock = (parentStructure->getType() == ResourceDefinition::Node::TYPE_INTERFACE_BLOCK);
3730 const bool namedNonArrayBlock = isInterfaceBlock &&
3731 static_cast<const ResourceDefinition::InterfaceBlock*>(parentStructure.get())->m_named &&
3732 parentStructure->getEnclosingNode()->getType() != ResourceDefinition::Node::TYPE_ARRAY_ELEMENT;
3733
3734 if (!isInterfaceBlock)
3735 {
3736 // .types
3737 {
3738 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), "types", "Types");
3739 targetGroup->addChild(blockGroup);
3740
3741 generateVariableCases(context, parentStructure, blockGroup, queryTarget, 3, false);
3742 generateOpaqueTypeCases(context, parentStructure, blockGroup, queryTarget, 3, false);
3743 }
3744
3745 // .aggregates
3746 {
3747 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), "aggregates", "Aggregate types");
3748 targetGroup->addChild(blockGroup);
3749
3750 // .atomic_uint_struct
3751 // .atomic_uint_array
3752 {
3753 const ResourceDefinition::Node::SharedPtr offset (new ResourceDefinition::LayoutQualifier(parentStructure, glu::Layout(-1, -1, 4)));
3754 const ResourceDefinition::Node::SharedPtr arrayElement (new ResourceDefinition::ArrayElement(offset));
3755 const ResourceDefinition::Node::SharedPtr elementVariable (new ResourceDefinition::Variable(arrayElement, glu::TYPE_UINT_ATOMIC_COUNTER));
3756
3757 blockGroup->addChild(new ResourceTestCase(context, elementVariable, queryTarget, "atomic_uint_array"));
3758 }
3759
3760 // .float_array
3761 // .float_struct
3762 {
3763 const ResourceDefinition::Node::SharedPtr structMember (new ResourceDefinition::StructMember(parentStructure));
3764 const ResourceDefinition::Node::SharedPtr arrayElement (new ResourceDefinition::ArrayElement(parentStructure));
3765 const ResourceDefinition::Node::SharedPtr memberVariable (new ResourceDefinition::Variable(structMember, glu::TYPE_FLOAT));
3766 const ResourceDefinition::Node::SharedPtr elementVariable (new ResourceDefinition::Variable(arrayElement, glu::TYPE_FLOAT));
3767
3768 blockGroup->addChild(new ResourceTestCase(context, memberVariable, queryTarget, "float_struct"));
3769 blockGroup->addChild(new ResourceTestCase(context, elementVariable, queryTarget, "float_array"));
3770 }
3771 }
3772 }
3773 else if (namedNonArrayBlock)
3774 {
3775 // .types
3776 {
3777 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), "types", "Types");
3778 targetGroup->addChild(blockGroup);
3779
3780 generateVariableCases(context, parentStructure, blockGroup, queryTarget, 3, false);
3781 generateOpaqueTypeCases(context, parentStructure, blockGroup, queryTarget, 3, false);
3782 }
3783
3784 // .aggregates
3785 {
3786 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), "aggregates", "Aggregate types");
3787 targetGroup->addChild(blockGroup);
3788
3789 // .float_array
3790 // .float_struct
3791 {
3792 const ResourceDefinition::Node::SharedPtr structMember (new ResourceDefinition::StructMember(parentStructure));
3793 const ResourceDefinition::Node::SharedPtr arrayElement (new ResourceDefinition::StructMember(parentStructure));
3794 const ResourceDefinition::Node::SharedPtr memberVariable (new ResourceDefinition::Variable(structMember, glu::TYPE_FLOAT));
3795 const ResourceDefinition::Node::SharedPtr elementVariable (new ResourceDefinition::Variable(arrayElement, glu::TYPE_FLOAT));
3796
3797 blockGroup->addChild(new ResourceTestCase(context, memberVariable, queryTarget, "float_struct"));
3798 blockGroup->addChild(new ResourceTestCase(context, elementVariable, queryTarget, "float_array"));
3799 }
3800 }
3801 }
3802 else
3803 {
3804 generateVariableCases(context, parentStructure, targetGroup, queryTarget, 1);
3805 generateVariableArrayCases(context, parentStructure, targetGroup, queryTarget, 1);
3806 generateCompoundVariableCases(context, parentStructure, targetGroup, queryTarget, 1);
3807 }
3808 }
3809
generateMatrixVariableCases(Context & context,const ResourceDefinition::Node::SharedPtr & parentStructure,tcu::TestCaseGroup * const targetGroup,const ProgramResourceQueryTestTarget & queryTarget,bool createTestGroup=true,int expandLevel=2)3810 static void generateMatrixVariableCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup, const ProgramResourceQueryTestTarget& queryTarget, bool createTestGroup = true, int expandLevel = 2)
3811 {
3812 static const struct
3813 {
3814 int priority;
3815 glu::DataType type;
3816 } variableTypes[] =
3817 {
3818 { 0, glu::TYPE_FLOAT_MAT2 },
3819 { 1, glu::TYPE_FLOAT_MAT2X3 },
3820 { 2, glu::TYPE_FLOAT_MAT2X4 },
3821 { 2, glu::TYPE_FLOAT_MAT3X2 },
3822 { 1, glu::TYPE_FLOAT_MAT3 },
3823 { 0, glu::TYPE_FLOAT_MAT3X4 },
3824 { 2, glu::TYPE_FLOAT_MAT4X2 },
3825 { 1, glu::TYPE_FLOAT_MAT4X3 },
3826 { 0, glu::TYPE_FLOAT_MAT4 },
3827 };
3828
3829 tcu::TestCaseGroup* group;
3830
3831 if (createTestGroup)
3832 {
3833 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), "matrix", "Basic matrix type");
3834 targetGroup->addChild(blockGroup);
3835 group = blockGroup;
3836 }
3837 else
3838 group = targetGroup;
3839
3840 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(variableTypes); ++ndx)
3841 {
3842 if (variableTypes[ndx].priority < expandLevel)
3843 {
3844 const ResourceDefinition::Node::SharedPtr variable(new ResourceDefinition::Variable(parentStructure, variableTypes[ndx].type));
3845 group->addChild(new ResourceTestCase(context, variable, queryTarget));
3846 }
3847 }
3848 }
3849
3850 static void generateMatrixStructCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup, const ProgramResourceQueryTestTarget& queryTarget, int expandLevel);
3851
generateMatrixArrayCases(Context & context,const ResourceDefinition::Node::SharedPtr & parentStructure,tcu::TestCaseGroup * const targetGroup,const ProgramResourceQueryTestTarget & queryTarget,int expandLevel)3852 static void generateMatrixArrayCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup, const ProgramResourceQueryTestTarget& queryTarget, int expandLevel)
3853 {
3854 if (expandLevel > 0)
3855 {
3856 const ResourceDefinition::Node::SharedPtr arrayElement (new ResourceDefinition::ArrayElement(parentStructure));
3857 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), "array", "Arrays");
3858
3859 targetGroup->addChild(blockGroup);
3860
3861 // Arrays of basic variables
3862 generateMatrixVariableCases(context, arrayElement, blockGroup, queryTarget, expandLevel != 1, expandLevel);
3863
3864 // Arrays of arrays
3865 generateMatrixArrayCases(context, arrayElement, blockGroup, queryTarget, expandLevel-1);
3866
3867 // Arrays of structs
3868 generateMatrixStructCases(context, arrayElement, blockGroup, queryTarget, expandLevel-1);
3869 }
3870 }
3871
generateMatrixStructCases(Context & context,const ResourceDefinition::Node::SharedPtr & parentStructure,tcu::TestCaseGroup * const targetGroup,const ProgramResourceQueryTestTarget & queryTarget,int expandLevel)3872 static void generateMatrixStructCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup, const ProgramResourceQueryTestTarget& queryTarget, int expandLevel)
3873 {
3874 if (expandLevel > 0)
3875 {
3876 const ResourceDefinition::Node::SharedPtr structMember (new ResourceDefinition::StructMember(parentStructure));
3877 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), "struct", "Structs");
3878
3879 targetGroup->addChild(blockGroup);
3880
3881 // Struct containing basic variable
3882 generateMatrixVariableCases(context, structMember, blockGroup, queryTarget, expandLevel != 1, expandLevel);
3883
3884 // Struct containing arrays
3885 generateMatrixArrayCases(context, structMember, blockGroup, queryTarget, expandLevel-1);
3886
3887 // Struct containing struct
3888 generateMatrixStructCases(context, structMember, blockGroup, queryTarget, expandLevel-1);
3889 }
3890 }
3891
generateUniformMatrixOrderCaseBlockContentCases(Context & context,const ResourceDefinition::Node::SharedPtr & parentStructure,tcu::TestCaseGroup * const targetGroup,bool extendedBasicTypeCases,bool opaqueCases)3892 static void generateUniformMatrixOrderCaseBlockContentCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup, bool extendedBasicTypeCases, bool opaqueCases)
3893 {
3894 static const struct
3895 {
3896 const char* name;
3897 glu::MatrixOrder order;
3898 } qualifiers[] =
3899 {
3900 { "no_qualifier", glu::MATRIXORDER_LAST },
3901 { "row_major", glu::MATRIXORDER_ROW_MAJOR },
3902 { "column_major", glu::MATRIXORDER_COLUMN_MAJOR },
3903 };
3904
3905 const ProgramResourceQueryTestTarget queryTarget(PROGRAMINTERFACE_UNIFORM, PROGRAMRESOURCEPROP_MATRIX_ROW_MAJOR);
3906
3907 for (int qualifierNdx = 0; qualifierNdx < DE_LENGTH_OF_ARRAY(qualifiers); ++qualifierNdx)
3908 {
3909 // Add layout qualifiers only for block members
3910 if (qualifiers[qualifierNdx].order == glu::MATRIXORDER_LAST || parentStructure->getType() == ResourceDefinition::Node::TYPE_INTERFACE_BLOCK)
3911 {
3912 ResourceDefinition::Node::SharedPtr subStructure = parentStructure;
3913 tcu::TestCaseGroup* const qualifierGroup = new tcu::TestCaseGroup(context.getTestContext(), qualifiers[qualifierNdx].name, "");
3914
3915 targetGroup->addChild(qualifierGroup);
3916
3917 if (qualifiers[qualifierNdx].order != glu::MATRIXORDER_LAST)
3918 {
3919 glu::Layout layout;
3920 layout.matrixOrder = qualifiers[qualifierNdx].order;
3921 subStructure = ResourceDefinition::Node::SharedPtr(new ResourceDefinition::LayoutQualifier(subStructure, layout));
3922 }
3923
3924 if (extendedBasicTypeCases && qualifiers[qualifierNdx].order == glu::MATRIXORDER_LAST)
3925 {
3926 // .types
3927 {
3928 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), "types", "");
3929 qualifierGroup->addChild(blockGroup);
3930
3931 generateVariableCases(context, subStructure, blockGroup, queryTarget, 1, false);
3932 generateMatrixVariableCases(context, subStructure, blockGroup, queryTarget, false);
3933 if (opaqueCases)
3934 generateOpaqueTypeCases(context, subStructure, blockGroup, queryTarget, 2, false);
3935 }
3936
3937 // .aggregates
3938 {
3939 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), "aggregates", "");
3940 qualifierGroup->addChild(blockGroup);
3941
3942 generateBufferBackedVariableAggregateTypeCases(context, subStructure, blockGroup, queryTarget.interface, PROGRAMRESOURCEPROP_MATRIX_ROW_MAJOR, glu::TYPE_FLOAT_MAT3X2, "", 1);
3943 }
3944 }
3945 else
3946 {
3947 generateBufferBackedVariableAggregateTypeCases(context, subStructure, qualifierGroup, queryTarget.interface, PROGRAMRESOURCEPROP_MATRIX_ROW_MAJOR, glu::TYPE_FLOAT_MAT3X2, "", 1);
3948 }
3949 }
3950 }
3951 }
3952
generateUniformMatrixStrideCaseBlockContentCases(Context & context,const ResourceDefinition::Node::SharedPtr & parentStructure,tcu::TestCaseGroup * const targetGroup,bool extendedBasicTypeCases,bool opaqueCases)3953 static void generateUniformMatrixStrideCaseBlockContentCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup, bool extendedBasicTypeCases, bool opaqueCases)
3954 {
3955 static const struct
3956 {
3957 const char* name;
3958 glu::MatrixOrder order;
3959 } qualifiers[] =
3960 {
3961 { "no_qualifier", glu::MATRIXORDER_LAST },
3962 { "row_major", glu::MATRIXORDER_ROW_MAJOR },
3963 { "column_major", glu::MATRIXORDER_COLUMN_MAJOR },
3964 };
3965
3966 const ProgramResourceQueryTestTarget queryTarget(PROGRAMINTERFACE_UNIFORM, PROGRAMRESOURCEPROP_MATRIX_STRIDE);
3967
3968 for (int qualifierNdx = 0; qualifierNdx < DE_LENGTH_OF_ARRAY(qualifiers); ++qualifierNdx)
3969 {
3970 // Add layout qualifiers only for block members
3971 if (qualifiers[qualifierNdx].order == glu::MATRIXORDER_LAST || parentStructure->getType() == ResourceDefinition::Node::TYPE_INTERFACE_BLOCK)
3972 {
3973 ResourceDefinition::Node::SharedPtr subStructure = parentStructure;
3974 tcu::TestCaseGroup* const qualifierGroup = new tcu::TestCaseGroup(context.getTestContext(), qualifiers[qualifierNdx].name, "");
3975
3976 targetGroup->addChild(qualifierGroup);
3977
3978 if (qualifiers[qualifierNdx].order != glu::MATRIXORDER_LAST)
3979 {
3980 glu::Layout layout;
3981 layout.matrixOrder = qualifiers[qualifierNdx].order;
3982 subStructure = ResourceDefinition::Node::SharedPtr(new ResourceDefinition::LayoutQualifier(subStructure, layout));
3983 }
3984
3985 if (extendedBasicTypeCases)
3986 {
3987 // .types
3988 // .matrix
3989 if (qualifiers[qualifierNdx].order == glu::MATRIXORDER_LAST)
3990 {
3991 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), "types", "");
3992 qualifierGroup->addChild(blockGroup);
3993
3994 generateVariableCases(context, subStructure, blockGroup, queryTarget, 1, false);
3995 generateMatrixVariableCases(context, subStructure, blockGroup, queryTarget, false);
3996 if (opaqueCases)
3997 generateOpaqueTypeCases(context, subStructure, blockGroup, queryTarget, 2, false);
3998 }
3999 else
4000 generateMatrixVariableCases(context, subStructure, qualifierGroup, queryTarget);
4001
4002 // .aggregates
4003 {
4004 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), "aggregates", "");
4005 qualifierGroup->addChild(blockGroup);
4006
4007 generateBufferBackedVariableAggregateTypeCases(context, subStructure, blockGroup, queryTarget.interface, PROGRAMRESOURCEPROP_MATRIX_ROW_MAJOR, glu::TYPE_FLOAT_MAT3X2, "", 1);
4008 }
4009 }
4010 else
4011 generateBufferBackedVariableAggregateTypeCases(context, subStructure, qualifierGroup, queryTarget.interface, PROGRAMRESOURCEPROP_MATRIX_ROW_MAJOR, glu::TYPE_FLOAT_MAT3X2, "", 1);
4012 }
4013 }
4014 }
4015
generateUniformMatrixCaseBlocks(Context & context,const ResourceDefinition::Node::SharedPtr & parentStructure,tcu::TestCaseGroup * const targetGroup,void (* blockContentGenerator)(Context &,const ResourceDefinition::Node::SharedPtr &,tcu::TestCaseGroup * const,bool,bool))4016 static void generateUniformMatrixCaseBlocks (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup, void (*blockContentGenerator)(Context&, const ResourceDefinition::Node::SharedPtr&, tcu::TestCaseGroup* const, bool, bool))
4017 {
4018 static const struct
4019 {
4020 const char* name;
4021 const char* description;
4022 bool block;
4023 bool namedBlock;
4024 bool extendedBasicTypeCases;
4025 glu::MatrixOrder order;
4026 } children[] =
4027 {
4028 { "default_block", "Default block", false, true, true, glu::MATRIXORDER_LAST },
4029 { "named_block", "Named uniform block", true, true, true, glu::MATRIXORDER_LAST },
4030 { "named_block_row_major", "Named uniform block", true, true, false, glu::MATRIXORDER_ROW_MAJOR },
4031 { "named_block_col_major", "Named uniform block", true, true, false, glu::MATRIXORDER_COLUMN_MAJOR },
4032 { "unnamed_block", "Unnamed uniform block", true, false, false, glu::MATRIXORDER_LAST },
4033 { "unnamed_block_row_major", "Unnamed uniform block", true, false, false, glu::MATRIXORDER_ROW_MAJOR },
4034 { "unnamed_block_col_major", "Unnamed uniform block", true, false, false, glu::MATRIXORDER_COLUMN_MAJOR },
4035 };
4036
4037 const ResourceDefinition::Node::SharedPtr defaultBlock (new ResourceDefinition::DefaultBlock(parentStructure));
4038 const ResourceDefinition::Node::SharedPtr uniform (new ResourceDefinition::StorageQualifier(defaultBlock, glu::STORAGE_UNIFORM));
4039
4040 for (int childNdx = 0; childNdx < (int)DE_LENGTH_OF_ARRAY(children); ++childNdx)
4041 {
4042 ResourceDefinition::Node::SharedPtr subStructure = uniform;
4043 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), children[childNdx].name, children[childNdx].description);
4044 const bool addOpaqueCases = children[childNdx].extendedBasicTypeCases && !children[childNdx].block;
4045
4046 targetGroup->addChild(blockGroup);
4047
4048 if (children[childNdx].order != glu::MATRIXORDER_LAST)
4049 {
4050 glu::Layout layout;
4051 layout.matrixOrder = children[childNdx].order;
4052 subStructure = ResourceDefinition::Node::SharedPtr(new ResourceDefinition::LayoutQualifier(subStructure, layout));
4053 }
4054
4055 if (children[childNdx].block)
4056 subStructure = ResourceDefinition::Node::SharedPtr(new ResourceDefinition::InterfaceBlock(subStructure, children[childNdx].namedBlock));
4057
4058 blockContentGenerator(context, subStructure, blockGroup, children[childNdx].extendedBasicTypeCases, addOpaqueCases);
4059 }
4060 }
4061
generateBufferReferencedByShaderInterfaceBlockCases(Context & context,const ResourceDefinition::Node::SharedPtr & parentStructure,tcu::TestCaseGroup * const targetGroup,const ProgramResourceQueryTestTarget & queryTarget,bool extendedCases)4062 static void generateBufferReferencedByShaderInterfaceBlockCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup, const ProgramResourceQueryTestTarget& queryTarget, bool extendedCases)
4063 {
4064 const bool isDefaultBlock = (parentStructure->getType() != ResourceDefinition::Node::TYPE_INTERFACE_BLOCK);
4065
4066 // .float
4067 // .float_array
4068 // .float_struct
4069 {
4070 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(parentStructure, glu::TYPE_FLOAT));
4071 const ResourceDefinition::Node::SharedPtr arrayElement (new ResourceDefinition::ArrayElement(parentStructure));
4072 const ResourceDefinition::Node::SharedPtr structMember (new ResourceDefinition::StructMember(parentStructure));
4073 const ResourceDefinition::Node::SharedPtr variableArray (new ResourceDefinition::Variable(arrayElement, glu::TYPE_FLOAT));
4074 const ResourceDefinition::Node::SharedPtr variableStruct (new ResourceDefinition::Variable(structMember, glu::TYPE_FLOAT));
4075
4076 targetGroup->addChild(new ResourceTestCase(context, variable, queryTarget, "float"));
4077 targetGroup->addChild(new ResourceTestCase(context, variableArray, queryTarget, "float_array"));
4078 targetGroup->addChild(new ResourceTestCase(context, variableStruct, queryTarget, "float_struct"));
4079 }
4080
4081 // .sampler
4082 // .sampler_array
4083 // .sampler_struct
4084 if (isDefaultBlock)
4085 {
4086 const ResourceDefinition::Node::SharedPtr layout (new ResourceDefinition::LayoutQualifier(parentStructure, glu::Layout(-1, 0)));
4087 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(layout, glu::TYPE_SAMPLER_2D));
4088 const ResourceDefinition::Node::SharedPtr arrayElement (new ResourceDefinition::ArrayElement(layout));
4089 const ResourceDefinition::Node::SharedPtr structMember (new ResourceDefinition::StructMember(parentStructure));
4090 const ResourceDefinition::Node::SharedPtr variableArray (new ResourceDefinition::Variable(arrayElement, glu::TYPE_SAMPLER_2D));
4091 const ResourceDefinition::Node::SharedPtr variableStruct (new ResourceDefinition::Variable(structMember, glu::TYPE_SAMPLER_2D));
4092
4093 targetGroup->addChild(new ResourceTestCase(context, variable, queryTarget, "sampler"));
4094 targetGroup->addChild(new ResourceTestCase(context, variableArray, queryTarget, "sampler_array"));
4095 targetGroup->addChild(new ResourceTestCase(context, variableStruct, queryTarget, "sampler_struct"));
4096 }
4097
4098 // .atomic_uint
4099 // .atomic_uint_array
4100 if (isDefaultBlock)
4101 {
4102 const ResourceDefinition::Node::SharedPtr layout (new ResourceDefinition::LayoutQualifier(parentStructure, glu::Layout(-1, 0)));
4103 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(layout, glu::TYPE_UINT_ATOMIC_COUNTER));
4104 const ResourceDefinition::Node::SharedPtr arrayElement (new ResourceDefinition::ArrayElement(layout));
4105 const ResourceDefinition::Node::SharedPtr variableArray (new ResourceDefinition::Variable(arrayElement, glu::TYPE_UINT_ATOMIC_COUNTER));
4106
4107 targetGroup->addChild(new ResourceTestCase(context, variable, queryTarget, "atomic_uint"));
4108 targetGroup->addChild(new ResourceTestCase(context, variableArray, queryTarget, "atomic_uint_array"));
4109 }
4110
4111 if (extendedCases)
4112 {
4113 // .float_array_struct
4114 {
4115 const ResourceDefinition::Node::SharedPtr structMember (new ResourceDefinition::StructMember(parentStructure));
4116 const ResourceDefinition::Node::SharedPtr arrayElement (new ResourceDefinition::ArrayElement(structMember));
4117 const ResourceDefinition::Node::SharedPtr variableArrayStruct (new ResourceDefinition::Variable(arrayElement, glu::TYPE_FLOAT));
4118
4119 targetGroup->addChild(new ResourceTestCase(context, variableArrayStruct, queryTarget, "float_array_struct"));
4120 }
4121
4122 // .float_struct_array
4123 {
4124 const ResourceDefinition::Node::SharedPtr arrayElement (new ResourceDefinition::ArrayElement(parentStructure));
4125 const ResourceDefinition::Node::SharedPtr arrayStructMember (new ResourceDefinition::StructMember(arrayElement));
4126 const ResourceDefinition::Node::SharedPtr variableArrayStruct (new ResourceDefinition::Variable(arrayStructMember, glu::TYPE_FLOAT));
4127
4128 targetGroup->addChild(new ResourceTestCase(context, variableArrayStruct, queryTarget, "float_struct_array"));
4129 }
4130
4131 // .float_array_array
4132 {
4133 const ResourceDefinition::Node::SharedPtr arrayElement (new ResourceDefinition::ArrayElement(parentStructure));
4134 const ResourceDefinition::Node::SharedPtr subArrayElement (new ResourceDefinition::ArrayElement(arrayElement));
4135 const ResourceDefinition::Node::SharedPtr variableArrayStruct (new ResourceDefinition::Variable(subArrayElement, glu::TYPE_FLOAT));
4136
4137 targetGroup->addChild(new ResourceTestCase(context, variableArrayStruct, queryTarget, "float_array_array"));
4138 }
4139
4140 // .float_struct_struct
4141 {
4142 const ResourceDefinition::Node::SharedPtr structMember (new ResourceDefinition::StructMember(parentStructure));
4143 const ResourceDefinition::Node::SharedPtr subStructMember (new ResourceDefinition::StructMember(structMember));
4144 const ResourceDefinition::Node::SharedPtr variableArrayStruct (new ResourceDefinition::Variable(subStructMember, glu::TYPE_FLOAT));
4145
4146 targetGroup->addChild(new ResourceTestCase(context, variableArrayStruct, queryTarget, "float_struct_struct"));
4147 }
4148
4149 if (queryTarget.interface == PROGRAMINTERFACE_BUFFER_VARIABLE)
4150 {
4151 const ResourceDefinition::Node::SharedPtr arrayElement(new ResourceDefinition::ArrayElement(parentStructure, ResourceDefinition::ArrayElement::UNSIZED_ARRAY));
4152
4153 // .float_unsized_array
4154 {
4155 const ResourceDefinition::Node::SharedPtr variableArray (new ResourceDefinition::Variable(arrayElement, glu::TYPE_FLOAT));
4156
4157 targetGroup->addChild(new ResourceTestCase(context, variableArray, queryTarget, "float_unsized_array"));
4158 }
4159
4160 // .float_unsized_struct_array
4161 {
4162 const ResourceDefinition::Node::SharedPtr structMember (new ResourceDefinition::StructMember(arrayElement));
4163 const ResourceDefinition::Node::SharedPtr variableArray (new ResourceDefinition::Variable(structMember, glu::TYPE_FLOAT));
4164
4165 targetGroup->addChild(new ResourceTestCase(context, variableArray, queryTarget, "float_unsized_struct_array"));
4166 }
4167 }
4168 }
4169 }
4170
generateUniformReferencedByShaderSingleBlockContentCases(Context & context,const ResourceDefinition::Node::SharedPtr & parentStructure,tcu::TestCaseGroup * const targetGroup,int expandLevel)4171 static void generateUniformReferencedByShaderSingleBlockContentCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup, int expandLevel)
4172 {
4173 DE_UNREF(expandLevel);
4174
4175 const ResourceDefinition::Node::SharedPtr defaultBlock (new ResourceDefinition::DefaultBlock(parentStructure));
4176 const ResourceDefinition::Node::SharedPtr uniform (new ResourceDefinition::StorageQualifier(defaultBlock, glu::STORAGE_UNIFORM));
4177 const ProgramResourceQueryTestTarget queryTarget (PROGRAMINTERFACE_UNIFORM, PROGRAMRESOURCEPROP_REFERENCED_BY_SHADER);
4178 const bool singleShaderCase = parentStructure->getType() == ResourceDefinition::Node::TYPE_SHADER;
4179
4180 // .default_block
4181 {
4182 TestCaseGroup* const blockGroup = new TestCaseGroup(context, "default_block", "");
4183 targetGroup->addChild(blockGroup);
4184
4185 generateBufferReferencedByShaderInterfaceBlockCases(context, uniform, blockGroup, queryTarget, singleShaderCase);
4186 }
4187
4188 // .named_block
4189 {
4190 const ResourceDefinition::Node::SharedPtr block (new ResourceDefinition::InterfaceBlock(uniform, true));
4191 TestCaseGroup* const blockGroup = new TestCaseGroup(context, "uniform_block", "");
4192
4193 targetGroup->addChild(blockGroup);
4194
4195 generateBufferReferencedByShaderInterfaceBlockCases(context, block, blockGroup, queryTarget, singleShaderCase);
4196 }
4197
4198 // .unnamed_block
4199 {
4200 const ResourceDefinition::Node::SharedPtr block (new ResourceDefinition::InterfaceBlock(uniform, false));
4201 TestCaseGroup* const blockGroup = new TestCaseGroup(context, "unnamed_block", "");
4202
4203 targetGroup->addChild(blockGroup);
4204
4205 generateBufferReferencedByShaderInterfaceBlockCases(context, block, blockGroup, queryTarget, false);
4206 }
4207
4208 // .block_array
4209 {
4210 const ResourceDefinition::Node::SharedPtr arrayElement (new ResourceDefinition::ArrayElement(uniform));
4211 const ResourceDefinition::Node::SharedPtr block (new ResourceDefinition::InterfaceBlock(arrayElement, true));
4212 TestCaseGroup* const blockGroup = new TestCaseGroup(context, "block_array", "");
4213
4214 targetGroup->addChild(blockGroup);
4215
4216 generateBufferReferencedByShaderInterfaceBlockCases(context, block, blockGroup, queryTarget, false);
4217 }
4218 }
4219
generateReferencedByShaderCaseBlocks(Context & context,tcu::TestCaseGroup * const targetGroup,glu::GLSLVersion glslVersion,void (* generateBlockContent)(Context &,const ResourceDefinition::Node::SharedPtr &,tcu::TestCaseGroup *,int expandLevel))4220 static void generateReferencedByShaderCaseBlocks (Context& context, tcu::TestCaseGroup* const targetGroup, glu::GLSLVersion glslVersion, void (*generateBlockContent)(Context&, const ResourceDefinition::Node::SharedPtr&, tcu::TestCaseGroup*, int expandLevel))
4221 {
4222 static const struct
4223 {
4224 const char* name;
4225 glu::ShaderType stage;
4226 int expandLevel;
4227 } singleStageCases[] =
4228 {
4229 { "compute", glu::SHADERTYPE_COMPUTE, 3 },
4230 { "separable_vertex", glu::SHADERTYPE_VERTEX, 2 },
4231 { "separable_fragment", glu::SHADERTYPE_FRAGMENT, 2 },
4232 { "separable_tess_ctrl", glu::SHADERTYPE_TESSELLATION_CONTROL, 2 },
4233 { "separable_tess_eval", glu::SHADERTYPE_TESSELLATION_EVALUATION, 2 },
4234 { "separable_geometry", glu::SHADERTYPE_GEOMETRY, 2 },
4235 };
4236 static const struct
4237 {
4238 const char* name;
4239 deUint32 flags;
4240 int expandLevel;
4241 int subExpandLevel;
4242 } pipelines[] =
4243 {
4244 {
4245 "vertex_fragment",
4246 (1 << glu::SHADERTYPE_VERTEX) | (1 << glu::SHADERTYPE_FRAGMENT),
4247 3,
4248 2,
4249 },
4250 {
4251 "vertex_tess_fragment",
4252 (1 << glu::SHADERTYPE_VERTEX) | (1 << glu::SHADERTYPE_FRAGMENT) | (1 << glu::SHADERTYPE_TESSELLATION_CONTROL) | (1 << glu::SHADERTYPE_TESSELLATION_EVALUATION),
4253 2,
4254 2,
4255 },
4256 {
4257 "vertex_geo_fragment",
4258 (1 << glu::SHADERTYPE_VERTEX) | (1 << glu::SHADERTYPE_FRAGMENT) | (1 << glu::SHADERTYPE_GEOMETRY),
4259 2,
4260 2,
4261 },
4262 {
4263 "vertex_tess_geo_fragment",
4264 (1 << glu::SHADERTYPE_VERTEX) | (1 << glu::SHADERTYPE_FRAGMENT) | (1 << glu::SHADERTYPE_TESSELLATION_CONTROL) | (1 << glu::SHADERTYPE_TESSELLATION_EVALUATION) | (1 << glu::SHADERTYPE_GEOMETRY),
4265 2,
4266 1,
4267 },
4268 };
4269
4270 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(singleStageCases); ++ndx)
4271 {
4272 TestCaseGroup* const blockGroup = new TestCaseGroup(context, singleStageCases[ndx].name, "");
4273 const bool programSeparable = (singleStageCases[ndx].stage != glu::SHADERTYPE_COMPUTE);
4274 const ResourceDefinition::Node::SharedPtr program (new ResourceDefinition::Program(programSeparable));
4275 const ResourceDefinition::Node::SharedPtr stage (new ResourceDefinition::Shader(program, singleStageCases[ndx].stage, glslVersion));
4276
4277 targetGroup->addChild(blockGroup);
4278
4279 generateBlockContent(context, stage, blockGroup, singleStageCases[ndx].expandLevel);
4280 }
4281
4282 for (int pipelineNdx = 0; pipelineNdx < DE_LENGTH_OF_ARRAY(pipelines); ++pipelineNdx)
4283 {
4284 // whole pipeline
4285 {
4286 TestCaseGroup* const blockGroup = new TestCaseGroup(context, pipelines[pipelineNdx].name, "");
4287 const ResourceDefinition::Node::SharedPtr program (new ResourceDefinition::Program());
4288 ResourceDefinition::ShaderSet* shaderSet = new ResourceDefinition::ShaderSet(program,
4289 glslVersion,
4290 pipelines[pipelineNdx].flags,
4291 pipelines[pipelineNdx].flags);
4292 targetGroup->addChild(blockGroup);
4293
4294 {
4295 const ResourceDefinition::Node::SharedPtr shaders(shaderSet);
4296 generateBlockContent(context, shaders, blockGroup, pipelines[pipelineNdx].expandLevel);
4297 }
4298 }
4299
4300 // only one stage
4301 for (int selectedStageBit = 0; selectedStageBit < glu::SHADERTYPE_LAST; ++selectedStageBit)
4302 {
4303 if (pipelines[pipelineNdx].flags & (1 << selectedStageBit))
4304 {
4305 const ResourceDefinition::Node::SharedPtr program (new ResourceDefinition::Program());
4306 ResourceDefinition::ShaderSet* shaderSet = new ResourceDefinition::ShaderSet(program,
4307 glslVersion,
4308 pipelines[pipelineNdx].flags,
4309 (1u << selectedStageBit));
4310 const char* stageName = (selectedStageBit == glu::SHADERTYPE_VERTEX) ? ("vertex")
4311 : (selectedStageBit == glu::SHADERTYPE_FRAGMENT) ? ("fragment")
4312 : (selectedStageBit == glu::SHADERTYPE_GEOMETRY) ? ("geo")
4313 : (selectedStageBit == glu::SHADERTYPE_TESSELLATION_CONTROL) ? ("tess_ctrl")
4314 : (selectedStageBit == glu::SHADERTYPE_TESSELLATION_EVALUATION) ? ("tess_eval")
4315 : (DE_NULL);
4316 const std::string setName = std::string() + pipelines[pipelineNdx].name + "_only_" + stageName;
4317 TestCaseGroup* const blockGroup = new TestCaseGroup(context, setName.c_str(), "");
4318 const ResourceDefinition::Node::SharedPtr shaders (shaderSet);
4319
4320 generateBlockContent(context, shaders, blockGroup, pipelines[pipelineNdx].subExpandLevel);
4321 targetGroup->addChild(blockGroup);
4322 }
4323 }
4324 }
4325 }
4326
generateRandomDataType(de::Random & rnd,bool excludeOpaqueTypes)4327 static glu::DataType generateRandomDataType (de::Random& rnd, bool excludeOpaqueTypes)
4328 {
4329 static const glu::DataType s_types[] =
4330 {
4331 glu::TYPE_FLOAT,
4332 glu::TYPE_INT,
4333 glu::TYPE_UINT,
4334 glu::TYPE_BOOL,
4335 glu::TYPE_FLOAT_VEC2,
4336 glu::TYPE_FLOAT_VEC3,
4337 glu::TYPE_FLOAT_VEC4,
4338 glu::TYPE_INT_VEC2,
4339 glu::TYPE_INT_VEC3,
4340 glu::TYPE_INT_VEC4,
4341 glu::TYPE_UINT_VEC2,
4342 glu::TYPE_UINT_VEC3,
4343 glu::TYPE_UINT_VEC4,
4344 glu::TYPE_BOOL_VEC2,
4345 glu::TYPE_BOOL_VEC3,
4346 glu::TYPE_BOOL_VEC4,
4347 glu::TYPE_FLOAT_MAT2,
4348 glu::TYPE_FLOAT_MAT2X3,
4349 glu::TYPE_FLOAT_MAT2X4,
4350 glu::TYPE_FLOAT_MAT3X2,
4351 glu::TYPE_FLOAT_MAT3,
4352 glu::TYPE_FLOAT_MAT3X4,
4353 glu::TYPE_FLOAT_MAT4X2,
4354 glu::TYPE_FLOAT_MAT4X3,
4355 glu::TYPE_FLOAT_MAT4,
4356
4357 glu::TYPE_SAMPLER_2D,
4358 glu::TYPE_SAMPLER_CUBE,
4359 glu::TYPE_SAMPLER_2D_ARRAY,
4360 glu::TYPE_SAMPLER_3D,
4361 glu::TYPE_SAMPLER_2D_SHADOW,
4362 glu::TYPE_SAMPLER_CUBE_SHADOW,
4363 glu::TYPE_SAMPLER_2D_ARRAY_SHADOW,
4364 glu::TYPE_INT_SAMPLER_2D,
4365 glu::TYPE_INT_SAMPLER_CUBE,
4366 glu::TYPE_INT_SAMPLER_2D_ARRAY,
4367 glu::TYPE_INT_SAMPLER_3D,
4368 glu::TYPE_UINT_SAMPLER_2D,
4369 glu::TYPE_UINT_SAMPLER_CUBE,
4370 glu::TYPE_UINT_SAMPLER_2D_ARRAY,
4371 glu::TYPE_UINT_SAMPLER_3D,
4372 glu::TYPE_SAMPLER_2D_MULTISAMPLE,
4373 glu::TYPE_INT_SAMPLER_2D_MULTISAMPLE,
4374 glu::TYPE_UINT_SAMPLER_2D_MULTISAMPLE,
4375 glu::TYPE_IMAGE_2D,
4376 glu::TYPE_IMAGE_CUBE,
4377 glu::TYPE_IMAGE_2D_ARRAY,
4378 glu::TYPE_IMAGE_3D,
4379 glu::TYPE_INT_IMAGE_2D,
4380 glu::TYPE_INT_IMAGE_CUBE,
4381 glu::TYPE_INT_IMAGE_2D_ARRAY,
4382 glu::TYPE_INT_IMAGE_3D,
4383 glu::TYPE_UINT_IMAGE_2D,
4384 glu::TYPE_UINT_IMAGE_CUBE,
4385 glu::TYPE_UINT_IMAGE_2D_ARRAY,
4386 glu::TYPE_UINT_IMAGE_3D,
4387 glu::TYPE_UINT_ATOMIC_COUNTER
4388 };
4389
4390 for (;;)
4391 {
4392 const glu::DataType type = s_types[rnd.getInt(0, DE_LENGTH_OF_ARRAY(s_types)-1)];
4393
4394 if (!excludeOpaqueTypes ||
4395 glu::isDataTypeScalarOrVector(type) ||
4396 glu::isDataTypeMatrix(type))
4397 return type;
4398 }
4399 }
4400
generateRandomVariableDefinition(de::Random & rnd,const ResourceDefinition::Node::SharedPtr & parentStructure,glu::DataType baseType,const glu::Layout & layout,bool allowUnsized)4401 static ResourceDefinition::Node::SharedPtr generateRandomVariableDefinition (de::Random& rnd,
4402 const ResourceDefinition::Node::SharedPtr& parentStructure,
4403 glu::DataType baseType,
4404 const glu::Layout& layout,
4405 bool allowUnsized)
4406 {
4407 const int maxNesting = 4;
4408 ResourceDefinition::Node::SharedPtr currentStructure = parentStructure;
4409 const bool canBeInsideAStruct = layout.binding == -1 && !isDataTypeLayoutQualified(baseType);
4410
4411 for (int nestNdx = 0; nestNdx < maxNesting; ++nestNdx)
4412 {
4413 if (allowUnsized && nestNdx == 0 && rnd.getFloat() < 0.2)
4414 currentStructure = ResourceDefinition::Node::SharedPtr(new ResourceDefinition::ArrayElement(currentStructure, ResourceDefinition::ArrayElement::UNSIZED_ARRAY));
4415 else if (rnd.getFloat() < 0.3 && canBeInsideAStruct)
4416 currentStructure = ResourceDefinition::Node::SharedPtr(new ResourceDefinition::StructMember(currentStructure));
4417 else if (rnd.getFloat() < 0.3)
4418 currentStructure = ResourceDefinition::Node::SharedPtr(new ResourceDefinition::ArrayElement(currentStructure));
4419 else
4420 break;
4421 }
4422
4423 return ResourceDefinition::Node::SharedPtr(new ResourceDefinition::Variable(currentStructure, baseType));
4424 }
4425
generateRandomCoreShaderSet(de::Random & rnd,glu::GLSLVersion glslVersion)4426 static ResourceDefinition::Node::SharedPtr generateRandomCoreShaderSet (de::Random& rnd, glu::GLSLVersion glslVersion)
4427 {
4428 if (rnd.getFloat() < 0.5f)
4429 {
4430 // compute only
4431 const ResourceDefinition::Node::SharedPtr program(new ResourceDefinition::Program());
4432 return ResourceDefinition::Node::SharedPtr(new ResourceDefinition::Shader(program, glu::SHADERTYPE_COMPUTE, glslVersion));
4433 }
4434 else if (rnd.getFloat() < 0.5f)
4435 {
4436 // vertex and fragment
4437 const ResourceDefinition::Node::SharedPtr program (new ResourceDefinition::Program());
4438 ResourceDefinition::ShaderSet* shaderSet = new ResourceDefinition::ShaderSet(program, glslVersion);
4439
4440 if (rnd.getBool())
4441 {
4442 shaderSet->setStage(glu::SHADERTYPE_VERTEX, true);
4443 shaderSet->setStage(glu::SHADERTYPE_FRAGMENT, rnd.getBool());
4444 }
4445 else
4446 {
4447 shaderSet->setStage(glu::SHADERTYPE_VERTEX, rnd.getBool());
4448 shaderSet->setStage(glu::SHADERTYPE_FRAGMENT, true);
4449 }
4450
4451 return ResourceDefinition::Node::SharedPtr(shaderSet);
4452 }
4453 else
4454 {
4455 // separate vertex or fragment
4456 const ResourceDefinition::Node::SharedPtr program (new ResourceDefinition::Program(true));
4457 const glu::ShaderType shaderType = (rnd.getBool()) ? (glu::SHADERTYPE_VERTEX) : (glu::SHADERTYPE_FRAGMENT);
4458
4459 return ResourceDefinition::Node::SharedPtr(new ResourceDefinition::Shader(program, shaderType, glslVersion));
4460 }
4461 }
4462
generateRandomExtShaderSet(de::Random & rnd,glu::GLSLVersion glslVersion)4463 static ResourceDefinition::Node::SharedPtr generateRandomExtShaderSet (de::Random& rnd, glu::GLSLVersion glslVersion)
4464 {
4465 if (rnd.getFloat() < 0.5f)
4466 {
4467 // whole pipeline
4468 const ResourceDefinition::Node::SharedPtr program (new ResourceDefinition::Program());
4469 ResourceDefinition::ShaderSet* shaderSet = new ResourceDefinition::ShaderSet(program, glslVersion);
4470
4471 shaderSet->setStage(glu::SHADERTYPE_VERTEX, rnd.getBool());
4472 shaderSet->setStage(glu::SHADERTYPE_FRAGMENT, rnd.getBool());
4473
4474 // tess shader are either both or neither present. Make cases interesting
4475 // by forcing one extended shader to always have reference
4476 if (rnd.getBool())
4477 {
4478 shaderSet->setStage(glu::SHADERTYPE_GEOMETRY, true);
4479
4480 if (rnd.getBool())
4481 {
4482 shaderSet->setStage(glu::SHADERTYPE_TESSELLATION_CONTROL, rnd.getBool());
4483 shaderSet->setStage(glu::SHADERTYPE_TESSELLATION_EVALUATION, rnd.getBool());
4484 }
4485 }
4486 else
4487 {
4488 shaderSet->setStage(glu::SHADERTYPE_GEOMETRY, rnd.getBool());
4489
4490 if (rnd.getBool())
4491 {
4492 shaderSet->setStage(glu::SHADERTYPE_TESSELLATION_CONTROL, true);
4493 shaderSet->setStage(glu::SHADERTYPE_TESSELLATION_EVALUATION, rnd.getBool());
4494 }
4495 else
4496 {
4497 shaderSet->setStage(glu::SHADERTYPE_TESSELLATION_CONTROL, rnd.getBool());
4498 shaderSet->setStage(glu::SHADERTYPE_TESSELLATION_EVALUATION, true);
4499 }
4500 }
4501
4502 return ResourceDefinition::Node::SharedPtr(shaderSet);
4503 }
4504 else
4505 {
4506 // separate
4507 const ResourceDefinition::Node::SharedPtr program (new ResourceDefinition::Program(true));
4508 const int selector = rnd.getInt(0, 2);
4509 const glu::ShaderType shaderType = (selector == 0) ? (glu::SHADERTYPE_GEOMETRY)
4510 : (selector == 1) ? (glu::SHADERTYPE_TESSELLATION_CONTROL)
4511 : (selector == 2) ? (glu::SHADERTYPE_TESSELLATION_EVALUATION)
4512 : (glu::SHADERTYPE_LAST);
4513
4514 return ResourceDefinition::Node::SharedPtr(new ResourceDefinition::Shader(program, shaderType, glslVersion));
4515 }
4516 }
4517
generateRandomShaderSet(de::Random & rnd,glu::GLSLVersion glslVersion,bool onlyExtensionStages)4518 static ResourceDefinition::Node::SharedPtr generateRandomShaderSet (de::Random& rnd, glu::GLSLVersion glslVersion, bool onlyExtensionStages)
4519 {
4520 if (!onlyExtensionStages)
4521 return generateRandomCoreShaderSet(rnd, glslVersion);
4522 else
4523 return generateRandomExtShaderSet(rnd, glslVersion);
4524 }
4525
generateRandomUniformBlockLayout(de::Random & rnd)4526 static glu::Layout generateRandomUniformBlockLayout (de::Random& rnd)
4527 {
4528 glu::Layout layout;
4529
4530 if (rnd.getBool())
4531 layout.binding = rnd.getInt(0, 5);
4532
4533 if (rnd.getBool())
4534 layout.matrixOrder = (rnd.getBool()) ? (glu::MATRIXORDER_COLUMN_MAJOR) : (glu::MATRIXORDER_ROW_MAJOR);
4535
4536 return layout;
4537 }
4538
generateRandomBufferBlockLayout(de::Random & rnd)4539 static glu::Layout generateRandomBufferBlockLayout (de::Random& rnd)
4540 {
4541 return generateRandomUniformBlockLayout(rnd);
4542 }
4543
generateRandomVariableLayout(de::Random & rnd,glu::DataType type,bool interfaceBlockMember)4544 static glu::Layout generateRandomVariableLayout (de::Random& rnd, glu::DataType type, bool interfaceBlockMember)
4545 {
4546 glu::Layout layout;
4547
4548 if ((glu::isDataTypeAtomicCounter(type) || glu::isDataTypeImage(type) || glu::isDataTypeSampler(type)) && rnd.getBool())
4549 layout.binding = rnd.getInt(0, 5);
4550
4551 if (glu::isDataTypeAtomicCounter(type) && rnd.getBool())
4552 layout.offset = rnd.getInt(0, 3) * 4;
4553
4554 if (glu::isDataTypeMatrix(type) && interfaceBlockMember && rnd.getBool())
4555 layout.matrixOrder = (rnd.getBool()) ? (glu::MATRIXORDER_COLUMN_MAJOR) : (glu::MATRIXORDER_ROW_MAJOR);
4556
4557 return layout;
4558 }
4559
generateUniformRandomCase(Context & context,tcu::TestCaseGroup * const targetGroup,glu::GLSLVersion glslVersion,int index,bool onlyExtensionStages)4560 static void generateUniformRandomCase (Context& context, tcu::TestCaseGroup* const targetGroup, glu::GLSLVersion glslVersion, int index, bool onlyExtensionStages)
4561 {
4562 de::Random rnd (index * 0x12345);
4563 const ResourceDefinition::Node::SharedPtr shader = generateRandomShaderSet(rnd, glslVersion, onlyExtensionStages);
4564 const bool interfaceBlock = rnd.getBool();
4565 const glu::DataType type = generateRandomDataType(rnd, interfaceBlock);
4566 const glu::Layout layout = generateRandomVariableLayout(rnd, type, interfaceBlock);
4567 const ResourceDefinition::Node::SharedPtr defaultBlock (new ResourceDefinition::DefaultBlock(shader));
4568 const ResourceDefinition::Node::SharedPtr uniform (new ResourceDefinition::StorageQualifier(defaultBlock, glu::STORAGE_UNIFORM));
4569 ResourceDefinition::Node::SharedPtr currentStructure = uniform;
4570
4571 if (interfaceBlock)
4572 {
4573 const bool namedBlock = rnd.getBool();
4574
4575 currentStructure = ResourceDefinition::Node::SharedPtr(new ResourceDefinition::LayoutQualifier(currentStructure, generateRandomUniformBlockLayout(rnd)));
4576
4577 if (namedBlock && rnd.getBool())
4578 currentStructure = ResourceDefinition::Node::SharedPtr(new ResourceDefinition::ArrayElement(currentStructure));
4579
4580 currentStructure = ResourceDefinition::Node::SharedPtr(new ResourceDefinition::InterfaceBlock(currentStructure, namedBlock));
4581 }
4582
4583 currentStructure = ResourceDefinition::Node::SharedPtr(new ResourceDefinition::LayoutQualifier(currentStructure, layout));
4584 currentStructure = generateRandomVariableDefinition(rnd, currentStructure, type, layout, false);
4585
4586 targetGroup->addChild(new ResourceTestCase(context, currentStructure, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_UNIFORM, PROGRAMRESOURCEPROP_UNIFORM_INTERFACE_MASK), de::toString(index).c_str()));
4587 }
4588
generateUniformCaseRandomCases(Context & context,tcu::TestCaseGroup * const targetGroup,glu::GLSLVersion glslVersion)4589 static void generateUniformCaseRandomCases (Context& context, tcu::TestCaseGroup* const targetGroup, glu::GLSLVersion glslVersion)
4590 {
4591 const int numBasicCases = 40;
4592 const int numTessGeoCases = 40;
4593
4594 for (int ndx = 0; ndx < numBasicCases; ++ndx)
4595 generateUniformRandomCase(context, targetGroup, glslVersion, ndx, false);
4596 for (int ndx = 0; ndx < numTessGeoCases; ++ndx)
4597 generateUniformRandomCase(context, targetGroup, glslVersion, numBasicCases + ndx, true);
4598 }
4599
4600 class UniformInterfaceTestGroup : public TestCaseGroup
4601 {
4602 public:
4603 UniformInterfaceTestGroup (Context& context);
4604 void init (void);
4605 };
4606
UniformInterfaceTestGroup(Context & context)4607 UniformInterfaceTestGroup::UniformInterfaceTestGroup (Context& context)
4608 : TestCaseGroup(context, "uniform", "Uniform interace")
4609 {
4610 }
4611
init(void)4612 void UniformInterfaceTestGroup::init (void)
4613 {
4614 glu::GLSLVersion glslVersion = glu::getContextTypeGLSLVersion(m_context.getRenderContext().getType());
4615 const ResourceDefinition::Node::SharedPtr program (new ResourceDefinition::Program());
4616 const ResourceDefinition::Node::SharedPtr computeShader (new ResourceDefinition::Shader(program, glu::SHADERTYPE_COMPUTE, glslVersion));
4617
4618 // .resource_list
4619 {
4620 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "resource_list", "Resource list");
4621 addChild(blockGroup);
4622 generateUniformCaseBlocks(m_context, computeShader, blockGroup, BLOCKFLAG_ALL, generateUniformResourceListBlockContents);
4623 }
4624
4625 // .array_size
4626 {
4627 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "array_size", "Query array size");
4628 addChild(blockGroup);
4629 generateUniformCaseBlocks(m_context, computeShader, blockGroup, BLOCKFLAG_ALL, generateUniformBlockArraySizeContents);
4630 }
4631
4632 // .array_stride
4633 {
4634 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "array_stride", "Query array stride");
4635 addChild(blockGroup);
4636 generateUniformCaseBlocks(m_context, computeShader, blockGroup, BLOCKFLAG_ALL, generateUniformBlockArrayStrideContents);
4637 }
4638
4639 // .atomic_counter_buffer_index
4640 {
4641 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "atomic_counter_buffer_index", "Query atomic counter buffer index");
4642 addChild(blockGroup);
4643 generateUniformCaseBlocks(m_context, computeShader, blockGroup, BLOCKFLAG_DEFAULT | BLOCKFLAG_NAMED, generateUniformBlockAtomicCounterBufferIndexContents);
4644 }
4645
4646 // .block_index
4647 {
4648 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "block_index", "Query block index");
4649 addChild(blockGroup);
4650 generateUniformBlockBlockIndexContents(m_context, blockGroup, glslVersion);
4651 }
4652
4653 // .location
4654 {
4655 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "location", "Query location");
4656 addChild(blockGroup);
4657 generateUniformCaseBlocks(m_context, computeShader, blockGroup, BLOCKFLAG_DEFAULT | BLOCKFLAG_NAMED | BLOCKFLAG_UNNAMED, generateUniformBlockLocationContents);
4658 }
4659
4660 // .matrix_row_major
4661 {
4662 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "matrix_row_major", "Query matrix row_major");
4663 addChild(blockGroup);
4664 generateUniformMatrixCaseBlocks(m_context, computeShader, blockGroup, generateUniformMatrixOrderCaseBlockContentCases);
4665 }
4666
4667 // .matrix_stride
4668 {
4669 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "matrix_stride", "Query matrix stride");
4670 addChild(blockGroup);
4671 generateUniformMatrixCaseBlocks(m_context, computeShader, blockGroup, generateUniformMatrixStrideCaseBlockContentCases);
4672 }
4673
4674 // .name_length
4675 {
4676 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "name_length", "Query name length");
4677 addChild(blockGroup);
4678 generateUniformCaseBlocks(m_context, computeShader, blockGroup, BLOCKFLAG_ALL, generateUniformBlockNameLengthContents);
4679 }
4680
4681 // .offset
4682 {
4683 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "offset", "Query offset");
4684 addChild(blockGroup);
4685 generateUniformCaseBlocks(m_context, computeShader, blockGroup, BLOCKFLAG_ALL, generateUniformBlockOffsetContents);
4686 }
4687
4688 // .referenced_by_shader
4689 {
4690 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "referenced_by_shader", "Query referenced by shader");
4691 addChild(blockGroup);
4692 generateReferencedByShaderCaseBlocks(m_context, blockGroup, glslVersion, generateUniformReferencedByShaderSingleBlockContentCases);
4693 }
4694
4695 // .type
4696 {
4697 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "type", "Query type");
4698 addChild(blockGroup);
4699 generateUniformCaseBlocks(m_context, computeShader, blockGroup, BLOCKFLAG_ALL, generateUniformBlockTypeContents);
4700 }
4701
4702 // .random
4703 {
4704 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "random", "Random");
4705 addChild(blockGroup);
4706 generateUniformCaseRandomCases(m_context, blockGroup, glslVersion);
4707 }
4708 }
4709
generateBufferBackedInterfaceResourceListCase(Context & context,const ResourceDefinition::Node::SharedPtr & targetResource,tcu::TestCaseGroup * const targetGroup,ProgramInterface interface,const char * blockName)4710 static void generateBufferBackedInterfaceResourceListCase (Context& context, const ResourceDefinition::Node::SharedPtr& targetResource, tcu::TestCaseGroup* const targetGroup, ProgramInterface interface, const char* blockName)
4711 {
4712 targetGroup->addChild(new ResourceListTestCase(context, targetResource, interface, blockName));
4713 }
4714
generateBufferBackedInterfaceNameLengthCase(Context & context,const ResourceDefinition::Node::SharedPtr & targetResource,tcu::TestCaseGroup * const targetGroup,ProgramInterface interface,const char * blockName)4715 static void generateBufferBackedInterfaceNameLengthCase (Context& context, const ResourceDefinition::Node::SharedPtr& targetResource, tcu::TestCaseGroup* const targetGroup, ProgramInterface interface, const char* blockName)
4716 {
4717 targetGroup->addChild(new ResourceTestCase(context, targetResource, ProgramResourceQueryTestTarget(interface, PROGRAMRESOURCEPROP_NAME_LENGTH), blockName));
4718 }
4719
generateBufferBackedInterfaceResourceBasicBlockTypes(Context & context,tcu::TestCaseGroup * targetGroup,glu::GLSLVersion glslVersion,glu::Storage storage,void (* blockContentGenerator)(Context &,const ResourceDefinition::Node::SharedPtr &,tcu::TestCaseGroup * const,ProgramInterface interface,const char * blockName))4720 static void generateBufferBackedInterfaceResourceBasicBlockTypes (Context& context, tcu::TestCaseGroup* targetGroup, glu::GLSLVersion glslVersion, glu::Storage storage, void (*blockContentGenerator)(Context&, const ResourceDefinition::Node::SharedPtr&, tcu::TestCaseGroup* const, ProgramInterface interface, const char* blockName))
4721 {
4722 const ResourceDefinition::Node::SharedPtr program (new ResourceDefinition::Program());
4723 const ResourceDefinition::Node::SharedPtr shader (new ResourceDefinition::Shader(program, glu::SHADERTYPE_COMPUTE, glslVersion));
4724 const ResourceDefinition::Node::SharedPtr defaultBlock (new ResourceDefinition::DefaultBlock(shader));
4725 const ResourceDefinition::Node::SharedPtr storageQualifier (new ResourceDefinition::StorageQualifier(defaultBlock, storage));
4726 const ResourceDefinition::Node::SharedPtr binding (new ResourceDefinition::LayoutQualifier(storageQualifier, glu::Layout(-1, 1)));
4727 const ProgramInterface programInterface = (storage == glu::STORAGE_UNIFORM) ? (PROGRAMINTERFACE_UNIFORM_BLOCK) : (PROGRAMINTERFACE_SHADER_STORAGE_BLOCK);
4728
4729 // .named_block
4730 {
4731 const ResourceDefinition::Node::SharedPtr block (new ResourceDefinition::InterfaceBlock(binding, true));
4732 const ResourceDefinition::Node::SharedPtr dummyVariable (new ResourceDefinition::Variable(block, glu::TYPE_BOOL_VEC3));
4733
4734 blockContentGenerator(context, dummyVariable, targetGroup, programInterface, "named_block");
4735 }
4736
4737 // .unnamed_block
4738 {
4739 const ResourceDefinition::Node::SharedPtr block (new ResourceDefinition::InterfaceBlock(binding, false));
4740 const ResourceDefinition::Node::SharedPtr dummyVariable (new ResourceDefinition::Variable(block, glu::TYPE_BOOL_VEC3));
4741
4742 blockContentGenerator(context, dummyVariable, targetGroup, programInterface, "unnamed_block");
4743 }
4744
4745 // .block_array
4746 {
4747 const ResourceDefinition::Node::SharedPtr arrayElement (new ResourceDefinition::ArrayElement(binding, 3));
4748 const ResourceDefinition::Node::SharedPtr block (new ResourceDefinition::InterfaceBlock(arrayElement, true));
4749 const ResourceDefinition::Node::SharedPtr dummyVariable (new ResourceDefinition::Variable(block, glu::TYPE_BOOL_VEC3));
4750
4751 blockContentGenerator(context, dummyVariable, targetGroup, programInterface, "block_array");
4752 }
4753
4754 // .block_array_single_element
4755 {
4756 const ResourceDefinition::Node::SharedPtr arrayElement (new ResourceDefinition::ArrayElement(binding, 1));
4757 const ResourceDefinition::Node::SharedPtr block (new ResourceDefinition::InterfaceBlock(arrayElement, true));
4758 const ResourceDefinition::Node::SharedPtr dummyVariable (new ResourceDefinition::Variable(block, glu::TYPE_BOOL_VEC3));
4759
4760 blockContentGenerator(context, dummyVariable, targetGroup, programInterface, "block_array_single_element");
4761 }
4762 }
4763
generateBufferBackedInterfaceResourceBufferBindingCases(Context & context,tcu::TestCaseGroup * targetGroup,glu::GLSLVersion glslVersion,glu::Storage storage)4764 static void generateBufferBackedInterfaceResourceBufferBindingCases (Context& context, tcu::TestCaseGroup* targetGroup, glu::GLSLVersion glslVersion, glu::Storage storage)
4765 {
4766 const ResourceDefinition::Node::SharedPtr program (new ResourceDefinition::Program());
4767 const ResourceDefinition::Node::SharedPtr shader (new ResourceDefinition::Shader(program, glu::SHADERTYPE_COMPUTE, glslVersion));
4768 const ResourceDefinition::Node::SharedPtr defaultBlock (new ResourceDefinition::DefaultBlock(shader));
4769 const ResourceDefinition::Node::SharedPtr storageQualifier (new ResourceDefinition::StorageQualifier(defaultBlock, storage));
4770
4771 for (int ndx = 0; ndx < 2; ++ndx)
4772 {
4773 const bool explicitBinding = (ndx == 1);
4774 const int bindingNdx = (explicitBinding) ? (1) : (-1);
4775 const std::string nameSuffix = (explicitBinding) ? ("_explicit_binding") : ("");
4776 const ResourceDefinition::Node::SharedPtr binding (new ResourceDefinition::LayoutQualifier(storageQualifier, glu::Layout(-1, bindingNdx)));
4777 const ProgramInterface programInterface = (storage == glu::STORAGE_UNIFORM) ? (PROGRAMINTERFACE_UNIFORM_BLOCK) : (PROGRAMINTERFACE_SHADER_STORAGE_BLOCK);
4778
4779 // .named_block*
4780 {
4781 const ResourceDefinition::Node::SharedPtr block (new ResourceDefinition::InterfaceBlock(binding, true));
4782 const ResourceDefinition::Node::SharedPtr dummyVariable (new ResourceDefinition::Variable(block, glu::TYPE_BOOL_VEC3));
4783
4784 targetGroup->addChild(new ResourceTestCase(context, dummyVariable, ProgramResourceQueryTestTarget(programInterface, PROGRAMRESOURCEPROP_BUFFER_BINDING), ("named_block" + nameSuffix).c_str()));
4785 }
4786
4787 // .unnamed_block*
4788 {
4789 const ResourceDefinition::Node::SharedPtr block (new ResourceDefinition::InterfaceBlock(binding, false));
4790 const ResourceDefinition::Node::SharedPtr dummyVariable (new ResourceDefinition::Variable(block, glu::TYPE_BOOL_VEC3));
4791
4792 targetGroup->addChild(new ResourceTestCase(context, dummyVariable, ProgramResourceQueryTestTarget(programInterface, PROGRAMRESOURCEPROP_BUFFER_BINDING), ("unnamed_block" + nameSuffix).c_str()));
4793 }
4794
4795 // .block_array*
4796 {
4797 const ResourceDefinition::Node::SharedPtr arrayElement (new ResourceDefinition::ArrayElement(binding, 3));
4798 const ResourceDefinition::Node::SharedPtr block (new ResourceDefinition::InterfaceBlock(arrayElement, true));
4799 const ResourceDefinition::Node::SharedPtr dummyVariable (new ResourceDefinition::Variable(block, glu::TYPE_BOOL_VEC3));
4800
4801 targetGroup->addChild(new ResourceTestCase(context, dummyVariable, ProgramResourceQueryTestTarget(programInterface, PROGRAMRESOURCEPROP_BUFFER_BINDING), ("block_array" + nameSuffix).c_str()));
4802 }
4803 }
4804 }
4805
4806 template <glu::Storage Storage>
generateBufferBlockReferencedByShaderSingleBlockContentCases(Context & context,const ResourceDefinition::Node::SharedPtr & parentStructure,tcu::TestCaseGroup * targetGroup,int expandLevel)4807 static void generateBufferBlockReferencedByShaderSingleBlockContentCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup, int expandLevel)
4808 {
4809 const ProgramInterface programInterface = (Storage == glu::STORAGE_UNIFORM) ? (PROGRAMINTERFACE_UNIFORM_BLOCK) :
4810 (Storage == glu::STORAGE_BUFFER) ? (PROGRAMINTERFACE_SHADER_STORAGE_BLOCK) :
4811 (PROGRAMINTERFACE_LAST);
4812 const ResourceDefinition::Node::SharedPtr defaultBlock (new ResourceDefinition::DefaultBlock(parentStructure));
4813 const ResourceDefinition::Node::SharedPtr storage (new ResourceDefinition::StorageQualifier(defaultBlock, Storage));
4814
4815 DE_UNREF(expandLevel);
4816
4817 DE_ASSERT(programInterface != PROGRAMINTERFACE_LAST);
4818
4819 // .named_block
4820 {
4821 const ResourceDefinition::Node::SharedPtr block (new ResourceDefinition::InterfaceBlock(storage, true));
4822 const ResourceDefinition::Node::SharedPtr dummyVariable (new ResourceDefinition::Variable(block, glu::TYPE_BOOL_VEC3));
4823
4824 targetGroup->addChild(new ResourceTestCase(context, dummyVariable, ProgramResourceQueryTestTarget(programInterface, PROGRAMRESOURCEPROP_REFERENCED_BY_SHADER), "named_block"));
4825 }
4826
4827 // .unnamed_block
4828 {
4829 const ResourceDefinition::Node::SharedPtr block (new ResourceDefinition::InterfaceBlock(storage, false));
4830 const ResourceDefinition::Node::SharedPtr dummyVariable (new ResourceDefinition::Variable(block, glu::TYPE_BOOL_VEC3));
4831
4832 targetGroup->addChild(new ResourceTestCase(context, dummyVariable, ProgramResourceQueryTestTarget(programInterface, PROGRAMRESOURCEPROP_REFERENCED_BY_SHADER), "unnamed_block"));
4833 }
4834
4835 // .block_array
4836 {
4837 const ResourceDefinition::Node::SharedPtr arrayElement (new ResourceDefinition::ArrayElement(storage, 3));
4838 const ResourceDefinition::Node::SharedPtr block (new ResourceDefinition::InterfaceBlock(arrayElement, true));
4839 const ResourceDefinition::Node::SharedPtr dummyVariable (new ResourceDefinition::Variable(block, glu::TYPE_BOOL_VEC3));
4840
4841 targetGroup->addChild(new ResourceTestCase(context, dummyVariable, ProgramResourceQueryTestTarget(programInterface, PROGRAMRESOURCEPROP_REFERENCED_BY_SHADER), "block_array"));
4842 }
4843 }
4844
generateBufferBackedInterfaceResourceActiveVariablesCase(Context & context,tcu::TestCaseGroup * targetGroup,glu::Storage storage)4845 static void generateBufferBackedInterfaceResourceActiveVariablesCase (Context& context, tcu::TestCaseGroup* targetGroup, glu::Storage storage)
4846 {
4847 targetGroup->addChild(new InterfaceBlockActiveVariablesTestCase(context, "named_block", "Named block", storage, InterfaceBlockActiveVariablesTestCase::CASE_NAMED_BLOCK));
4848 targetGroup->addChild(new InterfaceBlockActiveVariablesTestCase(context, "unnamed_block", "Unnamed block", storage, InterfaceBlockActiveVariablesTestCase::CASE_UNNAMED_BLOCK));
4849 targetGroup->addChild(new InterfaceBlockActiveVariablesTestCase(context, "block_array", "Block array", storage, InterfaceBlockActiveVariablesTestCase::CASE_BLOCK_ARRAY));
4850 }
4851
generateBufferBackedInterfaceResourceBufferDataSizeCases(Context & context,tcu::TestCaseGroup * targetGroup,glu::Storage storage)4852 static void generateBufferBackedInterfaceResourceBufferDataSizeCases (Context& context, tcu::TestCaseGroup* targetGroup, glu::Storage storage)
4853 {
4854 targetGroup->addChild(new InterfaceBlockDataSizeTestCase(context, "named_block", "Named block", storage, InterfaceBlockDataSizeTestCase::CASE_NAMED_BLOCK));
4855 targetGroup->addChild(new InterfaceBlockDataSizeTestCase(context, "unnamed_block", "Unnamed block", storage, InterfaceBlockDataSizeTestCase::CASE_UNNAMED_BLOCK));
4856 targetGroup->addChild(new InterfaceBlockDataSizeTestCase(context, "block_array", "Block array", storage, InterfaceBlockDataSizeTestCase::CASE_BLOCK_ARRAY));
4857 }
4858
4859 class BufferBackedBlockInterfaceTestGroup : public TestCaseGroup
4860 {
4861 public:
4862 BufferBackedBlockInterfaceTestGroup (Context& context, glu::Storage interfaceBlockStorage);
4863 void init (void);
4864
4865 private:
4866 static const char* getGroupName (glu::Storage storage);
4867 static const char* getGroupDescription (glu::Storage storage);
4868
4869 const glu::Storage m_storage;
4870 };
4871
BufferBackedBlockInterfaceTestGroup(Context & context,glu::Storage storage)4872 BufferBackedBlockInterfaceTestGroup::BufferBackedBlockInterfaceTestGroup(Context& context, glu::Storage storage)
4873 : TestCaseGroup (context, getGroupName(storage), getGroupDescription(storage))
4874 , m_storage (storage)
4875 {
4876 DE_ASSERT(storage == glu::STORAGE_BUFFER || storage == glu::STORAGE_UNIFORM);
4877 }
4878
init(void)4879 void BufferBackedBlockInterfaceTestGroup::init (void)
4880 {
4881 const glu::GLSLVersion glslVersion = glu::getContextTypeGLSLVersion(m_context.getRenderContext().getType());
4882
4883 // .resource_list
4884 {
4885 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "resource_list", "Resource list");
4886 addChild(blockGroup);
4887 generateBufferBackedInterfaceResourceBasicBlockTypes(m_context, blockGroup, glslVersion, m_storage, generateBufferBackedInterfaceResourceListCase);
4888 }
4889
4890 // .active_variables
4891 {
4892 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "active_variables", "Active variables");
4893 addChild(blockGroup);
4894 generateBufferBackedInterfaceResourceActiveVariablesCase(m_context, blockGroup, m_storage);
4895 }
4896
4897 // .buffer_binding
4898 {
4899 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "buffer_binding", "Buffer binding");
4900 addChild(blockGroup);
4901 generateBufferBackedInterfaceResourceBufferBindingCases(m_context, blockGroup, glslVersion, m_storage);
4902 }
4903
4904 // .buffer_data_size
4905 {
4906 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "buffer_data_size", "Buffer data size");
4907 addChild(blockGroup);
4908 generateBufferBackedInterfaceResourceBufferDataSizeCases(m_context, blockGroup, m_storage);
4909 }
4910
4911 // .name_length
4912 {
4913 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "name_length", "Name length");
4914 addChild(blockGroup);
4915 generateBufferBackedInterfaceResourceBasicBlockTypes(m_context, blockGroup, glslVersion, m_storage, generateBufferBackedInterfaceNameLengthCase);
4916 }
4917
4918 // .referenced_by
4919 {
4920 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "referenced_by", "Referenced by shader");
4921 addChild(blockGroup);
4922
4923 if (m_storage == glu::STORAGE_UNIFORM)
4924 generateReferencedByShaderCaseBlocks(m_context, blockGroup, glslVersion, generateBufferBlockReferencedByShaderSingleBlockContentCases<glu::STORAGE_UNIFORM>);
4925 else if (m_storage == glu::STORAGE_BUFFER)
4926 generateReferencedByShaderCaseBlocks(m_context, blockGroup, glslVersion, generateBufferBlockReferencedByShaderSingleBlockContentCases<glu::STORAGE_BUFFER>);
4927 else
4928 DE_ASSERT(false);
4929 }
4930 }
4931
getGroupName(glu::Storage storage)4932 const char* BufferBackedBlockInterfaceTestGroup::getGroupName (glu::Storage storage)
4933 {
4934 switch (storage)
4935 {
4936 case glu::STORAGE_UNIFORM: return "uniform_block";
4937 case glu::STORAGE_BUFFER: return "shader_storage_block";
4938 default:
4939 DE_FATAL("invalid storage enum value");
4940 return DE_NULL;
4941 }
4942 }
4943
getGroupDescription(glu::Storage storage)4944 const char* BufferBackedBlockInterfaceTestGroup::getGroupDescription (glu::Storage storage)
4945 {
4946 switch (storage)
4947 {
4948 case glu::STORAGE_UNIFORM: return "Uniform block interface";
4949 case glu::STORAGE_BUFFER: return "Shader storage block interface";
4950 default:
4951 DE_FATAL("invalid storage enum value");
4952 return DE_NULL;
4953 }
4954 }
4955
4956 class AtomicCounterTestGroup : public TestCaseGroup
4957 {
4958 public:
4959 AtomicCounterTestGroup (Context& context);
4960 void init (void);
4961 };
4962
AtomicCounterTestGroup(Context & context)4963 AtomicCounterTestGroup::AtomicCounterTestGroup (Context& context)
4964 : TestCaseGroup(context, "atomic_counter_buffer", "Atomic counter buffer")
4965 {
4966 }
4967
init(void)4968 void AtomicCounterTestGroup::init (void)
4969 {
4970 static const struct
4971 {
4972 const char* name;
4973 deUint32 flags;
4974 } pipelines[] =
4975 {
4976 {
4977 "vertex_fragment",
4978 (1 << glu::SHADERTYPE_VERTEX) | (1 << glu::SHADERTYPE_FRAGMENT)
4979 },
4980 {
4981 "vertex_tess_fragment",
4982 (1 << glu::SHADERTYPE_VERTEX) | (1 << glu::SHADERTYPE_FRAGMENT) | (1 << glu::SHADERTYPE_TESSELLATION_CONTROL) | (1 << glu::SHADERTYPE_TESSELLATION_EVALUATION)
4983 },
4984 {
4985 "vertex_geo_fragment",
4986 (1 << glu::SHADERTYPE_VERTEX) | (1 << glu::SHADERTYPE_FRAGMENT) | (1 << glu::SHADERTYPE_GEOMETRY)
4987 },
4988 {
4989 "vertex_tess_geo_fragment",
4990 (1 << glu::SHADERTYPE_VERTEX) | (1 << glu::SHADERTYPE_FRAGMENT) | (1 << glu::SHADERTYPE_TESSELLATION_CONTROL) | (1 << glu::SHADERTYPE_TESSELLATION_EVALUATION) | (1 << glu::SHADERTYPE_GEOMETRY),
4991 },
4992 };
4993
4994 // .resource_list
4995 addChild(new AtomicCounterResourceListCase(m_context, "resource_list", "Resource list"));
4996
4997 // .active_variables
4998 addChild(new AtomicCounterActiveVariablesCase(m_context, "active_variables", "Active variables"));
4999
5000 // .buffer_binding
5001 addChild(new AtomicCounterBufferBindingCase(m_context, "buffer_binding", "Buffer binding"));
5002
5003 // .buffer_data_size
5004 addChild(new AtomicCounterBufferDataSizeCase(m_context, "buffer_data_size", "Buffer binding"));
5005
5006 // .referenced_by
5007 addChild(new AtomicCounterReferencedByCase(m_context, "referenced_by_compute", "", false, (1 << glu::SHADERTYPE_COMPUTE), (1 << glu::SHADERTYPE_COMPUTE)));
5008 addChild(new AtomicCounterReferencedByCase(m_context, "referenced_by_separable_vertex", "", true, (1 << glu::SHADERTYPE_VERTEX), (1 << glu::SHADERTYPE_VERTEX)));
5009 addChild(new AtomicCounterReferencedByCase(m_context, "referenced_by_separable_fragment", "", true, (1 << glu::SHADERTYPE_FRAGMENT), (1 << glu::SHADERTYPE_FRAGMENT)));
5010 addChild(new AtomicCounterReferencedByCase(m_context, "referenced_by_separable_geometry", "", true, (1 << glu::SHADERTYPE_GEOMETRY), (1 << glu::SHADERTYPE_GEOMETRY)));
5011 addChild(new AtomicCounterReferencedByCase(m_context, "referenced_by_separable_tess_ctrl", "", true, (1 << glu::SHADERTYPE_TESSELLATION_CONTROL), (1 << glu::SHADERTYPE_TESSELLATION_CONTROL)));
5012 addChild(new AtomicCounterReferencedByCase(m_context, "referenced_by_separable_tess_eval", "", true, (1 << glu::SHADERTYPE_TESSELLATION_EVALUATION), (1 << glu::SHADERTYPE_TESSELLATION_EVALUATION)));
5013
5014 for (int pipelineNdx = 0; pipelineNdx < DE_LENGTH_OF_ARRAY(pipelines); ++pipelineNdx)
5015 {
5016 addChild(new AtomicCounterReferencedByCase(m_context, (std::string() + "referenced_by_" + pipelines[pipelineNdx].name).c_str(), "", false, pipelines[pipelineNdx].flags, pipelines[pipelineNdx].flags));
5017
5018 for (deUint32 stageNdx = 0; stageNdx < glu::SHADERTYPE_LAST; ++stageNdx)
5019 {
5020 const deUint32 currentBit = (1u << stageNdx);
5021 if (currentBit > pipelines[pipelineNdx].flags)
5022 break;
5023 if (currentBit & pipelines[pipelineNdx].flags)
5024 {
5025 const char* stageName = (stageNdx == glu::SHADERTYPE_VERTEX) ? ("vertex")
5026 : (stageNdx == glu::SHADERTYPE_FRAGMENT) ? ("fragment")
5027 : (stageNdx == glu::SHADERTYPE_GEOMETRY) ? ("geo")
5028 : (stageNdx == glu::SHADERTYPE_TESSELLATION_CONTROL) ? ("tess_ctrl")
5029 : (stageNdx == glu::SHADERTYPE_TESSELLATION_EVALUATION) ? ("tess_eval")
5030 : (DE_NULL);
5031 const std::string name = std::string() + "referenced_by_" + pipelines[pipelineNdx].name + "_only_" + stageName;
5032
5033 addChild(new AtomicCounterReferencedByCase(m_context, name.c_str(), "", false, pipelines[pipelineNdx].flags, currentBit));
5034 }
5035 }
5036 }
5037 }
5038
generateProgramInputOutputShaderCaseBlocks(Context & context,tcu::TestCaseGroup * targetGroup,glu::GLSLVersion glslVersion,bool withCompute,bool inputCase,void (* blockContentGenerator)(Context &,const ResourceDefinition::Node::SharedPtr &,tcu::TestCaseGroup *,deUint32))5039 static void generateProgramInputOutputShaderCaseBlocks (Context& context, tcu::TestCaseGroup* targetGroup, glu::GLSLVersion glslVersion, bool withCompute, bool inputCase, void (*blockContentGenerator)(Context&, const ResourceDefinition::Node::SharedPtr&, tcu::TestCaseGroup*, deUint32))
5040 {
5041 static const struct
5042 {
5043 const char* name;
5044 glu::ShaderType stage;
5045 } singleStageCases[] =
5046 {
5047 { "separable_vertex", glu::SHADERTYPE_VERTEX },
5048 { "separable_fragment", glu::SHADERTYPE_FRAGMENT },
5049 { "separable_tess_ctrl", glu::SHADERTYPE_TESSELLATION_CONTROL },
5050 { "separable_tess_eval", glu::SHADERTYPE_TESSELLATION_EVALUATION },
5051 { "separable_geometry", glu::SHADERTYPE_GEOMETRY },
5052 };
5053
5054 // .vertex_fragment
5055 {
5056 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "vertex_fragment", "Vertex and fragment");
5057 const ResourceDefinition::Node::SharedPtr program (new ResourceDefinition::Program(false));
5058 ResourceDefinition::ShaderSet* shaderSetPtr = new ResourceDefinition::ShaderSet(program, glslVersion);
5059 const ResourceDefinition::Node::SharedPtr shaderSet (shaderSetPtr);
5060 const ResourceDefinition::Node::SharedPtr defaultBlock (new ResourceDefinition::DefaultBlock(shaderSet));
5061
5062 shaderSetPtr->setStage(glu::SHADERTYPE_VERTEX, inputCase);
5063 shaderSetPtr->setStage(glu::SHADERTYPE_FRAGMENT, !inputCase);
5064
5065 targetGroup->addChild(blockGroup);
5066
5067 blockContentGenerator(context, defaultBlock, blockGroup, (1 << glu::SHADERTYPE_VERTEX) | (1 << glu::SHADERTYPE_FRAGMENT));
5068 }
5069
5070 // .separable_*
5071 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(singleStageCases); ++ndx)
5072 {
5073 TestCaseGroup* const blockGroup = new TestCaseGroup(context, singleStageCases[ndx].name, "");
5074 const ResourceDefinition::Node::SharedPtr program (new ResourceDefinition::Program(true));
5075 const ResourceDefinition::Node::SharedPtr shader (new ResourceDefinition::Shader(program, singleStageCases[ndx].stage, glslVersion));
5076 const ResourceDefinition::Node::SharedPtr defaultBlock (new ResourceDefinition::DefaultBlock(shader));
5077
5078 targetGroup->addChild(blockGroup);
5079 blockContentGenerator(context, defaultBlock, blockGroup, (1 << singleStageCases[ndx].stage));
5080 }
5081
5082 // .compute
5083 if (withCompute)
5084 {
5085 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "compute", "Compute");
5086 const ResourceDefinition::Node::SharedPtr program (new ResourceDefinition::Program(true));
5087 const ResourceDefinition::Node::SharedPtr shader (new ResourceDefinition::Shader(program, glu::SHADERTYPE_COMPUTE, glslVersion));
5088 const ResourceDefinition::Node::SharedPtr defaultBlock (new ResourceDefinition::DefaultBlock(shader));
5089
5090 targetGroup->addChild(blockGroup);
5091
5092 blockContentGenerator(context, defaultBlock, blockGroup, (1 << glu::SHADERTYPE_COMPUTE));
5093 }
5094
5095 // .interface_blocks
5096 {
5097 static const struct
5098 {
5099 const char* inputName;
5100 glu::ShaderType inputStage;
5101 glu::Storage inputStorage;
5102 const char* outputName;
5103 glu::ShaderType outputStage;
5104 glu::Storage outputStorage;
5105 } ioBlockTypes[] =
5106 {
5107 {
5108 "in",
5109 glu::SHADERTYPE_FRAGMENT,
5110 glu::STORAGE_IN,
5111 "out",
5112 glu::SHADERTYPE_VERTEX,
5113 glu::STORAGE_OUT,
5114 },
5115 {
5116 "patch_in",
5117 glu::SHADERTYPE_TESSELLATION_EVALUATION,
5118 glu::STORAGE_PATCH_IN,
5119 "patch_out",
5120 glu::SHADERTYPE_TESSELLATION_CONTROL,
5121 glu::STORAGE_PATCH_OUT,
5122 },
5123 };
5124
5125 tcu::TestCaseGroup* const ioBlocksGroup = new TestCaseGroup(context, "interface_blocks", "Interface blocks");
5126 targetGroup->addChild(ioBlocksGroup);
5127
5128 // .in/out
5129 // .sample in/out
5130 // .patch in/out
5131 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(ioBlockTypes); ++ndx)
5132 {
5133 const char* const name = (inputCase) ? (ioBlockTypes[ndx].inputName) : (ioBlockTypes[ndx].outputName);
5134 const glu::ShaderType shaderType = (inputCase) ? (ioBlockTypes[ndx].inputStage) : (ioBlockTypes[ndx].outputStage);
5135 const glu::Storage storageType = (inputCase) ? (ioBlockTypes[ndx].inputStorage) : (ioBlockTypes[ndx].outputStorage);
5136 tcu::TestCaseGroup* const ioBlockGroup = new TestCaseGroup(context, name, "");
5137 const ResourceDefinition::Node::SharedPtr program (new ResourceDefinition::Program(true));
5138 const ResourceDefinition::Node::SharedPtr shader (new ResourceDefinition::Shader(program, shaderType, glslVersion));
5139 const ResourceDefinition::Node::SharedPtr defaultBlock (new ResourceDefinition::DefaultBlock(shader));
5140 const ResourceDefinition::Node::SharedPtr storage (new ResourceDefinition::StorageQualifier(defaultBlock, storageType));
5141
5142 ioBlocksGroup->addChild(ioBlockGroup);
5143
5144 // .named_block
5145 {
5146 const ResourceDefinition::Node::SharedPtr block (new ResourceDefinition::InterfaceBlock(storage, true));
5147 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "named_block", "Named block");
5148
5149 ioBlockGroup->addChild(blockGroup);
5150
5151 blockContentGenerator(context, block, blockGroup, (1 << shaderType));
5152 }
5153
5154 // .named_block_explicit_location
5155 {
5156 const ResourceDefinition::Node::SharedPtr layout (new ResourceDefinition::LayoutQualifier(storage, glu::Layout(3)));
5157 const ResourceDefinition::Node::SharedPtr block (new ResourceDefinition::InterfaceBlock(layout, true));
5158 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "named_block_explicit_location", "Named block with explicit location");
5159
5160 ioBlockGroup->addChild(blockGroup);
5161
5162 blockContentGenerator(context, block, blockGroup, (1 << shaderType));
5163 }
5164
5165 // .unnamed_block
5166 {
5167 const ResourceDefinition::Node::SharedPtr block (new ResourceDefinition::InterfaceBlock(storage, false));
5168 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "unnamed_block", "Unnamed block");
5169
5170 ioBlockGroup->addChild(blockGroup);
5171
5172 blockContentGenerator(context, block, blockGroup, (1 << shaderType));
5173 }
5174
5175 // .block_array
5176 {
5177 const ResourceDefinition::Node::SharedPtr arrayElement (new ResourceDefinition::ArrayElement(storage));
5178 const ResourceDefinition::Node::SharedPtr block (new ResourceDefinition::InterfaceBlock(arrayElement, true));
5179 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "block_array", "Block array");
5180
5181 ioBlockGroup->addChild(blockGroup);
5182
5183 blockContentGenerator(context, block, blockGroup, (1 << shaderType));
5184 }
5185 }
5186 }
5187 }
5188
generateProgramInputBlockContents(Context & context,const ResourceDefinition::Node::SharedPtr & parentStructure,tcu::TestCaseGroup * targetGroup,deUint32 presentShadersMask,bool includeEmpty,void (* genCase)(Context & context,const ResourceDefinition::Node::SharedPtr & parentStructure,tcu::TestCaseGroup * targetGroup,ProgramInterface interface,const char * name))5189 static void generateProgramInputBlockContents (Context& context,
5190 const ResourceDefinition::Node::SharedPtr& parentStructure,
5191 tcu::TestCaseGroup* targetGroup,
5192 deUint32 presentShadersMask,
5193 bool includeEmpty,
5194 void (*genCase)(Context& context,
5195 const ResourceDefinition::Node::SharedPtr& parentStructure,
5196 tcu::TestCaseGroup* targetGroup,
5197 ProgramInterface interface,
5198 const char* name))
5199 {
5200 const bool inDefaultBlock = parentStructure->getType() == ResourceDefinition::Node::TYPE_DEFAULT_BLOCK;
5201 const ResourceDefinition::Node::SharedPtr input = (inDefaultBlock)
5202 ? (ResourceDefinition::Node::SharedPtr(new ResourceDefinition::StorageQualifier(parentStructure, glu::STORAGE_IN)))
5203 : (parentStructure);
5204 const glu::ShaderType firstStage = getShaderMaskFirstStage(presentShadersMask);
5205
5206 // .empty
5207 if (includeEmpty && inDefaultBlock)
5208 genCase(context, parentStructure, targetGroup, PROGRAMINTERFACE_PROGRAM_INPUT, "empty");
5209
5210 if (firstStage == glu::SHADERTYPE_VERTEX)
5211 {
5212 // .var
5213 const ResourceDefinition::Node::SharedPtr variable(new ResourceDefinition::Variable(input, glu::TYPE_FLOAT_VEC4));
5214 genCase(context, variable, targetGroup, PROGRAMINTERFACE_PROGRAM_INPUT, "var");
5215 }
5216 else if (firstStage == glu::SHADERTYPE_FRAGMENT || !inDefaultBlock)
5217 {
5218 // .var
5219 {
5220 const ResourceDefinition::Node::SharedPtr variable(new ResourceDefinition::Variable(input, glu::TYPE_FLOAT_VEC4));
5221 genCase(context, variable, targetGroup, PROGRAMINTERFACE_PROGRAM_INPUT, "var");
5222 }
5223 // .var_struct
5224 {
5225 const ResourceDefinition::Node::SharedPtr structMbr (new ResourceDefinition::StructMember(input));
5226 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(structMbr, glu::TYPE_FLOAT_VEC4));
5227 genCase(context, variable, targetGroup, PROGRAMINTERFACE_PROGRAM_INPUT, "var_struct");
5228 }
5229 // .var_array
5230 {
5231 const ResourceDefinition::Node::SharedPtr arrayElem (new ResourceDefinition::ArrayElement(input));
5232 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(arrayElem, glu::TYPE_FLOAT_VEC4));
5233 genCase(context, variable, targetGroup, PROGRAMINTERFACE_PROGRAM_INPUT, "var_array");
5234 }
5235 }
5236 else if (firstStage == glu::SHADERTYPE_TESSELLATION_CONTROL ||
5237 firstStage == glu::SHADERTYPE_GEOMETRY)
5238 {
5239 // arrayed interface
5240
5241 // .var
5242 {
5243 const ResourceDefinition::Node::SharedPtr arrayElem (new ResourceDefinition::ArrayElement(input, ResourceDefinition::ArrayElement::UNSIZED_ARRAY));
5244 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(arrayElem, glu::TYPE_FLOAT_VEC4));
5245 genCase(context, variable, targetGroup, PROGRAMINTERFACE_PROGRAM_INPUT, "var");
5246 }
5247 // extension forbids use arrays of structs
5248 // extension forbids use arrays of arrays
5249 }
5250 else if (firstStage == glu::SHADERTYPE_TESSELLATION_EVALUATION)
5251 {
5252 // arrayed interface
5253 const ResourceDefinition::Node::SharedPtr patchInput(new ResourceDefinition::StorageQualifier(parentStructure, glu::STORAGE_PATCH_IN));
5254
5255 // .var
5256 {
5257 const ResourceDefinition::Node::SharedPtr arrayElem (new ResourceDefinition::ArrayElement(input, ResourceDefinition::ArrayElement::UNSIZED_ARRAY));
5258 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(arrayElem, glu::TYPE_FLOAT_VEC4));
5259 genCase(context, variable, targetGroup, PROGRAMINTERFACE_PROGRAM_INPUT, "var");
5260 }
5261 // extension forbids use arrays of structs
5262 // extension forbids use arrays of arrays
5263
5264 // .patch_var
5265 {
5266 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(patchInput, glu::TYPE_FLOAT_VEC4));
5267 genCase(context, variable, targetGroup, PROGRAMINTERFACE_PROGRAM_INPUT, "patch_var");
5268 }
5269 // .patch_var_struct
5270 {
5271 const ResourceDefinition::Node::SharedPtr structMbr (new ResourceDefinition::StructMember(patchInput));
5272 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(structMbr, glu::TYPE_FLOAT_VEC4));
5273 genCase(context, variable, targetGroup, PROGRAMINTERFACE_PROGRAM_INPUT, "patch_var_struct");
5274 }
5275 // .patch_var_array
5276 {
5277 const ResourceDefinition::Node::SharedPtr arrayElem (new ResourceDefinition::ArrayElement(patchInput));
5278 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(arrayElem, glu::TYPE_FLOAT_VEC4));
5279 genCase(context, variable, targetGroup, PROGRAMINTERFACE_PROGRAM_INPUT, "patch_var_array");
5280 }
5281 }
5282 else if (firstStage == glu::SHADERTYPE_COMPUTE)
5283 {
5284 // nada
5285 }
5286 else
5287 DE_ASSERT(false);
5288 }
5289
generateProgramOutputBlockContents(Context & context,const ResourceDefinition::Node::SharedPtr & parentStructure,tcu::TestCaseGroup * targetGroup,deUint32 presentShadersMask,bool includeEmpty,void (* genCase)(Context & context,const ResourceDefinition::Node::SharedPtr & parentStructure,tcu::TestCaseGroup * targetGroup,ProgramInterface interface,const char * name))5290 static void generateProgramOutputBlockContents (Context& context,
5291 const ResourceDefinition::Node::SharedPtr& parentStructure,
5292 tcu::TestCaseGroup* targetGroup,
5293 deUint32 presentShadersMask,
5294 bool includeEmpty,
5295 void (*genCase)(Context& context,
5296 const ResourceDefinition::Node::SharedPtr& parentStructure,
5297 tcu::TestCaseGroup* targetGroup,
5298 ProgramInterface interface,
5299 const char* name))
5300 {
5301 const bool inDefaultBlock = parentStructure->getType() == ResourceDefinition::Node::TYPE_DEFAULT_BLOCK;
5302 const ResourceDefinition::Node::SharedPtr output = (inDefaultBlock)
5303 ? (ResourceDefinition::Node::SharedPtr(new ResourceDefinition::StorageQualifier(parentStructure, glu::STORAGE_OUT)))
5304 : (parentStructure);
5305 const glu::ShaderType lastStage = getShaderMaskLastStage(presentShadersMask);
5306
5307 // .empty
5308 if (includeEmpty && inDefaultBlock)
5309 genCase(context, parentStructure, targetGroup, PROGRAMINTERFACE_PROGRAM_OUTPUT, "empty");
5310
5311 if (lastStage == glu::SHADERTYPE_VERTEX ||
5312 lastStage == glu::SHADERTYPE_GEOMETRY ||
5313 lastStage == glu::SHADERTYPE_TESSELLATION_EVALUATION ||
5314 !inDefaultBlock)
5315 {
5316 // .var
5317 {
5318 const ResourceDefinition::Node::SharedPtr variable(new ResourceDefinition::Variable(output, glu::TYPE_FLOAT_VEC4));
5319 genCase(context, variable, targetGroup, PROGRAMINTERFACE_PROGRAM_OUTPUT, "var");
5320 }
5321 // .var_struct
5322 {
5323 const ResourceDefinition::Node::SharedPtr structMbr (new ResourceDefinition::StructMember(output));
5324 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(structMbr, glu::TYPE_FLOAT_VEC4));
5325 genCase(context, variable, targetGroup, PROGRAMINTERFACE_PROGRAM_OUTPUT, "var_struct");
5326 }
5327 // .var_array
5328 {
5329 const ResourceDefinition::Node::SharedPtr arrayElem (new ResourceDefinition::ArrayElement(output));
5330 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(arrayElem, glu::TYPE_FLOAT_VEC4));
5331 genCase(context, variable, targetGroup, PROGRAMINTERFACE_PROGRAM_OUTPUT, "var_array");
5332 }
5333 }
5334 else if (lastStage == glu::SHADERTYPE_FRAGMENT)
5335 {
5336 // .var
5337 {
5338 const ResourceDefinition::Node::SharedPtr variable(new ResourceDefinition::Variable(output, glu::TYPE_FLOAT_VEC4));
5339 genCase(context, variable, targetGroup, PROGRAMINTERFACE_PROGRAM_OUTPUT, "var");
5340 }
5341 // .var_array
5342 {
5343 const ResourceDefinition::Node::SharedPtr arrayElem (new ResourceDefinition::ArrayElement(output));
5344 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(arrayElem, glu::TYPE_FLOAT_VEC4));
5345 genCase(context, variable, targetGroup, PROGRAMINTERFACE_PROGRAM_OUTPUT, "var_array");
5346 }
5347 }
5348 else if (lastStage == glu::SHADERTYPE_TESSELLATION_CONTROL)
5349 {
5350 // arrayed interface
5351 const ResourceDefinition::Node::SharedPtr patchOutput(new ResourceDefinition::StorageQualifier(parentStructure, glu::STORAGE_PATCH_OUT));
5352
5353 // .var
5354 {
5355 const ResourceDefinition::Node::SharedPtr arrayElem (new ResourceDefinition::ArrayElement(output, ResourceDefinition::ArrayElement::UNSIZED_ARRAY));
5356 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(arrayElem, glu::TYPE_FLOAT_VEC4));
5357 genCase(context, variable, targetGroup, PROGRAMINTERFACE_PROGRAM_OUTPUT, "var");
5358 }
5359 // extension forbids use arrays of structs
5360 // extension forbids use array of arrays
5361
5362 // .patch_var
5363 {
5364 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(patchOutput, glu::TYPE_FLOAT_VEC4));
5365 genCase(context, variable, targetGroup, PROGRAMINTERFACE_PROGRAM_OUTPUT, "patch_var");
5366 }
5367 // .patch_var_struct
5368 {
5369 const ResourceDefinition::Node::SharedPtr structMbr (new ResourceDefinition::StructMember(patchOutput));
5370 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(structMbr, glu::TYPE_FLOAT_VEC4));
5371 genCase(context, variable, targetGroup, PROGRAMINTERFACE_PROGRAM_OUTPUT, "patch_var_struct");
5372 }
5373 // .patch_var_array
5374 {
5375 const ResourceDefinition::Node::SharedPtr arrayElem (new ResourceDefinition::ArrayElement(patchOutput));
5376 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(arrayElem, glu::TYPE_FLOAT_VEC4));
5377 genCase(context, variable, targetGroup, PROGRAMINTERFACE_PROGRAM_OUTPUT, "patch_var_array");
5378 }
5379 }
5380 else if (lastStage == glu::SHADERTYPE_COMPUTE)
5381 {
5382 // nada
5383 }
5384 else
5385 DE_ASSERT(false);
5386 }
5387
addProgramInputOutputResourceListCase(Context & context,const ResourceDefinition::Node::SharedPtr & parentStructure,tcu::TestCaseGroup * targetGroup,ProgramInterface programInterface,const char * name)5388 static void addProgramInputOutputResourceListCase (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup, ProgramInterface programInterface, const char* name)
5389 {
5390 ResourceListTestCase* const resourceListCase = new ResourceListTestCase(context, parentStructure, programInterface);
5391
5392 DE_ASSERT(deStringEqual(name, resourceListCase->getName()));
5393 DE_UNREF(name);
5394 targetGroup->addChild(resourceListCase);
5395 }
5396
generateProgramInputResourceListBlockContents(Context & context,const ResourceDefinition::Node::SharedPtr & parentStructure,tcu::TestCaseGroup * targetGroup,deUint32 presentShadersMask)5397 static void generateProgramInputResourceListBlockContents (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup, deUint32 presentShadersMask)
5398 {
5399 generateProgramInputBlockContents(context, parentStructure, targetGroup, presentShadersMask, true, addProgramInputOutputResourceListCase);
5400 }
5401
generateProgramOutputResourceListBlockContents(Context & context,const ResourceDefinition::Node::SharedPtr & parentStructure,tcu::TestCaseGroup * targetGroup,deUint32 presentShadersMask)5402 static void generateProgramOutputResourceListBlockContents (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup, deUint32 presentShadersMask)
5403 {
5404 generateProgramOutputBlockContents(context, parentStructure, targetGroup, presentShadersMask, true, addProgramInputOutputResourceListCase);
5405 }
5406
5407 template <ProgramResourcePropFlags TargetProp>
addProgramInputOutputResourceTestCase(Context & context,const ResourceDefinition::Node::SharedPtr & parentStructure,tcu::TestCaseGroup * targetGroup,ProgramInterface programInterface,const char * name)5408 static void addProgramInputOutputResourceTestCase (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup, ProgramInterface programInterface, const char* name)
5409 {
5410 ResourceTestCase* const resourceTestCase = new ResourceTestCase(context, parentStructure, ProgramResourceQueryTestTarget(programInterface, TargetProp), name);
5411 targetGroup->addChild(resourceTestCase);
5412 }
5413
5414 template <ProgramResourcePropFlags TargetProp>
generateProgramInputBasicBlockContents(Context & context,const ResourceDefinition::Node::SharedPtr & parentStructure,tcu::TestCaseGroup * targetGroup,deUint32 presentShadersMask)5415 static void generateProgramInputBasicBlockContents (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup, deUint32 presentShadersMask)
5416 {
5417 generateProgramInputBlockContents(context, parentStructure, targetGroup, presentShadersMask, false, addProgramInputOutputResourceTestCase<TargetProp>);
5418 }
5419
5420 template <ProgramResourcePropFlags TargetProp>
generateProgramOutputBasicBlockContents(Context & context,const ResourceDefinition::Node::SharedPtr & parentStructure,tcu::TestCaseGroup * targetGroup,deUint32 presentShadersMask)5421 static void generateProgramOutputBasicBlockContents (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup, deUint32 presentShadersMask)
5422 {
5423 generateProgramOutputBlockContents(context, parentStructure, targetGroup, presentShadersMask, false, addProgramInputOutputResourceTestCase<TargetProp>);
5424 }
5425
generateProgramInputLocationBlockContents(Context & context,const ResourceDefinition::Node::SharedPtr & parentStructure,tcu::TestCaseGroup * targetGroup,deUint32 presentShadersMask)5426 static void generateProgramInputLocationBlockContents (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup, deUint32 presentShadersMask)
5427 {
5428 const bool inDefaultBlock = parentStructure->getType() == ResourceDefinition::Node::TYPE_DEFAULT_BLOCK;
5429 const ResourceDefinition::Node::SharedPtr input = (inDefaultBlock)
5430 ? (ResourceDefinition::Node::SharedPtr(new ResourceDefinition::StorageQualifier(parentStructure, glu::STORAGE_IN)))
5431 : (parentStructure);
5432 const glu::ShaderType firstStage = getShaderMaskFirstStage(presentShadersMask);
5433
5434 if (firstStage == glu::SHADERTYPE_VERTEX)
5435 {
5436 // .var
5437 {
5438 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(input, glu::TYPE_FLOAT_VEC4));
5439 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_INPUT, PROGRAMRESOURCEPROP_LOCATION), "var"));
5440 }
5441 // .var_explicit_location
5442 {
5443 const ResourceDefinition::Node::SharedPtr layout (new ResourceDefinition::LayoutQualifier(input, glu::Layout(2)));
5444 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(layout, glu::TYPE_FLOAT_VEC4));
5445 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_INPUT, PROGRAMRESOURCEPROP_LOCATION), "var_explicit_location"));
5446 }
5447 }
5448 else if (firstStage == glu::SHADERTYPE_FRAGMENT || !inDefaultBlock)
5449 {
5450 // .var
5451 {
5452 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(input, glu::TYPE_FLOAT_VEC4));
5453 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_INPUT, PROGRAMRESOURCEPROP_LOCATION), "var"));
5454 }
5455 // .var_explicit_location
5456 {
5457 const ResourceDefinition::Node::SharedPtr layout (new ResourceDefinition::LayoutQualifier(input, glu::Layout(2)));
5458 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(layout, glu::TYPE_FLOAT_VEC4));
5459 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_INPUT, PROGRAMRESOURCEPROP_LOCATION), "var_explicit_location"));
5460 }
5461 // .var_struct
5462 {
5463 const ResourceDefinition::Node::SharedPtr structMbr (new ResourceDefinition::StructMember(input));
5464 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(structMbr, glu::TYPE_FLOAT_VEC4));
5465 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_INPUT, PROGRAMRESOURCEPROP_LOCATION), "var_struct"));
5466 }
5467 // .var_struct_explicit_location
5468 {
5469 const ResourceDefinition::Node::SharedPtr layout (new ResourceDefinition::LayoutQualifier(input, glu::Layout(2)));
5470 const ResourceDefinition::Node::SharedPtr structMbr (new ResourceDefinition::StructMember(layout));
5471 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(structMbr, glu::TYPE_FLOAT_VEC4));
5472 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_INPUT, PROGRAMRESOURCEPROP_LOCATION), "var_struct_explicit_location"));
5473 }
5474 // .var_array
5475 {
5476 const ResourceDefinition::Node::SharedPtr arrayElem (new ResourceDefinition::ArrayElement(input));
5477 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(arrayElem, glu::TYPE_FLOAT_VEC4));
5478 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_INPUT, PROGRAMRESOURCEPROP_LOCATION), "var_array"));
5479 }
5480 // .var_array_explicit_location
5481 {
5482 const ResourceDefinition::Node::SharedPtr layout (new ResourceDefinition::LayoutQualifier(input, glu::Layout(2)));
5483 const ResourceDefinition::Node::SharedPtr arrayElem (new ResourceDefinition::ArrayElement(layout));
5484 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(arrayElem, glu::TYPE_FLOAT_VEC4));
5485 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_INPUT, PROGRAMRESOURCEPROP_LOCATION), "var_array_explicit_location"));
5486 }
5487 }
5488 else if (firstStage == glu::SHADERTYPE_TESSELLATION_CONTROL ||
5489 firstStage == glu::SHADERTYPE_GEOMETRY)
5490 {
5491 // arrayed interface
5492
5493 // .var
5494 {
5495 const ResourceDefinition::Node::SharedPtr arrayElem (new ResourceDefinition::ArrayElement(input, ResourceDefinition::ArrayElement::UNSIZED_ARRAY));
5496 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(arrayElem, glu::TYPE_FLOAT_VEC4));
5497 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_INPUT, PROGRAMRESOURCEPROP_LOCATION), "var"));
5498 }
5499 // .var_explicit_location
5500 {
5501 const ResourceDefinition::Node::SharedPtr layout (new ResourceDefinition::LayoutQualifier(input, glu::Layout(2)));
5502 const ResourceDefinition::Node::SharedPtr arrayElem (new ResourceDefinition::ArrayElement(layout, ResourceDefinition::ArrayElement::UNSIZED_ARRAY));
5503 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(arrayElem, glu::TYPE_FLOAT_VEC4));
5504 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_INPUT, PROGRAMRESOURCEPROP_LOCATION), "var_explicit_location"));
5505 }
5506 // extension forbids use arrays of structs
5507 // extension forbids use arrays of arrays
5508 }
5509 else if (firstStage == glu::SHADERTYPE_TESSELLATION_EVALUATION)
5510 {
5511 // arrayed interface
5512 const ResourceDefinition::Node::SharedPtr patchInput(new ResourceDefinition::StorageQualifier(parentStructure, glu::STORAGE_PATCH_IN));
5513
5514 // .var
5515 {
5516 const ResourceDefinition::Node::SharedPtr arrayElem (new ResourceDefinition::ArrayElement(input, ResourceDefinition::ArrayElement::UNSIZED_ARRAY));
5517 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(arrayElem, glu::TYPE_FLOAT_VEC4));
5518 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_INPUT, PROGRAMRESOURCEPROP_LOCATION), "var"));
5519 }
5520 // .var_explicit_location
5521 {
5522 const ResourceDefinition::Node::SharedPtr layout (new ResourceDefinition::LayoutQualifier(input, glu::Layout(2)));
5523 const ResourceDefinition::Node::SharedPtr arrayElem (new ResourceDefinition::ArrayElement(layout, ResourceDefinition::ArrayElement::UNSIZED_ARRAY));
5524 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(arrayElem, glu::TYPE_FLOAT_VEC4));
5525 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_INPUT, PROGRAMRESOURCEPROP_LOCATION), "var_explicit_location"));
5526 }
5527 // extension forbids use arrays of structs
5528 // extension forbids use arrays of arrays
5529
5530 // .patch_var
5531 {
5532 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(patchInput, glu::TYPE_FLOAT_VEC4));
5533 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_INPUT, PROGRAMRESOURCEPROP_LOCATION), "patch_var"));
5534 }
5535 // .patch_var_explicit_location
5536 {
5537 const ResourceDefinition::Node::SharedPtr layout (new ResourceDefinition::LayoutQualifier(patchInput, glu::Layout(2)));
5538 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(layout, glu::TYPE_FLOAT_VEC4));
5539 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_INPUT, PROGRAMRESOURCEPROP_LOCATION), "patch_var_explicit_location"));
5540 }
5541 // .patch_var_struct
5542 {
5543 const ResourceDefinition::Node::SharedPtr structMbr (new ResourceDefinition::StructMember(patchInput));
5544 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(structMbr, glu::TYPE_FLOAT_VEC4));
5545 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_INPUT, PROGRAMRESOURCEPROP_LOCATION), "patch_var_struct"));
5546 }
5547 // .patch_var_struct_explicit_location
5548 {
5549 const ResourceDefinition::Node::SharedPtr layout (new ResourceDefinition::LayoutQualifier(patchInput, glu::Layout(2)));
5550 const ResourceDefinition::Node::SharedPtr structMbr (new ResourceDefinition::StructMember(layout));
5551 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(structMbr, glu::TYPE_FLOAT_VEC4));
5552 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_INPUT, PROGRAMRESOURCEPROP_LOCATION), "patch_var_struct_explicit_location"));
5553 }
5554 // .patch_var_array
5555 {
5556 const ResourceDefinition::Node::SharedPtr arrayElem (new ResourceDefinition::ArrayElement(patchInput));
5557 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(arrayElem, glu::TYPE_FLOAT_VEC4));
5558 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_INPUT, PROGRAMRESOURCEPROP_LOCATION), "patch_var_array"));
5559 }
5560 // .patch_var_array_explicit_location
5561 {
5562 const ResourceDefinition::Node::SharedPtr layout (new ResourceDefinition::LayoutQualifier(patchInput, glu::Layout(2)));
5563 const ResourceDefinition::Node::SharedPtr arrayElem (new ResourceDefinition::ArrayElement(layout));
5564 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(arrayElem, glu::TYPE_FLOAT_VEC4));
5565 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_INPUT, PROGRAMRESOURCEPROP_LOCATION), "patch_var_array_explicit_location"));
5566 }
5567 }
5568 else if (firstStage == glu::SHADERTYPE_COMPUTE)
5569 {
5570 // nada
5571 }
5572 else
5573 DE_ASSERT(false);
5574 }
5575
generateProgramOutputLocationBlockContents(Context & context,const ResourceDefinition::Node::SharedPtr & parentStructure,tcu::TestCaseGroup * targetGroup,deUint32 presentShadersMask)5576 static void generateProgramOutputLocationBlockContents (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup, deUint32 presentShadersMask)
5577 {
5578 const bool inDefaultBlock = parentStructure->getType() == ResourceDefinition::Node::TYPE_DEFAULT_BLOCK;
5579 const ResourceDefinition::Node::SharedPtr output = (inDefaultBlock)
5580 ? (ResourceDefinition::Node::SharedPtr(new ResourceDefinition::StorageQualifier(parentStructure, glu::STORAGE_OUT)))
5581 : (parentStructure);
5582 const glu::ShaderType lastStage = getShaderMaskLastStage(presentShadersMask);
5583
5584 if (lastStage == glu::SHADERTYPE_VERTEX ||
5585 lastStage == glu::SHADERTYPE_GEOMETRY ||
5586 lastStage == glu::SHADERTYPE_TESSELLATION_EVALUATION ||
5587 !inDefaultBlock)
5588 {
5589 // .var
5590 {
5591 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(output, glu::TYPE_FLOAT_VEC4));
5592 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_OUTPUT, PROGRAMRESOURCEPROP_LOCATION), "var"));
5593 }
5594 // .var_explicit_location
5595 {
5596 const ResourceDefinition::Node::SharedPtr layout (new ResourceDefinition::LayoutQualifier(output, glu::Layout(2)));
5597 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(layout, glu::TYPE_FLOAT_VEC4));
5598 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_OUTPUT, PROGRAMRESOURCEPROP_LOCATION), "var_explicit_location"));
5599 }
5600 // .var_struct
5601 {
5602 const ResourceDefinition::Node::SharedPtr structMbr (new ResourceDefinition::StructMember(output));
5603 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(structMbr, glu::TYPE_FLOAT_VEC4));
5604 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_OUTPUT, PROGRAMRESOURCEPROP_LOCATION), "var_struct"));
5605 }
5606 // .var_struct_explicit_location
5607 {
5608 const ResourceDefinition::Node::SharedPtr layout (new ResourceDefinition::LayoutQualifier(output, glu::Layout(2)));
5609 const ResourceDefinition::Node::SharedPtr structMbr (new ResourceDefinition::StructMember(layout));
5610 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(structMbr, glu::TYPE_FLOAT_VEC4));
5611 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_OUTPUT, PROGRAMRESOURCEPROP_LOCATION), "var_struct_explicit_location"));
5612 }
5613 // .var_array
5614 {
5615 const ResourceDefinition::Node::SharedPtr arrayElem (new ResourceDefinition::ArrayElement(output));
5616 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(arrayElem, glu::TYPE_FLOAT_VEC4));
5617 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_OUTPUT, PROGRAMRESOURCEPROP_LOCATION), "var_array"));
5618 }
5619 // .var_array_explicit_location
5620 {
5621 const ResourceDefinition::Node::SharedPtr layout (new ResourceDefinition::LayoutQualifier(output, glu::Layout(2)));
5622 const ResourceDefinition::Node::SharedPtr arrayElem (new ResourceDefinition::ArrayElement(layout));
5623 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(arrayElem, glu::TYPE_FLOAT_VEC4));
5624 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_OUTPUT, PROGRAMRESOURCEPROP_LOCATION), "var_array_explicit_location"));
5625 }
5626 }
5627 else if (lastStage == glu::SHADERTYPE_FRAGMENT)
5628 {
5629 // .var
5630 {
5631 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(output, glu::TYPE_FLOAT_VEC4));
5632 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_OUTPUT, PROGRAMRESOURCEPROP_LOCATION), "var"));
5633 }
5634 // .var_explicit_location
5635 {
5636 const ResourceDefinition::Node::SharedPtr layout (new ResourceDefinition::LayoutQualifier(output, glu::Layout(2)));
5637 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(layout, glu::TYPE_FLOAT_VEC4));
5638 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_OUTPUT, PROGRAMRESOURCEPROP_LOCATION), "var_explicit_location"));
5639 }
5640 // .var_array
5641 {
5642 const ResourceDefinition::Node::SharedPtr arrayElem (new ResourceDefinition::ArrayElement(output));
5643 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(arrayElem, glu::TYPE_FLOAT_VEC4));
5644 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_OUTPUT, PROGRAMRESOURCEPROP_LOCATION), "var_array"));
5645 }
5646 // .var_array_explicit_location
5647 {
5648 const ResourceDefinition::Node::SharedPtr layout (new ResourceDefinition::LayoutQualifier(output, glu::Layout(1)));
5649 const ResourceDefinition::Node::SharedPtr arrayElem (new ResourceDefinition::ArrayElement(layout));
5650 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(arrayElem, glu::TYPE_FLOAT_VEC4));
5651 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_OUTPUT, PROGRAMRESOURCEPROP_LOCATION), "var_array_explicit_location"));
5652 }
5653 }
5654 else if (lastStage == glu::SHADERTYPE_TESSELLATION_CONTROL)
5655 {
5656 // arrayed interface
5657 const ResourceDefinition::Node::SharedPtr patchOutput(new ResourceDefinition::StorageQualifier(parentStructure, glu::STORAGE_PATCH_OUT));
5658
5659 // .var
5660 {
5661 const ResourceDefinition::Node::SharedPtr arrayElem (new ResourceDefinition::ArrayElement(output, ResourceDefinition::ArrayElement::UNSIZED_ARRAY));
5662 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(arrayElem, glu::TYPE_FLOAT_VEC4));
5663 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_OUTPUT, PROGRAMRESOURCEPROP_LOCATION), "var"));
5664 }
5665 // .var_explicit_location
5666 {
5667 const ResourceDefinition::Node::SharedPtr layout (new ResourceDefinition::LayoutQualifier(output, glu::Layout(2)));
5668 const ResourceDefinition::Node::SharedPtr arrayElem (new ResourceDefinition::ArrayElement(layout, ResourceDefinition::ArrayElement::UNSIZED_ARRAY));
5669 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(arrayElem, glu::TYPE_FLOAT_VEC4));
5670 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_OUTPUT, PROGRAMRESOURCEPROP_LOCATION), "var_explicit_location"));
5671 }
5672 // extension forbids use arrays of structs
5673 // extension forbids use array of arrays
5674
5675 // .patch_var
5676 {
5677 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(patchOutput, glu::TYPE_FLOAT_VEC4));
5678 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_OUTPUT, PROGRAMRESOURCEPROP_LOCATION), "patch_var"));
5679 }
5680 // .patch_var_explicit_location
5681 {
5682 const ResourceDefinition::Node::SharedPtr layout (new ResourceDefinition::LayoutQualifier(patchOutput, glu::Layout(2)));
5683 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(layout, glu::TYPE_FLOAT_VEC4));
5684 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_OUTPUT, PROGRAMRESOURCEPROP_LOCATION), "patch_var_explicit_location"));
5685 }
5686 // .patch_var_struct
5687 {
5688 const ResourceDefinition::Node::SharedPtr structMbr (new ResourceDefinition::StructMember(patchOutput));
5689 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(structMbr, glu::TYPE_FLOAT_VEC4));
5690 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_OUTPUT, PROGRAMRESOURCEPROP_LOCATION), "patch_var_struct"));
5691 }
5692 // .patch_var_struct_explicit_location
5693 {
5694 const ResourceDefinition::Node::SharedPtr layout (new ResourceDefinition::LayoutQualifier(patchOutput, glu::Layout(2)));
5695 const ResourceDefinition::Node::SharedPtr structMbr (new ResourceDefinition::StructMember(layout));
5696 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(structMbr, glu::TYPE_FLOAT_VEC4));
5697 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_OUTPUT, PROGRAMRESOURCEPROP_LOCATION), "patch_var_struct_explicit_location"));
5698 }
5699 // .patch_var_array
5700 {
5701 const ResourceDefinition::Node::SharedPtr arrayElem (new ResourceDefinition::ArrayElement(patchOutput));
5702 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(arrayElem, glu::TYPE_FLOAT_VEC4));
5703 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_OUTPUT, PROGRAMRESOURCEPROP_LOCATION), "patch_var_array"));
5704 }
5705 // .patch_var_array_explicit_location
5706 {
5707 const ResourceDefinition::Node::SharedPtr layout (new ResourceDefinition::LayoutQualifier(patchOutput, glu::Layout(2)));
5708 const ResourceDefinition::Node::SharedPtr arrayElem (new ResourceDefinition::ArrayElement(layout));
5709 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(arrayElem, glu::TYPE_FLOAT_VEC4));
5710 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_PROGRAM_OUTPUT, PROGRAMRESOURCEPROP_LOCATION), "patch_var_array_explicit_location"));
5711 }
5712 }
5713 else if (lastStage == glu::SHADERTYPE_COMPUTE)
5714 {
5715 // nada
5716 }
5717 else
5718 DE_ASSERT(false);
5719 }
5720
generateProgramInputOutputReferencedByCases(Context & context,tcu::TestCaseGroup * targetGroup,glu::Storage storage)5721 static void generateProgramInputOutputReferencedByCases (Context& context, tcu::TestCaseGroup* targetGroup, glu::Storage storage)
5722 {
5723 // all whole pipelines
5724 targetGroup->addChild(new ProgramInputOutputReferencedByCase(context, "referenced_by_vertex_fragment", "", storage, ProgramInputOutputReferencedByCase::CASE_VERTEX_FRAGMENT));
5725 targetGroup->addChild(new ProgramInputOutputReferencedByCase(context, "referenced_by_vertex_tess_fragment", "", storage, ProgramInputOutputReferencedByCase::CASE_VERTEX_TESS_FRAGMENT));
5726 targetGroup->addChild(new ProgramInputOutputReferencedByCase(context, "referenced_by_vertex_geo_fragment", "", storage, ProgramInputOutputReferencedByCase::CASE_VERTEX_GEO_FRAGMENT));
5727 targetGroup->addChild(new ProgramInputOutputReferencedByCase(context, "referenced_by_vertex_tess_geo_fragment", "", storage, ProgramInputOutputReferencedByCase::CASE_VERTEX_TESS_GEO_FRAGMENT));
5728
5729 // all partial pipelines
5730 targetGroup->addChild(new ProgramInputOutputReferencedByCase(context, "referenced_by_separable_vertex", "", storage, ProgramInputOutputReferencedByCase::CASE_SEPARABLE_VERTEX));
5731 targetGroup->addChild(new ProgramInputOutputReferencedByCase(context, "referenced_by_separable_fragment", "", storage, ProgramInputOutputReferencedByCase::CASE_SEPARABLE_FRAGMENT));
5732 targetGroup->addChild(new ProgramInputOutputReferencedByCase(context, "referenced_by_separable_geometry", "", storage, ProgramInputOutputReferencedByCase::CASE_SEPARABLE_GEOMETRY));
5733 targetGroup->addChild(new ProgramInputOutputReferencedByCase(context, "referenced_by_separable_tess_eval", "", storage, ProgramInputOutputReferencedByCase::CASE_SEPARABLE_TESS_EVAL));
5734 targetGroup->addChild(new ProgramInputOutputReferencedByCase(context, "referenced_by_separable_tess_ctrl", "", storage, ProgramInputOutputReferencedByCase::CASE_SEPARABLE_TESS_CTRL));
5735
5736 // patch
5737 if (storage == glu::STORAGE_IN)
5738 targetGroup->addChild(new ProgramInputOutputReferencedByCase(context, "referenced_by_separable_tess_eval_patch_in", "", glu::STORAGE_PATCH_IN, ProgramInputOutputReferencedByCase::CASE_SEPARABLE_TESS_EVAL));
5739 else if (storage == glu::STORAGE_OUT)
5740 targetGroup->addChild(new ProgramInputOutputReferencedByCase(context, "referenced_by_separable_tess_ctrl_patch_out", "", glu::STORAGE_PATCH_OUT, ProgramInputOutputReferencedByCase::CASE_SEPARABLE_TESS_CTRL));
5741 else
5742 DE_ASSERT(false);
5743 }
5744
5745 template <ProgramInterface interface>
generateProgramInputOutputTypeBasicTypeCases(Context & context,const ResourceDefinition::Node::SharedPtr & parentStructure,tcu::TestCaseGroup * targetGroup,bool allowMatrixCases,int expandLevel)5746 static void generateProgramInputOutputTypeBasicTypeCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup, bool allowMatrixCases, int expandLevel)
5747 {
5748 static const struct
5749 {
5750 glu::DataType type;
5751 bool isMatrix;
5752 int level;
5753 } variableTypes[] =
5754 {
5755 { glu::TYPE_FLOAT, false, 0 },
5756 { glu::TYPE_INT, false, 1 },
5757 { glu::TYPE_UINT, false, 1 },
5758 { glu::TYPE_FLOAT_VEC2, false, 2 },
5759 { glu::TYPE_FLOAT_VEC3, false, 1 },
5760 { glu::TYPE_FLOAT_VEC4, false, 2 },
5761 { glu::TYPE_INT_VEC2, false, 0 },
5762 { glu::TYPE_INT_VEC3, false, 2 },
5763 { glu::TYPE_INT_VEC4, false, 2 },
5764 { glu::TYPE_UINT_VEC2, false, 2 },
5765 { glu::TYPE_UINT_VEC3, false, 2 },
5766 { glu::TYPE_UINT_VEC4, false, 0 },
5767 { glu::TYPE_FLOAT_MAT2, true, 2 },
5768 { glu::TYPE_FLOAT_MAT2X3, true, 2 },
5769 { glu::TYPE_FLOAT_MAT2X4, true, 2 },
5770 { glu::TYPE_FLOAT_MAT3X2, true, 0 },
5771 { glu::TYPE_FLOAT_MAT3, true, 2 },
5772 { glu::TYPE_FLOAT_MAT3X4, true, 2 },
5773 { glu::TYPE_FLOAT_MAT4X2, true, 2 },
5774 { glu::TYPE_FLOAT_MAT4X3, true, 2 },
5775 { glu::TYPE_FLOAT_MAT4, true, 2 },
5776 };
5777
5778 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(variableTypes); ++ndx)
5779 {
5780 if (!allowMatrixCases && variableTypes[ndx].isMatrix)
5781 continue;
5782
5783 if (variableTypes[ndx].level <= expandLevel)
5784 {
5785 const ResourceDefinition::Node::SharedPtr variable(new ResourceDefinition::Variable(parentStructure, variableTypes[ndx].type));
5786 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(interface, PROGRAMRESOURCEPROP_TYPE)));
5787 }
5788 }
5789 }
5790
generateProgramInputTypeBlockContents(Context & context,const ResourceDefinition::Node::SharedPtr & parentStructure,tcu::TestCaseGroup * targetGroup,deUint32 presentShadersMask)5791 static void generateProgramInputTypeBlockContents (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup, deUint32 presentShadersMask)
5792 {
5793 const bool inDefaultBlock = parentStructure->getType() == ResourceDefinition::Node::TYPE_DEFAULT_BLOCK;
5794 const ResourceDefinition::Node::SharedPtr input = (inDefaultBlock)
5795 ? (ResourceDefinition::Node::SharedPtr(new ResourceDefinition::StorageQualifier(parentStructure, glu::STORAGE_IN)))
5796 : (parentStructure);
5797 const glu::ShaderType firstStage = getShaderMaskFirstStage(presentShadersMask);
5798 const int interfaceBlockExpansionReducement = (!inDefaultBlock) ? (1) : (0); // lesser expansions on block members to keep test counts reasonable
5799
5800 if (firstStage == glu::SHADERTYPE_VERTEX)
5801 {
5802 // Only basic types (and no booleans)
5803 generateProgramInputOutputTypeBasicTypeCases<PROGRAMINTERFACE_PROGRAM_INPUT>(context, input, targetGroup, true, 2 - interfaceBlockExpansionReducement);
5804 }
5805 else if (firstStage == glu::SHADERTYPE_FRAGMENT || !inDefaultBlock)
5806 {
5807 const ResourceDefinition::Node::SharedPtr flatShading(new ResourceDefinition::InterpolationQualifier(input, glu::INTERPOLATION_FLAT));
5808
5809 // Only basic types, arrays of basic types, struct of basic types (and no booleans)
5810 {
5811 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "basic_type", "Basic types");
5812 targetGroup->addChild(blockGroup);
5813 generateProgramInputOutputTypeBasicTypeCases<PROGRAMINTERFACE_PROGRAM_INPUT>(context, flatShading, blockGroup, true, 2 - interfaceBlockExpansionReducement);
5814 }
5815 {
5816 const ResourceDefinition::Node::SharedPtr arrayElement (new ResourceDefinition::ArrayElement(flatShading));
5817 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "array", "Array types");
5818
5819 targetGroup->addChild(blockGroup);
5820 generateProgramInputOutputTypeBasicTypeCases<PROGRAMINTERFACE_PROGRAM_INPUT>(context, arrayElement, blockGroup, true, 2 - interfaceBlockExpansionReducement);
5821 }
5822 {
5823 const ResourceDefinition::Node::SharedPtr structMember (new ResourceDefinition::StructMember(flatShading));
5824 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "struct", "Struct types");
5825
5826 targetGroup->addChild(blockGroup);
5827 generateProgramInputOutputTypeBasicTypeCases<PROGRAMINTERFACE_PROGRAM_INPUT>(context, structMember, blockGroup, true, 2 - interfaceBlockExpansionReducement);
5828 }
5829 }
5830 else if (firstStage == glu::SHADERTYPE_TESSELLATION_CONTROL ||
5831 firstStage == glu::SHADERTYPE_GEOMETRY)
5832 {
5833 // arrayed interface
5834
5835 // Only basic types (and no booleans)
5836 const ResourceDefinition::Node::SharedPtr arrayElement(new ResourceDefinition::ArrayElement(input, ResourceDefinition::ArrayElement::UNSIZED_ARRAY));
5837 generateProgramInputOutputTypeBasicTypeCases<PROGRAMINTERFACE_PROGRAM_INPUT>(context, arrayElement, targetGroup, true, 2);
5838 }
5839 else if (firstStage == glu::SHADERTYPE_TESSELLATION_EVALUATION)
5840 {
5841 // arrayed interface
5842 const ResourceDefinition::Node::SharedPtr patchInput(new ResourceDefinition::StorageQualifier(parentStructure, glu::STORAGE_PATCH_IN));
5843
5844 // .var
5845 {
5846 const ResourceDefinition::Node::SharedPtr arrayElem (new ResourceDefinition::ArrayElement(input, ResourceDefinition::ArrayElement::UNSIZED_ARRAY));
5847 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "basic_type", "Basic types");
5848
5849 targetGroup->addChild(blockGroup);
5850 generateProgramInputOutputTypeBasicTypeCases<PROGRAMINTERFACE_PROGRAM_INPUT>(context, arrayElem, blockGroup, true, 2);
5851 }
5852 // extension forbids use arrays of structs
5853 // extension forbids use arrays of arrays
5854
5855 // .patch_var
5856 {
5857 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "patch_var", "Basic types, per-patch");
5858
5859 targetGroup->addChild(blockGroup);
5860 generateProgramInputOutputTypeBasicTypeCases<PROGRAMINTERFACE_PROGRAM_INPUT>(context, patchInput, blockGroup, true, 1);
5861 }
5862 // .patch_var_struct
5863 {
5864 const ResourceDefinition::Node::SharedPtr structMbr (new ResourceDefinition::StructMember(patchInput));
5865 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "patch_var_struct", "Struct types, per-patch");
5866
5867 targetGroup->addChild(blockGroup);
5868 generateProgramInputOutputTypeBasicTypeCases<PROGRAMINTERFACE_PROGRAM_INPUT>(context, structMbr, blockGroup, true, 1);
5869 }
5870 // .patch_var_array
5871 {
5872 const ResourceDefinition::Node::SharedPtr arrayElem (new ResourceDefinition::ArrayElement(patchInput));
5873 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "patch_var_array", "Array types, per-patch");
5874
5875 targetGroup->addChild(blockGroup);
5876 generateProgramInputOutputTypeBasicTypeCases<PROGRAMINTERFACE_PROGRAM_INPUT>(context, arrayElem, blockGroup, true, 1);
5877 }
5878 }
5879 else if (firstStage == glu::SHADERTYPE_COMPUTE)
5880 {
5881 // nada
5882 }
5883 else
5884 DE_ASSERT(false);
5885 }
5886
generateProgramOutputTypeBlockContents(Context & context,const ResourceDefinition::Node::SharedPtr & parentStructure,tcu::TestCaseGroup * targetGroup,deUint32 presentShadersMask)5887 static void generateProgramOutputTypeBlockContents (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup, deUint32 presentShadersMask)
5888 {
5889 const bool inDefaultBlock = parentStructure->getType() == ResourceDefinition::Node::TYPE_DEFAULT_BLOCK;
5890 const ResourceDefinition::Node::SharedPtr output = (inDefaultBlock)
5891 ? (ResourceDefinition::Node::SharedPtr(new ResourceDefinition::StorageQualifier(parentStructure, glu::STORAGE_OUT)))
5892 : (parentStructure);
5893 const glu::ShaderType lastStage = getShaderMaskLastStage(presentShadersMask);
5894 const int interfaceBlockExpansionReducement = (!inDefaultBlock) ? (1) : (0); // lesser expansions on block members to keep test counts reasonable
5895
5896 if (lastStage == glu::SHADERTYPE_VERTEX ||
5897 lastStage == glu::SHADERTYPE_GEOMETRY ||
5898 lastStage == glu::SHADERTYPE_TESSELLATION_EVALUATION ||
5899 !inDefaultBlock)
5900 {
5901 const ResourceDefinition::Node::SharedPtr flatShading(new ResourceDefinition::InterpolationQualifier(output, glu::INTERPOLATION_FLAT));
5902
5903 // Only basic types, arrays of basic types, struct of basic types (and no booleans)
5904 {
5905 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "basic_type", "Basic types");
5906 targetGroup->addChild(blockGroup);
5907 generateProgramInputOutputTypeBasicTypeCases<PROGRAMINTERFACE_PROGRAM_OUTPUT>(context, flatShading, blockGroup, true, 2 - interfaceBlockExpansionReducement);
5908 }
5909 {
5910 const ResourceDefinition::Node::SharedPtr arrayElement (new ResourceDefinition::ArrayElement(flatShading));
5911 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "array", "Array types");
5912 const int typeExpansionReducement = (lastStage != glu::SHADERTYPE_VERTEX) ? (1) : (0); // lesser expansions on other stages
5913 const int expansionLevel = 2 - interfaceBlockExpansionReducement - typeExpansionReducement;
5914
5915 targetGroup->addChild(blockGroup);
5916 generateProgramInputOutputTypeBasicTypeCases<PROGRAMINTERFACE_PROGRAM_OUTPUT>(context, arrayElement, blockGroup, true, expansionLevel);
5917 }
5918 {
5919 const ResourceDefinition::Node::SharedPtr structMember (new ResourceDefinition::StructMember(flatShading));
5920 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "struct", "Struct types");
5921 const int typeExpansionReducement = (lastStage != glu::SHADERTYPE_VERTEX) ? (1) : (0); // lesser expansions on other stages
5922 const int expansionLevel = 2 - interfaceBlockExpansionReducement - typeExpansionReducement;
5923
5924 targetGroup->addChild(blockGroup);
5925 generateProgramInputOutputTypeBasicTypeCases<PROGRAMINTERFACE_PROGRAM_OUTPUT>(context, structMember, blockGroup, true, expansionLevel);
5926 }
5927 }
5928 else if (lastStage == glu::SHADERTYPE_FRAGMENT)
5929 {
5930 // only basic type and basic type array (and no booleans or matrices)
5931 {
5932 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "basic_type", "Basic types");
5933 targetGroup->addChild(blockGroup);
5934 generateProgramInputOutputTypeBasicTypeCases<PROGRAMINTERFACE_PROGRAM_OUTPUT>(context, output, blockGroup, false, 2);
5935 }
5936 {
5937 const ResourceDefinition::Node::SharedPtr arrayElement (new ResourceDefinition::ArrayElement(output));
5938 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "array", "Array types");
5939
5940 targetGroup->addChild(blockGroup);
5941 generateProgramInputOutputTypeBasicTypeCases<PROGRAMINTERFACE_PROGRAM_OUTPUT>(context, arrayElement, blockGroup, false, 2);
5942 }
5943 }
5944 else if (lastStage == glu::SHADERTYPE_TESSELLATION_CONTROL)
5945 {
5946 // arrayed interface
5947 const ResourceDefinition::Node::SharedPtr patchOutput(new ResourceDefinition::StorageQualifier(parentStructure, glu::STORAGE_PATCH_OUT));
5948
5949 // .var
5950 {
5951 const ResourceDefinition::Node::SharedPtr arrayElem (new ResourceDefinition::ArrayElement(output, ResourceDefinition::ArrayElement::UNSIZED_ARRAY));
5952 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "basic_type", "Basic types");
5953
5954 targetGroup->addChild(blockGroup);
5955 generateProgramInputOutputTypeBasicTypeCases<PROGRAMINTERFACE_PROGRAM_OUTPUT>(context, arrayElem, blockGroup, true, 2);
5956 }
5957 // extension forbids use arrays of structs
5958 // extension forbids use arrays of arrays
5959
5960 // .patch_var
5961 {
5962 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "patch_var", "Basic types, per-patch");
5963
5964 targetGroup->addChild(blockGroup);
5965 generateProgramInputOutputTypeBasicTypeCases<PROGRAMINTERFACE_PROGRAM_OUTPUT>(context, patchOutput, blockGroup, true, 1);
5966 }
5967 // .patch_var_struct
5968 {
5969 const ResourceDefinition::Node::SharedPtr structMbr (new ResourceDefinition::StructMember(patchOutput));
5970 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "patch_var_struct", "Struct types, per-patch");
5971
5972 targetGroup->addChild(blockGroup);
5973 generateProgramInputOutputTypeBasicTypeCases<PROGRAMINTERFACE_PROGRAM_OUTPUT>(context, structMbr, blockGroup, true, 1);
5974 }
5975 // .patch_var_array
5976 {
5977 const ResourceDefinition::Node::SharedPtr arrayElem (new ResourceDefinition::ArrayElement(patchOutput));
5978 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "patch_var_array", "Array types, per-patch");
5979
5980 targetGroup->addChild(blockGroup);
5981 generateProgramInputOutputTypeBasicTypeCases<PROGRAMINTERFACE_PROGRAM_OUTPUT>(context, arrayElem, blockGroup, true, 1);
5982 }
5983 }
5984 else if (lastStage == glu::SHADERTYPE_COMPUTE)
5985 {
5986 // nada
5987 }
5988 else
5989 DE_ASSERT(false);
5990 }
5991
5992 class ProgramInputTestGroup : public TestCaseGroup
5993 {
5994 public:
5995 ProgramInputTestGroup (Context& context);
5996 void init (void);
5997 };
5998
ProgramInputTestGroup(Context & context)5999 ProgramInputTestGroup::ProgramInputTestGroup (Context& context)
6000 : TestCaseGroup(context, "program_input", "Program input")
6001 {
6002 }
6003
init(void)6004 void ProgramInputTestGroup::init (void)
6005 {
6006 const glu::GLSLVersion glslVersion = glu::getContextTypeGLSLVersion(m_context.getRenderContext().getType());
6007
6008 // .resource_list
6009 {
6010 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "resource_list", "Resource list");
6011 addChild(blockGroup);
6012 generateProgramInputOutputShaderCaseBlocks(m_context, blockGroup, glslVersion, true, true, generateProgramInputResourceListBlockContents);
6013 }
6014
6015 // .array_size
6016 {
6017 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "array_size", "Array size");
6018 addChild(blockGroup);
6019 generateProgramInputOutputShaderCaseBlocks(m_context, blockGroup, glslVersion, false, true, generateProgramInputBasicBlockContents<PROGRAMRESOURCEPROP_ARRAY_SIZE>);
6020 }
6021
6022 // .location
6023 {
6024 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "location", "Location");
6025 addChild(blockGroup);
6026 generateProgramInputOutputShaderCaseBlocks(m_context, blockGroup, glslVersion, false, true, generateProgramInputLocationBlockContents);
6027 }
6028
6029 // .name_length
6030 {
6031 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "name_length", "Name length");
6032 addChild(blockGroup);
6033 generateProgramInputOutputShaderCaseBlocks(m_context, blockGroup, glslVersion, false, true, generateProgramInputBasicBlockContents<PROGRAMRESOURCEPROP_NAME_LENGTH>);
6034 }
6035
6036 // .referenced_by
6037 {
6038 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "referenced_by", "Reference by shader");
6039 addChild(blockGroup);
6040 generateProgramInputOutputReferencedByCases(m_context, blockGroup, glu::STORAGE_IN);
6041 }
6042
6043 // .type
6044 {
6045 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "type", "Type");
6046 addChild(blockGroup);
6047 generateProgramInputOutputShaderCaseBlocks(m_context, blockGroup, glslVersion, false, true, generateProgramInputTypeBlockContents);
6048 }
6049
6050 // .is_per_patch
6051 {
6052 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "is_per_patch", "Is per patch");
6053 addChild(blockGroup);
6054 generateProgramInputOutputShaderCaseBlocks(m_context, blockGroup, glslVersion, false, true, generateProgramInputBasicBlockContents<PROGRAMRESOURCEPROP_IS_PER_PATCH>);
6055 }
6056 }
6057
6058 class ProgramOutputTestGroup : public TestCaseGroup
6059 {
6060 public:
6061 ProgramOutputTestGroup (Context& context);
6062 void init (void);
6063 };
6064
ProgramOutputTestGroup(Context & context)6065 ProgramOutputTestGroup::ProgramOutputTestGroup (Context& context)
6066 : TestCaseGroup(context, "program_output", "Program output")
6067 {
6068 }
6069
init(void)6070 void ProgramOutputTestGroup::init (void)
6071 {
6072 const glu::GLSLVersion glslVersion = glu::getContextTypeGLSLVersion(m_context.getRenderContext().getType());
6073
6074 // .resource_list
6075 {
6076 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "resource_list", "Resource list");
6077 addChild(blockGroup);
6078 generateProgramInputOutputShaderCaseBlocks(m_context, blockGroup, glslVersion, true, false, generateProgramOutputResourceListBlockContents);
6079 }
6080
6081 // .array_size
6082 {
6083 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "array_size", "Array size");
6084 addChild(blockGroup);
6085 generateProgramInputOutputShaderCaseBlocks(m_context, blockGroup, glslVersion, false, false, generateProgramOutputBasicBlockContents<PROGRAMRESOURCEPROP_ARRAY_SIZE>);
6086 }
6087
6088 // .location
6089 {
6090 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "location", "Location");
6091 addChild(blockGroup);
6092 generateProgramInputOutputShaderCaseBlocks(m_context, blockGroup, glslVersion, false, false, generateProgramOutputLocationBlockContents);
6093 }
6094
6095 // .name_length
6096 {
6097 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "name_length", "Name length");
6098 addChild(blockGroup);
6099 generateProgramInputOutputShaderCaseBlocks(m_context, blockGroup, glslVersion, false, false, generateProgramOutputBasicBlockContents<PROGRAMRESOURCEPROP_NAME_LENGTH>);
6100 }
6101
6102 // .referenced_by
6103 {
6104 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "referenced_by", "Reference by shader");
6105 addChild(blockGroup);
6106 generateProgramInputOutputReferencedByCases(m_context, blockGroup, glu::STORAGE_OUT);
6107 }
6108
6109 // .type
6110 {
6111 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "type", "Type");
6112 addChild(blockGroup);
6113 generateProgramInputOutputShaderCaseBlocks(m_context, blockGroup, glslVersion, false, false, generateProgramOutputTypeBlockContents);
6114 }
6115
6116 // .is_per_patch
6117 {
6118 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(m_testCtx, "is_per_patch", "Is per patch");
6119 addChild(blockGroup);
6120 generateProgramInputOutputShaderCaseBlocks(m_context, blockGroup, glslVersion, false, false, generateProgramOutputBasicBlockContents<PROGRAMRESOURCEPROP_IS_PER_PATCH>);
6121 }
6122 }
6123
generateTransformFeedbackShaderCaseBlocks(Context & context,tcu::TestCaseGroup * targetGroup,glu::GLSLVersion glslVersion,void (* blockContentGenerator)(Context &,const ResourceDefinition::Node::SharedPtr &,tcu::TestCaseGroup *,bool))6124 static void generateTransformFeedbackShaderCaseBlocks (Context& context, tcu::TestCaseGroup* targetGroup, glu::GLSLVersion glslVersion, void (*blockContentGenerator)(Context&, const ResourceDefinition::Node::SharedPtr&, tcu::TestCaseGroup*, bool))
6125 {
6126 static const struct
6127 {
6128 const char* name;
6129 deUint32 stageBits;
6130 deUint32 lastStageBit;
6131 bool reducedSet;
6132 } pipelines[] =
6133 {
6134 {
6135 "vertex_fragment",
6136 (1 << glu::SHADERTYPE_VERTEX) | (1 << glu::SHADERTYPE_FRAGMENT),
6137 (1 << glu::SHADERTYPE_VERTEX),
6138 false
6139 },
6140 {
6141 "vertex_tess_fragment",
6142 (1 << glu::SHADERTYPE_VERTEX) | (1 << glu::SHADERTYPE_FRAGMENT) | (1 << glu::SHADERTYPE_TESSELLATION_CONTROL) | (1 << glu::SHADERTYPE_TESSELLATION_EVALUATION),
6143 (1 << glu::SHADERTYPE_TESSELLATION_EVALUATION),
6144 true
6145 },
6146 {
6147 "vertex_geo_fragment",
6148 (1 << glu::SHADERTYPE_VERTEX) | (1 << glu::SHADERTYPE_FRAGMENT) | (1 << glu::SHADERTYPE_GEOMETRY),
6149 (1 << glu::SHADERTYPE_GEOMETRY),
6150 true
6151 },
6152 {
6153 "vertex_tess_geo_fragment",
6154 (1 << glu::SHADERTYPE_VERTEX) | (1 << glu::SHADERTYPE_FRAGMENT) | (1 << glu::SHADERTYPE_TESSELLATION_CONTROL) | (1 << glu::SHADERTYPE_TESSELLATION_EVALUATION) | (1 << glu::SHADERTYPE_GEOMETRY),
6155 (1 << glu::SHADERTYPE_GEOMETRY),
6156 true
6157 },
6158 };
6159 static const struct
6160 {
6161 const char* name;
6162 glu::ShaderType stage;
6163 bool reducedSet;
6164 } singleStageCases[] =
6165 {
6166 { "separable_vertex", glu::SHADERTYPE_VERTEX, false },
6167 { "separable_tess_eval", glu::SHADERTYPE_TESSELLATION_EVALUATION, true },
6168 { "separable_geometry", glu::SHADERTYPE_GEOMETRY, true },
6169 };
6170
6171 // monolithic pipeline
6172 for (int pipelineNdx = 0; pipelineNdx < DE_LENGTH_OF_ARRAY(pipelines); ++pipelineNdx)
6173 {
6174 TestCaseGroup* const blockGroup = new TestCaseGroup(context, pipelines[pipelineNdx].name, "");
6175 const ResourceDefinition::Node::SharedPtr program (new ResourceDefinition::Program());
6176 const ResourceDefinition::Node::SharedPtr shaderSet (new ResourceDefinition::ShaderSet(program,
6177 glslVersion,
6178 pipelines[pipelineNdx].stageBits,
6179 pipelines[pipelineNdx].lastStageBit));
6180
6181 targetGroup->addChild(blockGroup);
6182 blockContentGenerator(context, shaderSet, blockGroup, pipelines[pipelineNdx].reducedSet);
6183 }
6184
6185 // separable pipeline
6186 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(singleStageCases); ++ndx)
6187 {
6188 TestCaseGroup* const blockGroup = new TestCaseGroup(context, singleStageCases[ndx].name, "");
6189 const ResourceDefinition::Node::SharedPtr program (new ResourceDefinition::Program(true));
6190 const ResourceDefinition::Node::SharedPtr shader (new ResourceDefinition::Shader(program, singleStageCases[ndx].stage, glslVersion));
6191
6192 targetGroup->addChild(blockGroup);
6193 blockContentGenerator(context, shader, blockGroup, singleStageCases[ndx].reducedSet);
6194 }
6195 }
6196
generateTransformFeedbackResourceListBlockContents(Context & context,const ResourceDefinition::Node::SharedPtr & parentStructure,tcu::TestCaseGroup * targetGroup,bool reducedSet)6197 static void generateTransformFeedbackResourceListBlockContents (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup, bool reducedSet)
6198 {
6199 const ResourceDefinition::Node::SharedPtr defaultBlock (new ResourceDefinition::DefaultBlock(parentStructure));
6200 const ResourceDefinition::Node::SharedPtr output (new ResourceDefinition::StorageQualifier(defaultBlock, glu::STORAGE_OUT));
6201
6202 DE_UNREF(reducedSet);
6203
6204 // .builtin_gl_position
6205 {
6206 const ResourceDefinition::Node::SharedPtr xfbTarget(new ResourceDefinition::TransformFeedbackTarget(defaultBlock, "gl_Position"));
6207 targetGroup->addChild(new FeedbackResourceListTestCase(context, xfbTarget, "builtin_gl_position"));
6208 }
6209 // .default_block_basic_type
6210 {
6211 const ResourceDefinition::Node::SharedPtr xfbTarget (new ResourceDefinition::TransformFeedbackTarget(output));
6212 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(xfbTarget, glu::TYPE_FLOAT_VEC4));
6213 targetGroup->addChild(new FeedbackResourceListTestCase(context, variable, "default_block_basic_type"));
6214 }
6215 // .default_block_struct_member
6216 {
6217 const ResourceDefinition::Node::SharedPtr structMbr (new ResourceDefinition::StructMember(output));
6218 const ResourceDefinition::Node::SharedPtr xfbTarget (new ResourceDefinition::TransformFeedbackTarget(structMbr));
6219 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(xfbTarget, glu::TYPE_FLOAT_VEC4));
6220 targetGroup->addChild(new FeedbackResourceListTestCase(context, variable, "default_block_struct_member"));
6221 }
6222 // .default_block_array
6223 {
6224 const ResourceDefinition::Node::SharedPtr xfbTarget (new ResourceDefinition::TransformFeedbackTarget(output));
6225 const ResourceDefinition::Node::SharedPtr arrayElem (new ResourceDefinition::ArrayElement(xfbTarget));
6226 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(arrayElem, glu::TYPE_FLOAT_VEC4));
6227 targetGroup->addChild(new FeedbackResourceListTestCase(context, variable, "default_block_array"));
6228 }
6229 // .default_block_array_element
6230 {
6231 const ResourceDefinition::Node::SharedPtr arrayElem (new ResourceDefinition::ArrayElement(output));
6232 const ResourceDefinition::Node::SharedPtr xfbTarget (new ResourceDefinition::TransformFeedbackTarget(arrayElem));
6233 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(xfbTarget, glu::TYPE_FLOAT_VEC4));
6234 targetGroup->addChild(new FeedbackResourceListTestCase(context, variable, "default_block_array_element"));
6235 }
6236 }
6237
6238 template <ProgramResourcePropFlags TargetProp>
generateTransformFeedbackVariableBlockContents(Context & context,const ResourceDefinition::Node::SharedPtr & parentStructure,tcu::TestCaseGroup * targetGroup,bool reducedSet)6239 static void generateTransformFeedbackVariableBlockContents (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup, bool reducedSet)
6240 {
6241 const ResourceDefinition::Node::SharedPtr defaultBlock (new ResourceDefinition::DefaultBlock(parentStructure));
6242 const ResourceDefinition::Node::SharedPtr output (new ResourceDefinition::StorageQualifier(defaultBlock, glu::STORAGE_OUT));
6243
6244 DE_UNREF(reducedSet);
6245
6246 // .builtin_gl_position
6247 {
6248 const ResourceDefinition::Node::SharedPtr xfbTarget(new ResourceDefinition::TransformFeedbackTarget(defaultBlock, "gl_Position"));
6249 targetGroup->addChild(new ResourceTestCase(context, xfbTarget, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_TRANSFORM_FEEDBACK_VARYING, TargetProp), "builtin_gl_position"));
6250 }
6251 // .default_block_basic_type
6252 {
6253 const ResourceDefinition::Node::SharedPtr xfbTarget (new ResourceDefinition::TransformFeedbackTarget(output));
6254 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(xfbTarget, glu::TYPE_FLOAT_VEC4));
6255 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_TRANSFORM_FEEDBACK_VARYING, TargetProp), "default_block_basic_type"));
6256 }
6257 // .default_block_struct_member
6258 {
6259 const ResourceDefinition::Node::SharedPtr structMbr (new ResourceDefinition::StructMember(output));
6260 const ResourceDefinition::Node::SharedPtr xfbTarget (new ResourceDefinition::TransformFeedbackTarget(structMbr));
6261 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(xfbTarget, glu::TYPE_FLOAT_VEC4));
6262 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_TRANSFORM_FEEDBACK_VARYING, TargetProp), "default_block_struct_member"));
6263 }
6264 // .default_block_array
6265 {
6266 const ResourceDefinition::Node::SharedPtr xfbTarget (new ResourceDefinition::TransformFeedbackTarget(output));
6267 const ResourceDefinition::Node::SharedPtr arrayElem (new ResourceDefinition::ArrayElement(xfbTarget));
6268 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(arrayElem, glu::TYPE_FLOAT_VEC4));
6269 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_TRANSFORM_FEEDBACK_VARYING, TargetProp), "default_block_array"));
6270 }
6271 // .default_block_array_element
6272 {
6273 const ResourceDefinition::Node::SharedPtr arrayElem (new ResourceDefinition::ArrayElement(output));
6274 const ResourceDefinition::Node::SharedPtr xfbTarget (new ResourceDefinition::TransformFeedbackTarget(arrayElem));
6275 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(xfbTarget, glu::TYPE_FLOAT_VEC4));
6276 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_TRANSFORM_FEEDBACK_VARYING, TargetProp), "default_block_array_element"));
6277 }
6278 }
6279
generateTransformFeedbackVariableBasicTypeCases(Context & context,const ResourceDefinition::Node::SharedPtr & parentStructure,tcu::TestCaseGroup * targetGroup,bool reducedSet)6280 static void generateTransformFeedbackVariableBasicTypeCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup, bool reducedSet)
6281 {
6282 static const struct
6283 {
6284 glu::DataType type;
6285 bool important;
6286 } variableTypes[] =
6287 {
6288 { glu::TYPE_FLOAT, true },
6289 { glu::TYPE_INT, true },
6290 { glu::TYPE_UINT, true },
6291
6292 { glu::TYPE_FLOAT_VEC2, false },
6293 { glu::TYPE_FLOAT_VEC3, true },
6294 { glu::TYPE_FLOAT_VEC4, false },
6295
6296 { glu::TYPE_INT_VEC2, false },
6297 { glu::TYPE_INT_VEC3, true },
6298 { glu::TYPE_INT_VEC4, false },
6299
6300 { glu::TYPE_UINT_VEC2, true },
6301 { glu::TYPE_UINT_VEC3, false },
6302 { glu::TYPE_UINT_VEC4, false },
6303
6304 { glu::TYPE_FLOAT_MAT2, false },
6305 { glu::TYPE_FLOAT_MAT2X3, false },
6306 { glu::TYPE_FLOAT_MAT2X4, false },
6307 { glu::TYPE_FLOAT_MAT3X2, false },
6308 { glu::TYPE_FLOAT_MAT3, false },
6309 { glu::TYPE_FLOAT_MAT3X4, true },
6310 { glu::TYPE_FLOAT_MAT4X2, false },
6311 { glu::TYPE_FLOAT_MAT4X3, false },
6312 { glu::TYPE_FLOAT_MAT4, false },
6313 };
6314
6315 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(variableTypes); ++ndx)
6316 {
6317 if (variableTypes[ndx].important || !reducedSet)
6318 {
6319 const ResourceDefinition::Node::SharedPtr variable(new ResourceDefinition::Variable(parentStructure, variableTypes[ndx].type));
6320 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_TRANSFORM_FEEDBACK_VARYING, PROGRAMRESOURCEPROP_TYPE)));
6321 }
6322 }
6323 }
6324
generateTransformFeedbackVariableTypeBlockContents(Context & context,const ResourceDefinition::Node::SharedPtr & parentStructure,tcu::TestCaseGroup * targetGroup,bool reducedSet)6325 static void generateTransformFeedbackVariableTypeBlockContents (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup, bool reducedSet)
6326 {
6327 const ResourceDefinition::Node::SharedPtr defaultBlock (new ResourceDefinition::DefaultBlock(parentStructure));
6328 const ResourceDefinition::Node::SharedPtr output (new ResourceDefinition::StorageQualifier(defaultBlock, glu::STORAGE_OUT));
6329 const ResourceDefinition::Node::SharedPtr flatShading (new ResourceDefinition::InterpolationQualifier(output, glu::INTERPOLATION_FLAT));
6330
6331 // Only builtins, basic types, arrays of basic types, struct of basic types (and no booleans)
6332 {
6333 const ResourceDefinition::Node::SharedPtr xfbTarget (new ResourceDefinition::TransformFeedbackTarget(defaultBlock, "gl_Position"));
6334 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "builtin", "Built-in outputs");
6335
6336 targetGroup->addChild(blockGroup);
6337 blockGroup->addChild(new ResourceTestCase(context, xfbTarget, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_TRANSFORM_FEEDBACK_VARYING, PROGRAMRESOURCEPROP_TYPE), "gl_position"));
6338 }
6339 {
6340 const ResourceDefinition::Node::SharedPtr xfbTarget (new ResourceDefinition::TransformFeedbackTarget(flatShading));
6341 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "basic_type", "Basic types");
6342
6343 targetGroup->addChild(blockGroup);
6344 generateTransformFeedbackVariableBasicTypeCases(context, xfbTarget, blockGroup, reducedSet);
6345 }
6346 {
6347 const ResourceDefinition::Node::SharedPtr arrayElement (new ResourceDefinition::ArrayElement(flatShading));
6348 const ResourceDefinition::Node::SharedPtr xfbTarget (new ResourceDefinition::TransformFeedbackTarget(arrayElement));
6349 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "array", "Array types");
6350
6351 targetGroup->addChild(blockGroup);
6352 generateTransformFeedbackVariableBasicTypeCases(context, xfbTarget, blockGroup, reducedSet);
6353 }
6354 {
6355 const ResourceDefinition::Node::SharedPtr xfbTarget (new ResourceDefinition::TransformFeedbackTarget(flatShading));
6356 const ResourceDefinition::Node::SharedPtr arrayElement (new ResourceDefinition::ArrayElement(xfbTarget));
6357 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "whole_array", "Whole array");
6358
6359 targetGroup->addChild(blockGroup);
6360 generateTransformFeedbackVariableBasicTypeCases(context, arrayElement, blockGroup, reducedSet);
6361 }
6362 {
6363 const ResourceDefinition::Node::SharedPtr structMember (new ResourceDefinition::StructMember(flatShading));
6364 const ResourceDefinition::Node::SharedPtr xfbTarget (new ResourceDefinition::TransformFeedbackTarget(structMember));
6365 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "struct", "Struct types");
6366
6367 targetGroup->addChild(blockGroup);
6368 generateTransformFeedbackVariableBasicTypeCases(context, xfbTarget, blockGroup, reducedSet);
6369 }
6370 }
6371
6372 class TransformFeedbackVaryingTestGroup : public TestCaseGroup
6373 {
6374 public:
6375 TransformFeedbackVaryingTestGroup (Context& context);
6376 void init (void);
6377 };
6378
TransformFeedbackVaryingTestGroup(Context & context)6379 TransformFeedbackVaryingTestGroup::TransformFeedbackVaryingTestGroup (Context& context)
6380 : TestCaseGroup(context, "transform_feedback_varying", "Transform feedback varyings")
6381 {
6382 }
6383
init(void)6384 void TransformFeedbackVaryingTestGroup::init (void)
6385 {
6386 const glu::GLSLVersion glslVersion = glu::getContextTypeGLSLVersion(m_context.getRenderContext().getType());
6387
6388 // .resource_list
6389 {
6390 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(m_context, "resource_list", "Resource list");
6391 addChild(blockGroup);
6392 generateTransformFeedbackShaderCaseBlocks(m_context, blockGroup, glslVersion, generateTransformFeedbackResourceListBlockContents);
6393 }
6394
6395 // .array_size
6396 {
6397 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(m_context, "array_size", "Array size");
6398 addChild(blockGroup);
6399 generateTransformFeedbackShaderCaseBlocks(m_context, blockGroup, glslVersion, generateTransformFeedbackVariableBlockContents<PROGRAMRESOURCEPROP_ARRAY_SIZE>);
6400 }
6401
6402 // .name_length
6403 {
6404 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(m_context, "name_length", "Name length");
6405 addChild(blockGroup);
6406 generateTransformFeedbackShaderCaseBlocks(m_context, blockGroup, glslVersion, generateTransformFeedbackVariableBlockContents<PROGRAMRESOURCEPROP_NAME_LENGTH>);
6407 }
6408
6409 // .type
6410 {
6411 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(m_context, "type", "Type");
6412 addChild(blockGroup);
6413 generateTransformFeedbackShaderCaseBlocks(m_context, blockGroup, glslVersion, generateTransformFeedbackVariableTypeBlockContents);
6414 }
6415 }
6416
generateBufferVariableBufferCaseBlocks(Context & context,tcu::TestCaseGroup * targetGroup,glu::GLSLVersion glslVersion,void (* blockContentGenerator)(Context &,const ResourceDefinition::Node::SharedPtr &,tcu::TestCaseGroup *))6417 static void generateBufferVariableBufferCaseBlocks (Context& context, tcu::TestCaseGroup* targetGroup, glu::GLSLVersion glslVersion, void (*blockContentGenerator)(Context&, const ResourceDefinition::Node::SharedPtr&, tcu::TestCaseGroup*))
6418 {
6419 const ResourceDefinition::Node::SharedPtr program (new ResourceDefinition::Program());
6420 const ResourceDefinition::Node::SharedPtr shader (new ResourceDefinition::Shader(program, glu::SHADERTYPE_COMPUTE, glslVersion));
6421 const ResourceDefinition::Node::SharedPtr defaultBlock (new ResourceDefinition::DefaultBlock(shader));
6422 const ResourceDefinition::Node::SharedPtr bufferStorage (new ResourceDefinition::StorageQualifier(defaultBlock, glu::STORAGE_BUFFER));
6423 const ResourceDefinition::Node::SharedPtr binding (new ResourceDefinition::LayoutQualifier(bufferStorage, glu::Layout(-1, 0)));
6424
6425 // .named_block
6426 {
6427 const ResourceDefinition::Node::SharedPtr buffer (new ResourceDefinition::InterfaceBlock(binding, true));
6428 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "named_block", "Named block");
6429
6430 targetGroup->addChild(blockGroup);
6431
6432 blockContentGenerator(context, buffer, blockGroup);
6433 }
6434
6435 // .unnamed_block
6436 {
6437 const ResourceDefinition::Node::SharedPtr buffer (new ResourceDefinition::InterfaceBlock(binding, false));
6438 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "unnamed_block", "Unnamed block");
6439
6440 targetGroup->addChild(blockGroup);
6441
6442 blockContentGenerator(context, buffer, blockGroup);
6443 }
6444
6445 // .block_array
6446 {
6447 const ResourceDefinition::Node::SharedPtr arrayElement (new ResourceDefinition::ArrayElement(binding));
6448 const ResourceDefinition::Node::SharedPtr buffer (new ResourceDefinition::InterfaceBlock(arrayElement, true));
6449 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "block_array", "Block array");
6450
6451 targetGroup->addChild(blockGroup);
6452
6453 blockContentGenerator(context, buffer, blockGroup);
6454 }
6455 }
6456
generateBufferVariableResourceListBlockContentsProxy(Context & context,const ResourceDefinition::Node::SharedPtr & parentStructure,tcu::TestCaseGroup * const targetGroup)6457 static void generateBufferVariableResourceListBlockContentsProxy (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup)
6458 {
6459 generateBufferBackedResourceListBlockContentCases(context, parentStructure, targetGroup, PROGRAMINTERFACE_BUFFER_VARIABLE, 4);
6460 }
6461
generateBufferVariableArraySizeSubCases(Context & context,const ResourceDefinition::Node::SharedPtr & parentStructure,tcu::TestCaseGroup * const targetGroup,ProgramResourcePropFlags targetProp,bool sizedArray,bool extendedCases)6462 static void generateBufferVariableArraySizeSubCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup, ProgramResourcePropFlags targetProp, bool sizedArray, bool extendedCases)
6463 {
6464 const ProgramResourceQueryTestTarget queryTarget (PROGRAMINTERFACE_BUFFER_VARIABLE, targetProp);
6465 tcu::TestCaseGroup* aggregateGroup;
6466
6467 // .types
6468 if (extendedCases)
6469 {
6470 tcu::TestCaseGroup* const blockGroup = new tcu::TestCaseGroup(context.getTestContext(), "types", "Types");
6471 targetGroup->addChild(blockGroup);
6472
6473 generateVariableCases(context, parentStructure, blockGroup, queryTarget, (sizedArray) ? (2) : (1), false);
6474 }
6475
6476 // .aggregates
6477 if (extendedCases)
6478 {
6479 aggregateGroup = new tcu::TestCaseGroup(context.getTestContext(), "aggregates", "Aggregate types");
6480 targetGroup->addChild(aggregateGroup);
6481 }
6482 else
6483 aggregateGroup = targetGroup;
6484
6485 // .float_*
6486 generateBufferBackedArrayStrideTypeAggregateCases(context, parentStructure, aggregateGroup, queryTarget.interface, glu::TYPE_FLOAT, (extendedCases && sizedArray) ? (2) : (1), !extendedCases);
6487
6488 // .bool_*
6489 generateBufferBackedArrayStrideTypeAggregateCases(context, parentStructure, aggregateGroup, queryTarget.interface, glu::TYPE_BOOL, (extendedCases && sizedArray) ? (1) : (0), !extendedCases);
6490
6491 // .bvec3_*
6492 generateBufferBackedArrayStrideTypeAggregateCases(context, parentStructure, aggregateGroup, queryTarget.interface, glu::TYPE_BOOL_VEC3, (extendedCases && sizedArray) ? (2) : (1), !extendedCases);
6493
6494 // .vec4_*
6495 generateBufferBackedArrayStrideTypeAggregateCases(context, parentStructure, aggregateGroup, queryTarget.interface, glu::TYPE_FLOAT_VEC4, (extendedCases && sizedArray) ? (2) : (1), !extendedCases);
6496
6497 // .ivec2_*
6498 generateBufferBackedArrayStrideTypeAggregateCases(context, parentStructure, aggregateGroup, queryTarget.interface, glu::TYPE_INT_VEC2, (extendedCases && sizedArray) ? (2) : (1), !extendedCases);
6499 }
6500
6501 template <ProgramResourcePropFlags TargetProp>
generateBufferVariableArrayCases(Context & context,const ResourceDefinition::Node::SharedPtr & parentStructure,tcu::TestCaseGroup * const targetGroup)6502 static void generateBufferVariableArrayCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* const targetGroup)
6503 {
6504 const ProgramResourceQueryTestTarget queryTarget (PROGRAMINTERFACE_BUFFER_VARIABLE, TargetProp);
6505 const bool namedNonArrayBlock = static_cast<const ResourceDefinition::InterfaceBlock*>(parentStructure.get())->m_named && parentStructure->getEnclosingNode()->getType() != ResourceDefinition::Node::TYPE_ARRAY_ELEMENT;
6506
6507 // .non_array
6508 if (namedNonArrayBlock)
6509 {
6510 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "non_array", "Non-array target");
6511 targetGroup->addChild(blockGroup);
6512
6513 generateVariableCases(context, parentStructure, blockGroup, queryTarget, 1, false);
6514 }
6515
6516 // .sized
6517 {
6518 const ResourceDefinition::Node::SharedPtr sized (new ResourceDefinition::ArrayElement(parentStructure));
6519 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "sized", "Sized target");
6520 targetGroup->addChild(blockGroup);
6521
6522 generateBufferVariableArraySizeSubCases(context, sized, blockGroup, TargetProp, true, namedNonArrayBlock);
6523 }
6524
6525 // .unsized
6526 {
6527 const ResourceDefinition::Node::SharedPtr unsized (new ResourceDefinition::ArrayElement(parentStructure, ResourceDefinition::ArrayElement::UNSIZED_ARRAY));
6528 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "unsized", "Unsized target");
6529 targetGroup->addChild(blockGroup);
6530
6531 generateBufferVariableArraySizeSubCases(context, unsized, blockGroup, TargetProp, false, namedNonArrayBlock);
6532 }
6533 }
6534
generateBufferVariableBlockIndexCases(Context & context,glu::GLSLVersion glslVersion,tcu::TestCaseGroup * const targetGroup)6535 static void generateBufferVariableBlockIndexCases (Context& context, glu::GLSLVersion glslVersion, tcu::TestCaseGroup* const targetGroup)
6536 {
6537 const ResourceDefinition::Node::SharedPtr program (new ResourceDefinition::Program());
6538 const ResourceDefinition::Node::SharedPtr shader (new ResourceDefinition::Shader(program, glu::SHADERTYPE_COMPUTE, glslVersion));
6539 const ResourceDefinition::Node::SharedPtr defaultBlock (new ResourceDefinition::DefaultBlock(shader));
6540 const ResourceDefinition::Node::SharedPtr bufferStorage (new ResourceDefinition::StorageQualifier(defaultBlock, glu::STORAGE_BUFFER));
6541 const ResourceDefinition::Node::SharedPtr binding (new ResourceDefinition::LayoutQualifier(bufferStorage, glu::Layout(-1, 0)));
6542
6543 // .named_block
6544 {
6545 const ResourceDefinition::Node::SharedPtr buffer (new ResourceDefinition::InterfaceBlock(binding, true));
6546 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(buffer, glu::TYPE_FLOAT_VEC4));
6547
6548 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_BUFFER_VARIABLE, PROGRAMRESOURCEPROP_BLOCK_INDEX), "named_block"));
6549 }
6550
6551 // .unnamed_block
6552 {
6553 const ResourceDefinition::Node::SharedPtr buffer (new ResourceDefinition::InterfaceBlock(binding, false));
6554 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(buffer, glu::TYPE_FLOAT_VEC4));
6555
6556 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_BUFFER_VARIABLE, PROGRAMRESOURCEPROP_BLOCK_INDEX), "unnamed_block"));
6557 }
6558
6559 // .block_array
6560 {
6561 const ResourceDefinition::Node::SharedPtr arrayElement (new ResourceDefinition::ArrayElement(binding));
6562 const ResourceDefinition::Node::SharedPtr buffer (new ResourceDefinition::InterfaceBlock(arrayElement, true));
6563 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(buffer, glu::TYPE_FLOAT_VEC4));
6564
6565 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_BUFFER_VARIABLE, PROGRAMRESOURCEPROP_BLOCK_INDEX), "block_array"));
6566 }
6567 }
6568
generateBufferVariableMatrixCaseBlocks(Context & context,tcu::TestCaseGroup * const targetGroup,glu::GLSLVersion glslVersion,void (* blockContentGenerator)(Context &,const ResourceDefinition::Node::SharedPtr &,tcu::TestCaseGroup *,bool))6569 static void generateBufferVariableMatrixCaseBlocks (Context& context, tcu::TestCaseGroup* const targetGroup, glu::GLSLVersion glslVersion, void (*blockContentGenerator)(Context&, const ResourceDefinition::Node::SharedPtr&, tcu::TestCaseGroup*, bool))
6570 {
6571 static const struct
6572 {
6573 const char* name;
6574 const char* description;
6575 bool namedBlock;
6576 bool extendedBasicTypeCases;
6577 glu::MatrixOrder order;
6578 } children[] =
6579 {
6580 { "named_block", "Named uniform block", true, true, glu::MATRIXORDER_LAST },
6581 { "named_block_row_major", "Named uniform block", true, false, glu::MATRIXORDER_ROW_MAJOR },
6582 { "named_block_col_major", "Named uniform block", true, false, glu::MATRIXORDER_COLUMN_MAJOR },
6583 { "unnamed_block", "Unnamed uniform block", false, false, glu::MATRIXORDER_LAST },
6584 { "unnamed_block_row_major", "Unnamed uniform block", false, false, glu::MATRIXORDER_ROW_MAJOR },
6585 { "unnamed_block_col_major", "Unnamed uniform block", false, false, glu::MATRIXORDER_COLUMN_MAJOR },
6586 };
6587
6588 const ResourceDefinition::Node::SharedPtr program (new ResourceDefinition::Program());
6589 const ResourceDefinition::Node::SharedPtr shader (new ResourceDefinition::Shader(program, glu::SHADERTYPE_COMPUTE, glslVersion));
6590 const ResourceDefinition::Node::SharedPtr defaultBlock (new ResourceDefinition::DefaultBlock(shader));
6591 const ResourceDefinition::Node::SharedPtr buffer (new ResourceDefinition::StorageQualifier(defaultBlock, glu::STORAGE_BUFFER));
6592
6593 for (int childNdx = 0; childNdx < (int)DE_LENGTH_OF_ARRAY(children); ++childNdx)
6594 {
6595 ResourceDefinition::Node::SharedPtr parentStructure = buffer;
6596 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, children[childNdx].name, children[childNdx].description);
6597
6598 targetGroup->addChild(blockGroup);
6599
6600 if (children[childNdx].order != glu::MATRIXORDER_LAST)
6601 {
6602 glu::Layout layout;
6603 layout.matrixOrder = children[childNdx].order;
6604 parentStructure = ResourceDefinition::Node::SharedPtr(new ResourceDefinition::LayoutQualifier(parentStructure, layout));
6605 }
6606
6607 parentStructure = ResourceDefinition::Node::SharedPtr(new ResourceDefinition::InterfaceBlock(parentStructure, children[childNdx].namedBlock));
6608
6609 blockContentGenerator(context, parentStructure, blockGroup, children[childNdx].extendedBasicTypeCases);
6610 }
6611 }
6612
generateBufferVariableMatrixVariableBasicTypeCases(Context & context,const ResourceDefinition::Node::SharedPtr & parentStructure,tcu::TestCaseGroup * targetGroup,ProgramResourcePropFlags targetProp)6613 static void generateBufferVariableMatrixVariableBasicTypeCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup, ProgramResourcePropFlags targetProp)
6614 {
6615 // all matrix types and some non-matrix
6616
6617 static const glu::DataType variableTypes[] =
6618 {
6619 glu::TYPE_FLOAT,
6620 glu::TYPE_INT_VEC3,
6621 glu::TYPE_FLOAT_MAT2,
6622 glu::TYPE_FLOAT_MAT2X3,
6623 glu::TYPE_FLOAT_MAT2X4,
6624 glu::TYPE_FLOAT_MAT3X2,
6625 glu::TYPE_FLOAT_MAT3,
6626 glu::TYPE_FLOAT_MAT3X4,
6627 glu::TYPE_FLOAT_MAT4X2,
6628 glu::TYPE_FLOAT_MAT4X3,
6629 glu::TYPE_FLOAT_MAT4,
6630 };
6631
6632 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(variableTypes); ++ndx)
6633 {
6634 const ResourceDefinition::Node::SharedPtr variable(new ResourceDefinition::Variable(parentStructure, variableTypes[ndx]));
6635 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_BUFFER_VARIABLE, targetProp)));
6636 }
6637 }
6638
generateBufferVariableMatrixVariableCases(Context & context,const ResourceDefinition::Node::SharedPtr & parentStructure,tcu::TestCaseGroup * targetGroup,ProgramResourcePropFlags targetProp)6639 static void generateBufferVariableMatrixVariableCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup, ProgramResourcePropFlags targetProp)
6640 {
6641 // Basic aggregates
6642 generateBufferBackedVariableAggregateTypeCases(context, parentStructure, targetGroup, PROGRAMINTERFACE_BUFFER_VARIABLE, targetProp, glu::TYPE_FLOAT_MAT3X2, "", 2);
6643
6644 // Unsized array
6645 {
6646 const ResourceDefinition::Node::SharedPtr unsized (new ResourceDefinition::ArrayElement(parentStructure, ResourceDefinition::ArrayElement::UNSIZED_ARRAY));
6647 const ResourceDefinition::Node::SharedPtr variable (new ResourceDefinition::Variable(unsized, glu::TYPE_FLOAT_MAT3X2));
6648
6649 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_BUFFER_VARIABLE, targetProp), "var_unsized_array"));
6650 }
6651 }
6652
6653 template <ProgramResourcePropFlags TargetProp>
generateBufferVariableMatrixCases(Context & context,const ResourceDefinition::Node::SharedPtr & parentStructure,tcu::TestCaseGroup * targetGroup,bool extendedTypeCases)6654 static void generateBufferVariableMatrixCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup, bool extendedTypeCases)
6655 {
6656 // .types
6657 if (extendedTypeCases)
6658 {
6659 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "types", "Types");
6660 targetGroup->addChild(blockGroup);
6661 generateBufferVariableMatrixVariableBasicTypeCases(context, parentStructure, blockGroup, TargetProp);
6662 }
6663
6664 // .no_qualifier
6665 {
6666 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "no_qualifier", "No qualifier");
6667 targetGroup->addChild(blockGroup);
6668 generateBufferVariableMatrixVariableCases(context, parentStructure, blockGroup, TargetProp);
6669 }
6670
6671 // .column_major
6672 {
6673 const ResourceDefinition::Node::SharedPtr matrixOrder(new ResourceDefinition::LayoutQualifier(parentStructure, glu::Layout(-1, -1, -1, glu::FORMATLAYOUT_LAST, glu::MATRIXORDER_COLUMN_MAJOR)));
6674
6675 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "column_major", "Column major qualifier");
6676 targetGroup->addChild(blockGroup);
6677 generateBufferVariableMatrixVariableCases(context, matrixOrder, blockGroup, TargetProp);
6678 }
6679
6680 // .row_major
6681 {
6682 const ResourceDefinition::Node::SharedPtr matrixOrder(new ResourceDefinition::LayoutQualifier(parentStructure, glu::Layout(-1, -1, -1, glu::FORMATLAYOUT_LAST, glu::MATRIXORDER_ROW_MAJOR)));
6683
6684 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "row_major", "Row major qualifier");
6685 targetGroup->addChild(blockGroup);
6686 generateBufferVariableMatrixVariableCases(context, matrixOrder, blockGroup, TargetProp);
6687 }
6688 }
6689
generateBufferVariableNameLengthCases(Context & context,const ResourceDefinition::Node::SharedPtr & parentStructure,tcu::TestCaseGroup * targetGroup)6690 static void generateBufferVariableNameLengthCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup)
6691 {
6692 // .sized
6693 {
6694 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "sized", "Sized target");
6695 targetGroup->addChild(blockGroup);
6696
6697 generateBufferBackedVariableAggregateTypeCases(context, parentStructure, blockGroup, PROGRAMINTERFACE_BUFFER_VARIABLE, PROGRAMRESOURCEPROP_NAME_LENGTH, glu::TYPE_FLOAT, "", 3);
6698 }
6699
6700 // .unsized
6701 {
6702 const ResourceDefinition::Node::SharedPtr unsized (new ResourceDefinition::ArrayElement(parentStructure, ResourceDefinition::ArrayElement::UNSIZED_ARRAY));
6703 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "unsized", "Unsized target");
6704 targetGroup->addChild(blockGroup);
6705
6706 generateBufferBackedVariableAggregateTypeCases(context, unsized, blockGroup, PROGRAMINTERFACE_BUFFER_VARIABLE, PROGRAMRESOURCEPROP_NAME_LENGTH, glu::TYPE_FLOAT, "", 2);
6707 }
6708 }
6709
generateBufferVariableOffsetCases(Context & context,const ResourceDefinition::Node::SharedPtr & parentStructure,tcu::TestCaseGroup * targetGroup)6710 static void generateBufferVariableOffsetCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup)
6711 {
6712 // .sized
6713 {
6714 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "sized", "Sized target");
6715 targetGroup->addChild(blockGroup);
6716
6717 generateBufferBackedVariableAggregateTypeCases(context, parentStructure, blockGroup, PROGRAMINTERFACE_BUFFER_VARIABLE, PROGRAMRESOURCEPROP_OFFSET, glu::TYPE_FLOAT, "", 3);
6718 }
6719
6720 // .unsized
6721 {
6722 const ResourceDefinition::Node::SharedPtr unsized (new ResourceDefinition::ArrayElement(parentStructure, ResourceDefinition::ArrayElement::UNSIZED_ARRAY));
6723 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "unsized", "Unsized target");
6724 targetGroup->addChild(blockGroup);
6725
6726 generateBufferBackedVariableAggregateTypeCases(context, unsized, blockGroup, PROGRAMINTERFACE_BUFFER_VARIABLE, PROGRAMRESOURCEPROP_OFFSET, glu::TYPE_FLOAT, "", 2);
6727 }
6728 }
6729
generateBufferVariableReferencedByBlockContents(Context & context,const ResourceDefinition::Node::SharedPtr & parentStructure,tcu::TestCaseGroup * targetGroup,int expandLevel)6730 static void generateBufferVariableReferencedByBlockContents (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup, int expandLevel)
6731 {
6732 DE_UNREF(expandLevel);
6733
6734 const ProgramResourceQueryTestTarget queryTarget (PROGRAMINTERFACE_BUFFER_VARIABLE, PROGRAMRESOURCEPROP_REFERENCED_BY_SHADER);
6735 const ResourceDefinition::Node::SharedPtr defaultBlock (new ResourceDefinition::DefaultBlock(parentStructure));
6736 const ResourceDefinition::Node::SharedPtr storage (new ResourceDefinition::StorageQualifier(defaultBlock, glu::STORAGE_BUFFER));
6737 const bool singleShaderCase = parentStructure->getType() == ResourceDefinition::Node::TYPE_SHADER;
6738
6739 // .named_block
6740 {
6741 const ResourceDefinition::Node::SharedPtr buffer (new ResourceDefinition::InterfaceBlock(storage, true));
6742 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "named_block", "Named block");
6743
6744 targetGroup->addChild(blockGroup);
6745
6746 generateBufferReferencedByShaderInterfaceBlockCases(context, buffer, blockGroup, queryTarget, singleShaderCase);
6747 }
6748
6749 // .unnamed_block
6750 {
6751 const ResourceDefinition::Node::SharedPtr buffer (new ResourceDefinition::InterfaceBlock(storage, false));
6752 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "unnamed_block", "Unnamed block");
6753
6754 targetGroup->addChild(blockGroup);
6755
6756 generateBufferReferencedByShaderInterfaceBlockCases(context, buffer, blockGroup, queryTarget, false);
6757 }
6758
6759 // .block_array
6760 {
6761 const ResourceDefinition::Node::SharedPtr arrayElement (new ResourceDefinition::ArrayElement(storage));
6762 const ResourceDefinition::Node::SharedPtr buffer (new ResourceDefinition::InterfaceBlock(arrayElement, true));
6763 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "block_array", "Block array");
6764
6765 targetGroup->addChild(blockGroup);
6766
6767 generateBufferReferencedByShaderInterfaceBlockCases(context, buffer, blockGroup, queryTarget, false);
6768 }
6769 }
6770
6771 template <ProgramResourcePropFlags TargetProp>
generateBufferVariableTopLevelCases(Context & context,const ResourceDefinition::Node::SharedPtr & parentStructure,tcu::TestCaseGroup * targetGroup)6772 static void generateBufferVariableTopLevelCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup)
6773 {
6774 // basic and aggregate types
6775 generateBufferBackedVariableAggregateTypeCases(context, parentStructure, targetGroup, PROGRAMINTERFACE_BUFFER_VARIABLE, TargetProp, glu::TYPE_FLOAT_VEC4, "", 3);
6776
6777 // basic and aggregate types in an unsized array
6778 {
6779 const ResourceDefinition::Node::SharedPtr unsized(new ResourceDefinition::ArrayElement(parentStructure, ResourceDefinition::ArrayElement::UNSIZED_ARRAY));
6780
6781 generateBufferBackedVariableAggregateTypeCases(context, unsized, targetGroup, PROGRAMINTERFACE_BUFFER_VARIABLE, TargetProp, glu::TYPE_FLOAT_VEC4, "_unsized_array", 2);
6782 }
6783 }
6784
generateBufferVariableTypeBasicTypeCases(Context & context,const ResourceDefinition::Node::SharedPtr & parentStructure,tcu::TestCaseGroup * targetGroup,int expandLevel)6785 static void generateBufferVariableTypeBasicTypeCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup, int expandLevel)
6786 {
6787 static const struct
6788 {
6789 int level;
6790 glu::DataType dataType;
6791 } variableTypes[] =
6792 {
6793 { 0, glu::TYPE_FLOAT },
6794 { 1, glu::TYPE_INT },
6795 { 1, glu::TYPE_UINT },
6796 { 1, glu::TYPE_BOOL },
6797
6798 { 3, glu::TYPE_FLOAT_VEC2 },
6799 { 1, glu::TYPE_FLOAT_VEC3 },
6800 { 1, glu::TYPE_FLOAT_VEC4 },
6801
6802 { 3, glu::TYPE_INT_VEC2 },
6803 { 2, glu::TYPE_INT_VEC3 },
6804 { 3, glu::TYPE_INT_VEC4 },
6805
6806 { 3, glu::TYPE_UINT_VEC2 },
6807 { 2, glu::TYPE_UINT_VEC3 },
6808 { 3, glu::TYPE_UINT_VEC4 },
6809
6810 { 3, glu::TYPE_BOOL_VEC2 },
6811 { 2, glu::TYPE_BOOL_VEC3 },
6812 { 3, glu::TYPE_BOOL_VEC4 },
6813
6814 { 2, glu::TYPE_FLOAT_MAT2 },
6815 { 3, glu::TYPE_FLOAT_MAT2X3 },
6816 { 3, glu::TYPE_FLOAT_MAT2X4 },
6817 { 2, glu::TYPE_FLOAT_MAT3X2 },
6818 { 2, glu::TYPE_FLOAT_MAT3 },
6819 { 3, glu::TYPE_FLOAT_MAT3X4 },
6820 { 2, glu::TYPE_FLOAT_MAT4X2 },
6821 { 3, glu::TYPE_FLOAT_MAT4X3 },
6822 { 2, glu::TYPE_FLOAT_MAT4 },
6823 };
6824
6825 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(variableTypes); ++ndx)
6826 {
6827 if (variableTypes[ndx].level <= expandLevel)
6828 {
6829 const ResourceDefinition::Node::SharedPtr variable(new ResourceDefinition::Variable(parentStructure, variableTypes[ndx].dataType));
6830 targetGroup->addChild(new ResourceTestCase(context, variable, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_BUFFER_VARIABLE, PROGRAMRESOURCEPROP_TYPE)));
6831 }
6832 }
6833 }
6834
generateBufferVariableTypeCases(Context & context,const ResourceDefinition::Node::SharedPtr & parentStructure,tcu::TestCaseGroup * targetGroup,int depth=3)6835 static void generateBufferVariableTypeCases (Context& context, const ResourceDefinition::Node::SharedPtr& parentStructure, tcu::TestCaseGroup* targetGroup, int depth = 3)
6836 {
6837 // .basic_type
6838 if (depth > 0)
6839 {
6840 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "basic_type", "Basic type");
6841 targetGroup->addChild(blockGroup);
6842 generateBufferVariableTypeBasicTypeCases(context, parentStructure, blockGroup, depth);
6843 }
6844 else
6845 {
6846 // flatten bottom-level
6847 generateBufferVariableTypeBasicTypeCases(context, parentStructure, targetGroup, depth);
6848 }
6849
6850 // .array
6851 if (depth > 0)
6852 {
6853 const ResourceDefinition::Node::SharedPtr arrayElement (new ResourceDefinition::ArrayElement(parentStructure));
6854 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "array", "Arrays");
6855
6856 targetGroup->addChild(blockGroup);
6857 generateBufferVariableTypeCases(context, arrayElement, blockGroup, depth-1);
6858 }
6859
6860 // .struct
6861 if (depth > 0)
6862 {
6863 const ResourceDefinition::Node::SharedPtr structMember (new ResourceDefinition::StructMember(parentStructure));
6864 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(context, "struct", "Structs");
6865
6866 targetGroup->addChild(blockGroup);
6867 generateBufferVariableTypeCases(context, structMember, blockGroup, depth-1);
6868 }
6869 }
6870
generateBufferVariableTypeBlock(Context & context,tcu::TestCaseGroup * targetGroup,glu::GLSLVersion glslVersion)6871 static void generateBufferVariableTypeBlock (Context& context, tcu::TestCaseGroup* targetGroup, glu::GLSLVersion glslVersion)
6872 {
6873 const ResourceDefinition::Node::SharedPtr program (new ResourceDefinition::Program());
6874 const ResourceDefinition::Node::SharedPtr shader (new ResourceDefinition::Shader(program, glu::SHADERTYPE_COMPUTE, glslVersion));
6875 const ResourceDefinition::Node::SharedPtr defaultBlock (new ResourceDefinition::DefaultBlock(shader));
6876 const ResourceDefinition::Node::SharedPtr buffer (new ResourceDefinition::StorageQualifier(defaultBlock, glu::STORAGE_BUFFER));
6877 const ResourceDefinition::Node::SharedPtr block (new ResourceDefinition::InterfaceBlock(buffer, true));
6878
6879 generateBufferVariableTypeCases(context, block, targetGroup);
6880 }
6881
generateBufferVariableRandomCase(Context & context,tcu::TestCaseGroup * const targetGroup,glu::GLSLVersion glslVersion,int index,bool onlyExtensionStages)6882 static void generateBufferVariableRandomCase (Context& context, tcu::TestCaseGroup* const targetGroup, glu::GLSLVersion glslVersion, int index, bool onlyExtensionStages)
6883 {
6884 de::Random rnd (index * 0x12345);
6885 const ResourceDefinition::Node::SharedPtr shader = generateRandomShaderSet(rnd, glslVersion, onlyExtensionStages);
6886 const glu::DataType type = generateRandomDataType(rnd, true);
6887 const glu::Layout layout = generateRandomVariableLayout(rnd, type, true);
6888 const bool namedBlock = rnd.getBool();
6889 const ResourceDefinition::Node::SharedPtr defaultBlock (new ResourceDefinition::DefaultBlock(shader));
6890 const ResourceDefinition::Node::SharedPtr buffer (new ResourceDefinition::StorageQualifier(defaultBlock, glu::STORAGE_BUFFER));
6891 ResourceDefinition::Node::SharedPtr currentStructure (new ResourceDefinition::LayoutQualifier(buffer, generateRandomBufferBlockLayout(rnd)));
6892
6893 if (namedBlock && rnd.getBool())
6894 currentStructure = ResourceDefinition::Node::SharedPtr(new ResourceDefinition::ArrayElement(currentStructure));
6895 currentStructure = ResourceDefinition::Node::SharedPtr(new ResourceDefinition::InterfaceBlock(currentStructure, namedBlock));
6896
6897 currentStructure = ResourceDefinition::Node::SharedPtr(new ResourceDefinition::LayoutQualifier(currentStructure, layout));
6898 currentStructure = generateRandomVariableDefinition(rnd, currentStructure, type, layout, true);
6899
6900 targetGroup->addChild(new ResourceTestCase(context, currentStructure, ProgramResourceQueryTestTarget(PROGRAMINTERFACE_BUFFER_VARIABLE, PROGRAMRESOURCEPROP_BUFFER_VARIABLE_MASK), de::toString(index).c_str()));
6901 }
6902
generateBufferVariableRandomCases(Context & context,tcu::TestCaseGroup * const targetGroup,glu::GLSLVersion glslVersion)6903 static void generateBufferVariableRandomCases (Context& context, tcu::TestCaseGroup* const targetGroup, glu::GLSLVersion glslVersion)
6904 {
6905 const int numBasicCases = 40;
6906 const int numTessGeoCases = 40;
6907
6908 for (int ndx = 0; ndx < numBasicCases; ++ndx)
6909 generateBufferVariableRandomCase(context, targetGroup, glslVersion, ndx, false);
6910 for (int ndx = 0; ndx < numTessGeoCases; ++ndx)
6911 generateBufferVariableRandomCase(context, targetGroup, glslVersion, numBasicCases + ndx, true);
6912 }
6913
6914 class BufferVariableTestGroup : public TestCaseGroup
6915 {
6916 public:
6917 BufferVariableTestGroup (Context& context);
6918 void init (void);
6919 };
6920
BufferVariableTestGroup(Context & context)6921 BufferVariableTestGroup::BufferVariableTestGroup (Context& context)
6922 : TestCaseGroup(context, "buffer_variable", "Buffer variable")
6923 {
6924 }
6925
init(void)6926 void BufferVariableTestGroup::init (void)
6927 {
6928 const glu::GLSLVersion glslVersion = glu::getContextTypeGLSLVersion(m_context.getRenderContext().getType());
6929
6930 // .resource_list
6931 {
6932 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(m_context, "resource_list", "Resource list");
6933 addChild(blockGroup);
6934 generateBufferVariableBufferCaseBlocks(m_context, blockGroup, glslVersion, generateBufferVariableResourceListBlockContentsProxy);
6935 }
6936
6937 // .array_size
6938 {
6939 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(m_context, "array_size", "Array size");
6940 addChild(blockGroup);
6941 generateBufferVariableBufferCaseBlocks(m_context, blockGroup, glslVersion, generateBufferVariableArrayCases<PROGRAMRESOURCEPROP_ARRAY_SIZE>);
6942 }
6943
6944 // .array_stride
6945 {
6946 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(m_context, "array_stride", "Array stride");
6947 addChild(blockGroup);
6948 generateBufferVariableBufferCaseBlocks(m_context, blockGroup, glslVersion, generateBufferVariableArrayCases<PROGRAMRESOURCEPROP_ARRAY_STRIDE>);
6949 }
6950
6951 // .block_index
6952 {
6953 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(m_context, "block_index", "Block index");
6954 addChild(blockGroup);
6955 generateBufferVariableBlockIndexCases(m_context, glslVersion, blockGroup);
6956 }
6957
6958 // .is_row_major
6959 {
6960 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(m_context, "is_row_major", "Is row major");
6961 addChild(blockGroup);
6962 generateBufferVariableMatrixCaseBlocks(m_context, blockGroup, glslVersion, generateBufferVariableMatrixCases<PROGRAMRESOURCEPROP_MATRIX_ROW_MAJOR>);
6963 }
6964
6965 // .matrix_stride
6966 {
6967 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(m_context, "matrix_stride", "Matrix stride");
6968 addChild(blockGroup);
6969 generateBufferVariableMatrixCaseBlocks(m_context, blockGroup, glslVersion, generateBufferVariableMatrixCases<PROGRAMRESOURCEPROP_MATRIX_STRIDE>);
6970 }
6971
6972 // .name_length
6973 {
6974 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(m_context, "name_length", "Name length");
6975 addChild(blockGroup);
6976 generateBufferVariableBufferCaseBlocks(m_context, blockGroup, glslVersion, generateBufferVariableNameLengthCases);
6977 }
6978
6979 // .offset
6980 {
6981 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(m_context, "offset", "Offset");
6982 addChild(blockGroup);
6983 generateBufferVariableBufferCaseBlocks(m_context, blockGroup, glslVersion, generateBufferVariableOffsetCases);
6984 }
6985
6986 // .referenced_by
6987 {
6988 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(m_context, "referenced_by", "Referenced by");
6989 addChild(blockGroup);
6990 generateReferencedByShaderCaseBlocks(m_context, blockGroup, glslVersion, generateBufferVariableReferencedByBlockContents);
6991 }
6992
6993 // .top_level_array_size
6994 {
6995 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(m_context, "top_level_array_size", "Top-level array size");
6996 addChild(blockGroup);
6997 generateBufferVariableBufferCaseBlocks(m_context, blockGroup, glslVersion, generateBufferVariableTopLevelCases<PROGRAMRESOURCEPROP_TOP_LEVEL_ARRAY_SIZE>);
6998 }
6999
7000 // .top_level_array_stride
7001 {
7002 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(m_context, "top_level_array_stride", "Top-level array stride");
7003 addChild(blockGroup);
7004 generateBufferVariableBufferCaseBlocks(m_context, blockGroup, glslVersion, generateBufferVariableTopLevelCases<PROGRAMRESOURCEPROP_TOP_LEVEL_ARRAY_STRIDE>);
7005 }
7006
7007 // .type
7008 {
7009 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(m_context, "type", "Type");
7010 addChild(blockGroup);
7011 generateBufferVariableTypeBlock(m_context, blockGroup, glslVersion);
7012 }
7013
7014 // .random
7015 {
7016 tcu::TestCaseGroup* const blockGroup = new TestCaseGroup(m_context, "random", "Random");
7017 addChild(blockGroup);
7018 generateBufferVariableRandomCases(m_context, blockGroup, glslVersion);
7019 }
7020 }
7021
7022 } // anonymous
7023
ProgramInterfaceQueryTests(Context & context)7024 ProgramInterfaceQueryTests::ProgramInterfaceQueryTests (Context& context)
7025 : TestCaseGroup(context, "program_interface_query", "Program interface query tests")
7026 {
7027 }
7028
~ProgramInterfaceQueryTests(void)7029 ProgramInterfaceQueryTests::~ProgramInterfaceQueryTests (void)
7030 {
7031 }
7032
init(void)7033 void ProgramInterfaceQueryTests::init (void)
7034 {
7035 // Misc queries
7036
7037 // .buffer_limited_query
7038 {
7039 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "buffer_limited_query", "Queries limited by the buffer size");
7040
7041 addChild(group);
7042
7043 group->addChild(new ResourceNameBufferLimitCase(m_context, "resource_name_query", "Test GetProgramResourceName with too small a buffer"));
7044 group->addChild(new ResourceQueryBufferLimitCase(m_context, "resource_query", "Test GetProgramResourceiv with too small a buffer"));
7045 }
7046
7047 // Interfaces
7048
7049 // .uniform
7050 addChild(new UniformInterfaceTestGroup(m_context));
7051
7052 // .uniform_block
7053 addChild(new BufferBackedBlockInterfaceTestGroup(m_context, glu::STORAGE_UNIFORM));
7054
7055 // .atomic_counter_buffer
7056 addChild(new AtomicCounterTestGroup(m_context));
7057
7058 // .program_input
7059 addChild(new ProgramInputTestGroup(m_context));
7060
7061 // .program_output
7062 addChild(new ProgramOutputTestGroup(m_context));
7063
7064 // .transform_feedback_varying
7065 addChild(new TransformFeedbackVaryingTestGroup(m_context));
7066
7067 // .buffer_variable
7068 addChild(new BufferVariableTestGroup(m_context));
7069
7070 // .shader_storage_block
7071 addChild(new BufferBackedBlockInterfaceTestGroup(m_context, glu::STORAGE_BUFFER));
7072 }
7073
7074 } // Functional
7075 } // gles31
7076 } // deqp
7077