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