197 vk::BufferCreateInfo stagingBufferInfo;
198 stagingBufferInfo.setSize(size);
199 stagingBufferInfo.setUsage(vk::BufferUsageFlagBits::eTransferSrc);
200 stagingBufferInfo.setSharingMode(vk::SharingMode::eExclusive);
202 vk::Buffer stagingBuffer;
203 vk::DeviceMemory stagingMemory;
206 stagingBuffer =
m_device.createBuffer(stagingBufferInfo);
208 vk::MemoryRequirements memRequirements =
m_device.getBufferMemoryRequirements(stagingBuffer);
210 vk::MemoryAllocateInfo allocInfo;
211 allocInfo.setAllocationSize(memRequirements.size);
213 memRequirements.memoryTypeBits,
214 vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent));
216 stagingMemory =
m_device.allocateMemory(allocInfo);
217 m_device.bindBufferMemory(stagingBuffer, stagingMemory, 0);
219 void* mappedData =
m_device.mapMemory(stagingMemory, 0, size);
220 memcpy(mappedData, data, size);
221 m_device.unmapMemory(stagingMemory);
225 vk::BufferCopy copyRegion;
226 copyRegion.setSrcOffset(0);
227 copyRegion.setDstOffset(0);
228 copyRegion.setSize(size);
229 cmdBuffer.copyBuffer(stagingBuffer, dstBuffer, 1, ©Region);
233 m_device.destroyBuffer(stagingBuffer);
236 catch (
const std::exception& e) {
237 ferr <<
"Failed to transfer data to buffer: " << e.what() << std::endl;
240 m_device.destroyBuffer(stagingBuffer);
258 vk::Format format, uint32_t mipLevels, uint32_t arrayLayers,
259 vk::ImageAspectFlags aspectMask,
const void* data,
size_t dataSize,
260 vk::Fence* outFence, std::function<
void()>* cleanUpCallback)
263 size_t fullImageSize = width * height *
depth * pixelSize;
264 vk::BufferCreateInfo stagingBufferInfo;
265 stagingBufferInfo.setSize(fullImageSize);
266 stagingBufferInfo.setUsage(vk::BufferUsageFlagBits::eTransferSrc);
267 stagingBufferInfo.setSharingMode(vk::SharingMode::eExclusive);
269 vk::Buffer stagingBuffer;
270 vk::DeviceMemory stagingMemory;
273 stagingBuffer =
m_device.createBuffer(stagingBufferInfo);
275 vk::MemoryRequirements memRequirements =
m_device.getBufferMemoryRequirements(stagingBuffer);
277 vk::MemoryAllocateInfo allocInfo;
278 allocInfo.setAllocationSize(memRequirements.size);
280 memRequirements.memoryTypeBits,
281 vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent));
283 stagingMemory =
m_device.allocateMemory(allocInfo);
284 m_device.bindBufferMemory(stagingBuffer, stagingMemory, 0);
286 void* mappedData =
m_device.mapMemory(stagingMemory, 0, dataSize);
287 memcpy(mappedData, data, dataSize);
288 m_device.unmapMemory(stagingMemory);
293 vk::ImageLayout finalLayout;
294 vk::AccessFlags finalAccessMask;
296 if (aspectMask & vk::ImageAspectFlagBits::eDepth || aspectMask & vk::ImageAspectFlagBits::eStencil) {
297 finalLayout = vk::ImageLayout::eDepthStencilAttachmentOptimal;
298 finalAccessMask = vk::AccessFlagBits::eDepthStencilAttachmentRead | vk::AccessFlagBits::eDepthStencilAttachmentWrite;
300 finalLayout = vk::ImageLayout::eShaderReadOnlyOptimal;
301 finalAccessMask = vk::AccessFlagBits::eShaderRead;
304 vk::ImageMemoryBarrier barrier;
305 barrier.setOldLayout(vk::ImageLayout::eUndefined);
306 barrier.setNewLayout(vk::ImageLayout::eTransferDstOptimal);
308 if (needsQueueTransfer) {
309 barrier.setSrcQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED);
310 barrier.setDstQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED);
312 barrier.setSrcQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED);
313 barrier.setDstQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED);
316 barrier.setImage(dstImage);
317 barrier.setSubresourceRange(vk::ImageSubresourceRange(
318 aspectMask, 0, mipLevels, 0, arrayLayers));
319 barrier.setSrcAccessMask(vk::AccessFlagBits::eNone);
320 barrier.setDstAccessMask(vk::AccessFlagBits::eTransferWrite);
322 cmdBuffer.pipelineBarrier(
323 vk::PipelineStageFlagBits::eTopOfPipe,
324 vk::PipelineStageFlagBits::eTransfer,
325 vk::DependencyFlags(),
330 vk::BufferImageCopy region;
331 region.setBufferOffset(0);
332 region.setBufferRowLength(0);
333 region.setBufferImageHeight(0);
334 region.setImageSubresource(vk::ImageSubresourceLayers(
335 aspectMask, 0, 0, arrayLayers));
336 region.setImageOffset(vk::Offset3D(0, 0, 0));
337 region.setImageExtent(vk::Extent3D(width, height,
depth));
339 cmdBuffer.copyBufferToImage(
342 vk::ImageLayout::eTransferDstOptimal,
345 barrier.setOldLayout(vk::ImageLayout::eTransferDstOptimal);
347 if (needsQueueTransfer) {
348 barrier.setNewLayout(vk::ImageLayout::eTransferDstOptimal);
351 barrier.setSrcAccessMask(vk::AccessFlagBits::eTransferWrite);
352 barrier.setDstAccessMask(vk::AccessFlagBits::eShaderRead);
354 barrier.setNewLayout(finalLayout);
355 barrier.setSrcQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED);
356 barrier.setDstQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED);
357 barrier.setSrcAccessMask(vk::AccessFlagBits::eTransferWrite);
358 barrier.setDstAccessMask(finalAccessMask);
361 cmdBuffer.pipelineBarrier(
362 vk::PipelineStageFlagBits::eTransfer,
363 vk::PipelineStageFlagBits::eTransfer,
364 vk::DependencyFlags(),
373 if (cleanUpCallback) {
374 vk::Buffer capturedBuffer = stagingBuffer;
375 vk::DeviceMemory capturedMemory = stagingMemory;
376 vk::Image capturedImage = dstImage;
377 bool capturedNeedsQueueTransfer = needsQueueTransfer;
378 vk::ImageAspectFlags capturedAspectMask = aspectMask;
379 uint32_t capturedMipLevels = mipLevels;
380 uint32_t capturedArrayLayers = arrayLayers;
381 vk::ImageLayout capturedFinalLayout = finalLayout;
382 vk::AccessFlags capturedFinalAccessMask = finalAccessMask;
383 vk::Fence capturedFence = fence;
384 vk::CommandBuffer capturedCmdBuffer = cmdBuffer;
386 *cleanUpCallback = [
this, capturedBuffer, capturedMemory, capturedImage,
387 capturedNeedsQueueTransfer, capturedAspectMask,
388 capturedMipLevels, capturedArrayLayers,
389 capturedFinalLayout, capturedFinalAccessMask,
390 capturedFence,capturedCmdBuffer]() {
391 m_device.waitForFences(1, &capturedFence, VK_TRUE, UINT64_MAX);
392 m_device.destroyFence(capturedFence);
397 if (capturedNeedsQueueTransfer) {
400 vk::ImageMemoryBarrier finalBarrier;
401 finalBarrier.setOldLayout(vk::ImageLayout::eTransferDstOptimal);
402 finalBarrier.setNewLayout(capturedFinalLayout);
405 finalBarrier.setImage(capturedImage);
406 finalBarrier.setSubresourceRange(vk::ImageSubresourceRange(
407 capturedAspectMask, 0, capturedMipLevels, 0, capturedArrayLayers));
408 finalBarrier.setSrcAccessMask(vk::AccessFlagBits::eTransferWrite);
409 finalBarrier.setDstAccessMask(capturedFinalAccessMask);
411 vk::PipelineStageFlags finalStage;
412 if (capturedAspectMask & vk::ImageAspectFlagBits::eDepth ||
413 capturedAspectMask & vk::ImageAspectFlagBits::eStencil) {
414 finalStage = vk::PipelineStageFlagBits::eEarlyFragmentTests;
416 finalStage = vk::PipelineStageFlagBits::eAllCommands;
419 graphicsCmdBuffer.pipelineBarrier(
420 vk::PipelineStageFlagBits::eAllCommands,
422 vk::DependencyFlags(),
430 if (capturedBuffer) {
431 m_device.destroyBuffer(capturedBuffer);
433 if (capturedMemory) {
434 m_device.freeMemory(capturedMemory);
442 ferr <<
"callback is nullptr, resource is leaked in transferDataToImage" << std::endl;
447 if (needsQueueTransfer) {
450 vk::ImageMemoryBarrier finalBarrier;
451 finalBarrier.setOldLayout(vk::ImageLayout::eTransferDstOptimal);
452 finalBarrier.setNewLayout(finalLayout);
455 finalBarrier.setImage(dstImage);
456 finalBarrier.setSubresourceRange(vk::ImageSubresourceRange(
457 aspectMask, 0, mipLevels, 0, arrayLayers));
458 finalBarrier.setSrcAccessMask(vk::AccessFlagBits::eTransferWrite);
459 finalBarrier.setDstAccessMask(finalAccessMask);
461 vk::PipelineStageFlags finalStage;
462 if (aspectMask & vk::ImageAspectFlagBits::eDepth ||
463 aspectMask & vk::ImageAspectFlagBits::eStencil) {
464 finalStage = vk::PipelineStageFlagBits::eEarlyFragmentTests;
466 finalStage = vk::PipelineStageFlagBits::eAllCommands;
469 graphicsCmdBuffer.pipelineBarrier(
470 vk::PipelineStageFlagBits::eAllCommands,
472 vk::DependencyFlags(),
480 m_device.destroyBuffer(stagingBuffer);
484 catch (
const std::exception& e) {
485 ferr <<
"Failed to transfer data to image: " << e.what() << std::endl;
488 m_device.destroyBuffer(stagingBuffer);