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 "vktDynamicStateImageObjectUtil.hpp"
38 #include "tcuSurface.hpp"
39 #include "tcuVectorUtil.hpp"
41 #include "vkRefUtil.hpp"
42 #include "vkQueryUtil.hpp"
43 #include "vkImageUtil.hpp"
44 #include "vktDynamicStateCreateInfoUtil.hpp"
45 #include "vktDynamicStateBufferObjectUtil.hpp"
47 #include "tcuTextureUtil.hpp"
51 namespace DynamicState
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));
140 // slower, per row path
141 for (size_t d = 0; d < (size_t)depth; d++)
143 vk::VkDeviceSize offsetDepthDst = d * (pixelSize * width * height);
144 vk::VkDeviceSize offsetDepthSrc = d * depthPitch;
145 srcRow = srcStart + offsetDepthSrc;
146 dstRow = dstStart + offsetDepthDst;
147 for (int r = 0; r < height; ++r)
149 deMemcpy(dstRow, srcRow, static_cast<size_t>(pixelSize * width));
151 dstRow += pixelSize * width;
157 Image::Image (const vk::DeviceInterface& vk,
160 const vk::VkExtent3D& extend,
163 vk::Move<vk::VkImage> object_)
164 : m_allocation (DE_NULL)
168 , m_levelCount (levelCount)
169 , m_layerCount (layerCount)
175 tcu::ConstPixelBufferAccess Image::readSurface (vk::VkQueue queue,
176 vk::Allocator& allocator,
177 vk::VkImageLayout layout,
178 vk::VkOffset3D offset,
181 vk::VkImageAspectFlagBits aspect,
182 unsigned int mipLevel,
183 unsigned int arrayElement)
185 m_pixelAccessData.resize(width * height * vk::mapVkFormat(m_format).getPixelSize());
186 deMemset(m_pixelAccessData.data(), 0, m_pixelAccessData.size());
187 if (aspect == vk::VK_IMAGE_ASPECT_COLOR_BIT)
189 read(queue, allocator, layout, offset, width, height, 1, mipLevel, arrayElement, aspect, vk::VK_IMAGE_TYPE_2D,
190 m_pixelAccessData.data());
192 if (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT || aspect == vk::VK_IMAGE_ASPECT_STENCIL_BIT)
194 readUsingBuffer(queue, allocator, layout, offset, width, height, 1, mipLevel, arrayElement, aspect, m_pixelAccessData.data());
196 return tcu::ConstPixelBufferAccess(vk::mapVkFormat(m_format), width, height, 1, m_pixelAccessData.data());
199 tcu::ConstPixelBufferAccess Image::readVolume (vk::VkQueue queue,
200 vk::Allocator& allocator,
201 vk::VkImageLayout layout,
202 vk::VkOffset3D offset,
206 vk::VkImageAspectFlagBits aspect,
207 unsigned int mipLevel,
208 unsigned int arrayElement)
210 m_pixelAccessData.resize(width * height * depth * vk::mapVkFormat(m_format).getPixelSize());
211 deMemset(m_pixelAccessData.data(), 0, m_pixelAccessData.size());
212 if (aspect == vk::VK_IMAGE_ASPECT_COLOR_BIT)
214 read(queue, allocator, layout, offset, width, height, depth, mipLevel, arrayElement, aspect, vk::VK_IMAGE_TYPE_3D,
215 m_pixelAccessData.data());
217 if (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT || aspect == vk::VK_IMAGE_ASPECT_STENCIL_BIT)
219 readUsingBuffer(queue, allocator, layout, offset, width, height, depth, mipLevel, arrayElement, aspect, m_pixelAccessData.data());
221 return tcu::ConstPixelBufferAccess(vk::mapVkFormat(m_format), width, height, depth, m_pixelAccessData.data());
224 tcu::ConstPixelBufferAccess Image::readSurface1D(vk::VkQueue queue,
225 vk::Allocator& allocator,
226 vk::VkImageLayout layout,
227 vk::VkOffset3D offset,
229 vk::VkImageAspectFlagBits aspect,
230 unsigned int mipLevel,
231 unsigned int arrayElement)
233 m_pixelAccessData.resize(width * vk::mapVkFormat(m_format).getPixelSize());
234 deMemset(m_pixelAccessData.data(), 0, m_pixelAccessData.size());
235 if (aspect == vk::VK_IMAGE_ASPECT_COLOR_BIT)
237 read(queue, allocator, layout, offset, width, 1, 1, mipLevel, arrayElement, aspect, vk::VK_IMAGE_TYPE_1D,
238 m_pixelAccessData.data());
240 if (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT || aspect == vk::VK_IMAGE_ASPECT_STENCIL_BIT)
242 readUsingBuffer(queue, allocator, layout, offset, width, 1, 1, mipLevel, arrayElement, aspect,
243 m_pixelAccessData.data());
245 return tcu::ConstPixelBufferAccess(vk::mapVkFormat(m_format), width, 1, 1, m_pixelAccessData.data());
248 void Image::read (vk::VkQueue queue,
249 vk::Allocator& allocator,
250 vk::VkImageLayout layout,
251 vk::VkOffset3D offset,
255 unsigned int mipLevel,
256 unsigned int arrayElement,
257 vk::VkImageAspectFlagBits aspect,
258 vk::VkImageType type,
261 DE_ASSERT(layout == vk::VK_IMAGE_LAYOUT_GENERAL || layout == vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
263 de::SharedPtr<Image> stagingResource = copyToLinearImage(queue, allocator, layout, offset, width,
264 height, depth, mipLevel, arrayElement, aspect, type);
265 const vk::VkOffset3D zeroOffset = {0, 0, 0};
266 stagingResource->readLinear(zeroOffset, width, height, depth, 0, 0, aspect, data);
269 void Image::readUsingBuffer (vk::VkQueue queue,
270 vk::Allocator& allocator,
271 vk::VkImageLayout layout,
272 vk::VkOffset3D offset,
276 unsigned int mipLevel,
277 unsigned int arrayElement,
278 vk::VkImageAspectFlagBits aspect,
281 DE_ASSERT(layout == vk::VK_IMAGE_LAYOUT_GENERAL || layout == vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);;
283 de::SharedPtr<Buffer> stagingResource;
285 bool isCombinedType = isCombinedDepthStencilType(vk::mapVkFormat(m_format).type);
286 vk::VkDeviceSize bufferSize = 0;
289 bufferSize = vk::mapVkFormat(m_format).getPixelSize() * width * height * depth;
296 case vk::VK_FORMAT_D16_UNORM_S8_UINT:
297 pixelSize = (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT) ? 2 : 1;
299 case vk::VK_FORMAT_D32_SFLOAT_S8_UINT:
300 pixelSize = (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT) ? 4 : 1;
302 case vk::VK_FORMAT_X8_D24_UNORM_PACK32:
303 case vk::VK_FORMAT_D24_UNORM_S8_UINT:
304 pixelSize = (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT) ? 3 : 1;
308 DE_FATAL("Not implemented");
310 bufferSize = pixelSize*width*height*depth;
313 BufferCreateInfo stagingBufferResourceCreateInfo(bufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT | vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
314 stagingResource = Buffer::createAndAlloc(m_vk, m_device, stagingBufferResourceCreateInfo, allocator, vk::MemoryRequirement::HostVisible);
317 //todo [scygan] get proper queueFamilyIndex
318 CmdPoolCreateInfo copyCmdPoolCreateInfo(0);
319 vk::Unique<vk::VkCommandPool> copyCmdPool(vk::createCommandPool(m_vk, m_device, ©CmdPoolCreateInfo));
321 const vk::VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
323 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
324 DE_NULL, // const void* pNext;
325 *copyCmdPool, // VkCommandPool commandPool;
326 vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCommandBufferLevel level;
327 1u, // deUint32 bufferCount;
329 vk::Unique<vk::VkCommandBuffer> copyCmdBuffer(vk::allocateCommandBuffer(m_vk, m_device, &cmdBufferAllocateInfo));
331 CmdBufferBeginInfo beginInfo;
332 VK_CHECK(m_vk.beginCommandBuffer(*copyCmdBuffer, &beginInfo));
334 if (layout == vk::VK_IMAGE_LAYOUT_UNDEFINED)
336 layout = vk::VK_IMAGE_LAYOUT_GENERAL;
338 vk::VkImageMemoryBarrier barrier;
339 barrier.sType = vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
340 barrier.pNext = DE_NULL;
341 barrier.srcAccessMask = 0;
342 barrier.dstAccessMask = 0;
343 barrier.oldLayout = vk::VK_IMAGE_LAYOUT_UNDEFINED;
344 barrier.newLayout = vk::VK_IMAGE_LAYOUT_GENERAL;
345 barrier.srcQueueFamilyIndex = vk::VK_QUEUE_FAMILY_IGNORED;
346 barrier.dstQueueFamilyIndex = vk::VK_QUEUE_FAMILY_IGNORED;
347 barrier.image = object();
349 barrier.subresourceRange.aspectMask = aspect;
350 barrier.subresourceRange.baseMipLevel = 0;
351 barrier.subresourceRange.levelCount = m_levelCount;
352 barrier.subresourceRange.baseArrayLayer = 0;
353 barrier.subresourceRange.layerCount = m_layerCount;
355 m_vk.cmdPipelineBarrier(*copyCmdBuffer, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (vk::VkDependencyFlags)0,
356 0, (const vk::VkMemoryBarrier*)DE_NULL,
357 0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
361 vk::VkBufferImageCopy region =
364 { aspect, mipLevel, arrayElement, 1 },
366 { (deUint32)width, (deUint32)height, (deUint32)depth }
369 m_vk.cmdCopyImageToBuffer(*copyCmdBuffer, object(), layout, stagingResource->object(), 1, ®ion);
370 VK_CHECK(m_vk.endCommandBuffer(*copyCmdBuffer));
372 vk::VkSubmitInfo submitInfo =
374 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
375 DE_NULL, // const void* pNext;
376 0, // deUint32 waitSemaphoreCount;
377 DE_NULL, // const VkSemaphore* pWaitSemaphores;
378 (const vk::VkPipelineStageFlags*)DE_NULL,
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 = {(deUint32)width, (deUint32)height, (deUint32)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, {(deUint32)width, (deUint32)height, (deUint32)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 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 (const vk::VkPipelineStageFlags*)DE_NULL,
483 1, // deUint32 commandBufferCount;
484 ©CmdBuffer.get(), // const VkCommandBuffer* pCommandBuffers;
485 0, // deUint32 signalSemaphoreCount;
486 DE_NULL // const VkSemaphore* pSignalSemaphores;
488 m_vk.queueSubmit(queue, 1, &submitInfo, DE_NULL);
490 // TODO: make this less intrusive
491 VK_CHECK(m_vk.queueWaitIdle(queue));
493 return stagingResource;
496 void Image::uploadVolume(const tcu::ConstPixelBufferAccess& access,
498 vk::Allocator& allocator,
499 vk::VkImageLayout layout,
500 vk::VkOffset3D offset,
501 vk::VkImageAspectFlagBits aspect,
502 unsigned int mipLevel,
503 unsigned int arrayElement)
505 if (aspect == vk::VK_IMAGE_ASPECT_COLOR_BIT)
507 upload(queue, allocator, layout, offset, access.getWidth(),
508 access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, vk::VK_IMAGE_TYPE_3D,
509 access.getDataPtr());
511 if (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT || aspect == vk::VK_IMAGE_ASPECT_STENCIL_BIT)
513 uploadUsingBuffer(queue, allocator, layout, offset, access.getWidth(),
514 access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, access.getDataPtr());
518 void Image::uploadSurface (const tcu::ConstPixelBufferAccess& access,
520 vk::Allocator& allocator,
521 vk::VkImageLayout layout,
522 vk::VkOffset3D offset,
523 vk::VkImageAspectFlagBits aspect,
524 unsigned int mipLevel,
525 unsigned int arrayElement)
527 if (aspect == vk::VK_IMAGE_ASPECT_COLOR_BIT)
529 upload(queue, allocator, layout, offset, access.getWidth(),
530 access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, vk::VK_IMAGE_TYPE_2D,
531 access.getDataPtr());
533 if (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT || aspect == vk::VK_IMAGE_ASPECT_STENCIL_BIT)
535 uploadUsingBuffer(queue, allocator, layout, offset, access.getWidth(),
536 access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, access.getDataPtr());
540 void Image::uploadSurface1D (const tcu::ConstPixelBufferAccess& access,
542 vk::Allocator& allocator,
543 vk::VkImageLayout layout,
544 vk::VkOffset3D offset,
545 vk::VkImageAspectFlagBits aspect,
546 unsigned int mipLevel,
547 unsigned int arrayElement)
549 if (aspect == vk::VK_IMAGE_ASPECT_COLOR_BIT)
551 upload(queue, allocator, layout, offset, access.getWidth(),
552 access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, vk::VK_IMAGE_TYPE_1D,
553 access.getDataPtr());
555 if (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT || aspect == vk::VK_IMAGE_ASPECT_STENCIL_BIT)
557 uploadUsingBuffer(queue, allocator, layout, offset, access.getWidth(),
558 access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, access.getDataPtr());
562 void Image::uploadSurfaceLinear (const tcu::ConstPixelBufferAccess& access,
563 vk::VkOffset3D offset,
567 vk::VkImageAspectFlagBits aspect,
568 unsigned int mipLevel,
569 unsigned int arrayElement)
571 uploadLinear(offset, width, height, depth, mipLevel, arrayElement, aspect, access.getDataPtr());
574 void Image::upload (vk::VkQueue queue,
575 vk::Allocator& allocator,
576 vk::VkImageLayout layout,
577 vk::VkOffset3D offset,
581 unsigned int mipLevel,
582 unsigned int arrayElement,
583 vk::VkImageAspectFlagBits aspect,
584 vk::VkImageType type,
587 DE_ASSERT(layout == vk::VK_IMAGE_LAYOUT_GENERAL || layout == vk::VK_IMAGE_LAYOUT_UNDEFINED || layout == vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
589 de::SharedPtr<Image> stagingResource;
590 vk::VkExtent3D extent = {(deUint32)width, (deUint32)height, (deUint32)depth};
591 ImageCreateInfo stagingResourceCreateInfo(
592 type, m_format, extent, 1, 1, vk::VK_SAMPLE_COUNT_1_BIT,
593 vk::VK_IMAGE_TILING_LINEAR, vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
595 stagingResource = Image::createAndAlloc(m_vk, m_device, stagingResourceCreateInfo, allocator,
596 vk::MemoryRequirement::HostVisible);
598 const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
599 stagingResource->uploadLinear(zeroOffset, width, height, depth, 0, 0, aspect, data);
602 //todo [scygan] get proper queueFamilyIndex
603 CmdPoolCreateInfo copyCmdPoolCreateInfo(0);
604 vk::Unique<vk::VkCommandPool> copyCmdPool(vk::createCommandPool(m_vk, m_device, ©CmdPoolCreateInfo));
606 const vk::VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
608 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
609 DE_NULL, // const void* pNext;
610 *copyCmdPool, // VkCommandPool commandPool;
611 vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCommandBufferLevel level;
612 1u, // deUint32 bufferCount;
615 vk::Unique<vk::VkCommandBuffer> copyCmdBuffer(vk::allocateCommandBuffer(m_vk, m_device, &cmdBufferAllocateInfo));
617 CmdBufferBeginInfo beginInfo;
618 VK_CHECK(m_vk.beginCommandBuffer(*copyCmdBuffer, &beginInfo));
620 if (layout == vk::VK_IMAGE_LAYOUT_UNDEFINED)
622 layout = vk::VK_IMAGE_LAYOUT_GENERAL;
624 vk::VkImageMemoryBarrier barrier;
625 barrier.sType = vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
626 barrier.pNext = DE_NULL;
627 barrier.srcAccessMask = 0;
628 barrier.dstAccessMask = 0;
629 barrier.oldLayout = vk::VK_IMAGE_LAYOUT_UNDEFINED;
630 barrier.newLayout = vk::VK_IMAGE_LAYOUT_GENERAL;
631 barrier.srcQueueFamilyIndex = vk::VK_QUEUE_FAMILY_IGNORED;
632 barrier.dstQueueFamilyIndex = vk::VK_QUEUE_FAMILY_IGNORED;
633 barrier.image = object();
635 barrier.subresourceRange.aspectMask = aspect;
636 barrier.subresourceRange.baseMipLevel = 0;
637 barrier.subresourceRange.levelCount = m_levelCount;
638 barrier.subresourceRange.baseArrayLayer = 0;
639 barrier.subresourceRange.layerCount = m_layerCount;
641 m_vk.cmdPipelineBarrier(*copyCmdBuffer, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (vk::VkDependencyFlags)0,
642 0, (const vk::VkMemoryBarrier*)DE_NULL,
643 0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
647 transition2DImage(m_vk, *copyCmdBuffer, stagingResource->object(), aspect, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_GENERAL);
649 vk::VkImageCopy region = {{aspect, 0, 0, 1},
651 {aspect, mipLevel, arrayElement, 1},
653 {(deUint32)width, (deUint32)height, (deUint32)depth}};
655 m_vk.cmdCopyImage(*copyCmdBuffer, stagingResource->object(),
656 vk::VK_IMAGE_LAYOUT_GENERAL, object(), layout, 1, ®ion);
657 VK_CHECK(m_vk.endCommandBuffer(*copyCmdBuffer));
659 vk::VkSubmitInfo submitInfo =
661 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
662 DE_NULL, // const void* pNext;
663 0, // deUint32 waitSemaphoreCount;
664 DE_NULL, // const VkSemaphore* pWaitSemaphores;
665 (const vk::VkPipelineStageFlags*)DE_NULL,
666 1, // deUint32 commandBufferCount;
667 ©CmdBuffer.get(), // const VkCommandBuffer* pCommandBuffers;
668 0, // deUint32 signalSemaphoreCount;
669 DE_NULL // const VkSemaphore* pSignalSemaphores;
671 m_vk.queueSubmit(queue, 1, &submitInfo, DE_NULL);
673 // TODO: make this less intrusive
674 VK_CHECK(m_vk.queueWaitIdle(queue));
678 void Image::uploadUsingBuffer (vk::VkQueue queue,
679 vk::Allocator& allocator,
680 vk::VkImageLayout layout,
681 vk::VkOffset3D offset,
685 unsigned int mipLevel,
686 unsigned int arrayElement,
687 vk::VkImageAspectFlagBits aspect,
690 DE_ASSERT(layout == vk::VK_IMAGE_LAYOUT_GENERAL || layout == vk::VK_IMAGE_LAYOUT_UNDEFINED || layout == vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
692 de::SharedPtr<Buffer> stagingResource;
693 bool isCombinedType = isCombinedDepthStencilType(vk::mapVkFormat(m_format).type);
694 vk::VkDeviceSize bufferSize = 0;
696 bufferSize = vk::mapVkFormat(m_format).getPixelSize() *width*height*depth;
702 case vk::VK_FORMAT_D16_UNORM_S8_UINT:
703 pixelSize = (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT) ? 2 : 1;
705 case vk::VK_FORMAT_D32_SFLOAT_S8_UINT:
706 pixelSize = (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT) ? 4 : 1;
708 case vk::VK_FORMAT_X8_D24_UNORM_PACK32:
709 case vk::VK_FORMAT_D24_UNORM_S8_UINT:
710 pixelSize = (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT) ? 3 : 1;
714 DE_FATAL("Not implemented");
716 bufferSize = pixelSize*width*height*depth;
718 BufferCreateInfo stagingBufferResourceCreateInfo(bufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT | vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
719 stagingResource = Buffer::createAndAlloc(m_vk, m_device, stagingBufferResourceCreateInfo, allocator, vk::MemoryRequirement::HostVisible);
720 char* destPtr = reinterpret_cast<char*>(stagingResource->getBoundMemory().getHostPtr());
721 deMemcpy(destPtr, data, static_cast<size_t>(bufferSize));
722 vk::flushMappedMemoryRange(m_vk, m_device, stagingResource->getBoundMemory().getMemory(), stagingResource->getBoundMemory().getOffset(), bufferSize);
724 //todo [scygan] get proper queueFamilyIndex
725 CmdPoolCreateInfo copyCmdPoolCreateInfo(0);
726 vk::Unique<vk::VkCommandPool> copyCmdPool(vk::createCommandPool(m_vk, m_device, ©CmdPoolCreateInfo));
728 const vk::VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
730 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
731 DE_NULL, // const void* pNext;
732 *copyCmdPool, // VkCommandPool commandPool;
733 vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCommandBufferLevel level;
734 1u, // deUint32 bufferCount;
736 vk::Unique<vk::VkCommandBuffer> copyCmdBuffer(vk::allocateCommandBuffer(m_vk, m_device, &cmdBufferAllocateInfo));
738 CmdBufferBeginInfo beginInfo;
739 VK_CHECK(m_vk.beginCommandBuffer(*copyCmdBuffer, &beginInfo));
741 if (layout == vk::VK_IMAGE_LAYOUT_UNDEFINED)
743 layout = vk::VK_IMAGE_LAYOUT_GENERAL;
745 vk::VkImageMemoryBarrier barrier;
746 barrier.sType = vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
747 barrier.pNext = DE_NULL;
748 barrier.srcAccessMask = 0;
749 barrier.dstAccessMask = 0;
750 barrier.oldLayout = vk::VK_IMAGE_LAYOUT_UNDEFINED;
751 barrier.newLayout = vk::VK_IMAGE_LAYOUT_GENERAL;
752 barrier.srcQueueFamilyIndex = vk::VK_QUEUE_FAMILY_IGNORED;
753 barrier.dstQueueFamilyIndex = vk::VK_QUEUE_FAMILY_IGNORED;
754 barrier.image = object();
756 barrier.subresourceRange.aspectMask = aspect;
757 barrier.subresourceRange.baseMipLevel = 0;
758 barrier.subresourceRange.levelCount = m_levelCount;
759 barrier.subresourceRange.baseArrayLayer = 0;
760 barrier.subresourceRange.layerCount = m_layerCount;
762 m_vk.cmdPipelineBarrier(*copyCmdBuffer, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (vk::VkDependencyFlags)0,
763 0, (const vk::VkMemoryBarrier*)DE_NULL,
764 0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
768 vk::VkBufferImageCopy region = {
770 { aspect, mipLevel, arrayElement, 1 },
772 { (deUint32)width, (deUint32)height, (deUint32)depth }
775 m_vk.cmdCopyBufferToImage(*copyCmdBuffer, stagingResource->object(),
776 object(), layout, 1, ®ion);
777 VK_CHECK(m_vk.endCommandBuffer(*copyCmdBuffer));
779 vk::VkSubmitInfo submitInfo =
781 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
782 DE_NULL, // const void* pNext;
783 0, // deUint32 waitSemaphoreCount;
784 DE_NULL, // const VkSemaphore* pWaitSemaphores;
785 (const vk::VkPipelineStageFlags*)DE_NULL,
786 1, // deUint32 commandBufferCount;
787 ©CmdBuffer.get(), // const VkCommandBuffer* pCommandBuffers;
788 0, // deUint32 signalSemaphoreCount;
789 DE_NULL // const VkSemaphore* pSignalSemaphores;
791 m_vk.queueSubmit(queue, 1, &submitInfo, DE_NULL);
793 // TODO: make this less intrusive
794 VK_CHECK(m_vk.queueWaitIdle(queue));
798 void Image::uploadLinear (vk::VkOffset3D offset,
802 unsigned int mipLevel,
803 unsigned int arrayElement,
804 vk::VkImageAspectFlagBits aspect,
807 vk::VkSubresourceLayout imageLayout;
809 vk::VkImageSubresource imageSubResource = {aspect, mipLevel, arrayElement};
811 m_vk.getImageSubresourceLayout(m_device, object(), &imageSubResource,
814 char* destPtr = reinterpret_cast<char*>(getBoundMemory().getHostPtr());
816 destPtr += imageLayout.offset + getPixelOffset(offset, imageLayout.rowPitch, imageLayout.depthPitch, mipLevel, arrayElement);
818 MemoryOp::pack(vk::mapVkFormat(m_format).getPixelSize(), width, height, depth,
819 imageLayout.rowPitch, imageLayout.depthPitch, data, destPtr);
822 vk::VkDeviceSize Image::getPixelOffset (vk::VkOffset3D offset,
823 vk::VkDeviceSize rowPitch,
824 vk::VkDeviceSize depthPitch,
828 DE_ASSERT(level < m_levelCount);
829 DE_ASSERT(layer < m_layerCount);
831 vk::VkDeviceSize mipLevelSizes[32];
832 vk::VkDeviceSize mipLevelRectSizes[32];
834 = tcu::IVec3(m_extent.width, m_extent.height, m_extent.depth);
836 vk::VkDeviceSize arrayElemSize = 0;
837 for (unsigned int i = 0; i < m_levelCount && (mipExtend[0] > 1 || mipExtend[1] > 1 || mipExtend[2] > 1); ++i)
839 // Rect size is just a 3D image size;
840 mipLevelSizes[i] = mipExtend[2] * depthPitch;
842 arrayElemSize += mipLevelSizes[0];
844 mipExtend = tcu::max(mipExtend / 2, tcu::IVec3(1));
847 vk::VkDeviceSize pixelOffset = layer * arrayElemSize;
848 for (size_t i = 0; i < level; ++i) {
849 pixelOffset += mipLevelSizes[i];
851 pixelOffset += offset.z * mipLevelRectSizes[level];
852 pixelOffset += offset.y * rowPitch;
853 pixelOffset += offset.x;
858 void Image::bindMemory (de::MovePtr<vk::Allocation> allocation)
860 DE_ASSERT(allocation);
861 VK_CHECK(m_vk.bindImageMemory(m_device, *m_object, allocation->getMemory(), allocation->getOffset()));
863 DE_ASSERT(!m_allocation);
864 m_allocation = allocation;
867 de::SharedPtr<Image> Image::createAndAlloc(const vk::DeviceInterface& vk,
869 const vk::VkImageCreateInfo& createInfo,
870 vk::Allocator& allocator,
871 vk::MemoryRequirement memoryRequirement)
873 de::SharedPtr<Image> ret = create(vk, device, createInfo);
875 vk::VkMemoryRequirements imageRequirements = vk::getImageMemoryRequirements(vk, device, ret->object());
876 ret->bindMemory(allocator.allocate(imageRequirements, memoryRequirement));
880 de::SharedPtr<Image> Image::create(const vk::DeviceInterface& vk,
882 const vk::VkImageCreateInfo &createInfo)
884 return de::SharedPtr<Image>(new Image(vk, device, createInfo.format, createInfo.extent,
885 createInfo.mipLevels, createInfo.arrayLayers,
886 vk::createImage(vk, device, &createInfo)));
889 void transition2DImage (const vk::DeviceInterface& vk,
890 vk::VkCommandBuffer cmdBuffer,
892 vk::VkImageAspectFlags aspectMask,
893 vk::VkImageLayout oldLayout,
894 vk::VkImageLayout newLayout)
896 vk::VkImageMemoryBarrier barrier;
897 barrier.sType = vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
898 barrier.pNext = DE_NULL;
899 barrier.srcAccessMask = 0;
900 barrier.dstAccessMask = 0;
901 barrier.oldLayout = oldLayout;
902 barrier.newLayout = newLayout;
903 barrier.srcQueueFamilyIndex = vk::VK_QUEUE_FAMILY_IGNORED;
904 barrier.dstQueueFamilyIndex = vk::VK_QUEUE_FAMILY_IGNORED;
905 barrier.image = image;
906 barrier.subresourceRange.aspectMask = aspectMask;
907 barrier.subresourceRange.baseMipLevel = 0;
908 barrier.subresourceRange.levelCount = 1;
909 barrier.subresourceRange.baseArrayLayer = 0;
910 barrier.subresourceRange.layerCount = 1;
912 vk.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (vk::VkDependencyFlags)0,
913 0, (const vk::VkMemoryBarrier*)DE_NULL,
914 0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
918 void initialTransitionColor2DImage (const vk::DeviceInterface &vk, vk::VkCommandBuffer cmdBuffer, vk::VkImage image, vk::VkImageLayout layout)
920 transition2DImage(vk, cmdBuffer, image, vk::VK_IMAGE_ASPECT_COLOR_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, layout);
923 void initialTransitionDepth2DImage (const vk::DeviceInterface &vk, vk::VkCommandBuffer cmdBuffer, vk::VkImage image, vk::VkImageLayout layout)
925 transition2DImage(vk, cmdBuffer, image, vk::VK_IMAGE_ASPECT_DEPTH_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, layout);
928 void initialTransitionStencil2DImage (const vk::DeviceInterface &vk, vk::VkCommandBuffer cmdBuffer, vk::VkImage image, vk::VkImageLayout layout)
930 transition2DImage(vk, cmdBuffer, image, vk::VK_IMAGE_ASPECT_STENCIL_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, layout);
933 void initialTransitionDepthStencil2DImage (const vk::DeviceInterface &vk, vk::VkCommandBuffer cmdBuffer, vk::VkImage image, vk::VkImageLayout layout)
935 transition2DImage(vk, cmdBuffer, image, vk::VK_IMAGE_ASPECT_DEPTH_BIT | vk::VK_IMAGE_ASPECT_STENCIL_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, layout);