Skip to content
Snippets Groups Projects
Verified Commit d0cdcb2e authored by Tobias Frisch's avatar Tobias Frisch
Browse files

[#31] Filled image with just one buffer because it was easier

parent 27eed21f
No related branches found
No related tags found
1 merge request!32Resolve "Image-Klasse"
Pipeline #25283 passed
...@@ -27,7 +27,7 @@ set(vkcv_sources ...@@ -27,7 +27,7 @@ set(vkcv_sources
${vkcv_include}/vkcv/Image.hpp ${vkcv_include}/vkcv/Image.hpp
${vkcv_source}/vkcv/Image.cpp ${vkcv_source}/vkcv/Image.cpp
${vkcv_include}/vkcv/ImageManager.hpp ${vkcv_source}/vkcv/ImageManager.hpp
${vkcv_source}/vkcv/ImageManager.cpp ${vkcv_source}/vkcv/ImageManager.cpp
${vkcv_include}/vkcv/SwapChain.hpp ${vkcv_include}/vkcv/SwapChain.hpp
......
...@@ -25,16 +25,15 @@ namespace vkcv ...@@ -25,16 +25,15 @@ namespace vkcv
class BufferManager class BufferManager
{ {
friend class Core; friend class Core;
friend class ImageManager;
private: private:
struct Buffer struct Buffer
{ {
vk::Buffer m_handle; vk::Buffer m_handle;
vk::DeviceMemory m_memory; vk::DeviceMemory m_memory;
size_t m_size; size_t m_size = 0;
void* m_mapped = nullptr; void* m_mapped = nullptr;
bool m_mappable; bool m_mappable = false;
}; };
Core* m_core; Core* m_core;
...@@ -56,7 +55,7 @@ namespace vkcv ...@@ -56,7 +55,7 @@ namespace vkcv
/** /**
* Creates and allocates a new buffer and returns its * Creates and allocates a new buffer and returns its
* unique buffer handle id. * unique buffer handle.
* *
* @param type Type of buffer * @param type Type of buffer
* @param size Size of buffer in bytes * @param size Size of buffer in bytes
...@@ -67,7 +66,7 @@ namespace vkcv ...@@ -67,7 +66,7 @@ namespace vkcv
/** /**
* Returns the Vulkan buffer handle of a buffer * Returns the Vulkan buffer handle of a buffer
* represented by a given buffer handle id. * represented by a given buffer handle.
* *
* @param handle Buffer handle * @param handle Buffer handle
* @return Vulkan buffer handle * @return Vulkan buffer handle
...@@ -75,6 +74,16 @@ namespace vkcv ...@@ -75,6 +74,16 @@ namespace vkcv
[[nodiscard]] [[nodiscard]]
vk::Buffer getBuffer(const BufferHandle& handle) const; vk::Buffer getBuffer(const BufferHandle& handle) const;
/**
* Returns the size of a buffer represented
* by a given buffer handle.
*
* @param handle Buffer handle
* @return Size of the buffer
*/
[[nodiscard]]
size_t getBufferSize(const BufferHandle& handle) const;
/** /**
* Returns the Vulkan device memory handle of a buffer * Returns the Vulkan device memory handle of a buffer
* represented by a given buffer handle id. * represented by a given buffer handle id.
...@@ -87,7 +96,7 @@ namespace vkcv ...@@ -87,7 +96,7 @@ namespace vkcv
/** /**
* Fills a buffer represented by a given buffer * Fills a buffer represented by a given buffer
* handle id with custom data. * handle with custom data.
* *
* @param handle Buffer handle * @param handle Buffer handle
* @param data Pointer to data * @param data Pointer to data
...@@ -98,7 +107,7 @@ namespace vkcv ...@@ -98,7 +107,7 @@ namespace vkcv
/** /**
* Maps memory to a buffer represented by a given * Maps memory to a buffer represented by a given
* buffer handle id and returns it. * buffer handle and returns it.
* *
* @param handle Buffer handle * @param handle Buffer handle
* @param offset Offset of mapping in bytes * @param offset Offset of mapping in bytes
...@@ -109,7 +118,7 @@ namespace vkcv ...@@ -109,7 +118,7 @@ namespace vkcv
/** /**
* Unmaps memory from a buffer represented by a given * Unmaps memory from a buffer represented by a given
* buffer handle id. * buffer handle.
* *
* @param handle Buffer handle * @param handle Buffer handle
*/ */
...@@ -117,7 +126,7 @@ namespace vkcv ...@@ -117,7 +126,7 @@ namespace vkcv
/** /**
* Destroys and deallocates buffer represented by a given * Destroys and deallocates buffer represented by a given
* buffer handle id. * buffer handle.
* *
* @param handle Buffer handle * @param handle Buffer handle
*/ */
......
...@@ -64,4 +64,10 @@ namespace vkcv ...@@ -64,4 +64,10 @@ namespace vkcv
using Handle::Handle; using Handle::Handle;
}; };
class ImageHandle : public Handle {
friend class ImageManager;
private:
using Handle::Handle;
};
} }
...@@ -6,12 +6,17 @@ ...@@ -6,12 +6,17 @@
*/ */
#include "vulkan/vulkan.hpp" #include "vulkan/vulkan.hpp"
#include "Handles.hpp"
namespace vkcv { namespace vkcv {
class ImageManager; class ImageManager;
class Image { class Image {
public: public:
static Image create(ImageManager* manager, uint32_t width, uint32_t height); static Image create(ImageManager* manager, vk::Format format, uint32_t width, uint32_t height, uint32_t depth);
[[nodiscard]]
vk::Format getFormat() const;
[[nodiscard]] [[nodiscard]]
uint32_t getWidth() const; uint32_t getWidth() const;
...@@ -19,18 +24,25 @@ namespace vkcv { ...@@ -19,18 +24,25 @@ namespace vkcv {
[[nodiscard]] [[nodiscard]]
uint32_t getHeight() const; uint32_t getHeight() const;
[[nodiscard]]
uint32_t getDepth() const;
[[nodiscard]] [[nodiscard]]
vk::ImageLayout getLayout() const; vk::ImageLayout getLayout() const;
void switchLayout(vk::ImageLayout newLayout); void switchLayout(vk::ImageLayout newLayout);
void fill(void* data, size_t size = SIZE_MAX);
private: private:
ImageManager* const m_manager; ImageManager* const m_manager;
const uint64_t m_handle_id; const ImageHandle m_handle;
const vk::Format m_format;
const uint32_t m_width; const uint32_t m_width;
const uint32_t m_height; const uint32_t m_height;
const uint32_t m_depth;
vk::ImageLayout m_layout; vk::ImageLayout m_layout;
Image(ImageManager* manager, uint64_t id, uint32_t width, uint32_t height); Image(ImageManager* manager, const ImageHandle& handle, vk::Format format, uint32_t width, uint32_t height, uint32_t depth);
}; };
} }
...@@ -194,6 +194,18 @@ namespace vkcv { ...@@ -194,6 +194,18 @@ namespace vkcv {
return buffer.m_handle; return buffer.m_handle;
} }
size_t BufferManager::getBufferSize(const BufferHandle &handle) const {
const uint64_t id = handle.getId();
if (id >= m_buffers.size()) {
return 0;
}
auto& buffer = m_buffers[id];
return buffer.m_size;
}
vk::DeviceMemory BufferManager::getDeviceMemory(const BufferHandle& handle) const { vk::DeviceMemory BufferManager::getDeviceMemory(const BufferHandle& handle) const {
const uint64_t id = handle.getId(); const uint64_t id = handle.getId();
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
#include "PassManager.hpp" #include "PassManager.hpp"
#include "PipelineManager.hpp" #include "PipelineManager.hpp"
#include "vkcv/BufferManager.hpp" #include "vkcv/BufferManager.hpp"
#include "vkcv/ImageManager.hpp" #include "ImageManager.hpp"
#include "DescriptorManager.hpp" #include "DescriptorManager.hpp"
#include "Surface.hpp" #include "Surface.hpp"
#include "ImageLayoutTransitions.hpp" #include "ImageLayoutTransitions.hpp"
...@@ -96,14 +96,14 @@ namespace vkcv ...@@ -96,14 +96,14 @@ namespace vkcv
m_PipelineManager{std::make_unique<PipelineManager>(m_Context.m_Device)}, m_PipelineManager{std::make_unique<PipelineManager>(m_Context.m_Device)},
m_DescriptorManager(std::make_unique<DescriptorManager>(m_Context.m_Device)), m_DescriptorManager(std::make_unique<DescriptorManager>(m_Context.m_Device)),
m_BufferManager{std::unique_ptr<BufferManager>(new BufferManager())}, m_BufferManager{std::unique_ptr<BufferManager>(new BufferManager())},
m_ImageManager{std::unique_ptr<ImageManager>(new ImageManager())}, m_ImageManager{std::unique_ptr<ImageManager>(new ImageManager(*m_BufferManager))},
m_CommandResources(commandResources), m_CommandResources(commandResources),
m_SyncResources(syncResources) m_SyncResources(syncResources)
{ {
m_BufferManager->m_core = this; m_BufferManager->m_core = this;
m_BufferManager->init(); m_BufferManager->init();
m_ImageManager->m_core = this;
m_ImageManager->init(m_BufferManager.get()); m_ImageManager->m_core = this;
} }
Core::~Core() noexcept { Core::~Core() noexcept {
......
...@@ -4,13 +4,17 @@ ...@@ -4,13 +4,17 @@
* @brief class for image handles * @brief class for image handles
*/ */
#include "vkcv/Image.hpp" #include "vkcv/Image.hpp"
#include "vkcv/ImageManager.hpp" #include "ImageManager.hpp"
namespace vkcv{ namespace vkcv{
Image Image::create(ImageManager* manager, uint32_t width, uint32_t height) Image Image::create(ImageManager* manager, vk::Format format, uint32_t width, uint32_t height, uint32_t depth)
{ {
return Image(manager, manager->createImage(width, height), width, height); return Image(manager, manager->createImage(width, height, depth, format), format, width, height, depth);
}
vk::Format Image::getFormat() const {
return m_format;
} }
uint32_t Image::getWidth() const { uint32_t Image::getWidth() const {
...@@ -21,21 +25,32 @@ namespace vkcv{ ...@@ -21,21 +25,32 @@ namespace vkcv{
return m_height; return m_height;
} }
uint32_t Image::getDepth() const {
return m_depth;
}
vk::ImageLayout Image::getLayout() const { vk::ImageLayout Image::getLayout() const {
return m_layout; return m_layout;
} }
void Image::switchLayout(vk::ImageLayout newLayout) void Image::switchLayout(vk::ImageLayout newLayout)
{ {
m_manager->switchImageLayout(m_handle_id, m_layout, newLayout); m_manager->switchImageLayout(m_handle, m_layout, newLayout);
m_layout = newLayout; m_layout = newLayout;
} }
Image::Image(ImageManager* manager, uint64_t id, uint32_t width, uint32_t height) : void Image::fill(void *data, size_t size) {
m_manager->fillImage(m_handle, data, size);
}
Image::Image(ImageManager* manager, const ImageHandle& handle,
vk::Format format, uint32_t width, uint32_t height, uint32_t depth) :
m_manager(manager), m_manager(manager),
m_handle_id(id), m_handle(handle),
m_format(format),
m_width(width), m_width(width),
m_height(height), m_height(height),
m_depth(depth),
m_layout(vk::ImageLayout::eUndefined) m_layout(vk::ImageLayout::eUndefined)
{ {
} }
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* @file vkcv/ImageManager.cpp * @file vkcv/ImageManager.cpp
* @brief class creating and managing images * @brief class creating and managing images
*/ */
#include "vkcv/ImageManager.hpp" #include "ImageManager.hpp"
#include "vkcv/Core.hpp" #include "vkcv/Core.hpp"
namespace vkcv { namespace vkcv {
...@@ -33,34 +33,24 @@ namespace vkcv { ...@@ -33,34 +33,24 @@ namespace vkcv {
// failed to find memory type // failed to find memory type
return -1; 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 : ImageManager::ImageManager(BufferManager& bufferManager) noexcept :
m_core(nullptr), m_images() m_core(nullptr), m_bufferManager(bufferManager), m_images()
{ {
} }
ImageManager::~ImageManager() noexcept { ImageManager::~ImageManager() noexcept {
for (size_t id = 0; id < m_images.size(); id++) { for (uint64_t id = 0; id < m_images.size(); id++) {
destroyImage(id); destroyImage(ImageHandle(id));
} }
} }
uint64_t ImageManager::createImage(uint32_t width, uint32_t height) ImageHandle ImageManager::createImage(uint32_t width, uint32_t height, uint32_t depth, vk::Format format)
{ {
vk::ImageCreateFlags createFlags; vk::ImageCreateFlags createFlags;
vk::ImageUsageFlags imageUsageFlags = (vk::ImageUsageFlagBits::eSampled | vk::ImageUsageFlagBits::eTransferDst); vk::ImageUsageFlags imageUsageFlags = (vk::ImageUsageFlagBits::eSampled | vk::ImageUsageFlagBits::eTransferDst);
vk::Format format = vk::Format::eR8G8B8A8Unorm; // TODO format = vk::Format::eR8G8B8A8Unorm; // TODO
uint32_t channels = 3; // TODO
const vk::Device& device = m_core->getContext().getDevice(); const vk::Device& device = m_core->getContext().getDevice();
...@@ -96,11 +86,11 @@ namespace vkcv { ...@@ -96,11 +86,11 @@ namespace vkcv {
device.bindImageMemory(image, memory, 0); device.bindImageMemory(image, memory, 0);
const uint64_t id = m_images.size(); const uint64_t id = m_images.size();
m_images.push_back({ image, memory, width * height * channels }); m_images.push_back({ image, memory, width, height, depth, format });
return id; return ImageHandle(id);
} }
void ImageManager::switchImageLayout(uint64_t id, vk::ImageLayout oldLayout, vk::ImageLayout newLayout) { void ImageManager::switchImageLayout(const ImageHandle& handle, vk::ImageLayout oldLayout, vk::ImageLayout newLayout) {
//alternativly we could use switch case for every variable to set //alternativly we could use switch case for every variable to set
vk::AccessFlags sourceAccessMask; vk::AccessFlags sourceAccessMask;
vk::PipelineStageFlags sourceStage; vk::PipelineStageFlags sourceStage;
...@@ -125,14 +115,20 @@ namespace vkcv { ...@@ -125,14 +115,20 @@ namespace vkcv {
} }
vk::ImageSubresourceRange imageSubresourceRange( vk::ImageSubresourceRange imageSubresourceRange(
vk::ImageAspectFlagBits::eColor , vk::ImageAspectFlagBits::eColor,
0, 0,
1, 1,
0, 0,
1 1
); );
ImageManager::Image image = m_images[id]; const uint64_t id = handle.getId();
if (id >= m_images.size()) {
return;
}
auto& image = m_images[id];
vk::ImageMemoryBarrier imageMemoryBarrier( vk::ImageMemoryBarrier imageMemoryBarrier(
sourceAccessMask, sourceAccessMask,
...@@ -163,121 +159,86 @@ namespace vkcv { ...@@ -163,121 +159,86 @@ namespace vkcv {
nullptr nullptr
); );
} }
struct ImageStagingStepInfo { void ImageManager::fillImage(const ImageHandle& handle, void* data, size_t size)
void* data;
size_t size;
uint32_t width;
uint32_t height;
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)
{ {
if (size == 0) { if (size == 0) {
size = SIZE_MAX; size = SIZE_MAX;
} }
const uint64_t id = handle.getId();
if (id >= m_images.size()) { if (id >= m_images.size()) {
return; return;
} }
auto& image = m_images[id]; auto& image = m_images[id];
switchImageLayout(id, vk::ImageLayout::eUndefined, vk::ImageLayout::eTransferDstOptimal); switchImageLayout(
handle,
vk::ImageLayout::eUndefined,
vk::ImageLayout::eTransferDstOptimal
);
const size_t max_size = std::min(size, image.m_size); uint32_t channels = 3; // TODO
const size_t image_size = (
image.m_width * image.m_height * image.m_depth * channels * sizeof(char)
);
//const size_t max_size = std::min(size, image.m_size - offset); const size_t max_size = std::min(size, image_size);
ImageStagingStepInfo info;
info.data = data; BufferHandle bufferHandle = m_bufferManager.createBuffer(
info.size = max_size; BufferType::STAGING, max_size, BufferMemoryType::HOST_VISIBLE
);
info.image = image.m_handle;
info.stagingBuffer = m_stagingBuffer; m_bufferManager.fillBuffer(bufferHandle, data, max_size, 0);
info.stagingMemory = m_stagingMemory;
vk::Buffer stagingBuffer = m_bufferManager.getBuffer(bufferHandle);
const vk::MemoryRequirements stagingRequirements = m_core->getContext().getDevice().getBufferMemoryRequirements(m_stagingBuffer);
info.stagingLimit = stagingRequirements.size; //TODO SubmitInfo submitInfo;
info.stagingPosition = 0; submitInfo.queueType = QueueType::Transfer;
copyStagingToImage(m_core, info); m_core->submitCommands(
switchImageLayout(id, vk::ImageLayout::eTransferDstOptimal, vk::ImageLayout::eShaderReadOnlyOptimal); submitInfo,
[&image, &stagingBuffer](const vk::CommandBuffer& commandBuffer) {
const vk::BufferImageCopy region (
0,
0,
0,
vk::ImageSubresourceLayers(
vk::ImageAspectFlagBits::eColor,
0,
0,
1
),
vk::Offset3D(0, 0, 0),
vk::Extent3D(image.m_width, image.m_height, image.m_depth)
);
commandBuffer.copyBufferToImage(
stagingBuffer,
image.m_handle,
vk::ImageLayout::eTransferDstOptimal,
1,
&region
);
},
[&]() {
switchImageLayout(
handle,
vk::ImageLayout::eTransferDstOptimal,
vk::ImageLayout::eShaderReadOnlyOptimal
);
m_bufferManager.destroyBuffer(bufferHandle);
}
);
} }
void ImageManager::destroyImage(uint64_t id) void ImageManager::destroyImage(const ImageHandle& handle)
{ {
const uint64_t id = handle.getId();
if (id >= m_images.size()) { if (id >= m_images.size()) {
return; return;
} }
......
...@@ -7,9 +7,11 @@ ...@@ -7,9 +7,11 @@
#include <vector> #include <vector>
#include <vulkan/vulkan.hpp> #include <vulkan/vulkan.hpp>
#include "vkcv/BufferManager.hpp"
#include "vkcv/Handles.hpp"
namespace vkcv { namespace vkcv {
class Core;
class BufferManager;
class ImageManager class ImageManager
{ {
friend class Core; friend class Core;
...@@ -18,16 +20,19 @@ namespace vkcv { ...@@ -18,16 +20,19 @@ namespace vkcv {
{ {
vk::Image m_handle; vk::Image m_handle;
vk::DeviceMemory m_memory; vk::DeviceMemory m_memory;
size_t m_size; uint32_t m_width = 0;
uint32_t m_height = 0;
uint32_t m_depth = 0;
vk::Format m_format;
}; };
Core* m_core; Core* m_core;
vk::Buffer m_stagingBuffer; BufferManager& m_bufferManager;
vk::DeviceMemory m_stagingMemory;
std::vector<Image> m_images; std::vector<Image> m_images;
void init(BufferManager* bufferManager);
ImageManager() noexcept; ImageManager(BufferManager& bufferManager) noexcept;
public: public:
~ImageManager() noexcept; ~ImageManager() noexcept;
ImageManager(ImageManager&& other) = delete; ImageManager(ImageManager&& other) = delete;
...@@ -36,17 +41,18 @@ namespace vkcv { ...@@ -36,17 +41,18 @@ namespace vkcv {
ImageManager& operator=(ImageManager&& other) = delete; ImageManager& operator=(ImageManager&& other) = delete;
ImageManager& operator=(const ImageManager& other) = delete; ImageManager& operator=(const ImageManager& other) = delete;
void switchImageLayout(uint64_t id, vk::ImageLayout oldLayout, vk::ImageLayout newLayout); void switchImageLayout(const ImageHandle& handle, vk::ImageLayout oldLayout, vk::ImageLayout newLayout);
void fillImage(uint64_t id, void* data, size_t size); void fillImage(const ImageHandle& handle, void* data, size_t size);
uint64_t createImage(uint32_t width, uint32_t height); ImageHandle createImage(uint32_t width, uint32_t height, uint32_t depth, vk::Format format);
/** /**
* Destroys and deallocates image represented by a given * Destroys and deallocates image represented by a given
* buffer handle id. * buffer handle.
* *
* @param id Buffer handle id * @param handle Image handle
*/ */
void destroyImage(uint64_t id); void destroyImage(const ImageHandle& handle);
}; };
} }
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment