Fix missing dependency on sparse binds
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / ubo / vktUniformBlockCase.cpp
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2015 The Khronos Group Inc.
6  * Copyright (c) 2015 Samsung Electronics Co., Ltd.
7  * Copyright (c) 2016 The Android Open Source Project
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  *//*!
22  * \file
23  * \brief Uniform block case.
24  *//*--------------------------------------------------------------------*/
25
26 #include "vktUniformBlockCase.hpp"
27
28 #include "vkPrograms.hpp"
29
30 #include "gluVarType.hpp"
31 #include "tcuTestLog.hpp"
32 #include "tcuSurface.hpp"
33 #include "deInt32.h"
34 #include "deRandom.hpp"
35 #include "deStringUtil.hpp"
36
37 #include "tcuTextureUtil.hpp"
38 #include "deSharedPtr.hpp"
39 #include "deFloat16.h"
40
41 #include "vkMemUtil.hpp"
42 #include "vkQueryUtil.hpp"
43 #include "vkTypeUtil.hpp"
44 #include "vkRef.hpp"
45 #include "vkRefUtil.hpp"
46 #include "vkBuilderUtil.hpp"
47 #include "vkCmdUtil.hpp"
48 #include "vkObjUtil.hpp"
49 #include "vkImageUtil.hpp"
50
51 #include <map>
52 #include <set>
53
54 namespace vkt
55 {
56 namespace ubo
57 {
58
59 using namespace vk;
60
61 // VarType implementation.
62
63 VarType::VarType (void)
64         : m_type        (TYPE_LAST)
65         , m_flags       (0)
66 {
67 }
68
69 VarType::VarType (const VarType& other)
70         : m_type        (TYPE_LAST)
71         , m_flags       (0)
72 {
73         *this = other;
74 }
75
76 VarType::VarType (glu::DataType basicType, deUint32 flags)
77         : m_type        (TYPE_BASIC)
78         , m_flags       (flags)
79 {
80         m_data.basicType = basicType;
81 }
82
83 VarType::VarType (const VarType& elementType, int arraySize)
84         : m_type        (TYPE_ARRAY)
85         , m_flags       (0)
86 {
87         m_data.array.size                       = arraySize;
88         m_data.array.elementType        = new VarType(elementType);
89 }
90
91 VarType::VarType (const StructType* structPtr, deUint32 flags)
92         : m_type        (TYPE_STRUCT)
93         , m_flags       (flags)
94 {
95         m_data.structPtr = structPtr;
96 }
97
98 VarType::~VarType (void)
99 {
100         if (m_type == TYPE_ARRAY)
101                 delete m_data.array.elementType;
102 }
103
104 VarType& VarType::operator= (const VarType& other)
105 {
106         if (this == &other)
107                 return *this; // Self-assignment.
108
109         VarType *oldElementType = m_type == TYPE_ARRAY ? m_data.array.elementType : DE_NULL;
110
111         m_type  = other.m_type;
112         m_flags = other.m_flags;
113         m_data  = Data();
114
115         if (m_type == TYPE_ARRAY)
116         {
117                 m_data.array.elementType        = new VarType(*other.m_data.array.elementType);
118                 m_data.array.size                       = other.m_data.array.size;
119         }
120         else
121                 m_data = other.m_data;
122
123         delete oldElementType;
124
125         return *this;
126 }
127
128 // StructType implementation.
129
130 void StructType::addMember (const std::string& name, const VarType& type, deUint32 flags)
131 {
132         m_members.push_back(StructMember(name, type, flags));
133 }
134
135 // Uniform implementation.
136
137 Uniform::Uniform (const std::string& name, const VarType& type, deUint32 flags)
138         : m_name        (name)
139         , m_type        (type)
140         , m_flags       (flags)
141 {
142 }
143
144 // UniformBlock implementation.
145
146 UniformBlock::UniformBlock (const std::string& blockName)
147         : m_blockName   (blockName)
148         , m_arraySize   (0)
149         , m_flags               (0)
150 {
151 }
152
153 std::ostream& operator<< (std::ostream& stream, const BlockLayoutEntry& entry)
154 {
155         stream << entry.name << " { name = " << entry.name
156                    << ", size = " << entry.size
157                    << ", activeUniformIndices = [";
158
159         for (std::vector<int>::const_iterator i = entry.activeUniformIndices.begin(); i != entry.activeUniformIndices.end(); i++)
160         {
161                 if (i != entry.activeUniformIndices.begin())
162                         stream << ", ";
163                 stream << *i;
164         }
165
166         stream << "] }";
167         return stream;
168 }
169
170 std::ostream& operator<< (std::ostream& stream, const UniformLayoutEntry& entry)
171 {
172         stream << entry.name << " { type = " << glu::getDataTypeName(entry.type)
173                    << ", size = " << entry.size
174                    << ", blockNdx = " << entry.blockNdx
175                    << ", offset = " << entry.offset
176                    << ", arrayStride = " << entry.arrayStride
177                    << ", matrixStride = " << entry.matrixStride
178                    << ", isRowMajor = " << (entry.isRowMajor ? "true" : "false")
179                    << " }";
180         return stream;
181 }
182
183 int UniformLayout::getUniformLayoutIndex (int blockNdx, const std::string& name) const
184 {
185         for (int ndx = 0; ndx < (int)uniforms.size(); ndx++)
186         {
187                 if (blocks[uniforms[ndx].blockNdx].blockDeclarationNdx == blockNdx &&
188                         uniforms[ndx].name == name)
189                         return ndx;
190         }
191
192         return -1;
193 }
194
195 int UniformLayout::getBlockLayoutIndex (int blockNdx, int instanceNdx) const
196 {
197         for (int ndx = 0; ndx < (int)blocks.size(); ndx++)
198         {
199                 if (blocks[ndx].blockDeclarationNdx == blockNdx &&
200                         blocks[ndx].instanceNdx == instanceNdx)
201                         return ndx;
202         }
203
204         return -1;
205 }
206
207 // ShaderInterface implementation.
208
209 ShaderInterface::ShaderInterface (void)
210 {
211 }
212
213 ShaderInterface::~ShaderInterface (void)
214 {
215 }
216
217 StructType& ShaderInterface::allocStruct (const std::string& name)
218 {
219         m_structs.push_back(StructTypeSP(new StructType(name)));
220         return *m_structs.back();
221 }
222
223 struct StructNameEquals
224 {
225         std::string name;
226
227         StructNameEquals (const std::string& name_) : name(name_) {}
228
229         bool operator() (const StructTypeSP type) const
230         {
231                 return type->hasTypeName() && name == type->getTypeName();
232         }
233 };
234
235 void ShaderInterface::getNamedStructs (std::vector<const StructType*>& structs) const
236 {
237         for (std::vector<StructTypeSP>::const_iterator i = m_structs.begin(); i != m_structs.end(); i++)
238         {
239                 if ((*i)->hasTypeName())
240                         structs.push_back((*i).get());
241         }
242 }
243
244 UniformBlock& ShaderInterface::allocBlock (const std::string& name)
245 {
246         m_uniformBlocks.push_back(UniformBlockSP(new UniformBlock(name)));
247         return *m_uniformBlocks.back();
248 }
249
250 bool ShaderInterface::usesBlockLayout (UniformFlags layoutFlag) const
251 {
252         for (int i = 0, num_blocks = getNumUniformBlocks() ; i < num_blocks ; i++)
253         {
254                 if (m_uniformBlocks[i]->getFlags() & layoutFlag)
255                         return true;
256         }
257         return false;
258 }
259
260 namespace // Utilities
261 {
262
263 struct PrecisionFlagsFmt
264 {
265         deUint32 flags;
266         PrecisionFlagsFmt (deUint32 flags_) : flags(flags_) {}
267 };
268
269 std::ostream& operator<< (std::ostream& str, const PrecisionFlagsFmt& fmt)
270 {
271         // Precision.
272         DE_ASSERT(dePop32(fmt.flags & (PRECISION_LOW|PRECISION_MEDIUM|PRECISION_HIGH)) <= 1);
273         str << (fmt.flags & PRECISION_LOW               ? "lowp"        :
274                         fmt.flags & PRECISION_MEDIUM    ? "mediump"     :
275                         fmt.flags & PRECISION_HIGH              ? "highp"       : "");
276         return str;
277 }
278
279 struct LayoutFlagsFmt
280 {
281         deUint32 flags;
282         deUint32 offset;
283         LayoutFlagsFmt (deUint32 flags_, deUint32 offset_ = 0u) : flags(flags_), offset(offset_) {}
284 };
285
286 std::ostream& operator<< (std::ostream& str, const LayoutFlagsFmt& fmt)
287 {
288         static const struct
289         {
290                 deUint32        bit;
291                 const char*     token;
292         } bitDesc[] =
293         {
294                 { LAYOUT_STD140,                "std140"                },
295                 { LAYOUT_STD430,                "std430"                },
296                 { LAYOUT_SCALAR,                "scalar"                },
297                 { LAYOUT_ROW_MAJOR,             "row_major"             },
298                 { LAYOUT_COLUMN_MAJOR,  "column_major"  },
299                 { LAYOUT_OFFSET,                "offset"                },
300         };
301
302         deUint32 remBits = fmt.flags;
303         for (int descNdx = 0; descNdx < DE_LENGTH_OF_ARRAY(bitDesc); descNdx++)
304         {
305                 if (remBits & bitDesc[descNdx].bit)
306                 {
307                         if (remBits != fmt.flags)
308                                 str << ", ";
309                         str << bitDesc[descNdx].token;
310                         if (bitDesc[descNdx].bit == LAYOUT_OFFSET)
311                                 str << " = " << fmt.offset;
312                         remBits &= ~bitDesc[descNdx].bit;
313                 }
314         }
315         DE_ASSERT(remBits == 0);
316         return str;
317 }
318
319 // Layout computation.
320
321 int getDataTypeByteSize (glu::DataType type)
322 {
323         if (deInRange32(type, glu::TYPE_UINT8, glu::TYPE_UINT8_VEC4) || deInRange32(type, glu::TYPE_INT8, glu::TYPE_INT8_VEC4))
324         {
325                 return glu::getDataTypeScalarSize(type)*(int)sizeof(deUint8);
326         }
327         if (deInRange32(type, glu::TYPE_UINT16, glu::TYPE_UINT16_VEC4) || deInRange32(type, glu::TYPE_INT16, glu::TYPE_INT16_VEC4) || deInRange32(type, glu::TYPE_FLOAT16, glu::TYPE_FLOAT16_VEC4))
328         {
329                 return glu::getDataTypeScalarSize(type)*(int)sizeof(deUint16);
330         }
331         else
332         {
333                 return glu::getDataTypeScalarSize(type)*(int)sizeof(deUint32);
334         }
335 }
336
337 int getDataTypeByteAlignment (glu::DataType type)
338 {
339         switch (type)
340         {
341                 case glu::TYPE_FLOAT:
342                 case glu::TYPE_INT:
343                 case glu::TYPE_UINT:
344                 case glu::TYPE_BOOL:            return 1*(int)sizeof(deUint32);
345
346                 case glu::TYPE_FLOAT_VEC2:
347                 case glu::TYPE_INT_VEC2:
348                 case glu::TYPE_UINT_VEC2:
349                 case glu::TYPE_BOOL_VEC2:       return 2*(int)sizeof(deUint32);
350
351                 case glu::TYPE_FLOAT_VEC3:
352                 case glu::TYPE_INT_VEC3:
353                 case glu::TYPE_UINT_VEC3:
354                 case glu::TYPE_BOOL_VEC3:       // Fall-through to vec4
355
356                 case glu::TYPE_FLOAT_VEC4:
357                 case glu::TYPE_INT_VEC4:
358                 case glu::TYPE_UINT_VEC4:
359                 case glu::TYPE_BOOL_VEC4:       return 4*(int)sizeof(deUint32);
360
361                 case glu::TYPE_UINT8:
362                 case glu::TYPE_INT8     :                       return 1*(int)sizeof(deUint8);
363
364                 case glu::TYPE_UINT8_VEC2:
365                 case glu::TYPE_INT8_VEC2:               return 2*(int)sizeof(deUint8);
366
367                 case glu::TYPE_UINT8_VEC3:
368                 case glu::TYPE_INT8_VEC3:               // Fall-through to vec4
369
370                 case glu::TYPE_UINT8_VEC4:
371                 case glu::TYPE_INT8_VEC4:               return 4*(int)sizeof(deUint8);
372
373                 case glu::TYPE_UINT16:
374                 case glu::TYPE_INT16:
375                 case glu::TYPE_FLOAT16:                 return 1*(int)sizeof(deUint16);
376
377                 case glu::TYPE_UINT16_VEC2:
378                 case glu::TYPE_INT16_VEC2:
379                 case glu::TYPE_FLOAT16_VEC2:    return 2*(int)sizeof(deUint16);
380
381                 case glu::TYPE_UINT16_VEC3:
382                 case glu::TYPE_INT16_VEC3:
383                 case glu::TYPE_FLOAT16_VEC3:    // Fall-through to vec4
384
385                 case glu::TYPE_UINT16_VEC4:
386                 case glu::TYPE_INT16_VEC4:
387                 case glu::TYPE_FLOAT16_VEC4:    return 4*(int)sizeof(deUint16);
388
389                 default:
390                         DE_ASSERT(false);
391                         return 0;
392         }
393 }
394
395 deInt32 getminUniformBufferOffsetAlignment (Context &ctx)
396 {
397         VkPhysicalDeviceProperties properties;
398         ctx.getInstanceInterface().getPhysicalDeviceProperties(ctx.getPhysicalDevice(), &properties);
399         VkDeviceSize align = properties.limits.minUniformBufferOffsetAlignment;
400         DE_ASSERT(align == (VkDeviceSize)(deInt32)align);
401         return (deInt32)align;
402 }
403
404
405 int computeStd140BaseAlignment (const VarType& type, deUint32 layoutFlags)
406 {
407         const int vec4Alignment = (int)sizeof(deUint32)*4;
408
409         if (type.isBasicType())
410         {
411                 glu::DataType basicType = type.getBasicType();
412
413                 if (glu::isDataTypeMatrix(basicType))
414                 {
415                         const bool      isRowMajor      = !!(layoutFlags & LAYOUT_ROW_MAJOR);
416                         const int       vecSize         = isRowMajor ? glu::getDataTypeMatrixNumColumns(basicType)
417                                                                                                  : glu::getDataTypeMatrixNumRows(basicType);
418                         const int       vecAlign        = deAlign32(getDataTypeByteAlignment(glu::getDataTypeFloatVec(vecSize)), vec4Alignment);
419
420                         return vecAlign;
421                 }
422                 else
423                         return getDataTypeByteAlignment(basicType);
424         }
425         else if (type.isArrayType())
426         {
427                 int elemAlignment = computeStd140BaseAlignment(type.getElementType(), layoutFlags);
428
429                 // Round up to alignment of vec4
430                 return deAlign32(elemAlignment, vec4Alignment);
431         }
432         else
433         {
434                 DE_ASSERT(type.isStructType());
435
436                 int maxBaseAlignment = 0;
437
438                 for (StructType::ConstIterator memberIter = type.getStructPtr()->begin(); memberIter != type.getStructPtr()->end(); memberIter++)
439                         maxBaseAlignment = de::max(maxBaseAlignment, computeStd140BaseAlignment(memberIter->getType(), layoutFlags));
440
441                 return deAlign32(maxBaseAlignment, vec4Alignment);
442         }
443 }
444
445 int computeStd430BaseAlignment (const VarType& type, deUint32 layoutFlags)
446 {
447         // Otherwise identical to std140 except that alignment of structures and arrays
448         // are not rounded up to alignment of vec4.
449
450         if (type.isBasicType())
451         {
452                 glu::DataType basicType = type.getBasicType();
453
454                 if (glu::isDataTypeMatrix(basicType))
455                 {
456                         const bool      isRowMajor      = !!(layoutFlags & LAYOUT_ROW_MAJOR);
457                         const int       vecSize         = isRowMajor ? glu::getDataTypeMatrixNumColumns(basicType)
458                                                                                                  : glu::getDataTypeMatrixNumRows(basicType);
459                         const int       vecAlign        = getDataTypeByteAlignment(glu::getDataTypeFloatVec(vecSize));
460                         return vecAlign;
461                 }
462                 else
463                         return getDataTypeByteAlignment(basicType);
464         }
465         else if (type.isArrayType())
466         {
467                 return computeStd430BaseAlignment(type.getElementType(), layoutFlags);
468         }
469         else
470         {
471                 DE_ASSERT(type.isStructType());
472
473                 int maxBaseAlignment = 0;
474
475                 for (StructType::ConstIterator memberIter = type.getStructPtr()->begin(); memberIter != type.getStructPtr()->end(); memberIter++)
476                         maxBaseAlignment = de::max(maxBaseAlignment, computeStd430BaseAlignment(memberIter->getType(), layoutFlags));
477
478                 return maxBaseAlignment;
479         }
480 }
481
482 int computeRelaxedBlockBaseAlignment (const VarType& type, deUint32 layoutFlags)
483 {
484         if (type.isBasicType())
485         {
486                 glu::DataType basicType = type.getBasicType();
487
488                 if (glu::isDataTypeVector(basicType))
489                         return getDataTypeByteAlignment(glu::getDataTypeScalarType(basicType));
490
491                 if (glu::isDataTypeMatrix(basicType))
492                 {
493                         const bool      isRowMajor      = !!(layoutFlags & LAYOUT_ROW_MAJOR);
494                         const int       vecSize         = isRowMajor ? glu::getDataTypeMatrixNumColumns(basicType)
495                                                                                                  : glu::getDataTypeMatrixNumRows(basicType);
496                         const int       vecAlign        = getDataTypeByteAlignment(glu::getDataTypeFloatVec(vecSize));
497                         return vecAlign;
498                 }
499                 else
500                         return getDataTypeByteAlignment(basicType);
501         }
502         else if (type.isArrayType())
503                 return computeStd430BaseAlignment(type.getElementType(), layoutFlags);
504         else
505         {
506                 DE_ASSERT(type.isStructType());
507
508                 int maxBaseAlignment = 0;
509                 for (StructType::ConstIterator memberIter = type.getStructPtr()->begin(); memberIter != type.getStructPtr()->end(); memberIter++)
510                         maxBaseAlignment = de::max(maxBaseAlignment, computeRelaxedBlockBaseAlignment(memberIter->getType(), layoutFlags));
511
512                 return maxBaseAlignment;
513         }
514 }
515
516 int computeScalarBlockAlignment (const VarType& type, deUint32 layoutFlags)
517 {
518         if (type.isBasicType())
519         {
520                 return getDataTypeByteAlignment(glu::getDataTypeScalarType(type.getBasicType()));
521         }
522         else if (type.isArrayType())
523                 return computeScalarBlockAlignment(type.getElementType(), layoutFlags);
524         else
525         {
526                 DE_ASSERT(type.isStructType());
527
528                 int maxBaseAlignment = 0;
529                 for (StructType::ConstIterator memberIter = type.getStructPtr()->begin(); memberIter != type.getStructPtr()->end(); memberIter++)
530                         maxBaseAlignment = de::max(maxBaseAlignment, computeScalarBlockAlignment(memberIter->getType(), layoutFlags));
531
532                 return maxBaseAlignment;
533         }
534 }
535
536 inline deUint32 mergeLayoutFlags (deUint32 prevFlags, deUint32 newFlags)
537 {
538         const deUint32  packingMask             = LAYOUT_STD140|LAYOUT_STD430|LAYOUT_SCALAR;
539         const deUint32  matrixMask              = LAYOUT_ROW_MAJOR|LAYOUT_COLUMN_MAJOR;
540
541         deUint32 mergedFlags = 0;
542
543         mergedFlags |= ((newFlags & packingMask)        ? newFlags : prevFlags) & packingMask;
544         mergedFlags |= ((newFlags & matrixMask)         ? newFlags : prevFlags) & matrixMask;
545
546         return mergedFlags;
547 }
548
549 //! Appends all child elements to layout, returns value that should be appended to offset.
550 int computeReferenceLayout (
551         UniformLayout&          layout,
552         int                                     curBlockNdx,
553         int                                     baseOffset,
554         const std::string&      curPrefix,
555         const VarType&          type,
556         deUint32                        layoutFlags)
557 {
558         // HACK to make code match SSBO tests
559         const int LAYOUT_RELAXED = 0;
560         // Reference layout uses std140 rules by default. std430 rules are
561         // choosen only for blocks that have std140 layout.
562         const int       baseAlignment           = (layoutFlags & LAYOUT_SCALAR)  != 0 ? computeScalarBlockAlignment(type, layoutFlags)                  :
563                                                                           (layoutFlags & LAYOUT_STD430)  != 0 ? computeStd430BaseAlignment(type, layoutFlags)           :
564                                                                           (layoutFlags & LAYOUT_RELAXED) != 0 ? computeRelaxedBlockBaseAlignment(type, layoutFlags)     :
565                                                                           computeStd140BaseAlignment(type, layoutFlags);
566         int                     curOffset                       = deAlign32(baseOffset, baseAlignment);
567         const int       topLevelArraySize       = 1; // Default values
568         const int       topLevelArrayStride     = 0;
569
570         if (type.isBasicType())
571         {
572                 const glu::DataType             basicType       = type.getBasicType();
573                 UniformLayoutEntry              entry;
574
575                 entry.name                                      = curPrefix;
576                 entry.type                                      = basicType;
577                 entry.arraySize                         = 1;
578                 entry.arrayStride                       = 0;
579                 entry.matrixStride                      = 0;
580                 entry.topLevelArraySize         = topLevelArraySize;
581                 entry.topLevelArrayStride       = topLevelArrayStride;
582                 entry.blockNdx                          = curBlockNdx;
583
584                 if (glu::isDataTypeMatrix(basicType))
585                 {
586                         // Array of vectors as specified in rules 5 & 7.
587                         const bool      isRowMajor                      = !!(layoutFlags & LAYOUT_ROW_MAJOR);
588                         const int       vecSize                         = isRowMajor ? glu::getDataTypeMatrixNumColumns(basicType)
589                                                                                                                  : glu::getDataTypeMatrixNumRows(basicType);
590                         const glu::DataType     vecType         = glu::getDataTypeFloatVec(vecSize);
591                         const int       numVecs                         = isRowMajor ? glu::getDataTypeMatrixNumRows(basicType)
592                                                                                                                  : glu::getDataTypeMatrixNumColumns(basicType);
593                         const int       vecStride                       = (layoutFlags & LAYOUT_SCALAR) ? getDataTypeByteSize(vecType) : baseAlignment;
594
595                         entry.offset            = curOffset;
596                         entry.matrixStride      = vecStride;
597                         entry.isRowMajor        = isRowMajor;
598
599                         curOffset += numVecs*entry.matrixStride;
600                 }
601                 else
602                 {
603                         if (!(layoutFlags & LAYOUT_SCALAR) && (layoutFlags & LAYOUT_RELAXED) &&
604                                 glu::isDataTypeVector(basicType) && (getDataTypeByteSize(basicType) <= 16 ? curOffset / 16 != (curOffset +  getDataTypeByteSize(basicType) - 1) / 16 : curOffset % 16 != 0))
605                                 curOffset = deIntRoundToPow2(curOffset, 16);
606
607                         // Scalar or vector.
608                         entry.offset = curOffset;
609
610                         curOffset += getDataTypeByteSize(basicType);
611                 }
612
613                 layout.uniforms.push_back(entry);
614         }
615         else if (type.isArrayType())
616         {
617                 const VarType&  elemType        = type.getElementType();
618
619                 if (elemType.isBasicType() && !glu::isDataTypeMatrix(elemType.getBasicType()))
620                 {
621                         // Array of scalars or vectors.
622                         const glu::DataType             elemBasicType   = elemType.getBasicType();
623                         const int                               stride                  = (layoutFlags & LAYOUT_SCALAR) ? getDataTypeByteSize(elemBasicType) : baseAlignment;
624                         UniformLayoutEntry              entry;
625
626                         entry.name                                      = curPrefix + "[0]"; // Array variables are always postfixed with [0]
627                         entry.type                                      = elemBasicType;
628                         entry.blockNdx                          = curBlockNdx;
629                         entry.offset                            = curOffset;
630                         entry.arraySize                         = type.getArraySize();
631                         entry.arrayStride                       = stride;
632                         entry.matrixStride                      = 0;
633                         entry.topLevelArraySize         = topLevelArraySize;
634                         entry.topLevelArrayStride       = topLevelArrayStride;
635
636                         curOffset += stride*type.getArraySize();
637
638                         layout.uniforms.push_back(entry);
639                 }
640                 else if (elemType.isBasicType() && glu::isDataTypeMatrix(elemType.getBasicType()))
641                 {
642                         // Array of matrices.
643                         const glu::DataType                     elemBasicType   = elemType.getBasicType();
644                         const bool                                      isRowMajor              = !!(layoutFlags & LAYOUT_ROW_MAJOR);
645                         const int                                       vecSize                 = isRowMajor ? glu::getDataTypeMatrixNumColumns(elemBasicType)
646                                                                                                                                          : glu::getDataTypeMatrixNumRows(elemBasicType);
647                         const glu::DataType                     vecType                 = glu::getDataTypeFloatVec(vecSize);
648                         const int                                       numVecs                 = isRowMajor ? glu::getDataTypeMatrixNumRows(elemBasicType)
649                                                                                                                                          : glu::getDataTypeMatrixNumColumns(elemBasicType);
650                         const int                                       vecStride               = (layoutFlags & LAYOUT_SCALAR) ? getDataTypeByteSize(vecType) : baseAlignment;
651                         UniformLayoutEntry                      entry;
652
653                         entry.name                                      = curPrefix + "[0]"; // Array variables are always postfixed with [0]
654                         entry.type                                      = elemBasicType;
655                         entry.blockNdx                          = curBlockNdx;
656                         entry.offset                            = curOffset;
657                         entry.arraySize                         = type.getArraySize();
658                         entry.arrayStride                       = vecStride*numVecs;
659                         entry.matrixStride                      = vecStride;
660                         entry.isRowMajor                        = isRowMajor;
661                         entry.topLevelArraySize         = topLevelArraySize;
662                         entry.topLevelArrayStride       = topLevelArrayStride;
663
664                         curOffset += entry.arrayStride*type.getArraySize();
665
666                         layout.uniforms.push_back(entry);
667                 }
668                 else
669                 {
670                         DE_ASSERT(elemType.isStructType() || elemType.isArrayType());
671
672                         for (int elemNdx = 0; elemNdx < type.getArraySize(); elemNdx++)
673                                 curOffset += computeReferenceLayout(layout, curBlockNdx, curOffset, curPrefix + "[" + de::toString(elemNdx) + "]", type.getElementType(), layoutFlags);
674                 }
675         }
676         else
677         {
678                 DE_ASSERT(type.isStructType());
679
680                 for (StructType::ConstIterator memberIter = type.getStructPtr()->begin(); memberIter != type.getStructPtr()->end(); memberIter++)
681                         curOffset += computeReferenceLayout(layout, curBlockNdx, curOffset, curPrefix + "." + memberIter->getName(), memberIter->getType(), layoutFlags);
682
683                 if (!(layoutFlags & LAYOUT_SCALAR))
684                         curOffset = deAlign32(curOffset, baseAlignment);
685         }
686
687         return curOffset-baseOffset;
688 }
689
690 void computeReferenceLayout (UniformLayout& layout, const ShaderInterface& interface)
691 {
692         int numUniformBlocks = interface.getNumUniformBlocks();
693
694         for (int blockNdx = 0; blockNdx < numUniformBlocks; blockNdx++)
695         {
696                 const UniformBlock&     block                   = interface.getUniformBlock(blockNdx);
697                 bool                            hasInstanceName = block.hasInstanceName();
698                 std::string                     blockPrefix             = hasInstanceName ? (block.getBlockName() + ".") : "";
699                 int                                     curOffset               = 0;
700                 int                                     activeBlockNdx  = (int)layout.blocks.size();
701                 int                                     firstUniformNdx = (int)layout.uniforms.size();
702
703                 for (UniformBlock::ConstIterator uniformIter = block.begin(); uniformIter != block.end(); uniformIter++)
704                 {
705                         const Uniform& uniform = *uniformIter;
706                         curOffset += computeReferenceLayout(layout, activeBlockNdx, curOffset, blockPrefix + uniform.getName(), uniform.getType(), mergeLayoutFlags(block.getFlags(), uniform.getFlags()));
707                 }
708
709                 int     uniformIndicesEnd       = (int)layout.uniforms.size();
710                 int     blockSize                       = curOffset;
711                 int     numInstances            = block.isArray() ? block.getArraySize() : 1;
712
713                 // Create block layout entries for each instance.
714                 for (int instanceNdx = 0; instanceNdx < numInstances; instanceNdx++)
715                 {
716                         // Allocate entry for instance.
717                         layout.blocks.push_back(BlockLayoutEntry());
718                         BlockLayoutEntry& blockEntry = layout.blocks.back();
719
720                         blockEntry.name = block.getBlockName();
721                         blockEntry.size = blockSize;
722                         blockEntry.bindingNdx = blockNdx;
723                         blockEntry.blockDeclarationNdx = blockNdx;
724                         blockEntry.instanceNdx = instanceNdx;
725
726                         // Compute active uniform set for block.
727                         for (int uniformNdx = firstUniformNdx; uniformNdx < uniformIndicesEnd; uniformNdx++)
728                                 blockEntry.activeUniformIndices.push_back(uniformNdx);
729
730                         if (block.isArray())
731                                 blockEntry.name += "[" + de::toString(instanceNdx) + "]";
732                 }
733         }
734 }
735
736 // Value generator.
737
738 void generateValue (const UniformLayoutEntry& entry, void* basePtr, de::Random& rnd)
739 {
740         glu::DataType   scalarType              = glu::getDataTypeScalarType(entry.type);
741         int                             scalarSize              = glu::getDataTypeScalarSize(entry.type);
742         bool                    isMatrix                = glu::isDataTypeMatrix(entry.type);
743         int                             numVecs                 = isMatrix ? (entry.isRowMajor ? glu::getDataTypeMatrixNumRows(entry.type) : glu::getDataTypeMatrixNumColumns(entry.type)) : 1;
744         int                             vecSize                 = scalarSize / numVecs;
745         bool                    isArray                 = entry.size > 1;
746         const size_t    compSize                = getDataTypeByteSize(scalarType);
747
748         DE_ASSERT(scalarSize%numVecs == 0);
749
750         for (int elemNdx = 0; elemNdx < entry.size; elemNdx++)
751         {
752                 deUint8* elemPtr = (deUint8*)basePtr + entry.offset + (isArray ? elemNdx*entry.arrayStride : 0);
753
754                 for (int vecNdx = 0; vecNdx < numVecs; vecNdx++)
755                 {
756                         deUint8* vecPtr = elemPtr + (isMatrix ? vecNdx*entry.matrixStride : 0);
757
758                         for (int compNdx = 0; compNdx < vecSize; compNdx++)
759                         {
760                                 deUint8* compPtr = vecPtr + compSize*compNdx;
761
762                                 switch (scalarType)
763                                 {
764                                         case glu::TYPE_FLOAT:   *((float*)compPtr)              = (float)rnd.getInt(-9, 9);                                             break;
765                                         case glu::TYPE_INT:             *((int*)compPtr)                = rnd.getInt(-9, 9);                                                    break;
766                                         case glu::TYPE_UINT:    *((deUint32*)compPtr)   = (deUint32)rnd.getInt(0, 9);                                   break;
767                                         case glu::TYPE_INT8:    *((deInt8*)compPtr)             = (deInt8)rnd.getInt(-9, 9);                                    break;
768                                         case glu::TYPE_UINT8:   *((deUint8*)compPtr)    = (deUint8)rnd.getInt(0, 9);                                    break;
769                                         case glu::TYPE_INT16:   *((deInt16*)compPtr)    = (deInt16)rnd.getInt(-9, 9);                                   break;
770                                         case glu::TYPE_UINT16:  *((deUint16*)compPtr)   = (deUint16)rnd.getInt(0, 9);                                   break;
771                                         case glu::TYPE_FLOAT16: *((deFloat16*)compPtr)  = deFloat32To16((float)rnd.getInt(-9, 9));              break;
772                                         // \note Random bit pattern is used for true values. Spec states that all non-zero values are
773                                         //       interpreted as true but some implementations fail this.
774                                         case glu::TYPE_BOOL:    *((deUint32*)compPtr)   = rnd.getBool() ? rnd.getUint32()|1u : 0u;              break;
775                                         default:
776                                                 DE_ASSERT(false);
777                                 }
778                         }
779                 }
780         }
781 }
782
783 void generateValues (const UniformLayout& layout, const std::map<int, void*>& blockPointers, deUint32 seed)
784 {
785         de::Random      rnd                     (seed);
786         int                     numBlocks       = (int)layout.blocks.size();
787
788         for (int blockNdx = 0; blockNdx < numBlocks; blockNdx++)
789         {
790                 void*   basePtr         = blockPointers.find(blockNdx)->second;
791                 int             numEntries      = (int)layout.blocks[blockNdx].activeUniformIndices.size();
792
793                 for (int entryNdx = 0; entryNdx < numEntries; entryNdx++)
794                 {
795                         const UniformLayoutEntry& entry = layout.uniforms[layout.blocks[blockNdx].activeUniformIndices[entryNdx]];
796                         generateValue(entry, basePtr, rnd);
797                 }
798         }
799 }
800
801 // Shader generator.
802
803 const char* getCompareFuncForType (glu::DataType type)
804 {
805         switch (type)
806         {
807                 case glu::TYPE_FLOAT:                   return "mediump float compare_float    (highp float a, highp float b)  { return abs(a - b) < 0.05 ? 1.0 : 0.0; }\n";
808                 case glu::TYPE_FLOAT_VEC2:              return "mediump float compare_vec2     (highp vec2 a, highp vec2 b)    { return compare_float(a.x, b.x)*compare_float(a.y, b.y); }\n";
809                 case glu::TYPE_FLOAT_VEC3:              return "mediump float compare_vec3     (highp vec3 a, highp vec3 b)    { return compare_float(a.x, b.x)*compare_float(a.y, b.y)*compare_float(a.z, b.z); }\n";
810                 case glu::TYPE_FLOAT_VEC4:              return "mediump float compare_vec4     (highp vec4 a, highp vec4 b)    { return compare_float(a.x, b.x)*compare_float(a.y, b.y)*compare_float(a.z, b.z)*compare_float(a.w, b.w); }\n";
811                 case glu::TYPE_FLOAT_MAT2:              return "mediump float compare_mat2     (highp mat2 a, highp mat2 b)    { return compare_vec2(a[0], b[0])*compare_vec2(a[1], b[1]); }\n";
812                 case glu::TYPE_FLOAT_MAT2X3:    return "mediump float compare_mat2x3   (highp mat2x3 a, highp mat2x3 b){ return compare_vec3(a[0], b[0])*compare_vec3(a[1], b[1]); }\n";
813                 case glu::TYPE_FLOAT_MAT2X4:    return "mediump float compare_mat2x4   (highp mat2x4 a, highp mat2x4 b){ return compare_vec4(a[0], b[0])*compare_vec4(a[1], b[1]); }\n";
814                 case glu::TYPE_FLOAT_MAT3X2:    return "mediump float compare_mat3x2   (highp mat3x2 a, highp mat3x2 b){ return compare_vec2(a[0], b[0])*compare_vec2(a[1], b[1])*compare_vec2(a[2], b[2]); }\n";
815                 case glu::TYPE_FLOAT_MAT3:              return "mediump float compare_mat3     (highp mat3 a, highp mat3 b)    { return compare_vec3(a[0], b[0])*compare_vec3(a[1], b[1])*compare_vec3(a[2], b[2]); }\n";
816                 case glu::TYPE_FLOAT_MAT3X4:    return "mediump float compare_mat3x4   (highp mat3x4 a, highp mat3x4 b){ return compare_vec4(a[0], b[0])*compare_vec4(a[1], b[1])*compare_vec4(a[2], b[2]); }\n";
817                 case glu::TYPE_FLOAT_MAT4X2:    return "mediump float compare_mat4x2   (highp mat4x2 a, highp mat4x2 b){ return compare_vec2(a[0], b[0])*compare_vec2(a[1], b[1])*compare_vec2(a[2], b[2])*compare_vec2(a[3], b[3]); }\n";
818                 case glu::TYPE_FLOAT_MAT4X3:    return "mediump float compare_mat4x3   (highp mat4x3 a, highp mat4x3 b){ return compare_vec3(a[0], b[0])*compare_vec3(a[1], b[1])*compare_vec3(a[2], b[2])*compare_vec3(a[3], b[3]); }\n";
819                 case glu::TYPE_FLOAT_MAT4:              return "mediump float compare_mat4     (highp mat4 a, highp mat4 b)    { return compare_vec4(a[0], b[0])*compare_vec4(a[1], b[1])*compare_vec4(a[2], b[2])*compare_vec4(a[3], b[3]); }\n";
820                 case glu::TYPE_INT:                             return "mediump float compare_int      (highp int a, highp int b)      { return a == b ? 1.0 : 0.0; }\n";
821                 case glu::TYPE_INT_VEC2:                return "mediump float compare_ivec2    (highp ivec2 a, highp ivec2 b)  { return a == b ? 1.0 : 0.0; }\n";
822                 case glu::TYPE_INT_VEC3:                return "mediump float compare_ivec3    (highp ivec3 a, highp ivec3 b)  { return a == b ? 1.0 : 0.0; }\n";
823                 case glu::TYPE_INT_VEC4:                return "mediump float compare_ivec4    (highp ivec4 a, highp ivec4 b)  { return a == b ? 1.0 : 0.0; }\n";
824                 case glu::TYPE_UINT:                    return "mediump float compare_uint     (highp uint a, highp uint b)    { return a == b ? 1.0 : 0.0; }\n";
825                 case glu::TYPE_UINT_VEC2:               return "mediump float compare_uvec2    (highp uvec2 a, highp uvec2 b)  { return a == b ? 1.0 : 0.0; }\n";
826                 case glu::TYPE_UINT_VEC3:               return "mediump float compare_uvec3    (highp uvec3 a, highp uvec3 b)  { return a == b ? 1.0 : 0.0; }\n";
827                 case glu::TYPE_UINT_VEC4:               return "mediump float compare_uvec4    (highp uvec4 a, highp uvec4 b)  { return a == b ? 1.0 : 0.0; }\n";
828                 case glu::TYPE_BOOL:                    return "mediump float compare_bool     (bool a, bool b)                { return a == b ? 1.0 : 0.0; }\n";
829                 case glu::TYPE_BOOL_VEC2:               return "mediump float compare_bvec2    (bvec2 a, bvec2 b)              { return a == b ? 1.0 : 0.0; }\n";
830                 case glu::TYPE_BOOL_VEC3:               return "mediump float compare_bvec3    (bvec3 a, bvec3 b)              { return a == b ? 1.0 : 0.0; }\n";
831                 case glu::TYPE_BOOL_VEC4:               return "mediump float compare_bvec4    (bvec4 a, bvec4 b)              { return a == b ? 1.0 : 0.0; }\n";
832                 case glu::TYPE_FLOAT16:                 return "mediump float compare_float16_t(highp float a, highp float b)  { return abs(a - b) < 0.05 ? 1.0 : 0.0; }\n";
833                 case glu::TYPE_FLOAT16_VEC2:    return "mediump float compare_f16vec2  (highp vec2 a, highp vec2 b)    { return compare_float(a.x, b.x)*compare_float(a.y, b.y); }\n";
834                 case glu::TYPE_FLOAT16_VEC3:    return "mediump float compare_f16vec3  (highp vec3 a, highp vec3 b)    { return compare_float(a.x, b.x)*compare_float(a.y, b.y)*compare_float(a.z, b.z); }\n";
835                 case glu::TYPE_FLOAT16_VEC4:    return "mediump float compare_f16vec4  (highp vec4 a, highp vec4 b)    { return compare_float(a.x, b.x)*compare_float(a.y, b.y)*compare_float(a.z, b.z)*compare_float(a.w, b.w); }\n";
836                 case glu::TYPE_INT8:                    return "mediump float compare_int8_t   (highp int a, highp int b)      { return a == b ? 1.0 : 0.0; }\n";
837                 case glu::TYPE_INT8_VEC2:               return "mediump float compare_i8vec2   (highp ivec2 a, highp ivec2 b)  { return a == b ? 1.0 : 0.0; }\n";
838                 case glu::TYPE_INT8_VEC3:               return "mediump float compare_i8vec3   (highp ivec3 a, highp ivec3 b)  { return a == b ? 1.0 : 0.0; }\n";
839                 case glu::TYPE_INT8_VEC4:               return "mediump float compare_i8vec4   (highp ivec4 a, highp ivec4 b)  { return a == b ? 1.0 : 0.0; }\n";
840                 case glu::TYPE_UINT8:                   return "mediump float compare_uint8_t  (highp uint a, highp uint b)    { return a == b ? 1.0 : 0.0; }\n";
841                 case glu::TYPE_UINT8_VEC2:              return "mediump float compare_u8vec2   (highp uvec2 a, highp uvec2 b)  { return a == b ? 1.0 : 0.0; }\n";
842                 case glu::TYPE_UINT8_VEC3:              return "mediump float compare_u8vec3   (highp uvec3 a, highp uvec3 b)  { return a == b ? 1.0 : 0.0; }\n";
843                 case glu::TYPE_UINT8_VEC4:              return "mediump float compare_u8vec4   (highp uvec4 a, highp uvec4 b)  { return a == b ? 1.0 : 0.0; }\n";
844                 case glu::TYPE_INT16:                   return "mediump float compare_int16_t  (highp int a, highp int b)      { return a == b ? 1.0 : 0.0; }\n";
845                 case glu::TYPE_INT16_VEC2:              return "mediump float compare_i16vec2  (highp ivec2 a, highp ivec2 b)  { return a == b ? 1.0 : 0.0; }\n";
846                 case glu::TYPE_INT16_VEC3:              return "mediump float compare_i16vec3  (highp ivec3 a, highp ivec3 b)  { return a == b ? 1.0 : 0.0; }\n";
847                 case glu::TYPE_INT16_VEC4:              return "mediump float compare_i16vec4  (highp ivec4 a, highp ivec4 b)  { return a == b ? 1.0 : 0.0; }\n";
848                 case glu::TYPE_UINT16:                  return "mediump float compare_uint16_t (highp uint a, highp uint b)    { return a == b ? 1.0 : 0.0; }\n";
849                 case glu::TYPE_UINT16_VEC2:             return "mediump float compare_u16vec2  (highp uvec2 a, highp uvec2 b)  { return a == b ? 1.0 : 0.0; }\n";
850                 case glu::TYPE_UINT16_VEC3:             return "mediump float compare_u16vec3  (highp uvec3 a, highp uvec3 b)  { return a == b ? 1.0 : 0.0; }\n";
851                 case glu::TYPE_UINT16_VEC4:             return "mediump float compare_u16vec4  (highp uvec4 a, highp uvec4 b)  { return a == b ? 1.0 : 0.0; }\n";
852                 default:
853                         DE_ASSERT(false);
854                         return DE_NULL;
855         }
856 }
857
858 void getCompareDependencies (std::set<glu::DataType>& compareFuncs, glu::DataType basicType)
859 {
860         switch (basicType)
861         {
862                 case glu::TYPE_FLOAT_VEC2:
863                 case glu::TYPE_FLOAT_VEC3:
864                 case glu::TYPE_FLOAT_VEC4:
865                 case glu::TYPE_FLOAT16_VEC2:
866                 case glu::TYPE_FLOAT16_VEC3:
867                 case glu::TYPE_FLOAT16_VEC4:
868                         compareFuncs.insert(glu::TYPE_FLOAT);
869                         compareFuncs.insert(basicType);
870                         break;
871
872                 case glu::TYPE_FLOAT_MAT2:
873                 case glu::TYPE_FLOAT_MAT2X3:
874                 case glu::TYPE_FLOAT_MAT2X4:
875                 case glu::TYPE_FLOAT_MAT3X2:
876                 case glu::TYPE_FLOAT_MAT3:
877                 case glu::TYPE_FLOAT_MAT3X4:
878                 case glu::TYPE_FLOAT_MAT4X2:
879                 case glu::TYPE_FLOAT_MAT4X3:
880                 case glu::TYPE_FLOAT_MAT4:
881                         compareFuncs.insert(glu::TYPE_FLOAT);
882                         compareFuncs.insert(glu::getDataTypeFloatVec(glu::getDataTypeMatrixNumRows(basicType)));
883                         compareFuncs.insert(basicType);
884                         break;
885
886                 default:
887                         compareFuncs.insert(basicType);
888                         break;
889         }
890 }
891
892 void collectUniqueBasicTypes (std::set<glu::DataType>& basicTypes, const VarType& type)
893 {
894         if (type.isStructType())
895         {
896                 for (StructType::ConstIterator iter = type.getStruct().begin(); iter != type.getStruct().end(); ++iter)
897                         collectUniqueBasicTypes(basicTypes, iter->getType());
898         }
899         else if (type.isArrayType())
900                 collectUniqueBasicTypes(basicTypes, type.getElementType());
901         else
902         {
903                 DE_ASSERT(type.isBasicType());
904                 basicTypes.insert(type.getBasicType());
905         }
906 }
907
908 void collectUniqueBasicTypes (std::set<glu::DataType>& basicTypes, const UniformBlock& uniformBlock)
909 {
910         for (UniformBlock::ConstIterator iter = uniformBlock.begin(); iter != uniformBlock.end(); ++iter)
911                 collectUniqueBasicTypes(basicTypes, iter->getType());
912 }
913
914 void collectUniqueBasicTypes (std::set<glu::DataType>& basicTypes, const ShaderInterface& interface)
915 {
916         for (int ndx = 0; ndx < interface.getNumUniformBlocks(); ++ndx)
917                 collectUniqueBasicTypes(basicTypes, interface.getUniformBlock(ndx));
918 }
919
920 void generateCompareFuncs (std::ostream& str, const ShaderInterface& interface)
921 {
922         std::set<glu::DataType> types;
923         std::set<glu::DataType> compareFuncs;
924
925         // Collect unique basic types
926         collectUniqueBasicTypes(types, interface);
927
928         // Set of compare functions required
929         for (std::set<glu::DataType>::const_iterator iter = types.begin(); iter != types.end(); ++iter)
930         {
931                 getCompareDependencies(compareFuncs, *iter);
932         }
933
934         for (int type = 0; type < glu::TYPE_LAST; ++type)
935         {
936                 if (compareFuncs.find(glu::DataType(type)) != compareFuncs.end())
937                         str << getCompareFuncForType(glu::DataType(type));
938         }
939 }
940
941 struct Indent
942 {
943         int level;
944         Indent (int level_) : level(level_) {}
945 };
946
947 std::ostream& operator<< (std::ostream& str, const Indent& indent)
948 {
949         for (int i = 0; i < indent.level; i++)
950                 str << "\t";
951         return str;
952 }
953
954 void            generateDeclaration                     (std::ostringstream& src, const VarType& type, const std::string& name, int indentLevel, deUint32 unusedHints, deUint32 flagsMask, deUint32 offset);
955 void            generateDeclaration                     (std::ostringstream& src, const Uniform& uniform, int indentLevel, deUint32 offset);
956 void            generateDeclaration                     (std::ostringstream& src, const StructType& structType, int indentLevel);
957
958 void            generateLocalDeclaration        (std::ostringstream& src, const StructType& structType, int indentLevel);
959 void            generateFullDeclaration         (std::ostringstream& src, const StructType& structType, int indentLevel);
960
961 void generateDeclaration (std::ostringstream& src, const StructType& structType, int indentLevel)
962 {
963         DE_ASSERT(structType.hasTypeName());
964         generateFullDeclaration(src, structType, indentLevel);
965         src << ";\n";
966 }
967
968 void generateFullDeclaration (std::ostringstream& src, const StructType& structType, int indentLevel)
969 {
970         src << "struct";
971         if (structType.hasTypeName())
972                 src << " " << structType.getTypeName();
973         src << "\n" << Indent(indentLevel) << "{\n";
974
975         for (StructType::ConstIterator memberIter = structType.begin(); memberIter != structType.end(); memberIter++)
976         {
977                 src << Indent(indentLevel + 1);
978                 generateDeclaration(src, memberIter->getType(), memberIter->getName(), indentLevel + 1, memberIter->getFlags() & UNUSED_BOTH, ~LAYOUT_OFFSET, 0u);
979         }
980
981         src << Indent(indentLevel) << "}";
982 }
983
984 void generateLocalDeclaration (std::ostringstream& src, const StructType& structType, int /* indentLevel */)
985 {
986         src << structType.getTypeName();
987 }
988
989 void generateLayoutAndPrecisionDeclaration (std::ostringstream& src, deUint32 flags, deUint32 offset)
990 {
991         if ((flags & LAYOUT_MASK) != 0)
992                 src << "layout(" << LayoutFlagsFmt(flags & LAYOUT_MASK, offset) << ") ";
993
994         if ((flags & PRECISION_MASK) != 0)
995                 src << PrecisionFlagsFmt(flags & PRECISION_MASK) << " ";
996 }
997
998 void generateDeclaration (std::ostringstream& src, const VarType& type, const std::string& name, int indentLevel, deUint32 unusedHints, deUint32 flagsMask, deUint32 offset)
999 {
1000         generateLayoutAndPrecisionDeclaration(src, type.getFlags() & flagsMask, offset);
1001
1002         if (type.isBasicType())
1003                 src << glu::getDataTypeName(type.getBasicType()) << " " << name;
1004         else if (type.isArrayType())
1005         {
1006                 std::vector<int>        arraySizes;
1007                 const VarType*          curType         = &type;
1008                 while (curType->isArrayType())
1009                 {
1010                         arraySizes.push_back(curType->getArraySize());
1011                         curType = &curType->getElementType();
1012                 }
1013
1014                 generateLayoutAndPrecisionDeclaration(src, curType->getFlags() & flagsMask, offset);
1015
1016                 if (curType->isBasicType())
1017                         src << glu::getDataTypeName(curType->getBasicType());
1018                 else
1019                 {
1020                         DE_ASSERT(curType->isStructType());
1021                         generateLocalDeclaration(src, curType->getStruct(), indentLevel+1);
1022                 }
1023
1024                 src << " " << name;
1025
1026                 for (std::vector<int>::const_iterator sizeIter = arraySizes.begin(); sizeIter != arraySizes.end(); sizeIter++)
1027                         src << "[" << *sizeIter << "]";
1028         }
1029         else
1030         {
1031                 generateLocalDeclaration(src, type.getStruct(), indentLevel+1);
1032                 src << " " << name;
1033         }
1034
1035         src << ";";
1036
1037         // Print out unused hints.
1038         if (unusedHints != 0)
1039                 src << " // unused in " << (unusedHints == UNUSED_BOTH          ? "both shaders"        :
1040                                                                         unusedHints == UNUSED_VERTEX    ? "vertex shader"       :
1041                                                                         unusedHints == UNUSED_FRAGMENT  ? "fragment shader" : "???");
1042
1043         src << "\n";
1044 }
1045
1046 void generateDeclaration (std::ostringstream& src, const Uniform& uniform, int indentLevel, deUint32 offset)
1047 {
1048         if ((uniform.getFlags() & LAYOUT_MASK) != 0)
1049                 src << "layout(" << LayoutFlagsFmt(uniform.getFlags() & LAYOUT_MASK) << ") ";
1050
1051         generateDeclaration(src, uniform.getType(), uniform.getName(), indentLevel, uniform.getFlags() & UNUSED_BOTH, ~0u, offset);
1052 }
1053
1054 deUint32 getBlockMemberOffset (int blockNdx, const UniformBlock& block, const Uniform& uniform, const UniformLayout& layout)
1055 {
1056         std::ostringstream      name;
1057         const VarType*          curType = &uniform.getType();
1058
1059         if (block.getInstanceName().length() != 0)
1060                 name << block.getBlockName() << ".";    // \note UniformLayoutEntry uses block name rather than instance name
1061
1062         name << uniform.getName();
1063
1064         while (!curType->isBasicType())
1065         {
1066                 if (curType->isArrayType())
1067                 {
1068                         name << "[0]";
1069                         curType = &curType->getElementType();
1070                 }
1071
1072                 if (curType->isStructType())
1073                 {
1074                         const StructType::ConstIterator firstMember = curType->getStruct().begin();
1075                         name << "." << firstMember->getName();
1076                         curType = &firstMember->getType();
1077                 }
1078         }
1079
1080         const int uniformNdx = layout.getUniformLayoutIndex(blockNdx, name.str());
1081         DE_ASSERT(uniformNdx >= 0);
1082
1083         return layout.uniforms[uniformNdx].offset;
1084 }
1085
1086 template<typename T>
1087 void semiShuffle (std::vector<T>& v)
1088 {
1089         const std::vector<T>    src     = v;
1090         int                                             i       = -1;
1091         int                                             n       = static_cast<int>(src.size());
1092
1093         v.clear();
1094
1095         while (n)
1096         {
1097                 i += n;
1098                 v.push_back(src[i]);
1099                 n = (n > 0 ? 1 - n : -1 - n);
1100         }
1101 }
1102
1103 template<typename T>
1104 //! \note Stores pointers to original elements
1105 class Traverser
1106 {
1107 public:
1108         template<typename Iter>
1109         Traverser (const Iter beg, const Iter end, const bool shuffled)
1110         {
1111                 for (Iter it = beg; it != end; ++it)
1112                         m_elements.push_back(&(*it));
1113
1114                 if (shuffled)
1115                         semiShuffle(m_elements);
1116
1117                 m_next = m_elements.begin();
1118         }
1119
1120         T* next (void)
1121         {
1122                 if (m_next != m_elements.end())
1123                         return *m_next++;
1124                 else
1125                         return DE_NULL;
1126         }
1127
1128 private:
1129         typename std::vector<T*>                                        m_elements;
1130         typename std::vector<T*>::const_iterator        m_next;
1131 };
1132
1133 glu::DataType getPromoteType(glu::DataType type)
1134 {
1135         switch (type)
1136         {
1137         case glu::TYPE_UINT8:                   return glu::TYPE_UINT;
1138         case glu::TYPE_UINT8_VEC2:              return glu::TYPE_UINT_VEC2;
1139         case glu::TYPE_UINT8_VEC3:              return glu::TYPE_UINT_VEC3;
1140         case glu::TYPE_UINT8_VEC4:              return glu::TYPE_UINT_VEC4;
1141         case glu::TYPE_INT8:                    return glu::TYPE_INT;
1142         case glu::TYPE_INT8_VEC2:               return glu::TYPE_INT_VEC2;
1143         case glu::TYPE_INT8_VEC3:               return glu::TYPE_INT_VEC3;
1144         case glu::TYPE_INT8_VEC4:               return glu::TYPE_INT_VEC4;
1145         case glu::TYPE_UINT16:                  return glu::TYPE_UINT;
1146         case glu::TYPE_UINT16_VEC2:             return glu::TYPE_UINT_VEC2;
1147         case glu::TYPE_UINT16_VEC3:             return glu::TYPE_UINT_VEC3;
1148         case glu::TYPE_UINT16_VEC4:             return glu::TYPE_UINT_VEC4;
1149         case glu::TYPE_INT16:                   return glu::TYPE_INT;
1150         case glu::TYPE_INT16_VEC2:              return glu::TYPE_INT_VEC2;
1151         case glu::TYPE_INT16_VEC3:              return glu::TYPE_INT_VEC3;
1152         case glu::TYPE_INT16_VEC4:              return glu::TYPE_INT_VEC4;
1153         case glu::TYPE_FLOAT16:                 return glu::TYPE_FLOAT;
1154         case glu::TYPE_FLOAT16_VEC2:    return glu::TYPE_FLOAT_VEC2;
1155         case glu::TYPE_FLOAT16_VEC3:    return glu::TYPE_FLOAT_VEC3;
1156         case glu::TYPE_FLOAT16_VEC4:    return glu::TYPE_FLOAT_VEC4;
1157         default: return type;
1158         }
1159 }
1160
1161 void generateDeclaration (std::ostringstream& src, int blockNdx, const UniformBlock& block, const UniformLayout& layout, bool shuffleUniformMembers)
1162 {
1163         src << "layout(set = 0, binding = " << blockNdx;
1164         if ((block.getFlags() & LAYOUT_MASK) != 0)
1165                 src << ", " << LayoutFlagsFmt(block.getFlags() & LAYOUT_MASK);
1166         src << ") ";
1167
1168         src << "uniform " << block.getBlockName();
1169         src << "\n{\n";
1170
1171         Traverser<const Uniform> uniforms(block.begin(), block.end(), shuffleUniformMembers);
1172
1173         while (const Uniform* pUniform = uniforms.next())
1174         {
1175                 src << Indent(1);
1176                 generateDeclaration(src, *pUniform, 1 /* indent level */, getBlockMemberOffset(blockNdx, block, *pUniform, layout));
1177         }
1178
1179         src << "}";
1180
1181         if (block.hasInstanceName())
1182         {
1183                 src << " " << block.getInstanceName();
1184                 if (block.isArray())
1185                 {
1186                         if (block.getFlags() & LAYOUT_DESCRIPTOR_INDEXING)
1187                                 src << "[]";
1188                         else
1189                                 src << "[" << block.getArraySize() << "]";
1190                 }
1191         }
1192         else
1193                 DE_ASSERT(!block.isArray());
1194
1195         src << ";\n";
1196 }
1197
1198 void generateValueSrc (std::ostringstream& src, const UniformLayoutEntry& entry, const void* basePtr, int elementNdx)
1199 {
1200         glu::DataType   scalarType              = glu::getDataTypeScalarType(entry.type);
1201         int                             scalarSize              = glu::getDataTypeScalarSize(entry.type);
1202         bool                    isArray                 = entry.size > 1;
1203         const deUint8*  elemPtr                 = (const deUint8*)basePtr + entry.offset + (isArray ? elementNdx * entry.arrayStride : 0);
1204         const size_t    compSize                = getDataTypeByteSize(scalarType);
1205
1206         if (scalarSize > 1)
1207                 src << glu::getDataTypeName(getPromoteType(entry.type)) << "(";
1208
1209         if (glu::isDataTypeMatrix(entry.type))
1210         {
1211                 int     numRows = glu::getDataTypeMatrixNumRows(entry.type);
1212                 int     numCols = glu::getDataTypeMatrixNumColumns(entry.type);
1213
1214                 DE_ASSERT(scalarType == glu::TYPE_FLOAT);
1215
1216                 // Constructed in column-wise order.
1217                 for (int colNdx = 0; colNdx < numCols; colNdx++)
1218                 {
1219                         for (int rowNdx = 0; rowNdx < numRows; rowNdx++)
1220                         {
1221                                 const deUint8*  compPtr = elemPtr + (entry.isRowMajor ? (rowNdx * entry.matrixStride + colNdx * compSize)
1222                                                                                                                                           : (colNdx * entry.matrixStride + rowNdx * compSize));
1223
1224                                 if (colNdx > 0 || rowNdx > 0)
1225                                         src << ", ";
1226
1227                                 src << de::floatToString(*((const float*)compPtr), 1);
1228                         }
1229                 }
1230         }
1231         else
1232         {
1233                 for (int scalarNdx = 0; scalarNdx < scalarSize; scalarNdx++)
1234                 {
1235                         const deUint8* compPtr = elemPtr + scalarNdx * compSize;
1236
1237                         if (scalarNdx > 0)
1238                                 src << ", ";
1239
1240                         switch (scalarType)
1241                         {
1242                                 case glu::TYPE_FLOAT16: src << de::floatToString(deFloat16To32(*((const deFloat16*)compPtr)), 1);       break;
1243                                 case glu::TYPE_FLOAT:   src << de::floatToString(*((const float*)compPtr), 1);                  break;
1244                                 case glu::TYPE_INT8:    src << (deUint32)*((const deInt8*)compPtr);                                             break;
1245                                 case glu::TYPE_INT16:   src << *((const deInt16*)compPtr);                                                              break;
1246                                 case glu::TYPE_INT:             src << *((const int*)compPtr);                                                                  break;
1247                                 case glu::TYPE_UINT8:   src << (deUint32)*((const deUint8*)compPtr) << "u";                             break;
1248                                 case glu::TYPE_UINT16:  src << *((const deUint16*)compPtr) << "u";                                              break;
1249                                 case glu::TYPE_UINT:    src << *((const deUint32*)compPtr) << "u";                                              break;
1250                                 case glu::TYPE_BOOL:    src << (*((const deUint32*)compPtr) != 0u ? "true" : "false");  break;
1251                                 default:
1252                                         DE_ASSERT(false);
1253                         }
1254                 }
1255         }
1256
1257         if (scalarSize > 1)
1258                 src << ")";
1259 }
1260
1261 bool isMatrix (glu::DataType elementType)
1262 {
1263         return (elementType >= glu::TYPE_FLOAT_MAT2) && (elementType <= glu::TYPE_FLOAT_MAT4);
1264 }
1265
1266 void writeMatrixTypeSrc (int                                            columnCount,
1267                                                  int                                            rowCount,
1268                                                  std::string                            compare,
1269                                                  std::string                            compareType,
1270                                                  std::ostringstream&            src,
1271                                                  const std::string&                     srcName,
1272                                                  const void*                            basePtr,
1273                                                  const UniformLayoutEntry&      entry,
1274                                                  bool                                           vector)
1275 {
1276         if (vector)     // generateTestSrcMatrixPerVec
1277         {
1278                 for (int colNdex = 0; colNdex < columnCount; colNdex++)
1279                 {
1280                         src << "\tresult *= " << compare + compareType << "(" << srcName << "[" << colNdex << "], ";
1281
1282                         if (glu::isDataTypeMatrix(entry.type))
1283                         {
1284                                 int     scalarSize = glu::getDataTypeScalarSize(entry.type);
1285                                 const deUint8*  elemPtr                 = (const deUint8*)basePtr + entry.offset;
1286                                 const int               compSize                = sizeof(deUint32);
1287
1288                                 if (scalarSize > 1)
1289                                         src << compareType << "(";
1290                                 for (int rowNdex = 0; rowNdex < rowCount; rowNdex++)
1291                                 {
1292                                         const deUint8*  compPtr = elemPtr + (entry.isRowMajor ? (rowNdex * entry.matrixStride + colNdex * compSize)
1293                                                                                                                                                   : (colNdex * entry.matrixStride + rowNdex * compSize));
1294                                         src << de::floatToString(*((const float*)compPtr), 1);
1295
1296                                         if (rowNdex < rowCount-1)
1297                                                 src << ", ";
1298                                 }
1299                                 src << "));\n";
1300                         }
1301                         else
1302                         {
1303                                 generateValueSrc(src, entry, basePtr, 0);
1304                                 src << "[" << colNdex << "]);\n";
1305                         }
1306                 }
1307         }
1308         else            // generateTestSrcMatrixPerElement
1309         {
1310                 for (int colNdex = 0; colNdex < columnCount; colNdex++)
1311                 {
1312                         for (int rowNdex = 0; rowNdex < rowCount; rowNdex++)
1313                         {
1314                                 src << "\tresult *= " << compare + compareType << "(" << srcName << "[" << colNdex << "][" << rowNdex << "], ";
1315                                 if (glu::isDataTypeMatrix(entry.type))
1316                                 {
1317                                         const deUint8*  elemPtr                 = (const deUint8*)basePtr + entry.offset;
1318                                         const int               compSize                = sizeof(deUint32);
1319                                         const deUint8*  compPtr = elemPtr + (entry.isRowMajor ? (rowNdex * entry.matrixStride + colNdex * compSize)
1320                                                                                                                                                   : (colNdex * entry.matrixStride + rowNdex * compSize));
1321
1322                                         src << de::floatToString(*((const float*)compPtr), 1) << ");\n";
1323                                 }
1324                                 else
1325                                 {
1326                                         generateValueSrc(src, entry, basePtr, 0);
1327                                         src << "[" << colNdex << "][" << rowNdex << "]);\n";
1328                                 }
1329                         }
1330                 }
1331         }
1332 }
1333
1334 void generateTestSrcMatrixPerVec (glu::DataType                         elementType,
1335                                                                   std::ostringstream&           src,
1336                                                                   const std::string&            srcName,
1337                                                                   const void*                           basePtr,
1338                                                                   const UniformLayoutEntry&     entry,
1339                                                                   bool                                          vector)
1340 {
1341         std::string compare = "compare_";
1342         switch (elementType)
1343         {
1344                 case glu::TYPE_FLOAT_MAT2:
1345                         writeMatrixTypeSrc(2, 2, compare, "vec2", src, srcName, basePtr, entry, vector);
1346                         break;
1347
1348                 case glu::TYPE_FLOAT_MAT2X3:
1349                         writeMatrixTypeSrc(2, 3, compare, "vec3", src, srcName, basePtr, entry, vector);
1350                         break;
1351
1352                 case glu::TYPE_FLOAT_MAT2X4:
1353                         writeMatrixTypeSrc(2, 4, compare, "vec4", src, srcName, basePtr, entry, vector);
1354                         break;
1355
1356                 case glu::TYPE_FLOAT_MAT3X4:
1357                         writeMatrixTypeSrc(3, 4, compare, "vec4", src, srcName, basePtr, entry, vector);
1358                         break;
1359
1360                 case glu::TYPE_FLOAT_MAT4:
1361                         writeMatrixTypeSrc(4, 4, compare, "vec4", src, srcName, basePtr, entry, vector);
1362                         break;
1363
1364                 case glu::TYPE_FLOAT_MAT4X2:
1365                         writeMatrixTypeSrc(4, 2, compare, "vec2", src, srcName, basePtr, entry, vector);
1366                         break;
1367
1368                 case glu::TYPE_FLOAT_MAT4X3:
1369                         writeMatrixTypeSrc(4, 3, compare, "vec3", src, srcName, basePtr, entry, vector);
1370                         break;
1371
1372                 default:
1373                         break;
1374         }
1375 }
1376
1377 void generateTestSrcMatrixPerElement (glu::DataType                             elementType,
1378                                                                           std::ostringstream&           src,
1379                                                                           const std::string&            srcName,
1380                                                                           const void*                           basePtr,
1381                                                                           const UniformLayoutEntry&     entry,
1382                                                                           bool                                          vector)
1383 {
1384         std::string compare = "compare_";
1385         std::string compareType = "float";
1386         switch (elementType)
1387         {
1388                 case glu::TYPE_FLOAT_MAT2:
1389                         writeMatrixTypeSrc(2, 2, compare, compareType, src, srcName, basePtr, entry, vector);
1390                         break;
1391
1392                 case glu::TYPE_FLOAT_MAT2X3:
1393                         writeMatrixTypeSrc(2, 3, compare, compareType, src, srcName, basePtr, entry, vector);
1394                         break;
1395
1396                 case glu::TYPE_FLOAT_MAT2X4:
1397                         writeMatrixTypeSrc(2, 4, compare, compareType, src, srcName, basePtr, entry, vector);
1398                         break;
1399
1400                 case glu::TYPE_FLOAT_MAT3X4:
1401                         writeMatrixTypeSrc(3, 4, compare, compareType, src, srcName, basePtr, entry, vector);
1402                         break;
1403
1404                 case glu::TYPE_FLOAT_MAT4:
1405                         writeMatrixTypeSrc(4, 4, compare, compareType, src, srcName, basePtr, entry, vector);
1406                         break;
1407
1408                 case glu::TYPE_FLOAT_MAT4X2:
1409                         writeMatrixTypeSrc(4, 2, compare, compareType, src, srcName, basePtr, entry, vector);
1410                         break;
1411
1412                 case glu::TYPE_FLOAT_MAT4X3:
1413                         writeMatrixTypeSrc(4, 3, compare, compareType, src, srcName, basePtr, entry, vector);
1414                         break;
1415
1416                 default:
1417                         break;
1418         }
1419 }
1420
1421 void generateSingleCompare (std::ostringstream&                 src,
1422                                                         glu::DataType                           elementType,
1423                                                         const std::string&                      srcName,
1424                                                         const void*                                     basePtr,
1425                                                         const UniformLayoutEntry&       entry,
1426                                                         MatrixLoadFlags                         matrixLoadFlag)
1427 {
1428         if (matrixLoadFlag == LOAD_FULL_MATRIX)
1429         {
1430                 const char* typeName = glu::getDataTypeName(elementType);
1431                 const char* castName = "";
1432                 glu::DataType promoteType = getPromoteType(elementType);
1433                 if (elementType != promoteType)
1434                 {
1435                         castName = glu::getDataTypeName(promoteType);
1436                 }
1437
1438                 src << "\tresult *= compare_" << typeName << "(" << castName << "(" << srcName << "), ";
1439                 generateValueSrc(src, entry, basePtr, 0);
1440                 src << ");\n";
1441         }
1442         else
1443         {
1444                 if (isMatrix(elementType))
1445                 {
1446                         generateTestSrcMatrixPerVec             (elementType, src, srcName, basePtr, entry, true);
1447                         generateTestSrcMatrixPerElement (elementType, src, srcName, basePtr, entry, false);
1448                 }
1449         }
1450 }
1451
1452 void generateCompareSrc (std::ostringstream&    src,
1453                                                  const char*                    resultVar,
1454                                                  const VarType&                 type,
1455                                                  const std::string&             srcName,
1456                                                  const std::string&             apiName,
1457                                                  const UniformLayout&   layout,
1458                                                  int                                    blockNdx,
1459                                                  const void*                    basePtr,
1460                                                  deUint32                               unusedMask,
1461                                                  MatrixLoadFlags                matrixLoadFlag)
1462 {
1463         if (type.isBasicType() || (type.isArrayType() && type.getElementType().isBasicType()))
1464         {
1465                 // Basic type or array of basic types.
1466                 bool                                            isArray                 = type.isArrayType();
1467                 glu::DataType                           elementType             = isArray ? type.getElementType().getBasicType() : type.getBasicType();
1468                 const char*                                     typeName                = glu::getDataTypeName(elementType);
1469                 std::string                                     fullApiName             = std::string(apiName) + (isArray ? "[0]" : ""); // Arrays are always postfixed with [0]
1470                 int                                                     uniformNdx              = layout.getUniformLayoutIndex(blockNdx, fullApiName);
1471                 const UniformLayoutEntry&       entry                   = layout.uniforms[uniformNdx];
1472
1473                 const char* castName = "";
1474                 glu::DataType promoteType = getPromoteType(elementType);
1475                 if (elementType != promoteType)
1476                 {
1477                         castName = glu::getDataTypeName(promoteType);
1478                 }
1479
1480                 if (isArray)
1481                 {
1482                         for (int elemNdx = 0; elemNdx < type.getArraySize(); elemNdx++)
1483                         {
1484                                 src << "\tresult *= compare_" << typeName << "(" << castName << "(" << srcName << "[" << elemNdx << "]), ";
1485                                 generateValueSrc(src, entry, basePtr, elemNdx);
1486                                 src << ");\n";
1487                         }
1488                 }
1489                 else
1490                 {
1491                         generateSingleCompare(src, elementType, srcName, basePtr, entry, matrixLoadFlag);
1492                 }
1493         }
1494         else if (type.isArrayType())
1495         {
1496                 const VarType& elementType = type.getElementType();
1497
1498                 for (int elementNdx = 0; elementNdx < type.getArraySize(); elementNdx++)
1499                 {
1500                         std::string op = std::string("[") + de::toString(elementNdx) + "]";
1501                         std::string elementSrcName = std::string(srcName) + op;
1502                         std::string elementApiName = std::string(apiName) + op;
1503                         generateCompareSrc(src, resultVar, elementType, elementSrcName, elementApiName, layout, blockNdx, basePtr, unusedMask, LOAD_FULL_MATRIX);
1504                 }
1505         }
1506         else
1507         {
1508                 DE_ASSERT(type.isStructType());
1509
1510                 for (StructType::ConstIterator memberIter = type.getStruct().begin(); memberIter != type.getStruct().end(); memberIter++)
1511                 {
1512                         if (memberIter->getFlags() & unusedMask)
1513                                 continue; // Skip member.
1514
1515                         std::string op = std::string(".") + memberIter->getName();
1516                         std::string memberSrcName = std::string(srcName) + op;
1517                         std::string memberApiName = std::string(apiName) + op;
1518                         generateCompareSrc(src, resultVar, memberIter->getType(), memberSrcName, memberApiName, layout, blockNdx, basePtr, unusedMask, LOAD_FULL_MATRIX);
1519                 }
1520         }
1521 }
1522
1523 void generateCompareSrc (std::ostringstream& src,
1524                                                  const char* resultVar,
1525                                                  const ShaderInterface& interface,
1526                                                  const UniformLayout& layout,
1527                                                  const std::map<int,
1528                                                  void*>& blockPointers,
1529                                                  bool isVertex,
1530                                                  MatrixLoadFlags matrixLoadFlag)
1531 {
1532         deUint32 unusedMask = isVertex ? UNUSED_VERTEX : UNUSED_FRAGMENT;
1533
1534         for (int blockNdx = 0; blockNdx < interface.getNumUniformBlocks(); blockNdx++)
1535         {
1536                 const UniformBlock& block = interface.getUniformBlock(blockNdx);
1537
1538                 if ((block.getFlags() & (isVertex ? DECLARE_VERTEX : DECLARE_FRAGMENT)) == 0)
1539                         continue; // Skip.
1540
1541                 bool                    hasInstanceName = block.hasInstanceName();
1542                 bool                    isArray                 = block.isArray();
1543                 int                             numInstances    = isArray ? block.getArraySize() : 1;
1544                 std::string             apiPrefix               = hasInstanceName ? block.getBlockName() + "." : std::string("");
1545
1546                 DE_ASSERT(!isArray || hasInstanceName);
1547
1548                 for (int instanceNdx = 0; instanceNdx < numInstances; instanceNdx++)
1549                 {
1550                         std::string instancePostfix = "";
1551                         if (isArray)
1552                         {
1553                                 std::string indexStr = de::toString(instanceNdx);
1554                                 if (interface.usesBlockLayout(LAYOUT_DESCRIPTOR_INDEXING))
1555                                         indexStr = std::string("nonuniformEXT(") + indexStr + ")";
1556                                 instancePostfix = std::string("[") + indexStr + "]";
1557                         }
1558
1559                         std::string             blockInstanceName       = block.getBlockName() + instancePostfix;
1560                         std::string             srcPrefix                       = hasInstanceName ? block.getInstanceName() + instancePostfix + "." : std::string("");
1561                         int                             blockLayoutNdx          = layout.getBlockLayoutIndex(blockNdx, instanceNdx);
1562                         void*                   basePtr                         = blockPointers.find(blockLayoutNdx)->second;
1563
1564                         for (UniformBlock::ConstIterator uniformIter = block.begin(); uniformIter != block.end(); uniformIter++)
1565                         {
1566                                 const Uniform& uniform = *uniformIter;
1567
1568                                 if (uniform.getFlags() & unusedMask)
1569                                         continue; // Don't read from that uniform.
1570
1571                                 std::string srcName = srcPrefix + uniform.getName();
1572                                 std::string apiName = apiPrefix + uniform.getName();
1573                                 generateCompareSrc(src, resultVar, uniform.getType(), srcName, apiName, layout, blockNdx, basePtr, unusedMask, matrixLoadFlag);
1574                         }
1575                 }
1576         }
1577 }
1578
1579 std::string generateVertexShader (const ShaderInterface& interface, const UniformLayout& layout, const std::map<int, void*>& blockPointers, MatrixLoadFlags matrixLoadFlag, bool shuffleUniformMembers)
1580 {
1581         std::ostringstream src;
1582         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n";
1583         src << "#extension GL_EXT_shader_16bit_storage : enable\n";
1584         src << "#extension GL_EXT_shader_8bit_storage : enable\n";
1585         src << "#extension GL_EXT_scalar_block_layout : enable\n";
1586         src << "#extension GL_EXT_nonuniform_qualifier : enable\n";
1587
1588         src << "layout(location = 0) in highp vec4 a_position;\n";
1589         src << "layout(location = 0) out mediump float v_vtxResult;\n";
1590         src << "\n";
1591
1592         std::vector<const StructType*> namedStructs;
1593         interface.getNamedStructs(namedStructs);
1594         for (std::vector<const StructType*>::const_iterator structIter = namedStructs.begin(); structIter != namedStructs.end(); structIter++)
1595                 generateDeclaration(src, **structIter, 0);
1596
1597         for (int blockNdx = 0; blockNdx < interface.getNumUniformBlocks(); blockNdx++)
1598         {
1599                 const UniformBlock& block = interface.getUniformBlock(blockNdx);
1600                 if (block.getFlags() & DECLARE_VERTEX)
1601                         generateDeclaration(src, blockNdx, block, layout, shuffleUniformMembers);
1602         }
1603
1604         // Comparison utilities.
1605         src << "\n";
1606         generateCompareFuncs(src, interface);
1607
1608         src << "\n"
1609                    "void main (void)\n"
1610                    "{\n"
1611                    "    gl_Position = a_position;\n"
1612                    "    mediump float result = 1.0;\n";
1613
1614         // Value compare.
1615         generateCompareSrc(src, "result", interface, layout, blockPointers, true, matrixLoadFlag);
1616
1617         src << "        v_vtxResult = result;\n"
1618                    "}\n";
1619
1620         return src.str();
1621 }
1622
1623 std::string generateFragmentShader (const ShaderInterface& interface, const UniformLayout& layout, const std::map<int, void*>& blockPointers, MatrixLoadFlags matrixLoadFlag, bool shuffleUniformMembers)
1624 {
1625         std::ostringstream src;
1626         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n";
1627         src << "#extension GL_EXT_shader_16bit_storage : enable\n";
1628         src << "#extension GL_EXT_shader_8bit_storage : enable\n";
1629         src << "#extension GL_EXT_scalar_block_layout : enable\n";
1630         src << "#extension GL_EXT_nonuniform_qualifier : enable\n";
1631
1632         src << "layout(location = 0) in mediump float v_vtxResult;\n";
1633         src << "layout(location = 0) out mediump vec4 dEQP_FragColor;\n";
1634         src << "\n";
1635
1636         std::vector<const StructType*> namedStructs;
1637         interface.getNamedStructs(namedStructs);
1638         for (std::vector<const StructType*>::const_iterator structIter = namedStructs.begin(); structIter != namedStructs.end(); structIter++)
1639                 generateDeclaration(src, **structIter, 0);
1640
1641         for (int blockNdx = 0; blockNdx < interface.getNumUniformBlocks(); blockNdx++)
1642         {
1643                 const UniformBlock& block = interface.getUniformBlock(blockNdx);
1644                 if (block.getFlags() & DECLARE_FRAGMENT)
1645                         generateDeclaration(src, blockNdx, block, layout, shuffleUniformMembers);
1646         }
1647
1648         // Comparison utilities.
1649         src << "\n";
1650         generateCompareFuncs(src, interface);
1651
1652         src << "\n"
1653                    "void main (void)\n"
1654                    "{\n"
1655                    "    mediump float result = 1.0;\n";
1656
1657         // Value compare.
1658         generateCompareSrc(src, "result", interface, layout, blockPointers, false, matrixLoadFlag);
1659
1660         src << "        dEQP_FragColor = vec4(1.0, v_vtxResult, result, 1.0);\n"
1661                    "}\n";
1662
1663         return src.str();
1664 }
1665
1666 Move<VkBuffer> createBuffer (Context& context, VkDeviceSize bufferSize, vk::VkBufferUsageFlags usageFlags)
1667 {
1668         const VkDevice                          vkDevice                        = context.getDevice();
1669         const DeviceInterface&          vk                                      = context.getDeviceInterface();
1670         const deUint32                          queueFamilyIndex        = context.getUniversalQueueFamilyIndex();
1671
1672         const VkBufferCreateInfo        bufferInfo                      =
1673         {
1674                 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,   // VkStructureType              sType;
1675                 DE_NULL,                                                                // const void*                  pNext;
1676                 0u,                                                                             // VkBufferCreateFlags  flags;
1677                 bufferSize,                                                             // VkDeviceSize                 size;
1678                 usageFlags,                                                             // VkBufferUsageFlags   usage;
1679                 VK_SHARING_MODE_EXCLUSIVE,                              // VkSharingMode                sharingMode;
1680                 1u,                                                                             // deUint32                             queueFamilyIndexCount;
1681                 &queueFamilyIndex                                               // const deUint32*              pQueueFamilyIndices;
1682         };
1683
1684         return vk::createBuffer(vk, vkDevice, &bufferInfo);
1685 }
1686
1687 Move<vk::VkImage> createImage2D (Context& context, deUint32 width, deUint32 height, vk::VkFormat format, vk::VkImageTiling tiling, vk::VkImageUsageFlags usageFlags)
1688 {
1689         const deUint32                          queueFamilyIndex        = context.getUniversalQueueFamilyIndex();
1690         const vk::VkImageCreateInfo     params                          =
1691         {
1692                 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,        // VkStructureType                      sType
1693                 DE_NULL,                                                                        // const void*                          pNext
1694                 0u,                                                                                     // VkImageCreateFlags           flags
1695                 vk::VK_IMAGE_TYPE_2D,                                           // VkImageType                          imageType
1696                 format,                                                                         // VkFormat                                     format
1697                 { width, height, 1u },                                          // VkExtent3D                           extent
1698                 1u,                                                                                     // deUint32                                     mipLevels
1699                 1u,                                                                                     // deUint32                                     arrayLayers
1700                 VK_SAMPLE_COUNT_1_BIT,                                          // VkSampleCountFlagBits        samples
1701                 tiling,                                                                         // VkImageTiling                        tiling
1702                 usageFlags,                                                                     // VkImageUsageFlags            usage
1703                 vk::VK_SHARING_MODE_EXCLUSIVE,                          // VkSharingMode                        sharingMode
1704                 1u,                                                                                     // deUint32                                     queueFamilyIndexCount
1705                 &queueFamilyIndex,                                                      // const deUint32*                      pQueueFamilyIndices
1706                 vk::VK_IMAGE_LAYOUT_UNDEFINED,                          // VkImageLayout                        initialLayout
1707         };
1708
1709         return vk::createImage(context.getDeviceInterface(), context.getDevice(), &params);
1710 }
1711
1712 de::MovePtr<vk::Allocation> allocateAndBindMemory (Context& context, vk::VkBuffer buffer, vk::MemoryRequirement memReqs)
1713 {
1714         const vk::DeviceInterface&              vkd             = context.getDeviceInterface();
1715         const vk::VkMemoryRequirements  bufReqs = vk::getBufferMemoryRequirements(vkd, context.getDevice(), buffer);
1716         de::MovePtr<vk::Allocation>             memory  = context.getDefaultAllocator().allocate(bufReqs, memReqs);
1717
1718         vkd.bindBufferMemory(context.getDevice(), buffer, memory->getMemory(), memory->getOffset());
1719
1720         return memory;
1721 }
1722
1723 de::MovePtr<vk::Allocation> allocateAndBindMemory (Context& context, vk::VkImage image, vk::MemoryRequirement memReqs)
1724 {
1725         const vk::DeviceInterface&        vkd    = context.getDeviceInterface();
1726         const vk::VkMemoryRequirements  imgReqs = vk::getImageMemoryRequirements(vkd, context.getDevice(), image);
1727         de::MovePtr<vk::Allocation>              memory  = context.getDefaultAllocator().allocate(imgReqs, memReqs);
1728
1729         vkd.bindImageMemory(context.getDevice(), image, memory->getMemory(), memory->getOffset());
1730
1731         return memory;
1732 }
1733
1734 Move<vk::VkImageView> createAttachmentView (Context& context, vk::VkImage image, vk::VkFormat format)
1735 {
1736         const vk::VkImageViewCreateInfo params =
1737         {
1738                 vk::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,           // sType
1739                 DE_NULL,                                                                                        // pNext
1740                 0u,                                                                                                     // flags
1741                 image,                                                                                          // image
1742                 vk::VK_IMAGE_VIEW_TYPE_2D,                                                      // viewType
1743                 format,                                                                                         // format
1744                 vk::makeComponentMappingRGBA(),                                         // components
1745                 { vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u,1u },       // subresourceRange
1746         };
1747
1748         return vk::createImageView(context.getDeviceInterface(), context.getDevice(), &params);
1749 }
1750
1751 Move<vk::VkPipelineLayout> createPipelineLayout (Context& context, vk::VkDescriptorSetLayout descriptorSetLayout)
1752 {
1753         const vk::VkPipelineLayoutCreateInfo params =
1754         {
1755                 vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,      // sType
1756                 DE_NULL,                                                                                        // pNext
1757                 0u,                                                                                                     // flags
1758                 1u,                                                                                                     // setLayoutCount
1759                 &descriptorSetLayout,                                                           // pSetLayouts
1760                 0u,                                                                                                     // pushConstantRangeCount
1761                 DE_NULL,                                                                                        // pPushConstantRanges
1762         };
1763
1764         return vk::createPipelineLayout(context.getDeviceInterface(), context.getDevice(), &params);
1765 }
1766
1767 Move<vk::VkCommandPool> createCmdPool (Context& context)
1768 {
1769         const deUint32  queueFamilyIndex        = context.getUniversalQueueFamilyIndex();
1770
1771         return vk::createCommandPool(context.getDeviceInterface(), context.getDevice(), vk::VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
1772 }
1773
1774 Move<vk::VkCommandBuffer> createCmdBuffer (Context& context, vk::VkCommandPool cmdPool)
1775 {
1776         return vk::allocateCommandBuffer(context.getDeviceInterface(), context.getDevice(), cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1777 }
1778
1779 // UniformBlockCaseInstance
1780
1781 class UniformBlockCaseInstance : public vkt::TestInstance
1782 {
1783 public:
1784                                                                         UniformBlockCaseInstance        (Context&                                               context,
1785                                                                                                                                  UniformBlockCase::BufferMode   bufferMode,
1786                                                                                                                                  const UniformLayout&                   layout,
1787                                                                                                                                  const std::map<int, void*>&    blockPointers);
1788         virtual                                                 ~UniformBlockCaseInstance       (void);
1789         virtual tcu::TestStatus                 iterate                                         (void);
1790
1791 private:
1792         enum
1793         {
1794                 RENDER_WIDTH = 100,
1795                 RENDER_HEIGHT = 100,
1796         };
1797
1798         vk::Move<VkRenderPass>                  createRenderPass                        (vk::VkFormat format) const;
1799         vk::Move<VkFramebuffer>                 createFramebuffer                       (vk::VkRenderPass renderPass, vk::VkImageView colorImageView) const;
1800         vk::Move<VkDescriptorSetLayout> createDescriptorSetLayout       (void) const;
1801         vk::Move<VkDescriptorPool>              createDescriptorPool            (void) const;
1802         vk::Move<VkPipeline>                    createPipeline                          (vk::VkShaderModule vtxShaderModule, vk::VkShaderModule fragShaderModule, vk::VkPipelineLayout pipelineLayout, vk::VkRenderPass renderPass) const;
1803
1804         vk::VkDescriptorBufferInfo              addUniformData                          (deUint32 size, const void* dataPtr);
1805
1806         UniformBlockCase::BufferMode    m_bufferMode;
1807         const UniformLayout&                    m_layout;
1808         const std::map<int, void*>&             m_blockPointers;
1809
1810         typedef de::SharedPtr<vk::Unique<vk::VkBuffer> >        VkBufferSp;
1811         typedef de::SharedPtr<vk::Allocation>                           AllocationSp;
1812
1813         std::vector<VkBufferSp>                 m_uniformBuffers;
1814         std::vector<AllocationSp>               m_uniformAllocs;
1815 };
1816
1817 UniformBlockCaseInstance::UniformBlockCaseInstance (Context&                                            ctx,
1818                                                                                                         UniformBlockCase::BufferMode    bufferMode,
1819                                                                                                         const UniformLayout&                    layout,
1820                                                                                                         const std::map<int, void*>&             blockPointers)
1821         : vkt::TestInstance (ctx)
1822         , m_bufferMode          (bufferMode)
1823         , m_layout                      (layout)
1824         , m_blockPointers       (blockPointers)
1825 {
1826 }
1827
1828 UniformBlockCaseInstance::~UniformBlockCaseInstance (void)
1829 {
1830 }
1831
1832 tcu::TestStatus UniformBlockCaseInstance::iterate (void)
1833 {
1834         const vk::DeviceInterface&              vk                                      = m_context.getDeviceInterface();
1835         const vk::VkDevice                              device                          = m_context.getDevice();
1836         const vk::VkQueue                               queue                           = m_context.getUniversalQueue();
1837         const deUint32                                  queueFamilyIndex        = m_context.getUniversalQueueFamilyIndex();
1838
1839         const float positions[] =
1840         {
1841                 -1.0f, -1.0f, 0.0f, 1.0f,
1842                 -1.0f, +1.0f, 0.0f, 1.0f,
1843                 +1.0f, -1.0f, 0.0f, 1.0f,
1844                 +1.0f, +1.0f, 0.0f, 1.0f
1845         };
1846
1847         const deUint32 indices[] = { 0, 1, 2, 2, 1, 3 };
1848
1849         vk::Unique<VkBuffer>                            positionsBuffer         (createBuffer(m_context, sizeof(positions), vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
1850         de::UniquePtr<Allocation>                       positionsAlloc          (allocateAndBindMemory(m_context, *positionsBuffer, MemoryRequirement::HostVisible));
1851         vk::Unique<VkBuffer>                            indicesBuffer           (createBuffer(m_context, sizeof(indices), vk::VK_BUFFER_USAGE_INDEX_BUFFER_BIT|vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
1852         de::UniquePtr<Allocation>                       indicesAlloc            (allocateAndBindMemory(m_context, *indicesBuffer, MemoryRequirement::HostVisible));
1853
1854         int minUniformBufferOffsetAlignment = getminUniformBufferOffsetAlignment(m_context);
1855
1856         // Upload attrbiutes data
1857         {
1858                 deMemcpy(positionsAlloc->getHostPtr(), positions, sizeof(positions));
1859                 flushAlloc(vk, device, *positionsAlloc);
1860
1861                 deMemcpy(indicesAlloc->getHostPtr(), indices, sizeof(indices));
1862                 flushAlloc(vk, device, *indicesAlloc);
1863         }
1864
1865         vk::Unique<VkImage>                                     colorImage                      (createImage2D(m_context,
1866                                                                                                                                                         RENDER_WIDTH,
1867                                                                                                                                                         RENDER_HEIGHT,
1868                                                                                                                                                         vk::VK_FORMAT_R8G8B8A8_UNORM,
1869                                                                                                                                                         vk::VK_IMAGE_TILING_OPTIMAL,
1870                                                                                                                                                         vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT|vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT));
1871         de::UniquePtr<Allocation>                       colorImageAlloc         (allocateAndBindMemory(m_context, *colorImage, MemoryRequirement::Any));
1872         vk::Unique<VkImageView>                         colorImageView          (createAttachmentView(m_context, *colorImage, vk::VK_FORMAT_R8G8B8A8_UNORM));
1873
1874         vk::Unique<VkDescriptorSetLayout>       descriptorSetLayout     (createDescriptorSetLayout());
1875         vk::Unique<VkDescriptorPool>            descriptorPool          (createDescriptorPool());
1876
1877         const VkDescriptorSetAllocateInfo       descriptorSetAllocateInfo =
1878         {
1879                 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,         // VkStructureType                              sType;
1880                 DE_NULL,                                                                                        // const void*                                  pNext;
1881                 *descriptorPool,                                                                        // VkDescriptorPool                             descriptorPool;
1882                 1u,                                                                                                     // deUint32                                             setLayoutCount;
1883                 &descriptorSetLayout.get()                                                      // const VkDescriptorSetLayout* pSetLayouts;
1884         };
1885
1886         vk::Unique<VkDescriptorSet>                     descriptorSet(vk::allocateDescriptorSet(vk, device, &descriptorSetAllocateInfo));
1887         int                                                                     numBlocks = (int)m_layout.blocks.size();
1888         std::vector<vk::VkDescriptorBufferInfo> descriptors(numBlocks);
1889
1890         // Upload uniform data
1891         {
1892                 vk::DescriptorSetUpdateBuilder  descriptorSetUpdateBuilder;
1893
1894                 if (m_bufferMode == UniformBlockCase::BUFFERMODE_PER_BLOCK)
1895                 {
1896                         for (int blockNdx = 0; blockNdx < numBlocks; blockNdx++)
1897                         {
1898                                 const BlockLayoutEntry& block = m_layout.blocks[blockNdx];
1899                                 const void*     srcPtr = m_blockPointers.find(blockNdx)->second;
1900
1901                                 descriptors[blockNdx] = addUniformData(block.size, srcPtr);
1902                                 descriptorSetUpdateBuilder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::bindingArrayElement(block.bindingNdx, block.instanceNdx),
1903                                                                                                                 VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &descriptors[blockNdx]);
1904                         }
1905                 }
1906                 else
1907                 {
1908                         int currentOffset = 0;
1909                         std::map<int, int> offsets;
1910                         for (int blockNdx = 0; blockNdx < numBlocks; blockNdx++)
1911                         {
1912                                 if (minUniformBufferOffsetAlignment > 0)
1913                                         currentOffset = deAlign32(currentOffset, minUniformBufferOffsetAlignment);
1914                                 offsets[blockNdx] = currentOffset;
1915                                 currentOffset += m_layout.blocks[blockNdx].size;
1916                         }
1917
1918                         deUint32 totalSize = currentOffset;
1919
1920                         // Make a copy of the data that satisfies the device's min uniform buffer alignment
1921                         std::vector<deUint8> data;
1922                         data.resize(totalSize);
1923                         for (int blockNdx = 0; blockNdx < numBlocks; blockNdx++)
1924                         {
1925                                 deMemcpy(&data[offsets[blockNdx]], m_blockPointers.find(blockNdx)->second, m_layout.blocks[blockNdx].size);
1926                         }
1927
1928                         vk::VkBuffer buffer = addUniformData(totalSize, &data[0]).buffer;
1929
1930                         for (int blockNdx = 0; blockNdx < numBlocks; blockNdx++)
1931                         {
1932                                 const BlockLayoutEntry& block = m_layout.blocks[blockNdx];
1933                                 deUint32 size = block.size;
1934
1935                                 const VkDescriptorBufferInfo    descriptor =
1936                                 {
1937                                         buffer,                                                 // VkBuffer             buffer;
1938                                         (deUint32)offsets[blockNdx],    // VkDeviceSize offset;
1939                                         size,                                                   // VkDeviceSize range;
1940                                 };
1941
1942                                 descriptors[blockNdx] = descriptor;
1943                                 descriptorSetUpdateBuilder.writeSingle(*descriptorSet,
1944                                                                                                                 vk::DescriptorSetUpdateBuilder::Location::bindingArrayElement(block.bindingNdx, block.instanceNdx),
1945                                                                                                                 VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
1946                                                                                                                 &descriptors[blockNdx]);
1947                         }
1948                 }
1949
1950                 descriptorSetUpdateBuilder.update(vk, device);
1951         }
1952
1953         vk::Unique<VkRenderPass>                        renderPass                      (createRenderPass(vk::VK_FORMAT_R8G8B8A8_UNORM));
1954         vk::Unique<VkFramebuffer>                       framebuffer                     (createFramebuffer(*renderPass, *colorImageView));
1955         vk::Unique<VkPipelineLayout>            pipelineLayout          (createPipelineLayout(m_context, *descriptorSetLayout));
1956
1957         vk::Unique<VkShaderModule>                      vtxShaderModule         (vk::createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0));
1958         vk::Unique<VkShaderModule>                      fragShaderModule        (vk::createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0));
1959         vk::Unique<VkPipeline>                          pipeline                        (createPipeline(*vtxShaderModule, *fragShaderModule, *pipelineLayout, *renderPass));
1960         vk::Unique<VkCommandPool>                       cmdPool                         (createCmdPool(m_context));
1961         vk::Unique<VkCommandBuffer>                     cmdBuffer                       (createCmdBuffer(m_context, *cmdPool));
1962         vk::Unique<VkBuffer>                            readImageBuffer         (createBuffer(m_context, (vk::VkDeviceSize)(RENDER_WIDTH * RENDER_HEIGHT * 4), vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1963         de::UniquePtr<Allocation>                       readImageAlloc          (allocateAndBindMemory(m_context, *readImageBuffer, vk::MemoryRequirement::HostVisible));
1964
1965         // Record command buffer
1966         const vk::VkCommandBufferBeginInfo beginInfo    =
1967         {
1968                 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,        // VkStructureType                                      sType;
1969                 DE_NULL,                                                                                        // const void*                                          pNext;
1970                 0u,                                                                                                     // VkCommandBufferUsageFlags            flags;
1971                 (const vk::VkCommandBufferInheritanceInfo*)DE_NULL,
1972         };
1973         VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &beginInfo));
1974
1975         // Add barrier for initializing image state
1976         {
1977                 const vk::VkImageMemoryBarrier  initializeBarrier =
1978                 {
1979                         vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,             // VkStructureType                      sType;
1980                         DE_NULL,                                                                                // const void*                          pNext
1981                         0,                                                                                              // VVkAccessFlags                       srcAccessMask;
1982                         vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,               // VkAccessFlags                        dstAccessMask;
1983                         vk::VK_IMAGE_LAYOUT_UNDEFINED,                                  // VkImageLayout                        oldLayout;
1984                         vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,   // VkImageLayout                        newLayout;
1985                         queueFamilyIndex,                                                               // deUint32                                     srcQueueFamilyIndex;
1986                         queueFamilyIndex,                                                               // deUint32                                     dstQueueFamilyIndex;
1987                         *colorImage,                                                                    // VkImage                                      image;
1988                         {
1989                                 vk::VK_IMAGE_ASPECT_COLOR_BIT,                  // VkImageAspectFlags   aspectMask;
1990                                 0u,                                                                             // deUint32                             baseMipLevel;
1991                                 1u,                                                                             // deUint32                             mipLevels;
1992                                 0u,                                                                             // deUint32                             baseArraySlice;
1993                                 1u,                                                                             // deUint32                             arraySize;
1994                         }                                                                                               // VkImageSubresourceRange      subresourceRange
1995                 };
1996
1997                 vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, (vk::VkDependencyFlags)0,
1998                         0, (const vk::VkMemoryBarrier*)DE_NULL,
1999                         0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
2000                         1, &initializeBarrier);
2001         }
2002
2003         beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(0, 0, RENDER_WIDTH, RENDER_HEIGHT), tcu::Vec4(0.125f, 0.25f, 0.75f, 1.0f));
2004
2005         vk.cmdBindPipeline(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
2006         vk.cmdBindDescriptorSets(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &*descriptorSet, 0u, DE_NULL);
2007
2008         const vk::VkDeviceSize offsets[] = { 0u };
2009         vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &*positionsBuffer, offsets);
2010         vk.cmdBindIndexBuffer(*cmdBuffer, *indicesBuffer, (vk::VkDeviceSize)0, vk::VK_INDEX_TYPE_UINT32);
2011
2012         vk.cmdDrawIndexed(*cmdBuffer, DE_LENGTH_OF_ARRAY(indices), 1u, 0u, 0u, 0u);
2013         endRenderPass(vk, *cmdBuffer);
2014
2015         copyImageToBuffer(vk, *cmdBuffer, *colorImage, *readImageBuffer, tcu::IVec2(RENDER_WIDTH, RENDER_HEIGHT));
2016
2017         endCommandBuffer(vk, *cmdBuffer);
2018
2019         // Submit the command buffer
2020         submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
2021
2022         // Read back the results
2023         tcu::Surface surface(RENDER_WIDTH, RENDER_HEIGHT);
2024         {
2025                 const tcu::TextureFormat textureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8);
2026                 const tcu::ConstPixelBufferAccess imgAccess(textureFormat, RENDER_WIDTH, RENDER_HEIGHT, 1, readImageAlloc->getHostPtr());
2027                 invalidateAlloc(vk, device, *readImageAlloc);
2028
2029                 tcu::copy(surface.getAccess(), imgAccess);
2030         }
2031
2032         // Check if the result image is all white
2033         tcu::RGBA white(tcu::RGBA::white());
2034         int numFailedPixels = 0;
2035
2036         for (int y = 0; y < surface.getHeight(); y++)
2037         {
2038                 for (int x = 0; x < surface.getWidth(); x++)
2039                 {
2040                         if (surface.getPixel(x, y) != white)
2041                                 numFailedPixels += 1;
2042                 }
2043         }
2044
2045         if (numFailedPixels > 0)
2046         {
2047                 tcu::TestLog& log = m_context.getTestContext().getLog();
2048                 log << tcu::TestLog::Image("Image", "Rendered image", surface);
2049                 log << tcu::TestLog::Message << "Image comparison failed, got " << numFailedPixels << " non-white pixels" << tcu::TestLog::EndMessage;
2050
2051                 for (size_t blockNdx = 0; blockNdx < m_layout.blocks.size(); blockNdx++)
2052                 {
2053                         const BlockLayoutEntry& block = m_layout.blocks[blockNdx];
2054                         log << tcu::TestLog::Message << "Block index: " << blockNdx << " infos: " << block << tcu::TestLog::EndMessage;
2055                 }
2056
2057                 for (size_t uniformNdx = 0; uniformNdx < m_layout.uniforms.size(); uniformNdx++)
2058                 {
2059                         log << tcu::TestLog::Message << "Uniform index: " << uniformNdx << " infos: " << m_layout.uniforms[uniformNdx] << tcu::TestLog::EndMessage;
2060                 }
2061
2062                 return tcu::TestStatus::fail("Detected non-white pixels");
2063         }
2064         else
2065                 return tcu::TestStatus::pass("Full white image ok");
2066 }
2067
2068 vk::VkDescriptorBufferInfo UniformBlockCaseInstance::addUniformData (deUint32 size, const void* dataPtr)
2069 {
2070         const VkDevice                                  vkDevice                        = m_context.getDevice();
2071         const DeviceInterface&                  vk                                      = m_context.getDeviceInterface();
2072
2073         Move<VkBuffer>                                  buffer  = createBuffer(m_context, size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
2074         de::MovePtr<Allocation>                 alloc   = allocateAndBindMemory(m_context, *buffer, vk::MemoryRequirement::HostVisible);
2075
2076         deMemcpy(alloc->getHostPtr(), dataPtr, size);
2077         flushAlloc(vk, vkDevice, *alloc);
2078
2079         const VkDescriptorBufferInfo                    descriptor                      =
2080         {
2081                 *buffer,                                // VkBuffer             buffer;
2082                 0u,                                             // VkDeviceSize offset;
2083                 size,                                   // VkDeviceSize range;
2084
2085         };
2086
2087         m_uniformBuffers.push_back(VkBufferSp(new vk::Unique<vk::VkBuffer>(buffer)));
2088         m_uniformAllocs.push_back(AllocationSp(alloc.release()));
2089
2090         return descriptor;
2091 }
2092
2093 vk::Move<VkRenderPass> UniformBlockCaseInstance::createRenderPass (vk::VkFormat format) const
2094 {
2095         const VkDevice                                  vkDevice                                = m_context.getDevice();
2096         const DeviceInterface&                  vk                                              = m_context.getDeviceInterface();
2097
2098         return vk::makeRenderPass(vk, vkDevice, format);
2099 }
2100
2101 vk::Move<VkFramebuffer> UniformBlockCaseInstance::createFramebuffer (vk::VkRenderPass renderPass, vk::VkImageView colorImageView) const
2102 {
2103         const VkDevice                                  vkDevice                        = m_context.getDevice();
2104         const DeviceInterface&                  vk                                      = m_context.getDeviceInterface();
2105
2106         const VkFramebufferCreateInfo   framebufferParams       =
2107         {
2108                 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,              // VkStructureType                      sType;
2109                 DE_NULL,                                                                                // const void*                          pNext;
2110                 0u,                                                                                             // VkFramebufferCreateFlags     flags;
2111                 renderPass,                                                                             // VkRenderPass                         renderPass;
2112                 1u,                                                                                             // deUint32                                     attachmentCount;
2113                 &colorImageView,                                                                // const VkImageView*           pAttachments;
2114                 RENDER_WIDTH,                                                                   // deUint32                                     width;
2115                 RENDER_HEIGHT,                                                                  // deUint32                                     height;
2116                 1u                                                                                              // deUint32                                     layers;
2117         };
2118
2119         return vk::createFramebuffer(vk, vkDevice, &framebufferParams);
2120 }
2121
2122 vk::Move<VkDescriptorSetLayout> UniformBlockCaseInstance::createDescriptorSetLayout (void) const
2123 {
2124         int numBlocks = (int)m_layout.blocks.size();
2125         int lastBindingNdx = -1;
2126         std::vector<int> lengths;
2127
2128         for (int blockNdx = 0; blockNdx < numBlocks; blockNdx++)
2129         {
2130                 const BlockLayoutEntry& block = m_layout.blocks[blockNdx];
2131
2132                 if (block.bindingNdx == lastBindingNdx)
2133                 {
2134                         lengths.back()++;
2135                 }
2136                 else
2137                 {
2138                         lengths.push_back(1);
2139                         lastBindingNdx = block.bindingNdx;
2140                 }
2141         }
2142
2143         vk::DescriptorSetLayoutBuilder layoutBuilder;
2144         for (size_t i = 0; i < lengths.size(); i++)
2145         {
2146                 if (lengths[i] > 0)
2147                 {
2148                         layoutBuilder.addArrayBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, lengths[i], vk::VK_SHADER_STAGE_ALL);
2149                 }
2150                 else
2151                 {
2152                         layoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, vk::VK_SHADER_STAGE_ALL);
2153                 }
2154         }
2155
2156         return layoutBuilder.build(m_context.getDeviceInterface(), m_context.getDevice());
2157 }
2158
2159 vk::Move<VkDescriptorPool> UniformBlockCaseInstance::createDescriptorPool (void) const
2160 {
2161         vk::DescriptorPoolBuilder poolBuilder;
2162
2163         return poolBuilder
2164                 .addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, (int)m_layout.blocks.size())
2165                 .build(m_context.getDeviceInterface(), m_context.getDevice(), VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
2166 }
2167
2168 vk::Move<VkPipeline> UniformBlockCaseInstance::createPipeline (vk::VkShaderModule vtxShaderModule, vk::VkShaderModule fragShaderModule, vk::VkPipelineLayout pipelineLayout, vk::VkRenderPass renderPass) const
2169 {
2170         const VkDevice                                                                  vkDevice                                = m_context.getDevice();
2171         const DeviceInterface&                                                  vk                                              = m_context.getDeviceInterface();
2172
2173         const std::vector<VkViewport>                                   viewports                               (1, makeViewport(tcu::UVec2(RENDER_WIDTH, RENDER_HEIGHT)));
2174         const std::vector<VkRect2D>                                             scissors                                (1, makeRect2D(tcu::UVec2(RENDER_WIDTH, RENDER_HEIGHT)));
2175
2176         return vk::makeGraphicsPipeline(vk,                                     // const DeviceInterface&            vk
2177                                                                         vkDevice,                       // const VkDevice                    device
2178                                                                         pipelineLayout,         // const VkPipelineLayout            pipelineLayout
2179                                                                         vtxShaderModule,        // const VkShaderModule              vertexShaderModule
2180                                                                         DE_NULL,                        // const VkShaderModule              tessellationControlShaderModule
2181                                                                         DE_NULL,                        // const VkShaderModule              tessellationEvalShaderModule
2182                                                                         DE_NULL,                        // const VkShaderModule              geometryShaderModule
2183                                                                         fragShaderModule,       // const VkShaderModule              fragmentShaderModule
2184                                                                         renderPass,                     // const VkRenderPass                renderPass
2185                                                                         viewports,                      // const std::vector<VkViewport>&    viewports
2186                                                                         scissors);                      // const std::vector<VkRect2D>&      scissors
2187 }
2188
2189 } // anonymous (utilities)
2190
2191 // UniformBlockCase.
2192
2193 UniformBlockCase::UniformBlockCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, BufferMode bufferMode, MatrixLoadFlags matrixLoadFlag, bool shuffleUniformMembers)
2194         : TestCase                                      (testCtx, name, description)
2195         , m_bufferMode                          (bufferMode)
2196         , m_matrixLoadFlag                      (matrixLoadFlag)
2197         , m_shuffleUniformMembers       (shuffleUniformMembers)
2198 {
2199 }
2200
2201 UniformBlockCase::~UniformBlockCase (void)
2202 {
2203 }
2204
2205 void UniformBlockCase::initPrograms (vk::SourceCollections& programCollection) const
2206 {
2207         DE_ASSERT(!m_vertShaderSource.empty());
2208         DE_ASSERT(!m_fragShaderSource.empty());
2209
2210         vk::ShaderBuildOptions::Flags flags = vk::ShaderBuildOptions::Flags(0);
2211         // TODO(dneto): If these tests ever use LAYOUT_RELAXED, then add support
2212         // here as well.
2213         if (usesBlockLayout(LAYOUT_SCALAR))
2214                 flags = vk::ShaderBuildOptions::FLAG_ALLOW_SCALAR_OFFSETS;
2215         else if (usesBlockLayout(LAYOUT_STD430))
2216                 flags = vk::ShaderBuildOptions::FLAG_ALLOW_STD430_UBOS;
2217
2218         programCollection.glslSources.add("vert") << glu::VertexSource(m_vertShaderSource)
2219         << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::getBaselineSpirvVersion(programCollection.usedVulkanVersion), flags);
2220
2221         programCollection.glslSources.add("frag") << glu::FragmentSource(m_fragShaderSource)
2222         << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::getBaselineSpirvVersion(programCollection.usedVulkanVersion), flags);
2223 }
2224
2225 TestInstance* UniformBlockCase::createInstance (Context& context) const
2226 {
2227         if (!context.get16BitStorageFeatures().uniformAndStorageBuffer16BitAccess && usesBlockLayout(LAYOUT_16BIT_STORAGE))
2228                 TCU_THROW(NotSupportedError, "uniformAndStorageBuffer16BitAccess not supported");
2229         if (!context.get8BitStorageFeatures().uniformAndStorageBuffer8BitAccess && usesBlockLayout(LAYOUT_8BIT_STORAGE))
2230                 TCU_THROW(NotSupportedError, "uniformAndStorageBuffer8BitAccess not supported");
2231         if (!context.getScalarBlockLayoutFeatures().scalarBlockLayout && !context.getUniformBufferStandardLayoutFeatures().uniformBufferStandardLayout && usesBlockLayout(LAYOUT_STD430))
2232                 TCU_THROW(NotSupportedError, "std430 not supported");
2233         if (!context.getScalarBlockLayoutFeatures().scalarBlockLayout && usesBlockLayout(LAYOUT_SCALAR))
2234                 TCU_THROW(NotSupportedError, "scalarBlockLayout not supported");
2235         if (usesBlockLayout(LAYOUT_DESCRIPTOR_INDEXING) && (    !context.getDescriptorIndexingFeatures().shaderUniformBufferArrayNonUniformIndexing ||
2236                                                                                                                         !context.getDescriptorIndexingFeatures().runtimeDescriptorArray ) )
2237                 TCU_THROW(NotSupportedError, "Descriptor indexing over uniform buffer not supported");
2238
2239         return new UniformBlockCaseInstance(context, m_bufferMode, m_uniformLayout, m_blockPointers);
2240 }
2241
2242 void UniformBlockCase::delayedInit (void)
2243 {
2244         const int vec4Alignment = (int)sizeof(deUint32)*4;
2245
2246         // Compute reference layout.
2247         computeReferenceLayout(m_uniformLayout, m_interface);
2248
2249         // Assign storage for reference values.
2250         {
2251                 int totalSize = 0;
2252                 for (std::vector<BlockLayoutEntry>::const_iterator blockIter = m_uniformLayout.blocks.begin(); blockIter != m_uniformLayout.blocks.end(); blockIter++)
2253                 {
2254                         // Include enough space for alignment of individual blocks
2255                         totalSize += deRoundUp32(blockIter->size, vec4Alignment);
2256                 }
2257                 m_data.resize(totalSize);
2258
2259                 // Pointers for each block.
2260                 int curOffset = 0;
2261                 for (int blockNdx = 0; blockNdx < (int)m_uniformLayout.blocks.size(); blockNdx++)
2262                 {
2263                         m_blockPointers[blockNdx] = &m_data[0] + curOffset;
2264
2265                         // Ensure each new block starts fully aligned to avoid unaligned host accesses
2266                         curOffset += deRoundUp32(m_uniformLayout.blocks[blockNdx].size, vec4Alignment);
2267                 }
2268         }
2269
2270         // Generate values.
2271         generateValues(m_uniformLayout, m_blockPointers, 1 /* seed */);
2272
2273         // Generate shaders.
2274         m_vertShaderSource = generateVertexShader(m_interface, m_uniformLayout, m_blockPointers, m_matrixLoadFlag, m_shuffleUniformMembers);
2275         m_fragShaderSource = generateFragmentShader(m_interface, m_uniformLayout, m_blockPointers, m_matrixLoadFlag, m_shuffleUniformMembers);
2276 }
2277
2278 } // ubo
2279 } // vkt