diff --git a/include/vkcv/BufferManager.hpp b/include/vkcv/BufferManager.hpp index eb8cb178d1b844fff57892c7312ed71d325900cc..466559df8e5fb4d7c1d9e8342e4083e1f0596695 100644 --- a/include/vkcv/BufferManager.hpp +++ b/include/vkcv/BufferManager.hpp @@ -22,6 +22,7 @@ namespace vkcv class BufferManager { friend class Core; + friend class ImageManager; private: struct Buffer diff --git a/include/vkcv/Image.hpp b/include/vkcv/Image.hpp index 3c211402ffdc00a3cf7ee10ef7d0e557589af121..a7de56cf527e177a7ba29a406d4f9dbea22eed12 100644 --- a/include/vkcv/Image.hpp +++ b/include/vkcv/Image.hpp @@ -4,16 +4,18 @@ * @file vkcv/Buffer.hpp * @brief class for image handles */ -#include "ImageManager.hpp" +#include "vulkan/vulkan.hpp" namespace vkcv { + class ImageManager; class Image { public: static Image create(ImageManager* manager, uint32_t width, uint32_t height); - void switchImageLayout(vk::Format format, vk::ImageLayout oldLayout, vk::ImageLayout newLayout); + void switchImageLayout(vk::ImageLayout newLayout); private: ImageManager* const m_manager; const uint64_t m_handle_id; + vk::ImageLayout m_layout; Image(ImageManager* manager, uint64_t id); }; diff --git a/include/vkcv/ImageManager.hpp b/include/vkcv/ImageManager.hpp index b4fe888e3007d4263030ae0c344bc878e0651c9f..faf974b7272e96feb74960ecc1b7b8fa119bc706 100644 --- a/include/vkcv/ImageManager.hpp +++ b/include/vkcv/ImageManager.hpp @@ -9,7 +9,8 @@ namespace vkcv { class Core; - class ImageManager + class BufferManager; + class ImageManager { friend class Core; private: @@ -17,11 +18,13 @@ namespace vkcv { { vk::Image m_handle; vk::DeviceMemory m_memory; - void* m_mapped = nullptr; - bool m_mappable; }; Core* m_core; + vk::Buffer m_stagingBuffer; + vk::DeviceMemory m_stagingMemory; + std::vector<Image> m_images; + void init(BufferManager* bufferManager); ImageManager() noexcept; public: ~ImageManager() noexcept; @@ -30,9 +33,9 @@ namespace vkcv { ImageManager& operator=(ImageManager&& other) = delete; ImageManager& operator=(const ImageManager& other) = delete; - - void copyBufferToImage(vk::Buffer buffer, vk::Image image, uint32_t width, uint32_t height); + void switchImageLayout(uint64_t id, vk::ImageLayout oldLayout, vk::ImageLayout newLayout); + void fillImage(uint64_t id, void* data, size_t size); uint64_t createImage(uint32_t width, uint32_t height); diff --git a/src/vkcv/Core.cpp b/src/vkcv/Core.cpp index 4fc53eb90fd1e0121170e3f3849e3ba42b4a9b05..66156843b8ed3861f9eefe3524c59b0dadf6d366 100644 --- a/src/vkcv/Core.cpp +++ b/src/vkcv/Core.cpp @@ -10,6 +10,7 @@ #include "PassManager.hpp" #include "PipelineManager.hpp" #include "vkcv/BufferManager.hpp" +#include "vkcv/ImageManager.hpp" #include "Surface.hpp" #include "ImageLayoutTransitions.hpp" #include "Framebuffer.hpp" @@ -100,6 +101,7 @@ namespace vkcv m_BufferManager->m_core = this; m_BufferManager->init(); m_ImageManager->m_core = this; + m_ImageManager->init(m_BufferManager.get()); } Core::~Core() noexcept { diff --git a/src/vkcv/Image.cpp b/src/vkcv/Image.cpp index 887bf3b29adcd1d7e9490ab2820545b28691d3a6..cd41c0e2a87ba5949050c50ddb8b094fc1634f3f 100644 --- a/src/vkcv/Image.cpp +++ b/src/vkcv/Image.cpp @@ -4,6 +4,7 @@ * @brief class for image handles */ #include "vkcv/Image.hpp" +#include "vkcv/ImageManager.hpp" namespace vkcv{ Image Image::create(ImageManager* manager, uint32_t width, uint32_t height) @@ -11,13 +12,15 @@ namespace vkcv{ return Image(manager, manager->createImage(width, height)); } - void Image::switchImageLayout(vk::Format format, vk::ImageLayout oldLayout, vk::ImageLayout newLayout) + void Image::switchImageLayout(vk::ImageLayout newLayout) { - m_manager->switchImageLayout(m_handle_id, oldLayout, newLayout); + m_manager->switchImageLayout(m_handle_id, m_layout, newLayout); + m_layout = newLayout; } Image::Image(ImageManager* manager, uint64_t id) : m_manager(manager), - m_handle_id(id) + m_handle_id(id), + m_layout(vk::ImageLayout::eUndefined) { } diff --git a/src/vkcv/ImageManager.cpp b/src/vkcv/ImageManager.cpp index 46d703b453823c898639ab927c0f0929bbc7a937..38e0b554f2ec8d4b19c94d0b5898b6649749f721 100644 --- a/src/vkcv/ImageManager.cpp +++ b/src/vkcv/ImageManager.cpp @@ -34,6 +34,15 @@ namespace vkcv { return -1; } + void ImageManager::init(BufferManager* bufferManager) + { + if (!m_core) { + return; + } + uint64_t stagingID = bufferManager->createBuffer(BufferType::STAGING, 1024 * 1024, BufferMemoryType::HOST_VISIBLE); + m_stagingBuffer = bufferManager->m_buffers[stagingID].m_handle; + } + ImageManager::ImageManager() noexcept : m_core(nullptr), m_images() { @@ -45,25 +54,7 @@ namespace vkcv { } } - void ImageManager::copyBufferToImage(vk::Buffer buffer, vk::Image image, uint32_t width, uint32_t height) - { - vk::BufferImageCopy copyRegion(0,width,height); // possibly add offset etc - - SubmitInfo submitInfo; - submitInfo.queueType = QueueType::Transfer; //not sure - m_core->submitCommands( - submitInfo, - [buffer, image,copyRegion](const vk::CommandBuffer& commandBuffer) { - commandBuffer.copyBufferToImage( - buffer, - image,vk::ImageLayout::eTransferDstOptimal, - copyRegion - ); - }, - []() {} - ); - - } + uint64_t ImageManager::createImage(uint32_t width, uint32_t height) @@ -95,7 +86,6 @@ namespace vkcv { const vk::PhysicalDevice& physicalDevice = m_core->getContext().getPhysicalDevice(); vk::MemoryPropertyFlags memoryTypeFlags = vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent; - bool mappable = false; const uint32_t memoryTypeIndex = searchImageMemoryType( physicalDevice.getMemoryProperties(), @@ -107,7 +97,7 @@ namespace vkcv { device.bindImageMemory(image, memory, 0); const uint64_t id = m_images.size(); - m_images.push_back({ image, memory, nullptr, mappable }); + m_images.push_back({ image, memory}); return id; } @@ -154,10 +144,114 @@ namespace vkcv { imageMemoryBarrier ); }, - []() {} + nullptr ); } + struct ImageStagingStepInfo { + void* data; + size_t size; + uint32_t width; + uint32_t height; + size_t offset; + + vk::Image image; + vk::Buffer stagingBuffer; + vk::DeviceMemory stagingMemory; + + size_t stagingLimit; + size_t stagingPosition; + }; + + void copyStagingToImage(Core* core, ImageStagingStepInfo info) + { + /* + * Alte implementation + vk::BufferImageCopy copyRegion(0, width, height); + + SubmitInfo submitInfo; + submitInfo.queueType = QueueType::Transfer; //not sure + core->submitCommands( + submitInfo, + [buffer, image, copyRegion](const vk::CommandBuffer& commandBuffer) { + commandBuffer.copyBufferToImage( + buffer, + image, vk::ImageLayout::eTransferDstOptimal, + copyRegion + ); + }, + []() {} + ); + */ + + const size_t remaining = info.size - info.stagingPosition; + const size_t mapped_size = std::min(remaining, info.stagingLimit); + + const vk::Device& device = core->getContext().getDevice(); + + void* mapped = device.mapMemory(info.stagingMemory, 0, mapped_size); + memcpy(mapped, reinterpret_cast<char*>(info.data) + info.stagingPosition, mapped_size); + device.unmapMemory(info.stagingMemory); + + SubmitInfo submitInfo; + submitInfo.queueType = QueueType::Transfer; + + core->submitCommands( + submitInfo, + [&info, &mapped_size](const vk::CommandBuffer& commandBuffer) { + /* + const vk::BufferImageCopy region( + info.offset, //bufferOffset + info.size, //bufferRowlength + 0, //bufferImageHeight + vk::ImageSubresourceLayers(vk::ImageAspectFlagBits::eColor,0,0,1),//soubresource layer + vk::Offset2D(info.offset,0), //imageoffset + vk::Extent3D(info.width,info.height,1) //extend3d + ); + + commandBuffer.copyBufferToImage( + info.stagingBuffer, + info.image, + vk::ImageLayout::eTransferDstOptimal, + region); + */ + }, + [&core, &info, &mapped_size, &remaining]() { + if (mapped_size < remaining) { + info.stagingPosition += mapped_size; + + copyStagingToImage( + core, + info + ); + } + } + ); + } + void ImageManager::fillImage(uint64_t id, void* data, size_t size) + { + uint64_t width =0, height = 0; // TODO + //Image wird geladen + size_t sizeImage = width * height * 3; //TODO + switchImageLayout(id, vk::ImageLayout::eUndefined, vk::ImageLayout::eTransferDstOptimal); + //const size_t max_size = std::min(size, image.m_size - offset); + ImageStagingStepInfo info; + info.data = data; + info.size = size;//TODO + info.offset = 0; + + info.image = m_images[id].m_handle; + info.stagingBuffer = m_stagingBuffer; + info.stagingMemory = m_stagingMemory; + + const vk::MemoryRequirements stagingRequirements = m_core->getContext().getDevice().getBufferMemoryRequirements(m_stagingBuffer); + info.stagingLimit = stagingRequirements.size; + info.stagingPosition = 0; + + copyStagingToImage(m_core, info); + switchImageLayout(id, vk::ImageLayout::eTransferDstOptimal, vk::ImageLayout::eShaderReadOnlyOptimal); + } + void ImageManager::destroyImage(uint64_t id) { if (id >= m_images.size()) {