Home | History | Annotate | Download | only in shaderrender
      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 
     51 namespace vkt
     52 {
     53 namespace sr
     54 {
     55 
     56 using namespace vk;
     57 
     58 namespace
     59 {
     60 
     61 static const int		GRID_SIZE			= 64;
     62 static const deUint32	MAX_RENDER_WIDTH	= 128;
     63 static const deUint32	MAX_RENDER_HEIGHT	= 128;
     64 static const tcu::Vec4	DEFAULT_CLEAR_COLOR	= tcu::Vec4(0.125f, 0.25f, 0.5f, 1.0f);
     65 
     66 static 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 
     84 static 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 */
    103 static 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 */
    113 static 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 
    139 class QuadGrid
    140 {
    141 public:
    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 
    171 private:
    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 
    189 QuadGrid::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 
    257 QuadGrid::~QuadGrid (void)
    258 {
    259 }
    260 
    261 inline 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 
    268 inline 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 
    273 inline 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 
    281 TextureBinding::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 
    296 TextureBinding::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 
    303 TextureBinding::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 
    310 TextureBinding::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 
    317 TextureBinding::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 
    324 TextureBinding::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 
    331 TextureBinding::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 
    338 TextureBinding::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 
    345 TextureBinding::~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 
    360 de::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 
    380 ShaderEvalContext::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 
    413 ShaderEvalContext::~ShaderEvalContext (void)
    414 {
    415 }
    416 
    417 void 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 
    434 tcu::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 
    444 ShaderEvaluator::ShaderEvaluator (void)
    445 	: m_evalFunc(DE_NULL)
    446 {
    447 }
    448 
    449 ShaderEvaluator::ShaderEvaluator (ShaderEvalFunc evalFunc)
    450 	: m_evalFunc(evalFunc)
    451 {
    452 }
    453 
    454 ShaderEvaluator::~ShaderEvaluator (void)
    455 {
    456 }
    457 
    458 void ShaderEvaluator::evaluate (ShaderEvalContext& ctx) const
    459 {
    460 	DE_ASSERT(m_evalFunc);
    461 	m_evalFunc(ctx);
    462 }
    463 
    464 // UniformSetup.
    465 
    466 UniformSetup::UniformSetup (void)
    467 	: m_setupFunc(DE_NULL)
    468 {
    469 }
    470 
    471 UniformSetup::UniformSetup (UniformSetupFunc setupFunc)
    472 	: m_setupFunc(setupFunc)
    473 {
    474 }
    475 
    476 UniformSetup::~UniformSetup (void)
    477 {
    478 }
    479 
    480 void UniformSetup::setup (ShaderRenderCaseInstance& instance, const tcu::Vec4& constCoords) const
    481 {
    482 	if (m_setupFunc)
    483 		m_setupFunc(instance, constCoords);
    484 }
    485 
    486 // ShaderRenderCase.
    487 
    488 ShaderRenderCase::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 
    502 ShaderRenderCase::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 
    516 ShaderRenderCase::~ShaderRenderCase (void)
    517 {
    518 }
    519 
    520 void 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 
    526 TestInstance* 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 
    535 ShaderRenderCaseInstance::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 
    554 ShaderRenderCaseInstance::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 
    577 ShaderRenderCaseInstance::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 
    600 static 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 
    614 ShaderRenderCaseInstance::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 
    624 Move<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 
    657 vk::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 
    663 ShaderRenderCaseInstance::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 
    673 vk::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 
    683 ShaderRenderCaseInstance::~ShaderRenderCaseInstance (void)
    684 {
    685 }
    686 
    687 VkDevice 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 
    695 deUint32 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 
    703 const 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 
    711 VkQueue 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 
    719 VkPhysicalDevice ShaderRenderCaseInstance::getPhysicalDevice (void) const
    720 {
    721 	// Same in sparse and regular case
    722 	return m_context.getPhysicalDevice();
    723 }
    724 
    725 const InstanceInterface& ShaderRenderCaseInstance::getInstanceInterface (void) const
    726 {
    727 	// Same in sparse and regular case
    728 	return m_context.getInstanceInterface();
    729 }
    730 
    731 tcu::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 
    764 void 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 
    779 void 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 
    814 void 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 
    822 void 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 
    879 void 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 
    889 void ShaderRenderCaseInstance::setupUniforms (const tcu::Vec4& constCoords)
    890 {
    891 	if (m_uniformSetup)
    892 		m_uniformSetup->setup(*this, constCoords);
    893 }
    894 
    895 void 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 
   1006 const 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 
   1012 void ShaderRenderCaseInstance::setSampleCount (VkSampleCountFlagBits sampleCount)
   1013 {
   1014 	m_sampleCount	= sampleCount;
   1015 }
   1016 
   1017 bool ShaderRenderCaseInstance::isMultiSampling (void) const
   1018 {
   1019 	return m_sampleCount != VK_SAMPLE_COUNT_1_BIT;
   1020 }
   1021 
   1022 void 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 
   1246 void 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
   1392 Move<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 
   1404 VkExtent3D 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 
   1415 tcu::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 
   1426 bool 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 
   1448 void 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 
   1467 void 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 
   1890 void 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 
   2084 void 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 
   2093 void ShaderRenderCaseInstance::updatePushConstants (vk::VkCommandBuffer, vk::VkPipelineLayout)
   2094 {
   2095 }
   2096 
   2097 void 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 
   2233 void 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 
   2308 void 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 
   2316 void 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 
   3128 void 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 
   3217 void 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 
   3246 bool 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