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