Skip to content
Snippets Groups Projects
Commit 07f72bd7 authored by Alexander Gauggel's avatar Alexander Gauggel
Browse files

Merge branch '22-resource-management' into 'develop'

Resolve "Resource Management"

Closes #22

See merge request !18
parents 81bfa2d9 73b27493
No related branches found
No related tags found
1 merge request!18Resolve "Resource Management"
Pipeline #24987 passed
......@@ -19,6 +19,9 @@ set(vkcv_sources
${vkcv_include}/vkcv/Window.hpp
${vkcv_source}/vkcv/Window.cpp
${vkcv_include}/vkcv/Buffer.hpp
${vkcv_source}/vkcv/Buffer.cpp
${vkcv_include}/vkcv/SwapChain.hpp
${vkcv_source}/vkcv/SwapChain.cpp
......
#pragma once
/**
* @authors Lars Hoerttrich
* @file include/vkcv/Buffer.hpp
* @brief template buffer class, template for type security, implemented here because template classes can't be written in .cpp
*/
#include "vkcv/Handles.hpp"
#include <vulkan/vulkan.hpp>
#include "vkcv/Context.hpp"
namespace vkcv {
//Enum of buffertypes
enum BufferType { VERTEX, UNIFORM, STORAGE };
//Functions outsourced to Buffer.cpp file:
void outsourcedDestructor(vk::Device device, vk::DeviceMemory bufferMemory, vk::Buffer buffer);
vk::Buffer outsourcedCreateBuffer(vk::Device device, BufferType type, size_t size);
vk::DeviceMemory outsourcedAllocateMemory(vk::Device device, vk::PhysicalDevice physicalDevice, vk::MemoryRequirements memoryRequirements);
template<typename T>
class Buffer {
public:
//future bufferHandle struct
struct Handle {
uint64_t id;
};
// explicit destruction of default constructor
Buffer<T>() = delete;
// is never called directly
~Buffer<T>() noexcept {
outsourcedDestructor(m_Device, m_BufferMemory, m_Buffer);
}
Buffer<T>(const Buffer<T>& other) = delete; // copy-ctor
Buffer<T>(Buffer<T>&& other) noexcept :
m_Buffer(other.m_Buffer),
m_BufferMemory(other.m_BufferMemory),
m_Device(other.m_Device),
m_Type(other.m_Type),
m_Size(other.m_Size),
m_DataP(other.m_DataP)
{
other.m_Buffer = nullptr;
other.m_BufferMemory = nullptr;
other.m_Device = nullptr;
other.m_Type = vkcv::VERTEX; //set to 0
other.m_Size = 0;
other.m_DataP = nullptr;
} // move-ctor
Buffer<T>& operator=(const Buffer<T>& other) = delete; // copy assignment
Buffer<T>& operator=(Buffer<T>&& other) noexcept {
m_Buffer = other.m_Buffer;
m_BufferMemory = other.m_BufferMemory;
m_Device = other.m_Device;
m_Type = other.m_Type;
m_Size = other.m_Size;
m_DataP = other.m_DataP;
other.m_Buffer = nullptr;
other.m_BufferMemory = nullptr;
other.m_Device = nullptr;
other.m_Type = vkcv::VERTEX; //set to 0
other.m_Size = 0;
other.m_DataP = nullptr;
}// move assignment
BufferType getType() { return m_Type; };
size_t getSize() { return m_Size; };
/**
* Maps this buffers Memory, fills this buffer with @p data of type T and count @p count
* unmaps afterwards.
* @p data Pointer to data
* @p count Amount of data of type T
*/
// TODO: we will probably need staging-buffer here later (possible add in BufferManager later?)
void fill(T* data, size_t count) {
const vk::MemoryRequirements requirements = m_Device.getBufferMemoryRequirements(m_Buffer);
// TODO: check if mapped already
m_DataP = static_cast<uint8_t*>(m_Device.mapMemory(m_BufferMemory, 0, requirements.size));
memcpy(m_DataP, data, sizeof(T) * count);
m_Device.unmapMemory(m_BufferMemory);
};
T* map() {
const vk::MemoryRequirements requirements = m_Device.getBufferMemoryRequirements(m_Buffer);
m_DataP = static_cast<uint8_t*>(m_Device.mapMemory(m_BufferMemory, 0, requirements.size));
// TODO: make sure to unmap before deallocation
return reinterpret_cast<T*>(m_DataP);
};
void unmap() {
m_Device.unmapMemory(m_BufferMemory);
// TODO: mark m_DataP as invalid?
};
/**
* * Create function of #Buffer requires a @p device, a @p physicalDevice, a @p buffer type and a @p size. *
* @param device Vulkan-Device
* @param physicalDevice Vulkan-PhysicalDevice
* @param type Enum type of possible vkcv::BufferType
* @param Size size of data
*/
static Buffer<T> create(vk::Device device, vk::PhysicalDevice physicalDevice, BufferType type, size_t size) {
vk::Buffer buffer = nullptr;
buffer = outsourcedCreateBuffer(device, type, sizeof(T) * size);
if (!buffer) {
//TODO: potential issue
}
//get requirements for allocation
const vk::MemoryRequirements requirements = device.getBufferMemoryRequirements(buffer);
vk::DeviceMemory memory= outsourcedAllocateMemory(device, physicalDevice, requirements);
if (!memory) {
//TODO: other potential issue
}
device.bindBufferMemory(buffer, memory, 0);
return Buffer<T>(buffer, memory, device, type, size);
}
private:
vk::Buffer m_Buffer;
vk::DeviceMemory m_BufferMemory;
vk::Device m_Device;
BufferType m_Type;
size_t m_Size=0;
uint8_t* m_DataP;
/**
* * Constructor of #Buffer requires a @p buffer, a @p memory, @p device, @ requirement, a @p buffer type and a @p size.
* @param buffer Vulkan-Buffer
* @param memory Vulkan-DeviceMemory
* @param device Vulkan-Device
* @param requirement Vulkan-MemoryRequirements
* @param type Enum type of possible vkcv::BufferType
* @param Size size of data
*/
Buffer<T>(vk::Buffer buffer, vk::DeviceMemory memory, vk::Device device, BufferType type, size_t size) :
m_Buffer(buffer),
m_BufferMemory(memory),
m_Device(device),
m_Type(type),
m_Size(size),
m_DataP(nullptr)
{}
};
}
......@@ -12,6 +12,7 @@
#include "vkcv/Window.hpp"
#include "vkcv/PassConfig.hpp"
#include "vkcv/Handles.hpp"
#include "vkcv/Buffer.hpp"
#include "vkcv/PipelineConfig.hpp"
#include "CommandResources.hpp"
#include "SyncResources.hpp"
......@@ -19,9 +20,6 @@
namespace vkcv
{
// TODO:
class Buffer;
// forward declarations
class PassManager;
class PipelineManager;
......@@ -138,8 +136,16 @@ namespace vkcv
[[nodiscard]]
PassHandle createPass(const PassConfig &config);
// TODO:
BufferHandle createBuffer(const Buffer &buf);
/**
* Creates a #Buffer with data-type T and @p bufferType
* @param bufferType Type of Buffer created
* @param size Amount of Data of type T
* return Buffer-Object
*/
template<typename T>
Buffer<T> createBuffer(vkcv::BufferType bufferType,size_t size) {
return Buffer<T>::create(m_Context.getDevice(), m_Context.getPhysicalDevice(), bufferType, size);
}
/**
* @brief start recording command buffers and increment frame index
......
......@@ -28,6 +28,17 @@ int main(int argc, const char** argv) {
const vk::Instance& instance = context.getInstance();
const vk::PhysicalDevice& physicalDevice = context.getPhysicalDevice();
const vk::Device& device = context.getDevice();
struct vec3 {
float x, y, z;
};
auto buffer = core.createBuffer<vec3>(vkcv::BufferType::VERTEX, 3);
vec3* m = buffer.map();
m[0] = { 0, 0, 0 };
m[0] = { 0, 0, 0 };
m[0] = { 0, 0, 0 };
std::cout << "Physical device: " << physicalDevice.getProperties().deviceName << std::endl;
......
/**
* @authors Lars Hoerttrich
* @file src/vkcv/Buffer.cpp
* @brief Implementation of template buffer class, template for type security
*/
#include"vkcv/Buffer.hpp"
namespace vkcv {
/**
* @brief searches memory type index for buffer allocation, inspired by vulkan tutorial and "https://github.com/KhronosGroup/Vulkan-Hpp/blob/master/samples/utils/utils.hpp"
* @param physicalMemoryProperties Memory Properties of physical device
* @param typeBits
* @param requirements Property flags that are required
* @return memory type index for Buffer
*/
uint32_t searchMemoryType(vk::PhysicalDeviceMemoryProperties const& physicalMemoryProperties, uint32_t typeBits, vk::MemoryPropertyFlags requirements) {
uint32_t memoryTypeIndex = uint32_t(0);
for (uint32_t i = 0; i < physicalMemoryProperties.memoryTypeCount; i++)
{
if ((typeBits & 1) &&
((physicalMemoryProperties.memoryTypes[i].propertyFlags & requirements) == requirements))
{
memoryTypeIndex = i;
break;
}
typeBits >>= 1;
}
return memoryTypeIndex;
}
void outsourcedDestructor(vk::Device device, vk::DeviceMemory bufferMemory, vk::Buffer buffer)
{
if (device) {
device.freeMemory(bufferMemory);
device.destroyBuffer(buffer);
}
}
vk::Buffer outsourcedCreateBuffer(vk::Device device, BufferType type, size_t size)
{
switch (type) {
case VERTEX: {
//create vertex buffer
return device.createBuffer(vk::BufferCreateInfo(vk::BufferCreateFlags(), size, vk::BufferUsageFlagBits::eVertexBuffer));
}
default: {
// TODO: maybe an issue
}
}
return vk::Buffer(); //should never be reached
}
vk::DeviceMemory outsourcedAllocateMemory(vk::Device device, vk::PhysicalDevice physicalDevice, vk::MemoryRequirements memoryRequirements)
{
//find Memory Type
uint32_t memoryType = searchMemoryType(physicalDevice.getMemoryProperties(), memoryRequirements.memoryTypeBits, vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent);
return device.allocateMemory(vk::MemoryAllocateInfo(memoryRequirements.size, memoryType));
}
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment