• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
pack(int pixelSize,int width,int height,int depth,vk::VkDeviceSize rowPitchOrZero,vk::VkDeviceSize depthPitchOrZero,const void * srcBuffer,void * destBuffer)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 
unpack(int pixelSize,int width,int height,int depth,vk::VkDeviceSize rowPitchOrZero,vk::VkDeviceSize depthPitchOrZero,const void * srcBuffer,void * destBuffer)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 
Image(const vk::DeviceInterface & vk,vk::VkDevice device,vk::VkFormat format,const vk::VkExtent3D & extend,deUint32 levelCount,deUint32 layerCount,vk::Move<vk::VkImage> object_)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 
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)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 
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)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 
readSurface1D(vk::VkQueue queue,vk::Allocator & allocator,vk::VkImageLayout layout,vk::VkOffset3D offset,int width,vk::VkImageAspectFlagBits aspect,unsigned int mipLevel,unsigned int arrayElement)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 
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)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 
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)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::VK_QUEUE_FAMILY_IGNORED;
335 			barrier.dstQueueFamilyIndex = vk::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 			{ 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 
readSurfaceLinear(vk::VkOffset3D offset,int width,int height,int depth,vk::VkImageAspectFlagBits aspect,unsigned int mipLevel,unsigned int arrayElement)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 
readLinear(vk::VkOffset3D offset,int width,int height,int depth,unsigned int mipLevel,unsigned int arrayElement,vk::VkImageAspectFlagBits aspect,void * data)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 = { aspect, mipLevel, arrayElement };
406 
407 	vk::VkSubresourceLayout imageLayout;
408 
409 	deMemset(&imageLayout, 0, sizeof(imageLayout));
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 
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)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 = { {aspect, mipLevel, arrayElement, 1}, offset, {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 
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)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 
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)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 
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)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 
uploadSurfaceLinear(const tcu::ConstPixelBufferAccess & access,vk::VkOffset3D offset,int width,int height,int depth,vk::VkImageAspectFlagBits aspect,unsigned int mipLevel,unsigned int arrayElement)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 
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)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::VK_QUEUE_FAMILY_IGNORED;
621 			barrier.dstQueueFamilyIndex = vk::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 = {{aspect, 0, 0, 1},
639 									zeroOffset,
640 									{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 
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)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::VK_QUEUE_FAMILY_IGNORED;
742 			barrier.dstQueueFamilyIndex = vk::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 			{ 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 
uploadLinear(vk::VkOffset3D offset,int width,int height,int depth,unsigned int mipLevel,unsigned int arrayElement,vk::VkImageAspectFlagBits aspect,const void * data)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 = {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 
getPixelOffset(vk::VkOffset3D offset,vk::VkDeviceSize rowPitch,vk::VkDeviceSize depthPitch,unsigned int level,unsigned int layer)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 
bindMemory(de::MovePtr<vk::Allocation> allocation)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 
createAndAlloc(const vk::DeviceInterface & vk,vk::VkDevice device,const vk::VkImageCreateInfo & createInfo,vk::Allocator & allocator,vk::MemoryRequirement memoryRequirement)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 
create(const vk::DeviceInterface & vk,vk::VkDevice device,const vk::VkImageCreateInfo & createInfo)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 
transition2DImage(const vk::DeviceInterface & vk,vk::VkCommandBuffer cmdBuffer,vk::VkImage image,vk::VkImageAspectFlags aspectMask,vk::VkImageLayout oldLayout,vk::VkImageLayout newLayout)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 {
885 	vk::VkImageMemoryBarrier barrier;
886 	barrier.sType							= vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
887 	barrier.pNext							= DE_NULL;
888 	barrier.srcAccessMask					= 0;
889 	barrier.dstAccessMask					= 0;
890 	barrier.oldLayout						= oldLayout;
891 	barrier.newLayout						= newLayout;
892 	barrier.srcQueueFamilyIndex				= vk::VK_QUEUE_FAMILY_IGNORED;
893 	barrier.dstQueueFamilyIndex				= vk::VK_QUEUE_FAMILY_IGNORED;
894 	barrier.image							= image;
895 	barrier.subresourceRange.aspectMask		= aspectMask;
896 	barrier.subresourceRange.baseMipLevel	= 0;
897 	barrier.subresourceRange.levelCount		= 1;
898 	barrier.subresourceRange.baseArrayLayer = 0;
899 	barrier.subresourceRange.layerCount		= 1;
900 
901 	vk.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (vk::VkDependencyFlags)0,
902 						  0, (const vk::VkMemoryBarrier*)DE_NULL,
903 						  0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
904 						  1, &barrier);
905 }
906 
initialTransitionColor2DImage(const vk::DeviceInterface & vk,vk::VkCommandBuffer cmdBuffer,vk::VkImage image,vk::VkImageLayout layout)907 void initialTransitionColor2DImage (const vk::DeviceInterface &vk, vk::VkCommandBuffer cmdBuffer, vk::VkImage image, vk::VkImageLayout layout)
908 {
909 	transition2DImage(vk, cmdBuffer, image, vk::VK_IMAGE_ASPECT_COLOR_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, layout);
910 }
911 
initialTransitionDepth2DImage(const vk::DeviceInterface & vk,vk::VkCommandBuffer cmdBuffer,vk::VkImage image,vk::VkImageLayout layout)912 void initialTransitionDepth2DImage (const vk::DeviceInterface &vk, vk::VkCommandBuffer cmdBuffer, vk::VkImage image, vk::VkImageLayout layout)
913 {
914 	transition2DImage(vk, cmdBuffer, image, vk::VK_IMAGE_ASPECT_DEPTH_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, layout);
915 }
916 
initialTransitionStencil2DImage(const vk::DeviceInterface & vk,vk::VkCommandBuffer cmdBuffer,vk::VkImage image,vk::VkImageLayout layout)917 void initialTransitionStencil2DImage (const vk::DeviceInterface &vk, vk::VkCommandBuffer cmdBuffer, vk::VkImage image, vk::VkImageLayout layout)
918 {
919 	transition2DImage(vk, cmdBuffer, image, vk::VK_IMAGE_ASPECT_STENCIL_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, layout);
920 }
921 
initialTransitionDepthStencil2DImage(const vk::DeviceInterface & vk,vk::VkCommandBuffer cmdBuffer,vk::VkImage image,vk::VkImageLayout layout)922 void initialTransitionDepthStencil2DImage (const vk::DeviceInterface &vk, vk::VkCommandBuffer cmdBuffer, vk::VkImage image, vk::VkImageLayout layout)
923 {
924 	transition2DImage(vk, cmdBuffer, image, vk::VK_IMAGE_ASPECT_DEPTH_BIT | vk::VK_IMAGE_ASPECT_STENCIL_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, layout);
925 }
926 
927 } // Draw
928 } // vkt
929