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 "vktDynamicStateImageObjectUtil.hpp"
27 #include "tcuSurface.hpp"
28 #include "tcuVectorUtil.hpp"
30 #include "vkRefUtil.hpp"
31 #include "vkQueryUtil.hpp"
32 #include "vkImageUtil.hpp"
33 #include "vktDynamicStateCreateInfoUtil.hpp"
34 #include "vktDynamicStateBufferObjectUtil.hpp"
36 #include "tcuTextureUtil.hpp"
40 namespace DynamicState
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));
129 // slower, per row path
130 for (size_t d = 0; d < (size_t)depth; d++)
132 vk::VkDeviceSize offsetDepthDst = d * (pixelSize * width * height);
133 vk::VkDeviceSize offsetDepthSrc = d * depthPitch;
134 srcRow = srcStart + offsetDepthSrc;
135 dstRow = dstStart + offsetDepthDst;
136 for (int r = 0; r < height; ++r)
138 deMemcpy(dstRow, srcRow, static_cast<size_t>(pixelSize * width));
140 dstRow += pixelSize * width;
146 Image::Image (const vk::DeviceInterface& vk,
149 const vk::VkExtent3D& extend,
152 vk::Move<vk::VkImage> object_)
153 : m_allocation (DE_NULL)
157 , m_levelCount (levelCount)
158 , m_layerCount (layerCount)
164 tcu::ConstPixelBufferAccess Image::readSurface (vk::VkQueue queue,
165 vk::Allocator& allocator,
166 vk::VkImageLayout layout,
167 vk::VkOffset3D offset,
170 vk::VkImageAspectFlagBits aspect,
171 unsigned int mipLevel,
172 unsigned int arrayElement)
174 m_pixelAccessData.resize(width * height * vk::mapVkFormat(m_format).getPixelSize());
175 deMemset(m_pixelAccessData.data(), 0, m_pixelAccessData.size());
176 if (aspect == vk::VK_IMAGE_ASPECT_COLOR_BIT)
178 read(queue, allocator, layout, offset, width, height, 1, mipLevel, arrayElement, aspect, vk::VK_IMAGE_TYPE_2D,
179 m_pixelAccessData.data());
181 if (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT || aspect == vk::VK_IMAGE_ASPECT_STENCIL_BIT)
183 readUsingBuffer(queue, allocator, layout, offset, width, height, 1, mipLevel, arrayElement, aspect, m_pixelAccessData.data());
185 return tcu::ConstPixelBufferAccess(vk::mapVkFormat(m_format), width, height, 1, m_pixelAccessData.data());
188 tcu::ConstPixelBufferAccess Image::readVolume (vk::VkQueue queue,
189 vk::Allocator& allocator,
190 vk::VkImageLayout layout,
191 vk::VkOffset3D offset,
195 vk::VkImageAspectFlagBits aspect,
196 unsigned int mipLevel,
197 unsigned int arrayElement)
199 m_pixelAccessData.resize(width * height * depth * 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, height, depth, mipLevel, arrayElement, aspect, vk::VK_IMAGE_TYPE_3D,
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, height, depth, mipLevel, arrayElement, aspect, m_pixelAccessData.data());
210 return tcu::ConstPixelBufferAccess(vk::mapVkFormat(m_format), width, height, depth, m_pixelAccessData.data());
213 tcu::ConstPixelBufferAccess Image::readSurface1D(vk::VkQueue queue,
214 vk::Allocator& allocator,
215 vk::VkImageLayout layout,
216 vk::VkOffset3D offset,
218 vk::VkImageAspectFlagBits aspect,
219 unsigned int mipLevel,
220 unsigned int arrayElement)
222 m_pixelAccessData.resize(width * vk::mapVkFormat(m_format).getPixelSize());
223 deMemset(m_pixelAccessData.data(), 0, m_pixelAccessData.size());
224 if (aspect == vk::VK_IMAGE_ASPECT_COLOR_BIT)
226 read(queue, allocator, layout, offset, width, 1, 1, mipLevel, arrayElement, aspect, vk::VK_IMAGE_TYPE_1D,
227 m_pixelAccessData.data());
229 if (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT || aspect == vk::VK_IMAGE_ASPECT_STENCIL_BIT)
231 readUsingBuffer(queue, allocator, layout, offset, width, 1, 1, mipLevel, arrayElement, aspect,
232 m_pixelAccessData.data());
234 return tcu::ConstPixelBufferAccess(vk::mapVkFormat(m_format), width, 1, 1, m_pixelAccessData.data());
237 void Image::read (vk::VkQueue queue,
238 vk::Allocator& allocator,
239 vk::VkImageLayout layout,
240 vk::VkOffset3D offset,
244 unsigned int mipLevel,
245 unsigned int arrayElement,
246 vk::VkImageAspectFlagBits aspect,
247 vk::VkImageType type,
250 DE_ASSERT(layout == vk::VK_IMAGE_LAYOUT_GENERAL || layout == vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
252 de::SharedPtr<Image> stagingResource = copyToLinearImage(queue, allocator, layout, offset, width,
253 height, depth, mipLevel, arrayElement, aspect, type);
254 const vk::VkOffset3D zeroOffset = {0, 0, 0};
255 stagingResource->readLinear(zeroOffset, width, height, depth, 0, 0, aspect, data);
258 void Image::readUsingBuffer (vk::VkQueue queue,
259 vk::Allocator& allocator,
260 vk::VkImageLayout layout,
261 vk::VkOffset3D offset,
265 unsigned int mipLevel,
266 unsigned int arrayElement,
267 vk::VkImageAspectFlagBits aspect,
270 DE_ASSERT(layout == vk::VK_IMAGE_LAYOUT_GENERAL || layout == vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);;
272 de::SharedPtr<Buffer> stagingResource;
274 bool isCombinedType = isCombinedDepthStencilType(vk::mapVkFormat(m_format).type);
275 vk::VkDeviceSize bufferSize = 0;
278 bufferSize = vk::mapVkFormat(m_format).getPixelSize() * width * height * depth;
285 case vk::VK_FORMAT_D16_UNORM_S8_UINT:
286 pixelSize = (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT) ? 2 : 1;
288 case vk::VK_FORMAT_D32_SFLOAT_S8_UINT:
289 pixelSize = (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT) ? 4 : 1;
291 case vk::VK_FORMAT_X8_D24_UNORM_PACK32:
292 case vk::VK_FORMAT_D24_UNORM_S8_UINT:
293 pixelSize = (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT) ? 3 : 1;
297 DE_FATAL("Not implemented");
299 bufferSize = pixelSize*width*height*depth;
302 BufferCreateInfo stagingBufferResourceCreateInfo(bufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT | vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
303 stagingResource = Buffer::createAndAlloc(m_vk, m_device, stagingBufferResourceCreateInfo, allocator, vk::MemoryRequirement::HostVisible);
306 //todo [scygan] get proper queueFamilyIndex
307 CmdPoolCreateInfo copyCmdPoolCreateInfo(0);
308 vk::Unique<vk::VkCommandPool> copyCmdPool(vk::createCommandPool(m_vk, m_device, ©CmdPoolCreateInfo));
310 const vk::VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
312 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
313 DE_NULL, // const void* pNext;
314 *copyCmdPool, // VkCommandPool commandPool;
315 vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCommandBufferLevel level;
316 1u, // deUint32 bufferCount;
318 vk::Unique<vk::VkCommandBuffer> copyCmdBuffer(vk::allocateCommandBuffer(m_vk, m_device, &cmdBufferAllocateInfo));
320 CmdBufferBeginInfo beginInfo;
321 VK_CHECK(m_vk.beginCommandBuffer(*copyCmdBuffer, &beginInfo));
323 if (layout == vk::VK_IMAGE_LAYOUT_UNDEFINED)
325 layout = vk::VK_IMAGE_LAYOUT_GENERAL;
327 vk::VkImageMemoryBarrier barrier;
328 barrier.sType = vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
329 barrier.pNext = DE_NULL;
330 barrier.srcAccessMask = 0;
331 barrier.dstAccessMask = 0;
332 barrier.oldLayout = vk::VK_IMAGE_LAYOUT_UNDEFINED;
333 barrier.newLayout = vk::VK_IMAGE_LAYOUT_GENERAL;
334 barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
335 barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
336 barrier.image = object();
338 barrier.subresourceRange.aspectMask = aspect;
339 barrier.subresourceRange.baseMipLevel = 0;
340 barrier.subresourceRange.levelCount = m_levelCount;
341 barrier.subresourceRange.baseArrayLayer = 0;
342 barrier.subresourceRange.layerCount = m_layerCount;
344 m_vk.cmdPipelineBarrier(*copyCmdBuffer, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (vk::VkDependencyFlags)0,
345 0, (const vk::VkMemoryBarrier*)DE_NULL,
346 0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
350 vk::VkBufferImageCopy region =
353 { aspect, mipLevel, arrayElement, 1 },
355 { (deUint32)width, (deUint32)height, (deUint32)depth }
358 m_vk.cmdCopyImageToBuffer(*copyCmdBuffer, object(), layout, stagingResource->object(), 1, ®ion);
359 VK_CHECK(m_vk.endCommandBuffer(*copyCmdBuffer));
361 vk::VkSubmitInfo submitInfo =
363 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
364 DE_NULL, // const void* pNext;
365 0, // deUint32 waitSemaphoreCount;
366 DE_NULL, // const VkSemaphore* pWaitSemaphores;
367 (const vk::VkPipelineStageFlags*)DE_NULL,
368 1, // deUint32 commandBufferCount;
369 ©CmdBuffer.get(), // const VkCommandBuffer* pCommandBuffers;
370 0, // deUint32 signalSemaphoreCount;
371 DE_NULL // const VkSemaphore* pSignalSemaphores;
373 m_vk.queueSubmit(queue, 1, &submitInfo, DE_NULL);
375 // TODO: make this less intrusive
376 VK_CHECK(m_vk.queueWaitIdle(queue));
379 char* destPtr = reinterpret_cast<char*>(stagingResource->getBoundMemory().getHostPtr());
380 deMemcpy(data, destPtr, static_cast<size_t>(bufferSize));
383 tcu::ConstPixelBufferAccess Image::readSurfaceLinear (vk::VkOffset3D offset,
387 vk::VkImageAspectFlagBits aspect,
388 unsigned int mipLevel,
389 unsigned int arrayElement)
391 m_pixelAccessData.resize(width * height * vk::mapVkFormat(m_format).getPixelSize());
392 readLinear(offset, width, height, depth, mipLevel, arrayElement, aspect, m_pixelAccessData.data());
393 return tcu::ConstPixelBufferAccess(vk::mapVkFormat(m_format), width, height, 1, m_pixelAccessData.data());
396 void Image::readLinear (vk::VkOffset3D offset,
400 unsigned int mipLevel,
401 unsigned int arrayElement,
402 vk::VkImageAspectFlagBits aspect,
405 vk::VkImageSubresource imageSubResource = { aspect, mipLevel, arrayElement };
407 vk::VkSubresourceLayout imageLayout;
408 deMemset(&imageLayout, 0, sizeof(imageLayout));
410 m_vk.getImageSubresourceLayout(m_device, object(), &imageSubResource, &imageLayout);
412 const char* srcPtr = reinterpret_cast<const char*>(getBoundMemory().getHostPtr());
413 srcPtr += imageLayout.offset + getPixelOffset(offset, imageLayout.rowPitch, imageLayout.depthPitch, mipLevel, arrayElement);
415 MemoryOp::unpack(vk::mapVkFormat(m_format).getPixelSize(), width, height, depth,
416 imageLayout.rowPitch, imageLayout.depthPitch, srcPtr, data);
419 de::SharedPtr<Image> Image::copyToLinearImage (vk::VkQueue queue,
420 vk::Allocator& allocator,
421 vk::VkImageLayout layout,
422 vk::VkOffset3D offset,
426 unsigned int mipLevel,
427 unsigned int arrayElement,
428 vk::VkImageAspectFlagBits aspect,
429 vk::VkImageType type)
431 de::SharedPtr<Image> stagingResource;
433 vk::VkExtent3D stagingExtent = {(deUint32)width, (deUint32)height, (deUint32)depth};
434 ImageCreateInfo stagingResourceCreateInfo(type, m_format, stagingExtent, 1, 1, vk::VK_SAMPLE_COUNT_1_BIT,
435 vk::VK_IMAGE_TILING_LINEAR, vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT);
437 stagingResource = Image::createAndAlloc(m_vk, m_device, stagingResourceCreateInfo, allocator,
438 vk::MemoryRequirement::HostVisible);
440 //todo [scygan] get proper queueFamilyIndex
441 CmdPoolCreateInfo copyCmdPoolCreateInfo(0);
442 vk::Unique<vk::VkCommandPool> copyCmdPool(vk::createCommandPool(m_vk, m_device, ©CmdPoolCreateInfo));
444 const vk::VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
446 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
447 DE_NULL, // const void* pNext;
448 *copyCmdPool, // VkCommandPool commandPool;
449 vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCommandBufferLevel level;
450 1u, // deUint32 bufferCount;
452 vk::Unique<vk::VkCommandBuffer> copyCmdBuffer(vk::allocateCommandBuffer(m_vk, m_device, &cmdBufferAllocateInfo));
454 CmdBufferBeginInfo beginInfo;
455 VK_CHECK(m_vk.beginCommandBuffer(*copyCmdBuffer, &beginInfo));
457 transition2DImage(m_vk, *copyCmdBuffer, stagingResource->object(), aspect, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_GENERAL);
459 const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
460 vk::VkImageCopy region = { {aspect, mipLevel, arrayElement, 1}, offset, {aspect, 0, 0, 1}, zeroOffset, {(deUint32)width, (deUint32)height, (deUint32)depth} };
462 m_vk.cmdCopyImage(*copyCmdBuffer, object(), layout, stagingResource->object(), vk::VK_IMAGE_LAYOUT_GENERAL, 1, ®ion);
463 VK_CHECK(m_vk.endCommandBuffer(*copyCmdBuffer));
465 vk::VkSubmitInfo submitInfo =
467 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
468 DE_NULL, // const void* pNext;
469 0, // deUint32 waitSemaphoreCount;
470 DE_NULL, // const VkSemaphore* pWaitSemaphores;
471 (const vk::VkPipelineStageFlags*)DE_NULL,
472 1, // deUint32 commandBufferCount;
473 ©CmdBuffer.get(), // const VkCommandBuffer* pCommandBuffers;
474 0, // deUint32 signalSemaphoreCount;
475 DE_NULL // const VkSemaphore* pSignalSemaphores;
477 m_vk.queueSubmit(queue, 1, &submitInfo, DE_NULL);
479 // TODO: make this less intrusive
480 VK_CHECK(m_vk.queueWaitIdle(queue));
482 return stagingResource;
485 void Image::uploadVolume(const tcu::ConstPixelBufferAccess& access,
487 vk::Allocator& allocator,
488 vk::VkImageLayout layout,
489 vk::VkOffset3D offset,
490 vk::VkImageAspectFlagBits aspect,
491 unsigned int mipLevel,
492 unsigned int arrayElement)
494 if (aspect == vk::VK_IMAGE_ASPECT_COLOR_BIT)
496 upload(queue, allocator, layout, offset, access.getWidth(),
497 access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, vk::VK_IMAGE_TYPE_3D,
498 access.getDataPtr());
500 if (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT || aspect == vk::VK_IMAGE_ASPECT_STENCIL_BIT)
502 uploadUsingBuffer(queue, allocator, layout, offset, access.getWidth(),
503 access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, access.getDataPtr());
507 void Image::uploadSurface (const tcu::ConstPixelBufferAccess& access,
509 vk::Allocator& allocator,
510 vk::VkImageLayout layout,
511 vk::VkOffset3D offset,
512 vk::VkImageAspectFlagBits aspect,
513 unsigned int mipLevel,
514 unsigned int arrayElement)
516 if (aspect == vk::VK_IMAGE_ASPECT_COLOR_BIT)
518 upload(queue, allocator, layout, offset, access.getWidth(),
519 access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, vk::VK_IMAGE_TYPE_2D,
520 access.getDataPtr());
522 if (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT || aspect == vk::VK_IMAGE_ASPECT_STENCIL_BIT)
524 uploadUsingBuffer(queue, allocator, layout, offset, access.getWidth(),
525 access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, access.getDataPtr());
529 void Image::uploadSurface1D (const tcu::ConstPixelBufferAccess& access,
531 vk::Allocator& allocator,
532 vk::VkImageLayout layout,
533 vk::VkOffset3D offset,
534 vk::VkImageAspectFlagBits aspect,
535 unsigned int mipLevel,
536 unsigned int arrayElement)
538 if (aspect == vk::VK_IMAGE_ASPECT_COLOR_BIT)
540 upload(queue, allocator, layout, offset, access.getWidth(),
541 access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, vk::VK_IMAGE_TYPE_1D,
542 access.getDataPtr());
544 if (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT || aspect == vk::VK_IMAGE_ASPECT_STENCIL_BIT)
546 uploadUsingBuffer(queue, allocator, layout, offset, access.getWidth(),
547 access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, access.getDataPtr());
551 void Image::uploadSurfaceLinear (const tcu::ConstPixelBufferAccess& access,
552 vk::VkOffset3D offset,
556 vk::VkImageAspectFlagBits aspect,
557 unsigned int mipLevel,
558 unsigned int arrayElement)
560 uploadLinear(offset, width, height, depth, mipLevel, arrayElement, aspect, access.getDataPtr());
563 void Image::upload (vk::VkQueue queue,
564 vk::Allocator& allocator,
565 vk::VkImageLayout layout,
566 vk::VkOffset3D offset,
570 unsigned int mipLevel,
571 unsigned int arrayElement,
572 vk::VkImageAspectFlagBits aspect,
573 vk::VkImageType type,
576 DE_ASSERT(layout == vk::VK_IMAGE_LAYOUT_GENERAL || layout == vk::VK_IMAGE_LAYOUT_UNDEFINED || layout == vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
578 de::SharedPtr<Image> stagingResource;
579 vk::VkExtent3D extent = {(deUint32)width, (deUint32)height, (deUint32)depth};
580 ImageCreateInfo stagingResourceCreateInfo(
581 type, m_format, extent, 1, 1, vk::VK_SAMPLE_COUNT_1_BIT,
582 vk::VK_IMAGE_TILING_LINEAR, vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
584 stagingResource = Image::createAndAlloc(m_vk, m_device, stagingResourceCreateInfo, allocator,
585 vk::MemoryRequirement::HostVisible);
587 const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
588 stagingResource->uploadLinear(zeroOffset, width, height, depth, 0, 0, aspect, data);
591 //todo [scygan] get proper queueFamilyIndex
592 CmdPoolCreateInfo copyCmdPoolCreateInfo(0);
593 vk::Unique<vk::VkCommandPool> copyCmdPool(vk::createCommandPool(m_vk, m_device, ©CmdPoolCreateInfo));
595 const vk::VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
597 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
598 DE_NULL, // const void* pNext;
599 *copyCmdPool, // VkCommandPool commandPool;
600 vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCommandBufferLevel level;
601 1u, // deUint32 bufferCount;
604 vk::Unique<vk::VkCommandBuffer> copyCmdBuffer(vk::allocateCommandBuffer(m_vk, m_device, &cmdBufferAllocateInfo));
606 CmdBufferBeginInfo beginInfo;
607 VK_CHECK(m_vk.beginCommandBuffer(*copyCmdBuffer, &beginInfo));
609 if (layout == vk::VK_IMAGE_LAYOUT_UNDEFINED)
611 layout = vk::VK_IMAGE_LAYOUT_GENERAL;
613 vk::VkImageMemoryBarrier barrier;
614 barrier.sType = vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
615 barrier.pNext = DE_NULL;
616 barrier.srcAccessMask = 0;
617 barrier.dstAccessMask = 0;
618 barrier.oldLayout = vk::VK_IMAGE_LAYOUT_UNDEFINED;
619 barrier.newLayout = vk::VK_IMAGE_LAYOUT_GENERAL;
620 barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
621 barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
622 barrier.image = object();
624 barrier.subresourceRange.aspectMask = aspect;
625 barrier.subresourceRange.baseMipLevel = 0;
626 barrier.subresourceRange.levelCount = m_levelCount;
627 barrier.subresourceRange.baseArrayLayer = 0;
628 barrier.subresourceRange.layerCount = m_layerCount;
630 m_vk.cmdPipelineBarrier(*copyCmdBuffer, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (vk::VkDependencyFlags)0,
631 0, (const vk::VkMemoryBarrier*)DE_NULL,
632 0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
636 transition2DImage(m_vk, *copyCmdBuffer, stagingResource->object(), aspect, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_GENERAL);
638 vk::VkImageCopy region = {{aspect, 0, 0, 1},
640 {aspect, mipLevel, arrayElement, 1},
642 {(deUint32)width, (deUint32)height, (deUint32)depth}};
644 m_vk.cmdCopyImage(*copyCmdBuffer, stagingResource->object(),
645 vk::VK_IMAGE_LAYOUT_GENERAL, object(), layout, 1, ®ion);
646 VK_CHECK(m_vk.endCommandBuffer(*copyCmdBuffer));
648 vk::VkSubmitInfo submitInfo =
650 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
651 DE_NULL, // const void* pNext;
652 0, // deUint32 waitSemaphoreCount;
653 DE_NULL, // const VkSemaphore* pWaitSemaphores;
654 (const vk::VkPipelineStageFlags*)DE_NULL,
655 1, // deUint32 commandBufferCount;
656 ©CmdBuffer.get(), // const VkCommandBuffer* pCommandBuffers;
657 0, // deUint32 signalSemaphoreCount;
658 DE_NULL // const VkSemaphore* pSignalSemaphores;
660 m_vk.queueSubmit(queue, 1, &submitInfo, DE_NULL);
662 // TODO: make this less intrusive
663 VK_CHECK(m_vk.queueWaitIdle(queue));
667 void Image::uploadUsingBuffer (vk::VkQueue queue,
668 vk::Allocator& allocator,
669 vk::VkImageLayout layout,
670 vk::VkOffset3D offset,
674 unsigned int mipLevel,
675 unsigned int arrayElement,
676 vk::VkImageAspectFlagBits aspect,
679 DE_ASSERT(layout == vk::VK_IMAGE_LAYOUT_GENERAL || layout == vk::VK_IMAGE_LAYOUT_UNDEFINED || layout == vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
681 de::SharedPtr<Buffer> stagingResource;
682 bool isCombinedType = isCombinedDepthStencilType(vk::mapVkFormat(m_format).type);
683 vk::VkDeviceSize bufferSize = 0;
685 bufferSize = vk::mapVkFormat(m_format).getPixelSize() *width*height*depth;
691 case vk::VK_FORMAT_D16_UNORM_S8_UINT:
692 pixelSize = (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT) ? 2 : 1;
694 case vk::VK_FORMAT_D32_SFLOAT_S8_UINT:
695 pixelSize = (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT) ? 4 : 1;
697 case vk::VK_FORMAT_X8_D24_UNORM_PACK32:
698 case vk::VK_FORMAT_D24_UNORM_S8_UINT:
699 pixelSize = (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT) ? 3 : 1;
703 DE_FATAL("Not implemented");
705 bufferSize = pixelSize*width*height*depth;
707 BufferCreateInfo stagingBufferResourceCreateInfo(bufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT | vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
708 stagingResource = Buffer::createAndAlloc(m_vk, m_device, stagingBufferResourceCreateInfo, allocator, vk::MemoryRequirement::HostVisible);
709 char* destPtr = reinterpret_cast<char*>(stagingResource->getBoundMemory().getHostPtr());
710 deMemcpy(destPtr, data, static_cast<size_t>(bufferSize));
711 vk::flushMappedMemoryRange(m_vk, m_device, stagingResource->getBoundMemory().getMemory(), stagingResource->getBoundMemory().getOffset(), bufferSize);
713 //todo [scygan] get proper queueFamilyIndex
714 CmdPoolCreateInfo copyCmdPoolCreateInfo(0);
715 vk::Unique<vk::VkCommandPool> copyCmdPool(vk::createCommandPool(m_vk, m_device, ©CmdPoolCreateInfo));
717 const vk::VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
719 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
720 DE_NULL, // const void* pNext;
721 *copyCmdPool, // VkCommandPool commandPool;
722 vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCommandBufferLevel level;
723 1u, // deUint32 bufferCount;
725 vk::Unique<vk::VkCommandBuffer> copyCmdBuffer(vk::allocateCommandBuffer(m_vk, m_device, &cmdBufferAllocateInfo));
727 CmdBufferBeginInfo beginInfo;
728 VK_CHECK(m_vk.beginCommandBuffer(*copyCmdBuffer, &beginInfo));
730 if (layout == vk::VK_IMAGE_LAYOUT_UNDEFINED)
732 layout = vk::VK_IMAGE_LAYOUT_GENERAL;
734 vk::VkImageMemoryBarrier barrier;
735 barrier.sType = vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
736 barrier.pNext = DE_NULL;
737 barrier.srcAccessMask = 0;
738 barrier.dstAccessMask = 0;
739 barrier.oldLayout = vk::VK_IMAGE_LAYOUT_UNDEFINED;
740 barrier.newLayout = vk::VK_IMAGE_LAYOUT_GENERAL;
741 barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
742 barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
743 barrier.image = object();
745 barrier.subresourceRange.aspectMask = aspect;
746 barrier.subresourceRange.baseMipLevel = 0;
747 barrier.subresourceRange.levelCount = m_levelCount;
748 barrier.subresourceRange.baseArrayLayer = 0;
749 barrier.subresourceRange.layerCount = m_layerCount;
751 m_vk.cmdPipelineBarrier(*copyCmdBuffer, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (vk::VkDependencyFlags)0,
752 0, (const vk::VkMemoryBarrier*)DE_NULL,
753 0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
757 vk::VkBufferImageCopy region = {
759 { aspect, mipLevel, arrayElement, 1 },
761 { (deUint32)width, (deUint32)height, (deUint32)depth }
764 m_vk.cmdCopyBufferToImage(*copyCmdBuffer, stagingResource->object(),
765 object(), layout, 1, ®ion);
766 VK_CHECK(m_vk.endCommandBuffer(*copyCmdBuffer));
768 vk::VkSubmitInfo submitInfo =
770 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
771 DE_NULL, // const void* pNext;
772 0, // deUint32 waitSemaphoreCount;
773 DE_NULL, // const VkSemaphore* pWaitSemaphores;
774 (const vk::VkPipelineStageFlags*)DE_NULL,
775 1, // deUint32 commandBufferCount;
776 ©CmdBuffer.get(), // const VkCommandBuffer* pCommandBuffers;
777 0, // deUint32 signalSemaphoreCount;
778 DE_NULL // const VkSemaphore* pSignalSemaphores;
780 m_vk.queueSubmit(queue, 1, &submitInfo, DE_NULL);
782 // TODO: make this less intrusive
783 VK_CHECK(m_vk.queueWaitIdle(queue));
787 void Image::uploadLinear (vk::VkOffset3D offset,
791 unsigned int mipLevel,
792 unsigned int arrayElement,
793 vk::VkImageAspectFlagBits aspect,
796 vk::VkSubresourceLayout imageLayout;
798 vk::VkImageSubresource imageSubResource = {aspect, mipLevel, arrayElement};
800 m_vk.getImageSubresourceLayout(m_device, object(), &imageSubResource,
803 char* destPtr = reinterpret_cast<char*>(getBoundMemory().getHostPtr());
805 destPtr += imageLayout.offset + getPixelOffset(offset, imageLayout.rowPitch, imageLayout.depthPitch, mipLevel, arrayElement);
807 MemoryOp::pack(vk::mapVkFormat(m_format).getPixelSize(), width, height, depth,
808 imageLayout.rowPitch, imageLayout.depthPitch, data, destPtr);
811 vk::VkDeviceSize Image::getPixelOffset (vk::VkOffset3D offset,
812 vk::VkDeviceSize rowPitch,
813 vk::VkDeviceSize depthPitch,
817 DE_ASSERT(level < m_levelCount);
818 DE_ASSERT(layer < m_layerCount);
820 vk::VkDeviceSize mipLevelSizes[32];
821 vk::VkDeviceSize mipLevelRectSizes[32];
823 = tcu::IVec3(m_extent.width, m_extent.height, m_extent.depth);
825 vk::VkDeviceSize arrayElemSize = 0;
826 for (unsigned int i = 0; i < m_levelCount && (mipExtend[0] > 1 || mipExtend[1] > 1 || mipExtend[2] > 1); ++i)
828 // Rect size is just a 3D image size;
829 mipLevelSizes[i] = mipExtend[2] * depthPitch;
831 arrayElemSize += mipLevelSizes[0];
833 mipExtend = tcu::max(mipExtend / 2, tcu::IVec3(1));
836 vk::VkDeviceSize pixelOffset = layer * arrayElemSize;
837 for (size_t i = 0; i < level; ++i) {
838 pixelOffset += mipLevelSizes[i];
840 pixelOffset += offset.z * mipLevelRectSizes[level];
841 pixelOffset += offset.y * rowPitch;
842 pixelOffset += offset.x;
847 void Image::bindMemory (de::MovePtr<vk::Allocation> allocation)
849 DE_ASSERT(allocation);
850 VK_CHECK(m_vk.bindImageMemory(m_device, *m_object, allocation->getMemory(), allocation->getOffset()));
852 DE_ASSERT(!m_allocation);
853 m_allocation = allocation;
856 de::SharedPtr<Image> Image::createAndAlloc(const vk::DeviceInterface& vk,
858 const vk::VkImageCreateInfo& createInfo,
859 vk::Allocator& allocator,
860 vk::MemoryRequirement memoryRequirement)
862 de::SharedPtr<Image> ret = create(vk, device, createInfo);
864 vk::VkMemoryRequirements imageRequirements = vk::getImageMemoryRequirements(vk, device, ret->object());
865 ret->bindMemory(allocator.allocate(imageRequirements, memoryRequirement));
869 de::SharedPtr<Image> Image::create(const vk::DeviceInterface& vk,
871 const vk::VkImageCreateInfo &createInfo)
873 return de::SharedPtr<Image>(new Image(vk, device, createInfo.format, createInfo.extent,
874 createInfo.mipLevels, createInfo.arrayLayers,
875 vk::createImage(vk, device, &createInfo)));
878 void transition2DImage (const vk::DeviceInterface& vk,
879 vk::VkCommandBuffer cmdBuffer,
881 vk::VkImageAspectFlags aspectMask,
882 vk::VkImageLayout oldLayout,
883 vk::VkImageLayout newLayout,
884 vk::VkAccessFlags srcAccessMask,
885 vk::VkAccessFlags dstAccessMask)
887 vk::VkImageMemoryBarrier barrier;
888 barrier.sType = vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
889 barrier.pNext = DE_NULL;
890 barrier.srcAccessMask = srcAccessMask;
891 barrier.dstAccessMask = dstAccessMask;
892 barrier.oldLayout = oldLayout;
893 barrier.newLayout = newLayout;
894 barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
895 barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
896 barrier.image = image;
897 barrier.subresourceRange.aspectMask = aspectMask;
898 barrier.subresourceRange.baseMipLevel = 0;
899 barrier.subresourceRange.levelCount = 1;
900 barrier.subresourceRange.baseArrayLayer = 0;
901 barrier.subresourceRange.layerCount = 1;
903 vk.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (vk::VkDependencyFlags)0,
904 0, (const vk::VkMemoryBarrier*)DE_NULL,
905 0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
909 void initialTransitionColor2DImage (const vk::DeviceInterface &vk, vk::VkCommandBuffer cmdBuffer, vk::VkImage image, vk::VkImageLayout layout)
911 transition2DImage(vk, cmdBuffer, image, vk::VK_IMAGE_ASPECT_COLOR_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, layout);
914 void initialTransitionDepth2DImage (const vk::DeviceInterface &vk, vk::VkCommandBuffer cmdBuffer, vk::VkImage image, vk::VkImageLayout layout)
916 transition2DImage(vk, cmdBuffer, image, vk::VK_IMAGE_ASPECT_DEPTH_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, layout);
919 void initialTransitionStencil2DImage (const vk::DeviceInterface &vk, vk::VkCommandBuffer cmdBuffer, vk::VkImage image, vk::VkImageLayout layout)
921 transition2DImage(vk, cmdBuffer, image, vk::VK_IMAGE_ASPECT_STENCIL_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, layout);
924 void initialTransitionDepthStencil2DImage (const vk::DeviceInterface& vk,
925 vk::VkCommandBuffer cmdBuffer,
927 vk::VkImageLayout layout,
928 vk::VkAccessFlags srcAccessMask,
929 vk::VkAccessFlags dstAccessMask)
931 transition2DImage(vk, cmdBuffer, image, vk::VK_IMAGE_ASPECT_DEPTH_BIT | vk::VK_IMAGE_ASPECT_STENCIL_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, layout, srcAccessMask, dstAccessMask);