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