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 
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)191 tcu::ConstPixelBufferAccess Image::readVolume (vk::VkQueue					queue,
192 											   vk::Allocator&				allocator,
193 											   vk::VkImageLayout			layout,
194 											   vk::VkOffset3D				offset,
195 											   int							width,
196 											   int							height,
197 											   int							depth,
198 											   vk::VkImageAspectFlagBits	aspect,
199 											   unsigned int					mipLevel,
200 											   unsigned int					arrayElement)
201 {
202 	m_pixelAccessData.resize(width * height * depth * vk::mapVkFormat(m_format).getPixelSize());
203 	deMemset(m_pixelAccessData.data(), 0, m_pixelAccessData.size());
204 	if (aspect == vk::VK_IMAGE_ASPECT_COLOR_BIT)
205 	{
206 		read(queue, allocator, layout, offset, width, height, depth, mipLevel, arrayElement, aspect, vk::VK_IMAGE_TYPE_3D,
207 		m_pixelAccessData.data());
208 	}
209 	if (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT || aspect == vk::VK_IMAGE_ASPECT_STENCIL_BIT)
210 	{
211 		readUsingBuffer(queue, allocator, layout, offset, width, height, depth, mipLevel, arrayElement, aspect, m_pixelAccessData.data());
212 	}
213 	return tcu::ConstPixelBufferAccess(vk::mapVkFormat(m_format), width, height, depth, m_pixelAccessData.data());
214 }
215 
readSurface1D(vk::VkQueue queue,vk::Allocator & allocator,vk::VkImageLayout layout,vk::VkOffset3D offset,int width,vk::VkImageAspectFlagBits aspect,unsigned int mipLevel,unsigned int arrayElement)216 tcu::ConstPixelBufferAccess Image::readSurface1D(vk::VkQueue				queue,
217 												 vk::Allocator&				allocator,
218 												 vk::VkImageLayout			layout,
219 												 vk::VkOffset3D				offset,
220 												 int						width,
221 												 vk::VkImageAspectFlagBits	aspect,
222 												 unsigned int				mipLevel,
223 												 unsigned int				arrayElement)
224 {
225 	m_pixelAccessData.resize(width * vk::mapVkFormat(m_format).getPixelSize());
226 	deMemset(m_pixelAccessData.data(), 0, m_pixelAccessData.size());
227 	if (aspect == vk::VK_IMAGE_ASPECT_COLOR_BIT)
228 	{
229 		read(queue, allocator, layout, offset, width, 1, 1, mipLevel, arrayElement, aspect, vk::VK_IMAGE_TYPE_1D,
230 		m_pixelAccessData.data());
231 	}
232 	if (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT || aspect == vk::VK_IMAGE_ASPECT_STENCIL_BIT)
233 	{
234 		readUsingBuffer(queue, allocator, layout, offset, width, 1, 1, mipLevel, arrayElement, aspect,
235 		m_pixelAccessData.data());
236 	}
237 	return tcu::ConstPixelBufferAccess(vk::mapVkFormat(m_format), width, 1, 1, m_pixelAccessData.data());
238 }
239 
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)240 void Image::read (vk::VkQueue					queue,
241 				  vk::Allocator&				allocator,
242 				  vk::VkImageLayout				layout,
243 				  vk::VkOffset3D				offset,
244 				  int							width,
245 				  int							height,
246 				  int							depth,
247 				  unsigned int					mipLevel,
248 				  unsigned int					arrayElement,
249 				  vk::VkImageAspectFlagBits		aspect,
250 				  vk::VkImageType				type,
251 				  void *						data)
252 {
253 	DE_ASSERT(layout == vk::VK_IMAGE_LAYOUT_GENERAL || layout == vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
254 
255 	de::SharedPtr<Image> stagingResource = copyToLinearImage(queue, allocator, layout, offset, width,
256 															 height, depth, mipLevel, arrayElement, aspect, type);
257 	const vk::VkOffset3D zeroOffset = {0, 0, 0};
258 	stagingResource->readLinear(zeroOffset, width, height, depth, 0, 0, aspect, data);
259 }
260 
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)261 void Image::readUsingBuffer (vk::VkQueue				queue,
262 							 vk::Allocator&				allocator,
263 							 vk::VkImageLayout			layout,
264 							 vk::VkOffset3D				offset,
265 							 int						width,
266 							 int						height,
267 							 int						depth,
268 							 unsigned int				mipLevel,
269 							 unsigned int				arrayElement,
270 							 vk::VkImageAspectFlagBits	aspect,
271 							 void *						data)
272 {
273 	DE_ASSERT(layout == vk::VK_IMAGE_LAYOUT_GENERAL || layout == vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);;
274 
275 	de::SharedPtr<Buffer> stagingResource;
276 
277 	bool isCombinedType = isCombinedDepthStencilType(vk::mapVkFormat(m_format).type);
278 	vk::VkDeviceSize bufferSize = 0;
279 
280 	if (!isCombinedType)
281 		bufferSize = vk::mapVkFormat(m_format).getPixelSize() * width * height * depth;
282 
283 	if (isCombinedType)
284 	{
285 		int pixelSize = 0;
286 		switch (m_format)
287 		{
288 			case vk::VK_FORMAT_D16_UNORM_S8_UINT:
289 				pixelSize = (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT) ? 2 : 1;
290 				break;
291 			case  vk::VK_FORMAT_D32_SFLOAT_S8_UINT:
292 				pixelSize = (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT) ? 4 : 1;
293 				break;
294 			case vk::VK_FORMAT_X8_D24_UNORM_PACK32:
295 			case vk::VK_FORMAT_D24_UNORM_S8_UINT:
296 				pixelSize = (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT) ? 3 : 1;
297 				break;
298 
299 			default:
300 				DE_FATAL("Not implemented");
301 		}
302 		bufferSize = pixelSize*width*height*depth;
303 	}
304 
305 	BufferCreateInfo stagingBufferResourceCreateInfo(bufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT | vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
306 	stagingResource = Buffer::createAndAlloc(m_vk, m_device, stagingBufferResourceCreateInfo, allocator, vk::MemoryRequirement::HostVisible);
307 
308 	{
309 		CmdPoolCreateInfo copyCmdPoolCreateInfo(m_queueFamilyIndex);
310 		vk::Unique<vk::VkCommandPool> copyCmdPool(vk::createCommandPool(m_vk, m_device, &copyCmdPoolCreateInfo));
311 		vk::Unique<vk::VkCommandBuffer> copyCmdBuffer(vk::allocateCommandBuffer(m_vk, m_device, *copyCmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
312 
313 		beginCommandBuffer(m_vk, *copyCmdBuffer);
314 
315 		if (layout == vk::VK_IMAGE_LAYOUT_UNDEFINED)
316 		{
317 			layout = vk::VK_IMAGE_LAYOUT_GENERAL;
318 
319 			vk::VkImageMemoryBarrier barrier;
320 			barrier.sType = vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
321 			barrier.pNext = DE_NULL;
322 			barrier.srcAccessMask = 0;
323 			barrier.dstAccessMask = 0;
324 			barrier.oldLayout = vk::VK_IMAGE_LAYOUT_UNDEFINED;
325 			barrier.newLayout = vk::VK_IMAGE_LAYOUT_GENERAL;
326 			barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
327 			barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
328 			barrier.image = object();
329 
330 			barrier.subresourceRange.aspectMask = aspect;
331 			barrier.subresourceRange.baseMipLevel = 0;
332 			barrier.subresourceRange.levelCount = m_levelCount;
333 			barrier.subresourceRange.baseArrayLayer = 0;
334 			barrier.subresourceRange.layerCount = m_layerCount;
335 
336 			m_vk.cmdPipelineBarrier(*copyCmdBuffer, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (vk::VkDependencyFlags)0,
337 									0, (const vk::VkMemoryBarrier*)DE_NULL,
338 									0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
339 									1, &barrier);
340 		}
341 
342 		vk::VkBufferImageCopy region =
343 		{
344 			0, 0, 0,
345 			{ (vk::VkImageAspectFlags)aspect, mipLevel, arrayElement, 1 },
346 			offset,
347 			{ (deUint32)width, (deUint32)height, (deUint32)depth }
348 		};
349 
350 		m_vk.cmdCopyImageToBuffer(*copyCmdBuffer, object(), layout, stagingResource->object(), 1, &region);
351 		endCommandBuffer(m_vk, *copyCmdBuffer);
352 
353 		submitCommandsAndWait(m_vk, m_device, queue, copyCmdBuffer.get());
354 	}
355 
356 	// Validate the results
357 	const vk::Allocation& bufAllocation = stagingResource->getBoundMemory();
358 	invalidateMappedMemoryRange(m_vk, m_device, bufAllocation.getMemory(), bufAllocation.getOffset(), VK_WHOLE_SIZE);
359 
360 	deUint8* destPtr = reinterpret_cast<deUint8*>(stagingResource->getBoundMemory().getHostPtr());
361 	deMemcpy(data, destPtr, static_cast<size_t>(bufferSize));
362 }
363 
readSurfaceLinear(vk::VkOffset3D offset,int width,int height,int depth,vk::VkImageAspectFlagBits aspect,unsigned int mipLevel,unsigned int arrayElement)364 tcu::ConstPixelBufferAccess Image::readSurfaceLinear (vk::VkOffset3D				offset,
365 													  int							width,
366 													  int							height,
367 													  int							depth,
368 													  vk::VkImageAspectFlagBits		aspect,
369 													  unsigned int					mipLevel,
370 													  unsigned int					arrayElement)
371 {
372 	m_pixelAccessData.resize(width * height * vk::mapVkFormat(m_format).getPixelSize());
373 	readLinear(offset, width, height, depth, mipLevel, arrayElement, aspect, m_pixelAccessData.data());
374 	return tcu::ConstPixelBufferAccess(vk::mapVkFormat(m_format), width, height, 1, m_pixelAccessData.data());
375 }
376 
readLinear(vk::VkOffset3D offset,int width,int height,int depth,unsigned int mipLevel,unsigned int arrayElement,vk::VkImageAspectFlagBits aspect,void * data)377 void Image::readLinear (vk::VkOffset3D				offset,
378 						int							width,
379 						int							height,
380 						int							depth,
381 						unsigned int				mipLevel,
382 						unsigned int				arrayElement,
383 						vk::VkImageAspectFlagBits	aspect,
384 						void *						data)
385 {
386 	DE_ASSERT(mipLevel < m_levelCount);
387 	DE_ASSERT(arrayElement < m_layerCount);
388 
389 	vk::VkImageSubresource imageSubResource = { (vk::VkImageAspectFlags)aspect, mipLevel, arrayElement };
390 
391 	vk::VkSubresourceLayout imageLayout;
392 	deMemset(&imageLayout, 0, sizeof(imageLayout));
393 
394 	m_vk.getImageSubresourceLayout(m_device, object(), &imageSubResource, &imageLayout);
395 
396 	const deUint8* srcPtr = reinterpret_cast<const deUint8*>(getBoundMemory().getHostPtr());
397 	srcPtr += imageLayout.offset;
398 	srcPtr += offset.z * imageLayout.depthPitch;
399 	srcPtr += offset.y * imageLayout.rowPitch;
400 	srcPtr += offset.x;
401 
402 	MemoryOp::unpack(vk::mapVkFormat(m_format).getPixelSize(), width, height, depth,
403 		imageLayout.rowPitch, imageLayout.depthPitch, srcPtr, data);
404 }
405 
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)406 de::SharedPtr<Image> Image::copyToLinearImage (vk::VkQueue					queue,
407 											   vk::Allocator&				allocator,
408 											   vk::VkImageLayout			layout,
409 											   vk::VkOffset3D				offset,
410 											   int							width,
411 											   int							height,
412 											   int							depth,
413 											   unsigned int					mipLevel,
414 											   unsigned int					arrayElement,
415 											   vk::VkImageAspectFlagBits	aspect,
416 											   vk::VkImageType				type)
417 {
418 	de::SharedPtr<Image> stagingResource;
419 	{
420 		vk::VkExtent3D stagingExtent = {(deUint32)width, (deUint32)height, (deUint32)depth};
421 		ImageCreateInfo stagingResourceCreateInfo(type, m_format, stagingExtent, 1, 1, vk::VK_SAMPLE_COUNT_1_BIT,
422 												  vk::VK_IMAGE_TILING_LINEAR, vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT);
423 
424 		stagingResource = Image::createAndAlloc(m_vk, m_device, stagingResourceCreateInfo, allocator, m_queueFamilyIndex,
425 												vk::MemoryRequirement::HostVisible);
426 
427 		CmdPoolCreateInfo copyCmdPoolCreateInfo(m_queueFamilyIndex);
428 		vk::Unique<vk::VkCommandPool> copyCmdPool(vk::createCommandPool(m_vk, m_device, &copyCmdPoolCreateInfo));
429 		vk::Unique<vk::VkCommandBuffer> copyCmdBuffer(vk::allocateCommandBuffer(m_vk, m_device, *copyCmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
430 
431 		beginCommandBuffer(m_vk, *copyCmdBuffer);
432 
433 		transition2DImage(m_vk, *copyCmdBuffer, stagingResource->object(), aspect, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_GENERAL,
434 						  0u, vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT);
435 
436 		const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
437 		vk::VkImageCopy region = { { (vk::VkImageAspectFlags)aspect, mipLevel, arrayElement, 1}, offset, { (vk::VkImageAspectFlags)aspect, 0, 0, 1}, zeroOffset, {(deUint32)width, (deUint32)height, (deUint32)depth} };
438 
439 		m_vk.cmdCopyImage(*copyCmdBuffer, object(), layout, stagingResource->object(), vk::VK_IMAGE_LAYOUT_GENERAL, 1, &region);
440 		endCommandBuffer(m_vk, *copyCmdBuffer);
441 
442 		submitCommandsAndWait(m_vk, m_device, queue, copyCmdBuffer.get());
443 
444 		// Validate the results
445 		const vk::Allocation& imgAllocation = stagingResource->getBoundMemory();
446 		invalidateMappedMemoryRange(m_vk, m_device, imgAllocation.getMemory(), imgAllocation.getOffset(), VK_WHOLE_SIZE);
447 	}
448 	return stagingResource;
449 }
450 
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)451 void Image::uploadVolume(const tcu::ConstPixelBufferAccess&	access,
452 						 vk::VkQueue						queue,
453 						 vk::Allocator&						allocator,
454 						 vk::VkImageLayout					layout,
455 						 vk::VkOffset3D						offset,
456 						 vk::VkImageAspectFlagBits			aspect,
457 						 unsigned int						mipLevel,
458 						 unsigned int						arrayElement)
459 {
460 	if (aspect == vk::VK_IMAGE_ASPECT_COLOR_BIT)
461 	{
462 		upload(queue, allocator, layout, offset, access.getWidth(),
463 		access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, vk::VK_IMAGE_TYPE_3D,
464 		access.getDataPtr());
465 	}
466 	if (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT || aspect == vk::VK_IMAGE_ASPECT_STENCIL_BIT)
467 	{
468 		uploadUsingBuffer(queue, allocator, layout, offset, access.getWidth(),
469 		access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, access.getDataPtr());
470 	}
471 }
472 
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)473 void Image::uploadSurface (const tcu::ConstPixelBufferAccess&	access,
474 						   vk::VkQueue							queue,
475 						   vk::Allocator&						allocator,
476 						   vk::VkImageLayout					layout,
477 						   vk::VkOffset3D						offset,
478 						   vk::VkImageAspectFlagBits			aspect,
479 						   unsigned int							mipLevel,
480 						   unsigned int							arrayElement)
481 {
482 	if (aspect == vk::VK_IMAGE_ASPECT_COLOR_BIT)
483 	{
484 		upload(queue, allocator, layout, offset, access.getWidth(),
485 			access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, vk::VK_IMAGE_TYPE_2D,
486 			access.getDataPtr());
487 	}
488 	if (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT || aspect == vk::VK_IMAGE_ASPECT_STENCIL_BIT)
489 	{
490 		uploadUsingBuffer(queue, allocator, layout, offset, access.getWidth(),
491 			access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, access.getDataPtr());
492 	}
493 }
494 
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)495 void Image::uploadSurface1D (const tcu::ConstPixelBufferAccess&	access,
496 							 vk::VkQueue						queue,
497 							 vk::Allocator&						allocator,
498 							 vk::VkImageLayout					layout,
499 							 vk::VkOffset3D						offset,
500 							 vk::VkImageAspectFlagBits			aspect,
501 							 unsigned int						mipLevel,
502 							 unsigned int						arrayElement)
503 {
504 	if (aspect == vk::VK_IMAGE_ASPECT_COLOR_BIT)
505 	{
506 		upload(queue, allocator, layout, offset, access.getWidth(),
507 			access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, vk::VK_IMAGE_TYPE_1D,
508 			access.getDataPtr());
509 	}
510 	if (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT || aspect == vk::VK_IMAGE_ASPECT_STENCIL_BIT)
511 	{
512 		uploadUsingBuffer(queue, allocator, layout, offset, access.getWidth(),
513 			access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, access.getDataPtr());
514 	}
515 }
516 
uploadSurfaceLinear(const tcu::ConstPixelBufferAccess & access,vk::VkOffset3D offset,int width,int height,int depth,vk::VkImageAspectFlagBits aspect,unsigned int mipLevel,unsigned int arrayElement)517 void Image::uploadSurfaceLinear (const tcu::ConstPixelBufferAccess&	access,
518 								 vk::VkOffset3D						offset,
519 								 int								width,
520 								 int								height,
521 								 int								depth,
522 								 vk::VkImageAspectFlagBits			aspect,
523 								 unsigned int						mipLevel,
524 								 unsigned int						arrayElement)
525 {
526 	uploadLinear(offset, width, height, depth, mipLevel, arrayElement, aspect, access.getDataPtr());
527 }
528 
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)529 void Image::upload (vk::VkQueue					queue,
530 					vk::Allocator&				allocator,
531 					vk::VkImageLayout			layout,
532 					vk::VkOffset3D				offset,
533 					int							width,
534 					int							height,
535 					int							depth,
536 					unsigned int				mipLevel,
537 					unsigned int				arrayElement,
538 					vk::VkImageAspectFlagBits	aspect,
539 					vk::VkImageType				type,
540 					const void *				data)
541 {
542 	DE_ASSERT(layout == vk::VK_IMAGE_LAYOUT_GENERAL || layout == vk::VK_IMAGE_LAYOUT_UNDEFINED || layout == vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
543 
544 	de::SharedPtr<Image> stagingResource;
545 	vk::VkExtent3D extent = {(deUint32)width, (deUint32)height, (deUint32)depth};
546 	ImageCreateInfo stagingResourceCreateInfo(
547 		type, m_format, extent, 1, 1, vk::VK_SAMPLE_COUNT_1_BIT,
548 		vk::VK_IMAGE_TILING_LINEAR, vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
549 
550 	stagingResource = Image::createAndAlloc(m_vk, m_device, stagingResourceCreateInfo, allocator, m_queueFamilyIndex,
551 								vk::MemoryRequirement::HostVisible);
552 
553 	const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
554 	stagingResource->uploadLinear(zeroOffset, width, height, depth, 0, 0, aspect, data);
555 
556 	{
557 		CmdPoolCreateInfo copyCmdPoolCreateInfo(m_queueFamilyIndex);
558 		vk::Unique<vk::VkCommandPool> copyCmdPool(vk::createCommandPool(m_vk, m_device, &copyCmdPoolCreateInfo));
559 		vk::Unique<vk::VkCommandBuffer> copyCmdBuffer(vk::allocateCommandBuffer(m_vk, m_device, *copyCmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
560 
561 		beginCommandBuffer(m_vk, *copyCmdBuffer);
562 
563 		if (layout == vk::VK_IMAGE_LAYOUT_UNDEFINED)
564 		{
565 			layout = vk::VK_IMAGE_LAYOUT_GENERAL;
566 
567 			vk::VkImageMemoryBarrier barrier;
568 			barrier.sType = vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
569 			barrier.pNext = DE_NULL;
570 			barrier.srcAccessMask = 0;
571 			barrier.dstAccessMask = 0;
572 			barrier.oldLayout = vk::VK_IMAGE_LAYOUT_UNDEFINED;
573 			barrier.newLayout = vk::VK_IMAGE_LAYOUT_GENERAL;
574 			barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
575 			barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
576 			barrier.image = object();
577 
578 			barrier.subresourceRange.aspectMask = aspect;
579 			barrier.subresourceRange.baseMipLevel = 0;
580 			barrier.subresourceRange.levelCount = m_levelCount;
581 			barrier.subresourceRange.baseArrayLayer = 0;
582 			barrier.subresourceRange.layerCount = m_layerCount;
583 
584 			m_vk.cmdPipelineBarrier(*copyCmdBuffer, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (vk::VkDependencyFlags)0,
585 									0, (const vk::VkMemoryBarrier*)DE_NULL,
586 									0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
587 									1, &barrier);
588 		}
589 
590 		transition2DImage(m_vk, *copyCmdBuffer, stagingResource->object(), aspect, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_GENERAL,
591 						  0u, vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT);
592 
593 		vk::VkImageCopy region = {{ (vk::VkImageAspectFlags)aspect, 0, 0, 1},
594 									zeroOffset,
595 									{ (vk::VkImageAspectFlags)aspect, mipLevel, arrayElement, 1},
596 									offset,
597 									{(deUint32)width, (deUint32)height, (deUint32)depth}};
598 
599 		m_vk.cmdCopyImage(*copyCmdBuffer, stagingResource->object(),
600 								vk::VK_IMAGE_LAYOUT_GENERAL, object(), layout, 1, &region);
601 		endCommandBuffer(m_vk, *copyCmdBuffer);
602 
603 		submitCommandsAndWait(m_vk, m_device, queue, copyCmdBuffer.get());
604 	}
605 }
606 
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)607 void Image::uploadUsingBuffer (vk::VkQueue					queue,
608 							   vk::Allocator&				allocator,
609 							   vk::VkImageLayout			layout,
610 							   vk::VkOffset3D				offset,
611 							   int							width,
612 							   int							height,
613 							   int							depth,
614 							   unsigned int					mipLevel,
615 							   unsigned int					arrayElement,
616 							   vk::VkImageAspectFlagBits	aspect,
617 							   const void *					data)
618 {
619 	DE_ASSERT(layout == vk::VK_IMAGE_LAYOUT_GENERAL || layout == vk::VK_IMAGE_LAYOUT_UNDEFINED || layout == vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
620 
621 	de::SharedPtr<Buffer> stagingResource;
622 	bool isCombinedType = isCombinedDepthStencilType(vk::mapVkFormat(m_format).type);
623 	vk::VkDeviceSize bufferSize = 0;
624 	if (!isCombinedType)
625 		bufferSize = vk::mapVkFormat(m_format).getPixelSize() *width*height*depth;
626 	if (isCombinedType)
627 	{
628 		int pixelSize = 0;
629 		switch (m_format)
630 		{
631 			case vk::VK_FORMAT_D16_UNORM_S8_UINT:
632 				pixelSize = (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT) ? 2 : 1;
633 				break;
634 			case  vk::VK_FORMAT_D32_SFLOAT_S8_UINT:
635 				pixelSize = (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT) ? 4 : 1;
636 				break;
637 			case vk::VK_FORMAT_X8_D24_UNORM_PACK32:
638 			case vk::VK_FORMAT_D24_UNORM_S8_UINT:
639 				pixelSize = (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT) ? 3 : 1;
640 				break;
641 
642 			default:
643 				DE_FATAL("Not implemented");
644 		}
645 		bufferSize = pixelSize*width*height*depth;
646 	}
647 	BufferCreateInfo stagingBufferResourceCreateInfo(bufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT | vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
648 	stagingResource = Buffer::createAndAlloc(m_vk, m_device, stagingBufferResourceCreateInfo, allocator, vk::MemoryRequirement::HostVisible);
649 	deUint8* destPtr = reinterpret_cast<deUint8*>(stagingResource->getBoundMemory().getHostPtr());
650 	deMemcpy(destPtr, data, static_cast<size_t>(bufferSize));
651 	vk::flushAlloc(m_vk, m_device, stagingResource->getBoundMemory());
652 	{
653 		CmdPoolCreateInfo copyCmdPoolCreateInfo(m_queueFamilyIndex);
654 		vk::Unique<vk::VkCommandPool> copyCmdPool(vk::createCommandPool(m_vk, m_device, &copyCmdPoolCreateInfo));
655 		vk::Unique<vk::VkCommandBuffer> copyCmdBuffer(vk::allocateCommandBuffer(m_vk, m_device, *copyCmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
656 
657 		beginCommandBuffer(m_vk, *copyCmdBuffer);
658 
659 		if (layout == vk::VK_IMAGE_LAYOUT_UNDEFINED)
660 		{
661 			layout = vk::VK_IMAGE_LAYOUT_GENERAL;
662 
663 			vk::VkImageMemoryBarrier barrier;
664 			barrier.sType = vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
665 			barrier.pNext = DE_NULL;
666 			barrier.srcAccessMask = 0;
667 			barrier.dstAccessMask = 0;
668 			barrier.oldLayout = vk::VK_IMAGE_LAYOUT_UNDEFINED;
669 			barrier.newLayout = vk::VK_IMAGE_LAYOUT_GENERAL;
670 			barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
671 			barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
672 			barrier.image = object();
673 
674 			barrier.subresourceRange.aspectMask = aspect;
675 			barrier.subresourceRange.baseMipLevel = 0;
676 			barrier.subresourceRange.levelCount = m_levelCount;
677 			barrier.subresourceRange.baseArrayLayer = 0;
678 			barrier.subresourceRange.layerCount = m_layerCount;
679 
680 			m_vk.cmdPipelineBarrier(*copyCmdBuffer, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (vk::VkDependencyFlags)0,
681 									0, (const vk::VkMemoryBarrier*)DE_NULL,
682 									0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
683 									1, &barrier);
684 		}
685 
686 		vk::VkBufferImageCopy region = {
687 			0, 0, 0,
688 			{ (vk::VkImageAspectFlags)aspect, mipLevel, arrayElement, 1 },
689 			offset,
690 			{ (deUint32)width, (deUint32)height, (deUint32)depth }
691 		};
692 
693 		m_vk.cmdCopyBufferToImage(*copyCmdBuffer, stagingResource->object(),
694 			object(), layout, 1, &region);
695 		endCommandBuffer(m_vk, *copyCmdBuffer);
696 
697 		submitCommandsAndWait(m_vk, m_device, queue, copyCmdBuffer.get());
698 	}
699 }
700 
uploadLinear(vk::VkOffset3D offset,int width,int height,int depth,unsigned int mipLevel,unsigned int arrayElement,vk::VkImageAspectFlagBits aspect,const void * data)701 void Image::uploadLinear (vk::VkOffset3D			offset,
702 						  int						width,
703 						  int						height,
704 						  int						depth,
705 						  unsigned int				mipLevel,
706 						  unsigned int				arrayElement,
707 						  vk::VkImageAspectFlagBits	aspect,
708 						  const void *				data)
709 {
710 	DE_ASSERT(mipLevel < m_levelCount);
711 	DE_ASSERT(arrayElement < m_layerCount);
712 
713 	vk::VkSubresourceLayout imageLayout;
714 
715 	vk::VkImageSubresource imageSubResource = { (vk::VkImageAspectFlags)aspect, mipLevel, arrayElement};
716 
717 	m_vk.getImageSubresourceLayout(m_device, object(), &imageSubResource,
718 													&imageLayout);
719 
720 	deUint8* destPtr = reinterpret_cast<deUint8*>(getBoundMemory().getHostPtr());
721 	destPtr += imageLayout.offset;
722 	destPtr += offset.z * imageLayout.depthPitch;
723 	destPtr += offset.y * imageLayout.rowPitch;
724 	destPtr += offset.x;
725 
726 	MemoryOp::pack(vk::mapVkFormat(m_format).getPixelSize(), width, height, depth,
727 		imageLayout.rowPitch, imageLayout.depthPitch, data, destPtr);
728 }
729 
bindMemory(de::MovePtr<vk::Allocation> allocation)730 void Image::bindMemory (de::MovePtr<vk::Allocation> allocation)
731 {
732 	DE_ASSERT(allocation);
733 	VK_CHECK(m_vk.bindImageMemory(m_device, *m_object, allocation->getMemory(), allocation->getOffset()));
734 
735 	DE_ASSERT(!m_allocation);
736 	m_allocation = allocation;
737 }
738 
createAndAlloc(const vk::DeviceInterface & vk,vk::VkDevice device,const vk::VkImageCreateInfo & createInfo,vk::Allocator & allocator,deUint32 queueFamilyIndex,vk::MemoryRequirement memoryRequirement)739 de::SharedPtr<Image> Image::createAndAlloc(const vk::DeviceInterface&	vk,
740 										   vk::VkDevice					device,
741 										   const vk::VkImageCreateInfo& createInfo,
742 										   vk::Allocator&				allocator,
743 										   deUint32						queueFamilyIndex,
744 										   vk::MemoryRequirement		memoryRequirement)
745 {
746 	de::SharedPtr<Image> ret = create(vk, device, createInfo, queueFamilyIndex);
747 
748 	vk::VkMemoryRequirements imageRequirements = vk::getImageMemoryRequirements(vk, device, ret->object());
749 	ret->bindMemory(allocator.allocate(imageRequirements, memoryRequirement));
750 	return ret;
751 }
752 
create(const vk::DeviceInterface & vk,vk::VkDevice device,const vk::VkImageCreateInfo & createInfo,deUint32 queueFamilyIndex)753 de::SharedPtr<Image> Image::create(const vk::DeviceInterface&	vk,
754 								   vk::VkDevice					device,
755 								   const vk::VkImageCreateInfo	&createInfo,
756 								   deUint32						queueFamilyIndex)
757 {
758 	return de::SharedPtr<Image>(new Image(vk, device, queueFamilyIndex, createInfo.format, createInfo.extent,
759 								createInfo.mipLevels, createInfo.arrayLayers, vk::createImage(vk, device, &createInfo)));
760 }
761 
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)762 void transition2DImage (const vk::DeviceInterface&	vk,
763 						vk::VkCommandBuffer			cmdBuffer,
764 						vk::VkImage					image,
765 						vk::VkImageAspectFlags		aspectMask,
766 						vk::VkImageLayout			oldLayout,
767 						vk::VkImageLayout			newLayout,
768 						vk::VkAccessFlags			srcAccessMask,
769 						vk::VkAccessFlags			dstAccessMask,
770 						vk::VkPipelineStageFlags	srcStageMask,
771 						vk::VkPipelineStageFlags	dstStageMask)
772 {
773 	vk::VkImageMemoryBarrier barrier;
774 	barrier.sType							= vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
775 	barrier.pNext							= DE_NULL;
776 	barrier.srcAccessMask					= srcAccessMask;
777 	barrier.dstAccessMask					= dstAccessMask;
778 	barrier.oldLayout						= oldLayout;
779 	barrier.newLayout						= newLayout;
780 	barrier.srcQueueFamilyIndex				= VK_QUEUE_FAMILY_IGNORED;
781 	barrier.dstQueueFamilyIndex				= VK_QUEUE_FAMILY_IGNORED;
782 	barrier.image							= image;
783 	barrier.subresourceRange.aspectMask		= aspectMask;
784 	barrier.subresourceRange.baseMipLevel	= 0;
785 	barrier.subresourceRange.levelCount		= 1;
786 	barrier.subresourceRange.baseArrayLayer = 0;
787 	barrier.subresourceRange.layerCount		= 1;
788 
789 	vk.cmdPipelineBarrier(cmdBuffer, srcStageMask, dstStageMask, (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier*)DE_NULL,
790 						  0, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1, &barrier);
791 }
792 
initialTransitionColor2DImage(const vk::DeviceInterface & vk,vk::VkCommandBuffer cmdBuffer,vk::VkImage image,vk::VkImageLayout layout,vk::VkAccessFlags dstAccessMask,vk::VkPipelineStageFlags dstStageMask)793 void initialTransitionColor2DImage (const vk::DeviceInterface &vk, vk::VkCommandBuffer cmdBuffer, vk::VkImage image, vk::VkImageLayout layout,
794 									vk::VkAccessFlags dstAccessMask, vk::VkPipelineStageFlags dstStageMask)
795 {
796 	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);
797 }
798 
initialTransitionDepth2DImage(const vk::DeviceInterface & vk,vk::VkCommandBuffer cmdBuffer,vk::VkImage image,vk::VkImageLayout layout,vk::VkAccessFlags dstAccessMask,vk::VkPipelineStageFlags dstStageMask)799 void initialTransitionDepth2DImage (const vk::DeviceInterface &vk, vk::VkCommandBuffer cmdBuffer, vk::VkImage image, vk::VkImageLayout layout,
800 									vk::VkAccessFlags dstAccessMask, vk::VkPipelineStageFlags dstStageMask)
801 {
802 	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);
803 }
804 
initialTransitionStencil2DImage(const vk::DeviceInterface & vk,vk::VkCommandBuffer cmdBuffer,vk::VkImage image,vk::VkImageLayout layout,vk::VkAccessFlags dstAccessMask,vk::VkPipelineStageFlags dstStageMask)805 void initialTransitionStencil2DImage (const vk::DeviceInterface &vk, vk::VkCommandBuffer cmdBuffer, vk::VkImage image, vk::VkImageLayout layout,
806 									  vk::VkAccessFlags dstAccessMask, vk::VkPipelineStageFlags dstStageMask)
807 {
808 	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);
809 }
810 
initialTransitionDepthStencil2DImage(const vk::DeviceInterface & vk,vk::VkCommandBuffer cmdBuffer,vk::VkImage image,vk::VkImageLayout layout,vk::VkAccessFlags dstAccessMask,vk::VkPipelineStageFlags dstStageMask)811 void initialTransitionDepthStencil2DImage (const vk::DeviceInterface&	vk,
812 										   vk::VkCommandBuffer			cmdBuffer,
813 										   vk::VkImage					image,
814 										   vk::VkImageLayout			layout,
815 										   vk::VkAccessFlags			dstAccessMask,
816 										   vk::VkPipelineStageFlags		dstStageMask)
817 {
818 	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);
819 }
820 
821 } // Draw
822 } // vkt
823