...
 
Commits (4)
...@@ -70,6 +70,7 @@ add_library( ...@@ -70,6 +70,7 @@ add_library(
src/Lib/src/VkUtil/VkResult.cpp src/Lib/src/VkUtil/VkResult.cpp
src/Lib/src/VkUtil/Buffer.cpp src/Lib/src/VkUtil/Buffer.cpp
src/Lib/src/VkUtil/Texture.cpp src/Lib/src/VkUtil/Texture.cpp
src/Lib/src/VkUtil/RenderTarget.cpp
src/Lib/src/VkUtil/StagedBuffer.cpp src/Lib/src/VkUtil/StagedBuffer.cpp
src/Lib/src/VkUtil/OneTimeCommandBuffer.cpp src/Lib/src/VkUtil/OneTimeCommandBuffer.cpp
src/Lib/src/VkUtil/StbImageImpl.cpp src/Lib/src/VkUtil/StbImageImpl.cpp
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
layout(location = 0) in vec2 texCoord; layout(location = 0) in vec2 texCoord;
layout(location = 0) out vec4 color; layout(location = 0) out vec4 color;
layout(binding = 0) uniform sampler2D texSampler; layout(binding = 0) uniform sampler2D texSampler[4];
void main() { void main() {
vec2 offsets[9] = { vec2 offsets[9] = {
...@@ -25,12 +25,12 @@ void main() { ...@@ -25,12 +25,12 @@ void main() {
1.0 / 84.0, 4.0 / 84.0, 1.0 / 84.0, 1.0 / 84.0, 4.0 / 84.0, 1.0 / 84.0,
}; };
vec2 relativePixelSize = vec2(1.0) / textureSize(texSampler, 0); vec2 relativePixelSize = vec2(1.0) / textureSize(texSampler[0], 0);
vec4 samples[9]; vec4 samples[9];
for(int i = 0; i < 9; i++) { for(int i = 0; i < 9; i++) {
samples[i] = texture(texSampler, texCoord + offsets[i] * relativePixelSize); samples[i] = texture(texSampler[0], texCoord + offsets[i] * relativePixelSize);
} }
vec3 edge = vec3(0); vec3 edge = vec3(0);
...@@ -50,6 +50,6 @@ void main() { ...@@ -50,6 +50,6 @@ void main() {
res = l * blur + (1 - l) * samples[5].rgb; res = l * blur + (1 - l) * samples[5].rgb;
color = vec4(vec3(samples[5].a * 0.5), 1.0); // color = vec4(vec3(samples[5].a * 0.5), 1.0);
// color = vec4(res, 1.0); color = vec4(res, 1.0);
} }
\ No newline at end of file
\section{Bewertung} \section{Bewertung}
Die beiden Umsetzungen sollen danach entsprechend der folgenden Kriterien bewertet werden: Die beiden Umsetzungen sollen danach entsprechend der folgenden Kriterien bewertet und mit bestehenden
Verfahren verglichen werden.
% %
\paragraph{Qualität:} \paragraph{Qualität:}
\begin{enumerate} \begin{enumerate}
...@@ -15,3 +16,9 @@ Die beiden Umsetzungen sollen danach entsprechend der folgenden Kriterien bewert ...@@ -15,3 +16,9 @@ Die beiden Umsetzungen sollen danach entsprechend der folgenden Kriterien bewert
\item Gibt es noch Optimierungspotenzial? \item Gibt es noch Optimierungspotenzial?
\end{enumerate} \end{enumerate}
% %
\paragraph{Vergleich zu rasterbasierten Techniken:}
\begin{enumerate}
\item Liefert das Verfahren optisch bessere/detailliertere Ergebnisse?
\item Sind die Performancekosten in Bezug auf das erreichte Ergebnis mit bestehenden Verfahren
vergleichbar? Wie ist das \gquote{Kosten-Nutzen-Verhältnis}?
\end{enumerate}
\ No newline at end of file
...@@ -9,14 +9,13 @@ ...@@ -9,14 +9,13 @@
\item Hardwareunterstützung \item Hardwareunterstützung
\end{enumerate} \end{enumerate}
% %
\item Die Rendergleichung und ihre Umsetzung mittels Raytracing \item Die Rendergleichung und ihre (annähernde) Umsetzung mittels Raytracing
\item Implementierungsgrundlagen eines Raytracers mit Vulkan \& NVIDIA-Erweiterung \item Implementierungsgrundlagen eines Raytracers mit Vulkan \& NVIDIA-Erweiterung
% %
\item Darstellung von Strahlenbüscheln \item Darstellung von Strahlenbüscheln
\begin{enumerate} \begin{enumerate}
\item Physikalische Grundlagen \item Physikalische Grundlagen
\item Bisherige Forschung \item Bisherige Forschung
%
\item Umsetzung durch Raytracing im Medium \item Umsetzung durch Raytracing im Medium
% %
\begin{enumerate} \begin{enumerate}
...@@ -42,10 +41,4 @@ ...@@ -42,10 +41,4 @@
\end{enumerate} \end{enumerate}
% %
\item Anhänge, Quellen, etc. \item Anhänge, Quellen, etc.
\end{enumerate} \end{enumerate}
% \ No newline at end of file
% http://graphics.cs.aueb.gr/graphics/docs/papers/GraphiCon09_PapadopoulosPapaioannou.pdf
% https://graphics.stanford.edu/courses/cs348b-03/papers/veach-chapter9.pdf
% http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.671.766&rep=rep1&type=pdf
% https://nvpro-samples.github.io/vk_raytracing_tutorial/vkrt_tuto_intersection.md.html#environmentsetup/intersectionshader
% https://www.saschawillems.de/blog/2016/08/13/vulkan-tutorial-on-rendering-a-fullscreen-quad-without-buffers/
\ No newline at end of file
...@@ -12,9 +12,9 @@ extrem bereichern. ...@@ -12,9 +12,9 @@ extrem bereichern.
\\ \\
Der Effekt lässt sich auch gut während der Morgen- und Abenddämmerung beobachten. Der Effekt lässt sich auch gut während der Morgen- und Abenddämmerung beobachten.
Auch unter Wasser oder wenn die Sonne in einen nebligen Wald scheint, lässt sich der Effekt Auch unter Wasser oder wenn die Sonne in einen nebligen Wald scheint, lässt sich der Effekt
beobachten. Ein künstlich erzeugtes Beispiel ist die Sichtbarmachung de Verlaufs eines Lasers durch Staub beobachten. Ein künstlich erzeugtes Beispiel ist die Sichtbarmachung des Verlaufs eines Lasers durch Staub
oder Puder. Der Effekt lässt sich auch umgekehrt beobachten, das heißt, dass der Großteil eines Mediums von oder Puder. Der Effekt lässt sich auch umgekehrt beobachten, das heißt, dass der Großteil eines Mediums von
Strahlenbüscheln erfüllt ist, dadurch heller aussieht und es aussieht als würden Objekte Schatten im Medium Strahlenbüscheln erfüllt ist, dadurch heller wirkt und es aussieht als würden Objekte Schatten im Medium
erzeugen. Hieraus folgt auch die Überlegung, dass die Streuung von Licht im Medium praktisch immer auftritt, erzeugen. Hieraus folgt auch die Überlegung, dass die Streuung von Licht im Medium praktisch immer auftritt,
jedoch normalerweise unbemerkt bleibt, weil das Licht an jedem Punkt des Mediums ähnlich gestreut wird. jedoch normalerweise unbemerkt bleibt, weil das Licht an jedem Punkt des Mediums ähnlich gestreut wird.
...@@ -31,4 +31,4 @@ Dieser Effekt soll nun computergrafisch dargestellt, also in eine Szene gerender ...@@ -31,4 +31,4 @@ Dieser Effekt soll nun computergrafisch dargestellt, also in eine Szene gerender
natürlich sehr einfache Möglichkeiten, wie eine zuvor erzeugte Textur an einen bestimmten Platz zu rendern und natürlich sehr einfache Möglichkeiten, wie eine zuvor erzeugte Textur an einen bestimmten Platz zu rendern und
sehr aufwändige wie die physikalisch plausible Berechnung von Lichtbrechungen.\\ sehr aufwändige wie die physikalisch plausible Berechnung von Lichtbrechungen.\\
Das Ziel dieser Arbeit soll die Entwicklung eines Algorithmus' sein, der den oben besprochenen Effekt Das Ziel dieser Arbeit soll die Entwicklung eines Algorithmus' sein, der den oben besprochenen Effekt
physikalisch plausibel in beliebigen Szenen darstellen kann. physikalisch plausibel in beliebigen Szenen darstellen kann und dazu primär Raytracing nutzt.
\ No newline at end of file \ No newline at end of file
...@@ -43,14 +43,14 @@ Berechnung im Lightspace vorgenommen und nicht mittels Raytracing ausgeführt. ...@@ -43,14 +43,14 @@ Berechnung im Lightspace vorgenommen und nicht mittels Raytracing ausgeführt.
In diesem Video sagt Eric Haines in Bezug auf grafische Effekte beim Raytracing: In diesem Video sagt Eric Haines in Bezug auf grafische Effekte beim Raytracing:
% %
\begin{quote} \begin{quote}
You can also atmospheric effects, so if, say you have a beam of light, you can do a thing called ray You can also do atmospheric effects, so if, say you have a beam of light, you can do a thing called ray
marching, where the ray hits the beam, marches through it and light scattering in and light scattering out marching, where the ray hits the beam, marches through it and light scattering in and light scattering out
and so and you just kind of walk through that thing and sample it as you go. And you can get these nice beams and so and you just kind of walk through that thing and sample it as you go. And you can get these nice beams
of light, godrays, kind of effects. of light, godrays, kind of effects.
\end{quote} \end{quote}
% %
\paragraph{Anmerkung:} Der Begriff \gquote{ray marching} ist nicht eindeutig. \paragraph{Anmerkung:} Der Begriff \gquote{ray marching} ist nicht eindeutig.
Prinzipiell beschreibt es - wie der Name vermuten lässt - eine Familie von Techniken, bei denen eine Strahl Prinzipiell beschreibt es - wie der Name vermuten lässt - eine Familie von Techniken, bei denen ein Strahl
abgetastet wird, bzw. bei denen entlang eines Strahls eine Funktion berechnet wird. Häufig wird die Technik abgetastet wird, bzw. bei denen entlang eines Strahls eine Funktion berechnet wird. Häufig wird die Technik
genutzt um den Schnittpunkt eines Strahls mit der Szene zu bestimmen (z.B. wenn die Objekte der Szene nicht genutzt um den Schnittpunkt eines Strahls mit der Szene zu bestimmen (z.B. wenn die Objekte der Szene nicht
als Dreiecke sondern als mathematische Definitionen vorliegen). als Dreiecke sondern als mathematische Definitionen vorliegen).
...@@ -80,18 +80,36 @@ ausgewertet und für den gesamten Block genutzt. ...@@ -80,18 +80,36 @@ ausgewertet und für den gesamten Block genutzt.
% %
\subsection{Interactive Volumetric Shadows in Participating Media with Single-Scattering} \subsection{Interactive Volumetric Shadows in Participating Media with Single-Scattering}
\label{interactiveVolumetricShadowsInParticipatingMediaWithSingleScattering} \label{interactiveVolumetricShadowsInParticipatingMediaWithSingleScattering}
\paragraph{Quelle:}C. Wyman and S. Ramsey, \paragraph{Quelle:}C. Wyman and S. Ramsey,
\gquote{Interactive volumetric shadows in participating media with single-scattering,} 2008 IEEE Symposium on \gquote{Interactive volumetric shadows in participating media with single-scattering,} 2008 IEEE Symposium on
Interactive Ray Tracing, Los Angeles, CA, 2008, pp. 87-92, doi: 10.1109/RT.2008.4634627. Interactive Ray Tracing, Los Angeles, CA, 2008, pp. 87-92, doi: 10.1109/RT.2008.4634627.
\paragraph{Technik} \paragraph{Technik}
Wyman und Ramsey nutzen Raymarching wie Tóth und Umenhoffer (siehe Wyman und Ramsey nutzen Raymarching wie Tóth und Umenhoffer (siehe
\ref{ss:realTimeVolumetricLightingInParticipatingMedia}), verbessern das Verfahren jedoch durch den Einsatz \ref{ss:realTimeVolumetricLightingInParticipatingMedia}), verbessern das Verfahren jedoch durch den Einsatz
von Schattenvolumen. Dahinter steht die Überlegung, dass Bereiche im Schatten keinen Beitrag zum eingestreuten von Schattenvolumen. Dahinter steht die Überlegung, dass Bereiche im Schatten keinen Beitrag zum eingestreuten
Licht liefern und es daher reicht, die beleuchteten Bereiche zu sampeln. Diese Technik könnte auch helfen, Licht liefern und es daher reicht, die beleuchteten Bereiche zu sampeln. Diese Technik könnte auch helfen,
beim Einsatz mit Raytracing die benötigten Sampel zu reduzieren. Jedoch erzeugt das Rendern von beim Einsatz mit Raytracing die benötigten Sampel zu reduzieren. Jedoch erzeugt das Rendern von
Schattenvolumen auch gewisse Kosten und ist bei Szenen mit detaillierten Szenen (wie z.B. Gartenzäune) wenig Schattenvolumen auch gewisse Kosten und ist bei detaillierten Szenen mit vielen abwechselnd beleuchteten und
nützlich. In diesem Fall, so Wyman und Ramsey, verkommt der Algorithmus zu herkömmlichem Raymarching. Ein beschatteten Bereichen (wie z.B. entlang eines Gartenzaunes) wenig
nützlich. In diesem Fall, so Wyman und Ramsey, verkommt der Algorithmus zu herkömmlichem Raymarching. Ein
anderer Aspekt ist, dass detaillierte Schatten gerade eine Stärke von Raytracing sind und der Einsatz von anderer Aspekt ist, dass detaillierte Schatten gerade eine Stärke von Raytracing sind und der Einsatz von
Schattenvolumen diesen Vorteil ignorieren würde. Jedoch lässt sich dieser Ansatz vielleicht irgendwie Schattenvolumen diesen Vorteil ignorieren würde. Jedoch lässt sich dieser Ansatz vielleicht irgendwie
einsetzen um die Sample entlang eines Strahls \gquote{intelligenter} zu verteilen und - wie im Paper einsetzen um die Sample entlang eines Strahls \gquote{intelligenter} zu verteilen und - wie im Paper
vorgestellt - weniger redundante Samples auszuwerten. vorgestellt - weniger redundante Samples auszuwerten.
%
\subsubsection{Raytracing Gems}
\label{ss:RaytracingGems}
\paragraph{Quelle:} Eric Haines and Tomas Akenine-Möller (2019). Ray Tracing Gems. Apress.
\paragraph{Homepage:}\url{https://www.realtimerendering.com/raytracinggems/}
\paragraph{Inhalt:}
Das Buch fokussiert sich auf allgemeine (jedoch weit fortgeschrittene) Techniken rund ums Raytracing und
bietet damit eine wichtige Quelle. Nach einem ersten Überfliegen existiert kein Kapitel über das Rendern von
Strahlenbüscheln. Wichtig sind jedoch die dort aufgeführten Techniken zur Reduktion der genutzten Strahlen
und diverse Ausführungen zu hybriden Rendertechniken. Dabei sticht vor allem die temporale
Reprojektion heraus, dies ist eine Technik, bei der der Inhalt von früheren Bildern zum Rendern des aktuellen
Bildes genutzt wird. Eine dargestellte Anwendung (Kapitel 13 \gquote{Ray Traced Shadows: Maintaining
Real-Time Frame Rates}) bestand darin, aus alten Bildern zu bestimmen, welche Teile einer Szene im Licht,
im Kernschatten, bzw. im Halbschatten liegen. Für Bereiche, die im Kernschatten oder im Licht liegen reicht
es pro Pixelgruppe einen \gquote{Kontrollstrahl} zu nutzen, für Pixel im Halbschatten werden mehrere Strahlen
pro Pixel genutzt um diese Bereiche realistischer zu rendern. Eine Technik die sich auch nutzen ließe
um die Anzahl von Sampeln pro Frame in einem Medium zu reduzieren.
...@@ -55,8 +55,8 @@ Vorgehen ist das folgende: ...@@ -55,8 +55,8 @@ Vorgehen ist das folgende:
% %
Dabei ist natürlich vor allem auf die Performance zu achten. Je mehr Schattenfühler genutzt werden, desto Dabei ist natürlich vor allem auf die Performance zu achten. Je mehr Schattenfühler genutzt werden, desto
genauer wird das Ergebnis, desto teurer wird jedoch auch die Berechnung. Auch für die genaue Art der genauer wird das Ergebnis, desto teurer wird jedoch auch die Berechnung. Auch für die genaue Art der
Verrechnung der einzelnen Samples muss eine Formel gesucht werden. Optimierungspotenzial liegt in redundanten Verrechnung der einzelnen Samples muss eine Formel gesucht werden. Optimierungspotenzial liegt in der
Schattenfühlern, bzw. viele ähnliche Schattenfühlern. Reduzierung redundanter bzw. sehr ähnlicher Schattenfühler.
\subsection{Umsetzung mittels Berechnung von der Lichtquelle aus} \subsection{Umsetzung mittels Berechnung von der Lichtquelle aus}
Der zweite Lösungsansatz verfolgt einen ähnlichen Ansatz wie Photon-Mapping, indem versucht wird die Der zweite Lösungsansatz verfolgt einen ähnlichen Ansatz wie Photon-Mapping, indem versucht wird die
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include "VkUtil/TopLevelAccelerationStructure.hpp" #include "VkUtil/TopLevelAccelerationStructure.hpp"
#include "VkUtil/VkUtil.hpp" #include "VkUtil/VkUtil.hpp"
#include "VkUtil/Texture.hpp" #include "VkUtil/Texture.hpp"
#include "VkUtil/RenderTarget.hpp"
#include "imgui_impl_vulkan.h" #include "imgui_impl_vulkan.h"
namespace lib namespace lib
...@@ -191,7 +192,6 @@ namespace lib ...@@ -191,7 +192,6 @@ namespace lib
const uint32_t lightSources = 5; const uint32_t lightSources = 5;
const uint32_t vertices = 6; const uint32_t vertices = 6;
const uint32_t indices = 7; const uint32_t indices = 7;
const uint32_t dummyTexture = 8;
} const descriptorBindings; } const descriptorBindings;
struct struct
...@@ -203,6 +203,9 @@ namespace lib ...@@ -203,6 +203,9 @@ namespace lib
} shaderOffsets; } shaderOffsets;
std::unique_ptr<lib::Buffer> shaderBindingTableBuffer; std::unique_ptr<lib::Buffer> shaderBindingTableBuffer;
const uint32_t temporalInterpolationCount = 4;
uint32_t temporalInterpolationImageIndex = 0;
std::vector<lib::TemporalInterpolationFrame> temporalInterpolationFrames;
bool modelLoaded; bool modelLoaded;
bool shadersLoaded; bool shadersLoaded;
...@@ -288,7 +291,7 @@ namespace lib ...@@ -288,7 +291,7 @@ namespace lib
bool IsOk() const; bool IsOk() const;
bool IsRecoverable() const; bool IsRecoverable() const;
void UpdateCommandBuffer(uint32_t imageIndex); void UpdateCommandBuffer(uint32_t imageIndex, uint32_t temporalInterpolationImageIndex);
void BeginFrame(); void BeginFrame();
void DrawFrame(lib::time_diff_t diff); void DrawFrame(lib::time_diff_t diff);
void EndFrame(); void EndFrame();
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
#include <memory> #include <memory>
#include "VkUtil/Texture.hpp" #include "VkUtil/RenderTarget.hpp"
#include "GlfwAndVulkan.hpp" #include "GlfwAndVulkan.hpp"
#include "VkUtil/StagedBuffer.hpp" #include "VkUtil/StagedBuffer.hpp"
...@@ -10,18 +10,23 @@ namespace lib ...@@ -10,18 +10,23 @@ namespace lib
{ {
struct Frame struct Frame
{ {
std::unique_ptr<lib::StagedBuffer> ubo;
vk::CommandPool commandPool; vk::CommandPool commandPool;
vk::CommandBuffer commandBuffer; vk::CommandBuffer commandBuffer;
vk::Fence inFlightFence; vk::Fence inFlightFence;
vk::DescriptorSet raytracingDescriptorSet;
vk::DescriptorSet rasterizationDescriptorSet;
vk::Image swapChainImage; vk::Image swapChainImage;
vk::ImageView swapChainImageView; vk::ImageView swapChainImageView;
vk::Framebuffer swapChainFramebufferForRasterizationRenderPass; vk::Framebuffer swapChainFramebufferForRasterizationRenderPass;
vk::Framebuffer swapChainFramebufferForImGui; vk::Framebuffer swapChainFramebufferForImGui;
};
std::unique_ptr<lib::Texture> raytracingTexture; struct TemporalInterpolationFrame
{
vk::DescriptorSet raytracingDescriptorSet;
vk::DescriptorSet rasterizationDescriptorSet;
std::unique_ptr<lib::RenderTarget> raytracingRenderTarget;
// TODO gehört eigentlich zum Frame, nicht zum TemporalInterpolationFrame
std::unique_ptr<lib::StagedBuffer> ubo;
}; };
} // namespace lib } // namespace lib
#pragma once
#include "GlfwAndVulkan.hpp"
#include "VkUtil/Texture.hpp"
#include <vector>
#include <map>
namespace lib
{
class RenderTarget : public lib::Texture
{
private:
std::map<vk::RenderPass, vk::Framebuffer> framebuffersByRenderPass;
vk::Semaphore semaphore;
void CreateFramebufferForRenderPass(vk::RenderPass renderPass);
public:
RenderTarget(CgContext *parent, uint32_t width, uint32_t height, const lib::TextureCreateInfo &textureCreateInfo);
RenderTarget(const RenderTarget &copy) = delete;
RenderTarget(RenderTarget &&move) = delete;
~RenderTarget();
RenderTarget &operator=(const RenderTarget &copy) = delete;
RenderTarget &operator=(RenderTarget &&move) = delete;
const vk::Semaphore &GetSemaphore() const;
const vk::Framebuffer &GetFrameBufferForRenderPass(const vk::RenderPass &renderpass) const;
void CreateFramebuffersForRenderPasses(const std::initializer_list<vk::RenderPass> &renderpasses);
template <typename TForwardIt>
void CreateFramebuffersForRenderPasses(TForwardIt begin, TForwardIt end)
{
for (; begin != end; ++begin)
{
this->CreateFramebufferForRenderPass(*begin);
}
}
};
} // namespace lib
...@@ -69,6 +69,9 @@ namespace lib ...@@ -69,6 +69,9 @@ namespace lib
vk::DeviceMemory memory; vk::DeviceMemory memory;
vk::Sampler sampler; vk::Sampler sampler;
uint32_t width;
uint32_t height;
protected: protected:
CgContext *parent; CgContext *parent;
...@@ -137,16 +140,20 @@ namespace lib ...@@ -137,16 +140,20 @@ namespace lib
Texture(Texture &&) = delete; Texture(Texture &&) = delete;
Texture(const Texture &) = delete; Texture(const Texture &) = delete;
~Texture(); ~Texture();
Texture &operator=(Texture &&) = delete;
Texture &operator=(const Texture &) = delete;
const vk::Image &GetHandle() const; const vk::Image &GetHandle() const;
const vk::ImageView &GetView() const; const vk::ImageView &GetView() const;
const vk::Sampler &GetSampler() const; const vk::Sampler &GetSampler() const;
Texture &operator=(Texture &&) = delete; uint32_t GetHeight() const;
Texture &operator=(const Texture &) = delete;
uint32_t GetWidth() const;
}; // namespace lib }; // namespace lib
} // namespace lib } // namespace lib
...@@ -158,7 +158,7 @@ bool lib::CgContext::TryCreateRasterizerPipeline() ...@@ -158,7 +158,7 @@ bool lib::CgContext::TryCreateRasterizerPipeline()
void lib::CgContext::CreateRasterizationDescriptorSets() void lib::CgContext::CreateRasterizationDescriptorSets()
{ {
const auto count = static_cast<uint32_t>(this->frames.size()); const auto count = static_cast<uint32_t>(this->temporalInterpolationFrames.size());
std::vector<vk::DescriptorSetLayout> layouts(count, this->rasterizationStep.descriptorSetLayout); std::vector<vk::DescriptorSetLayout> layouts(count, this->rasterizationStep.descriptorSetLayout);
...@@ -170,27 +170,41 @@ void lib::CgContext::CreateRasterizationDescriptorSets() ...@@ -170,27 +170,41 @@ void lib::CgContext::CreateRasterizationDescriptorSets()
auto sets = this->logicalDevice.allocateDescriptorSets(allocateInfo); auto sets = this->logicalDevice.allocateDescriptorSets(allocateInfo);
auto setsIt = std::begin(sets); auto setsIt = std::begin(sets);
for (auto &frame : this->frames) for (size_t i = 0; i < count; i++)
{ {
auto &frame = this->temporalInterpolationFrames[i];
frame.rasterizationDescriptorSet = *setsIt++; frame.rasterizationDescriptorSet = *setsIt++;
vk::DescriptorImageInfo rtImageInfo; std::vector<vk::DescriptorImageInfo> imageInfos;
rtImageInfo.imageLayout = vk::ImageLayout::eGeneral; std::vector<vk::WriteDescriptorSet> writes;
rtImageInfo.imageView = frame.raytracingTexture->GetView();
rtImageInfo.sampler = frame.raytracingTexture->GetSampler();
// rtImageInfo.imageView = this->dummyTexture->GetView(); imageInfos.reserve(temporalInterpolationCount + 1);
// rtImageInfo.sampler = this->dummyTexture->GetSampler(); writes.reserve(temporalInterpolationCount + 1);
vk::WriteDescriptorSet rtImageWrite; for (uint32_t j = 0; j < this->temporalInterpolationCount + 1; j++)
rtImageWrite.descriptorCount = 1; {
rtImageWrite.descriptorType = vk::DescriptorType::eCombinedImageSampler; auto frameIndex = this->temporalInterpolationCount > 0
rtImageWrite.dstArrayElement = 0; ? (this->temporalInterpolationCount + i - j) % this->temporalInterpolationCount
rtImageWrite.dstBinding = 0; : i;
rtImageWrite.pImageInfo = &rtImageInfo;
rtImageWrite.dstSet = frame.rasterizationDescriptorSet; auto &backFrame = this->temporalInterpolationFrames[frameIndex];
auto &info = imageInfos.emplace_back();
info.imageLayout = vk::ImageLayout::eShaderReadOnlyOptimal;
info.imageView = backFrame.raytracingRenderTarget->GetView();
info.sampler = backFrame.raytracingRenderTarget->GetSampler();
auto &imageWrite = writes.emplace_back();
imageWrite.descriptorCount = 1;
imageWrite.descriptorType = vk::DescriptorType::eCombinedImageSampler;
imageWrite.dstArrayElement = j;
imageWrite.dstBinding = 0;
imageWrite.pImageInfo = &info;
imageWrite.dstSet = frame.rasterizationDescriptorSet;
}
this->logicalDevice.updateDescriptorSets(rtImageWrite, {}); this->logicalDevice.updateDescriptorSets(writes, {});
} }
lib::log::Info("Successfully created rasterization descriptor sets!"); lib::log::Info("Successfully created rasterization descriptor sets!");
...@@ -198,10 +212,10 @@ void lib::CgContext::CreateRasterizationDescriptorSets() ...@@ -198,10 +212,10 @@ void lib::CgContext::CreateRasterizationDescriptorSets()
void lib::CgContext::CreateRasterizationDescriptorPool() void lib::CgContext::CreateRasterizationDescriptorPool()
{ {
const auto count = static_cast<uint32_t>(this->frames.size()); const auto count = static_cast<uint32_t>(this->temporalInterpolationFrames.size());
std::vector<vk::DescriptorPoolSize> poolSizes{ std::vector<vk::DescriptorPoolSize> poolSizes{
{vk::DescriptorType::eCombinedImageSampler, count}, {vk::DescriptorType::eCombinedImageSampler, count * (this->temporalInterpolationCount + 1)},
}; };
vk::DescriptorPoolCreateInfo createInfo; vk::DescriptorPoolCreateInfo createInfo;
...@@ -221,7 +235,7 @@ void lib::CgContext::CreateRasterizationDescriptorSetLayout() ...@@ -221,7 +235,7 @@ void lib::CgContext::CreateRasterizationDescriptorSetLayout()
auto &item = layoutBindings.emplace_back(); auto &item = layoutBindings.emplace_back();
item.binding = 0; item.binding = 0;
item.descriptorType = vk::DescriptorType::eCombinedImageSampler; item.descriptorType = vk::DescriptorType::eCombinedImageSampler;
item.descriptorCount = 1; item.descriptorCount = this->temporalInterpolationCount + 1;
item.stageFlags = vk::ShaderStageFlagBits::eFragment; item.stageFlags = vk::ShaderStageFlagBits::eFragment;
vk::DescriptorSetLayoutCreateInfo createInfo; vk::DescriptorSetLayoutCreateInfo createInfo;
...@@ -276,9 +290,7 @@ void lib::CgContext::CreateRasterizationRenderPass() ...@@ -276,9 +290,7 @@ void lib::CgContext::CreateRasterizationRenderPass()
void lib::CgContext::CreateRasterizationFrameBuffers() void lib::CgContext::CreateRasterizationFrameBuffers()
{ {
const auto count = static_cast<uint32_t>(frames.size()); for (auto &frame : this->temporalInterpolationFrames)
for (auto &frame : this->frames)
{ {
const lib::TextureCreateInfo textureCreateInfo{ const lib::TextureCreateInfo textureCreateInfo{
{ {
...@@ -292,13 +304,16 @@ void lib::CgContext::CreateRasterizationFrameBuffers() ...@@ -292,13 +304,16 @@ void lib::CgContext::CreateRasterizationFrameBuffers()
vk::ImageUsageFlagBits::eStorage, vk::ImageUsageFlagBits::eStorage,
vk::ImageLayout::eGeneral}; vk::ImageLayout::eGeneral};
auto newTexture = new lib::Texture{this, auto newTexture = new lib::RenderTarget{this,
this->swapChainExtent.width, this->swapChainExtent.width,
this->swapChainExtent.height, this->swapChainExtent.height,
textureCreateInfo}; textureCreateInfo};
frame.raytracingTexture.reset(newTexture); frame.raytracingRenderTarget.reset(newTexture);
}
for (auto &frame : this->frames)
{
vk::FramebufferCreateInfo createInfo; vk::FramebufferCreateInfo createInfo;
createInfo.renderPass = this->rasterizationStep.renderPass; createInfo.renderPass = this->rasterizationStep.renderPass;
createInfo.attachmentCount = 1; createInfo.attachmentCount = 1;
......
...@@ -113,13 +113,6 @@ void lib::CgContext::CreateRaytracingDescriptorSetLayout() ...@@ -113,13 +113,6 @@ void lib::CgContext::CreateRaytracingDescriptorSetLayout()
layoutBindings.back().descriptorType = vk::DescriptorType::eStorageBuffer; layoutBindings.back().descriptorType = vk::DescriptorType::eStorageBuffer;
layoutBindings.back().stageFlags = vk::ShaderStageFlagBits::eClosestHitNV; layoutBindings.back().stageFlags = vk::ShaderStageFlagBits::eClosestHitNV;
// dummy texture
layoutBindings.emplace_back();
layoutBindings.back().binding = this->descriptorBindings.dummyTexture;
layoutBindings.back().descriptorCount = 1;
layoutBindings.back().descriptorType = vk::DescriptorType::eCombinedImageSampler;
layoutBindings.back().stageFlags = vk::ShaderStageFlagBits::eClosestHitNV | vk::ShaderStageFlagBits::eRaygenNV;
vk::DescriptorSetLayoutCreateInfo createInfo; vk::DescriptorSetLayoutCreateInfo createInfo;
createInfo.bindingCount = static_cast<uint32_t>(layoutBindings.size()); createInfo.bindingCount = static_cast<uint32_t>(layoutBindings.size());
createInfo.pBindings = layoutBindings.data(); createInfo.pBindings = layoutBindings.data();
...@@ -131,7 +124,7 @@ void lib::CgContext::CreateRaytracingDescriptorSetLayout() ...@@ -131,7 +124,7 @@ void lib::CgContext::CreateRaytracingDescriptorSetLayout()
void lib::CgContext::CreateRaytracingDescriptorPool() void lib::CgContext::CreateRaytracingDescriptorPool()
{ {
auto count = static_cast<uint32_t>(this->frames.size()); auto count = static_cast<uint32_t>(this->temporalInterpolationFrames.size());
std::vector<vk::DescriptorPoolSize> sizes{ std::vector<vk::DescriptorPoolSize> sizes{
//Acceleration structure //Acceleration structure
vk::DescriptorPoolSize(vk::DescriptorType::eAccelerationStructureNV, count), vk::DescriptorPoolSize(vk::DescriptorType::eAccelerationStructureNV, count),
...@@ -163,7 +156,7 @@ void lib::CgContext::CreateRaytracingDescriptorPool() ...@@ -163,7 +156,7 @@ void lib::CgContext::CreateRaytracingDescriptorPool()
void lib::CgContext::CreateRaytracingDescriptorSets() void lib::CgContext::CreateRaytracingDescriptorSets()
{ {
auto count = static_cast<uint32_t>(this->frames.size()); auto count = static_cast<uint32_t>(this->temporalInterpolationFrames.size());
std::vector<vk::DescriptorSetLayout> layouts(count, this->raytracingStep.descriptorSetLayout); std::vector<vk::DescriptorSetLayout> layouts(count, this->raytracingStep.descriptorSetLayout);
vk::DescriptorSetAllocateInfo allocateInfo; vk::DescriptorSetAllocateInfo allocateInfo;
...@@ -175,7 +168,7 @@ void lib::CgContext::CreateRaytracingDescriptorSets() ...@@ -175,7 +168,7 @@ void lib::CgContext::CreateRaytracingDescriptorSets()
for (size_t i = 0; i < count; i++) for (size_t i = 0; i < count; i++)
{ {
auto &frame = this->frames[i]; auto &frame = this->temporalInterpolationFrames[i];
frame.raytracingDescriptorSet = descriptorSets[i]; frame.raytracingDescriptorSet = descriptorSets[i];
vk::StructureChain<vk::WriteDescriptorSet, vk::WriteDescriptorSetAccelerationStructureNV> accelerationStructureWrite; vk::StructureChain<vk::WriteDescriptorSet, vk::WriteDescriptorSetAccelerationStructureNV> accelerationStructureWrite;
...@@ -189,7 +182,7 @@ void lib::CgContext::CreateRaytracingDescriptorSets() ...@@ -189,7 +182,7 @@ void lib::CgContext::CreateRaytracingDescriptorSets()
vk::DescriptorImageInfo outputImageInfo; vk::DescriptorImageInfo outputImageInfo;
outputImageInfo.imageLayout = vk::ImageLayout::eGeneral; outputImageInfo.imageLayout = vk::ImageLayout::eGeneral;
outputImageInfo.imageView = frame.raytracingTexture->GetView(); outputImageInfo.imageView = frame.raytracingRenderTarget->GetView();
vk::WriteDescriptorSet outputImageWrite; vk::WriteDescriptorSet outputImageWrite;
outputImageWrite.dstSet = frame.raytracingDescriptorSet; outputImageWrite.dstSet = frame.raytracingDescriptorSet;
...@@ -271,27 +264,15 @@ void lib::CgContext::CreateRaytracingDescriptorSets() ...@@ -271,27 +264,15 @@ void lib::CgContext::CreateRaytracingDescriptorSets()
objectInstanceWrite.descriptorCount = 1; objectInstanceWrite.descriptorCount = 1;
objectInstanceWrite.pBufferInfo = &objectInstanceInfo; objectInstanceWrite.pBufferInfo = &objectInstanceInfo;
vk::DescriptorImageInfo dummyTextureInfo; this->logicalDevice.updateDescriptorSets({
dummyTextureInfo.imageLayout = vk::ImageLayout::eShaderReadOnlyOptimal; accelerationStructureWrite.get<vk::WriteDescriptorSet>(),
dummyTextureInfo.imageView = this->dummyTexture->GetView(); outputImageWrite,
dummyTextureInfo.sampler = this->dummyTexture->GetSampler(); camWrite,
vertexBufferWrite,
vk::WriteDescriptorSet dummyTextureWrite; indexBufferWrite,
dummyTextureWrite.dstSet = frame.raytracingDescriptorSet; materialBufferWrite,
dummyTextureWrite.dstBinding = this->descriptorBindings.dummyTexture; objectInstanceWrite,
dummyTextureWrite.dstArrayElement = 0; },
dummyTextureWrite.descriptorType = vk::DescriptorType::eCombinedImageSampler;
dummyTextureWrite.descriptorCount = 1;
dummyTextureWrite.pImageInfo = &dummyTextureInfo;
this->logicalDevice.updateDescriptorSets({accelerationStructureWrite.get<vk::WriteDescriptorSet>(),
outputImageWrite,
camWrite,
vertexBufferWrite,
indexBufferWrite,
materialBufferWrite,
objectInstanceWrite,
dummyTextureWrite},
{}); {});
} }
......
...@@ -158,10 +158,14 @@ lib::CgContext::~CgContext() ...@@ -158,10 +158,14 @@ lib::CgContext::~CgContext()
for (auto &frame : this->frames) for (auto &frame : this->frames)
{ {
frame.ubo.reset();
this->logicalDevice.destroyCommandPool(frame.commandPool); this->logicalDevice.destroyCommandPool(frame.commandPool);
} }
for (auto &frame : this->temporalInterpolationFrames)
{
frame.ubo.reset();
}
for (auto &semaphore : this->imageAvailableSemaphores) for (auto &semaphore : this->imageAvailableSemaphores)
{ {
if (semaphore) if (semaphore)
...@@ -286,11 +290,11 @@ void lib::CgContext::CleanupSwapChain() ...@@ -286,11 +290,11 @@ void lib::CgContext::CleanupSwapChain()
{ {
this->logicalDevice.destroyImageView(frame.swapChainImageView); this->logicalDevice.destroyImageView(frame.swapChainImageView);
} }
}
if (frame.raytracingTexture) for (auto &frame : this->temporalInterpolationFrames)
{ {
frame.raytracingTexture.reset(); frame.raytracingRenderTarget.reset();
}
} }
if (this->swapChain) if (this->swapChain)
...@@ -696,6 +700,8 @@ void lib::CgContext::CreateSwapChain() ...@@ -696,6 +700,8 @@ void lib::CgContext::CreateSwapChain()
this->frames[i].swapChainImage = swapChainImages[i]; this->frames[i].swapChainImage = swapChainImages[i];
} }
this->temporalInterpolationFrames.resize(swapChainImages.size() + this->temporalInterpolationCount);
lib::log::Info("Successfully acquired swap chain images!"); lib::log::Info("Successfully acquired swap chain images!");
} }
...@@ -729,9 +735,10 @@ void lib::CgContext::CreateCommandPool() ...@@ -729,9 +735,10 @@ void lib::CgContext::CreateCommandPool()
lib::log::Info("Successfully created command pools!"); lib::log::Info("Successfully created command pools!");
} }
void lib::CgContext::UpdateCommandBuffer(uint32_t imageIndex) void lib::CgContext::UpdateCommandBuffer(uint32_t imageIndex, uint32_t temporalInterpolationImageIndex)
{ {
auto &frame = this->frames[imageIndex]; auto &frame = this->frames[imageIndex];
auto &interpolationFrame = this->temporalInterpolationFrames[temporalInterpolationImageIndex];
this->logicalDevice.resetCommandPool(frame.commandPool, vk::CommandPoolResetFlagBits::eReleaseResources); this->logicalDevice.resetCommandPool(frame.commandPool, vk::CommandPoolResetFlagBits::eReleaseResources);
this->pushConstant.rngSeed = this->randomDistribution(this->randomEngine); this->pushConstant.rngSeed = this->randomDistribution(this->randomEngine);
...@@ -745,16 +752,16 @@ void lib::CgContext::UpdateCommandBuffer(uint32_t imageIndex) ...@@ -745,16 +752,16 @@ void lib::CgContext::UpdateCommandBuffer(uint32_t imageIndex)
frame.commandBuffer.bindPipeline(vk::PipelineBindPoint::eRayTracingNV, this->raytracingStep.pipeline); frame.commandBuffer.bindPipeline(vk::PipelineBindPoint::eRayTracingNV, this->raytracingStep.pipeline);
frame.commandBuffer.bindDescriptorSets(vk::PipelineBindPoint::eRayTracingNV, frame.commandBuffer.bindDescriptorSets(vk::PipelineBindPoint::eRayTracingNV,
this->raytracingStep.pipelineLayout, this->raytracingStep.pipelineLayout,
0, frame.raytracingDescriptorSet, 0, interpolationFrame.raytracingDescriptorSet,
{}); {});
TransitionImageLayout(frame.commandBuffer, TransitionImageLayout(frame.commandBuffer,
frame.raytracingTexture->GetHandle(), this->swapChainImageFormat, interpolationFrame.raytracingRenderTarget->GetHandle(), this->swapChainImageFormat,
vk::ImageLayout::eUndefined, vk::ImageLayout::eGeneral, vk::ImageLayout::eUndefined, vk::ImageLayout::eGeneral,
vk::PipelineStageFlagBits::eTopOfPipe, vk::PipelineStageFlagBits::eTopOfPipe,
vk::PipelineStageFlagBits::eRayTracingShaderNV); vk::PipelineStageFlagBits::eRayTracingShaderNV);
frame.ubo->ScheduleTransfer(frame.commandBuffer); interpolationFrame.ubo->ScheduleTransfer(frame.commandBuffer);
frame.commandBuffer.pushConstants(this->raytracingStep.pipelineLayout, frame.commandBuffer.pushConstants(this->raytracingStep.pipelineLayout,
vk::ShaderStageFlagBits::eRaygenNV | vk::ShaderStageFlagBits::eClosestHitNV, vk::ShaderStageFlagBits::eRaygenNV | vk::ShaderStageFlagBits::eClosestHitNV,
...@@ -768,10 +775,12 @@ void lib::CgContext::UpdateCommandBuffer(uint32_t imageIndex) ...@@ -768,10 +775,12 @@ void lib::CgContext::UpdateCommandBuffer(uint32_t imageIndex)
this->shaderBindingTableBuffer->GetBufferHandle(), this->shaderOffsets.hitGroup * sbtEntrySize, sbtEntrySize, this->shaderBindingTableBuffer->GetBufferHandle(), this->shaderOffsets.hitGroup * sbtEntrySize, sbtEntrySize,
this->shaderBindingTableBuffer->GetBufferHandle(), 0, 0, this->shaderBindingTableBuffer->GetBufferHandle(), 0, 0,
this->swapChainExtent.width, this->swapChainExtent.height, 1); this->swapChainExtent.width, this->swapChainExtent.height, 1);
}
TransitionImageLayout(frame.commandBuffer,
interpolationFrame.raytracingRenderTarget->GetHandle(), this->swapChainImageFormat,
vk::ImageLayout::eGeneral, vk::ImageLayout::eShaderReadOnlyOptimal,
vk::PipelineStageFlagBits::eRayTracingShaderNV, vk::PipelineStageFlagBits::eAllGraphics);
if (this->IsOk())
{
vk::RenderPassBeginInfo ppBeginInfo; vk::RenderPassBeginInfo ppBeginInfo;
ppBeginInfo.renderPass = this->rasterizationStep.renderPass; ppBeginInfo.renderPass = this->rasterizationStep.renderPass;
ppBeginInfo.framebuffer = frame.swapChainFramebufferForRasterizationRenderPass; ppBeginInfo.framebuffer = frame.swapChainFramebufferForRasterizationRenderPass;
...@@ -782,7 +791,7 @@ void lib::CgContext::UpdateCommandBuffer(uint32_t imageIndex) ...@@ -782,7 +791,7 @@ void lib::CgContext::UpdateCommandBuffer(uint32_t imageIndex)
frame.commandBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, this->rasterizationStep.pipeline); frame.commandBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, this->rasterizationStep.pipeline);
frame.commandBuffer.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, frame.commandBuffer.bindDescriptorSets(vk::PipelineBindPoint::eGraphics,
this->rasterizationStep.pipelineLayout, this->rasterizationStep.pipelineLayout,
0, frame.rasterizationDescriptorSet, {}); 0, interpolationFrame.rasterizationDescriptorSet, {});
frame.commandBuffer.draw(3, 1, 0, 0); frame.commandBuffer.draw(3, 1, 0, 0);
frame.commandBuffer.endRenderPass(); frame.commandBuffer.endRenderPass();
} }
...@@ -962,7 +971,7 @@ vk::ShaderModule lib::CgContext::LoadShader(const ShaderInfo &info) ...@@ -962,7 +971,7 @@ vk::ShaderModule lib::CgContext::LoadShader(const ShaderInfo &info)
void lib::CgContext::UpdateUniformBuffer(uint32_t imageIndex, lib::time_diff_t delta) void lib::CgContext::UpdateUniformBuffer(uint32_t imageIndex, lib::time_diff_t delta)
{ {
this->camera.UpdateMatrices(); this->camera.UpdateMatrices();
this->frames[imageIndex].ubo->BufferDataHostOnly(SceneDescription{ this->temporalInterpolationFrames[imageIndex].ubo->BufferDataHostOnly(SceneDescription{
this->camera.GetModel(), this->camera.GetModel(),
this->lightSources, this->lightSources,
this->clearColor}); this->clearColor});
...@@ -1009,11 +1018,12 @@ void lib::CgContext::DrawFrame(lib::time_diff_t delta) ...@@ -1009,11 +1018,12 @@ void lib::CgContext::DrawFrame(lib::time_diff_t delta)
this->logicalDevice.waitForFences(this->frames[imageIndex].inFlightFence, VK_TRUE, std::numeric_limits<uint64_t>::max()); this->logicalDevice.waitForFences(this->frames[imageIndex].inFlightFence, VK_TRUE, std::numeric_limits<uint64_t>::max());
} }
this->UpdateCommandBuffer(imageIndex); this->UpdateCommandBuffer(imageIndex, imageIndex);
this->frames[imageIndex].inFlightFence = this->inFlightFences[this->frameIndex]; this->frames[imageIndex].inFlightFence = this->inFlightFences[this->frameIndex];
vk::PipelineStageFlags waitStages[] = {vk::PipelineStageFlagBits::eColorAttachmentOutput}; vk::PipelineStageFlags waitStages[] = {vk::PipelineStageFlagBits::eColorAttachmentOutput};
vk::SubmitInfo submitInfo; vk::SubmitInfo submitInfo;
submitInfo.waitSemaphoreCount = 1; submitInfo.waitSemaphoreCount = 1;
submitInfo.pWaitSemaphores = &this->imageAvailableSemaphores[this->frameIndex]; submitInfo.pWaitSemaphores = &this->imageAvailableSemaphores[this->frameIndex];
...@@ -1208,7 +1218,7 @@ void lib::CgContext::CreateUniformBuffers() ...@@ -1208,7 +1218,7 @@ void lib::CgContext::CreateUniformBuffers()
int i = 0; int i = 0;
for (auto &frame : this->frames) for (auto &frame : this->temporalInterpolationFrames)
{ {
const auto name = "UBO" + std::to_string(i); const auto name = "UBO" + std::to_string(i);
......
#include "Core/CgContext.hpp"
#include "VkUtil/RenderTarget.hpp"
lib::RenderTarget::RenderTarget(CgContext *parent, uint32_t width, uint32_t height, const lib::TextureCreateInfo &textureCreateInfo)
: lib::Texture(parent, width, height, textureCreateInfo)
{
this->semaphore = this->parent->GetLogicalDevice().createSemaphore({});
}
lib::RenderTarget::~RenderTarget()
{
auto logicalDevice = this->parent->GetLogicalDevice();
if (this->semaphore)
{
logicalDevice.destroySemaphore(this->semaphore);
}
for (auto [_, framebuffer] : this->framebuffersByRenderPass)
{
if (framebuffer)
{
logicalDevice.destroyFramebuffer(framebuffer);
}
}
}
void lib::RenderTarget::CreateFramebufferForRenderPass(vk::RenderPass renderPass)
{
auto logicalDevice = this->parent->GetLogicalDevice();
auto existing = this->framebuffersByRenderPass.find(renderPass);
if (existing != this->framebuffersByRenderPass.end())
{
logicalDevice.destroyFramebuffer(existing->second);
}
vk::FramebufferCreateInfo createInfo;
createInfo.attachmentCount = 1;
createInfo.height = this->GetHeight();
createInfo.width = this->GetWidth();
createInfo.layers = 1;
createInfo.renderPass = renderPass;
this->framebuffersByRenderPass[renderPass] = logicalDevice.createFramebuffer(createInfo);
}
const vk::Semaphore &lib::RenderTarget::GetSemaphore() const
{
return this->semaphore;
}
const vk::Framebuffer &lib::RenderTarget::GetFrameBufferForRenderPass(const vk::RenderPass &renderPass) const
{
return this->framebuffersByRenderPass.at(renderPass);
}
void lib::RenderTarget::CreateFramebuffersForRenderPasses(const std::initializer_list<vk::RenderPass> &renderpasses)
{
this->CreateFramebuffersForRenderPasses(std::begin(renderpasses), std::end(renderpasses));
}
...@@ -67,6 +67,9 @@ lib::Texture::~Texture() ...@@ -67,6 +67,9 @@ lib::Texture::~Texture()
void lib::Texture::LoadData(uint32_t width, uint32_t height, const void *data, uint8_t pixelByteCount, const TextureCreateInfo &createInfo) void lib::Texture::LoadData(uint32_t width, uint32_t height, const void *data, uint8_t pixelByteCount, const TextureCreateInfo &createInfo)
{ {
this->width = width;
this->height = height;
auto queueFamilyIndices = createInfo.queueFamilyIndices; auto queueFamilyIndices = createInfo.queueFamilyIndices;
lib::FilterUnique(queueFamilyIndices); lib::FilterUnique(queueFamilyIndices);
...@@ -181,4 +184,13 @@ const vk::ImageView &lib::Texture::GetView() const ...@@ -181,4 +184,13 @@ const vk::ImageView &lib::Texture::GetView() const
const vk::Sampler &lib::Texture::GetSampler() const const vk::Sampler &lib::Texture::GetSampler() const
{ {
return this->sampler; return this->sampler;
} }
\ No newline at end of file uint32_t lib::Texture::GetHeight() const
{
return this->height;
}
uint32_t lib::Texture::GetWidth() const
{
return this->width;
}