• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  * Copyright (c) 2018 The Khronos Group Inc.
9  *
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  *      http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  *
22  *//*!
23  * \file
24  * \brief Vulkan Transform Feedback Fuzz Layout Tests
25  *//*--------------------------------------------------------------------*/
26 
27 #include "vktTransformFeedbackFuzzLayoutCase.hpp"
28 
29 #include "vkPrograms.hpp"
30 
31 #include "gluVarType.hpp"
32 #include "tcuTestLog.hpp"
33 #include "tcuSurface.hpp"
34 #include "deRandom.hpp"
35 #include "deStringUtil.hpp"
36 
37 #include "tcuTextureUtil.hpp"
38 #include "deSharedPtr.hpp"
39 #include "deFloat16.h"
40 
41 #include "vkMemUtil.hpp"
42 #include "vkQueryUtil.hpp"
43 #include "vkTypeUtil.hpp"
44 #include "vkRef.hpp"
45 #include "vkRefUtil.hpp"
46 #include "vkBuilderUtil.hpp"
47 #include "vkCmdUtil.hpp"
48 #include "vkObjUtil.hpp"
49 
50 #include <map>
51 #include <set>
52 #include <vector>
53 #include <iostream>
54 #include <iomanip>
55 
56 namespace vkt
57 {
58 namespace TransformFeedback
59 {
60 
61 using namespace vk;
62 
63 typedef std::map<int, int> BufferGeneralMapping;
64 
65 typedef std::pair<int, int>				UsedRange;
66 typedef std::vector<UsedRange>			UsedRangeList;
67 typedef std::map<int, UsedRangeList>	BufferUsedRangesMap;
68 
69 // VarType implementation.
70 
VarType(void)71 VarType::VarType (void)
72 	: m_type	(TYPE_LAST)
73 	, m_flags	(0)
74 {
75 }
76 
VarType(const VarType & other)77 VarType::VarType (const VarType& other)
78 	: m_type	(TYPE_LAST)
79 	, m_flags	(0)
80 {
81 	*this = other;
82 }
83 
VarType(glu::DataType basicType,deUint32 flags)84 VarType::VarType (glu::DataType basicType, deUint32 flags)
85 	: m_type	(TYPE_BASIC)
86 	, m_flags	(flags)
87 {
88 	m_data.basicType = basicType;
89 }
90 
VarType(const VarType & elementType,int arraySize)91 VarType::VarType (const VarType& elementType, int arraySize)
92 	: m_type	(TYPE_ARRAY)
93 	, m_flags	(0)
94 {
95 	m_data.array.size			= arraySize;
96 	m_data.array.elementType	= new VarType(elementType);
97 }
98 
VarType(const StructType * structPtr,deUint32 flags)99 VarType::VarType (const StructType* structPtr, deUint32 flags)
100 	: m_type	(TYPE_STRUCT)
101 	, m_flags	(flags)
102 {
103 	m_data.structPtr = structPtr;
104 }
105 
~VarType(void)106 VarType::~VarType (void)
107 {
108 	if (m_type == TYPE_ARRAY)
109 		delete m_data.array.elementType;
110 }
111 
operator =(const VarType & other)112 VarType& VarType::operator= (const VarType& other)
113 {
114 	if (this == &other)
115 		return *this; // Self-assignment.
116 
117 	VarType *oldElementType = m_type == TYPE_ARRAY ? m_data.array.elementType : DE_NULL;
118 
119 	m_type	= other.m_type;
120 	m_flags	= other.m_flags;
121 	m_data	= Data();
122 
123 	if (m_type == TYPE_ARRAY)
124 	{
125 		m_data.array.elementType	= new VarType(*other.m_data.array.elementType);
126 		m_data.array.size			= other.m_data.array.size;
127 	}
128 	else
129 		m_data = other.m_data;
130 
131 	delete oldElementType;
132 
133 	return *this;
134 }
135 
136 // StructType implementation.
addMember(const std::string & name,const VarType & type,deUint32 flags)137 void StructType::addMember (const std::string& name, const VarType& type, deUint32 flags)
138 {
139 	m_members.push_back(StructMember(name, type, flags));
140 }
141 
142 // InterfaceBlockMember implementation.
InterfaceBlockMember(const std::string & name,const VarType & type,deUint32 flags)143 InterfaceBlockMember::InterfaceBlockMember (const std::string& name, const VarType& type, deUint32 flags)
144 	: m_name	(name)
145 	, m_type	(type)
146 	, m_flags	(flags)
147 {
148 }
149 
150 // InterfaceBlock implementation.
InterfaceBlock(const std::string & blockName)151 InterfaceBlock::InterfaceBlock (const std::string& blockName)
152 	: m_blockName	(blockName)
153 	, m_xfbBuffer	(0)
154 	, m_arraySize	(0)
155 	, m_flags		(0)
156 {
157 }
158 
operator <<(std::ostream & stream,const BlockLayoutEntry & entry)159 std::ostream& operator<< (std::ostream& stream, const BlockLayoutEntry& entry)
160 {
161 	stream << entry.name << " { name = " << entry.name
162 		   << ", buffer = " << entry.xfbBuffer
163 		   << ", offset = " << entry.xfbOffset
164 		   << ", size = " << entry.xfbSize
165 		   << ", blockDeclarationNdx = " << entry.blockDeclarationNdx
166 		   << ", instanceNdx = " << entry.instanceNdx
167 		   << ", activeInterfaceIndices = [";
168 
169 	for (std::vector<int>::const_iterator i = entry.activeInterfaceIndices.begin(); i != entry.activeInterfaceIndices.end(); i++)
170 	{
171 		if (i != entry.activeInterfaceIndices.begin())
172 			stream << ", ";
173 		stream << *i;
174 	}
175 
176 	stream << "] }";
177 	return stream;
178 }
179 
operator <<(std::ostream & stream,const InterfaceLayoutEntry & entry)180 std::ostream& operator<< (std::ostream& stream, const InterfaceLayoutEntry& entry)
181 {
182 	stream << entry.name << " { type = " << glu::getDataTypeName(entry.type)
183 		   << ", arraySize = " << entry.arraySize
184 		   << ", blockNdx = " << entry.blockLayoutNdx
185 		   << ", offset = " << entry.offset
186 		   << ", arrayStride = " << entry.arrayStride
187 		   << ", matrixStride = " << entry.matrixStride
188 		   << " }";
189 
190 	return stream;
191 }
192 
operator <<(std::ostream & str,const InterfaceLayout & layout)193 std::ostream& operator<< (std::ostream& str, const InterfaceLayout& layout)
194 {
195 	const int	numBlocks	= (int)layout.blocks.size();
196 
197 	str << "Blocks:" << std::endl;
198 	for (int blockNdx = 0; blockNdx < numBlocks; blockNdx++)
199 		str << layout.blocks[blockNdx] << std::endl;
200 	str << std::endl;
201 
202 	str << "Interfaces:" << std::endl;
203 	for (int blockNdx = 0; blockNdx < numBlocks; blockNdx++)
204 	{
205 		int		numEntries	= (int)layout.blocks[blockNdx].activeInterfaceIndices.size();
206 
207 		for (int entryNdx = 0; entryNdx < numEntries; entryNdx++)
208 		{
209 			const InterfaceLayoutEntry&	entry	= layout.interfaces[layout.blocks[blockNdx].activeInterfaceIndices[entryNdx]];
210 
211 			str << blockNdx << ":" << entryNdx << " " << entry << std::endl;
212 		}
213 	}
214 	str << std::endl;
215 
216 	return str;
217 }
218 
getInterfaceLayoutIndex(int blockNdx,const std::string & name) const219 int InterfaceLayout::getInterfaceLayoutIndex (int blockNdx, const std::string& name) const
220 {
221 	for (int ndx = 0; ndx < (int)interfaces.size(); ndx++)
222 	{
223 		if (blocks[interfaces[ndx].blockLayoutNdx].blockDeclarationNdx == blockNdx && interfaces[ndx].name == name)
224 			return ndx;
225 	}
226 
227 	return -1;
228 }
229 
getBlockLayoutIndex(int blockNdx,int instanceNdx) const230 int InterfaceLayout::getBlockLayoutIndex (int blockNdx, int instanceNdx) const
231 {
232 	for (int ndx = 0; ndx < (int)blocks.size(); ndx++)
233 	{
234 		if (blocks[ndx].blockDeclarationNdx == blockNdx && blocks[ndx].instanceNdx == instanceNdx)
235 			return ndx;
236 	}
237 
238 	return -1;
239 }
240 
241 // ShaderInterface implementation.
242 
ShaderInterface(void)243 ShaderInterface::ShaderInterface (void)
244 {
245 }
246 
~ShaderInterface(void)247 ShaderInterface::~ShaderInterface (void)
248 {
249 }
250 
allocStruct(const std::string & name)251 StructType& ShaderInterface::allocStruct (const std::string& name)
252 {
253 	m_structs.push_back(StructTypeSP(new StructType(name)));
254 	return *m_structs.back();
255 }
256 
257 struct StructNameEquals
258 {
259 	std::string name;
260 
StructNameEqualsvkt::TransformFeedback::StructNameEquals261 	StructNameEquals (const std::string& name_) : name(name_) {}
262 
operator ()vkt::TransformFeedback::StructNameEquals263 	bool operator() (const StructTypeSP type) const
264 	{
265 		return type->hasTypeName() && name == type->getTypeName();
266 	}
267 };
268 
getNamedStructs(std::vector<const StructType * > & structs) const269 void ShaderInterface::getNamedStructs (std::vector<const StructType*>& structs) const
270 {
271 	for (std::vector<StructTypeSP>::const_iterator i = m_structs.begin(); i != m_structs.end(); i++)
272 	{
273 		if ((*i)->hasTypeName())
274 			structs.push_back((*i).get());
275 	}
276 }
277 
allocBlock(const std::string & name)278 InterfaceBlock& ShaderInterface::allocBlock (const std::string& name)
279 {
280 	m_interfaceBlocks.push_back(InterfaceBlockSP(new InterfaceBlock(name)));
281 
282 	return *m_interfaceBlocks.back();
283 }
284 
285 namespace // Utilities
286 {
287 
288 struct PrecisionFlagsFmt
289 {
290 	deUint32 flags;
PrecisionFlagsFmtvkt::TransformFeedback::__anona5d2d2920111::PrecisionFlagsFmt291 	PrecisionFlagsFmt (deUint32 flags_) : flags(flags_) {}
292 };
293 
dumpBytes(std::ostream & str,const std::string & msg,const void * dataBytes,size_t size,const void * dataMask=DE_NULL)294 void dumpBytes (std::ostream& str, const std::string& msg, const void* dataBytes, size_t size, const void* dataMask = DE_NULL)
295 {
296 	const deUint8*		data	= (const deUint8*)dataBytes;
297 	const deUint8*		mask	= (const deUint8*)dataMask;
298 	std::ios::fmtflags	flags;
299 
300 	str << msg;
301 
302 	flags = str.flags ( std::ios::hex | std::ios::uppercase );
303 	{
304 		for (size_t i = 0; i < size; i++)
305 		{
306 			if (i%16 == 0) str << std::endl << std::setfill('0') << std::setw(8) << i << ":";
307 			else if (i%8 == 0) str << "  ";
308 			else if (i%4 == 0) str << " ";
309 
310 			str << " " << std::setfill('0') << std::setw(2);
311 
312 			if (mask == DE_NULL || mask[i] != 0)
313 				str << (deUint32)data[i];
314 			else
315 				str << "__";
316 		}
317 		str << std::endl << std::endl;
318 	}
319 	str.flags ( flags );
320 }
321 
operator <<(std::ostream & str,const PrecisionFlagsFmt & fmt)322 std::ostream& operator<< (std::ostream& str, const PrecisionFlagsFmt& fmt)
323 {
324 	// Precision.
325 	DE_ASSERT(dePop32(fmt.flags & (PRECISION_LOW|PRECISION_MEDIUM|PRECISION_HIGH)) <= 1);
326 	str << (fmt.flags & PRECISION_LOW		? "lowp"	:
327 			fmt.flags & PRECISION_MEDIUM	? "mediump"	:
328 			fmt.flags & PRECISION_HIGH		? "highp"	: "");
329 	return str;
330 }
331 
332 struct LayoutFlagsFmt
333 {
334 	deUint32 flags;
335 	deUint32 buffer;
336 	deUint32 stride;
337 	deUint32 offset;
338 
LayoutFlagsFmtvkt::TransformFeedback::__anona5d2d2920111::LayoutFlagsFmt339 	LayoutFlagsFmt	(const deUint32	flags_,
340 					 const deUint32	buffer_,
341 					 const deUint32	stride_,
342 					 const deUint32	offset_)
343 		: flags		(flags_)
344 		, buffer	(buffer_)
345 		, stride	(stride_)
346 		, offset	(offset_)
347 	{
348 	}
349 };
350 
operator <<(std::ostream & str,const LayoutFlagsFmt & fmt)351 std::ostream& operator<< (std::ostream& str, const LayoutFlagsFmt& fmt)
352 {
353 	static const struct
354 	{
355 		deUint32	bit;
356 		const char*	token;
357 	} bitDesc[] =
358 	{
359 		{ LAYOUT_XFBBUFFER,	"xfb_buffer"	},
360 		{ LAYOUT_XFBOFFSET,	"xfb_offset"	},
361 		{ LAYOUT_XFBSTRIDE,	"xfb_stride"	},
362 	};
363 
364 	deUint32 remBits = fmt.flags;
365 	for (int descNdx = 0; descNdx < DE_LENGTH_OF_ARRAY(bitDesc); descNdx++)
366 	{
367 		if (remBits & bitDesc[descNdx].bit)
368 		{
369 			str << bitDesc[descNdx].token;
370 
371 			if (bitDesc[descNdx].bit == LAYOUT_XFBBUFFER) str << " = " << fmt.buffer;
372 			if (bitDesc[descNdx].bit == LAYOUT_XFBOFFSET) str << " = " << fmt.offset;
373 			if (bitDesc[descNdx].bit == LAYOUT_XFBSTRIDE) str << " = " << fmt.stride;
374 
375 			remBits &= ~bitDesc[descNdx].bit;
376 
377 			if (remBits != 0)
378 				str << ", ";
379 		}
380 	}
381 	DE_ASSERT(remBits == 0);
382 	return str;
383 }
384 
operator <<(std::ostream & str,const DeviceSizeVector & vec)385 std::ostream& operator<< (std::ostream& str, const DeviceSizeVector& vec)
386 {
387 	str << " [";
388 
389 	for (size_t vecNdx = 0; vecNdx < vec.size(); vecNdx++)
390 		str << (deUint64)vec[vecNdx] << (vecNdx + 1 < vec.size() ? ", " : "]");
391 
392 	return str;
393 }
394 
395 // Layout computation.
396 
getDataTypeByteSize(glu::DataType type)397 int getDataTypeByteSize (glu::DataType type)
398 {
399 	if (getDataTypeScalarType(type) == glu::TYPE_DOUBLE)
400 	{
401 		return glu::getDataTypeScalarSize(type)*(int)sizeof(deUint64);
402 	}
403 	else
404 	{
405 		return glu::getDataTypeScalarSize(type)*(int)sizeof(deUint32);
406 	}
407 }
408 
getDataTypeArrayStride(glu::DataType type)409 int getDataTypeArrayStride (glu::DataType type)
410 {
411 	DE_ASSERT(!glu::isDataTypeMatrix(type));
412 
413 	return getDataTypeByteSize(type);
414 }
415 
getDataTypeArrayStrideForLocation(glu::DataType type)416 int getDataTypeArrayStrideForLocation (glu::DataType type)
417 {
418 	DE_ASSERT(!glu::isDataTypeMatrix(type));
419 
420 	const int baseStride	= getDataTypeByteSize(type);
421 	const int vec4Alignment	= (int)sizeof(deUint32) * 4;
422 
423 	return deAlign32(baseStride, vec4Alignment);
424 }
425 
computeInterfaceBlockMemberAlignment(const VarType & type)426 int computeInterfaceBlockMemberAlignment (const VarType& type)
427 {
428 	if (type.isBasicType())
429 	{
430 		glu::DataType basicType = type.getBasicType();
431 
432 		if (glu::isDataTypeMatrix(basicType) || isDataTypeVector(basicType))
433 			basicType = glu::getDataTypeScalarType(basicType);
434 
435 		switch (basicType)
436 		{
437 			case glu::TYPE_FLOAT:
438 			case glu::TYPE_INT:
439 			case glu::TYPE_UINT:	return sizeof(deUint32);
440 			case glu::TYPE_DOUBLE:	return sizeof(deUint64);
441 			default:				TCU_THROW(InternalError, "Invalid type");
442 		}
443 	}
444 	else if (type.isArrayType())
445 	{
446 		return computeInterfaceBlockMemberAlignment(type.getElementType());
447 	}
448 	else if (type.isStructType())
449 	{
450 		int maxAlignment = 0;
451 
452 		for (StructType::ConstIterator memberIter = type.getStruct().begin(); memberIter != type.getStruct().end(); memberIter++)
453 			maxAlignment = de::max(maxAlignment, computeInterfaceBlockMemberAlignment(memberIter->getType()));
454 
455 		return maxAlignment;
456 	}
457 	else
458 		TCU_THROW(InternalError, "Invalid type");
459 }
460 
createMask(void * maskBasePtr,const InterfaceLayoutEntry & entry,const void * basePtr0,const void * basePtr)461 void createMask (void* maskBasePtr, const InterfaceLayoutEntry& entry, const void* basePtr0, const void* basePtr)
462 {
463 	const glu::DataType	scalarType	= glu::getDataTypeScalarType(entry.type);
464 	const int			scalarSize	= glu::getDataTypeScalarSize(entry.type);
465 	const bool			isMatrix	= glu::isDataTypeMatrix(entry.type);
466 	const int			numVecs		= isMatrix ? glu::getDataTypeMatrixNumColumns(entry.type) : 1;
467 	const int			vecSize		= scalarSize / numVecs;
468 	const bool			isArray		= entry.arraySize > 1;
469 	const size_t		compSize	= getDataTypeByteSize(scalarType);
470 
471 	DE_ASSERT(scalarSize%numVecs == 0);
472 
473 	for (int elemNdx = 0; elemNdx < entry.arraySize; elemNdx++)
474 	{
475 		deUint8* elemPtr = (deUint8*)basePtr + entry.offset + (isArray ? elemNdx*entry.arrayStride : 0);
476 
477 		for (int vecNdx = 0; vecNdx < numVecs; vecNdx++)
478 		{
479 			deUint8* vecPtr = elemPtr + (isMatrix ? vecNdx*entry.matrixStride : 0);
480 
481 			for (int compNdx = 0; compNdx < vecSize; compNdx++)
482 			{
483 				const deUint8*	compPtr		= vecPtr + compSize*compNdx;
484 				const size_t	offset		= compPtr - (deUint8*)basePtr0;
485 				deUint8*		maskPtr		= (deUint8*)maskBasePtr + offset;
486 
487 				switch (scalarType)
488 				{
489 					case glu::TYPE_DOUBLE:
490 					case glu::TYPE_FLOAT:
491 					case glu::TYPE_INT:
492 					case glu::TYPE_UINT:
493 					{
494 						for (size_t ndx = 0; ndx < compSize; ++ndx)
495 							++maskPtr[ndx];
496 
497 						break;
498 					}
499 					default:
500 						DE_ASSERT(false);
501 				}
502 			}
503 		}
504 	}
505 }
506 
createMask(const InterfaceLayout & layout,const std::map<int,void * > & blockPointers,const void * basePtr0,const size_t baseSize)507 std::vector<deUint8> createMask (const InterfaceLayout& layout, const std::map<int, void*>& blockPointers, const void* basePtr0, const size_t baseSize)
508 {
509 	std::vector<deUint8>	mask		(baseSize, 0);
510 	const int				numBlocks	((int)layout.blocks.size());
511 
512 	for (int blockNdx = 0; blockNdx < numBlocks; blockNdx++)
513 	{
514 		void*	basePtr		= blockPointers.find(blockNdx)->second;
515 		int		numEntries	= (int)layout.blocks[blockNdx].activeInterfaceIndices.size();
516 
517 		for (int entryNdx = 0; entryNdx < numEntries; entryNdx++)
518 		{
519 			const InterfaceLayoutEntry&	entry	= layout.interfaces[layout.blocks[blockNdx].activeInterfaceIndices[entryNdx]];
520 
521 			if (entry.validate)
522 				createMask (&mask[0], entry, basePtr0, basePtr);
523 		}
524 	}
525 
526 	return mask;
527 }
528 
computeInterfaceBlockAlignment(const InterfaceBlock & interfaceBlock)529 int computeInterfaceBlockAlignment(const InterfaceBlock& interfaceBlock)
530 {
531 	int baseAlignment = 0;
532 
533 	for (InterfaceBlock::ConstIterator memberIter = interfaceBlock.begin(); memberIter != interfaceBlock.end(); memberIter++)
534 	{
535 		const InterfaceBlockMember& member = *memberIter;
536 
537 		baseAlignment = std::max(baseAlignment, computeInterfaceBlockMemberAlignment(member.getType()));
538 	}
539 
540 	return baseAlignment;
541 }
542 
isOverlaped(const int a1,const int b1,const int a2,const int b2)543 static inline bool isOverlaped(const int a1, const int b1, const int a2, const int b2)
544 {
545 	DE_ASSERT(b1 > 0 && b2 > 0);
546 
547 	const int b1s = b1 - 1;
548 	const int b2s = b2 - 1;
549 
550 	return	deInRange32(a1,  a2, b2s) ||
551 			deInRange32(b1s, a2, b2s) ||
552 			deInRange32(a2,  a1, b1s) ||
553 			deInRange32(b2s, a1, b1s);
554 }
555 
computeXfbLayout(InterfaceLayout & layout,int & curOffset,int & curLocation,int curBlockNdx,const std::string & curPrefix,const VarType & type,deUint32 layoutFlags)556 void computeXfbLayout (InterfaceLayout& layout, int& curOffset, int& curLocation, int curBlockNdx, const std::string& curPrefix, const VarType& type, deUint32 layoutFlags)
557 {
558 	const int	locationAlignSize	= 16;
559 	const bool	validate			= 0 == (layoutFlags & (FIELD_MISSING|FIELD_UNASSIGNED));
560 	int			baseAlignment		= computeInterfaceBlockMemberAlignment(type);
561 
562 	DE_ASSERT(baseAlignment == sizeof(deUint32) || baseAlignment == sizeof(deUint64));
563 
564 	curOffset = deAlign32(curOffset, baseAlignment);
565 
566 	if (type.isBasicType())
567 	{
568 		const glu::DataType		basicType				= type.getBasicType();
569 		int						fieldSize				= 0;
570 		int						fieldSizeForLocation	= 0;
571 		InterfaceLayoutEntry	entry;
572 
573 		entry.name				= curPrefix;
574 		entry.type				= basicType;
575 		entry.arraySize			= 1;
576 		entry.arrayStride		= 0;
577 		entry.matrixStride		= 0;
578 		entry.blockLayoutNdx	= curBlockNdx;
579 		entry.locationNdx		= 0;
580 		entry.validate			= validate;
581 
582 		if (glu::isDataTypeMatrix(basicType))
583 		{
584 			// Array of vectors
585 			const int				vecSize				= glu::getDataTypeMatrixNumRows(basicType);
586 			const int				numVecs				= glu::getDataTypeMatrixNumColumns(basicType);
587 			const glu::DataType		elemType			= glu::getDataTypeScalarType(basicType);
588 			const int				stride				= getDataTypeArrayStride(glu::getDataTypeVector(elemType, vecSize));
589 			const int				strideForLocation	= getDataTypeArrayStrideForLocation(glu::getDataTypeVector(elemType, vecSize));
590 
591 			entry.matrixStride		= stride;
592 
593 			fieldSize				= numVecs * stride;
594 			fieldSizeForLocation	= numVecs * strideForLocation;
595 		}
596 		else
597 		{
598 			// Scalar or vector.
599 			fieldSize				= getDataTypeByteSize(basicType);
600 			fieldSizeForLocation	= deAlign32(fieldSize, locationAlignSize);
601 		}
602 
603 		entry.offset		= curOffset;
604 		entry.locationNdx	= curLocation;
605 
606 		curOffset += fieldSize;
607 		curLocation += deDivRoundUp32(fieldSizeForLocation, locationAlignSize);
608 
609 		layout.interfaces.push_back(entry);
610 	}
611 	else if (type.isArrayType())
612 	{
613 		const VarType&	elemType	= type.getElementType();
614 
615 		if (elemType.isBasicType() && !glu::isDataTypeMatrix(elemType.getBasicType()))
616 		{
617 			// Array of scalars or vectors.
618 			const glu::DataType		elemBasicType			= elemType.getBasicType();
619 			const int				stride					= getDataTypeArrayStride(elemBasicType);
620 			const int				fieldSize				= stride * type.getArraySize();
621 			const int				strideForLocation		= getDataTypeArrayStrideForLocation(elemBasicType);
622 			const int				fieldSizeForLocation	= strideForLocation * type.getArraySize();
623 			InterfaceLayoutEntry	entry;
624 
625 			entry.name				= curPrefix + "[0]"; // Array interfaces are always postfixed with [0]
626 			entry.type				= elemBasicType;
627 			entry.blockLayoutNdx	= curBlockNdx;
628 			entry.offset			= curOffset;
629 			entry.arraySize			= type.getArraySize();
630 			entry.arrayStride		= stride;
631 			entry.matrixStride		= 0;
632 			entry.locationNdx		= curLocation;
633 			entry.validate			= validate;
634 
635 			curOffset += fieldSize;
636 			curLocation += deDivRoundUp32(fieldSizeForLocation, locationAlignSize);
637 
638 			layout.interfaces.push_back(entry);
639 		}
640 		else if (elemType.isBasicType() && glu::isDataTypeMatrix(elemType.getBasicType()))
641 		{
642 			// Array of matrices.
643 			const glu::DataType		elemBasicType			= elemType.getBasicType();
644 			const glu::DataType		scalarType				= glu::getDataTypeScalarType(elemBasicType);
645 			const int				vecSize					= glu::getDataTypeMatrixNumRows(elemBasicType);
646 			const int				numVecs					= glu::getDataTypeMatrixNumColumns(elemBasicType);
647 			const int				stride					= getDataTypeArrayStride(glu::getDataTypeVector(scalarType, vecSize));
648 			const int				fieldSize				= numVecs * type.getArraySize() * stride;
649 			const int				strideForLocation		= getDataTypeArrayStrideForLocation(glu::getDataTypeVector(scalarType, vecSize));
650 			const int				fieldSizeForLocation	= numVecs * type.getArraySize() * strideForLocation;
651 			InterfaceLayoutEntry	entry;
652 
653 			entry.name				= curPrefix + "[0]"; // Array interfaces are always postfixed with [0]
654 			entry.type				= elemBasicType;
655 			entry.blockLayoutNdx	= curBlockNdx;
656 			entry.offset			= curOffset;
657 			entry.arraySize			= type.getArraySize();
658 			entry.arrayStride		= stride*numVecs;
659 			entry.matrixStride		= stride;
660 			entry.locationNdx		= curLocation;
661 			entry.validate			= validate;
662 
663 			curOffset += fieldSize;
664 			curLocation += deDivRoundUp32(fieldSizeForLocation, locationAlignSize);
665 
666 			layout.interfaces.push_back(entry);
667 		}
668 		else
669 		{
670 			DE_ASSERT(elemType.isStructType() || elemType.isArrayType());
671 
672 			for (int elemNdx = 0; elemNdx < type.getArraySize(); elemNdx++)
673 				computeXfbLayout(layout, curOffset, curLocation, curBlockNdx, curPrefix + "[" + de::toString(elemNdx) + "]", type.getElementType(), layoutFlags);
674 		}
675 	}
676 	else
677 	{
678 		DE_ASSERT(type.isStructType());
679 
680 		for (StructType::ConstIterator memberIter = type.getStruct().begin(); memberIter != type.getStruct().end(); memberIter++)
681 			computeXfbLayout(layout, curOffset, curLocation, curBlockNdx, curPrefix + "." + memberIter->getName(), memberIter->getType(), (memberIter->getFlags() | layoutFlags) & FIELD_OPTIONS);
682 
683 		curOffset = deAlign32(curOffset, baseAlignment);
684 	}
685 }
686 
computeXfbLayout(InterfaceLayout & layout,ShaderInterface & shaderInterface,BufferGeneralMapping & perBufferXfbOffsets,deUint32 & locationsUsed)687 void computeXfbLayout (InterfaceLayout& layout, ShaderInterface& shaderInterface, BufferGeneralMapping& perBufferXfbOffsets, deUint32& locationsUsed)
688 {
689 	const int				numInterfaceBlocks	= shaderInterface.getNumInterfaceBlocks();
690 	int						curLocation			= 0;
691 	BufferGeneralMapping	bufferAlignments;
692 	BufferGeneralMapping	buffersList;
693 	BufferGeneralMapping	bufferStrideGroup;
694 	BufferUsedRangesMap		bufferUsedRanges;
695 
696 	for (int blockNdx = 0; blockNdx < numInterfaceBlocks; blockNdx++)
697 	{
698 		const InterfaceBlock&	interfaceBlock	= shaderInterface.getInterfaceBlock(blockNdx);
699 		const int				xfbBuffer		= interfaceBlock.getXfbBuffer();
700 
701 		buffersList[xfbBuffer] = 1;
702 		bufferStrideGroup[xfbBuffer] = xfbBuffer;
703 	}
704 
705 	for (BufferGeneralMapping::const_iterator xfbBuffersIter = buffersList.begin(); xfbBuffersIter != buffersList.end(); xfbBuffersIter++)
706 	{
707 		const int	xfbBufferAnalyzed	= xfbBuffersIter->first;
708 
709 		for (int blockNdx = 0; blockNdx < numInterfaceBlocks; blockNdx++)
710 		{
711 			InterfaceBlock&	interfaceBlock	= shaderInterface.getInterfaceBlockForModify(blockNdx);
712 
713 			if (interfaceBlock.getXfbBuffer() == xfbBufferAnalyzed)
714 			{
715 				const bool			hasInstanceName		= interfaceBlock.hasInstanceName();
716 				const std::string	blockPrefix			= hasInstanceName ? (interfaceBlock.getBlockName() + ".") : "";
717 				const int			numInstances		= interfaceBlock.isArray() ? interfaceBlock.getArraySize() : 1;
718 				int					activeBlockNdx		= (int)layout.blocks.size();
719 				int					startInterfaceNdx	= (int)layout.interfaces.size();
720 				int					startLocationNdx	= (int)curLocation;
721 				int					interfaceAlignement	= computeInterfaceBlockAlignment(interfaceBlock);
722 				int					curOffset			= 0;
723 				int					blockSize			= 0;
724 
725 				do
726 				{
727 					const int		xfbFirstInstanceBuffer			= interfaceBlock.getXfbBuffer();
728 					int&			xfbFirstInstanceBufferOffset	= perBufferXfbOffsets[xfbFirstInstanceBuffer];
729 					const int		savedLayoutInterfacesNdx		= (int)layout.interfaces.size();
730 					const int		savedCurOffset					= curOffset;
731 					const int		savedCurLocation				= curLocation;
732 					UsedRangeList&	usedRanges						= bufferUsedRanges[xfbFirstInstanceBuffer];
733 					bool			fitIntoBuffer					= true;
734 
735 					// GLSL 4.60
736 					// Further, if applied to an aggregate containing a double, the offset must also be a multiple of 8,
737 					// and the space taken in the buffer will be a multiple of 8.
738 					xfbFirstInstanceBufferOffset	= deAlign32(xfbFirstInstanceBufferOffset, interfaceAlignement);
739 
740 					for (InterfaceBlock::ConstIterator memberIter = interfaceBlock.begin(); memberIter != interfaceBlock.end(); memberIter++)
741 					{
742 						const InterfaceBlockMember& member	= *memberIter;
743 
744 						computeXfbLayout(layout, curOffset, curLocation, activeBlockNdx, blockPrefix + member.getName(), member.getType(), member.getFlags() & FIELD_OPTIONS);
745 					}
746 
747 					// GLSL 4.60
748 					// Further, if applied to an aggregate containing a double, the offset must also be a multiple of 8,
749 					// and the space taken in the buffer will be a multiple of 8.
750 					blockSize	= deAlign32(curOffset, interfaceAlignement);
751 
752 					// Overlapping check
753 					for (UsedRangeList::const_iterator	usedRangeIt = usedRanges.begin();
754 														usedRangeIt != usedRanges.end();
755 														++usedRangeIt)
756 					{
757 						const int&	usedRangeStart	= usedRangeIt->first;
758 						const int&	usedRangeEnd	= usedRangeIt->second;
759 						const int	genRangeStart	= xfbFirstInstanceBufferOffset;
760 						const int	genRangeEnd		= xfbFirstInstanceBufferOffset + blockSize;
761 
762 						// Validate if block has overlapping
763 						if (isOverlaped(genRangeStart, genRangeEnd, usedRangeStart, usedRangeEnd))
764 						{
765 							// Restart from obstacle interface end
766 							fitIntoBuffer					= false;
767 
768 							DE_ASSERT(xfbFirstInstanceBufferOffset > usedRangeEnd);
769 
770 							// Bump up interface start to the end of used range
771 							xfbFirstInstanceBufferOffset	= usedRangeEnd;
772 
773 							// Undo allocation
774 							curOffset						= savedCurOffset;
775 							curLocation						= savedCurLocation;
776 
777 							layout.interfaces.resize(savedLayoutInterfacesNdx);
778 						}
779 					}
780 
781 					if (fitIntoBuffer)
782 						break;
783 				} while (true);
784 
785 				const int	xfbFirstInstanceBuffer			= interfaceBlock.getXfbBuffer();
786 				const int	xfbFirstInstanceBufferOffset	= perBufferXfbOffsets[xfbFirstInstanceBuffer];
787 				const int	endInterfaceNdx					= (int)layout.interfaces.size();
788 				const int	blockSizeInLocations			= curLocation - startLocationNdx;
789 
790 				curLocation -= blockSizeInLocations;
791 
792 				if (numInstances > 1)
793 					interfaceBlock.setFlag(LAYOUT_XFBSTRIDE);
794 
795 				// Create block layout entries for each instance.
796 				for (int instanceNdx = 0; instanceNdx < numInstances; instanceNdx++)
797 				{
798 					// Allocate entry for instance.
799 					layout.blocks.push_back(BlockLayoutEntry());
800 
801 					BlockLayoutEntry&	blockEntry		= layout.blocks.back();
802 					const int			xfbBuffer		= xfbFirstInstanceBuffer + instanceNdx;
803 					int&				xfbBufferOffset	= perBufferXfbOffsets[xfbBuffer];
804 
805 					DE_ASSERT(xfbBufferOffset <= xfbFirstInstanceBufferOffset);
806 
807 					xfbBufferOffset					= xfbFirstInstanceBufferOffset;
808 
809 					blockEntry.name					= interfaceBlock.getBlockName();
810 					blockEntry.xfbBuffer			= xfbBuffer;
811 					blockEntry.xfbOffset			= xfbBufferOffset;
812 					blockEntry.xfbSize				= blockSize;
813 					blockEntry.blockDeclarationNdx	= blockNdx;
814 					blockEntry.instanceNdx			= instanceNdx;
815 					blockEntry.locationNdx			= curLocation;
816 					blockEntry.locationSize			= blockSizeInLocations;
817 
818 					xfbBufferOffset	+= blockSize;
819 					curLocation		+= blockSizeInLocations;
820 
821 					// Compute active interface set for block.
822 					for (int interfaceNdx = startInterfaceNdx; interfaceNdx < endInterfaceNdx; interfaceNdx++)
823 						blockEntry.activeInterfaceIndices.push_back(interfaceNdx);
824 
825 					if (interfaceBlock.isArray())
826 						blockEntry.name += "[" + de::toString(instanceNdx) + "]";
827 
828 					bufferUsedRanges[xfbBuffer].push_back(UsedRange(blockEntry.xfbOffset, blockEntry.xfbOffset + blockEntry.xfbSize));
829 
830 					// Store maximum per-buffer alignment
831 					bufferAlignments[xfbBuffer] = std::max(interfaceAlignement, bufferAlignments[xfbBuffer]);
832 
833 					// Buffers bound through instanced arrays must have same stride (and alignment)
834 					bufferStrideGroup[xfbBuffer] = bufferStrideGroup[xfbFirstInstanceBuffer];
835 				}
836 			}
837 		}
838 	}
839 
840 	// All XFB buffers within group must have same stride
841 	{
842 		BufferGeneralMapping groupStride;
843 
844 		for (BufferGeneralMapping::const_iterator xfbBuffersIter = perBufferXfbOffsets.begin(); xfbBuffersIter != perBufferXfbOffsets.end(); xfbBuffersIter++)
845 		{
846 			const int	xfbBuffer	= xfbBuffersIter->first;
847 			const int	xfbStride	= perBufferXfbOffsets[xfbBuffer];
848 			const int	group		= bufferStrideGroup[xfbBuffer];
849 
850 			groupStride[group] = std::max(groupStride[group], xfbStride);
851 		}
852 
853 		for (BufferGeneralMapping::const_iterator xfbBuffersIter = perBufferXfbOffsets.begin(); xfbBuffersIter != perBufferXfbOffsets.end(); xfbBuffersIter++)
854 		{
855 			const int	xfbBuffer	= xfbBuffersIter->first;
856 			const int	group		= bufferStrideGroup[xfbBuffer];
857 
858 			perBufferXfbOffsets[xfbBuffer] = groupStride[group];
859 		}
860 	}
861 
862 	// All XFB buffers within group must have same stride alignment
863 	{
864 		BufferGeneralMapping groupAlignment;
865 
866 		for (BufferGeneralMapping::const_iterator xfbBuffersIter = perBufferXfbOffsets.begin(); xfbBuffersIter != perBufferXfbOffsets.end(); xfbBuffersIter++)
867 		{
868 			const int	xfbBuffer	= xfbBuffersIter->first;
869 			const int	group		= bufferStrideGroup[xfbBuffer];
870 			const int	xfbAlign	= bufferAlignments[xfbBuffer];
871 
872 			groupAlignment[group] = std::max(groupAlignment[group], xfbAlign);
873 		}
874 
875 		for (BufferGeneralMapping::const_iterator xfbBuffersIter = perBufferXfbOffsets.begin(); xfbBuffersIter != perBufferXfbOffsets.end(); xfbBuffersIter++)
876 		{
877 			const int	xfbBuffer	= xfbBuffersIter->first;
878 			const int	group		= bufferStrideGroup[xfbBuffer];
879 
880 			bufferAlignments[xfbBuffer] = groupAlignment[group];
881 		}
882 	}
883 
884 	// GLSL 4.60
885 	// If the buffer is capturing any outputs with double-precision components, the stride must be a multiple of 8, ...
886 	for (BufferGeneralMapping::const_iterator xfbBuffersIter = perBufferXfbOffsets.begin(); xfbBuffersIter != perBufferXfbOffsets.end(); xfbBuffersIter++)
887 	{
888 		const int	xfbBuffer	= xfbBuffersIter->first;
889 		const int	xfbAlign	= bufferAlignments[xfbBuffer];
890 		int&		xfbOffset	= perBufferXfbOffsets[xfbBuffer];
891 
892 		xfbOffset	= deAlign32(xfbOffset, xfbAlign);
893 	}
894 
895 	// Keep stride in interface blocks
896 	for (int blockNdx = 0; blockNdx < (int)layout.blocks.size(); blockNdx++)
897 		layout.blocks[blockNdx].xfbStride	= perBufferXfbOffsets[layout.blocks[blockNdx].xfbBuffer];
898 
899 	locationsUsed = static_cast<deUint32>(curLocation);
900 }
901 
902 // Value generator.
903 
generateValue(const InterfaceLayoutEntry & entry,void * basePtr,de::Random & rnd)904 void generateValue (const InterfaceLayoutEntry& entry, void* basePtr, de::Random& rnd)
905 {
906 	const glu::DataType	scalarType	= glu::getDataTypeScalarType(entry.type);
907 	const int			scalarSize	= glu::getDataTypeScalarSize(entry.type);
908 	const bool			isMatrix	= glu::isDataTypeMatrix(entry.type);
909 	const int			numVecs		= isMatrix ? glu::getDataTypeMatrixNumColumns(entry.type) : 1;
910 	const int			vecSize		= scalarSize / numVecs;
911 	const bool			isArray		= entry.arraySize > 1;
912 	const size_t		compSize	= getDataTypeByteSize(scalarType);
913 
914 	DE_ASSERT(scalarSize%numVecs == 0);
915 
916 	for (int elemNdx = 0; elemNdx < entry.arraySize; elemNdx++)
917 	{
918 		deUint8* elemPtr = (deUint8*)basePtr + entry.offset + (isArray ? elemNdx*entry.arrayStride : 0);
919 
920 		for (int vecNdx = 0; vecNdx < numVecs; vecNdx++)
921 		{
922 			deUint8* vecPtr = elemPtr + (isMatrix ? vecNdx*entry.matrixStride : 0);
923 
924 			for (int compNdx = 0; compNdx < vecSize; compNdx++)
925 			{
926 				deUint8*	compPtr = vecPtr + compSize*compNdx;
927 				const int	sign	= rnd.getBool() ? +1 : -1;
928 				const int	value	= rnd.getInt(1, 127);
929 
930 				switch (scalarType)
931 				{
932 					case glu::TYPE_DOUBLE:	*((double*)compPtr)		= (double)  (sign * value);	break;
933 					case glu::TYPE_FLOAT:	*((float*)compPtr)		= (float)   (sign * value);	break;
934 					case glu::TYPE_INT:		*((deInt32*)compPtr)	= (deInt32) (sign * value);	break;
935 					case glu::TYPE_UINT:	*((deUint32*)compPtr)	= (deUint32)(       value);	break;
936 					default:
937 						DE_ASSERT(false);
938 				}
939 			}
940 		}
941 	}
942 }
943 
generateValues(const InterfaceLayout & layout,const std::map<int,void * > & blockPointers,deUint32 seed)944 void generateValues (const InterfaceLayout& layout, const std::map<int, void*>& blockPointers, deUint32 seed)
945 {
946 	de::Random	rnd			(seed);
947 	int			numBlocks	= (int)layout.blocks.size();
948 
949 	for (int blockNdx = 0; blockNdx < numBlocks; blockNdx++)
950 	{
951 		void*	basePtr		= blockPointers.find(blockNdx)->second;
952 		int		numEntries	= (int)layout.blocks[blockNdx].activeInterfaceIndices.size();
953 
954 		for (int entryNdx = 0; entryNdx < numEntries; entryNdx++)
955 		{
956 			const InterfaceLayoutEntry& entry = layout.interfaces[layout.blocks[blockNdx].activeInterfaceIndices[entryNdx]];
957 
958 			if (entry.validate)
959 				generateValue(entry, basePtr, rnd);
960 		}
961 	}
962 }
963 
964 // Shader generator.
965 
966 struct Indent
967 {
968 	int level;
Indentvkt::TransformFeedback::__anona5d2d2920111::Indent969 	Indent (int level_) : level(level_) {}
970 };
971 
operator <<(std::ostream & str,const Indent & indent)972 std::ostream& operator<< (std::ostream& str, const Indent& indent)
973 {
974 	for (int i = 0; i < indent.level; i++)
975 		str << "\t";
976 	return str;
977 }
978 
979 void	generateDeclaration			(std::ostringstream& src, const VarType& type, const std::string& name, int indentLevel, deUint32 unusedHints, deUint32 flagsMask, deUint32 buffer, deUint32 stride, deUint32 offset);
980 void	generateDeclaration			(std::ostringstream& src, const InterfaceBlockMember& member, int indentLevel, deUint32 buffer, deUint32 stride, deUint32 offset);
981 void	generateDeclaration			(std::ostringstream& src, const StructType& structType, int indentLevel);
982 
983 void	generateLocalDeclaration	(std::ostringstream& src, const StructType& structType, int indentLevel);
984 void	generateFullDeclaration		(std::ostringstream& src, const StructType& structType, int indentLevel);
985 
generateDeclaration(std::ostringstream & src,const StructType & structType,int indentLevel)986 void generateDeclaration (std::ostringstream& src, const StructType& structType, int indentLevel)
987 {
988 	DE_ASSERT(structType.hasTypeName());
989 	generateFullDeclaration(src, structType, indentLevel);
990 	src << ";\n";
991 }
992 
generateFullDeclaration(std::ostringstream & src,const StructType & structType,int indentLevel)993 void generateFullDeclaration (std::ostringstream& src, const StructType& structType, int indentLevel)
994 {
995 	src << "struct";
996 	if (structType.hasTypeName())
997 		src << " " << structType.getTypeName();
998 	src << "\n" << Indent(indentLevel) << "{\n";
999 
1000 	for (StructType::ConstIterator memberIter = structType.begin(); memberIter != structType.end(); memberIter++)
1001 	{
1002 		src << Indent(indentLevel + 1);
1003 		generateDeclaration(src, memberIter->getType(), memberIter->getName(), indentLevel + 1, memberIter->getFlags() & FIELD_OPTIONS, ~LAYOUT_MASK, 0u, 0u, 0u);
1004 	}
1005 
1006 	src << Indent(indentLevel) << "}";
1007 }
1008 
generateLocalDeclaration(std::ostringstream & src,const StructType & structType,int)1009 void generateLocalDeclaration (std::ostringstream& src, const StructType& structType, int /* indentLevel */)
1010 {
1011 	src << structType.getTypeName();
1012 }
1013 
generateLayoutAndPrecisionDeclaration(std::ostringstream & src,deUint32 flags,deUint32 buffer,deUint32 stride,deUint32 offset)1014 void generateLayoutAndPrecisionDeclaration (std::ostringstream& src, deUint32 flags, deUint32 buffer, deUint32 stride, deUint32 offset)
1015 {
1016 	if ((flags & LAYOUT_MASK) != 0)
1017 		src << "layout(" << LayoutFlagsFmt(flags & LAYOUT_MASK, buffer, stride, offset) << ") ";
1018 
1019 	if ((flags & PRECISION_MASK) != 0)
1020 		src << PrecisionFlagsFmt(flags & PRECISION_MASK) << " ";
1021 }
1022 
generateDeclaration(std::ostringstream & src,const VarType & type,const std::string & name,int indentLevel,deUint32 fieldHints,deUint32 flagsMask,deUint32 buffer,deUint32 stride,deUint32 offset)1023 void generateDeclaration (std::ostringstream& src, const VarType& type, const std::string& name, int indentLevel, deUint32 fieldHints, deUint32 flagsMask, deUint32 buffer, deUint32 stride, deUint32 offset)
1024 {
1025 	if (fieldHints & FIELD_MISSING)
1026 		src << "// ";
1027 
1028 	generateLayoutAndPrecisionDeclaration(src, type.getFlags() & flagsMask, buffer, stride, offset);
1029 
1030 	if (type.isBasicType())
1031 		src << glu::getDataTypeName(type.getBasicType()) << " " << name;
1032 	else if (type.isArrayType())
1033 	{
1034 		std::vector<int>	arraySizes;
1035 		const VarType*		curType		= &type;
1036 		while (curType->isArrayType())
1037 		{
1038 			arraySizes.push_back(curType->getArraySize());
1039 			curType = &curType->getElementType();
1040 		}
1041 
1042 		generateLayoutAndPrecisionDeclaration(src, curType->getFlags() & flagsMask, buffer, stride, offset);
1043 
1044 		if (curType->isBasicType())
1045 			src << glu::getDataTypeName(curType->getBasicType());
1046 		else
1047 		{
1048 			DE_ASSERT(curType->isStructType());
1049 			generateLocalDeclaration(src, curType->getStruct(), indentLevel+1);
1050 		}
1051 
1052 		src << " " << name;
1053 
1054 		for (std::vector<int>::const_iterator sizeIter = arraySizes.begin(); sizeIter != arraySizes.end(); sizeIter++)
1055 			src << "[" << *sizeIter << "]";
1056 	}
1057 	else
1058 	{
1059 		generateLocalDeclaration(src, type.getStruct(), indentLevel+1);
1060 		src << " " << name;
1061 	}
1062 
1063 	src << ";";
1064 
1065 	// Print out unused hints.
1066 	if (fieldHints & FIELD_MISSING)
1067 		src << " // missing field";
1068 	else if (fieldHints & FIELD_UNASSIGNED)
1069 		src << " // unassigned";
1070 
1071 	src << "\n";
1072 }
1073 
generateDeclaration(std::ostringstream & src,const InterfaceBlockMember & member,int indentLevel,deUint32 buffer,deUint32 stride,deUint32 offset)1074 void generateDeclaration (std::ostringstream& src, const InterfaceBlockMember& member, int indentLevel, deUint32 buffer, deUint32 stride, deUint32 offset)
1075 {
1076 	if ((member.getFlags() & LAYOUT_MASK) != 0)
1077 		src << "layout(" << LayoutFlagsFmt(member.getFlags() & LAYOUT_MASK, buffer, stride, offset) << ") ";
1078 
1079 	generateDeclaration(src, member.getType(), member.getName(), indentLevel, member.getFlags() & FIELD_OPTIONS, ~0u, buffer, stride, offset);
1080 }
1081 
getBlockMemberOffset(int blockNdx,const InterfaceBlock & block,const InterfaceBlockMember & member,const InterfaceLayout & layout)1082 deUint32 getBlockMemberOffset (int blockNdx, const InterfaceBlock& block, const InterfaceBlockMember& member, const InterfaceLayout& layout)
1083 {
1084 	std::ostringstream	name;
1085 	const VarType*		curType = &member.getType();
1086 
1087 	if (block.getInstanceName().length() != 0)
1088 		name << block.getBlockName() << ".";	// \note InterfaceLayoutEntry uses block name rather than instance name
1089 
1090 	name << member.getName();
1091 
1092 	while (!curType->isBasicType())
1093 	{
1094 		if (curType->isArrayType())
1095 		{
1096 			name << "[0]";
1097 			curType = &curType->getElementType();
1098 		}
1099 
1100 		if (curType->isStructType())
1101 		{
1102 			const StructType::ConstIterator firstMember = curType->getStruct().begin();
1103 
1104 			name << "." << firstMember->getName();
1105 			curType = &firstMember->getType();
1106 		}
1107 	}
1108 
1109 	const int interfaceLayoutNdx = layout.getInterfaceLayoutIndex(blockNdx, name.str());
1110 	DE_ASSERT(interfaceLayoutNdx >= 0);
1111 
1112 	return layout.interfaces[interfaceLayoutNdx].offset;
1113 }
1114 
1115 template<typename T>
semiShuffle(std::vector<T> & v)1116 void semiShuffle (std::vector<T>& v)
1117 {
1118 	const std::vector<T>	src	= v;
1119 	int						i	= -1;
1120 	int						n	= static_cast<int>(src.size());
1121 
1122 	v.clear();
1123 
1124 	while (n)
1125 	{
1126 		i += n;
1127 		v.push_back(src[i]);
1128 		n = (n > 0 ? 1 - n : -1 - n);
1129 	}
1130 }
1131 
1132 template<typename T>
1133 //! \note Stores pointers to original elements
1134 class Traverser
1135 {
1136 public:
1137 	template<typename Iter>
Traverser(const Iter beg,const Iter end,const bool shuffled)1138 	Traverser (const Iter beg, const Iter end, const bool shuffled)
1139 	{
1140 		for (Iter it = beg; it != end; ++it)
1141 			m_elements.push_back(&(*it));
1142 
1143 		if (shuffled)
1144 			semiShuffle(m_elements);
1145 
1146 		m_next = m_elements.begin();
1147 	}
1148 
next(void)1149 	T* next (void)
1150 	{
1151 		if (m_next != m_elements.end())
1152 			return *m_next++;
1153 		else
1154 			return DE_NULL;
1155 	}
1156 
1157 private:
1158 	typename std::vector<T*>					m_elements;
1159 	typename std::vector<T*>::const_iterator	m_next;
1160 };
1161 
generateDeclaration(std::ostringstream & src,int blockNdx,const InterfaceBlock & block,const InterfaceLayout & layout,bool shuffleUniformMembers)1162 void generateDeclaration (std::ostringstream& src, int blockNdx, const InterfaceBlock& block, const InterfaceLayout& layout, bool shuffleUniformMembers)
1163 {
1164 	const int indentOne		= 1;
1165 	const int ndx			= layout.getBlockLayoutIndex(blockNdx, 0);
1166 	const int locationNdx	= layout.blocks[ndx].locationNdx;
1167 	const int xfbOffset		= layout.blocks[ndx].xfbOffset;
1168 	const int xfbBuffer		= layout.blocks[ndx].xfbBuffer;
1169 	const int xfbStride		= layout.blocks[ndx].xfbStride;
1170 
1171 	src << "layout(";
1172 	src << "location = " << locationNdx;
1173 	if ((block.getFlags() & LAYOUT_MASK) != 0)
1174 		src << ", " << LayoutFlagsFmt(block.getFlags() & LAYOUT_MASK, xfbBuffer, xfbStride, xfbOffset);
1175 	src << ") out " << block.getBlockName();
1176 
1177 	src << " //"
1178 		<< " sizeInBytes=" << layout.blocks[ndx].xfbSize
1179 		<< " sizeInLocations=" << layout.blocks[ndx].locationSize;
1180 
1181 	src << "\n{\n";
1182 
1183 	Traverser<const InterfaceBlockMember> interfaces(block.begin(), block.end(), shuffleUniformMembers);
1184 
1185 	while (const InterfaceBlockMember* pUniform = interfaces.next())
1186 	{
1187 		src << Indent(indentOne);
1188 		generateDeclaration(src, *pUniform, indentOne, xfbBuffer, xfbStride, xfbOffset + getBlockMemberOffset(blockNdx, block, *pUniform, layout));
1189 	}
1190 
1191 	src << "}";
1192 
1193 	if (block.hasInstanceName())
1194 	{
1195 		src << " " << block.getInstanceName();
1196 		if (block.isArray())
1197 			src << "[" << block.getArraySize() << "]";
1198 	}
1199 	else
1200 		DE_ASSERT(!block.isArray());
1201 
1202 	src << ";\n";
1203 }
1204 
generateValueSrc(std::ostringstream & src,const InterfaceLayoutEntry & entry,const void * basePtr,int elementNdx)1205 int generateValueSrc (std::ostringstream& src, const InterfaceLayoutEntry& entry, const void* basePtr, int elementNdx)
1206 {
1207 	const glu::DataType	scalarType	= glu::getDataTypeScalarType(entry.type);
1208 	const int			scalarSize	= glu::getDataTypeScalarSize(entry.type);
1209 	const bool			isArray		= entry.arraySize > 1;
1210 	const deUint8*		elemPtr		= (const deUint8*)basePtr + entry.offset + (isArray ? elementNdx * entry.arrayStride : 0);
1211 	const size_t		compSize	= getDataTypeByteSize(scalarType);
1212 
1213 	if (scalarSize > 1)
1214 		src << glu::getDataTypeName(entry.type) << "(";
1215 
1216 	if (glu::isDataTypeMatrix(entry.type))
1217 	{
1218 		const int	numRows	= glu::getDataTypeMatrixNumRows(entry.type);
1219 		const int	numCols	= glu::getDataTypeMatrixNumColumns(entry.type);
1220 
1221 		DE_ASSERT(scalarType == glu::TYPE_FLOAT || scalarType == glu::TYPE_DOUBLE);
1222 
1223 		// Constructed in column-wise order.
1224 		for (int colNdx = 0; colNdx < numCols; colNdx++)
1225 		{
1226 			for (int rowNdx = 0; rowNdx < numRows; rowNdx++)
1227 			{
1228 				const deUint8*	compPtr	= elemPtr + (colNdx * entry.matrixStride + rowNdx * compSize);
1229 				const float		compVal	= (scalarType == glu::TYPE_FLOAT) ? *((const float*)compPtr)
1230 										: (scalarType == glu::TYPE_DOUBLE) ? (float)*((const double*)compPtr)
1231 										: 0.0f;
1232 
1233 				if (colNdx > 0 || rowNdx > 0)
1234 					src << ", ";
1235 
1236 				src << de::floatToString(compVal, 1);
1237 			}
1238 		}
1239 	}
1240 	else
1241 	{
1242 		for (int scalarNdx = 0; scalarNdx < scalarSize; scalarNdx++)
1243 		{
1244 			const deUint8* compPtr = elemPtr + scalarNdx * compSize;
1245 
1246 			if (scalarNdx > 0)
1247 				src << ", ";
1248 
1249 			switch (scalarType)
1250 			{
1251 				case glu::TYPE_DOUBLE:	src << de::floatToString((float)(*((const double*)compPtr)), 1);	break;
1252 				case glu::TYPE_FLOAT:	src << de::floatToString(*((const float*)compPtr), 1) << "f";		break;
1253 				case glu::TYPE_INT:		src << *((const int*)compPtr);										break;
1254 				case glu::TYPE_UINT:	src << *((const deUint32*)compPtr) << "u";							break;
1255 				default:				DE_ASSERT(false && "Invalid type");									break;
1256 			}
1257 		}
1258 	}
1259 
1260 	if (scalarSize > 1)
1261 		src << ")";
1262 
1263 	return static_cast<int>(elemPtr - static_cast<const deUint8*>(basePtr));
1264 }
1265 
writeMatrixTypeSrc(int columnCount,int rowCount,std::string type,std::ostringstream & src,const std::string & srcName,const void * basePtr,const InterfaceLayoutEntry & entry,bool vector)1266 void writeMatrixTypeSrc (int							columnCount,
1267 						 int							rowCount,
1268 						 std::string					type,
1269 						 std::ostringstream&			src,
1270 						 const std::string&				srcName,
1271 						 const void*					basePtr,
1272 						 const InterfaceLayoutEntry&	entry,
1273 						 bool							vector)
1274 {
1275 	if (vector)	// generateTestSrcMatrixPerVec
1276 	{
1277 		for (int colNdx = 0; colNdx < columnCount; colNdx++)
1278 		{
1279 			src << "\t" << srcName << "[" << colNdx << "] = ";
1280 
1281 			if (glu::isDataTypeMatrix(entry.type))
1282 			{
1283 				const glu::DataType	scalarType	= glu::getDataTypeScalarType(entry.type);
1284 				const int			scalarSize	= glu::getDataTypeScalarSize(entry.type);
1285 				const deUint8*		compPtr		= (const deUint8*)basePtr + entry.offset;
1286 
1287 				if (scalarSize > 1)
1288 					src << type << "(";
1289 
1290 				for (int rowNdx = 0; rowNdx < rowCount; rowNdx++)
1291 				{
1292 					const float		compVal	= (scalarType == glu::TYPE_FLOAT) ? *((const float*)compPtr)
1293 											: (scalarType == glu::TYPE_DOUBLE) ? (float)*((const double*)compPtr)
1294 											: 0.0f;
1295 
1296 					src << de::floatToString(compVal, 1);
1297 
1298 					if (rowNdx < rowCount-1)
1299 						src << ", ";
1300 				}
1301 
1302 				src << ");\n";
1303 			}
1304 			else
1305 			{
1306 				generateValueSrc(src, entry, basePtr, 0);
1307 				src << "[" << colNdx << "];\n";
1308 			}
1309 		}
1310 	}
1311 	else		// generateTestSrcMatrixPerElement
1312 	{
1313 		const glu::DataType	scalarType	= glu::getDataTypeScalarType(entry.type);
1314 
1315 		for (int colNdx = 0; colNdx < columnCount; colNdx++)
1316 		{
1317 			for (int rowNdx = 0; rowNdx < rowCount; rowNdx++)
1318 			{
1319 				src << "\t" << srcName << "[" << colNdx << "][" << rowNdx << "] = ";
1320 				if (glu::isDataTypeMatrix(entry.type))
1321 				{
1322 					const deUint8*	elemPtr		= (const deUint8*)basePtr + entry.offset;
1323 					const size_t	compSize	= getDataTypeByteSize(scalarType);
1324 					const deUint8*	compPtr		= elemPtr + (colNdx * entry.matrixStride + rowNdx * compSize);
1325 					const float		compVal		= (scalarType == glu::TYPE_FLOAT) ? *((const float*)compPtr)
1326 												: (scalarType == glu::TYPE_DOUBLE) ? (float)*((const double*)compPtr)
1327 												: 0.0f;
1328 
1329 					src << de::floatToString(compVal, 1) << ";\n";
1330 				}
1331 				else
1332 				{
1333 					generateValueSrc(src, entry, basePtr, 0);
1334 					src << "[" << colNdx << "][" << rowNdx << "];\n";
1335 				}
1336 			}
1337 		}
1338 	}
1339 }
1340 
generateTestSrcMatrixPerVec(std::ostringstream & src,glu::DataType elementType,const std::string & srcName,const void * basePtr,const InterfaceLayoutEntry & entry)1341 void generateTestSrcMatrixPerVec (std::ostringstream&			src,
1342 								  glu::DataType					elementType,
1343 								  const std::string&			srcName,
1344 								  const void*					basePtr,
1345 								  const InterfaceLayoutEntry&	entry)
1346 {
1347 	switch (elementType)
1348 	{
1349 		case glu::TYPE_FLOAT_MAT2:		writeMatrixTypeSrc(2, 2, "vec2", src, srcName, basePtr, entry, true);	break;
1350 		case glu::TYPE_FLOAT_MAT2X3:	writeMatrixTypeSrc(2, 3, "vec3", src, srcName, basePtr, entry, true);	break;
1351 		case glu::TYPE_FLOAT_MAT2X4:	writeMatrixTypeSrc(2, 4, "vec4", src, srcName, basePtr, entry, true);	break;
1352 		case glu::TYPE_FLOAT_MAT3X4:	writeMatrixTypeSrc(3, 4, "vec4", src, srcName, basePtr, entry, true);	break;
1353 		case glu::TYPE_FLOAT_MAT4:		writeMatrixTypeSrc(4, 4, "vec4", src, srcName, basePtr, entry, true);	break;
1354 		case glu::TYPE_FLOAT_MAT4X2:	writeMatrixTypeSrc(4, 2, "vec2", src, srcName, basePtr, entry, true);	break;
1355 		case glu::TYPE_FLOAT_MAT4X3:	writeMatrixTypeSrc(4, 3, "vec3", src, srcName, basePtr, entry, true);	break;
1356 		default:						DE_ASSERT(false && "Invalid type");										break;
1357 	}
1358 }
1359 
generateTestSrcMatrixPerElement(std::ostringstream & src,glu::DataType elementType,const std::string & srcName,const void * basePtr,const InterfaceLayoutEntry & entry)1360 void generateTestSrcMatrixPerElement (std::ostringstream&			src,
1361 									  glu::DataType					elementType,
1362 									  const std::string&			srcName,
1363 									  const void*					basePtr,
1364 									  const InterfaceLayoutEntry&	entry)
1365 {
1366 	std::string type = "float";
1367 	switch (elementType)
1368 	{
1369 		case glu::TYPE_FLOAT_MAT2:		writeMatrixTypeSrc(2, 2, type, src, srcName, basePtr, entry, false);	break;
1370 		case glu::TYPE_FLOAT_MAT2X3:	writeMatrixTypeSrc(2, 3, type, src, srcName, basePtr, entry, false);	break;
1371 		case glu::TYPE_FLOAT_MAT2X4:	writeMatrixTypeSrc(2, 4, type, src, srcName, basePtr, entry, false);	break;
1372 		case glu::TYPE_FLOAT_MAT3X4:	writeMatrixTypeSrc(3, 4, type, src, srcName, basePtr, entry, false);	break;
1373 		case glu::TYPE_FLOAT_MAT4:		writeMatrixTypeSrc(4, 4, type, src, srcName, basePtr, entry, false);	break;
1374 		case glu::TYPE_FLOAT_MAT4X2:	writeMatrixTypeSrc(4, 2, type, src, srcName, basePtr, entry, false);	break;
1375 		case glu::TYPE_FLOAT_MAT4X3:	writeMatrixTypeSrc(4, 3, type, src, srcName, basePtr, entry, false);	break;
1376 		default:						DE_ASSERT(false && "Invalid type");										break;
1377 	}
1378 }
1379 
generateSingleAssignment(std::ostringstream & src,glu::DataType elementType,const std::string & srcName,const void * basePtr,const InterfaceLayoutEntry & entry,MatrixLoadFlags matrixLoadFlag)1380 void generateSingleAssignment (std::ostringstream&			src,
1381 							   glu::DataType				elementType,
1382 							   const std::string&			srcName,
1383 							   const void*					basePtr,
1384 							   const InterfaceLayoutEntry&	entry,
1385 							   MatrixLoadFlags				matrixLoadFlag)
1386 {
1387 	if (matrixLoadFlag == LOAD_FULL_MATRIX)
1388 	{
1389 		src << "\t" << srcName << " = ";
1390 		generateValueSrc(src, entry, basePtr, 0);
1391 		src << ";\n";
1392 	}
1393 	else
1394 	{
1395 		if (glu::isDataTypeMatrix(elementType))
1396 		{
1397 			generateTestSrcMatrixPerVec		(src, elementType, srcName, basePtr, entry);
1398 			generateTestSrcMatrixPerElement	(src, elementType, srcName, basePtr, entry);
1399 		}
1400 	}
1401 }
1402 
generateAssignment(std::ostringstream & src,const InterfaceLayout & layout,const VarType & type,const std::string & srcName,const std::string & apiName,int blockNdx,const void * basePtr,MatrixLoadFlags matrixLoadFlag)1403 void generateAssignment (std::ostringstream&	src,
1404 						 const InterfaceLayout&	layout,
1405 						 const VarType&			type,
1406 						 const std::string&		srcName,
1407 						 const std::string&		apiName,
1408 						 int					blockNdx,
1409 						 const void*			basePtr,
1410 						 MatrixLoadFlags		matrixLoadFlag)
1411 {
1412 	if (type.isBasicType() || (type.isArrayType() && type.getElementType().isBasicType()))
1413 	{
1414 		// Basic type or array of basic types.
1415 		bool						isArray				= type.isArrayType();
1416 		glu::DataType				elementType			= isArray ? type.getElementType().getBasicType() : type.getBasicType();
1417 		std::string					fullApiName			= std::string(apiName) + (isArray ? "[0]" : ""); // Arrays are always postfixed with [0]
1418 		int							interfaceLayoutNdx	= layout.getInterfaceLayoutIndex(blockNdx, fullApiName);
1419 		const InterfaceLayoutEntry&	entry				= layout.interfaces[interfaceLayoutNdx];
1420 
1421 		if (isArray)
1422 		{
1423 			for (int elemNdx = 0; elemNdx < type.getArraySize(); elemNdx++)
1424 			{
1425 				src << "\t" << srcName << "[" << elemNdx << "] = ";
1426 				generateValueSrc(src, entry, basePtr, elemNdx);
1427 				src << ";\n";
1428 			}
1429 		}
1430 		else
1431 		{
1432 			generateSingleAssignment(src, elementType, srcName, basePtr, entry, matrixLoadFlag);
1433 		}
1434 	}
1435 	else if (type.isArrayType())
1436 	{
1437 		const VarType& elementType = type.getElementType();
1438 
1439 		for (int elementNdx = 0; elementNdx < type.getArraySize(); elementNdx++)
1440 		{
1441 			const std::string op				= std::string("[") + de::toString(elementNdx) + "]";
1442 			const std::string elementSrcName	= std::string(srcName) + op;
1443 			const std::string elementApiName	= std::string(apiName) + op;
1444 
1445 			generateAssignment(src, layout, elementType, elementSrcName, elementApiName, blockNdx, basePtr, LOAD_FULL_MATRIX);
1446 		}
1447 	}
1448 	else
1449 	{
1450 		DE_ASSERT(type.isStructType());
1451 
1452 		for (StructType::ConstIterator memberIter = type.getStruct().begin(); memberIter != type.getStruct().end(); memberIter++)
1453 		{
1454 			const StructMember&	member			= *memberIter;
1455 			const std::string	op				= std::string(".") + member.getName();
1456 			const std::string	memberSrcName	= std::string(srcName) + op;
1457 			const std::string	memberApiName	= std::string(apiName) + op;
1458 
1459 			if (0 == (member.getFlags() & (FIELD_UNASSIGNED | FIELD_MISSING)))
1460 				generateAssignment(src, layout, memberIter->getType(), memberSrcName, memberApiName, blockNdx, basePtr, LOAD_FULL_MATRIX);
1461 		}
1462 	}
1463 }
1464 
generateAssignment(std::ostringstream & src,const InterfaceLayout & layout,const ShaderInterface & shaderInterface,const std::map<int,void * > & blockPointers,MatrixLoadFlags matrixLoadFlag)1465 void generateAssignment (std::ostringstream&			src,
1466 						 const InterfaceLayout&			layout,
1467 						 const ShaderInterface&			shaderInterface,
1468 						 const std::map<int, void*>&	blockPointers,
1469 						 MatrixLoadFlags				matrixLoadFlag)
1470 {
1471 	for (int blockNdx = 0; blockNdx < shaderInterface.getNumInterfaceBlocks(); blockNdx++)
1472 	{
1473 		const InterfaceBlock& block = shaderInterface.getInterfaceBlock(blockNdx);
1474 
1475 		bool			hasInstanceName	= block.hasInstanceName();
1476 		bool			isArray			= block.isArray();
1477 		int				numInstances	= isArray ? block.getArraySize() : 1;
1478 		std::string		apiPrefix		= hasInstanceName ? block.getBlockName() + "." : std::string("");
1479 
1480 		DE_ASSERT(!isArray || hasInstanceName);
1481 
1482 		for (int instanceNdx = 0; instanceNdx < numInstances; instanceNdx++)
1483 		{
1484 			std::string		instancePostfix		= isArray ? std::string("[") + de::toString(instanceNdx) + "]" : std::string("");
1485 			std::string		blockInstanceName	= block.getBlockName() + instancePostfix;
1486 			std::string		srcPrefix			= hasInstanceName ? block.getInstanceName() + instancePostfix + "." : std::string("");
1487 			int				blockLayoutNdx		= layout.getBlockLayoutIndex(blockNdx, instanceNdx);
1488 			void*			basePtr				= blockPointers.find(blockLayoutNdx)->second;
1489 
1490 			for (InterfaceBlock::ConstIterator interfaceMemberIter = block.begin(); interfaceMemberIter != block.end(); interfaceMemberIter++)
1491 			{
1492 				const InterfaceBlockMember& interfaceMember = *interfaceMemberIter;
1493 
1494 				if ((interfaceMember.getFlags() & (FIELD_MISSING | FIELD_UNASSIGNED)) == 0)
1495 				{
1496 					std::string srcName = srcPrefix + interfaceMember.getName();
1497 					std::string apiName = apiPrefix + interfaceMember.getName();
1498 
1499 					generateAssignment(src, layout, interfaceMember.getType(), srcName, apiName, blockNdx, basePtr, matrixLoadFlag);
1500 				}
1501 			}
1502 		}
1503 	}
1504 }
1505 
generatePassthroughShader()1506 std::string generatePassthroughShader ()
1507 {
1508 	std::ostringstream	src;
1509 
1510 	src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n";
1511 
1512 	src << "\n"
1513 		   "void main (void)\n"
1514 		   "{\n"
1515 		   "}\n";
1516 
1517 	return src.str();
1518 }
1519 
generateTestShader(const ShaderInterface & shaderInterface,const InterfaceLayout & layout,const std::map<int,void * > & blockPointers,MatrixLoadFlags matrixLoadFlag,TestStageFlags testStageFlags,bool shuffleUniformMembers)1520 std::string generateTestShader (const ShaderInterface& shaderInterface, const InterfaceLayout& layout, const std::map<int, void*>& blockPointers, MatrixLoadFlags matrixLoadFlag, TestStageFlags testStageFlags, bool shuffleUniformMembers)
1521 {
1522 	std::ostringstream				src;
1523 	std::vector<const StructType*>	namedStructs;
1524 
1525 	src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n\n";
1526 
1527 	if (testStageFlags == TEST_STAGE_GEOMETRY)
1528 	{
1529 		src << "layout(points) in;\n"
1530 			<< "layout(points, max_vertices = 1) out;\n\n";
1531 	}
1532 
1533 	shaderInterface.getNamedStructs(namedStructs);
1534 	for (std::vector<const StructType*>::const_iterator structIter = namedStructs.begin(); structIter != namedStructs.end(); structIter++)
1535 		generateDeclaration(src, **structIter, 0);
1536 
1537 	for (int blockNdx = 0; blockNdx < shaderInterface.getNumInterfaceBlocks(); blockNdx++)
1538 	{
1539 		const InterfaceBlock& block = shaderInterface.getInterfaceBlock(blockNdx);
1540 
1541 		generateDeclaration(src, blockNdx, block, layout, shuffleUniformMembers);
1542 	}
1543 
1544 	src << "\n"
1545 		   "void main (void)\n"
1546 		   "{\n";
1547 
1548 	generateAssignment(src, layout, shaderInterface, blockPointers, matrixLoadFlag);
1549 
1550 	if (testStageFlags == TEST_STAGE_GEOMETRY)
1551 	{
1552 		src << "\n"
1553 			<< "\tEmitVertex();\n"
1554 			<< "\tEndPrimitive();\n";
1555 	}
1556 
1557 	src << "}\n";
1558 
1559 	return src.str();
1560 }
1561 
makeGraphicsPipeline(const DeviceInterface & vk,const VkDevice device,const VkPipelineLayout pipelineLayout,const VkRenderPass renderPass,const VkShaderModule vertexModule,const VkShaderModule geometryModule,const VkExtent2D renderSize)1562 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface&		vk,
1563 									   const VkDevice				device,
1564 									   const VkPipelineLayout		pipelineLayout,
1565 									   const VkRenderPass			renderPass,
1566 									   const VkShaderModule			vertexModule,
1567 									   const VkShaderModule			geometryModule,
1568 									   const VkExtent2D				renderSize)
1569 {
1570 	const std::vector<VkViewport>				viewports						(1, makeViewport(renderSize));
1571 	const std::vector<VkRect2D>					scissors						(1, makeRect2D(renderSize));
1572 	const VkPipelineVertexInputStateCreateInfo	vertexInputStateCreateInfo	=
1573 	{
1574 		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	// VkStructureType								sType
1575 		DE_NULL,													// const void*									pNext
1576 		(VkPipelineVertexInputStateCreateFlags)0,					// VkPipelineVertexInputStateCreateFlags		flags
1577 		0u,															// deUint32										vertexBindingDescriptionCount
1578 		DE_NULL,													// const VkVertexInputBindingDescription*		pVertexBindingDescriptions
1579 		0u,															// deUint32										vertexAttributeDescriptionCount
1580 		DE_NULL,													// const VkVertexInputAttributeDescription*		pVertexAttributeDescriptions
1581 	};
1582 
1583 	return makeGraphicsPipeline(vk,									// const DeviceInterface&						vk
1584 								device,								// const VkDevice								device
1585 								pipelineLayout,						// const VkPipelineLayout						pipelineLayout
1586 								vertexModule,						// const VkShaderModule							vertexShaderModule
1587 								DE_NULL,							// const VkShaderModule							tessellationControlModule
1588 								DE_NULL,							// const VkShaderModule							tessellationEvalModule
1589 								geometryModule,						// const VkShaderModule							geometryShaderModule
1590 								DE_NULL,							// const VkShaderModule							m_maxGeometryBlocksShaderModule
1591 								renderPass,							// const VkRenderPass							renderPass
1592 								viewports,							// const std::vector<VkViewport>&				viewports
1593 								scissors,							// const std::vector<VkRect2D>&					scissors
1594 								VK_PRIMITIVE_TOPOLOGY_POINT_LIST,	// const VkPrimitiveTopology					topology
1595 								0u,									// const deUint32								subpass
1596 								0u,									// const deUint32								patchControlPoints
1597 								&vertexInputStateCreateInfo);		// const VkPipelineVertexInputStateCreateInfo*	vertexInputStateCreateInfo
1598 }
1599 
1600 // InterfaceBlockCaseInstance
1601 
1602 class InterfaceBlockCaseInstance : public vkt::TestInstance
1603 {
1604 public:
1605 									InterfaceBlockCaseInstance	(Context&							context,
1606 																 const InterfaceLayout&				layout,
1607 																 const std::map<int, void*>&		blockPointers,
1608 																 const std::vector<deUint8>&		data,
1609 																 const std::vector<VkDeviceSize>&	tfBufBindingOffsets,
1610 																 const std::vector<VkDeviceSize>&	tfBufBindingSizes,
1611 																 const deUint32						locationsRequired,
1612 																 const TestStageFlags				testStageFlags);
1613 
1614 	virtual							~InterfaceBlockCaseInstance	(void);
1615 	virtual tcu::TestStatus			iterate						(void);
1616 
1617 private:
1618 	Move<VkShaderModule>			getGeometryShaderModule		(const DeviceInterface&	vk,
1619 																 const VkDevice			device);
1620 
1621 	bool							usesFloat64					(void);
1622 	std::string						validateValue				(const InterfaceLayoutEntry& entry, const void* basePtr0, const void* basePtr, const void* receivedBasePtr);
1623 	std::string						validateValues				(const void* recievedDataPtr);
1624 
1625 	typedef de::SharedPtr<vk::Unique<vk::VkBuffer> >	VkBufferSp;
1626 	typedef de::SharedPtr<vk::Allocation>				AllocationSp;
1627 
1628 	const InterfaceLayout&			m_layout;
1629 	const std::vector<deUint8>&		m_data;
1630 	const DeviceSizeVector&			m_tfBufBindingOffsets;
1631 	const DeviceSizeVector&			m_tfBufBindingSizes;
1632 	const std::map<int, void*>&		m_blockPointers;
1633 	const deUint32					m_locationsRequired;
1634 	const TestStageFlags			m_testStageFlags;
1635 	const VkExtent2D				m_imageExtent2D;
1636 };
1637 
InterfaceBlockCaseInstance(Context & ctx,const InterfaceLayout & layout,const std::map<int,void * > & blockPointers,const std::vector<deUint8> & data,const std::vector<VkDeviceSize> & tfBufBindingOffsets,const std::vector<VkDeviceSize> & tfBufBindingSizes,const deUint32 locationsRequired,const TestStageFlags testStageFlags)1638 InterfaceBlockCaseInstance::InterfaceBlockCaseInstance (Context&							ctx,
1639 														const InterfaceLayout&				layout,
1640 														const std::map<int, void*>&			blockPointers,
1641 														const std::vector<deUint8>&			data,
1642 														const std::vector<VkDeviceSize>&	tfBufBindingOffsets,
1643 														const std::vector<VkDeviceSize>&	tfBufBindingSizes,
1644 														const deUint32						locationsRequired,
1645 														const TestStageFlags				testStageFlags)
1646 	: vkt::TestInstance		(ctx)
1647 	, m_layout				(layout)
1648 	, m_data				(data)
1649 	, m_tfBufBindingOffsets	(tfBufBindingOffsets)
1650 	, m_tfBufBindingSizes	(tfBufBindingSizes)
1651 	, m_blockPointers		(blockPointers)
1652 	, m_locationsRequired	(locationsRequired)
1653 	, m_testStageFlags		(testStageFlags)
1654 	, m_imageExtent2D		(makeExtent2D(256u, 256u))
1655 {
1656 	const deUint32											componentsPerLocation		= 4u;
1657 	const deUint32											componentsRequired			= m_locationsRequired * componentsPerLocation + 7u; // Add 7 for built-in components
1658 	const InstanceInterface&								vki							= m_context.getInstanceInterface();
1659 	const VkPhysicalDevice									physDevice					= m_context.getPhysicalDevice();
1660 	const VkPhysicalDeviceFeatures							features					= getPhysicalDeviceFeatures(vki, physDevice);
1661 	const VkPhysicalDeviceTransformFeedbackFeaturesEXT&		transformFeedbackFeatures	= m_context.getTransformFeedbackFeaturesEXT();
1662 	const VkPhysicalDeviceLimits							limits						= getPhysicalDeviceProperties(vki, physDevice).limits;
1663 	VkPhysicalDeviceTransformFeedbackPropertiesEXT			transformFeedbackProperties;
1664 	VkPhysicalDeviceProperties2								deviceProperties2;
1665 
1666 	if (transformFeedbackFeatures.transformFeedback == DE_FALSE)
1667 		TCU_THROW(NotSupportedError, "transformFeedback feature is not supported");
1668 
1669 	deMemset(&deviceProperties2, 0, sizeof(deviceProperties2));
1670 	deMemset(&transformFeedbackProperties, 0x00, sizeof(transformFeedbackProperties));
1671 
1672 	deviceProperties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
1673 	deviceProperties2.pNext = &transformFeedbackProperties;
1674 
1675 	transformFeedbackProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_PROPERTIES_EXT;
1676 	transformFeedbackProperties.pNext = DE_NULL;
1677 
1678 	vki.getPhysicalDeviceProperties2(physDevice, &deviceProperties2);
1679 
1680 	if (transformFeedbackProperties.maxTransformFeedbackBuffers < tfBufBindingSizes.size())
1681 		TCU_THROW(NotSupportedError, "maxTransformFeedbackBuffers=" + de::toString(transformFeedbackProperties.maxTransformFeedbackBuffers) + " is less than required (" + de::toString(tfBufBindingSizes.size()) + ")");
1682 
1683 	if (transformFeedbackProperties.maxTransformFeedbackBufferDataSize < m_data.size())
1684 		TCU_THROW(NotSupportedError, "maxTransformFeedbackBufferDataSize=" + de::toString(transformFeedbackProperties.maxTransformFeedbackBufferDataSize) + " is less than required (" + de::toString(m_data.size()) + ")");
1685 
1686 	if (m_testStageFlags == TEST_STAGE_VERTEX)
1687 	{
1688 		if (limits.maxVertexOutputComponents < componentsRequired)
1689 			TCU_THROW(NotSupportedError, "maxVertexOutputComponents=" + de::toString(limits.maxVertexOutputComponents) + " is less than required (" + de::toString(componentsRequired) + ")");
1690 	}
1691 
1692 	if (m_testStageFlags == TEST_STAGE_GEOMETRY)
1693 	{
1694 		if (!features.geometryShader)
1695 			TCU_THROW(NotSupportedError, "Missing feature: geometryShader");
1696 
1697 		if (limits.maxGeometryOutputComponents < componentsRequired)
1698 			TCU_THROW(NotSupportedError, "maxGeometryOutputComponents=" + de::toString(limits.maxGeometryOutputComponents) + " is less than required (" + de::toString(componentsRequired) + ")");
1699 	}
1700 
1701 	if (usesFloat64())
1702 		m_context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SHADER_FLOAT64);
1703 }
1704 
~InterfaceBlockCaseInstance(void)1705 InterfaceBlockCaseInstance::~InterfaceBlockCaseInstance (void)
1706 {
1707 }
1708 
usesFloat64(void)1709 bool InterfaceBlockCaseInstance::usesFloat64 (void)
1710 {
1711 	for (size_t layoutNdx = 0; layoutNdx< m_layout.interfaces.size(); ++layoutNdx)
1712 		if (isDataTypeDoubleType(m_layout.interfaces[layoutNdx].type))
1713 			return true;
1714 
1715 	return false;
1716 }
1717 
getGeometryShaderModule(const DeviceInterface & vk,const VkDevice device)1718 Move<VkShaderModule> InterfaceBlockCaseInstance::getGeometryShaderModule (const DeviceInterface&	vk,
1719 																		  const VkDevice			device)
1720 {
1721 	if (m_testStageFlags == TEST_STAGE_GEOMETRY)
1722 		return createShaderModule(vk, device, m_context.getBinaryCollection().get("geom"), 0u);
1723 
1724 	return Move<VkShaderModule>();
1725 }
1726 
iterate(void)1727 tcu::TestStatus InterfaceBlockCaseInstance::iterate (void)
1728 {
1729 	const DeviceInterface&			vk					= m_context.getDeviceInterface();
1730 	const VkDevice					device				= m_context.getDevice();
1731 	const deUint32					queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
1732 	const VkQueue					queue				= m_context.getUniversalQueue();
1733 	Allocator&						allocator			= m_context.getDefaultAllocator();
1734 
1735 	const Move<VkShaderModule>		vertModule			(createShaderModule		(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
1736 	const Move<VkShaderModule>		geomModule			(getGeometryShaderModule(vk, device));
1737 	const Move<VkRenderPass>		renderPass			(makeRenderPass			(vk, device, VK_FORMAT_UNDEFINED));
1738 	const Move<VkFramebuffer>		framebuffer			(makeFramebuffer		(vk, device, *renderPass, 0u, DE_NULL, m_imageExtent2D.width, m_imageExtent2D.height));
1739 	const Move<VkPipelineLayout>	pipelineLayout		(makePipelineLayout		(vk, device));
1740 	const Move<VkPipeline>			pipeline			(makeGraphicsPipeline	(vk, device, *pipelineLayout, *renderPass, *vertModule, *geomModule, m_imageExtent2D));
1741 	const Move<VkCommandPool>		cmdPool				(createCommandPool		(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1742 	const Move<VkCommandBuffer>		cmdBuffer			(allocateCommandBuffer	(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1743 
1744 	const VkBufferCreateInfo		tfBufCreateInfo		= makeBufferCreateInfo(m_data.size(), VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT);
1745 	const Move<VkBuffer>			tfBuf				= createBuffer(vk, device, &tfBufCreateInfo);
1746 	const de::MovePtr<Allocation>	tfBufAllocation		= allocator.allocate(getBufferMemoryRequirements(vk, device, *tfBuf), MemoryRequirement::HostVisible);
1747 	const deUint32					tfBufBindingCount	= static_cast<deUint32>(m_tfBufBindingOffsets.size());
1748 	const std::vector<VkBuffer>		tfBufBindings		(tfBufBindingCount, *tfBuf);
1749 
1750 	DE_ASSERT(tfBufBindings.size() == tfBufBindingCount);
1751 
1752 	VK_CHECK(vk.bindBufferMemory(device, *tfBuf, tfBufAllocation->getMemory(), tfBufAllocation->getOffset()));
1753 
1754 	deMemset(tfBufAllocation->getHostPtr(), 0, m_data.size());
1755 	flushMappedMemoryRange(vk, device, tfBufAllocation->getMemory(), tfBufAllocation->getOffset(), VK_WHOLE_SIZE);
1756 
1757 	beginCommandBuffer(vk, *cmdBuffer);
1758 	{
1759 		beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D));
1760 		{
1761 			vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1762 
1763 			vk.cmdBindTransformFeedbackBuffersEXT(*cmdBuffer, 0, tfBufBindingCount, &tfBufBindings[0], &m_tfBufBindingOffsets[0], &m_tfBufBindingSizes[0]);
1764 
1765 			vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
1766 			{
1767 				vk.cmdDraw(*cmdBuffer, 1u, 1u, 0u, 0u);
1768 			}
1769 			vk.cmdEndTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
1770 		}
1771 		endRenderPass(vk, *cmdBuffer);
1772 
1773 		const VkMemoryBarrier tfMemoryBarrier =
1774 		{
1775 			VK_STRUCTURE_TYPE_MEMORY_BARRIER,               // VkStructureType      sType;
1776 			DE_NULL,                                        // const void*          pNext;
1777 			VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT,     // VkAccessFlags        outputMask;
1778 			VK_ACCESS_HOST_READ_BIT                         // VkAccessFlags        inputMask;
1779 		};
1780 		vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &tfMemoryBarrier, 0u, DE_NULL, 0u, DE_NULL);
1781 	}
1782 	endCommandBuffer(vk, *cmdBuffer);
1783 	submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1784 
1785 	invalidateMappedMemoryRange(vk, device, tfBufAllocation->getMemory(), tfBufAllocation->getOffset(), VK_WHOLE_SIZE);
1786 
1787 	std::string result = validateValues(tfBufAllocation->getHostPtr());
1788 
1789 	if (!result.empty())
1790 		return tcu::TestStatus::fail(result);
1791 
1792 	return tcu::TestStatus::pass("Pass");
1793 }
1794 
validateValue(const InterfaceLayoutEntry & entry,const void * basePtr0,const void * basePtr,const void * receivedBasePtr)1795 std::string InterfaceBlockCaseInstance::validateValue (const InterfaceLayoutEntry& entry, const void* basePtr0, const void* basePtr, const void* receivedBasePtr)
1796 {
1797 	const glu::DataType	scalarType	= glu::getDataTypeScalarType(entry.type);
1798 	const int			scalarSize	= glu::getDataTypeScalarSize(entry.type);
1799 	const bool			isMatrix	= glu::isDataTypeMatrix(entry.type);
1800 	const int			numVecs		= isMatrix ? glu::getDataTypeMatrixNumColumns(entry.type) : 1;
1801 	const int			vecSize		= scalarSize / numVecs;
1802 	const bool			isArray		= entry.arraySize > 1;
1803 	const size_t		compSize	= getDataTypeByteSize(scalarType);
1804 	std::string			result;
1805 
1806 	DE_ASSERT(scalarSize%numVecs == 0);
1807 
1808 	for (int elemNdx = 0; elemNdx < entry.arraySize; elemNdx++)
1809 	{
1810 		deUint8* elemPtr = (deUint8*)basePtr + entry.offset + (isArray ? elemNdx*entry.arrayStride : 0);
1811 
1812 		for (int vecNdx = 0; vecNdx < numVecs; vecNdx++)
1813 		{
1814 			deUint8* vecPtr = elemPtr + (isMatrix ? vecNdx*entry.matrixStride : 0);
1815 
1816 			for (int compNdx = 0; compNdx < vecSize; compNdx++)
1817 			{
1818 				const deUint8*	compPtr		= vecPtr + compSize*compNdx;
1819 				const size_t	offset		= compPtr - (deUint8*)basePtr0;
1820 				const deUint8*	receivedPtr	= (deUint8*)receivedBasePtr + offset;
1821 
1822 				switch (scalarType)
1823 				{
1824 					case glu::TYPE_DOUBLE:
1825 					{
1826 						const double expected	= *((double*)compPtr);
1827 						const double received	= *((double*)receivedPtr);
1828 
1829 						if (deAbs(received - expected) > 0.05)
1830 							result = "Mismatch at offset " + de::toString(offset) + " expected " + de::toString(expected) + " received " + de::toString(received);
1831 
1832 						break;
1833 					}
1834 					case glu::TYPE_FLOAT:
1835 					{
1836 						const float expected	= *((float*)compPtr);
1837 						const float received	= *((float*)receivedPtr);
1838 
1839 						if (deAbs(received - expected) > 0.05)
1840 							result = "Mismatch at offset " + de::toString(offset) + " expected " + de::toString(expected) + " received " + de::toString(received);
1841 
1842 						break;
1843 					}
1844 					case glu::TYPE_INT:
1845 					{
1846 						const deInt32 expected	= *((deInt32*)compPtr);
1847 						const deInt32 received	= *((deInt32*)receivedPtr);
1848 
1849 						if (received != expected)
1850 							result = "Mismatch at offset " + de::toString(offset) + " expected " + de::toString(expected) + " received " + de::toString(received);
1851 
1852 						break;
1853 					}
1854 					case glu::TYPE_UINT:
1855 					{
1856 						const deUint32 expected	= *((deUint32*)compPtr);
1857 						const deUint32 received	= *((deUint32*)receivedPtr);
1858 
1859 						if (received != expected)
1860 							result = "Mismatch at offset " + de::toString(offset) + " expected " + de::toString(expected) + " received " + de::toString(received);
1861 
1862 						break;
1863 					}
1864 					default:
1865 						DE_ASSERT(false);
1866 				}
1867 
1868 				if (!result.empty())
1869 				{
1870 					result += " (elemNdx=" + de::toString(elemNdx) + " vecNdx=" + de::toString(vecNdx) + " compNdx=" + de::toString(compNdx) + ")";
1871 
1872 					return result;
1873 				}
1874 			}
1875 		}
1876 	}
1877 
1878 	return result;
1879 }
1880 
validateValues(const void * recievedDataPtr)1881 std::string InterfaceBlockCaseInstance::validateValues (const void* recievedDataPtr)
1882 {
1883 	const int	numBlocks	= (int)m_layout.blocks.size();
1884 
1885 	for (int blockNdx = 0; blockNdx < numBlocks; blockNdx++)
1886 	{
1887 		void*	basePtr		= m_blockPointers.find(blockNdx)->second;
1888 		int		numEntries	= (int)m_layout.blocks[blockNdx].activeInterfaceIndices.size();
1889 
1890 		for (int entryNdx = 0; entryNdx < numEntries; entryNdx++)
1891 		{
1892 			const InterfaceLayoutEntry&	entry	= m_layout.interfaces[m_layout.blocks[blockNdx].activeInterfaceIndices[entryNdx]];
1893 			const std::string			result	= entry.validate ? validateValue(entry, &m_data[0], basePtr, recievedDataPtr) : "";
1894 
1895 			if (!result.empty())
1896 			{
1897 				tcu::TestLog&			log		= m_context.getTestContext().getLog();
1898 				std::vector<deUint8>	mask	= createMask(m_layout, m_blockPointers, &m_data[0], m_data.size());
1899 				std::ostringstream		str;
1900 
1901 				str << "Error at entry '" << entry.name << "' block '" << m_layout.blocks[blockNdx].name << "'" << std::endl;
1902 				str << result << std::endl;
1903 
1904 				str << m_layout;
1905 
1906 				str << "Xfb buffer offsets: " << m_tfBufBindingOffsets << std::endl;
1907 				str << "Xfb buffer sizes: " << m_tfBufBindingSizes << std::endl << std::endl;
1908 
1909 				dumpBytes(str, "Expected:", &m_data[0], m_data.size(), &mask[0]);
1910 				dumpBytes(str, "Retrieved:", recievedDataPtr, m_data.size(), &mask[0]);
1911 
1912 				dumpBytes(str, "Expected (unfiltered):", &m_data[0], m_data.size());
1913 				dumpBytes(str, "Retrieved (unfiltered):", recievedDataPtr, m_data.size());
1914 
1915 				log << tcu::TestLog::Message << str.str() << tcu::TestLog::EndMessage;
1916 
1917 				return result;
1918 			}
1919 		}
1920 	}
1921 
1922 	return std::string();
1923 }
1924 
1925 } // anonymous (utilities)
1926 
1927 // InterfaceBlockCase.
1928 
InterfaceBlockCase(tcu::TestContext & testCtx,const std::string & name,const std::string & description,MatrixLoadFlags matrixLoadFlag,TestStageFlags testStageFlags,bool shuffleInterfaceMembers)1929 InterfaceBlockCase::InterfaceBlockCase (tcu::TestContext&	testCtx,
1930 										const std::string&	name,
1931 										const std::string&	description,
1932 										MatrixLoadFlags		matrixLoadFlag,
1933 										TestStageFlags		testStageFlags,
1934 										bool				shuffleInterfaceMembers)
1935 	: TestCase					(testCtx, name, description)
1936 	, m_matrixLoadFlag			(matrixLoadFlag)
1937 	, m_testStageFlags			(testStageFlags)
1938 	, m_shuffleInterfaceMembers	(shuffleInterfaceMembers)
1939 	, m_locationsRequired		(0)
1940 {
1941 }
1942 
~InterfaceBlockCase(void)1943 InterfaceBlockCase::~InterfaceBlockCase (void)
1944 {
1945 }
1946 
initPrograms(vk::SourceCollections & programCollection) const1947 void InterfaceBlockCase::initPrograms (vk::SourceCollections& programCollection) const
1948 {
1949 	DE_ASSERT(!m_vertShaderSource.empty());
1950 
1951 	programCollection.glslSources.add("vert") << glu::VertexSource(m_vertShaderSource);
1952 
1953 	if (!m_geomShaderSource.empty())
1954 		programCollection.glslSources.add("geom") << glu::GeometrySource(m_geomShaderSource);
1955 }
1956 
createInstance(Context & context) const1957 TestInstance* InterfaceBlockCase::createInstance (Context& context) const
1958 {
1959 	return new InterfaceBlockCaseInstance(context, m_interfaceLayout, m_blockPointers, m_data, m_tfBufBindingOffsets, m_tfBufBindingSizes, m_locationsRequired, m_testStageFlags);
1960 }
1961 
delayedInit(void)1962 void InterfaceBlockCase::delayedInit (void)
1963 {
1964 	BufferGeneralMapping	xfbBufferSize;
1965 	std::string				notSupportedComment;
1966 
1967 	// Compute reference layout.
1968 	computeXfbLayout(m_interfaceLayout, m_interface, xfbBufferSize, m_locationsRequired);
1969 
1970 	// Assign storage for reference values.
1971 	// m_data contains all xfb buffers starting with all interfaces of first xfb_buffer, then all interfaces of next xfb_buffer
1972 	{
1973 		BufferGeneralMapping	xfbBufferOffsets;
1974 		int						totalSize			= 0;
1975 		int						maxXfb				= 0;
1976 
1977 		for (BufferGeneralMapping::const_iterator xfbBuffersIter = xfbBufferSize.begin(); xfbBuffersIter != xfbBufferSize.end(); xfbBuffersIter++)
1978 		{
1979 			xfbBufferOffsets[xfbBuffersIter->first] = totalSize;
1980 			totalSize += xfbBuffersIter->second;
1981 			maxXfb = std::max(maxXfb, xfbBuffersIter->first);
1982 		}
1983 		m_data.resize(totalSize);
1984 
1985 		DE_ASSERT(de::inBounds(maxXfb, 0, 256)); // Not correlated with spec: just make sure vectors won't be huge
1986 
1987 		m_tfBufBindingSizes.resize(maxXfb + 1);
1988 		for (BufferGeneralMapping::const_iterator xfbBuffersIter = xfbBufferSize.begin(); xfbBuffersIter != xfbBufferSize.end(); xfbBuffersIter++)
1989 			m_tfBufBindingSizes[xfbBuffersIter->first] = xfbBuffersIter->second;
1990 
1991 		m_tfBufBindingOffsets.resize(maxXfb + 1);
1992 		for (BufferGeneralMapping::const_iterator xfbBuffersIter = xfbBufferOffsets.begin(); xfbBuffersIter != xfbBufferOffsets.end(); xfbBuffersIter++)
1993 			m_tfBufBindingOffsets[xfbBuffersIter->first] = xfbBuffersIter->second;
1994 
1995 		// Pointers for each block.
1996 		for (int blockNdx = 0; blockNdx < (int)m_interfaceLayout.blocks.size(); blockNdx++)
1997 		{
1998 			const int dataXfbBufferStartOffset	= xfbBufferOffsets[m_interfaceLayout.blocks[blockNdx].xfbBuffer];
1999 			const int offset					= dataXfbBufferStartOffset + m_interfaceLayout.blocks[blockNdx].xfbOffset;
2000 
2001 			m_blockPointers[blockNdx] = &m_data[0] + offset;
2002 		}
2003 	}
2004 
2005 	// Generate values.
2006 	generateValues(m_interfaceLayout, m_blockPointers, 1 /* seed */);
2007 
2008 	// Overlap validation
2009 	{
2010 		std::vector<deUint8>	mask	= createMask(m_interfaceLayout, m_blockPointers, &m_data[0], m_data.size());
2011 
2012 		for (size_t maskNdx = 0; maskNdx < mask.size(); ++maskNdx)
2013 			DE_ASSERT(mask[maskNdx] <= 1);
2014 	}
2015 
2016 	if (m_testStageFlags == TEST_STAGE_VERTEX)
2017 	{
2018 		m_vertShaderSource = generateTestShader(m_interface, m_interfaceLayout, m_blockPointers, m_matrixLoadFlag, m_testStageFlags, m_shuffleInterfaceMembers);
2019 		m_geomShaderSource = "";
2020 	}
2021 	else if (m_testStageFlags == TEST_STAGE_GEOMETRY)
2022 	{
2023 		m_vertShaderSource = generatePassthroughShader();
2024 		m_geomShaderSource = generateTestShader(m_interface, m_interfaceLayout, m_blockPointers, m_matrixLoadFlag, m_testStageFlags, m_shuffleInterfaceMembers);
2025 	}
2026 	else
2027 	{
2028 		DE_ASSERT(false && "Unknown test stage specified");
2029 	}
2030 }
2031 
2032 } // TransformFeedback
2033 } // vkt
2034