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 void* barriers[] = { &barrier };
357 m_vk.cmdPipelineBarrier(*copyCmdBuffer, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
358 false, DE_LENGTH_OF_ARRAY(barriers), barriers);
361 vk::VkBufferImageCopy region =
364 { aspect, mipLevel, arrayElement, 1 },
366 { width, height, 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 1, // deUint32 commandBufferCount;
379 ©CmdBuffer.get(), // const VkCommandBuffer* pCommandBuffers;
380 0, // deUint32 signalSemaphoreCount;
381 DE_NULL // const VkSemaphore* pSignalSemaphores;
383 m_vk.queueSubmit(queue, 1, &submitInfo, DE_NULL);
385 // TODO: make this less intrusive
386 VK_CHECK(m_vk.queueWaitIdle(queue));
389 char* destPtr = reinterpret_cast<char*>(stagingResource->getBoundMemory().getHostPtr());
390 deMemcpy(data, destPtr, static_cast<size_t>(bufferSize));
393 tcu::ConstPixelBufferAccess Image::readSurfaceLinear (vk::VkOffset3D offset,
397 vk::VkImageAspectFlagBits aspect,
398 unsigned int mipLevel,
399 unsigned int arrayElement)
401 m_pixelAccessData.resize(width * height * vk::mapVkFormat(m_format).getPixelSize());
402 readLinear(offset, width, height, depth, mipLevel, arrayElement, aspect, m_pixelAccessData.data());
403 return tcu::ConstPixelBufferAccess(vk::mapVkFormat(m_format), width, height, 1, m_pixelAccessData.data());
406 void Image::readLinear (vk::VkOffset3D offset,
410 unsigned int mipLevel,
411 unsigned int arrayElement,
412 vk::VkImageAspectFlagBits aspect,
415 vk::VkImageSubresource imageSubResource = { aspect, mipLevel, arrayElement };
417 vk::VkSubresourceLayout imageLayout;
418 deMemset(&imageLayout, 0, sizeof(imageLayout));
420 m_vk.getImageSubresourceLayout(m_device, object(), &imageSubResource, &imageLayout);
422 const char* srcPtr = reinterpret_cast<const char*>(getBoundMemory().getHostPtr());
423 srcPtr += imageLayout.offset + getPixelOffset(offset, imageLayout.rowPitch, imageLayout.depthPitch, mipLevel, arrayElement);
425 MemoryOp::unpack(vk::mapVkFormat(m_format).getPixelSize(), width, height, depth,
426 imageLayout.rowPitch, imageLayout.depthPitch, srcPtr, data);
429 de::SharedPtr<Image> Image::copyToLinearImage (vk::VkQueue queue,
430 vk::Allocator& allocator,
431 vk::VkImageLayout layout,
432 vk::VkOffset3D offset,
436 unsigned int mipLevel,
437 unsigned int arrayElement,
438 vk::VkImageAspectFlagBits aspect,
439 vk::VkImageType type)
441 de::SharedPtr<Image> stagingResource;
443 vk::VkExtent3D stagingExtent = {width, height, depth};
444 ImageCreateInfo stagingResourceCreateInfo(type, m_format, stagingExtent, 1, 1, vk::VK_SAMPLE_COUNT_1_BIT,
445 vk::VK_IMAGE_TILING_LINEAR, vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT);
447 stagingResource = Image::createAndAlloc(m_vk, m_device, stagingResourceCreateInfo, allocator,
448 vk::MemoryRequirement::HostVisible);
450 //todo [scygan] get proper queueFamilyIndex
451 CmdPoolCreateInfo copyCmdPoolCreateInfo(0);
452 vk::Unique<vk::VkCommandPool> copyCmdPool(vk::createCommandPool(m_vk, m_device, ©CmdPoolCreateInfo));
454 const vk::VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
456 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
457 DE_NULL, // const void* pNext;
458 *copyCmdPool, // VkCommandPool commandPool;
459 vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCommandBufferLevel level;
460 1u, // deUint32 bufferCount;
462 vk::Unique<vk::VkCommandBuffer> copyCmdBuffer(vk::allocateCommandBuffer(m_vk, m_device, &cmdBufferAllocateInfo));
464 CmdBufferBeginInfo beginInfo;
465 VK_CHECK(m_vk.beginCommandBuffer(*copyCmdBuffer, &beginInfo));
467 transition2DImage(m_vk, *copyCmdBuffer, stagingResource->object(), aspect, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_GENERAL);
469 const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
470 vk::VkImageCopy region = { {aspect, mipLevel, arrayElement, 1}, offset, {aspect, 0, 0, 1}, zeroOffset, {width, height, depth} };
472 m_vk.cmdCopyImage(*copyCmdBuffer, object(), layout, stagingResource->object(), vk::VK_IMAGE_LAYOUT_GENERAL, 1, ®ion);
473 VK_CHECK(m_vk.endCommandBuffer(*copyCmdBuffer));
475 vk::VkSubmitInfo submitInfo =
477 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
478 DE_NULL, // const void* pNext;
479 0, // deUint32 waitSemaphoreCount;
480 DE_NULL, // const VkSemaphore* pWaitSemaphores;
481 1, // deUint32 commandBufferCount;
482 ©CmdBuffer.get(), // const VkCommandBuffer* pCommandBuffers;
483 0, // deUint32 signalSemaphoreCount;
484 DE_NULL // const VkSemaphore* pSignalSemaphores;
486 m_vk.queueSubmit(queue, 1, &submitInfo, DE_NULL);
488 // TODO: make this less intrusive
489 VK_CHECK(m_vk.queueWaitIdle(queue));
491 return stagingResource;
494 void Image::uploadVolume(const tcu::ConstPixelBufferAccess& access,
496 vk::Allocator& allocator,
497 vk::VkImageLayout layout,
498 vk::VkOffset3D offset,
499 vk::VkImageAspectFlagBits aspect,
500 unsigned int mipLevel,
501 unsigned int arrayElement)
503 if (aspect == vk::VK_IMAGE_ASPECT_COLOR_BIT)
505 upload(queue, allocator, layout, offset, access.getWidth(),
506 access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, vk::VK_IMAGE_TYPE_3D,
507 access.getDataPtr());
509 if (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT || aspect == vk::VK_IMAGE_ASPECT_STENCIL_BIT)
511 uploadUsingBuffer(queue, allocator, layout, offset, access.getWidth(),
512 access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, access.getDataPtr());
516 void Image::uploadSurface (const tcu::ConstPixelBufferAccess& access,
518 vk::Allocator& allocator,
519 vk::VkImageLayout layout,
520 vk::VkOffset3D offset,
521 vk::VkImageAspectFlagBits aspect,
522 unsigned int mipLevel,
523 unsigned int arrayElement)
525 if (aspect == vk::VK_IMAGE_ASPECT_COLOR_BIT)
527 upload(queue, allocator, layout, offset, access.getWidth(),
528 access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, vk::VK_IMAGE_TYPE_2D,
529 access.getDataPtr());
531 if (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT || aspect == vk::VK_IMAGE_ASPECT_STENCIL_BIT)
533 uploadUsingBuffer(queue, allocator, layout, offset, access.getWidth(),
534 access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, access.getDataPtr());
538 void Image::uploadSurface1D (const tcu::ConstPixelBufferAccess& access,
540 vk::Allocator& allocator,
541 vk::VkImageLayout layout,
542 vk::VkOffset3D offset,
543 vk::VkImageAspectFlagBits aspect,
544 unsigned int mipLevel,
545 unsigned int arrayElement)
547 if (aspect == vk::VK_IMAGE_ASPECT_COLOR_BIT)
549 upload(queue, allocator, layout, offset, access.getWidth(),
550 access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, vk::VK_IMAGE_TYPE_1D,
551 access.getDataPtr());
553 if (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT || aspect == vk::VK_IMAGE_ASPECT_STENCIL_BIT)
555 uploadUsingBuffer(queue, allocator, layout, offset, access.getWidth(),
556 access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, access.getDataPtr());
560 void Image::uploadSurfaceLinear (const tcu::ConstPixelBufferAccess& access,
561 vk::VkOffset3D offset,
565 vk::VkImageAspectFlagBits aspect,
566 unsigned int mipLevel,
567 unsigned int arrayElement)
569 uploadLinear(offset, width, height, depth, mipLevel, arrayElement, aspect, access.getDataPtr());
572 void Image::upload (vk::VkQueue queue,
573 vk::Allocator& allocator,
574 vk::VkImageLayout layout,
575 vk::VkOffset3D offset,
579 unsigned int mipLevel,
580 unsigned int arrayElement,
581 vk::VkImageAspectFlagBits aspect,
582 vk::VkImageType type,
585 DE_ASSERT(layout == vk::VK_IMAGE_LAYOUT_GENERAL || layout == vk::VK_IMAGE_LAYOUT_UNDEFINED || layout == vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
587 de::SharedPtr<Image> stagingResource;
588 vk::VkExtent3D extent = {width, height, depth};
589 ImageCreateInfo stagingResourceCreateInfo(
590 type, m_format, extent, 1, 1, vk::VK_SAMPLE_COUNT_1_BIT,
591 vk::VK_IMAGE_TILING_LINEAR, vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
593 stagingResource = Image::createAndAlloc(m_vk, m_device, stagingResourceCreateInfo, allocator,
594 vk::MemoryRequirement::HostVisible);
596 const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
597 stagingResource->uploadLinear(zeroOffset, width, height, depth, 0, 0, aspect, data);
600 //todo [scygan] get proper queueFamilyIndex
601 CmdPoolCreateInfo copyCmdPoolCreateInfo(0);
602 vk::Unique<vk::VkCommandPool> copyCmdPool(vk::createCommandPool(m_vk, m_device, ©CmdPoolCreateInfo));
604 const vk::VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
606 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
607 DE_NULL, // const void* pNext;
608 *copyCmdPool, // VkCommandPool commandPool;
609 vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCommandBufferLevel level;
610 1u, // deUint32 bufferCount;
613 vk::Unique<vk::VkCommandBuffer> copyCmdBuffer(vk::allocateCommandBuffer(m_vk, m_device, &cmdBufferAllocateInfo));
615 CmdBufferBeginInfo beginInfo;
616 VK_CHECK(m_vk.beginCommandBuffer(*copyCmdBuffer, &beginInfo));
618 if (layout == vk::VK_IMAGE_LAYOUT_UNDEFINED)
620 layout = vk::VK_IMAGE_LAYOUT_GENERAL;
622 vk::VkImageMemoryBarrier barrier;
623 barrier.sType = vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
624 barrier.pNext = DE_NULL;
625 barrier.srcAccessMask = 0;
626 barrier.dstAccessMask = 0;
627 barrier.oldLayout = vk::VK_IMAGE_LAYOUT_UNDEFINED;
628 barrier.newLayout = vk::VK_IMAGE_LAYOUT_GENERAL;
629 barrier.srcQueueFamilyIndex = vk::VK_QUEUE_FAMILY_IGNORED;
630 barrier.dstQueueFamilyIndex = vk::VK_QUEUE_FAMILY_IGNORED;
631 barrier.image = object();
633 barrier.subresourceRange.aspectMask = aspect;
634 barrier.subresourceRange.baseMipLevel = 0;
635 barrier.subresourceRange.levelCount = m_levelCount;
636 barrier.subresourceRange.baseArrayLayer = 0;
637 barrier.subresourceRange.layerCount = m_layerCount;
639 void* barriers[] = { &barrier };
641 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);
644 transition2DImage(m_vk, *copyCmdBuffer, stagingResource->object(), aspect, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_GENERAL);
646 vk::VkImageCopy region = {{aspect, 0, 0, 1},
648 {aspect, mipLevel, arrayElement, 1},
650 {width, height, depth}};
652 m_vk.cmdCopyImage(*copyCmdBuffer, stagingResource->object(),
653 vk::VK_IMAGE_LAYOUT_GENERAL, object(), layout, 1, ®ion);
654 VK_CHECK(m_vk.endCommandBuffer(*copyCmdBuffer));
656 vk::VkSubmitInfo submitInfo =
658 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
659 DE_NULL, // const void* pNext;
660 0, // deUint32 waitSemaphoreCount;
661 DE_NULL, // const VkSemaphore* pWaitSemaphores;
662 1, // deUint32 commandBufferCount;
663 ©CmdBuffer.get(), // const VkCommandBuffer* pCommandBuffers;
664 0, // deUint32 signalSemaphoreCount;
665 DE_NULL // const VkSemaphore* pSignalSemaphores;
667 m_vk.queueSubmit(queue, 1, &submitInfo, DE_NULL);
669 // TODO: make this less intrusive
670 VK_CHECK(m_vk.queueWaitIdle(queue));
674 void Image::uploadUsingBuffer (vk::VkQueue queue,
675 vk::Allocator& allocator,
676 vk::VkImageLayout layout,
677 vk::VkOffset3D offset,
681 unsigned int mipLevel,
682 unsigned int arrayElement,
683 vk::VkImageAspectFlagBits aspect,
686 DE_ASSERT(layout == vk::VK_IMAGE_LAYOUT_GENERAL || layout == vk::VK_IMAGE_LAYOUT_UNDEFINED || layout == vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
688 de::SharedPtr<Buffer> stagingResource;
689 bool isCombinedType = isCombinedDepthStencilType(vk::mapVkFormat(m_format).type);
690 vk::VkDeviceSize bufferSize = 0;
692 bufferSize = vk::mapVkFormat(m_format).getPixelSize() *width*height*depth;
698 case vk::VK_FORMAT_D16_UNORM_S8_UINT:
699 pixelSize = (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT) ? 2 : 1;
701 case vk::VK_FORMAT_D32_SFLOAT_S8_UINT:
702 pixelSize = (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT) ? 4 : 1;
704 case vk::VK_FORMAT_X8_D24_UNORM_PACK32:
705 case vk::VK_FORMAT_D24_UNORM_S8_UINT:
706 pixelSize = (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT) ? 3 : 1;
710 DE_FATAL("Not implemented");
712 bufferSize = pixelSize*width*height*depth;
714 BufferCreateInfo stagingBufferResourceCreateInfo(bufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT | vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
715 stagingResource = Buffer::createAndAlloc(m_vk, m_device, stagingBufferResourceCreateInfo, allocator, vk::MemoryRequirement::HostVisible);
716 char* destPtr = reinterpret_cast<char*>(stagingResource->getBoundMemory().getHostPtr());
717 deMemcpy(destPtr, data, static_cast<size_t>(bufferSize));
718 vk::flushMappedMemoryRange(m_vk, m_device, stagingResource->getBoundMemory().getMemory(), stagingResource->getBoundMemory().getOffset(), bufferSize);
720 //todo [scygan] get proper queueFamilyIndex
721 CmdPoolCreateInfo copyCmdPoolCreateInfo(0);
722 vk::Unique<vk::VkCommandPool> copyCmdPool(vk::createCommandPool(m_vk, m_device, ©CmdPoolCreateInfo));
724 const vk::VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
726 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
727 DE_NULL, // const void* pNext;
728 *copyCmdPool, // VkCommandPool commandPool;
729 vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCommandBufferLevel level;
730 1u, // deUint32 bufferCount;
732 vk::Unique<vk::VkCommandBuffer> copyCmdBuffer(vk::allocateCommandBuffer(m_vk, m_device, &cmdBufferAllocateInfo));
734 CmdBufferBeginInfo beginInfo;
735 VK_CHECK(m_vk.beginCommandBuffer(*copyCmdBuffer, &beginInfo));
737 if (layout == vk::VK_IMAGE_LAYOUT_UNDEFINED)
739 layout = vk::VK_IMAGE_LAYOUT_GENERAL;
741 vk::VkImageMemoryBarrier barrier;
742 barrier.sType = vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
743 barrier.pNext = DE_NULL;
744 barrier.srcAccessMask = 0;
745 barrier.dstAccessMask = 0;
746 barrier.oldLayout = vk::VK_IMAGE_LAYOUT_UNDEFINED;
747 barrier.newLayout = vk::VK_IMAGE_LAYOUT_GENERAL;
748 barrier.srcQueueFamilyIndex = vk::VK_QUEUE_FAMILY_IGNORED;
749 barrier.dstQueueFamilyIndex = vk::VK_QUEUE_FAMILY_IGNORED;
750 barrier.image = object();
752 barrier.subresourceRange.aspectMask = aspect;
753 barrier.subresourceRange.baseMipLevel = 0;
754 barrier.subresourceRange.levelCount = m_levelCount;
755 barrier.subresourceRange.baseArrayLayer = 0;
756 barrier.subresourceRange.layerCount = m_layerCount;
758 void* barriers[] = { &barrier };
760 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);
763 vk::VkBufferImageCopy region = {
765 { aspect, mipLevel, arrayElement, 1 },
767 { width, height, depth }
770 m_vk.cmdCopyBufferToImage(*copyCmdBuffer, stagingResource->object(),
771 object(), layout, 1, ®ion);
772 VK_CHECK(m_vk.endCommandBuffer(*copyCmdBuffer));
774 vk::VkSubmitInfo submitInfo =
776 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
777 DE_NULL, // const void* pNext;
778 0, // deUint32 waitSemaphoreCount;
779 DE_NULL, // const VkSemaphore* pWaitSemaphores;
780 1, // deUint32 commandBufferCount;
781 ©CmdBuffer.get(), // const VkCommandBuffer* pCommandBuffers;
782 0, // deUint32 signalSemaphoreCount;
783 DE_NULL // const VkSemaphore* pSignalSemaphores;
785 m_vk.queueSubmit(queue, 1, &submitInfo, DE_NULL);
787 // TODO: make this less intrusive
788 VK_CHECK(m_vk.queueWaitIdle(queue));
792 void Image::uploadLinear (vk::VkOffset3D offset,
796 unsigned int mipLevel,
797 unsigned int arrayElement,
798 vk::VkImageAspectFlagBits aspect,
801 vk::VkSubresourceLayout imageLayout;
803 vk::VkImageSubresource imageSubResource = {aspect, mipLevel, arrayElement};
805 m_vk.getImageSubresourceLayout(m_device, object(), &imageSubResource,
808 char* destPtr = reinterpret_cast<char*>(getBoundMemory().getHostPtr());
810 destPtr += imageLayout.offset + getPixelOffset(offset, imageLayout.rowPitch, imageLayout.depthPitch, mipLevel, arrayElement);
812 MemoryOp::pack(vk::mapVkFormat(m_format).getPixelSize(), width, height, depth,
813 imageLayout.rowPitch, imageLayout.depthPitch, data, destPtr);
816 vk::VkDeviceSize Image::getPixelOffset (vk::VkOffset3D offset,
817 vk::VkDeviceSize rowPitch,
818 vk::VkDeviceSize depthPitch,
822 DE_ASSERT(level < m_levelCount);
823 DE_ASSERT(layer < m_layerCount);
825 vk::VkDeviceSize mipLevelSizes[32];
826 vk::VkDeviceSize mipLevelRectSizes[32];
828 = tcu::IVec3(m_extent.width, m_extent.height, m_extent.depth);
830 vk::VkDeviceSize arrayElemSize = 0;
831 for (unsigned int i = 0; i < m_levelCount && (mipExtend[0] > 1 || mipExtend[1] > 1 || mipExtend[2] > 1); ++i)
833 // Rect size is just a 3D image size;
834 mipLevelSizes[i] = mipExtend[2] * depthPitch;
836 arrayElemSize += mipLevelSizes[0];
838 mipExtend = tcu::max(mipExtend / 2, tcu::IVec3(1));
841 vk::VkDeviceSize pixelOffset = layer * arrayElemSize;
842 for (size_t i = 0; i < level; ++i) {
843 pixelOffset += mipLevelSizes[i];
845 pixelOffset += offset.z * mipLevelRectSizes[level];
846 pixelOffset += offset.y * rowPitch;
847 pixelOffset += offset.x;
852 void Image::bindMemory (de::MovePtr<vk::Allocation> allocation)
854 DE_ASSERT(allocation);
855 VK_CHECK(m_vk.bindImageMemory(m_device, *m_object, allocation->getMemory(), allocation->getOffset()));
857 DE_ASSERT(!m_allocation);
858 m_allocation = allocation;
861 de::SharedPtr<Image> Image::createAndAlloc(const vk::DeviceInterface& vk,
863 const vk::VkImageCreateInfo& createInfo,
864 vk::Allocator& allocator,
865 vk::MemoryRequirement memoryRequirement)
867 de::SharedPtr<Image> ret = create(vk, device, createInfo);
869 vk::VkMemoryRequirements imageRequirements = vk::getImageMemoryRequirements(vk, device, ret->object());
870 ret->bindMemory(allocator.allocate(imageRequirements, memoryRequirement));
874 de::SharedPtr<Image> Image::create(const vk::DeviceInterface& vk,
876 const vk::VkImageCreateInfo &createInfo)
878 return de::SharedPtr<Image>(new Image(vk, device, createInfo.format, createInfo.extent,
879 createInfo.mipLevels, createInfo.arrayLayers,
880 vk::createImage(vk, device, &createInfo)));
883 void transition2DImage (const vk::DeviceInterface& vk,
884 vk::VkCommandBuffer cmdBuffer,
886 vk::VkImageAspectFlags aspectMask,
887 vk::VkImageLayout oldLayout,
888 vk::VkImageLayout newLayout)
890 vk::VkImageMemoryBarrier barrier;
891 barrier.sType = vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
892 barrier.pNext = DE_NULL;
893 barrier.srcAccessMask = 0;
894 barrier.dstAccessMask = 0;
895 barrier.oldLayout = oldLayout;
896 barrier.newLayout = newLayout;
897 barrier.srcQueueFamilyIndex = vk::VK_QUEUE_FAMILY_IGNORED;
898 barrier.dstQueueFamilyIndex = vk::VK_QUEUE_FAMILY_IGNORED;
899 barrier.image = image;
900 barrier.subresourceRange.aspectMask = aspectMask;
901 barrier.subresourceRange.baseMipLevel = 0;
902 barrier.subresourceRange.levelCount = 1;
903 barrier.subresourceRange.baseArrayLayer = 0;
904 barrier.subresourceRange.layerCount = 1;
906 void* barriers[] = { &barrier };
908 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);
911 void initialTransitionColor2DImage (const vk::DeviceInterface &vk, vk::VkCommandBuffer cmdBuffer, vk::VkImage image, vk::VkImageLayout layout)
913 transition2DImage(vk, cmdBuffer, image, vk::VK_IMAGE_ASPECT_COLOR_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, layout);
916 void initialTransitionDepth2DImage (const vk::DeviceInterface &vk, vk::VkCommandBuffer cmdBuffer, vk::VkImage image, vk::VkImageLayout layout)
918 transition2DImage(vk, cmdBuffer, image, vk::VK_IMAGE_ASPECT_DEPTH_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, layout);
921 void initialTransitionStencil2DImage (const vk::DeviceInterface &vk, vk::VkCommandBuffer cmdBuffer, vk::VkImage image, vk::VkImageLayout layout)
923 transition2DImage(vk, cmdBuffer, image, vk::VK_IMAGE_ASPECT_STENCIL_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, layout);
926 void initialTransitionDepthStencil2DImage (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_ASPECT_STENCIL_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, layout);