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 m_vk.cmdPipelineBarrier(*copyCmdBuffer, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (vk::VkDependencyFlags)0,
357 0, (const vk::VkMemoryBarrier*)DE_NULL,
358 0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
362 const vk::VkBufferImageCopy region =
365 { aspect, mipLevel, arrayElement, 1 },
367 { (deUint32)width, (deUint32)height, (deUint32)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 (const vk::VkPipelineStageFlags*)DE_NULL,
380 1, // deUint32 commandBufferCount;
381 ©CmdBuffer.get(), // const VkCommandBuffer* pCommandBuffers;
382 0, // deUint32 signalSemaphoreCount;
383 DE_NULL // const VkSemaphore* pSignalSemaphores;
385 m_vk.queueSubmit(queue, 1, &submitInfo, DE_NULL);
387 // TODO: make this less intrusive
388 VK_CHECK(m_vk.queueWaitIdle(queue));
391 char* destPtr = reinterpret_cast<char*>(stagingResource->getBoundMemory().getHostPtr());
392 deMemcpy(data, destPtr, static_cast<size_t>(bufferSize));
395 tcu::ConstPixelBufferAccess Image::readSurfaceLinear (vk::VkOffset3D offset,
399 vk::VkImageAspectFlagBits aspect,
400 unsigned int mipLevel,
401 unsigned int arrayElement)
403 m_pixelAccessData.resize(width * height * vk::mapVkFormat(m_format).getPixelSize());
404 readLinear(offset, width, height, depth, mipLevel, arrayElement, aspect, m_pixelAccessData.data());
405 return tcu::ConstPixelBufferAccess(vk::mapVkFormat(m_format), width, height, 1, m_pixelAccessData.data());
408 void Image::readLinear (vk::VkOffset3D offset,
412 unsigned int mipLevel,
413 unsigned int arrayElement,
414 vk::VkImageAspectFlagBits aspect,
417 vk::VkImageSubresource imageSubResource = { aspect, mipLevel, arrayElement };
419 vk::VkSubresourceLayout imageLayout;
420 deMemset(&imageLayout, 0, sizeof(imageLayout));
422 m_vk.getImageSubresourceLayout(m_device, object(), &imageSubResource, &imageLayout);
424 const char* srcPtr = reinterpret_cast<const char*>(getBoundMemory().getHostPtr());
425 srcPtr += imageLayout.offset + getPixelOffset(offset, imageLayout.rowPitch, imageLayout.depthPitch, mipLevel, arrayElement);
427 MemoryOp::unpack(vk::mapVkFormat(m_format).getPixelSize(), width, height, depth,
428 imageLayout.rowPitch, imageLayout.depthPitch, srcPtr, data);
431 de::SharedPtr<Image> Image::copyToLinearImage (vk::VkQueue queue,
432 vk::Allocator& allocator,
433 vk::VkImageLayout layout,
434 vk::VkOffset3D offset,
438 unsigned int mipLevel,
439 unsigned int arrayElement,
440 vk::VkImageAspectFlagBits aspect,
441 vk::VkImageType type)
443 de::SharedPtr<Image> stagingResource;
445 vk::VkExtent3D stagingExtent = {(deUint32)width, (deUint32)height, (deUint32)depth};
446 ImageCreateInfo stagingResourceCreateInfo(type, m_format, stagingExtent, 1, 1, vk::VK_SAMPLE_COUNT_1_BIT,
447 vk::VK_IMAGE_TILING_LINEAR, vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT);
449 stagingResource = Image::createAndAlloc(m_vk, m_device, stagingResourceCreateInfo, allocator,
450 vk::MemoryRequirement::HostVisible);
452 //todo [scygan] get proper queueFamilyIndex
453 CmdPoolCreateInfo copyCmdPoolCreateInfo(0);
454 vk::Unique<vk::VkCommandPool> copyCmdPool(vk::createCommandPool(m_vk, m_device, ©CmdPoolCreateInfo));
456 const vk::VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
458 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
459 DE_NULL, // const void* pNext;
460 *copyCmdPool, // VkCommandPool commandPool;
461 vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCommandBufferLevel level;
462 1u, // deUint32 bufferCount;
464 vk::Unique<vk::VkCommandBuffer> copyCmdBuffer(vk::allocateCommandBuffer(m_vk, m_device, &cmdBufferAllocateInfo));
466 CmdBufferBeginInfo beginInfo;
467 VK_CHECK(m_vk.beginCommandBuffer(*copyCmdBuffer, &beginInfo));
469 transition2DImage(m_vk, *copyCmdBuffer, stagingResource->object(), aspect, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_GENERAL);
471 const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
472 vk::VkImageCopy region = { {aspect, mipLevel, arrayElement, 1}, offset, {aspect, 0, 0, 1}, zeroOffset, {(deUint32)width, (deUint32)height, (deUint32)depth} };
474 m_vk.cmdCopyImage(*copyCmdBuffer, object(), layout, stagingResource->object(), vk::VK_IMAGE_LAYOUT_GENERAL, 1, ®ion);
475 VK_CHECK(m_vk.endCommandBuffer(*copyCmdBuffer));
477 const vk::VkSubmitInfo submitInfo =
479 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
480 DE_NULL, // const void* pNext;
481 0, // deUint32 waitSemaphoreCount;
482 DE_NULL, // const VkSemaphore* pWaitSemaphores;
483 (const vk::VkPipelineStageFlags*)DE_NULL,
484 1, // deUint32 commandBufferCount;
485 ©CmdBuffer.get(), // const VkCommandBuffer* pCommandBuffers;
486 0, // deUint32 signalSemaphoreCount;
487 DE_NULL // const VkSemaphore* pSignalSemaphores;
489 m_vk.queueSubmit(queue, 1, &submitInfo, DE_NULL);
491 // TODO: make this less intrusive
492 VK_CHECK(m_vk.queueWaitIdle(queue));
494 return stagingResource;
497 void Image::uploadVolume(const tcu::ConstPixelBufferAccess& access,
499 vk::Allocator& allocator,
500 vk::VkImageLayout layout,
501 vk::VkOffset3D offset,
502 vk::VkImageAspectFlagBits aspect,
503 unsigned int mipLevel,
504 unsigned int arrayElement)
506 if (aspect == vk::VK_IMAGE_ASPECT_COLOR_BIT)
508 upload(queue, allocator, layout, offset, access.getWidth(),
509 access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, vk::VK_IMAGE_TYPE_3D,
510 access.getDataPtr());
512 if (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT || aspect == vk::VK_IMAGE_ASPECT_STENCIL_BIT)
514 uploadUsingBuffer(queue, allocator, layout, offset, access.getWidth(),
515 access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, access.getDataPtr());
519 void Image::uploadSurface (const tcu::ConstPixelBufferAccess& access,
521 vk::Allocator& allocator,
522 vk::VkImageLayout layout,
523 vk::VkOffset3D offset,
524 vk::VkImageAspectFlagBits aspect,
525 unsigned int mipLevel,
526 unsigned int arrayElement)
528 if (aspect == vk::VK_IMAGE_ASPECT_COLOR_BIT)
530 upload(queue, allocator, layout, offset, access.getWidth(),
531 access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, vk::VK_IMAGE_TYPE_2D,
532 access.getDataPtr());
534 if (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT || aspect == vk::VK_IMAGE_ASPECT_STENCIL_BIT)
536 uploadUsingBuffer(queue, allocator, layout, offset, access.getWidth(),
537 access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, access.getDataPtr());
541 void Image::uploadSurface1D (const tcu::ConstPixelBufferAccess& access,
543 vk::Allocator& allocator,
544 vk::VkImageLayout layout,
545 vk::VkOffset3D offset,
546 vk::VkImageAspectFlagBits aspect,
547 unsigned int mipLevel,
548 unsigned int arrayElement)
550 if (aspect == vk::VK_IMAGE_ASPECT_COLOR_BIT)
552 upload(queue, allocator, layout, offset, access.getWidth(),
553 access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, vk::VK_IMAGE_TYPE_1D,
554 access.getDataPtr());
556 if (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT || aspect == vk::VK_IMAGE_ASPECT_STENCIL_BIT)
558 uploadUsingBuffer(queue, allocator, layout, offset, access.getWidth(),
559 access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, access.getDataPtr());
563 void Image::uploadSurfaceLinear (const tcu::ConstPixelBufferAccess& access,
564 vk::VkOffset3D offset,
568 vk::VkImageAspectFlagBits aspect,
569 unsigned int mipLevel,
570 unsigned int arrayElement)
572 uploadLinear(offset, width, height, depth, mipLevel, arrayElement, aspect, access.getDataPtr());
575 void Image::upload (vk::VkQueue queue,
576 vk::Allocator& allocator,
577 vk::VkImageLayout layout,
578 vk::VkOffset3D offset,
582 unsigned int mipLevel,
583 unsigned int arrayElement,
584 vk::VkImageAspectFlagBits aspect,
585 vk::VkImageType type,
588 DE_ASSERT(layout == vk::VK_IMAGE_LAYOUT_GENERAL || layout == vk::VK_IMAGE_LAYOUT_UNDEFINED || layout == vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
590 de::SharedPtr<Image> stagingResource;
591 vk::VkExtent3D extent = {(deUint32)width, (deUint32)height, (deUint32)depth};
592 ImageCreateInfo stagingResourceCreateInfo(
593 type, m_format, extent, 1, 1, vk::VK_SAMPLE_COUNT_1_BIT,
594 vk::VK_IMAGE_TILING_LINEAR, vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
596 stagingResource = Image::createAndAlloc(m_vk, m_device, stagingResourceCreateInfo, allocator,
597 vk::MemoryRequirement::HostVisible);
599 const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
600 stagingResource->uploadLinear(zeroOffset, width, height, depth, 0, 0, aspect, data);
603 //todo [scygan] get proper queueFamilyIndex
604 CmdPoolCreateInfo copyCmdPoolCreateInfo(0);
605 vk::Unique<vk::VkCommandPool> copyCmdPool(vk::createCommandPool(m_vk, m_device, ©CmdPoolCreateInfo));
607 const vk::VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
609 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
610 DE_NULL, // const void* pNext;
611 *copyCmdPool, // VkCommandPool commandPool;
612 vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCommandBufferLevel level;
613 1u, // deUint32 bufferCount;
616 vk::Unique<vk::VkCommandBuffer> copyCmdBuffer(vk::allocateCommandBuffer(m_vk, m_device, &cmdBufferAllocateInfo));
618 CmdBufferBeginInfo beginInfo;
619 VK_CHECK(m_vk.beginCommandBuffer(*copyCmdBuffer, &beginInfo));
621 if (layout == vk::VK_IMAGE_LAYOUT_UNDEFINED)
623 layout = vk::VK_IMAGE_LAYOUT_GENERAL;
625 vk::VkImageMemoryBarrier barrier;
626 barrier.sType = vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
627 barrier.pNext = DE_NULL;
628 barrier.srcAccessMask = 0;
629 barrier.dstAccessMask = 0;
630 barrier.oldLayout = vk::VK_IMAGE_LAYOUT_UNDEFINED;
631 barrier.newLayout = vk::VK_IMAGE_LAYOUT_GENERAL;
632 barrier.srcQueueFamilyIndex = vk::VK_QUEUE_FAMILY_IGNORED;
633 barrier.dstQueueFamilyIndex = vk::VK_QUEUE_FAMILY_IGNORED;
634 barrier.image = object();
636 barrier.subresourceRange.aspectMask = aspect;
637 barrier.subresourceRange.baseMipLevel = 0;
638 barrier.subresourceRange.levelCount = m_levelCount;
639 barrier.subresourceRange.baseArrayLayer = 0;
640 barrier.subresourceRange.layerCount = m_layerCount;
642 m_vk.cmdPipelineBarrier(*copyCmdBuffer, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (vk::VkDependencyFlags)0,
643 0, (const vk::VkMemoryBarrier*)DE_NULL,
644 0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
648 transition2DImage(m_vk, *copyCmdBuffer, stagingResource->object(), aspect, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_GENERAL);
650 vk::VkImageCopy region = {{aspect, 0, 0, 1},
652 {aspect, mipLevel, arrayElement, 1},
654 {(deUint32)width, (deUint32)height, (deUint32)depth}};
656 m_vk.cmdCopyImage(*copyCmdBuffer, stagingResource->object(),
657 vk::VK_IMAGE_LAYOUT_GENERAL, object(), layout, 1, ®ion);
658 VK_CHECK(m_vk.endCommandBuffer(*copyCmdBuffer));
660 const vk::VkSubmitInfo submitInfo =
662 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
663 DE_NULL, // const void* pNext;
664 0, // deUint32 waitSemaphoreCount;
665 DE_NULL, // const VkSemaphore* pWaitSemaphores;
666 (const vk::VkPipelineStageFlags*)DE_NULL,
667 1, // deUint32 commandBufferCount;
668 ©CmdBuffer.get(), // const VkCommandBuffer* pCommandBuffers;
669 0, // deUint32 signalSemaphoreCount;
670 DE_NULL // const VkSemaphore* pSignalSemaphores;
672 m_vk.queueSubmit(queue, 1, &submitInfo, DE_NULL);
674 // TODO: make this less intrusive
675 VK_CHECK(m_vk.queueWaitIdle(queue));
679 void Image::uploadUsingBuffer (vk::VkQueue queue,
680 vk::Allocator& allocator,
681 vk::VkImageLayout layout,
682 vk::VkOffset3D offset,
686 unsigned int mipLevel,
687 unsigned int arrayElement,
688 vk::VkImageAspectFlagBits aspect,
691 DE_ASSERT(layout == vk::VK_IMAGE_LAYOUT_GENERAL || layout == vk::VK_IMAGE_LAYOUT_UNDEFINED || layout == vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
693 de::SharedPtr<Buffer> stagingResource;
694 bool isCombinedType = isCombinedDepthStencilType(vk::mapVkFormat(m_format).type);
695 vk::VkDeviceSize bufferSize = 0;
697 bufferSize = vk::mapVkFormat(m_format).getPixelSize() *width*height*depth;
703 case vk::VK_FORMAT_D16_UNORM_S8_UINT:
704 pixelSize = (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT) ? 2 : 1;
706 case vk::VK_FORMAT_D32_SFLOAT_S8_UINT:
707 pixelSize = (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT) ? 4 : 1;
709 case vk::VK_FORMAT_X8_D24_UNORM_PACK32:
710 case vk::VK_FORMAT_D24_UNORM_S8_UINT:
711 pixelSize = (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT) ? 3 : 1;
715 DE_FATAL("Not implemented");
717 bufferSize = pixelSize*width*height*depth;
719 BufferCreateInfo stagingBufferResourceCreateInfo(bufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT | vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
720 stagingResource = Buffer::createAndAlloc(m_vk, m_device, stagingBufferResourceCreateInfo, allocator, vk::MemoryRequirement::HostVisible);
721 char* destPtr = reinterpret_cast<char*>(stagingResource->getBoundMemory().getHostPtr());
722 deMemcpy(destPtr, data, static_cast<size_t>(bufferSize));
723 vk::flushMappedMemoryRange(m_vk, m_device, stagingResource->getBoundMemory().getMemory(), stagingResource->getBoundMemory().getOffset(), bufferSize);
725 //todo [scygan] get proper queueFamilyIndex
726 CmdPoolCreateInfo copyCmdPoolCreateInfo(0);
727 vk::Unique<vk::VkCommandPool> copyCmdPool(vk::createCommandPool(m_vk, m_device, ©CmdPoolCreateInfo));
729 const vk::VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
731 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
732 DE_NULL, // const void* pNext;
733 *copyCmdPool, // VkCommandPool commandPool;
734 vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCommandBufferLevel level;
735 1u, // deUint32 bufferCount;
737 vk::Unique<vk::VkCommandBuffer> copyCmdBuffer(vk::allocateCommandBuffer(m_vk, m_device, &cmdBufferAllocateInfo));
739 CmdBufferBeginInfo beginInfo;
740 VK_CHECK(m_vk.beginCommandBuffer(*copyCmdBuffer, &beginInfo));
742 if (layout == vk::VK_IMAGE_LAYOUT_UNDEFINED)
744 layout = vk::VK_IMAGE_LAYOUT_GENERAL;
746 vk::VkImageMemoryBarrier barrier;
747 barrier.sType = vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
748 barrier.pNext = DE_NULL;
749 barrier.srcAccessMask = 0;
750 barrier.dstAccessMask = 0;
751 barrier.oldLayout = vk::VK_IMAGE_LAYOUT_UNDEFINED;
752 barrier.newLayout = vk::VK_IMAGE_LAYOUT_GENERAL;
753 barrier.srcQueueFamilyIndex = vk::VK_QUEUE_FAMILY_IGNORED;
754 barrier.dstQueueFamilyIndex = vk::VK_QUEUE_FAMILY_IGNORED;
755 barrier.image = object();
757 barrier.subresourceRange.aspectMask = aspect;
758 barrier.subresourceRange.baseMipLevel = 0;
759 barrier.subresourceRange.levelCount = m_levelCount;
760 barrier.subresourceRange.baseArrayLayer = 0;
761 barrier.subresourceRange.layerCount = m_layerCount;
763 m_vk.cmdPipelineBarrier(*copyCmdBuffer, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (vk::VkDependencyFlags)0,
764 0, (const vk::VkMemoryBarrier*)DE_NULL,
765 0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
769 vk::VkBufferImageCopy region =
772 { aspect, mipLevel, arrayElement, 1 },
774 { (deUint32)width, (deUint32)height, (deUint32)depth }
777 m_vk.cmdCopyBufferToImage(*copyCmdBuffer, stagingResource->object(),
778 object(), layout, 1, ®ion);
779 VK_CHECK(m_vk.endCommandBuffer(*copyCmdBuffer));
781 vk::VkSubmitInfo submitInfo =
783 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
784 DE_NULL, // const void* pNext;
785 0, // deUint32 waitSemaphoreCount;
786 DE_NULL, // const VkSemaphore* pWaitSemaphores;
787 (const vk::VkPipelineStageFlags*)DE_NULL,
788 1, // deUint32 commandBufferCount;
789 ©CmdBuffer.get(), // const VkCommandBuffer* pCommandBuffers;
790 0, // deUint32 signalSemaphoreCount;
791 DE_NULL // const VkSemaphore* pSignalSemaphores;
793 m_vk.queueSubmit(queue, 1, &submitInfo, DE_NULL);
795 // TODO: make this less intrusive
796 VK_CHECK(m_vk.queueWaitIdle(queue));
800 void Image::uploadLinear (vk::VkOffset3D offset,
804 unsigned int mipLevel,
805 unsigned int arrayElement,
806 vk::VkImageAspectFlagBits aspect,
809 vk::VkSubresourceLayout imageLayout;
811 vk::VkImageSubresource imageSubResource = {aspect, mipLevel, arrayElement};
813 m_vk.getImageSubresourceLayout(m_device, object(), &imageSubResource,
816 char* destPtr = reinterpret_cast<char*>(getBoundMemory().getHostPtr());
818 destPtr += imageLayout.offset + getPixelOffset(offset, imageLayout.rowPitch, imageLayout.depthPitch, mipLevel, arrayElement);
820 MemoryOp::pack(vk::mapVkFormat(m_format).getPixelSize(), width, height, depth,
821 imageLayout.rowPitch, imageLayout.depthPitch, data, destPtr);
824 vk::VkDeviceSize Image::getPixelOffset (vk::VkOffset3D offset,
825 vk::VkDeviceSize rowPitch,
826 vk::VkDeviceSize depthPitch,
830 DE_ASSERT(level < m_levelCount);
831 DE_ASSERT(layer < m_layerCount);
833 vk::VkDeviceSize mipLevelSizes[32];
834 vk::VkDeviceSize mipLevelRectSizes[32];
836 = tcu::IVec3(m_extent.width, m_extent.height, m_extent.depth);
838 vk::VkDeviceSize arrayElemSize = 0;
839 for (unsigned int i = 0; i < m_levelCount && (mipExtend[0] > 1 || mipExtend[1] > 1 || mipExtend[2] > 1); ++i)
841 // Rect size is just a 3D image size;
842 mipLevelSizes[i] = mipExtend[2] * depthPitch;
844 arrayElemSize += mipLevelSizes[0];
846 mipExtend = tcu::max(mipExtend / 2, tcu::IVec3(1));
849 vk::VkDeviceSize pixelOffset = layer * arrayElemSize;
850 for (size_t i = 0; i < level; ++i)
852 pixelOffset += mipLevelSizes[i];
854 pixelOffset += offset.z * mipLevelRectSizes[level];
855 pixelOffset += offset.y * rowPitch;
856 pixelOffset += offset.x;
861 void Image::bindMemory (de::MovePtr<vk::Allocation> allocation)
863 DE_ASSERT(allocation);
864 VK_CHECK(m_vk.bindImageMemory(m_device, *m_object, allocation->getMemory(), allocation->getOffset()));
866 DE_ASSERT(!m_allocation);
867 m_allocation = allocation;
870 de::SharedPtr<Image> Image::createAndAlloc(const vk::DeviceInterface& vk,
872 const vk::VkImageCreateInfo& createInfo,
873 vk::Allocator& allocator,
874 vk::MemoryRequirement memoryRequirement)
876 de::SharedPtr<Image> ret = create(vk, device, createInfo);
878 vk::VkMemoryRequirements imageRequirements = vk::getImageMemoryRequirements(vk, device, ret->object());
879 ret->bindMemory(allocator.allocate(imageRequirements, memoryRequirement));
883 de::SharedPtr<Image> Image::create(const vk::DeviceInterface& vk,
885 const vk::VkImageCreateInfo &createInfo)
887 return de::SharedPtr<Image>(new Image(vk, device, createInfo.format, createInfo.extent,
888 createInfo.mipLevels, createInfo.arrayLayers,
889 vk::createImage(vk, device, &createInfo)));
892 void transition2DImage (const vk::DeviceInterface& vk,
893 vk::VkCommandBuffer cmdBuffer,
895 vk::VkImageAspectFlags aspectMask,
896 vk::VkImageLayout oldLayout,
897 vk::VkImageLayout newLayout)
899 vk::VkImageMemoryBarrier barrier;
900 barrier.sType = vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
901 barrier.pNext = DE_NULL;
902 barrier.srcAccessMask = 0;
903 barrier.dstAccessMask = 0;
904 barrier.oldLayout = oldLayout;
905 barrier.newLayout = newLayout;
906 barrier.srcQueueFamilyIndex = vk::VK_QUEUE_FAMILY_IGNORED;
907 barrier.dstQueueFamilyIndex = vk::VK_QUEUE_FAMILY_IGNORED;
908 barrier.image = image;
909 barrier.subresourceRange.aspectMask = aspectMask;
910 barrier.subresourceRange.baseMipLevel = 0;
911 barrier.subresourceRange.levelCount = 1;
912 barrier.subresourceRange.baseArrayLayer = 0;
913 barrier.subresourceRange.layerCount = 1;
915 vk.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (vk::VkDependencyFlags)0,
916 0, (const vk::VkMemoryBarrier*)DE_NULL,
917 0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
921 void initialTransitionColor2DImage (const vk::DeviceInterface &vk, vk::VkCommandBuffer cmdBuffer, vk::VkImage image, vk::VkImageLayout layout)
923 transition2DImage(vk, cmdBuffer, image, vk::VK_IMAGE_ASPECT_COLOR_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, layout);
926 void initialTransitionDepth2DImage (const vk::DeviceInterface &vk, vk::VkCommandBuffer cmdBuffer, vk::VkImage image, vk::VkImageLayout layout)
928 transition2DImage(vk, cmdBuffer, image, vk::VK_IMAGE_ASPECT_DEPTH_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, layout);
931 void initialTransitionStencil2DImage (const vk::DeviceInterface &vk, vk::VkCommandBuffer cmdBuffer, vk::VkImage image, vk::VkImageLayout layout)
933 transition2DImage(vk, cmdBuffer, image, vk::VK_IMAGE_ASPECT_STENCIL_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, layout);
936 void initialTransitionDepthStencil2DImage (const vk::DeviceInterface &vk, vk::VkCommandBuffer cmdBuffer, vk::VkImage image, vk::VkImageLayout layout)
938 transition2DImage(vk, cmdBuffer, image, vk::VK_IMAGE_ASPECT_DEPTH_BIT | vk::VK_IMAGE_ASPECT_STENCIL_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, layout);