...
 
Commits (6)
......@@ -18,7 +18,7 @@ add_subdirectory(./src/submodules/glfw)
set(SHADERC_SKIP_TESTS on)
set(SHADERC_ENABLE_SHARED_CRT on)
add_subdirectory(./src/submodules/shaderc/src)
add_subdirectory(./src/submodules/shaderc/)
# set(ASSIMP_NO_EXPORT on)
set(ASSIMP_BUILD_TESTS off)
......@@ -88,7 +88,8 @@ target_include_directories(Lib
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/src/submodules/glfw/include
${CMAKE_CURRENT_SOURCE_DIR}/src/submodules/glm
${CMAKE_CURRENT_SOURCE_DIR}/src/submodules/shaderc/.shaderc/include
${CMAKE_CURRENT_SOURCE_DIR}/src/submodules/shaderc/libshaderc/include
${CMAKE_CURRENT_SOURCE_DIR}/src/submodules/shaderc/libshaderc_util/include
${CMAKE_CURRENT_SOURCE_DIR}/src/submodules/assimp/include
${CMAKE_CURRENT_SOURCE_DIR}/src/submodules/dearImGui
${CMAKE_CURRENT_SOURCE_DIR}/src/submodules/dearImGui/examples
......@@ -128,7 +129,8 @@ target_include_directories(App
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/src/submodules/glfw/include
${CMAKE_CURRENT_SOURCE_DIR}/src/submodules/glm
${CMAKE_CURRENT_SOURCE_DIR}/src/submodules/shaderc/src/libshaderc/include
${CMAKE_CURRENT_SOURCE_DIR}/src/submodules/shaderc/libshaderc/include
${CMAKE_CURRENT_SOURCE_DIR}/src/submodules/shaderc/libshaderc_util/include
${CMAKE_CURRENT_SOURCE_DIR}/src/submodules/assimp/include
${CMAKE_CURRENT_SOURCE_DIR}/src/submodules/dearImGui
${CMAKE_CURRENT_SOURCE_DIR}/src/submodules/dearImGui/examples
......@@ -161,7 +163,8 @@ target_include_directories(Playground
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/src/submodules/glfw/include
${CMAKE_CURRENT_SOURCE_DIR}/src/submodules/glm
${CMAKE_CURRENT_SOURCE_DIR}/src/submodules/shaderc/src/libshaderc/include
${CMAKE_CURRENT_SOURCE_DIR}/src/submodules/shaderc/libshaderc/include
${CMAKE_CURRENT_SOURCE_DIR}/src/submodules/shaderc/libshaderc_util/include
${CMAKE_CURRENT_SOURCE_DIR}/src/submodules/assimp/include
${CMAKE_CURRENT_SOURCE_DIR}/src/submodules/dearImGui
${CMAKE_CURRENT_SOURCE_DIR}/src/submodules/dearImGui/examples
......
#version 450
#extension GL_GOOGLE_include_directive : enable
#extension GL_ARB_separate_shader_objects : enable
// #extension GL_GOOGLE_include_directive : enable
// #extension GL_ARB_separate_shader_objects : enable
layout(location = 0) out vec2 texCoord;
......
\section{Grundlagen der Aufgabe}
Die Ausarbeitung soll sich sprachlich auf einem Niveau befinden, das für Leser mit grundlegenden Kenntnissen
über Computergrafik, Geometrie im dreidimensionalen Raum und Programmierung in modernem C++ verständlich ist.
Fachbegriffe sollen dennoch kurz wiederholt werden. Oft haben Fachbegriffe keine deutsche Entsprechung oder die deutsche
Entsprechung ist zu unhandlich und zu unbekannt, sodass auf englische Begriffe im Fließtext nicht verzichtet
werden kann. Sofern möglich sollen Prinzipien nicht nur beschrieben, sondern grafisch dargestellt werden.\\
Der Grundgedanke ist, eine Palette von grafischen Effekten vertieft zu betrachten und an diesen Effekten die
Möglichkeiten und Einschränkungen von Raytracing zu erkunden.
\section{Grundlagen von Raytracing}
Zunächst sollen die Grundlagen von Raytracing und die wichtigen Begriffe kurz umrissen werden um eine Basis
für die Verständlichkeit des Dokuments zu legen. Dies ist auch in der Ausarbeitung selbst erforderlich und
kann dort noch mehr vertieft werden.
%
\paragraph{Strahl/Ray:} Ein Strahl (oder eben Ray) besteht aus einem Startpunkt und einer Richtung (Punkt- und
Richtungsvektor). Der
Kerngedanke des Raytracings ist, die Schnittpunkte eines solchen Strahls mit der Szene zu berechnen. Dieser Prozess
wird in aktuellen Grafikkarten durch spezielle Rechenkerne beschleunigt und ermöglicht so Raytracing in
Echtzeit. Für jeden Schnittpunkt kann danach ein Shader aufgerufen werden, um den Treffer zu
verarbeiten und die Farbe des Trefferpunktes zu bestimmen. Prinzipiell kann ein Strahl eine Vielzahl von
Treffern auslösen, häufig wird jedoch nur der Treffer, der dem Startpunkt des Strahls am nächsten liegt,
beachtet.
%
\paragraph{Ray-Payload:} Die Informationen, die mit einem Strahl verknüpft sind. Diese sind frei definierbar
und beinhalten zum Beispiel die Farbe des getroffenen Objekts, oder lediglich eine Flag, die anzeigt ob
überhaupt ein Objekt getroffen wurde.
%
\paragraph{Schattenfühler:} Schattenfühler sind besondere Strahlen, die von einem Trefferpunkt eines Strahls
in der Szene ausgesendet werden um zu prüfen, ob der getroffene Punkt von der Lichtquelle aus erreichbar ist.
Somit lässt sich prüfen, ob ein Punkt von einer Lichtquelle aus im Schatten liegt oder nicht.
%
\paragraph{Stochastisches Raytracing:}
Um für einen Punkt eine korrekte Beleuchtung zu berechnen, müssten
theoretisch - der Rendergleichung folgend - unendlich viele Strahlen ausgesendet werden, um alle einfallenden
Lichtstrahlen zurückzuverfolgen. Beim stochastischen Raytracing wird versucht, die Rendergleichung durch eine
Monte-Carlo-Simulation anzunähern. Dazu werden Strahlen zufällig leicht variiert, was am Ende ein verrauschtes
Bild erzeugt, aber bessere Ergebnisse liefert (z.B. für weiche Schatten).
\section{Einleitung}
%
\begin{quotation}
There is an old joke that goes, \gquote{Raytracing is the technology of the future and it always will be!}\\
- David Kirk
\end{quotation}
%
Raytracing ist eine Rendertechnik, bei der der Verlauf von Lichtstrahlen und deren Interaktion mit der Umgebung
simuliert wird um photorealisitsche Bilder zu erstellen. Sowohl theoretische Grundlagen, als auch
Implementierung der Technik sind seit Ende der 1960er Jahre bekannt. Die Technik rückte jedoch erst vor
wenigen Jahren in den Fokus der breiten Masse, als mit NVIDIAs RTX-Serie erstmals erschwingliche Grafikkarten
mit Hardwarebeschleunigung für Raytracing auf den Markt kamen und Raytracing in Echtzeit ermöglichten.\\
Durch den Einsatz in der Spielebranche erlangte die Technik inzwischen einen hohen Bekanntheitsgrad und bietet
sich daher auch als Forschungsthema an. Die Technik unterscheidet sich dabei grundlegend vom klassischen und
praktisch allgegenwärtigen Ansatz des Rasterisierens. Dadurch bietet Raytracing viele neue Möglichkeiten, bringt aber auch
neue Probleme mit sich, die es zu lösen gilt. Gerade weil die Technik einen sehr allgemeinen Ansatz für das
Rendern in hoher Qualität bietet, scheint eine Vertiefung der Prinzipien des Raytracings
für zukünftige Forschung und Entwicklung wichtig.
\section{Grundlagen von Raytracing}
Zunächst sollen die Grundlagen von Raytracing und die wichtigen Begriffe kurz umrissen werden um eine Basis
für die Verständlichkeit des Dokuments zu legen. Dies ist auch in der Ausarbeitung selbst erforderlich und
kann dort noch mehr vertieft werden.
%
\paragraph{Strahl/Ray:} Ein Strahl (oder eben Ray) besteht aus einem Startpunkt und einer Richtung (Punkt- und
Richtungsvektor). Der
Kerngedanke des Raytracings ist, die Schnittpunkte eines solchen Strahls mit der Szene zu berechnen. Dieser Prozess
wird in aktuellen Grafikkarten durch spezielle Rechenkerne beschleunigt und ermöglicht so Raytracing in
Echtzeit. Für jeden Schnittpunkt kann danach ein Shader aufgerufen werden, um den Treffer zu
verarbeiten und die Farbe des Trefferpunktes zu bestimmen. Prinzipiell kann ein Strahl eine Vielzahl von
Treffern auslösen, häufig wird jedoch nur der Treffer, der dem Startpunkt des Strahls am nächsten liegt,
beachtet.
%
\paragraph{Ray-Payload:} Die Informationen, die mit einem Strahl verknüpft sind. Diese sind frei definierbar
und beinhalten zum Beispiel die Farbe des getroffenen Objekts, oder lediglich eine Flag, die anzeigt ob
überhaupt ein Objekt getroffen wurde.
%
\paragraph{Schattenfühler:} Schattenfühler sind besondere Strahlen, die von einem Trefferpunkt eines Strahls
in der Szene ausgesendet werden um zu prüfen, ob der getroffene Punkt von der Lichtquelle aus erreichbar ist.
Somit lässt sich prüfen, ob ein Punkt von einer Lichtquelle aus im Schatten liegt oder nicht.
%
\paragraph{Stochastisches Raytracing:}
Um für einen Punkt eine korrekte Beleuchtung zu berechnen, müssten
theoretisch - der Rendergleichung folgend - unendlich viele Strahlen ausgesendet werden, um alle einfallenden
Lichtstrahlen zurückzuverfolgen. Beim stochastischen Raytracing wird versucht, die Rendergleichung durch eine
Monte-Carlo-Simulation anzunähern. Dazu werden Strahlen zufällig leicht variiert, was am Ende ein verrauschtes
Bild erzeugt, aber bessere Ergebnisse liefert (z.B. für weiche Schatten).
......@@ -276,7 +276,7 @@ lib::AppCreateInfo app::VkrtApp::CreateInitInfo() const
info.shaderTable.postProcessingFragmentShader.path = "./assets/shaders/post-processing/default.frag.glsl";
info.shaderTable.postProcessingFragmentShader.compileOptions.optimizationLevel = lib::ShaderOptimizationLevel::Performance;
info.shaderTable.postProcessingVertexShader.type = lib::ShaderType::Fragment;
info.shaderTable.postProcessingVertexShader.type = lib::ShaderType::Vertex;
info.shaderTable.postProcessingVertexShader.fileType = lib::ShaderFileType::Glsl;
info.shaderTable.postProcessingVertexShader.path = "./assets/shaders/post-processing/default.vert.glsl";
info.shaderTable.postProcessingVertexShader.compileOptions.optimizationLevel = lib::ShaderOptimizationLevel::Performance;
......
......@@ -97,6 +97,21 @@ namespace lib
* @return const glm::vec3& Die Hintergrundfarbe.
*/
virtual const glm::vec3 &GetClearColor() const = 0;
/**
* @brief Holt einen Wert der angibt, ob PostProcessing aktiviert ist oder nicht.
*
* @return true PostProcessing ist aktiviert.
* @return false PostProcessing ist nicht aktiviert.
*/
virtual bool IsPostProcessingEnabled() const = 0;
/**
* @brief Setzt einen Wert der angibt, ob PostProcessing aktiviert ist oder nicht.
*
* @param value Der neue Wert.
*/
virtual void SetPostProcessingEnabled(bool value) = 0;
};
/**
......@@ -203,10 +218,11 @@ namespace lib
vk::DescriptorPool descriptorPool;
vk::RenderPass renderPass;
ImGui_ImplVulkanH_Window window = {};
std::vector<vk::Framebuffer> frameBuffers;
bool show = false;
} imGui;
bool doPostProcessing = true;
void InitRandomGenerators();
void CreateInstance();
void SetupDebugCallbacks();
......@@ -217,6 +233,7 @@ namespace lib
void CreateSwapChain();
void CreateImageViews();
void CreateRasterizationRenderPass();
void CreateRasterizationFrameBuffers();
void CreateCommandPool();
void LoadDummyTexture();
......@@ -308,6 +325,8 @@ namespace lib
const std::array<lib::LightSource, lib::MaxLights> &GetLightSources() const override;
glm::vec3 &GetClearColor() override;
const glm::vec3 &GetClearColor() const override;
bool IsPostProcessingEnabled() const override;
void SetPostProcessingEnabled(bool value) override;
vk::ShaderModule LoadShader(const ShaderInfo &info);
......
......@@ -14,12 +14,14 @@ namespace lib
vk::CommandPool commandPool;
vk::CommandBuffer commandBuffer;
vk::Fence inFlightFence;
vk::DescriptorSet descriptorSet;
vk::DescriptorSet raytracingDescriptorSet;
vk::DescriptorSet rasterizationDescriptorSet;
vk::Image swapChainImage;
vk::ImageView swapChainImageView;
vk::Framebuffer swapChainFramebufferForRasterizationRenderPass;
vk::Framebuffer swapChainFramebufferForImGui;
std::unique_ptr<lib::Texture> raytracingTexture;
vk::Framebuffer raytracingTextureFbo;
};
} // namespace lib
......@@ -10,7 +10,6 @@ namespace lib
vk::Pipeline pipeline;
vk::DescriptorSetLayout descriptorSetLayout;
vk::DescriptorPool descriptorPool;
std::vector<vk::DescriptorSet> descriptorSets;
vk::RenderPass renderPass;
};
} // namespace lib
......@@ -22,4 +22,17 @@ namespace lib
inline const glm::vec3 y = {0, 1, 0};
inline const glm::vec3 z = {0, 0, 1};
} // namespace axis
namespace ansiColors
{
constexpr auto Black = "\u001b[30m";
constexpr auto Red = "\u001b[31m";
constexpr auto Green = "\u001b[32m";
constexpr auto Yellow = "\u001b[33m";
constexpr auto Blue = "\u001b[34m";
constexpr auto Magenta = "\u001b[35m";
constexpr auto Cyan = "\u001b[36m";
constexpr auto White = "\u001b[37m";
constexpr auto Reset = "\u001b[0m";
} // namespace ansiColors
} // namespace lib
......@@ -7,63 +7,98 @@
namespace lib
{
namespace log
{
void SetLoggingStatus(bool debugEnabled, bool infoEnabled, bool warningEnabled, bool errorEnabled);
bool IsDebugEnabled();
bool IsInfoEnabled();
bool IsWarningEnabled();
bool IsErrorEnabled();
void LogDebug(const std::string &text);
void Log(const std::string &text);
void LogWarning(const std::string &text);
void LogError(const std::string &text);
template <class TFirst, class... TArgs>
void LogDebug(const std::string &format, const TFirst &first, const TArgs &... args)
{
if constexpr (IsDebug)
namespace log
{
if (!lib::log::IsDebugEnabled())
struct ChannelState
{
return;
}
bool enabled;
bool flush;
std::string prefix;
std::string suffix;
lib::log::LogDebug(Format(format, first, args...));
}
}
inline ChannelState(
bool enabled,
std::string prefix,
std::string suffix,
bool flush)
: enabled(enabled),
flush(flush),
prefix(prefix),
suffix(suffix) {}
};
template <class TFirst, class... TArgs>
void Log(const std::string &format, const TFirst &first, const TArgs &... args)
{
if (!lib::log::IsInfoEnabled())
{
return;
}
struct State
{
ChannelState debug;
ChannelState info;
ChannelState warning;
ChannelState error;
lib::log::Log(Format(format, first, args...));
}
inline State(
ChannelState debug,
ChannelState info,
ChannelState warning,
ChannelState error)
: debug(debug),
info(info),
warning(warning),
error(error)
{
}
};
template <class TFirst, class... TArgs>
void LogWarning(const std::string &format, const TFirst &first, const TArgs &... args)
{
if (!lib::log::IsWarningEnabled())
{
return;
}
State &GetState();
lib::log::LogWarning(Format(format, first, args...));
}
void Debug(const std::string &text);
void Info(const std::string &text);
void Warning(const std::string &text);
void Error(const std::string &text);
template <class TFirst, class... TArgs>
void LogError(const std::string &format, const TFirst &first, const TArgs &... args)
{
if (!lib::log::IsErrorEnabled())
{
return;
}
template <class TFirst, class... TArgs>
void Debug(const std::string &format, const TFirst &first, const TArgs &... args)
{
if constexpr (IsDebug)
{
if (!lib::log::GetState().debug.enabled)
{
return;
}
lib::log::LogError(Format(format, first, args...));
}
} // namespace log
lib::log::Debug(Format(format, first, args...));
}
}
template <class TFirst, class... TArgs>
void Info(const std::string &format, const TFirst &first, const TArgs &... args)
{
if (!lib::log::GetState().info.enabled)
{
return;
}
lib::log::Info(Format(format, first, args...));
}
template <class TFirst, class... TArgs>
void Warning(const std::string &format, const TFirst &first, const TArgs &... args)
{
if (!lib::log::GetState().warning.enabled)
{
return;
}
lib::log::Warning(Format(format, first, args...));
}
template <class TFirst, class... TArgs>
void Error(const std::string &format, const TFirst &first, const TArgs &... args)
{
if (!lib::log::GetState().error.enabled)
{
return;
}
lib::log::Error(Format(format, first, args...));
}
} // namespace log
} // namespace lib
\ No newline at end of file
......@@ -13,15 +13,18 @@ namespace lib
struct TextureCreateInfo
{
inline TextureCreateInfo(vk::Format format = vk::Format{},
inline TextureCreateInfo(std::vector<uint32_t> queueFamilyIndices = {},
vk::Format format = vk::Format{},
vk::ImageUsageFlags usage = vk::ImageUsageFlagBits{},
vk::ImageLayout layout = vk::ImageLayout{})
: format(format),
: queueFamilyIndices(queueFamilyIndices),
format(format),
usage(usage),
layout(layout)
{
}
std::vector<uint32_t> queueFamilyIndices;
vk::Format format;
vk::ImageUsageFlags usage;
vk::ImageLayout layout;
......@@ -104,6 +107,9 @@ namespace lib
this->LoadData(width, height, buf.data(), sizeof(buf.front()), createInfo);
}
Texture(Texture &&) = delete;
Texture(const Texture &) = delete;
~Texture();
const vk::Image &GetHandle() const;
......@@ -111,5 +117,8 @@ namespace lib
const vk::ImageView &GetView() const;
const vk::Sampler &GetSampler() const;
Texture &operator=(Texture &&) = delete;
Texture &operator=(const Texture &) = delete;
}; // namespace lib
} // namespace lib
......@@ -8,9 +8,9 @@
#include <numeric>
#include <cmath>
using lib::log::Log;
using lib::log::LogError;
using lib::log::LogWarning;
using lib::log::Info;
using lib::log::Error;
using lib::log::Warning;
#undef CreateWindow
......@@ -145,20 +145,20 @@ lib::App::App(const AppCreateInfo &info) : appBaseName(info.appName),
{
if (!info.Validate(false))
{
LogError("Invalid create info!");
Error("Invalid create info!");
return;
}
if (!glfwInit())
{
LogError("Glfw could not be initialized!");
Error("Glfw could not be initialized!");
return;
}
if (!glfwVulkanSupported())
{
LogError("Vulkan is not supported!");
Error("Vulkan is not supported!");
return;
}
......@@ -172,22 +172,22 @@ lib::App::App(const AppCreateInfo &info) : appBaseName(info.appName),
if (this->context->IsOk())
{
Log("Successfully initialized App!");
Info("Successfully initialized App!");
}
else if (this->context->IsRecoverable())
{
LogWarning("Initialized App with recoverable errors!");
Warning("Initialized App with recoverable errors!");
}
else
{
LogError("Failed to initialize App: Failed to initialize Vulkan Context!");
Error("Failed to initialize App: Failed to initialize Vulkan Context!");
}
this->RegisterCallbacks();
}
catch (const std::exception &e)
{
LogError("Failed to initialize App: Exception occurred: %", e.what());
Error("Failed to initialize App: Exception occurred: %", e.what());
}
}
......@@ -227,21 +227,21 @@ void lib::App::Run()
{
if (!this->IsOk())
{
LogError("The App was not initialized correctly, can't run!");
Error("The App was not initialized correctly, can't run!");
return;
}
if (!this->adapter)
{
LogError("There must be an IAppAdapter attached to run!");
Error("There must be an IAppAdapter attached to run!");
return;
}
this->adapter->AfterInit(*this);
Log("Starting main loop!");
Info("Starting main loop!");
auto hasException = false;
::t0 = ::t1 = std::chrono::high_resolution_clock::now();
......@@ -261,12 +261,12 @@ void lib::App::Run()
}
catch (const std::exception &e)
{
LogError("Exception occurred: %", e.what());
Error("Exception occurred: %", e.what());
hasException = true;
}
catch (...)
{
LogError("Unidentified exception occurred");
Error("Unidentified exception occurred");
hasException = true;
}
}
......
......@@ -57,7 +57,7 @@ bool lib::AppCreateInfo::Validate(bool silent) const
{
for (const auto &error : errors)
{
lib::log::LogError(::errorMessages[error]);
lib::log::Error(::errorMessages[error]);
}
}
......
......@@ -17,10 +17,10 @@
#include "Util/Utils.hpp"
#include "VkUtil/VkUtil.hpp"
using lib::log::Log;
using lib::log::LogDebug;
using lib::log::LogError;
using lib::log::LogWarning;
using lib::log::Debug;
using lib::log::Error;
using lib::log::Info;
using lib::log::Warning;
#undef min
#undef max
......@@ -29,11 +29,11 @@ void lib::CgContext::QueryExtensions()
{
this->availableExtensions = vk::enumerateInstanceExtensionProperties();
if (lib::log::IsDebugEnabled())
if (lib::log::GetState().debug.enabled)
{
for (const auto &availableExtension : this->availableExtensions)
{
LogDebug("Available extension %", availableExtension.extensionName);
Debug("Available extension %", availableExtension.extensionName);
}
}
}
......@@ -52,11 +52,11 @@ bool lib::CgContext::CheckAndAdd(const char *name, NameList &buf, bool required)
if (required)
{
LogError("Could not find required extension %", name);
Error("Could not find required extension %", name);
}
else
{
LogWarning("Could not find optional extension %", name);
Warning("Could not find optional extension %", name);
}
return false;
......@@ -78,11 +78,11 @@ void lib::CgContext::QueryLayers()
{
this->availableLayers = vk::enumerateInstanceLayerProperties();
if (lib::log::IsDebugEnabled())
if (lib::log::GetState().debug.enabled)
{
for (const auto &availableLayer : this->availableLayers)
{
LogDebug("Available extension %", availableLayer.layerName);
Debug("Available extension %", availableLayer.layerName);
}
}
}
......@@ -97,7 +97,7 @@ bool lib::CgContext::CheckLayer(const char *name)
}
}
LogError("Could not find layer %", name);
Error("Could not find layer %", name);
return false;
}
......@@ -287,4 +287,14 @@ void lib::CgContext::SetObjectName(const vk::Buffer &buffer, const std::string &
void lib::CgContext::SetShowUi(bool show)
{
this->imGui.show = show;
}
\ No newline at end of file
}
bool lib::CgContext::IsPostProcessingEnabled() const
{
return this->doPostProcessing;
}
void lib::CgContext::SetPostProcessingEnabled(bool value)
{
this->doPostProcessing = value;
}
......@@ -44,7 +44,7 @@ namespace
vk::AttachmentReference attachmentReference;
attachmentReference.attachment = 0;
attachmentReference.layout = vk::ImageLayout::eGeneral;
attachmentReference.layout = vk::ImageLayout::eColorAttachmentOptimal;
vk::SubpassDescription subpass;
subpass.pipelineBindPoint = vk::PipelineBindPoint::eGraphics;
......@@ -60,30 +60,21 @@ namespace
return logicalDevice.createRenderPass(createInfo);
}
std::vector<vk::Framebuffer> genImGuiFrameBuffers(vk::Device logicalDevice,
const vk::RenderPass &renderpass,
const vk::Extent2D &extent,
const std::vector<lib::Frame> &frames)
vk::Framebuffer genImGuiFramebuffer(vk::Device logicalDevice,
const vk::RenderPass &renderpass,
const vk::Extent2D &extent,
const vk::ImageView &imageView)
{
const auto count = static_cast<uint32_t>(frames.size());
std::vector<vk::Framebuffer> res;
res.reserve(count);
for (uint32_t i = 0; i < count; i++)
{
vk::FramebufferCreateInfo createInfo;
createInfo.renderPass = renderpass;
createInfo.attachmentCount = 1;
createInfo.pAttachments = &frames[i].swapChainImageView;
createInfo.width = extent.width;
createInfo.height = extent.height;
createInfo.layers = 1;
res.push_back(logicalDevice.createFramebuffer(createInfo));
}
vk::FramebufferCreateInfo createInfo;
createInfo.renderPass = renderpass;
createInfo.attachmentCount = 1;
createInfo.pAttachments = &imageView;
createInfo.width = extent.width;
createInfo.height = extent.height;
createInfo.layers = 1;
return res;
return logicalDevice.createFramebuffer(createInfo);
}
void PrepareImGuiSettings()
......@@ -96,10 +87,14 @@ void lib::CgContext::CreateImGuiComponents()
this->imGui.descriptorPool = ::genImGuiDescriptorPool(this->logicalDevice,
static_cast<uint32_t>(this->frames.size()));
this->imGui.renderPass = ::genImGuiRenderPass(this->logicalDevice, this->swapChainImageFormat);
this->imGui.frameBuffers = ::genImGuiFrameBuffers(this->logicalDevice,
this->imGui.renderPass,
this->swapChainExtent,
this->frames);
for (auto &frame : this->frames)
{
frame.swapChainFramebufferForImGui = ::genImGuiFramebuffer(this->logicalDevice,
this->imGui.renderPass,
this->swapChainExtent,
frame.swapChainImageView);
}
ImGui_ImplVulkan_InitInfo info = {};
info.Instance = this->instance;
......@@ -145,9 +140,10 @@ void lib::CgContext::DestroyImGuiComponents()
this->logicalDevice.destroyRenderPass(this->imGui.renderPass);
this->logicalDevice.destroyDescriptorPool(this->imGui.descriptorPool);
for (const auto &frameBuffer : this->imGui.frameBuffers)
for (auto &frame : this->frames)
{
this->logicalDevice.destroyFramebuffer(frameBuffer);
this->logicalDevice.destroyFramebuffer(frame.swapChainFramebufferForImGui);
frame.swapChainFramebufferForImGui = nullptr;
}
}
......
......@@ -26,22 +26,21 @@
#include "imgui_impl_vulkan.h"
#include "imgui_impl_glfw.h"
using lib::log::Log;
using lib::log::LogDebug;
using lib::log::LogError;
using lib::log::LogWarning;
using lib::log::Debug;
using lib::log::Error;
using lib::log::Info;
using lib::log::Warning;
bool lib::CgContext::TryCreateRasterizerPipeline()
{
auto success = true;
auto vertexModule = this->LoadShader(this->appInfo.shaderTable.postProcessingVertexShader);
success = success && vertexModule;
auto fragmentModule = this->LoadShader(this->appInfo.shaderTable.postProcessingFragmentShader);
success = success && vertexModule;
success = success && fragmentModule;
if (success)
{
......@@ -67,12 +66,15 @@ bool lib::CgContext::TryCreateRasterizerPipeline()
inputAssemblyCreateInfo.primitiveRestartEnable = false;
vk::Viewport viewport;
viewport.x = 0.f;
viewport.y = 0.f;
viewport.width = static_cast<float>(this->swapChainExtent.width);
viewport.height = static_cast<float>(this->swapChainExtent.height);
viewport.minDepth = 0.f;
viewport.maxDepth = 1.f;
vk::Rect2D scissor;
scissor.offset = {0, 0};
scissor.extent = this->swapChainExtent;
vk::PipelineViewportStateCreateInfo viewportStateCreateInfo;
......@@ -82,10 +84,13 @@ bool lib::CgContext::TryCreateRasterizerPipeline()
viewportStateCreateInfo.pScissors = &scissor;
vk::PipelineRasterizationStateCreateInfo rasterizationStateCreateInfo;
rasterizationStateCreateInfo.cullMode = vk::CullModeFlagBits::eFront;
rasterizationStateCreateInfo.frontFace = vk::FrontFace::eCounterClockwise;
rasterizationStateCreateInfo.lineWidth = 1.f;
rasterizationStateCreateInfo.depthClampEnable = false;
rasterizationStateCreateInfo.rasterizerDiscardEnable = false;
rasterizationStateCreateInfo.polygonMode = vk::PolygonMode::eFill;
rasterizationStateCreateInfo.lineWidth = 1.f;
rasterizationStateCreateInfo.frontFace = vk::FrontFace::eCounterClockwise;
rasterizationStateCreateInfo.cullMode = vk::CullModeFlagBits::eBack;
rasterizationStateCreateInfo.depthBiasEnable = false;
vk::PipelineMultisampleStateCreateInfo multiSampleStageCreateInfo;
multiSampleStageCreateInfo.sampleShadingEnable = false;
......@@ -119,10 +124,21 @@ bool lib::CgContext::TryCreateRasterizerPipeline()
createInfo.pRasterizationState = &rasterizationStateCreateInfo;
createInfo.pMultisampleState = &multiSampleStageCreateInfo;
createInfo.pColorBlendState = &colorBlendStateCreateInfo;
createInfo.renderPass = this->rasterizationStep.renderPass;
createInfo.layout = this->rasterizationStep.pipelineLayout;
const auto result = this->logicalDevice.createGraphicsPipeline(nullptr, createInfo);
this->rasterizationStep.pipeline = result.value;
if (result.result == vk::Result::eSuccess)
{
this->rasterizationStep.pipeline = result.value;
}
else
{
Error("Failed to create Graphicspipeline!");
success = false;
}
}
if (vertexModule)
......@@ -135,6 +151,8 @@ bool lib::CgContext::TryCreateRasterizerPipeline()
this->logicalDevice.destroyShaderModule(fragmentModule);
}
lib::log::Info("Successfully create rasterization pipeline!");
return success;
}
......@@ -149,14 +167,20 @@ void lib::CgContext::CreateRasterizationDescriptorSets()
allocateInfo.descriptorSetCount = count;
allocateInfo.pSetLayouts = layouts.data();
this->rasterizationStep.descriptorSets = this->logicalDevice.allocateDescriptorSets(allocateInfo);
auto sets = this->logicalDevice.allocateDescriptorSets(allocateInfo);
auto setsIt = std::begin(sets);
for (uint32_t i = 0; i < count; i++)
for (auto &frame : this->frames)
{
frame.rasterizationDescriptorSet = *setsIt++;
vk::DescriptorImageInfo rtImageInfo;
rtImageInfo.imageLayout = vk::ImageLayout::eShaderReadOnlyOptimal;
rtImageInfo.imageView = this->frames[i].raytracingTexture->GetView();
rtImageInfo.sampler = this->frames[i].raytracingTexture->GetSampler();
// rtImageInfo.imageView = frame.raytracingTexture->GetView();
// rtImageInfo.sampler = frame.raytracingTexture->GetSampler();
rtImageInfo.imageView = this->dummyTexture->GetView();
rtImageInfo.sampler = this->dummyTexture->GetSampler();
vk::WriteDescriptorSet rtImageWrite;
rtImageWrite.descriptorCount = 1;
......@@ -164,10 +188,12 @@ void lib::CgContext::CreateRasterizationDescriptorSets()
rtImageWrite.dstArrayElement = 0;
rtImageWrite.dstBinding = 0;
rtImageWrite.pImageInfo = &rtImageInfo;
rtImageWrite.dstSet = this->rasterizationStep.descriptorSets[i];
rtImageWrite.dstSet = frame.rasterizationDescriptorSet;
this->logicalDevice.updateDescriptorSets(rtImageWrite, {});
}
lib::log::Info("Successfully created rasterization descriptor sets!");
}
void lib::CgContext::CreateRasterizationDescriptorPool()
......@@ -184,6 +210,8 @@ void lib::CgContext::CreateRasterizationDescriptorPool()
createInfo.maxSets = count;
this->rasterizationStep.descriptorPool = this->logicalDevice.createDescriptorPool(createInfo);
lib::log::Info("Successfully created rasterization descriptor pool!");
}
void lib::CgContext::CreateRasterizationDescriptorSetLayout()
......@@ -201,13 +229,15 @@ void lib::CgContext::CreateRasterizationDescriptorSetLayout()
createInfo.pBindings = layoutBindings.data();
this->rasterizationStep.descriptorSetLayout = this->logicalDevice.createDescriptorSetLayout(createInfo);
lib::log::Info("Successfully created rasterization descriptor set layouts!");
}
void lib::CgContext::CreateRasterizationRenderPass()
{
vk::AttachmentDescription colorAttachment;
colorAttachment.initialLayout = vk::ImageLayout::eColorAttachmentOptimal;
colorAttachment.finalLayout = vk::ImageLayout::eColorAttachmentOptimal;
colorAttachment.initialLayout = vk::ImageLayout::eUndefined;
colorAttachment.finalLayout = vk::ImageLayout::ePresentSrcKHR;
colorAttachment.loadOp = vk::AttachmentLoadOp::eDontCare;
colorAttachment.storeOp = vk::AttachmentStoreOp::eStore;
colorAttachment.format = this->swapChainImageFormat;
......@@ -240,4 +270,46 @@ void lib::CgContext::CreateRasterizationRenderPass()
createInfo.pAttachments = &colorAttachment;
this->rasterizationStep.renderPass = this->logicalDevice.createRenderPass(createInfo);
lib::log::Info("Successfully created rasterization render pass!");
}
void lib::CgContext::CreateRasterizationFrameBuffers()
{
const auto count = static_cast<uint32_t>(frames.size());
for (auto &frame : this->frames)
{
const lib::TextureCreateInfo textureCreateInfo{
{
this->physicalDeviceInfo.GetGraphicsQueueFamily(),
this->physicalDeviceInfo.GetBufferStagingQueueFamily(),
this->physicalDeviceInfo.GetComputeQueueFamily(),
this->physicalDeviceInfo.GetPresentationQueueFamily(),
},
this->swapChainImageFormat,
vk::ImageUsageFlagBits::eSampled |
vk::ImageUsageFlagBits::eStorage |
vk::ImageUsageFlagBits::eColorAttachment,
vk::ImageLayout::eGeneral};
auto newTexture = new lib::Texture{this,
this->swapChainExtent.width,
this->swapChainExtent.height,
textureCreateInfo};
frame.raytracingTexture.reset(newTexture);
vk::FramebufferCreateInfo createInfo;
createInfo.renderPass = this->rasterizationStep.renderPass;
createInfo.attachmentCount = 1;
createInfo.pAttachments = &frame.swapChainImageView;
createInfo.width = this->swapChainExtent.width;
createInfo.height = this->swapChainExtent.height;
createInfo.layers = 1;
frame.swapChainFramebufferForRasterizationRenderPass = logicalDevice.createFramebuffer(createInfo);
}
lib::log::Info("Successfully created rasterization framebuffers!");
}
\ No newline at end of file
......@@ -26,11 +26,6 @@
#include "imgui_impl_vulkan.h"
#include "imgui_impl_glfw.h"
using lib::log::Log;
using lib::log::LogDebug;
using lib::log::LogError;
using lib::log::LogWarning;
void lib::CgContext::CreateAccelerationStructures()
{
auto commandBuffer = this->AllocateSingleUseComputeCommandBuffer();
......@@ -51,7 +46,7 @@ void lib::CgContext::CreateAccelerationStructures()
commandBuffer.Run();
Log("Successfully created acceleration structures!");
lib::log::Info("Successfully created acceleration structures!");
}
void lib::CgContext::CreateRaytracingDescriptorSetLayout()
......@@ -131,7 +126,7 @@ void lib::CgContext::CreateRaytracingDescriptorSetLayout()
this->raytracingStep.descriptorSetLayout = this->logicalDevice.createDescriptorSetLayout(createInfo);
Log("Successfully created descriptor set layout!");
lib::log::Info("Successfully created raytracing descriptor set layout!");
}
void lib::CgContext::CreateRaytracingDescriptorPool()
......@@ -162,6 +157,8 @@ void lib::CgContext::CreateRaytracingDescriptorPool()
createInfo.maxSets = static_cast<uint32_t>(count);
this->raytracingStep.descriptorPool = this->logicalDevice.createDescriptorPool(createInfo);
lib::log::Info("Successfully created raytracing descriptor pool!");
}
void lib::CgContext::CreateRaytracingDescriptorSets()
......@@ -179,10 +176,10 @@ void lib::CgContext::CreateRaytracingDescriptorSets()
for (size_t i = 0; i < count; i++)
{
auto &frame = this->frames[i];
frame.descriptorSet = descriptorSets[i];
frame.raytracingDescriptorSet = descriptorSets[i];
vk::StructureChain<vk::WriteDescriptorSet, vk::WriteDescriptorSetAccelerationStructureNV> accelerationStructureWrite;
accelerationStructureWrite.get<vk::WriteDescriptorSet>().dstSet = frame.descriptorSet;
accelerationStructureWrite.get<vk::WriteDescriptorSet>().dstSet = frame.raytracingDescriptorSet;
accelerationStructureWrite.get<vk::WriteDescriptorSet>().dstBinding = this->descriptorBindings.accelerationStructure;
accelerationStructureWrite.get<vk::WriteDescriptorSet>().dstArrayElement = 0;
accelerationStructureWrite.get<vk::WriteDescriptorSet>().descriptorType = vk::DescriptorType::eAccelerationStructureNV;
......@@ -195,7 +192,7 @@ void lib::CgContext::CreateRaytracingDescriptorSets()
outputImageInfo.imageView = frame.raytracingTexture->GetView();
vk::WriteDescriptorSet outputImageWrite;
outputImageWrite.dstSet = frame.descriptorSet;
outputImageWrite.dstSet = frame.raytracingDescriptorSet;
outputImageWrite.dstBinding = this->descriptorBindings.outputImage;
outputImageWrite.dstArrayElement = 0;
outputImageWrite.descriptorType = vk::DescriptorType::eStorageImage;
......@@ -204,10 +201,10 @@ void lib::CgContext::CreateRaytracingDescriptorSets()
vk::DescriptorBufferInfo camInfo;
camInfo.buffer = frame.ubo->GetDeviceBufferHandle();
camInfo.range = sizeof(SceneDescription);
camInfo.range = VK_WHOLE_SIZE;
vk::WriteDescriptorSet camWrite;
camWrite.dstSet = frame.descriptorSet;
camWrite.dstSet = frame.raytracingDescriptorSet;
camWrite.dstBinding = this->descriptorBindings.cameraAndLightUbo;
camWrite.dstArrayElement = 0;
camWrite.descriptorType = vk::DescriptorType::eUniformBuffer;
......@@ -225,7 +222,7 @@ void lib::CgContext::CreateRaytracingDescriptorSets()
}
vk::WriteDescriptorSet vertexBufferWrite;
vertexBufferWrite.dstSet = frame.descriptorSet;
vertexBufferWrite.dstSet = frame.raytracingDescriptorSet;
vertexBufferWrite.dstBinding = this->descriptorBindings.vertices;
vertexBufferWrite.dstArrayElement = 0;
vertexBufferWrite.descriptorType = vk::DescriptorType::eStorageBuffer;
......@@ -243,7 +240,7 @@ void lib::CgContext::CreateRaytracingDescriptorSets()
}
vk::WriteDescriptorSet indexBufferWrite;
indexBufferWrite.dstSet = frame.descriptorSet;
indexBufferWrite.dstSet = frame.raytracingDescriptorSet;
indexBufferWrite.dstBinding = this->descriptorBindings.indices;
indexBufferWrite.dstArrayElement = 0;
indexBufferWrite.descriptorType = vk::DescriptorType::eStorageBuffer;
......@@ -255,7 +252,7 @@ void lib::CgContext::CreateRaytracingDescriptorSets()
materialBufferInfo.range = VK_WHOLE_SIZE;
vk::WriteDescriptorSet materialBufferWrite;
materialBufferWrite.dstSet = frame.descriptorSet;
materialBufferWrite.dstSet = frame.raytracingDescriptorSet;
materialBufferWrite.dstBinding = this->descriptorBindings.materials;
materialBufferWrite.dstArrayElement = 0;
materialBufferWrite.descriptorType = vk::DescriptorType::eStorageBuffer;
......@@ -267,7 +264,7 @@ void lib::CgContext::CreateRaytracingDescriptorSets()
objectInstanceInfo.range = VK_WHOLE_SIZE;
vk::WriteDescriptorSet objectInstanceWrite;
objectInstanceWrite.dstSet = frame.descriptorSet;
objectInstanceWrite.dstSet = frame.raytracingDescriptorSet;
objectInstanceWrite.dstBinding = this->descriptorBindings.objectInstances;
objectInstanceWrite.dstArrayElement = 0;
objectInstanceWrite.descriptorType = vk::DescriptorType::eStorageBuffer;
......@@ -280,7 +277,7 @@ void lib::CgContext::CreateRaytracingDescriptorSets()
dummyTextureInfo.sampler = this->dummyTexture->GetSampler();
vk::WriteDescriptorSet dummyTextureWrite;
dummyTextureWrite.dstSet = frame.descriptorSet;
dummyTextureWrite.dstSet = frame.raytracingDescriptorSet;
dummyTextureWrite.dstBinding = this->descriptorBindings.dummyTexture;
dummyTextureWrite.dstArrayElement = 0;
dummyTextureWrite.descriptorType = vk::DescriptorType::eCombinedImageSampler;
......@@ -298,7 +295,7 @@ void lib::CgContext::CreateRaytracingDescriptorSets()
{});
}
Log("Successfully created raytracing descriptor set!");
lib::log::Info("Successfully created raytracing descriptor set!");
}
bool lib::CgContext::TryCreateRayTracingPipeline()
......@@ -414,13 +411,13 @@ bool lib::CgContext::TryCreateRayTracingPipeline()
const auto result = this->logicalDevice.createRayTracingPipelinesNV(vk::PipelineCache(), pipelineCreateInfo);
this->raytracingStep.pipeline = result.value[0];
Log("Successfully created raytracing pipeline!");
lib::log::Info("Successfully created raytracing pipeline!");
success = true;
}
else
{
LogError("Failed to load shaders required for raytracing!");
lib::log::Error("Failed to load shaders required for raytracing!");
}
if (raygenModule)
......@@ -449,19 +446,38 @@ bool lib::CgContext::TryCreateRayTracingPipeline()
void lib::CgContext::CreateShaderBindingTable()
{
uint32_t sbtSize = static_cast<uint32_t>(this->shaderOffsets.count * this->physicalDeviceInfo.GetRaytracingProperties().shaderGroupHandleSize);
auto shadercount = static_cast<uint32_t>(this->appInfo.shaderTable.missShaders.size() + this->appInfo.shaderTable.closestHitShaders.size() + 1);
auto handleSize = this->physicalDeviceInfo.GetRaytracingProperties().shaderGroupHandleSize;
auto baseAlignment = this->physicalDeviceInfo.GetRaytracingProperties().shaderGroupBaseAlignment;
auto sbtBufferSize = shadercount * handleSize;
auto sbtSize = shadercount * baseAlignment;
std::vector<uint8_t> sbtBuf(sbtBufferSize);
this->logicalDevice.getRayTracingShaderGroupHandlesNV(this->raytracingStep.pipeline, 0, shadercount,
sbtBufferSize, sbtBuf.data());
std::vector<uint8_t> alignedSbtBuf(sbtSize);
uint32_t rPos = 0;
uint32_t wPos = 0;
std::vector<uint8_t> sbtBuf(sbtSize);
this->logicalDevice.getRayTracingShaderGroupHandlesNV(this->raytracingStep.pipeline, 0, this->shaderOffsets.count,
sbtSize, sbtBuf.data());
for (uint32_t i = 0; i < shadercount; i++)
{
for (uint32_t j = 0; j < handleSize; j++)
{
alignedSbtBuf[wPos++] = sbtBuf[rPos++];
}
wPos += baseAlignment - handleSize;
}
auto [stagingBuffer, finalBuffer] = this->CreateStagingBuffers(vk::BufferUsageFlagBits::eRayTracingNV);
stagingBuffer.BufferData(sbtBuf);
finalBuffer.AllocateFor(sbtBuf);
stagingBuffer.BufferData(alignedSbtBuf);
finalBuffer.AllocateFor(alignedSbtBuf);
this->CopyBuffer(stagingBuffer, finalBuffer);
this->shaderBindingTableBuffer.reset(new lib::Buffer(std::move(finalBuffer)));
Log("Successfully created shader binding table!");
lib::log::Info("Successfully created shader binding table!");
}
......@@ -26,44 +26,38 @@
#include "imgui_impl_vulkan.h"
#include "imgui_impl_glfw.h"
using lib::log::Log;
using lib::log::LogDebug;
using lib::log::LogError;
using lib::log::LogWarning;
#undef min
#undef max
namespace
{
VKAPI_ATTR vk::Bool32 VKAPI_CALL debugCallback(vk::DebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
vk::DebugUtilsMessageTypeFlagsEXT messageType,
const vk::DebugUtilsMessengerCallbackDataEXT &pCallbackData,
void *pUserData)
bool debugCallback(vk::DebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
vk::DebugUtilsMessageTypeFlagsEXT messageType,
const vk::DebugUtilsMessengerCallbackDataEXT &pCallbackData,
void *pUserData)
{
switch (messageSeverity)
{
case vk::DebugUtilsMessageSeverityFlagBitsEXT::eVerbose:
lib::log::LogDebug("[ValidationLayer] %", pCallbackData.pMessage);
lib::log::Debug("[ValidationLayer] %", pCallbackData.pMessage);
break;
case vk::DebugUtilsMessageSeverityFlagBitsEXT::eInfo:
lib::log::Log("[ValidationLayer] %", pCallbackData.pMessage);
lib::log::Info("[ValidationLayer] %", pCallbackData.pMessage);
break;
case vk::DebugUtilsMessageSeverityFlagBitsEXT::eWarning:
lib::log::LogWarning("[ValidationLayer] %", pCallbackData.pMessage);
lib::log::Warning("[ValidationLayer] %", pCallbackData.pMessage);
break;
case vk::DebugUtilsMessageSeverityFlagBitsEXT::eError:
lib::log::LogError("[ValidationLayer] %", pCallbackData.pMessage);
lib::log::Error("[ValidationLayer] %", pCallbackData.pMessage);
break;
}
return VK_FALSE;
return false;
}
/**
* @brief Behandelt Debug callbacks von Vulkan und stellt sie in einem vereinheitlichten Format dar.
*/
* @brief Behandelt Debug callbacks von Vulkan und stellt sie in einem vereinheitlichten Format dar.
*/
VKAPI_ATTR vk::Bool32 VKAPI_CALL debugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
VkDebugUtilsMessageTypeFlagsEXT messageType,
const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData,
......@@ -88,11 +82,11 @@ lib::CgContext::CgContext(const AppCreateInfo &info, GLFWwindow *window) : windo
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = dl.getProcAddress<PFN_vkGetInstanceProcAddr>("vkGetInstanceProcAddr");
VULKAN_HPP_DEFAULT_DISPATCHER.init(vkGetInstanceProcAddr);
Log("Starting %\nVersion: %.%.%\nTimeStamp: %\nBuildType: %",
this->appInfo.appName,
version::Major, version::Minor, version::Patch,
version::TimeStamp,
version::Type);
lib::log::Info("Starting %\nVersion: %.%.%\nTimeStamp: %\nBuildType: %",
this->appInfo.appName,
version::Major, version::Minor, version::Patch,
version::TimeStamp,
version::Type);
try
{
......@@ -106,6 +100,8 @@ lib::CgContext::CgContext(const AppCreateInfo &info, GLFWwindow *window) : windo
this->CreateImageViews();
this->CreateUniformBuffers();
this->CreateCommandPool();
this->CreateRasterizationRenderPass();
this->CreateRasterizationFrameBuffers();
this->LoadDummyTexture();
this->modelLoaded = this->TryLoadModel();
......@@ -127,15 +123,15 @@ lib::CgContext::CgContext(const AppCreateInfo &info, GLFWwindow *window) : windo
this->CreateSyncObjects();
this->InitializeImGui();
this->frameIndex = 0;
Log("Successfully initialized Vulkan!");
lib::log::Info("Successfully initialized Vulkan!");
}
catch (CoreInitException &e)
{
LogError("Failed to initialize Vulkan!\nReason: %", e.what());
lib::log::Error("Failed to initialize Vulkan!\nReason: %", e.what());
}
catch (std::exception &e)
{
LogError("Failed to initialize Vulkan after unhandled exception!\n What: %!", e.what());
lib::log::Error("Failed to initialize Vulkan after unhandled exception!\n What: %!", e.what());
}
}
......@@ -225,9 +221,15 @@ lib::CgContext::~CgContext()
void lib::CgContext::CleanupSwapChain()
{
for (const auto &frame : this->frames)
for (auto &frame : this->frames)
{
this->logicalDevice.freeCommandBuffers(frame.commandPool, frame.commandBuffer);
if (frame.swapChainFramebufferForRasterizationRenderPass)
{
this->logicalDevice.destroyFramebuffer(frame.swapChainFramebufferForRasterizationRenderPass);
frame.swapChainFramebufferForRasterizationRenderPass = nullptr;
}
}
if (this->shaderBindingTableBuffer)
......@@ -260,6 +262,12 @@ void lib::CgContext::CleanupSwapChain()
this->rasterizationStep.pipelineLayout = nullptr;
}
if (this->rasterizationStep.renderPass)
{
this->logicalDevice.destroyRenderPass(this->rasterizationStep.renderPass);
this->rasterizationStep.renderPass = nullptr;
}
if (this->raytracingStep.descriptorPool)
{
this->logicalDevice.destroyDescriptorPool(this->raytracingStep.descriptorPool);
......@@ -272,12 +280,17 @@ void lib::CgContext::CleanupSwapChain()
this->rasterizationStep.descriptorPool = nullptr;
}
for (const auto &frame : this->frames)
for (auto &frame : this->frames)
{
if (frame.swapChainImageView)
{
this->logicalDevice.destroyImageView(frame.swapChainImageView);
}
if (frame.raytracingTexture)
{
frame.raytracingTexture.reset();
}
}
if (this->swapChain)
......@@ -324,6 +337,8 @@ void lib::CgContext::RecreateSwapChain()
this->CreateSwapChain();
this->CreateImageViews();
this->CreateRasterizationRenderPass();
this->CreateRasterizationFrameBuffers();
if (!this->modelLoaded)
{
......@@ -405,17 +420,28 @@ void lib::CgContext::CreateInstance()
if (this->appInfo.validationInfo.useValidationLayers)
{
if (this->CheckLayer("VK_LAYER_LUNARG_standard_validation"))
constexpr auto newLayer = "VK_LAYER_KHRONOS_validation";
constexpr auto legacyLayer = "VK_LAYER_LUNARG_standard_validation";
if (this->CheckLayer(newLayer))
{
usedLayers.Add("VK_LAYER_LUNARG_standard_validation");
usedLayers.Add(newLayer);
lib::log::Info("Using Khronos validation.");
}
else if (this->CheckLayer(legacyLayer))
{
usedLayers.Add(legacyLayer);
lib::log::Info("Using legacy lunarG validation.");
}
else if (this->appInfo.validationInfo.requireValidationLayers)
{
throw CoreInitException("Not all required Layers are available!");
throw CoreInitException("Validation layers were required, but failed to load any!");
}
else
{
LogWarning("Not all required Layers are available!");
lib::log::Warning("Validation layers could not be loaded, but were not required.");
}
}
......@@ -429,7 +455,7 @@ void lib::CgContext::CreateInstance()
this->instance = vk::createInstance(createInfo);
Log("Successfully created vulkan instance!");
lib::log::Info("Successfully created vulkan instance!");
VULKAN_HPP_DEFAULT_DISPATCHER.init(this->instance);
......@@ -443,10 +469,20 @@ void lib::CgContext::SetupDebugCallbacks()
{
vk::DebugUtilsMessengerCreateInfoEXT createInfo;
lib::log::SetLoggingStatus(this->appInfo.loggingInfo.debugEnabled,
this->appInfo.loggingInfo.infosEnabled,
this->appInfo.loggingInfo.warningsEnabled,
this->appInfo.loggingInfo.errorsEnabled);
auto log = lib::log::GetState();
log.debug.enabled = this->appInfo.loggingInfo.debugEnabled;
log.debug.prefix = lib::ansiColors::White + log.debug.prefix;
log.debug.suffix = lib::ansiColors::Reset;
log.info.enabled = this->appInfo.loggingInfo.infosEnabled;
log.info.prefix = lib::ansiColors::Green + log.info.prefix;
log.info.suffix = lib::ansiColors::Reset;
log.warning.enabled = this->appInfo.loggingInfo.warningsEnabled;
log.warning.prefix = lib::ansiColors::Yellow + log.warning.prefix;
log.warning.suffix = lib::ansiColors::Reset;
log.error.enabled = this->appInfo.loggingInfo.errorsEnabled;
log.error.prefix = lib::ansiColors::Red + log.error.prefix;
log.error.suffix = lib::ansiColors::Reset;
if (this->appInfo.loggingInfo.debugEnabled)
{
......@@ -463,11 +499,6 @@ void lib::CgContext::SetupDebugCallbacks()
createInfo.messageSeverity |= vk::DebugUtilsMessageSeverityFlagBitsEXT::eError;
}
if (this->appInfo.loggingInfo.infosEnabled)
{
createInfo.messageSeverity |= vk::DebugUtilsMessageSeverityFlagBitsEXT::eInfo;
}
createInfo.messageType = vk::DebugUtilsMessageTypeFlagBitsEXT::eGeneral |
vk::DebugUtilsMessageTypeFlagBitsEXT::eValidation |
vk::DebugUtilsMessageTypeFlagBitsEXT::ePerformance;
......@@ -476,7 +507,7 @@ void lib::CgContext::SetupDebugCallbacks()
this->debugMessenger = this->instance.createDebugUtilsMessengerEXT(createInfo, nullptr);
Log("Successfully set up debug callbacks!");
lib::log::Info("Successfully set up debug callbacks!");
}
void lib::CgContext::FindPhysicalDevice()
......@@ -516,9 +547,9 @@ void lib::CgContext::FindPhysicalDevice()
{
auto rating = deviceInfo.Rate(deviceRequirements);
Log("Found device \"%\" with rating %",
deviceInfo.GetName(),
rating);
lib::log::Info("Found device \"%\" with rating %",
deviceInfo.GetName(),
rating);
if (rating > 0 &&
(!best.info || rating > best.rating))
......@@ -533,11 +564,11 @@ void lib::CgContext::FindPhysicalDevice()
throw CoreInitException("Could not find any suitable device!");
}
Log("Best device is \"%\", with a score of %.\n\twith max recursion depth %\n\twith max triangle count %",
best.info->GetName(),
best.rating,
best.info->GetRaytracingProperties().maxRecursionDepth,
best.info->GetRaytracingProperties().maxTriangleCount);
lib::log::Info("Best device is \"%\", with a score of %.\n\twith max recursion depth %\n\twith max triangle count %",
best.info->GetName(),
best.rating,
best.info->GetRaytracingProperties().maxRecursionDepth,
best.info->GetRaytracingProperties().maxTriangleCount);
this->physicalDeviceInfo = *best.info;
}
......@@ -580,7 +611,7 @@ void lib::CgContext::CreateLogicalDevice()
VULKAN_HPP_DEFAULT_DISPATCHER.init(this->logicalDevice);
Log("Successfully created logical device!");
lib::log::Info("Successfully created logical device!");
}
void lib::CgContext::CreateQueues()
......@@ -590,7 +621,7 @@ void lib::CgContext::CreateQueues()
this->bufferStagingQueue = this->logicalDevice.getQueue(this->physicalDeviceInfo.GetBufferStagingQueueFamily(), 0);
this->computeQueue = this->logicalDevice.getQueue(this->physicalDeviceInfo.GetComputeQueueFamily(), 0);
Log("Successfully created queues!");
lib::log::Info("Successfully created queues!");
}
void lib::CgContext::CreateSurface()
......@@ -605,7 +636,7 @@ void lib::CgContext::CreateSurface()
this->surface = surface;
Log("Successfully created window surface!");
lib::log::Info("Successfully created window surface!");
}
void lib::CgContext::CreateSwapChain()
......@@ -654,7 +685,7 @@ void lib::CgContext::CreateSwapChain()
this->swapChainImageFormat = createInfo.imageFormat;
this->swapChain = this->logicalDevice.createSwapchainKHR(createInfo);
Log("Successfully created swap chain!");
lib::log::Info("Successfully created swap chain!");
const auto swapChainImages = this->logicalDevice.getSwapchainImagesKHR(this->swapChain);
......@@ -665,7 +696,7 @@ void lib::CgContext::CreateSwapChain()
this->frames[i].swapChainImage = swapChainImages[i];
}
Log("Successfully acquired swap chain images!");
lib::log::Info("Successfully acquired swap chain images!");
}
void lib::CgContext::CreateImageViews()
......@@ -675,7 +706,7 @@ void lib::CgContext::CreateImageViews()
frame.swapChainImageView = lib::CreateImageView(this->logicalDevice, frame.swapChainImage, this->swapChainImageFormat);
}
Log("Successfully created all image views!");
lib::log::Info("Successfully created all image views!");
}
void lib::CgContext::CreateCommandPool()
......@@ -695,7 +726,7 @@ void lib::CgContext::CreateCommandPool()
vk::CommandPoolCreateFlagBits::eTransient,
this->physicalDeviceInfo.GetBufferStagingQueueFamily()));
Log("Successfully created command pools!");
lib::log::Info("Successfully created command pools!");
}
void lib::CgContext::UpdateCommandBuffer(uint32_t imageIndex)
......@@ -709,61 +740,68 @@ void lib::CgContext::UpdateCommandBuffer(uint32_t imageIndex)
frame.commandBuffer.begin(beginInfo);
if (this->IsOk())
{
frame.commandBuffer.bindPipeline(vk::PipelineBindPoint::eRayTracingNV, this->raytracingStep.pipeline);
frame.commandBuffer.bindDescriptorSets(vk::PipelineBindPoint::eRayTracingNV, this->raytracingStep.pipelineLayout,
0, frame.descriptorSet, {});
}
// if (this->IsOk())
// {
// frame.commandBuffer.bindPipeline(vk::PipelineBindPoint::eRayTracingNV, this->raytracingStep.pipeline);
// frame.commandBuffer.bindDescriptorSets(vk::PipelineBindPoint::eRayTracingNV,
// this->raytracingStep.pipelineLayout,
// 0, frame.raytracingDescriptorSet,
// {});
// TransitionImageLayout(frame.commandBuffer,
// frame.raytracingTexture->GetHandle(), this->swapChainImageFormat,
// vk::ImageLayout::eUndefined, vk::ImageLayout::eGeneral,
// vk::PipelineStageFlagBits::eTopOfPipe,
// vk::PipelineStageFlagBits::eRayTracingShaderNV);
// frame.ubo->ScheduleTransfer(frame.commandBuffer);
// frame.commandBuffer.pushConstants(this->raytracingStep.pipelineLayout,
// vk::ShaderStageFlagBits::eRaygenNV | vk::ShaderStageFlagBits::eClosestHitNV,
// 0, sizeof(this->pushConstant),
// &this->pushConstant);
// auto sbtEntrySize = this->physicalDeviceInfo.GetRaytracingProperties().shaderGroupBaseAlignment;
// frame.commandBuffer.traceRaysNV(this->shaderBindingTableBuffer->GetBufferHandle(), this->shaderOffsets.rayGen * sbtEntrySize,
// this->shaderBindingTableBuffer->GetBufferHandle(), this->shaderOffsets.miss * sbtEntrySize, sbtEntrySize,