Home | History | Annotate | Download | only in shaderrender
      1 /*------------------------------------------------------------------------
      2  * Vulkan Conformance Tests
      3  * ------------------------
      4  *
      5  * Copyright (c) 2015 The Khronos Group Inc.
      6  * Copyright (c) 2015 Samsung Electronics Co., Ltd.
      7  * Copyright (c) 2016 The Android Open Source Project
      8  *
      9  * Licensed under the Apache License, Version 2.0 (the "License");
     10  * you may not use this file except in compliance with the License.
     11  * You may obtain a copy of the License at
     12  *
     13  *      http://www.apache.org/licenses/LICENSE-2.0
     14  *
     15  * Unless required by applicable law or agreed to in writing, software
     16  * distributed under the License is distributed on an "AS IS" BASIS,
     17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     18  * See the License for the specific language governing permissions and
     19  * limitations under the License.
     20  *
     21  *//*!
     22  * \file
     23  * \brief Vulkan ShaderRenderCase
     24  *//*--------------------------------------------------------------------*/
     25 
     26 #include "vktShaderRender.hpp"
     27 
     28 #include "tcuImageCompare.hpp"
     29 #include "tcuImageIO.hpp"
     30 #include "tcuTestLog.hpp"
     31 #include "tcuTextureUtil.hpp"
     32 #include "tcuSurface.hpp"
     33 #include "tcuVector.hpp"
     34 
     35 #include "deFilePath.hpp"
     36 #include "deMath.h"
     37 #include "deUniquePtr.hpp"
     38 
     39 #include "vkDeviceUtil.hpp"
     40 #include "vkImageUtil.hpp"
     41 #include "vkPlatform.hpp"
     42 #include "vkQueryUtil.hpp"
     43 #include "vkRef.hpp"
     44 #include "vkRefUtil.hpp"
     45 #include "vkStrUtil.hpp"
     46 #include "vkTypeUtil.hpp"
     47 
     48 #include <vector>
     49 #include <string>
     50 
     51 namespace vkt
     52 {
     53 namespace sr
     54 {
     55 
     56 using namespace vk;
     57 
     58 namespace
     59 {
     60 
     61 static const int		GRID_SIZE			= 2;
     62 static const deUint32	MAX_RENDER_WIDTH	= 128;
     63 static const deUint32	MAX_RENDER_HEIGHT	= 128;
     64 static const tcu::Vec4	DEFAULT_CLEAR_COLOR	= tcu::Vec4(0.125f, 0.25f, 0.5f, 1.0f);
     65 
     66 static bool isSupportedLinearTilingFormat (const InstanceInterface& instanceInterface, VkPhysicalDevice device, VkFormat format)
     67 {
     68 	VkFormatProperties formatProps;
     69 
     70 	instanceInterface.getPhysicalDeviceFormatProperties(device, format, &formatProps);
     71 
     72 	return (formatProps.linearTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) != 0u;
     73 }
     74 
     75 static bool isSupportedOptimalTilingFormat (const InstanceInterface& instanceInterface, VkPhysicalDevice device, VkFormat format)
     76 {
     77 	VkFormatProperties formatProps;
     78 
     79 	instanceInterface.getPhysicalDeviceFormatProperties(device, format, &formatProps);
     80 
     81 	return (formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) != 0u;
     82 }
     83 
     84 static VkImageMemoryBarrier createImageMemoryBarrier (const VkImage&	image,
     85 													  VkAccessFlags		srcAccessMask,
     86 													  VkAccessFlags		dstAccessMask,
     87 													  VkImageLayout		oldLayout,
     88 													  VkImageLayout		newLayout)
     89 {
     90 	VkImageMemoryBarrier imageMemoryBarrier	=
     91 	{
     92 		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		// VkStructureType				sType;
     93 		DE_NULL,									// const void*					pNext;
     94 		srcAccessMask,								// VkAccessFlags				srcAccessMask;
     95 		dstAccessMask,								// VkAccessFlags				dstAccessMask;
     96 		oldLayout,									// VkImageLayout				oldLayout;
     97 		newLayout,									// VkImageLayout				newLayout;
     98 		VK_QUEUE_FAMILY_IGNORED,					// deUint32						srcQueueFamilyIndex;
     99 		VK_QUEUE_FAMILY_IGNORED,					// deUint32						dstQueueFamilyIndex;
    100 		image,										// VkImage						image;
    101 		{
    102 			VK_IMAGE_ASPECT_COLOR_BIT,	// VkImageAspectFlags	aspectMask;
    103 			0,							// deUint32				baseMipLevel;
    104 			1,							// deUint32				mipLevels;
    105 			0,							// deUint32				baseArrayLayer;
    106 			1							// deUint32				arraySize;
    107 		}											// VkImageSubresourceRange		subresourceRange;
    108 	};
    109 	return imageMemoryBarrier;
    110 }
    111 
    112 } // anonymous
    113 
    114 // QuadGrid.
    115 
    116 class QuadGrid
    117 {
    118 public:
    119 											QuadGrid				(int									gridSize,
    120 																	 int									screenWidth,
    121 																	 int									screenHeight,
    122 																	 const tcu::Vec4&						constCoords,
    123 																	 const std::vector<tcu::Mat4>&			userAttribTransforms,
    124 																	 const std::vector<TextureBindingSp>&	textures);
    125 											~QuadGrid				(void);
    126 
    127 	int										getGridSize				(void) const { return m_gridSize; }
    128 	int										getNumVertices			(void) const { return m_numVertices; }
    129 	int										getNumTriangles			(void) const { return m_numTriangles; }
    130 	const tcu::Vec4&						getConstCoords			(void) const { return m_constCoords; }
    131 	const std::vector<tcu::Mat4>			getUserAttribTransforms	(void) const { return m_userAttribTransforms; }
    132 	const std::vector<TextureBindingSp>&	getTextures				(void) const { return m_textures; }
    133 
    134 	const tcu::Vec4*						getPositions			(void) const { return &m_positions[0]; }
    135 	const float*							getAttribOne			(void) const { return &m_attribOne[0]; }
    136 	const tcu::Vec4*						getCoords				(void) const { return &m_coords[0]; }
    137 	const tcu::Vec4*						getUnitCoords			(void) const { return &m_unitCoords[0]; }
    138 
    139 	const tcu::Vec4*						getUserAttrib			(int attribNdx) const { return &m_userAttribs[attribNdx][0]; }
    140 	const deUint16*							getIndices				(void) const { return &m_indices[0]; }
    141 
    142 	tcu::Vec4								getCoords				(float sx, float sy) const;
    143 	tcu::Vec4								getUnitCoords			(float sx, float sy) const;
    144 
    145 	int										getNumUserAttribs		(void) const { return (int)m_userAttribTransforms.size(); }
    146 	tcu::Vec4								getUserAttrib			(int attribNdx, float sx, float sy) const;
    147 
    148 private:
    149 	const int								m_gridSize;
    150 	const int								m_numVertices;
    151 	const int								m_numTriangles;
    152 	const tcu::Vec4							m_constCoords;
    153 	const std::vector<tcu::Mat4>			m_userAttribTransforms;
    154 
    155 	const std::vector<TextureBindingSp>&	m_textures;
    156 
    157 	std::vector<tcu::Vec4>					m_screenPos;
    158 	std::vector<tcu::Vec4>					m_positions;
    159 	std::vector<tcu::Vec4>					m_coords;		//!< Near-unit coordinates, roughly [-2.0 .. 2.0].
    160 	std::vector<tcu::Vec4>					m_unitCoords;	//!< Positive-only coordinates [0.0 .. 1.5].
    161 	std::vector<float>						m_attribOne;
    162 	std::vector<tcu::Vec4>					m_userAttribs[ShaderEvalContext::MAX_TEXTURES];
    163 	std::vector<deUint16>					m_indices;
    164 };
    165 
    166 QuadGrid::QuadGrid (int										gridSize,
    167 					int										width,
    168 					int										height,
    169 					const tcu::Vec4&						constCoords,
    170 					const std::vector<tcu::Mat4>&			userAttribTransforms,
    171 					const std::vector<TextureBindingSp>&	textures)
    172 	: m_gridSize				(gridSize)
    173 	, m_numVertices				((gridSize + 1) * (gridSize + 1))
    174 	, m_numTriangles			(gridSize * gridSize * 2)
    175 	, m_constCoords				(constCoords)
    176 	, m_userAttribTransforms	(userAttribTransforms)
    177 	, m_textures				(textures)
    178 {
    179 	const tcu::Vec4 viewportScale	((float)width, (float)height, 0.0f, 0.0f);
    180 
    181 	// Compute vertices.
    182 	m_screenPos.resize(m_numVertices);
    183 	m_positions.resize(m_numVertices);
    184 	m_coords.resize(m_numVertices);
    185 	m_unitCoords.resize(m_numVertices);
    186 	m_attribOne.resize(m_numVertices);
    187 
    188 	// User attributes.
    189 	for (int attrNdx = 0; attrNdx < DE_LENGTH_OF_ARRAY(m_userAttribs); attrNdx++)
    190 		m_userAttribs[attrNdx].resize(m_numVertices);
    191 
    192 	for (int y = 0; y < gridSize+1; y++)
    193 	for (int x = 0; x < gridSize+1; x++)
    194 	{
    195 		float		sx			= (float)x / (float)gridSize;
    196 		float		sy			= (float)y / (float)gridSize;
    197 		float		fx			= 2.0f * sx - 1.0f;
    198 		float		fy			= 2.0f * sy - 1.0f;
    199 		int			vtxNdx		= ((y * (gridSize+1)) + x);
    200 
    201 		m_positions[vtxNdx]		= tcu::Vec4(fx, fy, 0.0f, 1.0f);
    202 		m_coords[vtxNdx]		= getCoords(sx, sy);
    203 		m_unitCoords[vtxNdx]	= getUnitCoords(sx, sy);
    204 		m_attribOne[vtxNdx]		= 1.0f;
    205 
    206 		m_screenPos[vtxNdx]		= tcu::Vec4(sx, sy, 0.0f, 1.0f) * viewportScale;
    207 
    208 		for (int attribNdx = 0; attribNdx < getNumUserAttribs(); attribNdx++)
    209 			m_userAttribs[attribNdx][vtxNdx] = getUserAttrib(attribNdx, sx, sy);
    210 	}
    211 
    212 	// Compute indices.
    213 	m_indices.resize(3 * m_numTriangles);
    214 	for (int y = 0; y < gridSize; y++)
    215 	for (int x = 0; x < gridSize; x++)
    216 	{
    217 		int stride				= gridSize + 1;
    218 		int v00					= (y * stride) + x;
    219 		int v01					= (y * stride) + x + 1;
    220 		int v10					= ((y+1) * stride) + x;
    221 		int v11					= ((y+1) * stride) + x + 1;
    222 
    223 		int baseNdx				= ((y * gridSize) + x) * 6;
    224 		m_indices[baseNdx + 0]	= (deUint16)v10;
    225 		m_indices[baseNdx + 1]	= (deUint16)v00;
    226 		m_indices[baseNdx + 2]	= (deUint16)v01;
    227 
    228 		m_indices[baseNdx + 3]	= (deUint16)v10;
    229 		m_indices[baseNdx + 4]	= (deUint16)v01;
    230 		m_indices[baseNdx + 5]	= (deUint16)v11;
    231 	}
    232 }
    233 
    234 QuadGrid::~QuadGrid (void)
    235 {
    236 }
    237 
    238 inline tcu::Vec4 QuadGrid::getCoords (float sx, float sy) const
    239 {
    240 	const float fx = 2.0f * sx - 1.0f;
    241 	const float fy = 2.0f * sy - 1.0f;
    242 	return tcu::Vec4(fx, fy, -fx + 0.33f*fy, -0.275f*fx - fy);
    243 }
    244 
    245 inline tcu::Vec4 QuadGrid::getUnitCoords (float sx, float sy) const
    246 {
    247 	return tcu::Vec4(sx, sy, 0.33f*sx + 0.5f*sy, 0.5f*sx + 0.25f*sy);
    248 }
    249 
    250 inline tcu::Vec4 QuadGrid::getUserAttrib (int attribNdx, float sx, float sy) const
    251 {
    252 	// homogeneous normalized screen-space coordinates
    253 	return m_userAttribTransforms[attribNdx] * tcu::Vec4(sx, sy, 0.0f, 1.0f);
    254 }
    255 
    256 // TextureBinding
    257 
    258 TextureBinding::TextureBinding (const tcu::Archive&	archive,
    259 								const char*			filename,
    260 								const Type			type,
    261 								const tcu::Sampler&	sampler)
    262 	: m_type	(type)
    263 	, m_sampler	(sampler)
    264 {
    265 	switch(m_type)
    266 	{
    267 		case TYPE_2D: m_binding.tex2D = loadTexture2D(archive, filename).release(); break;
    268 		default:
    269 			DE_FATAL("Unsupported texture type");
    270 	}
    271 }
    272 
    273 TextureBinding::~TextureBinding (void)
    274 {
    275 	switch(m_type)
    276 	{
    277 		case TYPE_2D: delete m_binding.tex2D; break;
    278 		default: break;
    279 	}
    280 }
    281 
    282 
    283 de::MovePtr<tcu::Texture2D> TextureBinding::loadTexture2D (const tcu::Archive& archive, const char* filename)
    284 {
    285 	tcu::TextureLevel level;
    286 	tcu::ImageIO::loadImage(level, archive, filename);
    287 
    288 	TCU_CHECK_INTERNAL(level.getFormat() == tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8) ||
    289 					   level.getFormat() == tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8));
    290 
    291 	// \todo [2015-10-08 elecro] for some reason we get better when using RGBA texture even in RGB case, this needs to be investigated
    292 	de::MovePtr<tcu::Texture2D> texture(new tcu::Texture2D(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), level.getWidth(), level.getHeight()));
    293 
    294 	// Fill level 0.
    295 	texture->allocLevel(0);
    296 	tcu::copy(texture->getLevel(0), level.getAccess());
    297 
    298 	return texture;
    299 }
    300 
    301 // ShaderEvalContext.
    302 
    303 ShaderEvalContext::ShaderEvalContext (const QuadGrid& quadGrid)
    304 	: constCoords	(quadGrid.getConstCoords())
    305 	, isDiscarded	(false)
    306 	, m_quadGrid	(quadGrid)
    307 {
    308 	const std::vector<TextureBindingSp>& bindings = m_quadGrid.getTextures();
    309 	DE_ASSERT((int)bindings.size() <= MAX_TEXTURES);
    310 
    311 	// Fill in texture array.
    312 	for (int ndx = 0; ndx < (int)bindings.size(); ndx++)
    313 	{
    314 		const TextureBinding& binding = *bindings[ndx];
    315 
    316 		if (binding.getType() == TextureBinding::TYPE_NONE)
    317 			continue;
    318 
    319 		textures[ndx].sampler = binding.getSampler();
    320 
    321 		switch (binding.getType())
    322 		{
    323 			case TextureBinding::TYPE_2D:		textures[ndx].tex2D			= &binding.get2D();		break;
    324 			// \todo [2015-09-07 elecro] Add support for the other binding types
    325 			/*
    326 			case TextureBinding::TYPE_CUBE_MAP:	textures[ndx].texCube		= binding.getCube();	break;
    327 			case TextureBinding::TYPE_2D_ARRAY:	textures[ndx].tex2DArray	= binding.get2DArray();	break;
    328 			case TextureBinding::TYPE_3D:		textures[ndx].tex3D			= binding.get3D();		break;
    329 			*/
    330 			default:
    331 				TCU_THROW(InternalError, "Handling of texture binding type not implemented");
    332 		}
    333 	}
    334 }
    335 
    336 ShaderEvalContext::~ShaderEvalContext (void)
    337 {
    338 }
    339 
    340 void ShaderEvalContext::reset (float sx, float sy)
    341 {
    342 	// Clear old values
    343 	color		= tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
    344 	isDiscarded	= false;
    345 
    346 	// Compute coords
    347 	coords		= m_quadGrid.getCoords(sx, sy);
    348 	unitCoords	= m_quadGrid.getUnitCoords(sx, sy);
    349 
    350 	// Compute user attributes.
    351 	const int numAttribs = m_quadGrid.getNumUserAttribs();
    352 	DE_ASSERT(numAttribs <= MAX_USER_ATTRIBS);
    353 	for (int attribNdx = 0; attribNdx < numAttribs; attribNdx++)
    354 		in[attribNdx] = m_quadGrid.getUserAttrib(attribNdx, sx, sy);
    355 }
    356 
    357 tcu::Vec4 ShaderEvalContext::texture2D (int unitNdx, const tcu::Vec2& texCoords)
    358 {
    359 	if (textures[unitNdx].tex2D)
    360 		return textures[unitNdx].tex2D->sample(textures[unitNdx].sampler, texCoords.x(), texCoords.y(), 0.0f);
    361 	else
    362 		return tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
    363 }
    364 
    365 // ShaderEvaluator.
    366 
    367 ShaderEvaluator::ShaderEvaluator (void)
    368 	: m_evalFunc(DE_NULL)
    369 {
    370 }
    371 
    372 ShaderEvaluator::ShaderEvaluator (ShaderEvalFunc evalFunc)
    373 	: m_evalFunc(evalFunc)
    374 {
    375 }
    376 
    377 ShaderEvaluator::~ShaderEvaluator (void)
    378 {
    379 }
    380 
    381 void ShaderEvaluator::evaluate (ShaderEvalContext& ctx) const
    382 {
    383 	DE_ASSERT(m_evalFunc);
    384 	m_evalFunc(ctx);
    385 }
    386 
    387 // UniformSetup.
    388 
    389 UniformSetup::UniformSetup (void)
    390 	: m_setupFunc(DE_NULL)
    391 {
    392 }
    393 
    394 UniformSetup::UniformSetup (UniformSetupFunc setupFunc)
    395 	: m_setupFunc(setupFunc)
    396 {
    397 }
    398 
    399 UniformSetup::~UniformSetup (void)
    400 {
    401 }
    402 
    403 void UniformSetup::setup (ShaderRenderCaseInstance& instance, const tcu::Vec4& constCoords) const
    404 {
    405 	if (m_setupFunc)
    406 		m_setupFunc(instance, constCoords);
    407 }
    408 
    409 // ShaderRenderCase.
    410 
    411 ShaderRenderCase::ShaderRenderCase (tcu::TestContext&			testCtx,
    412 									const std::string&			name,
    413 									const std::string&			description,
    414 									const bool					isVertexCase,
    415 									const ShaderEvalFunc		evalFunc,
    416 									const UniformSetup*			uniformSetup,
    417 									const AttributeSetupFunc	attribFunc)
    418 	: vkt::TestCase		(testCtx, name, description)
    419 	, m_isVertexCase	(isVertexCase)
    420 	, m_evaluator		(new ShaderEvaluator(evalFunc))
    421 	, m_uniformSetup	(uniformSetup ? uniformSetup : new UniformSetup())
    422 	, m_attribFunc		(attribFunc)
    423 {}
    424 
    425 ShaderRenderCase::ShaderRenderCase (tcu::TestContext&			testCtx,
    426 									const std::string&			name,
    427 									const std::string&			description,
    428 									const bool					isVertexCase,
    429 									const ShaderEvaluator*		evaluator,
    430 									const UniformSetup*			uniformSetup,
    431 									const AttributeSetupFunc	attribFunc)
    432 	: vkt::TestCase		(testCtx, name, description)
    433 	, m_isVertexCase	(isVertexCase)
    434 	, m_evaluator		(evaluator)
    435 	, m_uniformSetup	(uniformSetup ? uniformSetup : new UniformSetup())
    436 	, m_attribFunc		(attribFunc)
    437 {}
    438 
    439 ShaderRenderCase::~ShaderRenderCase (void)
    440 {
    441 }
    442 
    443 void ShaderRenderCase::initPrograms (vk::SourceCollections& programCollection) const
    444 {
    445 	programCollection.glslSources.add("vert") << glu::VertexSource(m_vertShaderSource);
    446 	programCollection.glslSources.add("frag") << glu::FragmentSource(m_fragShaderSource);
    447 }
    448 
    449 TestInstance* ShaderRenderCase::createInstance (Context& context) const
    450 {
    451 	DE_ASSERT(m_evaluator != DE_NULL);
    452 	DE_ASSERT(m_uniformSetup != DE_NULL);
    453 	return new ShaderRenderCaseInstance(context, m_isVertexCase, *m_evaluator, *m_uniformSetup, m_attribFunc);
    454 }
    455 
    456 // ShaderRenderCaseInstance.
    457 
    458 ShaderRenderCaseInstance::ShaderRenderCaseInstance (Context&					context,
    459 													const bool					isVertexCase,
    460 													const ShaderEvaluator&		evaluator,
    461 													const UniformSetup&			uniformSetup,
    462 													const AttributeSetupFunc	attribFunc)
    463 	: vkt::TestInstance	(context)
    464 	, m_clearColor		(DEFAULT_CLEAR_COLOR)
    465 	, m_memAlloc		(context.getDefaultAllocator())
    466 	, m_isVertexCase	(isVertexCase)
    467 	, m_evaluator		(evaluator)
    468 	, m_uniformSetup	(uniformSetup)
    469 	, m_attribFunc		(attribFunc)
    470 	, m_renderSize		(128, 128)
    471 	, m_colorFormat		(VK_FORMAT_R8G8B8A8_UNORM)
    472 {
    473 }
    474 
    475 ShaderRenderCaseInstance::~ShaderRenderCaseInstance (void)
    476 {
    477 }
    478 
    479 tcu::TestStatus ShaderRenderCaseInstance::iterate (void)
    480 {
    481 	setup();
    482 
    483 	// Create quad grid.
    484 	const tcu::UVec2	viewportSize	= getViewportSize();
    485 	const int			width			= viewportSize.x();
    486 	const int			height			= viewportSize.y();
    487 
    488 	QuadGrid			quadGrid		(m_isVertexCase ? GRID_SIZE : 4, width, height, tcu::Vec4(0.125f, 0.25f, 0.5f, 1.0f), m_userAttribTransforms, m_textures);
    489 
    490 	// Render result.
    491 	tcu::Surface		resImage		(width, height);
    492 	render(resImage, quadGrid);
    493 
    494 	// Compute reference.
    495 	tcu::Surface		refImage		(width, height);
    496 	if (m_isVertexCase)
    497 		computeVertexReference(refImage, quadGrid);
    498 	else
    499 		computeFragmentReference(refImage, quadGrid);
    500 
    501 	// Compare.
    502 	const bool			compareOk		= compareImages(resImage, refImage, 0.05f);
    503 
    504 	if (compareOk)
    505 		return tcu::TestStatus::pass("Result image matches reference");
    506 	else
    507 		return tcu::TestStatus::fail("Image mismatch");
    508 }
    509 
    510 void ShaderRenderCaseInstance::setupUniformData (deUint32 bindingLocation, size_t size, const void* dataPtr)
    511 {
    512 	const VkDevice					vkDevice			= m_context.getDevice();
    513 	const DeviceInterface&			vk					= m_context.getDeviceInterface();
    514 	const deUint32					queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
    515 
    516 	const VkBufferCreateInfo		uniformBufferParams	=
    517 	{
    518 		VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
    519 		DE_NULL,									// const void*			pNext;
    520 		0u,											// VkBufferCreateFlags	flags;
    521 		size,										// VkDeviceSize			size;
    522 		VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,			// VkBufferUsageFlags	usage;
    523 		VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
    524 		1u,											// deUint32				queueFamilyCount;
    525 		&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
    526 	};
    527 
    528 	Move<VkBuffer>					buffer				= createBuffer(vk, vkDevice, &uniformBufferParams);
    529 	de::MovePtr<Allocation>			alloc				= m_memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *buffer), MemoryRequirement::HostVisible);
    530 	VK_CHECK(vk.bindBufferMemory(vkDevice, *buffer, alloc->getMemory(), alloc->getOffset()));
    531 
    532 	deMemcpy(alloc->getHostPtr(), dataPtr, size);
    533 	flushMappedMemoryRange(vk, vkDevice, alloc->getMemory(), alloc->getOffset(), size);
    534 
    535 	de::MovePtr<BufferUniform> uniformInfo(new BufferUniform());
    536 	uniformInfo->type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
    537 	uniformInfo->descriptor = makeDescriptorBufferInfo(*buffer, 0u, size);
    538 	uniformInfo->location = bindingLocation;
    539 	uniformInfo->buffer = VkBufferSp(new vk::Unique<VkBuffer>(buffer));
    540 	uniformInfo->alloc = AllocationSp(alloc.release());
    541 
    542 	m_uniformInfos.push_back(UniformInfoSp(new de::UniquePtr<UniformInfo>(uniformInfo)));
    543 }
    544 
    545 void ShaderRenderCaseInstance::addUniform (deUint32 bindingLocation, vk::VkDescriptorType descriptorType, size_t dataSize, const void* data)
    546 {
    547 	m_descriptorSetLayoutBuilder.addSingleBinding(descriptorType, vk::VK_SHADER_STAGE_ALL);
    548 	m_descriptorPoolBuilder.addType(descriptorType);
    549 
    550 	setupUniformData(bindingLocation, dataSize, data);
    551 }
    552 
    553 void ShaderRenderCaseInstance::addAttribute (deUint32		bindingLocation,
    554 											 vk::VkFormat	format,
    555 											 deUint32		sizePerElement,
    556 											 deUint32		count,
    557 											 const void*	dataPtr)
    558 {
    559 	// Add binding specification
    560 	const deUint32							binding					= (deUint32)m_vertexBindingDescription.size();
    561 	const VkVertexInputBindingDescription	bindingDescription		=
    562 	{
    563 		binding,							// deUint32				binding;
    564 		sizePerElement,						// deUint32				stride;
    565 		VK_VERTEX_INPUT_RATE_VERTEX			// VkVertexInputRate	stepRate;
    566 	};
    567 
    568 	m_vertexBindingDescription.push_back(bindingDescription);
    569 
    570 	// Add location and format specification
    571 	const VkVertexInputAttributeDescription	attributeDescription	=
    572 	{
    573 		bindingLocation,			// deUint32	location;
    574 		binding,					// deUint32	binding;
    575 		format,						// VkFormat	format;
    576 		0u,							// deUint32	offset;
    577 	};
    578 
    579 	m_vertexattributeDescription.push_back(attributeDescription);
    580 
    581 	// Upload data to buffer
    582 	const VkDevice							vkDevice				= m_context.getDevice();
    583 	const DeviceInterface&					vk						= m_context.getDeviceInterface();
    584 	const deUint32							queueFamilyIndex		= m_context.getUniversalQueueFamilyIndex();
    585 
    586 	const VkDeviceSize						inputSize				= sizePerElement * count;
    587 	const VkBufferCreateInfo				vertexBufferParams		=
    588 	{
    589 		VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
    590 		DE_NULL,									// const void*			pNext;
    591 		0u,											// VkBufferCreateFlags	flags;
    592 		inputSize,									// VkDeviceSize			size;
    593 		VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,			// VkBufferUsageFlags	usage;
    594 		VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
    595 		1u,											// deUint32				queueFamilyCount;
    596 		&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
    597 	};
    598 
    599 	Move<VkBuffer>							buffer					= createBuffer(vk, vkDevice, &vertexBufferParams);
    600 	de::MovePtr<vk::Allocation>				alloc					= m_memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *buffer), MemoryRequirement::HostVisible);
    601 	VK_CHECK(vk.bindBufferMemory(vkDevice, *buffer, alloc->getMemory(), alloc->getOffset()));
    602 
    603 	deMemcpy(alloc->getHostPtr(), dataPtr, (size_t)inputSize);
    604 	flushMappedMemoryRange(vk, vkDevice, alloc->getMemory(), alloc->getOffset(), inputSize);
    605 
    606 	m_vertexBuffers.push_back(VkBufferSp(new vk::Unique<VkBuffer>(buffer)));
    607 	m_vertexBufferAllocs.push_back(AllocationSp(alloc.release()));
    608 }
    609 
    610 void ShaderRenderCaseInstance::useAttribute (deUint32 bindingLocation, BaseAttributeType type)
    611 {
    612 	const EnabledBaseAttribute attribute =
    613 	{
    614 		bindingLocation,	// deUint32				location;
    615 		type				// BaseAttributeType	type;
    616 	};
    617 	m_enabledBaseAttributes.push_back(attribute);
    618 }
    619 
    620 void ShaderRenderCaseInstance::setup (void)
    621 {
    622 }
    623 
    624 void ShaderRenderCaseInstance::setupUniforms (const tcu::Vec4& constCoords)
    625 {
    626 	m_uniformSetup.setup(*this, constCoords);
    627 }
    628 
    629 void ShaderRenderCaseInstance::useUniform (deUint32 bindingLocation, BaseUniformType type)
    630 {
    631 	#define UNIFORM_CASE(type, value) case type: addUniform(bindingLocation, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, value); break
    632 
    633 	switch(type)
    634 	{
    635 		// Bool
    636 		UNIFORM_CASE(UB_FALSE,	0);
    637 		UNIFORM_CASE(UB_TRUE,	1);
    638 
    639 		// BVec4
    640 		UNIFORM_CASE(UB4_FALSE,	tcu::Vec4(0));
    641 		UNIFORM_CASE(UB4_TRUE,	tcu::Vec4(1));
    642 
    643 		// Integer
    644 		UNIFORM_CASE(UI_ZERO,	0);
    645 		UNIFORM_CASE(UI_ONE,	1);
    646 		UNIFORM_CASE(UI_TWO,	2);
    647 		UNIFORM_CASE(UI_THREE,	3);
    648 		UNIFORM_CASE(UI_FOUR,	4);
    649 		UNIFORM_CASE(UI_FIVE,	5);
    650 		UNIFORM_CASE(UI_SIX,	6);
    651 		UNIFORM_CASE(UI_SEVEN,	7);
    652 		UNIFORM_CASE(UI_EIGHT,	8);
    653 		UNIFORM_CASE(UI_ONEHUNDREDONE, 101);
    654 
    655 		// IVec2
    656 		UNIFORM_CASE(UI2_MINUS_ONE,	tcu::IVec2(-1));
    657 		UNIFORM_CASE(UI2_ZERO,		tcu::IVec2(0));
    658 		UNIFORM_CASE(UI2_ONE,		tcu::IVec2(1));
    659 		UNIFORM_CASE(UI2_TWO,		tcu::IVec2(2));
    660 		UNIFORM_CASE(UI2_THREE,		tcu::IVec2(3));
    661 		UNIFORM_CASE(UI2_FOUR,		tcu::IVec2(4));
    662 		UNIFORM_CASE(UI2_FIVE,		tcu::IVec2(5));
    663 
    664 		// IVec3
    665 		UNIFORM_CASE(UI3_MINUS_ONE,	tcu::IVec3(-1));
    666 		UNIFORM_CASE(UI3_ZERO,		tcu::IVec3(0));
    667 		UNIFORM_CASE(UI3_ONE,		tcu::IVec3(1));
    668 		UNIFORM_CASE(UI3_TWO,		tcu::IVec3(2));
    669 		UNIFORM_CASE(UI3_THREE,		tcu::IVec3(3));
    670 		UNIFORM_CASE(UI3_FOUR,		tcu::IVec3(4));
    671 		UNIFORM_CASE(UI3_FIVE,		tcu::IVec3(5));
    672 
    673 		// IVec4
    674 		UNIFORM_CASE(UI4_MINUS_ONE, tcu::IVec4(-1));
    675 		UNIFORM_CASE(UI4_ZERO,		tcu::IVec4(0));
    676 		UNIFORM_CASE(UI4_ONE,		tcu::IVec4(1));
    677 		UNIFORM_CASE(UI4_TWO,		tcu::IVec4(2));
    678 		UNIFORM_CASE(UI4_THREE,		tcu::IVec4(3));
    679 		UNIFORM_CASE(UI4_FOUR,		tcu::IVec4(4));
    680 		UNIFORM_CASE(UI4_FIVE,		tcu::IVec4(5));
    681 
    682 		// Float
    683 		UNIFORM_CASE(UF_ZERO,		0.0f);
    684 		UNIFORM_CASE(UF_ONE,		1.0f);
    685 		UNIFORM_CASE(UF_TWO,		2.0f);
    686 		UNIFORM_CASE(UF_THREE,		3.0f);
    687 		UNIFORM_CASE(UF_FOUR,		4.0f);
    688 		UNIFORM_CASE(UF_FIVE,		5.0f);
    689 		UNIFORM_CASE(UF_SIX,		6.0f);
    690 		UNIFORM_CASE(UF_SEVEN,		7.0f);
    691 		UNIFORM_CASE(UF_EIGHT,		8.0f);
    692 
    693 		UNIFORM_CASE(UF_HALF,		1.0f / 2.0f);
    694 		UNIFORM_CASE(UF_THIRD,		1.0f / 3.0f);
    695 		UNIFORM_CASE(UF_FOURTH,		1.0f / 4.0f);
    696 		UNIFORM_CASE(UF_FIFTH,		1.0f / 5.0f);
    697 		UNIFORM_CASE(UF_SIXTH,		1.0f / 6.0f);
    698 		UNIFORM_CASE(UF_SEVENTH,	1.0f / 7.0f);
    699 		UNIFORM_CASE(UF_EIGHTH,		1.0f / 8.0f);
    700 
    701 		// Vec2
    702 		UNIFORM_CASE(UV2_MINUS_ONE,	tcu::Vec2(-1.0f));
    703 		UNIFORM_CASE(UV2_ZERO,		tcu::Vec2(0.0f));
    704 		UNIFORM_CASE(UV2_ONE,		tcu::Vec2(1.0f));
    705 		UNIFORM_CASE(UV2_TWO,		tcu::Vec2(2.0f));
    706 		UNIFORM_CASE(UV2_THREE,		tcu::Vec2(3.0f));
    707 
    708 		UNIFORM_CASE(UV2_HALF,		tcu::Vec2(1.0f / 2.0f));
    709 
    710 		// Vec3
    711 		UNIFORM_CASE(UV3_MINUS_ONE,	tcu::Vec3(-1.0f));
    712 		UNIFORM_CASE(UV3_ZERO,		tcu::Vec3(0.0f));
    713 		UNIFORM_CASE(UV3_ONE,		tcu::Vec3(1.0f));
    714 		UNIFORM_CASE(UV3_TWO,		tcu::Vec3(2.0f));
    715 		UNIFORM_CASE(UV3_THREE,		tcu::Vec3(3.0f));
    716 
    717 		UNIFORM_CASE(UV3_HALF,		tcu::Vec3(1.0f / 2.0f));
    718 
    719 		// Vec4
    720 		UNIFORM_CASE(UV4_MINUS_ONE,	tcu::Vec4(-1.0f));
    721 		UNIFORM_CASE(UV4_ZERO,		tcu::Vec4(0.0f));
    722 		UNIFORM_CASE(UV4_ONE,		tcu::Vec4(1.0f));
    723 		UNIFORM_CASE(UV4_TWO,		tcu::Vec4(2.0f));
    724 		UNIFORM_CASE(UV4_THREE,		tcu::Vec4(3.0f));
    725 
    726 		UNIFORM_CASE(UV4_HALF,		tcu::Vec4(1.0f / 2.0f));
    727 
    728 		UNIFORM_CASE(UV4_BLACK,		tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
    729 		UNIFORM_CASE(UV4_GRAY,		tcu::Vec4(0.5f, 0.5f, 0.5f, 1.0f));
    730 		UNIFORM_CASE(UV4_WHITE,		tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
    731 
    732 		default:
    733 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Unknown Uniform type: " << type << tcu::TestLog::EndMessage;
    734 			break;
    735 	}
    736 
    737 	#undef UNIFORM_CASE
    738 }
    739 
    740 const tcu::UVec2 ShaderRenderCaseInstance::getViewportSize (void) const
    741 {
    742 	return tcu::UVec2(de::min(m_renderSize.x(), MAX_RENDER_WIDTH),
    743 					  de::min(m_renderSize.y(), MAX_RENDER_HEIGHT));
    744 }
    745 
    746 Move<VkImage> ShaderRenderCaseInstance::createImage2D (const tcu::Texture2D&	texture,
    747 													   const VkFormat			format,
    748 													   const VkImageUsageFlags	usage,
    749 													   const VkImageTiling		tiling)
    750 {
    751 	const VkDevice			vkDevice			= m_context.getDevice();
    752 	const DeviceInterface&	vk					= m_context.getDeviceInterface();
    753 	const deUint32			queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
    754 
    755 	const VkImageCreateInfo	imageCreateInfo		=
    756 	{
    757 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,						// VkStructureType			sType;
    758 		DE_NULL,													// const void*				pNext;
    759 		0,															// VkImageCreateFlags		flags;
    760 		VK_IMAGE_TYPE_2D,											// VkImageType				imageType;
    761 		format,														// VkFormat					format;
    762 		{
    763 			(deUint32)texture.getWidth(),
    764 			(deUint32)texture.getHeight(),
    765 			1u
    766 		},															// VkExtend3D				extent;
    767 		1u,															// deUint32					mipLevels;
    768 		1u,															// deUint32					arraySize;
    769 		VK_SAMPLE_COUNT_1_BIT,										// deUint32					samples;
    770 		tiling,														// VkImageTiling			tiling;
    771 		usage,														// VkImageUsageFlags		usage;
    772 		VK_SHARING_MODE_EXCLUSIVE,									// VkSharingMode			sharingMode;
    773 		1,															// deuint32					queueFamilyCount;
    774 		&queueFamilyIndex,											// const deUint32*			pQueueFamilyIndices;
    775 		VK_IMAGE_LAYOUT_UNDEFINED,									// VkImageLayout			initialLayout;
    776 	};
    777 
    778 	Move<VkImage>			vkTexture			= createImage(vk, vkDevice, &imageCreateInfo);
    779 	return vkTexture;
    780 }
    781 
    782 de::MovePtr<Allocation> ShaderRenderCaseInstance::uploadImage2D (const tcu::Texture2D&	refTexture,
    783 																 const VkImage&			vkTexture)
    784 {
    785 	const VkDevice				vkDevice	= m_context.getDevice();
    786 	const DeviceInterface&		vk			= m_context.getDeviceInterface();
    787 
    788 	de::MovePtr<Allocation>		allocation	= m_memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, vkTexture), MemoryRequirement::HostVisible);
    789 	VK_CHECK(vk.bindImageMemory(vkDevice, vkTexture, allocation->getMemory(), allocation->getOffset()));
    790 
    791 	const VkImageSubresource	subres				=
    792 	{
    793 		VK_IMAGE_ASPECT_COLOR_BIT,	// VkImageAspectFlags	aspectMask;
    794 		0u,							// deUint32				mipLevel;
    795 		0u							// deUint32				arraySlice
    796 	};
    797 
    798 	VkSubresourceLayout layout;
    799 	vk.getImageSubresourceLayout(vkDevice, vkTexture, &subres, &layout);
    800 
    801 	tcu::ConstPixelBufferAccess	access		= refTexture.getLevel(0);
    802 	tcu::PixelBufferAccess		destAccess	(refTexture.getFormat(), refTexture.getWidth(), refTexture.getHeight(), 1, allocation->getHostPtr());
    803 
    804 	tcu::copy(destAccess, access);
    805 
    806 	flushMappedMemoryRange(vk, vkDevice, allocation->getMemory(), allocation->getOffset(), layout.size);
    807 
    808 	return allocation;
    809 }
    810 
    811 void ShaderRenderCaseInstance::copyTilingImageToOptimal	(const vk::VkImage&	srcImage,
    812 														 const vk::VkImage&	dstImage,
    813 														 deUint32			width,
    814 														 deUint32			height)
    815 {
    816 	const VkDevice						vkDevice			= m_context.getDevice();
    817 	const DeviceInterface&				vk					= m_context.getDeviceInterface();
    818 	const VkQueue						queue				= m_context.getUniversalQueue();
    819 	const deUint32						queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
    820 
    821 	// Create command pool
    822 	const VkCommandPoolCreateInfo		cmdPoolParams		=
    823 	{
    824 		VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,	// VkStructureType		sType;
    825 		DE_NULL,									// const void*			pNext;
    826 		VK_COMMAND_POOL_CREATE_TRANSIENT_BIT,		// VkCmdPoolCreateFlags	flags;
    827 		queueFamilyIndex,							// deUint32				queueFamilyIndex;
    828 	};
    829 
    830 	Move<VkCommandPool>					cmdPool				= createCommandPool(vk, vkDevice, &cmdPoolParams);
    831 
    832 	// Create command buffer
    833 	const VkCommandBufferAllocateInfo	cmdBufferParams		=
    834 	{
    835 		VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,	// VkStructureType			sType;
    836 		DE_NULL,										// const void*				pNext;
    837 		*cmdPool,										// VkCommandPool			commandPool;
    838 		VK_COMMAND_BUFFER_LEVEL_PRIMARY,				// VkCommandBufferLevel		level;
    839 		1u												// deUint32					bufferCount;
    840 	};
    841 
    842 	const VkCommandBufferUsageFlags		usageFlags			= VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
    843 	const VkCommandBufferBeginInfo		cmdBufferBeginInfo	=
    844 	{
    845 		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,	// VkStructureType				sType;
    846 		DE_NULL,										// const void*					pNext;
    847 		usageFlags,										// VkCommandBufferUsageFlags	flags;
    848 		(const VkCommandBufferInheritanceInfo*)DE_NULL,
    849 	};
    850 
    851 	Move<VkCommandBuffer>				cmdBuffer			= allocateCommandBuffer(vk, vkDevice, &cmdBufferParams);
    852 
    853 	VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufferBeginInfo));
    854 
    855 	// Add image barriers
    856 	const VkImageMemoryBarrier			layoutBarriers[2]	=
    857 	{
    858 		createImageMemoryBarrier(srcImage, (VkAccessFlags)0u, (VkAccessFlags)0u, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL),
    859 		createImageMemoryBarrier(dstImage, (VkAccessFlags)0u, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)
    860 	};
    861 
    862 	vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (VkDependencyFlags)0,
    863 						  0, (const VkMemoryBarrier*)DE_NULL,
    864 						  0, (const VkBufferMemoryBarrier*)DE_NULL,
    865 						  DE_LENGTH_OF_ARRAY(layoutBarriers), layoutBarriers);
    866 
    867 	// Add image copy
    868 	const VkImageCopy				imageCopy			=
    869 	{
    870 		{
    871 			VK_IMAGE_ASPECT_COLOR_BIT,		// VkImageAspect	aspect;
    872 			0u,								// deUint32			mipLevel;
    873 			0u,								// deUint32			arrayLayer;
    874 			1u								// deUint32			arraySize;
    875 		},											// VkImageSubresourceCopy	srcSubresource;
    876 		{
    877 			0,								// int32			x;
    878 			0,								// int32			y;
    879 			0								// int32			z;
    880 		},											// VkOffset3D				srcOffset;
    881 		{
    882 			VK_IMAGE_ASPECT_COLOR_BIT,		// VkImageAspect	aspect;
    883 			0u,								// deUint32			mipLevel;
    884 			0u,								// deUint32			arrayLayer;
    885 			1u								// deUint32			arraySize;
    886 		},											// VkImageSubresourceCopy	destSubResource;
    887 		{
    888 			0,								// int32			x;
    889 			0,								// int32			y;
    890 			0								// int32			z;
    891 		},											// VkOffset3D				dstOffset;
    892 		{
    893 			width,							// int32			width;
    894 			height,							// int32			height;
    895 			1,								// int32			depth
    896 		}	// VkExtent3D					extent;
    897 	};
    898 
    899 	vk.cmdCopyImage(*cmdBuffer, srcImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dstImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &imageCopy);
    900 
    901 	// Add destination barrier
    902 	const VkImageMemoryBarrier		dstBarrier			=
    903 			createImageMemoryBarrier(dstImage, VK_ACCESS_HOST_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT, 0u, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
    904 
    905 	vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (VkDependencyFlags)0,
    906 						  0, (const VkMemoryBarrier*)DE_NULL,
    907 						  0, (const VkBufferMemoryBarrier*)DE_NULL,
    908 						  1, &dstBarrier);
    909 
    910 	VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
    911 
    912 	const VkFenceCreateInfo			fenceParams			=
    913 	{
    914 		VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,	// VkStructureType		sType;
    915 		DE_NULL,								// const void*			pNext;
    916 		0u										// VkFenceCreateFlags	flags;
    917 	};
    918 	const Unique<VkFence>			fence				(createFence(vk, vkDevice, &fenceParams));
    919 	const VkSubmitInfo				submitInfo			=
    920 	{
    921 		VK_STRUCTURE_TYPE_SUBMIT_INFO,
    922 		DE_NULL,
    923 		0u,
    924 		(const VkSemaphore*)DE_NULL,
    925 		(const VkPipelineStageFlags*)DE_NULL,
    926 		1u,
    927 		&cmdBuffer.get(),
    928 		0u,
    929 		(const VkSemaphore*)DE_NULL,
    930 	};
    931 
    932 
    933 	// Execute copy
    934 	VK_CHECK(vk.resetFences(vkDevice, 1, &fence.get()));
    935 	VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *fence));
    936 	VK_CHECK(vk.waitForFences(vkDevice, 1, &fence.get(), true, ~(0ull) /* infinity*/));
    937 }
    938 
    939 void ShaderRenderCaseInstance::useSampler2D (deUint32 bindingLocation, deUint32 textureID)
    940 {
    941 	DE_ASSERT(textureID < m_textures.size());
    942 
    943 	const VkDevice					vkDevice		= m_context.getDevice();
    944 	const DeviceInterface&			vk				= m_context.getDeviceInterface();
    945 	const TextureBinding&			textureBinding	= *m_textures[textureID];
    946 	const tcu::Texture2D&			refTexture		= textureBinding.get2D();
    947 	const tcu::Sampler&				refSampler		= textureBinding.getSampler();
    948 	const VkFormat					format			= refTexture.getFormat() == tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)
    949 														? VK_FORMAT_R8G8B8A8_UNORM
    950 														: VK_FORMAT_R8G8B8_UNORM;
    951 
    952 	// Create & alloc the image
    953 	Move<VkImage>					vkTexture;
    954 	de::MovePtr<Allocation>			allocation;
    955 
    956 	if (isSupportedLinearTilingFormat(m_context.getInstanceInterface(), m_context.getPhysicalDevice(), format))
    957 	{
    958 		vkTexture = createImage2D(refTexture, format, VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_TILING_LINEAR);
    959 		allocation = uploadImage2D(refTexture, *vkTexture);
    960 	}
    961 	else if (isSupportedOptimalTilingFormat(m_context.getInstanceInterface(), m_context.getPhysicalDevice(), format))
    962 	{
    963 		Move<VkImage>				stagingTexture	(createImage2D(refTexture, format, VK_IMAGE_USAGE_TRANSFER_SRC_BIT, VK_IMAGE_TILING_LINEAR));
    964 		de::MovePtr<Allocation>		stagingAlloc	(uploadImage2D(refTexture, *stagingTexture));
    965 
    966 		const VkImageUsageFlags		dstUsageFlags	= VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
    967 		vkTexture = createImage2D(refTexture, format, dstUsageFlags, VK_IMAGE_TILING_OPTIMAL);
    968 		allocation = m_memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *vkTexture), MemoryRequirement::Any);
    969 		VK_CHECK(vk.bindImageMemory(vkDevice, *vkTexture, allocation->getMemory(), allocation->getOffset()));
    970 
    971 		copyTilingImageToOptimal(*stagingTexture, *vkTexture, refTexture.getWidth(), refTexture.getHeight());
    972 	}
    973 	else
    974 	{
    975 		TCU_THROW(InternalError, "Unable to create 2D image");
    976 	}
    977 
    978 	// Create sampler
    979 	const VkSamplerCreateInfo		samplerParams	= mapSampler(refSampler, refTexture.getFormat());
    980 	Move<VkSampler>					sampler			= createSampler(vk, vkDevice, &samplerParams);
    981 
    982 	const VkImageViewCreateInfo		viewParams		=
    983 	{
    984 		VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,	// VkStructureType			sType;
    985 		NULL,										// const voide*				pNext;
    986 		0u,											// VkImageViewCreateFlags	flags;
    987 		*vkTexture,									// VkImage					image;
    988 		VK_IMAGE_VIEW_TYPE_2D,						// VkImageViewType			viewType;
    989 		format,										// VkFormat					format;
    990 		{
    991 			VK_COMPONENT_SWIZZLE_R,			// VkChannelSwizzle		r;
    992 			VK_COMPONENT_SWIZZLE_G,			// VkChannelSwizzle		g;
    993 			VK_COMPONENT_SWIZZLE_B,			// VkChannelSwizzle		b;
    994 			VK_COMPONENT_SWIZZLE_A			// VkChannelSwizzle		a;
    995 		},											// VkChannelMapping			channels;
    996 		{
    997 			VK_IMAGE_ASPECT_COLOR_BIT,		// VkImageAspectFlags	aspectMask;
    998 			0,								// deUint32				baseMipLevel;
    999 			1,								// deUint32				mipLevels;
   1000 			0,								// deUint32				baseArraySlice;
   1001 			1								// deUint32				arraySize;
   1002 		},											// VkImageSubresourceRange	subresourceRange;
   1003 	};
   1004 
   1005 	Move<VkImageView>				imageView		= createImageView(vk, vkDevice, &viewParams);
   1006 
   1007 	const vk::VkDescriptorImageInfo	descriptor		=
   1008 	{
   1009 		sampler.get(),								// VkSampler				sampler;
   1010 		imageView.get(),							// VkImageView				imageView;
   1011 		VK_IMAGE_LAYOUT_GENERAL,					// VkImageLayout			imageLayout;
   1012 	};
   1013 
   1014 	de::MovePtr<SamplerUniform> uniform(new SamplerUniform());
   1015 	uniform->type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
   1016 	uniform->descriptor = descriptor;
   1017 	uniform->location = bindingLocation;
   1018 	uniform->image = VkImageSp(new vk::Unique<VkImage>(vkTexture));
   1019 	uniform->imageView = VkImageViewSp(new vk::Unique<VkImageView>(imageView));
   1020 	uniform->sampler = VkSamplerSp(new vk::Unique<VkSampler>(sampler));
   1021 	uniform->alloc = AllocationSp(allocation.release());
   1022 
   1023 	m_descriptorSetLayoutBuilder.addSingleSamplerBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, vk::VK_SHADER_STAGE_ALL, &uniform->descriptor.sampler);
   1024 	m_descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
   1025 
   1026 	m_uniformInfos.push_back(UniformInfoSp(new de::UniquePtr<UniformInfo>(uniform)));
   1027 }
   1028 
   1029 void ShaderRenderCaseInstance::setupDefaultInputs (const QuadGrid& quadGrid)
   1030 {
   1031 	/* Configuration of the vertex input attributes:
   1032 		a_position   is at location 0
   1033 		a_coords     is at location 1
   1034 		a_unitCoords is at location 2
   1035 		a_one        is at location 3
   1036 
   1037 	  User attributes starts from at the location 4.
   1038 	*/
   1039 	addAttribute(0u, VK_FORMAT_R32G32B32A32_SFLOAT, sizeof(tcu::Vec4), quadGrid.getNumVertices(), quadGrid.getPositions());
   1040 	addAttribute(1u, VK_FORMAT_R32G32B32A32_SFLOAT, sizeof(tcu::Vec4), quadGrid.getNumVertices(), quadGrid.getCoords());
   1041 	addAttribute(2u, VK_FORMAT_R32G32B32A32_SFLOAT, sizeof(tcu::Vec4), quadGrid.getNumVertices(), quadGrid.getUnitCoords());
   1042 	addAttribute(3u, VK_FORMAT_R32_SFLOAT, sizeof(float), quadGrid.getNumVertices(), quadGrid.getAttribOne());
   1043 
   1044 	static const struct
   1045 	{
   1046 		BaseAttributeType	type;
   1047 		int					userNdx;
   1048 	} userAttributes[] =
   1049 	{
   1050 		{ A_IN0, 0 },
   1051 		{ A_IN1, 1 },
   1052 		{ A_IN2, 2 },
   1053 		{ A_IN3, 3 }
   1054 	};
   1055 
   1056 	static const struct
   1057 	{
   1058 		BaseAttributeType	matrixType;
   1059 		int					numCols;
   1060 		int					numRows;
   1061 	} matrices[] =
   1062 	{
   1063 		{ MAT2,		2, 2 },
   1064 		{ MAT2x3,	2, 3 },
   1065 		{ MAT2x4,	2, 4 },
   1066 		{ MAT3x2,	3, 2 },
   1067 		{ MAT3,		3, 3 },
   1068 		{ MAT3x4,	3, 4 },
   1069 		{ MAT4x2,	4, 2 },
   1070 		{ MAT4x3,	4, 3 },
   1071 		{ MAT4,		4, 4 }
   1072 	};
   1073 
   1074 	for (size_t attrNdx = 0; attrNdx < m_enabledBaseAttributes.size(); attrNdx++)
   1075 	{
   1076 		for (int userNdx = 0; userNdx < DE_LENGTH_OF_ARRAY(userAttributes); userNdx++)
   1077 		{
   1078 			if (userAttributes[userNdx].type != m_enabledBaseAttributes[attrNdx].type)
   1079 				continue;
   1080 
   1081 			addAttribute(m_enabledBaseAttributes[attrNdx].location, VK_FORMAT_R32G32B32A32_SFLOAT, sizeof(tcu::Vec4), quadGrid.getNumVertices(), quadGrid.getUserAttrib(userNdx));
   1082 		}
   1083 
   1084 		for (int matNdx = 0; matNdx < DE_LENGTH_OF_ARRAY(matrices); matNdx++)
   1085 		{
   1086 
   1087 			if (matrices[matNdx].matrixType != m_enabledBaseAttributes[attrNdx].type)
   1088 				continue;
   1089 
   1090 			const int numCols = matrices[matNdx].numCols;
   1091 
   1092 			for (int colNdx = 0; colNdx < numCols; colNdx++)
   1093 			{
   1094 				addAttribute(m_enabledBaseAttributes[attrNdx].location + colNdx, VK_FORMAT_R32G32B32A32_SFLOAT, (deUint32)(4 * sizeof(float)), quadGrid.getNumVertices(), quadGrid.getUserAttrib(colNdx));
   1095 			}
   1096 		}
   1097 	}
   1098 }
   1099 
   1100 void ShaderRenderCaseInstance::render (tcu::Surface& result, const QuadGrid& quadGrid)
   1101 {
   1102 	const VkDevice										vkDevice					= m_context.getDevice();
   1103 	const DeviceInterface&								vk							= m_context.getDeviceInterface();
   1104 	const VkQueue										queue						= m_context.getUniversalQueue();
   1105 	const deUint32										queueFamilyIndex			= m_context.getUniversalQueueFamilyIndex();
   1106 
   1107 	// Create color image
   1108 	{
   1109 		const VkImageCreateInfo							colorImageParams			=
   1110 		{
   1111 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,										// VkStructureType		sType;
   1112 			DE_NULL,																	// const void*			pNext;
   1113 			0u,																			// VkImageCreateFlags	flags;
   1114 			VK_IMAGE_TYPE_2D,															// VkImageType			imageType;
   1115 			m_colorFormat,																// VkFormat				format;
   1116 			{ m_renderSize.x(), m_renderSize.y(), 1u },									// VkExtent3D			extent;
   1117 			1u,																			// deUint32				mipLevels;
   1118 			1u,																			// deUint32				arraySize;
   1119 			VK_SAMPLE_COUNT_1_BIT,														// deUint32				samples;
   1120 			VK_IMAGE_TILING_OPTIMAL,													// VkImageTiling		tiling;
   1121 			VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,		// VkImageUsageFlags	usage;
   1122 			VK_SHARING_MODE_EXCLUSIVE,													// VkSharingMode		sharingMode;
   1123 			1u,																			// deUint32				queueFamilyCount;
   1124 			&queueFamilyIndex,															// const deUint32*		pQueueFamilyIndices;
   1125 			VK_IMAGE_LAYOUT_UNDEFINED,													// VkImageLayout		initialLayout;
   1126 		};
   1127 
   1128 		m_colorImage = createImage(vk, vkDevice, &colorImageParams);
   1129 
   1130 		// Allocate and bind color image memory
   1131 		m_colorImageAlloc = m_memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImage), MemoryRequirement::Any);
   1132 		VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImage, m_colorImageAlloc->getMemory(), m_colorImageAlloc->getOffset()));
   1133 	}
   1134 
   1135 	// Create color attachment view
   1136 	{
   1137 		const VkImageViewCreateInfo						colorImageViewParams		=
   1138 		{
   1139 			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,			// VkStructureType			sType;
   1140 			DE_NULL,											// const void*				pNext;
   1141 			0u,													// VkImageViewCreateFlags	flags;
   1142 			*m_colorImage,										// VkImage					image;
   1143 			VK_IMAGE_VIEW_TYPE_2D,								// VkImageViewType			viewType;
   1144 			m_colorFormat,										// VkFormat					format;
   1145 			{
   1146 				VK_COMPONENT_SWIZZLE_R,			// VkChannelSwizzle		r;
   1147 				VK_COMPONENT_SWIZZLE_G,			// VkChannelSwizzle		g;
   1148 				VK_COMPONENT_SWIZZLE_B,			// VkChannelSwizzle		b;
   1149 				VK_COMPONENT_SWIZZLE_A			// VkChannelSwizzle		a;
   1150 			},													// VkChannelMapping			channels;
   1151 			{
   1152 				VK_IMAGE_ASPECT_COLOR_BIT,		// VkImageAspectFlags	aspectMask;
   1153 				0,								// deUint32				baseMipLevel;
   1154 				1,								// deUint32				mipLevels;
   1155 				0,								// deUint32				baseArraySlice;
   1156 				1								// deUint32				arraySize;
   1157 			},													// VkImageSubresourceRange	subresourceRange;
   1158 		};
   1159 
   1160 		m_colorImageView = createImageView(vk, vkDevice, &colorImageViewParams);
   1161 	}
   1162 
   1163 	// Create render pass
   1164 	{
   1165 		const VkAttachmentDescription					attachmentDescription		=
   1166 		{
   1167 			(VkAttachmentDescriptionFlags)0,
   1168 			m_colorFormat,										// VkFormat						format;
   1169 			VK_SAMPLE_COUNT_1_BIT,								// deUint32						samples;
   1170 			VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp			loadOp;
   1171 			VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp			storeOp;
   1172 			VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// VkAttachmentLoadOp			stencilLoadOp;
   1173 			VK_ATTACHMENT_STORE_OP_DONT_CARE,					// VkAttachmentStoreOp			stencilStoreOp;
   1174 			VK_IMAGE_LAYOUT_UNDEFINED,							// VkImageLayout				initialLayout;
   1175 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout				finalLayout;
   1176 		};
   1177 
   1178 		const VkAttachmentReference						attachmentReference			=
   1179 		{
   1180 			0u,													// deUint32			attachment;
   1181 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout	layout;
   1182 		};
   1183 
   1184 		const VkSubpassDescription						subpassDescription			=
   1185 		{
   1186 			0u,													// VkSubpassDescriptionFlags	flags;
   1187 			VK_PIPELINE_BIND_POINT_GRAPHICS,					// VkPipelineBindPoint			pipelineBindPoint;
   1188 			0u,													// deUint32						inputCount;
   1189 			DE_NULL,											// constVkAttachmentReference*	pInputAttachments;
   1190 			1u,													// deUint32						colorCount;
   1191 			&attachmentReference,								// constVkAttachmentReference*	pColorAttachments;
   1192 			DE_NULL,											// constVkAttachmentReference*	pResolveAttachments;
   1193 			DE_NULL,											// VkAttachmentReference		depthStencilAttachment;
   1194 			0u,													// deUint32						preserveCount;
   1195 			DE_NULL												// constVkAttachmentReference*	pPreserveAttachments;
   1196 		};
   1197 
   1198 		const VkRenderPassCreateInfo					renderPassParams			=
   1199 		{
   1200 			VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,			// VkStructureType					sType;
   1201 			DE_NULL,											// const void*						pNext;
   1202 			(VkRenderPassCreateFlags)0,
   1203 			1u,													// deUint32							attachmentCount;
   1204 			&attachmentDescription,								// const VkAttachmentDescription*	pAttachments;
   1205 			1u,													// deUint32							subpassCount;
   1206 			&subpassDescription,								// const VkSubpassDescription*		pSubpasses;
   1207 			0u,													// deUint32							dependencyCount;
   1208 			DE_NULL												// const VkSubpassDependency*		pDependencies;
   1209 		};
   1210 
   1211 		m_renderPass = createRenderPass(vk, vkDevice, &renderPassParams);
   1212 	}
   1213 
   1214 	// Create framebuffer
   1215 	{
   1216 		const VkFramebufferCreateInfo					framebufferParams			=
   1217 		{
   1218 			VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,			// VkStructureType				sType;
   1219 			DE_NULL,											// const void*					pNext;
   1220 			(VkFramebufferCreateFlags)0,
   1221 			*m_renderPass,										// VkRenderPass					renderPass;
   1222 			1u,													// deUint32						attachmentCount;
   1223 			&*m_colorImageView,									// const VkImageView*			pAttachments;
   1224 			(deUint32)m_renderSize.x(),							// deUint32						width;
   1225 			(deUint32)m_renderSize.y(),							// deUint32						height;
   1226 			1u													// deUint32						layers;
   1227 		};
   1228 
   1229 		m_framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
   1230 	}
   1231 
   1232 	// Create descriptors
   1233 	{
   1234 		setupUniforms(quadGrid.getConstCoords());
   1235 
   1236 		m_descriptorSetLayout = m_descriptorSetLayoutBuilder.build(vk, vkDevice);
   1237 		if (!m_uniformInfos.empty())
   1238 		{
   1239 			m_descriptorPool 								= m_descriptorPoolBuilder.build(vk, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
   1240 			const VkDescriptorSetAllocateInfo	allocInfo	=
   1241 			{
   1242 				VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
   1243 				DE_NULL,
   1244 				*m_descriptorPool,
   1245 				1u,
   1246 				&m_descriptorSetLayout.get(),
   1247 			};
   1248 
   1249 			m_descriptorSet = allocateDescriptorSet(vk, vkDevice, &allocInfo);
   1250 		}
   1251 
   1252 		for (deUint32 i = 0; i < m_uniformInfos.size(); i++)
   1253 		{
   1254 			const UniformInfo* uniformInfo = m_uniformInfos[i].get()->get();
   1255 			deUint32 location = uniformInfo->location;
   1256 
   1257 			if (uniformInfo->type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER)
   1258 			{
   1259 				const BufferUniform*	bufferInfo	= dynamic_cast<const BufferUniform*>(uniformInfo);
   1260 
   1261 				m_descriptorSetUpdateBuilder.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(location), uniformInfo->type, &bufferInfo->descriptor);
   1262 			}
   1263 			else if (uniformInfo->type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
   1264 			{
   1265 				const SamplerUniform*	samplerInfo	= dynamic_cast<const SamplerUniform*>(uniformInfo);
   1266 
   1267 				m_descriptorSetUpdateBuilder.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(location), uniformInfo->type, &samplerInfo->descriptor);
   1268 			}
   1269 			else
   1270 				DE_FATAL("Impossible");
   1271 		}
   1272 
   1273 		m_descriptorSetUpdateBuilder.update(vk, vkDevice);
   1274 	}
   1275 
   1276 	// Create pipeline layout
   1277 	{
   1278 		const VkPipelineLayoutCreateInfo				pipelineLayoutParams		=
   1279 		{
   1280 			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType				sType;
   1281 			DE_NULL,											// const void*					pNext;
   1282 			(VkPipelineLayoutCreateFlags)0,
   1283 			1u,													// deUint32						descriptorSetCount;
   1284 			&*m_descriptorSetLayout,							// const VkDescriptorSetLayout*	pSetLayouts;
   1285 			0u,													// deUint32						pushConstantRangeCount;
   1286 			DE_NULL												// const VkPushConstantRange*	pPushConstantRanges;
   1287 		};
   1288 
   1289 		m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
   1290 	}
   1291 
   1292 	// Create shaders
   1293 	{
   1294 		m_vertexShaderModule	= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("vert"), 0);
   1295 		m_fragmentShaderModule	= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("frag"), 0);
   1296 	}
   1297 
   1298 	// Create pipeline
   1299 	{
   1300 		const VkPipelineShaderStageCreateInfo			shaderStageParams[2]		=
   1301 		{
   1302 			{
   1303 				VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,		// VkStructureType				sType;
   1304 				DE_NULL,													// const void*					pNext;
   1305 				(VkPipelineShaderStageCreateFlags)0,
   1306 				VK_SHADER_STAGE_VERTEX_BIT,									// VkShaderStage				stage;
   1307 				*m_vertexShaderModule,										// VkShader						shader;
   1308 				"main",
   1309 				DE_NULL														// const VkSpecializationInfo*	pSpecializationInfo;
   1310 			},
   1311 			{
   1312 				VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,		// VkStructureType				sType;
   1313 				DE_NULL,													// const void*					pNext;
   1314 				(VkPipelineShaderStageCreateFlags)0,
   1315 				VK_SHADER_STAGE_FRAGMENT_BIT,								// VkShaderStage				stage;
   1316 				*m_fragmentShaderModule,									// VkShader						shader;
   1317 				"main",
   1318 				DE_NULL														// const VkSpecializationInfo*	pSpecializationInfo;
   1319 			}
   1320 		};
   1321 
   1322 		// Add test case specific attributes
   1323 		if (m_attribFunc)
   1324 			m_attribFunc(*this, quadGrid.getNumVertices());
   1325 
   1326 		// Add base attributes
   1327 		setupDefaultInputs(quadGrid);
   1328 
   1329 		const VkPipelineVertexInputStateCreateInfo		vertexInputStateParams		=
   1330 		{
   1331 			VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType							sType;
   1332 			DE_NULL,														// const void*								pNext;
   1333 			(VkPipelineVertexInputStateCreateFlags)0,
   1334 			(deUint32)m_vertexBindingDescription.size(),					// deUint32									bindingCount;
   1335 			&m_vertexBindingDescription[0],									// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
   1336 			(deUint32)m_vertexattributeDescription.size(),					// deUint32									attributeCount;
   1337 			&m_vertexattributeDescription[0],								// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
   1338 		};
   1339 
   1340 		const VkPipelineInputAssemblyStateCreateInfo	inputAssemblyStateParams	=
   1341 		{
   1342 			VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	// VkStructureType		sType;
   1343 			DE_NULL,														// const void*			pNext;
   1344 			(VkPipelineInputAssemblyStateCreateFlags)0,
   1345 			VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,							// VkPrimitiveTopology	topology;
   1346 			false															// VkBool32				primitiveRestartEnable;
   1347 		};
   1348 
   1349 		const VkViewport								viewport					=
   1350 		{
   1351 			0.0f,						// float	originX;
   1352 			0.0f,						// float	originY;
   1353 			(float)m_renderSize.x(),	// float	width;
   1354 			(float)m_renderSize.y(),	// float	height;
   1355 			0.0f,						// float	minDepth;
   1356 			1.0f						// float	maxDepth;
   1357 		};
   1358 
   1359 		const VkRect2D									scissor						=
   1360 		{
   1361 			{
   1362 				0u,					// deUint32	x;
   1363 				0u,					// deUint32	y;
   1364 			},							// VkOffset2D	offset;
   1365 			{
   1366 				m_renderSize.x(),	// deUint32	width;
   1367 				m_renderSize.y(),	// deUint32	height;
   1368 			},							// VkExtent2D	extent;
   1369 		};
   1370 
   1371 		const VkPipelineViewportStateCreateInfo			viewportStateParams			=
   1372 		{
   1373 			VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,			// VkStructureType		sType;
   1374 			DE_NULL,														// const void*			pNext;
   1375 			(VkPipelineViewportStateCreateFlags)0,
   1376 			1u,																// deUint32				viewportCount;
   1377 			&viewport,														// const VkViewport*	pViewports;
   1378 			1u,																// deUint32				scissorsCount;
   1379 			&scissor,														// const VkRect2D*		pScissors;
   1380 		};
   1381 
   1382 		const VkPipelineRasterizationStateCreateInfo	rasterStateParams			=
   1383 		{
   1384 			VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,		// VkStructureType	sType;
   1385 			DE_NULL,														// const void*		pNext;
   1386 			(VkPipelineRasterizationStateCreateFlags)0,
   1387 			false,															// VkBool32			depthClipEnable;
   1388 			false,															// VkBool32			rasterizerDiscardEnable;
   1389 			VK_POLYGON_MODE_FILL,											// VkFillMode		fillMode;
   1390 			VK_CULL_MODE_NONE,												// VkCullMode		cullMode;
   1391 			VK_FRONT_FACE_COUNTER_CLOCKWISE,								// VkFrontFace		frontFace;
   1392 			false,															// VkBool32			depthBiasEnable;
   1393 			0.0f,															// float			depthBias;
   1394 			0.0f,															// float			depthBiasClamp;
   1395 			0.0f,															// float			slopeScaledDepthBias;
   1396 			1.0f,															// float			lineWidth;
   1397 		};
   1398 
   1399 		const VkPipelineMultisampleStateCreateInfo		multisampleStateParams =
   1400 		{
   1401 			VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,		// VkStructureType							sType;
   1402 			DE_NULL,														// const void*								pNext;
   1403 			0u,																// VkPipelineMultisampleStateCreateFlags	flags;
   1404 			VK_SAMPLE_COUNT_1_BIT,											// VkSampleCountFlagBits					rasterizationSamples;
   1405 			VK_FALSE,														// VkBool32									sampleShadingEnable;
   1406 			0.0f,															// float									minSampleShading;
   1407 			DE_NULL,														// const VkSampleMask*						pSampleMask;
   1408 			VK_FALSE,														// VkBool32									alphaToCoverageEnable;
   1409 			VK_FALSE														// VkBool32									alphaToOneEnable;
   1410 		};
   1411 
   1412 		const VkPipelineColorBlendAttachmentState		colorBlendAttachmentState	=
   1413 		{
   1414 			false,															// VkBool32			blendEnable;
   1415 			VK_BLEND_FACTOR_ONE,											// VkBlend			srcBlendColor;
   1416 			VK_BLEND_FACTOR_ZERO,											// VkBlend			destBlendColor;
   1417 			VK_BLEND_OP_ADD,												// VkBlendOp		blendOpColor;
   1418 			VK_BLEND_FACTOR_ONE,											// VkBlend			srcBlendAlpha;
   1419 			VK_BLEND_FACTOR_ZERO,											// VkBlend			destBlendAlpha;
   1420 			VK_BLEND_OP_ADD,												// VkBlendOp		blendOpAlpha;
   1421 			(VK_COLOR_COMPONENT_R_BIT |
   1422 			 VK_COLOR_COMPONENT_G_BIT |
   1423 			 VK_COLOR_COMPONENT_B_BIT |
   1424 			 VK_COLOR_COMPONENT_A_BIT),										// VkChannelFlags	channelWriteMask;
   1425 		};
   1426 
   1427 		const VkPipelineColorBlendStateCreateInfo		colorBlendStateParams		=
   1428 		{
   1429 			VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType;
   1430 			DE_NULL,													// const void*									pNext;
   1431 			(VkPipelineColorBlendStateCreateFlags)0,
   1432 			false,														// VkBool32										logicOpEnable;
   1433 			VK_LOGIC_OP_COPY,											// VkLogicOp									logicOp;
   1434 			1u,															// deUint32										attachmentCount;
   1435 			&colorBlendAttachmentState,									// const VkPipelineColorBlendAttachmentState*	pAttachments;
   1436 			{ 0.0f, 0.0f, 0.0f, 0.0f },									// float										blendConst[4];
   1437 		};
   1438 
   1439 		const VkGraphicsPipelineCreateInfo				graphicsPipelineParams		=
   1440 		{
   1441 			VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,	// VkStructureType									sType;
   1442 			DE_NULL,											// const void*										pNext;
   1443 			0u,													// VkPipelineCreateFlags							flags;
   1444 			2u,													// deUint32											stageCount;
   1445 			shaderStageParams,									// const VkPipelineShaderStageCreateInfo*			pStages;
   1446 			&vertexInputStateParams,							// const VkPipelineVertexInputStateCreateInfo*		pVertexInputState;
   1447 			&inputAssemblyStateParams,							// const VkPipelineInputAssemblyStateCreateInfo*	pInputAssemblyState;
   1448 			DE_NULL,											// const VkPipelineTessellationStateCreateInfo*		pTessellationState;
   1449 			&viewportStateParams,								// const VkPipelineViewportStateCreateInfo*			pViewportState;
   1450 			&rasterStateParams,									// const VkPipelineRasterStateCreateInfo*			pRasterState;
   1451 			&multisampleStateParams,							// const VkPipelineMultisampleStateCreateInfo*		pMultisampleState;
   1452 			DE_NULL,											// const VkPipelineDepthStencilStateCreateInfo*		pDepthStencilState;
   1453 			&colorBlendStateParams,								// const VkPipelineColorBlendStateCreateInfo*		pColorBlendState;
   1454 			(const VkPipelineDynamicStateCreateInfo*)DE_NULL,	// const VkPipelineDynamicStateCreateInfo*			pDynamicState;
   1455 			*m_pipelineLayout,									// VkPipelineLayout									layout;
   1456 			*m_renderPass,										// VkRenderPass										renderPass;
   1457 			0u,													// deUint32											subpass;
   1458 			0u,													// VkPipeline										basePipelineHandle;
   1459 			0u													// deInt32											basePipelineIndex;
   1460 		};
   1461 
   1462 		m_graphicsPipeline = createGraphicsPipeline(vk, vkDevice, DE_NULL, &graphicsPipelineParams);
   1463 	}
   1464 
   1465 	// Create vertex indices buffer
   1466 	{
   1467 		const VkDeviceSize								indiceBufferSize			= quadGrid.getNumTriangles() * 3 * sizeof(deUint16);
   1468 		const VkBufferCreateInfo						indiceBufferParams			=
   1469 		{
   1470 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
   1471 			DE_NULL,									// const void*			pNext;
   1472 			0u,											// VkBufferCreateFlags	flags;
   1473 			indiceBufferSize,							// VkDeviceSize			size;
   1474 			VK_BUFFER_USAGE_INDEX_BUFFER_BIT,			// VkBufferUsageFlags	usage;
   1475 			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
   1476 			1u,											// deUint32				queueFamilyCount;
   1477 			&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
   1478 		};
   1479 
   1480 		m_indiceBuffer		= createBuffer(vk, vkDevice, &indiceBufferParams);
   1481 		m_indiceBufferAlloc	= m_memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_indiceBuffer), MemoryRequirement::HostVisible);
   1482 
   1483 		VK_CHECK(vk.bindBufferMemory(vkDevice, *m_indiceBuffer, m_indiceBufferAlloc->getMemory(), m_indiceBufferAlloc->getOffset()));
   1484 
   1485 		// Load vertice indices into buffer
   1486 		deMemcpy(m_indiceBufferAlloc->getHostPtr(), quadGrid.getIndices(), (size_t)indiceBufferSize);
   1487 		flushMappedMemoryRange(vk, vkDevice, m_indiceBufferAlloc->getMemory(), m_indiceBufferAlloc->getOffset(), indiceBufferSize);
   1488 	}
   1489 
   1490 	// Create command pool
   1491 	{
   1492 		const VkCommandPoolCreateInfo					cmdPoolParams				=
   1493 		{
   1494 			VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,		// VkStructureType		sType;
   1495 			DE_NULL,										// const void*			pNext;
   1496 			VK_COMMAND_POOL_CREATE_TRANSIENT_BIT,			// VkCmdPoolCreateFlags	flags;
   1497 			queueFamilyIndex,								// deUint32				queueFamilyIndex;
   1498 		};
   1499 
   1500 		m_cmdPool = createCommandPool(vk, vkDevice, &cmdPoolParams);
   1501 	}
   1502 
   1503 	// Create command buffer
   1504 	{
   1505 		const VkCommandBufferAllocateInfo				cmdBufferParams				=
   1506 		{
   1507 			VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,	// VkStructureType			sType;
   1508 			DE_NULL,										// const void*				pNext;
   1509 			*m_cmdPool,										// VkCmdPool				cmdPool;
   1510 			VK_COMMAND_BUFFER_LEVEL_PRIMARY,				// VkCmdBufferLevel			level;
   1511 			1u												// deUint32					bufferCount;
   1512 		};
   1513 
   1514 		const VkCommandBufferBeginInfo					cmdBufferBeginInfo			=
   1515 		{
   1516 			VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,	// VkStructureType			sType;
   1517 			DE_NULL,										// const void*				pNext;
   1518 			0u,												// VkCmdBufferOptimizeFlags	flags;
   1519 			(const VkCommandBufferInheritanceInfo*)DE_NULL,
   1520 		};
   1521 
   1522 		const VkClearValue								clearValues					= makeClearValueColorF32(m_clearColor.x(),
   1523 																											 m_clearColor.y(),
   1524 																											 m_clearColor.z(),
   1525 																											 m_clearColor.w());
   1526 
   1527 		const VkRenderPassBeginInfo						renderPassBeginInfo			=
   1528 		{
   1529 			VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,				// VkStructureType		sType;
   1530 			DE_NULL,												// const void*			pNext;
   1531 			*m_renderPass,											// VkRenderPass			renderPass;
   1532 			*m_framebuffer,											// VkFramebuffer		framebuffer;
   1533 			{ { 0, 0 },  {m_renderSize.x(), m_renderSize.y() } },	// VkRect2D				renderArea;
   1534 			1,														// deUint32				clearValueCount;
   1535 			&clearValues,											// const VkClearValue*	pClearValues;
   1536 		};
   1537 
   1538 		m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, &cmdBufferParams);
   1539 
   1540 		VK_CHECK(vk.beginCommandBuffer(*m_cmdBuffer, &cmdBufferBeginInfo));
   1541 
   1542 		// Add texture barriers
   1543 		std::vector<VkImageMemoryBarrier> barriers;
   1544 
   1545 		for(deUint32 i = 0; i < m_uniformInfos.size(); i++)
   1546 		{
   1547 			const UniformInfo* uniformInfo = m_uniformInfos[i].get()->get();
   1548 
   1549 			if (uniformInfo->type != VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
   1550 			{
   1551 				continue;
   1552 			}
   1553 
   1554 			const SamplerUniform*		sampler			= static_cast<const SamplerUniform*>(uniformInfo);
   1555 			const VkImageMemoryBarrier	textureBarrier	= createImageMemoryBarrier(sampler->image->get(), 0u, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
   1556 
   1557 			barriers.push_back(textureBarrier);
   1558 		}
   1559 
   1560 		vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (VkDependencyFlags)0,
   1561 							  0, (const VkMemoryBarrier*)DE_NULL,
   1562 							  0, (const VkBufferMemoryBarrier*)DE_NULL,
   1563 							  (deUint32)barriers.size(), (barriers.empty() ? (const VkImageMemoryBarrier*)DE_NULL : &barriers[0]));
   1564 
   1565 		vk.cmdBeginRenderPass(*m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
   1566 
   1567 		vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipeline);
   1568 		if (!m_uniformInfos.empty())
   1569 			vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0u, 1, &*m_descriptorSet, 0u, DE_NULL);
   1570 		vk.cmdBindIndexBuffer(*m_cmdBuffer, *m_indiceBuffer, 0, VK_INDEX_TYPE_UINT16);
   1571 
   1572 		const deUint32 numberOfVertexAttributes = (deUint32)m_vertexBuffers.size();
   1573 		const std::vector<VkDeviceSize> offsets(numberOfVertexAttributes, 0);
   1574 
   1575 		std::vector<VkBuffer> buffers(numberOfVertexAttributes);
   1576 		for (size_t i = 0; i < numberOfVertexAttributes; i++)
   1577 		{
   1578 			buffers[i] = m_vertexBuffers[i].get()->get();
   1579 		}
   1580 
   1581 		vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, numberOfVertexAttributes, &buffers[0], &offsets[0]);
   1582 		vk.cmdDrawIndexed(*m_cmdBuffer, quadGrid.getNumTriangles() * 3, 1, 0, 0, 0);
   1583 
   1584 		vk.cmdEndRenderPass(*m_cmdBuffer);
   1585 		VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer));
   1586 	}
   1587 
   1588 	// Create fence
   1589 	{
   1590 		const VkFenceCreateInfo							fenceParams					=
   1591 		{
   1592 			VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,	// VkStructureType		sType;
   1593 			DE_NULL,								// const void*			pNext;
   1594 			0u										// VkFenceCreateFlags	flags;
   1595 		};
   1596 		m_fence = createFence(vk, vkDevice, &fenceParams);
   1597 	}
   1598 
   1599 	// Execute Draw
   1600 	{
   1601 		const VkSubmitInfo	submitInfo	=
   1602 		{
   1603 			VK_STRUCTURE_TYPE_SUBMIT_INFO,
   1604 			DE_NULL,
   1605 			0u,
   1606 			(const VkSemaphore*)DE_NULL,
   1607 			(const VkPipelineStageFlags*)DE_NULL,
   1608 			1u,
   1609 			&m_cmdBuffer.get(),
   1610 			0u,
   1611 			(const VkSemaphore*)DE_NULL,
   1612 		};
   1613 
   1614 		VK_CHECK(vk.resetFences(vkDevice, 1, &m_fence.get()));
   1615 		VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *m_fence));
   1616 		VK_CHECK(vk.waitForFences(vkDevice, 1, &m_fence.get(), true, ~(0ull) /* infinity*/));
   1617 	}
   1618 
   1619 	// Read back the result
   1620 	{
   1621 		const VkDeviceSize								imageSizeBytes				= (VkDeviceSize)(sizeof(deUint32) * m_renderSize.x() * m_renderSize.y());
   1622 		const VkBufferCreateInfo						readImageBufferParams		=
   1623 		{
   1624 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		//  VkStructureType		sType;
   1625 			DE_NULL,									//  const void*			pNext;
   1626 			0u,											//  VkBufferCreateFlags	flags;
   1627 			imageSizeBytes,								//  VkDeviceSize		size;
   1628 			VK_BUFFER_USAGE_TRANSFER_DST_BIT,			//  VkBufferUsageFlags	usage;
   1629 			VK_SHARING_MODE_EXCLUSIVE,					//  VkSharingMode		sharingMode;
   1630 			1u,											//  deUint32			queueFamilyCount;
   1631 			&queueFamilyIndex,							//  const deUint32*		pQueueFamilyIndices;
   1632 		};
   1633 		const Unique<VkBuffer>							readImageBuffer				(createBuffer(vk, vkDevice, &readImageBufferParams));
   1634 		const de::UniquePtr<Allocation>					readImageBufferMemory		(m_memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *readImageBuffer), MemoryRequirement::HostVisible));
   1635 
   1636 		VK_CHECK(vk.bindBufferMemory(vkDevice, *readImageBuffer, readImageBufferMemory->getMemory(), readImageBufferMemory->getOffset()));
   1637 
   1638 		// Copy image to buffer
   1639 		const VkCommandBufferAllocateInfo				cmdBufferParams				=
   1640 		{
   1641 			VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,	// VkStructureType			sType;
   1642 			DE_NULL,										// const void*				pNext;
   1643 			*m_cmdPool,										// VkCmdPool				cmdPool;
   1644 			VK_COMMAND_BUFFER_LEVEL_PRIMARY,				// VkCmdBufferLevel			level;
   1645 			1u												// deUint32					bufferCount;
   1646 		};
   1647 
   1648 		const VkCommandBufferBeginInfo					cmdBufferBeginInfo			=
   1649 		{
   1650 			VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,	// VkStructureType			sType;
   1651 			DE_NULL,										// const void*				pNext;
   1652 			0u,												// VkCmdBufferOptimizeFlags	flags;
   1653 			(const VkCommandBufferInheritanceInfo*)DE_NULL,
   1654 		};
   1655 
   1656 		const Move<VkCommandBuffer>						cmdBuffer					= allocateCommandBuffer(vk, vkDevice, &cmdBufferParams);
   1657 
   1658 		const VkBufferImageCopy							copyParams					=
   1659 		{
   1660 			0u,											// VkDeviceSize			bufferOffset;
   1661 			(deUint32)m_renderSize.x(),					// deUint32				bufferRowLength;
   1662 			(deUint32)m_renderSize.y(),					// deUint32				bufferImageHeight;
   1663 			{
   1664 				VK_IMAGE_ASPECT_COLOR_BIT,			// VkImageAspect		aspect;
   1665 				0u,									// deUint32				mipLevel;
   1666 				0u,									// deUint32				arraySlice;
   1667 				1u,									// deUint32				arraySize;
   1668 			},											// VkImageSubresourceCopy	imageSubresource;
   1669 			{ 0u, 0u, 0u },								// VkOffset3D			imageOffset;
   1670 			{ m_renderSize.x(), m_renderSize.y(), 1u }	// VkExtent3D			imageExtent;
   1671 		};
   1672 		const VkSubmitInfo								submitInfo					=
   1673 		{
   1674 			VK_STRUCTURE_TYPE_SUBMIT_INFO,
   1675 			DE_NULL,
   1676 			0u,
   1677 			(const VkSemaphore*)DE_NULL,
   1678 			(const VkPipelineStageFlags*)DE_NULL,
   1679 			1u,
   1680 			&cmdBuffer.get(),
   1681 			0u,
   1682 			(const VkSemaphore*)DE_NULL,
   1683 		};
   1684 
   1685 		VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufferBeginInfo));
   1686 
   1687 		const VkImageMemoryBarrier imageBarrier =
   1688 		{
   1689 			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		// VkStructureType			sType;
   1690 			DE_NULL,									// const void*				pNext;
   1691 			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,		// VkAccessFlags			srcAccessMask;
   1692 			VK_ACCESS_TRANSFER_READ_BIT,				// VkAccessFlags			dstAccessMask;
   1693 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// VkImageLayout			oldLayout;
   1694 			VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,		// VkImageLayout			newLayout;
   1695 			VK_QUEUE_FAMILY_IGNORED,					// deUint32					srcQueueFamilyIndex;
   1696 			VK_QUEUE_FAMILY_IGNORED,					// deUint32					dstQueueFamilyIndex;
   1697 			*m_colorImage,								// VkImage					image;
   1698 			{											// VkImageSubresourceRange	subresourceRange;
   1699 				VK_IMAGE_ASPECT_COLOR_BIT,				// VkImageAspectFlags	aspectMask;
   1700 				0u,							// deUint32				baseMipLevel;
   1701 				1u,							// deUint32				mipLevels;
   1702 				0u,							// deUint32				baseArraySlice;
   1703 				1u							// deUint32				arraySize;
   1704 			}
   1705 		};
   1706 
   1707 		const VkBufferMemoryBarrier bufferBarrier =
   1708 		{
   1709 			VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	// VkStructureType	sType;
   1710 			DE_NULL,									// const void*		pNext;
   1711 			VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags	srcAccessMask;
   1712 			VK_ACCESS_HOST_READ_BIT,					// VkAccessFlags	dstAccessMask;
   1713 			VK_QUEUE_FAMILY_IGNORED,					// deUint32			srcQueueFamilyIndex;
   1714 			VK_QUEUE_FAMILY_IGNORED,					// deUint32			dstQueueFamilyIndex;
   1715 			*readImageBuffer,							// VkBuffer			buffer;
   1716 			0u,											// VkDeviceSize		offset;
   1717 			imageSizeBytes								// VkDeviceSize		size;
   1718 		};
   1719 
   1720 		vk.cmdPipelineBarrier(*cmdBuffer, 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);
   1721 		vk.cmdCopyImageToBuffer(*cmdBuffer, *m_colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *readImageBuffer, 1u, &copyParams);
   1722 		vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &bufferBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL);
   1723 
   1724 		VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
   1725 
   1726 		VK_CHECK(vk.resetFences(vkDevice, 1, &m_fence.get()));
   1727 		VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *m_fence));
   1728 		VK_CHECK(vk.waitForFences(vkDevice, 1, &m_fence.get(), true, ~(0ull) /* infinity */));
   1729 
   1730 		invalidateMappedMemoryRange(vk, vkDevice, readImageBufferMemory->getMemory(), readImageBufferMemory->getOffset(), imageSizeBytes);
   1731 
   1732 		const tcu::TextureFormat						resultFormat				(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8);
   1733 		const tcu::ConstPixelBufferAccess				resultAccess				(resultFormat, m_renderSize.x(), m_renderSize.y(), 1, readImageBufferMemory->getHostPtr());
   1734 
   1735 		tcu::copy(result.getAccess(), resultAccess);
   1736 	}
   1737 }
   1738 
   1739 void ShaderRenderCaseInstance::computeVertexReference (tcu::Surface& result, const QuadGrid& quadGrid)
   1740 {
   1741 	// Buffer info.
   1742 	const int				width		= result.getWidth();
   1743 	const int				height		= result.getHeight();
   1744 	const int				gridSize	= quadGrid.getGridSize();
   1745 	const int				stride		= gridSize + 1;
   1746 	const bool				hasAlpha	= true; // \todo [2015-09-07 elecro] add correct alpha check
   1747 	ShaderEvalContext		evalCtx		(quadGrid);
   1748 
   1749 	// Evaluate color for each vertex.
   1750 	std::vector<tcu::Vec4>	colors		((gridSize + 1) * (gridSize + 1));
   1751 	for (int y = 0; y < gridSize+1; y++)
   1752 	for (int x = 0; x < gridSize+1; x++)
   1753 	{
   1754 		const float	sx			= (float)x / (float)gridSize;
   1755 		const float	sy			= (float)y / (float)gridSize;
   1756 		const int	vtxNdx		= ((y * (gridSize+1)) + x);
   1757 
   1758 		evalCtx.reset(sx, sy);
   1759 		m_evaluator.evaluate(evalCtx);
   1760 		DE_ASSERT(!evalCtx.isDiscarded); // Discard is not available in vertex shader.
   1761 		tcu::Vec4 color = evalCtx.color;
   1762 
   1763 		if (!hasAlpha)
   1764 			color.w() = 1.0f;
   1765 
   1766 		colors[vtxNdx] = color;
   1767 	}
   1768 
   1769 	// Render quads.
   1770 	for (int y = 0; y < gridSize; y++)
   1771 	for (int x = 0; x < gridSize; x++)
   1772 	{
   1773 		const float		x0		= (float)x       / (float)gridSize;
   1774 		const float		x1		= (float)(x + 1) / (float)gridSize;
   1775 		const float		y0		= (float)y       / (float)gridSize;
   1776 		const float		y1		= (float)(y + 1) / (float)gridSize;
   1777 
   1778 		const float		sx0		= x0 * (float)width;
   1779 		const float		sx1		= x1 * (float)width;
   1780 		const float		sy0		= y0 * (float)height;
   1781 		const float		sy1		= y1 * (float)height;
   1782 		const float		oosx	= 1.0f / (sx1 - sx0);
   1783 		const float		oosy	= 1.0f / (sy1 - sy0);
   1784 
   1785 		const int		ix0		= deCeilFloatToInt32(sx0 - 0.5f);
   1786 		const int		ix1		= deCeilFloatToInt32(sx1 - 0.5f);
   1787 		const int		iy0		= deCeilFloatToInt32(sy0 - 0.5f);
   1788 		const int		iy1		= deCeilFloatToInt32(sy1 - 0.5f);
   1789 
   1790 		const int		v00		= (y * stride) + x;
   1791 		const int		v01		= (y * stride) + x + 1;
   1792 		const int		v10		= ((y + 1) * stride) + x;
   1793 		const int		v11		= ((y + 1) * stride) + x + 1;
   1794 		const tcu::Vec4	c00		= colors[v00];
   1795 		const tcu::Vec4	c01		= colors[v01];
   1796 		const tcu::Vec4	c10		= colors[v10];
   1797 		const tcu::Vec4	c11		= colors[v11];
   1798 
   1799 		//printf("(%d,%d) -> (%f..%f, %f..%f) (%d..%d, %d..%d)\n", x, y, sx0, sx1, sy0, sy1, ix0, ix1, iy0, iy1);
   1800 
   1801 		for (int iy = iy0; iy < iy1; iy++)
   1802 		for (int ix = ix0; ix < ix1; ix++)
   1803 		{
   1804 			DE_ASSERT(deInBounds32(ix, 0, width));
   1805 			DE_ASSERT(deInBounds32(iy, 0, height));
   1806 
   1807 			const float			sfx		= (float)ix + 0.5f;
   1808 			const float			sfy		= (float)iy + 0.5f;
   1809 			const float			fx1		= deFloatClamp((sfx - sx0) * oosx, 0.0f, 1.0f);
   1810 			const float			fy1		= deFloatClamp((sfy - sy0) * oosy, 0.0f, 1.0f);
   1811 
   1812 			// Triangle quad interpolation.
   1813 			const bool			tri		= fx1 + fy1 <= 1.0f;
   1814 			const float			tx		= tri ? fx1 : (1.0f-fx1);
   1815 			const float			ty		= tri ? fy1 : (1.0f-fy1);
   1816 			const tcu::Vec4&	t0		= tri ? c00 : c11;
   1817 			const tcu::Vec4&	t1		= tri ? c01 : c10;
   1818 			const tcu::Vec4&	t2		= tri ? c10 : c01;
   1819 			const tcu::Vec4		color	= t0 + (t1-t0)*tx + (t2-t0)*ty;
   1820 
   1821 			result.setPixel(ix, iy, tcu::RGBA(color));
   1822 		}
   1823 	}
   1824 }
   1825 
   1826 void ShaderRenderCaseInstance::computeFragmentReference (tcu::Surface& result, const QuadGrid& quadGrid)
   1827 {
   1828 	// Buffer info.
   1829 	const int			width		= result.getWidth();
   1830 	const int			height		= result.getHeight();
   1831 	const bool			hasAlpha	= true;  // \todo [2015-09-07 elecro] add correct alpha check
   1832 	ShaderEvalContext	evalCtx		(quadGrid);
   1833 
   1834 	// Render.
   1835 	for (int y = 0; y < height; y++)
   1836 	for (int x = 0; x < width; x++)
   1837 	{
   1838 		const float sx = ((float)x + 0.5f) / (float)width;
   1839 		const float sy = ((float)y + 0.5f) / (float)height;
   1840 
   1841 		evalCtx.reset(sx, sy);
   1842 		m_evaluator.evaluate(evalCtx);
   1843 		// Select either clear color or computed color based on discarded bit.
   1844 		tcu::Vec4 color = evalCtx.isDiscarded ? m_clearColor : evalCtx.color;
   1845 
   1846 		if (!hasAlpha)
   1847 			color.w() = 1.0f;
   1848 
   1849 		result.setPixel(x, y, tcu::RGBA(color));
   1850 	}
   1851 }
   1852 
   1853 bool ShaderRenderCaseInstance::compareImages (const tcu::Surface& resImage, const tcu::Surface& refImage, float errorThreshold)
   1854 {
   1855 	return tcu::fuzzyCompare(m_context.getTestContext().getLog(), "ComparisonResult", "Image comparison result", refImage, resImage, errorThreshold, tcu::COMPARE_LOG_RESULT);
   1856 }
   1857 
   1858 } // sr
   1859 } // vkt
   1860