Merge \\"Add tests for uniform block linking by binding\\" into nyc-dev am: 845104ba90
[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 void generateCompareSrc (std::ostringstream&    src,
947                                                  const char*                    resultVar,
948                                                  const VarType&                 type,
949                                                  const std::string&             srcName,
950                                                  const std::string&             apiName,
951                                                  const UniformLayout&   layout,
952                                                  int                                    blockNdx,
953                                                  const void*                    basePtr,
954                                                  deUint32                               unusedMask)
955 {
956         if (type.isBasicType() || (type.isArrayType() && type.getElementType().isBasicType()))
957         {
958                 // Basic type or array of basic types.
959                 bool                                            isArray                 = type.isArrayType();
960                 glu::DataType                           elementType             = isArray ? type.getElementType().getBasicType() : type.getBasicType();
961                 const char*                                     typeName                = glu::getDataTypeName(elementType);
962                 std::string                                     fullApiName             = std::string(apiName) + (isArray ? "[0]" : ""); // Arrays are always postfixed with [0]
963                 int                                                     uniformNdx              = layout.getUniformLayoutIndex(blockNdx, fullApiName);
964                 const UniformLayoutEntry&       entry                   = layout.uniforms[uniformNdx];
965
966                 if (isArray)
967                 {
968                         for (int elemNdx = 0; elemNdx < type.getArraySize(); elemNdx++)
969                         {
970                                 src << "\tresult *= compare_" << typeName << "(" << srcName << "[" << elemNdx << "], ";
971                                 generateValueSrc(src, entry, basePtr, elemNdx);
972                                 src << ");\n";
973                         }
974                 }
975                 else
976                 {
977                         src << "\tresult *= compare_" << typeName << "(" << srcName << ", ";
978                         generateValueSrc(src, entry, basePtr, 0);
979                         src << ");\n";
980                 }
981         }
982         else if (type.isArrayType())
983         {
984                 const VarType& elementType = type.getElementType();
985
986                 for (int elementNdx = 0; elementNdx < type.getArraySize(); elementNdx++)
987                 {
988                         std::string op = std::string("[") + de::toString(elementNdx) + "]";
989                         std::string elementSrcName = std::string(srcName) + op;
990                         std::string elementApiName = std::string(apiName) + op;
991                         generateCompareSrc(src, resultVar, elementType, elementSrcName, elementApiName, layout, blockNdx, basePtr, unusedMask);
992                 }
993         }
994         else
995         {
996                 DE_ASSERT(type.isStructType());
997
998                 for (StructType::ConstIterator memberIter = type.getStruct().begin(); memberIter != type.getStruct().end(); memberIter++)
999                 {
1000                         if (memberIter->getFlags() & unusedMask)
1001                                 continue; // Skip member.
1002
1003                         std::string op = std::string(".") + memberIter->getName();
1004                         std::string memberSrcName = std::string(srcName) + op;
1005                         std::string memberApiName = std::string(apiName) + op;
1006                         generateCompareSrc(src, resultVar, memberIter->getType(), memberSrcName, memberApiName, layout, blockNdx, basePtr, unusedMask);
1007                 }
1008         }
1009 }
1010
1011 void generateCompareSrc (std::ostringstream& src, const char* resultVar, const ShaderInterface& interface, const UniformLayout& layout, const std::map<int, void*>& blockPointers, bool isVertex)
1012 {
1013         deUint32 unusedMask = isVertex ? UNUSED_VERTEX : UNUSED_FRAGMENT;
1014
1015         for (int blockNdx = 0; blockNdx < interface.getNumUniformBlocks(); blockNdx++)
1016         {
1017                 const UniformBlock& block = interface.getUniformBlock(blockNdx);
1018
1019                 if ((block.getFlags() & (isVertex ? DECLARE_VERTEX : DECLARE_FRAGMENT)) == 0)
1020                         continue; // Skip.
1021
1022                 bool                    hasInstanceName = block.hasInstanceName();
1023                 bool                    isArray                 = block.isArray();
1024                 int                             numInstances    = isArray ? block.getArraySize() : 1;
1025                 std::string             apiPrefix               = hasInstanceName ? block.getBlockName() + "." : std::string("");
1026
1027                 DE_ASSERT(!isArray || hasInstanceName);
1028
1029                 for (int instanceNdx = 0; instanceNdx < numInstances; instanceNdx++)
1030                 {
1031                         std::string             instancePostfix         = isArray ? std::string("[") + de::toString(instanceNdx) + "]" : std::string("");
1032                         std::string             blockInstanceName       = block.getBlockName() + instancePostfix;
1033                         std::string             srcPrefix                       = hasInstanceName ? block.getInstanceName() + instancePostfix + "." : std::string("");
1034                         int                             blockLayoutNdx          = layout.getBlockLayoutIndex(blockNdx, instanceNdx);
1035                         void*                   basePtr                         = blockPointers.find(blockLayoutNdx)->second;
1036
1037                         for (UniformBlock::ConstIterator uniformIter = block.begin(); uniformIter != block.end(); uniformIter++)
1038                         {
1039                                 const Uniform& uniform = *uniformIter;
1040
1041                                 if (uniform.getFlags() & unusedMask)
1042                                         continue; // Don't read from that uniform.
1043
1044                                 std::string srcName = srcPrefix + uniform.getName();
1045                                 std::string apiName = apiPrefix + uniform.getName();
1046                                 generateCompareSrc(src, resultVar, uniform.getType(), srcName, apiName, layout, blockNdx, basePtr, unusedMask);
1047                         }
1048                 }
1049         }
1050 }
1051
1052 std::string generateVertexShader (const ShaderInterface& interface, const UniformLayout& layout, const std::map<int, void*>& blockPointers)
1053 {
1054         std::ostringstream src;
1055         src << "#version 450\n";
1056
1057         src << "layout(location = 0) in highp vec4 a_position;\n";
1058         src << "layout(location = 0) out mediump float v_vtxResult;\n";
1059         src << "\n";
1060
1061         std::vector<const StructType*> namedStructs;
1062         interface.getNamedStructs(namedStructs);
1063         for (std::vector<const StructType*>::const_iterator structIter = namedStructs.begin(); structIter != namedStructs.end(); structIter++)
1064                 generateDeclaration(src, **structIter, 0);
1065
1066         for (int blockNdx = 0; blockNdx < interface.getNumUniformBlocks(); blockNdx++)
1067         {
1068                 const UniformBlock& block = interface.getUniformBlock(blockNdx);
1069                 if (block.getFlags() & DECLARE_VERTEX)
1070                         generateDeclaration(src, blockNdx, block);
1071         }
1072
1073         // Comparison utilities.
1074         src << "\n";
1075         generateCompareFuncs(src, interface);
1076
1077         src << "\n"
1078                    "void main (void)\n"
1079                    "{\n"
1080                    "    gl_Position = a_position;\n"
1081                    "    mediump float result = 1.0;\n";
1082
1083         // Value compare.
1084         generateCompareSrc(src, "result", interface, layout, blockPointers, true);
1085
1086         src << "        v_vtxResult = result;\n"
1087                    "}\n";
1088
1089         return src.str();
1090 }
1091
1092 std::string generateFragmentShader (const ShaderInterface& interface, const UniformLayout& layout, const std::map<int, void*>& blockPointers)
1093 {
1094         std::ostringstream src;
1095         src << "#version 450\n";
1096
1097         src << "layout(location = 0) in mediump float v_vtxResult;\n";
1098         src << "layout(location = 0) out mediump vec4 dEQP_FragColor;\n";
1099         src << "\n";
1100
1101         std::vector<const StructType*> namedStructs;
1102         interface.getNamedStructs(namedStructs);
1103         for (std::vector<const StructType*>::const_iterator structIter = namedStructs.begin(); structIter != namedStructs.end(); structIter++)
1104                 generateDeclaration(src, **structIter, 0);
1105
1106         for (int blockNdx = 0; blockNdx < interface.getNumUniformBlocks(); blockNdx++)
1107         {
1108                 const UniformBlock& block = interface.getUniformBlock(blockNdx);
1109                 if (block.getFlags() & DECLARE_FRAGMENT)
1110                         generateDeclaration(src, blockNdx, block);
1111         }
1112
1113         // Comparison utilities.
1114         src << "\n";
1115         generateCompareFuncs(src, interface);
1116
1117         src << "\n"
1118                    "void main (void)\n"
1119                    "{\n"
1120                    "    mediump float result = 1.0;\n";
1121
1122         // Value compare.
1123         generateCompareSrc(src, "result", interface, layout, blockPointers, false);
1124
1125         src << "        dEQP_FragColor = vec4(1.0, v_vtxResult, result, 1.0);\n"
1126                    "}\n";
1127
1128         return src.str();
1129 }
1130
1131 Move<VkBuffer> createBuffer (Context& context, VkDeviceSize bufferSize, vk::VkBufferUsageFlags usageFlags)
1132 {
1133         const VkDevice                          vkDevice                        = context.getDevice();
1134         const DeviceInterface&          vk                                      = context.getDeviceInterface();
1135         const deUint32                          queueFamilyIndex        = context.getUniversalQueueFamilyIndex();
1136
1137         const VkBufferCreateInfo        bufferInfo                      =
1138         {
1139                 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,   // VkStructureType              sType;
1140                 DE_NULL,                                                                // const void*                  pNext;
1141                 0u,                                                                             // VkBufferCreateFlags  flags;
1142                 bufferSize,                                                             // VkDeviceSize                 size;
1143                 usageFlags,                                                             // VkBufferUsageFlags   usage;
1144                 VK_SHARING_MODE_EXCLUSIVE,                              // VkSharingMode                sharingMode;
1145                 1u,                                                                             // deUint32                             queueFamilyIndexCount;
1146                 &queueFamilyIndex                                               // const deUint32*              pQueueFamilyIndices;
1147         };
1148
1149         return vk::createBuffer(vk, vkDevice, &bufferInfo);
1150 }
1151
1152 Move<vk::VkImage> createImage2D (Context& context, deUint32 width, deUint32 height, vk::VkFormat format, vk::VkImageTiling tiling, vk::VkImageUsageFlags usageFlags)
1153 {
1154         const deUint32                          queueFamilyIndex        = context.getUniversalQueueFamilyIndex();
1155         const vk::VkImageCreateInfo     params                          =
1156         {
1157                 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,        // VkStructureType                      sType
1158                 DE_NULL,                                                                        // const void*                          pNext
1159                 0u,                                                                                     // VkImageCreateFlags           flags
1160                 vk::VK_IMAGE_TYPE_2D,                                           // VkImageType                          imageType
1161                 format,                                                                         // VkFormat                                     format
1162                 { width, height, 1u },                                          // VkExtent3D                           extent
1163                 1u,                                                                                     // deUint32                                     mipLevels
1164                 1u,                                                                                     // deUint32                                     arrayLayers
1165                 VK_SAMPLE_COUNT_1_BIT,                                          // VkSampleCountFlagBits        samples
1166                 tiling,                                                                         // VkImageTiling                        tiling
1167                 usageFlags,                                                                     // VkImageUsageFlags            usage
1168                 vk::VK_SHARING_MODE_EXCLUSIVE,                          // VkSharingMode                        sharingMode
1169                 1u,                                                                                     // deUint32                                     queueFamilyIndexCount
1170                 &queueFamilyIndex,                                                      // const deUint32*                      pQueueFamilyIndices
1171                 vk::VK_IMAGE_LAYOUT_UNDEFINED,                          // VkImageLayout                        initialLayout
1172         };
1173
1174         return vk::createImage(context.getDeviceInterface(), context.getDevice(), &params);
1175 }
1176
1177 de::MovePtr<vk::Allocation> allocateAndBindMemory (Context& context, vk::VkBuffer buffer, vk::MemoryRequirement memReqs)
1178 {
1179         const vk::DeviceInterface&              vkd             = context.getDeviceInterface();
1180         const vk::VkMemoryRequirements  bufReqs = vk::getBufferMemoryRequirements(vkd, context.getDevice(), buffer);
1181         de::MovePtr<vk::Allocation>             memory  = context.getDefaultAllocator().allocate(bufReqs, memReqs);
1182
1183         vkd.bindBufferMemory(context.getDevice(), buffer, memory->getMemory(), memory->getOffset());
1184
1185         return memory;
1186 }
1187
1188 de::MovePtr<vk::Allocation> allocateAndBindMemory (Context& context, vk::VkImage image, vk::MemoryRequirement memReqs)
1189 {
1190         const vk::DeviceInterface&        vkd    = context.getDeviceInterface();
1191         const vk::VkMemoryRequirements  imgReqs = vk::getImageMemoryRequirements(vkd, context.getDevice(), image);
1192         de::MovePtr<vk::Allocation>              memory  = context.getDefaultAllocator().allocate(imgReqs, memReqs);
1193
1194         vkd.bindImageMemory(context.getDevice(), image, memory->getMemory(), memory->getOffset());
1195
1196         return memory;
1197 }
1198
1199 Move<vk::VkImageView> createAttachmentView (Context& context, vk::VkImage image, vk::VkFormat format)
1200 {
1201         const vk::VkImageViewCreateInfo params =
1202         {
1203                 vk::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,           // sType
1204                 DE_NULL,                                                                                        // pNext
1205                 0u,                                                                                                     // flags
1206                 image,                                                                                          // image
1207                 vk::VK_IMAGE_VIEW_TYPE_2D,                                                      // viewType
1208                 format,                                                                                         // format
1209                 vk::makeComponentMappingRGBA(),                                         // components
1210                 { vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u,1u },       // subresourceRange
1211         };
1212
1213         return vk::createImageView(context.getDeviceInterface(), context.getDevice(), &params);
1214 }
1215
1216 Move<vk::VkPipelineLayout> createPipelineLayout (Context& context, vk::VkDescriptorSetLayout descriptorSetLayout)
1217 {
1218         const vk::VkPipelineLayoutCreateInfo params =
1219         {
1220                 vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,      // sType
1221                 DE_NULL,                                                                                        // pNext
1222                 0u,                                                                                                     // flags
1223                 1u,                                                                                                     // setLayoutCount
1224                 &descriptorSetLayout,                                                           // pSetLayouts
1225                 0u,                                                                                                     // pushConstantRangeCount
1226                 DE_NULL,                                                                                        // pPushConstantRanges
1227         };
1228
1229         return vk::createPipelineLayout(context.getDeviceInterface(), context.getDevice(), &params);
1230 }
1231
1232 Move<vk::VkCommandPool> createCmdPool (Context& context)
1233 {
1234         const deUint32                                  queueFamilyIndex        = context.getUniversalQueueFamilyIndex();
1235         const vk::VkCommandPoolCreateInfo       params                          =
1236         {
1237                 vk::VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,                 // sType
1238                 DE_NULL,                                                                                                // pNext
1239                 vk::VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,    // flags
1240                 queueFamilyIndex,                                                                               // queueFamilyIndex
1241         };
1242
1243         return vk::createCommandPool(context.getDeviceInterface(), context.getDevice(), &params);
1244 }
1245
1246 Move<vk::VkCommandBuffer> createCmdBuffer (Context& context, vk::VkCommandPool cmdPool)
1247 {
1248         const vk::VkCommandBufferAllocateInfo params =
1249         {
1250                 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,     // sType
1251                 DE_NULL,                                                                                        // pNext
1252                 cmdPool,                                                                                        // commandPool
1253                 vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY,                            // level
1254                 1u,                                                                                                     // bufferCount
1255         };
1256
1257         return vk::allocateCommandBuffer(context.getDeviceInterface(), context.getDevice(), &params);
1258 }
1259
1260
1261 // UniformBlockCaseInstance
1262
1263 class UniformBlockCaseInstance : public vkt::TestInstance
1264 {
1265 public:
1266                                                                         UniformBlockCaseInstance        (Context&                                               context,
1267                                                                                                                                  UniformBlockCase::BufferMode   bufferMode,
1268                                                                                                                                  const UniformLayout&                   layout,
1269                                                                                                                                  const std::map<int, void*>&    blockPointers);
1270         virtual                                                 ~UniformBlockCaseInstance       (void);
1271         virtual tcu::TestStatus                 iterate                                         (void);
1272
1273 private:
1274         enum
1275         {
1276                 RENDER_WIDTH = 100,
1277                 RENDER_HEIGHT = 100,
1278         };
1279
1280         vk::Move<VkRenderPass>                  createRenderPass                        (vk::VkFormat format) const;
1281         vk::Move<VkFramebuffer>                 createFramebuffer                       (vk::VkRenderPass renderPass, vk::VkImageView colorImageView) const;
1282         vk::Move<VkDescriptorSetLayout> createDescriptorSetLayout       (void) const;
1283         vk::Move<VkDescriptorPool>              createDescriptorPool            (void) const;
1284         vk::Move<VkPipeline>                    createPipeline                          (vk::VkShaderModule vtxShaderModule, vk::VkShaderModule fragShaderModule, vk::VkPipelineLayout pipelineLayout, vk::VkRenderPass renderPass) const;
1285
1286         vk::VkDescriptorBufferInfo              addUniformData                          (deUint32 size, const void* dataPtr);
1287
1288         UniformBlockCase::BufferMode    m_bufferMode;
1289         const UniformLayout&                    m_layout;
1290         const std::map<int, void*>&             m_blockPointers;
1291
1292         typedef de::SharedPtr<vk::Unique<vk::VkBuffer> >        VkBufferSp;
1293         typedef de::SharedPtr<vk::Allocation>                           AllocationSp;
1294
1295         std::vector<VkBufferSp>                 m_uniformBuffers;
1296         std::vector<AllocationSp>               m_uniformAllocs;
1297 };
1298
1299 UniformBlockCaseInstance::UniformBlockCaseInstance (Context&                                            ctx,
1300                                                                                                         UniformBlockCase::BufferMode    bufferMode,
1301                                                                                                         const UniformLayout&                    layout,
1302                                                                                                         const std::map<int, void*>&             blockPointers)
1303         : vkt::TestInstance (ctx)
1304         , m_bufferMode          (bufferMode)
1305         , m_layout                      (layout)
1306         , m_blockPointers       (blockPointers)
1307 {
1308 }
1309
1310 UniformBlockCaseInstance::~UniformBlockCaseInstance (void)
1311 {
1312 }
1313
1314 tcu::TestStatus UniformBlockCaseInstance::iterate (void)
1315 {
1316         const vk::DeviceInterface&              vk                                      = m_context.getDeviceInterface();
1317         const vk::VkDevice                              device                          = m_context.getDevice();
1318         const vk::VkQueue                               queue                           = m_context.getUniversalQueue();
1319         const deUint32                                  queueFamilyIndex        = m_context.getUniversalQueueFamilyIndex();
1320
1321         const float positions[] =
1322         {
1323                 -1.0f, -1.0f, 0.0f, 1.0f,
1324                 -1.0f, +1.0f, 0.0f, 1.0f,
1325                 +1.0f, -1.0f, 0.0f, 1.0f,
1326                 +1.0f, +1.0f, 0.0f, 1.0f
1327         };
1328
1329         const deUint32 indices[] = { 0, 1, 2, 2, 1, 3 };
1330
1331         vk::Unique<VkBuffer>                            positionsBuffer         (createBuffer(m_context, sizeof(positions), vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
1332         de::UniquePtr<Allocation>                       positionsAlloc          (allocateAndBindMemory(m_context, *positionsBuffer, MemoryRequirement::HostVisible));
1333         vk::Unique<VkBuffer>                            indicesBuffer           (createBuffer(m_context, sizeof(indices), vk::VK_BUFFER_USAGE_INDEX_BUFFER_BIT|vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
1334         de::UniquePtr<Allocation>                       indicesAlloc            (allocateAndBindMemory(m_context, *indicesBuffer, MemoryRequirement::HostVisible));
1335
1336         int minUniformBufferOffsetAlignment = getminUniformBufferOffsetAlignment(m_context);
1337
1338         // Upload attrbiutes data
1339         {
1340                 deMemcpy(positionsAlloc->getHostPtr(), positions, sizeof(positions));
1341                 flushMappedMemoryRange(vk, device, positionsAlloc->getMemory(), positionsAlloc->getOffset(), sizeof(positions));
1342
1343                 deMemcpy(indicesAlloc->getHostPtr(), indices, sizeof(indices));
1344                 flushMappedMemoryRange(vk, device, indicesAlloc->getMemory(), indicesAlloc->getOffset(), sizeof(indices));
1345         }
1346
1347         vk::Unique<VkImage>                                     colorImage                      (createImage2D(m_context,
1348                                                                                                                                                         RENDER_WIDTH,
1349                                                                                                                                                         RENDER_HEIGHT,
1350                                                                                                                                                         vk::VK_FORMAT_R8G8B8A8_UNORM,
1351                                                                                                                                                         vk::VK_IMAGE_TILING_OPTIMAL,
1352                                                                                                                                                         vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT|vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT));
1353         de::UniquePtr<Allocation>                       colorImageAlloc         (allocateAndBindMemory(m_context, *colorImage, MemoryRequirement::Any));
1354         vk::Unique<VkImageView>                         colorImageView          (createAttachmentView(m_context, *colorImage, vk::VK_FORMAT_R8G8B8A8_UNORM));
1355
1356         vk::Unique<VkDescriptorSetLayout>       descriptorSetLayout     (createDescriptorSetLayout());
1357         vk::Unique<VkDescriptorPool>            descriptorPool          (createDescriptorPool());
1358
1359         const VkDescriptorSetAllocateInfo       descriptorSetAllocateInfo =
1360         {
1361                 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,         // VkStructureType                              sType;
1362                 DE_NULL,                                                                                        // const void*                                  pNext;
1363                 *descriptorPool,                                                                        // VkDescriptorPool                             descriptorPool;
1364                 1u,                                                                                                     // deUint32                                             setLayoutCount;
1365                 &descriptorSetLayout.get()                                                      // const VkDescriptorSetLayout* pSetLayouts;
1366         };
1367
1368         vk::Unique<VkDescriptorSet>                     descriptorSet(vk::allocateDescriptorSet(vk, device, &descriptorSetAllocateInfo));
1369         int                                                                     numBlocks = (int)m_layout.blocks.size();
1370         std::vector<vk::VkDescriptorBufferInfo> descriptors(numBlocks);
1371
1372         // Upload uniform data
1373         {
1374                 vk::DescriptorSetUpdateBuilder  descriptorSetUpdateBuilder;
1375
1376                 if (m_bufferMode == UniformBlockCase::BUFFERMODE_PER_BLOCK)
1377                 {
1378                         for (int blockNdx = 0; blockNdx < numBlocks; blockNdx++)
1379                         {
1380                                 const BlockLayoutEntry& block = m_layout.blocks[blockNdx];
1381                                 const void*     srcPtr = m_blockPointers.find(blockNdx)->second;
1382
1383                                 descriptors[blockNdx] = addUniformData(block.size, srcPtr);
1384                                 descriptorSetUpdateBuilder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::bindingArrayElement(block.bindingNdx, block.instanceNdx),
1385                                                                                                                 VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &descriptors[blockNdx]);
1386                         }
1387                 }
1388                 else
1389                 {
1390                         int currentOffset = 0;
1391                         std::map<int, int> offsets;
1392                         for (int blockNdx = 0; blockNdx < numBlocks; blockNdx++)
1393                         {
1394                                 if (minUniformBufferOffsetAlignment > 0)
1395                                         currentOffset = deAlign32(currentOffset, minUniformBufferOffsetAlignment);
1396                                 offsets[blockNdx] = currentOffset;
1397                                 currentOffset += m_layout.blocks[blockNdx].size;
1398                         }
1399
1400                         deUint32 totalSize = currentOffset;
1401
1402                         // Make a copy of the data that satisfies the device's min uniform buffer alignment
1403                         std::vector<deUint8> data;
1404                         data.resize(totalSize);
1405                         for (int blockNdx = 0; blockNdx < numBlocks; blockNdx++)
1406                         {
1407                                 deMemcpy(&data[offsets[blockNdx]], m_blockPointers.find(blockNdx)->second, m_layout.blocks[blockNdx].size);
1408                         }
1409
1410                         vk::VkBuffer buffer = addUniformData(totalSize, &data[0]).buffer;
1411
1412                         for (int blockNdx = 0; blockNdx < numBlocks; blockNdx++)
1413                         {
1414                                 const BlockLayoutEntry& block = m_layout.blocks[blockNdx];
1415                                 deUint32 size = block.size;
1416
1417                                 const VkDescriptorBufferInfo    descriptor =
1418                                 {
1419                                         buffer,                                                 // VkBuffer             buffer;
1420                                         (deUint32)offsets[blockNdx],    // VkDeviceSize offset;
1421                                         size,                                                   // VkDeviceSize range;
1422                                 };
1423
1424                                 descriptors[blockNdx] = descriptor;
1425                                 descriptorSetUpdateBuilder.writeSingle(*descriptorSet,
1426                                                                                                                 vk::DescriptorSetUpdateBuilder::Location::bindingArrayElement(block.bindingNdx, block.instanceNdx),
1427                                                                                                                 VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
1428                                                                                                                 &descriptors[blockNdx]);
1429                         }
1430                 }
1431
1432                 descriptorSetUpdateBuilder.update(vk, device);
1433         }
1434
1435         vk::Unique<VkRenderPass>                        renderPass                      (createRenderPass(vk::VK_FORMAT_R8G8B8A8_UNORM));
1436         vk::Unique<VkFramebuffer>                       framebuffer                     (createFramebuffer(*renderPass, *colorImageView));
1437         vk::Unique<VkPipelineLayout>            pipelineLayout          (createPipelineLayout(m_context, *descriptorSetLayout));
1438
1439         vk::Unique<VkShaderModule>                      vtxShaderModule         (vk::createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0));
1440         vk::Unique<VkShaderModule>                      fragShaderModule        (vk::createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0));
1441         vk::Unique<VkPipeline>                          pipeline                        (createPipeline(*vtxShaderModule, *fragShaderModule, *pipelineLayout, *renderPass));
1442         vk::Unique<VkCommandPool>                       cmdPool                         (createCmdPool(m_context));
1443         vk::Unique<VkCommandBuffer>                     cmdBuffer                       (createCmdBuffer(m_context, *cmdPool));
1444         vk::Unique<VkBuffer>                            readImageBuffer         (createBuffer(m_context, (vk::VkDeviceSize)(RENDER_WIDTH * RENDER_HEIGHT * 4), vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1445         de::UniquePtr<Allocation>                       readImageAlloc          (allocateAndBindMemory(m_context, *readImageBuffer, vk::MemoryRequirement::HostVisible));
1446
1447         // Record command buffer
1448         const vk::VkCommandBufferBeginInfo beginInfo    =
1449         {
1450                 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,        // VkStructureType                                      sType;
1451                 DE_NULL,                                                                                        // const void*                                          pNext;
1452                 0u,                                                                                                     // VkCommandBufferUsageFlags            flags;
1453                 (const vk::VkCommandBufferInheritanceInfo*)DE_NULL,
1454         };
1455         VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &beginInfo));
1456
1457         const vk::VkClearValue clearValue = vk::makeClearValueColorF32(0.125f, 0.25f, 0.75f, 1.0f);
1458         const vk::VkRenderPassBeginInfo passBeginInfo   =
1459         {
1460                 vk::VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,   // VkStructureType              sType;
1461                 DE_NULL,                                                                                // const void*                  pNext;
1462                 *renderPass,                                                                    // VkRenderPass                 renderPass;
1463                 *framebuffer,                                                                   // VkFramebuffer                framebuffer;
1464                 { { 0, 0 }, { RENDER_WIDTH, RENDER_HEIGHT } },  // VkRect2D                             renderArea;
1465                 1u,                                                                                             // deUint32                             clearValueCount;
1466                 &clearValue,                                                                    // const VkClearValue*  pClearValues;
1467         };
1468
1469         // Add barrier for initializing image state 
1470         {
1471                 const vk::VkImageMemoryBarrier  initializeBarrier =
1472                 {
1473                         vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,             // VkStructureType                      sType;
1474                         DE_NULL,                                                                                // const void*                          pNext
1475                         0,                                                                                              // VVkAccessFlags                       srcAccessMask;
1476                         vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,               // VkAccessFlags                        dstAccessMask;
1477                         vk::VK_IMAGE_LAYOUT_UNDEFINED,                                  // VkImageLayout                        oldLayout;
1478                         vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,   // VkImageLayout                        newLayout;
1479                         queueFamilyIndex,                                                               // deUint32                                     srcQueueFamilyIndex;
1480                         queueFamilyIndex,                                                               // deUint32                                     dstQueueFamilyIndex;
1481                         *colorImage,                                                                    // VkImage                                      image;
1482                         {
1483                                 vk::VK_IMAGE_ASPECT_COLOR_BIT,                  // VkImageAspectFlags   aspectMask;
1484                                 0u,                                                                             // deUint32                             baseMipLevel;
1485                                 1u,                                                                             // deUint32                             mipLevels;
1486                                 0u,                                                                             // deUint32                             baseArraySlice;
1487                                 1u,                                                                             // deUint32                             arraySize;
1488                         }                                                                                               // VkImageSubresourceRange      subresourceRange
1489                 };
1490
1491                 vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, (vk::VkDependencyFlags)0,
1492                         0, (const vk::VkMemoryBarrier*)DE_NULL,
1493                         0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
1494                         1, &initializeBarrier);
1495         }
1496
1497         vk.cmdBeginRenderPass(*cmdBuffer, &passBeginInfo, vk::VK_SUBPASS_CONTENTS_INLINE);
1498
1499         vk.cmdBindPipeline(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1500         vk.cmdBindDescriptorSets(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &*descriptorSet, 0u, DE_NULL);
1501
1502         const vk::VkDeviceSize offsets[] = { 0u };
1503         vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &*positionsBuffer, offsets);
1504         vk.cmdBindIndexBuffer(*cmdBuffer, *indicesBuffer, (vk::VkDeviceSize)0, vk::VK_INDEX_TYPE_UINT32);
1505
1506         vk.cmdDrawIndexed(*cmdBuffer, DE_LENGTH_OF_ARRAY(indices), 1u, 0u, 0u, 0u);
1507         vk.cmdEndRenderPass(*cmdBuffer);
1508
1509         // Add render finish barrier
1510         {
1511                 const vk::VkImageMemoryBarrier  renderFinishBarrier =
1512                 {
1513                         vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,             // VkStructureType                      sType;
1514                         DE_NULL,                                                                                // const void*                          pNext
1515                         vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,               // VVkAccessFlags                       srcAccessMask;
1516                         vk::VK_ACCESS_TRANSFER_READ_BIT,                                // VkAccessFlags                        dstAccessMask;
1517                         vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,   // VkImageLayout                        oldLayout;
1518                         vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,               // VkImageLayout                        newLayout;
1519                         queueFamilyIndex,                                                               // deUint32                                     srcQueueFamilyIndex;
1520                         queueFamilyIndex,                                                               // deUint32                                     dstQueueFamilyIndex;
1521                         *colorImage,                                                                    // VkImage                                      image;
1522                         {
1523                                 vk::VK_IMAGE_ASPECT_COLOR_BIT,                  // VkImageAspectFlags   aspectMask;
1524                                 0u,                                                                             // deUint32                             baseMipLevel;
1525                                 1u,                                                                             // deUint32                             mipLevels;
1526                                 0u,                                                                             // deUint32                             baseArraySlice;
1527                                 1u,                                                                             // deUint32                             arraySize;
1528                         }                                                                                               // VkImageSubresourceRange      subresourceRange
1529                 };
1530
1531                 vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (vk::VkDependencyFlags)0,
1532                                                           0, (const vk::VkMemoryBarrier*)DE_NULL,
1533                                                           0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
1534                                                           1, &renderFinishBarrier);
1535         }
1536
1537         // Add Image->Buffer copy command
1538         {
1539                 const vk::VkBufferImageCopy copyParams =
1540                 {
1541                         (vk::VkDeviceSize)0u,                                   // VkDeviceSize                         bufferOffset;
1542                         (deUint32)RENDER_WIDTH,                                 // deUint32                                     bufferRowLength;
1543                         (deUint32)RENDER_HEIGHT,                                // deUint32                                     bufferImageHeight;
1544                         {
1545                                 vk::VK_IMAGE_ASPECT_COLOR_BIT,  // VkImageAspect        aspect;
1546                                 0u,                                                             // deUint32                     mipLevel;
1547                                 0u,                                                             // deUint32                     arrayLayer;
1548                                 1u,                                                             // deUint32                     arraySize;
1549                         },                                                                              // VkImageSubresourceCopy       imageSubresource
1550                         { 0u, 0u, 0u },                                                 // VkOffset3D                           imageOffset;
1551                         { RENDER_WIDTH, RENDER_HEIGHT, 1u }             // VkExtent3D                           imageExtent;
1552                 };
1553
1554                 vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImage, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *readImageBuffer, 1u, &copyParams);
1555         }
1556
1557         // Add copy finish barrier
1558         {
1559                 const vk::VkBufferMemoryBarrier copyFinishBarrier       =
1560                 {
1561                         vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,            // VkStructureType              sType;
1562                         DE_NULL,                                                                                        // const void*                  pNext;
1563                         VK_ACCESS_TRANSFER_WRITE_BIT,                                           // VkAccessFlags                srcAccessMask;
1564                         VK_ACCESS_HOST_READ_BIT,                                                        // VkAccessFlags                dstAccessMask;
1565                         queueFamilyIndex,                                                                       // deUint32                             srcQueueFamilyIndex;
1566                         queueFamilyIndex,                                                                       // deUint32                             destQueueFamilyIndex;
1567                         *readImageBuffer,                                                                       // VkBuffer                             buffer;
1568                         0u,                                                                                                     // VkDeviceSize                 offset;
1569                         (vk::VkDeviceSize)(RENDER_WIDTH * RENDER_HEIGHT * 4)// VkDeviceSize                     size;
1570                 };
1571
1572                 vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT, (vk::VkDependencyFlags)0,
1573                                                           0, (const vk::VkMemoryBarrier*)DE_NULL,
1574                                                           1, &copyFinishBarrier,
1575                                                           0, (const vk::VkImageMemoryBarrier*)DE_NULL);
1576         }
1577
1578         VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1579
1580         // Submit the command buffer
1581         {
1582                 const vk::VkFenceCreateInfo fenceParams =
1583                 {
1584                         vk::VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,        // VkStructureType              sType;
1585                         DE_NULL,                                                                        // const void*                  pNext;
1586                         0u,                                                                                     // VkFenceCreateFlags   flags;
1587                 };
1588                 const Unique<vk::VkFence> fence(vk::createFence(vk, device, &fenceParams));
1589
1590                 const VkSubmitInfo                      submitInfo      =
1591                 {
1592                         VK_STRUCTURE_TYPE_SUBMIT_INFO,  // VkStructureType                      sType;
1593                         DE_NULL,                                                // const void*                          pNext;
1594                         0u,                                                             // deUint32                                     waitSemaphoreCount;
1595                         DE_NULL,                                                // const VkSemaphore*           pWaitSemaphores;
1596                         (const VkPipelineStageFlags*)DE_NULL,
1597                         1u,                                                             // deUint32                                     commandBufferCount;
1598                         &cmdBuffer.get(),                               // const VkCommandBuffer*       pCommandBuffers;
1599                         0u,                                                             // deUint32                                     signalSemaphoreCount;
1600                         DE_NULL                                                 // const VkSemaphore*           pSignalSemaphores;
1601                 };
1602
1603                 VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, *fence));
1604                 VK_CHECK(vk.waitForFences(device, 1u, &fence.get(), DE_TRUE, ~0ull));
1605         }
1606
1607         // Read back the results
1608         tcu::Surface surface(RENDER_WIDTH, RENDER_HEIGHT);
1609         {
1610                 const tcu::TextureFormat textureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8);
1611                 const tcu::ConstPixelBufferAccess imgAccess(textureFormat, RENDER_WIDTH, RENDER_HEIGHT, 1, readImageAlloc->getHostPtr());
1612                 const vk::VkDeviceSize bufferSize = RENDER_WIDTH * RENDER_HEIGHT * 4;
1613                 invalidateMappedMemoryRange(vk, device, readImageAlloc->getMemory(), readImageAlloc->getOffset(), bufferSize);
1614
1615                 tcu::copy(surface.getAccess(), imgAccess);
1616         }
1617
1618         // Check if the result image is all white
1619         tcu::RGBA white(tcu::RGBA::white());
1620         int numFailedPixels = 0;
1621
1622         for (int y = 0; y < surface.getHeight(); y++)
1623         {
1624                 for (int x = 0; x < surface.getWidth(); x++)
1625                 {
1626                         if (surface.getPixel(x, y) != white)
1627                                 numFailedPixels += 1;
1628                 }
1629         }
1630
1631         if (numFailedPixels > 0)
1632         {
1633                 tcu::TestLog& log = m_context.getTestContext().getLog();
1634                 log << tcu::TestLog::Image("Image", "Rendered image", surface);
1635                 log << tcu::TestLog::Message << "Image comparison failed, got " << numFailedPixels << " non-white pixels" << tcu::TestLog::EndMessage;
1636
1637                 for (size_t blockNdx = 0; blockNdx < m_layout.blocks.size(); blockNdx++)
1638                 {
1639                         const BlockLayoutEntry& block = m_layout.blocks[blockNdx];
1640                         log << tcu::TestLog::Message << "Block index: " << blockNdx << " infos: " << block << tcu::TestLog::EndMessage;
1641                 }
1642
1643                 for (size_t uniformNdx = 0; uniformNdx < m_layout.uniforms.size(); uniformNdx++)
1644                 {
1645                         log << tcu::TestLog::Message << "Uniform index: " << uniformNdx << " infos: " << m_layout.uniforms[uniformNdx] << tcu::TestLog::EndMessage;
1646                 }
1647
1648                 return tcu::TestStatus::fail("Detected non-white pixels");
1649         }
1650         else
1651                 return tcu::TestStatus::pass("Full white image ok");
1652 }
1653
1654 vk::VkDescriptorBufferInfo UniformBlockCaseInstance::addUniformData (deUint32 size, const void* dataPtr)
1655 {
1656         const VkDevice                                  vkDevice                        = m_context.getDevice();
1657         const DeviceInterface&                  vk                                      = m_context.getDeviceInterface();
1658
1659         Move<VkBuffer>                                  buffer  = createBuffer(m_context, size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
1660         de::MovePtr<Allocation>                 alloc   = allocateAndBindMemory(m_context, *buffer, vk::MemoryRequirement::HostVisible);
1661
1662         deMemcpy(alloc->getHostPtr(), dataPtr, size);
1663         flushMappedMemoryRange(vk, vkDevice, alloc->getMemory(), alloc->getOffset(), size);
1664
1665         const VkDescriptorBufferInfo                    descriptor                      =
1666         {
1667                 *buffer,                                // VkBuffer             buffer;
1668                 0u,                                             // VkDeviceSize offset;
1669                 size,                                   // VkDeviceSize range;
1670
1671         };
1672
1673         m_uniformBuffers.push_back(VkBufferSp(new vk::Unique<vk::VkBuffer>(buffer)));
1674         m_uniformAllocs.push_back(AllocationSp(alloc.release()));
1675
1676         return descriptor;
1677 }
1678
1679 vk::Move<VkRenderPass> UniformBlockCaseInstance::createRenderPass (vk::VkFormat format) const
1680 {
1681         const VkDevice                                  vkDevice                                = m_context.getDevice();
1682         const DeviceInterface&                  vk                                              = m_context.getDeviceInterface();
1683
1684         const VkAttachmentDescription   attachmentDescription   =
1685         {
1686                 0u,                                                                                             // VkAttachmentDescriptorFlags  flags;
1687                 format,                                                                                 // VkFormat                                             format;
1688                 VK_SAMPLE_COUNT_1_BIT,                                                  // VkSampleCountFlagBits                samples;
1689                 VK_ATTACHMENT_LOAD_OP_CLEAR,                                    // VkAttachmentLoadOp                   loadOp;
1690                 VK_ATTACHMENT_STORE_OP_STORE,                                   // VkAttachmentStoreOp                  storeOp;
1691                 VK_ATTACHMENT_LOAD_OP_DONT_CARE,                                // VkAttachmentLoadOp                   stencilLoadOp;
1692                 VK_ATTACHMENT_STORE_OP_DONT_CARE,                               // VkAttachmentStoreOp                  stencilStoreOp;
1693                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,               // VkImageLayout                                initialLayout;
1694                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,               // VkImageLayout                                finalLayout;
1695         };
1696
1697         const VkAttachmentReference             attachmentReference             =
1698         {
1699                 0u,                                                                                     // deUint32                     attachment;
1700                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL        // VkImageLayout        layout;
1701         };
1702
1703
1704         const VkSubpassDescription              subpassDescription              =
1705         {
1706                 0u,                                                                                             // VkSubpassDescriptionFlags    flags;
1707                 VK_PIPELINE_BIND_POINT_GRAPHICS,                                // VkPipelineBindPoint                  pipelineBindPoint;
1708                 0u,                                                                                             // deUint32                                             inputAttachmentCount;
1709                 DE_NULL,                                                                                // const VkAttachmentReference* pInputAttachments;
1710                 1u,                                                                                             // deUint32                                             colorAttachmentCount;
1711                 &attachmentReference,                                                   // const VkAttachmentReference* pColorAttachments;
1712                 DE_NULL,                                                                                // const VkAttachmentReference* pResolveAttachments;
1713                 DE_NULL,                                                                                // const VkAttachmentReference* pDepthStencilAttachment;
1714                 0u,                                                                                             // deUint32                                             preserveAttachmentCount;
1715                 DE_NULL                                                                                 // const VkAttachmentReference* pPreserveAttachments;
1716         };
1717
1718         const VkRenderPassCreateInfo    renderPassParams                =
1719         {
1720                 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,              // VkStructureType                                      sType;
1721                 DE_NULL,                                                                                // const void*                                          pNext;
1722                 0u,                                                                                             // VkRenderPassCreateFlags                      flags;
1723                 1u,                                                                                             // deUint32                                                     attachmentCount;
1724                 &attachmentDescription,                                                 // const VkAttachmentDescription*       pAttachments;
1725                 1u,                                                                                             // deUint32                                                     subpassCount;
1726                 &subpassDescription,                                                    // const VkSubpassDescription*          pSubpasses;
1727                 0u,                                                                                             // deUint32                                                     dependencyCount;
1728                 DE_NULL                                                                                 // const VkSubpassDependency*           pDependencies;
1729         };
1730
1731         return vk::createRenderPass(vk, vkDevice, &renderPassParams);
1732 }
1733
1734 vk::Move<VkFramebuffer> UniformBlockCaseInstance::createFramebuffer (vk::VkRenderPass renderPass, vk::VkImageView colorImageView) const
1735 {
1736         const VkDevice                                  vkDevice                        = m_context.getDevice();
1737         const DeviceInterface&                  vk                                      = m_context.getDeviceInterface();
1738
1739         const VkFramebufferCreateInfo   framebufferParams       =
1740         {
1741                 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,              // VkStructureType                      sType;
1742                 DE_NULL,                                                                                // const void*                          pNext;
1743                 0u,                                                                                             // VkFramebufferCreateFlags     flags;
1744                 renderPass,                                                                             // VkRenderPass                         renderPass;
1745                 1u,                                                                                             // deUint32                                     attachmentCount;
1746                 &colorImageView,                                                                // const VkImageView*           pAttachments;
1747                 RENDER_WIDTH,                                                                   // deUint32                                     width;
1748                 RENDER_HEIGHT,                                                                  // deUint32                                     height;
1749                 1u                                                                                              // deUint32                                     layers;
1750         };
1751
1752         return vk::createFramebuffer(vk, vkDevice, &framebufferParams);
1753 }
1754
1755 vk::Move<VkDescriptorSetLayout> UniformBlockCaseInstance::createDescriptorSetLayout (void) const
1756 {
1757         int numBlocks = (int)m_layout.blocks.size();
1758         int lastBindingNdx = -1;
1759         std::vector<int> lengths;
1760
1761         for (int blockNdx = 0; blockNdx < numBlocks; blockNdx++)
1762         {
1763                 const BlockLayoutEntry& block = m_layout.blocks[blockNdx];
1764
1765                 if (block.bindingNdx == lastBindingNdx)
1766                 {
1767                         lengths.back()++;
1768                 }
1769                 else
1770                 {
1771                         lengths.push_back(1);
1772                         lastBindingNdx = block.bindingNdx;
1773                 }
1774         }
1775
1776         vk::DescriptorSetLayoutBuilder layoutBuilder;
1777         for (size_t i = 0; i < lengths.size(); i++)
1778         {
1779                 if (lengths[i] > 0)
1780                 {
1781                         layoutBuilder.addArrayBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, lengths[i], vk::VK_SHADER_STAGE_ALL);
1782                 }
1783                 else
1784                 {
1785                         layoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, vk::VK_SHADER_STAGE_ALL);
1786                 }
1787         }
1788
1789         return layoutBuilder.build(m_context.getDeviceInterface(), m_context.getDevice());
1790 }
1791
1792 vk::Move<VkDescriptorPool> UniformBlockCaseInstance::createDescriptorPool (void) const
1793 {
1794         vk::DescriptorPoolBuilder poolBuilder;
1795
1796         return poolBuilder
1797                 .addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, (int)m_layout.blocks.size())
1798                 .build(m_context.getDeviceInterface(), m_context.getDevice(), VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1799 }
1800
1801 vk::Move<VkPipeline> UniformBlockCaseInstance::createPipeline (vk::VkShaderModule vtxShaderModule, vk::VkShaderModule fragShaderModule, vk::VkPipelineLayout pipelineLayout, vk::VkRenderPass renderPass) const
1802 {
1803         const VkDevice                                                                  vkDevice                                = m_context.getDevice();
1804         const DeviceInterface&                                                  vk                                              = m_context.getDeviceInterface();
1805
1806         const VkVertexInputBindingDescription                   vertexBinding                   =
1807         {
1808                 0,                                                                      // deUint32                                     binding;
1809                 (deUint32)sizeof(float) * 4,            // deUint32                                     strideInBytes;
1810                 VK_VERTEX_INPUT_RATE_VERTEX                     // VkVertexInputStepRate        inputRate;
1811         };
1812
1813         const VkVertexInputAttributeDescription                 vertexAttribute                 =
1814         {
1815                 0,                                                                      // deUint32             location;
1816                 0,                                                                      // deUint32             binding;
1817                 VK_FORMAT_R32G32B32A32_SFLOAT,          // VkFormat             format;
1818                 0u                                                                      // deUint32             offset;
1819         };
1820
1821         const VkPipelineShaderStageCreateInfo                   shaderStages[2] =
1822         {
1823                 {
1824                         VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,    // VkStructureType                                      sType;
1825                         DE_NULL,                                                                                                // const void*                                          pNext;
1826                         0u,                                                                                                             // VkPipelineShaderStageCreateFlags     flags;
1827                         VK_SHADER_STAGE_VERTEX_BIT,                                                             // VkShaderStageFlagBits                        stage;
1828                         vtxShaderModule,                                                                                // VkShaderModule                                       module;
1829                         "main",                                                                                                 // const char*                                          pName;
1830                         DE_NULL                                                                                                 // const VkSpecializationInfo*          pSpecializationInfo;
1831                 },
1832                 {
1833                         VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,    // VkStructureType                                      sType;
1834                         DE_NULL,                                                                                                // const void*                                          pNext;
1835                         0u,                                                                                                             // VkPipelineShaderStageCreateFlags flags;
1836                         VK_SHADER_STAGE_FRAGMENT_BIT,                                                   // VkShaderStageFlagBits                        stage;
1837                         fragShaderModule,                                                                               // VkShaderModule                                       module;
1838                         "main",                                                                                                 // const char*                                          pName;
1839                         DE_NULL                                                                                                 // const VkSpecializationInfo*          pSpecializationInfo;
1840                 }
1841         };
1842
1843         const VkPipelineVertexInputStateCreateInfo              vertexInputStateParams          =
1844         {
1845                 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,      // VkStructureType                                                      sType;
1846                 DE_NULL,                                                                                                        // const void*                                                          pNext;
1847                 0u,                                                                                                                     // VkPipelineVertexInputStateCreateFlags        flags;
1848                 1u,                                                                                                                     // deUint32                                                                     vertexBindingDescriptionCount;
1849                 &vertexBinding,                                                                                         // const VkVertexInputBindingDescription*       pVertexBindingDescriptions;
1850                 1u,                                                                                                                     // deUint32                                                                     vertexAttributeDescriptionCount;
1851                 &vertexAttribute,                                                                                       // const VkVertexInputAttributeDescription*     pVertexAttributeDescriptions;
1852         };
1853
1854         const VkPipelineInputAssemblyStateCreateInfo    inputAssemblyStateParams        =
1855         {
1856                 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,// VkStructureType                                                  sType;
1857                 DE_NULL,                                                                                                        // const void*                                                          pNext;
1858                 0u,                                                                                                                     // VkPipelineInputAssemblyStateCreateFlags      flags;
1859                 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,                                            // VkPrimitiveTopology                                          topology;
1860                 false                                                                                                           // VkBool32                                                                     primitiveRestartEnable;
1861         };
1862
1863         const VkViewport                                                                viewport                                        =
1864         {
1865                 0.0f,                                   // float        originX;
1866                 0.0f,                                   // float        originY;
1867                 (float)RENDER_WIDTH,    // float        width;
1868                 (float)RENDER_HEIGHT,   // float        height;
1869                 0.0f,                                   // float        minDepth;
1870                 1.0f                                    // float        maxDepth;
1871         };
1872
1873
1874         const VkRect2D                                                                  scissor                                         =
1875         {
1876                 {
1877                         0u,                             // deUint32     x;
1878                         0u,                             // deUint32     y;
1879                 },                                              // VkOffset2D   offset;
1880                 {
1881                         RENDER_WIDTH,   // deUint32     width;
1882                         RENDER_HEIGHT,  // deUint32     height;
1883                 },                                              // VkExtent2D   extent;
1884         };
1885
1886         const VkPipelineViewportStateCreateInfo                 viewportStateParams                     =
1887         {
1888                 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,          // VkStructureType                                              sType;
1889                 DE_NULL,                                                                                                        // const void*                                                  pNext;
1890                 0u,                                                                                                                     // VkPipelineViewportStateCreateFlags   flags;
1891                 1u,                                                                                                                     // deUint32                                                             viewportCount;
1892                 &viewport,                                                                                                      // const VkViewport*                                    pViewports;
1893                 1u,                                                                                                                     // deUint32                                                             scissorsCount;
1894                 &scissor,                                                                                                       // const VkRect2D*                                              pScissors;
1895         };
1896
1897         const VkPipelineRasterizationStateCreateInfo    rasterStateParams                       =
1898         {
1899                 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType                                                  sType;
1900                 DE_NULL,                                                                                                        // const void*                                                          pNext;
1901                 0u,                                                                                                                     // VkPipelineRasterizationStateCreateFlags      flags;
1902                 false,                                                                                                          // VkBool32                                                                     depthClampEnable;
1903                 false,                                                                                                          // VkBool32                                                                     rasterizerDiscardEnable;
1904                 VK_POLYGON_MODE_FILL,                                                                           // VkPolygonMode                                                        polygonMode;
1905                 VK_CULL_MODE_NONE,                                                                                      // VkCullModeFlags                                                      cullMode;
1906                 VK_FRONT_FACE_COUNTER_CLOCKWISE,                                                        // VkFrontFace                                                          frontFace;
1907                 false,                                                                                                          // VkBool32                                                                     depthBiasEnable;
1908                 0.0f,                                                                                                           // float                                                                        depthBiasConstantFactor;
1909                 0.0f,                                                                                                           // float                                                                        depthBiasClamp;
1910                 0.0f,                                                                                                           // float                                                                        depthBiasSlopeFactor;
1911                 1.0f,                                                                                                           // float                                                                        lineWidth;
1912         };
1913
1914         const VkPipelineMultisampleStateCreateInfo              multisampleStateParams =
1915         {
1916                 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,       // VkStructureType                                                      sType;
1917                 DE_NULL,                                                                                                        // const void*                                                          pNext;
1918                 0u,                                                                                                                     // VkPipelineMultisampleStateCreateFlags        flags;
1919                 VK_SAMPLE_COUNT_1_BIT,                                                                          // VkSampleCountFlagBits                                        rasterizationSamples;
1920                 VK_FALSE,                                                                                                       // VkBool32                                                                     sampleShadingEnable;
1921                 0.0f,                                                                                                           // float                                                                        minSampleShading;
1922                 DE_NULL,                                                                                                        // const VkSampleMask*                                          pSampleMask;
1923                 VK_FALSE,                                                                                                       // VkBool32                                                                     alphaToCoverageEnable;
1924                 VK_FALSE                                                                                                        // VkBool32                                                                     alphaToOneEnable;
1925          };
1926
1927         const VkPipelineColorBlendAttachmentState               colorBlendAttachmentState       =
1928         {
1929                 false,                                                                                                                                          // VkBool32                     blendEnable;
1930                 VK_BLEND_FACTOR_ONE,                                                                                                            // VkBlend                      srcBlendColor;
1931                 VK_BLEND_FACTOR_ZERO,                                                                                                           // VkBlend                      destBlendColor;
1932                 VK_BLEND_OP_ADD,                                                                                                                        // VkBlendOp            blendOpColor;
1933                 VK_BLEND_FACTOR_ONE,                                                                                                            // VkBlend                      srcBlendAlpha;
1934                 VK_BLEND_FACTOR_ZERO,                                                                                                           // VkBlend                      destBlendAlpha;
1935                 VK_BLEND_OP_ADD,                                                                                                                        // VkBlendOp            blendOpAlpha;
1936                 VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |                                           // VkChannelFlags       channelWriteMask;
1937                 VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT
1938         };
1939
1940         const VkPipelineColorBlendStateCreateInfo               colorBlendStateParams           =
1941         {
1942                 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,       // VkStructureType                                                              sType;
1943                 DE_NULL,                                                                                                        // const void*                                                                  pNext;
1944                 0u,                                                                                                                     // VkPipelineColorBlendStateCreateFlags                 flags;
1945                 false,                                                                                                          // VkBool32                                                                             logicOpEnable;
1946                 VK_LOGIC_OP_COPY,                                                                                       // VkLogicOp                                                                    logicOp;
1947                 1u,                                                                                                                     // deUint32                                                                             attachmentCount;
1948                 &colorBlendAttachmentState,                                                                     // const VkPipelineColorBlendAttachmentState*   pAttachments;
1949                 { 0.0f, 0.0f, 0.0f, 0.0f },                                                                     // float                                                                                blendConstants[4];
1950         };
1951
1952         const VkGraphicsPipelineCreateInfo                              graphicsPipelineParams          =
1953         {
1954                 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,        // VkStructureType                                                                      sType;
1955                 DE_NULL,                                                                                        // const void*                                                                          pNext;
1956                 0u,                                                                                                     // VkPipelineCreateFlags                                                        flags;
1957                 2u,                                                                                                     // deUint32                                                                                     stageCount;
1958                 shaderStages,                                                                           // const VkPipelineShaderStageCreateInfo*                       pStages;
1959                 &vertexInputStateParams,                                                        // const VkPipelineVertexInputStateCreateInfo*          pVertexInputState;
1960                 &inputAssemblyStateParams,                                                      // const VkPipelineInputAssemblyStateCreateInfo*        pInputAssemblyState;
1961                 DE_NULL,                                                                                        // const VkPipelineTessellationStateCreateInfo*         pTessellationState;
1962                 &viewportStateParams,                                                           // const VkPipelineViewportStateCreateInfo*                     pViewportState;
1963                 &rasterStateParams,                                                                     // const VkPipelineRasterizationStateCreateInfo*        pRasterizationState;
1964                 &multisampleStateParams,                                                        // const VkPipelineMultisampleStateCreateInfo*          pMultisampleState;
1965                 DE_NULL,                                                                                        // const VkPipelineDepthStencilStateCreateInfo*         pDepthStencilState;
1966                 &colorBlendStateParams,                                                         // const VkPipelineColorBlendStateCreateInfo*           pColorBlendState;
1967                 (const VkPipelineDynamicStateCreateInfo*)DE_NULL,       // const VkPipelineDynamicStateCreateInfo*                      pDynamicState;
1968                 pipelineLayout,                                                                         // VkPipelineLayout                                                                     layout;
1969                 renderPass,                                                                                     // VkRenderPass                                                                         renderPass;
1970                 0u,                                                                                                     // deUint32                                                                                     subpass;
1971                 0u,                                                                                                     // VkPipeline                                                                           basePipelineHandle;
1972                 0u                                                                                                      // deInt32                                                                                      basePipelineIndex;
1973         };
1974
1975         return vk::createGraphicsPipeline(vk, vkDevice, DE_NULL, &graphicsPipelineParams);
1976 }
1977
1978 } // anonymous (utilities)
1979
1980 // UniformBlockCase.
1981
1982 UniformBlockCase::UniformBlockCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, BufferMode bufferMode)
1983         : TestCase              (testCtx, name, description)
1984         , m_bufferMode  (bufferMode)
1985 {
1986 }
1987
1988 UniformBlockCase::~UniformBlockCase (void)
1989 {
1990 }
1991
1992 void UniformBlockCase::initPrograms (vk::SourceCollections& programCollection) const
1993 {
1994         DE_ASSERT(!m_vertShaderSource.empty());
1995         DE_ASSERT(!m_fragShaderSource.empty());
1996
1997         programCollection.glslSources.add("vert") << glu::VertexSource(m_vertShaderSource);
1998         programCollection.glslSources.add("frag") << glu::FragmentSource(m_fragShaderSource);
1999 }
2000
2001 TestInstance* UniformBlockCase::createInstance (Context& context) const
2002 {
2003         return new UniformBlockCaseInstance(context, m_bufferMode, m_uniformLayout, m_blockPointers);
2004 }
2005
2006 void UniformBlockCase::init (void)
2007 {
2008         // Compute reference layout.
2009         computeStd140Layout(m_uniformLayout, m_interface);
2010
2011         // Assign storage for reference values.
2012         {
2013                 int totalSize = 0;
2014                 for (std::vector<BlockLayoutEntry>::const_iterator blockIter = m_uniformLayout.blocks.begin(); blockIter != m_uniformLayout.blocks.end(); blockIter++)
2015                         totalSize += blockIter->size;
2016                 m_data.resize(totalSize);
2017
2018                 // Pointers for each block.
2019                 int curOffset = 0;
2020                 for (int blockNdx = 0; blockNdx < (int)m_uniformLayout.blocks.size(); blockNdx++)
2021                 {
2022                         m_blockPointers[blockNdx] = &m_data[0] + curOffset;
2023                         curOffset += m_uniformLayout.blocks[blockNdx].size;
2024                 }
2025         }
2026
2027         // Generate values.
2028         generateValues(m_uniformLayout, m_blockPointers, 1 /* seed */);
2029
2030         // Generate shaders.
2031         m_vertShaderSource = generateVertexShader(m_interface, m_uniformLayout, m_blockPointers);
2032         m_fragShaderSource = generateFragmentShader(m_interface, m_uniformLayout, m_blockPointers);
2033 }
2034
2035 } // ubo
2036 } // vkt