1 /*------------------------------------------------------------------------ 2 * Vulkan Conformance Tests 3 * ------------------------ 4 * 5 * Copyright (c) 2015 The Khronos Group Inc. 6 * Copyright (c) 2015 Intel Corporation 7 * 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 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 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. 19 * 20 *//*! 21 * \file 22 * \brief Image Object Util 23 *//*--------------------------------------------------------------------*/ 24 25 #include "vktDrawImageObjectUtil.hpp" 26 27 #include "tcuSurface.hpp" 28 #include "tcuVectorUtil.hpp" 29 30 #include "vkRefUtil.hpp" 31 #include "vkQueryUtil.hpp" 32 #include "vkImageUtil.hpp" 33 #include "vktDrawCreateInfoUtil.hpp" 34 #include "vktDrawBufferObjectUtil.hpp" 35 36 #include "tcuTextureUtil.hpp" 37 38 namespace vkt 39 { 40 namespace Draw 41 { 42 43 void MemoryOp::pack (int pixelSize, 44 int width, 45 int height, 46 int depth, 47 vk::VkDeviceSize rowPitchOrZero, 48 vk::VkDeviceSize depthPitchOrZero, 49 const void * srcBuffer, 50 void * destBuffer) 51 { 52 vk::VkDeviceSize rowPitch = rowPitchOrZero; 53 vk::VkDeviceSize depthPitch = depthPitchOrZero; 54 55 if (rowPitch == 0) 56 rowPitch = width * pixelSize; 57 58 if (depthPitch == 0) 59 depthPitch = rowPitch * height; 60 61 const vk::VkDeviceSize size = depthPitch * depth; 62 63 const deUint8 *srcRow = reinterpret_cast<const deUint8 *>(srcBuffer); 64 const deUint8 *srcStart; 65 srcStart = srcRow; 66 deUint8 *dstRow = reinterpret_cast<deUint8 *>(destBuffer); 67 deUint8 *dstStart; 68 dstStart = dstRow; 69 70 if (rowPitch == static_cast<vk::VkDeviceSize>(width * pixelSize) && 71 depthPitch == static_cast<vk::VkDeviceSize>(rowPitch * height)) 72 { 73 // fast path 74 deMemcpy(dstRow, srcRow, static_cast<size_t>(size)); 75 } 76 else 77 { 78 // slower, per row path 79 for (int d = 0; d < depth; d++) 80 { 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) 86 { 87 deMemcpy(dstRow, srcRow, static_cast<size_t>(rowPitch)); 88 srcRow += pixelSize * width; 89 dstRow += rowPitch; 90 } 91 } 92 } 93 } 94 95 void MemoryOp::unpack (int pixelSize, 96 int width, 97 int height, 98 int depth, 99 vk::VkDeviceSize rowPitchOrZero, 100 vk::VkDeviceSize depthPitchOrZero, 101 const void * srcBuffer, 102 void * destBuffer) 103 { 104 vk::VkDeviceSize rowPitch = rowPitchOrZero; 105 vk::VkDeviceSize depthPitch = depthPitchOrZero; 106 107 if (rowPitch == 0) 108 rowPitch = width * pixelSize; 109 110 if (depthPitch == 0) 111 depthPitch = rowPitch * height; 112 113 const vk::VkDeviceSize size = depthPitch * depth; 114 115 const deUint8 *srcRow = reinterpret_cast<const deUint8 *>(srcBuffer); 116 const deUint8 *srcStart; 117 srcStart = srcRow; 118 deUint8 *dstRow = reinterpret_cast<deUint8 *>(destBuffer); 119 deUint8 *dstStart; 120 dstStart = dstRow; 121 122 if (rowPitch == static_cast<vk::VkDeviceSize>(width * pixelSize) && 123 depthPitch == static_cast<vk::VkDeviceSize>(rowPitch * height)) 124 { 125 // fast path 126 deMemcpy(dstRow, srcRow, static_cast<size_t>(size)); 127 } 128 else { 129 // slower, per row path 130 for (size_t d = 0; d < (size_t)depth; d++) 131 { 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) 137 { 138 deMemcpy(dstRow, srcRow, static_cast<size_t>(pixelSize * width)); 139 srcRow += rowPitch; 140 dstRow += pixelSize * width; 141 } 142 } 143 } 144 } 145 146 Image::Image (const vk::DeviceInterface& vk, 147 vk::VkDevice device, 148 vk::VkFormat format, 149 const vk::VkExtent3D& extend, 150 deUint32 levelCount, 151 deUint32 layerCount, 152 vk::Move<vk::VkImage> object_) 153 : m_allocation (DE_NULL) 154 , m_object (object_) 155 , m_format (format) 156 , m_extent (extend) 157 , m_levelCount (levelCount) 158 , m_layerCount (layerCount) 159 , m_vk(vk) 160 , m_device(device) 161 { 162 } 163 164 tcu::ConstPixelBufferAccess Image::readSurface (vk::VkQueue queue, 165 vk::Allocator& allocator, 166 vk::VkImageLayout layout, 167 vk::VkOffset3D offset, 168 int width, 169 int height, 170 vk::VkImageAspectFlagBits aspect, 171 unsigned int mipLevel, 172 unsigned int arrayElement) 173 { 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) 177 { 178 read(queue, allocator, layout, offset, width, height, 1, mipLevel, arrayElement, aspect, vk::VK_IMAGE_TYPE_2D, 179 m_pixelAccessData.data()); 180 } 181 if (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT || aspect == vk::VK_IMAGE_ASPECT_STENCIL_BIT) 182 { 183 readUsingBuffer(queue, allocator, layout, offset, width, height, 1, mipLevel, arrayElement, aspect, m_pixelAccessData.data()); 184 } 185 return tcu::ConstPixelBufferAccess(vk::mapVkFormat(m_format), width, height, 1, m_pixelAccessData.data()); 186 } 187 188 tcu::ConstPixelBufferAccess Image::readVolume (vk::VkQueue queue, 189 vk::Allocator& allocator, 190 vk::VkImageLayout layout, 191 vk::VkOffset3D offset, 192 int width, 193 int height, 194 int depth, 195 vk::VkImageAspectFlagBits aspect, 196 unsigned int mipLevel, 197 unsigned int arrayElement) 198 { 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) 202 { 203 read(queue, allocator, layout, offset, width, height, depth, mipLevel, arrayElement, aspect, vk::VK_IMAGE_TYPE_3D, 204 m_pixelAccessData.data()); 205 } 206 if (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT || aspect == vk::VK_IMAGE_ASPECT_STENCIL_BIT) 207 { 208 readUsingBuffer(queue, allocator, layout, offset, width, height, depth, mipLevel, arrayElement, aspect, m_pixelAccessData.data()); 209 } 210 return tcu::ConstPixelBufferAccess(vk::mapVkFormat(m_format), width, height, depth, m_pixelAccessData.data()); 211 } 212 213 tcu::ConstPixelBufferAccess Image::readSurface1D(vk::VkQueue queue, 214 vk::Allocator& allocator, 215 vk::VkImageLayout layout, 216 vk::VkOffset3D offset, 217 int width, 218 vk::VkImageAspectFlagBits aspect, 219 unsigned int mipLevel, 220 unsigned int arrayElement) 221 { 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) 225 { 226 read(queue, allocator, layout, offset, width, 1, 1, mipLevel, arrayElement, aspect, vk::VK_IMAGE_TYPE_1D, 227 m_pixelAccessData.data()); 228 } 229 if (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT || aspect == vk::VK_IMAGE_ASPECT_STENCIL_BIT) 230 { 231 readUsingBuffer(queue, allocator, layout, offset, width, 1, 1, mipLevel, arrayElement, aspect, 232 m_pixelAccessData.data()); 233 } 234 return tcu::ConstPixelBufferAccess(vk::mapVkFormat(m_format), width, 1, 1, m_pixelAccessData.data()); 235 } 236 237 void Image::read (vk::VkQueue queue, 238 vk::Allocator& allocator, 239 vk::VkImageLayout layout, 240 vk::VkOffset3D offset, 241 int width, 242 int height, 243 int depth, 244 unsigned int mipLevel, 245 unsigned int arrayElement, 246 vk::VkImageAspectFlagBits aspect, 247 vk::VkImageType type, 248 void * data) 249 { 250 DE_ASSERT(layout == vk::VK_IMAGE_LAYOUT_GENERAL || layout == vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); 251 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); 256 } 257 258 void Image::readUsingBuffer (vk::VkQueue queue, 259 vk::Allocator& allocator, 260 vk::VkImageLayout layout, 261 vk::VkOffset3D offset, 262 int width, 263 int height, 264 int depth, 265 unsigned int mipLevel, 266 unsigned int arrayElement, 267 vk::VkImageAspectFlagBits aspect, 268 void * data) 269 { 270 DE_ASSERT(layout == vk::VK_IMAGE_LAYOUT_GENERAL || layout == vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);; 271 272 de::SharedPtr<Buffer> stagingResource; 273 274 bool isCombinedType = isCombinedDepthStencilType(vk::mapVkFormat(m_format).type); 275 vk::VkDeviceSize bufferSize = 0; 276 277 if (!isCombinedType) 278 bufferSize = vk::mapVkFormat(m_format).getPixelSize() * width * height * depth; 279 280 if (isCombinedType) 281 { 282 int pixelSize = 0; 283 switch (m_format) 284 { 285 case vk::VK_FORMAT_D16_UNORM_S8_UINT: 286 pixelSize = (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT) ? 2 : 1; 287 break; 288 case vk::VK_FORMAT_D32_SFLOAT_S8_UINT: 289 pixelSize = (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT) ? 4 : 1; 290 break; 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; 294 break; 295 296 default: 297 DE_FATAL("Not implemented"); 298 } 299 bufferSize = pixelSize*width*height*depth; 300 } 301 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); 304 305 { 306 //todo [scygan] get proper queueFamilyIndex 307 CmdPoolCreateInfo copyCmdPoolCreateInfo(0); 308 vk::Unique<vk::VkCommandPool> copyCmdPool(vk::createCommandPool(m_vk, m_device, ©CmdPoolCreateInfo)); 309 310 const vk::VkCommandBufferAllocateInfo cmdBufferAllocateInfo = 311 { 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; 317 }; 318 vk::Unique<vk::VkCommandBuffer> copyCmdBuffer(vk::allocateCommandBuffer(m_vk, m_device, &cmdBufferAllocateInfo)); 319 320 CmdBufferBeginInfo beginInfo; 321 VK_CHECK(m_vk.beginCommandBuffer(*copyCmdBuffer, &beginInfo)); 322 323 if (layout == vk::VK_IMAGE_LAYOUT_UNDEFINED) 324 { 325 layout = vk::VK_IMAGE_LAYOUT_GENERAL; 326 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(); 337 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; 343 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, 347 1, &barrier); 348 } 349 350 vk::VkBufferImageCopy region = 351 { 352 0, 0, 0, 353 { (vk::VkImageAspectFlags)aspect, mipLevel, arrayElement, 1 }, 354 offset, 355 { (deUint32)width, (deUint32)height, (deUint32)depth } 356 }; 357 358 m_vk.cmdCopyImageToBuffer(*copyCmdBuffer, object(), layout, stagingResource->object(), 1, ®ion); 359 VK_CHECK(m_vk.endCommandBuffer(*copyCmdBuffer)); 360 361 vk::VkSubmitInfo submitInfo = 362 { 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; 372 }; 373 m_vk.queueSubmit(queue, 1, &submitInfo, DE_NULL); 374 375 // TODO: make this less intrusive 376 VK_CHECK(m_vk.queueWaitIdle(queue)); 377 } 378 379 deUint8* destPtr = reinterpret_cast<deUint8*>(stagingResource->getBoundMemory().getHostPtr()); 380 deMemcpy(data, destPtr, static_cast<size_t>(bufferSize)); 381 } 382 383 tcu::ConstPixelBufferAccess Image::readSurfaceLinear (vk::VkOffset3D offset, 384 int width, 385 int height, 386 int depth, 387 vk::VkImageAspectFlagBits aspect, 388 unsigned int mipLevel, 389 unsigned int arrayElement) 390 { 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()); 394 } 395 396 void Image::readLinear (vk::VkOffset3D offset, 397 int width, 398 int height, 399 int depth, 400 unsigned int mipLevel, 401 unsigned int arrayElement, 402 vk::VkImageAspectFlagBits aspect, 403 void * data) 404 { 405 vk::VkImageSubresource imageSubResource = { (vk::VkImageAspectFlags)aspect, mipLevel, arrayElement }; 406 407 vk::VkSubresourceLayout imageLayout; 408 deMemset(&imageLayout, 0, sizeof(imageLayout)); 409 410 m_vk.getImageSubresourceLayout(m_device, object(), &imageSubResource, &imageLayout); 411 412 const deUint8* srcPtr = reinterpret_cast<const deUint8*>(getBoundMemory().getHostPtr()); 413 srcPtr += imageLayout.offset + getPixelOffset(offset, imageLayout.rowPitch, imageLayout.depthPitch, mipLevel, arrayElement); 414 415 MemoryOp::unpack(vk::mapVkFormat(m_format).getPixelSize(), width, height, depth, 416 imageLayout.rowPitch, imageLayout.depthPitch, srcPtr, data); 417 } 418 419 de::SharedPtr<Image> Image::copyToLinearImage (vk::VkQueue queue, 420 vk::Allocator& allocator, 421 vk::VkImageLayout layout, 422 vk::VkOffset3D offset, 423 int width, 424 int height, 425 int depth, 426 unsigned int mipLevel, 427 unsigned int arrayElement, 428 vk::VkImageAspectFlagBits aspect, 429 vk::VkImageType type) 430 { 431 de::SharedPtr<Image> stagingResource; 432 { 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); 436 437 stagingResource = Image::createAndAlloc(m_vk, m_device, stagingResourceCreateInfo, allocator, 438 vk::MemoryRequirement::HostVisible); 439 440 //todo [scygan] get proper queueFamilyIndex 441 CmdPoolCreateInfo copyCmdPoolCreateInfo(0); 442 vk::Unique<vk::VkCommandPool> copyCmdPool(vk::createCommandPool(m_vk, m_device, ©CmdPoolCreateInfo)); 443 444 const vk::VkCommandBufferAllocateInfo cmdBufferAllocateInfo = 445 { 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; 451 }; 452 vk::Unique<vk::VkCommandBuffer> copyCmdBuffer(vk::allocateCommandBuffer(m_vk, m_device, &cmdBufferAllocateInfo)); 453 454 CmdBufferBeginInfo beginInfo; 455 VK_CHECK(m_vk.beginCommandBuffer(*copyCmdBuffer, &beginInfo)); 456 457 transition2DImage(m_vk, *copyCmdBuffer, stagingResource->object(), aspect, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_GENERAL); 458 459 const vk::VkOffset3D zeroOffset = { 0, 0, 0 }; 460 vk::VkImageCopy region = { { (vk::VkImageAspectFlags)aspect, mipLevel, arrayElement, 1}, offset, { (vk::VkImageAspectFlags)aspect, 0, 0, 1}, zeroOffset, {(deUint32)width, (deUint32)height, (deUint32)depth} }; 461 462 m_vk.cmdCopyImage(*copyCmdBuffer, object(), layout, stagingResource->object(), vk::VK_IMAGE_LAYOUT_GENERAL, 1, ®ion); 463 VK_CHECK(m_vk.endCommandBuffer(*copyCmdBuffer)); 464 465 vk::VkSubmitInfo submitInfo = 466 { 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; 476 }; 477 m_vk.queueSubmit(queue, 1, &submitInfo, DE_NULL); 478 479 // TODO: make this less intrusive 480 VK_CHECK(m_vk.queueWaitIdle(queue)); 481 } 482 return stagingResource; 483 } 484 485 void Image::uploadVolume(const tcu::ConstPixelBufferAccess& access, 486 vk::VkQueue queue, 487 vk::Allocator& allocator, 488 vk::VkImageLayout layout, 489 vk::VkOffset3D offset, 490 vk::VkImageAspectFlagBits aspect, 491 unsigned int mipLevel, 492 unsigned int arrayElement) 493 { 494 if (aspect == vk::VK_IMAGE_ASPECT_COLOR_BIT) 495 { 496 upload(queue, allocator, layout, offset, access.getWidth(), 497 access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, vk::VK_IMAGE_TYPE_3D, 498 access.getDataPtr()); 499 } 500 if (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT || aspect == vk::VK_IMAGE_ASPECT_STENCIL_BIT) 501 { 502 uploadUsingBuffer(queue, allocator, layout, offset, access.getWidth(), 503 access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, access.getDataPtr()); 504 } 505 } 506 507 void Image::uploadSurface (const tcu::ConstPixelBufferAccess& access, 508 vk::VkQueue queue, 509 vk::Allocator& allocator, 510 vk::VkImageLayout layout, 511 vk::VkOffset3D offset, 512 vk::VkImageAspectFlagBits aspect, 513 unsigned int mipLevel, 514 unsigned int arrayElement) 515 { 516 if (aspect == vk::VK_IMAGE_ASPECT_COLOR_BIT) 517 { 518 upload(queue, allocator, layout, offset, access.getWidth(), 519 access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, vk::VK_IMAGE_TYPE_2D, 520 access.getDataPtr()); 521 } 522 if (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT || aspect == vk::VK_IMAGE_ASPECT_STENCIL_BIT) 523 { 524 uploadUsingBuffer(queue, allocator, layout, offset, access.getWidth(), 525 access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, access.getDataPtr()); 526 } 527 } 528 529 void Image::uploadSurface1D (const tcu::ConstPixelBufferAccess& access, 530 vk::VkQueue queue, 531 vk::Allocator& allocator, 532 vk::VkImageLayout layout, 533 vk::VkOffset3D offset, 534 vk::VkImageAspectFlagBits aspect, 535 unsigned int mipLevel, 536 unsigned int arrayElement) 537 { 538 if (aspect == vk::VK_IMAGE_ASPECT_COLOR_BIT) 539 { 540 upload(queue, allocator, layout, offset, access.getWidth(), 541 access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, vk::VK_IMAGE_TYPE_1D, 542 access.getDataPtr()); 543 } 544 if (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT || aspect == vk::VK_IMAGE_ASPECT_STENCIL_BIT) 545 { 546 uploadUsingBuffer(queue, allocator, layout, offset, access.getWidth(), 547 access.getHeight(), access.getDepth(), mipLevel, arrayElement, aspect, access.getDataPtr()); 548 } 549 } 550 551 void Image::uploadSurfaceLinear (const tcu::ConstPixelBufferAccess& access, 552 vk::VkOffset3D offset, 553 int width, 554 int height, 555 int depth, 556 vk::VkImageAspectFlagBits aspect, 557 unsigned int mipLevel, 558 unsigned int arrayElement) 559 { 560 uploadLinear(offset, width, height, depth, mipLevel, arrayElement, aspect, access.getDataPtr()); 561 } 562 563 void Image::upload (vk::VkQueue queue, 564 vk::Allocator& allocator, 565 vk::VkImageLayout layout, 566 vk::VkOffset3D offset, 567 int width, 568 int height, 569 int depth, 570 unsigned int mipLevel, 571 unsigned int arrayElement, 572 vk::VkImageAspectFlagBits aspect, 573 vk::VkImageType type, 574 const void * data) 575 { 576 DE_ASSERT(layout == vk::VK_IMAGE_LAYOUT_GENERAL || layout == vk::VK_IMAGE_LAYOUT_UNDEFINED || layout == vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); 577 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); 583 584 stagingResource = Image::createAndAlloc(m_vk, m_device, stagingResourceCreateInfo, allocator, 585 vk::MemoryRequirement::HostVisible); 586 587 const vk::VkOffset3D zeroOffset = { 0, 0, 0 }; 588 stagingResource->uploadLinear(zeroOffset, width, height, depth, 0, 0, aspect, data); 589 590 { 591 //todo [scygan] get proper queueFamilyIndex 592 CmdPoolCreateInfo copyCmdPoolCreateInfo(0); 593 vk::Unique<vk::VkCommandPool> copyCmdPool(vk::createCommandPool(m_vk, m_device, ©CmdPoolCreateInfo)); 594 595 const vk::VkCommandBufferAllocateInfo cmdBufferAllocateInfo = 596 { 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; 602 }; 603 604 vk::Unique<vk::VkCommandBuffer> copyCmdBuffer(vk::allocateCommandBuffer(m_vk, m_device, &cmdBufferAllocateInfo)); 605 606 CmdBufferBeginInfo beginInfo; 607 VK_CHECK(m_vk.beginCommandBuffer(*copyCmdBuffer, &beginInfo)); 608 609 if (layout == vk::VK_IMAGE_LAYOUT_UNDEFINED) 610 { 611 layout = vk::VK_IMAGE_LAYOUT_GENERAL; 612 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(); 623 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; 629 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, 633 1, &barrier); 634 } 635 636 transition2DImage(m_vk, *copyCmdBuffer, stagingResource->object(), aspect, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_GENERAL); 637 638 vk::VkImageCopy region = {{ (vk::VkImageAspectFlags)aspect, 0, 0, 1}, 639 zeroOffset, 640 { (vk::VkImageAspectFlags)aspect, mipLevel, arrayElement, 1}, 641 offset, 642 {(deUint32)width, (deUint32)height, (deUint32)depth}}; 643 644 m_vk.cmdCopyImage(*copyCmdBuffer, stagingResource->object(), 645 vk::VK_IMAGE_LAYOUT_GENERAL, object(), layout, 1, ®ion); 646 VK_CHECK(m_vk.endCommandBuffer(*copyCmdBuffer)); 647 648 vk::VkSubmitInfo submitInfo = 649 { 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; 659 }; 660 m_vk.queueSubmit(queue, 1, &submitInfo, DE_NULL); 661 662 // TODO: make this less intrusive 663 VK_CHECK(m_vk.queueWaitIdle(queue)); 664 } 665 } 666 667 void Image::uploadUsingBuffer (vk::VkQueue queue, 668 vk::Allocator& allocator, 669 vk::VkImageLayout layout, 670 vk::VkOffset3D offset, 671 int width, 672 int height, 673 int depth, 674 unsigned int mipLevel, 675 unsigned int arrayElement, 676 vk::VkImageAspectFlagBits aspect, 677 const void * data) 678 { 679 DE_ASSERT(layout == vk::VK_IMAGE_LAYOUT_GENERAL || layout == vk::VK_IMAGE_LAYOUT_UNDEFINED || layout == vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); 680 681 de::SharedPtr<Buffer> stagingResource; 682 bool isCombinedType = isCombinedDepthStencilType(vk::mapVkFormat(m_format).type); 683 vk::VkDeviceSize bufferSize = 0; 684 if (!isCombinedType) 685 bufferSize = vk::mapVkFormat(m_format).getPixelSize() *width*height*depth; 686 if (isCombinedType) 687 { 688 int pixelSize = 0; 689 switch (m_format) 690 { 691 case vk::VK_FORMAT_D16_UNORM_S8_UINT: 692 pixelSize = (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT) ? 2 : 1; 693 break; 694 case vk::VK_FORMAT_D32_SFLOAT_S8_UINT: 695 pixelSize = (aspect == vk::VK_IMAGE_ASPECT_DEPTH_BIT) ? 4 : 1; 696 break; 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; 700 break; 701 702 default: 703 DE_FATAL("Not implemented"); 704 } 705 bufferSize = pixelSize*width*height*depth; 706 } 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 deUint8* destPtr = reinterpret_cast<deUint8*>(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); 712 { 713 //todo [scygan] get proper queueFamilyIndex 714 CmdPoolCreateInfo copyCmdPoolCreateInfo(0); 715 vk::Unique<vk::VkCommandPool> copyCmdPool(vk::createCommandPool(m_vk, m_device, ©CmdPoolCreateInfo)); 716 717 const vk::VkCommandBufferAllocateInfo cmdBufferAllocateInfo = 718 { 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; 724 }; 725 vk::Unique<vk::VkCommandBuffer> copyCmdBuffer(vk::allocateCommandBuffer(m_vk, m_device, &cmdBufferAllocateInfo)); 726 727 CmdBufferBeginInfo beginInfo; 728 VK_CHECK(m_vk.beginCommandBuffer(*copyCmdBuffer, &beginInfo)); 729 730 if (layout == vk::VK_IMAGE_LAYOUT_UNDEFINED) 731 { 732 layout = vk::VK_IMAGE_LAYOUT_GENERAL; 733 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(); 744 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; 750 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, 754 1, &barrier); 755 } 756 757 vk::VkBufferImageCopy region = { 758 0, 0, 0, 759 { (vk::VkImageAspectFlags)aspect, mipLevel, arrayElement, 1 }, 760 offset, 761 { (deUint32)width, (deUint32)height, (deUint32)depth } 762 }; 763 764 m_vk.cmdCopyBufferToImage(*copyCmdBuffer, stagingResource->object(), 765 object(), layout, 1, ®ion); 766 VK_CHECK(m_vk.endCommandBuffer(*copyCmdBuffer)); 767 768 vk::VkSubmitInfo submitInfo = 769 { 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; 779 }; 780 m_vk.queueSubmit(queue, 1, &submitInfo, DE_NULL); 781 782 // TODO: make this less intrusive 783 VK_CHECK(m_vk.queueWaitIdle(queue)); 784 } 785 } 786 787 void Image::uploadLinear (vk::VkOffset3D offset, 788 int width, 789 int height, 790 int depth, 791 unsigned int mipLevel, 792 unsigned int arrayElement, 793 vk::VkImageAspectFlagBits aspect, 794 const void * data) 795 { 796 vk::VkSubresourceLayout imageLayout; 797 798 vk::VkImageSubresource imageSubResource = { (vk::VkImageAspectFlags)aspect, mipLevel, arrayElement}; 799 800 m_vk.getImageSubresourceLayout(m_device, object(), &imageSubResource, 801 &imageLayout); 802 803 deUint8* destPtr = reinterpret_cast<deUint8*>(getBoundMemory().getHostPtr()); 804 805 destPtr += imageLayout.offset + getPixelOffset(offset, imageLayout.rowPitch, imageLayout.depthPitch, mipLevel, arrayElement); 806 807 MemoryOp::pack(vk::mapVkFormat(m_format).getPixelSize(), width, height, depth, 808 imageLayout.rowPitch, imageLayout.depthPitch, data, destPtr); 809 } 810 811 vk::VkDeviceSize Image::getPixelOffset (vk::VkOffset3D offset, 812 vk::VkDeviceSize rowPitch, 813 vk::VkDeviceSize depthPitch, 814 unsigned int level, 815 unsigned int layer) 816 { 817 DE_ASSERT(level < m_levelCount); 818 DE_ASSERT(layer < m_layerCount); 819 820 vk::VkDeviceSize mipLevelSizes[32]; 821 vk::VkDeviceSize mipLevelRectSizes[32]; 822 tcu::IVec3 mipExtend 823 = tcu::IVec3(m_extent.width, m_extent.height, m_extent.depth); 824 825 vk::VkDeviceSize arrayElemSize = 0; 826 for (unsigned int i = 0; i < m_levelCount && (mipExtend[0] > 1 || mipExtend[1] > 1 || mipExtend[2] > 1); ++i) 827 { 828 // Rect size is just a 3D image size; 829 mipLevelSizes[i] = mipExtend[2] * depthPitch; 830 831 arrayElemSize += mipLevelSizes[0]; 832 833 mipExtend = tcu::max(mipExtend / 2, tcu::IVec3(1)); 834 } 835 836 vk::VkDeviceSize pixelOffset = layer * arrayElemSize; 837 for (size_t i = 0; i < level; ++i) { 838 pixelOffset += mipLevelSizes[i]; 839 } 840 pixelOffset += offset.z * mipLevelRectSizes[level]; 841 pixelOffset += offset.y * rowPitch; 842 pixelOffset += offset.x; 843 844 return pixelOffset; 845 } 846 847 void Image::bindMemory (de::MovePtr<vk::Allocation> allocation) 848 { 849 DE_ASSERT(allocation); 850 VK_CHECK(m_vk.bindImageMemory(m_device, *m_object, allocation->getMemory(), allocation->getOffset())); 851 852 DE_ASSERT(!m_allocation); 853 m_allocation = allocation; 854 } 855 856 de::SharedPtr<Image> Image::createAndAlloc(const vk::DeviceInterface& vk, 857 vk::VkDevice device, 858 const vk::VkImageCreateInfo& createInfo, 859 vk::Allocator& allocator, 860 vk::MemoryRequirement memoryRequirement) 861 { 862 de::SharedPtr<Image> ret = create(vk, device, createInfo); 863 864 vk::VkMemoryRequirements imageRequirements = vk::getImageMemoryRequirements(vk, device, ret->object()); 865 ret->bindMemory(allocator.allocate(imageRequirements, memoryRequirement)); 866 return ret; 867 } 868 869 de::SharedPtr<Image> Image::create(const vk::DeviceInterface& vk, 870 vk::VkDevice device, 871 const vk::VkImageCreateInfo &createInfo) 872 { 873 return de::SharedPtr<Image>(new Image(vk, device, createInfo.format, createInfo.extent, 874 createInfo.mipLevels, createInfo.arrayLayers, 875 vk::createImage(vk, device, &createInfo))); 876 } 877 878 void transition2DImage (const vk::DeviceInterface& vk, 879 vk::VkCommandBuffer cmdBuffer, 880 vk::VkImage image, 881 vk::VkImageAspectFlags aspectMask, 882 vk::VkImageLayout oldLayout, 883 vk::VkImageLayout newLayout, 884 vk::VkAccessFlags srcAccessMask, 885 vk::VkAccessFlags dstAccessMask) 886 { 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; 902 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, 906 1, &barrier); 907 } 908 909 void initialTransitionColor2DImage (const vk::DeviceInterface &vk, vk::VkCommandBuffer cmdBuffer, vk::VkImage image, vk::VkImageLayout layout) 910 { 911 transition2DImage(vk, cmdBuffer, image, vk::VK_IMAGE_ASPECT_COLOR_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, layout); 912 } 913 914 void initialTransitionDepth2DImage (const vk::DeviceInterface &vk, vk::VkCommandBuffer cmdBuffer, vk::VkImage image, vk::VkImageLayout layout) 915 { 916 transition2DImage(vk, cmdBuffer, image, vk::VK_IMAGE_ASPECT_DEPTH_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, layout); 917 } 918 919 void initialTransitionStencil2DImage (const vk::DeviceInterface &vk, vk::VkCommandBuffer cmdBuffer, vk::VkImage image, vk::VkImageLayout layout) 920 { 921 transition2DImage(vk, cmdBuffer, image, vk::VK_IMAGE_ASPECT_STENCIL_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, layout); 922 } 923 924 void initialTransitionDepthStencil2DImage (const vk::DeviceInterface& vk, 925 vk::VkCommandBuffer cmdBuffer, 926 vk::VkImage image, 927 vk::VkImageLayout layout, 928 vk::VkAccessFlags srcAccessMask, 929 vk::VkAccessFlags dstAccessMask) 930 { 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); 932 } 933 934 } // Draw 935 } // vkt 936