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