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