Home | History | Annotate | Download | only in pipeline
      1 /*------------------------------------------------------------------------
      2  * Vulkan Conformance Tests
      3  * ------------------------
      4  *
      5  * Copyright (c) 2015 The Khronos Group Inc.
      6  * Copyright (c) 2015 Imagination Technologies Ltd.
      7  *
      8  * Licensed under the Apache License, Version 2.0 (the "License");
      9  * you may not use this file except in compliance with the License.
     10  * You may obtain a copy of the License at
     11  *
     12  *      http://www.apache.org/licenses/LICENSE-2.0
     13  *
     14  * Unless required by applicable law or agreed to in writing, software
     15  * distributed under the License is distributed on an "AS IS" BASIS,
     16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     17  * See the License for the specific language governing permissions and
     18  * limitations under the License.
     19  *
     20  *//*!
     21  * \file
     22  * \brief Image sampling case
     23  *//*--------------------------------------------------------------------*/
     24 
     25 #include "vktPipelineImageSamplingInstance.hpp"
     26 #include "vktPipelineClearUtil.hpp"
     27 #include "vktPipelineReferenceRenderer.hpp"
     28 #include "vkBuilderUtil.hpp"
     29 #include "vkImageUtil.hpp"
     30 #include "vkPrograms.hpp"
     31 #include "vkQueryUtil.hpp"
     32 #include "vkRefUtil.hpp"
     33 #include "tcuImageCompare.hpp"
     34 
     35 namespace vkt
     36 {
     37 namespace pipeline
     38 {
     39 
     40 using namespace vk;
     41 using de::MovePtr;
     42 
     43 namespace
     44 {
     45 
     46 static VkImageType getCompatibleImageType (VkImageViewType viewType)
     47 {
     48 	switch (viewType)
     49 	{
     50 		case VK_IMAGE_VIEW_TYPE_1D:				return VK_IMAGE_TYPE_1D;
     51 		case VK_IMAGE_VIEW_TYPE_1D_ARRAY:		return VK_IMAGE_TYPE_1D;
     52 		case VK_IMAGE_VIEW_TYPE_2D:				return VK_IMAGE_TYPE_2D;
     53 		case VK_IMAGE_VIEW_TYPE_2D_ARRAY:		return VK_IMAGE_TYPE_2D;
     54 		case VK_IMAGE_VIEW_TYPE_3D:				return VK_IMAGE_TYPE_3D;
     55 		case VK_IMAGE_VIEW_TYPE_CUBE:			return VK_IMAGE_TYPE_2D;
     56 		case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:		return VK_IMAGE_TYPE_2D;
     57 		default:
     58 			break;
     59 	}
     60 
     61 	DE_ASSERT(false);
     62 	return VK_IMAGE_TYPE_1D;
     63 }
     64 
     65 template<typename TcuFormatType>
     66 static MovePtr<TestTexture> createTestTexture (const TcuFormatType format, VkImageViewType viewType, const tcu::IVec3& size, int layerCount)
     67 {
     68 	MovePtr<TestTexture>	texture;
     69 	const VkImageType		imageType = getCompatibleImageType(viewType);
     70 
     71 	switch (imageType)
     72 	{
     73 		case VK_IMAGE_TYPE_1D:
     74 			if (layerCount == 1)
     75 				texture = MovePtr<TestTexture>(new TestTexture1D(format, size.x()));
     76 			else
     77 				texture = MovePtr<TestTexture>(new TestTexture1DArray(format, size.x(), layerCount));
     78 
     79 			break;
     80 
     81 		case VK_IMAGE_TYPE_2D:
     82 			if (layerCount == 1)
     83 			{
     84 				texture = MovePtr<TestTexture>(new TestTexture2D(format, size.x(), size.y()));
     85 			}
     86 			else
     87 			{
     88 				if (viewType == VK_IMAGE_VIEW_TYPE_CUBE || viewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
     89 				{
     90 					if (layerCount == tcu::CUBEFACE_LAST)
     91 					{
     92 						texture = MovePtr<TestTexture>(new TestTextureCube(format, size.x()));
     93 					}
     94 					else
     95 					{
     96 						DE_ASSERT(layerCount % tcu::CUBEFACE_LAST == 0);
     97 
     98 						texture = MovePtr<TestTexture>(new TestTextureCubeArray(format, size.x(), layerCount));
     99 					}
    100 				}
    101 				else
    102 				{
    103 					texture = MovePtr<TestTexture>(new TestTexture2DArray(format, size.x(), size.y(), layerCount));
    104 				}
    105 			}
    106 
    107 			break;
    108 
    109 		case VK_IMAGE_TYPE_3D:
    110 			texture = MovePtr<TestTexture>(new TestTexture3D(format, size.x(), size.y(), size.z()));
    111 			break;
    112 
    113 		default:
    114 			DE_ASSERT(false);
    115 	}
    116 
    117 	return texture;
    118 }
    119 
    120 template<typename TcuTextureType>
    121 static void copySubresourceRange (TcuTextureType& dest, const TcuTextureType& src, const VkImageSubresourceRange& subresourceRange)
    122 {
    123 	DE_ASSERT(subresourceRange.levelCount <= (deUint32)dest.getNumLevels());
    124 	DE_ASSERT(subresourceRange.baseMipLevel + subresourceRange.levelCount <= (deUint32)src.getNumLevels());
    125 
    126 	for (int levelNdx = 0; levelNdx < dest.getNumLevels(); levelNdx++)
    127 	{
    128 		const tcu::ConstPixelBufferAccess	srcLevel		(src.getLevel(subresourceRange.baseMipLevel + levelNdx));
    129 		const deUint32						srcLayerOffset	= subresourceRange.baseArrayLayer * srcLevel.getWidth() * srcLevel.getHeight() * srcLevel.getFormat().getPixelSize();
    130 		const tcu::ConstPixelBufferAccess	srcLevelLayers	(srcLevel.getFormat(), srcLevel.getWidth(), srcLevel.getHeight(), subresourceRange.layerCount, (deUint8*)srcLevel.getDataPtr() + srcLayerOffset);
    131 
    132 		if (dest.isLevelEmpty(levelNdx))
    133 			dest.allocLevel(levelNdx);
    134 
    135 		tcu::copy(dest.getLevel(levelNdx), srcLevelLayers);
    136 	}
    137 }
    138 
    139 template<>
    140 void copySubresourceRange<tcu::Texture1DArray> (tcu::Texture1DArray& dest, const tcu::Texture1DArray& src, const VkImageSubresourceRange& subresourceRange)
    141 {
    142 	DE_ASSERT(subresourceRange.levelCount <= (deUint32)dest.getNumLevels());
    143 	DE_ASSERT(subresourceRange.baseMipLevel + subresourceRange.levelCount <= (deUint32)src.getNumLevels());
    144 
    145 	DE_ASSERT(subresourceRange.layerCount == (deUint32)dest.getNumLayers());
    146 	DE_ASSERT(subresourceRange.baseArrayLayer + subresourceRange.layerCount <= (deUint32)src.getNumLayers());
    147 
    148 	for (int levelNdx = 0; levelNdx < dest.getNumLevels(); levelNdx++)
    149 	{
    150 		const tcu::ConstPixelBufferAccess	srcLevel		(src.getLevel(subresourceRange.baseMipLevel + levelNdx));
    151 		const deUint32						srcLayerOffset	= subresourceRange.baseArrayLayer * srcLevel.getWidth() * srcLevel.getFormat().getPixelSize();
    152 		const tcu::ConstPixelBufferAccess	srcLevelLayers	(srcLevel.getFormat(), srcLevel.getWidth(), subresourceRange.layerCount, 1, (deUint8*)srcLevel.getDataPtr() + srcLayerOffset);
    153 
    154 		if (dest.isLevelEmpty(levelNdx))
    155 			dest.allocLevel(levelNdx);
    156 
    157 		tcu::copy(dest.getLevel(levelNdx), srcLevelLayers);
    158 	}
    159 }
    160 
    161 template<>
    162 void copySubresourceRange<tcu::Texture3D>(tcu::Texture3D& dest, const tcu::Texture3D& src, const VkImageSubresourceRange& subresourceRange)
    163 {
    164 	DE_ASSERT(subresourceRange.levelCount <= (deUint32)dest.getNumLevels());
    165 	DE_ASSERT(subresourceRange.baseMipLevel + subresourceRange.levelCount <= (deUint32)src.getNumLevels());
    166 
    167 	for (int levelNdx = 0; levelNdx < dest.getNumLevels(); levelNdx++)
    168 	{
    169 		const tcu::ConstPixelBufferAccess	srcLevel(src.getLevel(subresourceRange.baseMipLevel + levelNdx));
    170 		const tcu::ConstPixelBufferAccess	srcLevelLayers(srcLevel.getFormat(), srcLevel.getWidth(), srcLevel.getHeight(), srcLevel.getDepth(), (deUint8*)srcLevel.getDataPtr());
    171 
    172 		if (dest.isLevelEmpty(levelNdx))
    173 			dest.allocLevel(levelNdx);
    174 
    175 		tcu::copy(dest.getLevel(levelNdx), srcLevelLayers);
    176 	}
    177 }
    178 
    179 static MovePtr<Program> createRefProgram(const tcu::TextureFormat&			renderTargetFormat,
    180 										  const tcu::Sampler&				sampler,
    181 										  float								samplerLod,
    182 										  const tcu::UVec4&					componentMapping,
    183 										  const TestTexture&				testTexture,
    184 										  VkImageViewType					viewType,
    185 										  int								layerCount,
    186 										  const VkImageSubresourceRange&	subresource)
    187 {
    188 	MovePtr<Program>	program;
    189 	const VkImageType	imageType		= getCompatibleImageType(viewType);
    190 	tcu::Vec4			lookupScale		(1.0f);
    191 	tcu::Vec4			lookupBias		(0.0f);
    192 
    193 	if (!testTexture.isCompressed())
    194 	{
    195 		const tcu::TextureFormatInfo	fmtInfo	= tcu::getTextureFormatInfo(testTexture.getLevel(0, 0).getFormat());
    196 
    197 		// Needed to normalize various formats to 0..1 range for writing into RT
    198 		lookupScale	= fmtInfo.lookupScale;
    199 		lookupBias	= fmtInfo.lookupBias;
    200 	}
    201 	// else: All supported compressed formats are fine with no normalization.
    202 	//		 ASTC LDR blocks decompress to f16 so querying normalization parameters
    203 	//		 based on uncompressed formats would actually lead to massive precision loss
    204 	//		 and complete lack of coverage in case of R8G8B8A8_UNORM RT.
    205 
    206 	switch (imageType)
    207 	{
    208 		case VK_IMAGE_TYPE_1D:
    209 			if (layerCount == 1)
    210 			{
    211 				const tcu::Texture1D& texture = dynamic_cast<const TestTexture1D&>(testTexture).getTexture();
    212 				program = MovePtr<Program>(new SamplerProgram<tcu::Texture1D>(renderTargetFormat, texture, sampler, samplerLod, lookupScale, lookupBias, componentMapping));
    213 			}
    214 			else
    215 			{
    216 				const tcu::Texture1DArray& texture = dynamic_cast<const TestTexture1DArray&>(testTexture).getTexture();
    217 
    218 				if (subresource.baseMipLevel > 0 || subresource.layerCount < (deUint32)texture.getNumLayers())
    219 				{
    220 					// Not all texture levels and layers are needed. Create new sub-texture.
    221 					const tcu::ConstPixelBufferAccess	baseLevel	= texture.getLevel(subresource.baseMipLevel);
    222 					tcu::Texture1DArray					textureView	(texture.getFormat(), baseLevel.getWidth(), subresource.layerCount);
    223 
    224 					copySubresourceRange(textureView, texture, subresource);
    225 
    226 					program = MovePtr<Program>(new SamplerProgram<tcu::Texture1DArray>(renderTargetFormat, textureView, sampler, samplerLod, lookupScale, lookupBias, componentMapping));
    227 				}
    228 				else
    229 				{
    230 					program = MovePtr<Program>(new SamplerProgram<tcu::Texture1DArray>(renderTargetFormat, texture, sampler, samplerLod, lookupScale, lookupBias, componentMapping));
    231 				}
    232 			}
    233 			break;
    234 
    235 		case VK_IMAGE_TYPE_2D:
    236 			if (layerCount == 1)
    237 			{
    238 				const tcu::Texture2D& texture = dynamic_cast<const TestTexture2D&>(testTexture).getTexture();
    239 				program = MovePtr<Program>(new SamplerProgram<tcu::Texture2D>(renderTargetFormat, texture, sampler, samplerLod, lookupScale, lookupBias, componentMapping));
    240 			}
    241 			else
    242 			{
    243 				if (viewType == VK_IMAGE_VIEW_TYPE_CUBE || viewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
    244 				{
    245 					if (layerCount == tcu::CUBEFACE_LAST)
    246 					{
    247 						const tcu::TextureCube& texture = dynamic_cast<const TestTextureCube&>(testTexture).getTexture();
    248 						program = MovePtr<Program>(new SamplerProgram<tcu::TextureCube>(renderTargetFormat, texture, sampler, samplerLod, lookupScale, lookupBias, componentMapping));
    249 					}
    250 					else
    251 					{
    252 						DE_ASSERT(layerCount % tcu::CUBEFACE_LAST == 0);
    253 
    254 						const tcu::TextureCubeArray& texture = dynamic_cast<const TestTextureCubeArray&>(testTexture).getTexture();
    255 
    256 						if (subresource.baseMipLevel > 0 || subresource.layerCount < (deUint32)texture.getDepth())
    257 						{
    258 							DE_ASSERT(subresource.baseArrayLayer + subresource.layerCount <= (deUint32)texture.getDepth());
    259 
    260 							// Not all texture levels and layers are needed. Create new sub-texture.
    261 							const tcu::ConstPixelBufferAccess	baseLevel		= texture.getLevel(subresource.baseMipLevel);
    262 							tcu::TextureCubeArray				textureView		(texture.getFormat(), baseLevel.getWidth(), subresource.layerCount);
    263 
    264 							copySubresourceRange(textureView, texture, subresource);
    265 
    266 							program = MovePtr<Program>(new SamplerProgram<tcu::TextureCubeArray>(renderTargetFormat, textureView, sampler, samplerLod, lookupScale, lookupBias, componentMapping));
    267 						}
    268 						else
    269 						{
    270 							// Use all array layers
    271 							program = MovePtr<Program>(new SamplerProgram<tcu::TextureCubeArray>(renderTargetFormat, texture, sampler, samplerLod, lookupScale, lookupBias, componentMapping));
    272 						}
    273 					}
    274 				}
    275 				else
    276 				{
    277 					const tcu::Texture2DArray& texture = dynamic_cast<const TestTexture2DArray&>(testTexture).getTexture();
    278 
    279 					if (subresource.baseMipLevel > 0 || subresource.layerCount < (deUint32)texture.getNumLayers())
    280 					{
    281 						DE_ASSERT(subresource.baseArrayLayer + subresource.layerCount <= (deUint32)texture.getNumLayers());
    282 
    283 						// Not all texture levels and layers are needed. Create new sub-texture.
    284 						const tcu::ConstPixelBufferAccess	baseLevel	= texture.getLevel(subresource.baseMipLevel);
    285 						tcu::Texture2DArray					textureView	(texture.getFormat(), baseLevel.getWidth(), baseLevel.getHeight(), subresource.layerCount);
    286 
    287 						copySubresourceRange(textureView, texture, subresource);
    288 
    289 						program = MovePtr<Program>(new SamplerProgram<tcu::Texture2DArray>(renderTargetFormat, textureView, sampler, samplerLod, lookupScale, lookupBias, componentMapping));
    290 					}
    291 					else
    292 					{
    293 						// Use all array layers
    294 						program = MovePtr<Program>(new SamplerProgram<tcu::Texture2DArray>(renderTargetFormat, texture, sampler, samplerLod, lookupScale, lookupBias, componentMapping));
    295 					}
    296 				}
    297 			}
    298 			break;
    299 
    300 		case VK_IMAGE_TYPE_3D:
    301 			{
    302 				const tcu::Texture3D& texture = dynamic_cast<const TestTexture3D&>(testTexture).getTexture();
    303 
    304 				if (subresource.baseMipLevel > 0)
    305 				{
    306 					// Not all texture levels are needed. Create new sub-texture.
    307 					const tcu::ConstPixelBufferAccess	baseLevel = texture.getLevel(subresource.baseMipLevel);
    308 					tcu::Texture3D						textureView(texture.getFormat(), baseLevel.getWidth(), baseLevel.getHeight(), baseLevel.getDepth());
    309 
    310 					copySubresourceRange(textureView, texture, subresource);
    311 
    312 					program = MovePtr<Program>(new SamplerProgram<tcu::Texture3D>(renderTargetFormat, textureView, sampler, samplerLod, lookupScale, lookupBias, componentMapping));
    313 				}
    314 				else
    315 				{
    316 					program = MovePtr<Program>(new SamplerProgram<tcu::Texture3D>(renderTargetFormat, texture, sampler, samplerLod, lookupScale, lookupBias, componentMapping));
    317 				}
    318 			}
    319 			break;
    320 
    321 		default:
    322 			DE_ASSERT(false);
    323 	}
    324 
    325 	return program;
    326 }
    327 
    328 } // anonymous
    329 
    330 ImageSamplingInstance::ImageSamplingInstance (Context&							context,
    331 											  const tcu::UVec2&					renderSize,
    332 											  VkImageViewType					imageViewType,
    333 											  VkFormat							imageFormat,
    334 											  const tcu::IVec3&					imageSize,
    335 											  int								layerCount,
    336 											  const VkComponentMapping&			componentMapping,
    337 											  const VkImageSubresourceRange&	subresourceRange,
    338 											  const VkSamplerCreateInfo&		samplerParams,
    339 											  float								samplerLod,
    340 											  const std::vector<Vertex4Tex4>&	vertices)
    341 	: vkt::TestInstance		(context)
    342 	, m_imageViewType		(imageViewType)
    343 	, m_imageFormat			(imageFormat)
    344 	, m_imageSize			(imageSize)
    345 	, m_layerCount			(layerCount)
    346 	, m_componentMapping	(componentMapping)
    347 	, m_subresourceRange	(subresourceRange)
    348 	, m_samplerParams		(samplerParams)
    349 	, m_samplerLod			(samplerLod)
    350 	, m_renderSize			(renderSize)
    351 	, m_colorFormat			(VK_FORMAT_R8G8B8A8_UNORM)
    352 	, m_vertices			(vertices)
    353 {
    354 	const DeviceInterface&		vk						= context.getDeviceInterface();
    355 	const VkDevice				vkDevice				= context.getDevice();
    356 	const VkQueue				queue					= context.getUniversalQueue();
    357 	const deUint32				queueFamilyIndex		= context.getUniversalQueueFamilyIndex();
    358 	SimpleAllocator				memAlloc				(vk, vkDevice, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice()));
    359 	const VkComponentMapping	componentMappingRGBA	= { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
    360 
    361 	if (!isSupportedSamplableFormat(context.getInstanceInterface(), context.getPhysicalDevice(), imageFormat))
    362 		throw tcu::NotSupportedError(std::string("Unsupported format for sampling: ") + getFormatName(imageFormat));
    363 
    364 	if ((samplerParams.minFilter == VK_FILTER_LINEAR ||
    365 		 samplerParams.magFilter == VK_FILTER_LINEAR ||
    366 		 samplerParams.mipmapMode == VK_SAMPLER_MIPMAP_MODE_LINEAR) &&
    367 		!isLinearFilteringSupported(context.getInstanceInterface(), context.getPhysicalDevice(), imageFormat, VK_IMAGE_TILING_OPTIMAL))
    368 		throw tcu::NotSupportedError(std::string("Unsupported format for linear filtering: ") + getFormatName(imageFormat));
    369 
    370 	if (isCompressedFormat(imageFormat) && imageViewType == VK_IMAGE_VIEW_TYPE_3D)
    371 	{
    372 		// \todo [2016-01-22 pyry] Mandate VK_ERROR_FORMAT_NOT_SUPPORTED
    373 		try
    374 		{
    375 			const VkImageFormatProperties	formatProperties	= getPhysicalDeviceImageFormatProperties(context.getInstanceInterface(),
    376 																										 context.getPhysicalDevice(),
    377 																										 imageFormat,
    378 																										 VK_IMAGE_TYPE_3D,
    379 																										 VK_IMAGE_TILING_OPTIMAL,
    380 																										 VK_IMAGE_USAGE_SAMPLED_BIT,
    381 																										 (VkImageCreateFlags)0);
    382 
    383 			if (formatProperties.maxExtent.width == 0 &&
    384 				formatProperties.maxExtent.height == 0 &&
    385 				formatProperties.maxExtent.depth == 0)
    386 				TCU_THROW(NotSupportedError, "3D compressed format not supported");
    387 		}
    388 		catch (const Error&)
    389 		{
    390 			TCU_THROW(NotSupportedError, "3D compressed format not supported");
    391 		}
    392 	}
    393 
    394 	// Create texture image, view and sampler
    395 	{
    396 		VkImageCreateFlags			imageFlags			= 0u;
    397 
    398 		if (m_imageViewType == VK_IMAGE_VIEW_TYPE_CUBE || m_imageViewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
    399 			imageFlags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
    400 
    401 		// Initialize texture data
    402 		if (isCompressedFormat(imageFormat))
    403 			m_texture = createTestTexture(mapVkCompressedFormat(imageFormat), imageViewType, imageSize, layerCount);
    404 		else
    405 			m_texture = createTestTexture(mapVkFormat(imageFormat), imageViewType, imageSize, layerCount);
    406 
    407 		const VkImageCreateInfo	imageParams =
    408 		{
    409 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,							// VkStructureType			sType;
    410 			DE_NULL,														// const void*				pNext;
    411 			imageFlags,														// VkImageCreateFlags		flags;
    412 			getCompatibleImageType(m_imageViewType),						// VkImageType				imageType;
    413 			imageFormat,													// VkFormat					format;
    414 			{																// VkExtent3D				extent;
    415 				(deUint32)m_imageSize.x(),
    416 				(deUint32)m_imageSize.y(),
    417 				(deUint32)m_imageSize.z()
    418 			},
    419 			(deUint32)m_texture->getNumLevels(),							// deUint32					mipLevels;
    420 			(deUint32)m_layerCount,											// deUint32					arrayLayers;
    421 			VK_SAMPLE_COUNT_1_BIT,											// VkSampleCountFlagBits	samples;
    422 			VK_IMAGE_TILING_OPTIMAL,										// VkImageTiling			tiling;
    423 			VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,	// VkImageUsageFlags		usage;
    424 			VK_SHARING_MODE_EXCLUSIVE,										// VkSharingMode			sharingMode;
    425 			1u,																// deUint32					queueFamilyIndexCount;
    426 			&queueFamilyIndex,												// const deUint32*			pQueueFamilyIndices;
    427 			VK_IMAGE_LAYOUT_UNDEFINED										// VkImageLayout			initialLayout;
    428 		};
    429 
    430 		m_image			= createImage(vk, vkDevice, &imageParams);
    431 		m_imageAlloc	= memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_image), MemoryRequirement::Any);
    432 		VK_CHECK(vk.bindImageMemory(vkDevice, *m_image, m_imageAlloc->getMemory(), m_imageAlloc->getOffset()));
    433 
    434 		// Upload texture data
    435 		uploadTestTexture(vk, vkDevice, queue, queueFamilyIndex, memAlloc, *m_texture, *m_image);
    436 
    437 		// Create image view and sampler
    438 		const VkImageViewCreateInfo imageViewParams =
    439 		{
    440 			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,	// VkStructureType			sType;
    441 			DE_NULL,									// const void*				pNext;
    442 			0u,											// VkImageViewCreateFlags	flags;
    443 			*m_image,									// VkImage					image;
    444 			m_imageViewType,							// VkImageViewType			viewType;
    445 			imageFormat,								// VkFormat					format;
    446 			m_componentMapping,							// VkComponentMapping		components;
    447 			m_subresourceRange,							// VkImageSubresourceRange	subresourceRange;
    448 		};
    449 
    450 		m_imageView	= createImageView(vk, vkDevice, &imageViewParams);
    451 		m_sampler	= createSampler(vk, vkDevice, &m_samplerParams);
    452 	}
    453 
    454 	// Create descriptor set for combined image and sampler
    455 	{
    456 		DescriptorPoolBuilder descriptorPoolBuilder;
    457 		descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1u);
    458 		m_descriptorPool = descriptorPoolBuilder.build(vk, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
    459 
    460 		DescriptorSetLayoutBuilder setLayoutBuilder;
    461 		setLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT);
    462 		m_descriptorSetLayout = setLayoutBuilder.build(vk, vkDevice);
    463 
    464 		const VkDescriptorSetAllocateInfo descriptorSetAllocateInfo =
    465 		{
    466 			VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,		// VkStructureType				sType;
    467 			DE_NULL,											// const void*					pNext;
    468 			*m_descriptorPool,									// VkDescriptorPool				descriptorPool;
    469 			1u,													// deUint32						setLayoutCount;
    470 			&m_descriptorSetLayout.get()						// const VkDescriptorSetLayout*	pSetLayouts;
    471 		};
    472 
    473 		m_descriptorSet = allocateDescriptorSet(vk, vkDevice, &descriptorSetAllocateInfo);
    474 
    475 		const VkDescriptorImageInfo descriptorImageInfo =
    476 		{
    477 			*m_sampler,									// VkSampler		sampler;
    478 			*m_imageView,								// VkImageView		imageView;
    479 			VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL	// VkImageLayout	imageLayout;
    480 		};
    481 
    482 		DescriptorSetUpdateBuilder setUpdateBuilder;
    483 		setUpdateBuilder.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &descriptorImageInfo);
    484 		setUpdateBuilder.update(vk, vkDevice);
    485 	}
    486 
    487 	// Create color image and view
    488 	{
    489 		const VkImageCreateInfo colorImageParams =
    490 		{
    491 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,										// VkStructureType			sType;
    492 			DE_NULL,																	// const void*				pNext;
    493 			0u,																			// VkImageCreateFlags		flags;
    494 			VK_IMAGE_TYPE_2D,															// VkImageType				imageType;
    495 			m_colorFormat,																// VkFormat					format;
    496 			{ (deUint32)m_renderSize.x(), (deUint32)m_renderSize.y(), 1u },				// VkExtent3D				extent;
    497 			1u,																			// deUint32					mipLevels;
    498 			1u,																			// deUint32					arrayLayers;
    499 			VK_SAMPLE_COUNT_1_BIT,														// VkSampleCountFlagBits	samples;
    500 			VK_IMAGE_TILING_OPTIMAL,													// VkImageTiling			tiling;
    501 			VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,		// VkImageUsageFlags		usage;
    502 			VK_SHARING_MODE_EXCLUSIVE,													// VkSharingMode			sharingMode;
    503 			1u,																			// deUint32					queueFamilyIndexCount;
    504 			&queueFamilyIndex,															// const deUint32*			pQueueFamilyIndices;
    505 			VK_IMAGE_LAYOUT_UNDEFINED													// VkImageLayout			initialLayout;
    506 		};
    507 
    508 		m_colorImage			= createImage(vk, vkDevice, &colorImageParams);
    509 		m_colorImageAlloc		= memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImage), MemoryRequirement::Any);
    510 		VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImage, m_colorImageAlloc->getMemory(), m_colorImageAlloc->getOffset()));
    511 
    512 		const VkImageViewCreateInfo colorAttachmentViewParams =
    513 		{
    514 			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,			// VkStructureType			sType;
    515 			DE_NULL,											// const void*				pNext;
    516 			0u,													// VkImageViewCreateFlags	flags;
    517 			*m_colorImage,										// VkImage					image;
    518 			VK_IMAGE_VIEW_TYPE_2D,								// VkImageViewType			viewType;
    519 			m_colorFormat,										// VkFormat					format;
    520 			componentMappingRGBA,								// VkComponentMapping		components;
    521 			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }		// VkImageSubresourceRange	subresourceRange;
    522 		};
    523 
    524 		m_colorAttachmentView = createImageView(vk, vkDevice, &colorAttachmentViewParams);
    525 	}
    526 
    527 	// Create render pass
    528 	{
    529 		const VkAttachmentDescription colorAttachmentDescription =
    530 		{
    531 			0u,													// VkAttachmentDescriptionFlags		flags;
    532 			m_colorFormat,										// VkFormat							format;
    533 			VK_SAMPLE_COUNT_1_BIT,								// VkSampleCountFlagBits			samples;
    534 			VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp				loadOp;
    535 			VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp				storeOp;
    536 			VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// VkAttachmentLoadOp				stencilLoadOp;
    537 			VK_ATTACHMENT_STORE_OP_DONT_CARE,					// VkAttachmentStoreOp				stencilStoreOp;
    538 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout					initialLayout;
    539 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout					finalLayout;
    540 		};
    541 
    542 		const VkAttachmentReference colorAttachmentReference =
    543 		{
    544 			0u,													// deUint32			attachment;
    545 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout	layout;
    546 		};
    547 
    548 		const VkSubpassDescription subpassDescription =
    549 		{
    550 			0u,													// VkSubpassDescriptionFlags	flags;
    551 			VK_PIPELINE_BIND_POINT_GRAPHICS,					// VkPipelineBindPoint			pipelineBindPoint;
    552 			0u,													// deUint32						inputAttachmentCount;
    553 			DE_NULL,											// const VkAttachmentReference*	pInputAttachments;
    554 			1u,													// deUint32						colorAttachmentCount;
    555 			&colorAttachmentReference,							// const VkAttachmentReference*	pColorAttachments;
    556 			DE_NULL,											// const VkAttachmentReference*	pResolveAttachments;
    557 			DE_NULL,											// const VkAttachmentReference*	pDepthStencilAttachment;
    558 			0u,													// deUint32						preserveAttachmentCount;
    559 			DE_NULL												// const VkAttachmentReference*	pPreserveAttachments;
    560 		};
    561 
    562 		const VkRenderPassCreateInfo renderPassParams =
    563 		{
    564 			VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,			// VkStructureType					sType;
    565 			DE_NULL,											// const void*						pNext;
    566 			0u,													// VkRenderPassCreateFlags			flags;
    567 			1u,													// deUint32							attachmentCount;
    568 			&colorAttachmentDescription,						// const VkAttachmentDescription*	pAttachments;
    569 			1u,													// deUint32							subpassCount;
    570 			&subpassDescription,								// const VkSubpassDescription*		pSubpasses;
    571 			0u,													// deUint32							dependencyCount;
    572 			DE_NULL												// const VkSubpassDependency*		pDependencies;
    573 		};
    574 
    575 		m_renderPass = createRenderPass(vk, vkDevice, &renderPassParams);
    576 	}
    577 
    578 	// Create framebuffer
    579 	{
    580 		const VkFramebufferCreateInfo framebufferParams =
    581 		{
    582 			VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,			// VkStructureType			sType;
    583 			DE_NULL,											// const void*				pNext;
    584 			0u,													// VkFramebufferCreateFlags	flags;
    585 			*m_renderPass,										// VkRenderPass				renderPass;
    586 			1u,													// deUint32					attachmentCount;
    587 			&m_colorAttachmentView.get(),						// const VkImageView*		pAttachments;
    588 			(deUint32)m_renderSize.x(),							// deUint32					width;
    589 			(deUint32)m_renderSize.y(),							// deUint32					height;
    590 			1u													// deUint32					layers;
    591 		};
    592 
    593 		m_framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
    594 	}
    595 
    596 	// Create pipeline layout
    597 	{
    598 		const VkPipelineLayoutCreateInfo pipelineLayoutParams =
    599 		{
    600 			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType				sType;
    601 			DE_NULL,											// const void*					pNext;
    602 			0u,													// VkPipelineLayoutCreateFlags	flags;
    603 			1u,													// deUint32						setLayoutCount;
    604 			&m_descriptorSetLayout.get(),						// const VkDescriptorSetLayout*	pSetLayouts;
    605 			0u,													// deUint32						pushConstantRangeCount;
    606 			DE_NULL												// const VkPushConstantRange*	pPushConstantRanges;
    607 		};
    608 
    609 		m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
    610 	}
    611 
    612 	m_vertexShaderModule	= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("tex_vert"), 0);
    613 	m_fragmentShaderModule	= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("tex_frag"), 0);
    614 
    615 	// Create pipeline
    616 	{
    617 		const VkPipelineShaderStageCreateInfo shaderStages[2] =
    618 		{
    619 			{
    620 				VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,		// VkStructureType						sType;
    621 				DE_NULL,													// const void*							pNext;
    622 				0u,															// VkPipelineShaderStageCreateFlags		flags;
    623 				VK_SHADER_STAGE_VERTEX_BIT,									// VkShaderStageFlagBits				stage;
    624 				*m_vertexShaderModule,										// VkShaderModule						module;
    625 				"main",														// const char*							pName;
    626 				DE_NULL														// const VkSpecializationInfo*			pSpecializationInfo;
    627 			},
    628 			{
    629 				VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,		// VkStructureType						sType;
    630 				DE_NULL,													// const void*							pNext;
    631 				0u,															// VkPipelineShaderStageCreateFlags		flags;
    632 				VK_SHADER_STAGE_FRAGMENT_BIT,								// VkShaderStageFlagBits				stage;
    633 				*m_fragmentShaderModule,									// VkShaderModule						module;
    634 				"main",														// const char*							pName;
    635 				DE_NULL														// const VkSpecializationInfo*			pSpecializationInfo;
    636 			}
    637 		};
    638 
    639 		const VkVertexInputBindingDescription vertexInputBindingDescription =
    640 		{
    641 			0u,									// deUint32					binding;
    642 			sizeof(Vertex4Tex4),				// deUint32					strideInBytes;
    643 			VK_VERTEX_INPUT_RATE_VERTEX			// VkVertexInputStepRate	inputRate;
    644 		};
    645 
    646 		const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] =
    647 		{
    648 			{
    649 				0u,										// deUint32	location;
    650 				0u,										// deUint32	binding;
    651 				VK_FORMAT_R32G32B32A32_SFLOAT,			// VkFormat	format;
    652 				0u										// deUint32	offset;
    653 			},
    654 			{
    655 				1u,										// deUint32	location;
    656 				0u,										// deUint32	binding;
    657 				VK_FORMAT_R32G32B32A32_SFLOAT,			// VkFormat	format;
    658 				DE_OFFSET_OF(Vertex4Tex4, texCoord),	// deUint32	offset;
    659 			}
    660 		};
    661 
    662 		const VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
    663 		{
    664 			VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType							sType;
    665 			DE_NULL,														// const void*								pNext;
    666 			0u,																// VkPipelineVertexInputStateCreateFlags	flags;
    667 			1u,																// deUint32									vertexBindingDescriptionCount;
    668 			&vertexInputBindingDescription,									// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
    669 			2u,																// deUint32									vertexAttributeDescriptionCount;
    670 			vertexInputAttributeDescriptions								// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
    671 		};
    672 
    673 		const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateParams =
    674 		{
    675 			VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	// VkStructureType							sType;
    676 			DE_NULL,														// const void*								pNext;
    677 			0u,																// VkPipelineInputAssemblyStateCreateFlags	flags;
    678 			VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,							// VkPrimitiveTopology						topology;
    679 			false															// VkBool32									primitiveRestartEnable;
    680 		};
    681 
    682 		const VkViewport viewport =
    683 		{
    684 			0.0f,						// float	x;
    685 			0.0f,						// float	y;
    686 			(float)m_renderSize.x(),	// float	width;
    687 			(float)m_renderSize.y(),	// float	height;
    688 			0.0f,						// float	minDepth;
    689 			1.0f						// float	maxDepth;
    690 		};
    691 
    692 		const VkRect2D scissor = { { 0, 0 }, { (deUint32)m_renderSize.x(), (deUint32)m_renderSize.y() } };
    693 
    694 		const VkPipelineViewportStateCreateInfo viewportStateParams =
    695 		{
    696 			VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,			// VkStructureType						sType;
    697 			DE_NULL,														// const void*							pNext;
    698 			0u,																// VkPipelineViewportStateCreateFlags	flags;
    699 			1u,																// deUint32								viewportCount;
    700 			&viewport,														// const VkViewport*					pViewports;
    701 			1u,																// deUint32								scissorCount;
    702 			&scissor														// const VkRect2D*						pScissors;
    703 		};
    704 
    705 		const VkPipelineRasterizationStateCreateInfo rasterStateParams =
    706 		{
    707 			VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,		// VkStructureType							sType;
    708 			DE_NULL,														// const void*								pNext;
    709 			0u,																// VkPipelineRasterizationStateCreateFlags	flags;
    710 			false,															// VkBool32									depthClampEnable;
    711 			false,															// VkBool32									rasterizerDiscardEnable;
    712 			VK_POLYGON_MODE_FILL,											// VkPolygonMode							polygonMode;
    713 			VK_CULL_MODE_NONE,												// VkCullModeFlags							cullMode;
    714 			VK_FRONT_FACE_COUNTER_CLOCKWISE,								// VkFrontFace								frontFace;
    715 			false,															// VkBool32									depthBiasEnable;
    716 			0.0f,															// float									depthBiasConstantFactor;
    717 			0.0f,															// float									depthBiasClamp;
    718 			0.0f,															// float									depthBiasSlopeFactor;
    719 			1.0f															// float									lineWidth;
    720 		};
    721 
    722 		const VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
    723 		{
    724 			false,														// VkBool32					blendEnable;
    725 			VK_BLEND_FACTOR_ONE,										// VkBlendFactor			srcColorBlendFactor;
    726 			VK_BLEND_FACTOR_ZERO,										// VkBlendFactor			dstColorBlendFactor;
    727 			VK_BLEND_OP_ADD,											// VkBlendOp				colorBlendOp;
    728 			VK_BLEND_FACTOR_ONE,										// VkBlendFactor			srcAlphaBlendFactor;
    729 			VK_BLEND_FACTOR_ZERO,										// VkBlendFactor			dstAlphaBlendFactor;
    730 			VK_BLEND_OP_ADD,											// VkBlendOp				alphaBlendOp;
    731 			VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |		// VkColorComponentFlags	colorWriteMask;
    732 				VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT
    733 		};
    734 
    735 		const VkPipelineColorBlendStateCreateInfo colorBlendStateParams =
    736 		{
    737 			VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType;
    738 			DE_NULL,													// const void*									pNext;
    739 			0u,															// VkPipelineColorBlendStateCreateFlags			flags;
    740 			false,														// VkBool32										logicOpEnable;
    741 			VK_LOGIC_OP_COPY,											// VkLogicOp									logicOp;
    742 			1u,															// deUint32										attachmentCount;
    743 			&colorBlendAttachmentState,									// const VkPipelineColorBlendAttachmentState*	pAttachments;
    744 			{ 0.0f, 0.0f, 0.0f, 0.0f }									// float										blendConstants[4];
    745 		};
    746 
    747 		const VkPipelineMultisampleStateCreateInfo multisampleStateParams =
    748 		{
    749 			VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType;
    750 			DE_NULL,													// const void*								pNext;
    751 			0u,															// VkPipelineMultisampleStateCreateFlags	flags;
    752 			VK_SAMPLE_COUNT_1_BIT,										// VkSampleCountFlagBits					rasterizationSamples;
    753 			false,														// VkBool32									sampleShadingEnable;
    754 			0.0f,														// float									minSampleShading;
    755 			DE_NULL,													// const VkSampleMask*						pSampleMask;
    756 			false,														// VkBool32									alphaToCoverageEnable;
    757 			false														// VkBool32									alphaToOneEnable;
    758 		};
    759 
    760 		VkPipelineDepthStencilStateCreateInfo depthStencilStateParams =
    761 		{
    762 			VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,	// VkStructureType							sType;
    763 			DE_NULL,													// const void*								pNext;
    764 			0u,															// VkPipelineDepthStencilStateCreateFlags	flags;
    765 			false,														// VkBool32									depthTestEnable;
    766 			false,														// VkBool32									depthWriteEnable;
    767 			VK_COMPARE_OP_LESS,											// VkCompareOp								depthCompareOp;
    768 			false,														// VkBool32									depthBoundsTestEnable;
    769 			false,														// VkBool32									stencilTestEnable;
    770 			{															// VkStencilOpState							front;
    771 				VK_STENCIL_OP_ZERO,		// VkStencilOp	failOp;
    772 				VK_STENCIL_OP_ZERO,		// VkStencilOp	passOp;
    773 				VK_STENCIL_OP_ZERO,		// VkStencilOp	depthFailOp;
    774 				VK_COMPARE_OP_NEVER,	// VkCompareOp	compareOp;
    775 				0u,						// deUint32		compareMask;
    776 				0u,						// deUint32		writeMask;
    777 				0u						// deUint32		reference;
    778 			},
    779 			{															// VkStencilOpState	back;
    780 				VK_STENCIL_OP_ZERO,		// VkStencilOp	failOp;
    781 				VK_STENCIL_OP_ZERO,		// VkStencilOp	passOp;
    782 				VK_STENCIL_OP_ZERO,		// VkStencilOp	depthFailOp;
    783 				VK_COMPARE_OP_NEVER,	// VkCompareOp	compareOp;
    784 				0u,						// deUint32		compareMask;
    785 				0u,						// deUint32		writeMask;
    786 				0u						// deUint32		reference;
    787 			},
    788 			0.0f,														// float			minDepthBounds;
    789 			1.0f														// float			maxDepthBounds;
    790 		};
    791 
    792 		const VkGraphicsPipelineCreateInfo graphicsPipelineParams =
    793 		{
    794 			VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,	// VkStructureType									sType;
    795 			DE_NULL,											// const void*										pNext;
    796 			0u,													// VkPipelineCreateFlags							flags;
    797 			2u,													// deUint32											stageCount;
    798 			shaderStages,										// const VkPipelineShaderStageCreateInfo*			pStages;
    799 			&vertexInputStateParams,							// const VkPipelineVertexInputStateCreateInfo*		pVertexInputState;
    800 			&inputAssemblyStateParams,							// const VkPipelineInputAssemblyStateCreateInfo*	pInputAssemblyState;
    801 			DE_NULL,											// const VkPipelineTessellationStateCreateInfo*		pTessellationState;
    802 			&viewportStateParams,								// const VkPipelineViewportStateCreateInfo*			pViewportState;
    803 			&rasterStateParams,									// const VkPipelineRasterizationStateCreateInfo*	pRasterizationState;
    804 			&multisampleStateParams,							// const VkPipelineMultisampleStateCreateInfo*		pMultisampleState;
    805 			&depthStencilStateParams,							// const VkPipelineDepthStencilStateCreateInfo*		pDepthStencilState;
    806 			&colorBlendStateParams,								// const VkPipelineColorBlendStateCreateInfo*		pColorBlendState;
    807 			(const VkPipelineDynamicStateCreateInfo*)DE_NULL,	// const VkPipelineDynamicStateCreateInfo*			pDynamicState;
    808 			*m_pipelineLayout,									// VkPipelineLayout									layout;
    809 			*m_renderPass,										// VkRenderPass										renderPass;
    810 			0u,													// deUint32											subpass;
    811 			0u,													// VkPipeline										basePipelineHandle;
    812 			0u													// deInt32											basePipelineIndex;
    813 		};
    814 
    815 		m_graphicsPipeline	= createGraphicsPipeline(vk, vkDevice, DE_NULL, &graphicsPipelineParams);
    816 	}
    817 
    818 	// Create vertex buffer
    819 	{
    820 		const VkDeviceSize			vertexBufferSize	= (VkDeviceSize)(m_vertices.size() * sizeof(Vertex4Tex4));
    821 		const VkBufferCreateInfo	vertexBufferParams	=
    822 		{
    823 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
    824 			DE_NULL,									// const void*			pNext;
    825 			0u,											// VkBufferCreateFlags	flags;
    826 			vertexBufferSize,							// VkDeviceSize			size;
    827 			VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,			// VkBufferUsageFlags	usage;
    828 			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
    829 			1u,											// deUint32				queueFamilyIndexCount;
    830 			&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
    831 		};
    832 
    833 		DE_ASSERT(vertexBufferSize > 0);
    834 
    835 		m_vertexBuffer		= createBuffer(vk, vkDevice, &vertexBufferParams);
    836 		m_vertexBufferAlloc	= memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_vertexBuffer), MemoryRequirement::HostVisible);
    837 
    838 		VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset()));
    839 
    840 		// Load vertices into vertex buffer
    841 		deMemcpy(m_vertexBufferAlloc->getHostPtr(), &m_vertices[0], (size_t)vertexBufferSize);
    842 		flushMappedMemoryRange(vk, vkDevice, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset(), vertexBufferParams.size);
    843 	}
    844 
    845 	// Create command pool
    846 	{
    847 		const VkCommandPoolCreateInfo cmdPoolParams =
    848 		{
    849 			VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,		// VkStructureType				sType;
    850 			DE_NULL,										// const void*					pNext;
    851 			VK_COMMAND_POOL_CREATE_TRANSIENT_BIT,			// VkCommandPoolCreateFlags	flags;
    852 			queueFamilyIndex								// deUint32					queueFamilyIndex;
    853 		};
    854 
    855 		m_cmdPool = createCommandPool(vk, vkDevice, &cmdPoolParams);
    856 	}
    857 
    858 	// Create command buffer
    859 	{
    860 		const VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
    861 		{
    862 			VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,	// VkStructureType			sType;
    863 			DE_NULL,										// const void*				pNext;
    864 			*m_cmdPool,										// VkCommandPool			commandPool;
    865 			VK_COMMAND_BUFFER_LEVEL_PRIMARY,				// VkCommandBufferLevel		level;
    866 			1u,												// deUint32					bufferCount;
    867 		};
    868 
    869 		const VkCommandBufferBeginInfo cmdBufferBeginInfo =
    870 		{
    871 			VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,	// VkStructureType					sType;
    872 			DE_NULL,										// const void*						pNext;
    873 			0u,												// VkCommandBufferUsageFlags		flags;
    874 			(const VkCommandBufferInheritanceInfo*)DE_NULL,
    875 		};
    876 
    877 		const VkClearValue attachmentClearValue = defaultClearValue(m_colorFormat);
    878 
    879 		const VkRenderPassBeginInfo renderPassBeginInfo =
    880 		{
    881 			VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,				// VkStructureType		sType;
    882 			DE_NULL,												// const void*			pNext;
    883 			*m_renderPass,											// VkRenderPass			renderPass;
    884 			*m_framebuffer,											// VkFramebuffer		framebuffer;
    885 			{
    886 				{ 0, 0 },
    887 				{ (deUint32)m_renderSize.x(), (deUint32)m_renderSize.y() }
    888 			},														// VkRect2D				renderArea;
    889 			1,														// deUint32				clearValueCount;
    890 			&attachmentClearValue									// const VkClearValue*	pClearValues;
    891 		};
    892 
    893 		const VkImageMemoryBarrier preAttachmentBarrier =
    894 		{
    895 			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType			sType;
    896 			DE_NULL,										// const void*				pNext;
    897 			0u,												// VkAccessFlags			srcAccessMask;
    898 			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,			// VkAccessFlags			dstAccessMask;
    899 			VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout			oldLayout;
    900 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,		// VkImageLayout			newLayout;
    901 			VK_QUEUE_FAMILY_IGNORED,						// deUint32					srcQueueFamilyIndex;
    902 			VK_QUEUE_FAMILY_IGNORED,						// deUint32					dstQueueFamilyIndex;
    903 			*m_colorImage,									// VkImage					image;
    904 			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }	// VkImageSubresourceRange	subresourceRange;
    905 		};
    906 
    907 		m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, &cmdBufferAllocateInfo);
    908 
    909 		VK_CHECK(vk.beginCommandBuffer(*m_cmdBuffer, &cmdBufferBeginInfo));
    910 
    911 		vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, (VkDependencyFlags)0,
    912 			0u, DE_NULL, 0u, DE_NULL, 1u, &preAttachmentBarrier);
    913 
    914 		vk.cmdBeginRenderPass(*m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
    915 
    916 		vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipeline);
    917 
    918 		vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0, 1, &m_descriptorSet.get(), 0, DE_NULL);
    919 
    920 		const VkDeviceSize vertexBufferOffset = 0;
    921 		vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
    922 		vk.cmdDraw(*m_cmdBuffer, (deUint32)m_vertices.size(), 1, 0, 0);
    923 
    924 		vk.cmdEndRenderPass(*m_cmdBuffer);
    925 		VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer));
    926 	}
    927 
    928 	// Create fence
    929 	{
    930 		const VkFenceCreateInfo fenceParams =
    931 		{
    932 			VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,	// VkStructureType		sType;
    933 			DE_NULL,								// const void*			pNext;
    934 			0u										// VkFenceCreateFlags	flags;
    935 		};
    936 
    937 		m_fence = createFence(vk, vkDevice, &fenceParams);
    938 	}
    939 }
    940 
    941 ImageSamplingInstance::~ImageSamplingInstance (void)
    942 {
    943 }
    944 
    945 tcu::TestStatus ImageSamplingInstance::iterate (void)
    946 {
    947 	const DeviceInterface&		vk			= m_context.getDeviceInterface();
    948 	const VkDevice				vkDevice	= m_context.getDevice();
    949 	const VkQueue				queue		= m_context.getUniversalQueue();
    950 	const VkSubmitInfo			submitInfo	=
    951 	{
    952 		VK_STRUCTURE_TYPE_SUBMIT_INFO,	// VkStructureType			sType;
    953 		DE_NULL,						// const void*				pNext;
    954 		0u,								// deUint32					waitSemaphoreCount;
    955 		DE_NULL,						// const VkSemaphore*		pWaitSemaphores;
    956 		DE_NULL,
    957 		1u,								// deUint32					commandBufferCount;
    958 		&m_cmdBuffer.get(),				// const VkCommandBuffer*	pCommandBuffers;
    959 		0u,								// deUint32					signalSemaphoreCount;
    960 		DE_NULL							// const VkSemaphore*		pSignalSemaphores;
    961 	};
    962 
    963 	VK_CHECK(vk.resetFences(vkDevice, 1, &m_fence.get()));
    964 	VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *m_fence));
    965 	VK_CHECK(vk.waitForFences(vkDevice, 1, &m_fence.get(), true, ~(0ull) /* infinity */));
    966 
    967 	return verifyImage();
    968 }
    969 
    970 tcu::TestStatus ImageSamplingInstance::verifyImage (void)
    971 {
    972 	const tcu::TextureFormat		colorFormat				= mapVkFormat(m_colorFormat);
    973 	const tcu::TextureFormat		depthStencilFormat		= tcu::TextureFormat(); // Undefined depth/stencil format.
    974 	const tcu::Sampler				sampler					= mapVkSampler(m_samplerParams);
    975 	const tcu::UVec4				componentMapping		= mapVkComponentMapping(m_componentMapping);
    976 	float							samplerLod;
    977 	bool							compareOk;
    978 	MovePtr<Program>				program;
    979 	MovePtr<ReferenceRenderer>		refRenderer;
    980 
    981 	// Set up LOD of reference sampler
    982 	samplerLod = de::max(m_samplerParams.minLod, de::min(m_samplerParams.maxLod, m_samplerParams.mipLodBias + m_samplerLod));
    983 
    984 	// Create reference program that uses image subresource range
    985 	program = createRefProgram(colorFormat, sampler, samplerLod, componentMapping, *m_texture, m_imageViewType, m_layerCount, m_subresourceRange);
    986 	const rr::Program referenceProgram = program->getReferenceProgram();
    987 
    988 	// Render reference image
    989 	refRenderer = MovePtr<ReferenceRenderer>(new ReferenceRenderer(m_renderSize.x(), m_renderSize.y(), 1, colorFormat, depthStencilFormat, &referenceProgram));
    990 	const rr::RenderState renderState(refRenderer->getViewportState());
    991 	refRenderer->draw(renderState, rr::PRIMITIVETYPE_TRIANGLES, m_vertices);
    992 
    993 	// Compare result with reference image
    994 	{
    995 		const DeviceInterface&		vk							= m_context.getDeviceInterface();
    996 		const VkDevice				vkDevice					= m_context.getDevice();
    997 		const VkQueue				queue						= m_context.getUniversalQueue();
    998 		const deUint32				queueFamilyIndex			= m_context.getUniversalQueueFamilyIndex();
    999 		SimpleAllocator				memAlloc					(vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
   1000 		MovePtr<tcu::TextureLevel>	result						= readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, memAlloc, *m_colorImage, m_colorFormat, m_renderSize);
   1001 		tcu::UVec4					threshold					= tcu::UVec4(4, 4, 4, 4);
   1002 
   1003 		if ((m_imageFormat == vk::VK_FORMAT_EAC_R11G11_SNORM_BLOCK) || (m_imageFormat == vk::VK_FORMAT_EAC_R11_SNORM_BLOCK))
   1004 			threshold = tcu::UVec4(8, 8, 8, 8);
   1005 
   1006 		compareOk = tcu::intThresholdPositionDeviationCompare(m_context.getTestContext().getLog(),
   1007 															  "IntImageCompare",
   1008 															  "Image comparison",
   1009 															  refRenderer->getAccess(),
   1010 															  result->getAccess(),
   1011 															  threshold,
   1012 															  tcu::IVec3(1, 1, 0),
   1013 															  true,
   1014 															  tcu::COMPARE_LOG_RESULT);
   1015 	}
   1016 
   1017 	if (compareOk)
   1018 		return tcu::TestStatus::pass("Result image matches reference");
   1019 	else
   1020 		return tcu::TestStatus::fail("Image mismatch");
   1021 }
   1022 
   1023 } // pipeline
   1024 } // vkt
   1025