vktShaderRender.cpp revision 3fabf9547b3e2113a74936b196c69f101ce0851b
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_1D:			return VK_IMAGE_VIEW_TYPE_1D;
71		case TextureBinding::TYPE_2D:			return VK_IMAGE_VIEW_TYPE_2D;
72		case TextureBinding::TYPE_3D:			return VK_IMAGE_VIEW_TYPE_3D;
73		case TextureBinding::TYPE_CUBE_MAP:		return VK_IMAGE_VIEW_TYPE_CUBE;
74		case TextureBinding::TYPE_1D_ARRAY:		return VK_IMAGE_VIEW_TYPE_1D_ARRAY;
75		case TextureBinding::TYPE_2D_ARRAY:		return VK_IMAGE_VIEW_TYPE_2D_ARRAY;
76		case TextureBinding::TYPE_CUBE_ARRAY:	return VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
77
78		default:
79			DE_FATAL("Impossible");
80			return (VkImageViewType)0;
81	}
82}
83
84static VkImageType viewTypeToImageType (VkImageViewType type)
85{
86	switch (type)
87	{
88		case VK_IMAGE_VIEW_TYPE_1D:
89		case VK_IMAGE_VIEW_TYPE_1D_ARRAY:		return VK_IMAGE_TYPE_1D;
90		case VK_IMAGE_VIEW_TYPE_2D:
91		case VK_IMAGE_VIEW_TYPE_2D_ARRAY:		return VK_IMAGE_TYPE_2D;
92		case VK_IMAGE_VIEW_TYPE_3D:				return VK_IMAGE_TYPE_3D;
93		case VK_IMAGE_VIEW_TYPE_CUBE:
94		case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:		return VK_IMAGE_TYPE_2D;
95
96		default:
97			DE_FATAL("Impossible");
98			return (VkImageType)0;
99	}
100}
101
102/*! Gets the next multiple of a given divisor */
103static deUint32 getNextMultiple (deUint32 divisor, deUint32 value)
104{
105	if (value % divisor == 0)
106	{
107		return value;
108	}
109	return value + divisor - (value % divisor);
110}
111
112/*! Gets the next value that is multiple of all given divisors */
113static deUint32 getNextMultiple (const std::vector<deUint32>& divisors, deUint32 value)
114{
115	deUint32	nextMultiple		= value;
116	bool		nextMultipleFound	= false;
117
118	while (true)
119	{
120		nextMultipleFound = true;
121
122		for (size_t divNdx = 0; divNdx < divisors.size(); divNdx++)
123			nextMultipleFound = nextMultipleFound && (nextMultiple % divisors[divNdx] == 0);
124
125		if (nextMultipleFound)
126			break;
127
128		DE_ASSERT(nextMultiple < ~((deUint32)0u));
129		nextMultiple = getNextMultiple(divisors[0], nextMultiple + 1);
130	}
131
132	return nextMultiple;
133}
134
135} // anonymous
136
137// QuadGrid.
138
139class QuadGrid
140{
141public:
142											QuadGrid				(int									gridSize,
143																	 int									screenWidth,
144																	 int									screenHeight,
145																	 const tcu::Vec4&						constCoords,
146																	 const std::vector<tcu::Mat4>&			userAttribTransforms,
147																	 const std::vector<TextureBindingSp>&	textures);
148											~QuadGrid				(void);
149
150	int										getGridSize				(void) const { return m_gridSize; }
151	int										getNumVertices			(void) const { return m_numVertices; }
152	int										getNumTriangles			(void) const { return m_numTriangles; }
153	const tcu::Vec4&						getConstCoords			(void) const { return m_constCoords; }
154	const std::vector<tcu::Mat4>			getUserAttribTransforms	(void) const { return m_userAttribTransforms; }
155	const std::vector<TextureBindingSp>&	getTextures				(void) const { return m_textures; }
156
157	const tcu::Vec4*						getPositions			(void) const { return &m_positions[0]; }
158	const float*							getAttribOne			(void) const { return &m_attribOne[0]; }
159	const tcu::Vec4*						getCoords				(void) const { return &m_coords[0]; }
160	const tcu::Vec4*						getUnitCoords			(void) const { return &m_unitCoords[0]; }
161
162	const tcu::Vec4*						getUserAttrib			(int attribNdx) const { return &m_userAttribs[attribNdx][0]; }
163	const deUint16*							getIndices				(void) const { return &m_indices[0]; }
164
165	tcu::Vec4								getCoords				(float sx, float sy) const;
166	tcu::Vec4								getUnitCoords			(float sx, float sy) const;
167
168	int										getNumUserAttribs		(void) const { return (int)m_userAttribTransforms.size(); }
169	tcu::Vec4								getUserAttrib			(int attribNdx, float sx, float sy) const;
170
171private:
172	const int								m_gridSize;
173	const int								m_numVertices;
174	const int								m_numTriangles;
175	const tcu::Vec4							m_constCoords;
176	const std::vector<tcu::Mat4>			m_userAttribTransforms;
177
178	const std::vector<TextureBindingSp>&	m_textures;
179
180	std::vector<tcu::Vec4>					m_screenPos;
181	std::vector<tcu::Vec4>					m_positions;
182	std::vector<tcu::Vec4>					m_coords;		//!< Near-unit coordinates, roughly [-2.0 .. 2.0].
183	std::vector<tcu::Vec4>					m_unitCoords;	//!< Positive-only coordinates [0.0 .. 1.5].
184	std::vector<float>						m_attribOne;
185	std::vector<tcu::Vec4>					m_userAttribs[ShaderEvalContext::MAX_TEXTURES];
186	std::vector<deUint16>					m_indices;
187};
188
189QuadGrid::QuadGrid (int										gridSize,
190					int										width,
191					int										height,
192					const tcu::Vec4&						constCoords,
193					const std::vector<tcu::Mat4>&			userAttribTransforms,
194					const std::vector<TextureBindingSp>&	textures)
195	: m_gridSize				(gridSize)
196	, m_numVertices				((gridSize + 1) * (gridSize + 1))
197	, m_numTriangles			(gridSize * gridSize * 2)
198	, m_constCoords				(constCoords)
199	, m_userAttribTransforms	(userAttribTransforms)
200	, m_textures				(textures)
201{
202	const tcu::Vec4 viewportScale	((float)width, (float)height, 0.0f, 0.0f);
203
204	// Compute vertices.
205	m_screenPos.resize(m_numVertices);
206	m_positions.resize(m_numVertices);
207	m_coords.resize(m_numVertices);
208	m_unitCoords.resize(m_numVertices);
209	m_attribOne.resize(m_numVertices);
210
211	// User attributes.
212	for (int attrNdx = 0; attrNdx < DE_LENGTH_OF_ARRAY(m_userAttribs); attrNdx++)
213		m_userAttribs[attrNdx].resize(m_numVertices);
214
215	for (int y = 0; y < gridSize+1; y++)
216	for (int x = 0; x < gridSize+1; x++)
217	{
218		float		sx			= (float)x / (float)gridSize;
219		float		sy			= (float)y / (float)gridSize;
220		float		fx			= 2.0f * sx - 1.0f;
221		float		fy			= 2.0f * sy - 1.0f;
222		int			vtxNdx		= ((y * (gridSize+1)) + x);
223
224		m_positions[vtxNdx]		= tcu::Vec4(fx, fy, 0.0f, 1.0f);
225		m_coords[vtxNdx]		= getCoords(sx, sy);
226		m_unitCoords[vtxNdx]	= getUnitCoords(sx, sy);
227		m_attribOne[vtxNdx]		= 1.0f;
228
229		m_screenPos[vtxNdx]		= tcu::Vec4(sx, sy, 0.0f, 1.0f) * viewportScale;
230
231		for (int attribNdx = 0; attribNdx < getNumUserAttribs(); attribNdx++)
232			m_userAttribs[attribNdx][vtxNdx] = getUserAttrib(attribNdx, sx, sy);
233	}
234
235	// Compute indices.
236	m_indices.resize(3 * m_numTriangles);
237	for (int y = 0; y < gridSize; y++)
238	for (int x = 0; x < gridSize; x++)
239	{
240		int stride				= gridSize + 1;
241		int v00					= (y * stride) + x;
242		int v01					= (y * stride) + x + 1;
243		int v10					= ((y+1) * stride) + x;
244		int v11					= ((y+1) * stride) + x + 1;
245
246		int baseNdx				= ((y * gridSize) + x) * 6;
247		m_indices[baseNdx + 0]	= (deUint16)v10;
248		m_indices[baseNdx + 1]	= (deUint16)v00;
249		m_indices[baseNdx + 2]	= (deUint16)v01;
250
251		m_indices[baseNdx + 3]	= (deUint16)v10;
252		m_indices[baseNdx + 4]	= (deUint16)v01;
253		m_indices[baseNdx + 5]	= (deUint16)v11;
254	}
255}
256
257QuadGrid::~QuadGrid (void)
258{
259}
260
261inline tcu::Vec4 QuadGrid::getCoords (float sx, float sy) const
262{
263	const float fx = 2.0f * sx - 1.0f;
264	const float fy = 2.0f * sy - 1.0f;
265	return tcu::Vec4(fx, fy, -fx + 0.33f*fy, -0.275f*fx - fy);
266}
267
268inline tcu::Vec4 QuadGrid::getUnitCoords (float sx, float sy) const
269{
270	return tcu::Vec4(sx, sy, 0.33f*sx + 0.5f*sy, 0.5f*sx + 0.25f*sy);
271}
272
273inline tcu::Vec4 QuadGrid::getUserAttrib (int attribNdx, float sx, float sy) const
274{
275	// homogeneous normalized screen-space coordinates
276	return m_userAttribTransforms[attribNdx] * tcu::Vec4(sx, sy, 0.0f, 1.0f);
277}
278
279// TextureBinding
280
281TextureBinding::TextureBinding (const tcu::Archive&	archive,
282								const char*			filename,
283								const Type			type,
284								const tcu::Sampler&	sampler)
285	: m_type	(type)
286	, m_sampler	(sampler)
287{
288	switch(m_type)
289	{
290		case TYPE_2D: m_binding.tex2D = loadTexture2D(archive, filename).release(); break;
291		default:
292			DE_FATAL("Unsupported texture type");
293	}
294}
295
296TextureBinding::TextureBinding (const tcu::Texture1D* tex1D, const tcu::Sampler& sampler)
297	: m_type	(TYPE_1D)
298	, m_sampler	(sampler)
299{
300	m_binding.tex1D = tex1D;
301}
302
303TextureBinding::TextureBinding (const tcu::Texture2D* tex2D, const tcu::Sampler& sampler)
304	: m_type	(TYPE_2D)
305	, m_sampler	(sampler)
306{
307	m_binding.tex2D = tex2D;
308}
309
310TextureBinding::TextureBinding (const tcu::Texture3D* tex3D, const tcu::Sampler& sampler)
311	: m_type	(TYPE_3D)
312	, m_sampler	(sampler)
313{
314	m_binding.tex3D = tex3D;
315}
316
317TextureBinding::TextureBinding (const tcu::TextureCube* texCube, const tcu::Sampler& sampler)
318	: m_type	(TYPE_CUBE_MAP)
319	, m_sampler	(sampler)
320{
321	m_binding.texCube = texCube;
322}
323
324TextureBinding::TextureBinding (const tcu::Texture1DArray* tex1DArray, const tcu::Sampler& sampler)
325	: m_type	(TYPE_1D_ARRAY)
326	, m_sampler	(sampler)
327{
328	m_binding.tex1DArray = tex1DArray;
329}
330
331TextureBinding::TextureBinding (const tcu::Texture2DArray* tex2DArray, const tcu::Sampler& sampler)
332	: m_type	(TYPE_2D_ARRAY)
333	, m_sampler	(sampler)
334{
335	m_binding.tex2DArray = tex2DArray;
336}
337
338TextureBinding::TextureBinding (const tcu::TextureCubeArray* texCubeArray, const tcu::Sampler& sampler)
339	: m_type	(TYPE_CUBE_ARRAY)
340	, m_sampler	(sampler)
341{
342	m_binding.texCubeArray = texCubeArray;
343}
344
345TextureBinding::~TextureBinding (void)
346{
347	switch(m_type)
348	{
349		case TYPE_1D:			delete m_binding.tex1D;			break;
350		case TYPE_2D:			delete m_binding.tex2D;			break;
351		case TYPE_3D:			delete m_binding.tex3D;			break;
352		case TYPE_CUBE_MAP:		delete m_binding.texCube;		break;
353		case TYPE_1D_ARRAY:		delete m_binding.tex1DArray;	break;
354		case TYPE_2D_ARRAY:		delete m_binding.tex2DArray;	break;
355		case TYPE_CUBE_ARRAY:	delete m_binding.texCubeArray;	break;
356		default:												break;
357	}
358}
359
360de::MovePtr<tcu::Texture2D> TextureBinding::loadTexture2D (const tcu::Archive& archive, const char* filename)
361{
362	tcu::TextureLevel level;
363	tcu::ImageIO::loadImage(level, archive, filename);
364
365	TCU_CHECK_INTERNAL(level.getFormat() == tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8) ||
366					   level.getFormat() == tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8));
367
368	// \todo [2015-10-08 elecro] for some reason we get better when using RGBA texture even in RGB case, this needs to be investigated
369	de::MovePtr<tcu::Texture2D> texture(new tcu::Texture2D(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), level.getWidth(), level.getHeight()));
370
371	// Fill level 0.
372	texture->allocLevel(0);
373	tcu::copy(texture->getLevel(0), level.getAccess());
374
375	return texture;
376}
377
378// ShaderEvalContext.
379
380ShaderEvalContext::ShaderEvalContext (const QuadGrid& quadGrid)
381	: constCoords	(quadGrid.getConstCoords())
382	, isDiscarded	(false)
383	, m_quadGrid	(quadGrid)
384{
385	const std::vector<TextureBindingSp>& bindings = m_quadGrid.getTextures();
386	DE_ASSERT((int)bindings.size() <= MAX_TEXTURES);
387
388	// Fill in texture array.
389	for (int ndx = 0; ndx < (int)bindings.size(); ndx++)
390	{
391		const TextureBinding& binding = *bindings[ndx];
392
393		if (binding.getType() == TextureBinding::TYPE_NONE)
394			continue;
395
396		textures[ndx].sampler = binding.getSampler();
397
398		switch (binding.getType())
399		{
400			case TextureBinding::TYPE_1D:			textures[ndx].tex1D			= &binding.get1D();			break;
401			case TextureBinding::TYPE_2D:			textures[ndx].tex2D			= &binding.get2D();			break;
402			case TextureBinding::TYPE_3D:			textures[ndx].tex3D			= &binding.get3D();			break;
403			case TextureBinding::TYPE_CUBE_MAP:		textures[ndx].texCube		= &binding.getCube();		break;
404			case TextureBinding::TYPE_1D_ARRAY:		textures[ndx].tex1DArray	= &binding.get1DArray();	break;
405			case TextureBinding::TYPE_2D_ARRAY:		textures[ndx].tex2DArray	= &binding.get2DArray();	break;
406			case TextureBinding::TYPE_CUBE_ARRAY:	textures[ndx].texCubeArray	= &binding.getCubeArray();	break;
407			default:
408				TCU_THROW(InternalError, "Handling of texture binding type not implemented");
409		}
410	}
411}
412
413ShaderEvalContext::~ShaderEvalContext (void)
414{
415}
416
417void ShaderEvalContext::reset (float sx, float sy)
418{
419	// Clear old values
420	color		= tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
421	isDiscarded	= false;
422
423	// Compute coords
424	coords		= m_quadGrid.getCoords(sx, sy);
425	unitCoords	= m_quadGrid.getUnitCoords(sx, sy);
426
427	// Compute user attributes.
428	const int numAttribs = m_quadGrid.getNumUserAttribs();
429	DE_ASSERT(numAttribs <= MAX_USER_ATTRIBS);
430	for (int attribNdx = 0; attribNdx < numAttribs; attribNdx++)
431		in[attribNdx] = m_quadGrid.getUserAttrib(attribNdx, sx, sy);
432}
433
434tcu::Vec4 ShaderEvalContext::texture2D (int unitNdx, const tcu::Vec2& texCoords)
435{
436	if (textures[unitNdx].tex2D)
437		return textures[unitNdx].tex2D->sample(textures[unitNdx].sampler, texCoords.x(), texCoords.y(), 0.0f);
438	else
439		return tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
440}
441
442// ShaderEvaluator.
443
444ShaderEvaluator::ShaderEvaluator (void)
445	: m_evalFunc(DE_NULL)
446{
447}
448
449ShaderEvaluator::ShaderEvaluator (ShaderEvalFunc evalFunc)
450	: m_evalFunc(evalFunc)
451{
452}
453
454ShaderEvaluator::~ShaderEvaluator (void)
455{
456}
457
458void ShaderEvaluator::evaluate (ShaderEvalContext& ctx) const
459{
460	DE_ASSERT(m_evalFunc);
461	m_evalFunc(ctx);
462}
463
464// UniformSetup.
465
466UniformSetup::UniformSetup (void)
467	: m_setupFunc(DE_NULL)
468{
469}
470
471UniformSetup::UniformSetup (UniformSetupFunc setupFunc)
472	: m_setupFunc(setupFunc)
473{
474}
475
476UniformSetup::~UniformSetup (void)
477{
478}
479
480void UniformSetup::setup (ShaderRenderCaseInstance& instance, const tcu::Vec4& constCoords) const
481{
482	if (m_setupFunc)
483		m_setupFunc(instance, constCoords);
484}
485
486// ShaderRenderCase.
487
488ShaderRenderCase::ShaderRenderCase (tcu::TestContext&			testCtx,
489									const std::string&			name,
490									const std::string&			description,
491									const bool					isVertexCase,
492									const ShaderEvalFunc		evalFunc,
493									const UniformSetup*			uniformSetup,
494									const AttributeSetupFunc	attribFunc)
495	: vkt::TestCase		(testCtx, name, description)
496	, m_isVertexCase	(isVertexCase)
497	, m_evaluator		(new ShaderEvaluator(evalFunc))
498	, m_uniformSetup	(uniformSetup ? uniformSetup : new UniformSetup())
499	, m_attribFunc		(attribFunc)
500{}
501
502ShaderRenderCase::ShaderRenderCase (tcu::TestContext&			testCtx,
503									const std::string&			name,
504									const std::string&			description,
505									const bool					isVertexCase,
506									const ShaderEvaluator*		evaluator,
507									const UniformSetup*			uniformSetup,
508									const AttributeSetupFunc	attribFunc)
509	: vkt::TestCase		(testCtx, name, description)
510	, m_isVertexCase	(isVertexCase)
511	, m_evaluator		(evaluator)
512	, m_uniformSetup	(uniformSetup ? uniformSetup : new UniformSetup())
513	, m_attribFunc		(attribFunc)
514{}
515
516ShaderRenderCase::~ShaderRenderCase (void)
517{
518}
519
520void ShaderRenderCase::initPrograms (vk::SourceCollections& programCollection) const
521{
522	programCollection.glslSources.add("vert") << glu::VertexSource(m_vertShaderSource);
523	programCollection.glslSources.add("frag") << glu::FragmentSource(m_fragShaderSource);
524}
525
526TestInstance* ShaderRenderCase::createInstance (Context& context) const
527{
528	DE_ASSERT(m_evaluator != DE_NULL);
529	DE_ASSERT(m_uniformSetup != DE_NULL);
530	return new ShaderRenderCaseInstance(context, m_isVertexCase, *m_evaluator, *m_uniformSetup, m_attribFunc);
531}
532
533// ShaderRenderCaseInstance.
534
535ShaderRenderCaseInstance::ShaderRenderCaseInstance (Context& context)
536	: vkt::TestInstance		(context)
537	, m_memAlloc			(context.getDefaultAllocator())
538	, m_clearColor			(DEFAULT_CLEAR_COLOR)
539	, m_isVertexCase		(false)
540	, m_vertexShaderName	("vert")
541	, m_fragmentShaderName	("frag")
542	, m_renderSize			(128, 128)
543	, m_colorFormat			(VK_FORMAT_R8G8B8A8_UNORM)
544	, m_evaluator			(DE_NULL)
545	, m_uniformSetup		(DE_NULL)
546	, m_attribFunc			(DE_NULL)
547	, m_sparseContext		(createSparseContext())
548	, m_sampleCount			(VK_SAMPLE_COUNT_1_BIT)
549{
550}
551
552
553ShaderRenderCaseInstance::ShaderRenderCaseInstance (Context&					context,
554													const bool					isVertexCase,
555													const ShaderEvaluator&		evaluator,
556													const UniformSetup&			uniformSetup,
557													const AttributeSetupFunc	attribFunc,
558													const ImageBackingMode		imageBackingMode)
559	: vkt::TestInstance		(context)
560	, m_memAlloc			(context.getDefaultAllocator())
561	, m_clearColor			(DEFAULT_CLEAR_COLOR)
562	, m_isVertexCase		(isVertexCase)
563	, m_vertexShaderName	("vert")
564	, m_fragmentShaderName	("frag")
565	, m_renderSize			(128, 128)
566	, m_colorFormat			(VK_FORMAT_R8G8B8A8_UNORM)
567	, m_imageBackingMode	(imageBackingMode)
568	, m_evaluator			(&evaluator)
569	, m_uniformSetup		(&uniformSetup)
570	, m_attribFunc			(attribFunc)
571	, m_sparseContext		(createSparseContext())
572	, m_sampleCount			(VK_SAMPLE_COUNT_1_BIT)
573{
574}
575
576ShaderRenderCaseInstance::ShaderRenderCaseInstance (Context&					context,
577													const bool					isVertexCase,
578													const ShaderEvaluator*		evaluator,
579													const UniformSetup*			uniformSetup,
580													const AttributeSetupFunc	attribFunc,
581													const ImageBackingMode		imageBackingMode)
582	: vkt::TestInstance		(context)
583	, m_memAlloc			(context.getDefaultAllocator())
584	, m_clearColor			(DEFAULT_CLEAR_COLOR)
585	, m_isVertexCase		(isVertexCase)
586	, m_vertexShaderName	("vert")
587	, m_fragmentShaderName	("frag")
588	, m_renderSize			(128, 128)
589	, m_colorFormat			(VK_FORMAT_R8G8B8A8_UNORM)
590	, m_imageBackingMode	(imageBackingMode)
591	, m_evaluator			(evaluator)
592	, m_uniformSetup		(uniformSetup)
593	, m_attribFunc			(attribFunc)
594	, m_sparseContext		(createSparseContext())
595	, m_sampleCount			(VK_SAMPLE_COUNT_1_BIT)
596{
597}
598
599static deUint32 findQueueFamilyIndexWithCaps (const InstanceInterface& vkInstance, VkPhysicalDevice physicalDevice, VkQueueFlags requiredCaps)
600{
601	const std::vector<VkQueueFamilyProperties>	queueProps	= getPhysicalDeviceQueueFamilyProperties(vkInstance, physicalDevice);
602
603	for (size_t queueNdx = 0; queueNdx < queueProps.size(); queueNdx++)
604	{
605		if ((queueProps[queueNdx].queueFlags & requiredCaps) == requiredCaps)
606			return (deUint32)queueNdx;
607	}
608
609	TCU_THROW(NotSupportedError, "No matching queue found");
610}
611
612ShaderRenderCaseInstance::SparseContext* ShaderRenderCaseInstance::createSparseContext (void) const
613{
614	if (m_imageBackingMode == IMAGE_BACKING_MODE_SPARSE)
615	{
616		const InstanceInterface&		vk				= getInstanceInterface();
617		const VkPhysicalDevice			physicalDevice	= getPhysicalDevice();
618		const VkPhysicalDeviceFeatures	deviceFeatures	= getPhysicalDeviceFeatures(vk, physicalDevice);
619
620		const deUint32 queueIndex = findQueueFamilyIndexWithCaps(vk, physicalDevice, VK_QUEUE_GRAPHICS_BIT|VK_QUEUE_SPARSE_BINDING_BIT);
621
622		VkDeviceQueueCreateInfo			queueInfo;
623		VkDeviceCreateInfo				deviceInfo;
624		const float						queuePriority	= 1.0f;
625
626		deMemset(&queueInfo,	0, sizeof(queueInfo));
627		deMemset(&deviceInfo,	0, sizeof(deviceInfo));
628
629		queueInfo.sType							= VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
630		queueInfo.pNext							= DE_NULL;
631		queueInfo.flags							= (VkDeviceQueueCreateFlags)0u;
632		queueInfo.queueFamilyIndex				= queueIndex;
633		queueInfo.queueCount					= 1u;
634		queueInfo.pQueuePriorities				= &queuePriority;
635
636		deviceInfo.sType						= VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
637		deviceInfo.pNext						= DE_NULL;
638		deviceInfo.queueCreateInfoCount			= 1u;
639		deviceInfo.pQueueCreateInfos			= &queueInfo;
640		deviceInfo.enabledExtensionCount		= 0u;
641		deviceInfo.ppEnabledExtensionNames		= DE_NULL;
642		deviceInfo.enabledLayerCount			= 0u;
643		deviceInfo.ppEnabledLayerNames			= DE_NULL;
644		deviceInfo.pEnabledFeatures				= &deviceFeatures;
645
646		Move<VkDevice>	device = createDevice(vk, physicalDevice, &deviceInfo);
647
648		return new SparseContext(device, queueIndex, vk);
649	}
650
651	return DE_NULL;
652}
653
654ShaderRenderCaseInstance::~ShaderRenderCaseInstance (void)
655{
656}
657
658VkDevice ShaderRenderCaseInstance::getDevice (void) const
659{
660	if (m_imageBackingMode == IMAGE_BACKING_MODE_SPARSE)
661		return *m_sparseContext->m_device;
662
663	return m_context.getDevice();
664}
665
666deUint32 ShaderRenderCaseInstance::getUniversalQueueFamilyIndex	(void) const
667{
668	if (m_imageBackingMode == IMAGE_BACKING_MODE_SPARSE)
669		return m_sparseContext->m_universalQueueFamilyIndex;
670
671	return m_context.getUniversalQueueFamilyIndex();
672}
673
674const DeviceInterface& ShaderRenderCaseInstance::getDeviceInterface (void) const
675{
676	if (m_imageBackingMode == IMAGE_BACKING_MODE_SPARSE)
677		return m_sparseContext->m_deviceInterface;
678
679	return m_context.getDeviceInterface();
680}
681
682VkQueue ShaderRenderCaseInstance::getUniversalQueue (void) const
683{
684	if (m_imageBackingMode == IMAGE_BACKING_MODE_SPARSE)
685		return m_sparseContext->m_queue;
686
687	return m_context.getUniversalQueue();
688}
689
690VkPhysicalDevice ShaderRenderCaseInstance::getPhysicalDevice (void) const
691{
692	// Same in sparse and regular case
693	return m_context.getPhysicalDevice();
694}
695
696const InstanceInterface& ShaderRenderCaseInstance::getInstanceInterface (void) const
697{
698	// Same in sparse and regular case
699	return m_context.getInstanceInterface();
700}
701
702tcu::TestStatus ShaderRenderCaseInstance::iterate (void)
703{
704	setup();
705
706	// Create quad grid.
707	const tcu::UVec2	viewportSize	= getViewportSize();
708	const int			width			= viewportSize.x();
709	const int			height			= viewportSize.y();
710
711	m_quadGrid							= de::MovePtr<QuadGrid>(new QuadGrid(m_isVertexCase ? GRID_SIZE : 4, width, height, getDefaultConstCoords(), m_userAttribTransforms, m_textures));
712
713	// Render result.
714	tcu::Surface		resImage		(width, height);
715
716	render(m_quadGrid->getNumVertices(), m_quadGrid->getNumTriangles(), m_quadGrid->getIndices(), m_quadGrid->getConstCoords());
717	tcu::copy(resImage.getAccess(), m_resultImage.getAccess());
718
719	// Compute reference.
720	tcu::Surface		refImage		(width, height);
721	if (m_isVertexCase)
722		computeVertexReference(refImage, *m_quadGrid);
723	else
724		computeFragmentReference(refImage, *m_quadGrid);
725
726	// Compare.
727	const bool			compareOk		= compareImages(resImage, refImage, 0.1f);
728
729	if (compareOk)
730		return tcu::TestStatus::pass("Result image matches reference");
731	else
732		return tcu::TestStatus::fail("Image mismatch");
733}
734
735void ShaderRenderCaseInstance::setup (void)
736{
737	m_resultImage					= tcu::TextureLevel();
738	m_descriptorSetLayoutBuilder	= de::MovePtr<DescriptorSetLayoutBuilder>	(new DescriptorSetLayoutBuilder());
739	m_descriptorPoolBuilder			= de::MovePtr<DescriptorPoolBuilder>		(new DescriptorPoolBuilder());
740	m_descriptorSetUpdateBuilder	= de::MovePtr<DescriptorSetUpdateBuilder>	(new DescriptorSetUpdateBuilder());
741
742	m_uniformInfos.clear();
743	m_vertexBindingDescription.clear();
744	m_vertexAttributeDescription.clear();
745	m_vertexBuffers.clear();
746	m_vertexBufferAllocs.clear();
747}
748
749void ShaderRenderCaseInstance::setupUniformData (deUint32 bindingLocation, size_t size, const void* dataPtr)
750{
751	const VkDevice					vkDevice			= getDevice();
752	const DeviceInterface&			vk					= getDeviceInterface();
753	const deUint32					queueFamilyIndex	= getUniversalQueueFamilyIndex();
754
755	const VkBufferCreateInfo		uniformBufferParams	=
756	{
757		VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
758		DE_NULL,									// const void*			pNext;
759		0u,											// VkBufferCreateFlags	flags;
760		size,										// VkDeviceSize			size;
761		VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,			// VkBufferUsageFlags	usage;
762		VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
763		1u,											// deUint32				queueFamilyCount;
764		&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
765	};
766
767	Move<VkBuffer>					buffer				= createBuffer(vk, vkDevice, &uniformBufferParams);
768	de::MovePtr<Allocation>			alloc				= m_memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *buffer), MemoryRequirement::HostVisible);
769	VK_CHECK(vk.bindBufferMemory(vkDevice, *buffer, alloc->getMemory(), alloc->getOffset()));
770
771	deMemcpy(alloc->getHostPtr(), dataPtr, size);
772	flushMappedMemoryRange(vk, vkDevice, alloc->getMemory(), alloc->getOffset(), size);
773
774	de::MovePtr<BufferUniform> uniformInfo(new BufferUniform());
775	uniformInfo->type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
776	uniformInfo->descriptor = makeDescriptorBufferInfo(*buffer, 0u, size);
777	uniformInfo->location = bindingLocation;
778	uniformInfo->buffer = VkBufferSp(new vk::Unique<VkBuffer>(buffer));
779	uniformInfo->alloc = AllocationSp(alloc.release());
780
781	m_uniformInfos.push_back(UniformInfoSp(new de::UniquePtr<UniformInfo>(uniformInfo)));
782}
783
784void ShaderRenderCaseInstance::addUniform (deUint32 bindingLocation, vk::VkDescriptorType descriptorType, size_t dataSize, const void* data)
785{
786	m_descriptorSetLayoutBuilder->addSingleBinding(descriptorType, vk::VK_SHADER_STAGE_ALL);
787	m_descriptorPoolBuilder->addType(descriptorType);
788
789	setupUniformData(bindingLocation, dataSize, data);
790}
791
792void ShaderRenderCaseInstance::addAttribute (deUint32		bindingLocation,
793											 vk::VkFormat	format,
794											 deUint32		sizePerElement,
795											 deUint32		count,
796											 const void*	dataPtr)
797{
798	// Add binding specification
799	const deUint32							binding					= (deUint32)m_vertexBindingDescription.size();
800	const VkVertexInputBindingDescription	bindingDescription		=
801	{
802		binding,							// deUint32				binding;
803		sizePerElement,						// deUint32				stride;
804		VK_VERTEX_INPUT_RATE_VERTEX			// VkVertexInputRate	stepRate;
805	};
806
807	m_vertexBindingDescription.push_back(bindingDescription);
808
809	// Add location and format specification
810	const VkVertexInputAttributeDescription	attributeDescription	=
811	{
812		bindingLocation,			// deUint32	location;
813		binding,					// deUint32	binding;
814		format,						// VkFormat	format;
815		0u,							// deUint32	offset;
816	};
817
818	m_vertexAttributeDescription.push_back(attributeDescription);
819
820	// Upload data to buffer
821	const VkDevice							vkDevice				= getDevice();
822	const DeviceInterface&					vk						= getDeviceInterface();
823	const deUint32							queueFamilyIndex		= getUniversalQueueFamilyIndex();
824
825	const VkDeviceSize						inputSize				= sizePerElement * count;
826	const VkBufferCreateInfo				vertexBufferParams		=
827	{
828		VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
829		DE_NULL,									// const void*			pNext;
830		0u,											// VkBufferCreateFlags	flags;
831		inputSize,									// VkDeviceSize			size;
832		VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,			// VkBufferUsageFlags	usage;
833		VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
834		1u,											// deUint32				queueFamilyCount;
835		&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
836	};
837
838	Move<VkBuffer>							buffer					= createBuffer(vk, vkDevice, &vertexBufferParams);
839	de::MovePtr<vk::Allocation>				alloc					= m_memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *buffer), MemoryRequirement::HostVisible);
840	VK_CHECK(vk.bindBufferMemory(vkDevice, *buffer, alloc->getMemory(), alloc->getOffset()));
841
842	deMemcpy(alloc->getHostPtr(), dataPtr, (size_t)inputSize);
843	flushMappedMemoryRange(vk, vkDevice, alloc->getMemory(), alloc->getOffset(), inputSize);
844
845	m_vertexBuffers.push_back(VkBufferSp(new vk::Unique<VkBuffer>(buffer)));
846	m_vertexBufferAllocs.push_back(AllocationSp(alloc.release()));
847}
848
849void ShaderRenderCaseInstance::useAttribute (deUint32 bindingLocation, BaseAttributeType type)
850{
851	const EnabledBaseAttribute attribute =
852	{
853		bindingLocation,	// deUint32				location;
854		type				// BaseAttributeType	type;
855	};
856	m_enabledBaseAttributes.push_back(attribute);
857}
858
859void ShaderRenderCaseInstance::setupUniforms (const tcu::Vec4& constCoords)
860{
861	if (m_uniformSetup)
862		m_uniformSetup->setup(*this, constCoords);
863}
864
865void ShaderRenderCaseInstance::useUniform (deUint32 bindingLocation, BaseUniformType type)
866{
867	#define UNIFORM_CASE(type, value) case type: addUniform(bindingLocation, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, value); break
868
869	switch(type)
870	{
871		// Bool
872		UNIFORM_CASE(UB_FALSE,	0);
873		UNIFORM_CASE(UB_TRUE,	1);
874
875		// BVec4
876		UNIFORM_CASE(UB4_FALSE,	tcu::Vec4(0));
877		UNIFORM_CASE(UB4_TRUE,	tcu::Vec4(1));
878
879		// Integer
880		UNIFORM_CASE(UI_ZERO,	0);
881		UNIFORM_CASE(UI_ONE,	1);
882		UNIFORM_CASE(UI_TWO,	2);
883		UNIFORM_CASE(UI_THREE,	3);
884		UNIFORM_CASE(UI_FOUR,	4);
885		UNIFORM_CASE(UI_FIVE,	5);
886		UNIFORM_CASE(UI_SIX,	6);
887		UNIFORM_CASE(UI_SEVEN,	7);
888		UNIFORM_CASE(UI_EIGHT,	8);
889		UNIFORM_CASE(UI_ONEHUNDREDONE, 101);
890
891		// IVec2
892		UNIFORM_CASE(UI2_MINUS_ONE,	tcu::IVec2(-1));
893		UNIFORM_CASE(UI2_ZERO,		tcu::IVec2(0));
894		UNIFORM_CASE(UI2_ONE,		tcu::IVec2(1));
895		UNIFORM_CASE(UI2_TWO,		tcu::IVec2(2));
896		UNIFORM_CASE(UI2_THREE,		tcu::IVec2(3));
897		UNIFORM_CASE(UI2_FOUR,		tcu::IVec2(4));
898		UNIFORM_CASE(UI2_FIVE,		tcu::IVec2(5));
899
900		// IVec3
901		UNIFORM_CASE(UI3_MINUS_ONE,	tcu::IVec3(-1));
902		UNIFORM_CASE(UI3_ZERO,		tcu::IVec3(0));
903		UNIFORM_CASE(UI3_ONE,		tcu::IVec3(1));
904		UNIFORM_CASE(UI3_TWO,		tcu::IVec3(2));
905		UNIFORM_CASE(UI3_THREE,		tcu::IVec3(3));
906		UNIFORM_CASE(UI3_FOUR,		tcu::IVec3(4));
907		UNIFORM_CASE(UI3_FIVE,		tcu::IVec3(5));
908
909		// IVec4
910		UNIFORM_CASE(UI4_MINUS_ONE, tcu::IVec4(-1));
911		UNIFORM_CASE(UI4_ZERO,		tcu::IVec4(0));
912		UNIFORM_CASE(UI4_ONE,		tcu::IVec4(1));
913		UNIFORM_CASE(UI4_TWO,		tcu::IVec4(2));
914		UNIFORM_CASE(UI4_THREE,		tcu::IVec4(3));
915		UNIFORM_CASE(UI4_FOUR,		tcu::IVec4(4));
916		UNIFORM_CASE(UI4_FIVE,		tcu::IVec4(5));
917
918		// Float
919		UNIFORM_CASE(UF_ZERO,		0.0f);
920		UNIFORM_CASE(UF_ONE,		1.0f);
921		UNIFORM_CASE(UF_TWO,		2.0f);
922		UNIFORM_CASE(UF_THREE,		3.0f);
923		UNIFORM_CASE(UF_FOUR,		4.0f);
924		UNIFORM_CASE(UF_FIVE,		5.0f);
925		UNIFORM_CASE(UF_SIX,		6.0f);
926		UNIFORM_CASE(UF_SEVEN,		7.0f);
927		UNIFORM_CASE(UF_EIGHT,		8.0f);
928
929		UNIFORM_CASE(UF_HALF,		1.0f / 2.0f);
930		UNIFORM_CASE(UF_THIRD,		1.0f / 3.0f);
931		UNIFORM_CASE(UF_FOURTH,		1.0f / 4.0f);
932		UNIFORM_CASE(UF_FIFTH,		1.0f / 5.0f);
933		UNIFORM_CASE(UF_SIXTH,		1.0f / 6.0f);
934		UNIFORM_CASE(UF_SEVENTH,	1.0f / 7.0f);
935		UNIFORM_CASE(UF_EIGHTH,		1.0f / 8.0f);
936
937		// Vec2
938		UNIFORM_CASE(UV2_MINUS_ONE,	tcu::Vec2(-1.0f));
939		UNIFORM_CASE(UV2_ZERO,		tcu::Vec2(0.0f));
940		UNIFORM_CASE(UV2_ONE,		tcu::Vec2(1.0f));
941		UNIFORM_CASE(UV2_TWO,		tcu::Vec2(2.0f));
942		UNIFORM_CASE(UV2_THREE,		tcu::Vec2(3.0f));
943
944		UNIFORM_CASE(UV2_HALF,		tcu::Vec2(1.0f / 2.0f));
945
946		// Vec3
947		UNIFORM_CASE(UV3_MINUS_ONE,	tcu::Vec3(-1.0f));
948		UNIFORM_CASE(UV3_ZERO,		tcu::Vec3(0.0f));
949		UNIFORM_CASE(UV3_ONE,		tcu::Vec3(1.0f));
950		UNIFORM_CASE(UV3_TWO,		tcu::Vec3(2.0f));
951		UNIFORM_CASE(UV3_THREE,		tcu::Vec3(3.0f));
952
953		UNIFORM_CASE(UV3_HALF,		tcu::Vec3(1.0f / 2.0f));
954
955		// Vec4
956		UNIFORM_CASE(UV4_MINUS_ONE,	tcu::Vec4(-1.0f));
957		UNIFORM_CASE(UV4_ZERO,		tcu::Vec4(0.0f));
958		UNIFORM_CASE(UV4_ONE,		tcu::Vec4(1.0f));
959		UNIFORM_CASE(UV4_TWO,		tcu::Vec4(2.0f));
960		UNIFORM_CASE(UV4_THREE,		tcu::Vec4(3.0f));
961
962		UNIFORM_CASE(UV4_HALF,		tcu::Vec4(1.0f / 2.0f));
963
964		UNIFORM_CASE(UV4_BLACK,		tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
965		UNIFORM_CASE(UV4_GRAY,		tcu::Vec4(0.5f, 0.5f, 0.5f, 1.0f));
966		UNIFORM_CASE(UV4_WHITE,		tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
967
968		default:
969			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Unknown Uniform type: " << type << tcu::TestLog::EndMessage;
970			break;
971	}
972
973	#undef UNIFORM_CASE
974}
975
976const tcu::UVec2 ShaderRenderCaseInstance::getViewportSize (void) const
977{
978	return tcu::UVec2(de::min(m_renderSize.x(), MAX_RENDER_WIDTH),
979					  de::min(m_renderSize.y(), MAX_RENDER_HEIGHT));
980}
981
982void ShaderRenderCaseInstance::setSampleCount (VkSampleCountFlagBits sampleCount)
983{
984	m_sampleCount	= sampleCount;
985}
986
987bool ShaderRenderCaseInstance::isMultiSampling (void) const
988{
989	return m_sampleCount != VK_SAMPLE_COUNT_1_BIT;
990}
991
992void ShaderRenderCaseInstance::uploadImage (const tcu::TextureFormat&			texFormat,
993											const TextureData&					textureData,
994											const tcu::Sampler&					refSampler,
995											deUint32							mipLevels,
996											deUint32							arrayLayers,
997											VkImage								destImage)
998{
999	const VkDevice					vkDevice				= getDevice();
1000	const DeviceInterface&			vk						= getDeviceInterface();
1001	const VkQueue					queue					= getUniversalQueue();
1002	const deUint32					queueFamilyIndex		= getUniversalQueueFamilyIndex();
1003
1004	const bool						isShadowSampler			= refSampler.compare != tcu::Sampler::COMPAREMODE_NONE;
1005	const VkImageAspectFlags		aspectMask				= isShadowSampler ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT;
1006	deUint32						bufferSize				= 0u;
1007	Move<VkBuffer>					buffer;
1008	de::MovePtr<Allocation>			bufferAlloc;
1009	Move<VkCommandPool>				cmdPool;
1010	Move<VkCommandBuffer>			cmdBuffer;
1011	Move<VkFence>					fence;
1012	std::vector<VkBufferImageCopy>	copyRegions;
1013	std::vector<deUint32>			offsetMultiples;
1014
1015	offsetMultiples.push_back(4u);
1016	offsetMultiples.push_back(texFormat.getPixelSize());
1017
1018	// Calculate buffer size
1019	for (TextureData::const_iterator mit = textureData.begin(); mit != textureData.end(); ++mit)
1020	{
1021		for (TextureLayerData::const_iterator lit = mit->begin(); lit != mit->end(); ++lit)
1022		{
1023			const tcu::ConstPixelBufferAccess&	access	= *lit;
1024
1025			bufferSize = getNextMultiple(offsetMultiples, bufferSize);
1026			bufferSize += access.getWidth() * access.getHeight() * access.getDepth() * access.getFormat().getPixelSize();
1027		}
1028	}
1029
1030	// Create source buffer
1031	{
1032		const VkBufferCreateInfo bufferParams =
1033		{
1034			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
1035			DE_NULL,									// const void*			pNext;
1036			0u,											// VkBufferCreateFlags	flags;
1037			bufferSize,									// VkDeviceSize			size;
1038			VK_BUFFER_USAGE_TRANSFER_SRC_BIT,			// VkBufferUsageFlags	usage;
1039			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
1040			0u,											// deUint32				queueFamilyIndexCount;
1041			DE_NULL,									// const deUint32*		pQueueFamilyIndices;
1042		};
1043
1044		buffer		= createBuffer(vk, vkDevice, &bufferParams);
1045		bufferAlloc = m_memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *buffer), MemoryRequirement::HostVisible);
1046		VK_CHECK(vk.bindBufferMemory(vkDevice, *buffer, bufferAlloc->getMemory(), bufferAlloc->getOffset()));
1047	}
1048
1049	// Create command pool and buffer
1050	{
1051		const VkCommandPoolCreateInfo cmdPoolParams =
1052		{
1053			VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,		// VkStructureType			sType;
1054			DE_NULL,										// const void*				pNext;
1055			VK_COMMAND_POOL_CREATE_TRANSIENT_BIT,			// VkCommandPoolCreateFlags	flags;
1056			queueFamilyIndex,								// deUint32					queueFamilyIndex;
1057		};
1058
1059		cmdPool = createCommandPool(vk, vkDevice, &cmdPoolParams);
1060
1061		const VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
1062		{
1063			VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,	// VkStructureType			sType;
1064			DE_NULL,										// const void*				pNext;
1065			*cmdPool,										// VkCommandPool			commandPool;
1066			VK_COMMAND_BUFFER_LEVEL_PRIMARY,				// VkCommandBufferLevel		level;
1067			1u,												// deUint32					bufferCount;
1068		};
1069
1070		cmdBuffer = allocateCommandBuffer(vk, vkDevice, &cmdBufferAllocateInfo);
1071	}
1072
1073	// Create fence
1074	{
1075		const VkFenceCreateInfo fenceParams =
1076		{
1077			VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,		// VkStructureType		sType;
1078			DE_NULL,									// const void*			pNext;
1079			0u											// VkFenceCreateFlags	flags;
1080		};
1081
1082		fence = createFence(vk, vkDevice, &fenceParams);
1083	}
1084
1085	// Barriers for copying buffer to image
1086	const VkBufferMemoryBarrier preBufferBarrier =
1087	{
1088		VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	// VkStructureType	sType;
1089		DE_NULL,									// const void*		pNext;
1090		VK_ACCESS_HOST_WRITE_BIT,					// VkAccessFlags	srcAccessMask;
1091		VK_ACCESS_TRANSFER_READ_BIT,				// VkAccessFlags	dstAccessMask;
1092		VK_QUEUE_FAMILY_IGNORED,					// deUint32			srcQueueFamilyIndex;
1093		VK_QUEUE_FAMILY_IGNORED,					// deUint32			dstQueueFamilyIndex;
1094		*buffer,									// VkBuffer			buffer;
1095		0u,											// VkDeviceSize		offset;
1096		bufferSize									// VkDeviceSize		size;
1097	};
1098
1099	const VkImageMemoryBarrier preImageBarrier =
1100	{
1101		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType			sType;
1102		DE_NULL,										// const void*				pNext;
1103		0u,												// VkAccessFlags			srcAccessMask;
1104		VK_ACCESS_TRANSFER_WRITE_BIT,					// VkAccessFlags			dstAccessMask;
1105		VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout			oldLayout;
1106		VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,			// VkImageLayout			newLayout;
1107		VK_QUEUE_FAMILY_IGNORED,						// deUint32					srcQueueFamilyIndex;
1108		VK_QUEUE_FAMILY_IGNORED,						// deUint32					dstQueueFamilyIndex;
1109		destImage,										// VkImage					image;
1110		{												// VkImageSubresourceRange	subresourceRange;
1111			aspectMask,								// VkImageAspect	aspect;
1112			0u,										// deUint32			baseMipLevel;
1113			mipLevels,								// deUint32			mipLevels;
1114			0u,										// deUint32			baseArraySlice;
1115			arrayLayers								// deUint32			arraySize;
1116		}
1117	};
1118
1119	const VkImageMemoryBarrier postImageBarrier =
1120	{
1121		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType			sType;
1122		DE_NULL,										// const void*				pNext;
1123		VK_ACCESS_TRANSFER_WRITE_BIT,					// VkAccessFlags			srcAccessMask;
1124		VK_ACCESS_SHADER_READ_BIT,						// VkAccessFlags			dstAccessMask;
1125		VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,			// VkImageLayout			oldLayout;
1126		VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,		// VkImageLayout			newLayout;
1127		VK_QUEUE_FAMILY_IGNORED,						// deUint32					srcQueueFamilyIndex;
1128		VK_QUEUE_FAMILY_IGNORED,						// deUint32					dstQueueFamilyIndex;
1129		destImage,										// VkImage					image;
1130		{												// VkImageSubresourceRange	subresourceRange;
1131			aspectMask,								// VkImageAspect	aspect;
1132			0u,										// deUint32			baseMipLevel;
1133			mipLevels,								// deUint32			mipLevels;
1134			0u,										// deUint32			baseArraySlice;
1135			arrayLayers								// deUint32			arraySize;
1136		}
1137	};
1138
1139	const VkCommandBufferBeginInfo cmdBufferBeginInfo =
1140	{
1141		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,	// VkStructureType					sType;
1142		DE_NULL,										// const void*						pNext;
1143		VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,	// VkCommandBufferUsageFlags		flags;
1144		(const VkCommandBufferInheritanceInfo*)DE_NULL,
1145	};
1146
1147	// Get copy regions and write buffer data
1148	{
1149		deUint32	layerDataOffset		= 0;
1150		deUint8*	destPtr				= (deUint8*)bufferAlloc->getHostPtr();
1151
1152		for (size_t levelNdx = 0; levelNdx < textureData.size(); levelNdx++)
1153		{
1154			const TextureLayerData&		layerData	= textureData[levelNdx];
1155
1156			for (size_t layerNdx = 0; layerNdx < layerData.size(); layerNdx++)
1157			{
1158				layerDataOffset = getNextMultiple(offsetMultiples, layerDataOffset);
1159
1160				const tcu::ConstPixelBufferAccess&	access		= layerData[layerNdx];
1161				const tcu::PixelBufferAccess		destAccess	(access.getFormat(), access.getSize(), destPtr + layerDataOffset);
1162
1163				const VkBufferImageCopy				layerRegion =
1164				{
1165					layerDataOffset,						// VkDeviceSize				bufferOffset;
1166					(deUint32)access.getWidth(),			// deUint32					bufferRowLength;
1167					(deUint32)access.getHeight(),			// deUint32					bufferImageHeight;
1168					{										// VkImageSubresourceLayers	imageSubresource;
1169						aspectMask,								// VkImageAspectFlags		aspectMask;
1170						(deUint32)levelNdx,						// uint32_t					mipLevel;
1171						(deUint32)layerNdx,						// uint32_t					baseArrayLayer;
1172						1u										// uint32_t					layerCount;
1173					},
1174					{ 0u, 0u, 0u },							// VkOffset3D			imageOffset;
1175					{										// VkExtent3D			imageExtent;
1176						(deUint32)access.getWidth(),
1177						(deUint32)access.getHeight(),
1178						(deUint32)access.getDepth()
1179					}
1180				};
1181
1182				copyRegions.push_back(layerRegion);
1183				tcu::copy(destAccess, access);
1184
1185				layerDataOffset += access.getWidth() * access.getHeight() * access.getDepth() * access.getFormat().getPixelSize();
1186			}
1187		}
1188	}
1189
1190	flushMappedMemoryRange(vk, vkDevice, bufferAlloc->getMemory(), bufferAlloc->getOffset(), bufferSize);
1191
1192	// Copy buffer to image
1193	VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufferBeginInfo));
1194	vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &preBufferBarrier, 1, &preImageBarrier);
1195	vk.cmdCopyBufferToImage(*cmdBuffer, *buffer, destImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, (deUint32)copyRegions.size(), copyRegions.data());
1196	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);
1197	VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1198
1199	const VkSubmitInfo submitInfo =
1200	{
1201		VK_STRUCTURE_TYPE_SUBMIT_INFO,	// VkStructureType				sType;
1202		DE_NULL,						// const void*					pNext;
1203		0u,								// deUint32						waitSemaphoreCount;
1204		DE_NULL,						// const VkSemaphore*			pWaitSemaphores;
1205		DE_NULL,						// const VkPipelineStageFlags*	pWaitDstStageMask;
1206		1u,								// deUint32						commandBufferCount;
1207		&cmdBuffer.get(),				// const VkCommandBuffer*		pCommandBuffers;
1208		0u,								// deUint32						signalSemaphoreCount;
1209		DE_NULL							// const VkSemaphore*			pSignalSemaphores;
1210	};
1211
1212	VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *fence));
1213	VK_CHECK(vk.waitForFences(vkDevice, 1, &fence.get(), true, ~(0ull) /* infinity */));
1214}
1215
1216// Sparse utility function
1217Move<VkSemaphore> makeSemaphore (const DeviceInterface& vk, const VkDevice device)
1218{
1219	const VkSemaphoreCreateInfo semaphoreCreateInfo =
1220	{
1221		VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
1222		DE_NULL,
1223		0u
1224	};
1225
1226	return createSemaphore(vk, device, &semaphoreCreateInfo);
1227}
1228
1229VkExtent3D mipLevelExtents (const VkExtent3D& baseExtents, const deUint32 mipLevel)
1230{
1231	VkExtent3D result;
1232
1233	result.width	= std::max(baseExtents.width  >> mipLevel, 1u);
1234	result.height	= std::max(baseExtents.height >> mipLevel, 1u);
1235	result.depth	= std::max(baseExtents.depth  >> mipLevel, 1u);
1236
1237	return result;
1238}
1239
1240tcu::UVec3 alignedDivide (const VkExtent3D& extent, const VkExtent3D& divisor)
1241{
1242	tcu::UVec3 result;
1243
1244	result.x() = extent.width  / divisor.width  + ((extent.width  % divisor.width != 0)  ? 1u : 0u);
1245	result.y() = extent.height / divisor.height + ((extent.height % divisor.height != 0) ? 1u : 0u);
1246	result.z() = extent.depth  / divisor.depth  + ((extent.depth  % divisor.depth != 0)  ? 1u : 0u);
1247
1248	return result;
1249}
1250
1251bool isImageSizeSupported (const VkImageType imageType, const tcu::UVec3& imageSize, const vk::VkPhysicalDeviceLimits& limits)
1252{
1253	switch (imageType)
1254	{
1255		case VK_IMAGE_TYPE_1D:
1256			return (imageSize.x() <= limits.maxImageDimension1D
1257				 && imageSize.y() == 1
1258				 && imageSize.z() == 1);
1259		case VK_IMAGE_TYPE_2D:
1260			return (imageSize.x() <= limits.maxImageDimension2D
1261				 && imageSize.y() <= limits.maxImageDimension2D
1262				 && imageSize.z() == 1);
1263		case VK_IMAGE_TYPE_3D:
1264			return (imageSize.x() <= limits.maxImageDimension3D
1265				 && imageSize.y() <= limits.maxImageDimension3D
1266				 && imageSize.z() <= limits.maxImageDimension3D);
1267		default:
1268			DE_FATAL("Unknown image type");
1269			return false;
1270	}
1271}
1272
1273void ShaderRenderCaseInstance::checkSparseSupport (const VkImageType imageType) const
1274{
1275	const InstanceInterface&		instance		= getInstanceInterface();
1276	const VkPhysicalDevice			physicalDevice	= getPhysicalDevice();
1277	const VkPhysicalDeviceFeatures	deviceFeatures	= getPhysicalDeviceFeatures(instance, physicalDevice);
1278
1279	if (!deviceFeatures.shaderResourceResidency)
1280		TCU_THROW(NotSupportedError, "Required feature: shaderResourceResidency.");
1281
1282	if (!deviceFeatures.sparseBinding)
1283		TCU_THROW(NotSupportedError, "Required feature: sparseBinding.");
1284
1285	if (imageType == VK_IMAGE_TYPE_2D && !deviceFeatures.sparseResidencyImage2D)
1286		TCU_THROW(NotSupportedError, "Required feature: sparseResidencyImage2D.");
1287
1288	if (imageType == VK_IMAGE_TYPE_3D && !deviceFeatures.sparseResidencyImage3D)
1289		TCU_THROW(NotSupportedError, "Required feature: sparseResidencyImage3D.");
1290}
1291
1292void ShaderRenderCaseInstance::uploadSparseImage (const tcu::TextureFormat&		texFormat,
1293												  const TextureData&			textureData,
1294												  const tcu::Sampler&			refSampler,
1295												  const deUint32				mipLevels,
1296												  const deUint32				arrayLayers,
1297												  const VkImage					sparseImage,
1298												  const VkImageCreateInfo&		imageCreateInfo,
1299												  const tcu::UVec3				texSize)
1300{
1301	const VkDevice							vkDevice				= getDevice();
1302	const DeviceInterface&					vk						= getDeviceInterface();
1303	const VkPhysicalDevice					physicalDevice			= getPhysicalDevice();
1304	const VkQueue							queue					= getUniversalQueue();
1305	const deUint32							queueFamilyIndex		= getUniversalQueueFamilyIndex();
1306	const InstanceInterface&				instance				= getInstanceInterface();
1307	const VkPhysicalDeviceProperties		deviceProperties		= getPhysicalDeviceProperties(instance, physicalDevice);
1308	const VkPhysicalDeviceMemoryProperties	deviceMemoryProperties	= getPhysicalDeviceMemoryProperties(instance, physicalDevice);
1309	const bool								isShadowSampler			= refSampler.compare != tcu::Sampler::COMPAREMODE_NONE;
1310	const VkImageAspectFlags				aspectMask				= isShadowSampler ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT;
1311
1312	const Unique<VkSemaphore> 				imageMemoryBindSemaphore(makeSemaphore(vk, vkDevice));
1313	deUint32								bufferSize				= 0u;
1314	std::vector<deUint32>					offsetMultiples;
1315	offsetMultiples.push_back(4u);
1316	offsetMultiples.push_back(texFormat.getPixelSize());
1317
1318	if (isImageSizeSupported(imageCreateInfo.imageType, texSize, deviceProperties.limits) == false)
1319		TCU_THROW(NotSupportedError, "Image size not supported for device.");
1320
1321	// Calculate buffer size
1322	for (TextureData::const_iterator mit = textureData.begin(); mit != textureData.end(); ++mit)
1323	{
1324		for (TextureLayerData::const_iterator lit = mit->begin(); lit != mit->end(); ++lit)
1325		{
1326			const tcu::ConstPixelBufferAccess&	access	= *lit;
1327
1328			bufferSize = getNextMultiple(offsetMultiples, bufferSize);
1329			bufferSize += access.getWidth() * access.getHeight() * access.getDepth() * access.getFormat().getPixelSize();
1330		}
1331	}
1332
1333	{
1334		deUint32 sparseMemoryReqCount = 0;
1335
1336		vk.getImageSparseMemoryRequirements(vkDevice, sparseImage, &sparseMemoryReqCount, DE_NULL);
1337
1338		DE_ASSERT(sparseMemoryReqCount != 0);
1339
1340		std::vector<VkSparseImageMemoryRequirements> sparseImageMemoryRequirements;
1341		sparseImageMemoryRequirements.resize(sparseMemoryReqCount);
1342
1343		vk.getImageSparseMemoryRequirements(vkDevice, sparseImage, &sparseMemoryReqCount, &sparseImageMemoryRequirements[0]);
1344
1345		const deUint32 noMatchFound = ~((deUint32)0);
1346
1347		deUint32 colorAspectIndex = noMatchFound;
1348		for (deUint32 memoryReqNdx = 0; memoryReqNdx < sparseMemoryReqCount; ++memoryReqNdx)
1349		{
1350			if (sparseImageMemoryRequirements[memoryReqNdx].formatProperties.aspectMask & VK_IMAGE_ASPECT_COLOR_BIT)
1351			{
1352				colorAspectIndex = memoryReqNdx;
1353				break;
1354			}
1355		}
1356
1357		if (colorAspectIndex == noMatchFound)
1358			TCU_THROW(NotSupportedError, "Not supported image aspect - the test supports currently only VK_IMAGE_ASPECT_COLOR_BIT.");
1359
1360		const VkMemoryRequirements	memoryRequirements	= getImageMemoryRequirements(vk, vkDevice, sparseImage);
1361
1362		deUint32 memoryType = noMatchFound;
1363		for (deUint32 memoryTypeNdx = 0; memoryTypeNdx < deviceMemoryProperties.memoryTypeCount; ++memoryTypeNdx)
1364		{
1365			if ((memoryRequirements.memoryTypeBits & (1u << memoryTypeNdx)) != 0 &&
1366				MemoryRequirement::Any.matchesHeap(deviceMemoryProperties.memoryTypes[memoryTypeNdx].propertyFlags))
1367			{
1368				memoryType = memoryTypeNdx;
1369				break;
1370			}
1371		}
1372
1373		if (memoryType == noMatchFound)
1374			TCU_THROW(NotSupportedError, "No matching memory type found.");
1375
1376		if (memoryRequirements.size > deviceProperties.limits.sparseAddressSpaceSize)
1377			TCU_THROW(NotSupportedError, "Required memory size for sparse resource exceeds device limits.");
1378
1379		// Check if the image format supports sparse oprerations
1380		const std::vector<VkSparseImageFormatProperties> sparseImageFormatPropVec =
1381			getPhysicalDeviceSparseImageFormatProperties(instance, physicalDevice, imageCreateInfo.format, imageCreateInfo.imageType, imageCreateInfo.samples, imageCreateInfo.usage, imageCreateInfo.tiling);
1382
1383		if (sparseImageFormatPropVec.size() == 0)
1384			TCU_THROW(NotSupportedError, "The image format does not support sparse operations.");
1385
1386		const VkSparseImageMemoryRequirements		aspectRequirements	= sparseImageMemoryRequirements[colorAspectIndex];
1387		const VkExtent3D							imageGranularity	= aspectRequirements.formatProperties.imageGranularity;
1388
1389		std::vector<VkSparseImageMemoryBind>		imageResidencyMemoryBinds;
1390		std::vector<VkSparseMemoryBind>				imageMipTailMemoryBinds;
1391		std::vector< de::SharedPtr<Allocation> >	allocations;
1392
1393		for (deUint32 layerNdx = 0; layerNdx < arrayLayers; ++ layerNdx)
1394		{
1395			for (deUint32 mipLevelNdx = 0; mipLevelNdx < aspectRequirements.imageMipTailFirstLod; ++mipLevelNdx)
1396			{
1397				const VkExtent3D	mipExtent		= mipLevelExtents(imageCreateInfo.extent, mipLevelNdx);
1398				const tcu::UVec3	numSparseBinds	= alignedDivide(mipExtent, imageGranularity);
1399				const tcu::UVec3	lastBlockExtent	= tcu::UVec3(mipExtent.width  % imageGranularity.width  ? mipExtent.width  % imageGranularity.width  : imageGranularity.width,
1400																 mipExtent.height % imageGranularity.height ? mipExtent.height % imageGranularity.height : imageGranularity.height,
1401																 mipExtent.depth  % imageGranularity.depth  ? mipExtent.depth  % imageGranularity.depth  : imageGranularity.depth );
1402
1403				for (deUint32 z = 0; z < numSparseBinds.z(); ++z)
1404				for (deUint32 y = 0; y < numSparseBinds.y(); ++y)
1405				for (deUint32 x = 0; x < numSparseBinds.x(); ++x)
1406				{
1407					const deUint32 linearIndex = x + y*numSparseBinds.x() + z*numSparseBinds.x()*numSparseBinds.y() + layerNdx*numSparseBinds.x()*numSparseBinds.y()*numSparseBinds.z();
1408
1409					if (linearIndex % 2 == 1)
1410					{
1411						continue;
1412					}
1413
1414					const VkMemoryRequirements allocRequirements =
1415					{
1416						// 28.7.5 alignment shows the block size in bytes
1417						memoryRequirements.alignment,		// VkDeviceSize	size;
1418						memoryRequirements.alignment,		// VkDeviceSize	alignment;
1419						memoryRequirements.memoryTypeBits,	// uint32_t		memoryTypeBits;
1420					};
1421
1422					de::SharedPtr<Allocation> allocation(m_memAlloc.allocate(allocRequirements, MemoryRequirement::Any).release());
1423
1424					allocations.push_back(allocation);
1425
1426					VkOffset3D offset;
1427					offset.x = x*imageGranularity.width;
1428					offset.y = y*imageGranularity.height;
1429					offset.z = z*imageGranularity.depth;
1430
1431					VkExtent3D extent;
1432					extent.width	= (x == numSparseBinds.x() - 1) ? lastBlockExtent.x() : imageGranularity.width;
1433					extent.height	= (y == numSparseBinds.y() - 1) ? lastBlockExtent.y() : imageGranularity.height;
1434					extent.depth	= (z == numSparseBinds.z() - 1) ? lastBlockExtent.z() : imageGranularity.depth;
1435
1436					const VkSparseImageMemoryBind imageMemoryBind =
1437					{
1438						{
1439							aspectMask,	// VkImageAspectFlags	aspectMask;
1440							mipLevelNdx,// uint32_t				mipLevel;
1441							layerNdx,	// uint32_t				arrayLayer;
1442						},							// VkImageSubresource		subresource;
1443						offset,						// VkOffset3D				offset;
1444						extent,						// VkExtent3D				extent;
1445						allocation->getMemory(),	// VkDeviceMemory			memory;
1446						allocation->getOffset(),	// VkDeviceSize				memoryOffset;
1447						0u,							// VkSparseMemoryBindFlags	flags;
1448					};
1449
1450					imageResidencyMemoryBinds.push_back(imageMemoryBind);
1451				}
1452			}
1453
1454			// Handle MIP tail for each layer
1455			{
1456				const VkMemoryRequirements allocRequirements =
1457				{
1458					aspectRequirements.imageMipTailSize,	// VkDeviceSize	size;
1459					memoryRequirements.alignment,			// VkDeviceSize	alignment;
1460					memoryRequirements.memoryTypeBits,		// uint32_t		memoryTypeBits;
1461				};
1462
1463				const de::SharedPtr<Allocation> allocation(m_memAlloc.allocate(allocRequirements, MemoryRequirement::Any).release());
1464
1465				const VkSparseMemoryBind imageMipTailMemoryBind =
1466				{
1467					aspectRequirements.imageMipTailOffset + layerNdx * aspectRequirements.imageMipTailStride,	// VkDeviceSize					resourceOffset;
1468					aspectRequirements.imageMipTailSize,														// VkDeviceSize					size;
1469					allocation->getMemory(),																	// VkDeviceMemory				memory;
1470					allocation->getOffset(),																	// VkDeviceSize					memoryOffset;
1471					0u,																							// VkSparseMemoryBindFlags		flags;
1472				};
1473
1474				allocations.push_back(allocation);
1475				imageMipTailMemoryBinds.push_back(imageMipTailMemoryBind);
1476			}
1477		}
1478
1479		VkBindSparseInfo bindSparseInfo =
1480		{
1481			VK_STRUCTURE_TYPE_BIND_SPARSE_INFO,			//VkStructureType							sType;
1482			DE_NULL,									//const void*								pNext;
1483			0u,											//deUint32									waitSemaphoreCount;
1484			DE_NULL,									//const VkSemaphore*						pWaitSemaphores;
1485			0u,											//deUint32									bufferBindCount;
1486			DE_NULL,									//const VkSparseBufferMemoryBindInfo*		pBufferBinds;
1487			0u,											//deUint32									imageOpaqueBindCount;
1488			DE_NULL,									//const VkSparseImageOpaqueMemoryBindInfo*	pImageOpaqueBinds;
1489			0u,											//deUint32									imageBindCount;
1490			DE_NULL,									//const VkSparseImageMemoryBindInfo*		pImageBinds;
1491			1u,											//deUint32									signalSemaphoreCount;
1492			&imageMemoryBindSemaphore.get()				//const VkSemaphore*						pSignalSemaphores;
1493		};
1494
1495		VkSparseImageMemoryBindInfo			imageResidencyBindInfo;
1496		VkSparseImageOpaqueMemoryBindInfo	imageMipTailBindInfo;
1497
1498		if (imageResidencyMemoryBinds.size() > 0)
1499		{
1500			imageResidencyBindInfo.image		= sparseImage;
1501			imageResidencyBindInfo.bindCount	= static_cast<deUint32>(imageResidencyMemoryBinds.size());
1502			imageResidencyBindInfo.pBinds		= &imageResidencyMemoryBinds[0];
1503
1504			bindSparseInfo.imageBindCount		= 1u;
1505			bindSparseInfo.pImageBinds			= &imageResidencyBindInfo;
1506		}
1507
1508		if (imageMipTailMemoryBinds.size() > 0)
1509		{
1510			imageMipTailBindInfo.image = sparseImage;
1511			imageMipTailBindInfo.bindCount = static_cast<deUint32>(imageMipTailMemoryBinds.size());
1512			imageMipTailBindInfo.pBinds = &imageMipTailMemoryBinds[0];
1513
1514			bindSparseInfo.imageOpaqueBindCount = 1u;
1515			bindSparseInfo.pImageOpaqueBinds = &imageMipTailBindInfo;
1516		}
1517
1518		VK_CHECK(vk.queueBindSparse(queue, 1u, &bindSparseInfo, DE_NULL));
1519	}
1520
1521	Move<VkCommandPool>		cmdPool;
1522	Move<VkCommandBuffer>	cmdBuffer;
1523	// Create command pool
1524	{
1525		const VkCommandPoolCreateInfo cmdPoolParams =
1526		{
1527			VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,		// VkStructureType			sType;
1528			DE_NULL,										// const void*				pNext;
1529			VK_COMMAND_POOL_CREATE_TRANSIENT_BIT,			// VkCommandPoolCreateFlags	flags;
1530			queueFamilyIndex,								// deUint32					queueFamilyIndex;
1531		};
1532
1533		cmdPool = createCommandPool(vk, vkDevice, &cmdPoolParams);
1534	}
1535
1536	{
1537		// Create command buffer
1538		const VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
1539		{
1540			VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,	// VkStructureType			sType;
1541			DE_NULL,										// const void*				pNext;
1542			*cmdPool,										// VkCommandPool			commandPool;
1543			VK_COMMAND_BUFFER_LEVEL_PRIMARY,				// VkCommandBufferLevel		level;
1544			1u,												// deUint32					bufferCount;
1545		};
1546
1547		cmdBuffer = allocateCommandBuffer(vk, vkDevice, &cmdBufferAllocateInfo);
1548	}
1549
1550	// Create source buffer
1551	const VkBufferCreateInfo bufferParams =
1552	{
1553		VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
1554		DE_NULL,									// const void*			pNext;
1555		0u,											// VkBufferCreateFlags	flags;
1556		bufferSize,									// VkDeviceSize			size;
1557		VK_BUFFER_USAGE_TRANSFER_SRC_BIT,			// VkBufferUsageFlags	usage;
1558		VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
1559		0u,											// deUint32				queueFamilyIndexCount;
1560		DE_NULL,									// const deUint32*		pQueueFamilyIndices;
1561	};
1562
1563	Move<VkBuffer>					buffer		= createBuffer(vk, vkDevice, &bufferParams);
1564	de::MovePtr<Allocation>			bufferAlloc = m_memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *buffer), MemoryRequirement::HostVisible);
1565	VK_CHECK(vk.bindBufferMemory(vkDevice, *buffer, bufferAlloc->getMemory(), bufferAlloc->getOffset()));
1566
1567	// Barriers for copying buffer to image
1568	const VkBufferMemoryBarrier preBufferBarrier =
1569	{
1570		VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	// VkStructureType	sType;
1571		DE_NULL,									// const void*		pNext;
1572		VK_ACCESS_HOST_WRITE_BIT,					// VkAccessFlags	srcAccessMask;
1573		VK_ACCESS_TRANSFER_READ_BIT,				// VkAccessFlags	dstAccessMask;
1574		VK_QUEUE_FAMILY_IGNORED,					// deUint32			srcQueueFamilyIndex;
1575		VK_QUEUE_FAMILY_IGNORED,					// deUint32			dstQueueFamilyIndex;
1576		*buffer,									// VkBuffer			buffer;
1577		0u,											// VkDeviceSize		offset;
1578		bufferSize									// VkDeviceSize		size;
1579	};
1580
1581	const VkImageMemoryBarrier preImageBarrier =
1582	{
1583		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType			sType;
1584		DE_NULL,										// const void*				pNext;
1585		0u,												// VkAccessFlags			srcAccessMask;
1586		VK_ACCESS_TRANSFER_WRITE_BIT,					// VkAccessFlags			dstAccessMask;
1587		VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout			oldLayout;
1588		VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,			// VkImageLayout			newLayout;
1589		VK_QUEUE_FAMILY_IGNORED,						// deUint32					srcQueueFamilyIndex;
1590		VK_QUEUE_FAMILY_IGNORED,						// deUint32					dstQueueFamilyIndex;
1591		sparseImage,									// VkImage					image;
1592		{												// VkImageSubresourceRange	subresourceRange;
1593			aspectMask,								// VkImageAspect	aspect;
1594			0u,										// deUint32			baseMipLevel;
1595			mipLevels,								// deUint32			mipLevels;
1596			0u,										// deUint32			baseArraySlice;
1597			arrayLayers								// deUint32			arraySize;
1598		}
1599	};
1600
1601	const VkImageMemoryBarrier postImageBarrier =
1602	{
1603		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType			sType;
1604		DE_NULL,										// const void*				pNext;
1605		VK_ACCESS_TRANSFER_WRITE_BIT,					// VkAccessFlags			srcAccessMask;
1606		VK_ACCESS_SHADER_READ_BIT,						// VkAccessFlags			dstAccessMask;
1607		VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,			// VkImageLayout			oldLayout;
1608		VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,		// VkImageLayout			newLayout;
1609		VK_QUEUE_FAMILY_IGNORED,						// deUint32					srcQueueFamilyIndex;
1610		VK_QUEUE_FAMILY_IGNORED,						// deUint32					dstQueueFamilyIndex;
1611		sparseImage,									// VkImage					image;
1612		{												// VkImageSubresourceRange	subresourceRange;
1613			aspectMask,								// VkImageAspect	aspect;
1614			0u,										// deUint32			baseMipLevel;
1615			mipLevels,								// deUint32			mipLevels;
1616			0u,										// deUint32			baseArraySlice;
1617			arrayLayers								// deUint32			arraySize;
1618		}
1619	};
1620
1621	const VkCommandBufferBeginInfo cmdBufferBeginInfo =
1622	{
1623		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,	// VkStructureType					sType;
1624		DE_NULL,										// const void*						pNext;
1625		VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,	// VkCommandBufferUsageFlags		flags;
1626		(const VkCommandBufferInheritanceInfo*)DE_NULL,
1627	};
1628
1629	std::vector<VkBufferImageCopy>	copyRegions;
1630	// Get copy regions and write buffer data
1631	{
1632		deUint32	layerDataOffset		= 0;
1633		deUint8*	destPtr				= (deUint8*)bufferAlloc->getHostPtr();
1634
1635		for (size_t levelNdx = 0; levelNdx < textureData.size(); levelNdx++)
1636		{
1637			const TextureLayerData&		layerData	= textureData[levelNdx];
1638
1639			for (size_t layerNdx = 0; layerNdx < layerData.size(); layerNdx++)
1640			{
1641				layerDataOffset = getNextMultiple(offsetMultiples, layerDataOffset);
1642
1643				const tcu::ConstPixelBufferAccess&	access		= layerData[layerNdx];
1644				const tcu::PixelBufferAccess		destAccess	(access.getFormat(), access.getSize(), destPtr + layerDataOffset);
1645
1646				const VkBufferImageCopy				layerRegion =
1647				{
1648					layerDataOffset,						// VkDeviceSize				bufferOffset;
1649					(deUint32)access.getWidth(),			// deUint32					bufferRowLength;
1650					(deUint32)access.getHeight(),			// deUint32					bufferImageHeight;
1651					{										// VkImageSubresourceLayers	imageSubresource;
1652						aspectMask,								// VkImageAspectFlags		aspectMask;
1653						(deUint32)levelNdx,						// uint32_t					mipLevel;
1654						(deUint32)layerNdx,						// uint32_t					baseArrayLayer;
1655						1u										// uint32_t					layerCount;
1656					},
1657					{ 0u, 0u, 0u },							// VkOffset3D			imageOffset;
1658					{										// VkExtent3D			imageExtent;
1659						(deUint32)access.getWidth(),
1660						(deUint32)access.getHeight(),
1661						(deUint32)access.getDepth()
1662					}
1663				};
1664
1665				copyRegions.push_back(layerRegion);
1666				tcu::copy(destAccess, access);
1667
1668				layerDataOffset += access.getWidth() * access.getHeight() * access.getDepth() * access.getFormat().getPixelSize();
1669			}
1670		}
1671	}
1672
1673	// Copy buffer to image
1674	VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufferBeginInfo));
1675	vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &preBufferBarrier, 1, &preImageBarrier);
1676	vk.cmdCopyBufferToImage(*cmdBuffer, *buffer, sparseImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, (deUint32)copyRegions.size(), copyRegions.data());
1677	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);
1678	VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1679
1680	const VkPipelineStageFlags pipelineStageFlags = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT;
1681
1682	const VkSubmitInfo submitInfo =
1683	{
1684		VK_STRUCTURE_TYPE_SUBMIT_INFO,			// VkStructureType				sType;
1685		DE_NULL,								// const void*					pNext;
1686		1u,										// deUint32						waitSemaphoreCount;
1687		&imageMemoryBindSemaphore.get(),		// const VkSemaphore*			pWaitSemaphores;
1688		&pipelineStageFlags,					// const VkPipelineStageFlags*	pWaitDstStageMask;
1689		1u,										// deUint32						commandBufferCount;
1690		&cmdBuffer.get(),						// const VkCommandBuffer*		pCommandBuffers;
1691		0u,										// deUint32						signalSemaphoreCount;
1692		DE_NULL									// const VkSemaphore*			pSignalSemaphores;
1693	};
1694
1695	const VkFenceCreateInfo fenceParams =
1696	{
1697		VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,		// VkStructureType		sType;
1698		DE_NULL,									// const void*			pNext;
1699		0u											// VkFenceCreateFlags	flags;
1700	};
1701
1702	Move<VkFence>	fence = createFence(vk, vkDevice, &fenceParams);
1703
1704	try
1705	{
1706		VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *fence));
1707		VK_CHECK(vk.waitForFences(vkDevice, 1, &fence.get(), true, ~(0ull) /* infinity */));
1708	}
1709	catch (...)
1710	{
1711		VK_CHECK(vk.deviceWaitIdle(vkDevice));
1712		throw;
1713	}
1714}
1715
1716void ShaderRenderCaseInstance::useSampler (deUint32 bindingLocation, deUint32 textureId)
1717{
1718	DE_ASSERT(textureId < m_textures.size());
1719
1720	const TextureBinding&				textureBinding		= *m_textures[textureId];
1721	const TextureBinding::Type			textureType			= textureBinding.getType();
1722	const tcu::Sampler&					refSampler			= textureBinding.getSampler();
1723	const TextureBinding::Parameters&	textureParams		= textureBinding.getParameters();
1724	const bool							isMSTexture			= textureParams.samples != vk::VK_SAMPLE_COUNT_1_BIT;
1725	deUint32							mipLevels			= 1u;
1726	deUint32							arrayLayers			= 1u;
1727	tcu::TextureFormat					texFormat;
1728	tcu::UVec3							texSize;
1729	TextureData							textureData;
1730
1731	if (textureType == TextureBinding::TYPE_2D)
1732	{
1733		const tcu::Texture2D&			texture		= textureBinding.get2D();
1734
1735		texFormat									= texture.getFormat();
1736		texSize										= tcu::UVec3(texture.getWidth(), texture.getHeight(), 1u);
1737		mipLevels									= (deUint32)texture.getNumLevels();
1738		arrayLayers									= 1u;
1739
1740		textureData.resize(mipLevels);
1741
1742		for (deUint32 level = 0; level < mipLevels; ++level)
1743		{
1744			if (texture.isLevelEmpty(level))
1745				continue;
1746
1747			textureData[level].push_back(texture.getLevel(level));
1748		}
1749	}
1750	else if (textureType == TextureBinding::TYPE_CUBE_MAP)
1751	{
1752		const tcu::TextureCube&			texture		= textureBinding.getCube();
1753
1754		texFormat									= texture.getFormat();
1755		texSize										= tcu::UVec3(texture.getSize(), texture.getSize(), 1u);
1756		mipLevels									= (deUint32)texture.getNumLevels();
1757		arrayLayers									= 6u;
1758
1759		static const tcu::CubeFace		cubeFaceMapping[tcu::CUBEFACE_LAST] =
1760		{
1761			tcu::CUBEFACE_POSITIVE_X,
1762			tcu::CUBEFACE_NEGATIVE_X,
1763			tcu::CUBEFACE_POSITIVE_Y,
1764			tcu::CUBEFACE_NEGATIVE_Y,
1765			tcu::CUBEFACE_POSITIVE_Z,
1766			tcu::CUBEFACE_NEGATIVE_Z
1767		};
1768
1769		textureData.resize(mipLevels);
1770
1771		for (deUint32 level = 0; level < mipLevels; ++level)
1772		{
1773			for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; ++faceNdx)
1774			{
1775				tcu::CubeFace face = cubeFaceMapping[faceNdx];
1776
1777				if (texture.isLevelEmpty(face, level))
1778					continue;
1779
1780				textureData[level].push_back(texture.getLevelFace(level, face));
1781			}
1782		}
1783	}
1784	else if (textureType == TextureBinding::TYPE_2D_ARRAY)
1785	{
1786		const tcu::Texture2DArray&		texture		= textureBinding.get2DArray();
1787
1788		texFormat									= texture.getFormat();
1789		texSize										= tcu::UVec3(texture.getWidth(), texture.getHeight(), 1u);
1790		mipLevels									= (deUint32)texture.getNumLevels();
1791		arrayLayers									= (deUint32)texture.getNumLayers();
1792
1793		textureData.resize(mipLevels);
1794
1795		for (deUint32 level = 0; level < mipLevels; ++level)
1796		{
1797			if (texture.isLevelEmpty(level))
1798				continue;
1799
1800			const tcu::ConstPixelBufferAccess&	levelLayers		= texture.getLevel(level);
1801			const deUint32						layerSize		= levelLayers.getWidth() * levelLayers.getHeight() * levelLayers.getFormat().getPixelSize();
1802
1803			for (deUint32 layer = 0; layer < arrayLayers; ++layer)
1804			{
1805				const deUint32					layerOffset		= layerSize * layer;
1806				tcu::ConstPixelBufferAccess		layerData		(levelLayers.getFormat(), levelLayers.getWidth(), levelLayers.getHeight(), 1, (deUint8*)levelLayers.getDataPtr() + layerOffset);
1807				textureData[level].push_back(layerData);
1808			}
1809		}
1810	}
1811	else if (textureType == TextureBinding::TYPE_3D)
1812	{
1813		const tcu::Texture3D&			texture		= textureBinding.get3D();
1814
1815		texFormat									= texture.getFormat();
1816		texSize										= tcu::UVec3(texture.getWidth(), texture.getHeight(), texture.getDepth());
1817		mipLevels									= (deUint32)texture.getNumLevels();
1818		arrayLayers									= 1u;
1819
1820		textureData.resize(mipLevels);
1821
1822		for (deUint32 level = 0; level < mipLevels; ++level)
1823		{
1824			if (texture.isLevelEmpty(level))
1825				continue;
1826
1827			textureData[level].push_back(texture.getLevel(level));
1828		}
1829	}
1830	else if (textureType == TextureBinding::TYPE_1D)
1831	{
1832		const tcu::Texture1D&			texture		= textureBinding.get1D();
1833
1834		texFormat									= texture.getFormat();
1835		texSize										= tcu::UVec3(texture.getWidth(), 1, 1);
1836		mipLevels									= isMSTexture ? 1u : (deUint32)texture.getNumLevels();
1837		arrayLayers									= 1u;
1838
1839		textureData.resize(mipLevels);
1840
1841		for (deUint32 level = 0; level < mipLevels; ++level)
1842		{
1843			if (texture.isLevelEmpty(level))
1844				continue;
1845
1846			textureData[level].push_back(texture.getLevel(level));
1847		}
1848	}
1849	else if (textureType == TextureBinding::TYPE_1D_ARRAY)
1850	{
1851		const tcu::Texture1DArray&		texture		= textureBinding.get1DArray();
1852
1853		texFormat									= texture.getFormat();
1854		texSize										= tcu::UVec3(texture.getWidth(), 1, 1);
1855		mipLevels									= isMSTexture ? 1u : (deUint32)texture.getNumLevels();
1856		arrayLayers									= (deUint32)texture.getNumLayers();
1857
1858		textureData.resize(mipLevels);
1859
1860		for (deUint32 level = 0; level < mipLevels; ++level)
1861		{
1862			if (texture.isLevelEmpty(level))
1863				continue;
1864
1865			const tcu::ConstPixelBufferAccess&	levelLayers		= texture.getLevel(level);
1866			const deUint32						layerSize		= levelLayers.getWidth() * levelLayers.getFormat().getPixelSize();
1867
1868			for (deUint32 layer = 0; layer < arrayLayers; ++layer)
1869			{
1870				const deUint32					layerOffset		= layerSize * layer;
1871				tcu::ConstPixelBufferAccess		layerData		(levelLayers.getFormat(), levelLayers.getWidth(), 1, 1, (deUint8*)levelLayers.getDataPtr() + layerOffset);
1872				textureData[level].push_back(layerData);
1873			}
1874		}
1875	}
1876	else if (textureType == TextureBinding::TYPE_CUBE_ARRAY)
1877	{
1878		const tcu::TextureCubeArray&	texture		= textureBinding.getCubeArray();
1879		texFormat									= texture.getFormat();
1880		texSize										= tcu::UVec3(texture.getSize(), texture.getSize(), 1);
1881		mipLevels									= isMSTexture ? 1u : (deUint32)texture.getNumLevels();
1882		arrayLayers									= texture.getDepth();
1883
1884		textureData.resize(mipLevels);
1885
1886		for (deUint32 level = 0; level < mipLevels; ++level)
1887		{
1888			if (texture.isLevelEmpty(level))
1889				continue;
1890
1891			const tcu::ConstPixelBufferAccess&	levelLayers		= texture.getLevel(level);
1892			const deUint32						layerSize		= levelLayers.getWidth() * levelLayers.getHeight() * levelLayers.getFormat().getPixelSize();
1893
1894			for (deUint32 layer = 0; layer < arrayLayers; ++layer)
1895			{
1896				const deUint32					layerOffset		= layerSize * layer;
1897				tcu::ConstPixelBufferAccess		layerData		(levelLayers.getFormat(), levelLayers.getWidth(), levelLayers.getHeight(), 1, (deUint8*)levelLayers.getDataPtr() + layerOffset);
1898				textureData[level].push_back(layerData);
1899			}
1900		}
1901	}
1902	else
1903	{
1904		TCU_THROW(InternalError, "Invalid texture type");
1905	}
1906
1907	createSamplerUniform(bindingLocation, textureType, texFormat, texSize, textureData, refSampler, mipLevels, arrayLayers, textureParams);
1908}
1909
1910void ShaderRenderCaseInstance::createSamplerUniform (deUint32						bindingLocation,
1911													 TextureBinding::Type			textureType,
1912													 const tcu::TextureFormat&		texFormat,
1913													 const tcu::UVec3				texSize,
1914													 const TextureData&				textureData,
1915													 const tcu::Sampler&			refSampler,
1916													 deUint32						mipLevels,
1917													 deUint32						arrayLayers,
1918													 TextureBinding::Parameters		textureParams)
1919{
1920	const VkDevice					vkDevice			= getDevice();
1921	const DeviceInterface&			vk					= getDeviceInterface();
1922	const deUint32					queueFamilyIndex	= getUniversalQueueFamilyIndex();
1923
1924	const bool						isShadowSampler		= refSampler.compare != tcu::Sampler::COMPAREMODE_NONE;
1925	const VkImageAspectFlags		aspectMask			= isShadowSampler ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT;
1926	const VkImageViewType			imageViewType		= textureTypeToImageViewType(textureType);
1927	const VkImageType				imageType			= viewTypeToImageType(imageViewType);
1928	const VkFormat					format				= mapTextureFormat(texFormat);
1929	const bool						isCube				= imageViewType == VK_IMAGE_VIEW_TYPE_CUBE || imageViewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
1930	VkImageCreateFlags				imageCreateFlags	= isCube ? (VkImageCreateFlags)VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : (VkImageCreateFlags)0;
1931	VkImageUsageFlags				imageUsageFlags		= VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
1932	Move<VkImage>					vkTexture;
1933	de::MovePtr<Allocation>			allocation;
1934
1935	if (isShadowSampler)
1936		imageUsageFlags |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
1937
1938	if (m_imageBackingMode == IMAGE_BACKING_MODE_SPARSE)
1939	{
1940		checkSparseSupport(imageType);
1941		imageCreateFlags |= VK_IMAGE_CREATE_SPARSE_BINDING_BIT | VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT;
1942	}
1943
1944	// Create image
1945	const VkImageCreateInfo			imageParams =
1946	{
1947		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,							// VkStructureType			sType;
1948		DE_NULL,														// const void*				pNext;
1949		imageCreateFlags,												// VkImageCreateFlags		flags;
1950		imageType,														// VkImageType				imageType;
1951		format,															// VkFormat					format;
1952		{																// VkExtent3D				extent;
1953			texSize.x(),
1954			texSize.y(),
1955			texSize.z()
1956		},
1957		mipLevels,														// deUint32					mipLevels;
1958		arrayLayers,													// deUint32					arrayLayers;
1959		textureParams.samples,											// VkSampleCountFlagBits	samples;
1960		VK_IMAGE_TILING_OPTIMAL,										// VkImageTiling			tiling;
1961		imageUsageFlags,												// VkImageUsageFlags		usage;
1962		VK_SHARING_MODE_EXCLUSIVE,										// VkSharingMode			sharingMode;
1963		1u,																// deUint32					queueFamilyIndexCount;
1964		&queueFamilyIndex,												// const deUint32*			pQueueFamilyIndices;
1965		VK_IMAGE_LAYOUT_UNDEFINED										// VkImageLayout			initialLayout;
1966	};
1967
1968	vkTexture		= createImage(vk, vkDevice, &imageParams);
1969	allocation		= m_memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *vkTexture), MemoryRequirement::Any);
1970
1971	if (m_imageBackingMode == IMAGE_BACKING_MODE_SPARSE)
1972	{
1973		uploadSparseImage(texFormat, textureData, refSampler, mipLevels, arrayLayers, *vkTexture, imageParams, texSize);
1974	}
1975	else
1976	{
1977		// Upload texture data
1978		VK_CHECK(vk.bindImageMemory(vkDevice, *vkTexture, allocation->getMemory(), allocation->getOffset()));
1979		uploadImage(texFormat, textureData, refSampler, mipLevels, arrayLayers, *vkTexture);
1980	}
1981
1982	// Create sampler
1983	const VkSamplerCreateInfo		samplerParams	= mapSampler(refSampler, texFormat);
1984	Move<VkSampler>					sampler			= createSampler(vk, vkDevice, &samplerParams);
1985	const deUint32					baseMipLevel	= textureParams.baseMipLevel;
1986	const vk::VkComponentMapping	components		= textureParams.componentMapping;
1987	const VkImageViewCreateInfo		viewParams		=
1988	{
1989		VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,	// VkStructureType			sType;
1990		NULL,										// const voide*				pNext;
1991		0u,											// VkImageViewCreateFlags	flags;
1992		*vkTexture,									// VkImage					image;
1993		imageViewType,								// VkImageViewType			viewType;
1994		format,										// VkFormat					format;
1995		components,									// VkChannelMapping			channels;
1996		{
1997			aspectMask,						// VkImageAspectFlags	aspectMask;
1998			baseMipLevel,					// deUint32				baseMipLevel;
1999			mipLevels - baseMipLevel,		// deUint32				mipLevels;
2000			0,								// deUint32				baseArraySlice;
2001			arrayLayers						// deUint32				arraySize;
2002		},											// VkImageSubresourceRange	subresourceRange;
2003	};
2004
2005	Move<VkImageView>				imageView		= createImageView(vk, vkDevice, &viewParams);
2006
2007	const vk::VkDescriptorImageInfo	descriptor		=
2008	{
2009		sampler.get(),								// VkSampler				sampler;
2010		imageView.get(),							// VkImageView				imageView;
2011		VK_IMAGE_LAYOUT_GENERAL,					// VkImageLayout			imageLayout;
2012	};
2013
2014	de::MovePtr<SamplerUniform> uniform(new SamplerUniform());
2015	uniform->type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
2016	uniform->descriptor = descriptor;
2017	uniform->location = bindingLocation;
2018	uniform->image = VkImageSp(new vk::Unique<VkImage>(vkTexture));
2019	uniform->imageView = VkImageViewSp(new vk::Unique<VkImageView>(imageView));
2020	uniform->sampler = VkSamplerSp(new vk::Unique<VkSampler>(sampler));
2021	uniform->alloc = AllocationSp(allocation.release());
2022
2023	m_descriptorSetLayoutBuilder->addSingleSamplerBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, vk::VK_SHADER_STAGE_ALL, DE_NULL);
2024	m_descriptorPoolBuilder->addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
2025
2026	m_uniformInfos.push_back(UniformInfoSp(new de::UniquePtr<UniformInfo>(uniform)));
2027}
2028
2029void ShaderRenderCaseInstance::setupDefaultInputs (void)
2030{
2031	/* Configuration of the vertex input attributes:
2032		a_position   is at location 0
2033		a_coords     is at location 1
2034		a_unitCoords is at location 2
2035		a_one        is at location 3
2036
2037	  User attributes starts from at the location 4.
2038	*/
2039
2040	DE_ASSERT(m_quadGrid);
2041	const QuadGrid&		quadGrid	= *m_quadGrid;
2042
2043	addAttribute(0u, VK_FORMAT_R32G32B32A32_SFLOAT, sizeof(tcu::Vec4), quadGrid.getNumVertices(), quadGrid.getPositions());
2044	addAttribute(1u, VK_FORMAT_R32G32B32A32_SFLOAT, sizeof(tcu::Vec4), quadGrid.getNumVertices(), quadGrid.getCoords());
2045	addAttribute(2u, VK_FORMAT_R32G32B32A32_SFLOAT, sizeof(tcu::Vec4), quadGrid.getNumVertices(), quadGrid.getUnitCoords());
2046	addAttribute(3u, VK_FORMAT_R32_SFLOAT, sizeof(float), quadGrid.getNumVertices(), quadGrid.getAttribOne());
2047
2048	static const struct
2049	{
2050		BaseAttributeType	type;
2051		int					userNdx;
2052	} userAttributes[] =
2053	{
2054		{ A_IN0, 0 },
2055		{ A_IN1, 1 },
2056		{ A_IN2, 2 },
2057		{ A_IN3, 3 }
2058	};
2059
2060	static const struct
2061	{
2062		BaseAttributeType	matrixType;
2063		int					numCols;
2064		int					numRows;
2065	} matrices[] =
2066	{
2067		{ MAT2,		2, 2 },
2068		{ MAT2x3,	2, 3 },
2069		{ MAT2x4,	2, 4 },
2070		{ MAT3x2,	3, 2 },
2071		{ MAT3,		3, 3 },
2072		{ MAT3x4,	3, 4 },
2073		{ MAT4x2,	4, 2 },
2074		{ MAT4x3,	4, 3 },
2075		{ MAT4,		4, 4 }
2076	};
2077
2078	for (size_t attrNdx = 0; attrNdx < m_enabledBaseAttributes.size(); attrNdx++)
2079	{
2080		for (int userNdx = 0; userNdx < DE_LENGTH_OF_ARRAY(userAttributes); userNdx++)
2081		{
2082			if (userAttributes[userNdx].type != m_enabledBaseAttributes[attrNdx].type)
2083				continue;
2084
2085			addAttribute(m_enabledBaseAttributes[attrNdx].location, VK_FORMAT_R32G32B32A32_SFLOAT, sizeof(tcu::Vec4), quadGrid.getNumVertices(), quadGrid.getUserAttrib(userNdx));
2086		}
2087
2088		for (int matNdx = 0; matNdx < DE_LENGTH_OF_ARRAY(matrices); matNdx++)
2089		{
2090
2091			if (matrices[matNdx].matrixType != m_enabledBaseAttributes[attrNdx].type)
2092				continue;
2093
2094			const int numCols = matrices[matNdx].numCols;
2095
2096			for (int colNdx = 0; colNdx < numCols; colNdx++)
2097			{
2098				addAttribute(m_enabledBaseAttributes[attrNdx].location + colNdx, VK_FORMAT_R32G32B32A32_SFLOAT, (deUint32)(4 * sizeof(float)), quadGrid.getNumVertices(), quadGrid.getUserAttrib(colNdx));
2099			}
2100		}
2101	}
2102}
2103
2104void ShaderRenderCaseInstance::render (deUint32				numVertices,
2105									   deUint32				numTriangles,
2106									   const deUint16*		indices,
2107									   const tcu::Vec4&		constCoords)
2108{
2109	const VkDevice										vkDevice					= getDevice();
2110	const DeviceInterface&								vk							= getDeviceInterface();
2111	const VkQueue										queue						= getUniversalQueue();
2112	const deUint32										queueFamilyIndex			= getUniversalQueueFamilyIndex();
2113
2114	vk::Move<vk::VkImage>								colorImage;
2115	de::MovePtr<vk::Allocation>							colorImageAlloc;
2116	vk::Move<vk::VkImageView>							colorImageView;
2117	vk::Move<vk::VkImage>								resolvedImage;
2118	de::MovePtr<vk::Allocation>							resolvedImageAlloc;
2119	vk::Move<vk::VkImageView>							resolvedImageView;
2120	vk::Move<vk::VkRenderPass>							renderPass;
2121	vk::Move<vk::VkFramebuffer>							framebuffer;
2122	vk::Move<vk::VkPipelineLayout>						pipelineLayout;
2123	vk::Move<vk::VkPipeline>							graphicsPipeline;
2124	vk::Move<vk::VkShaderModule>						vertexShaderModule;
2125	vk::Move<vk::VkShaderModule>						fragmentShaderModule;
2126	vk::Move<vk::VkBuffer>								indiceBuffer;
2127	de::MovePtr<vk::Allocation>							indiceBufferAlloc;
2128	vk::Move<vk::VkDescriptorSetLayout>					descriptorSetLayout;
2129	vk::Move<vk::VkDescriptorPool>						descriptorPool;
2130	vk::Move<vk::VkDescriptorSet>						descriptorSet;
2131	vk::Move<vk::VkCommandPool>							cmdPool;
2132	vk::Move<vk::VkCommandBuffer>						cmdBuffer;
2133	vk::Move<vk::VkFence>								fence;
2134
2135	// Create color image
2136	{
2137		const VkImageUsageFlags	imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
2138		VkImageFormatProperties	properties;
2139
2140		if ((getInstanceInterface().getPhysicalDeviceImageFormatProperties(getPhysicalDevice(),
2141																		   m_colorFormat,
2142																		   VK_IMAGE_TYPE_2D,
2143																		   VK_IMAGE_TILING_OPTIMAL,
2144																		   imageUsage,
2145																		   0u,
2146																		   &properties) == VK_ERROR_FORMAT_NOT_SUPPORTED))
2147		{
2148			TCU_THROW(NotSupportedError, "Format not supported");
2149		}
2150
2151		if ((properties.sampleCounts & m_sampleCount) != m_sampleCount)
2152		{
2153			TCU_THROW(NotSupportedError, "Format not supported");
2154		}
2155
2156		const VkImageCreateInfo							colorImageParams			=
2157		{
2158			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,										// VkStructureType		sType;
2159			DE_NULL,																	// const void*			pNext;
2160			0u,																			// VkImageCreateFlags	flags;
2161			VK_IMAGE_TYPE_2D,															// VkImageType			imageType;
2162			m_colorFormat,																// VkFormat				format;
2163			{ m_renderSize.x(), m_renderSize.y(), 1u },									// VkExtent3D			extent;
2164			1u,																			// deUint32				mipLevels;
2165			1u,																			// deUint32				arraySize;
2166			m_sampleCount,																// deUint32				samples;
2167			VK_IMAGE_TILING_OPTIMAL,													// VkImageTiling		tiling;
2168			imageUsage,																	// VkImageUsageFlags	usage;
2169			VK_SHARING_MODE_EXCLUSIVE,													// VkSharingMode		sharingMode;
2170			1u,																			// deUint32				queueFamilyCount;
2171			&queueFamilyIndex,															// const deUint32*		pQueueFamilyIndices;
2172			VK_IMAGE_LAYOUT_UNDEFINED,													// VkImageLayout		initialLayout;
2173		};
2174
2175		colorImage = createImage(vk, vkDevice, &colorImageParams);
2176
2177		// Allocate and bind color image memory
2178		colorImageAlloc = m_memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *colorImage), MemoryRequirement::Any);
2179		VK_CHECK(vk.bindImageMemory(vkDevice, *colorImage, colorImageAlloc->getMemory(), colorImageAlloc->getOffset()));
2180	}
2181
2182	// Create color attachment view
2183	{
2184		const VkImageViewCreateInfo						colorImageViewParams		=
2185		{
2186			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,			// VkStructureType			sType;
2187			DE_NULL,											// const void*				pNext;
2188			0u,													// VkImageViewCreateFlags	flags;
2189			*colorImage,										// VkImage					image;
2190			VK_IMAGE_VIEW_TYPE_2D,								// VkImageViewType			viewType;
2191			m_colorFormat,										// VkFormat					format;
2192			{
2193				VK_COMPONENT_SWIZZLE_R,			// VkChannelSwizzle		r;
2194				VK_COMPONENT_SWIZZLE_G,			// VkChannelSwizzle		g;
2195				VK_COMPONENT_SWIZZLE_B,			// VkChannelSwizzle		b;
2196				VK_COMPONENT_SWIZZLE_A			// VkChannelSwizzle		a;
2197			},													// VkChannelMapping			channels;
2198			{
2199				VK_IMAGE_ASPECT_COLOR_BIT,		// VkImageAspectFlags	aspectMask;
2200				0,								// deUint32				baseMipLevel;
2201				1,								// deUint32				mipLevels;
2202				0,								// deUint32				baseArraySlice;
2203				1								// deUint32				arraySize;
2204			},													// VkImageSubresourceRange	subresourceRange;
2205		};
2206
2207		colorImageView = createImageView(vk, vkDevice, &colorImageViewParams);
2208	}
2209
2210	if (isMultiSampling())
2211	{
2212		// Resolved Image
2213		{
2214			const VkImageUsageFlags	imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
2215			VkImageFormatProperties	properties;
2216
2217			if ((getInstanceInterface().getPhysicalDeviceImageFormatProperties(getPhysicalDevice(),
2218																			   m_colorFormat,
2219																			   VK_IMAGE_TYPE_2D,
2220																			   VK_IMAGE_TILING_OPTIMAL,
2221																			   imageUsage,
2222																			   0,
2223																			   &properties) == VK_ERROR_FORMAT_NOT_SUPPORTED))
2224			{
2225				TCU_THROW(NotSupportedError, "Format not supported");
2226			}
2227
2228			const VkImageCreateInfo					imageCreateInfo			=
2229			{
2230				VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,		// VkStructureType			sType;
2231				DE_NULL,									// const void*				pNext;
2232				0u,											// VkImageCreateFlags		flags;
2233				VK_IMAGE_TYPE_2D,							// VkImageType				imageType;
2234				m_colorFormat,								// VkFormat					format;
2235				{ m_renderSize.x(),	m_renderSize.y(), 1u },	// VkExtent3D				extent;
2236				1u,											// deUint32					mipLevels;
2237				1u,											// deUint32					arrayLayers;
2238				VK_SAMPLE_COUNT_1_BIT,						// VkSampleCountFlagBits	samples;
2239				VK_IMAGE_TILING_OPTIMAL,					// VkImageTiling			tiling;
2240				imageUsage,									// VkImageUsageFlags		usage;
2241				VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode			sharingMode;
2242				1u,											// deUint32					queueFamilyIndexCount;
2243				&queueFamilyIndex,							// const deUint32*			pQueueFamilyIndices;
2244				VK_IMAGE_LAYOUT_UNDEFINED					// VkImageLayout			initialLayout;
2245			};
2246
2247			resolvedImage		= vk::createImage(vk, vkDevice, &imageCreateInfo, DE_NULL);
2248			resolvedImageAlloc	= m_memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *resolvedImage), MemoryRequirement::Any);
2249			VK_CHECK(vk.bindImageMemory(vkDevice, *resolvedImage, resolvedImageAlloc->getMemory(), resolvedImageAlloc->getOffset()));
2250		}
2251
2252		// Resolved Image View
2253		{
2254			const VkImageViewCreateInfo				imageViewCreateInfo		=
2255			{
2256				VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,	// VkStructureType				sType;
2257				DE_NULL,									// const void*					pNext;
2258				0u,											// VkImageViewCreateFlags		flags;
2259				*resolvedImage,								// VkImage						image;
2260				VK_IMAGE_VIEW_TYPE_2D,						// VkImageViewType				viewType;
2261				m_colorFormat,								// VkFormat						format;
2262				{
2263					VK_COMPONENT_SWIZZLE_R,					// VkChannelSwizzle		r;
2264					VK_COMPONENT_SWIZZLE_G,					// VkChannelSwizzle		g;
2265					VK_COMPONENT_SWIZZLE_B,					// VkChannelSwizzle		b;
2266					VK_COMPONENT_SWIZZLE_A					// VkChannelSwizzle		a;
2267				},
2268				{
2269					VK_IMAGE_ASPECT_COLOR_BIT,					// VkImageAspectFlags			aspectMask;
2270					0u,											// deUint32						baseMipLevel;
2271					1u,											// deUint32						mipLevels;
2272					0u,											// deUint32						baseArrayLayer;
2273					1u,											// deUint32						arraySize;
2274				},											// VkImageSubresourceRange		subresourceRange;
2275			};
2276
2277			resolvedImageView = vk::createImageView(vk, vkDevice, &imageViewCreateInfo, DE_NULL);
2278		}
2279	}
2280
2281	// Create render pass
2282	{
2283		const VkAttachmentDescription					attachmentDescription[]		=
2284		{
2285			{
2286				(VkAttachmentDescriptionFlags)0,					// VkAttachmentDescriptionFlags		flags;
2287				m_colorFormat,										// VkFormat							format;
2288				m_sampleCount,										// deUint32							samples;
2289				VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp				loadOp;
2290				VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp				storeOp;
2291				VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// VkAttachmentLoadOp				stencilLoadOp;
2292				VK_ATTACHMENT_STORE_OP_DONT_CARE,					// VkAttachmentStoreOp				stencilStoreOp;
2293				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout					initialLayout;
2294				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout					finalLayout;
2295			},
2296			{
2297				(VkAttachmentDescriptionFlags)0,					// VkAttachmentDescriptionFlags		flags;
2298				m_colorFormat,										// VkFormat							format;
2299				VK_SAMPLE_COUNT_1_BIT,								// VkSampleCountFlagBits			samples;
2300				VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp				loadOp;
2301				VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp				storeOp;
2302				VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// VkAttachmentLoadOp				stencilLoadOp;
2303				VK_ATTACHMENT_STORE_OP_DONT_CARE,					// VkAttachmentStoreOp				stencilStoreOp;
2304				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout					initialLayout;
2305				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout					finalLayout;
2306			}
2307		};
2308
2309		const VkAttachmentReference						attachmentReference			=
2310		{
2311			0u,													// deUint32			attachment;
2312			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout	layout;
2313		};
2314
2315		const VkAttachmentReference						resolveAttachmentRef		=
2316		{
2317			1u,													// deUint32			attachment;
2318			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout	layout;
2319		};
2320
2321		const VkSubpassDescription						subpassDescription			=
2322		{
2323			0u,													// VkSubpassDescriptionFlags	flags;
2324			VK_PIPELINE_BIND_POINT_GRAPHICS,					// VkPipelineBindPoint			pipelineBindPoint;
2325			0u,													// deUint32						inputCount;
2326			DE_NULL,											// constVkAttachmentReference*	pInputAttachments;
2327			1u,													// deUint32						colorCount;
2328			&attachmentReference,								// constVkAttachmentReference*	pColorAttachments;
2329			isMultiSampling() ? &resolveAttachmentRef : DE_NULL,// constVkAttachmentReference*	pResolveAttachments;
2330			DE_NULL,											// VkAttachmentReference		depthStencilAttachment;
2331			0u,													// deUint32						preserveCount;
2332			DE_NULL												// constVkAttachmentReference*	pPreserveAttachments;
2333		};
2334
2335		const VkRenderPassCreateInfo					renderPassParams			=
2336		{
2337			VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,			// VkStructureType					sType;
2338			DE_NULL,											// const void*						pNext;
2339			0u,													// VkRenderPassCreateFlags			flags;
2340			isMultiSampling() ? 2u : 1u,						// deUint32							attachmentCount;
2341			attachmentDescription,								// const VkAttachmentDescription*	pAttachments;
2342			1u,													// deUint32							subpassCount;
2343			&subpassDescription,								// const VkSubpassDescription*		pSubpasses;
2344			0u,													// deUint32							dependencyCount;
2345			DE_NULL												// const VkSubpassDependency*		pDependencies;
2346		};
2347
2348		renderPass = createRenderPass(vk, vkDevice, &renderPassParams);
2349	}
2350
2351	// Create framebuffer
2352	{
2353		const VkImageView								attachments[]				=
2354		{
2355			*colorImageView,
2356			*resolvedImageView
2357		};
2358
2359		const VkFramebufferCreateInfo					framebufferParams			=
2360		{
2361			VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,			// VkStructureType				sType;
2362			DE_NULL,											// const void*					pNext;
2363			(VkFramebufferCreateFlags)0,
2364			*renderPass,										// VkRenderPass					renderPass;
2365			isMultiSampling() ? 2u : 1u,						// deUint32						attachmentCount;
2366			attachments,										// const VkImageView*			pAttachments;
2367			(deUint32)m_renderSize.x(),							// deUint32						width;
2368			(deUint32)m_renderSize.y(),							// deUint32						height;
2369			1u													// deUint32						layers;
2370		};
2371
2372		framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
2373	}
2374
2375	// Create descriptors
2376	{
2377		setupUniforms(constCoords);
2378
2379		descriptorSetLayout = m_descriptorSetLayoutBuilder->build(vk, vkDevice);
2380		if (!m_uniformInfos.empty())
2381		{
2382			descriptorPool 									= m_descriptorPoolBuilder->build(vk, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
2383			const VkDescriptorSetAllocateInfo	allocInfo	=
2384			{
2385				VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
2386				DE_NULL,
2387				*descriptorPool,
2388				1u,
2389				&descriptorSetLayout.get(),
2390			};
2391
2392			descriptorSet = allocateDescriptorSet(vk, vkDevice, &allocInfo);
2393		}
2394
2395		for (deUint32 i = 0; i < m_uniformInfos.size(); i++)
2396		{
2397			const UniformInfo* uniformInfo = m_uniformInfos[i].get()->get();
2398			deUint32 location = uniformInfo->location;
2399
2400			if (uniformInfo->type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER)
2401			{
2402				const BufferUniform*	bufferInfo	= dynamic_cast<const BufferUniform*>(uniformInfo);
2403
2404				m_descriptorSetUpdateBuilder->writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(location), uniformInfo->type, &bufferInfo->descriptor);
2405			}
2406			else if (uniformInfo->type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
2407			{
2408				const SamplerUniform*	samplerInfo	= dynamic_cast<const SamplerUniform*>(uniformInfo);
2409
2410				m_descriptorSetUpdateBuilder->writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(location), uniformInfo->type, &samplerInfo->descriptor);
2411			}
2412			else
2413				DE_FATAL("Impossible");
2414		}
2415
2416		m_descriptorSetUpdateBuilder->update(vk, vkDevice);
2417	}
2418
2419	// Create pipeline layout
2420	{
2421		const VkPipelineLayoutCreateInfo				pipelineLayoutParams		=
2422		{
2423			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType				sType;
2424			DE_NULL,											// const void*					pNext;
2425			(VkPipelineLayoutCreateFlags)0,
2426			1u,													// deUint32						descriptorSetCount;
2427			&*descriptorSetLayout,								// const VkDescriptorSetLayout*	pSetLayouts;
2428			0u,													// deUint32						pushConstantRangeCount;
2429			DE_NULL												// const VkPushConstantRange*	pPushConstantRanges;
2430		};
2431
2432		pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
2433	}
2434
2435	// Create shaders
2436	{
2437		vertexShaderModule		= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get(m_vertexShaderName), 0);
2438		fragmentShaderModule	= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get(m_fragmentShaderName), 0);
2439	}
2440
2441	// Create pipeline
2442	{
2443		const VkPipelineShaderStageCreateInfo			shaderStageParams[2]		=
2444		{
2445			{
2446				VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,		// VkStructureType				sType;
2447				DE_NULL,													// const void*					pNext;
2448				(VkPipelineShaderStageCreateFlags)0,
2449				VK_SHADER_STAGE_VERTEX_BIT,									// VkShaderStage				stage;
2450				*vertexShaderModule,										// VkShader						shader;
2451				"main",
2452				DE_NULL														// const VkSpecializationInfo*	pSpecializationInfo;
2453			},
2454			{
2455				VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,		// VkStructureType				sType;
2456				DE_NULL,													// const void*					pNext;
2457				(VkPipelineShaderStageCreateFlags)0,
2458				VK_SHADER_STAGE_FRAGMENT_BIT,								// VkShaderStage				stage;
2459				*fragmentShaderModule,										// VkShader						shader;
2460				"main",
2461				DE_NULL														// const VkSpecializationInfo*	pSpecializationInfo;
2462			}
2463		};
2464
2465		// Add test case specific attributes
2466		if (m_attribFunc)
2467			m_attribFunc(*this, numVertices);
2468
2469		// Add base attributes
2470		setupDefaultInputs();
2471
2472		const VkPipelineVertexInputStateCreateInfo		vertexInputStateParams		=
2473		{
2474			VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType							sType;
2475			DE_NULL,														// const void*								pNext;
2476			(VkPipelineVertexInputStateCreateFlags)0,
2477			(deUint32)m_vertexBindingDescription.size(),					// deUint32									bindingCount;
2478			&m_vertexBindingDescription[0],									// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
2479			(deUint32)m_vertexAttributeDescription.size(),					// deUint32									attributeCount;
2480			&m_vertexAttributeDescription[0],								// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
2481		};
2482
2483		const VkPipelineInputAssemblyStateCreateInfo	inputAssemblyStateParams	=
2484		{
2485			VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	// VkStructureType		sType;
2486			DE_NULL,														// const void*			pNext;
2487			(VkPipelineInputAssemblyStateCreateFlags)0,
2488			VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,							// VkPrimitiveTopology	topology;
2489			false															// VkBool32				primitiveRestartEnable;
2490		};
2491
2492		const VkViewport								viewport					=
2493		{
2494			0.0f,						// float	originX;
2495			0.0f,						// float	originY;
2496			(float)m_renderSize.x(),	// float	width;
2497			(float)m_renderSize.y(),	// float	height;
2498			0.0f,						// float	minDepth;
2499			1.0f						// float	maxDepth;
2500		};
2501
2502		const VkRect2D									scissor						=
2503		{
2504			{
2505				0u,					// deUint32	x;
2506				0u,					// deUint32	y;
2507			},							// VkOffset2D	offset;
2508			{
2509				m_renderSize.x(),	// deUint32	width;
2510				m_renderSize.y(),	// deUint32	height;
2511			},							// VkExtent2D	extent;
2512		};
2513
2514		const VkPipelineViewportStateCreateInfo			viewportStateParams			=
2515		{
2516			VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,			// VkStructureType						sType;
2517			DE_NULL,														// const void*							pNext;
2518			0u,																// VkPipelineViewportStateCreateFlags	flags;
2519			1u,																// deUint32								viewportCount;
2520			&viewport,														// const VkViewport*					pViewports;
2521			1u,																// deUint32								scissorsCount;
2522			&scissor,														// const VkRect2D*						pScissors;
2523		};
2524
2525		const VkPipelineRasterizationStateCreateInfo	rasterStateParams			=
2526		{
2527			VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,		// VkStructureType	sType;
2528			DE_NULL,														// const void*		pNext;
2529			(VkPipelineRasterizationStateCreateFlags)0,
2530			false,															// VkBool32			depthClipEnable;
2531			false,															// VkBool32			rasterizerDiscardEnable;
2532			VK_POLYGON_MODE_FILL,											// VkFillMode		fillMode;
2533			VK_CULL_MODE_NONE,												// VkCullMode		cullMode;
2534			VK_FRONT_FACE_COUNTER_CLOCKWISE,								// VkFrontFace		frontFace;
2535			false,															// VkBool32			depthBiasEnable;
2536			0.0f,															// float			depthBias;
2537			0.0f,															// float			depthBiasClamp;
2538			0.0f,															// float			slopeScaledDepthBias;
2539			1.0f,															// float			lineWidth;
2540		};
2541
2542		const VkPipelineMultisampleStateCreateInfo		multisampleStateParams =
2543		{
2544			VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,		// VkStructureType							sType;
2545			DE_NULL,														// const void*								pNext;
2546			0u,																// VkPipelineMultisampleStateCreateFlags	flags;
2547			m_sampleCount,													// VkSampleCountFlagBits					rasterizationSamples;
2548			VK_FALSE,														// VkBool32									sampleShadingEnable;
2549			0.0f,															// float									minSampleShading;
2550			DE_NULL,														// const VkSampleMask*						pSampleMask;
2551			VK_FALSE,														// VkBool32									alphaToCoverageEnable;
2552			VK_FALSE														// VkBool32									alphaToOneEnable;
2553		};
2554
2555		const VkPipelineColorBlendAttachmentState		colorBlendAttachmentState	=
2556		{
2557			false,															// VkBool32			blendEnable;
2558			VK_BLEND_FACTOR_ONE,											// VkBlend			srcBlendColor;
2559			VK_BLEND_FACTOR_ZERO,											// VkBlend			destBlendColor;
2560			VK_BLEND_OP_ADD,												// VkBlendOp		blendOpColor;
2561			VK_BLEND_FACTOR_ONE,											// VkBlend			srcBlendAlpha;
2562			VK_BLEND_FACTOR_ZERO,											// VkBlend			destBlendAlpha;
2563			VK_BLEND_OP_ADD,												// VkBlendOp		blendOpAlpha;
2564			(VK_COLOR_COMPONENT_R_BIT |
2565			 VK_COLOR_COMPONENT_G_BIT |
2566			 VK_COLOR_COMPONENT_B_BIT |
2567			 VK_COLOR_COMPONENT_A_BIT),										// VkChannelFlags	channelWriteMask;
2568		};
2569
2570		const VkPipelineColorBlendStateCreateInfo		colorBlendStateParams		=
2571		{
2572			VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType;
2573			DE_NULL,													// const void*									pNext;
2574			(VkPipelineColorBlendStateCreateFlags)0,
2575			false,														// VkBool32										logicOpEnable;
2576			VK_LOGIC_OP_COPY,											// VkLogicOp									logicOp;
2577			1u,															// deUint32										attachmentCount;
2578			&colorBlendAttachmentState,									// const VkPipelineColorBlendAttachmentState*	pAttachments;
2579			{ 0.0f, 0.0f, 0.0f, 0.0f },									// float										blendConst[4];
2580		};
2581
2582		const VkGraphicsPipelineCreateInfo				graphicsPipelineParams		=
2583		{
2584			VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,	// VkStructureType									sType;
2585			DE_NULL,											// const void*										pNext;
2586			0u,													// VkPipelineCreateFlags							flags;
2587			2u,													// deUint32											stageCount;
2588			shaderStageParams,									// const VkPipelineShaderStageCreateInfo*			pStages;
2589			&vertexInputStateParams,							// const VkPipelineVertexInputStateCreateInfo*		pVertexInputState;
2590			&inputAssemblyStateParams,							// const VkPipelineInputAssemblyStateCreateInfo*	pInputAssemblyState;
2591			DE_NULL,											// const VkPipelineTessellationStateCreateInfo*		pTessellationState;
2592			&viewportStateParams,								// const VkPipelineViewportStateCreateInfo*			pViewportState;
2593			&rasterStateParams,									// const VkPipelineRasterStateCreateInfo*			pRasterState;
2594			&multisampleStateParams,							// const VkPipelineMultisampleStateCreateInfo*		pMultisampleState;
2595			DE_NULL,											// const VkPipelineDepthStencilStateCreateInfo*		pDepthStencilState;
2596			&colorBlendStateParams,								// const VkPipelineColorBlendStateCreateInfo*		pColorBlendState;
2597			(const VkPipelineDynamicStateCreateInfo*)DE_NULL,	// const VkPipelineDynamicStateCreateInfo*			pDynamicState;
2598			*pipelineLayout,									// VkPipelineLayout									layout;
2599			*renderPass,										// VkRenderPass										renderPass;
2600			0u,													// deUint32											subpass;
2601			0u,													// VkPipeline										basePipelineHandle;
2602			0u													// deInt32											basePipelineIndex;
2603		};
2604
2605		graphicsPipeline = createGraphicsPipeline(vk, vkDevice, DE_NULL, &graphicsPipelineParams);
2606	}
2607
2608	// Create vertex indices buffer
2609	{
2610		const VkDeviceSize								indiceBufferSize			= numTriangles * 3 * sizeof(deUint16);
2611		const VkBufferCreateInfo						indiceBufferParams			=
2612		{
2613			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
2614			DE_NULL,									// const void*			pNext;
2615			0u,											// VkBufferCreateFlags	flags;
2616			indiceBufferSize,							// VkDeviceSize			size;
2617			VK_BUFFER_USAGE_INDEX_BUFFER_BIT,			// VkBufferUsageFlags	usage;
2618			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
2619			1u,											// deUint32				queueFamilyCount;
2620			&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
2621		};
2622
2623		indiceBuffer		= createBuffer(vk, vkDevice, &indiceBufferParams);
2624		indiceBufferAlloc	= m_memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *indiceBuffer), MemoryRequirement::HostVisible);
2625
2626		VK_CHECK(vk.bindBufferMemory(vkDevice, *indiceBuffer, indiceBufferAlloc->getMemory(), indiceBufferAlloc->getOffset()));
2627
2628		// Load vertice indices into buffer
2629		deMemcpy(indiceBufferAlloc->getHostPtr(), indices, (size_t)indiceBufferSize);
2630		flushMappedMemoryRange(vk, vkDevice, indiceBufferAlloc->getMemory(), indiceBufferAlloc->getOffset(), indiceBufferSize);
2631	}
2632
2633	// Create command pool
2634	{
2635		const VkCommandPoolCreateInfo					cmdPoolParams				=
2636		{
2637			VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,		// VkStructureType		sType;
2638			DE_NULL,										// const void*			pNext;
2639			VK_COMMAND_POOL_CREATE_TRANSIENT_BIT,			// VkCmdPoolCreateFlags	flags;
2640			queueFamilyIndex,								// deUint32				queueFamilyIndex;
2641		};
2642
2643		cmdPool = createCommandPool(vk, vkDevice, &cmdPoolParams);
2644	}
2645
2646	// Create command buffer
2647	{
2648		const VkCommandBufferAllocateInfo				cmdBufferParams				=
2649		{
2650			VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,	// VkStructureType			sType;
2651			DE_NULL,										// const void*				pNext;
2652			*cmdPool,										// VkCmdPool				cmdPool;
2653			VK_COMMAND_BUFFER_LEVEL_PRIMARY,				// VkCmdBufferLevel			level;
2654			1u												// deUint32					bufferCount;
2655		};
2656
2657		const VkCommandBufferBeginInfo					cmdBufferBeginInfo			=
2658		{
2659			VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,	// VkStructureType			sType;
2660			DE_NULL,										// const void*				pNext;
2661			0u,												// VkCmdBufferOptimizeFlags	flags;
2662			(const VkCommandBufferInheritanceInfo*)DE_NULL,
2663		};
2664
2665		const VkClearValue								clearValues					= makeClearValueColorF32(m_clearColor.x(),
2666																											 m_clearColor.y(),
2667																											 m_clearColor.z(),
2668																											 m_clearColor.w());
2669
2670		const VkRenderPassBeginInfo						renderPassBeginInfo			=
2671		{
2672			VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,				// VkStructureType		sType;
2673			DE_NULL,												// const void*			pNext;
2674			*renderPass,											// VkRenderPass			renderPass;
2675			*framebuffer,											// VkFramebuffer		framebuffer;
2676			{ { 0, 0 },  {m_renderSize.x(), m_renderSize.y() } },	// VkRect2D				renderArea;
2677			1,														// deUint32				clearValueCount;
2678			&clearValues,											// const VkClearValue*	pClearValues;
2679		};
2680
2681		cmdBuffer = allocateCommandBuffer(vk, vkDevice, &cmdBufferParams);
2682
2683		VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufferBeginInfo));
2684
2685		{
2686			const VkImageMemoryBarrier					imageBarrier				=
2687			{
2688				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,										// VkStructureType			sType;
2689				DE_NULL,																	// const void*				pNext;
2690				0u,																			// VkAccessFlags			srcAccessMask;
2691				VK_PIPELINE_STAGE_TRANSFER_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,		// VkAccessFlags			dstAccessMask;
2692				VK_IMAGE_LAYOUT_UNDEFINED,													// VkImageLayout			oldLayout;
2693				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,									// VkImageLayout			newLayout;
2694				VK_QUEUE_FAMILY_IGNORED,													// deUint32					srcQueueFamilyIndex;
2695				VK_QUEUE_FAMILY_IGNORED,													// deUint32					dstQueueFamilyIndex;
2696				*colorImage,																// VkImage					image;
2697				{																			// VkImageSubresourceRange	subresourceRange;
2698					VK_IMAGE_ASPECT_COLOR_BIT,												// VkImageAspectFlags		aspectMask;
2699					0u,																		// deUint32					baseMipLevel;
2700					1u,																		// deUint32					mipLevels;
2701					0u,																		// deUint32					baseArrayLayer;
2702					1u,																		// deUint32					arraySize;
2703				}
2704			};
2705
2706			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);
2707
2708			if (isMultiSampling()) {
2709				// add multisample barrier
2710				const VkImageMemoryBarrier				multiSampleImageBarrier		=
2711				{
2712					VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,										// VkStructureType			sType;
2713					DE_NULL,																	// const void*				pNext;
2714					0u,																			// VkAccessFlags			srcAccessMask;
2715					VK_PIPELINE_STAGE_TRANSFER_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,		// VkAccessFlags			dstAccessMask;
2716					VK_IMAGE_LAYOUT_UNDEFINED,													// VkImageLayout			oldLayout;
2717					VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,									// VkImageLayout			newLayout;
2718					VK_QUEUE_FAMILY_IGNORED,													// deUint32					srcQueueFamilyIndex;
2719					VK_QUEUE_FAMILY_IGNORED,													// deUint32					dstQueueFamilyIndex;
2720					*resolvedImage,																// VkImage					image;
2721					{																			// VkImageSubresourceRange	subresourceRange;
2722						VK_IMAGE_ASPECT_COLOR_BIT,												// VkImageAspectFlags		aspectMask;
2723						0u,																		// deUint32					baseMipLevel;
2724						1u,																		// deUint32					mipLevels;
2725						0u,																		// deUint32					baseArrayLayer;
2726						1u,																		// deUint32					arraySize;
2727					}
2728				};
2729
2730				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);
2731			}
2732		}
2733
2734		vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
2735
2736		vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline);
2737		if (!m_uniformInfos.empty())
2738			vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1, &*descriptorSet, 0u, DE_NULL);
2739		vk.cmdBindIndexBuffer(*cmdBuffer, *indiceBuffer, 0, VK_INDEX_TYPE_UINT16);
2740
2741		const deUint32 numberOfVertexAttributes = (deUint32)m_vertexBuffers.size();
2742		const std::vector<VkDeviceSize> offsets(numberOfVertexAttributes, 0);
2743
2744		std::vector<VkBuffer> buffers(numberOfVertexAttributes);
2745		for (size_t i = 0; i < numberOfVertexAttributes; i++)
2746		{
2747			buffers[i] = m_vertexBuffers[i].get()->get();
2748		}
2749
2750		vk.cmdBindVertexBuffers(*cmdBuffer, 0, numberOfVertexAttributes, &buffers[0], &offsets[0]);
2751		vk.cmdDrawIndexed(*cmdBuffer, numTriangles * 3, 1, 0, 0, 0);
2752
2753		vk.cmdEndRenderPass(*cmdBuffer);
2754		VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
2755	}
2756
2757	// Create fence
2758	{
2759		const VkFenceCreateInfo							fenceParams					=
2760		{
2761			VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,	// VkStructureType		sType;
2762			DE_NULL,								// const void*			pNext;
2763			0u										// VkFenceCreateFlags	flags;
2764		};
2765		fence = createFence(vk, vkDevice, &fenceParams);
2766	}
2767
2768	// Execute Draw
2769	{
2770		const VkSubmitInfo	submitInfo	=
2771		{
2772			VK_STRUCTURE_TYPE_SUBMIT_INFO,
2773			DE_NULL,
2774			0u,
2775			(const VkSemaphore*)DE_NULL,
2776			(const VkPipelineStageFlags*)DE_NULL,
2777			1u,
2778			&cmdBuffer.get(),
2779			0u,
2780			(const VkSemaphore*)DE_NULL,
2781		};
2782
2783		VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *fence));
2784		VK_CHECK(vk.waitForFences(vkDevice, 1, &fence.get(), true, ~(0ull) /* infinity*/));
2785	}
2786
2787	// Read back the result
2788	{
2789		const tcu::TextureFormat						resultFormat				= mapVkFormat(m_colorFormat);
2790		const VkDeviceSize								imageSizeBytes				= (VkDeviceSize)(resultFormat.getPixelSize() * m_renderSize.x() * m_renderSize.y());
2791		const VkBufferCreateInfo						readImageBufferParams		=
2792		{
2793			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		//  VkStructureType		sType;
2794			DE_NULL,									//  const void*			pNext;
2795			0u,											//  VkBufferCreateFlags	flags;
2796			imageSizeBytes,								//  VkDeviceSize		size;
2797			VK_BUFFER_USAGE_TRANSFER_DST_BIT,			//  VkBufferUsageFlags	usage;
2798			VK_SHARING_MODE_EXCLUSIVE,					//  VkSharingMode		sharingMode;
2799			1u,											//  deUint32			queueFamilyCount;
2800			&queueFamilyIndex,							//  const deUint32*		pQueueFamilyIndices;
2801		};
2802		const Unique<VkBuffer>							readImageBuffer				(createBuffer(vk, vkDevice, &readImageBufferParams));
2803		const de::UniquePtr<Allocation>					readImageBufferMemory		(m_memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *readImageBuffer), MemoryRequirement::HostVisible));
2804
2805		VK_CHECK(vk.bindBufferMemory(vkDevice, *readImageBuffer, readImageBufferMemory->getMemory(), readImageBufferMemory->getOffset()));
2806
2807		// Copy image to buffer
2808		const VkCommandBufferAllocateInfo				cmdBufferParams				=
2809		{
2810			VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,	// VkStructureType			sType;
2811			DE_NULL,										// const void*				pNext;
2812			*cmdPool,										// VkCmdPool				cmdPool;
2813			VK_COMMAND_BUFFER_LEVEL_PRIMARY,				// VkCmdBufferLevel			level;
2814			1u												// deUint32					bufferCount;
2815		};
2816
2817		const VkCommandBufferBeginInfo					cmdBufferBeginInfo			=
2818		{
2819			VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,	// VkStructureType			sType;
2820			DE_NULL,										// const void*				pNext;
2821			0u,												// VkCmdBufferOptimizeFlags	flags;
2822			(const VkCommandBufferInheritanceInfo*)DE_NULL,
2823		};
2824
2825		const Move<VkCommandBuffer>						resultCmdBuffer				= allocateCommandBuffer(vk, vkDevice, &cmdBufferParams);
2826
2827		const VkBufferImageCopy							copyParams					=
2828		{
2829			0u,											// VkDeviceSize			bufferOffset;
2830			(deUint32)m_renderSize.x(),					// deUint32				bufferRowLength;
2831			(deUint32)m_renderSize.y(),					// deUint32				bufferImageHeight;
2832			{
2833				VK_IMAGE_ASPECT_COLOR_BIT,			// VkImageAspect		aspect;
2834				0u,									// deUint32				mipLevel;
2835				0u,									// deUint32				arraySlice;
2836				1u,									// deUint32				arraySize;
2837			},											// VkImageSubresourceCopy	imageSubresource;
2838			{ 0u, 0u, 0u },								// VkOffset3D			imageOffset;
2839			{ m_renderSize.x(), m_renderSize.y(), 1u }	// VkExtent3D			imageExtent;
2840		};
2841		const VkSubmitInfo								submitInfo					=
2842		{
2843			VK_STRUCTURE_TYPE_SUBMIT_INFO,
2844			DE_NULL,
2845			0u,
2846			(const VkSemaphore*)DE_NULL,
2847			(const VkPipelineStageFlags*)DE_NULL,
2848			1u,
2849			&resultCmdBuffer.get(),
2850			0u,
2851			(const VkSemaphore*)DE_NULL,
2852		};
2853
2854		VK_CHECK(vk.beginCommandBuffer(*resultCmdBuffer, &cmdBufferBeginInfo));
2855
2856		const VkImageMemoryBarrier						imageBarrier				=
2857		{
2858			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,									// VkStructureType			sType;
2859			DE_NULL,																// const void*				pNext;
2860			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT,	// VkAccessFlags			srcAccessMask;
2861			VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags			dstAccessMask;
2862			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,								// VkImageLayout			oldLayout;
2863			VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,									// VkImageLayout			newLayout;
2864			VK_QUEUE_FAMILY_IGNORED,												// deUint32					srcQueueFamilyIndex;
2865			VK_QUEUE_FAMILY_IGNORED,												// deUint32					dstQueueFamilyIndex;
2866			isMultiSampling() ? *resolvedImage : *colorImage,						// VkImage					image;
2867			{																		// VkImageSubresourceRange	subresourceRange;
2868				VK_IMAGE_ASPECT_COLOR_BIT,											// VkImageAspectFlags		aspectMask;
2869				0u,																	// deUint32					baseMipLevel;
2870				1u,																	// deUint32					mipLevels;
2871				0u,																	// deUint32					baseArraySlice;
2872				1u																	// deUint32					arraySize;
2873			}
2874		};
2875
2876		const VkBufferMemoryBarrier						bufferBarrier				=
2877		{
2878			VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	// VkStructureType	sType;
2879			DE_NULL,									// const void*		pNext;
2880			VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags	srcAccessMask;
2881			VK_ACCESS_HOST_READ_BIT,					// VkAccessFlags	dstAccessMask;
2882			VK_QUEUE_FAMILY_IGNORED,					// deUint32			srcQueueFamilyIndex;
2883			VK_QUEUE_FAMILY_IGNORED,					// deUint32			dstQueueFamilyIndex;
2884			*readImageBuffer,							// VkBuffer			buffer;
2885			0u,											// VkDeviceSize		offset;
2886			imageSizeBytes								// VkDeviceSize		size;
2887		};
2888
2889		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);
2890		vk.cmdCopyImageToBuffer(*resultCmdBuffer, isMultiSampling() ? *resolvedImage : *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *readImageBuffer, 1u, &copyParams);
2891		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);
2892
2893		VK_CHECK(vk.endCommandBuffer(*resultCmdBuffer));
2894
2895		VK_CHECK(vk.resetFences(vkDevice, 1, &fence.get()));
2896		VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *fence));
2897		VK_CHECK(vk.waitForFences(vkDevice, 1, &fence.get(), true, ~(0ull) /* infinity */));
2898
2899		invalidateMappedMemoryRange(vk, vkDevice, readImageBufferMemory->getMemory(), readImageBufferMemory->getOffset(), imageSizeBytes);
2900
2901		const tcu::ConstPixelBufferAccess				resultAccess				(resultFormat, m_renderSize.x(), m_renderSize.y(), 1, readImageBufferMemory->getHostPtr());
2902
2903		m_resultImage.setStorage(resultFormat, m_renderSize.x(), m_renderSize.y());
2904		tcu::copy(m_resultImage.getAccess(), resultAccess);
2905	}
2906}
2907
2908void ShaderRenderCaseInstance::computeVertexReference (tcu::Surface& result, const QuadGrid& quadGrid)
2909{
2910	DE_ASSERT(m_evaluator);
2911
2912	// Buffer info.
2913	const int				width		= result.getWidth();
2914	const int				height		= result.getHeight();
2915	const int				gridSize	= quadGrid.getGridSize();
2916	const int				stride		= gridSize + 1;
2917	const bool				hasAlpha	= true; // \todo [2015-09-07 elecro] add correct alpha check
2918	ShaderEvalContext		evalCtx		(quadGrid);
2919
2920	// Evaluate color for each vertex.
2921	std::vector<tcu::Vec4>	colors		((gridSize + 1) * (gridSize + 1));
2922	for (int y = 0; y < gridSize+1; y++)
2923	for (int x = 0; x < gridSize+1; x++)
2924	{
2925		const float	sx			= (float)x / (float)gridSize;
2926		const float	sy			= (float)y / (float)gridSize;
2927		const int	vtxNdx		= ((y * (gridSize+1)) + x);
2928
2929		evalCtx.reset(sx, sy);
2930		m_evaluator->evaluate(evalCtx);
2931		DE_ASSERT(!evalCtx.isDiscarded); // Discard is not available in vertex shader.
2932		tcu::Vec4 color = evalCtx.color;
2933
2934		if (!hasAlpha)
2935			color.w() = 1.0f;
2936
2937		colors[vtxNdx] = color;
2938	}
2939
2940	// Render quads.
2941	for (int y = 0; y < gridSize; y++)
2942	for (int x = 0; x < gridSize; x++)
2943	{
2944		const float		x0		= (float)x       / (float)gridSize;
2945		const float		x1		= (float)(x + 1) / (float)gridSize;
2946		const float		y0		= (float)y       / (float)gridSize;
2947		const float		y1		= (float)(y + 1) / (float)gridSize;
2948
2949		const float		sx0		= x0 * (float)width;
2950		const float		sx1		= x1 * (float)width;
2951		const float		sy0		= y0 * (float)height;
2952		const float		sy1		= y1 * (float)height;
2953		const float		oosx	= 1.0f / (sx1 - sx0);
2954		const float		oosy	= 1.0f / (sy1 - sy0);
2955
2956		const int		ix0		= deCeilFloatToInt32(sx0 - 0.5f);
2957		const int		ix1		= deCeilFloatToInt32(sx1 - 0.5f);
2958		const int		iy0		= deCeilFloatToInt32(sy0 - 0.5f);
2959		const int		iy1		= deCeilFloatToInt32(sy1 - 0.5f);
2960
2961		const int		v00		= (y * stride) + x;
2962		const int		v01		= (y * stride) + x + 1;
2963		const int		v10		= ((y + 1) * stride) + x;
2964		const int		v11		= ((y + 1) * stride) + x + 1;
2965		const tcu::Vec4	c00		= colors[v00];
2966		const tcu::Vec4	c01		= colors[v01];
2967		const tcu::Vec4	c10		= colors[v10];
2968		const tcu::Vec4	c11		= colors[v11];
2969
2970		//printf("(%d,%d) -> (%f..%f, %f..%f) (%d..%d, %d..%d)\n", x, y, sx0, sx1, sy0, sy1, ix0, ix1, iy0, iy1);
2971
2972		for (int iy = iy0; iy < iy1; iy++)
2973		for (int ix = ix0; ix < ix1; ix++)
2974		{
2975			DE_ASSERT(deInBounds32(ix, 0, width));
2976			DE_ASSERT(deInBounds32(iy, 0, height));
2977
2978			const float			sfx		= (float)ix + 0.5f;
2979			const float			sfy		= (float)iy + 0.5f;
2980			const float			fx1		= deFloatClamp((sfx - sx0) * oosx, 0.0f, 1.0f);
2981			const float			fy1		= deFloatClamp((sfy - sy0) * oosy, 0.0f, 1.0f);
2982
2983			// Triangle quad interpolation.
2984			const bool			tri		= fx1 + fy1 <= 1.0f;
2985			const float			tx		= tri ? fx1 : (1.0f-fx1);
2986			const float			ty		= tri ? fy1 : (1.0f-fy1);
2987			const tcu::Vec4&	t0		= tri ? c00 : c11;
2988			const tcu::Vec4&	t1		= tri ? c01 : c10;
2989			const tcu::Vec4&	t2		= tri ? c10 : c01;
2990			const tcu::Vec4		color	= t0 + (t1-t0)*tx + (t2-t0)*ty;
2991
2992			result.setPixel(ix, iy, tcu::RGBA(color));
2993		}
2994	}
2995}
2996
2997void ShaderRenderCaseInstance::computeFragmentReference (tcu::Surface& result, const QuadGrid& quadGrid)
2998{
2999	DE_ASSERT(m_evaluator);
3000
3001	// Buffer info.
3002	const int			width		= result.getWidth();
3003	const int			height		= result.getHeight();
3004	const bool			hasAlpha	= true;  // \todo [2015-09-07 elecro] add correct alpha check
3005	ShaderEvalContext	evalCtx		(quadGrid);
3006
3007	// Render.
3008	for (int y = 0; y < height; y++)
3009	for (int x = 0; x < width; x++)
3010	{
3011		const float sx = ((float)x + 0.5f) / (float)width;
3012		const float sy = ((float)y + 0.5f) / (float)height;
3013
3014		evalCtx.reset(sx, sy);
3015		m_evaluator->evaluate(evalCtx);
3016		// Select either clear color or computed color based on discarded bit.
3017		tcu::Vec4 color = evalCtx.isDiscarded ? m_clearColor : evalCtx.color;
3018
3019		if (!hasAlpha)
3020			color.w() = 1.0f;
3021
3022		result.setPixel(x, y, tcu::RGBA(color));
3023	}
3024}
3025
3026bool ShaderRenderCaseInstance::compareImages (const tcu::Surface& resImage, const tcu::Surface& refImage, float errorThreshold)
3027{
3028	return tcu::fuzzyCompare(m_context.getTestContext().getLog(), "ComparisonResult", "Image comparison result", refImage, resImage, errorThreshold, tcu::COMPARE_LOG_RESULT);
3029}
3030
3031} // sr
3032} // vkt
3033