diff --git a/include/Nazara/OpenGLRenderer/OpenGLDevice.hpp b/include/Nazara/OpenGLRenderer/OpenGLDevice.hpp index 412503875..e8305e55b 100644 --- a/include/Nazara/OpenGLRenderer/OpenGLDevice.hpp +++ b/include/Nazara/OpenGLRenderer/OpenGLDevice.hpp @@ -32,8 +32,6 @@ namespace Nz std::shared_ptr CreateContext(GL::ContextParams params) const; std::shared_ptr CreateContext(GL::ContextParams params, WindowHandle handle) const; - void Execute(const FunctionRef& callback, QueueType queueType) override; - const RenderDeviceInfo& GetDeviceInfo() const override; const RenderDeviceFeatures& GetEnabledFeatures() const override; inline const GL::Context& GetReferenceContext() const; diff --git a/include/Nazara/OpenGLRenderer/OpenGLSwapchain.hpp b/include/Nazara/OpenGLRenderer/OpenGLSwapchain.hpp index de58e9408..b43d2093e 100644 --- a/include/Nazara/OpenGLRenderer/OpenGLSwapchain.hpp +++ b/include/Nazara/OpenGLRenderer/OpenGLSwapchain.hpp @@ -41,6 +41,8 @@ namespace Nz void Present(); + TransientResources& Transient() override; + private: std::optional m_renderPass; std::size_t m_currentFrame; diff --git a/include/Nazara/Renderer/RenderDevice.hpp b/include/Nazara/Renderer/RenderDevice.hpp index 7391fb19f..7e0587979 100644 --- a/include/Nazara/Renderer/RenderDevice.hpp +++ b/include/Nazara/Renderer/RenderDevice.hpp @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include #include @@ -40,8 +40,6 @@ namespace Nz RenderDevice() = default; virtual ~RenderDevice(); - virtual void Execute(const FunctionRef& callback, QueueType queueType) = 0; - virtual const RenderDeviceInfo& GetDeviceInfo() const = 0; virtual const RenderDeviceFeatures& GetEnabledFeatures() const = 0; diff --git a/include/Nazara/Renderer/RenderFrame.inl b/include/Nazara/Renderer/RenderFrame.inl index d29f0abda..b8ccb04c9 100644 --- a/include/Nazara/Renderer/RenderFrame.inl +++ b/include/Nazara/Renderer/RenderFrame.inl @@ -19,6 +19,14 @@ namespace Nz { } + inline void RenderFrame::Execute(const FunctionRef& callback, QueueTypeFlags queueTypeFlags) + { + if NAZARA_UNLIKELY(!m_image) + throw std::runtime_error("frame is either invalid or has already been presented"); + + return m_image->Execute(callback, queueTypeFlags); + } + inline std::size_t RenderFrame::GetFramebufferIndex() const { return m_framebufferIndex; @@ -29,6 +37,14 @@ namespace Nz return m_size; } + inline UploadPool& RenderFrame::GetUploadPool() + { + if NAZARA_UNLIKELY(!m_image) + throw std::runtime_error("frame is either invalid or has already been presented"); + + return m_image->GetUploadPool(); + } + inline bool RenderFrame::IsFramebufferInvalidated() const { return m_framebufferInvalidation; @@ -37,18 +53,39 @@ namespace Nz template void RenderFrame::PushForRelease(T&& value) { - return PushReleaseCallback([v = std::forward(value)] {}); + if NAZARA_UNLIKELY(!m_image) + throw std::runtime_error("frame is either invalid or has already been presented"); + + m_image->PushForRelease(std::forward(value)); } template void RenderFrame::PushReleaseCallback(F&& releaseCallback) { - if (!m_image) + if NAZARA_UNLIKELY(!m_image) throw std::runtime_error("frame is either invalid or has already been presented"); m_image->PushReleaseCallback(std::forward(releaseCallback)); } + inline void RenderFrame::Present() + { + if NAZARA_UNLIKELY(!m_image) + throw std::runtime_error("frame is either invalid or has already been presented"); + + m_image->Present(); + m_image = nullptr; + } + + inline void RenderFrame::SubmitCommandBuffer(CommandBuffer* commandBuffer, QueueTypeFlags queueTypeFlags) + { + if NAZARA_UNLIKELY(!m_image) + throw std::runtime_error("frame is either invalid or has already been presented"); + + m_image->SubmitCommandBuffer(commandBuffer, queueTypeFlags); + } + + inline RenderFrame::operator bool() { return m_image != nullptr; diff --git a/include/Nazara/Renderer/RenderImage.hpp b/include/Nazara/Renderer/RenderImage.hpp index 373b343e3..a63aea78e 100644 --- a/include/Nazara/Renderer/RenderImage.hpp +++ b/include/Nazara/Renderer/RenderImage.hpp @@ -8,76 +8,14 @@ #define NAZARA_RENDERER_RENDERIMAGE_HPP #include -#include -#include -#include -#include -#include +#include namespace Nz { - class CommandBuffer; - class CommandBufferBuilder; - class UploadPool; - - class NAZARA_RENDERER_API RenderImage + class NAZARA_RENDERER_API RenderImage : public TransientResources { public: - class Releasable; - template class ReleasableLambda; - - virtual ~RenderImage(); - - virtual void Execute(const FunctionRef& callback, QueueTypeFlags queueTypeFlags) = 0; - - inline void FlushReleaseQueue(); - - virtual UploadPool& GetUploadPool() = 0; - virtual void Present() = 0; - - template void PushReleaseCallback(F&& callback); - - virtual void SubmitCommandBuffer(CommandBuffer* commandBuffer, QueueTypeFlags queueTypeFlags) = 0; - - protected: - RenderImage() = default; - RenderImage(const RenderImage&) = delete; - RenderImage(RenderImage&&) = delete; - - private: - static constexpr std::size_t BlockSize = 4 * 1024 * 1024; - - using Block = std::vector; - - std::vector m_releaseQueue; - std::vector m_releaseMemoryPool; - }; - - class NAZARA_RENDERER_API RenderImage::Releasable - { - public: - virtual ~Releasable(); - - virtual void Release() = 0; - }; - - template - class RenderImage::ReleasableLambda : public Releasable - { - public: - template ReleasableLambda(U&& lambda); - ReleasableLambda(const ReleasableLambda&) = delete; - ReleasableLambda(ReleasableLambda&&) = delete; - ~ReleasableLambda() = default; - - void Release() override; - - ReleasableLambda& operator=(const ReleasableLambda&) = delete; - ReleasableLambda& operator=(ReleasableLambda&&) = delete; - - private: - T m_lambda; }; } diff --git a/include/Nazara/Renderer/RenderImage.inl b/include/Nazara/Renderer/RenderImage.inl index ceb7bdae4..dbe08b351 100644 --- a/include/Nazara/Renderer/RenderImage.inl +++ b/include/Nazara/Renderer/RenderImage.inl @@ -2,91 +2,10 @@ // This file is part of the "Nazara Engine - Renderer module" // For conditions of distribution and use, see copyright notice in Config.hpp -#include -#include #include namespace Nz { - inline void RenderImage::FlushReleaseQueue() - { - for (Releasable* releasable : m_releaseQueue) - { - releasable->Release(); - PlacementDestroy(releasable); - } - m_releaseQueue.clear(); - - for (auto& memoryblock : m_releaseMemoryPool) - memoryblock.clear(); - } - - template - void RenderImage::PushReleaseCallback(F&& callback) - { - using Functor = ReleasableLambda>>; - - constexpr std::size_t functorSize = sizeof(Functor); - constexpr std::size_t functorAlignment = alignof(Functor); - - // Try to minimize lost space - struct - { - Block* block = nullptr; - UInt64 alignedOffset = 0; - UInt64 lostSpace = 0; - } bestBlock; - - for (Block& block : m_releaseMemoryPool) - { - std::size_t freeOffset = block.size(); - - UInt64 alignedOffset = Align(freeOffset, functorAlignment); - if (alignedOffset + functorSize > block.capacity()) - continue; //< Not enough space - - UInt64 lostSpace = alignedOffset - freeOffset; - - if (!bestBlock.block || lostSpace < bestBlock.lostSpace) - { - bestBlock.block = █ - bestBlock.alignedOffset = alignedOffset; - bestBlock.lostSpace = lostSpace; - } - } - - // No block found, allocate a new one - if (!bestBlock.block) - { - Block newBlock; - newBlock.reserve(BlockSize); - - bestBlock.block = &m_releaseMemoryPool.emplace_back(std::move(newBlock)); - bestBlock.alignedOffset = 0; - bestBlock.lostSpace = 0; - } - - Block& targetBlock = *bestBlock.block; - targetBlock.resize(bestBlock.alignedOffset + functorSize); - - Functor* releasable = reinterpret_cast(&targetBlock[bestBlock.alignedOffset]); - PlacementNew(releasable, std::forward(callback)); - - m_releaseQueue.push_back(releasable); - } - - template - template - RenderImage::ReleasableLambda::ReleasableLambda(U&& lambda) : - m_lambda(std::forward(lambda)) - { - } - - template - void RenderImage::ReleasableLambda::Release() - { - m_lambda(); - } } #include diff --git a/include/Nazara/Renderer/Swapchain.hpp b/include/Nazara/Renderer/Swapchain.hpp index 63af9d853..9993b8edb 100644 --- a/include/Nazara/Renderer/Swapchain.hpp +++ b/include/Nazara/Renderer/Swapchain.hpp @@ -20,6 +20,7 @@ namespace Nz { class CommandPool; class RenderDevice; + class TransientResources; class NAZARA_RENDERER_API Swapchain : public RenderTarget { @@ -33,6 +34,8 @@ namespace Nz virtual void NotifyResize(const Vector2ui& newSize) = 0; + virtual TransientResources& Transient() = 0; + protected: static void BuildRenderPass(PixelFormat colorFormat, PixelFormat depthFormat, std::vector& attachments, std::vector& subpassDescriptions, std::vector& subpassDependencies); }; diff --git a/include/Nazara/Renderer/TransientResources.hpp b/include/Nazara/Renderer/TransientResources.hpp new file mode 100644 index 000000000..1aa93e6fb --- /dev/null +++ b/include/Nazara/Renderer/TransientResources.hpp @@ -0,0 +1,87 @@ +// Copyright (C) 2023 Jérôme "Lynix" Leclercq (lynix680@gmail.com) +// This file is part of the "Nazara Engine - Renderer module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_RENDERER_TRANSIENTRESOURCES_HPP +#define NAZARA_RENDERER_TRANSIENTRESOURCES_HPP + +#include +#include +#include +#include +#include +#include +#include + +namespace Nz +{ + class CommandBuffer; + class CommandBufferBuilder; + class UploadPool; + + class NAZARA_RENDERER_API TransientResources + { + public: + class Releasable; + template class ReleasableLambda; + + virtual ~TransientResources(); + + virtual void Execute(const FunctionRef& callback, QueueTypeFlags queueTypeFlags) = 0; + + inline void FlushReleaseQueue(); + + virtual UploadPool& GetUploadPool() = 0; + + template void PushForRelease(const T& value) = delete; + template void PushForRelease(T&& value); + template void PushReleaseCallback(F&& callback); + + virtual void SubmitCommandBuffer(CommandBuffer* commandBuffer, QueueTypeFlags queueTypeFlags) = 0; + + protected: + TransientResources() = default; + TransientResources(const TransientResources&) = delete; + TransientResources(TransientResources&&) = delete; + + private: + static constexpr std::size_t BlockSize = 4 * 1024 * 1024; + + using Block = std::vector; + + std::vector m_releaseQueue; + std::vector m_releaseMemoryPool; + }; + + class NAZARA_RENDERER_API TransientResources::Releasable + { + public: + virtual ~Releasable(); + + virtual void Release() = 0; + }; + + template + class TransientResources::ReleasableLambda : public Releasable + { + public: + template ReleasableLambda(U&& lambda); + ReleasableLambda(const ReleasableLambda&) = delete; + ReleasableLambda(ReleasableLambda&&) = delete; + ~ReleasableLambda() = default; + + void Release() override; + + ReleasableLambda& operator=(const ReleasableLambda&) = delete; + ReleasableLambda& operator=(ReleasableLambda&&) = delete; + + private: + T m_lambda; + }; +} + +#include + +#endif // NAZARA_RENDERER_TRANSIENTRESOURCES_HPP diff --git a/include/Nazara/Renderer/TransientResources.inl b/include/Nazara/Renderer/TransientResources.inl new file mode 100644 index 000000000..e628f81d5 --- /dev/null +++ b/include/Nazara/Renderer/TransientResources.inl @@ -0,0 +1,100 @@ +// Copyright (C) 2023 Jérôme "Lynix" Leclercq (lynix680@gmail.com) +// This file is part of the "Nazara Engine - Renderer module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include + +namespace Nz +{ + inline void TransientResources::FlushReleaseQueue() + { + for (Releasable* releasable : m_releaseQueue) + { + releasable->Release(); + PlacementDestroy(releasable); + } + m_releaseQueue.clear(); + + for (auto& memoryblock : m_releaseMemoryPool) + memoryblock.clear(); + } + + template + void TransientResources::PushForRelease(T&& value) + { + static_assert(std::is_rvalue_reference_v); + + return PushReleaseCallback([v = std::move(value)] {}); + } + + template + void TransientResources::PushReleaseCallback(F&& callback) + { + using Functor = ReleasableLambda>>; + + constexpr std::size_t functorSize = sizeof(Functor); + constexpr std::size_t functorAlignment = alignof(Functor); + + // Try to minimize lost space + struct + { + Block* block = nullptr; + UInt64 alignedOffset = 0; + UInt64 lostSpace = 0; + } bestBlock; + + for (Block& block : m_releaseMemoryPool) + { + std::size_t freeOffset = block.size(); + + UInt64 alignedOffset = Align(freeOffset, functorAlignment); + if (alignedOffset + functorSize > block.capacity()) + continue; //< Not enough space + + UInt64 lostSpace = alignedOffset - freeOffset; + + if (!bestBlock.block || lostSpace < bestBlock.lostSpace) + { + bestBlock.block = █ + bestBlock.alignedOffset = alignedOffset; + bestBlock.lostSpace = lostSpace; + } + } + + // No block found, allocate a new one + if (!bestBlock.block) + { + Block newBlock; + newBlock.reserve(BlockSize); + + bestBlock.block = &m_releaseMemoryPool.emplace_back(std::move(newBlock)); + bestBlock.alignedOffset = 0; + bestBlock.lostSpace = 0; + } + + Block& targetBlock = *bestBlock.block; + targetBlock.resize(bestBlock.alignedOffset + functorSize); + + Functor* releasable = reinterpret_cast(&targetBlock[bestBlock.alignedOffset]); + PlacementNew(releasable, std::forward(callback)); + + m_releaseQueue.push_back(releasable); + } + + template + template + TransientResources::ReleasableLambda::ReleasableLambda(U&& lambda) : + m_lambda(std::forward(lambda)) + { + } + + template + void TransientResources::ReleasableLambda::Release() + { + m_lambda(); + } +} + +#include diff --git a/include/Nazara/Renderer/WindowSwapchain.hpp b/include/Nazara/Renderer/WindowSwapchain.hpp index 7c24593ec..2f1421c67 100644 --- a/include/Nazara/Renderer/WindowSwapchain.hpp +++ b/include/Nazara/Renderer/WindowSwapchain.hpp @@ -40,6 +40,8 @@ namespace Nz inline Swapchain& GetSwapchain(); inline const Swapchain& GetSwapchain() const; + inline TransientResources& Transient(); + WindowSwapchain& operator=(const WindowSwapchain&) = delete; WindowSwapchain& operator=(WindowSwapchain&& windowSwapchain) = delete; diff --git a/include/Nazara/Renderer/WindowSwapchain.inl b/include/Nazara/Renderer/WindowSwapchain.inl index 4c0d86efa..8a84bd4c1 100644 --- a/include/Nazara/Renderer/WindowSwapchain.inl +++ b/include/Nazara/Renderer/WindowSwapchain.inl @@ -40,6 +40,11 @@ namespace Nz return *m_swapchain; } + inline TransientResources& WindowSwapchain::Transient() + { + return m_swapchain->Transient(); + } + void WindowSwapchain::DisconnectSignals() { m_onGainedFocus.Disconnect(); diff --git a/include/Nazara/VulkanRenderer/VulkanDevice.hpp b/include/Nazara/VulkanRenderer/VulkanDevice.hpp index 9cc995ec6..a2d658201 100644 --- a/include/Nazara/VulkanRenderer/VulkanDevice.hpp +++ b/include/Nazara/VulkanRenderer/VulkanDevice.hpp @@ -23,8 +23,6 @@ namespace Nz VulkanDevice(VulkanDevice&&) = delete; ///TODO? ~VulkanDevice(); - void Execute(const FunctionRef& callback, QueueType queueType) override; - const RenderDeviceInfo& GetDeviceInfo() const override; const RenderDeviceFeatures& GetEnabledFeatures() const override; diff --git a/include/Nazara/VulkanRenderer/VulkanSwapchain.hpp b/include/Nazara/VulkanRenderer/VulkanSwapchain.hpp index 0c6423c53..aa184b37c 100644 --- a/include/Nazara/VulkanRenderer/VulkanSwapchain.hpp +++ b/include/Nazara/VulkanRenderer/VulkanSwapchain.hpp @@ -59,6 +59,8 @@ namespace Nz void Present(UInt32 imageIndex, VkSemaphore waitSemaphore = VK_NULL_HANDLE); + TransientResources& Transient() override; + VulkanSwapchain& operator=(const VulkanSwapchain&) = delete; VulkanSwapchain& operator=(VulkanSwapchain&&) = delete; diff --git a/src/Nazara/Graphics/Systems/RenderSystem.cpp b/src/Nazara/Graphics/Systems/RenderSystem.cpp index 46818efb6..6156f31ba 100644 --- a/src/Nazara/Graphics/Systems/RenderSystem.cpp +++ b/src/Nazara/Graphics/Systems/RenderSystem.cpp @@ -60,9 +60,9 @@ namespace Nz UpdateObservers(); UpdateInstances(); - for (auto& windowPtr : m_windowSwapchains) + for (auto& swapchainPtr : m_windowSwapchains) { - RenderFrame frame = windowPtr->AcquireFrame(); + RenderFrame frame = swapchainPtr->AcquireFrame(); if (!frame) continue; diff --git a/src/Nazara/OpenGLRenderer/OpenGLDevice.cpp b/src/Nazara/OpenGLRenderer/OpenGLDevice.cpp index 85e988a3f..b35f5f5ab 100644 --- a/src/Nazara/OpenGLRenderer/OpenGLDevice.cpp +++ b/src/Nazara/OpenGLRenderer/OpenGLDevice.cpp @@ -156,22 +156,6 @@ namespace Nz #endif } - void OpenGLDevice::Execute(const FunctionRef& callback, QueueType /*queueType*/) - { - const GL::Context* activeContext = GL::Context::GetCurrentContext(); - if (!activeContext || activeContext->GetDevice() != this) - { - if (!GL::Context::SetCurrentContext(m_referenceContext.get())) - throw std::runtime_error("failed to activate context"); - } - - OpenGLCommandBuffer commandBuffer; //< TODO: Use a pool and remove default constructor - OpenGLCommandBufferBuilder builder(commandBuffer); - callback(builder); - - commandBuffer.Execute(); - } - const RenderDeviceInfo& OpenGLDevice::GetDeviceInfo() const { return m_deviceInfo; diff --git a/src/Nazara/OpenGLRenderer/OpenGLSwapchain.cpp b/src/Nazara/OpenGLRenderer/OpenGLSwapchain.cpp index fa2fd81ab..d18659761 100644 --- a/src/Nazara/OpenGLRenderer/OpenGLSwapchain.cpp +++ b/src/Nazara/OpenGLRenderer/OpenGLSwapchain.cpp @@ -116,4 +116,9 @@ namespace Nz m_context->SwapBuffers(); m_currentFrame = (m_currentFrame + 1) % m_renderImage.size(); } + + TransientResources& OpenGLSwapchain::Transient() + { + return *m_renderImage[m_currentFrame]; + } } diff --git a/src/Nazara/Renderer/RenderFrame.cpp b/src/Nazara/Renderer/RenderFrame.cpp deleted file mode 100644 index f82d64062..000000000 --- a/src/Nazara/Renderer/RenderFrame.cpp +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (C) 2023 Jérôme "Lynix" Leclercq (lynix680@gmail.com) -// This file is part of the "Nazara Engine - Renderer module" -// For conditions of distribution and use, see copyright notice in Config.hpp - -#include -#include -#include -#include - -namespace Nz -{ - void RenderFrame::Execute(const FunctionRef& callback, QueueTypeFlags queueTypeFlags) - { - if (!m_image) - throw std::runtime_error("frame is either invalid or has already been presented"); - - return m_image->Execute(callback, queueTypeFlags); - } - - UploadPool& RenderFrame::GetUploadPool() - { - if (!m_image) - throw std::runtime_error("frame is either invalid or has already been presented"); - - return m_image->GetUploadPool(); - } - - void RenderFrame::Present() - { - if (!m_image) - throw std::runtime_error("frame is either invalid or has already been presented"); - - m_image->Present(); - m_image = nullptr; - } - - void RenderFrame::SubmitCommandBuffer(CommandBuffer* commandBuffer, QueueTypeFlags queueTypeFlags) - { - if (!m_image) - throw std::runtime_error("frame is either invalid or has already been presented"); - - m_image->SubmitCommandBuffer(commandBuffer, queueTypeFlags); - } -} diff --git a/src/Nazara/Renderer/RenderImage.cpp b/src/Nazara/Renderer/TransientResources.cpp similarity index 66% rename from src/Nazara/Renderer/RenderImage.cpp rename to src/Nazara/Renderer/TransientResources.cpp index 7b068bb16..57dbbbed5 100644 --- a/src/Nazara/Renderer/RenderImage.cpp +++ b/src/Nazara/Renderer/TransientResources.cpp @@ -2,15 +2,15 @@ // This file is part of the "Nazara Engine - Renderer module" // For conditions of distribution and use, see copyright notice in Config.hpp -#include +#include #include namespace Nz { - RenderImage::~RenderImage() + TransientResources::~TransientResources() { FlushReleaseQueue(); } - RenderImage::Releasable::~Releasable() = default; + TransientResources::Releasable::~Releasable() = default; } diff --git a/src/Nazara/VulkanRenderer/VulkanDevice.cpp b/src/Nazara/VulkanRenderer/VulkanDevice.cpp index 58256599e..7fa3656c6 100644 --- a/src/Nazara/VulkanRenderer/VulkanDevice.cpp +++ b/src/Nazara/VulkanRenderer/VulkanDevice.cpp @@ -21,22 +21,6 @@ namespace Nz { VulkanDevice::~VulkanDevice() = default; - void VulkanDevice::Execute(const FunctionRef& callback, QueueType queueType) - { - Vk::AutoCommandBuffer commandBuffer = AllocateCommandBuffer(queueType); - if (!commandBuffer->Begin(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT)) - throw std::runtime_error("failed to begin command buffer: " + TranslateVulkanError(commandBuffer->GetLastErrorCode())); - - VulkanCommandBufferBuilder builder(commandBuffer); - callback(builder); - - if (!commandBuffer->End()) - throw std::runtime_error("failed to build command buffer: " + TranslateVulkanError(commandBuffer->GetLastErrorCode())); - - GetQueue(GetDefaultFamilyIndex(queueType), 0).Submit(commandBuffer); - GetQueue(GetDefaultFamilyIndex(queueType), 0).WaitIdle(); - } - const RenderDeviceInfo& VulkanDevice::GetDeviceInfo() const { return m_renderDeviceInfo; diff --git a/src/Nazara/VulkanRenderer/VulkanSwapchain.cpp b/src/Nazara/VulkanRenderer/VulkanSwapchain.cpp index 143aa5ec3..a1ef3c910 100644 --- a/src/Nazara/VulkanRenderer/VulkanSwapchain.cpp +++ b/src/Nazara/VulkanRenderer/VulkanSwapchain.cpp @@ -332,6 +332,11 @@ namespace Nz } } + TransientResources& VulkanSwapchain::Transient() + { + return *m_concurrentImageData[m_currentFrame]; + } + bool VulkanSwapchain::SetupDepthBuffer() { VkImageCreateInfo imageCreateInfo = { diff --git a/tests/ComputeParticlesTest/main.cpp b/tests/ComputeParticlesTest/main.cpp index 103ce97d2..9e4dd3d10 100644 --- a/tests/ComputeParticlesTest/main.cpp +++ b/tests/ComputeParticlesTest/main.cpp @@ -31,7 +31,7 @@ struct SpriteRenderPipeline std::shared_ptr BuildComputePipeline(Nz::RenderDevice& device, std::shared_ptr pipelineLayout, std::shared_ptr moduleResolver); SpriteRenderPipeline BuildSpritePipeline(Nz::RenderDevice& device); SpriteRenderData BuildSpriteData(Nz::RenderDevice& device, const SpriteRenderPipeline& pipelineData, const Nz::Rectf& textureRect, const Nz::Vector2f& screenSize, const Nz::RenderBufferView& buffer, const Nz::RenderBufferView& particleBuffer, std::shared_ptr texture, std::shared_ptr sampler); -std::shared_ptr GenerateSpriteTexture(Nz::RenderDevice& device, std::shared_ptr moduleResolver); +std::shared_ptr GenerateSpriteTexture(Nz::RenderDevice& device, std::shared_ptr moduleResolver, Nz::WindowSwapchain& swapchain); int main() { @@ -179,7 +179,7 @@ int main() std::shared_ptr uniformBuffer = device->InstantiateBuffer(Nz::BufferType::Uniform, viewerBufferSize, Nz::BufferUsage::DeviceLocal, viewerBufferInitialData.data()); - std::shared_ptr texture = GenerateSpriteTexture(*device, moduleResolver); + std::shared_ptr texture = GenerateSpriteTexture(*device, moduleResolver, windowSwapchain); std::shared_ptr textureSampler = device->InstantiateTextureSampler({}); SpriteRenderPipeline spriteRenderPipeline = BuildSpritePipeline(*device); @@ -503,7 +503,7 @@ SpriteRenderData BuildSpriteData(Nz::RenderDevice& device, const SpriteRenderPip } } -std::shared_ptr GenerateSpriteTexture(Nz::RenderDevice& device, std::shared_ptr moduleResolver) +std::shared_ptr GenerateSpriteTexture(Nz::RenderDevice& device, std::shared_ptr moduleResolver, Nz::WindowSwapchain& swapchain) { nzsl::Ast::ModulePtr shaderModule = moduleResolver->Resolve("Compute.ParticleTexture"); if (!shaderModule) @@ -550,7 +550,7 @@ std::shared_ptr GenerateSpriteTexture(Nz::RenderDevice& device, std texParams.type = Nz::ImageType::E2D; texParams.pixelFormat = Nz::PixelFormat::RGBA8; texParams.width = texParams.height = 256; - texParams.usageFlags = Nz::TextureUsage::ShaderReadWrite | Nz::TextureUsage::ShaderSampling; + texParams.usageFlags = Nz::TextureUsage::ShaderReadWrite | Nz::TextureUsage::ShaderSampling | Nz::TextureUsage::TransferSource | Nz::TextureUsage::TransferDestination; std::shared_ptr targetTexture = device.InstantiateTexture(texParams); @@ -564,7 +564,7 @@ std::shared_ptr GenerateSpriteTexture(Nz::RenderDevice& device, std } }); - device.Execute([&](Nz::CommandBufferBuilder& builder) + swapchain.Transient().Execute([&](Nz::CommandBufferBuilder& builder) { builder.TextureBarrier(Nz::PipelineStage::BottomOfPipe, Nz::PipelineStage::ComputeShader, {}, Nz::MemoryAccess::ShaderWrite, Nz::TextureLayout::Undefined, Nz::TextureLayout::General, *targetTexture); @@ -576,5 +576,7 @@ std::shared_ptr GenerateSpriteTexture(Nz::RenderDevice& device, std }, Nz::QueueType::Compute); + device.WaitForIdle(); + return targetTexture; }