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