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