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 "vktDrawImageObjectUtil.hpp"
27 #include "tcuSurface.hpp"
28 #include "tcuVectorUtil.hpp"
30 #include "vkRefUtil.hpp"
31 #include "vkQueryUtil.hpp"
32 #include "vkImageUtil.hpp"
33 #include "vkCmdUtil.hpp"
34 #include "vktDrawCreateInfoUtil.hpp"
35 #include "vktDrawBufferObjectUtil.hpp"
37 #include "tcuTextureUtil.hpp"
44 void MemoryOp::pack (int pixelSize,
48 vk::VkDeviceSize rowPitchOrZero,
49 vk::VkDeviceSize depthPitchOrZero,
50 const void * srcBuffer,
53 vk::VkDeviceSize rowPitch = rowPitchOrZero;
54 vk::VkDeviceSize depthPitch = depthPitchOrZero;
57 rowPitch = width * pixelSize;
60 depthPitch = rowPitch * height;
62 const vk::VkDeviceSize size = depthPitch * depth;
64 const deUint8 *srcRow = reinterpret_cast<const deUint8 *>(srcBuffer);
65 const deUint8 *srcStart;
67 deUint8 *dstRow = reinterpret_cast<deUint8 *>(destBuffer);
71 if (rowPitch == static_cast<vk::VkDeviceSize>(width * pixelSize) &&
72 depthPitch == static_cast<vk::VkDeviceSize>(rowPitch * height))
75 deMemcpy(dstRow, srcRow, static_cast<size_t>(size));
79 // slower, per row path
80 for (int d = 0; d < depth; d++)
82 vk::VkDeviceSize offsetDepthDst = d * depthPitch;
83 vk::VkDeviceSize offsetDepthSrc = d * (pixelSize * width * height);
84 srcRow = srcStart + offsetDepthSrc;
85 dstRow = dstStart + offsetDepthDst;
86 for (int r = 0; r < height; ++r)
88 deMemcpy(dstRow, srcRow, static_cast<size_t>(rowPitch));
89 srcRow += pixelSize * width;
96 void MemoryOp::unpack (int pixelSize,
100 vk::VkDeviceSize rowPitchOrZero,
101 vk::VkDeviceSize depthPitchOrZero,
102 const void * srcBuffer,
105 vk::VkDeviceSize rowPitch = rowPitchOrZero;
106 vk::VkDeviceSize depthPitch = depthPitchOrZero;
109 rowPitch = width * pixelSize;
112 depthPitch = rowPitch * height;
114 const vk::VkDeviceSize size = depthPitch * depth;
116 const deUint8 *srcRow = reinterpret_cast<const deUint8 *>(srcBuffer);
117 const deUint8 *srcStart;
119 deUint8 *dstRow = reinterpret_cast<deUint8 *>(destBuffer);
123 if (rowPitch == static_cast<vk::VkDeviceSize>(width * pixelSize) &&
124 depthPitch == static_cast<vk::VkDeviceSize>(rowPitch * height))
127 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,
149 deUint32 queueFamilyIndex,
151 const vk::VkExtent3D& extend,
154 vk::Move<vk::VkImage> object_)
155 : m_allocation (DE_NULL)
157 , m_queueFamilyIndex(queueFamilyIndex)
160 , m_levelCount (levelCount)
161 , m_layerCount (layerCount)
167 tcu::ConstPixelBufferAccess Image::readSurface (vk::VkQueue queue,
168 vk::Allocator& allocator,
169 vk::VkImageLayout layout,
170 vk::VkOffset3D offset,
173 vk::VkImageAspectFlagBits aspect,
174 unsigned int mipLevel,
175 unsigned int arrayElement)
177 m_pixelAccessData.resize(width * height * vk::mapVkFormat(m_format).getPixelSize());
178 deMemset(m_pixelAccessData.data(), 0, m_pixelAccessData.size());
179 if (aspect == vk::VK_IMAGE_ASPECT_COLOR_BIT)
181 read(queue, allocator, layout, offset, width, height, 1, mipLevel, arrayElement, aspect, vk::VK_IMAGE_TYPE_2D,
182 m_pixelAccessData.data());
184 if (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT || aspect == vk::VK_IMAGE_ASPECT_STENCIL_BIT)
186 readUsingBuffer(queue, allocator, layout, offset, width, height, 1, mipLevel, arrayElement, aspect, m_pixelAccessData.data());
188 return tcu::ConstPixelBufferAccess(vk::mapVkFormat(m_format), width, height, 1, m_pixelAccessData.data());
191 tcu::ConstPixelBufferAccess Image::readDepth (vk::VkQueue queue,
192 vk::Allocator& allocator,
193 vk::VkImageLayout layout,
194 vk::VkOffset3D offset,
197 vk::VkImageAspectFlagBits aspect,
198 unsigned int mipLevel,
199 unsigned int arrayElement)
201 DE_ASSERT(aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT);
202 const tcu::TextureFormat tcuFormat = getDepthCopyFormat(m_format);
203 m_pixelAccessData.resize(width * height * tcuFormat.getPixelSize());
204 deMemset(m_pixelAccessData.data(), 0, m_pixelAccessData.size());
206 readUsingBuffer(queue, allocator, layout, offset, width, height, 1, mipLevel, arrayElement, aspect, m_pixelAccessData.data());
207 return tcu::ConstPixelBufferAccess(tcuFormat, width, height, 1, m_pixelAccessData.data());
210 tcu::ConstPixelBufferAccess Image::readVolume (vk::VkQueue queue,
211 vk::Allocator& allocator,
212 vk::VkImageLayout layout,
213 vk::VkOffset3D offset,
217 vk::VkImageAspectFlagBits aspect,
218 unsigned int mipLevel,
219 unsigned int arrayElement)
221 m_pixelAccessData.resize(width * height * depth * vk::mapVkFormat(m_format).getPixelSize());
222 deMemset(m_pixelAccessData.data(), 0, m_pixelAccessData.size());
223 if (aspect == vk::VK_IMAGE_ASPECT_COLOR_BIT)
225 read(queue, allocator, layout, offset, width, height, depth, mipLevel, arrayElement, aspect, vk::VK_IMAGE_TYPE_3D,
226 m_pixelAccessData.data());
228 if (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT || aspect == vk::VK_IMAGE_ASPECT_STENCIL_BIT)
230 readUsingBuffer(queue, allocator, layout, offset, width, height, depth, mipLevel, arrayElement, aspect, m_pixelAccessData.data());
232 return tcu::ConstPixelBufferAccess(vk::mapVkFormat(m_format), width, height, depth, m_pixelAccessData.data());
235 tcu::ConstPixelBufferAccess Image::readSurface1D(vk::VkQueue queue,
236 vk::Allocator& allocator,
237 vk::VkImageLayout layout,
238 vk::VkOffset3D offset,
240 vk::VkImageAspectFlagBits aspect,
241 unsigned int mipLevel,
242 unsigned int arrayElement)
244 m_pixelAccessData.resize(width * vk::mapVkFormat(m_format).getPixelSize());
245 deMemset(m_pixelAccessData.data(), 0, m_pixelAccessData.size());
246 if (aspect == vk::VK_IMAGE_ASPECT_COLOR_BIT)
248 read(queue, allocator, layout, offset, width, 1, 1, mipLevel, arrayElement, aspect, vk::VK_IMAGE_TYPE_1D,
249 m_pixelAccessData.data());
251 if (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT || aspect == vk::VK_IMAGE_ASPECT_STENCIL_BIT)
253 readUsingBuffer(queue, allocator, layout, offset, width, 1, 1, mipLevel, arrayElement, aspect,
254 m_pixelAccessData.data());
256 return tcu::ConstPixelBufferAccess(vk::mapVkFormat(m_format), width, 1, 1, m_pixelAccessData.data());
259 void Image::read (vk::VkQueue queue,
260 vk::Allocator& allocator,
261 vk::VkImageLayout layout,
262 vk::VkOffset3D offset,
266 unsigned int mipLevel,
267 unsigned int arrayElement,
268 vk::VkImageAspectFlagBits aspect,
269 vk::VkImageType type,
272 DE_ASSERT(layout == vk::VK_IMAGE_LAYOUT_GENERAL || layout == vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
274 de::SharedPtr<Image> stagingResource = copyToLinearImage(queue, allocator, layout, offset, width,
275 height, depth, mipLevel, arrayElement, aspect, type);
276 const vk::VkOffset3D zeroOffset = {0, 0, 0};
277 stagingResource->readLinear(zeroOffset, width, height, depth, 0, 0, aspect, data);
280 void Image::readUsingBuffer (vk::VkQueue queue,
281 vk::Allocator& allocator,
282 vk::VkImageLayout layout,
283 vk::VkOffset3D offset,
287 unsigned int mipLevel,
288 unsigned int arrayElement,
289 vk::VkImageAspectFlagBits aspect,
292 DE_ASSERT(layout == vk::VK_IMAGE_LAYOUT_GENERAL || layout == vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
294 de::SharedPtr<Buffer> stagingResource;
296 bool isCombinedType = isCombinedDepthStencilType(vk::mapVkFormat(m_format).type);
297 vk::VkDeviceSize bufferSize = 0;
300 bufferSize = vk::mapVkFormat(m_format).getPixelSize() * width * height * depth;
302 deUint32 pixelMask = 0xffffffff;
308 case vk::VK_FORMAT_D16_UNORM_S8_UINT:
309 pixelSize = (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT) ? 2 : 1;
311 case vk::VK_FORMAT_D32_SFLOAT_S8_UINT:
312 pixelSize = (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT) ? 4 : 1;
314 case vk::VK_FORMAT_X8_D24_UNORM_PACK32:
315 case vk::VK_FORMAT_D24_UNORM_S8_UINT:
316 // vkCmdCopyBufferToImage copies D24 data to 32-bit pixels.
317 pixelSize = (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT) ? 4 : 1;
318 pixelMask = 0x00ffffff;
322 DE_FATAL("Not implemented");
324 bufferSize = pixelSize*width*height*depth;
327 BufferCreateInfo stagingBufferResourceCreateInfo(bufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT | vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
328 stagingResource = Buffer::createAndAlloc(m_vk, m_device, stagingBufferResourceCreateInfo, allocator, vk::MemoryRequirement::HostVisible);
331 CmdPoolCreateInfo copyCmdPoolCreateInfo(m_queueFamilyIndex);
332 vk::Unique<vk::VkCommandPool> copyCmdPool(vk::createCommandPool(m_vk, m_device, ©CmdPoolCreateInfo));
333 vk::Unique<vk::VkCommandBuffer> copyCmdBuffer(vk::allocateCommandBuffer(m_vk, m_device, *copyCmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
335 beginCommandBuffer(m_vk, *copyCmdBuffer);
337 if (layout == vk::VK_IMAGE_LAYOUT_UNDEFINED)
339 layout = vk::VK_IMAGE_LAYOUT_GENERAL;
341 vk::VkImageMemoryBarrier barrier;
342 barrier.sType = vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
343 barrier.pNext = DE_NULL;
344 barrier.srcAccessMask = 0;
345 barrier.dstAccessMask = 0;
346 barrier.oldLayout = vk::VK_IMAGE_LAYOUT_UNDEFINED;
347 barrier.newLayout = vk::VK_IMAGE_LAYOUT_GENERAL;
348 barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
349 barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
350 barrier.image = object();
352 barrier.subresourceRange.aspectMask = aspect;
353 barrier.subresourceRange.baseMipLevel = 0;
354 barrier.subresourceRange.levelCount = m_levelCount;
355 barrier.subresourceRange.baseArrayLayer = 0;
356 barrier.subresourceRange.layerCount = m_layerCount;
358 m_vk.cmdPipelineBarrier(*copyCmdBuffer, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (vk::VkDependencyFlags)0,
359 0, (const vk::VkMemoryBarrier*)DE_NULL,
360 0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
364 vk::VkBufferImageCopy region =
367 { (vk::VkImageAspectFlags)aspect, mipLevel, arrayElement, 1 },
369 { (deUint32)width, (deUint32)height, (deUint32)depth }
372 m_vk.cmdCopyImageToBuffer(*copyCmdBuffer, object(), layout, stagingResource->object(), 1, ®ion);
374 // pipeline barrier for accessing the staging buffer from HOST
376 const vk::VkBufferMemoryBarrier memoryBarrier =
378 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
380 vk::VK_ACCESS_TRANSFER_WRITE_BIT,
381 vk::VK_ACCESS_HOST_READ_BIT,
382 VK_QUEUE_FAMILY_IGNORED,
383 VK_QUEUE_FAMILY_IGNORED,
384 stagingResource->object(),
388 m_vk.cmdPipelineBarrier(*copyCmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u, &memoryBarrier, 0u, DE_NULL);
391 endCommandBuffer(m_vk, *copyCmdBuffer);
393 submitCommandsAndWait(m_vk, m_device, queue, copyCmdBuffer.get());
396 // Validate the results
397 const vk::Allocation& bufAllocation = stagingResource->getBoundMemory();
398 invalidateMappedMemoryRange(m_vk, m_device, bufAllocation.getMemory(), bufAllocation.getOffset(), VK_WHOLE_SIZE);
400 deUint8* destPtr = reinterpret_cast<deUint8*>(stagingResource->getBoundMemory().getHostPtr());
401 deMemcpy(data, destPtr, static_cast<size_t>(bufferSize));
402 if (pixelMask != 0xffffffff) {
403 /* data copied to or from the depth aspect of a
404 VK_FORMAT_X8_D24_UNORM_PACK32 or VK_FORMAT_D24_UNORM_S8_UINT format
405 is packed with one 32-bit word per texel with the D24 value in the
406 LSBs of the word, and *undefined* values in the eight MSBs. */
407 deUint32* const data32 = static_cast<deUint32*>(data);
408 const vk::VkDeviceSize data32Count = bufferSize / sizeof(deUint32);
409 for(vk::VkDeviceSize i = 0; i < data32Count; ++i)
410 data32[i] &= pixelMask;
414 tcu::ConstPixelBufferAccess Image::readSurfaceLinear (vk::VkOffset3D offset,
418 vk::VkImageAspectFlagBits aspect,
419 unsigned int mipLevel,
420 unsigned int arrayElement)
422 m_pixelAccessData.resize(width * height * vk::mapVkFormat(m_format).getPixelSize());
423 readLinear(offset, width, height, depth, mipLevel, arrayElement, aspect, m_pixelAccessData.data());
424 return tcu::ConstPixelBufferAccess(vk::mapVkFormat(m_format), width, height, 1, m_pixelAccessData.data());
427 void Image::readLinear (vk::VkOffset3D offset,
431 unsigned int mipLevel,
432 unsigned int arrayElement,
433 vk::VkImageAspectFlagBits aspect,
436 DE_ASSERT(mipLevel < m_levelCount);
437 DE_ASSERT(arrayElement < m_layerCount);
439 vk::VkImageSubresource imageSubResource = { (vk::VkImageAspectFlags)aspect, mipLevel, arrayElement };
441 vk::VkSubresourceLayout imageLayout;
442 deMemset(&imageLayout, 0, sizeof(imageLayout));
444 m_vk.getImageSubresourceLayout(m_device, object(), &imageSubResource, &imageLayout);
446 const deUint8* srcPtr = reinterpret_cast<const deUint8*>(getBoundMemory().getHostPtr());
447 srcPtr += imageLayout.offset;
448 srcPtr += offset.z * imageLayout.depthPitch;
449 srcPtr += offset.y * imageLayout.rowPitch;
452 MemoryOp::unpack(vk::mapVkFormat(m_format).getPixelSize(), width, height, depth,
453 imageLayout.rowPitch, imageLayout.depthPitch, srcPtr, data);
456 de::SharedPtr<Image> Image::copyToLinearImage (vk::VkQueue queue,
457 vk::Allocator& allocator,
458 vk::VkImageLayout layout,
459 vk::VkOffset3D offset,
463 unsigned int mipLevel,
464 unsigned int arrayElement,
465 vk::VkImageAspectFlagBits aspect,
466 vk::VkImageType type)
468 de::SharedPtr<Image> stagingResource;
470 vk::VkExtent3D stagingExtent = {(deUint32)width, (deUint32)height, (deUint32)depth};
471 ImageCreateInfo stagingResourceCreateInfo(type, m_format, stagingExtent, 1, 1, vk::VK_SAMPLE_COUNT_1_BIT,
472 vk::VK_IMAGE_TILING_LINEAR, vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT);
474 stagingResource = Image::createAndAlloc(m_vk, m_device, stagingResourceCreateInfo, allocator, m_queueFamilyIndex,
475 vk::MemoryRequirement::HostVisible);
477 CmdPoolCreateInfo copyCmdPoolCreateInfo(m_queueFamilyIndex);
478 vk::Unique<vk::VkCommandPool> copyCmdPool(vk::createCommandPool(m_vk, m_device, ©CmdPoolCreateInfo));
479 vk::Unique<vk::VkCommandBuffer> copyCmdBuffer(vk::allocateCommandBuffer(m_vk, m_device, *copyCmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
481 beginCommandBuffer(m_vk, *copyCmdBuffer);
483 transition2DImage(m_vk, *copyCmdBuffer, stagingResource->object(), aspect, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_GENERAL,
484 0u, vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT);
486 const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
487 vk::VkImageCopy region = { { (vk::VkImageAspectFlags)aspect, mipLevel, arrayElement, 1}, offset, { (vk::VkImageAspectFlags)aspect, 0, 0, 1}, zeroOffset, {(deUint32)width, (deUint32)height, (deUint32)depth} };
489 m_vk.cmdCopyImage(*copyCmdBuffer, object(), layout, stagingResource->object(), vk::VK_IMAGE_LAYOUT_GENERAL, 1, ®ion);
491 // pipeline barrier for accessing the staging image from HOST
493 const vk::VkImageMemoryBarrier memoryBarrier =
495 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
497 vk::VK_ACCESS_TRANSFER_WRITE_BIT,
498 vk::VK_ACCESS_HOST_READ_BIT,
499 vk::VK_IMAGE_LAYOUT_GENERAL,
500 vk::VK_IMAGE_LAYOUT_GENERAL,
501 VK_QUEUE_FAMILY_IGNORED,
502 VK_QUEUE_FAMILY_IGNORED,
503 stagingResource->object(),
505 static_cast<vk::VkImageAspectFlags>(aspect),
512 m_vk.cmdPipelineBarrier(*copyCmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &memoryBarrier);
515 endCommandBuffer(m_vk, *copyCmdBuffer);
517 submitCommandsAndWait(m_vk, m_device, queue, copyCmdBuffer.get());
519 // Validate the results
520 const vk::Allocation& imgAllocation = stagingResource->getBoundMemory();
521 invalidateMappedMemoryRange(m_vk, m_device, imgAllocation.getMemory(), imgAllocation.getOffset(), VK_WHOLE_SIZE);
523 return stagingResource;
526 void Image::uploadVolume(const tcu::ConstPixelBufferAccess& access,
528 vk::Allocator& allocator,
529 vk::VkImageLayout layout,
530 vk::VkOffset3D offset,
531 vk::VkImageAspectFlagBits aspect,
532 unsigned int mipLevel,
533 unsigned int arrayElement)
535 if (aspect == vk::VK_IMAGE_ASPECT_COLOR_BIT)
537 upload(queue, allocator, layout, offset, access.getWidth(),
538 access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, vk::VK_IMAGE_TYPE_3D,
539 access.getDataPtr());
541 if (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT || aspect == vk::VK_IMAGE_ASPECT_STENCIL_BIT)
543 uploadUsingBuffer(queue, allocator, layout, offset, access.getWidth(),
544 access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, access.getDataPtr());
548 void Image::uploadSurface (const tcu::ConstPixelBufferAccess& access,
550 vk::Allocator& allocator,
551 vk::VkImageLayout layout,
552 vk::VkOffset3D offset,
553 vk::VkImageAspectFlagBits aspect,
554 unsigned int mipLevel,
555 unsigned int arrayElement)
557 if (aspect == vk::VK_IMAGE_ASPECT_COLOR_BIT)
559 upload(queue, allocator, layout, offset, access.getWidth(),
560 access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, vk::VK_IMAGE_TYPE_2D,
561 access.getDataPtr());
563 if (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT || aspect == vk::VK_IMAGE_ASPECT_STENCIL_BIT)
565 uploadUsingBuffer(queue, allocator, layout, offset, access.getWidth(),
566 access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, access.getDataPtr());
570 void Image::uploadSurface1D (const tcu::ConstPixelBufferAccess& access,
572 vk::Allocator& allocator,
573 vk::VkImageLayout layout,
574 vk::VkOffset3D offset,
575 vk::VkImageAspectFlagBits aspect,
576 unsigned int mipLevel,
577 unsigned int arrayElement)
579 if (aspect == vk::VK_IMAGE_ASPECT_COLOR_BIT)
581 upload(queue, allocator, layout, offset, access.getWidth(),
582 access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, vk::VK_IMAGE_TYPE_1D,
583 access.getDataPtr());
585 if (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT || aspect == vk::VK_IMAGE_ASPECT_STENCIL_BIT)
587 uploadUsingBuffer(queue, allocator, layout, offset, access.getWidth(),
588 access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, access.getDataPtr());
592 void Image::uploadSurfaceLinear (const tcu::ConstPixelBufferAccess& access,
593 vk::VkOffset3D offset,
597 vk::VkImageAspectFlagBits aspect,
598 unsigned int mipLevel,
599 unsigned int arrayElement)
601 uploadLinear(offset, width, height, depth, mipLevel, arrayElement, aspect, access.getDataPtr());
604 void Image::upload (vk::VkQueue queue,
605 vk::Allocator& allocator,
606 vk::VkImageLayout layout,
607 vk::VkOffset3D offset,
611 unsigned int mipLevel,
612 unsigned int arrayElement,
613 vk::VkImageAspectFlagBits aspect,
614 vk::VkImageType type,
617 DE_ASSERT(layout == vk::VK_IMAGE_LAYOUT_GENERAL || layout == vk::VK_IMAGE_LAYOUT_UNDEFINED || layout == vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
619 de::SharedPtr<Image> stagingResource;
620 vk::VkExtent3D extent = {(deUint32)width, (deUint32)height, (deUint32)depth};
621 ImageCreateInfo stagingResourceCreateInfo(
622 type, m_format, extent, 1, 1, vk::VK_SAMPLE_COUNT_1_BIT,
623 vk::VK_IMAGE_TILING_LINEAR, vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
625 stagingResource = Image::createAndAlloc(m_vk, m_device, stagingResourceCreateInfo, allocator, m_queueFamilyIndex,
626 vk::MemoryRequirement::HostVisible);
628 const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
629 stagingResource->uploadLinear(zeroOffset, width, height, depth, 0, 0, aspect, data);
632 CmdPoolCreateInfo copyCmdPoolCreateInfo(m_queueFamilyIndex);
633 vk::Unique<vk::VkCommandPool> copyCmdPool(vk::createCommandPool(m_vk, m_device, ©CmdPoolCreateInfo));
634 vk::Unique<vk::VkCommandBuffer> copyCmdBuffer(vk::allocateCommandBuffer(m_vk, m_device, *copyCmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
636 beginCommandBuffer(m_vk, *copyCmdBuffer);
638 if (layout == vk::VK_IMAGE_LAYOUT_UNDEFINED)
640 layout = vk::VK_IMAGE_LAYOUT_GENERAL;
642 vk::VkImageMemoryBarrier barrier;
643 barrier.sType = vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
644 barrier.pNext = DE_NULL;
645 barrier.srcAccessMask = 0;
646 barrier.dstAccessMask = 0;
647 barrier.oldLayout = vk::VK_IMAGE_LAYOUT_UNDEFINED;
648 barrier.newLayout = vk::VK_IMAGE_LAYOUT_GENERAL;
649 barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
650 barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
651 barrier.image = object();
653 barrier.subresourceRange.aspectMask = aspect;
654 barrier.subresourceRange.baseMipLevel = 0;
655 barrier.subresourceRange.levelCount = m_levelCount;
656 barrier.subresourceRange.baseArrayLayer = 0;
657 barrier.subresourceRange.layerCount = m_layerCount;
659 m_vk.cmdPipelineBarrier(*copyCmdBuffer, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (vk::VkDependencyFlags)0,
660 0, (const vk::VkMemoryBarrier*)DE_NULL,
661 0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
665 transition2DImage(m_vk, *copyCmdBuffer, stagingResource->object(), aspect, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_GENERAL,
666 0u, vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT);
668 vk::VkImageCopy region = {{ (vk::VkImageAspectFlags)aspect, 0, 0, 1},
670 { (vk::VkImageAspectFlags)aspect, mipLevel, arrayElement, 1},
672 {(deUint32)width, (deUint32)height, (deUint32)depth}};
674 m_vk.cmdCopyImage(*copyCmdBuffer, stagingResource->object(),
675 vk::VK_IMAGE_LAYOUT_GENERAL, object(), layout, 1, ®ion);
676 endCommandBuffer(m_vk, *copyCmdBuffer);
678 submitCommandsAndWait(m_vk, m_device, queue, copyCmdBuffer.get());
682 void Image::uploadUsingBuffer (vk::VkQueue queue,
683 vk::Allocator& allocator,
684 vk::VkImageLayout layout,
685 vk::VkOffset3D offset,
689 unsigned int mipLevel,
690 unsigned int arrayElement,
691 vk::VkImageAspectFlagBits aspect,
694 DE_ASSERT(layout == vk::VK_IMAGE_LAYOUT_GENERAL || layout == vk::VK_IMAGE_LAYOUT_UNDEFINED || layout == vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
696 de::SharedPtr<Buffer> stagingResource;
697 bool isCombinedType = isCombinedDepthStencilType(vk::mapVkFormat(m_format).type);
698 vk::VkDeviceSize bufferSize = 0;
700 bufferSize = vk::mapVkFormat(m_format).getPixelSize() *width*height*depth;
706 case vk::VK_FORMAT_D16_UNORM_S8_UINT:
707 pixelSize = (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT) ? 2 : 1;
709 case vk::VK_FORMAT_D32_SFLOAT_S8_UINT:
710 pixelSize = (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT) ? 4 : 1;
712 case vk::VK_FORMAT_X8_D24_UNORM_PACK32:
713 case vk::VK_FORMAT_D24_UNORM_S8_UINT:
714 pixelSize = (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT) ? 3 : 1;
718 DE_FATAL("Not implemented");
720 bufferSize = pixelSize*width*height*depth;
722 BufferCreateInfo stagingBufferResourceCreateInfo(bufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT | vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
723 stagingResource = Buffer::createAndAlloc(m_vk, m_device, stagingBufferResourceCreateInfo, allocator, vk::MemoryRequirement::HostVisible);
724 deUint8* destPtr = reinterpret_cast<deUint8*>(stagingResource->getBoundMemory().getHostPtr());
725 deMemcpy(destPtr, data, static_cast<size_t>(bufferSize));
726 vk::flushAlloc(m_vk, m_device, stagingResource->getBoundMemory());
728 CmdPoolCreateInfo copyCmdPoolCreateInfo(m_queueFamilyIndex);
729 vk::Unique<vk::VkCommandPool> copyCmdPool(vk::createCommandPool(m_vk, m_device, ©CmdPoolCreateInfo));
730 vk::Unique<vk::VkCommandBuffer> copyCmdBuffer(vk::allocateCommandBuffer(m_vk, m_device, *copyCmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
732 beginCommandBuffer(m_vk, *copyCmdBuffer);
734 if (layout == vk::VK_IMAGE_LAYOUT_UNDEFINED)
736 layout = vk::VK_IMAGE_LAYOUT_GENERAL;
738 vk::VkImageMemoryBarrier barrier;
739 barrier.sType = vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
740 barrier.pNext = DE_NULL;
741 barrier.srcAccessMask = 0;
742 barrier.dstAccessMask = 0;
743 barrier.oldLayout = vk::VK_IMAGE_LAYOUT_UNDEFINED;
744 barrier.newLayout = vk::VK_IMAGE_LAYOUT_GENERAL;
745 barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
746 barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
747 barrier.image = object();
749 barrier.subresourceRange.aspectMask = aspect;
750 barrier.subresourceRange.baseMipLevel = 0;
751 barrier.subresourceRange.levelCount = m_levelCount;
752 barrier.subresourceRange.baseArrayLayer = 0;
753 barrier.subresourceRange.layerCount = m_layerCount;
755 m_vk.cmdPipelineBarrier(*copyCmdBuffer, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (vk::VkDependencyFlags)0,
756 0, (const vk::VkMemoryBarrier*)DE_NULL,
757 0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
761 vk::VkBufferImageCopy region = {
763 { (vk::VkImageAspectFlags)aspect, mipLevel, arrayElement, 1 },
765 { (deUint32)width, (deUint32)height, (deUint32)depth }
768 m_vk.cmdCopyBufferToImage(*copyCmdBuffer, stagingResource->object(),
769 object(), layout, 1, ®ion);
770 endCommandBuffer(m_vk, *copyCmdBuffer);
772 submitCommandsAndWait(m_vk, m_device, queue, copyCmdBuffer.get());
776 void Image::uploadLinear (vk::VkOffset3D offset,
780 unsigned int mipLevel,
781 unsigned int arrayElement,
782 vk::VkImageAspectFlagBits aspect,
785 DE_ASSERT(mipLevel < m_levelCount);
786 DE_ASSERT(arrayElement < m_layerCount);
788 vk::VkSubresourceLayout imageLayout;
790 vk::VkImageSubresource imageSubResource = { (vk::VkImageAspectFlags)aspect, mipLevel, arrayElement};
792 m_vk.getImageSubresourceLayout(m_device, object(), &imageSubResource,
795 deUint8* destPtr = reinterpret_cast<deUint8*>(getBoundMemory().getHostPtr());
796 destPtr += imageLayout.offset;
797 destPtr += offset.z * imageLayout.depthPitch;
798 destPtr += offset.y * imageLayout.rowPitch;
801 MemoryOp::pack(vk::mapVkFormat(m_format).getPixelSize(), width, height, depth,
802 imageLayout.rowPitch, imageLayout.depthPitch, data, destPtr);
805 void Image::bindMemory (de::MovePtr<vk::Allocation> allocation)
807 DE_ASSERT(allocation);
808 VK_CHECK(m_vk.bindImageMemory(m_device, *m_object, allocation->getMemory(), allocation->getOffset()));
810 DE_ASSERT(!m_allocation);
811 m_allocation = allocation;
814 de::SharedPtr<Image> Image::createAndAlloc(const vk::DeviceInterface& vk,
816 const vk::VkImageCreateInfo& createInfo,
817 vk::Allocator& allocator,
818 deUint32 queueFamilyIndex,
819 vk::MemoryRequirement memoryRequirement)
821 de::SharedPtr<Image> ret = create(vk, device, createInfo, queueFamilyIndex);
823 vk::VkMemoryRequirements imageRequirements = vk::getImageMemoryRequirements(vk, device, ret->object());
824 ret->bindMemory(allocator.allocate(imageRequirements, memoryRequirement));
828 de::SharedPtr<Image> Image::create(const vk::DeviceInterface& vk,
830 const vk::VkImageCreateInfo &createInfo,
831 deUint32 queueFamilyIndex)
833 return de::SharedPtr<Image>(new Image(vk, device, queueFamilyIndex, createInfo.format, createInfo.extent,
834 createInfo.mipLevels, createInfo.arrayLayers, vk::createImage(vk, device, &createInfo)));
837 void transition2DImage (const vk::DeviceInterface& vk,
838 vk::VkCommandBuffer cmdBuffer,
840 vk::VkImageAspectFlags aspectMask,
841 vk::VkImageLayout oldLayout,
842 vk::VkImageLayout newLayout,
843 vk::VkAccessFlags srcAccessMask,
844 vk::VkAccessFlags dstAccessMask,
845 vk::VkPipelineStageFlags srcStageMask,
846 vk::VkPipelineStageFlags dstStageMask,
849 vk::VkImageMemoryBarrier barrier;
850 barrier.sType = vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
851 barrier.pNext = DE_NULL;
852 barrier.srcAccessMask = srcAccessMask;
853 barrier.dstAccessMask = dstAccessMask;
854 barrier.oldLayout = oldLayout;
855 barrier.newLayout = newLayout;
856 barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
857 barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
858 barrier.image = image;
859 barrier.subresourceRange.aspectMask = aspectMask;
860 barrier.subresourceRange.baseMipLevel = 0;
861 barrier.subresourceRange.levelCount = 1;
862 barrier.subresourceRange.baseArrayLayer = 0;
863 barrier.subresourceRange.layerCount = numLayers;
865 vk.cmdPipelineBarrier(cmdBuffer, srcStageMask, dstStageMask, (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier*)DE_NULL,
866 0, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1, &barrier);
869 void initialTransitionColor2DImage (const vk::DeviceInterface &vk, vk::VkCommandBuffer cmdBuffer, vk::VkImage image, vk::VkImageLayout layout,
870 vk::VkAccessFlags dstAccessMask, vk::VkPipelineStageFlags dstStageMask, deUint32 numLayers)
872 transition2DImage(vk, cmdBuffer, image, vk::VK_IMAGE_ASPECT_COLOR_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, layout, 0u, dstAccessMask, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, dstStageMask, numLayers);
875 void initialTransitionDepth2DImage (const vk::DeviceInterface &vk, vk::VkCommandBuffer cmdBuffer, vk::VkImage image, vk::VkImageLayout layout,
876 vk::VkAccessFlags dstAccessMask, vk::VkPipelineStageFlags dstStageMask)
878 transition2DImage(vk, cmdBuffer, image, vk::VK_IMAGE_ASPECT_DEPTH_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, layout, 0u, dstAccessMask, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, dstStageMask);
881 void initialTransitionStencil2DImage (const vk::DeviceInterface &vk, vk::VkCommandBuffer cmdBuffer, vk::VkImage image, vk::VkImageLayout layout,
882 vk::VkAccessFlags dstAccessMask, vk::VkPipelineStageFlags dstStageMask)
884 transition2DImage(vk, cmdBuffer, image, vk::VK_IMAGE_ASPECT_STENCIL_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, layout, 0u, dstAccessMask, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, dstStageMask);
887 void initialTransitionDepthStencil2DImage (const vk::DeviceInterface& vk,
888 vk::VkCommandBuffer cmdBuffer,
890 vk::VkImageLayout layout,
891 vk::VkAccessFlags dstAccessMask,
892 vk::VkPipelineStageFlags dstStageMask)
894 transition2DImage(vk, cmdBuffer, image, vk::VK_IMAGE_ASPECT_DEPTH_BIT | vk::VK_IMAGE_ASPECT_STENCIL_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, layout, 0u, dstAccessMask, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, dstStageMask);