Home | History | Annotate | Download | only in draw
      1 /*------------------------------------------------------------------------
      2  * Vulkan Conformance Tests
      3  * ------------------------
      4  *
      5  * Copyright (c) 2015 The Khronos Group Inc.
      6  * Copyright (c) 2015 Intel Corporation
      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 Object Util
     23  *//*--------------------------------------------------------------------*/
     24 
     25 #include "vktDrawImageObjectUtil.hpp"
     26 
     27 #include "tcuSurface.hpp"
     28 #include "tcuVectorUtil.hpp"
     29 
     30 #include "vkRefUtil.hpp"
     31 #include "vkQueryUtil.hpp"
     32 #include "vkImageUtil.hpp"
     33 #include "vktDrawCreateInfoUtil.hpp"
     34 #include "vktDrawBufferObjectUtil.hpp"
     35 
     36 #include "tcuTextureUtil.hpp"
     37 
     38 namespace vkt
     39 {
     40 namespace Draw
     41 {
     42 
     43 void MemoryOp::pack (int				pixelSize,
     44 					 int				width,
     45 					 int				height,
     46 					 int				depth,
     47 					 vk::VkDeviceSize	rowPitchOrZero,
     48 					 vk::VkDeviceSize	depthPitchOrZero,
     49 					 const void *		srcBuffer,
     50 					 void *				destBuffer)
     51 {
     52 	vk::VkDeviceSize rowPitch	= rowPitchOrZero;
     53 	vk::VkDeviceSize depthPitch	= depthPitchOrZero;
     54 
     55 	if (rowPitch == 0)
     56 		rowPitch = width * pixelSize;
     57 
     58 	if (depthPitch == 0)
     59 		depthPitch = rowPitch * height;
     60 
     61 	const vk::VkDeviceSize size = depthPitch * depth;
     62 
     63 	const deUint8 *srcRow = reinterpret_cast<const deUint8 *>(srcBuffer);
     64 	const deUint8 *srcStart;
     65 	srcStart = srcRow;
     66 	deUint8 *dstRow = reinterpret_cast<deUint8 *>(destBuffer);
     67 	deUint8 *dstStart;
     68 	dstStart = dstRow;
     69 
     70 	if (rowPitch == static_cast<vk::VkDeviceSize>(width * pixelSize) &&
     71 		depthPitch == static_cast<vk::VkDeviceSize>(rowPitch * height))
     72 	{
     73 		// fast path
     74 		deMemcpy(dstRow, srcRow, static_cast<size_t>(size));
     75 	}
     76 	else
     77 	{
     78 		// slower, per row path
     79 		for (int d = 0; d < depth; d++)
     80 		{
     81 			vk::VkDeviceSize offsetDepthDst = d * depthPitch;
     82 			vk::VkDeviceSize offsetDepthSrc = d * (pixelSize * width * height);
     83 			srcRow = srcStart + offsetDepthSrc;
     84 			dstRow = dstStart + offsetDepthDst;
     85 			for (int r = 0; r < height; ++r)
     86 			{
     87 				deMemcpy(dstRow, srcRow, static_cast<size_t>(rowPitch));
     88 				srcRow += pixelSize * width;
     89 				dstRow += rowPitch;
     90 			}
     91 		}
     92 	}
     93 }
     94 
     95 void MemoryOp::unpack (int					pixelSize,
     96 					   int					width,
     97 					   int					height,
     98 					   int					depth,
     99 					   vk::VkDeviceSize		rowPitchOrZero,
    100 					   vk::VkDeviceSize		depthPitchOrZero,
    101 					   const void *			srcBuffer,
    102 					   void *				destBuffer)
    103 {
    104 	vk::VkDeviceSize rowPitch	= rowPitchOrZero;
    105 	vk::VkDeviceSize depthPitch = depthPitchOrZero;
    106 
    107 	if (rowPitch == 0)
    108 		rowPitch = width * pixelSize;
    109 
    110 	if (depthPitch == 0)
    111 		depthPitch = rowPitch * height;
    112 
    113 	const vk::VkDeviceSize size = depthPitch * depth;
    114 
    115 	const deUint8 *srcRow = reinterpret_cast<const deUint8 *>(srcBuffer);
    116 	const deUint8 *srcStart;
    117 	srcStart = srcRow;
    118 	deUint8 *dstRow = reinterpret_cast<deUint8 *>(destBuffer);
    119 	deUint8 *dstStart;
    120 	dstStart = dstRow;
    121 
    122 	if (rowPitch == static_cast<vk::VkDeviceSize>(width * pixelSize) &&
    123 		depthPitch == static_cast<vk::VkDeviceSize>(rowPitch * height))
    124 	{
    125 		// fast path
    126 		deMemcpy(dstRow, srcRow, static_cast<size_t>(size));
    127 	}
    128 	else {
    129 		// slower, per row path
    130 		for (size_t d = 0; d < (size_t)depth; d++)
    131 		{
    132 			vk::VkDeviceSize offsetDepthDst = d * (pixelSize * width * height);
    133 			vk::VkDeviceSize offsetDepthSrc = d * depthPitch;
    134 			srcRow = srcStart + offsetDepthSrc;
    135 			dstRow = dstStart + offsetDepthDst;
    136 			for (int r = 0; r < height; ++r)
    137 			{
    138 				deMemcpy(dstRow, srcRow, static_cast<size_t>(pixelSize * width));
    139 				srcRow += rowPitch;
    140 				dstRow += pixelSize * width;
    141 			}
    142 		}
    143 	}
    144 }
    145 
    146 Image::Image (const vk::DeviceInterface& vk,
    147 			  vk::VkDevice				device,
    148 			  vk::VkFormat				format,
    149 			  const vk::VkExtent3D&		extend,
    150 			  deUint32					levelCount,
    151 			  deUint32					layerCount,
    152 			  vk::Move<vk::VkImage>		object_)
    153 	: m_allocation		(DE_NULL)
    154 	, m_object			(object_)
    155 	, m_format			(format)
    156 	, m_extent			(extend)
    157 	, m_levelCount		(levelCount)
    158 	, m_layerCount		(layerCount)
    159 	, m_vk(vk)
    160 	, m_device(device)
    161 {
    162 }
    163 
    164 tcu::ConstPixelBufferAccess Image::readSurface (vk::VkQueue					queue,
    165 												vk::Allocator&				allocator,
    166 												vk::VkImageLayout			layout,
    167 												vk::VkOffset3D				offset,
    168 												int							width,
    169 												int							height,
    170 												vk::VkImageAspectFlagBits	aspect,
    171 												unsigned int				mipLevel,
    172 												unsigned int				arrayElement)
    173 {
    174 	m_pixelAccessData.resize(width * height * vk::mapVkFormat(m_format).getPixelSize());
    175 	deMemset(m_pixelAccessData.data(), 0, m_pixelAccessData.size());
    176 	if (aspect == vk::VK_IMAGE_ASPECT_COLOR_BIT)
    177 	{
    178 		read(queue, allocator, layout, offset, width, height, 1, mipLevel, arrayElement, aspect, vk::VK_IMAGE_TYPE_2D,
    179 		m_pixelAccessData.data());
    180 	}
    181 	if (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT || aspect == vk::VK_IMAGE_ASPECT_STENCIL_BIT)
    182 	{
    183 		readUsingBuffer(queue, allocator, layout, offset, width, height, 1, mipLevel, arrayElement, aspect, m_pixelAccessData.data());
    184 	}
    185 	return tcu::ConstPixelBufferAccess(vk::mapVkFormat(m_format), width, height, 1, m_pixelAccessData.data());
    186 }
    187 
    188 tcu::ConstPixelBufferAccess Image::readVolume (vk::VkQueue					queue,
    189 											   vk::Allocator&				allocator,
    190 											   vk::VkImageLayout			layout,
    191 											   vk::VkOffset3D				offset,
    192 											   int							width,
    193 											   int							height,
    194 											   int							depth,
    195 											   vk::VkImageAspectFlagBits	aspect,
    196 											   unsigned int					mipLevel,
    197 											   unsigned int					arrayElement)
    198 {
    199 	m_pixelAccessData.resize(width * height * depth * vk::mapVkFormat(m_format).getPixelSize());
    200 	deMemset(m_pixelAccessData.data(), 0, m_pixelAccessData.size());
    201 	if (aspect == vk::VK_IMAGE_ASPECT_COLOR_BIT)
    202 	{
    203 		read(queue, allocator, layout, offset, width, height, depth, mipLevel, arrayElement, aspect, vk::VK_IMAGE_TYPE_3D,
    204 		m_pixelAccessData.data());
    205 	}
    206 	if (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT || aspect == vk::VK_IMAGE_ASPECT_STENCIL_BIT)
    207 	{
    208 		readUsingBuffer(queue, allocator, layout, offset, width, height, depth, mipLevel, arrayElement, aspect, m_pixelAccessData.data());
    209 	}
    210 	return tcu::ConstPixelBufferAccess(vk::mapVkFormat(m_format), width, height, depth, m_pixelAccessData.data());
    211 }
    212 
    213 tcu::ConstPixelBufferAccess Image::readSurface1D(vk::VkQueue				queue,
    214 												 vk::Allocator&				allocator,
    215 												 vk::VkImageLayout			layout,
    216 												 vk::VkOffset3D				offset,
    217 												 int						width,
    218 												 vk::VkImageAspectFlagBits	aspect,
    219 												 unsigned int				mipLevel,
    220 												 unsigned int				arrayElement)
    221 {
    222 	m_pixelAccessData.resize(width * vk::mapVkFormat(m_format).getPixelSize());
    223 	deMemset(m_pixelAccessData.data(), 0, m_pixelAccessData.size());
    224 	if (aspect == vk::VK_IMAGE_ASPECT_COLOR_BIT)
    225 	{
    226 		read(queue, allocator, layout, offset, width, 1, 1, mipLevel, arrayElement, aspect, vk::VK_IMAGE_TYPE_1D,
    227 		m_pixelAccessData.data());
    228 	}
    229 	if (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT || aspect == vk::VK_IMAGE_ASPECT_STENCIL_BIT)
    230 	{
    231 		readUsingBuffer(queue, allocator, layout, offset, width, 1, 1, mipLevel, arrayElement, aspect,
    232 		m_pixelAccessData.data());
    233 	}
    234 	return tcu::ConstPixelBufferAccess(vk::mapVkFormat(m_format), width, 1, 1, m_pixelAccessData.data());
    235 }
    236 
    237 void Image::read (vk::VkQueue					queue,
    238 				  vk::Allocator&				allocator,
    239 				  vk::VkImageLayout				layout,
    240 				  vk::VkOffset3D				offset,
    241 				  int							width,
    242 				  int							height,
    243 				  int							depth,
    244 				  unsigned int					mipLevel,
    245 				  unsigned int					arrayElement,
    246 				  vk::VkImageAspectFlagBits		aspect,
    247 				  vk::VkImageType				type,
    248 				  void *						data)
    249 {
    250 	DE_ASSERT(layout == vk::VK_IMAGE_LAYOUT_GENERAL || layout == vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
    251 
    252 	de::SharedPtr<Image> stagingResource = copyToLinearImage(queue, allocator, layout, offset, width,
    253 															 height, depth, mipLevel, arrayElement, aspect, type);
    254 	const vk::VkOffset3D zeroOffset = {0, 0, 0};
    255 	stagingResource->readLinear(zeroOffset, width, height, depth, 0, 0, aspect, data);
    256 }
    257 
    258 void Image::readUsingBuffer (vk::VkQueue				queue,
    259 							 vk::Allocator&				allocator,
    260 							 vk::VkImageLayout			layout,
    261 							 vk::VkOffset3D				offset,
    262 							 int						width,
    263 							 int						height,
    264 							 int						depth,
    265 							 unsigned int				mipLevel,
    266 							 unsigned int				arrayElement,
    267 							 vk::VkImageAspectFlagBits	aspect,
    268 							 void *						data)
    269 {
    270 	DE_ASSERT(layout == vk::VK_IMAGE_LAYOUT_GENERAL || layout == vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);;
    271 
    272 	de::SharedPtr<Buffer> stagingResource;
    273 
    274 	bool isCombinedType = isCombinedDepthStencilType(vk::mapVkFormat(m_format).type);
    275 	vk::VkDeviceSize bufferSize = 0;
    276 
    277 	if (!isCombinedType)
    278 		bufferSize = vk::mapVkFormat(m_format).getPixelSize() * width * height * depth;
    279 
    280 	if (isCombinedType)
    281 	{
    282 		int pixelSize = 0;
    283 		switch (m_format)
    284 		{
    285 			case vk::VK_FORMAT_D16_UNORM_S8_UINT:
    286 				pixelSize = (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT) ? 2 : 1;
    287 				break;
    288 			case  vk::VK_FORMAT_D32_SFLOAT_S8_UINT:
    289 				pixelSize = (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT) ? 4 : 1;
    290 				break;
    291 			case vk::VK_FORMAT_X8_D24_UNORM_PACK32:
    292 			case vk::VK_FORMAT_D24_UNORM_S8_UINT:
    293 				pixelSize = (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT) ? 3 : 1;
    294 				break;
    295 
    296 			default:
    297 				DE_FATAL("Not implemented");
    298 		}
    299 		bufferSize = pixelSize*width*height*depth;
    300 	}
    301 
    302 	BufferCreateInfo stagingBufferResourceCreateInfo(bufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT | vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
    303 	stagingResource = Buffer::createAndAlloc(m_vk, m_device, stagingBufferResourceCreateInfo, allocator, vk::MemoryRequirement::HostVisible);
    304 
    305 	{
    306 		//todo [scygan] get proper queueFamilyIndex
    307 		CmdPoolCreateInfo copyCmdPoolCreateInfo(0);
    308 		vk::Unique<vk::VkCommandPool> copyCmdPool(vk::createCommandPool(m_vk, m_device, &copyCmdPoolCreateInfo));
    309 
    310 		const vk::VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
    311 		{
    312 			vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,	// VkStructureType			sType;
    313 			DE_NULL,											// const void*				pNext;
    314 			*copyCmdPool,										// VkCommandPool			commandPool;
    315 			vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY,				// VkCommandBufferLevel		level;
    316 			1u,													// deUint32					bufferCount;
    317 		};
    318 		vk::Unique<vk::VkCommandBuffer> copyCmdBuffer(vk::allocateCommandBuffer(m_vk, m_device, &cmdBufferAllocateInfo));
    319 
    320 		CmdBufferBeginInfo beginInfo;
    321 		VK_CHECK(m_vk.beginCommandBuffer(*copyCmdBuffer, &beginInfo));
    322 
    323 		if (layout == vk::VK_IMAGE_LAYOUT_UNDEFINED)
    324 		{
    325 			layout = vk::VK_IMAGE_LAYOUT_GENERAL;
    326 
    327 			vk::VkImageMemoryBarrier barrier;
    328 			barrier.sType = vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
    329 			barrier.pNext = DE_NULL;
    330 			barrier.srcAccessMask = 0;
    331 			barrier.dstAccessMask = 0;
    332 			barrier.oldLayout = vk::VK_IMAGE_LAYOUT_UNDEFINED;
    333 			barrier.newLayout = vk::VK_IMAGE_LAYOUT_GENERAL;
    334 			barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
    335 			barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
    336 			barrier.image = object();
    337 
    338 			barrier.subresourceRange.aspectMask = aspect;
    339 			barrier.subresourceRange.baseMipLevel = 0;
    340 			barrier.subresourceRange.levelCount = m_levelCount;
    341 			barrier.subresourceRange.baseArrayLayer = 0;
    342 			barrier.subresourceRange.layerCount = m_layerCount;
    343 
    344 			m_vk.cmdPipelineBarrier(*copyCmdBuffer, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (vk::VkDependencyFlags)0,
    345 									0, (const vk::VkMemoryBarrier*)DE_NULL,
    346 									0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
    347 									1, &barrier);
    348 		}
    349 
    350 		vk::VkBufferImageCopy region =
    351 		{
    352 			0, 0, 0,
    353 			{ (vk::VkImageAspectFlags)aspect, mipLevel, arrayElement, 1 },
    354 			offset,
    355 			{ (deUint32)width, (deUint32)height, (deUint32)depth }
    356 		};
    357 
    358 		m_vk.cmdCopyImageToBuffer(*copyCmdBuffer, object(), layout, stagingResource->object(), 1, &region);
    359 		VK_CHECK(m_vk.endCommandBuffer(*copyCmdBuffer));
    360 
    361 		vk::VkSubmitInfo submitInfo =
    362 		{
    363 			vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,	// VkStructureType			sType;
    364 			DE_NULL,							// const void*				pNext;
    365 			0,									// deUint32					waitSemaphoreCount;
    366 			DE_NULL,							// const VkSemaphore*		pWaitSemaphores;
    367 			(const vk::VkPipelineStageFlags*)DE_NULL,
    368 			1,									// deUint32					commandBufferCount;
    369 			&copyCmdBuffer.get(),				// const VkCommandBuffer*	pCommandBuffers;
    370 			0,									// deUint32					signalSemaphoreCount;
    371 			DE_NULL								// const VkSemaphore*		pSignalSemaphores;
    372 		};
    373 		m_vk.queueSubmit(queue, 1, &submitInfo, DE_NULL);
    374 
    375 		// TODO: make this less intrusive
    376 		VK_CHECK(m_vk.queueWaitIdle(queue));
    377 	}
    378 
    379 	deUint8* destPtr = reinterpret_cast<deUint8*>(stagingResource->getBoundMemory().getHostPtr());
    380 	deMemcpy(data, destPtr, static_cast<size_t>(bufferSize));
    381 }
    382 
    383 tcu::ConstPixelBufferAccess Image::readSurfaceLinear (vk::VkOffset3D				offset,
    384 													  int							width,
    385 													  int							height,
    386 													  int							depth,
    387 													  vk::VkImageAspectFlagBits		aspect,
    388 													  unsigned int					mipLevel,
    389 													  unsigned int					arrayElement)
    390 {
    391 	m_pixelAccessData.resize(width * height * vk::mapVkFormat(m_format).getPixelSize());
    392 	readLinear(offset, width, height, depth, mipLevel, arrayElement, aspect, m_pixelAccessData.data());
    393 	return tcu::ConstPixelBufferAccess(vk::mapVkFormat(m_format), width, height, 1, m_pixelAccessData.data());
    394 }
    395 
    396 void Image::readLinear (vk::VkOffset3D				offset,
    397 						int							width,
    398 						int							height,
    399 						int							depth,
    400 						unsigned int				mipLevel,
    401 						unsigned int				arrayElement,
    402 						vk::VkImageAspectFlagBits	aspect,
    403 						void *						data)
    404 {
    405 	vk::VkImageSubresource imageSubResource = { (vk::VkImageAspectFlags)aspect, mipLevel, arrayElement };
    406 
    407 	vk::VkSubresourceLayout imageLayout;
    408 	deMemset(&imageLayout, 0, sizeof(imageLayout));
    409 
    410 	m_vk.getImageSubresourceLayout(m_device, object(), &imageSubResource, &imageLayout);
    411 
    412 	const deUint8* srcPtr = reinterpret_cast<const deUint8*>(getBoundMemory().getHostPtr());
    413 	srcPtr += imageLayout.offset + getPixelOffset(offset, imageLayout.rowPitch, imageLayout.depthPitch, mipLevel, arrayElement);
    414 
    415 	MemoryOp::unpack(vk::mapVkFormat(m_format).getPixelSize(), width, height, depth,
    416 		imageLayout.rowPitch, imageLayout.depthPitch, srcPtr, data);
    417 }
    418 
    419 de::SharedPtr<Image> Image::copyToLinearImage (vk::VkQueue					queue,
    420 											   vk::Allocator&				allocator,
    421 											   vk::VkImageLayout			layout,
    422 											   vk::VkOffset3D				offset,
    423 											   int							width,
    424 											   int							height,
    425 											   int							depth,
    426 											   unsigned int					mipLevel,
    427 											   unsigned int					arrayElement,
    428 											   vk::VkImageAspectFlagBits	aspect,
    429 											   vk::VkImageType				type)
    430 {
    431 	de::SharedPtr<Image> stagingResource;
    432 	{
    433 		vk::VkExtent3D stagingExtent = {(deUint32)width, (deUint32)height, (deUint32)depth};
    434 		ImageCreateInfo stagingResourceCreateInfo(type, m_format, stagingExtent, 1, 1, vk::VK_SAMPLE_COUNT_1_BIT,
    435 												  vk::VK_IMAGE_TILING_LINEAR, vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT);
    436 
    437 		stagingResource = Image::createAndAlloc(m_vk, m_device, stagingResourceCreateInfo, allocator,
    438 												vk::MemoryRequirement::HostVisible);
    439 
    440 		//todo [scygan] get proper queueFamilyIndex
    441 		CmdPoolCreateInfo copyCmdPoolCreateInfo(0);
    442 		vk::Unique<vk::VkCommandPool> copyCmdPool(vk::createCommandPool(m_vk, m_device, &copyCmdPoolCreateInfo));
    443 
    444 		const vk::VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
    445 		{
    446 			vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,	// VkStructureType			sType;
    447 			DE_NULL,											// const void*				pNext;
    448 			*copyCmdPool,										// VkCommandPool			commandPool;
    449 			vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY,				// VkCommandBufferLevel		level;
    450 			1u,													// deUint32					bufferCount;
    451 		};
    452 		vk::Unique<vk::VkCommandBuffer> copyCmdBuffer(vk::allocateCommandBuffer(m_vk, m_device, &cmdBufferAllocateInfo));
    453 
    454 		CmdBufferBeginInfo beginInfo;
    455 		VK_CHECK(m_vk.beginCommandBuffer(*copyCmdBuffer, &beginInfo));
    456 
    457 		transition2DImage(m_vk, *copyCmdBuffer, stagingResource->object(), aspect, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_GENERAL);
    458 
    459 		const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
    460 		vk::VkImageCopy region = { { (vk::VkImageAspectFlags)aspect, mipLevel, arrayElement, 1}, offset, { (vk::VkImageAspectFlags)aspect, 0, 0, 1}, zeroOffset, {(deUint32)width, (deUint32)height, (deUint32)depth} };
    461 
    462 		m_vk.cmdCopyImage(*copyCmdBuffer, object(), layout, stagingResource->object(), vk::VK_IMAGE_LAYOUT_GENERAL, 1, &region);
    463 		VK_CHECK(m_vk.endCommandBuffer(*copyCmdBuffer));
    464 
    465 		vk::VkSubmitInfo submitInfo =
    466 		{
    467 			vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,	// VkStructureType			sType;
    468 			DE_NULL,							// const void*				pNext;
    469 			0,									// deUint32					waitSemaphoreCount;
    470 			DE_NULL,							// const VkSemaphore*		pWaitSemaphores;
    471 			(const vk::VkPipelineStageFlags*)DE_NULL,
    472 			1,									// deUint32					commandBufferCount;
    473 			&copyCmdBuffer.get(),				// const VkCommandBuffer*	pCommandBuffers;
    474 			0,									// deUint32					signalSemaphoreCount;
    475 			DE_NULL								// const VkSemaphore*		pSignalSemaphores;
    476 		};
    477 		m_vk.queueSubmit(queue, 1, &submitInfo, DE_NULL);
    478 
    479 		// TODO: make this less intrusive
    480 		VK_CHECK(m_vk.queueWaitIdle(queue));
    481 	}
    482 	return stagingResource;
    483 }
    484 
    485 void Image::uploadVolume(const tcu::ConstPixelBufferAccess&	access,
    486 						 vk::VkQueue						queue,
    487 						 vk::Allocator&						allocator,
    488 						 vk::VkImageLayout					layout,
    489 						 vk::VkOffset3D						offset,
    490 						 vk::VkImageAspectFlagBits			aspect,
    491 						 unsigned int						mipLevel,
    492 						 unsigned int						arrayElement)
    493 {
    494 	if (aspect == vk::VK_IMAGE_ASPECT_COLOR_BIT)
    495 	{
    496 		upload(queue, allocator, layout, offset, access.getWidth(),
    497 		access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, vk::VK_IMAGE_TYPE_3D,
    498 		access.getDataPtr());
    499 	}
    500 	if (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT || aspect == vk::VK_IMAGE_ASPECT_STENCIL_BIT)
    501 	{
    502 		uploadUsingBuffer(queue, allocator, layout, offset, access.getWidth(),
    503 		access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, access.getDataPtr());
    504 	}
    505 }
    506 
    507 void Image::uploadSurface (const tcu::ConstPixelBufferAccess&	access,
    508 						   vk::VkQueue							queue,
    509 						   vk::Allocator&						allocator,
    510 						   vk::VkImageLayout					layout,
    511 						   vk::VkOffset3D						offset,
    512 						   vk::VkImageAspectFlagBits			aspect,
    513 						   unsigned int							mipLevel,
    514 						   unsigned int							arrayElement)
    515 {
    516 	if (aspect == vk::VK_IMAGE_ASPECT_COLOR_BIT)
    517 	{
    518 		upload(queue, allocator, layout, offset, access.getWidth(),
    519 			access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, vk::VK_IMAGE_TYPE_2D,
    520 			access.getDataPtr());
    521 	}
    522 	if (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT || aspect == vk::VK_IMAGE_ASPECT_STENCIL_BIT)
    523 	{
    524 		uploadUsingBuffer(queue, allocator, layout, offset, access.getWidth(),
    525 			access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, access.getDataPtr());
    526 	}
    527 }
    528 
    529 void Image::uploadSurface1D (const tcu::ConstPixelBufferAccess&	access,
    530 							 vk::VkQueue						queue,
    531 							 vk::Allocator&						allocator,
    532 							 vk::VkImageLayout					layout,
    533 							 vk::VkOffset3D						offset,
    534 							 vk::VkImageAspectFlagBits			aspect,
    535 							 unsigned int						mipLevel,
    536 							 unsigned int						arrayElement)
    537 {
    538 	if (aspect == vk::VK_IMAGE_ASPECT_COLOR_BIT)
    539 	{
    540 		upload(queue, allocator, layout, offset, access.getWidth(),
    541 			access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, vk::VK_IMAGE_TYPE_1D,
    542 			access.getDataPtr());
    543 	}
    544 	if (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT || aspect == vk::VK_IMAGE_ASPECT_STENCIL_BIT)
    545 	{
    546 		uploadUsingBuffer(queue, allocator, layout, offset, access.getWidth(),
    547 			access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, access.getDataPtr());
    548 	}
    549 }
    550 
    551 void Image::uploadSurfaceLinear (const tcu::ConstPixelBufferAccess&	access,
    552 								 vk::VkOffset3D						offset,
    553 								 int								width,
    554 								 int								height,
    555 								 int								depth,
    556 								 vk::VkImageAspectFlagBits			aspect,
    557 								 unsigned int						mipLevel,
    558 								 unsigned int						arrayElement)
    559 {
    560 	uploadLinear(offset, width, height, depth, mipLevel, arrayElement, aspect, access.getDataPtr());
    561 }
    562 
    563 void Image::upload (vk::VkQueue					queue,
    564 					vk::Allocator&				allocator,
    565 					vk::VkImageLayout			layout,
    566 					vk::VkOffset3D				offset,
    567 					int							width,
    568 					int							height,
    569 					int							depth,
    570 					unsigned int				mipLevel,
    571 					unsigned int				arrayElement,
    572 					vk::VkImageAspectFlagBits	aspect,
    573 					vk::VkImageType				type,
    574 					const void *				data)
    575 {
    576 	DE_ASSERT(layout == vk::VK_IMAGE_LAYOUT_GENERAL || layout == vk::VK_IMAGE_LAYOUT_UNDEFINED || layout == vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
    577 
    578 	de::SharedPtr<Image> stagingResource;
    579 	vk::VkExtent3D extent = {(deUint32)width, (deUint32)height, (deUint32)depth};
    580 	ImageCreateInfo stagingResourceCreateInfo(
    581 		type, m_format, extent, 1, 1, vk::VK_SAMPLE_COUNT_1_BIT,
    582 		vk::VK_IMAGE_TILING_LINEAR, vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
    583 
    584 	stagingResource = Image::createAndAlloc(m_vk, m_device, stagingResourceCreateInfo, allocator,
    585 								vk::MemoryRequirement::HostVisible);
    586 
    587 	const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
    588 	stagingResource->uploadLinear(zeroOffset, width, height, depth, 0, 0, aspect, data);
    589 
    590 	{
    591 		//todo [scygan] get proper queueFamilyIndex
    592 		CmdPoolCreateInfo copyCmdPoolCreateInfo(0);
    593 		vk::Unique<vk::VkCommandPool> copyCmdPool(vk::createCommandPool(m_vk, m_device, &copyCmdPoolCreateInfo));
    594 
    595 		const vk::VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
    596 		{
    597 			vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,	// VkStructureType			sType;
    598 			DE_NULL,											// const void*				pNext;
    599 			*copyCmdPool,										// VkCommandPool			commandPool;
    600 			vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY,				// VkCommandBufferLevel		level;
    601 			1u,													// deUint32					bufferCount;
    602 		};
    603 
    604 		vk::Unique<vk::VkCommandBuffer> copyCmdBuffer(vk::allocateCommandBuffer(m_vk, m_device, &cmdBufferAllocateInfo));
    605 
    606 		CmdBufferBeginInfo beginInfo;
    607 		VK_CHECK(m_vk.beginCommandBuffer(*copyCmdBuffer, &beginInfo));
    608 
    609 		if (layout == vk::VK_IMAGE_LAYOUT_UNDEFINED)
    610 		{
    611 			layout = vk::VK_IMAGE_LAYOUT_GENERAL;
    612 
    613 			vk::VkImageMemoryBarrier barrier;
    614 			barrier.sType = vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
    615 			barrier.pNext = DE_NULL;
    616 			barrier.srcAccessMask = 0;
    617 			barrier.dstAccessMask = 0;
    618 			barrier.oldLayout = vk::VK_IMAGE_LAYOUT_UNDEFINED;
    619 			barrier.newLayout = vk::VK_IMAGE_LAYOUT_GENERAL;
    620 			barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
    621 			barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
    622 			barrier.image = object();
    623 
    624 			barrier.subresourceRange.aspectMask = aspect;
    625 			barrier.subresourceRange.baseMipLevel = 0;
    626 			barrier.subresourceRange.levelCount = m_levelCount;
    627 			barrier.subresourceRange.baseArrayLayer = 0;
    628 			barrier.subresourceRange.layerCount = m_layerCount;
    629 
    630 			m_vk.cmdPipelineBarrier(*copyCmdBuffer, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (vk::VkDependencyFlags)0,
    631 									0, (const vk::VkMemoryBarrier*)DE_NULL,
    632 									0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
    633 									1, &barrier);
    634 		}
    635 
    636 		transition2DImage(m_vk, *copyCmdBuffer, stagingResource->object(), aspect, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_GENERAL);
    637 
    638 		vk::VkImageCopy region = {{ (vk::VkImageAspectFlags)aspect, 0, 0, 1},
    639 									zeroOffset,
    640 									{ (vk::VkImageAspectFlags)aspect, mipLevel, arrayElement, 1},
    641 									offset,
    642 									{(deUint32)width, (deUint32)height, (deUint32)depth}};
    643 
    644 		m_vk.cmdCopyImage(*copyCmdBuffer, stagingResource->object(),
    645 								vk::VK_IMAGE_LAYOUT_GENERAL, object(), layout, 1, &region);
    646 		VK_CHECK(m_vk.endCommandBuffer(*copyCmdBuffer));
    647 
    648 		vk::VkSubmitInfo submitInfo =
    649 		{
    650 			vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,	// VkStructureType			sType;
    651 			DE_NULL,							// const void*				pNext;
    652 			0,									// deUint32					waitSemaphoreCount;
    653 			DE_NULL,							// const VkSemaphore*		pWaitSemaphores;
    654 			(const vk::VkPipelineStageFlags*)DE_NULL,
    655 			1,									// deUint32					commandBufferCount;
    656 			&copyCmdBuffer.get(),				// const VkCommandBuffer*	pCommandBuffers;
    657 			0,									// deUint32					signalSemaphoreCount;
    658 			DE_NULL								// const VkSemaphore*		pSignalSemaphores;
    659 		};
    660 		m_vk.queueSubmit(queue, 1, &submitInfo, DE_NULL);
    661 
    662 		// TODO: make this less intrusive
    663 		VK_CHECK(m_vk.queueWaitIdle(queue));
    664 	}
    665 }
    666 
    667 void Image::uploadUsingBuffer (vk::VkQueue					queue,
    668 							   vk::Allocator&				allocator,
    669 							   vk::VkImageLayout			layout,
    670 							   vk::VkOffset3D				offset,
    671 							   int							width,
    672 							   int							height,
    673 							   int							depth,
    674 							   unsigned int					mipLevel,
    675 							   unsigned int					arrayElement,
    676 							   vk::VkImageAspectFlagBits	aspect,
    677 							   const void *					data)
    678 {
    679 	DE_ASSERT(layout == vk::VK_IMAGE_LAYOUT_GENERAL || layout == vk::VK_IMAGE_LAYOUT_UNDEFINED || layout == vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
    680 
    681 	de::SharedPtr<Buffer> stagingResource;
    682 	bool isCombinedType = isCombinedDepthStencilType(vk::mapVkFormat(m_format).type);
    683 	vk::VkDeviceSize bufferSize = 0;
    684 	if (!isCombinedType)
    685 		bufferSize = vk::mapVkFormat(m_format).getPixelSize() *width*height*depth;
    686 	if (isCombinedType)
    687 	{
    688 		int pixelSize = 0;
    689 		switch (m_format)
    690 		{
    691 			case vk::VK_FORMAT_D16_UNORM_S8_UINT:
    692 				pixelSize = (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT) ? 2 : 1;
    693 				break;
    694 			case  vk::VK_FORMAT_D32_SFLOAT_S8_UINT:
    695 				pixelSize = (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT) ? 4 : 1;
    696 				break;
    697 			case vk::VK_FORMAT_X8_D24_UNORM_PACK32:
    698 			case vk::VK_FORMAT_D24_UNORM_S8_UINT:
    699 				pixelSize = (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT) ? 3 : 1;
    700 				break;
    701 
    702 			default:
    703 				DE_FATAL("Not implemented");
    704 		}
    705 		bufferSize = pixelSize*width*height*depth;
    706 	}
    707 	BufferCreateInfo stagingBufferResourceCreateInfo(bufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT | vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
    708 	stagingResource = Buffer::createAndAlloc(m_vk, m_device, stagingBufferResourceCreateInfo, allocator, vk::MemoryRequirement::HostVisible);
    709 	deUint8* destPtr = reinterpret_cast<deUint8*>(stagingResource->getBoundMemory().getHostPtr());
    710 	deMemcpy(destPtr, data, static_cast<size_t>(bufferSize));
    711 	vk::flushMappedMemoryRange(m_vk, m_device, stagingResource->getBoundMemory().getMemory(), stagingResource->getBoundMemory().getOffset(), bufferSize);
    712 	{
    713 		//todo [scygan] get proper queueFamilyIndex
    714 		CmdPoolCreateInfo copyCmdPoolCreateInfo(0);
    715 		vk::Unique<vk::VkCommandPool> copyCmdPool(vk::createCommandPool(m_vk, m_device, &copyCmdPoolCreateInfo));
    716 
    717 		const vk::VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
    718 		{
    719 			vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,	// VkStructureType			sType;
    720 			DE_NULL,											// const void*				pNext;
    721 			*copyCmdPool,										// VkCommandPool			commandPool;
    722 			vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY,				// VkCommandBufferLevel		level;
    723 			1u,													// deUint32					bufferCount;
    724 		};
    725 		vk::Unique<vk::VkCommandBuffer> copyCmdBuffer(vk::allocateCommandBuffer(m_vk, m_device, &cmdBufferAllocateInfo));
    726 
    727 		CmdBufferBeginInfo beginInfo;
    728 		VK_CHECK(m_vk.beginCommandBuffer(*copyCmdBuffer, &beginInfo));
    729 
    730 		if (layout == vk::VK_IMAGE_LAYOUT_UNDEFINED)
    731 		{
    732 			layout = vk::VK_IMAGE_LAYOUT_GENERAL;
    733 
    734 			vk::VkImageMemoryBarrier barrier;
    735 			barrier.sType = vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
    736 			barrier.pNext = DE_NULL;
    737 			barrier.srcAccessMask = 0;
    738 			barrier.dstAccessMask = 0;
    739 			barrier.oldLayout = vk::VK_IMAGE_LAYOUT_UNDEFINED;
    740 			barrier.newLayout = vk::VK_IMAGE_LAYOUT_GENERAL;
    741 			barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
    742 			barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
    743 			barrier.image = object();
    744 
    745 			barrier.subresourceRange.aspectMask = aspect;
    746 			barrier.subresourceRange.baseMipLevel = 0;
    747 			barrier.subresourceRange.levelCount = m_levelCount;
    748 			barrier.subresourceRange.baseArrayLayer = 0;
    749 			barrier.subresourceRange.layerCount = m_layerCount;
    750 
    751 			m_vk.cmdPipelineBarrier(*copyCmdBuffer, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (vk::VkDependencyFlags)0,
    752 									0, (const vk::VkMemoryBarrier*)DE_NULL,
    753 									0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
    754 									1, &barrier);
    755 		}
    756 
    757 		vk::VkBufferImageCopy region = {
    758 			0, 0, 0,
    759 			{ (vk::VkImageAspectFlags)aspect, mipLevel, arrayElement, 1 },
    760 			offset,
    761 			{ (deUint32)width, (deUint32)height, (deUint32)depth }
    762 		};
    763 
    764 		m_vk.cmdCopyBufferToImage(*copyCmdBuffer, stagingResource->object(),
    765 			object(), layout, 1, &region);
    766 		VK_CHECK(m_vk.endCommandBuffer(*copyCmdBuffer));
    767 
    768 		vk::VkSubmitInfo submitInfo =
    769 		{
    770 			vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,	// VkStructureType			sType;
    771 			DE_NULL,							// const void*				pNext;
    772 			0,									// deUint32					waitSemaphoreCount;
    773 			DE_NULL,							// const VkSemaphore*		pWaitSemaphores;
    774 			(const vk::VkPipelineStageFlags*)DE_NULL,
    775 			1,									// deUint32					commandBufferCount;
    776 			&copyCmdBuffer.get(),				// const VkCommandBuffer*	pCommandBuffers;
    777 			0,									// deUint32					signalSemaphoreCount;
    778 			DE_NULL								// const VkSemaphore*		pSignalSemaphores;
    779 		};
    780 		m_vk.queueSubmit(queue, 1, &submitInfo, DE_NULL);
    781 
    782 		// TODO: make this less intrusive
    783 		VK_CHECK(m_vk.queueWaitIdle(queue));
    784 	}
    785 }
    786 
    787 void Image::uploadLinear (vk::VkOffset3D			offset,
    788 						  int						width,
    789 						  int						height,
    790 						  int						depth,
    791 						  unsigned int				mipLevel,
    792 						  unsigned int				arrayElement,
    793 						  vk::VkImageAspectFlagBits	aspect,
    794 						  const void *				data)
    795 {
    796 	vk::VkSubresourceLayout imageLayout;
    797 
    798 	vk::VkImageSubresource imageSubResource = { (vk::VkImageAspectFlags)aspect, mipLevel, arrayElement};
    799 
    800 	m_vk.getImageSubresourceLayout(m_device, object(), &imageSubResource,
    801 													&imageLayout);
    802 
    803 	deUint8* destPtr = reinterpret_cast<deUint8*>(getBoundMemory().getHostPtr());
    804 
    805 	destPtr += imageLayout.offset + getPixelOffset(offset, imageLayout.rowPitch, imageLayout.depthPitch, mipLevel, arrayElement);
    806 
    807 	MemoryOp::pack(vk::mapVkFormat(m_format).getPixelSize(), width, height, depth,
    808 		imageLayout.rowPitch, imageLayout.depthPitch, data, destPtr);
    809 }
    810 
    811 vk::VkDeviceSize Image::getPixelOffset (vk::VkOffset3D		offset,
    812 										vk::VkDeviceSize	rowPitch,
    813 										vk::VkDeviceSize	depthPitch,
    814 										unsigned int		level,
    815 										unsigned int		layer)
    816 {
    817 	DE_ASSERT(level < m_levelCount);
    818 	DE_ASSERT(layer < m_layerCount);
    819 
    820 	vk::VkDeviceSize mipLevelSizes[32];
    821 	vk::VkDeviceSize mipLevelRectSizes[32];
    822 	tcu::IVec3 mipExtend
    823 	= tcu::IVec3(m_extent.width, m_extent.height, m_extent.depth);
    824 
    825 	vk::VkDeviceSize arrayElemSize = 0;
    826 	for (unsigned int i = 0; i < m_levelCount && (mipExtend[0] > 1 || mipExtend[1] > 1 || mipExtend[2] > 1); ++i)
    827 	{
    828 		// Rect size is just a 3D image size;
    829 		mipLevelSizes[i] = mipExtend[2] * depthPitch;
    830 
    831 		arrayElemSize += mipLevelSizes[0];
    832 
    833 		mipExtend = tcu::max(mipExtend / 2, tcu::IVec3(1));
    834 	}
    835 
    836 	vk::VkDeviceSize pixelOffset = layer * arrayElemSize;
    837 	for (size_t i = 0; i < level; ++i) {
    838 		pixelOffset += mipLevelSizes[i];
    839 	}
    840 	pixelOffset += offset.z * mipLevelRectSizes[level];
    841 	pixelOffset += offset.y * rowPitch;
    842 	pixelOffset += offset.x;
    843 
    844 	return pixelOffset;
    845 }
    846 
    847 void Image::bindMemory (de::MovePtr<vk::Allocation> allocation)
    848 {
    849 	DE_ASSERT(allocation);
    850 	VK_CHECK(m_vk.bindImageMemory(m_device, *m_object, allocation->getMemory(), allocation->getOffset()));
    851 
    852 	DE_ASSERT(!m_allocation);
    853 	m_allocation = allocation;
    854 }
    855 
    856 de::SharedPtr<Image> Image::createAndAlloc(const vk::DeviceInterface&	vk,
    857 										   vk::VkDevice					device,
    858 										   const vk::VkImageCreateInfo& createInfo,
    859 										   vk::Allocator&				allocator,
    860 										   vk::MemoryRequirement		memoryRequirement)
    861 {
    862 	de::SharedPtr<Image> ret = create(vk, device, createInfo);
    863 
    864 	vk::VkMemoryRequirements imageRequirements = vk::getImageMemoryRequirements(vk, device, ret->object());
    865 	ret->bindMemory(allocator.allocate(imageRequirements, memoryRequirement));
    866 	return ret;
    867 }
    868 
    869 de::SharedPtr<Image> Image::create(const vk::DeviceInterface&	vk,
    870 								   vk::VkDevice					device,
    871 								   const vk::VkImageCreateInfo	&createInfo)
    872 {
    873 	return de::SharedPtr<Image>(new Image(vk, device, createInfo.format, createInfo.extent,
    874 								createInfo.mipLevels, createInfo.arrayLayers,
    875 								vk::createImage(vk, device, &createInfo)));
    876 }
    877 
    878 void transition2DImage (const vk::DeviceInterface&	vk,
    879 						vk::VkCommandBuffer			cmdBuffer,
    880 						vk::VkImage					image,
    881 						vk::VkImageAspectFlags		aspectMask,
    882 						vk::VkImageLayout			oldLayout,
    883 						vk::VkImageLayout			newLayout,
    884 						vk::VkAccessFlags			srcAccessMask,
    885 						vk::VkAccessFlags			dstAccessMask)
    886 {
    887 	vk::VkImageMemoryBarrier barrier;
    888 	barrier.sType							= vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
    889 	barrier.pNext							= DE_NULL;
    890 	barrier.srcAccessMask					= srcAccessMask;
    891 	barrier.dstAccessMask					= dstAccessMask;
    892 	barrier.oldLayout						= oldLayout;
    893 	barrier.newLayout						= newLayout;
    894 	barrier.srcQueueFamilyIndex				= VK_QUEUE_FAMILY_IGNORED;
    895 	barrier.dstQueueFamilyIndex				= VK_QUEUE_FAMILY_IGNORED;
    896 	barrier.image							= image;
    897 	barrier.subresourceRange.aspectMask		= aspectMask;
    898 	barrier.subresourceRange.baseMipLevel	= 0;
    899 	barrier.subresourceRange.levelCount		= 1;
    900 	barrier.subresourceRange.baseArrayLayer = 0;
    901 	barrier.subresourceRange.layerCount		= 1;
    902 
    903 	vk.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (vk::VkDependencyFlags)0,
    904 						  0, (const vk::VkMemoryBarrier*)DE_NULL,
    905 						  0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
    906 						  1, &barrier);
    907 }
    908 
    909 void initialTransitionColor2DImage (const vk::DeviceInterface &vk, vk::VkCommandBuffer cmdBuffer, vk::VkImage image, vk::VkImageLayout layout)
    910 {
    911 	transition2DImage(vk, cmdBuffer, image, vk::VK_IMAGE_ASPECT_COLOR_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, layout);
    912 }
    913 
    914 void initialTransitionDepth2DImage (const vk::DeviceInterface &vk, vk::VkCommandBuffer cmdBuffer, vk::VkImage image, vk::VkImageLayout layout)
    915 {
    916 	transition2DImage(vk, cmdBuffer, image, vk::VK_IMAGE_ASPECT_DEPTH_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, layout);
    917 }
    918 
    919 void initialTransitionStencil2DImage (const vk::DeviceInterface &vk, vk::VkCommandBuffer cmdBuffer, vk::VkImage image, vk::VkImageLayout layout)
    920 {
    921 	transition2DImage(vk, cmdBuffer, image, vk::VK_IMAGE_ASPECT_STENCIL_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, layout);
    922 }
    923 
    924 void initialTransitionDepthStencil2DImage (const vk::DeviceInterface&	vk,
    925 										   vk::VkCommandBuffer			cmdBuffer,
    926 										   vk::VkImage					image,
    927 										   vk::VkImageLayout			layout,
    928 										   vk::VkAccessFlags			srcAccessMask,
    929 										   vk::VkAccessFlags			dstAccessMask)
    930 {
    931 	transition2DImage(vk, cmdBuffer, image, vk::VK_IMAGE_ASPECT_DEPTH_BIT | vk::VK_IMAGE_ASPECT_STENCIL_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, layout, srcAccessMask, dstAccessMask);
    932 }
    933 
    934 } // Draw
    935 } // vkt
    936