...
 
Commits (9)
...@@ -75,6 +75,10 @@ add_library( ...@@ -75,6 +75,10 @@ add_library(
src/Lib/src/VkUtil/OneTimeCommandBuffer.cpp src/Lib/src/VkUtil/OneTimeCommandBuffer.cpp
src/Lib/src/VkUtil/StbImageImpl.cpp src/Lib/src/VkUtil/StbImageImpl.cpp
src/Lib/src/VkUtil/Memory/MappedMemory.cpp
src/Lib/src/VkUtil/Memory/Memory.cpp
src/Lib/src/VkUtil/Memory/OutOfMemoryException.cpp
src/submodules/dearImGui/imgui_demo.cpp src/submodules/dearImGui/imgui_demo.cpp
src/submodules/dearImGui/imgui_draw.cpp src/submodules/dearImGui/imgui_draw.cpp
src/submodules/dearImGui/imgui_widgets.cpp src/submodules/dearImGui/imgui_widgets.cpp
......
@book{Haines2019, @book{Haines2019,
title = {Ray Tracing Gems}, title = {Ray Tracing Gems},
editor = {Eric Haines and Tomas Akenine-M\"oller}, editor = {Eric Haines and Tomas Akenine-M\"oller},
publisher = {Apress}, publisher = {Apress},
year = {2019}, year = {2019},
note ={\url{http://raytracinggems.com}}, note ={\url{http://raytracinggems.com}},
} }
\ No newline at end of file
@article{Whitted1980
author = {Whitted, Turner},
title = {An Improved Illumination Model for Shaded Display},
year = {1980},
issue_date = {June 1980},
publisher = {Association for Computing Machinery},
address = {New York, NY, USA},
volume = {23},
number = {6},
issn = {0001-0782},
url = {https://doi.org/10.1145/358876.358882},
doi = {10.1145/358876.358882},
journal = {Commun. ACM},
month = jun,
pages = {343–349},
numpages = {7},
keywords = {visible surface algorithms, computer graphics, raster displays, shading, computer animation}
}
@inproceedings{Appel1968,
author = {Appel, Arthur},
title = {Some Techniques for Shading Machine Renderings of Solids},
year = {1968},
isbn = {9781450378970},
publisher = {Association for Computing Machinery},
address = {New York, NY, USA},
url = {https://doi.org/10.1145/1468075.1468082},
doi = {10.1145/1468075.1468082},
booktitle = {Proceedings of the April 30--May 2, 1968, Spring Joint Computer Conference},
pages = {37–45},
numpages = {9},
location = {Atlantic City, New Jersey},
series = {AFIPS ’68 (Spring)}
}
@inproceedings{Balazs2009,
title={Real-time Volumetric Lighting in Participating Media},
author={Bal{\'a}zs T{\'o}th and Tam{\'a}s Umenhoffer},
booktitle={Eurographics},
year={2009}
}
@inproceedings{Frhstck2011CausticsL,
title={Caustics , Light Shafts , God Rays},
author={Anna Fr{\"u}hst{\"u}ck and Stefanie Prast},
year={2011}
}
@article{Jambusaria2014GodRI,
title={God Rays in Modern Gaming},
author={Utsav Jambusaria and Neerja Katwala and Khushali Deulkar},
journal={International Journal of Computer Applications},
year={2014},
volume={108},
pages={31-33}
}
@article{Papadopoulos2010,
author = {Papadopoulos, Charilaos and Papaioannou, Georgios},
year = {2010},
month = {08},
pages = {},
title = {Realistic Real-time Underwater Caustics and Godrays},
journal = {19th International Conference on Computer Graphics and Vision, GraphiCon'2009 - Conference Proceedings}
}
@inproceedings{Wyman2008,
author = {Wyman, Chris and Ramsey, Shaun},
year = {2008},
month = {09},
pages = {87 - 92},
title = {Interactive Volumetric Shadows in Participating Media with Single-Scattering},
isbn = {978-1-4244-2741-3},
journal = {RT'08 - IEEE/EG Symposium on Interactive Ray Tracing 2008, Proceedings},
doi = {10.1109/RT.2008.4634627}
}
@inproceedings{10.1145/37401.37437,
author = {Nishita, Tomoyuki and Miyawaki, Yasuhiro and Nakamae, Eihachiro},
title = {A Shading Model for Atmospheric Scattering Considering Luminous Intensity Distribution of Light Sources},
year = {1987},
isbn = {0897912276},
publisher = {Association for Computing Machinery},
address = {New York, NY, USA},
url = {https://doi.org/10.1145/37401.37437},
doi = {10.1145/37401.37437},
booktitle = {Proceedings of the 14th Annual Conference on Computer Graphics and Interactive Techniques},
pages = {303–310},
numpages = {8},
series = {SIGGRAPH ’87}
}
@article{Nishita1987
author = {Nishita, Tomoyuki and Miyawaki, Yasuhiro and Nakamae, Eihachiro},
title = {A Shading Model for Atmospheric Scattering Considering Luminous Intensity Distribution of Light Sources},
year = {1987},
issue_date = {July 1987},
publisher = {Association for Computing Machinery},
address = {New York, NY, USA},
volume = {21},
number = {4},
issn = {0097-8930},
url = {https://doi.org/10.1145/37402.37437},
doi = {10.1145/37402.37437},
journal = {SIGGRAPH Comput. Graph.},
month = aug,
pages = {303–310},
numpages = {8}
}
@inproceedings{Kajiya1984,
author = {Kajiya, James T. and Von Herzen, Brian P},
title = {Ray Tracing Volume Densities},
year = {1984},
isbn = {0897911385},
publisher = {Association for Computing Machinery},
address = {New York, NY, USA},
url = {https://doi.org/10.1145/800031.808594},
doi = {10.1145/800031.808594},
booktitle = {Proceedings of the 11th Annual Conference on Computer Graphics and Interactive Techniques},
pages = {165–174},
numpages = {10},
keywords = {Radiative transport, Computer graphics, Raster graphics, Clouds, Stochastic modeling, Simulation of natural phenomena, Light scattering, Particle systems, Ray tracing},
series = {SIGGRAPH ’84}
}
@inproceedings{Jensen1998,
author = {Jensen, Henrik Wann and Christensen, Per H.},
title = {Efficient Simulation of Light Transport in Scenes with Participating Media Using Photon Maps},
year = {1998},
isbn = {0897919998},
publisher = {Association for Computing Machinery},
address = {New York, NY, USA},
url = {https://doi.org/10.1145/280814.280925},
doi = {10.1145/280814.280925},
booktitle = {Proceedings of the 25th Annual Conference on Computer Graphics and Interactive Techniques},
pages = {311–320},
numpages = {10},
keywords = {nonhomogeneous media, photon map, volume caustics, photon tracing, photo-realism, global illumination, anisotropic scattering, rendering, ray marching, multiple scattering, participating media, light transport},
series = {SIGGRAPH ’98}
}
@article{Iwasaki2002,
author = {Iwasaki, Kei and Dobashi, Yoshinori and Nishita, Tomoyuki},
year = {2002},
month = {12},
pages = {1-11},
title = {An Efficient Method for Rendering Underwater Optical Effects Using Graphics Hardware},
volume = {21},
journal = {Computer Graphics Forum},
doi = {10.1111/1467-8659.00628}
}
@inproceedings{Dobashi2002,
author = {Dobashi, Yoshinori and Yamamoto, Tsuyoshi and Nishita, Tomoyuki},
title = {Interactive Rendering of Atmospheric Scattering Effects Using Graphics Hardware},
year = {2002},
isbn = {1581135807},
publisher = {Eurographics Association},
address = {Goslar, DEU},
booktitle = {Proceedings of the ACM SIGGRAPH/EUROGRAPHICS Conference on Graphics Hardware},
pages = {99–107},
numpages = {9},
location = {Saarbrucken, Germany},
series = {HWWS ’02}
}
@INPROCEEDINGS{Zhou2007,
author = {K. {Zhou} and Q. {Hou} and M. {Gong} and J. {Snyder} and B. {Guo} and H. {Shum}},
booktitle={15th Pacific Conference on Computer Graphics and Applications (PG'07)},
title={Fogshop: Real-Time Design and Rendering of Inhomogeneous, Single-Scattering Media},
year={2007},
volume={},
number={},
pages={116-125},
}
@inproceedings{Hu2010,
author = {Hu, Wei and Dong, Zhao and Ihrke, Ivo and Grosch, Thorsten and Yuan, Guodong and Seidel, Hans-Peter},
year = {2010},
month = {02},
pages = {109-117},
title = {Interactive volume caustics in single-scattering media},
journal = {Proceedings of I3D 2010: The 2010 ACM SIGGRAPH Symposium on Interactive 3D Graphics and Games},
doi = {10.1145/1730804.1730822}
}
@inproceedings{Jensen1996,
author = {Jensen, Henrik Wann},
title = {Global Illumination Using Photon Maps},
year = {1996},
isbn = {3211828834},
publisher = {Springer-Verlag},
address = {Berlin, Heidelberg},
booktitle = {Proceedings of the Eurographics Workshop on Rendering Techniques ’96},
pages = {21–30},
numpages = {10},
keywords = {Monte Carlo, ray tracing, photon maps, global illumination},
location = {Porto, Portugal}
}
@inproceedings{Sun2008,
author = {Sun, Xin and Zhou, Kun and Stollnitz, Eric and Shi, Jiaoying and Guo, Baining},
title = {Interactive Relighting of Dynamic Refractive Objects},
year = {2008},
isbn = {9781450301121},
publisher = {Association for Computing Machinery},
address = {New York, NY, USA},
url = {https://doi.org/10.1145/1399504.1360634},
doi = {10.1145/1399504.1360634},
booktitle = {ACM SIGGRAPH 2008 Papers},
articleno = {35},
numpages = {9},
keywords = {refractive objects, photon tracing, ray tracing, interactive relighting},
location = {Los Angeles, California},
series = {SIGGRAPH ’08}
}
...@@ -17,8 +17,8 @@ ...@@ -17,8 +17,8 @@
#include "Util/GenericVertex.hpp" #include "Util/GenericVertex.hpp"
#include "Util/NameList.hpp" #include "Util/NameList.hpp"
#include "VkUtil/BottomLevelAccelerationStructure.hpp" #include "VkUtil/BottomLevelAccelerationStructure.hpp"
#include "VkUtil/Buffer.hpp" #include "VkUtil/Memory/Buffer.hpp"
#include "VkUtil/StagedBuffer.hpp" #include "VkUtil/Memory/StagedBuffer.hpp"
#include "VkUtil/OneTimeCommandBuffer.hpp" #include "VkUtil/OneTimeCommandBuffer.hpp"
#include "VkUtil/Shader.hpp" #include "VkUtil/Shader.hpp"
#include "VkUtil/TopLevelAccelerationStructure.hpp" #include "VkUtil/TopLevelAccelerationStructure.hpp"
......
#pragma once #pragma once
#include <exception> #include "Util/ExeptionBase.hpp"
#include <string> #include <string>
namespace lib namespace lib
{ {
/** /**
* @brief Stellt eine Ausnahme beim Initialisieren des Vulkan-Kerns dar. * @brief Stellt eine Ausnahme beim Initialisieren des Vulkan-Kerns dar.
* Wird primär genutzt um Ausnahmen in Folge von gescheiterten vkCreateXYZ-Aufrufen von anderen exceptions * Wird primär genutzt um Ausnahmen in Folge von gescheiterten vkCreateXYZ-Aufrufen von anderen exceptions
* zu unterscheiden, die nichts mit Vulkan zu tun haben. * zu unterscheiden, die nichts mit Vulkan zu tun haben.
*/ */
class CoreInitException final : public std::exception class CoreInitException final : public lib::ExceptionBase
{ {
public: public:
CoreInitException(const std::string &msg); CoreInitException(const std::string &msg);
}; CoreInitException(const char *msg);
};
} // namespace lib } // namespace lib
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
#include "VkUtil/RenderTarget.hpp" #include "VkUtil/RenderTarget.hpp"
#include "GlfwAndVulkan.hpp" #include "GlfwAndVulkan.hpp"
#include "VkUtil/StagedBuffer.hpp" #include "VkUtil/Memory/StagedBuffer.hpp"
namespace lib namespace lib
{ {
......
#pragma once #pragma once
#include <string> #include <string>
#include <exception>
#include "Util/ExeptionBase.hpp"
namespace lib namespace lib
{ {
/** /**
* @brief Exception die beim Laden eines Modells auftreten kann. * @brief Exception die beim Laden eines Modells auftreten kann.
*/ */
class ModelLoadException : public std::exception class ModelLoadException : public lib::ExceptionBase
{ {
public: public:
ModelLoadException(const std::string &reason, const std::string &path); ModelLoadException(const std::string &reason, const std::string &path);
......
#pragma once
#include <exception>
#include <string>
namespace lib
{
class ExceptionBase : public std::exception
{
private:
std::string message;
public:
ExceptionBase(std::string message);
ExceptionBase(const char *message);
const char *what() const noexcept override;
};
} // namespace lib
#pragma once
#include <type_traits>
#include <iterator>
namespace lib
{
/**
* @brief type trait um zu prüfen ob ein Typ ein Iterator ist.
*
* @tparam T Der zu prüfende Typ.
*/
template <typename T, typename = void>
struct is_iterator
{
static constexpr bool value = false;
};
/**
* @brief type trait um zu prüfen ob ein Typ ein Iterator ist.
*
* @tparam T Der zu prüfende Typ.
*/
template <typename T>
struct is_iterator<T, typename std::enable_if<!std::is_same<typename std::iterator_traits<T>::value_type, void>::value>::type>
{
static constexpr bool value = true;
};
/**
* @brief Kurzform von is_iterator<T>::value.
*
* @tparam T Der zu prüfende Typ.
*/
template <typename T>
static constexpr auto is_iterator_v = lib::is_iterator<T>::value;
/**
* @brief Prüft ob der gegebene Typ iterierbar ist, d.h. ob std::begin(t) und std::end(t) definiert sind
* und damit indirekt, ob T::begin() und T::end() definiert sind.
*
* @tparam T Der zu prüfende Typ.
*/
template <typename T, typename = void>
struct is_iterable
{
static constexpr bool value = false;
};
/**
* @brief Prüft ob der gegebene Typ iterierbar ist, d.h. ob std::begin(t) und std::end(t) definiert sind
* und damit indirekt, ob T::begin() und T::end() definiert sind.
*
* @tparam T Der zu prüfende Typ.
*/
template <typename T>
struct is_iterable<T, typename std::enable_if<
std::is_same<
decltype(std::begin(std::declval<T>())),
decltype(std::end(std::declval<T>()))>::value &&
lib::is_iterator<decltype(std::begin(std::declval<T>()))>::value &&
lib::is_iterator<decltype(std::end(std::declval<T>()))>::value>::type>
{
static constexpr bool value = true;
};
/**
* @brief Kurzform von is_iterable<T>::value.
*
* @tparam T Der zu prüfende Typ.
*/
template <typename T>
static constexpr auto is_iterable_v = lib::is_iterable<T>::value;
/**
* @brief Prüft ob ein Typ einen kontinuierlichen Speicher darstellt. Dies ist der Fall wenn der Container
* die Funktionen PointerType T::data() const und IntegralType T::size() const definiert.
*
* @tparam T Der zu prüfende Typ.
*/
template <typename T, typename = void>
struct is_contiguos_memory
{
static constexpr bool value = false;
};
/**
* @brief Prüft ob ein Typ einen kontinuierlichen Speicher darstellt. Dies ist der Fall wenn der Container
* die Funktionen PointerType T::data() const und UnsignedIntegralType T::size() const definiert.
*
* @tparam T Der zu prüfende Typ.
*/
template <typename T>
struct is_contiguos_memory<
T,
typename std::enable_if<
std::is_pointer<decltype(std::declval<T>().data())>::value &&
std::is_unsigned<decltype(std::declval<T>().size())>::value>::type>
{
static constexpr bool value = true;
};
/**
* @brief Kurzform von is_contiguos_memory<T>::value
*
* @tparam T Der zu prüfende Typ.
*/
template <typename T>
static constexpr auto is_contiguos_memory_v = is_contiguos_memory<T>::value;
} // namespace lib
\ No newline at end of file
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
#include <memory> #include <memory>
#include "VkUtil/VkUtil.hpp" #include "VkUtil/VkUtil.hpp"
#include "VkUtil/Buffer.hpp" #include "VkUtil/Memory/Buffer.hpp"
namespace lib namespace lib
{ {
......
#pragma once #pragma once
#include "GlfwAndVulkan.hpp" #include "GlfwAndVulkan.hpp"
namespace lib namespace lib
{ {
class CgContext; class CgContext;
class BufferPool class BufferPool
{ {
private: private:
class Buffer class Buffer
{ {
private: private:
friend BufferPool; friend BufferPool;
vk::Buffer handle; vk::Buffer handle;
vk::DeviceSize size; vk::DeviceSize size;
void *data; void *data;
public: public:
Buffer(BufferPool *parent); Buffer(BufferPool *parent);
void WriteData(); void WriteData();
}; };
vk::DeviceMemory memory; vk::DeviceMemory memory;
vk::DeviceSize totalAllocation = 0; vk::DeviceSize totalAllocation = 0;
vk::DeviceSize allocatedMemory = 0; vk::DeviceSize allocatedMemory = 0;
CgContext *context; CgContext *context;
public: public:
BufferPool(CgContext *context, vk::MemoryPropertyFlags memoryPropertyFlags); BufferPool(CgContext *context, vk::MemoryPropertyFlags memoryPropertyFlags);
BufferPool::Buffer AcquireBuffer(vk::BufferUsageFlags flags, const std::vector<uint32_t> &familyIndices); BufferPool::Buffer AcquireBuffer(vk::BufferUsageFlags flags, const std::vector<uint32_t> &familyIndices);
}; };
} // namespace lib } // namespace lib
#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
#pragma once
#include "VkUtil/Memory/MemoryAllocation.hpp"
#include "VkUtil/Memory/MappedMemory.hpp"
#include "GlfwAndVulkan.hpp"
#include <map>
namespace lib
{
/**
* @brief Forward-Declaration für CgContext.
*/
class CgContext;
/**
* @brief Stellt einen Block Speicher dar. Dieser Block kann für einen oder mehrere Puffer genutzt werden,
* stellt jedoch keine dynamische Allozierung bereit. Die Klasse arbeitet nach dem RAII-Prinzip, der
* Konstruktor alloziert Speicher, der Destruktor gibt diesen Speicher wieder frei.
*/
class Memory
{
private:
/**
* @brief Die gesamte Größe des Speicherblocks.
*/
vk::DeviceSize totalSize{0};
/**
* @brief Die Handle zum Speicher.
*/
vk::DeviceMemory handle{nullptr};
/**
* @brief Das Ende des derzeit allozierten Bereichs.
*/
vk::DeviceSize allocationEnd{0};
/**
* @brief Der zu nutzende CgContext.
*/
CgContext *context{nullptr};
public:
/**
* @brief Initialisiert eine neue Instanz der Memory Klasse und alloziert Speicher.
*
* @param context Der zu nutzende CgContext
* @param size Die Größe des angeforderten Speichers.
* @param type Der Typ des Speichers.
*/
Memory(CgContext *context, vk::DeviceSize size, uint32_t type);
/**
* @brief Gelöschter Copy-Constructor.
*/
Memory(const Memory &copy) = delete;
/**
* @brief Move-Constructor.
*
* @param move Das Objekt von dem Ressourcen bewegt werden sollen.
*/
Memory(Memory &&move);
/**
* @brief Zerstört das Memory Objekt und gibt den allozierten Speicher frei.
*/
~Memory();
/**
* @brief Ruft den gesamten verfügbaren Speicher ab.
*
* @return MemoryAllocation Der Bereich des allozierten Speichers.
*/
MemoryAllocation Acquire();
/**
* @brief Ruft einen Teil des verfügbaren Speichers ab.
*
* @return MemoryAllocation Der Bereich des allozierten Speichers.
*/
MemoryAllocation Acquire(vk::DeviceSize size);
/**
* @brief Mapped den gesamten Speicher.
*
* @return MappedMemory Der Gemappedte Speicher.
*/
MappedMemory Map() const;
/**
* @brief Mapped einen Teil des Speichers.
*
* @return MappedMemory Der Gemappedte Speicher.
*/
MappedMemory Map(vk::DeviceSize offset, vk::DeviceSize size) const;
/**
* @brief Gelöschter Copy-Assignment-Operator.
*/
Memory &operator=(const Memory &move) = delete;
/**
* @brief Move-Assignment-Operator.
*
* @param move Das Objekt von dem Ressourcen bewegt werden sollen.
*/
Memory &operator=(Memory &&move);
friend void swap(Memory &a, Memory &b);
};
/**
* @brief Tauscht die beiden Memory-Instanzen.
*
* @param a Das erste Objekt.
* @param b Das zweite Objekt.
*/
void swap(Memory &a, Memory &b);
} // namespace lib
#pragma once
#include "VkUtil/Memory/MappedMemory.hpp"
#include "GlfwAndVulkan.hpp"
namespace lib
{
/**
* @brief Stell ein Stück allozierten Speicher dar.
*/
struct MemoryAllocation
{
MemoryAllocation() = default;
inline MemoryAllocation(vk::DeviceMemory memory,
vk::DeviceSize offset,
vk::DeviceSize size)
: memory(memory),
offset(offset),
size(size)
{
}
vk::DeviceMemory memory{nullptr};
vk::DeviceSize offset{0};
vk::DeviceSize size{0};
};
} // namespace lib
#pragma once
#include "Util/ExeptionBase.hpp"
#include <GlfwAndVulkan.hpp>
namespace lib
{
/**
* @brief Ein Ausnahme, die erzeugt wird wenn ein Memory-Objekt keinen Speicher mehr verteilen kann.
*/
class OutOfMemoryException final : public lib::ExceptionBase
{
public:
/**
* @brief Initialisiert eine neue Instanz der Out Of Memory Exception Klasse.
*
* @param requested Der angeforderte Speicher in Byte.
* @param available Der verfügbare Speicher in Byte.
* @param total Der gesamte Speicher in Byte.
*/
OutOfMemoryException(vk::DeviceSize requested, vk::DeviceSize available, vk::DeviceSize total);
};
} // namespace lib
#pragma once
#include "GlfwAndVulkan.hpp"
#include <map>
class CgContext;
namespace lib
{
struct Allocation
{
vk::DeviceMemory memory;
vk::DeviceSize offset;
};
class MemoryAllocator
{
private:
struct Memory
{
vk::DeviceMemory memory;
vk::DeviceSize size;
};
std::map<uint32_t, Memory> memoryPerType;
vk::DeviceSize totalSize = 0;
CgContext *context = nullptr;
public:
MemoryAllocator(CgContext *context);
~MemoryAllocator();
Allocation Acquire(vk::DeviceSize size) const;
void Allocate() const;
void Reserve(vk::DeviceSize size) const;
};
class OutOfMemoryException : public std::exception
{
private:
friend MemoryAllocator;
OutOfMemoryException();
};
class MappedMemory
{
private:
friend MemoryAllocator;
vk::DeviceSize offset;
vk::DeviceSize size;
MappedMemory(vk::DeviceSize offset, vk::DeviceSize size, CgContext *);
public:
~MappedMemory();
void Write(const void *data, const size_t len);
template <typename T>
void Write(const T &data)
{
this->Write(static_cast<void *>(&data), sizeof(data));
}
template <typename T>
void Write(const std::vector<T> &data)
{
this->Write(data.data(), data.size() * sizeof(T));
}
};
class WriteOutOfBoundsException : public std::exception
{
private:
friend MappedMemory;
WriteOutOfBoundsException(const MappedMemory &errorMemory);
};
} // namespace lib
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
#include <exception> #include <exception>
#include "GlfwAndVulkan.hpp" #include "GlfwAndVulkan.hpp"
#include "VkUtil/Buffer.hpp" #include "VkUtil/Memory/Buffer.hpp"
namespace lib namespace lib
{ {
......
#include "Core/CoreInitException.hpp" #include "Core/CoreInitException.hpp"
lib::CoreInitException::CoreInitException(const std::string &msg) : std::exception(msg.c_str()) lib::CoreInitException::CoreInitException(const std::string &msg) : lib::ExceptionBase(msg)
{
}
lib::CoreInitException::CoreInitException(const char *msg) : lib::ExceptionBase(msg)
{ {
} }
\ No newline at end of file
#include "Core/Model/ModelLoadException.hpp" #include "Core/Model/ModelLoadException.hpp"
#include "Util/Utils.hpp" #include "Util/Utils.hpp"
namespace
{
std::string MakeMessage(const std::string &reason, const std::string &path)
{
return lib::Format("Failed to load model from %! Reason: %", path, reason);
}
} // namespace
lib::ModelLoadException::ModelLoadException(const std::string &reason, const std::string &path) lib::ModelLoadException::ModelLoadException(const std::string &reason, const std::string &path)
: std::exception(MakeMessage(reason, path).c_str()) : lib::ExceptionBase(lib::Format("Failed to load model from %! Reason: %", path, reason))
{ {
} }
\ No newline at end of file
#include "Util/ExeptionBase.hpp"
lib::ExceptionBase::ExceptionBase(std::string message)
: std::exception(),
message(message)
{
}
lib::ExceptionBase::ExceptionBase(const char *message)
: std::exception(message),
message()
{
}
const char *lib::ExceptionBase::what() const noexcept
{
return this->message.empty() ? this->std::exception::what() : this->message.c_str();
}
\ No newline at end of file
#include "Core/CgContext.hpp" #include "Core/CgContext.hpp"
#include "VkUtil/Buffer.hpp" #include "VkUtil/Memory/Buffer.hpp"
#include "Util/Utils.hpp" #include "Util/Utils.hpp"
#include "VkUtil/VkUtil.hpp" #include "VkUtil/VkUtil.hpp"
#include "Util/Logging.hpp" #include "Util/Logging.hpp"
......
#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);
}
#include <algorithm>
#include "Core/CgContext.hpp"
#include "VkUtil/Memory/Memory.hpp"
#include "VkUtil/Memory/OutOfMemoryException.hpp"
lib::Memory::Memory(CgContext *context, vk::DeviceSize size, uint32_t type)
: context(context),
totalSize(size)
{
vk::MemoryAllocateInfo info;
info.allocationSize = size;
info.memoryTypeIndex = type;
this->handle = this->context->GetLogicalDevice().allocateMemory(info);
}
lib::Memory::Memory(Memory &&move)
{
swap(*this, move);
}
lib::Memory::~Memory()
{
if (this->handle)
{
this->context->GetLogicalDevice().freeMemory(this->handle);
}
}
lib::MemoryAllocation lib::Memory::Acquire()
{
return this->Acquire(this->totalSize);
}
lib::MemoryAllocation lib::Memory::Acquire(vk::DeviceSize size)
{
if (this->allocationEnd + size > this->totalSize)
{
throw lib::OutOfMemoryException(size, this->totalSize - this->allocationEnd, this->totalSize);
}
MemoryAllocation res{
this->handle,
this->allocationEnd,
size};
this->allocationEnd += size;
return res;
}
lib::MappedMemory lib::Memory::Map() const
{
return this->Map(0, this->totalSize);
}
lib::MappedMemory lib::Memory::Map(vk::DeviceSize offset, vk::DeviceSize size) const
{
return MappedMemory(this->context, this->handle, offset, size);
}
lib::Memory &lib::Memory::operator=(Memory &&move)
{
if (this != &move)
{
swap(*this, move);
}
return *this;
}
void lib::swap(Memory &a, Memory &b)
{
using std::swap;
swap(a.allocationEnd, b.allocationEnd);
swap(a.context, b.context);
swap(a.handle, b.handle);
swap(a.totalSize, b.totalSize);
}
#include "VkUtil/Memory/OutOfMemoryException.hpp"
#include "Util/Utils.hpp"
lib::OutOfMemoryException::OutOfMemoryException(vk::DeviceSize requested, vk::DeviceSize available, vk::DeviceSize total)
: lib::ExceptionBase(lib::Format(
"Requested allocation of %b on memoryblock of %b with only %b free!", requested, total, available))
{
}
\ No newline at end of file
#include "Core/CgContext.hpp" #include "Core/CgContext.hpp"
#include "VkUtil/StagedBuffer.hpp" #include "VkUtil/Memory/StagedBuffer.hpp"
#include "Util/Utils.hpp" #include "Util/Utils.hpp"
#include "VkUtil/VkUtil.hpp" #include "VkUtil/VkUtil.hpp"
......