1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2015 The Khronos Group Inc.
6 * Copyright (c) 2015 Intel Corporation
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and/or associated documentation files (the
10 * "Materials"), to deal in the Materials without restriction, including
11 * without limitation the rights to use, copy, modify, merge, publish,
12 * distribute, sublicense, and/or sell copies of the Materials, and to
13 * permit persons to whom the Materials are furnished to do so, subject to
14 * the following conditions:
16 * The above copyright notice(s) and this permission notice shall be included
17 * in all copies or substantial portions of the Materials.
19 * The Materials are Confidential Information as defined by the
20 * Khronos Membership Agreement until designated non-confidential by Khronos,
21 * at which point this condition clause shall be removed.
23 * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
26 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
27 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
28 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
29 * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
33 * \brief Image Object Util
34 *//*--------------------------------------------------------------------*/
36 #include "vktQueryPoolImageObjectUtil.hpp"
38 #include "tcuSurface.hpp"
39 #include "tcuVectorUtil.hpp"
41 #include "vkRefUtil.hpp"
42 #include "vkQueryUtil.hpp"
43 #include "vkImageUtil.hpp"
44 #include "vktQueryPoolCreateInfoUtil.hpp"
45 #include "vktQueryPoolBufferObjectUtil.hpp"
47 #include "tcuTextureUtil.hpp"
54 void MemoryOp::pack (int pixelSize,
58 vk::VkDeviceSize rowPitchOrZero,
59 vk::VkDeviceSize depthPitchOrZero,
60 const void * srcBuffer,
63 vk::VkDeviceSize rowPitch = rowPitchOrZero;
64 vk::VkDeviceSize depthPitch = depthPitchOrZero;
67 rowPitch = width * pixelSize;
70 depthPitch = rowPitch * height;
72 const vk::VkDeviceSize size = depthPitch * depth;
74 const char *srcRow = reinterpret_cast<const char *>(srcBuffer);
77 char *dstRow = reinterpret_cast<char *>(destBuffer);
81 if (rowPitch == static_cast<vk::VkDeviceSize>(width * pixelSize) &&
82 depthPitch == static_cast<vk::VkDeviceSize>(rowPitch * height))
85 deMemcpy(dstRow, srcRow, static_cast<size_t>(size));
89 // slower, per row path
90 for (int d = 0; d < depth; d++)
92 vk::VkDeviceSize offsetDepthDst = d * depthPitch;
93 vk::VkDeviceSize offsetDepthSrc = d * (pixelSize * width * height);
94 srcRow = srcStart + offsetDepthSrc;
95 dstRow = dstStart + offsetDepthDst;
96 for (int r = 0; r < height; ++r)
98 deMemcpy(dstRow, srcRow, static_cast<size_t>(rowPitch));
99 srcRow += pixelSize * width;
106 void MemoryOp::unpack (int pixelSize,
110 vk::VkDeviceSize rowPitchOrZero,
111 vk::VkDeviceSize depthPitchOrZero,
112 const void * srcBuffer,
115 vk::VkDeviceSize rowPitch = rowPitchOrZero;
116 vk::VkDeviceSize depthPitch = depthPitchOrZero;
119 rowPitch = width * pixelSize;
122 depthPitch = rowPitch * height;
124 const vk::VkDeviceSize size = depthPitch * depth;
126 const char *srcRow = reinterpret_cast<const char *>(srcBuffer);
127 const char *srcStart;
129 char *dstRow = reinterpret_cast<char *>(destBuffer);
133 if (rowPitch == static_cast<vk::VkDeviceSize>(width * pixelSize) &&
134 depthPitch == static_cast<vk::VkDeviceSize>(rowPitch * height))
137 deMemcpy(dstRow, srcRow, static_cast<size_t>(size));
141 // slower, per row path
142 for (size_t d = 0; d < (size_t)depth; d++)
144 vk::VkDeviceSize offsetDepthDst = d * (pixelSize * width * height);
145 vk::VkDeviceSize offsetDepthSrc = d * depthPitch;
146 srcRow = srcStart + offsetDepthSrc;
147 dstRow = dstStart + offsetDepthDst;
148 for (int r = 0; r < height; ++r)
150 deMemcpy(dstRow, srcRow, static_cast<size_t>(pixelSize * width));
152 dstRow += pixelSize * width;
158 Image::Image (const vk::DeviceInterface& vk,
161 const vk::VkExtent3D& extend,
164 vk::Move<vk::VkImage> object_)
165 : m_allocation (DE_NULL)
169 , m_levelCount (levelCount)
170 , m_layerCount (layerCount)
176 tcu::ConstPixelBufferAccess Image::readSurface (vk::VkQueue queue,
177 vk::Allocator& allocator,
178 vk::VkImageLayout layout,
179 vk::VkOffset3D offset,
182 vk::VkImageAspectFlagBits aspect,
183 unsigned int mipLevel,
184 unsigned int arrayElement)
186 m_pixelAccessData.resize(width * height * vk::mapVkFormat(m_format).getPixelSize());
187 deMemset(m_pixelAccessData.data(), 0, m_pixelAccessData.size());
188 if (aspect == vk::VK_IMAGE_ASPECT_COLOR_BIT)
190 read(queue, allocator, layout, offset, width, height, 1, mipLevel, arrayElement, aspect, vk::VK_IMAGE_TYPE_2D,
191 m_pixelAccessData.data());
193 if (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT || aspect == vk::VK_IMAGE_ASPECT_STENCIL_BIT)
195 readUsingBuffer(queue, allocator, layout, offset, width, height, 1, mipLevel, arrayElement, aspect, m_pixelAccessData.data());
197 return tcu::ConstPixelBufferAccess(vk::mapVkFormat(m_format), width, height, 1, m_pixelAccessData.data());
200 tcu::ConstPixelBufferAccess Image::readVolume (vk::VkQueue queue,
201 vk::Allocator& allocator,
202 vk::VkImageLayout layout,
203 vk::VkOffset3D offset,
207 vk::VkImageAspectFlagBits aspect,
208 unsigned int mipLevel,
209 unsigned int arrayElement)
211 m_pixelAccessData.resize(width * height * depth * vk::mapVkFormat(m_format).getPixelSize());
212 deMemset(m_pixelAccessData.data(), 0, m_pixelAccessData.size());
213 if (aspect == vk::VK_IMAGE_ASPECT_COLOR_BIT)
215 read(queue, allocator, layout, offset, width, height, depth, mipLevel, arrayElement, aspect, vk::VK_IMAGE_TYPE_3D,
216 m_pixelAccessData.data());
218 if (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT || aspect == vk::VK_IMAGE_ASPECT_STENCIL_BIT)
220 readUsingBuffer(queue, allocator, layout, offset, width, height, depth, mipLevel, arrayElement, aspect, m_pixelAccessData.data());
222 return tcu::ConstPixelBufferAccess(vk::mapVkFormat(m_format), width, height, depth, m_pixelAccessData.data());
225 tcu::ConstPixelBufferAccess Image::readSurface1D(vk::VkQueue queue,
226 vk::Allocator& allocator,
227 vk::VkImageLayout layout,
228 vk::VkOffset3D offset,
230 vk::VkImageAspectFlagBits aspect,
231 unsigned int mipLevel,
232 unsigned int arrayElement)
234 m_pixelAccessData.resize(width * vk::mapVkFormat(m_format).getPixelSize());
235 deMemset(m_pixelAccessData.data(), 0, m_pixelAccessData.size());
236 if (aspect == vk::VK_IMAGE_ASPECT_COLOR_BIT)
238 read(queue, allocator, layout, offset, width, 1, 1, mipLevel, arrayElement, aspect, vk::VK_IMAGE_TYPE_1D,
239 m_pixelAccessData.data());
241 if (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT || aspect == vk::VK_IMAGE_ASPECT_STENCIL_BIT)
243 readUsingBuffer(queue, allocator, layout, offset, width, 1, 1, mipLevel, arrayElement, aspect,
244 m_pixelAccessData.data());
246 return tcu::ConstPixelBufferAccess(vk::mapVkFormat(m_format), width, 1, 1, m_pixelAccessData.data());
249 void Image::read (vk::VkQueue queue,
250 vk::Allocator& allocator,
251 vk::VkImageLayout layout,
252 vk::VkOffset3D offset,
256 unsigned int mipLevel,
257 unsigned int arrayElement,
258 vk::VkImageAspectFlagBits aspect,
259 vk::VkImageType type,
262 DE_ASSERT(layout == vk::VK_IMAGE_LAYOUT_GENERAL || layout == vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
264 de::SharedPtr<Image> stagingResource = copyToLinearImage(queue, allocator, layout, offset, width,
265 height, depth, mipLevel, arrayElement, aspect, type);
266 const vk::VkOffset3D zeroOffset = {0, 0, 0};
267 stagingResource->readLinear(zeroOffset, width, height, depth, 0, 0, aspect, data);
270 void Image::readUsingBuffer (vk::VkQueue queue,
271 vk::Allocator& allocator,
272 vk::VkImageLayout layout,
273 vk::VkOffset3D offset,
277 unsigned int mipLevel,
278 unsigned int arrayElement,
279 vk::VkImageAspectFlagBits aspect,
282 DE_ASSERT(layout == vk::VK_IMAGE_LAYOUT_GENERAL || layout == vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);;
284 de::SharedPtr<Buffer> stagingResource;
286 bool isCombinedType = isCombinedDepthStencilType(vk::mapVkFormat(m_format).type);
287 vk::VkDeviceSize bufferSize = 0;
290 bufferSize = vk::mapVkFormat(m_format).getPixelSize() * width * height * depth;
297 case vk::VK_FORMAT_D16_UNORM_S8_UINT:
298 pixelSize = (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT) ? 2 : 1;
300 case vk::VK_FORMAT_D32_SFLOAT_S8_UINT:
301 pixelSize = (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT) ? 4 : 1;
303 case vk::VK_FORMAT_X8_D24_UNORM_PACK32:
304 case vk::VK_FORMAT_D24_UNORM_S8_UINT:
305 pixelSize = (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT) ? 3 : 1;
309 DE_FATAL("Not implemented");
311 bufferSize = pixelSize*width*height*depth;
314 BufferCreateInfo stagingBufferResourceCreateInfo(bufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT | vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
315 stagingResource = Buffer::createAndAlloc(m_vk, m_device, stagingBufferResourceCreateInfo, allocator, vk::MemoryRequirement::HostVisible);
318 //todo [scygan] get proper queueFamilyIndex
319 CmdPoolCreateInfo copyCmdPoolCreateInfo(0);
320 vk::Unique<vk::VkCommandPool> copyCmdPool(vk::createCommandPool(m_vk, m_device, ©CmdPoolCreateInfo));
322 const vk::VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
324 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
325 DE_NULL, // const void* pNext;
326 *copyCmdPool, // VkCommandPool commandPool;
327 vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCommandBufferLevel level;
328 1u, // deUint32 bufferCount;
330 vk::Unique<vk::VkCommandBuffer> copyCmdBuffer(vk::allocateCommandBuffer(m_vk, m_device, &cmdBufferAllocateInfo));
332 CmdBufferBeginInfo beginInfo;
333 VK_CHECK(m_vk.beginCommandBuffer(*copyCmdBuffer, &beginInfo));
335 if (layout == vk::VK_IMAGE_LAYOUT_UNDEFINED)
337 layout = vk::VK_IMAGE_LAYOUT_GENERAL;
339 vk::VkImageMemoryBarrier barrier;
340 barrier.sType = vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
341 barrier.pNext = DE_NULL;
342 barrier.srcAccessMask = 0;
343 barrier.dstAccessMask = 0;
344 barrier.oldLayout = vk::VK_IMAGE_LAYOUT_UNDEFINED;
345 barrier.newLayout = vk::VK_IMAGE_LAYOUT_GENERAL;
346 barrier.srcQueueFamilyIndex = vk::VK_QUEUE_FAMILY_IGNORED;
347 barrier.dstQueueFamilyIndex = vk::VK_QUEUE_FAMILY_IGNORED;
348 barrier.image = object();
350 barrier.subresourceRange.aspectMask = aspect;
351 barrier.subresourceRange.baseMipLevel = 0;
352 barrier.subresourceRange.levelCount = m_levelCount;
353 barrier.subresourceRange.baseArrayLayer = 0;
354 barrier.subresourceRange.layerCount = m_layerCount;
356 void* barriers[] = { &barrier };
358 m_vk.cmdPipelineBarrier(*copyCmdBuffer, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
359 false, DE_LENGTH_OF_ARRAY(barriers), barriers);
362 const vk::VkBufferImageCopy region =
365 { aspect, mipLevel, arrayElement, 1 },
367 { width, height, depth }
370 m_vk.cmdCopyImageToBuffer(*copyCmdBuffer, object(), layout, stagingResource->object(), 1, ®ion);
371 VK_CHECK(m_vk.endCommandBuffer(*copyCmdBuffer));
373 const vk::VkSubmitInfo submitInfo =
375 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
376 DE_NULL, // const void* pNext;
377 0, // deUint32 waitSemaphoreCount;
378 DE_NULL, // const VkSemaphore* pWaitSemaphores;
379 1, // deUint32 commandBufferCount;
380 ©CmdBuffer.get(), // const VkCommandBuffer* pCommandBuffers;
381 0, // deUint32 signalSemaphoreCount;
382 DE_NULL // const VkSemaphore* pSignalSemaphores;
384 m_vk.queueSubmit(queue, 1, &submitInfo, DE_NULL);
386 // TODO: make this less intrusive
387 VK_CHECK(m_vk.queueWaitIdle(queue));
390 char* destPtr = reinterpret_cast<char*>(stagingResource->getBoundMemory().getHostPtr());
391 deMemcpy(data, destPtr, static_cast<size_t>(bufferSize));
394 tcu::ConstPixelBufferAccess Image::readSurfaceLinear (vk::VkOffset3D offset,
398 vk::VkImageAspectFlagBits aspect,
399 unsigned int mipLevel,
400 unsigned int arrayElement)
402 m_pixelAccessData.resize(width * height * vk::mapVkFormat(m_format).getPixelSize());
403 readLinear(offset, width, height, depth, mipLevel, arrayElement, aspect, m_pixelAccessData.data());
404 return tcu::ConstPixelBufferAccess(vk::mapVkFormat(m_format), width, height, 1, m_pixelAccessData.data());
407 void Image::readLinear (vk::VkOffset3D offset,
411 unsigned int mipLevel,
412 unsigned int arrayElement,
413 vk::VkImageAspectFlagBits aspect,
416 vk::VkImageSubresource imageSubResource = { aspect, mipLevel, arrayElement };
418 vk::VkSubresourceLayout imageLayout;
419 deMemset(&imageLayout, 0, sizeof(imageLayout));
421 m_vk.getImageSubresourceLayout(m_device, object(), &imageSubResource, &imageLayout);
423 const char* srcPtr = reinterpret_cast<const char*>(getBoundMemory().getHostPtr());
424 srcPtr += imageLayout.offset + getPixelOffset(offset, imageLayout.rowPitch, imageLayout.depthPitch, mipLevel, arrayElement);
426 MemoryOp::unpack(vk::mapVkFormat(m_format).getPixelSize(), width, height, depth,
427 imageLayout.rowPitch, imageLayout.depthPitch, srcPtr, data);
430 de::SharedPtr<Image> Image::copyToLinearImage (vk::VkQueue queue,
431 vk::Allocator& allocator,
432 vk::VkImageLayout layout,
433 vk::VkOffset3D offset,
437 unsigned int mipLevel,
438 unsigned int arrayElement,
439 vk::VkImageAspectFlagBits aspect,
440 vk::VkImageType type)
442 de::SharedPtr<Image> stagingResource;
444 vk::VkExtent3D stagingExtent = {width, height, depth};
445 ImageCreateInfo stagingResourceCreateInfo(type, m_format, stagingExtent, 1, 1, vk::VK_SAMPLE_COUNT_1_BIT,
446 vk::VK_IMAGE_TILING_LINEAR, vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT);
448 stagingResource = Image::createAndAlloc(m_vk, m_device, stagingResourceCreateInfo, allocator,
449 vk::MemoryRequirement::HostVisible);
451 //todo [scygan] get proper queueFamilyIndex
452 CmdPoolCreateInfo copyCmdPoolCreateInfo(0);
453 vk::Unique<vk::VkCommandPool> copyCmdPool(vk::createCommandPool(m_vk, m_device, ©CmdPoolCreateInfo));
455 const vk::VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
457 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
458 DE_NULL, // const void* pNext;
459 *copyCmdPool, // VkCommandPool commandPool;
460 vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCommandBufferLevel level;
461 1u, // deUint32 bufferCount;
463 vk::Unique<vk::VkCommandBuffer> copyCmdBuffer(vk::allocateCommandBuffer(m_vk, m_device, &cmdBufferAllocateInfo));
465 CmdBufferBeginInfo beginInfo;
466 VK_CHECK(m_vk.beginCommandBuffer(*copyCmdBuffer, &beginInfo));
468 transition2DImage(m_vk, *copyCmdBuffer, stagingResource->object(), aspect, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_GENERAL);
470 const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
471 vk::VkImageCopy region = { {aspect, mipLevel, arrayElement, 1}, offset, {aspect, 0, 0, 1}, zeroOffset, {width, height, depth} };
473 m_vk.cmdCopyImage(*copyCmdBuffer, object(), layout, stagingResource->object(), vk::VK_IMAGE_LAYOUT_GENERAL, 1, ®ion);
474 VK_CHECK(m_vk.endCommandBuffer(*copyCmdBuffer));
476 const vk::VkSubmitInfo submitInfo =
478 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
479 DE_NULL, // const void* pNext;
480 0, // deUint32 waitSemaphoreCount;
481 DE_NULL, // const VkSemaphore* pWaitSemaphores;
482 1, // deUint32 commandBufferCount;
483 ©CmdBuffer.get(), // const VkCommandBuffer* pCommandBuffers;
484 0, // deUint32 signalSemaphoreCount;
485 DE_NULL // const VkSemaphore* pSignalSemaphores;
487 m_vk.queueSubmit(queue, 1, &submitInfo, DE_NULL);
489 // TODO: make this less intrusive
490 VK_CHECK(m_vk.queueWaitIdle(queue));
492 return stagingResource;
495 void Image::uploadVolume(const tcu::ConstPixelBufferAccess& access,
497 vk::Allocator& allocator,
498 vk::VkImageLayout layout,
499 vk::VkOffset3D offset,
500 vk::VkImageAspectFlagBits aspect,
501 unsigned int mipLevel,
502 unsigned int arrayElement)
504 if (aspect == vk::VK_IMAGE_ASPECT_COLOR_BIT)
506 upload(queue, allocator, layout, offset, access.getWidth(),
507 access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, vk::VK_IMAGE_TYPE_3D,
508 access.getDataPtr());
510 if (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT || aspect == vk::VK_IMAGE_ASPECT_STENCIL_BIT)
512 uploadUsingBuffer(queue, allocator, layout, offset, access.getWidth(),
513 access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, access.getDataPtr());
517 void Image::uploadSurface (const tcu::ConstPixelBufferAccess& access,
519 vk::Allocator& allocator,
520 vk::VkImageLayout layout,
521 vk::VkOffset3D offset,
522 vk::VkImageAspectFlagBits aspect,
523 unsigned int mipLevel,
524 unsigned int arrayElement)
526 if (aspect == vk::VK_IMAGE_ASPECT_COLOR_BIT)
528 upload(queue, allocator, layout, offset, access.getWidth(),
529 access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, vk::VK_IMAGE_TYPE_2D,
530 access.getDataPtr());
532 if (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT || aspect == vk::VK_IMAGE_ASPECT_STENCIL_BIT)
534 uploadUsingBuffer(queue, allocator, layout, offset, access.getWidth(),
535 access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, access.getDataPtr());
539 void Image::uploadSurface1D (const tcu::ConstPixelBufferAccess& access,
541 vk::Allocator& allocator,
542 vk::VkImageLayout layout,
543 vk::VkOffset3D offset,
544 vk::VkImageAspectFlagBits aspect,
545 unsigned int mipLevel,
546 unsigned int arrayElement)
548 if (aspect == vk::VK_IMAGE_ASPECT_COLOR_BIT)
550 upload(queue, allocator, layout, offset, access.getWidth(),
551 access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, vk::VK_IMAGE_TYPE_1D,
552 access.getDataPtr());
554 if (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT || aspect == vk::VK_IMAGE_ASPECT_STENCIL_BIT)
556 uploadUsingBuffer(queue, allocator, layout, offset, access.getWidth(),
557 access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, access.getDataPtr());
561 void Image::uploadSurfaceLinear (const tcu::ConstPixelBufferAccess& access,
562 vk::VkOffset3D offset,
566 vk::VkImageAspectFlagBits aspect,
567 unsigned int mipLevel,
568 unsigned int arrayElement)
570 uploadLinear(offset, width, height, depth, mipLevel, arrayElement, aspect, access.getDataPtr());
573 void Image::upload (vk::VkQueue queue,
574 vk::Allocator& allocator,
575 vk::VkImageLayout layout,
576 vk::VkOffset3D offset,
580 unsigned int mipLevel,
581 unsigned int arrayElement,
582 vk::VkImageAspectFlagBits aspect,
583 vk::VkImageType type,
586 DE_ASSERT(layout == vk::VK_IMAGE_LAYOUT_GENERAL || layout == vk::VK_IMAGE_LAYOUT_UNDEFINED || layout == vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
588 de::SharedPtr<Image> stagingResource;
589 vk::VkExtent3D extent = {width, height, depth};
590 ImageCreateInfo stagingResourceCreateInfo(
591 type, m_format, extent, 1, 1, vk::VK_SAMPLE_COUNT_1_BIT,
592 vk::VK_IMAGE_TILING_LINEAR, vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
594 stagingResource = Image::createAndAlloc(m_vk, m_device, stagingResourceCreateInfo, allocator,
595 vk::MemoryRequirement::HostVisible);
597 const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
598 stagingResource->uploadLinear(zeroOffset, width, height, depth, 0, 0, aspect, data);
601 //todo [scygan] get proper queueFamilyIndex
602 CmdPoolCreateInfo copyCmdPoolCreateInfo(0);
603 vk::Unique<vk::VkCommandPool> copyCmdPool(vk::createCommandPool(m_vk, m_device, ©CmdPoolCreateInfo));
605 const vk::VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
607 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
608 DE_NULL, // const void* pNext;
609 *copyCmdPool, // VkCommandPool commandPool;
610 vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCommandBufferLevel level;
611 1u, // deUint32 bufferCount;
614 vk::Unique<vk::VkCommandBuffer> copyCmdBuffer(vk::allocateCommandBuffer(m_vk, m_device, &cmdBufferAllocateInfo));
616 CmdBufferBeginInfo beginInfo;
617 VK_CHECK(m_vk.beginCommandBuffer(*copyCmdBuffer, &beginInfo));
619 if (layout == vk::VK_IMAGE_LAYOUT_UNDEFINED)
621 layout = vk::VK_IMAGE_LAYOUT_GENERAL;
623 vk::VkImageMemoryBarrier barrier;
624 barrier.sType = vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
625 barrier.pNext = DE_NULL;
626 barrier.srcAccessMask = 0;
627 barrier.dstAccessMask = 0;
628 barrier.oldLayout = vk::VK_IMAGE_LAYOUT_UNDEFINED;
629 barrier.newLayout = vk::VK_IMAGE_LAYOUT_GENERAL;
630 barrier.srcQueueFamilyIndex = vk::VK_QUEUE_FAMILY_IGNORED;
631 barrier.dstQueueFamilyIndex = vk::VK_QUEUE_FAMILY_IGNORED;
632 barrier.image = object();
634 barrier.subresourceRange.aspectMask = aspect;
635 barrier.subresourceRange.baseMipLevel = 0;
636 barrier.subresourceRange.levelCount = m_levelCount;
637 barrier.subresourceRange.baseArrayLayer = 0;
638 barrier.subresourceRange.layerCount = m_layerCount;
640 void* barriers[] = { &barrier };
642 m_vk.cmdPipelineBarrier(*copyCmdBuffer, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, false, DE_LENGTH_OF_ARRAY(barriers), barriers);
645 transition2DImage(m_vk, *copyCmdBuffer, stagingResource->object(), aspect, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_GENERAL);
647 vk::VkImageCopy region = {{aspect, 0, 0, 1},
649 {aspect, mipLevel, arrayElement, 1},
651 {width, height, depth}};
653 m_vk.cmdCopyImage(*copyCmdBuffer, stagingResource->object(),
654 vk::VK_IMAGE_LAYOUT_GENERAL, object(), layout, 1, ®ion);
655 VK_CHECK(m_vk.endCommandBuffer(*copyCmdBuffer));
657 const vk::VkSubmitInfo submitInfo =
659 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
660 DE_NULL, // const void* pNext;
661 0, // deUint32 waitSemaphoreCount;
662 DE_NULL, // const VkSemaphore* pWaitSemaphores;
663 1, // deUint32 commandBufferCount;
664 ©CmdBuffer.get(), // const VkCommandBuffer* pCommandBuffers;
665 0, // deUint32 signalSemaphoreCount;
666 DE_NULL // const VkSemaphore* pSignalSemaphores;
668 m_vk.queueSubmit(queue, 1, &submitInfo, DE_NULL);
670 // TODO: make this less intrusive
671 VK_CHECK(m_vk.queueWaitIdle(queue));
675 void Image::uploadUsingBuffer (vk::VkQueue queue,
676 vk::Allocator& allocator,
677 vk::VkImageLayout layout,
678 vk::VkOffset3D offset,
682 unsigned int mipLevel,
683 unsigned int arrayElement,
684 vk::VkImageAspectFlagBits aspect,
687 DE_ASSERT(layout == vk::VK_IMAGE_LAYOUT_GENERAL || layout == vk::VK_IMAGE_LAYOUT_UNDEFINED || layout == vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
689 de::SharedPtr<Buffer> stagingResource;
690 bool isCombinedType = isCombinedDepthStencilType(vk::mapVkFormat(m_format).type);
691 vk::VkDeviceSize bufferSize = 0;
693 bufferSize = vk::mapVkFormat(m_format).getPixelSize() *width*height*depth;
699 case vk::VK_FORMAT_D16_UNORM_S8_UINT:
700 pixelSize = (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT) ? 2 : 1;
702 case vk::VK_FORMAT_D32_SFLOAT_S8_UINT:
703 pixelSize = (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT) ? 4 : 1;
705 case vk::VK_FORMAT_X8_D24_UNORM_PACK32:
706 case vk::VK_FORMAT_D24_UNORM_S8_UINT:
707 pixelSize = (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT) ? 3 : 1;
711 DE_FATAL("Not implemented");
713 bufferSize = pixelSize*width*height*depth;
715 BufferCreateInfo stagingBufferResourceCreateInfo(bufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT | vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
716 stagingResource = Buffer::createAndAlloc(m_vk, m_device, stagingBufferResourceCreateInfo, allocator, vk::MemoryRequirement::HostVisible);
717 char* destPtr = reinterpret_cast<char*>(stagingResource->getBoundMemory().getHostPtr());
718 deMemcpy(destPtr, data, static_cast<size_t>(bufferSize));
719 vk::flushMappedMemoryRange(m_vk, m_device, stagingResource->getBoundMemory().getMemory(), stagingResource->getBoundMemory().getOffset(), bufferSize);
721 //todo [scygan] get proper queueFamilyIndex
722 CmdPoolCreateInfo copyCmdPoolCreateInfo(0);
723 vk::Unique<vk::VkCommandPool> copyCmdPool(vk::createCommandPool(m_vk, m_device, ©CmdPoolCreateInfo));
725 const vk::VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
727 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
728 DE_NULL, // const void* pNext;
729 *copyCmdPool, // VkCommandPool commandPool;
730 vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCommandBufferLevel level;
731 1u, // deUint32 bufferCount;
733 vk::Unique<vk::VkCommandBuffer> copyCmdBuffer(vk::allocateCommandBuffer(m_vk, m_device, &cmdBufferAllocateInfo));
735 CmdBufferBeginInfo beginInfo;
736 VK_CHECK(m_vk.beginCommandBuffer(*copyCmdBuffer, &beginInfo));
738 if (layout == vk::VK_IMAGE_LAYOUT_UNDEFINED)
740 layout = vk::VK_IMAGE_LAYOUT_GENERAL;
742 vk::VkImageMemoryBarrier barrier;
743 barrier.sType = vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
744 barrier.pNext = DE_NULL;
745 barrier.srcAccessMask = 0;
746 barrier.dstAccessMask = 0;
747 barrier.oldLayout = vk::VK_IMAGE_LAYOUT_UNDEFINED;
748 barrier.newLayout = vk::VK_IMAGE_LAYOUT_GENERAL;
749 barrier.srcQueueFamilyIndex = vk::VK_QUEUE_FAMILY_IGNORED;
750 barrier.dstQueueFamilyIndex = vk::VK_QUEUE_FAMILY_IGNORED;
751 barrier.image = object();
753 barrier.subresourceRange.aspectMask = aspect;
754 barrier.subresourceRange.baseMipLevel = 0;
755 barrier.subresourceRange.levelCount = m_levelCount;
756 barrier.subresourceRange.baseArrayLayer = 0;
757 barrier.subresourceRange.layerCount = m_layerCount;
759 void* barriers[] = { &barrier };
761 m_vk.cmdPipelineBarrier(*copyCmdBuffer, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, false, DE_LENGTH_OF_ARRAY(barriers), barriers);
764 vk::VkBufferImageCopy region =
767 { aspect, mipLevel, arrayElement, 1 },
769 { width, height, depth }
772 m_vk.cmdCopyBufferToImage(*copyCmdBuffer, stagingResource->object(),
773 object(), layout, 1, ®ion);
774 VK_CHECK(m_vk.endCommandBuffer(*copyCmdBuffer));
776 vk::VkSubmitInfo submitInfo =
778 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
779 DE_NULL, // const void* pNext;
780 0, // deUint32 waitSemaphoreCount;
781 DE_NULL, // const VkSemaphore* pWaitSemaphores;
782 1, // deUint32 commandBufferCount;
783 ©CmdBuffer.get(), // const VkCommandBuffer* pCommandBuffers;
784 0, // deUint32 signalSemaphoreCount;
785 DE_NULL // const VkSemaphore* pSignalSemaphores;
787 m_vk.queueSubmit(queue, 1, &submitInfo, DE_NULL);
789 // TODO: make this less intrusive
790 VK_CHECK(m_vk.queueWaitIdle(queue));
794 void Image::uploadLinear (vk::VkOffset3D offset,
798 unsigned int mipLevel,
799 unsigned int arrayElement,
800 vk::VkImageAspectFlagBits aspect,
803 vk::VkSubresourceLayout imageLayout;
805 vk::VkImageSubresource imageSubResource = {aspect, mipLevel, arrayElement};
807 m_vk.getImageSubresourceLayout(m_device, object(), &imageSubResource,
810 char* destPtr = reinterpret_cast<char*>(getBoundMemory().getHostPtr());
812 destPtr += imageLayout.offset + getPixelOffset(offset, imageLayout.rowPitch, imageLayout.depthPitch, mipLevel, arrayElement);
814 MemoryOp::pack(vk::mapVkFormat(m_format).getPixelSize(), width, height, depth,
815 imageLayout.rowPitch, imageLayout.depthPitch, data, destPtr);
818 vk::VkDeviceSize Image::getPixelOffset (vk::VkOffset3D offset,
819 vk::VkDeviceSize rowPitch,
820 vk::VkDeviceSize depthPitch,
824 DE_ASSERT(level < m_levelCount);
825 DE_ASSERT(layer < m_layerCount);
827 vk::VkDeviceSize mipLevelSizes[32];
828 vk::VkDeviceSize mipLevelRectSizes[32];
830 = tcu::IVec3(m_extent.width, m_extent.height, m_extent.depth);
832 vk::VkDeviceSize arrayElemSize = 0;
833 for (unsigned int i = 0; i < m_levelCount && (mipExtend[0] > 1 || mipExtend[1] > 1 || mipExtend[2] > 1); ++i)
835 // Rect size is just a 3D image size;
836 mipLevelSizes[i] = mipExtend[2] * depthPitch;
838 arrayElemSize += mipLevelSizes[0];
840 mipExtend = tcu::max(mipExtend / 2, tcu::IVec3(1));
843 vk::VkDeviceSize pixelOffset = layer * arrayElemSize;
844 for (size_t i = 0; i < level; ++i)
846 pixelOffset += mipLevelSizes[i];
848 pixelOffset += offset.z * mipLevelRectSizes[level];
849 pixelOffset += offset.y * rowPitch;
850 pixelOffset += offset.x;
855 void Image::bindMemory (de::MovePtr<vk::Allocation> allocation)
857 DE_ASSERT(allocation);
858 VK_CHECK(m_vk.bindImageMemory(m_device, *m_object, allocation->getMemory(), allocation->getOffset()));
860 DE_ASSERT(!m_allocation);
861 m_allocation = allocation;
864 de::SharedPtr<Image> Image::createAndAlloc(const vk::DeviceInterface& vk,
866 const vk::VkImageCreateInfo& createInfo,
867 vk::Allocator& allocator,
868 vk::MemoryRequirement memoryRequirement)
870 de::SharedPtr<Image> ret = create(vk, device, createInfo);
872 vk::VkMemoryRequirements imageRequirements = vk::getImageMemoryRequirements(vk, device, ret->object());
873 ret->bindMemory(allocator.allocate(imageRequirements, memoryRequirement));
877 de::SharedPtr<Image> Image::create(const vk::DeviceInterface& vk,
879 const vk::VkImageCreateInfo &createInfo)
881 return de::SharedPtr<Image>(new Image(vk, device, createInfo.format, createInfo.extent,
882 createInfo.mipLevels, createInfo.arrayLayers,
883 vk::createImage(vk, device, &createInfo)));
886 void transition2DImage (const vk::DeviceInterface& vk,
887 vk::VkCommandBuffer cmdBuffer,
889 vk::VkImageAspectFlags aspectMask,
890 vk::VkImageLayout oldLayout,
891 vk::VkImageLayout newLayout)
893 vk::VkImageMemoryBarrier barrier;
894 barrier.sType = vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
895 barrier.pNext = DE_NULL;
896 barrier.srcAccessMask = 0;
897 barrier.dstAccessMask = 0;
898 barrier.oldLayout = oldLayout;
899 barrier.newLayout = newLayout;
900 barrier.srcQueueFamilyIndex = vk::VK_QUEUE_FAMILY_IGNORED;
901 barrier.dstQueueFamilyIndex = vk::VK_QUEUE_FAMILY_IGNORED;
902 barrier.image = image;
903 barrier.subresourceRange.aspectMask = aspectMask;
904 barrier.subresourceRange.baseMipLevel = 0;
905 barrier.subresourceRange.levelCount = 1;
906 barrier.subresourceRange.baseArrayLayer = 0;
907 barrier.subresourceRange.layerCount = 1;
909 void* barriers[] = { &barrier };
911 vk.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, false, DE_LENGTH_OF_ARRAY(barriers), barriers);
914 void initialTransitionColor2DImage (const vk::DeviceInterface &vk, vk::VkCommandBuffer cmdBuffer, vk::VkImage image, vk::VkImageLayout layout)
916 transition2DImage(vk, cmdBuffer, image, vk::VK_IMAGE_ASPECT_COLOR_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, layout);
919 void initialTransitionDepth2DImage (const vk::DeviceInterface &vk, vk::VkCommandBuffer cmdBuffer, vk::VkImage image, vk::VkImageLayout layout)
921 transition2DImage(vk, cmdBuffer, image, vk::VK_IMAGE_ASPECT_DEPTH_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, layout);
924 void initialTransitionStencil2DImage (const vk::DeviceInterface &vk, vk::VkCommandBuffer cmdBuffer, vk::VkImage image, vk::VkImageLayout layout)
926 transition2DImage(vk, cmdBuffer, image, vk::VK_IMAGE_ASPECT_STENCIL_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, layout);
929 void initialTransitionDepthStencil2DImage (const vk::DeviceInterface &vk, vk::VkCommandBuffer cmdBuffer, vk::VkImage image, vk::VkImageLayout layout)
931 transition2DImage(vk, cmdBuffer, image, vk::VK_IMAGE_ASPECT_DEPTH_BIT | vk::VK_IMAGE_ASPECT_STENCIL_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, layout);