From 97d5640967bfe1ab2d099507d35097847438b67c Mon Sep 17 00:00:00 2001 From: SirLynix Date: Fri, 17 Nov 2023 16:59:31 +0100 Subject: [PATCH] Renderer: Blit texture to window instead of using a full renderpass This may improve performance and allow for render targets to customize how they blit the final texture (allowing for render-to-texture) --- examples/DeferredShading/main.cpp | 50 ++--- .../Nazara/Graphics/ForwardFramePipeline.hpp | 1 - .../Nazara/Graphics/FramePassAttachment.hpp | 2 + .../OpenGLRenderer/OpenGLCommandBuffer.hpp | 11 ++ .../OpenGLRenderer/OpenGLCommandBuffer.inl | 13 ++ .../OpenGLCommandBufferBuilder.hpp | 1 + .../Nazara/OpenGLRenderer/OpenGLSwapchain.hpp | 4 +- .../Nazara/OpenGLRenderer/OpenGLSwapchain.inl | 5 + .../Nazara/OpenGLRenderer/Wrapper/Context.hpp | 3 + .../Nazara/Renderer/CommandBufferBuilder.hpp | 2 + include/Nazara/Renderer/RenderFrame.hpp | 6 +- include/Nazara/Renderer/RenderFrame.inl | 5 + include/Nazara/Renderer/RenderImage.hpp | 2 + include/Nazara/Renderer/RenderTarget.hpp | 5 + include/Nazara/Renderer/Swapchain.hpp | 2 + .../Nazara/Renderer/TransientResources.hpp | 5 +- .../Nazara/Renderer/TransientResources.inl | 11 ++ include/Nazara/Renderer/WindowSwapchain.hpp | 2 + include/Nazara/Renderer/WindowSwapchain.inl | 5 + .../VulkanCommandBufferBuilder.hpp | 1 + .../Nazara/VulkanRenderer/VulkanSwapchain.hpp | 3 +- .../Nazara/VulkanRenderer/VulkanSwapchain.inl | 5 + .../VulkanRenderer/Wrapper/Swapchain.hpp | 57 +++--- .../VulkanRenderer/Wrapper/Swapchain.inl | 185 +++++++++--------- .../Graphics/DirectionalLightShadowData.cpp | 11 +- src/Nazara/Graphics/ForwardFramePipeline.cpp | 50 +---- src/Nazara/Graphics/FrameGraph.cpp | 3 + src/Nazara/Graphics/PointLightShadowData.cpp | 9 +- src/Nazara/Graphics/SpotLightShadowData.cpp | 9 +- .../OpenGLRenderer/OpenGLCommandBuffer.cpp | 5 + .../OpenGLCommandBufferBuilder.cpp | 52 +++-- .../OpenGLRenderer/OpenGLRenderImage.cpp | 1 + src/Nazara/OpenGLRenderer/OpenGLSwapchain.cpp | 3 +- src/Nazara/OpenGLRenderer/Wrapper/Context.cpp | 70 ++++++- src/Nazara/Renderer/Swapchain.cpp | 16 ++ .../VulkanCommandBufferBuilder.cpp | 89 ++++++--- .../VulkanRenderer/VulkanRenderImage.cpp | 1 + src/Nazara/VulkanRenderer/VulkanSwapchain.cpp | 8 +- 38 files changed, 448 insertions(+), 265 deletions(-) diff --git a/examples/DeferredShading/main.cpp b/examples/DeferredShading/main.cpp index 987c7bb4b..961477e84 100644 --- a/examples/DeferredShading/main.cpp +++ b/examples/DeferredShading/main.cpp @@ -703,52 +703,52 @@ int main(int argc, char* argv[]) }); godRaysTexture = graph.AddAttachment({ - "God rays texture", - Nz::PixelFormat::RGBA16F, - Nz::FramePassAttachmentSize::SwapchainFactor, - 50'000, - 50'000 + .name = "God rays texture", + .format = Nz::PixelFormat::RGBA16F, + .size = Nz::FramePassAttachmentSize::SwapchainFactor, + .width = 50'000, + .height = 50'000 }); bloomOutput = graph.AddAttachmentProxy("Bloom output", lightOutput); unsigned int bloomSize = 50'000; bloomBrightOutput = graph.AddAttachment({ - "Bloom bright output", - Nz::PixelFormat::RGBA16F, - Nz::FramePassAttachmentSize::SwapchainFactor, - bloomSize, - bloomSize + .name = "Bloom bright output", + .format = Nz::PixelFormat::RGBA16F, + .size = Nz::FramePassAttachmentSize::SwapchainFactor, + .width = bloomSize, + .height = bloomSize }); for (std::size_t i = 0; i < BloomSubdivisionCount; ++i) { bloomTextures[i * 2 + 0] = graph.AddAttachment({ - "Bloom texture #" + std::to_string(i), - Nz::PixelFormat::RGBA16F, - Nz::FramePassAttachmentSize::SwapchainFactor, - bloomSize, - bloomSize + .name = "Bloom texture #" + std::to_string(i), + .format = Nz::PixelFormat::RGBA16F, + .size = Nz::FramePassAttachmentSize::SwapchainFactor, + .width = bloomSize, + .height = bloomSize }); bloomTextures[i * 2 + 1] = graph.AddAttachment({ - "Bloom texture #" + std::to_string(i), - Nz::PixelFormat::RGBA16F, - Nz::FramePassAttachmentSize::SwapchainFactor, - bloomSize, - bloomSize + .name = "Bloom texture #" + std::to_string(i), + .format = Nz::PixelFormat::RGBA16F, + .size = Nz::FramePassAttachmentSize::SwapchainFactor, + .width = bloomSize, + .height = bloomSize }); bloomSize /= 2; } toneMappingOutput = graph.AddAttachment({ - "Tone mapping", - Nz::PixelFormat::RGBA8, - Nz::FramePassAttachmentSize::SwapchainFactor, - 100'000, - 100'000 + .name = "Tone mapping", + .format = Nz::PixelFormat::RGBA8, + .size = Nz::FramePassAttachmentSize::SwapchainFactor, + .width = 100'000, + .height = 100'000 }); Nz::FramePass& gbufferPass = graph.AddPass("GBuffer"); diff --git a/include/Nazara/Graphics/ForwardFramePipeline.hpp b/include/Nazara/Graphics/ForwardFramePipeline.hpp index d861eb1d3..a8ec868c3 100644 --- a/include/Nazara/Graphics/ForwardFramePipeline.hpp +++ b/include/Nazara/Graphics/ForwardFramePipeline.hpp @@ -121,7 +121,6 @@ namespace Nz { std::size_t finalAttachment; std::vector viewers; - ShaderBindingPtr blitShaderBinding; }; struct SkeletonInstanceData diff --git a/include/Nazara/Graphics/FramePassAttachment.hpp b/include/Nazara/Graphics/FramePassAttachment.hpp index 628fbc867..040fe2022 100644 --- a/include/Nazara/Graphics/FramePassAttachment.hpp +++ b/include/Nazara/Graphics/FramePassAttachment.hpp @@ -9,6 +9,7 @@ #include #include +#include #include #include @@ -24,6 +25,7 @@ namespace Nz { std::string name; PixelFormat format; + TextureUsage additionalUsage = TextureUsage::TransferSource; FramePassAttachmentSize size = FramePassAttachmentSize::SwapchainFactor; unsigned int width = 100'000; unsigned int height = 100'000; diff --git a/include/Nazara/OpenGLRenderer/OpenGLCommandBuffer.hpp b/include/Nazara/OpenGLRenderer/OpenGLCommandBuffer.hpp index f15db2fcf..73422ff20 100644 --- a/include/Nazara/OpenGLRenderer/OpenGLCommandBuffer.hpp +++ b/include/Nazara/OpenGLRenderer/OpenGLCommandBuffer.hpp @@ -48,6 +48,7 @@ namespace Nz inline void BindVertexBuffer(UInt32 binding, GLuint vertexBuffer, UInt64 offset = 0); inline void BlitTexture(const OpenGLTexture& source, const Boxui& sourceBox, const OpenGLTexture& target, const Boxui& targetBox, SamplerFilter filter = SamplerFilter::Nearest); + inline void BlitTextureToWindow(const OpenGLTexture& source, const Boxui& sourceBox, const Boxui& targetBox, SamplerFilter filter = SamplerFilter::Nearest); inline void BuildMipmaps(OpenGLTexture& texture, UInt8 baseLevel, UInt8 levelCount); @@ -88,6 +89,7 @@ namespace Nz #define NAZARA_OPENGL_FOREACH_COMMANDS(cb, lastCb) \ cb(BeginDebugRegionCommand) \ cb(BlitTextureCommand) \ + cb(BlitTextureToWindowCommand) \ cb(BuildTextureMipmapsCommand) \ cb(CopyBufferCommand) \ cb(CopyBufferFromMemoryCommand) \ @@ -119,6 +121,7 @@ namespace Nz inline void Execute(const GL::Context* context, const BeginDebugRegionCommand& command); inline void Execute(const GL::Context* context, const BlitTextureCommand& command); + inline void Execute(const GL::Context* context, const BlitTextureToWindowCommand& command); inline void Execute(const GL::Context* context, const BuildTextureMipmapsCommand& command); inline void Execute(const GL::Context* context, const CopyBufferCommand& command); inline void Execute(const GL::Context* context, const CopyBufferFromMemoryCommand& command); @@ -148,6 +151,14 @@ namespace Nz SamplerFilter filter; }; + struct BlitTextureToWindowCommand + { + const OpenGLTexture* source; + Boxui sourceBox; + Boxui targetBox; + SamplerFilter filter; + }; + struct BuildTextureMipmapsCommand { OpenGLTexture* texture; diff --git a/include/Nazara/OpenGLRenderer/OpenGLCommandBuffer.inl b/include/Nazara/OpenGLRenderer/OpenGLCommandBuffer.inl index 98b1b3e7c..f4f65a9f4 100644 --- a/include/Nazara/OpenGLRenderer/OpenGLCommandBuffer.inl +++ b/include/Nazara/OpenGLRenderer/OpenGLCommandBuffer.inl @@ -88,6 +88,18 @@ namespace Nz m_commands.emplace_back(std::move(blitTexture)); } + inline void OpenGLCommandBuffer::BlitTextureToWindow(const OpenGLTexture& source, const Boxui& sourceBox, const Boxui& targetBox, SamplerFilter filter) + { + BlitTextureToWindowCommand blitTexture = { + &source, + sourceBox, + targetBox, + filter + }; + + m_commands.emplace_back(std::move(blitTexture)); + } + inline void OpenGLCommandBuffer::BuildMipmaps(OpenGLTexture& texture, UInt8 baseLevel, UInt8 levelCount) { BuildTextureMipmapsCommand buildMipmaps = { @@ -258,3 +270,4 @@ namespace Nz } #include +#include "OpenGLCommandBuffer.hpp" diff --git a/include/Nazara/OpenGLRenderer/OpenGLCommandBufferBuilder.hpp b/include/Nazara/OpenGLRenderer/OpenGLCommandBufferBuilder.hpp index 58cfb2808..3a7950a39 100644 --- a/include/Nazara/OpenGLRenderer/OpenGLCommandBufferBuilder.hpp +++ b/include/Nazara/OpenGLRenderer/OpenGLCommandBufferBuilder.hpp @@ -37,6 +37,7 @@ namespace Nz void BindVertexBuffer(UInt32 binding, const RenderBuffer& vertexBuffer, UInt64 offset = 0) override; void BlitTexture(const Texture& fromTexture, const Boxui& fromBox, TextureLayout fromLayout, const Texture& toTexture, const Boxui& toBox, TextureLayout toLayout, SamplerFilter filter) override; + void BlitTextureToSwapchain(const Texture& fromTexture, const Boxui& fromBox, TextureLayout fromLayout, const Swapchain& swapchain, std::size_t imageIndex) override; void BuildMipmaps(Texture& texture, UInt8 baseLevel, UInt8 levelCount, PipelineStageFlags srcStageMask, PipelineStageFlags dstStageMask, MemoryAccessFlags srcAccessMask, MemoryAccessFlags dstAccessMask, TextureLayout oldLayout, TextureLayout newLayout) override; diff --git a/include/Nazara/OpenGLRenderer/OpenGLSwapchain.hpp b/include/Nazara/OpenGLRenderer/OpenGLSwapchain.hpp index 2762cff68..37dfbc15b 100644 --- a/include/Nazara/OpenGLRenderer/OpenGLSwapchain.hpp +++ b/include/Nazara/OpenGLRenderer/OpenGLSwapchain.hpp @@ -32,6 +32,7 @@ namespace Nz std::shared_ptr CreateCommandPool(QueueType queueType) override; inline GL::Context& GetContext(); + inline OpenGLDevice& GetDevice(); const OpenGLFramebuffer& GetFramebuffer(std::size_t i) const override; std::size_t GetFramebufferCount() const override; PresentMode GetPresentMode() const override; @@ -50,8 +51,9 @@ namespace Nz private: std::optional m_renderPass; std::size_t m_currentFrame; - std::vector> m_renderImage; std::shared_ptr m_context; + std::vector> m_renderImage; + OpenGLDevice& m_device; OpenGLWindowFramebuffer m_framebuffer; PresentMode m_presentMode; PresentModeFlags m_supportedPresentModes; diff --git a/include/Nazara/OpenGLRenderer/OpenGLSwapchain.inl b/include/Nazara/OpenGLRenderer/OpenGLSwapchain.inl index 483de9d83..1147a402f 100644 --- a/include/Nazara/OpenGLRenderer/OpenGLSwapchain.inl +++ b/include/Nazara/OpenGLRenderer/OpenGLSwapchain.inl @@ -12,6 +12,11 @@ namespace Nz assert(m_context); return *m_context; } + + inline OpenGLDevice& OpenGLSwapchain::GetDevice() + { + return m_device; + } } #include diff --git a/include/Nazara/OpenGLRenderer/Wrapper/Context.hpp b/include/Nazara/OpenGLRenderer/Wrapper/Context.hpp index be77ff4a2..2ba4b04b9 100644 --- a/include/Nazara/OpenGLRenderer/Wrapper/Context.hpp +++ b/include/Nazara/OpenGLRenderer/Wrapper/Context.hpp @@ -29,6 +29,7 @@ namespace Nz namespace Nz::GL { + class Framebuffer; class Texture; enum class BufferTarget @@ -141,6 +142,7 @@ namespace Nz::GL void BindVertexArray(GLuint vertexArray, bool force = false) const; bool BlitTexture(const OpenGLTexture& source, const OpenGLTexture& destination, const Boxui& srcBox, const Boxui& dstBox, SamplerFilter filter) const; + bool BlitTextureToWindow(const OpenGLTexture& texture, const Boxui& srcBox, const Boxui& dstBox, SamplerFilter filter) const; bool ClearErrorStack() const; @@ -217,6 +219,7 @@ namespace Nz::GL private: void HandleDebugMessage(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message) const; bool InitializeBlitFramebuffers() const; + static void BindTextureToFramebuffer(Framebuffer& framebuffer, const OpenGLTexture& texture); enum class FunctionIndex { diff --git a/include/Nazara/Renderer/CommandBufferBuilder.hpp b/include/Nazara/Renderer/CommandBufferBuilder.hpp index 420a76820..03e52e7d0 100644 --- a/include/Nazara/Renderer/CommandBufferBuilder.hpp +++ b/include/Nazara/Renderer/CommandBufferBuilder.hpp @@ -26,6 +26,7 @@ namespace Nz class RenderPipeline; class RenderPipelineLayout; class ShaderBinding; + class Swapchain; class Texture; class NAZARA_RENDERER_API CommandBufferBuilder @@ -53,6 +54,7 @@ namespace Nz virtual void BindVertexBuffer(UInt32 binding, const RenderBuffer& vertexBuffer, UInt64 offset = 0) = 0; virtual void BlitTexture(const Texture& fromTexture, const Boxui& fromBox, TextureLayout fromLayout, const Texture& toTexture, const Boxui& toBox, TextureLayout toLayout, SamplerFilter filter) = 0; + virtual void BlitTextureToSwapchain(const Texture& fromTexture, const Boxui& fromBox, TextureLayout fromLayout, const Swapchain& swapchain, std::size_t imageIndex) = 0; virtual void BuildMipmaps(Texture& texture, UInt8 baseLevel, UInt8 levelCount, PipelineStageFlags srcStageMask, PipelineStageFlags dstStageMask, MemoryAccessFlags srcAccessMask, MemoryAccessFlags dstAccessMask, TextureLayout oldLayout, TextureLayout newLayout) = 0; diff --git a/include/Nazara/Renderer/RenderFrame.hpp b/include/Nazara/Renderer/RenderFrame.hpp index c92a70d10..446266752 100644 --- a/include/Nazara/Renderer/RenderFrame.hpp +++ b/include/Nazara/Renderer/RenderFrame.hpp @@ -19,6 +19,7 @@ namespace Nz { class CommandBuffer; class CommandBufferBuilder; + class RenderDevice; class UploadPool; class NAZARA_RENDERER_API RenderFrame @@ -30,11 +31,12 @@ namespace Nz RenderFrame(RenderFrame&&) = delete; ~RenderFrame() = default; - void Execute(const FunctionRef& callback, QueueTypeFlags queueTypeFlags); + inline void Execute(const FunctionRef& callback, QueueTypeFlags queueTypeFlags); inline std::size_t GetFramebufferIndex() const; const Vector2ui& GetSize() const; - UploadPool& GetUploadPool(); + inline RenderDevice& GetRenderDevice(); + inline UploadPool& GetUploadPool(); inline bool IsFramebufferInvalidated() const; diff --git a/include/Nazara/Renderer/RenderFrame.inl b/include/Nazara/Renderer/RenderFrame.inl index b8ccb04c9..6dc8ca1d7 100644 --- a/include/Nazara/Renderer/RenderFrame.inl +++ b/include/Nazara/Renderer/RenderFrame.inl @@ -37,6 +37,11 @@ namespace Nz return m_size; } + inline RenderDevice& RenderFrame::GetRenderDevice() + { + return m_image->GetRenderDevice(); + } + inline UploadPool& RenderFrame::GetUploadPool() { if NAZARA_UNLIKELY(!m_image) diff --git a/include/Nazara/Renderer/RenderImage.hpp b/include/Nazara/Renderer/RenderImage.hpp index a63aea78e..2040040ba 100644 --- a/include/Nazara/Renderer/RenderImage.hpp +++ b/include/Nazara/Renderer/RenderImage.hpp @@ -15,6 +15,8 @@ namespace Nz class NAZARA_RENDERER_API RenderImage : public TransientResources { public: + using TransientResources::TransientResources; + virtual void Present() = 0; }; } diff --git a/include/Nazara/Renderer/RenderTarget.hpp b/include/Nazara/Renderer/RenderTarget.hpp index 16784c8b0..86fbec65f 100644 --- a/include/Nazara/Renderer/RenderTarget.hpp +++ b/include/Nazara/Renderer/RenderTarget.hpp @@ -14,8 +14,11 @@ namespace Nz { + class CommandBufferBuilder; class Framebuffer; + class RenderFrame; class RenderPass; + class Texture; class NAZARA_RENDERER_API RenderTarget { @@ -23,6 +26,8 @@ namespace Nz RenderTarget() = default; virtual ~RenderTarget(); + virtual void BlitTexture(RenderFrame& renderFrame, CommandBufferBuilder& builder, const Texture& texture) const = 0; + virtual const Framebuffer& GetFramebuffer(std::size_t i) const = 0; virtual std::size_t GetFramebufferCount() const = 0; virtual const RenderPass& GetRenderPass() const = 0; diff --git a/include/Nazara/Renderer/Swapchain.hpp b/include/Nazara/Renderer/Swapchain.hpp index e01b39e75..756535920 100644 --- a/include/Nazara/Renderer/Swapchain.hpp +++ b/include/Nazara/Renderer/Swapchain.hpp @@ -29,6 +29,8 @@ namespace Nz virtual RenderFrame AcquireFrame() = 0; + void BlitTexture(RenderFrame& renderFrame, CommandBufferBuilder& builder, const Texture& texture) const override; + virtual std::shared_ptr CreateCommandPool(QueueType queueType) = 0; virtual PresentMode GetPresentMode() const = 0; diff --git a/include/Nazara/Renderer/TransientResources.hpp b/include/Nazara/Renderer/TransientResources.hpp index 1aa93e6fb..358ed0c8c 100644 --- a/include/Nazara/Renderer/TransientResources.hpp +++ b/include/Nazara/Renderer/TransientResources.hpp @@ -19,6 +19,7 @@ namespace Nz { class CommandBuffer; class CommandBufferBuilder; + class RenderDevice; class UploadPool; class NAZARA_RENDERER_API TransientResources @@ -33,6 +34,7 @@ namespace Nz inline void FlushReleaseQueue(); + inline RenderDevice& GetRenderDevice(); virtual UploadPool& GetUploadPool() = 0; template void PushForRelease(const T& value) = delete; @@ -42,7 +44,7 @@ namespace Nz virtual void SubmitCommandBuffer(CommandBuffer* commandBuffer, QueueTypeFlags queueTypeFlags) = 0; protected: - TransientResources() = default; + inline TransientResources(RenderDevice& renderDvice); TransientResources(const TransientResources&) = delete; TransientResources(TransientResources&&) = delete; @@ -53,6 +55,7 @@ namespace Nz std::vector m_releaseQueue; std::vector m_releaseMemoryPool; + RenderDevice& m_renderDevice; }; class NAZARA_RENDERER_API TransientResources::Releasable diff --git a/include/Nazara/Renderer/TransientResources.inl b/include/Nazara/Renderer/TransientResources.inl index 9ff359f7b..e8350de73 100644 --- a/include/Nazara/Renderer/TransientResources.inl +++ b/include/Nazara/Renderer/TransientResources.inl @@ -8,6 +8,11 @@ namespace Nz { + inline TransientResources::TransientResources(RenderDevice& renderDevice) : + m_renderDevice(renderDevice) + { + } + inline void TransientResources::FlushReleaseQueue() { for (Releasable* releasable : m_releaseQueue) @@ -21,6 +26,11 @@ namespace Nz memoryblock.clear(); } + inline RenderDevice& TransientResources::GetRenderDevice() + { + return m_renderDevice; + } + template void TransientResources::PushForRelease(T&& value) { @@ -98,3 +108,4 @@ namespace Nz } #include +#include "TransientResources.hpp" diff --git a/include/Nazara/Renderer/WindowSwapchain.hpp b/include/Nazara/Renderer/WindowSwapchain.hpp index 2f1421c67..00ece75a5 100644 --- a/include/Nazara/Renderer/WindowSwapchain.hpp +++ b/include/Nazara/Renderer/WindowSwapchain.hpp @@ -29,6 +29,8 @@ namespace Nz inline RenderFrame AcquireFrame(); + inline void BlitTexture(RenderFrame& renderFrame, CommandBufferBuilder& builder, const Texture& texture) const override; + inline bool DoesRenderOnlyIfFocused() const; inline void EnableRenderOnlyIfFocused(bool enable = true); diff --git a/include/Nazara/Renderer/WindowSwapchain.inl b/include/Nazara/Renderer/WindowSwapchain.inl index 8a84bd4c1..35a3dfbbc 100644 --- a/include/Nazara/Renderer/WindowSwapchain.inl +++ b/include/Nazara/Renderer/WindowSwapchain.inl @@ -20,6 +20,11 @@ namespace Nz return m_swapchain->AcquireFrame(); } + inline void WindowSwapchain::BlitTexture(RenderFrame& renderFrame, CommandBufferBuilder& builder, const Texture& texture) const + { + return m_swapchain->BlitTexture(renderFrame, builder, texture); + } + inline bool WindowSwapchain::DoesRenderOnlyIfFocused() const { return m_renderOnlyIfFocused; diff --git a/include/Nazara/VulkanRenderer/VulkanCommandBufferBuilder.hpp b/include/Nazara/VulkanRenderer/VulkanCommandBufferBuilder.hpp index ac1c71634..f5c3892e8 100644 --- a/include/Nazara/VulkanRenderer/VulkanCommandBufferBuilder.hpp +++ b/include/Nazara/VulkanRenderer/VulkanCommandBufferBuilder.hpp @@ -37,6 +37,7 @@ namespace Nz void BindVertexBuffer(UInt32 binding, const RenderBuffer& vertexBuffer, UInt64 offset = 0) override; void BlitTexture(const Texture& fromTexture, const Boxui& fromBox, TextureLayout fromLayout, const Texture& toTexture, const Boxui& toBox, TextureLayout toLayout, SamplerFilter filter) override; + void BlitTextureToSwapchain(const Texture& fromTexture, const Boxui& fromBox, TextureLayout fromLayout, const Swapchain& swapchain, std::size_t imageIndex) override; void BuildMipmaps(Texture& texture, UInt8 baseLevel, UInt8 levelCount, PipelineStageFlags srcStageMask, PipelineStageFlags dstStageMask, MemoryAccessFlags srcAccessMask, MemoryAccessFlags dstAccessMask, TextureLayout oldLayout, TextureLayout newLayout) override; diff --git a/include/Nazara/VulkanRenderer/VulkanSwapchain.hpp b/include/Nazara/VulkanRenderer/VulkanSwapchain.hpp index 0756e5702..732caffcd 100644 --- a/include/Nazara/VulkanRenderer/VulkanSwapchain.hpp +++ b/include/Nazara/VulkanRenderer/VulkanSwapchain.hpp @@ -46,11 +46,12 @@ namespace Nz std::shared_ptr CreateCommandPool(QueueType queueType) override; - const VulkanWindowFramebuffer& GetFramebuffer(std::size_t i) const override; + const VulkanWindowFramebuffer& GetFramebuffer(std::size_t imageIndex) const override; std::size_t GetFramebufferCount() const override; inline VulkanDevice& GetDevice(); inline const VulkanDevice& GetDevice() const; inline Vk::QueueHandle& GetGraphicsQueue(); + inline VkImage GetImage(std::size_t imageIndex) const; const VulkanRenderPass& GetRenderPass() const override; const Vector2ui& GetSize() const override; PresentMode GetPresentMode() const override; diff --git a/include/Nazara/VulkanRenderer/VulkanSwapchain.inl b/include/Nazara/VulkanRenderer/VulkanSwapchain.inl index 5970fecb9..6db03fc7e 100644 --- a/include/Nazara/VulkanRenderer/VulkanSwapchain.inl +++ b/include/Nazara/VulkanRenderer/VulkanSwapchain.inl @@ -21,6 +21,11 @@ namespace Nz return m_graphicsQueue; } + inline VkImage VulkanSwapchain::GetImage(std::size_t imageIndex) const + { + return m_swapchain.GetImage(imageIndex).image; + } + inline const Vk::Swapchain& VulkanSwapchain::GetSwapchain() const { return m_swapchain; diff --git a/include/Nazara/VulkanRenderer/Wrapper/Swapchain.hpp b/include/Nazara/VulkanRenderer/Wrapper/Swapchain.hpp index 9885a68a0..92877f6f9 100644 --- a/include/Nazara/VulkanRenderer/Wrapper/Swapchain.hpp +++ b/include/Nazara/VulkanRenderer/Wrapper/Swapchain.hpp @@ -11,48 +11,45 @@ #include #include -namespace Nz +namespace Nz::Vk { - namespace Vk + class Swapchain : public DeviceObject { - class Swapchain : public DeviceObject - { - friend DeviceObject; + friend DeviceObject; - public: - struct Image; + public: + struct Image; - Swapchain() = default; - Swapchain(const Swapchain&) = delete; - Swapchain(Swapchain&&) = default; - ~Swapchain() = default; + Swapchain() = default; + Swapchain(const Swapchain&) = delete; + Swapchain(Swapchain&&) = default; + ~Swapchain() = default; - inline bool AcquireNextImage(Nz::UInt64 timeout, VkSemaphore semaphore, VkFence fence, UInt32* imageIndex) const; + inline bool AcquireNextImage(Nz::UInt64 timeout, VkSemaphore semaphore, VkFence fence, UInt32* imageIndex) const; - inline bool Create(Device& device, const VkSwapchainCreateInfoKHR& createInfo, const VkAllocationCallbacks* allocator = nullptr); + inline bool Create(Device& device, const VkSwapchainCreateInfoKHR& createInfo, const VkAllocationCallbacks* allocator = nullptr); - inline const Image& GetImage(UInt32 index) const; - inline const std::vector& GetImages() const; - inline UInt32 GetImageCount() const; + inline const Image& GetImage(UInt32 index) const; + inline const std::vector& GetImages() const; + inline UInt32 GetImageCount() const; - inline bool IsSupported() const; + inline bool IsSupported() const; - Swapchain& operator=(const Swapchain&) = delete; - Swapchain& operator=(Swapchain&&) = default; + Swapchain& operator=(const Swapchain&) = delete; + Swapchain& operator=(Swapchain&&) = default; - struct Image - { - VkImage image; - ImageView view; - }; + struct Image + { + VkImage image; + ImageView view; + }; - private: - static inline VkResult CreateHelper(Device& device, const VkSwapchainCreateInfoKHR* createInfo, const VkAllocationCallbacks* allocator, VkSwapchainKHR* handle); - static inline void DestroyHelper(Device& device, VkSwapchainKHR handle, const VkAllocationCallbacks* allocator); + private: + static inline VkResult CreateHelper(Device& device, const VkSwapchainCreateInfoKHR* createInfo, const VkAllocationCallbacks* allocator, VkSwapchainKHR* handle); + static inline void DestroyHelper(Device& device, VkSwapchainKHR handle, const VkAllocationCallbacks* allocator); - std::vector m_images; - }; - } + std::vector m_images; + }; } #include diff --git a/include/Nazara/VulkanRenderer/Wrapper/Swapchain.inl b/include/Nazara/VulkanRenderer/Wrapper/Swapchain.inl index 234b115e8..cc1d15f02 100644 --- a/include/Nazara/VulkanRenderer/Wrapper/Swapchain.inl +++ b/include/Nazara/VulkanRenderer/Wrapper/Swapchain.inl @@ -7,117 +7,114 @@ #include #include -namespace Nz +namespace Nz::Vk { - namespace Vk + inline bool Swapchain::AcquireNextImage(Nz::UInt64 timeout, VkSemaphore semaphore, VkFence fence, UInt32* imageIndex) const { - inline bool Swapchain::AcquireNextImage(Nz::UInt64 timeout, VkSemaphore semaphore, VkFence fence, UInt32* imageIndex) const + m_lastErrorCode = m_device->vkAcquireNextImageKHR(*m_device, m_handle, timeout, semaphore, fence, imageIndex); + switch (m_lastErrorCode) { - m_lastErrorCode = m_device->vkAcquireNextImageKHR(*m_device, m_handle, timeout, semaphore, fence, imageIndex); - switch (m_lastErrorCode) - { - case VkResult::VK_SUBOPTIMAL_KHR: - case VkResult::VK_SUCCESS: - return true; + case VkResult::VK_SUBOPTIMAL_KHR: + case VkResult::VK_SUCCESS: + return true; - default: - { - NazaraErrorFmt("failed to acquire next swapchain image: {0}", TranslateVulkanError(m_lastErrorCode)); - return false; + default: + { + NazaraErrorFmt("failed to acquire next swapchain image: {0}", TranslateVulkanError(m_lastErrorCode)); + return false; + } + } + } + + inline bool Swapchain::Create(Device& device, const VkSwapchainCreateInfoKHR& createInfo, const VkAllocationCallbacks* allocator) + { + if (!DeviceObject::Create(device, createInfo, allocator)) + return false; + + UInt32 imageCount = 0; + m_lastErrorCode = m_device->vkGetSwapchainImagesKHR(*m_device, m_handle, &imageCount, nullptr); + if (m_lastErrorCode != VkResult::VK_SUCCESS || imageCount == 0) + { + NazaraErrorFmt("failed to query swapchain image count: {0}", TranslateVulkanError(m_lastErrorCode)); + return false; + } + + std::vector images(imageCount); + m_lastErrorCode = m_device->vkGetSwapchainImagesKHR(*m_device, m_handle, &imageCount, images.data()); + if (m_lastErrorCode != VkResult::VK_SUCCESS) + { + NazaraErrorFmt("failed to query swapchain images: {0}", TranslateVulkanError(m_lastErrorCode)); + return false; + } + + m_images.resize(imageCount); + for (UInt32 i = 0; i < imageCount; ++i) + { + m_images[i].image = images[i]; + + VkImageViewCreateInfo imageViewCreateInfo = { + VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType; + nullptr, // const void* pNext; + 0, // VkImageViewCreateFlags flags; + m_images[i].image, // VkImage image; + VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType; + createInfo.imageFormat, // VkFormat format; + { // VkComponentMapping components; + VK_COMPONENT_SWIZZLE_R, // VkComponentSwizzle .r; + VK_COMPONENT_SWIZZLE_G, // VkComponentSwizzle .g; + VK_COMPONENT_SWIZZLE_B, // VkComponentSwizzle .b; + VK_COMPONENT_SWIZZLE_A // VkComponentSwizzle .a; + }, + { // VkImageSubresourceRange subresourceRange; + VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags .aspectMask; + 0, // uint32_t .baseMipLevel; + 1, // uint32_t .levelCount; + 0, // uint32_t .baseArrayLayer; + 1 // uint32_t .layerCount; } - } - } + }; - inline bool Swapchain::Create(Device& device, const VkSwapchainCreateInfoKHR& createInfo, const VkAllocationCallbacks* allocator) - { - if (!DeviceObject::Create(device, createInfo, allocator)) - return false; - - UInt32 imageCount = 0; - m_lastErrorCode = m_device->vkGetSwapchainImagesKHR(*m_device, m_handle, &imageCount, nullptr); - if (m_lastErrorCode != VkResult::VK_SUCCESS || imageCount == 0) + if (!m_images[i].view.Create(*m_device, imageViewCreateInfo)) { - NazaraErrorFmt("failed to query swapchain image count: {0}", TranslateVulkanError(m_lastErrorCode)); + NazaraErrorFmt("failed to create image view for image #{0}", i); return false; } - - std::vector images(imageCount); - m_lastErrorCode = m_device->vkGetSwapchainImagesKHR(*m_device, m_handle, &imageCount, images.data()); - if (m_lastErrorCode != VkResult::VK_SUCCESS) - { - NazaraErrorFmt("failed to query swapchain images: {0}", TranslateVulkanError(m_lastErrorCode)); - return false; - } - - m_images.resize(imageCount); - for (UInt32 i = 0; i < imageCount; ++i) - { - m_images[i].image = images[i]; - - VkImageViewCreateInfo imageViewCreateInfo = { - VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType; - nullptr, // const void* pNext; - 0, // VkImageViewCreateFlags flags; - m_images[i].image, // VkImage image; - VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType; - createInfo.imageFormat, // VkFormat format; - { // VkComponentMapping components; - VK_COMPONENT_SWIZZLE_R, // VkComponentSwizzle .r; - VK_COMPONENT_SWIZZLE_G, // VkComponentSwizzle .g; - VK_COMPONENT_SWIZZLE_B, // VkComponentSwizzle .b; - VK_COMPONENT_SWIZZLE_A // VkComponentSwizzle .a; - }, - { // VkImageSubresourceRange subresourceRange; - VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags .aspectMask; - 0, // uint32_t .baseMipLevel; - 1, // uint32_t .levelCount; - 0, // uint32_t .baseArrayLayer; - 1 // uint32_t .layerCount; - } - }; - - if (!m_images[i].view.Create(*m_device, imageViewCreateInfo)) - { - NazaraErrorFmt("failed to create image view for image #{0}", i); - return false; - } - } - - return true; } - inline const Swapchain::Image& Swapchain::GetImage(UInt32 index) const - { - return m_images[index]; - } + return true; + } - inline const std::vector& Swapchain::GetImages() const - { - return m_images; - } + inline const Swapchain::Image& Swapchain::GetImage(UInt32 index) const + { + return m_images[index]; + } - inline UInt32 Swapchain::GetImageCount() const - { - return static_cast(m_images.size()); - } + inline const std::vector& Swapchain::GetImages() const + { + return m_images; + } - inline bool Swapchain::IsSupported() const - { - if (!m_device->IsExtensionLoaded(VK_KHR_SWAPCHAIN_EXTENSION_NAME)) - return false; + inline UInt32 Swapchain::GetImageCount() const + { + return static_cast(m_images.size()); + } - return true; - } + inline bool Swapchain::IsSupported() const + { + if (!m_device->IsExtensionLoaded(VK_KHR_SWAPCHAIN_EXTENSION_NAME)) + return false; - inline VkResult Swapchain::CreateHelper(Device& device, const VkSwapchainCreateInfoKHR* createInfo, const VkAllocationCallbacks* allocator, VkSwapchainKHR* handle) - { - return device.vkCreateSwapchainKHR(device, createInfo, allocator, handle); - } + return true; + } - inline void Swapchain::DestroyHelper(Device& device, VkSwapchainKHR handle, const VkAllocationCallbacks* allocator) - { - return device.vkDestroySwapchainKHR(device, handle, allocator); - } + inline VkResult Swapchain::CreateHelper(Device& device, const VkSwapchainCreateInfoKHR* createInfo, const VkAllocationCallbacks* allocator, VkSwapchainKHR* handle) + { + return device.vkCreateSwapchainKHR(device, createInfo, allocator, handle); + } + + inline void Swapchain::DestroyHelper(Device& device, VkSwapchainKHR handle, const VkAllocationCallbacks* allocator) + { + return device.vkDestroySwapchainKHR(device, handle, allocator); } } diff --git a/src/Nazara/Graphics/DirectionalLightShadowData.cpp b/src/Nazara/Graphics/DirectionalLightShadowData.cpp index 36aebd5bc..0bdfea5a8 100644 --- a/src/Nazara/Graphics/DirectionalLightShadowData.cpp +++ b/src/Nazara/Graphics/DirectionalLightShadowData.cpp @@ -230,11 +230,12 @@ namespace Nz PerViewerData& viewerData = *Retrieve(m_viewerData, viewer); viewerData.textureArrayAttachmentIndex = frameGraph.AddAttachmentArray({ - "Directional-light cascade shadowmaps", - m_light.GetShadowMapFormat(), - FramePassAttachmentSize::Fixed, - shadowMapSize, shadowMapSize, - }, m_cascadeCount); + .name = "Directional-light cascade shadowmaps", + .format = m_light.GetShadowMapFormat(), + .size = FramePassAttachmentSize::Fixed, + .width = shadowMapSize, + .height = shadowMapSize, + }, SafeCast(m_cascadeCount)); for (std::size_t i = 0; i < viewerData.cascades.size(); ++i) { diff --git a/src/Nazara/Graphics/ForwardFramePipeline.cpp b/src/Nazara/Graphics/ForwardFramePipeline.cpp index c00ab2313..6e4b0fbab 100644 --- a/src/Nazara/Graphics/ForwardFramePipeline.cpp +++ b/src/Nazara/Graphics/ForwardFramePipeline.cpp @@ -470,23 +470,6 @@ namespace Nz } }); } - - for (auto&& [_, renderTargetData] : m_renderTargets) - { - if (renderTargetData.blitShaderBinding) - renderFrame.PushForRelease(std::move(renderTargetData.blitShaderBinding)); - - renderTargetData.blitShaderBinding = graphics->GetBlitPipelineLayout()->AllocateShaderBinding(0); - renderTargetData.blitShaderBinding->Update({ - { - 0, - ShaderBinding::SampledTextureBinding { - m_bakedFrameGraph.GetAttachmentTexture(renderTargetData.finalAttachment).get(), - sampler.get() - } - } - }); - } } // Update UBOs and materials @@ -511,39 +494,14 @@ namespace Nz m_rebuildFrameGraph = false; // Final blit (TODO: Make part of frame graph) - const Vector2ui& frameSize = renderFrame.GetSize(); for (auto&& [renderTargetPtr, renderTargetData] : m_renderTargets) { - Recti renderRegion(0, 0, frameSize.x, frameSize.y); - const RenderTarget& renderTarget = *renderTargetPtr; const auto& data = renderTargetData; renderFrame.Execute([&](CommandBufferBuilder& builder) { const std::shared_ptr& sourceTexture = m_bakedFrameGraph.GetAttachmentTexture(data.finalAttachment); - - builder.TextureBarrier(PipelineStage::ColorOutput, PipelineStage::FragmentShader, MemoryAccess::ColorWrite, MemoryAccess::ShaderRead, TextureLayout::ColorOutput, TextureLayout::ColorInput, *sourceTexture); - - std::array clearValues; - clearValues[0].color = Color::Black(); - clearValues[1].depth = 1.f; - clearValues[1].stencil = 0; - - builder.BeginRenderPass(renderTarget.GetFramebuffer(renderFrame.GetFramebufferIndex()), renderTarget.GetRenderPass(), renderRegion, { clearValues[0], clearValues[1] }); - { - builder.BeginDebugRegion("Main window rendering", Color::Green()); - { - builder.SetScissor(renderRegion); - builder.SetViewport(renderRegion); - builder.BindRenderPipeline(*graphics->GetBlitPipeline(false)); - - builder.BindRenderShaderBinding(0, *data.blitShaderBinding); - builder.Draw(3); - } - builder.EndDebugRegion(); - } - builder.EndRenderPass(); - + renderTarget.BlitTexture(renderFrame, builder, *sourceTexture); }, QueueType::Graphics); } @@ -748,13 +706,7 @@ namespace Nz return lhs.second->renderOrder < rhs.second->renderOrder; }); - for (auto&& [_, renderTargetData] : m_renderTargets) - { - if (renderTargetData.blitShaderBinding) - renderFrame.PushForRelease(std::move(renderTargetData.blitShaderBinding)); - } m_renderTargets.clear(); - for (auto&& [renderTarget, viewerData] : viewers) { auto& renderTargetData = m_renderTargets[renderTarget]; diff --git a/src/Nazara/Graphics/FrameGraph.cpp b/src/Nazara/Graphics/FrameGraph.cpp index e72b5ea1a..8735dc1e9 100644 --- a/src/Nazara/Graphics/FrameGraph.cpp +++ b/src/Nazara/Graphics/FrameGraph.cpp @@ -1035,6 +1035,7 @@ namespace Nz data.height = attachmentData.height; data.size = attachmentData.size; data.layerCount = 1; + data.usage = attachmentData.additionalUsage; return textureId; } @@ -1077,6 +1078,7 @@ namespace Nz data.height = attachmentData.height; data.size = attachmentData.size; data.layerCount = attachmentData.layerCount; + data.usage = attachmentData.additionalUsage; return textureId; } @@ -1118,6 +1120,7 @@ namespace Nz data.height = attachmentData.height; data.size = attachmentData.size; data.layerCount = 1; + data.usage = attachmentData.additionalUsage; return textureId; } diff --git a/src/Nazara/Graphics/PointLightShadowData.cpp b/src/Nazara/Graphics/PointLightShadowData.cpp index 076011ff1..e4a35a46d 100644 --- a/src/Nazara/Graphics/PointLightShadowData.cpp +++ b/src/Nazara/Graphics/PointLightShadowData.cpp @@ -148,10 +148,11 @@ namespace Nz UInt32 shadowMapSize = m_light.GetShadowMapSize(); m_cubeAttachmentIndex = frameGraph.AddAttachmentCube({ - "Point-light shadowmap", - m_light.GetShadowMapFormat(), - FramePassAttachmentSize::Fixed, - shadowMapSize, shadowMapSize, + .name = "Point-light shadowmap", + .format = m_light.GetShadowMapFormat(), + .size = FramePassAttachmentSize::Fixed, + .width = shadowMapSize, + .height = shadowMapSize, }); for (std::size_t i = 0; i < m_directions.size(); ++i) diff --git a/src/Nazara/Graphics/SpotLightShadowData.cpp b/src/Nazara/Graphics/SpotLightShadowData.cpp index 4442298b9..fc09420e9 100644 --- a/src/Nazara/Graphics/SpotLightShadowData.cpp +++ b/src/Nazara/Graphics/SpotLightShadowData.cpp @@ -102,10 +102,11 @@ namespace Nz UInt32 shadowMapSize = m_light.GetShadowMapSize(); m_attachmentIndex = frameGraph.AddAttachment({ - "Shadowmap", - m_light.GetShadowMapFormat(), - FramePassAttachmentSize::Fixed, - shadowMapSize, shadowMapSize, + .name = "Shadowmap", + .format = m_light.GetShadowMapFormat(), + .size = FramePassAttachmentSize::Fixed, + .width = shadowMapSize, + .height = shadowMapSize, }); FramePipelinePass::PassInputOuputs passInputOuputs; diff --git a/src/Nazara/OpenGLRenderer/OpenGLCommandBuffer.cpp b/src/Nazara/OpenGLRenderer/OpenGLCommandBuffer.cpp index 0a9667c4a..309a92221 100644 --- a/src/Nazara/OpenGLRenderer/OpenGLCommandBuffer.cpp +++ b/src/Nazara/OpenGLRenderer/OpenGLCommandBuffer.cpp @@ -146,6 +146,11 @@ namespace Nz context->BlitTexture(*command.source, *command.target, command.sourceBox, command.targetBox, command.filter); } + inline void OpenGLCommandBuffer::Execute(const GL::Context* context, const BlitTextureToWindowCommand& command) + { + context->BlitTextureToWindow(*command.source, command.sourceBox, command.targetBox, command.filter); + } + inline void OpenGLCommandBuffer::Execute(const GL::Context* /*context*/, const BuildTextureMipmapsCommand& command) { command.texture->GenerateMipmaps(command.baseLevel, command.levelCount); diff --git a/src/Nazara/OpenGLRenderer/OpenGLCommandBufferBuilder.cpp b/src/Nazara/OpenGLRenderer/OpenGLCommandBufferBuilder.cpp index 48b6b71b9..252def75c 100644 --- a/src/Nazara/OpenGLRenderer/OpenGLCommandBufferBuilder.cpp +++ b/src/Nazara/OpenGLRenderer/OpenGLCommandBufferBuilder.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -24,101 +25,114 @@ namespace Nz void OpenGLCommandBufferBuilder::BeginRenderPass(const Framebuffer& framebuffer, const RenderPass& renderPass, const Recti& /*renderRect*/, const ClearValues* clearValues, std::size_t clearValueCount) { - m_commandBuffer.SetFramebuffer(static_cast(framebuffer), static_cast(renderPass), clearValues, clearValueCount); + m_commandBuffer.SetFramebuffer(SafeCast(framebuffer), SafeCast(renderPass), clearValues, clearValueCount); } void OpenGLCommandBufferBuilder::BindComputePipeline(const ComputePipeline& pipeline) { - const OpenGLComputePipeline& glPipeline = static_cast(pipeline); + const OpenGLComputePipeline& glPipeline = SafeCast(pipeline); m_commandBuffer.BindComputePipeline(&glPipeline); } void OpenGLCommandBufferBuilder::BindComputeShaderBinding(UInt32 set, const ShaderBinding& binding) { - const OpenGLShaderBinding& glBinding = static_cast(binding); + const OpenGLShaderBinding& glBinding = SafeCast(binding); m_commandBuffer.BindComputeShaderBinding(glBinding.GetOwner(), set, &glBinding); } void OpenGLCommandBufferBuilder::BindComputeShaderBinding(const RenderPipelineLayout& pipelineLayout, UInt32 set, const ShaderBinding& binding) { - const OpenGLRenderPipelineLayout& glPipelineLayout = static_cast(pipelineLayout); - const OpenGLShaderBinding& glBinding = static_cast(binding); + const OpenGLRenderPipelineLayout& glPipelineLayout = SafeCast(pipelineLayout); + const OpenGLShaderBinding& glBinding = SafeCast(binding); m_commandBuffer.BindComputeShaderBinding(glPipelineLayout, set, &glBinding); } void OpenGLCommandBufferBuilder::BindIndexBuffer(const RenderBuffer& indexBuffer, IndexType indexType, UInt64 offset) { - const OpenGLBuffer& glBuffer = static_cast(indexBuffer); + const OpenGLBuffer& glBuffer = SafeCast(indexBuffer); m_commandBuffer.BindIndexBuffer(glBuffer.GetBuffer().GetObjectId(), indexType, offset); } void OpenGLCommandBufferBuilder::BindRenderPipeline(const RenderPipeline& pipeline) { - const OpenGLRenderPipeline& glPipeline = static_cast(pipeline); + const OpenGLRenderPipeline& glPipeline = SafeCast(pipeline); m_commandBuffer.BindRenderPipeline(&glPipeline); } void OpenGLCommandBufferBuilder::BindRenderShaderBinding(UInt32 set, const ShaderBinding& binding) { - const OpenGLShaderBinding& glBinding = static_cast(binding); + const OpenGLShaderBinding& glBinding = SafeCast(binding); m_commandBuffer.BindRenderShaderBinding(glBinding.GetOwner(), set, &glBinding); } void OpenGLCommandBufferBuilder::BindRenderShaderBinding(const RenderPipelineLayout& pipelineLayout, UInt32 set, const ShaderBinding& binding) { - const OpenGLRenderPipelineLayout& glPipelineLayout = static_cast(pipelineLayout); - const OpenGLShaderBinding& glBinding = static_cast(binding); + const OpenGLRenderPipelineLayout& glPipelineLayout = SafeCast(pipelineLayout); + const OpenGLShaderBinding& glBinding = SafeCast(binding); m_commandBuffer.BindRenderShaderBinding(glPipelineLayout, set, &glBinding); } void OpenGLCommandBufferBuilder::BindVertexBuffer(UInt32 binding, const RenderBuffer& vertexBuffer, UInt64 offset) { - const OpenGLBuffer& glBuffer = static_cast(vertexBuffer); + const OpenGLBuffer& glBuffer = SafeCast(vertexBuffer); m_commandBuffer.BindVertexBuffer(binding, glBuffer.GetBuffer().GetObjectId(), offset); } void OpenGLCommandBufferBuilder::BlitTexture(const Texture& fromTexture, const Boxui& fromBox, TextureLayout /*fromLayout*/, const Texture& toTexture, const Boxui& toBox, TextureLayout /*toLayout*/, SamplerFilter filter) { - const OpenGLTexture& sourceTexture = static_cast(fromTexture); - const OpenGLTexture& targetTexture = static_cast(toTexture); + const OpenGLTexture& sourceTexture = SafeCast(fromTexture); + const OpenGLTexture& targetTexture = SafeCast(toTexture); m_commandBuffer.BlitTexture(sourceTexture, fromBox, targetTexture, toBox, filter); } + void OpenGLCommandBufferBuilder::BlitTextureToSwapchain(const Texture& fromTexture, const Boxui& fromBox, TextureLayout fromLayout, const Swapchain& swapchain, std::size_t imageIndex) + { + const OpenGLTexture& glTexture = SafeCast(fromTexture); + const OpenGLSwapchain& glSwapchain = SafeCast(swapchain); + + Vector2ui swapchainSize = glSwapchain.GetSize(); + + // We set the framebuffer to ensure the correct OpenGL context is activated (in case we're using multiple contextes) + m_commandBuffer.SetFramebuffer(glSwapchain.GetFramebuffer(imageIndex), glSwapchain.GetRenderPass(), nullptr, 0); + + m_commandBuffer.BlitTextureToWindow(glTexture, fromBox, Boxui(0, 0, 0, swapchainSize.x, swapchainSize.y, 1), SamplerFilter::Linear); + } + void OpenGLCommandBufferBuilder::BuildMipmaps(Texture& texture, UInt8 baseLevel, UInt8 levelCount, PipelineStageFlags srcStageMask, PipelineStageFlags /*dstStageMask*/, MemoryAccessFlags /*srcAccessMask*/, MemoryAccessFlags /*dstAccessMask*/, TextureLayout /*oldLayout*/, TextureLayout /*newLayout*/) { - OpenGLTexture& glTexture = static_cast(texture); + OpenGLTexture& glTexture = SafeCast(texture); m_commandBuffer.BuildMipmaps(glTexture, baseLevel, levelCount); } void OpenGLCommandBufferBuilder::CopyBuffer(const RenderBufferView& source, const RenderBufferView& target, UInt64 size, UInt64 sourceOffset, UInt64 targetOffset) { - OpenGLBuffer& sourceBuffer = *static_cast(source.GetBuffer()); - OpenGLBuffer& targetBuffer = *static_cast(target.GetBuffer()); + OpenGLBuffer& sourceBuffer = *SafeCast(source.GetBuffer()); + OpenGLBuffer& targetBuffer = *SafeCast(target.GetBuffer()); m_commandBuffer.CopyBuffer(sourceBuffer.GetBuffer().GetObjectId(), targetBuffer.GetBuffer().GetObjectId(), size, sourceOffset + source.GetOffset(), targetOffset + target.GetOffset()); } void OpenGLCommandBufferBuilder::CopyBuffer(const UploadPool::Allocation& allocation, const RenderBufferView& target, UInt64 size, UInt64 sourceOffset, UInt64 targetOffset) { - OpenGLBuffer& targetBuffer = *static_cast(target.GetBuffer()); + OpenGLBuffer& targetBuffer = *SafeCast(target.GetBuffer()); m_commandBuffer.CopyBuffer(allocation, targetBuffer.GetBuffer().GetObjectId(), size, sourceOffset, target.GetOffset() + targetOffset); } void OpenGLCommandBufferBuilder::CopyTexture(const Texture& fromTexture, const Boxui& fromBox, TextureLayout /*fromLayout*/, const Texture& toTexture, const Vector3ui& toPos, TextureLayout /*toLayout*/) { - const OpenGLTexture& sourceTexture = static_cast(fromTexture); - const OpenGLTexture& targetTexture = static_cast(toTexture); + const OpenGLTexture& sourceTexture = SafeCast(fromTexture); + const OpenGLTexture& targetTexture = SafeCast(toTexture); m_commandBuffer.CopyTexture(sourceTexture, fromBox, targetTexture, toPos); } diff --git a/src/Nazara/OpenGLRenderer/OpenGLRenderImage.cpp b/src/Nazara/OpenGLRenderer/OpenGLRenderImage.cpp index 3a1cb7778..c7aaa80bd 100644 --- a/src/Nazara/OpenGLRenderer/OpenGLRenderImage.cpp +++ b/src/Nazara/OpenGLRenderer/OpenGLRenderImage.cpp @@ -12,6 +12,7 @@ namespace Nz { OpenGLRenderImage::OpenGLRenderImage(OpenGLSwapchain& owner) : + RenderImage(owner.GetDevice()), m_owner(owner), m_uploadPool(2 * 1024 * 1024) { diff --git a/src/Nazara/OpenGLRenderer/OpenGLSwapchain.cpp b/src/Nazara/OpenGLRenderer/OpenGLSwapchain.cpp index 56551ab9e..f9f2ea6f7 100644 --- a/src/Nazara/OpenGLRenderer/OpenGLSwapchain.cpp +++ b/src/Nazara/OpenGLRenderer/OpenGLSwapchain.cpp @@ -12,6 +12,7 @@ namespace Nz { OpenGLSwapchain::OpenGLSwapchain(OpenGLDevice& device, WindowHandle windowHandle, const Vector2ui& windowSize, const SwapchainParameters& parameters) : m_currentFrame(0), + m_device(device), m_framebuffer(*this), m_size(windowSize), m_sizeInvalidated(false) @@ -22,7 +23,7 @@ namespace Nz #endif //TODO: Pass swapchain parameters to context - m_context = device.CreateContext(contextParams, windowHandle); + m_context = m_device.CreateContext(contextParams, windowHandle); if (!m_context) throw std::runtime_error("failed to create swapchain context"); diff --git a/src/Nazara/OpenGLRenderer/Wrapper/Context.cpp b/src/Nazara/OpenGLRenderer/Wrapper/Context.cpp index 08354185a..c276824bf 100644 --- a/src/Nazara/OpenGLRenderer/Wrapper/Context.cpp +++ b/src/Nazara/OpenGLRenderer/Wrapper/Context.cpp @@ -310,7 +310,7 @@ namespace Nz::GL } } - bool Context::BlitTexture(const OpenGLTexture& texture, const OpenGLTexture& destination, const Boxui& srcBox, const Boxui& dstBox, SamplerFilter filter) const + bool Context::BlitTexture(const OpenGLTexture& source, const OpenGLTexture& destination, const Boxui& srcBox, const Boxui& dstBox, SamplerFilter filter) const { if (!m_blitFramebuffers && !InitializeBlitFramebuffers()) return false; @@ -363,7 +363,7 @@ namespace Nz::GL }; // Attach textures to color attachment - BindTexture(m_blitFramebuffers->readFBO, texture); + BindTexture(m_blitFramebuffers->readFBO, source); BindTexture(m_blitFramebuffers->drawFBO, destination); // Validate framebuffer completeness @@ -383,6 +383,29 @@ namespace Nz::GL return true; } + bool Context::BlitTextureToWindow(const OpenGLTexture& texture, const Boxui& srcBox, const Boxui& dstBox, SamplerFilter filter) const + { + if (!m_blitFramebuffers && !InitializeBlitFramebuffers()) + return false; + + // Bind framebuffers before configuring them (so they won't override each other) + BindFramebuffer(FramebufferTarget::Draw, 0); + BindFramebuffer(FramebufferTarget::Read, m_blitFramebuffers->readFBO.GetObjectId()); + + // Attach textures to color attachment + BindTextureToFramebuffer(m_blitFramebuffers->readFBO, texture); + + // Validate framebuffer completeness + if (GLenum checkResult = m_blitFramebuffers->readFBO.Check(); checkResult != GL_FRAMEBUFFER_COMPLETE) + { + NazaraErrorFmt("blit read FBO is incomplete: {0}", TranslateOpenGLError(checkResult)); + return false; + } + + glBlitFramebuffer(srcBox.x, srcBox.y, srcBox.x + srcBox.width, srcBox.y + srcBox.height, dstBox.x, dstBox.y + srcBox.height, dstBox.x + dstBox.width, dstBox.y, GL_COLOR_BUFFER_BIT, ToOpenGL(filter)); + return true; + } + bool Context::ClearErrorStack() const { assert(GetCurrentContext() == this); @@ -1196,4 +1219,47 @@ namespace Nz::GL return true; } + + void Context::BindTextureToFramebuffer(Framebuffer& framebuffer, const OpenGLTexture& texture) + { + if (texture.RequiresTextureViewEmulation()) + { + const TextureViewInfo& texViewInfo = texture.GetTextureViewInfo(); + if (texViewInfo.viewType != ImageType::E2D) + throw std::runtime_error("unrestricted texture views can only be used as 2D texture attachment"); + + const OpenGLTexture& parentTexture = *texture.GetParentTexture(); + + switch (parentTexture.GetType()) + { + case ImageType::Cubemap: + { + constexpr std::array faceTargets = { GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z }; + assert(texViewInfo.baseArrayLayer < faceTargets.size()); + + GLenum texTarget = faceTargets[texViewInfo.baseArrayLayer]; + framebuffer.Texture2D(GL_COLOR_ATTACHMENT0, texTarget, parentTexture.GetTexture().GetObjectId(), texViewInfo.baseMipLevel); + break; + } + + case ImageType::E1D: + case ImageType::E2D: + framebuffer.Texture2D(GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, parentTexture.GetTexture().GetObjectId(), texViewInfo.baseMipLevel); + break; + + case ImageType::E1D_Array: + case ImageType::E2D_Array: + case ImageType::E3D: + framebuffer.TextureLayer(GL_COLOR_ATTACHMENT0, parentTexture.GetTexture().GetObjectId(), texViewInfo.baseArrayLayer, texViewInfo.baseMipLevel); + break; + } + } + else + { + if (texture.GetTexture().GetTarget() != TextureTarget::Target2D) + throw std::runtime_error("blit is not yet supported from/to other texture type than 2D textures"); + + framebuffer.Texture2D(GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.GetTexture().GetObjectId(), 0); + } + } } diff --git a/src/Nazara/Renderer/Swapchain.cpp b/src/Nazara/Renderer/Swapchain.cpp index edac19f86..dcee0347b 100644 --- a/src/Nazara/Renderer/Swapchain.cpp +++ b/src/Nazara/Renderer/Swapchain.cpp @@ -3,12 +3,28 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include +#include +#include #include namespace Nz { Swapchain::~Swapchain() = default; + void Swapchain::BlitTexture(RenderFrame& renderFrame, CommandBufferBuilder& builder, const Texture& texture) const + { + Vector2ui textureSize = Vector2ui(texture.GetSize()); + Boxui blitRegion(0, 0, 0, textureSize.x, textureSize.y, 1); + + builder.TextureBarrier(PipelineStage::ColorOutput, PipelineStage::Transfer, MemoryAccess::ColorWrite, MemoryAccess::TransferRead, TextureLayout::ColorOutput, TextureLayout::TransferSource, texture); + + builder.BeginDebugRegion("Blit to swapchain", Color::Blue()); + { + builder.BlitTextureToSwapchain(texture, blitRegion, TextureLayout::TransferSource, *this, renderFrame.GetFramebufferIndex()); + } + builder.EndDebugRegion(); + } + void Swapchain::BuildRenderPass(PixelFormat colorFormat, PixelFormat depthFormat, std::vector& attachments, std::vector& subpassDescriptions, std::vector& subpassDependencies) { assert(colorFormat != PixelFormat::Undefined); diff --git a/src/Nazara/VulkanRenderer/VulkanCommandBufferBuilder.cpp b/src/Nazara/VulkanRenderer/VulkanCommandBufferBuilder.cpp index 78bc6300f..bb3b4bd25 100644 --- a/src/Nazara/VulkanRenderer/VulkanCommandBufferBuilder.cpp +++ b/src/Nazara/VulkanRenderer/VulkanCommandBufferBuilder.cpp @@ -10,10 +10,12 @@ #include #include #include +#include #include #include #include #include +#include #include #include @@ -31,8 +33,8 @@ namespace Nz void VulkanCommandBufferBuilder::BeginRenderPass(const Framebuffer& framebuffer, const RenderPass& renderPass, const Recti& renderRect, const ClearValues* clearValues, std::size_t clearValueCount) { - const VulkanRenderPass& vkRenderPass = static_cast(renderPass); - const VulkanFramebuffer& vkFramebuffer = static_cast(framebuffer); + const VulkanRenderPass& vkRenderPass = SafeCast(renderPass); + const VulkanFramebuffer& vkFramebuffer = SafeCast(framebuffer); std::size_t attachmentCount = vkRenderPass.GetAttachmentCount(); @@ -80,14 +82,14 @@ namespace Nz void VulkanCommandBufferBuilder::BindComputePipeline(const ComputePipeline& pipeline) { - const VulkanComputePipeline& vkPipeline = static_cast(pipeline); + const VulkanComputePipeline& vkPipeline = SafeCast(pipeline); m_commandBuffer.BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, vkPipeline.GetPipeline()); } void VulkanCommandBufferBuilder::BindComputeShaderBinding(UInt32 set, const ShaderBinding& binding) { - const VulkanShaderBinding& vkBinding = static_cast(binding); + const VulkanShaderBinding& vkBinding = SafeCast(binding); const VulkanRenderPipelineLayout& pipelineLayout = vkBinding.GetOwner(); m_commandBuffer.BindDescriptorSet(VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout.GetPipelineLayout(), set, vkBinding.GetDescriptorSet()); @@ -95,15 +97,15 @@ namespace Nz void VulkanCommandBufferBuilder::BindComputeShaderBinding(const RenderPipelineLayout& pipelineLayout, UInt32 set, const ShaderBinding& binding) { - const VulkanRenderPipelineLayout& vkPipelineLayout = static_cast(pipelineLayout); - const VulkanShaderBinding& vkBinding = static_cast(binding); + const VulkanRenderPipelineLayout& vkPipelineLayout = SafeCast(pipelineLayout); + const VulkanShaderBinding& vkBinding = SafeCast(binding); m_commandBuffer.BindDescriptorSet(VK_PIPELINE_BIND_POINT_COMPUTE, vkPipelineLayout.GetPipelineLayout(), set, vkBinding.GetDescriptorSet()); } void VulkanCommandBufferBuilder::BindIndexBuffer(const RenderBuffer& indexBuffer, IndexType indexType, UInt64 offset) { - const VulkanBuffer& vkBuffer = static_cast(indexBuffer); + const VulkanBuffer& vkBuffer = SafeCast(indexBuffer); m_commandBuffer.BindIndexBuffer(vkBuffer.GetBuffer(), offset, ToVulkan(indexType)); } @@ -113,14 +115,14 @@ namespace Nz if (!m_currentRenderPass) throw std::runtime_error("BindPipeline must be called in a RenderPass"); - const VulkanRenderPipeline& vkPipeline = static_cast(pipeline); + const VulkanRenderPipeline& vkPipeline = SafeCast(pipeline); m_commandBuffer.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, vkPipeline.Get(*m_currentRenderPass, m_currentSubpassIndex)); } void VulkanCommandBufferBuilder::BindRenderShaderBinding(UInt32 set, const ShaderBinding& binding) { - const VulkanShaderBinding& vkBinding = static_cast(binding); + const VulkanShaderBinding& vkBinding = SafeCast(binding); const VulkanRenderPipelineLayout& pipelineLayout = vkBinding.GetOwner(); m_commandBuffer.BindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.GetPipelineLayout(), set, vkBinding.GetDescriptorSet()); @@ -128,23 +130,23 @@ namespace Nz void VulkanCommandBufferBuilder::BindRenderShaderBinding(const RenderPipelineLayout& pipelineLayout, UInt32 set, const ShaderBinding& binding) { - const VulkanRenderPipelineLayout& vkPipelineLayout = static_cast(pipelineLayout); - const VulkanShaderBinding& vkBinding = static_cast(binding); + const VulkanRenderPipelineLayout& vkPipelineLayout = SafeCast(pipelineLayout); + const VulkanShaderBinding& vkBinding = SafeCast(binding); m_commandBuffer.BindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, vkPipelineLayout.GetPipelineLayout(), set, vkBinding.GetDescriptorSet()); } void VulkanCommandBufferBuilder::BindVertexBuffer(UInt32 binding, const RenderBuffer& vertexBuffer, UInt64 offset) { - const VulkanBuffer& vkBuffer = static_cast(vertexBuffer); + const VulkanBuffer& vkBuffer = SafeCast(vertexBuffer); m_commandBuffer.BindVertexBuffer(binding, vkBuffer.GetBuffer(), offset); } void VulkanCommandBufferBuilder::BlitTexture(const Texture& fromTexture, const Boxui& fromBox, TextureLayout fromLayout, const Texture& toTexture, const Boxui& toBox, TextureLayout toLayout, SamplerFilter filter) { - const VulkanTexture& vkFromTexture = static_cast(fromTexture); - const VulkanTexture& vkToTexture = static_cast(toTexture); + const VulkanTexture& vkFromTexture = SafeCast(fromTexture); + const VulkanTexture& vkToTexture = SafeCast(toTexture); unsigned int fromBaseLayer, fromLayerCount; Image::RegionToArray(vkFromTexture.GetType(), fromBox, fromBaseLayer, fromLayerCount); @@ -184,9 +186,52 @@ namespace Nz m_commandBuffer.BlitImage(vkFromTexture.GetImage(), ToVulkan(fromLayout), vkToTexture.GetImage(), ToVulkan(toLayout), region, ToVulkan(filter)); } + void VulkanCommandBufferBuilder::BlitTextureToSwapchain(const Texture& fromTexture, const Boxui& fromBox, TextureLayout fromLayout, const Swapchain& swapchain, std::size_t imageIndex) + { + const VulkanTexture& vkFromTexture = SafeCast(fromTexture); + const VulkanSwapchain& vkSwapchain = SafeCast(swapchain); + + VkImage swapchainImage = vkSwapchain.GetImage(imageIndex); + + VkImageSubresourceRange swapchainImageRange = { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .baseMipLevel = 0, + .levelCount = 1, + .baseArrayLayer = 0, + .layerCount = 1, + }; + + Boxi fromBoxInt = Boxi(fromBox); + Vector2i swapchainSize = Vector2i(vkSwapchain.GetSize()); + + VkImageBlit swapchainBlit = { + .srcSubresource = vkFromTexture.BuildSubresourceLayers(0), + .srcOffsets = { + { fromBoxInt.x, fromBoxInt.y, fromBoxInt.z }, + { fromBoxInt.x + fromBoxInt.width, fromBoxInt.y + fromBoxInt.height, fromBoxInt.z + fromBoxInt.depth } + }, + .dstSubresource = { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .mipLevel = 0, + .baseArrayLayer = 0, + .layerCount = 1, + }, + .dstOffsets = { + { 0, 0, 0 }, + { swapchainSize.x, swapchainSize.y, 1 } + }, + }; + + m_commandBuffer.SetImageLayout(swapchainImage, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, swapchainImageRange); + + m_commandBuffer.BlitImage(vkFromTexture.GetImage(), ToVulkan(fromLayout), vkSwapchain.GetImage(imageIndex), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, swapchainBlit, VK_FILTER_LINEAR); + + m_commandBuffer.SetImageLayout(swapchainImage, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, swapchainImageRange); + } + void VulkanCommandBufferBuilder::BuildMipmaps(Texture& texture, UInt8 baseLevel, UInt8 levelCount, PipelineStageFlags srcStageMask, PipelineStageFlags dstStageMask, MemoryAccessFlags srcAccessMask, MemoryAccessFlags dstAccessMask, TextureLayout oldLayout, TextureLayout newLayout) { - VulkanTexture& vkTexture = static_cast(texture); + VulkanTexture& vkTexture = SafeCast(texture); VkImage vkImage = vkTexture.GetImage(); const TextureInfo& textureInfo = vkTexture.GetTextureInfo(); @@ -246,24 +291,24 @@ namespace Nz void VulkanCommandBufferBuilder::CopyBuffer(const RenderBufferView& source, const RenderBufferView& target, UInt64 size, UInt64 sourceOffset, UInt64 targetOffset) { - VulkanBuffer& sourceBuffer = *static_cast(source.GetBuffer()); - VulkanBuffer& targetBuffer = *static_cast(target.GetBuffer()); + VulkanBuffer& sourceBuffer = *SafeCast(source.GetBuffer()); + VulkanBuffer& targetBuffer = *SafeCast(target.GetBuffer()); m_commandBuffer.CopyBuffer(sourceBuffer.GetBuffer(), targetBuffer.GetBuffer(), size, sourceOffset + source.GetOffset(), targetOffset + target.GetOffset()); } void VulkanCommandBufferBuilder::CopyBuffer(const UploadPool::Allocation& allocation, const RenderBufferView& target, UInt64 size, UInt64 sourceOffset, UInt64 targetOffset) { - const auto& vkAllocation = static_cast(allocation); - VulkanBuffer& targetBuffer = *static_cast(target.GetBuffer()); + const auto& vkAllocation = SafeCast(allocation); + VulkanBuffer& targetBuffer = *SafeCast(target.GetBuffer()); m_commandBuffer.CopyBuffer(vkAllocation.buffer, targetBuffer.GetBuffer(), size, vkAllocation.offset + sourceOffset, target.GetOffset() + targetOffset); } void VulkanCommandBufferBuilder::CopyTexture(const Texture& fromTexture, const Boxui& fromBox, TextureLayout fromLayout, const Texture& toTexture, const Vector3ui& toPos, TextureLayout toLayout) { - const VulkanTexture& vkFromTexture = static_cast(fromTexture); - const VulkanTexture& vkToTexture = static_cast(toTexture); + const VulkanTexture& vkFromTexture = SafeCast(fromTexture); + const VulkanTexture& vkToTexture = SafeCast(toTexture); unsigned int fromBaseLayer, fromLayerCount; Image::RegionToArray(vkFromTexture.GetType(), fromBox, fromBaseLayer, fromLayerCount); @@ -358,7 +403,7 @@ namespace Nz void VulkanCommandBufferBuilder::TextureBarrier(PipelineStageFlags srcStageMask, PipelineStageFlags dstStageMask, MemoryAccessFlags srcAccessMask, MemoryAccessFlags dstAccessMask, TextureLayout oldLayout, TextureLayout newLayout, const Texture& texture) { - const VulkanTexture& vkTexture = static_cast(texture); + const VulkanTexture& vkTexture = SafeCast(texture); m_commandBuffer.ImageBarrier(ToVulkan(srcStageMask), ToVulkan(dstStageMask), VkDependencyFlags(0), ToVulkan(srcAccessMask), ToVulkan(dstAccessMask), ToVulkan(oldLayout), ToVulkan(newLayout), vkTexture.GetImage(), vkTexture.GetSubresourceRange()); } diff --git a/src/Nazara/VulkanRenderer/VulkanRenderImage.cpp b/src/Nazara/VulkanRenderer/VulkanRenderImage.cpp index bc22220f7..867d734b7 100644 --- a/src/Nazara/VulkanRenderer/VulkanRenderImage.cpp +++ b/src/Nazara/VulkanRenderer/VulkanRenderImage.cpp @@ -13,6 +13,7 @@ namespace Nz { VulkanRenderImage::VulkanRenderImage(VulkanSwapchain& owner) : + RenderImage(owner.GetDevice()), m_freeCommandBufferIndex(0), m_owner(owner), m_uploadPool(m_owner.GetDevice(), 2 * 1024 * 1024) diff --git a/src/Nazara/VulkanRenderer/VulkanSwapchain.cpp b/src/Nazara/VulkanRenderer/VulkanSwapchain.cpp index b8f09a849..717715709 100644 --- a/src/Nazara/VulkanRenderer/VulkanSwapchain.cpp +++ b/src/Nazara/VulkanRenderer/VulkanSwapchain.cpp @@ -293,10 +293,10 @@ namespace Nz return true; } - const VulkanWindowFramebuffer& VulkanSwapchain::GetFramebuffer(std::size_t i) const + const VulkanWindowFramebuffer& VulkanSwapchain::GetFramebuffer(std::size_t imageIndex) const { - assert(i < m_framebuffers.size()); - return m_framebuffers[i]; + assert(imageIndex < m_framebuffers.size()); + return m_framebuffers[imageIndex]; } std::size_t VulkanSwapchain::GetFramebufferCount() const @@ -628,7 +628,7 @@ namespace Nz m_surfaceFormat.colorSpace, extent, 1, - VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, + VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, VK_SHARING_MODE_EXCLUSIVE, 0, nullptr, surfaceCapabilities.currentTransform,