Commit 79eacc65 authored by Lukas Tietze's avatar Lukas Tietze

MappedMemory-Klasse

parent 2dff0297
#pragma once
#include "GlfwAndVulkan.hpp"
#include "Util/TypeTraits.hpp"
namespace lib
{
/**
* @brief Forward-declaration des Kontexts.
*/
class CgContext;
/**
* @brief Stellt einen Bereich Speicher dar der zum Host gemapped wurde.
* Dies folgt dem RAII-Prinzip, der Konstruktor mapped den Speicher, der Destruktor un-mapped ihn.
*/
class MappedMemory
{
private:
void *mappedMemory;
vk::DeviceMemory deviceMemory;
CgContext *context;
public:
/**
* @brief Initialisiert eine neue Instanz der Mapped Memory Klasse und mapped den Speicher.
*
* @param context Der zu nutzende CgContext.
* @param memory Der Speicher aus dem gemapped werden soll.
* @param offset Das Offset ab dem gemapped werden soll in Byte.
* @param size Die Länge des zu mappenden Speichers in Byte.
*/
MappedMemory(CgContext *context, vk::DeviceMemory memory, vk::DeviceSize offset, vk::DeviceSize size);
/**
* @brief Gelöschter Copy-Constructor.
*/
MappedMemory(const MappedMemory &copy) = delete;
/**
* @brief Move-Constructor.
*
* @param move Das Objekt von dem Ressourcen bewegt werden sollen.
*/
MappedMemory(MappedMemory &&move);
/**
* @brief Zerstört das Mapped Memory Objekt und unmapped den Speicher.
*/
~MappedMemory();
/**
* @brief Überladung von Write für Container, die iterierbar sind, aber keinen zusammenhängenden
* Speicher darstellen. Delegiert an WriteRange(std::cbegin(t), std::cend(t)).
*
* @tparam T Der Container-Typ.
* @param t Der Container.
* @param offset Das Offset ab dem geschrieben werden soll in Byte.
*/
template <typename T, std::enable_if_t<
lib::is_iterable_v<T> && !lib::is_contiguos_memory_v<T>,
int> = 0>
void Write(const T &t, vk::DeviceSize offset = 0)
{
this->WriteRange(std::begin(t), std::end(t), offset);
}
/**
* @brief Überladung von Write für Container, die iterierbar sind und einen zusammenhängenden
* Speicher darstellen. Delegiert zu Write(t.data(), t.size(), offset)
*
* @tparam T Der Container-Typ.
* @param t Der Container.
* @param offset Das Offset ab dem geschrieben werden soll in Byte.
*/
template <typename T, std::enable_if_t<
lib::is_iterable_v<T> && lib::is_contiguos_memory_v<T>,
int> = 0>
void Write(const T &t, vk::DeviceSize offset)
{
this->Write(static_cast<void *>(t.data()), t.size(), offset);
}
/**
* @brief Überladung von Write für Objekte, die keine Container darstellen.
*
* @tparam T Der Container-Typ.
* @param t Der Container.
* @param offset Das Offset ab dem geschrieben werden soll in Byte.
*/
template <typename T, std::enable_if_t<
!lib::is_iterable_v<T>,
int> = 0>
void Write(const T &t, vk::DeviceSize offset)
{
this->Write(static_cast<void *>(&t), sizeof(T), offset);
}
/**
* @brief Schreibt Daten in den gemappedten Speicher.
*
* @param data Pointer zu den zu schreibenden Daten.
* @param size Die Größe der Daten in Byte.
* @param offset Das Offset ab dem geschrieben werden soll in Byte.
*/
void Write(const void *data, vk::DeviceSize size, vk::DeviceSize offset = 0);
/**
* @brief Schreibt den Bereich [start, end) von Elementen, der durch Iteratoren besschrieben wird.
*
* @tparam TIterator Der Typ der Iteratoren.
* @param start Iterator zum ersten Element.
* @param end Iterator nach dem letzten Element.
* @param offset Das Offset ab dem geschrieben werden soll in Byte.
*/
template <typename TIterator>
void WriteRange(TIterator start, TIterator end, vk::DeviceSize offset = 0)
{
auto itemSize = sizeof(decltype(*start));
for (; start != end; ++start)
{
this->Write(*start, offset);
offset += itemSize;
}
}
/**
* @brief Gelöschter Copy-Assignment-Operator.
*/
MappedMemory &operator=(const MappedMemory &copy) = delete;
/**
* @brief Move-Assignment-operator.
*
* @param move Das Objekt von dem Ressourcen bewegt werden sollen.
* @return MappedMemory& Referenz zur aktuellen Instanz (*this).
*/
MappedMemory &operator=(MappedMemory &&move);
friend void swap(MappedMemory &a, MappedMemory &b);
};
/**
* @brief Tauscht den Inhalt zweier Objekte miteinander.
*
* @param a Das erste Objekt.
* @param b Das zweite Objekt.
*/
void swap(MappedMemory &a, MappedMemory &b);
} // namespace lib
#include "VkUtil/Memory/MappedMemory.hpp"
#include "Core/CgContext.hpp"
lib::MappedMemory::MappedMemory(CgContext *context, vk::DeviceMemory memory, vk::DeviceSize offset, vk::DeviceSize size)
: context(context)
{
this->mappedMemory = this->context->GetLogicalDevice().mapMemory(memory, offset, size);
}
lib::MappedMemory::MappedMemory(MappedMemory &&move)
{
swap(*this, move);
}
lib::MappedMemory::~MappedMemory()
{
this->context->GetLogicalDevice().unmapMemory(this->deviceMemory);
}
void lib::MappedMemory::Write(const void *data, vk::DeviceSize size, vk::DeviceSize offset)
{
memcpy(static_cast<void *>(static_cast<uint8_t *>(this->mappedMemory) + offset), data, size);
}
lib::MappedMemory &lib::MappedMemory::operator=(MappedMemory &&move)
{
if (this != &move)
{
swap(*this, move);
}
return *this;
}
void lib::swap(lib::MappedMemory &a, lib::MappedMemory &b)
{
using std::swap;
swap(a.context, b.context);
swap(a.deviceMemory, b.deviceMemory);
swap(a.mappedMemory, b.mappedMemory);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment