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 "vktDrawCreateInfoUtil.hpp"
34 #include "vktDrawBufferObjectUtil.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 deUint8 *srcRow = reinterpret_cast<const deUint8 *>(srcBuffer);
64 const deUint8 *srcStart;
66 deUint8 *dstRow = reinterpret_cast<deUint8 *>(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 deUint8 *srcRow = reinterpret_cast<const deUint8 *>(srcBuffer);
116 const deUint8 *srcStart;
118 deUint8 *dstRow = reinterpret_cast<deUint8 *>(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));
309 vk::Unique<vk::VkCommandBuffer> copyCmdBuffer(vk::allocateCommandBuffer(m_vk, m_device, *copyCmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
311 CmdBufferBeginInfo beginInfo;
312 VK_CHECK(m_vk.beginCommandBuffer(*copyCmdBuffer, &beginInfo));
314 if (layout == vk::VK_IMAGE_LAYOUT_UNDEFINED)
316 layout = vk::VK_IMAGE_LAYOUT_GENERAL;
318 vk::VkImageMemoryBarrier barrier;
319 barrier.sType = vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
320 barrier.pNext = DE_NULL;
321 barrier.srcAccessMask = 0;
322 barrier.dstAccessMask = 0;
323 barrier.oldLayout = vk::VK_IMAGE_LAYOUT_UNDEFINED;
324 barrier.newLayout = vk::VK_IMAGE_LAYOUT_GENERAL;
325 barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
326 barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
327 barrier.image = object();
329 barrier.subresourceRange.aspectMask = aspect;
330 barrier.subresourceRange.baseMipLevel = 0;
331 barrier.subresourceRange.levelCount = m_levelCount;
332 barrier.subresourceRange.baseArrayLayer = 0;
333 barrier.subresourceRange.layerCount = m_layerCount;
335 m_vk.cmdPipelineBarrier(*copyCmdBuffer, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (vk::VkDependencyFlags)0,
336 0, (const vk::VkMemoryBarrier*)DE_NULL,
337 0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
341 vk::VkBufferImageCopy region =
344 { (vk::VkImageAspectFlags)aspect, mipLevel, arrayElement, 1 },
346 { (deUint32)width, (deUint32)height, (deUint32)depth }
349 m_vk.cmdCopyImageToBuffer(*copyCmdBuffer, object(), layout, stagingResource->object(), 1, ®ion);
350 VK_CHECK(m_vk.endCommandBuffer(*copyCmdBuffer));
352 vk::VkSubmitInfo submitInfo =
354 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
355 DE_NULL, // const void* pNext;
356 0, // deUint32 waitSemaphoreCount;
357 DE_NULL, // const VkSemaphore* pWaitSemaphores;
358 (const vk::VkPipelineStageFlags*)DE_NULL,
359 1, // deUint32 commandBufferCount;
360 ©CmdBuffer.get(), // const VkCommandBuffer* pCommandBuffers;
361 0, // deUint32 signalSemaphoreCount;
362 DE_NULL // const VkSemaphore* pSignalSemaphores;
364 m_vk.queueSubmit(queue, 1, &submitInfo, DE_NULL);
366 // TODO: make this less intrusive
367 VK_CHECK(m_vk.queueWaitIdle(queue));
370 deUint8* destPtr = reinterpret_cast<deUint8*>(stagingResource->getBoundMemory().getHostPtr());
371 deMemcpy(data, destPtr, static_cast<size_t>(bufferSize));
374 tcu::ConstPixelBufferAccess Image::readSurfaceLinear (vk::VkOffset3D offset,
378 vk::VkImageAspectFlagBits aspect,
379 unsigned int mipLevel,
380 unsigned int arrayElement)
382 m_pixelAccessData.resize(width * height * vk::mapVkFormat(m_format).getPixelSize());
383 readLinear(offset, width, height, depth, mipLevel, arrayElement, aspect, m_pixelAccessData.data());
384 return tcu::ConstPixelBufferAccess(vk::mapVkFormat(m_format), width, height, 1, m_pixelAccessData.data());
387 void Image::readLinear (vk::VkOffset3D offset,
391 unsigned int mipLevel,
392 unsigned int arrayElement,
393 vk::VkImageAspectFlagBits aspect,
396 DE_ASSERT(mipLevel < m_levelCount);
397 DE_ASSERT(arrayElement < m_layerCount);
399 vk::VkImageSubresource imageSubResource = { (vk::VkImageAspectFlags)aspect, mipLevel, arrayElement };
401 vk::VkSubresourceLayout imageLayout;
402 deMemset(&imageLayout, 0, sizeof(imageLayout));
404 m_vk.getImageSubresourceLayout(m_device, object(), &imageSubResource, &imageLayout);
406 const deUint8* srcPtr = reinterpret_cast<const deUint8*>(getBoundMemory().getHostPtr());
407 srcPtr += imageLayout.offset;
408 srcPtr += offset.z * imageLayout.depthPitch;
409 srcPtr += offset.y * imageLayout.rowPitch;
412 MemoryOp::unpack(vk::mapVkFormat(m_format).getPixelSize(), width, height, depth,
413 imageLayout.rowPitch, imageLayout.depthPitch, srcPtr, data);
416 de::SharedPtr<Image> Image::copyToLinearImage (vk::VkQueue queue,
417 vk::Allocator& allocator,
418 vk::VkImageLayout layout,
419 vk::VkOffset3D offset,
423 unsigned int mipLevel,
424 unsigned int arrayElement,
425 vk::VkImageAspectFlagBits aspect,
426 vk::VkImageType type)
428 de::SharedPtr<Image> stagingResource;
430 vk::VkExtent3D stagingExtent = {(deUint32)width, (deUint32)height, (deUint32)depth};
431 ImageCreateInfo stagingResourceCreateInfo(type, m_format, stagingExtent, 1, 1, vk::VK_SAMPLE_COUNT_1_BIT,
432 vk::VK_IMAGE_TILING_LINEAR, vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT);
434 stagingResource = Image::createAndAlloc(m_vk, m_device, stagingResourceCreateInfo, allocator,
435 vk::MemoryRequirement::HostVisible);
437 //todo [scygan] get proper queueFamilyIndex
438 CmdPoolCreateInfo copyCmdPoolCreateInfo(0);
439 vk::Unique<vk::VkCommandPool> copyCmdPool(vk::createCommandPool(m_vk, m_device, ©CmdPoolCreateInfo));
440 vk::Unique<vk::VkCommandBuffer> copyCmdBuffer(vk::allocateCommandBuffer(m_vk, m_device, *copyCmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
442 CmdBufferBeginInfo beginInfo;
443 VK_CHECK(m_vk.beginCommandBuffer(*copyCmdBuffer, &beginInfo));
445 transition2DImage(m_vk, *copyCmdBuffer, stagingResource->object(), aspect, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_GENERAL);
447 const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
448 vk::VkImageCopy region = { { (vk::VkImageAspectFlags)aspect, mipLevel, arrayElement, 1}, offset, { (vk::VkImageAspectFlags)aspect, 0, 0, 1}, zeroOffset, {(deUint32)width, (deUint32)height, (deUint32)depth} };
450 m_vk.cmdCopyImage(*copyCmdBuffer, object(), layout, stagingResource->object(), vk::VK_IMAGE_LAYOUT_GENERAL, 1, ®ion);
451 VK_CHECK(m_vk.endCommandBuffer(*copyCmdBuffer));
453 vk::VkSubmitInfo submitInfo =
455 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
456 DE_NULL, // const void* pNext;
457 0, // deUint32 waitSemaphoreCount;
458 DE_NULL, // const VkSemaphore* pWaitSemaphores;
459 (const vk::VkPipelineStageFlags*)DE_NULL,
460 1, // deUint32 commandBufferCount;
461 ©CmdBuffer.get(), // const VkCommandBuffer* pCommandBuffers;
462 0, // deUint32 signalSemaphoreCount;
463 DE_NULL // const VkSemaphore* pSignalSemaphores;
465 m_vk.queueSubmit(queue, 1, &submitInfo, DE_NULL);
467 // TODO: make this less intrusive
468 VK_CHECK(m_vk.queueWaitIdle(queue));
470 return stagingResource;
473 void Image::uploadVolume(const tcu::ConstPixelBufferAccess& access,
475 vk::Allocator& allocator,
476 vk::VkImageLayout layout,
477 vk::VkOffset3D offset,
478 vk::VkImageAspectFlagBits aspect,
479 unsigned int mipLevel,
480 unsigned int arrayElement)
482 if (aspect == vk::VK_IMAGE_ASPECT_COLOR_BIT)
484 upload(queue, allocator, layout, offset, access.getWidth(),
485 access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, vk::VK_IMAGE_TYPE_3D,
486 access.getDataPtr());
488 if (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT || aspect == vk::VK_IMAGE_ASPECT_STENCIL_BIT)
490 uploadUsingBuffer(queue, allocator, layout, offset, access.getWidth(),
491 access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, access.getDataPtr());
495 void Image::uploadSurface (const tcu::ConstPixelBufferAccess& access,
497 vk::Allocator& allocator,
498 vk::VkImageLayout layout,
499 vk::VkOffset3D offset,
500 vk::VkImageAspectFlagBits aspect,
501 unsigned int mipLevel,
502 unsigned int arrayElement)
504 if (aspect == vk::VK_IMAGE_ASPECT_COLOR_BIT)
506 upload(queue, allocator, layout, offset, access.getWidth(),
507 access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, vk::VK_IMAGE_TYPE_2D,
508 access.getDataPtr());
510 if (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT || aspect == vk::VK_IMAGE_ASPECT_STENCIL_BIT)
512 uploadUsingBuffer(queue, allocator, layout, offset, access.getWidth(),
513 access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, access.getDataPtr());
517 void Image::uploadSurface1D (const tcu::ConstPixelBufferAccess& access,
519 vk::Allocator& allocator,
520 vk::VkImageLayout layout,
521 vk::VkOffset3D offset,
522 vk::VkImageAspectFlagBits aspect,
523 unsigned int mipLevel,
524 unsigned int arrayElement)
526 if (aspect == vk::VK_IMAGE_ASPECT_COLOR_BIT)
528 upload(queue, allocator, layout, offset, access.getWidth(),
529 access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, vk::VK_IMAGE_TYPE_1D,
530 access.getDataPtr());
532 if (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT || aspect == vk::VK_IMAGE_ASPECT_STENCIL_BIT)
534 uploadUsingBuffer(queue, allocator, layout, offset, access.getWidth(),
535 access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, access.getDataPtr());
539 void Image::uploadSurfaceLinear (const tcu::ConstPixelBufferAccess& access,
540 vk::VkOffset3D offset,
544 vk::VkImageAspectFlagBits aspect,
545 unsigned int mipLevel,
546 unsigned int arrayElement)
548 uploadLinear(offset, width, height, depth, mipLevel, arrayElement, aspect, access.getDataPtr());
551 void Image::upload (vk::VkQueue queue,
552 vk::Allocator& allocator,
553 vk::VkImageLayout layout,
554 vk::VkOffset3D offset,
558 unsigned int mipLevel,
559 unsigned int arrayElement,
560 vk::VkImageAspectFlagBits aspect,
561 vk::VkImageType type,
564 DE_ASSERT(layout == vk::VK_IMAGE_LAYOUT_GENERAL || layout == vk::VK_IMAGE_LAYOUT_UNDEFINED || layout == vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
566 de::SharedPtr<Image> stagingResource;
567 vk::VkExtent3D extent = {(deUint32)width, (deUint32)height, (deUint32)depth};
568 ImageCreateInfo stagingResourceCreateInfo(
569 type, m_format, extent, 1, 1, vk::VK_SAMPLE_COUNT_1_BIT,
570 vk::VK_IMAGE_TILING_LINEAR, vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
572 stagingResource = Image::createAndAlloc(m_vk, m_device, stagingResourceCreateInfo, allocator,
573 vk::MemoryRequirement::HostVisible);
575 const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
576 stagingResource->uploadLinear(zeroOffset, width, height, depth, 0, 0, aspect, data);
579 //todo [scygan] get proper queueFamilyIndex
580 CmdPoolCreateInfo copyCmdPoolCreateInfo(0);
581 vk::Unique<vk::VkCommandPool> copyCmdPool(vk::createCommandPool(m_vk, m_device, ©CmdPoolCreateInfo));
582 vk::Unique<vk::VkCommandBuffer> copyCmdBuffer(vk::allocateCommandBuffer(m_vk, m_device, *copyCmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
584 CmdBufferBeginInfo beginInfo;
585 VK_CHECK(m_vk.beginCommandBuffer(*copyCmdBuffer, &beginInfo));
587 if (layout == vk::VK_IMAGE_LAYOUT_UNDEFINED)
589 layout = vk::VK_IMAGE_LAYOUT_GENERAL;
591 vk::VkImageMemoryBarrier barrier;
592 barrier.sType = vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
593 barrier.pNext = DE_NULL;
594 barrier.srcAccessMask = 0;
595 barrier.dstAccessMask = 0;
596 barrier.oldLayout = vk::VK_IMAGE_LAYOUT_UNDEFINED;
597 barrier.newLayout = vk::VK_IMAGE_LAYOUT_GENERAL;
598 barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
599 barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
600 barrier.image = object();
602 barrier.subresourceRange.aspectMask = aspect;
603 barrier.subresourceRange.baseMipLevel = 0;
604 barrier.subresourceRange.levelCount = m_levelCount;
605 barrier.subresourceRange.baseArrayLayer = 0;
606 barrier.subresourceRange.layerCount = m_layerCount;
608 m_vk.cmdPipelineBarrier(*copyCmdBuffer, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (vk::VkDependencyFlags)0,
609 0, (const vk::VkMemoryBarrier*)DE_NULL,
610 0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
614 transition2DImage(m_vk, *copyCmdBuffer, stagingResource->object(), aspect, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_GENERAL);
616 vk::VkImageCopy region = {{ (vk::VkImageAspectFlags)aspect, 0, 0, 1},
618 { (vk::VkImageAspectFlags)aspect, mipLevel, arrayElement, 1},
620 {(deUint32)width, (deUint32)height, (deUint32)depth}};
622 m_vk.cmdCopyImage(*copyCmdBuffer, stagingResource->object(),
623 vk::VK_IMAGE_LAYOUT_GENERAL, object(), layout, 1, ®ion);
624 VK_CHECK(m_vk.endCommandBuffer(*copyCmdBuffer));
626 vk::VkSubmitInfo submitInfo =
628 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
629 DE_NULL, // const void* pNext;
630 0, // deUint32 waitSemaphoreCount;
631 DE_NULL, // const VkSemaphore* pWaitSemaphores;
632 (const vk::VkPipelineStageFlags*)DE_NULL,
633 1, // deUint32 commandBufferCount;
634 ©CmdBuffer.get(), // const VkCommandBuffer* pCommandBuffers;
635 0, // deUint32 signalSemaphoreCount;
636 DE_NULL // const VkSemaphore* pSignalSemaphores;
638 m_vk.queueSubmit(queue, 1, &submitInfo, DE_NULL);
640 // TODO: make this less intrusive
641 VK_CHECK(m_vk.queueWaitIdle(queue));
645 void Image::uploadUsingBuffer (vk::VkQueue queue,
646 vk::Allocator& allocator,
647 vk::VkImageLayout layout,
648 vk::VkOffset3D offset,
652 unsigned int mipLevel,
653 unsigned int arrayElement,
654 vk::VkImageAspectFlagBits aspect,
657 DE_ASSERT(layout == vk::VK_IMAGE_LAYOUT_GENERAL || layout == vk::VK_IMAGE_LAYOUT_UNDEFINED || layout == vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
659 de::SharedPtr<Buffer> stagingResource;
660 bool isCombinedType = isCombinedDepthStencilType(vk::mapVkFormat(m_format).type);
661 vk::VkDeviceSize bufferSize = 0;
663 bufferSize = vk::mapVkFormat(m_format).getPixelSize() *width*height*depth;
669 case vk::VK_FORMAT_D16_UNORM_S8_UINT:
670 pixelSize = (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT) ? 2 : 1;
672 case vk::VK_FORMAT_D32_SFLOAT_S8_UINT:
673 pixelSize = (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT) ? 4 : 1;
675 case vk::VK_FORMAT_X8_D24_UNORM_PACK32:
676 case vk::VK_FORMAT_D24_UNORM_S8_UINT:
677 pixelSize = (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT) ? 3 : 1;
681 DE_FATAL("Not implemented");
683 bufferSize = pixelSize*width*height*depth;
685 BufferCreateInfo stagingBufferResourceCreateInfo(bufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT | vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
686 stagingResource = Buffer::createAndAlloc(m_vk, m_device, stagingBufferResourceCreateInfo, allocator, vk::MemoryRequirement::HostVisible);
687 deUint8* destPtr = reinterpret_cast<deUint8*>(stagingResource->getBoundMemory().getHostPtr());
688 deMemcpy(destPtr, data, static_cast<size_t>(bufferSize));
689 vk::flushMappedMemoryRange(m_vk, m_device, stagingResource->getBoundMemory().getMemory(), stagingResource->getBoundMemory().getOffset(), bufferSize);
691 //todo [scygan] get proper queueFamilyIndex
692 CmdPoolCreateInfo copyCmdPoolCreateInfo(0);
693 vk::Unique<vk::VkCommandPool> copyCmdPool(vk::createCommandPool(m_vk, m_device, ©CmdPoolCreateInfo));
694 vk::Unique<vk::VkCommandBuffer> copyCmdBuffer(vk::allocateCommandBuffer(m_vk, m_device, *copyCmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
696 CmdBufferBeginInfo beginInfo;
697 VK_CHECK(m_vk.beginCommandBuffer(*copyCmdBuffer, &beginInfo));
699 if (layout == vk::VK_IMAGE_LAYOUT_UNDEFINED)
701 layout = vk::VK_IMAGE_LAYOUT_GENERAL;
703 vk::VkImageMemoryBarrier barrier;
704 barrier.sType = vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
705 barrier.pNext = DE_NULL;
706 barrier.srcAccessMask = 0;
707 barrier.dstAccessMask = 0;
708 barrier.oldLayout = vk::VK_IMAGE_LAYOUT_UNDEFINED;
709 barrier.newLayout = vk::VK_IMAGE_LAYOUT_GENERAL;
710 barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
711 barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
712 barrier.image = object();
714 barrier.subresourceRange.aspectMask = aspect;
715 barrier.subresourceRange.baseMipLevel = 0;
716 barrier.subresourceRange.levelCount = m_levelCount;
717 barrier.subresourceRange.baseArrayLayer = 0;
718 barrier.subresourceRange.layerCount = m_layerCount;
720 m_vk.cmdPipelineBarrier(*copyCmdBuffer, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (vk::VkDependencyFlags)0,
721 0, (const vk::VkMemoryBarrier*)DE_NULL,
722 0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
726 vk::VkBufferImageCopy region = {
728 { (vk::VkImageAspectFlags)aspect, mipLevel, arrayElement, 1 },
730 { (deUint32)width, (deUint32)height, (deUint32)depth }
733 m_vk.cmdCopyBufferToImage(*copyCmdBuffer, stagingResource->object(),
734 object(), layout, 1, ®ion);
735 VK_CHECK(m_vk.endCommandBuffer(*copyCmdBuffer));
737 vk::VkSubmitInfo submitInfo =
739 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
740 DE_NULL, // const void* pNext;
741 0, // deUint32 waitSemaphoreCount;
742 DE_NULL, // const VkSemaphore* pWaitSemaphores;
743 (const vk::VkPipelineStageFlags*)DE_NULL,
744 1, // deUint32 commandBufferCount;
745 ©CmdBuffer.get(), // const VkCommandBuffer* pCommandBuffers;
746 0, // deUint32 signalSemaphoreCount;
747 DE_NULL // const VkSemaphore* pSignalSemaphores;
749 m_vk.queueSubmit(queue, 1, &submitInfo, DE_NULL);
751 // TODO: make this less intrusive
752 VK_CHECK(m_vk.queueWaitIdle(queue));
756 void Image::uploadLinear (vk::VkOffset3D offset,
760 unsigned int mipLevel,
761 unsigned int arrayElement,
762 vk::VkImageAspectFlagBits aspect,
765 DE_ASSERT(mipLevel < m_levelCount);
766 DE_ASSERT(arrayElement < m_layerCount);
768 vk::VkSubresourceLayout imageLayout;
770 vk::VkImageSubresource imageSubResource = { (vk::VkImageAspectFlags)aspect, mipLevel, arrayElement};
772 m_vk.getImageSubresourceLayout(m_device, object(), &imageSubResource,
775 deUint8* destPtr = reinterpret_cast<deUint8*>(getBoundMemory().getHostPtr());
776 destPtr += imageLayout.offset;
777 destPtr += offset.z * imageLayout.depthPitch;
778 destPtr += offset.y * imageLayout.rowPitch;
781 MemoryOp::pack(vk::mapVkFormat(m_format).getPixelSize(), width, height, depth,
782 imageLayout.rowPitch, imageLayout.depthPitch, data, destPtr);
785 void Image::bindMemory (de::MovePtr<vk::Allocation> allocation)
787 DE_ASSERT(allocation);
788 VK_CHECK(m_vk.bindImageMemory(m_device, *m_object, allocation->getMemory(), allocation->getOffset()));
790 DE_ASSERT(!m_allocation);
791 m_allocation = allocation;
794 de::SharedPtr<Image> Image::createAndAlloc(const vk::DeviceInterface& vk,
796 const vk::VkImageCreateInfo& createInfo,
797 vk::Allocator& allocator,
798 vk::MemoryRequirement memoryRequirement)
800 de::SharedPtr<Image> ret = create(vk, device, createInfo);
802 vk::VkMemoryRequirements imageRequirements = vk::getImageMemoryRequirements(vk, device, ret->object());
803 ret->bindMemory(allocator.allocate(imageRequirements, memoryRequirement));
807 de::SharedPtr<Image> Image::create(const vk::DeviceInterface& vk,
809 const vk::VkImageCreateInfo &createInfo)
811 return de::SharedPtr<Image>(new Image(vk, device, createInfo.format, createInfo.extent,
812 createInfo.mipLevels, createInfo.arrayLayers,
813 vk::createImage(vk, device, &createInfo)));
816 void transition2DImage (const vk::DeviceInterface& vk,
817 vk::VkCommandBuffer cmdBuffer,
819 vk::VkImageAspectFlags aspectMask,
820 vk::VkImageLayout oldLayout,
821 vk::VkImageLayout newLayout,
822 vk::VkAccessFlags srcAccessMask,
823 vk::VkAccessFlags dstAccessMask)
825 vk::VkImageMemoryBarrier barrier;
826 barrier.sType = vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
827 barrier.pNext = DE_NULL;
828 barrier.srcAccessMask = srcAccessMask;
829 barrier.dstAccessMask = dstAccessMask;
830 barrier.oldLayout = oldLayout;
831 barrier.newLayout = newLayout;
832 barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
833 barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
834 barrier.image = image;
835 barrier.subresourceRange.aspectMask = aspectMask;
836 barrier.subresourceRange.baseMipLevel = 0;
837 barrier.subresourceRange.levelCount = 1;
838 barrier.subresourceRange.baseArrayLayer = 0;
839 barrier.subresourceRange.layerCount = 1;
841 vk.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (vk::VkDependencyFlags)0,
842 0, (const vk::VkMemoryBarrier*)DE_NULL,
843 0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
847 void initialTransitionColor2DImage (const vk::DeviceInterface &vk, vk::VkCommandBuffer cmdBuffer, vk::VkImage image, vk::VkImageLayout layout)
849 transition2DImage(vk, cmdBuffer, image, vk::VK_IMAGE_ASPECT_COLOR_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, layout);
852 void initialTransitionDepth2DImage (const vk::DeviceInterface &vk, vk::VkCommandBuffer cmdBuffer, vk::VkImage image, vk::VkImageLayout layout)
854 transition2DImage(vk, cmdBuffer, image, vk::VK_IMAGE_ASPECT_DEPTH_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, layout);
857 void initialTransitionStencil2DImage (const vk::DeviceInterface &vk, vk::VkCommandBuffer cmdBuffer, vk::VkImage image, vk::VkImageLayout layout)
859 transition2DImage(vk, cmdBuffer, image, vk::VK_IMAGE_ASPECT_STENCIL_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, layout);
862 void initialTransitionDepthStencil2DImage (const vk::DeviceInterface& vk,
863 vk::VkCommandBuffer cmdBuffer,
865 vk::VkImageLayout layout,
866 vk::VkAccessFlags srcAccessMask,
867 vk::VkAccessFlags dstAccessMask)
869 transition2DImage(vk, cmdBuffer, image, vk::VK_IMAGE_ASPECT_DEPTH_BIT | vk::VK_IMAGE_ASPECT_STENCIL_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, layout, srcAccessMask, dstAccessMask);