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