vktShaderRender.cpp revision d6a0393ade7cd708f3497dcd7d1e82a931c31b1e
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 Vulkan ShaderRenderCase
24 *//*--------------------------------------------------------------------*/
25
26#include "vktShaderRender.hpp"
27
28#include "tcuImageCompare.hpp"
29#include "tcuImageIO.hpp"
30#include "tcuTestLog.hpp"
31#include "tcuTextureUtil.hpp"
32#include "tcuSurface.hpp"
33#include "tcuVector.hpp"
34
35#include "deFilePath.hpp"
36#include "deMath.h"
37#include "deUniquePtr.hpp"
38
39#include "vkDeviceUtil.hpp"
40#include "vkImageUtil.hpp"
41#include "vkPlatform.hpp"
42#include "vkQueryUtil.hpp"
43#include "vkRef.hpp"
44#include "vkRefUtil.hpp"
45#include "vkStrUtil.hpp"
46#include "vkTypeUtil.hpp"
47
48#include <vector>
49#include <string>
50
51namespace vkt
52{
53namespace sr
54{
55
56using namespace vk;
57
58namespace
59{
60
61static const int		GRID_SIZE			= 64;
62static const deUint32	MAX_RENDER_WIDTH	= 128;
63static const deUint32	MAX_RENDER_HEIGHT	= 128;
64static const tcu::Vec4	DEFAULT_CLEAR_COLOR	= tcu::Vec4(0.125f, 0.25f, 0.5f, 1.0f);
65
66static VkImageViewType textureTypeToImageViewType (TextureBinding::Type type)
67{
68	switch (type)
69	{
70		case TextureBinding::TYPE_2D:			return VK_IMAGE_VIEW_TYPE_2D;
71		case TextureBinding::TYPE_2D_ARRAY:		return VK_IMAGE_VIEW_TYPE_2D_ARRAY;
72		case TextureBinding::TYPE_CUBE_MAP:		return VK_IMAGE_VIEW_TYPE_CUBE;
73		case TextureBinding::TYPE_3D:			return VK_IMAGE_VIEW_TYPE_3D;
74		default:
75			DE_FATAL("Impossible");
76			return (VkImageViewType)0;
77	}
78}
79
80static VkImageType viewTypeToImageType (VkImageViewType type)
81{
82	switch (type)
83	{
84		case VK_IMAGE_VIEW_TYPE_2D:
85		case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
86		case VK_IMAGE_VIEW_TYPE_CUBE:			return VK_IMAGE_TYPE_2D;
87		case VK_IMAGE_VIEW_TYPE_3D:				return VK_IMAGE_TYPE_3D;
88		default:
89			DE_FATAL("Impossible");
90			return (VkImageType)0;
91	}
92}
93
94/*! Gets the next multiple of a given divisor */
95static deUint32 getNextMultiple (deUint32 divisor, deUint32 value)
96{
97	if (value % divisor == 0)
98	{
99		return value;
100	}
101	return value + divisor - (value % divisor);
102}
103
104/*! Gets the next value that is multiple of all given divisors */
105static deUint32 getNextMultiple (const std::vector<deUint32>& divisors, deUint32 value)
106{
107	deUint32	nextMultiple		= value;
108	bool		nextMultipleFound	= false;
109
110	while (true)
111	{
112		nextMultipleFound = true;
113
114		for (size_t divNdx = 0; divNdx < divisors.size(); divNdx++)
115			nextMultipleFound = nextMultipleFound && (nextMultiple % divisors[divNdx] == 0);
116
117		if (nextMultipleFound)
118			break;
119
120		DE_ASSERT(nextMultiple < ~((deUint32)0u));
121		nextMultiple = getNextMultiple(divisors[0], nextMultiple + 1);
122	}
123
124	return nextMultiple;
125}
126
127} // anonymous
128
129// QuadGrid.
130
131class QuadGrid
132{
133public:
134											QuadGrid				(int									gridSize,
135																	 int									screenWidth,
136																	 int									screenHeight,
137																	 const tcu::Vec4&						constCoords,
138																	 const std::vector<tcu::Mat4>&			userAttribTransforms,
139																	 const std::vector<TextureBindingSp>&	textures);
140											~QuadGrid				(void);
141
142	int										getGridSize				(void) const { return m_gridSize; }
143	int										getNumVertices			(void) const { return m_numVertices; }
144	int										getNumTriangles			(void) const { return m_numTriangles; }
145	const tcu::Vec4&						getConstCoords			(void) const { return m_constCoords; }
146	const std::vector<tcu::Mat4>			getUserAttribTransforms	(void) const { return m_userAttribTransforms; }
147	const std::vector<TextureBindingSp>&	getTextures				(void) const { return m_textures; }
148
149	const tcu::Vec4*						getPositions			(void) const { return &m_positions[0]; }
150	const float*							getAttribOne			(void) const { return &m_attribOne[0]; }
151	const tcu::Vec4*						getCoords				(void) const { return &m_coords[0]; }
152	const tcu::Vec4*						getUnitCoords			(void) const { return &m_unitCoords[0]; }
153
154	const tcu::Vec4*						getUserAttrib			(int attribNdx) const { return &m_userAttribs[attribNdx][0]; }
155	const deUint16*							getIndices				(void) const { return &m_indices[0]; }
156
157	tcu::Vec4								getCoords				(float sx, float sy) const;
158	tcu::Vec4								getUnitCoords			(float sx, float sy) const;
159
160	int										getNumUserAttribs		(void) const { return (int)m_userAttribTransforms.size(); }
161	tcu::Vec4								getUserAttrib			(int attribNdx, float sx, float sy) const;
162
163private:
164	const int								m_gridSize;
165	const int								m_numVertices;
166	const int								m_numTriangles;
167	const tcu::Vec4							m_constCoords;
168	const std::vector<tcu::Mat4>			m_userAttribTransforms;
169
170	const std::vector<TextureBindingSp>&	m_textures;
171
172	std::vector<tcu::Vec4>					m_screenPos;
173	std::vector<tcu::Vec4>					m_positions;
174	std::vector<tcu::Vec4>					m_coords;		//!< Near-unit coordinates, roughly [-2.0 .. 2.0].
175	std::vector<tcu::Vec4>					m_unitCoords;	//!< Positive-only coordinates [0.0 .. 1.5].
176	std::vector<float>						m_attribOne;
177	std::vector<tcu::Vec4>					m_userAttribs[ShaderEvalContext::MAX_TEXTURES];
178	std::vector<deUint16>					m_indices;
179};
180
181QuadGrid::QuadGrid (int										gridSize,
182					int										width,
183					int										height,
184					const tcu::Vec4&						constCoords,
185					const std::vector<tcu::Mat4>&			userAttribTransforms,
186					const std::vector<TextureBindingSp>&	textures)
187	: m_gridSize				(gridSize)
188	, m_numVertices				((gridSize + 1) * (gridSize + 1))
189	, m_numTriangles			(gridSize * gridSize * 2)
190	, m_constCoords				(constCoords)
191	, m_userAttribTransforms	(userAttribTransforms)
192	, m_textures				(textures)
193{
194	const tcu::Vec4 viewportScale	((float)width, (float)height, 0.0f, 0.0f);
195
196	// Compute vertices.
197	m_screenPos.resize(m_numVertices);
198	m_positions.resize(m_numVertices);
199	m_coords.resize(m_numVertices);
200	m_unitCoords.resize(m_numVertices);
201	m_attribOne.resize(m_numVertices);
202
203	// User attributes.
204	for (int attrNdx = 0; attrNdx < DE_LENGTH_OF_ARRAY(m_userAttribs); attrNdx++)
205		m_userAttribs[attrNdx].resize(m_numVertices);
206
207	for (int y = 0; y < gridSize+1; y++)
208	for (int x = 0; x < gridSize+1; x++)
209	{
210		float		sx			= (float)x / (float)gridSize;
211		float		sy			= (float)y / (float)gridSize;
212		float		fx			= 2.0f * sx - 1.0f;
213		float		fy			= 2.0f * sy - 1.0f;
214		int			vtxNdx		= ((y * (gridSize+1)) + x);
215
216		m_positions[vtxNdx]		= tcu::Vec4(fx, fy, 0.0f, 1.0f);
217		m_coords[vtxNdx]		= getCoords(sx, sy);
218		m_unitCoords[vtxNdx]	= getUnitCoords(sx, sy);
219		m_attribOne[vtxNdx]		= 1.0f;
220
221		m_screenPos[vtxNdx]		= tcu::Vec4(sx, sy, 0.0f, 1.0f) * viewportScale;
222
223		for (int attribNdx = 0; attribNdx < getNumUserAttribs(); attribNdx++)
224			m_userAttribs[attribNdx][vtxNdx] = getUserAttrib(attribNdx, sx, sy);
225	}
226
227	// Compute indices.
228	m_indices.resize(3 * m_numTriangles);
229	for (int y = 0; y < gridSize; y++)
230	for (int x = 0; x < gridSize; x++)
231	{
232		int stride				= gridSize + 1;
233		int v00					= (y * stride) + x;
234		int v01					= (y * stride) + x + 1;
235		int v10					= ((y+1) * stride) + x;
236		int v11					= ((y+1) * stride) + x + 1;
237
238		int baseNdx				= ((y * gridSize) + x) * 6;
239		m_indices[baseNdx + 0]	= (deUint16)v10;
240		m_indices[baseNdx + 1]	= (deUint16)v00;
241		m_indices[baseNdx + 2]	= (deUint16)v01;
242
243		m_indices[baseNdx + 3]	= (deUint16)v10;
244		m_indices[baseNdx + 4]	= (deUint16)v01;
245		m_indices[baseNdx + 5]	= (deUint16)v11;
246	}
247}
248
249QuadGrid::~QuadGrid (void)
250{
251}
252
253inline tcu::Vec4 QuadGrid::getCoords (float sx, float sy) const
254{
255	const float fx = 2.0f * sx - 1.0f;
256	const float fy = 2.0f * sy - 1.0f;
257	return tcu::Vec4(fx, fy, -fx + 0.33f*fy, -0.275f*fx - fy);
258}
259
260inline tcu::Vec4 QuadGrid::getUnitCoords (float sx, float sy) const
261{
262	return tcu::Vec4(sx, sy, 0.33f*sx + 0.5f*sy, 0.5f*sx + 0.25f*sy);
263}
264
265inline tcu::Vec4 QuadGrid::getUserAttrib (int attribNdx, float sx, float sy) const
266{
267	// homogeneous normalized screen-space coordinates
268	return m_userAttribTransforms[attribNdx] * tcu::Vec4(sx, sy, 0.0f, 1.0f);
269}
270
271// TextureBinding
272
273TextureBinding::TextureBinding (const tcu::Archive&	archive,
274								const char*			filename,
275								const Type			type,
276								const tcu::Sampler&	sampler)
277	: m_type	(type)
278	, m_sampler	(sampler)
279{
280	switch(m_type)
281	{
282		case TYPE_2D: m_binding.tex2D = loadTexture2D(archive, filename).release(); break;
283		default:
284			DE_FATAL("Unsupported texture type");
285	}
286}
287
288TextureBinding::TextureBinding (const tcu::Texture2D* tex2D, const tcu::Sampler& sampler)
289	: m_type	(TYPE_2D)
290	, m_sampler	(sampler)
291{
292	m_binding.tex2D = tex2D;
293}
294
295TextureBinding::TextureBinding (const tcu::TextureCube* texCube, const tcu::Sampler& sampler)
296	: m_type	(TYPE_CUBE_MAP)
297	, m_sampler	(sampler)
298{
299	m_binding.texCube = texCube;
300}
301
302TextureBinding::TextureBinding (const tcu::Texture2DArray* tex2DArray, const tcu::Sampler& sampler)
303	: m_type	(TYPE_2D_ARRAY)
304	, m_sampler	(sampler)
305{
306	m_binding.tex2DArray = tex2DArray;
307}
308
309TextureBinding::TextureBinding (const tcu::Texture3D* tex3D, const tcu::Sampler& sampler)
310	: m_type	(TYPE_3D)
311	, m_sampler	(sampler)
312{
313	m_binding.tex3D = tex3D;
314}
315
316TextureBinding::~TextureBinding (void)
317{
318	switch(m_type)
319	{
320		case TYPE_2D:			delete m_binding.tex2D;			break;
321		case TYPE_CUBE_MAP:		delete m_binding.texCube;		break;
322		case TYPE_2D_ARRAY:		delete m_binding.tex2DArray;	break;
323		case TYPE_3D:			delete m_binding.tex3D;			break;
324		default:												break;
325	}
326}
327
328de::MovePtr<tcu::Texture2D> TextureBinding::loadTexture2D (const tcu::Archive& archive, const char* filename)
329{
330	tcu::TextureLevel level;
331	tcu::ImageIO::loadImage(level, archive, filename);
332
333	TCU_CHECK_INTERNAL(level.getFormat() == tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8) ||
334					   level.getFormat() == tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8));
335
336	// \todo [2015-10-08 elecro] for some reason we get better when using RGBA texture even in RGB case, this needs to be investigated
337	de::MovePtr<tcu::Texture2D> texture(new tcu::Texture2D(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), level.getWidth(), level.getHeight()));
338
339	// Fill level 0.
340	texture->allocLevel(0);
341	tcu::copy(texture->getLevel(0), level.getAccess());
342
343	return texture;
344}
345
346// ShaderEvalContext.
347
348ShaderEvalContext::ShaderEvalContext (const QuadGrid& quadGrid)
349	: constCoords	(quadGrid.getConstCoords())
350	, isDiscarded	(false)
351	, m_quadGrid	(quadGrid)
352{
353	const std::vector<TextureBindingSp>& bindings = m_quadGrid.getTextures();
354	DE_ASSERT((int)bindings.size() <= MAX_TEXTURES);
355
356	// Fill in texture array.
357	for (int ndx = 0; ndx < (int)bindings.size(); ndx++)
358	{
359		const TextureBinding& binding = *bindings[ndx];
360
361		if (binding.getType() == TextureBinding::TYPE_NONE)
362			continue;
363
364		textures[ndx].sampler = binding.getSampler();
365
366		switch (binding.getType())
367		{
368			case TextureBinding::TYPE_2D:		textures[ndx].tex2D			= &binding.get2D();			break;
369			case TextureBinding::TYPE_CUBE_MAP:	textures[ndx].texCube		= &binding.getCube();		break;
370			case TextureBinding::TYPE_2D_ARRAY:	textures[ndx].tex2DArray	= &binding.get2DArray();	break;
371			case TextureBinding::TYPE_3D:		textures[ndx].tex3D			= &binding.get3D();			break;
372			default:
373				TCU_THROW(InternalError, "Handling of texture binding type not implemented");
374		}
375	}
376}
377
378ShaderEvalContext::~ShaderEvalContext (void)
379{
380}
381
382void ShaderEvalContext::reset (float sx, float sy)
383{
384	// Clear old values
385	color		= tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
386	isDiscarded	= false;
387
388	// Compute coords
389	coords		= m_quadGrid.getCoords(sx, sy);
390	unitCoords	= m_quadGrid.getUnitCoords(sx, sy);
391
392	// Compute user attributes.
393	const int numAttribs = m_quadGrid.getNumUserAttribs();
394	DE_ASSERT(numAttribs <= MAX_USER_ATTRIBS);
395	for (int attribNdx = 0; attribNdx < numAttribs; attribNdx++)
396		in[attribNdx] = m_quadGrid.getUserAttrib(attribNdx, sx, sy);
397}
398
399tcu::Vec4 ShaderEvalContext::texture2D (int unitNdx, const tcu::Vec2& texCoords)
400{
401	if (textures[unitNdx].tex2D)
402		return textures[unitNdx].tex2D->sample(textures[unitNdx].sampler, texCoords.x(), texCoords.y(), 0.0f);
403	else
404		return tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
405}
406
407// ShaderEvaluator.
408
409ShaderEvaluator::ShaderEvaluator (void)
410	: m_evalFunc(DE_NULL)
411{
412}
413
414ShaderEvaluator::ShaderEvaluator (ShaderEvalFunc evalFunc)
415	: m_evalFunc(evalFunc)
416{
417}
418
419ShaderEvaluator::~ShaderEvaluator (void)
420{
421}
422
423void ShaderEvaluator::evaluate (ShaderEvalContext& ctx) const
424{
425	DE_ASSERT(m_evalFunc);
426	m_evalFunc(ctx);
427}
428
429// UniformSetup.
430
431UniformSetup::UniformSetup (void)
432	: m_setupFunc(DE_NULL)
433{
434}
435
436UniformSetup::UniformSetup (UniformSetupFunc setupFunc)
437	: m_setupFunc(setupFunc)
438{
439}
440
441UniformSetup::~UniformSetup (void)
442{
443}
444
445void UniformSetup::setup (ShaderRenderCaseInstance& instance, const tcu::Vec4& constCoords) const
446{
447	if (m_setupFunc)
448		m_setupFunc(instance, constCoords);
449}
450
451// ShaderRenderCase.
452
453ShaderRenderCase::ShaderRenderCase (tcu::TestContext&			testCtx,
454									const std::string&			name,
455									const std::string&			description,
456									const bool					isVertexCase,
457									const ShaderEvalFunc		evalFunc,
458									const UniformSetup*			uniformSetup,
459									const AttributeSetupFunc	attribFunc)
460	: vkt::TestCase		(testCtx, name, description)
461	, m_isVertexCase	(isVertexCase)
462	, m_evaluator		(new ShaderEvaluator(evalFunc))
463	, m_uniformSetup	(uniformSetup ? uniformSetup : new UniformSetup())
464	, m_attribFunc		(attribFunc)
465{}
466
467ShaderRenderCase::ShaderRenderCase (tcu::TestContext&			testCtx,
468									const std::string&			name,
469									const std::string&			description,
470									const bool					isVertexCase,
471									const ShaderEvaluator*		evaluator,
472									const UniformSetup*			uniformSetup,
473									const AttributeSetupFunc	attribFunc)
474	: vkt::TestCase		(testCtx, name, description)
475	, m_isVertexCase	(isVertexCase)
476	, m_evaluator		(evaluator)
477	, m_uniformSetup	(uniformSetup ? uniformSetup : new UniformSetup())
478	, m_attribFunc		(attribFunc)
479{}
480
481ShaderRenderCase::~ShaderRenderCase (void)
482{
483}
484
485void ShaderRenderCase::initPrograms (vk::SourceCollections& programCollection) const
486{
487	programCollection.glslSources.add("vert") << glu::VertexSource(m_vertShaderSource);
488	programCollection.glslSources.add("frag") << glu::FragmentSource(m_fragShaderSource);
489}
490
491TestInstance* ShaderRenderCase::createInstance (Context& context) const
492{
493	DE_ASSERT(m_evaluator != DE_NULL);
494	DE_ASSERT(m_uniformSetup != DE_NULL);
495	return new ShaderRenderCaseInstance(context, m_isVertexCase, *m_evaluator, *m_uniformSetup, m_attribFunc);
496}
497
498// ShaderRenderCaseInstance.
499
500ShaderRenderCaseInstance::ShaderRenderCaseInstance (Context&					context,
501													const bool					isVertexCase,
502													const ShaderEvaluator&		evaluator,
503													const UniformSetup&			uniformSetup,
504													const AttributeSetupFunc	attribFunc)
505	: vkt::TestInstance		(context)
506	, m_memAlloc			(context.getDefaultAllocator())
507	, m_clearColor			(DEFAULT_CLEAR_COLOR)
508	, m_isVertexCase		(isVertexCase)
509	, m_vertexShaderName	("vert")
510	, m_fragmentShaderName	("frag")
511	, m_renderSize			(128, 128)
512	, m_colorFormat			(VK_FORMAT_R8G8B8A8_UNORM)
513	, m_evaluator			(&evaluator)
514	, m_uniformSetup		(&uniformSetup)
515	, m_attribFunc			(attribFunc)
516	, m_sampleCount			(VK_SAMPLE_COUNT_1_BIT)
517{
518}
519
520ShaderRenderCaseInstance::ShaderRenderCaseInstance (Context&					context,
521													const bool					isVertexCase,
522													const ShaderEvaluator*		evaluator,
523													const UniformSetup*			uniformSetup,
524													const AttributeSetupFunc	attribFunc)
525	: vkt::TestInstance		(context)
526	, m_memAlloc			(context.getDefaultAllocator())
527	, m_clearColor			(DEFAULT_CLEAR_COLOR)
528	, m_isVertexCase		(isVertexCase)
529	, m_vertexShaderName	("vert")
530	, m_fragmentShaderName	("frag")
531	, m_renderSize			(128, 128)
532	, m_colorFormat			(VK_FORMAT_R8G8B8A8_UNORM)
533	, m_evaluator			(evaluator)
534	, m_uniformSetup		(uniformSetup)
535	, m_attribFunc			(attribFunc)
536	, m_sampleCount			(VK_SAMPLE_COUNT_1_BIT)
537{
538}
539
540ShaderRenderCaseInstance::~ShaderRenderCaseInstance (void)
541{
542}
543
544tcu::TestStatus ShaderRenderCaseInstance::iterate (void)
545{
546	setup();
547
548	// Create quad grid.
549	const tcu::UVec2	viewportSize	= getViewportSize();
550	const int			width			= viewportSize.x();
551	const int			height			= viewportSize.y();
552
553	m_quadGrid							= de::MovePtr<QuadGrid>(new QuadGrid(m_isVertexCase ? GRID_SIZE : 4, width, height, getDefaultConstCoords(), m_userAttribTransforms, m_textures));
554
555	// Render result.
556	tcu::Surface		resImage		(width, height);
557
558	render(m_quadGrid->getNumVertices(), m_quadGrid->getNumTriangles(), m_quadGrid->getIndices(), m_quadGrid->getConstCoords());
559	tcu::copy(resImage.getAccess(), m_resultImage.getAccess());
560
561	// Compute reference.
562	tcu::Surface		refImage		(width, height);
563	if (m_isVertexCase)
564		computeVertexReference(refImage, *m_quadGrid);
565	else
566		computeFragmentReference(refImage, *m_quadGrid);
567
568	// Compare.
569	const bool			compareOk		= compareImages(resImage, refImage, 0.1f);
570
571	if (compareOk)
572		return tcu::TestStatus::pass("Result image matches reference");
573	else
574		return tcu::TestStatus::fail("Image mismatch");
575}
576
577void ShaderRenderCaseInstance::setup (void)
578{
579	m_resultImage					= tcu::TextureLevel();
580	m_descriptorSetLayoutBuilder	= de::MovePtr<DescriptorSetLayoutBuilder>	(new DescriptorSetLayoutBuilder());
581	m_descriptorPoolBuilder			= de::MovePtr<DescriptorPoolBuilder>		(new DescriptorPoolBuilder());
582	m_descriptorSetUpdateBuilder	= de::MovePtr<DescriptorSetUpdateBuilder>	(new DescriptorSetUpdateBuilder());
583
584	m_uniformInfos.clear();
585	m_vertexBindingDescription.clear();
586	m_vertexAttributeDescription.clear();
587	m_vertexBuffers.clear();
588	m_vertexBufferAllocs.clear();
589}
590
591void ShaderRenderCaseInstance::setupUniformData (deUint32 bindingLocation, size_t size, const void* dataPtr)
592{
593	const VkDevice					vkDevice			= m_context.getDevice();
594	const DeviceInterface&			vk					= m_context.getDeviceInterface();
595	const deUint32					queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
596
597	const VkBufferCreateInfo		uniformBufferParams	=
598	{
599		VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
600		DE_NULL,									// const void*			pNext;
601		0u,											// VkBufferCreateFlags	flags;
602		size,										// VkDeviceSize			size;
603		VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,			// VkBufferUsageFlags	usage;
604		VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
605		1u,											// deUint32				queueFamilyCount;
606		&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
607	};
608
609	Move<VkBuffer>					buffer				= createBuffer(vk, vkDevice, &uniformBufferParams);
610	de::MovePtr<Allocation>			alloc				= m_memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *buffer), MemoryRequirement::HostVisible);
611	VK_CHECK(vk.bindBufferMemory(vkDevice, *buffer, alloc->getMemory(), alloc->getOffset()));
612
613	deMemcpy(alloc->getHostPtr(), dataPtr, size);
614	flushMappedMemoryRange(vk, vkDevice, alloc->getMemory(), alloc->getOffset(), size);
615
616	de::MovePtr<BufferUniform> uniformInfo(new BufferUniform());
617	uniformInfo->type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
618	uniformInfo->descriptor = makeDescriptorBufferInfo(*buffer, 0u, size);
619	uniformInfo->location = bindingLocation;
620	uniformInfo->buffer = VkBufferSp(new vk::Unique<VkBuffer>(buffer));
621	uniformInfo->alloc = AllocationSp(alloc.release());
622
623	m_uniformInfos.push_back(UniformInfoSp(new de::UniquePtr<UniformInfo>(uniformInfo)));
624}
625
626void ShaderRenderCaseInstance::addUniform (deUint32 bindingLocation, vk::VkDescriptorType descriptorType, size_t dataSize, const void* data)
627{
628	m_descriptorSetLayoutBuilder->addSingleBinding(descriptorType, vk::VK_SHADER_STAGE_ALL);
629	m_descriptorPoolBuilder->addType(descriptorType);
630
631	setupUniformData(bindingLocation, dataSize, data);
632}
633
634void ShaderRenderCaseInstance::addAttribute (deUint32		bindingLocation,
635											 vk::VkFormat	format,
636											 deUint32		sizePerElement,
637											 deUint32		count,
638											 const void*	dataPtr)
639{
640	// Add binding specification
641	const deUint32							binding					= (deUint32)m_vertexBindingDescription.size();
642	const VkVertexInputBindingDescription	bindingDescription		=
643	{
644		binding,							// deUint32				binding;
645		sizePerElement,						// deUint32				stride;
646		VK_VERTEX_INPUT_RATE_VERTEX			// VkVertexInputRate	stepRate;
647	};
648
649	m_vertexBindingDescription.push_back(bindingDescription);
650
651	// Add location and format specification
652	const VkVertexInputAttributeDescription	attributeDescription	=
653	{
654		bindingLocation,			// deUint32	location;
655		binding,					// deUint32	binding;
656		format,						// VkFormat	format;
657		0u,							// deUint32	offset;
658	};
659
660	m_vertexAttributeDescription.push_back(attributeDescription);
661
662	// Upload data to buffer
663	const VkDevice							vkDevice				= m_context.getDevice();
664	const DeviceInterface&					vk						= m_context.getDeviceInterface();
665	const deUint32							queueFamilyIndex		= m_context.getUniversalQueueFamilyIndex();
666
667	const VkDeviceSize						inputSize				= sizePerElement * count;
668	const VkBufferCreateInfo				vertexBufferParams		=
669	{
670		VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
671		DE_NULL,									// const void*			pNext;
672		0u,											// VkBufferCreateFlags	flags;
673		inputSize,									// VkDeviceSize			size;
674		VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,			// VkBufferUsageFlags	usage;
675		VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
676		1u,											// deUint32				queueFamilyCount;
677		&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
678	};
679
680	Move<VkBuffer>							buffer					= createBuffer(vk, vkDevice, &vertexBufferParams);
681	de::MovePtr<vk::Allocation>				alloc					= m_memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *buffer), MemoryRequirement::HostVisible);
682	VK_CHECK(vk.bindBufferMemory(vkDevice, *buffer, alloc->getMemory(), alloc->getOffset()));
683
684	deMemcpy(alloc->getHostPtr(), dataPtr, (size_t)inputSize);
685	flushMappedMemoryRange(vk, vkDevice, alloc->getMemory(), alloc->getOffset(), inputSize);
686
687	m_vertexBuffers.push_back(VkBufferSp(new vk::Unique<VkBuffer>(buffer)));
688	m_vertexBufferAllocs.push_back(AllocationSp(alloc.release()));
689}
690
691void ShaderRenderCaseInstance::useAttribute (deUint32 bindingLocation, BaseAttributeType type)
692{
693	const EnabledBaseAttribute attribute =
694	{
695		bindingLocation,	// deUint32				location;
696		type				// BaseAttributeType	type;
697	};
698	m_enabledBaseAttributes.push_back(attribute);
699}
700
701void ShaderRenderCaseInstance::setupUniforms (const tcu::Vec4& constCoords)
702{
703	if (m_uniformSetup)
704		m_uniformSetup->setup(*this, constCoords);
705}
706
707void ShaderRenderCaseInstance::useUniform (deUint32 bindingLocation, BaseUniformType type)
708{
709	#define UNIFORM_CASE(type, value) case type: addUniform(bindingLocation, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, value); break
710
711	switch(type)
712	{
713		// Bool
714		UNIFORM_CASE(UB_FALSE,	0);
715		UNIFORM_CASE(UB_TRUE,	1);
716
717		// BVec4
718		UNIFORM_CASE(UB4_FALSE,	tcu::Vec4(0));
719		UNIFORM_CASE(UB4_TRUE,	tcu::Vec4(1));
720
721		// Integer
722		UNIFORM_CASE(UI_ZERO,	0);
723		UNIFORM_CASE(UI_ONE,	1);
724		UNIFORM_CASE(UI_TWO,	2);
725		UNIFORM_CASE(UI_THREE,	3);
726		UNIFORM_CASE(UI_FOUR,	4);
727		UNIFORM_CASE(UI_FIVE,	5);
728		UNIFORM_CASE(UI_SIX,	6);
729		UNIFORM_CASE(UI_SEVEN,	7);
730		UNIFORM_CASE(UI_EIGHT,	8);
731		UNIFORM_CASE(UI_ONEHUNDREDONE, 101);
732
733		// IVec2
734		UNIFORM_CASE(UI2_MINUS_ONE,	tcu::IVec2(-1));
735		UNIFORM_CASE(UI2_ZERO,		tcu::IVec2(0));
736		UNIFORM_CASE(UI2_ONE,		tcu::IVec2(1));
737		UNIFORM_CASE(UI2_TWO,		tcu::IVec2(2));
738		UNIFORM_CASE(UI2_THREE,		tcu::IVec2(3));
739		UNIFORM_CASE(UI2_FOUR,		tcu::IVec2(4));
740		UNIFORM_CASE(UI2_FIVE,		tcu::IVec2(5));
741
742		// IVec3
743		UNIFORM_CASE(UI3_MINUS_ONE,	tcu::IVec3(-1));
744		UNIFORM_CASE(UI3_ZERO,		tcu::IVec3(0));
745		UNIFORM_CASE(UI3_ONE,		tcu::IVec3(1));
746		UNIFORM_CASE(UI3_TWO,		tcu::IVec3(2));
747		UNIFORM_CASE(UI3_THREE,		tcu::IVec3(3));
748		UNIFORM_CASE(UI3_FOUR,		tcu::IVec3(4));
749		UNIFORM_CASE(UI3_FIVE,		tcu::IVec3(5));
750
751		// IVec4
752		UNIFORM_CASE(UI4_MINUS_ONE, tcu::IVec4(-1));
753		UNIFORM_CASE(UI4_ZERO,		tcu::IVec4(0));
754		UNIFORM_CASE(UI4_ONE,		tcu::IVec4(1));
755		UNIFORM_CASE(UI4_TWO,		tcu::IVec4(2));
756		UNIFORM_CASE(UI4_THREE,		tcu::IVec4(3));
757		UNIFORM_CASE(UI4_FOUR,		tcu::IVec4(4));
758		UNIFORM_CASE(UI4_FIVE,		tcu::IVec4(5));
759
760		// Float
761		UNIFORM_CASE(UF_ZERO,		0.0f);
762		UNIFORM_CASE(UF_ONE,		1.0f);
763		UNIFORM_CASE(UF_TWO,		2.0f);
764		UNIFORM_CASE(UF_THREE,		3.0f);
765		UNIFORM_CASE(UF_FOUR,		4.0f);
766		UNIFORM_CASE(UF_FIVE,		5.0f);
767		UNIFORM_CASE(UF_SIX,		6.0f);
768		UNIFORM_CASE(UF_SEVEN,		7.0f);
769		UNIFORM_CASE(UF_EIGHT,		8.0f);
770
771		UNIFORM_CASE(UF_HALF,		1.0f / 2.0f);
772		UNIFORM_CASE(UF_THIRD,		1.0f / 3.0f);
773		UNIFORM_CASE(UF_FOURTH,		1.0f / 4.0f);
774		UNIFORM_CASE(UF_FIFTH,		1.0f / 5.0f);
775		UNIFORM_CASE(UF_SIXTH,		1.0f / 6.0f);
776		UNIFORM_CASE(UF_SEVENTH,	1.0f / 7.0f);
777		UNIFORM_CASE(UF_EIGHTH,		1.0f / 8.0f);
778
779		// Vec2
780		UNIFORM_CASE(UV2_MINUS_ONE,	tcu::Vec2(-1.0f));
781		UNIFORM_CASE(UV2_ZERO,		tcu::Vec2(0.0f));
782		UNIFORM_CASE(UV2_ONE,		tcu::Vec2(1.0f));
783		UNIFORM_CASE(UV2_TWO,		tcu::Vec2(2.0f));
784		UNIFORM_CASE(UV2_THREE,		tcu::Vec2(3.0f));
785
786		UNIFORM_CASE(UV2_HALF,		tcu::Vec2(1.0f / 2.0f));
787
788		// Vec3
789		UNIFORM_CASE(UV3_MINUS_ONE,	tcu::Vec3(-1.0f));
790		UNIFORM_CASE(UV3_ZERO,		tcu::Vec3(0.0f));
791		UNIFORM_CASE(UV3_ONE,		tcu::Vec3(1.0f));
792		UNIFORM_CASE(UV3_TWO,		tcu::Vec3(2.0f));
793		UNIFORM_CASE(UV3_THREE,		tcu::Vec3(3.0f));
794
795		UNIFORM_CASE(UV3_HALF,		tcu::Vec3(1.0f / 2.0f));
796
797		// Vec4
798		UNIFORM_CASE(UV4_MINUS_ONE,	tcu::Vec4(-1.0f));
799		UNIFORM_CASE(UV4_ZERO,		tcu::Vec4(0.0f));
800		UNIFORM_CASE(UV4_ONE,		tcu::Vec4(1.0f));
801		UNIFORM_CASE(UV4_TWO,		tcu::Vec4(2.0f));
802		UNIFORM_CASE(UV4_THREE,		tcu::Vec4(3.0f));
803
804		UNIFORM_CASE(UV4_HALF,		tcu::Vec4(1.0f / 2.0f));
805
806		UNIFORM_CASE(UV4_BLACK,		tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
807		UNIFORM_CASE(UV4_GRAY,		tcu::Vec4(0.5f, 0.5f, 0.5f, 1.0f));
808		UNIFORM_CASE(UV4_WHITE,		tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
809
810		default:
811			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Unknown Uniform type: " << type << tcu::TestLog::EndMessage;
812			break;
813	}
814
815	#undef UNIFORM_CASE
816}
817
818const tcu::UVec2 ShaderRenderCaseInstance::getViewportSize (void) const
819{
820	return tcu::UVec2(de::min(m_renderSize.x(), MAX_RENDER_WIDTH),
821					  de::min(m_renderSize.y(), MAX_RENDER_HEIGHT));
822}
823
824void ShaderRenderCaseInstance::setSampleCount (VkSampleCountFlagBits sampleCount)
825{
826	m_sampleCount	= sampleCount;
827}
828
829bool ShaderRenderCaseInstance::isMultiSampling (void) const
830{
831	return m_sampleCount != VK_SAMPLE_COUNT_1_BIT;
832}
833
834void ShaderRenderCaseInstance::uploadImage (const tcu::TextureFormat&			texFormat,
835											const TextureData&					textureData,
836											const tcu::Sampler&					refSampler,
837											deUint32							mipLevels,
838											deUint32							arrayLayers,
839											VkImage								destImage)
840{
841	const VkDevice					vkDevice				= m_context.getDevice();
842	const DeviceInterface&			vk						= m_context.getDeviceInterface();
843	const VkQueue					queue					= m_context.getUniversalQueue();
844	const deUint32					queueFamilyIndex		= m_context.getUniversalQueueFamilyIndex();
845
846	const bool						isShadowSampler			= refSampler.compare != tcu::Sampler::COMPAREMODE_NONE;
847	const VkImageAspectFlags		aspectMask				= isShadowSampler ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT;
848	deUint32						bufferSize				= 0u;
849	Move<VkBuffer>					buffer;
850	de::MovePtr<Allocation>			bufferAlloc;
851	Move<VkCommandPool>				cmdPool;
852	Move<VkCommandBuffer>			cmdBuffer;
853	Move<VkFence>					fence;
854	std::vector<VkBufferImageCopy>	copyRegions;
855	std::vector<deUint32>			offsetMultiples;
856
857	offsetMultiples.push_back(4u);
858	offsetMultiples.push_back(texFormat.getPixelSize());
859
860	// Calculate buffer size
861	for (TextureData::const_iterator mit = textureData.begin(); mit != textureData.end(); ++mit)
862	{
863		for (TextureLayerData::const_iterator lit = mit->begin(); lit != mit->end(); ++lit)
864		{
865			const tcu::ConstPixelBufferAccess&	access	= *lit;
866
867			bufferSize = getNextMultiple(offsetMultiples, bufferSize);
868			bufferSize += access.getWidth() * access.getHeight() * access.getDepth() * access.getFormat().getPixelSize();
869		}
870	}
871
872	// Create source buffer
873	{
874		const VkBufferCreateInfo bufferParams =
875		{
876			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
877			DE_NULL,									// const void*			pNext;
878			0u,											// VkBufferCreateFlags	flags;
879			bufferSize,									// VkDeviceSize			size;
880			VK_BUFFER_USAGE_TRANSFER_SRC_BIT,			// VkBufferUsageFlags	usage;
881			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
882			0u,											// deUint32				queueFamilyIndexCount;
883			DE_NULL,									// const deUint32*		pQueueFamilyIndices;
884		};
885
886		buffer		= createBuffer(vk, vkDevice, &bufferParams);
887		bufferAlloc = m_memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *buffer), MemoryRequirement::HostVisible);
888		VK_CHECK(vk.bindBufferMemory(vkDevice, *buffer, bufferAlloc->getMemory(), bufferAlloc->getOffset()));
889	}
890
891	// Create command pool and buffer
892	{
893		const VkCommandPoolCreateInfo cmdPoolParams =
894		{
895			VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,		// VkStructureType			sType;
896			DE_NULL,										// const void*				pNext;
897			VK_COMMAND_POOL_CREATE_TRANSIENT_BIT,			// VkCommandPoolCreateFlags	flags;
898			queueFamilyIndex,								// deUint32					queueFamilyIndex;
899		};
900
901		cmdPool = createCommandPool(vk, vkDevice, &cmdPoolParams);
902
903		const VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
904		{
905			VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,	// VkStructureType			sType;
906			DE_NULL,										// const void*				pNext;
907			*cmdPool,										// VkCommandPool			commandPool;
908			VK_COMMAND_BUFFER_LEVEL_PRIMARY,				// VkCommandBufferLevel		level;
909			1u,												// deUint32					bufferCount;
910		};
911
912		cmdBuffer = allocateCommandBuffer(vk, vkDevice, &cmdBufferAllocateInfo);
913	}
914
915	// Create fence
916	{
917		const VkFenceCreateInfo fenceParams =
918		{
919			VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,		// VkStructureType		sType;
920			DE_NULL,									// const void*			pNext;
921			0u											// VkFenceCreateFlags	flags;
922		};
923
924		fence = createFence(vk, vkDevice, &fenceParams);
925	}
926
927	// Barriers for copying buffer to image
928	const VkBufferMemoryBarrier preBufferBarrier =
929	{
930		VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	// VkStructureType	sType;
931		DE_NULL,									// const void*		pNext;
932		VK_ACCESS_HOST_WRITE_BIT,					// VkAccessFlags	srcAccessMask;
933		VK_ACCESS_TRANSFER_READ_BIT,				// VkAccessFlags	dstAccessMask;
934		VK_QUEUE_FAMILY_IGNORED,					// deUint32			srcQueueFamilyIndex;
935		VK_QUEUE_FAMILY_IGNORED,					// deUint32			dstQueueFamilyIndex;
936		*buffer,									// VkBuffer			buffer;
937		0u,											// VkDeviceSize		offset;
938		bufferSize									// VkDeviceSize		size;
939	};
940
941	const VkImageMemoryBarrier preImageBarrier =
942	{
943		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType			sType;
944		DE_NULL,										// const void*				pNext;
945		0u,												// VkAccessFlags			srcAccessMask;
946		VK_ACCESS_TRANSFER_WRITE_BIT,					// VkAccessFlags			dstAccessMask;
947		VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout			oldLayout;
948		VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,			// VkImageLayout			newLayout;
949		VK_QUEUE_FAMILY_IGNORED,						// deUint32					srcQueueFamilyIndex;
950		VK_QUEUE_FAMILY_IGNORED,						// deUint32					dstQueueFamilyIndex;
951		destImage,										// VkImage					image;
952		{												// VkImageSubresourceRange	subresourceRange;
953			aspectMask,								// VkImageAspect	aspect;
954			0u,										// deUint32			baseMipLevel;
955			mipLevels,								// deUint32			mipLevels;
956			0u,										// deUint32			baseArraySlice;
957			arrayLayers								// deUint32			arraySize;
958		}
959	};
960
961	const VkImageMemoryBarrier postImageBarrier =
962	{
963		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType			sType;
964		DE_NULL,										// const void*				pNext;
965		VK_ACCESS_TRANSFER_WRITE_BIT,					// VkAccessFlags			srcAccessMask;
966		VK_ACCESS_SHADER_READ_BIT,						// VkAccessFlags			dstAccessMask;
967		VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,			// VkImageLayout			oldLayout;
968		VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,		// VkImageLayout			newLayout;
969		VK_QUEUE_FAMILY_IGNORED,						// deUint32					srcQueueFamilyIndex;
970		VK_QUEUE_FAMILY_IGNORED,						// deUint32					dstQueueFamilyIndex;
971		destImage,										// VkImage					image;
972		{												// VkImageSubresourceRange	subresourceRange;
973			aspectMask,								// VkImageAspect	aspect;
974			0u,										// deUint32			baseMipLevel;
975			mipLevels,								// deUint32			mipLevels;
976			0u,										// deUint32			baseArraySlice;
977			arrayLayers								// deUint32			arraySize;
978		}
979	};
980
981	const VkCommandBufferBeginInfo cmdBufferBeginInfo =
982	{
983		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,	// VkStructureType					sType;
984		DE_NULL,										// const void*						pNext;
985		VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,	// VkCommandBufferUsageFlags		flags;
986		(const VkCommandBufferInheritanceInfo*)DE_NULL,
987	};
988
989	// Get copy regions and write buffer data
990	{
991		deUint32	layerDataOffset		= 0;
992		deUint8*	destPtr				= (deUint8*)bufferAlloc->getHostPtr();
993
994		for (size_t levelNdx = 0; levelNdx < textureData.size(); levelNdx++)
995		{
996			const TextureLayerData&		layerData	= textureData[levelNdx];
997
998			for (size_t layerNdx = 0; layerNdx < layerData.size(); layerNdx++)
999			{
1000				layerDataOffset = getNextMultiple(offsetMultiples, layerDataOffset);
1001
1002				const tcu::ConstPixelBufferAccess&	access		= layerData[layerNdx];
1003				const tcu::PixelBufferAccess		destAccess	(access.getFormat(), access.getSize(), destPtr + layerDataOffset);
1004
1005				const VkBufferImageCopy				layerRegion =
1006				{
1007					layerDataOffset,						// VkDeviceSize				bufferOffset;
1008					(deUint32)access.getWidth(),			// deUint32					bufferRowLength;
1009					(deUint32)access.getHeight(),			// deUint32					bufferImageHeight;
1010					{										// VkImageSubresourceLayers	imageSubresource;
1011						aspectMask,								// VkImageAspectFlags		aspectMask;
1012						(deUint32)levelNdx,						// uint32_t					mipLevel;
1013						(deUint32)layerNdx,						// uint32_t					baseArrayLayer;
1014						1u										// uint32_t					layerCount;
1015					},
1016					{ 0u, 0u, 0u },							// VkOffset3D			imageOffset;
1017					{										// VkExtent3D			imageExtent;
1018						(deUint32)access.getWidth(),
1019						(deUint32)access.getHeight(),
1020						(deUint32)access.getDepth()
1021					}
1022				};
1023
1024				copyRegions.push_back(layerRegion);
1025				tcu::copy(destAccess, access);
1026
1027				layerDataOffset += access.getWidth() * access.getHeight() * access.getDepth() * access.getFormat().getPixelSize();
1028			}
1029		}
1030	}
1031
1032	flushMappedMemoryRange(vk, vkDevice, bufferAlloc->getMemory(), bufferAlloc->getOffset(), bufferSize);
1033
1034	// Copy buffer to image
1035	VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufferBeginInfo));
1036	vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &preBufferBarrier, 1, &preImageBarrier);
1037	vk.cmdCopyBufferToImage(*cmdBuffer, *buffer, destImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, (deUint32)copyRegions.size(), copyRegions.data());
1038	vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &postImageBarrier);
1039	VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1040
1041	const VkSubmitInfo submitInfo =
1042	{
1043		VK_STRUCTURE_TYPE_SUBMIT_INFO,	// VkStructureType				sType;
1044		DE_NULL,						// const void*					pNext;
1045		0u,								// deUint32						waitSemaphoreCount;
1046		DE_NULL,						// const VkSemaphore*			pWaitSemaphores;
1047		DE_NULL,						// const VkPipelineStageFlags*	pWaitDstStageMask;
1048		1u,								// deUint32						commandBufferCount;
1049		&cmdBuffer.get(),				// const VkCommandBuffer*		pCommandBuffers;
1050		0u,								// deUint32						signalSemaphoreCount;
1051		DE_NULL							// const VkSemaphore*			pSignalSemaphores;
1052	};
1053
1054	VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *fence));
1055	VK_CHECK(vk.waitForFences(vkDevice, 1, &fence.get(), true, ~(0ull) /* infinity */));
1056}
1057
1058void ShaderRenderCaseInstance::useSampler (deUint32 bindingLocation, deUint32 textureId)
1059{
1060	DE_ASSERT(textureId < m_textures.size());
1061
1062	const TextureBinding&				textureBinding		= *m_textures[textureId];
1063	const TextureBinding::Type			textureType			= textureBinding.getType();
1064	const tcu::Sampler&					refSampler			= textureBinding.getSampler();
1065	const TextureBinding::Parameters&	textureParams		= textureBinding.getParameters();
1066	deUint32							mipLevels			= 1u;
1067	deUint32							arrayLayers			= 1u;
1068	tcu::TextureFormat					texFormat;
1069	tcu::IVec3							texSize;
1070	TextureData							textureData;
1071
1072	if (textureType == TextureBinding::TYPE_2D)
1073	{
1074		const tcu::Texture2D&			texture		= textureBinding.get2D();
1075
1076		texFormat									= texture.getFormat();
1077		texSize										= tcu::IVec3(texture.getWidth(), texture.getHeight(), 1u);
1078		mipLevels									= (deUint32)texture.getNumLevels();
1079		arrayLayers									= 1u;
1080
1081		textureData.resize(mipLevels);
1082
1083		for (deUint32 level = 0; level < mipLevels; ++level)
1084		{
1085			if (texture.isLevelEmpty(level))
1086				continue;
1087
1088			textureData[level].push_back(texture.getLevel(level));
1089		}
1090	}
1091	else if (textureType == TextureBinding::TYPE_CUBE_MAP)
1092	{
1093		const tcu::TextureCube&			texture		= textureBinding.getCube();
1094
1095		texFormat									= texture.getFormat();
1096		texSize										= tcu::IVec3(texture.getSize(), texture.getSize(), 1u);
1097		mipLevels									= (deUint32)texture.getNumLevels();
1098		arrayLayers									= 6u;
1099
1100		static const tcu::CubeFace		cubeFaceMapping[tcu::CUBEFACE_LAST] =
1101		{
1102			tcu::CUBEFACE_POSITIVE_X,
1103			tcu::CUBEFACE_NEGATIVE_X,
1104			tcu::CUBEFACE_POSITIVE_Y,
1105			tcu::CUBEFACE_NEGATIVE_Y,
1106			tcu::CUBEFACE_POSITIVE_Z,
1107			tcu::CUBEFACE_NEGATIVE_Z
1108		};
1109
1110		textureData.resize(mipLevels);
1111
1112		for (deUint32 level = 0; level < mipLevels; ++level)
1113		{
1114			for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; ++faceNdx)
1115			{
1116				tcu::CubeFace face = cubeFaceMapping[faceNdx];
1117
1118				if (texture.isLevelEmpty(face, level))
1119					continue;
1120
1121				textureData[level].push_back(texture.getLevelFace(level, face));
1122
1123			}
1124		}
1125	}
1126	else if (textureType == TextureBinding::TYPE_2D_ARRAY)
1127	{
1128		const tcu::Texture2DArray&		texture		= textureBinding.get2DArray();
1129
1130		texFormat									= texture.getFormat();
1131		texSize										= tcu::IVec3(texture.getWidth(), texture.getHeight(), 1u);
1132		mipLevels									= (deUint32)texture.getNumLevels();
1133		arrayLayers									= (deUint32)texture.getNumLayers();
1134
1135		textureData.resize(mipLevels);
1136
1137		for (deUint32 level = 0; level < mipLevels; ++level)
1138		{
1139			if (texture.isLevelEmpty(level))
1140				continue;
1141
1142			const tcu::ConstPixelBufferAccess&	levelLayers		= texture.getLevel(level);
1143			const deUint32						layerSize		= levelLayers.getWidth() * levelLayers.getHeight() * levelLayers.getFormat().getPixelSize();
1144
1145			for (deUint32 layer = 0; layer < arrayLayers; ++layer)
1146			{
1147				const deUint32					layerOffset		= layerSize * layer;
1148				tcu::ConstPixelBufferAccess		layerData		(levelLayers.getFormat(), levelLayers.getWidth(), levelLayers.getHeight(), 1, (deUint8*)levelLayers.getDataPtr() + layerOffset);
1149				textureData[level].push_back(layerData);
1150			}
1151		}
1152	}
1153	else if (textureType == TextureBinding::TYPE_3D)
1154	{
1155		const tcu::Texture3D&			texture		= textureBinding.get3D();
1156
1157		texFormat									= texture.getFormat();
1158		texSize										= tcu::IVec3(texture.getWidth(), texture.getHeight(), texture.getDepth());
1159		mipLevels									= (deUint32)texture.getNumLevels();
1160		arrayLayers									= 1u;
1161
1162		textureData.resize(mipLevels);
1163
1164		for (deUint32 level = 0; level < mipLevels; ++level)
1165		{
1166			if (texture.isLevelEmpty(level))
1167				continue;
1168
1169			textureData[level].push_back(texture.getLevel(level));
1170		}
1171	}
1172	else
1173	{
1174		TCU_THROW(InternalError, "Invalid texture type");
1175	}
1176
1177	createSamplerUniform(bindingLocation, textureType, texFormat, texSize, textureData, refSampler, mipLevels, arrayLayers, textureParams);
1178}
1179
1180void ShaderRenderCaseInstance::createSamplerUniform (deUint32						bindingLocation,
1181													 TextureBinding::Type			textureType,
1182													 const tcu::TextureFormat&		texFormat,
1183													 const tcu::IVec3				texSize,
1184													 const TextureData&				textureData,
1185													 const tcu::Sampler&			refSampler,
1186													 deUint32						mipLevels,
1187													 deUint32						arrayLayers,
1188													 TextureBinding::Parameters		textureParams)
1189{
1190	const VkDevice					vkDevice			= m_context.getDevice();
1191	const DeviceInterface&			vk					= m_context.getDeviceInterface();
1192	const deUint32					queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
1193
1194	const bool						isShadowSampler		= refSampler.compare != tcu::Sampler::COMPAREMODE_NONE;
1195	const VkImageAspectFlags		aspectMask			= isShadowSampler ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT;
1196	const VkImageViewType			imageViewType		= textureTypeToImageViewType(textureType);
1197	const VkImageType				imageType			= viewTypeToImageType(imageViewType);
1198	const VkFormat					format				= mapTextureFormat(texFormat);
1199	const bool						isCube				= imageViewType == VK_IMAGE_VIEW_TYPE_CUBE || imageViewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
1200	const VkImageCreateFlags		imageCreateFlags	= isCube ? (VkImageCreateFlags)VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : (VkImageCreateFlags)0;
1201	VkImageUsageFlags				imageUsageFlags		= VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
1202	Move<VkImage>					vkTexture;
1203	de::MovePtr<Allocation>			allocation;
1204
1205	if (isShadowSampler)
1206		imageUsageFlags |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
1207
1208	// Create image
1209	const VkImageCreateInfo			imageParams =
1210	{
1211		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,							// VkStructureType			sType;
1212		DE_NULL,														// const void*				pNext;
1213		imageCreateFlags,												// VkImageCreateFlags		flags;
1214		imageType,														// VkImageType				imageType;
1215		format,															// VkFormat					format;
1216		{																// VkExtent3D				extent;
1217			(deUint32)texSize.x(),
1218			(deUint32)texSize.y(),
1219			(deUint32)texSize.z()
1220		},
1221		mipLevels,														// deUint32					mipLevels;
1222		arrayLayers,													// deUint32					arrayLayers;
1223		VK_SAMPLE_COUNT_1_BIT,											// VkSampleCountFlagBits	samples;
1224		VK_IMAGE_TILING_OPTIMAL,										// VkImageTiling			tiling;
1225		imageUsageFlags,												// VkImageUsageFlags		usage;
1226		VK_SHARING_MODE_EXCLUSIVE,										// VkSharingMode			sharingMode;
1227		1u,																// deUint32					queueFamilyIndexCount;
1228		&queueFamilyIndex,												// const deUint32*			pQueueFamilyIndices;
1229		VK_IMAGE_LAYOUT_UNDEFINED										// VkImageLayout			initialLayout;
1230	};
1231
1232	vkTexture		= createImage(vk, vkDevice, &imageParams);
1233	allocation		= m_memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *vkTexture), MemoryRequirement::Any);
1234	VK_CHECK(vk.bindImageMemory(vkDevice, *vkTexture, allocation->getMemory(), allocation->getOffset()));
1235
1236	// Upload texture data
1237	uploadImage(texFormat, textureData, refSampler, mipLevels, arrayLayers, *vkTexture);
1238
1239	// Create sampler
1240	const VkSamplerCreateInfo		samplerParams	= mapSampler(refSampler, texFormat);
1241	Move<VkSampler>					sampler			= createSampler(vk, vkDevice, &samplerParams);
1242	const deUint32					baseMipLevel	= textureParams.baseMipLevel;
1243	const vk::VkComponentMapping	components		= textureParams.componentMapping;
1244	const VkImageViewCreateInfo		viewParams		=
1245	{
1246		VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,	// VkStructureType			sType;
1247		NULL,										// const voide*				pNext;
1248		0u,											// VkImageViewCreateFlags	flags;
1249		*vkTexture,									// VkImage					image;
1250		imageViewType,								// VkImageViewType			viewType;
1251		format,										// VkFormat					format;
1252		components,									// VkChannelMapping			channels;
1253		{
1254			aspectMask,						// VkImageAspectFlags	aspectMask;
1255			baseMipLevel,					// deUint32				baseMipLevel;
1256			mipLevels - baseMipLevel,		// deUint32				mipLevels;
1257			0,								// deUint32				baseArraySlice;
1258			arrayLayers						// deUint32				arraySize;
1259		},											// VkImageSubresourceRange	subresourceRange;
1260	};
1261
1262	Move<VkImageView>				imageView		= createImageView(vk, vkDevice, &viewParams);
1263
1264	const vk::VkDescriptorImageInfo	descriptor		=
1265	{
1266		sampler.get(),								// VkSampler				sampler;
1267		imageView.get(),							// VkImageView				imageView;
1268		VK_IMAGE_LAYOUT_GENERAL,					// VkImageLayout			imageLayout;
1269	};
1270
1271	de::MovePtr<SamplerUniform> uniform(new SamplerUniform());
1272	uniform->type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
1273	uniform->descriptor = descriptor;
1274	uniform->location = bindingLocation;
1275	uniform->image = VkImageSp(new vk::Unique<VkImage>(vkTexture));
1276	uniform->imageView = VkImageViewSp(new vk::Unique<VkImageView>(imageView));
1277	uniform->sampler = VkSamplerSp(new vk::Unique<VkSampler>(sampler));
1278	uniform->alloc = AllocationSp(allocation.release());
1279
1280	m_descriptorSetLayoutBuilder->addSingleSamplerBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, vk::VK_SHADER_STAGE_ALL, DE_NULL);
1281	m_descriptorPoolBuilder->addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
1282
1283	m_uniformInfos.push_back(UniformInfoSp(new de::UniquePtr<UniformInfo>(uniform)));
1284}
1285
1286void ShaderRenderCaseInstance::setupDefaultInputs (void)
1287{
1288	/* Configuration of the vertex input attributes:
1289		a_position   is at location 0
1290		a_coords     is at location 1
1291		a_unitCoords is at location 2
1292		a_one        is at location 3
1293
1294	  User attributes starts from at the location 4.
1295	*/
1296
1297	DE_ASSERT(m_quadGrid);
1298	const QuadGrid&		quadGrid	= *m_quadGrid;
1299
1300	addAttribute(0u, VK_FORMAT_R32G32B32A32_SFLOAT, sizeof(tcu::Vec4), quadGrid.getNumVertices(), quadGrid.getPositions());
1301	addAttribute(1u, VK_FORMAT_R32G32B32A32_SFLOAT, sizeof(tcu::Vec4), quadGrid.getNumVertices(), quadGrid.getCoords());
1302	addAttribute(2u, VK_FORMAT_R32G32B32A32_SFLOAT, sizeof(tcu::Vec4), quadGrid.getNumVertices(), quadGrid.getUnitCoords());
1303	addAttribute(3u, VK_FORMAT_R32_SFLOAT, sizeof(float), quadGrid.getNumVertices(), quadGrid.getAttribOne());
1304
1305	static const struct
1306	{
1307		BaseAttributeType	type;
1308		int					userNdx;
1309	} userAttributes[] =
1310	{
1311		{ A_IN0, 0 },
1312		{ A_IN1, 1 },
1313		{ A_IN2, 2 },
1314		{ A_IN3, 3 }
1315	};
1316
1317	static const struct
1318	{
1319		BaseAttributeType	matrixType;
1320		int					numCols;
1321		int					numRows;
1322	} matrices[] =
1323	{
1324		{ MAT2,		2, 2 },
1325		{ MAT2x3,	2, 3 },
1326		{ MAT2x4,	2, 4 },
1327		{ MAT3x2,	3, 2 },
1328		{ MAT3,		3, 3 },
1329		{ MAT3x4,	3, 4 },
1330		{ MAT4x2,	4, 2 },
1331		{ MAT4x3,	4, 3 },
1332		{ MAT4,		4, 4 }
1333	};
1334
1335	for (size_t attrNdx = 0; attrNdx < m_enabledBaseAttributes.size(); attrNdx++)
1336	{
1337		for (int userNdx = 0; userNdx < DE_LENGTH_OF_ARRAY(userAttributes); userNdx++)
1338		{
1339			if (userAttributes[userNdx].type != m_enabledBaseAttributes[attrNdx].type)
1340				continue;
1341
1342			addAttribute(m_enabledBaseAttributes[attrNdx].location, VK_FORMAT_R32G32B32A32_SFLOAT, sizeof(tcu::Vec4), quadGrid.getNumVertices(), quadGrid.getUserAttrib(userNdx));
1343		}
1344
1345		for (int matNdx = 0; matNdx < DE_LENGTH_OF_ARRAY(matrices); matNdx++)
1346		{
1347
1348			if (matrices[matNdx].matrixType != m_enabledBaseAttributes[attrNdx].type)
1349				continue;
1350
1351			const int numCols = matrices[matNdx].numCols;
1352
1353			for (int colNdx = 0; colNdx < numCols; colNdx++)
1354			{
1355				addAttribute(m_enabledBaseAttributes[attrNdx].location + colNdx, VK_FORMAT_R32G32B32A32_SFLOAT, (deUint32)(4 * sizeof(float)), quadGrid.getNumVertices(), quadGrid.getUserAttrib(colNdx));
1356			}
1357		}
1358	}
1359}
1360
1361void ShaderRenderCaseInstance::render (deUint32				numVertices,
1362									   deUint32				numTriangles,
1363									   const deUint16*		indices,
1364									   const tcu::Vec4&		constCoords)
1365{
1366	const VkDevice										vkDevice					= m_context.getDevice();
1367	const DeviceInterface&								vk							= m_context.getDeviceInterface();
1368	const VkQueue										queue						= m_context.getUniversalQueue();
1369	const deUint32										queueFamilyIndex			= m_context.getUniversalQueueFamilyIndex();
1370
1371	vk::Move<vk::VkImage>								colorImage;
1372	de::MovePtr<vk::Allocation>							colorImageAlloc;
1373	vk::Move<vk::VkImageView>							colorImageView;
1374	vk::Move<vk::VkImage>								resolvedImage;
1375	de::MovePtr<vk::Allocation>							resolvedImageAlloc;
1376	vk::Move<vk::VkImageView>							resolvedImageView;
1377	vk::Move<vk::VkRenderPass>							renderPass;
1378	vk::Move<vk::VkFramebuffer>							framebuffer;
1379	vk::Move<vk::VkPipelineLayout>						pipelineLayout;
1380	vk::Move<vk::VkPipeline>							graphicsPipeline;
1381	vk::Move<vk::VkShaderModule>						vertexShaderModule;
1382	vk::Move<vk::VkShaderModule>						fragmentShaderModule;
1383	vk::Move<vk::VkBuffer>								indiceBuffer;
1384	de::MovePtr<vk::Allocation>							indiceBufferAlloc;
1385	vk::Move<vk::VkDescriptorSetLayout>					descriptorSetLayout;
1386	vk::Move<vk::VkDescriptorPool>						descriptorPool;
1387	vk::Move<vk::VkDescriptorSet>						descriptorSet;
1388	vk::Move<vk::VkCommandPool>							cmdPool;
1389	vk::Move<vk::VkCommandBuffer>						cmdBuffer;
1390	vk::Move<vk::VkFence>								fence;
1391
1392	// Create color image
1393	{
1394		const VkImageCreateInfo							colorImageParams			=
1395		{
1396			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,										// VkStructureType		sType;
1397			DE_NULL,																	// const void*			pNext;
1398			0u,																			// VkImageCreateFlags	flags;
1399			VK_IMAGE_TYPE_2D,															// VkImageType			imageType;
1400			m_colorFormat,																// VkFormat				format;
1401			{ m_renderSize.x(), m_renderSize.y(), 1u },									// VkExtent3D			extent;
1402			1u,																			// deUint32				mipLevels;
1403			1u,																			// deUint32				arraySize;
1404			m_sampleCount,																// deUint32				samples;
1405			VK_IMAGE_TILING_OPTIMAL,													// VkImageTiling		tiling;
1406			VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,		// VkImageUsageFlags	usage;
1407			VK_SHARING_MODE_EXCLUSIVE,													// VkSharingMode		sharingMode;
1408			1u,																			// deUint32				queueFamilyCount;
1409			&queueFamilyIndex,															// const deUint32*		pQueueFamilyIndices;
1410			VK_IMAGE_LAYOUT_UNDEFINED,													// VkImageLayout		initialLayout;
1411		};
1412
1413		colorImage = createImage(vk, vkDevice, &colorImageParams);
1414
1415		// Allocate and bind color image memory
1416		colorImageAlloc = m_memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *colorImage), MemoryRequirement::Any);
1417		VK_CHECK(vk.bindImageMemory(vkDevice, *colorImage, colorImageAlloc->getMemory(), colorImageAlloc->getOffset()));
1418	}
1419
1420	// Create color attachment view
1421	{
1422		const VkImageViewCreateInfo						colorImageViewParams		=
1423		{
1424			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,			// VkStructureType			sType;
1425			DE_NULL,											// const void*				pNext;
1426			0u,													// VkImageViewCreateFlags	flags;
1427			*colorImage,										// VkImage					image;
1428			VK_IMAGE_VIEW_TYPE_2D,								// VkImageViewType			viewType;
1429			m_colorFormat,										// VkFormat					format;
1430			{
1431				VK_COMPONENT_SWIZZLE_R,			// VkChannelSwizzle		r;
1432				VK_COMPONENT_SWIZZLE_G,			// VkChannelSwizzle		g;
1433				VK_COMPONENT_SWIZZLE_B,			// VkChannelSwizzle		b;
1434				VK_COMPONENT_SWIZZLE_A			// VkChannelSwizzle		a;
1435			},													// VkChannelMapping			channels;
1436			{
1437				VK_IMAGE_ASPECT_COLOR_BIT,		// VkImageAspectFlags	aspectMask;
1438				0,								// deUint32				baseMipLevel;
1439				1,								// deUint32				mipLevels;
1440				0,								// deUint32				baseArraySlice;
1441				1								// deUint32				arraySize;
1442			},													// VkImageSubresourceRange	subresourceRange;
1443		};
1444
1445		colorImageView = createImageView(vk, vkDevice, &colorImageViewParams);
1446	}
1447
1448	if (isMultiSampling())
1449	{
1450		// Resolved Image
1451		{
1452			const VkImageUsageFlags	imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
1453			VkImageFormatProperties	properties;
1454
1455			if ((m_context.getInstanceInterface().getPhysicalDeviceImageFormatProperties(m_context.getPhysicalDevice(),
1456																						 m_colorFormat,
1457																						 VK_IMAGE_TYPE_2D,
1458																						 VK_IMAGE_TILING_OPTIMAL,
1459																						 imageUsage,
1460																						 0,
1461																						 &properties) == VK_ERROR_FORMAT_NOT_SUPPORTED))
1462			{
1463				TCU_THROW(NotSupportedError, "Format not supported");
1464			}
1465
1466			const VkImageCreateInfo					imageCreateInfo			=
1467			{
1468				VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,		// VkStructureType			sType;
1469				DE_NULL,									// const void*				pNext;
1470				0u,											// VkImageCreateFlags		flags;
1471				VK_IMAGE_TYPE_2D,							// VkImageType				imageType;
1472				m_colorFormat,								// VkFormat					format;
1473				{ m_renderSize.x(),	m_renderSize.y(), 1u },	// VkExtent3D				extent;
1474				1u,											// deUint32					mipLevels;
1475				1u,											// deUint32					arrayLayers;
1476				VK_SAMPLE_COUNT_1_BIT,						// VkSampleCountFlagBits	samples;
1477				VK_IMAGE_TILING_OPTIMAL,					// VkImageTiling			tiling;
1478				imageUsage,									// VkImageUsageFlags		usage;
1479				VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode			sharingMode;
1480				1u,											// deUint32					queueFamilyIndexCount;
1481				&queueFamilyIndex,							// const deUint32*			pQueueFamilyIndices;
1482				VK_IMAGE_LAYOUT_UNDEFINED					// VkImageLayout			initialLayout;
1483			};
1484
1485			resolvedImage		= vk::createImage(vk, vkDevice, &imageCreateInfo, DE_NULL);
1486			resolvedImageAlloc	= m_memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *resolvedImage), MemoryRequirement::Any);
1487			VK_CHECK(vk.bindImageMemory(vkDevice, *resolvedImage, resolvedImageAlloc->getMemory(), resolvedImageAlloc->getOffset()));
1488		}
1489
1490		// Resolved Image View
1491		{
1492			const VkImageViewCreateInfo				imageViewCreateInfo		=
1493			{
1494				VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,	// VkStructureType				sType;
1495				DE_NULL,									// const void*					pNext;
1496				0u,											// VkImageViewCreateFlags		flags;
1497				*resolvedImage,								// VkImage						image;
1498				VK_IMAGE_VIEW_TYPE_2D,						// VkImageViewType				viewType;
1499				m_colorFormat,								// VkFormat						format;
1500				{
1501					VK_COMPONENT_SWIZZLE_R,					// VkChannelSwizzle		r;
1502					VK_COMPONENT_SWIZZLE_G,					// VkChannelSwizzle		g;
1503					VK_COMPONENT_SWIZZLE_B,					// VkChannelSwizzle		b;
1504					VK_COMPONENT_SWIZZLE_A					// VkChannelSwizzle		a;
1505				},
1506				{
1507					VK_IMAGE_ASPECT_COLOR_BIT,					// VkImageAspectFlags			aspectMask;
1508					0u,											// deUint32						baseMipLevel;
1509					1u,											// deUint32						mipLevels;
1510					0u,											// deUint32						baseArrayLayer;
1511					1u,											// deUint32						arraySize;
1512				},											// VkImageSubresourceRange		subresourceRange;
1513			};
1514
1515			resolvedImageView = vk::createImageView(vk, vkDevice, &imageViewCreateInfo, DE_NULL);
1516		}
1517	}
1518
1519	// Create render pass
1520	{
1521		const VkAttachmentDescription					attachmentDescription[]		=
1522		{
1523			{
1524				(VkAttachmentDescriptionFlags)0,					// VkAttachmentDescriptionFlags		flags;
1525				m_colorFormat,										// VkFormat							format;
1526				m_sampleCount,										// deUint32							samples;
1527				VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp				loadOp;
1528				VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp				storeOp;
1529				VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// VkAttachmentLoadOp				stencilLoadOp;
1530				VK_ATTACHMENT_STORE_OP_DONT_CARE,					// VkAttachmentStoreOp				stencilStoreOp;
1531				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout					initialLayout;
1532				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout					finalLayout;
1533			},
1534			{
1535				(VkAttachmentDescriptionFlags)0,					// VkAttachmentDescriptionFlags		flags;
1536				m_colorFormat,										// VkFormat							format;
1537				VK_SAMPLE_COUNT_1_BIT,								// VkSampleCountFlagBits			samples;
1538				VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp				loadOp;
1539				VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp				storeOp;
1540				VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// VkAttachmentLoadOp				stencilLoadOp;
1541				VK_ATTACHMENT_STORE_OP_DONT_CARE,					// VkAttachmentStoreOp				stencilStoreOp;
1542				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout					initialLayout;
1543				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout					finalLayout;
1544			}
1545		};
1546
1547		const VkAttachmentReference						attachmentReference			=
1548		{
1549			0u,													// deUint32			attachment;
1550			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout	layout;
1551		};
1552
1553		const VkAttachmentReference						resolveAttachmentRef		=
1554		{
1555			1u,													// deUint32			attachment;
1556			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout	layout;
1557		};
1558
1559		const VkSubpassDescription						subpassDescription			=
1560		{
1561			0u,													// VkSubpassDescriptionFlags	flags;
1562			VK_PIPELINE_BIND_POINT_GRAPHICS,					// VkPipelineBindPoint			pipelineBindPoint;
1563			0u,													// deUint32						inputCount;
1564			DE_NULL,											// constVkAttachmentReference*	pInputAttachments;
1565			1u,													// deUint32						colorCount;
1566			&attachmentReference,								// constVkAttachmentReference*	pColorAttachments;
1567			isMultiSampling() ? &resolveAttachmentRef : DE_NULL,// constVkAttachmentReference*	pResolveAttachments;
1568			DE_NULL,											// VkAttachmentReference		depthStencilAttachment;
1569			0u,													// deUint32						preserveCount;
1570			DE_NULL												// constVkAttachmentReference*	pPreserveAttachments;
1571		};
1572
1573		const VkRenderPassCreateInfo					renderPassParams			=
1574		{
1575			VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,			// VkStructureType					sType;
1576			DE_NULL,											// const void*						pNext;
1577			0u,													// VkRenderPassCreateFlags			flags;
1578			isMultiSampling() ? 2u : 1u,						// deUint32							attachmentCount;
1579			attachmentDescription,								// const VkAttachmentDescription*	pAttachments;
1580			1u,													// deUint32							subpassCount;
1581			&subpassDescription,								// const VkSubpassDescription*		pSubpasses;
1582			0u,													// deUint32							dependencyCount;
1583			DE_NULL												// const VkSubpassDependency*		pDependencies;
1584		};
1585
1586		renderPass = createRenderPass(vk, vkDevice, &renderPassParams);
1587	}
1588
1589	// Create framebuffer
1590	{
1591		const VkImageView								attachments[]				=
1592		{
1593			*colorImageView,
1594			*resolvedImageView
1595		};
1596
1597		const VkFramebufferCreateInfo					framebufferParams			=
1598		{
1599			VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,			// VkStructureType				sType;
1600			DE_NULL,											// const void*					pNext;
1601			(VkFramebufferCreateFlags)0,
1602			*renderPass,										// VkRenderPass					renderPass;
1603			isMultiSampling() ? 2u : 1u,						// deUint32						attachmentCount;
1604			attachments,										// const VkImageView*			pAttachments;
1605			(deUint32)m_renderSize.x(),							// deUint32						width;
1606			(deUint32)m_renderSize.y(),							// deUint32						height;
1607			1u													// deUint32						layers;
1608		};
1609
1610		framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
1611	}
1612
1613	// Create descriptors
1614	{
1615		setupUniforms(constCoords);
1616
1617		descriptorSetLayout = m_descriptorSetLayoutBuilder->build(vk, vkDevice);
1618		if (!m_uniformInfos.empty())
1619		{
1620			descriptorPool 									= m_descriptorPoolBuilder->build(vk, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1621			const VkDescriptorSetAllocateInfo	allocInfo	=
1622			{
1623				VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
1624				DE_NULL,
1625				*descriptorPool,
1626				1u,
1627				&descriptorSetLayout.get(),
1628			};
1629
1630			descriptorSet = allocateDescriptorSet(vk, vkDevice, &allocInfo);
1631		}
1632
1633		for (deUint32 i = 0; i < m_uniformInfos.size(); i++)
1634		{
1635			const UniformInfo* uniformInfo = m_uniformInfos[i].get()->get();
1636			deUint32 location = uniformInfo->location;
1637
1638			if (uniformInfo->type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER)
1639			{
1640				const BufferUniform*	bufferInfo	= dynamic_cast<const BufferUniform*>(uniformInfo);
1641
1642				m_descriptorSetUpdateBuilder->writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(location), uniformInfo->type, &bufferInfo->descriptor);
1643			}
1644			else if (uniformInfo->type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
1645			{
1646				const SamplerUniform*	samplerInfo	= dynamic_cast<const SamplerUniform*>(uniformInfo);
1647
1648				m_descriptorSetUpdateBuilder->writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(location), uniformInfo->type, &samplerInfo->descriptor);
1649			}
1650			else
1651				DE_FATAL("Impossible");
1652		}
1653
1654		m_descriptorSetUpdateBuilder->update(vk, vkDevice);
1655	}
1656
1657	// Create pipeline layout
1658	{
1659		const VkPipelineLayoutCreateInfo				pipelineLayoutParams		=
1660		{
1661			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType				sType;
1662			DE_NULL,											// const void*					pNext;
1663			(VkPipelineLayoutCreateFlags)0,
1664			1u,													// deUint32						descriptorSetCount;
1665			&*descriptorSetLayout,								// const VkDescriptorSetLayout*	pSetLayouts;
1666			0u,													// deUint32						pushConstantRangeCount;
1667			DE_NULL												// const VkPushConstantRange*	pPushConstantRanges;
1668		};
1669
1670		pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
1671	}
1672
1673	// Create shaders
1674	{
1675		vertexShaderModule		= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get(m_vertexShaderName), 0);
1676		fragmentShaderModule	= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get(m_fragmentShaderName), 0);
1677	}
1678
1679	// Create pipeline
1680	{
1681		const VkPipelineShaderStageCreateInfo			shaderStageParams[2]		=
1682		{
1683			{
1684				VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,		// VkStructureType				sType;
1685				DE_NULL,													// const void*					pNext;
1686				(VkPipelineShaderStageCreateFlags)0,
1687				VK_SHADER_STAGE_VERTEX_BIT,									// VkShaderStage				stage;
1688				*vertexShaderModule,										// VkShader						shader;
1689				"main",
1690				DE_NULL														// const VkSpecializationInfo*	pSpecializationInfo;
1691			},
1692			{
1693				VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,		// VkStructureType				sType;
1694				DE_NULL,													// const void*					pNext;
1695				(VkPipelineShaderStageCreateFlags)0,
1696				VK_SHADER_STAGE_FRAGMENT_BIT,								// VkShaderStage				stage;
1697				*fragmentShaderModule,										// VkShader						shader;
1698				"main",
1699				DE_NULL														// const VkSpecializationInfo*	pSpecializationInfo;
1700			}
1701		};
1702
1703		// Add test case specific attributes
1704		if (m_attribFunc)
1705			m_attribFunc(*this, numVertices);
1706
1707		// Add base attributes
1708		setupDefaultInputs();
1709
1710		const VkPipelineVertexInputStateCreateInfo		vertexInputStateParams		=
1711		{
1712			VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType							sType;
1713			DE_NULL,														// const void*								pNext;
1714			(VkPipelineVertexInputStateCreateFlags)0,
1715			(deUint32)m_vertexBindingDescription.size(),					// deUint32									bindingCount;
1716			&m_vertexBindingDescription[0],									// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
1717			(deUint32)m_vertexAttributeDescription.size(),					// deUint32									attributeCount;
1718			&m_vertexAttributeDescription[0],								// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
1719		};
1720
1721		const VkPipelineInputAssemblyStateCreateInfo	inputAssemblyStateParams	=
1722		{
1723			VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	// VkStructureType		sType;
1724			DE_NULL,														// const void*			pNext;
1725			(VkPipelineInputAssemblyStateCreateFlags)0,
1726			VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,							// VkPrimitiveTopology	topology;
1727			false															// VkBool32				primitiveRestartEnable;
1728		};
1729
1730		const VkViewport								viewport					=
1731		{
1732			0.0f,						// float	originX;
1733			0.0f,						// float	originY;
1734			(float)m_renderSize.x(),	// float	width;
1735			(float)m_renderSize.y(),	// float	height;
1736			0.0f,						// float	minDepth;
1737			1.0f						// float	maxDepth;
1738		};
1739
1740		const VkRect2D									scissor						=
1741		{
1742			{
1743				0u,					// deUint32	x;
1744				0u,					// deUint32	y;
1745			},							// VkOffset2D	offset;
1746			{
1747				m_renderSize.x(),	// deUint32	width;
1748				m_renderSize.y(),	// deUint32	height;
1749			},							// VkExtent2D	extent;
1750		};
1751
1752		const VkPipelineViewportStateCreateInfo			viewportStateParams			=
1753		{
1754			VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,			// VkStructureType						sType;
1755			DE_NULL,														// const void*							pNext;
1756			0u,																// VkPipelineViewportStateCreateFlags	flags;
1757			1u,																// deUint32								viewportCount;
1758			&viewport,														// const VkViewport*					pViewports;
1759			1u,																// deUint32								scissorsCount;
1760			&scissor,														// const VkRect2D*						pScissors;
1761		};
1762
1763		const VkPipelineRasterizationStateCreateInfo	rasterStateParams			=
1764		{
1765			VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,		// VkStructureType	sType;
1766			DE_NULL,														// const void*		pNext;
1767			(VkPipelineRasterizationStateCreateFlags)0,
1768			false,															// VkBool32			depthClipEnable;
1769			false,															// VkBool32			rasterizerDiscardEnable;
1770			VK_POLYGON_MODE_FILL,											// VkFillMode		fillMode;
1771			VK_CULL_MODE_NONE,												// VkCullMode		cullMode;
1772			VK_FRONT_FACE_COUNTER_CLOCKWISE,								// VkFrontFace		frontFace;
1773			false,															// VkBool32			depthBiasEnable;
1774			0.0f,															// float			depthBias;
1775			0.0f,															// float			depthBiasClamp;
1776			0.0f,															// float			slopeScaledDepthBias;
1777			1.0f,															// float			lineWidth;
1778		};
1779
1780		const VkPipelineMultisampleStateCreateInfo		multisampleStateParams =
1781		{
1782			VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,		// VkStructureType							sType;
1783			DE_NULL,														// const void*								pNext;
1784			0u,																// VkPipelineMultisampleStateCreateFlags	flags;
1785			m_sampleCount,													// VkSampleCountFlagBits					rasterizationSamples;
1786			VK_FALSE,														// VkBool32									sampleShadingEnable;
1787			0.0f,															// float									minSampleShading;
1788			DE_NULL,														// const VkSampleMask*						pSampleMask;
1789			VK_FALSE,														// VkBool32									alphaToCoverageEnable;
1790			VK_FALSE														// VkBool32									alphaToOneEnable;
1791		};
1792
1793		const VkPipelineColorBlendAttachmentState		colorBlendAttachmentState	=
1794		{
1795			false,															// VkBool32			blendEnable;
1796			VK_BLEND_FACTOR_ONE,											// VkBlend			srcBlendColor;
1797			VK_BLEND_FACTOR_ZERO,											// VkBlend			destBlendColor;
1798			VK_BLEND_OP_ADD,												// VkBlendOp		blendOpColor;
1799			VK_BLEND_FACTOR_ONE,											// VkBlend			srcBlendAlpha;
1800			VK_BLEND_FACTOR_ZERO,											// VkBlend			destBlendAlpha;
1801			VK_BLEND_OP_ADD,												// VkBlendOp		blendOpAlpha;
1802			(VK_COLOR_COMPONENT_R_BIT |
1803			 VK_COLOR_COMPONENT_G_BIT |
1804			 VK_COLOR_COMPONENT_B_BIT |
1805			 VK_COLOR_COMPONENT_A_BIT),										// VkChannelFlags	channelWriteMask;
1806		};
1807
1808		const VkPipelineColorBlendStateCreateInfo		colorBlendStateParams		=
1809		{
1810			VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType;
1811			DE_NULL,													// const void*									pNext;
1812			(VkPipelineColorBlendStateCreateFlags)0,
1813			false,														// VkBool32										logicOpEnable;
1814			VK_LOGIC_OP_COPY,											// VkLogicOp									logicOp;
1815			1u,															// deUint32										attachmentCount;
1816			&colorBlendAttachmentState,									// const VkPipelineColorBlendAttachmentState*	pAttachments;
1817			{ 0.0f, 0.0f, 0.0f, 0.0f },									// float										blendConst[4];
1818		};
1819
1820		const VkGraphicsPipelineCreateInfo				graphicsPipelineParams		=
1821		{
1822			VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,	// VkStructureType									sType;
1823			DE_NULL,											// const void*										pNext;
1824			0u,													// VkPipelineCreateFlags							flags;
1825			2u,													// deUint32											stageCount;
1826			shaderStageParams,									// const VkPipelineShaderStageCreateInfo*			pStages;
1827			&vertexInputStateParams,							// const VkPipelineVertexInputStateCreateInfo*		pVertexInputState;
1828			&inputAssemblyStateParams,							// const VkPipelineInputAssemblyStateCreateInfo*	pInputAssemblyState;
1829			DE_NULL,											// const VkPipelineTessellationStateCreateInfo*		pTessellationState;
1830			&viewportStateParams,								// const VkPipelineViewportStateCreateInfo*			pViewportState;
1831			&rasterStateParams,									// const VkPipelineRasterStateCreateInfo*			pRasterState;
1832			&multisampleStateParams,							// const VkPipelineMultisampleStateCreateInfo*		pMultisampleState;
1833			DE_NULL,											// const VkPipelineDepthStencilStateCreateInfo*		pDepthStencilState;
1834			&colorBlendStateParams,								// const VkPipelineColorBlendStateCreateInfo*		pColorBlendState;
1835			(const VkPipelineDynamicStateCreateInfo*)DE_NULL,	// const VkPipelineDynamicStateCreateInfo*			pDynamicState;
1836			*pipelineLayout,									// VkPipelineLayout									layout;
1837			*renderPass,										// VkRenderPass										renderPass;
1838			0u,													// deUint32											subpass;
1839			0u,													// VkPipeline										basePipelineHandle;
1840			0u													// deInt32											basePipelineIndex;
1841		};
1842
1843		graphicsPipeline = createGraphicsPipeline(vk, vkDevice, DE_NULL, &graphicsPipelineParams);
1844	}
1845
1846	// Create vertex indices buffer
1847	{
1848		const VkDeviceSize								indiceBufferSize			= numTriangles * 3 * sizeof(deUint16);
1849		const VkBufferCreateInfo						indiceBufferParams			=
1850		{
1851			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
1852			DE_NULL,									// const void*			pNext;
1853			0u,											// VkBufferCreateFlags	flags;
1854			indiceBufferSize,							// VkDeviceSize			size;
1855			VK_BUFFER_USAGE_INDEX_BUFFER_BIT,			// VkBufferUsageFlags	usage;
1856			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
1857			1u,											// deUint32				queueFamilyCount;
1858			&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
1859		};
1860
1861		indiceBuffer		= createBuffer(vk, vkDevice, &indiceBufferParams);
1862		indiceBufferAlloc	= m_memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *indiceBuffer), MemoryRequirement::HostVisible);
1863
1864		VK_CHECK(vk.bindBufferMemory(vkDevice, *indiceBuffer, indiceBufferAlloc->getMemory(), indiceBufferAlloc->getOffset()));
1865
1866		// Load vertice indices into buffer
1867		deMemcpy(indiceBufferAlloc->getHostPtr(), indices, (size_t)indiceBufferSize);
1868		flushMappedMemoryRange(vk, vkDevice, indiceBufferAlloc->getMemory(), indiceBufferAlloc->getOffset(), indiceBufferSize);
1869	}
1870
1871	// Create command pool
1872	{
1873		const VkCommandPoolCreateInfo					cmdPoolParams				=
1874		{
1875			VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,		// VkStructureType		sType;
1876			DE_NULL,										// const void*			pNext;
1877			VK_COMMAND_POOL_CREATE_TRANSIENT_BIT,			// VkCmdPoolCreateFlags	flags;
1878			queueFamilyIndex,								// deUint32				queueFamilyIndex;
1879		};
1880
1881		cmdPool = createCommandPool(vk, vkDevice, &cmdPoolParams);
1882	}
1883
1884	// Create command buffer
1885	{
1886		const VkCommandBufferAllocateInfo				cmdBufferParams				=
1887		{
1888			VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,	// VkStructureType			sType;
1889			DE_NULL,										// const void*				pNext;
1890			*cmdPool,										// VkCmdPool				cmdPool;
1891			VK_COMMAND_BUFFER_LEVEL_PRIMARY,				// VkCmdBufferLevel			level;
1892			1u												// deUint32					bufferCount;
1893		};
1894
1895		const VkCommandBufferBeginInfo					cmdBufferBeginInfo			=
1896		{
1897			VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,	// VkStructureType			sType;
1898			DE_NULL,										// const void*				pNext;
1899			0u,												// VkCmdBufferOptimizeFlags	flags;
1900			(const VkCommandBufferInheritanceInfo*)DE_NULL,
1901		};
1902
1903		const VkClearValue								clearValues					= makeClearValueColorF32(m_clearColor.x(),
1904																											 m_clearColor.y(),
1905																											 m_clearColor.z(),
1906																											 m_clearColor.w());
1907
1908		const VkRenderPassBeginInfo						renderPassBeginInfo			=
1909		{
1910			VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,				// VkStructureType		sType;
1911			DE_NULL,												// const void*			pNext;
1912			*renderPass,											// VkRenderPass			renderPass;
1913			*framebuffer,											// VkFramebuffer		framebuffer;
1914			{ { 0, 0 },  {m_renderSize.x(), m_renderSize.y() } },	// VkRect2D				renderArea;
1915			1,														// deUint32				clearValueCount;
1916			&clearValues,											// const VkClearValue*	pClearValues;
1917		};
1918
1919		cmdBuffer = allocateCommandBuffer(vk, vkDevice, &cmdBufferParams);
1920
1921		VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufferBeginInfo));
1922
1923		{
1924			const VkImageMemoryBarrier					imageBarrier				=
1925			{
1926				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,										// VkStructureType			sType;
1927				DE_NULL,																	// const void*				pNext;
1928				0u,																			// VkAccessFlags			srcAccessMask;
1929				VK_PIPELINE_STAGE_TRANSFER_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,		// VkAccessFlags			dstAccessMask;
1930				VK_IMAGE_LAYOUT_UNDEFINED,													// VkImageLayout			oldLayout;
1931				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,									// VkImageLayout			newLayout;
1932				VK_QUEUE_FAMILY_IGNORED,													// deUint32					srcQueueFamilyIndex;
1933				VK_QUEUE_FAMILY_IGNORED,													// deUint32					dstQueueFamilyIndex;
1934				*colorImage,																// VkImage					image;
1935				{																			// VkImageSubresourceRange	subresourceRange;
1936					VK_IMAGE_ASPECT_COLOR_BIT,												// VkImageAspectFlags		aspectMask;
1937					0u,																		// deUint32					baseMipLevel;
1938					1u,																		// deUint32					mipLevels;
1939					0u,																		// deUint32					baseArrayLayer;
1940					1u,																		// deUint32					arraySize;
1941				}
1942			};
1943
1944			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, DE_NULL, 1, &imageBarrier);
1945
1946			if (isMultiSampling()) {
1947				// add multisample barrier
1948				const VkImageMemoryBarrier				multiSampleImageBarrier		=
1949				{
1950					VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,										// VkStructureType			sType;
1951					DE_NULL,																	// const void*				pNext;
1952					0u,																			// VkAccessFlags			srcAccessMask;
1953					VK_PIPELINE_STAGE_TRANSFER_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,		// VkAccessFlags			dstAccessMask;
1954					VK_IMAGE_LAYOUT_UNDEFINED,													// VkImageLayout			oldLayout;
1955					VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,									// VkImageLayout			newLayout;
1956					VK_QUEUE_FAMILY_IGNORED,													// deUint32					srcQueueFamilyIndex;
1957					VK_QUEUE_FAMILY_IGNORED,													// deUint32					dstQueueFamilyIndex;
1958					*resolvedImage,																// VkImage					image;
1959					{																			// VkImageSubresourceRange	subresourceRange;
1960						VK_IMAGE_ASPECT_COLOR_BIT,												// VkImageAspectFlags		aspectMask;
1961						0u,																		// deUint32					baseMipLevel;
1962						1u,																		// deUint32					mipLevels;
1963						0u,																		// deUint32					baseArrayLayer;
1964						1u,																		// deUint32					arraySize;
1965					}
1966				};
1967
1968				vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, DE_NULL, 1, &multiSampleImageBarrier);
1969			}
1970		}
1971
1972		vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
1973
1974		vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline);
1975		if (!m_uniformInfos.empty())
1976			vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1, &*descriptorSet, 0u, DE_NULL);
1977		vk.cmdBindIndexBuffer(*cmdBuffer, *indiceBuffer, 0, VK_INDEX_TYPE_UINT16);
1978
1979		const deUint32 numberOfVertexAttributes = (deUint32)m_vertexBuffers.size();
1980		const std::vector<VkDeviceSize> offsets(numberOfVertexAttributes, 0);
1981
1982		std::vector<VkBuffer> buffers(numberOfVertexAttributes);
1983		for (size_t i = 0; i < numberOfVertexAttributes; i++)
1984		{
1985			buffers[i] = m_vertexBuffers[i].get()->get();
1986		}
1987
1988		vk.cmdBindVertexBuffers(*cmdBuffer, 0, numberOfVertexAttributes, &buffers[0], &offsets[0]);
1989		vk.cmdDrawIndexed(*cmdBuffer, numTriangles * 3, 1, 0, 0, 0);
1990
1991		vk.cmdEndRenderPass(*cmdBuffer);
1992		VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1993	}
1994
1995	// Create fence
1996	{
1997		const VkFenceCreateInfo							fenceParams					=
1998		{
1999			VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,	// VkStructureType		sType;
2000			DE_NULL,								// const void*			pNext;
2001			0u										// VkFenceCreateFlags	flags;
2002		};
2003		fence = createFence(vk, vkDevice, &fenceParams);
2004	}
2005
2006	// Execute Draw
2007	{
2008		const VkSubmitInfo	submitInfo	=
2009		{
2010			VK_STRUCTURE_TYPE_SUBMIT_INFO,
2011			DE_NULL,
2012			0u,
2013			(const VkSemaphore*)DE_NULL,
2014			(const VkPipelineStageFlags*)DE_NULL,
2015			1u,
2016			&cmdBuffer.get(),
2017			0u,
2018			(const VkSemaphore*)DE_NULL,
2019		};
2020
2021		VK_CHECK(vk.resetFences(vkDevice, 1, &fence.get()));
2022		VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *fence));
2023		VK_CHECK(vk.waitForFences(vkDevice, 1, &fence.get(), true, ~(0ull) /* infinity*/));
2024	}
2025
2026	// Read back the result
2027	{
2028		const tcu::TextureFormat						resultFormat				= mapVkFormat(m_colorFormat);
2029		const VkDeviceSize								imageSizeBytes				= (VkDeviceSize)(resultFormat.getPixelSize() * m_renderSize.x() * m_renderSize.y());
2030		const VkBufferCreateInfo						readImageBufferParams		=
2031		{
2032			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		//  VkStructureType		sType;
2033			DE_NULL,									//  const void*			pNext;
2034			0u,											//  VkBufferCreateFlags	flags;
2035			imageSizeBytes,								//  VkDeviceSize		size;
2036			VK_BUFFER_USAGE_TRANSFER_DST_BIT,			//  VkBufferUsageFlags	usage;
2037			VK_SHARING_MODE_EXCLUSIVE,					//  VkSharingMode		sharingMode;
2038			1u,											//  deUint32			queueFamilyCount;
2039			&queueFamilyIndex,							//  const deUint32*		pQueueFamilyIndices;
2040		};
2041		const Unique<VkBuffer>							readImageBuffer				(createBuffer(vk, vkDevice, &readImageBufferParams));
2042		const de::UniquePtr<Allocation>					readImageBufferMemory		(m_memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *readImageBuffer), MemoryRequirement::HostVisible));
2043
2044		VK_CHECK(vk.bindBufferMemory(vkDevice, *readImageBuffer, readImageBufferMemory->getMemory(), readImageBufferMemory->getOffset()));
2045
2046		// Copy image to buffer
2047		const VkCommandBufferAllocateInfo				cmdBufferParams				=
2048		{
2049			VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,	// VkStructureType			sType;
2050			DE_NULL,										// const void*				pNext;
2051			*cmdPool,										// VkCmdPool				cmdPool;
2052			VK_COMMAND_BUFFER_LEVEL_PRIMARY,				// VkCmdBufferLevel			level;
2053			1u												// deUint32					bufferCount;
2054		};
2055
2056		const VkCommandBufferBeginInfo					cmdBufferBeginInfo			=
2057		{
2058			VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,	// VkStructureType			sType;
2059			DE_NULL,										// const void*				pNext;
2060			0u,												// VkCmdBufferOptimizeFlags	flags;
2061			(const VkCommandBufferInheritanceInfo*)DE_NULL,
2062		};
2063
2064		const Move<VkCommandBuffer>						resultCmdBuffer				= allocateCommandBuffer(vk, vkDevice, &cmdBufferParams);
2065
2066		const VkBufferImageCopy							copyParams					=
2067		{
2068			0u,											// VkDeviceSize			bufferOffset;
2069			(deUint32)m_renderSize.x(),					// deUint32				bufferRowLength;
2070			(deUint32)m_renderSize.y(),					// deUint32				bufferImageHeight;
2071			{
2072				VK_IMAGE_ASPECT_COLOR_BIT,			// VkImageAspect		aspect;
2073				0u,									// deUint32				mipLevel;
2074				0u,									// deUint32				arraySlice;
2075				1u,									// deUint32				arraySize;
2076			},											// VkImageSubresourceCopy	imageSubresource;
2077			{ 0u, 0u, 0u },								// VkOffset3D			imageOffset;
2078			{ m_renderSize.x(), m_renderSize.y(), 1u }	// VkExtent3D			imageExtent;
2079		};
2080		const VkSubmitInfo								submitInfo					=
2081		{
2082			VK_STRUCTURE_TYPE_SUBMIT_INFO,
2083			DE_NULL,
2084			0u,
2085			(const VkSemaphore*)DE_NULL,
2086			(const VkPipelineStageFlags*)DE_NULL,
2087			1u,
2088			&resultCmdBuffer.get(),
2089			0u,
2090			(const VkSemaphore*)DE_NULL,
2091		};
2092
2093		VK_CHECK(vk.beginCommandBuffer(*resultCmdBuffer, &cmdBufferBeginInfo));
2094
2095		const VkImageMemoryBarrier						imageBarrier				=
2096		{
2097			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,									// VkStructureType			sType;
2098			DE_NULL,																// const void*				pNext;
2099			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT,	// VkAccessFlags			srcAccessMask;
2100			VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags			dstAccessMask;
2101			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,								// VkImageLayout			oldLayout;
2102			VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,									// VkImageLayout			newLayout;
2103			VK_QUEUE_FAMILY_IGNORED,												// deUint32					srcQueueFamilyIndex;
2104			VK_QUEUE_FAMILY_IGNORED,												// deUint32					dstQueueFamilyIndex;
2105			isMultiSampling() ? *resolvedImage : *colorImage,						// VkImage					image;
2106			{																		// VkImageSubresourceRange	subresourceRange;
2107				VK_IMAGE_ASPECT_COLOR_BIT,											// VkImageAspectFlags		aspectMask;
2108				0u,																	// deUint32					baseMipLevel;
2109				1u,																	// deUint32					mipLevels;
2110				0u,																	// deUint32					baseArraySlice;
2111				1u																	// deUint32					arraySize;
2112			}
2113		};
2114
2115		const VkBufferMemoryBarrier						bufferBarrier				=
2116		{
2117			VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	// VkStructureType	sType;
2118			DE_NULL,									// const void*		pNext;
2119			VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags	srcAccessMask;
2120			VK_ACCESS_HOST_READ_BIT,					// VkAccessFlags	dstAccessMask;
2121			VK_QUEUE_FAMILY_IGNORED,					// deUint32			srcQueueFamilyIndex;
2122			VK_QUEUE_FAMILY_IGNORED,					// deUint32			dstQueueFamilyIndex;
2123			*readImageBuffer,							// VkBuffer			buffer;
2124			0u,											// VkDeviceSize		offset;
2125			imageSizeBytes								// VkDeviceSize		size;
2126		};
2127
2128		vk.cmdPipelineBarrier(*resultCmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &imageBarrier);
2129		vk.cmdCopyImageToBuffer(*resultCmdBuffer, isMultiSampling() ? *resolvedImage : *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *readImageBuffer, 1u, &copyParams);
2130		vk.cmdPipelineBarrier(*resultCmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &bufferBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL);
2131
2132		VK_CHECK(vk.endCommandBuffer(*resultCmdBuffer));
2133
2134		VK_CHECK(vk.resetFences(vkDevice, 1, &fence.get()));
2135		VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *fence));
2136		VK_CHECK(vk.waitForFences(vkDevice, 1, &fence.get(), true, ~(0ull) /* infinity */));
2137
2138		invalidateMappedMemoryRange(vk, vkDevice, readImageBufferMemory->getMemory(), readImageBufferMemory->getOffset(), imageSizeBytes);
2139
2140		const tcu::ConstPixelBufferAccess				resultAccess				(resultFormat, m_renderSize.x(), m_renderSize.y(), 1, readImageBufferMemory->getHostPtr());
2141
2142		m_resultImage.setStorage(resultFormat, m_renderSize.x(), m_renderSize.y());
2143		tcu::copy(m_resultImage.getAccess(), resultAccess);
2144	}
2145}
2146
2147void ShaderRenderCaseInstance::computeVertexReference (tcu::Surface& result, const QuadGrid& quadGrid)
2148{
2149	DE_ASSERT(m_evaluator);
2150
2151	// Buffer info.
2152	const int				width		= result.getWidth();
2153	const int				height		= result.getHeight();
2154	const int				gridSize	= quadGrid.getGridSize();
2155	const int				stride		= gridSize + 1;
2156	const bool				hasAlpha	= true; // \todo [2015-09-07 elecro] add correct alpha check
2157	ShaderEvalContext		evalCtx		(quadGrid);
2158
2159	// Evaluate color for each vertex.
2160	std::vector<tcu::Vec4>	colors		((gridSize + 1) * (gridSize + 1));
2161	for (int y = 0; y < gridSize+1; y++)
2162	for (int x = 0; x < gridSize+1; x++)
2163	{
2164		const float	sx			= (float)x / (float)gridSize;
2165		const float	sy			= (float)y / (float)gridSize;
2166		const int	vtxNdx		= ((y * (gridSize+1)) + x);
2167
2168		evalCtx.reset(sx, sy);
2169		m_evaluator->evaluate(evalCtx);
2170		DE_ASSERT(!evalCtx.isDiscarded); // Discard is not available in vertex shader.
2171		tcu::Vec4 color = evalCtx.color;
2172
2173		if (!hasAlpha)
2174			color.w() = 1.0f;
2175
2176		colors[vtxNdx] = color;
2177	}
2178
2179	// Render quads.
2180	for (int y = 0; y < gridSize; y++)
2181	for (int x = 0; x < gridSize; x++)
2182	{
2183		const float		x0		= (float)x       / (float)gridSize;
2184		const float		x1		= (float)(x + 1) / (float)gridSize;
2185		const float		y0		= (float)y       / (float)gridSize;
2186		const float		y1		= (float)(y + 1) / (float)gridSize;
2187
2188		const float		sx0		= x0 * (float)width;
2189		const float		sx1		= x1 * (float)width;
2190		const float		sy0		= y0 * (float)height;
2191		const float		sy1		= y1 * (float)height;
2192		const float		oosx	= 1.0f / (sx1 - sx0);
2193		const float		oosy	= 1.0f / (sy1 - sy0);
2194
2195		const int		ix0		= deCeilFloatToInt32(sx0 - 0.5f);
2196		const int		ix1		= deCeilFloatToInt32(sx1 - 0.5f);
2197		const int		iy0		= deCeilFloatToInt32(sy0 - 0.5f);
2198		const int		iy1		= deCeilFloatToInt32(sy1 - 0.5f);
2199
2200		const int		v00		= (y * stride) + x;
2201		const int		v01		= (y * stride) + x + 1;
2202		const int		v10		= ((y + 1) * stride) + x;
2203		const int		v11		= ((y + 1) * stride) + x + 1;
2204		const tcu::Vec4	c00		= colors[v00];
2205		const tcu::Vec4	c01		= colors[v01];
2206		const tcu::Vec4	c10		= colors[v10];
2207		const tcu::Vec4	c11		= colors[v11];
2208
2209		//printf("(%d,%d) -> (%f..%f, %f..%f) (%d..%d, %d..%d)\n", x, y, sx0, sx1, sy0, sy1, ix0, ix1, iy0, iy1);
2210
2211		for (int iy = iy0; iy < iy1; iy++)
2212		for (int ix = ix0; ix < ix1; ix++)
2213		{
2214			DE_ASSERT(deInBounds32(ix, 0, width));
2215			DE_ASSERT(deInBounds32(iy, 0, height));
2216
2217			const float			sfx		= (float)ix + 0.5f;
2218			const float			sfy		= (float)iy + 0.5f;
2219			const float			fx1		= deFloatClamp((sfx - sx0) * oosx, 0.0f, 1.0f);
2220			const float			fy1		= deFloatClamp((sfy - sy0) * oosy, 0.0f, 1.0f);
2221
2222			// Triangle quad interpolation.
2223			const bool			tri		= fx1 + fy1 <= 1.0f;
2224			const float			tx		= tri ? fx1 : (1.0f-fx1);
2225			const float			ty		= tri ? fy1 : (1.0f-fy1);
2226			const tcu::Vec4&	t0		= tri ? c00 : c11;
2227			const tcu::Vec4&	t1		= tri ? c01 : c10;
2228			const tcu::Vec4&	t2		= tri ? c10 : c01;
2229			const tcu::Vec4		color	= t0 + (t1-t0)*tx + (t2-t0)*ty;
2230
2231			result.setPixel(ix, iy, tcu::RGBA(color));
2232		}
2233	}
2234}
2235
2236void ShaderRenderCaseInstance::computeFragmentReference (tcu::Surface& result, const QuadGrid& quadGrid)
2237{
2238	DE_ASSERT(m_evaluator);
2239
2240	// Buffer info.
2241	const int			width		= result.getWidth();
2242	const int			height		= result.getHeight();
2243	const bool			hasAlpha	= true;  // \todo [2015-09-07 elecro] add correct alpha check
2244	ShaderEvalContext	evalCtx		(quadGrid);
2245
2246	// Render.
2247	for (int y = 0; y < height; y++)
2248	for (int x = 0; x < width; x++)
2249	{
2250		const float sx = ((float)x + 0.5f) / (float)width;
2251		const float sy = ((float)y + 0.5f) / (float)height;
2252
2253		evalCtx.reset(sx, sy);
2254		m_evaluator->evaluate(evalCtx);
2255		// Select either clear color or computed color based on discarded bit.
2256		tcu::Vec4 color = evalCtx.isDiscarded ? m_clearColor : evalCtx.color;
2257
2258		if (!hasAlpha)
2259			color.w() = 1.0f;
2260
2261		result.setPixel(x, y, tcu::RGBA(color));
2262	}
2263}
2264
2265bool ShaderRenderCaseInstance::compareImages (const tcu::Surface& resImage, const tcu::Surface& refImage, float errorThreshold)
2266{
2267	return tcu::fuzzyCompare(m_context.getTestContext().getLog(), "ComparisonResult", "Image comparison result", refImage, resImage, errorThreshold, tcu::COMPARE_LOG_RESULT);
2268}
2269
2270} // sr
2271} // vkt
2272