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)
This commit is contained in:
@@ -121,7 +121,6 @@ namespace Nz
|
||||
{
|
||||
std::size_t finalAttachment;
|
||||
std::vector<const ViewerData*> viewers;
|
||||
ShaderBindingPtr blitShaderBinding;
|
||||
};
|
||||
|
||||
struct SkeletonInstanceData
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#include <NazaraUtils/Prerequisites.hpp>
|
||||
#include <Nazara/Graphics/Config.hpp>
|
||||
#include <Nazara/Renderer/Enums.hpp>
|
||||
#include <Nazara/Utility/PixelFormat.hpp>
|
||||
#include <string>
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 <Nazara/OpenGLRenderer/DebugOff.hpp>
|
||||
#include "OpenGLCommandBuffer.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;
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ namespace Nz
|
||||
std::shared_ptr<CommandPool> 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<OpenGLRenderPass> m_renderPass;
|
||||
std::size_t m_currentFrame;
|
||||
std::vector<std::unique_ptr<OpenGLRenderImage>> m_renderImage;
|
||||
std::shared_ptr<GL::Context> m_context;
|
||||
std::vector<std::unique_ptr<OpenGLRenderImage>> m_renderImage;
|
||||
OpenGLDevice& m_device;
|
||||
OpenGLWindowFramebuffer m_framebuffer;
|
||||
PresentMode m_presentMode;
|
||||
PresentModeFlags m_supportedPresentModes;
|
||||
|
||||
@@ -12,6 +12,11 @@ namespace Nz
|
||||
assert(m_context);
|
||||
return *m_context;
|
||||
}
|
||||
|
||||
inline OpenGLDevice& OpenGLSwapchain::GetDevice()
|
||||
{
|
||||
return m_device;
|
||||
}
|
||||
}
|
||||
|
||||
#include <Nazara/OpenGLRenderer/DebugOff.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
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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<void(CommandBufferBuilder& builder)>& callback, QueueTypeFlags queueTypeFlags);
|
||||
inline void Execute(const FunctionRef<void(CommandBufferBuilder& builder)>& 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;
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -15,6 +15,8 @@ namespace Nz
|
||||
class NAZARA_RENDERER_API RenderImage : public TransientResources
|
||||
{
|
||||
public:
|
||||
using TransientResources::TransientResources;
|
||||
|
||||
virtual void Present() = 0;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<CommandPool> CreateCommandPool(QueueType queueType) = 0;
|
||||
|
||||
virtual PresentMode GetPresentMode() const = 0;
|
||||
|
||||
@@ -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<typename T> 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<Releasable*> m_releaseQueue;
|
||||
std::vector<Block> m_releaseMemoryPool;
|
||||
RenderDevice& m_renderDevice;
|
||||
};
|
||||
|
||||
class NAZARA_RENDERER_API TransientResources::Releasable
|
||||
|
||||
@@ -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<typename T>
|
||||
void TransientResources::PushForRelease(T&& value)
|
||||
{
|
||||
@@ -98,3 +108,4 @@ namespace Nz
|
||||
}
|
||||
|
||||
#include <Nazara/Renderer/DebugOff.hpp>
|
||||
#include "TransientResources.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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -46,11 +46,12 @@ namespace Nz
|
||||
|
||||
std::shared_ptr<CommandPool> 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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -11,48 +11,45 @@
|
||||
#include <Nazara/VulkanRenderer/Wrapper/DeviceObject.hpp>
|
||||
#include <Nazara/VulkanRenderer/Wrapper/ImageView.hpp>
|
||||
|
||||
namespace Nz
|
||||
namespace Nz::Vk
|
||||
{
|
||||
namespace Vk
|
||||
class Swapchain : public DeviceObject<Swapchain, VkSwapchainKHR, VkSwapchainCreateInfoKHR, VK_OBJECT_TYPE_SWAPCHAIN_KHR>
|
||||
{
|
||||
class Swapchain : public DeviceObject<Swapchain, VkSwapchainKHR, VkSwapchainCreateInfoKHR, VK_OBJECT_TYPE_SWAPCHAIN_KHR>
|
||||
{
|
||||
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<Image>& GetImages() const;
|
||||
inline UInt32 GetImageCount() const;
|
||||
inline const Image& GetImage(UInt32 index) const;
|
||||
inline const std::vector<Image>& 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<Image> m_images;
|
||||
};
|
||||
}
|
||||
std::vector<Image> m_images;
|
||||
};
|
||||
}
|
||||
|
||||
#include <Nazara/VulkanRenderer/Wrapper/Swapchain.inl>
|
||||
|
||||
@@ -7,117 +7,114 @@
|
||||
#include <Nazara/VulkanRenderer/Wrapper/Device.hpp>
|
||||
#include <Nazara/VulkanRenderer/Debug.hpp>
|
||||
|
||||
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<VkImage> 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<VkImage> 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::Image>& 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<UInt32>(m_images.size());
|
||||
}
|
||||
inline const std::vector<Swapchain::Image>& 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<UInt32>(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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user