1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2015 The Khronos Group Inc.
6 * Copyright (c) 2015 Intel Corporation
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
22 * \brief Image Object Util
23 *//*--------------------------------------------------------------------*/
25 #include "vktQueryPoolImageObjectUtil.hpp"
27 #include "tcuSurface.hpp"
28 #include "tcuVectorUtil.hpp"
30 #include "vkRefUtil.hpp"
31 #include "vkQueryUtil.hpp"
32 #include "vkImageUtil.hpp"
33 #include "vktQueryPoolCreateInfoUtil.hpp"
34 #include "vktQueryPoolBufferObjectUtil.hpp"
36 #include "tcuTextureUtil.hpp"
43 void MemoryOp::pack (int pixelSize,
47 vk::VkDeviceSize rowPitchOrZero,
48 vk::VkDeviceSize depthPitchOrZero,
49 const void * srcBuffer,
52 vk::VkDeviceSize rowPitch = rowPitchOrZero;
53 vk::VkDeviceSize depthPitch = depthPitchOrZero;
56 rowPitch = width * pixelSize;
59 depthPitch = rowPitch * height;
61 const vk::VkDeviceSize size = depthPitch * depth;
63 const char *srcRow = reinterpret_cast<const char *>(srcBuffer);
66 char *dstRow = reinterpret_cast<char *>(destBuffer);
70 if (rowPitch == static_cast<vk::VkDeviceSize>(width * pixelSize) &&
71 depthPitch == static_cast<vk::VkDeviceSize>(rowPitch * height))
74 deMemcpy(dstRow, srcRow, static_cast<size_t>(size));
78 // slower, per row path
79 for (int d = 0; d < depth; d++)
81 vk::VkDeviceSize offsetDepthDst = d * depthPitch;
82 vk::VkDeviceSize offsetDepthSrc = d * (pixelSize * width * height);
83 srcRow = srcStart + offsetDepthSrc;
84 dstRow = dstStart + offsetDepthDst;
85 for (int r = 0; r < height; ++r)
87 deMemcpy(dstRow, srcRow, static_cast<size_t>(rowPitch));
88 srcRow += pixelSize * width;
95 void MemoryOp::unpack (int pixelSize,
99 vk::VkDeviceSize rowPitchOrZero,
100 vk::VkDeviceSize depthPitchOrZero,
101 const void * srcBuffer,
104 vk::VkDeviceSize rowPitch = rowPitchOrZero;
105 vk::VkDeviceSize depthPitch = depthPitchOrZero;
108 rowPitch = width * pixelSize;
111 depthPitch = rowPitch * height;
113 const vk::VkDeviceSize size = depthPitch * depth;
115 const char *srcRow = reinterpret_cast<const char *>(srcBuffer);
116 const char *srcStart;
118 char *dstRow = reinterpret_cast<char *>(destBuffer);
122 if (rowPitch == static_cast<vk::VkDeviceSize>(width * pixelSize) &&
123 depthPitch == static_cast<vk::VkDeviceSize>(rowPitch * height))
126 deMemcpy(dstRow, srcRow, static_cast<size_t>(size));
130 // slower, per row path
131 for (size_t d = 0; d < (size_t)depth; d++)
133 vk::VkDeviceSize offsetDepthDst = d * (pixelSize * width * height);
134 vk::VkDeviceSize offsetDepthSrc = d * depthPitch;
135 srcRow = srcStart + offsetDepthSrc;
136 dstRow = dstStart + offsetDepthDst;
137 for (int r = 0; r < height; ++r)
139 deMemcpy(dstRow, srcRow, static_cast<size_t>(pixelSize * width));
141 dstRow += pixelSize * width;
147 Image::Image (const vk::DeviceInterface& vk,
150 const vk::VkExtent3D& extend,
153 vk::Move<vk::VkImage> object_)
154 : m_allocation (DE_NULL)
158 , m_levelCount (levelCount)
159 , m_layerCount (layerCount)
165 tcu::ConstPixelBufferAccess Image::readVolume (vk::VkQueue queue,
166 vk::Allocator& allocator,
167 vk::VkImageLayout layout,
168 vk::VkOffset3D offset,
172 vk::VkImageAspectFlagBits aspect,
173 unsigned int mipLevel,
174 unsigned int arrayElement)
176 m_pixelAccessData.resize(width * height * depth * vk::mapVkFormat(m_format).getPixelSize());
177 deMemset(m_pixelAccessData.data(), 0, m_pixelAccessData.size());
178 if (aspect == vk::VK_IMAGE_ASPECT_COLOR_BIT)
180 read(queue, allocator, layout, offset, width, height, depth, mipLevel, arrayElement, aspect, vk::VK_IMAGE_TYPE_3D,
181 m_pixelAccessData.data());
183 if (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT || aspect == vk::VK_IMAGE_ASPECT_STENCIL_BIT)
185 readUsingBuffer(queue, allocator, layout, offset, width, height, depth, mipLevel, arrayElement, aspect, m_pixelAccessData.data());
187 return tcu::ConstPixelBufferAccess(vk::mapVkFormat(m_format), width, height, depth, m_pixelAccessData.data());
190 tcu::ConstPixelBufferAccess Image::readSurface1D(vk::VkQueue queue,
191 vk::Allocator& allocator,
192 vk::VkImageLayout layout,
193 vk::VkOffset3D offset,
195 vk::VkImageAspectFlagBits aspect,
196 unsigned int mipLevel,
197 unsigned int arrayElement)
199 m_pixelAccessData.resize(width * vk::mapVkFormat(m_format).getPixelSize());
200 deMemset(m_pixelAccessData.data(), 0, m_pixelAccessData.size());
201 if (aspect == vk::VK_IMAGE_ASPECT_COLOR_BIT)
203 read(queue, allocator, layout, offset, width, 1, 1, mipLevel, arrayElement, aspect, vk::VK_IMAGE_TYPE_1D,
204 m_pixelAccessData.data());
206 if (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT || aspect == vk::VK_IMAGE_ASPECT_STENCIL_BIT)
208 readUsingBuffer(queue, allocator, layout, offset, width, 1, 1, mipLevel, arrayElement, aspect,
209 m_pixelAccessData.data());
211 return tcu::ConstPixelBufferAccess(vk::mapVkFormat(m_format), width, 1, 1, m_pixelAccessData.data());
214 void Image::read (vk::VkQueue queue,
215 vk::Allocator& allocator,
216 vk::VkImageLayout layout,
217 vk::VkOffset3D offset,
221 unsigned int mipLevel,
222 unsigned int arrayElement,
223 vk::VkImageAspectFlagBits aspect,
224 vk::VkImageType type,
227 DE_ASSERT(layout == vk::VK_IMAGE_LAYOUT_GENERAL || layout == vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
229 de::SharedPtr<Image> stagingResource = copyToLinearImage(queue, allocator, layout, offset, width,
230 height, depth, mipLevel, arrayElement, aspect, type);
231 const vk::VkOffset3D zeroOffset = {0, 0, 0};
232 stagingResource->readLinear(zeroOffset, width, height, depth, 0, 0, aspect, data);
235 void Image::readUsingBuffer (vk::VkQueue queue,
236 vk::Allocator& allocator,
237 vk::VkImageLayout layout,
238 vk::VkOffset3D offset,
242 unsigned int mipLevel,
243 unsigned int arrayElement,
244 vk::VkImageAspectFlagBits aspect,
247 DE_ASSERT(layout == vk::VK_IMAGE_LAYOUT_GENERAL || layout == vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);;
249 de::SharedPtr<Buffer> stagingResource;
251 bool isCombinedType = isCombinedDepthStencilType(vk::mapVkFormat(m_format).type);
252 vk::VkDeviceSize bufferSize = 0;
255 bufferSize = vk::mapVkFormat(m_format).getPixelSize() * width * height * depth;
262 case vk::VK_FORMAT_D16_UNORM_S8_UINT:
263 pixelSize = (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT) ? 2 : 1;
265 case vk::VK_FORMAT_D32_SFLOAT_S8_UINT:
266 pixelSize = (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT) ? 4 : 1;
268 case vk::VK_FORMAT_X8_D24_UNORM_PACK32:
269 case vk::VK_FORMAT_D24_UNORM_S8_UINT:
270 pixelSize = (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT) ? 3 : 1;
274 DE_FATAL("Not implemented");
276 bufferSize = pixelSize*width*height*depth;
279 BufferCreateInfo stagingBufferResourceCreateInfo(bufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT | vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
280 stagingResource = Buffer::createAndAlloc(m_vk, m_device, stagingBufferResourceCreateInfo, allocator, vk::MemoryRequirement::HostVisible);
283 //todo [scygan] get proper queueFamilyIndex
284 CmdPoolCreateInfo copyCmdPoolCreateInfo(0);
285 vk::Unique<vk::VkCommandPool> copyCmdPool(vk::createCommandPool(m_vk, m_device, ©CmdPoolCreateInfo));
287 const vk::VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
289 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
290 DE_NULL, // const void* pNext;
291 *copyCmdPool, // VkCommandPool commandPool;
292 vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCommandBufferLevel level;
293 1u, // deUint32 bufferCount;
295 vk::Unique<vk::VkCommandBuffer> copyCmdBuffer(vk::allocateCommandBuffer(m_vk, m_device, &cmdBufferAllocateInfo));
297 CmdBufferBeginInfo beginInfo;
298 VK_CHECK(m_vk.beginCommandBuffer(*copyCmdBuffer, &beginInfo));
300 if (layout == vk::VK_IMAGE_LAYOUT_UNDEFINED)
302 layout = vk::VK_IMAGE_LAYOUT_GENERAL;
304 vk::VkImageMemoryBarrier barrier;
305 barrier.sType = vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
306 barrier.pNext = DE_NULL;
307 barrier.srcAccessMask = 0;
308 barrier.dstAccessMask = 0;
309 barrier.oldLayout = vk::VK_IMAGE_LAYOUT_UNDEFINED;
310 barrier.newLayout = vk::VK_IMAGE_LAYOUT_GENERAL;
311 barrier.srcQueueFamilyIndex = vk::VK_QUEUE_FAMILY_IGNORED;
312 barrier.dstQueueFamilyIndex = vk::VK_QUEUE_FAMILY_IGNORED;
313 barrier.image = object();
315 barrier.subresourceRange.aspectMask = aspect;
316 barrier.subresourceRange.baseMipLevel = 0;
317 barrier.subresourceRange.levelCount = m_levelCount;
318 barrier.subresourceRange.baseArrayLayer = 0;
319 barrier.subresourceRange.layerCount = m_layerCount;
321 m_vk.cmdPipelineBarrier(*copyCmdBuffer, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (vk::VkDependencyFlags)0,
322 0, (const vk::VkMemoryBarrier*)DE_NULL,
323 0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
327 const vk::VkBufferImageCopy region =
330 { aspect, mipLevel, arrayElement, 1 },
332 { (deUint32)width, (deUint32)height, (deUint32)depth }
335 m_vk.cmdCopyImageToBuffer(*copyCmdBuffer, object(), layout, stagingResource->object(), 1, ®ion);
336 VK_CHECK(m_vk.endCommandBuffer(*copyCmdBuffer));
338 const vk::VkSubmitInfo submitInfo =
340 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
341 DE_NULL, // const void* pNext;
342 0, // deUint32 waitSemaphoreCount;
343 DE_NULL, // const VkSemaphore* pWaitSemaphores;
344 (const vk::VkPipelineStageFlags*)DE_NULL,
345 1, // deUint32 commandBufferCount;
346 ©CmdBuffer.get(), // const VkCommandBuffer* pCommandBuffers;
347 0, // deUint32 signalSemaphoreCount;
348 DE_NULL // const VkSemaphore* pSignalSemaphores;
350 m_vk.queueSubmit(queue, 1, &submitInfo, DE_NULL);
352 // TODO: make this less intrusive
353 VK_CHECK(m_vk.queueWaitIdle(queue));
356 char* destPtr = reinterpret_cast<char*>(stagingResource->getBoundMemory().getHostPtr());
357 deMemcpy(data, destPtr, static_cast<size_t>(bufferSize));
360 tcu::ConstPixelBufferAccess Image::readSurfaceLinear (vk::VkOffset3D offset,
364 vk::VkImageAspectFlagBits aspect,
365 unsigned int mipLevel,
366 unsigned int arrayElement)
368 m_pixelAccessData.resize(width * height * vk::mapVkFormat(m_format).getPixelSize());
369 readLinear(offset, width, height, depth, mipLevel, arrayElement, aspect, m_pixelAccessData.data());
370 return tcu::ConstPixelBufferAccess(vk::mapVkFormat(m_format), width, height, 1, m_pixelAccessData.data());
373 void Image::readLinear (vk::VkOffset3D offset,
377 unsigned int mipLevel,
378 unsigned int arrayElement,
379 vk::VkImageAspectFlagBits aspect,
382 vk::VkImageSubresource imageSubResource = { aspect, mipLevel, arrayElement };
384 vk::VkSubresourceLayout imageLayout;
385 deMemset(&imageLayout, 0, sizeof(imageLayout));
387 m_vk.getImageSubresourceLayout(m_device, object(), &imageSubResource, &imageLayout);
389 const char* srcPtr = reinterpret_cast<const char*>(getBoundMemory().getHostPtr());
390 srcPtr += imageLayout.offset + getPixelOffset(offset, imageLayout.rowPitch, imageLayout.depthPitch, mipLevel, arrayElement);
392 MemoryOp::unpack(vk::mapVkFormat(m_format).getPixelSize(), width, height, depth,
393 imageLayout.rowPitch, imageLayout.depthPitch, srcPtr, data);
396 de::SharedPtr<Image> Image::copyToLinearImage (vk::VkQueue queue,
397 vk::Allocator& allocator,
398 vk::VkImageLayout layout,
399 vk::VkOffset3D offset,
403 unsigned int mipLevel,
404 unsigned int arrayElement,
405 vk::VkImageAspectFlagBits aspect,
406 vk::VkImageType type)
408 de::SharedPtr<Image> stagingResource;
410 vk::VkExtent3D stagingExtent = {(deUint32)width, (deUint32)height, (deUint32)depth};
411 ImageCreateInfo stagingResourceCreateInfo(type, m_format, stagingExtent, 1, 1, vk::VK_SAMPLE_COUNT_1_BIT,
412 vk::VK_IMAGE_TILING_LINEAR, vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT);
414 stagingResource = Image::createAndAlloc(m_vk, m_device, stagingResourceCreateInfo, allocator,
415 vk::MemoryRequirement::HostVisible);
417 //todo [scygan] get proper queueFamilyIndex
418 CmdPoolCreateInfo copyCmdPoolCreateInfo(0);
419 vk::Unique<vk::VkCommandPool> copyCmdPool(vk::createCommandPool(m_vk, m_device, ©CmdPoolCreateInfo));
421 const vk::VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
423 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
424 DE_NULL, // const void* pNext;
425 *copyCmdPool, // VkCommandPool commandPool;
426 vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCommandBufferLevel level;
427 1u, // deUint32 bufferCount;
429 vk::Unique<vk::VkCommandBuffer> copyCmdBuffer(vk::allocateCommandBuffer(m_vk, m_device, &cmdBufferAllocateInfo));
431 CmdBufferBeginInfo beginInfo;
432 VK_CHECK(m_vk.beginCommandBuffer(*copyCmdBuffer, &beginInfo));
434 transition2DImage(m_vk, *copyCmdBuffer, stagingResource->object(), aspect, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_GENERAL);
436 const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
437 vk::VkImageCopy region = { {aspect, mipLevel, arrayElement, 1}, offset, {aspect, 0, 0, 1}, zeroOffset, {(deUint32)width, (deUint32)height, (deUint32)depth} };
439 m_vk.cmdCopyImage(*copyCmdBuffer, object(), layout, stagingResource->object(), vk::VK_IMAGE_LAYOUT_GENERAL, 1, ®ion);
440 VK_CHECK(m_vk.endCommandBuffer(*copyCmdBuffer));
442 const vk::VkSubmitInfo submitInfo =
444 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
445 DE_NULL, // const void* pNext;
446 0, // deUint32 waitSemaphoreCount;
447 DE_NULL, // const VkSemaphore* pWaitSemaphores;
448 (const vk::VkPipelineStageFlags*)DE_NULL,
449 1, // deUint32 commandBufferCount;
450 ©CmdBuffer.get(), // const VkCommandBuffer* pCommandBuffers;
451 0, // deUint32 signalSemaphoreCount;
452 DE_NULL // const VkSemaphore* pSignalSemaphores;
454 m_vk.queueSubmit(queue, 1, &submitInfo, DE_NULL);
456 // TODO: make this less intrusive
457 VK_CHECK(m_vk.queueWaitIdle(queue));
459 return stagingResource;
462 void Image::uploadVolume(const tcu::ConstPixelBufferAccess& access,
464 vk::Allocator& allocator,
465 vk::VkImageLayout layout,
466 vk::VkOffset3D offset,
467 vk::VkImageAspectFlagBits aspect,
468 unsigned int mipLevel,
469 unsigned int arrayElement)
471 if (aspect == vk::VK_IMAGE_ASPECT_COLOR_BIT)
473 upload(queue, allocator, layout, offset, access.getWidth(),
474 access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, vk::VK_IMAGE_TYPE_3D,
475 access.getDataPtr());
477 if (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT || aspect == vk::VK_IMAGE_ASPECT_STENCIL_BIT)
479 uploadUsingBuffer(queue, allocator, layout, offset, access.getWidth(),
480 access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, access.getDataPtr());
484 void Image::uploadSurface (const tcu::ConstPixelBufferAccess& access,
486 vk::Allocator& allocator,
487 vk::VkImageLayout layout,
488 vk::VkOffset3D offset,
489 vk::VkImageAspectFlagBits aspect,
490 unsigned int mipLevel,
491 unsigned int arrayElement)
493 if (aspect == vk::VK_IMAGE_ASPECT_COLOR_BIT)
495 upload(queue, allocator, layout, offset, access.getWidth(),
496 access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, vk::VK_IMAGE_TYPE_2D,
497 access.getDataPtr());
499 if (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT || aspect == vk::VK_IMAGE_ASPECT_STENCIL_BIT)
501 uploadUsingBuffer(queue, allocator, layout, offset, access.getWidth(),
502 access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, access.getDataPtr());
506 void Image::uploadSurface1D (const tcu::ConstPixelBufferAccess& access,
508 vk::Allocator& allocator,
509 vk::VkImageLayout layout,
510 vk::VkOffset3D offset,
511 vk::VkImageAspectFlagBits aspect,
512 unsigned int mipLevel,
513 unsigned int arrayElement)
515 if (aspect == vk::VK_IMAGE_ASPECT_COLOR_BIT)
517 upload(queue, allocator, layout, offset, access.getWidth(),
518 access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, vk::VK_IMAGE_TYPE_1D,
519 access.getDataPtr());
521 if (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT || aspect == vk::VK_IMAGE_ASPECT_STENCIL_BIT)
523 uploadUsingBuffer(queue, allocator, layout, offset, access.getWidth(),
524 access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, access.getDataPtr());
528 void Image::uploadSurfaceLinear (const tcu::ConstPixelBufferAccess& access,
529 vk::VkOffset3D offset,
533 vk::VkImageAspectFlagBits aspect,
534 unsigned int mipLevel,
535 unsigned int arrayElement)
537 uploadLinear(offset, width, height, depth, mipLevel, arrayElement, aspect, access.getDataPtr());
540 void Image::upload (vk::VkQueue queue,
541 vk::Allocator& allocator,
542 vk::VkImageLayout layout,
543 vk::VkOffset3D offset,
547 unsigned int mipLevel,
548 unsigned int arrayElement,
549 vk::VkImageAspectFlagBits aspect,
550 vk::VkImageType type,
553 DE_ASSERT(layout == vk::VK_IMAGE_LAYOUT_GENERAL || layout == vk::VK_IMAGE_LAYOUT_UNDEFINED || layout == vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
555 de::SharedPtr<Image> stagingResource;
556 vk::VkExtent3D extent = {(deUint32)width, (deUint32)height, (deUint32)depth};
557 ImageCreateInfo stagingResourceCreateInfo(
558 type, m_format, extent, 1, 1, vk::VK_SAMPLE_COUNT_1_BIT,
559 vk::VK_IMAGE_TILING_LINEAR, vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
561 stagingResource = Image::createAndAlloc(m_vk, m_device, stagingResourceCreateInfo, allocator,
562 vk::MemoryRequirement::HostVisible);
564 const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
565 stagingResource->uploadLinear(zeroOffset, width, height, depth, 0, 0, aspect, data);
568 //todo [scygan] get proper queueFamilyIndex
569 CmdPoolCreateInfo copyCmdPoolCreateInfo(0);
570 vk::Unique<vk::VkCommandPool> copyCmdPool(vk::createCommandPool(m_vk, m_device, ©CmdPoolCreateInfo));
572 const vk::VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
574 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
575 DE_NULL, // const void* pNext;
576 *copyCmdPool, // VkCommandPool commandPool;
577 vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCommandBufferLevel level;
578 1u, // deUint32 bufferCount;
581 vk::Unique<vk::VkCommandBuffer> copyCmdBuffer(vk::allocateCommandBuffer(m_vk, m_device, &cmdBufferAllocateInfo));
583 CmdBufferBeginInfo beginInfo;
584 VK_CHECK(m_vk.beginCommandBuffer(*copyCmdBuffer, &beginInfo));
586 if (layout == vk::VK_IMAGE_LAYOUT_UNDEFINED)
588 layout = vk::VK_IMAGE_LAYOUT_GENERAL;
590 vk::VkImageMemoryBarrier barrier;
591 barrier.sType = vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
592 barrier.pNext = DE_NULL;
593 barrier.srcAccessMask = 0;
594 barrier.dstAccessMask = 0;
595 barrier.oldLayout = vk::VK_IMAGE_LAYOUT_UNDEFINED;
596 barrier.newLayout = vk::VK_IMAGE_LAYOUT_GENERAL;
597 barrier.srcQueueFamilyIndex = vk::VK_QUEUE_FAMILY_IGNORED;
598 barrier.dstQueueFamilyIndex = vk::VK_QUEUE_FAMILY_IGNORED;
599 barrier.image = object();
601 barrier.subresourceRange.aspectMask = aspect;
602 barrier.subresourceRange.baseMipLevel = 0;
603 barrier.subresourceRange.levelCount = m_levelCount;
604 barrier.subresourceRange.baseArrayLayer = 0;
605 barrier.subresourceRange.layerCount = m_layerCount;
607 m_vk.cmdPipelineBarrier(*copyCmdBuffer, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (vk::VkDependencyFlags)0,
608 0, (const vk::VkMemoryBarrier*)DE_NULL,
609 0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
613 transition2DImage(m_vk, *copyCmdBuffer, stagingResource->object(), aspect, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_GENERAL);
615 vk::VkImageCopy region = {{aspect, 0, 0, 1},
617 {aspect, mipLevel, arrayElement, 1},
619 {(deUint32)width, (deUint32)height, (deUint32)depth}};
621 m_vk.cmdCopyImage(*copyCmdBuffer, stagingResource->object(),
622 vk::VK_IMAGE_LAYOUT_GENERAL, object(), layout, 1, ®ion);
623 VK_CHECK(m_vk.endCommandBuffer(*copyCmdBuffer));
625 const vk::VkSubmitInfo submitInfo =
627 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
628 DE_NULL, // const void* pNext;
629 0, // deUint32 waitSemaphoreCount;
630 DE_NULL, // const VkSemaphore* pWaitSemaphores;
631 (const vk::VkPipelineStageFlags*)DE_NULL,
632 1, // deUint32 commandBufferCount;
633 ©CmdBuffer.get(), // const VkCommandBuffer* pCommandBuffers;
634 0, // deUint32 signalSemaphoreCount;
635 DE_NULL // const VkSemaphore* pSignalSemaphores;
637 m_vk.queueSubmit(queue, 1, &submitInfo, DE_NULL);
639 // TODO: make this less intrusive
640 VK_CHECK(m_vk.queueWaitIdle(queue));
644 void Image::uploadUsingBuffer (vk::VkQueue queue,
645 vk::Allocator& allocator,
646 vk::VkImageLayout layout,
647 vk::VkOffset3D offset,
651 unsigned int mipLevel,
652 unsigned int arrayElement,
653 vk::VkImageAspectFlagBits aspect,
656 DE_ASSERT(layout == vk::VK_IMAGE_LAYOUT_GENERAL || layout == vk::VK_IMAGE_LAYOUT_UNDEFINED || layout == vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
658 de::SharedPtr<Buffer> stagingResource;
659 bool isCombinedType = isCombinedDepthStencilType(vk::mapVkFormat(m_format).type);
660 vk::VkDeviceSize bufferSize = 0;
662 bufferSize = vk::mapVkFormat(m_format).getPixelSize() *width*height*depth;
668 case vk::VK_FORMAT_D16_UNORM_S8_UINT:
669 pixelSize = (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT) ? 2 : 1;
671 case vk::VK_FORMAT_D32_SFLOAT_S8_UINT:
672 pixelSize = (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT) ? 4 : 1;
674 case vk::VK_FORMAT_X8_D24_UNORM_PACK32:
675 case vk::VK_FORMAT_D24_UNORM_S8_UINT:
676 pixelSize = (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT) ? 3 : 1;
680 DE_FATAL("Not implemented");
682 bufferSize = pixelSize*width*height*depth;
684 BufferCreateInfo stagingBufferResourceCreateInfo(bufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT | vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
685 stagingResource = Buffer::createAndAlloc(m_vk, m_device, stagingBufferResourceCreateInfo, allocator, vk::MemoryRequirement::HostVisible);
686 char* destPtr = reinterpret_cast<char*>(stagingResource->getBoundMemory().getHostPtr());
687 deMemcpy(destPtr, data, static_cast<size_t>(bufferSize));
688 vk::flushMappedMemoryRange(m_vk, m_device, stagingResource->getBoundMemory().getMemory(), stagingResource->getBoundMemory().getOffset(), bufferSize);
690 //todo [scygan] get proper queueFamilyIndex
691 CmdPoolCreateInfo copyCmdPoolCreateInfo(0);
692 vk::Unique<vk::VkCommandPool> copyCmdPool(vk::createCommandPool(m_vk, m_device, ©CmdPoolCreateInfo));
694 const vk::VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
696 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
697 DE_NULL, // const void* pNext;
698 *copyCmdPool, // VkCommandPool commandPool;
699 vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCommandBufferLevel level;
700 1u, // deUint32 bufferCount;
702 vk::Unique<vk::VkCommandBuffer> copyCmdBuffer(vk::allocateCommandBuffer(m_vk, m_device, &cmdBufferAllocateInfo));
704 CmdBufferBeginInfo beginInfo;
705 VK_CHECK(m_vk.beginCommandBuffer(*copyCmdBuffer, &beginInfo));
707 if (layout == vk::VK_IMAGE_LAYOUT_UNDEFINED)
709 layout = vk::VK_IMAGE_LAYOUT_GENERAL;
711 vk::VkImageMemoryBarrier barrier;
712 barrier.sType = vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
713 barrier.pNext = DE_NULL;
714 barrier.srcAccessMask = 0;
715 barrier.dstAccessMask = 0;
716 barrier.oldLayout = vk::VK_IMAGE_LAYOUT_UNDEFINED;
717 barrier.newLayout = vk::VK_IMAGE_LAYOUT_GENERAL;
718 barrier.srcQueueFamilyIndex = vk::VK_QUEUE_FAMILY_IGNORED;
719 barrier.dstQueueFamilyIndex = vk::VK_QUEUE_FAMILY_IGNORED;
720 barrier.image = object();
722 barrier.subresourceRange.aspectMask = aspect;
723 barrier.subresourceRange.baseMipLevel = 0;
724 barrier.subresourceRange.levelCount = m_levelCount;
725 barrier.subresourceRange.baseArrayLayer = 0;
726 barrier.subresourceRange.layerCount = m_layerCount;
728 m_vk.cmdPipelineBarrier(*copyCmdBuffer, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (vk::VkDependencyFlags)0,
729 0, (const vk::VkMemoryBarrier*)DE_NULL,
730 0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
734 vk::VkBufferImageCopy region =
737 { aspect, mipLevel, arrayElement, 1 },
739 { (deUint32)width, (deUint32)height, (deUint32)depth }
742 m_vk.cmdCopyBufferToImage(*copyCmdBuffer, stagingResource->object(),
743 object(), layout, 1, ®ion);
744 VK_CHECK(m_vk.endCommandBuffer(*copyCmdBuffer));
746 vk::VkSubmitInfo submitInfo =
748 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
749 DE_NULL, // const void* pNext;
750 0, // deUint32 waitSemaphoreCount;
751 DE_NULL, // const VkSemaphore* pWaitSemaphores;
752 (const vk::VkPipelineStageFlags*)DE_NULL,
753 1, // deUint32 commandBufferCount;
754 ©CmdBuffer.get(), // const VkCommandBuffer* pCommandBuffers;
755 0, // deUint32 signalSemaphoreCount;
756 DE_NULL // const VkSemaphore* pSignalSemaphores;
758 m_vk.queueSubmit(queue, 1, &submitInfo, DE_NULL);
760 // TODO: make this less intrusive
761 VK_CHECK(m_vk.queueWaitIdle(queue));
765 void Image::uploadLinear (vk::VkOffset3D offset,
769 unsigned int mipLevel,
770 unsigned int arrayElement,
771 vk::VkImageAspectFlagBits aspect,
774 vk::VkSubresourceLayout imageLayout;
776 vk::VkImageSubresource imageSubResource = {aspect, mipLevel, arrayElement};
778 m_vk.getImageSubresourceLayout(m_device, object(), &imageSubResource,
781 char* destPtr = reinterpret_cast<char*>(getBoundMemory().getHostPtr());
783 destPtr += imageLayout.offset + getPixelOffset(offset, imageLayout.rowPitch, imageLayout.depthPitch, mipLevel, arrayElement);
785 MemoryOp::pack(vk::mapVkFormat(m_format).getPixelSize(), width, height, depth,
786 imageLayout.rowPitch, imageLayout.depthPitch, data, destPtr);
789 vk::VkDeviceSize Image::getPixelOffset (vk::VkOffset3D offset,
790 vk::VkDeviceSize rowPitch,
791 vk::VkDeviceSize depthPitch,
795 DE_ASSERT(level < m_levelCount);
796 DE_ASSERT(layer < m_layerCount);
798 vk::VkDeviceSize mipLevelSizes[32];
799 vk::VkDeviceSize mipLevelRectSizes[32];
801 = tcu::IVec3(m_extent.width, m_extent.height, m_extent.depth);
803 vk::VkDeviceSize arrayElemSize = 0;
804 for (unsigned int i = 0; i < m_levelCount && (mipExtend[0] > 1 || mipExtend[1] > 1 || mipExtend[2] > 1); ++i)
806 // Rect size is just a 3D image size;
807 mipLevelSizes[i] = mipExtend[2] * depthPitch;
809 arrayElemSize += mipLevelSizes[0];
811 mipExtend = tcu::max(mipExtend / 2, tcu::IVec3(1));
814 vk::VkDeviceSize pixelOffset = layer * arrayElemSize;
815 for (size_t i = 0; i < level; ++i)
817 pixelOffset += mipLevelSizes[i];
819 pixelOffset += offset.z * mipLevelRectSizes[level];
820 pixelOffset += offset.y * rowPitch;
821 pixelOffset += offset.x;
826 void Image::bindMemory (de::MovePtr<vk::Allocation> allocation)
828 DE_ASSERT(allocation);
829 VK_CHECK(m_vk.bindImageMemory(m_device, *m_object, allocation->getMemory(), allocation->getOffset()));
831 DE_ASSERT(!m_allocation);
832 m_allocation = allocation;
835 de::SharedPtr<Image> Image::createAndAlloc(const vk::DeviceInterface& vk,
837 const vk::VkImageCreateInfo& createInfo,
838 vk::Allocator& allocator,
839 vk::MemoryRequirement memoryRequirement)
841 de::SharedPtr<Image> ret = create(vk, device, createInfo);
843 vk::VkMemoryRequirements imageRequirements = vk::getImageMemoryRequirements(vk, device, ret->object());
844 ret->bindMemory(allocator.allocate(imageRequirements, memoryRequirement));
848 de::SharedPtr<Image> Image::create(const vk::DeviceInterface& vk,
850 const vk::VkImageCreateInfo &createInfo)
852 return de::SharedPtr<Image>(new Image(vk, device, createInfo.format, createInfo.extent,
853 createInfo.mipLevels, createInfo.arrayLayers,
854 vk::createImage(vk, device, &createInfo)));
857 void transition2DImage (const vk::DeviceInterface& vk,
858 vk::VkCommandBuffer cmdBuffer,
860 vk::VkImageAspectFlags aspectMask,
861 vk::VkImageLayout oldLayout,
862 vk::VkImageLayout newLayout)
864 vk::VkImageMemoryBarrier barrier;
865 barrier.sType = vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
866 barrier.pNext = DE_NULL;
867 barrier.srcAccessMask = 0;
868 barrier.dstAccessMask = 0;
869 barrier.oldLayout = oldLayout;
870 barrier.newLayout = newLayout;
871 barrier.srcQueueFamilyIndex = vk::VK_QUEUE_FAMILY_IGNORED;
872 barrier.dstQueueFamilyIndex = vk::VK_QUEUE_FAMILY_IGNORED;
873 barrier.image = image;
874 barrier.subresourceRange.aspectMask = aspectMask;
875 barrier.subresourceRange.baseMipLevel = 0;
876 barrier.subresourceRange.levelCount = 1;
877 barrier.subresourceRange.baseArrayLayer = 0;
878 barrier.subresourceRange.layerCount = 1;
880 vk.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (vk::VkDependencyFlags)0,
881 0, (const vk::VkMemoryBarrier*)DE_NULL,
882 0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
886 void initialTransitionColor2DImage (const vk::DeviceInterface &vk, vk::VkCommandBuffer cmdBuffer, vk::VkImage image, vk::VkImageLayout layout)
888 transition2DImage(vk, cmdBuffer, image, vk::VK_IMAGE_ASPECT_COLOR_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, layout);
891 void initialTransitionDepth2DImage (const vk::DeviceInterface &vk, vk::VkCommandBuffer cmdBuffer, vk::VkImage image, vk::VkImageLayout layout)
893 transition2DImage(vk, cmdBuffer, image, vk::VK_IMAGE_ASPECT_DEPTH_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, layout);
896 void initialTransitionStencil2DImage (const vk::DeviceInterface &vk, vk::VkCommandBuffer cmdBuffer, vk::VkImage image, vk::VkImageLayout layout)
898 transition2DImage(vk, cmdBuffer, image, vk::VK_IMAGE_ASPECT_STENCIL_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, layout);
901 void initialTransitionDepthStencil2DImage (const vk::DeviceInterface &vk, vk::VkCommandBuffer cmdBuffer, vk::VkImage image, vk::VkImageLayout layout)
903 transition2DImage(vk, cmdBuffer, image, vk::VK_IMAGE_ASPECT_DEPTH_BIT | vk::VK_IMAGE_ASPECT_STENCIL_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, layout);