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