diff --git a/include/Nazara/OpenGLRenderer/OpenGLDevice.hpp b/include/Nazara/OpenGLRenderer/OpenGLDevice.hpp index 610438e10..1161e5667 100644 --- a/include/Nazara/OpenGLRenderer/OpenGLDevice.hpp +++ b/include/Nazara/OpenGLRenderer/OpenGLDevice.hpp @@ -34,6 +34,8 @@ namespace Nz std::shared_ptr InstantiateBuffer(BufferType type) override; std::shared_ptr InstantiateCommandPool(QueueType queueType) override; + std::shared_ptr InstantiateFramebuffer(unsigned int width, unsigned int height, const std::shared_ptr& renderPass, const std::vector>& attachments) override; + std::shared_ptr InstantiateRenderPass(std::vector attachments, std::vector subpassDescriptions, std::vector subpassDependencies) override; std::shared_ptr InstantiateRenderPipeline(RenderPipelineInfo pipelineInfo) override; std::shared_ptr InstantiateRenderPipelineLayout(RenderPipelineLayoutInfo pipelineLayoutInfo) override; std::shared_ptr InstantiateShaderStage(const ShaderAst& shaderAst, const ShaderWriter::States& states) override; @@ -42,6 +44,7 @@ namespace Nz std::shared_ptr InstantiateTextureSampler(const TextureSamplerInfo& params) override; inline void NotifyBufferDestruction(GLuint buffer) const; + inline void NotifyFramebufferDestruction(GLuint fbo) const; inline void NotifyProgramDestruction(GLuint program) const; inline void NotifySamplerDestruction(GLuint sampler) const; inline void NotifyTextureDestruction(GLuint texture) const; diff --git a/include/Nazara/OpenGLRenderer/OpenGLDevice.inl b/include/Nazara/OpenGLRenderer/OpenGLDevice.inl index a9c823a7e..e995edbb9 100644 --- a/include/Nazara/OpenGLRenderer/OpenGLDevice.inl +++ b/include/Nazara/OpenGLRenderer/OpenGLDevice.inl @@ -18,6 +18,12 @@ namespace Nz context->NotifyBufferDestruction(buffer); } + inline void OpenGLDevice::NotifyFramebufferDestruction(GLuint fbo) const + { + for (const GL::Context* context : m_contexts) + context->NotifyFramebufferDestruction(fbo); + } + inline void OpenGLDevice::NotifyProgramDestruction(GLuint program) const { for (const GL::Context* context : m_contexts) diff --git a/include/Nazara/OpenGLRenderer/OpenGLFboFramebuffer.hpp b/include/Nazara/OpenGLRenderer/OpenGLFboFramebuffer.hpp new file mode 100644 index 000000000..f4c5f960c --- /dev/null +++ b/include/Nazara/OpenGLRenderer/OpenGLFboFramebuffer.hpp @@ -0,0 +1,45 @@ +// Copyright (C) 2020 Jérôme Leclercq +// 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_OPENGLRENDERER_OPENGLWINDOWFRAMEBUFFER_HPP +#define NAZARA_OPENGLRENDERER_OPENGLWINDOWFRAMEBUFFER_HPP + +#include +#include +#include +#include +#include + +namespace Nz +{ + class OpenGLDevice; + class RenderPass; + class Texture; + + class NAZARA_OPENGLRENDERER_API OpenGLFboFramebuffer : public OpenGLFramebuffer + { + public: + OpenGLFboFramebuffer(OpenGLDevice& device, const std::vector>& attachments); + OpenGLFboFramebuffer(const OpenGLFboFramebuffer&) = delete; + OpenGLFboFramebuffer(OpenGLFboFramebuffer&&) noexcept = default; + ~OpenGLFboFramebuffer() = default; + + void Activate() const override; + + std::size_t GetColorBufferCount() const override; + + OpenGLFboFramebuffer& operator=(const OpenGLFboFramebuffer&) = delete; + OpenGLFboFramebuffer& operator=(OpenGLFboFramebuffer&&) = delete; + + private: + GL::Framebuffer m_framebuffer; + std::size_t m_colorAttachmentCount; + }; +} + +#include + +#endif // NAZARA_OPENGLRENDERER_OpenGLWindowFramebuffer_HPP diff --git a/include/Nazara/OpenGLRenderer/OpenGLFboFramebuffer.inl b/include/Nazara/OpenGLRenderer/OpenGLFboFramebuffer.inl new file mode 100644 index 000000000..c629eb72a --- /dev/null +++ b/include/Nazara/OpenGLRenderer/OpenGLFboFramebuffer.inl @@ -0,0 +1,12 @@ +// Copyright (C) 2020 Jérôme Leclercq +// This file is part of the "Nazara Engine - OpenGL Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +namespace Nz +{ +} + +#include diff --git a/include/Nazara/OpenGLRenderer/OpenGLTexture.hpp b/include/Nazara/OpenGLRenderer/OpenGLTexture.hpp index d3d66cb12..0b97585a8 100644 --- a/include/Nazara/OpenGLRenderer/OpenGLTexture.hpp +++ b/include/Nazara/OpenGLRenderer/OpenGLTexture.hpp @@ -34,6 +34,8 @@ namespace Nz OpenGLTexture& operator=(const OpenGLTexture&) = delete; OpenGLTexture& operator=(OpenGLTexture&&) = delete; + static inline GL::TextureTarget ToTextureTarget(ImageType imageType); + private: GL::Texture m_texture; TextureInfo m_params; diff --git a/include/Nazara/OpenGLRenderer/OpenGLTexture.inl b/include/Nazara/OpenGLRenderer/OpenGLTexture.inl index a9c2cfec4..e7d789788 100644 --- a/include/Nazara/OpenGLRenderer/OpenGLTexture.inl +++ b/include/Nazara/OpenGLRenderer/OpenGLTexture.inl @@ -3,6 +3,7 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include +#include #include namespace Nz @@ -11,6 +12,22 @@ namespace Nz { return m_texture; } + + inline GL::TextureTarget OpenGLTexture::ToTextureTarget(ImageType imageType) + { + switch (imageType) + { + case ImageType_2D: return GL::TextureTarget::Target2D; + case ImageType_2D_Array: return GL::TextureTarget::Target2D_Array; + case ImageType_3D: return GL::TextureTarget::Target3D; + case ImageType_Cubemap: return GL::TextureTarget::Cubemap; + + case ImageType_1D: + case ImageType_1D_Array: + default: + throw std::runtime_error("unsupported texture type"); + } + } } #include diff --git a/include/Nazara/OpenGLRenderer/OpenGLWindowFramebuffer.hpp b/include/Nazara/OpenGLRenderer/OpenGLWindowFramebuffer.hpp index e1a7cb998..e97c66ff4 100644 --- a/include/Nazara/OpenGLRenderer/OpenGLWindowFramebuffer.hpp +++ b/include/Nazara/OpenGLRenderer/OpenGLWindowFramebuffer.hpp @@ -36,4 +36,4 @@ namespace Nz #include -#endif // NAZARA_OPENGLRENDERER_OpenGLWindowFramebuffer_HPP +#endif diff --git a/include/Nazara/OpenGLRenderer/OpenGLWindowFramebuffer.inl b/include/Nazara/OpenGLRenderer/OpenGLWindowFramebuffer.inl index 9549a0467..033d596da 100644 --- a/include/Nazara/OpenGLRenderer/OpenGLWindowFramebuffer.inl +++ b/include/Nazara/OpenGLRenderer/OpenGLWindowFramebuffer.inl @@ -2,7 +2,7 @@ // This file is part of the "Nazara Engine - OpenGL Renderer" // For conditions of distribution and use, see copyright notice in Config.hpp -#include +#include #include namespace Nz diff --git a/include/Nazara/OpenGLRenderer/Wrapper/Context.hpp b/include/Nazara/OpenGLRenderer/Wrapper/Context.hpp index 4f95b5c21..db1932d1f 100644 --- a/include/Nazara/OpenGLRenderer/Wrapper/Context.hpp +++ b/include/Nazara/OpenGLRenderer/Wrapper/Context.hpp @@ -126,6 +126,7 @@ namespace Nz::GL bool Initialize(const ContextParams& params); inline void NotifyBufferDestruction(GLuint buffer) const; + inline void NotifyFramebufferDestruction(GLuint fbo) const; inline void NotifyProgramDestruction(GLuint program) const; inline void NotifySamplerDestruction(GLuint sampler) const; inline void NotifyTextureDestruction(GLuint texture) const; diff --git a/include/Nazara/OpenGLRenderer/Wrapper/Context.inl b/include/Nazara/OpenGLRenderer/Wrapper/Context.inl index 8c675cea7..f194afe99 100644 --- a/include/Nazara/OpenGLRenderer/Wrapper/Context.inl +++ b/include/Nazara/OpenGLRenderer/Wrapper/Context.inl @@ -58,6 +58,15 @@ namespace Nz::GL } } + inline void Context::NotifyFramebufferDestruction(GLuint fbo) const + { + if (m_state.boundDrawFBO == fbo) + m_state.boundDrawFBO = 0; + + if (m_state.boundReadFBO == fbo) + m_state.boundReadFBO = 0; + } + inline void Context::NotifyProgramDestruction(GLuint program) const { if (m_state.boundProgram == program) diff --git a/include/Nazara/OpenGLRenderer/Wrapper/CoreFunctions.hpp b/include/Nazara/OpenGLRenderer/Wrapper/CoreFunctions.hpp index c684b52ce..de1d45a08 100644 --- a/include/Nazara/OpenGLRenderer/Wrapper/CoreFunctions.hpp +++ b/include/Nazara/OpenGLRenderer/Wrapper/CoreFunctions.hpp @@ -36,6 +36,7 @@ typedef void (GL_APIENTRYP PFNGLSPECIALIZESHADERARBPROC) (GLuint shader, const G cb(glBufferSubData, PFNGLBUFFERSUBDATAPROC) \ cb(glClear, PFNGLCLEARPROC) \ cb(glClearBufferfi, PFNGLCLEARBUFFERFIPROC) \ + cb(glClearBufferfv, PFNGLCLEARBUFFERFVPROC) \ cb(glClearBufferuiv, PFNGLCLEARBUFFERUIVPROC) \ cb(glClearColor, PFNGLCLEARCOLORPROC) \ cb(glClearDepthf, PFNGLCLEARDEPTHFPROC) \ @@ -156,6 +157,9 @@ typedef void (GL_APIENTRYP PFNGLSPECIALIZESHADERARBPROC) (GLuint shader, const G \ extCb(glDebugMessageCallback, PFNGLDEBUGMESSAGECALLBACKPROC) \ \ + extCb(glMemoryBarrier, PFNGLMEMORYBARRIERPROC) \ + extCb(glMemoryBarrierByRegion, PFNGLMEMORYBARRIERBYREGIONPROC) \ + \ extCb(glObjectLabel, PFNGLOBJECTLABELPROC) \ extCb(glPopDebugGroup, PFNGLPOPDEBUGGROUPPROC) \ extCb(glPushDebugGroup, PFNGLPUSHDEBUGGROUPPROC) \ diff --git a/include/Nazara/OpenGLRenderer/Wrapper/DeviceObject.hpp b/include/Nazara/OpenGLRenderer/Wrapper/DeviceObject.hpp index e9a241ad4..9f7063875 100644 --- a/include/Nazara/OpenGLRenderer/Wrapper/DeviceObject.hpp +++ b/include/Nazara/OpenGLRenderer/Wrapper/DeviceObject.hpp @@ -9,6 +9,7 @@ #include #include +#include #include #include @@ -26,6 +27,8 @@ namespace Nz::GL bool Create(OpenGLDevice& device, CreateArgs... args); void Destroy(); + const Context& EnsureDeviceContext() const; + bool IsValid() const; OpenGLDevice* GetDevice() const; @@ -39,8 +42,6 @@ namespace Nz::GL static constexpr GLuint InvalidObject = 0; protected: - const Context& EnsureDeviceContext(); - MovablePtr m_device; MovableValue m_objectId; }; diff --git a/include/Nazara/OpenGLRenderer/Wrapper/DeviceObject.inl b/include/Nazara/OpenGLRenderer/Wrapper/DeviceObject.inl index 08d029c79..c92a83c61 100644 --- a/include/Nazara/OpenGLRenderer/Wrapper/DeviceObject.inl +++ b/include/Nazara/OpenGLRenderer/Wrapper/DeviceObject.inl @@ -46,6 +46,24 @@ namespace Nz::GL } } + template + const Context& DeviceObject::EnsureDeviceContext() const + { + assert(m_device); + + const Context* activeContext = Context::GetCurrentContext(); + if (!activeContext || activeContext->GetDevice() != m_device) + { + const Context& referenceContext = m_device->GetReferenceContext(); + if (!Context::SetCurrentContext(&referenceContext)) + throw std::runtime_error("failed to activate context"); + + return referenceContext; + } + + return *activeContext; + } + template bool DeviceObject::IsValid() const { @@ -72,24 +90,6 @@ namespace Nz::GL if (context.glObjectLabel) context.glObjectLabel(ObjectType, m_objectId, name.size(), name.data()); } - - template - const Context& DeviceObject::EnsureDeviceContext() - { - assert(m_device); - - const Context* activeContext = Context::GetCurrentContext(); - if (!activeContext || activeContext->GetDevice() != m_device) - { - const Context& referenceContext = m_device->GetReferenceContext(); - if (!Context::SetCurrentContext(&referenceContext)) - throw std::runtime_error("failed to activate context"); - - return referenceContext; - } - - return *activeContext; - } } #include diff --git a/include/Nazara/OpenGLRenderer/Wrapper/Framebuffer.hpp b/include/Nazara/OpenGLRenderer/Wrapper/Framebuffer.hpp index dcfe84546..4d9c27ad1 100644 --- a/include/Nazara/OpenGLRenderer/Wrapper/Framebuffer.hpp +++ b/include/Nazara/OpenGLRenderer/Wrapper/Framebuffer.hpp @@ -4,36 +4,38 @@ #pragma once -#ifndef NAZARA_OPENGLRENDERER_VKFRAMEBUFFER_HPP -#define NAZARA_OPENGLRENDERER_VKFRAMEBUFFER_HPP +#ifndef NAZARA_OPENGLRENDERER_GLFRAMEBUFFER_HPP +#define NAZARA_OPENGLRENDERER_GLFRAMEBUFFER_HPP #include #include -namespace Nz +namespace Nz::GL { - namespace Vk + class Framebuffer : public DeviceObject { - class Framebuffer : public DeviceObject - { - friend DeviceObject; + friend DeviceObject; - public: - Framebuffer() = default; - Framebuffer(const Framebuffer&) = delete; - Framebuffer(Framebuffer&&) = default; - ~Framebuffer() = default; + public: + Framebuffer() = default; + Framebuffer(const Framebuffer&) = delete; + Framebuffer(Framebuffer&&) noexcept = default; + ~Framebuffer() = default; - Framebuffer& operator=(const Framebuffer&) = delete; - Framebuffer& operator=(Framebuffer&&) = delete; + inline GLenum Check() const; - private: - static inline VkResult CreateHelper(Device& device, const VkFramebufferCreateInfo* createInfo, const VkAllocationCallbacks* allocator, VkFramebuffer* handle); - static inline void DestroyHelper(Device& device, VkFramebuffer handle, const VkAllocationCallbacks* allocator); - }; - } + inline void Renderbuffer(GLenum attachment, GLenum renderbuffer); + inline void Texture2D(GLenum attachment, GLenum textarget, GLuint texture, GLint level = 0); + + Framebuffer& operator=(const Framebuffer&) = delete; + Framebuffer& operator=(Framebuffer&&) noexcept = default; + + private: + static inline GLuint CreateHelper(OpenGLDevice& device, const Context& context); + static inline void DestroyHelper(OpenGLDevice& device, const Context& context, GLuint objectId); + }; } #include -#endif // NAZARA_OPENGLRENDERER_VKFRAMEBUFFER_HPP +#endif diff --git a/include/Nazara/OpenGLRenderer/Wrapper/Framebuffer.inl b/include/Nazara/OpenGLRenderer/Wrapper/Framebuffer.inl index 3656d27f8..54017a96a 100644 --- a/include/Nazara/OpenGLRenderer/Wrapper/Framebuffer.inl +++ b/include/Nazara/OpenGLRenderer/Wrapper/Framebuffer.inl @@ -3,21 +3,51 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include +#include #include -namespace Nz +namespace Nz::GL { - namespace Vk + inline GLenum Framebuffer::Check() const { - inline VkResult Framebuffer::CreateHelper(Device& device, const VkFramebufferCreateInfo* createInfo, const VkAllocationCallbacks* allocator, VkFramebuffer* handle) - { - return device.vkCreateFramebuffer(device, createInfo, allocator, handle); - } + assert(m_objectId); - inline void Framebuffer::DestroyHelper(Device& device, VkFramebuffer handle, const VkAllocationCallbacks* allocator) - { - return device.vkDestroyFramebuffer(device, handle, allocator); - } + const Context& context = EnsureDeviceContext(); + context.BindFramebuffer(m_objectId); + return context.glCheckFramebufferStatus(GL_FRAMEBUFFER); + } + + inline void Framebuffer::Renderbuffer(GLenum attachment, GLenum renderbuffer) + { + assert(m_objectId); + + const Context& context = EnsureDeviceContext(); + context.BindFramebuffer(m_objectId); + context.glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachment, GL_RENDERBUFFER, renderbuffer); + } + + inline void Framebuffer::Texture2D(GLenum attachment, GLenum textarget, GLuint texture, GLint level) + { + assert(m_objectId); + + const Context& context = EnsureDeviceContext(); + context.BindFramebuffer(m_objectId); + context.glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, textarget, texture, level); + } + + inline GLuint Framebuffer::CreateHelper(OpenGLDevice& /*device*/, const Context& context) + { + GLuint fbo = 0; + context.glGenFramebuffers(1U, &fbo); + + return fbo; + } + + inline void Framebuffer::DestroyHelper(OpenGLDevice& device, const Context& context, GLuint objectId) + { + context.glDeleteFramebuffers(1U, &objectId); + + device.NotifyFramebufferDestruction(objectId); } } diff --git a/include/Nazara/Renderer/RenderDevice.hpp b/include/Nazara/Renderer/RenderDevice.hpp index 5f658ef69..8030c0f55 100644 --- a/include/Nazara/Renderer/RenderDevice.hpp +++ b/include/Nazara/Renderer/RenderDevice.hpp @@ -10,6 +10,8 @@ #include #include #include +#include +#include #include #include #include @@ -33,6 +35,8 @@ namespace Nz virtual std::shared_ptr InstantiateBuffer(BufferType type) = 0; virtual std::shared_ptr InstantiateCommandPool(QueueType queueType) = 0; + virtual std::shared_ptr InstantiateFramebuffer(unsigned int width, unsigned int height, const std::shared_ptr& renderPass, const std::vector>& attachments) = 0; + virtual std::shared_ptr InstantiateRenderPass(std::vector attachments, std::vector subpassDescriptions, std::vector subpassDependencies) = 0; virtual std::shared_ptr InstantiateRenderPipeline(RenderPipelineInfo pipelineInfo) = 0; virtual std::shared_ptr InstantiateRenderPipelineLayout(RenderPipelineLayoutInfo pipelineLayoutInfo) = 0; virtual std::shared_ptr InstantiateShaderStage(const ShaderAst& shaderAst, const ShaderWriter::States& states) = 0; diff --git a/include/Nazara/Renderer/RenderPass.inl b/include/Nazara/Renderer/RenderPass.inl index a7360cd30..37345cbea 100644 --- a/include/Nazara/Renderer/RenderPass.inl +++ b/include/Nazara/Renderer/RenderPass.inl @@ -15,7 +15,7 @@ namespace Nz { } - inline auto Nz::RenderPass::GetAttachment(std::size_t attachmentIndex) const -> const Attachment& + inline auto RenderPass::GetAttachment(std::size_t attachmentIndex) const -> const Attachment& { assert(attachmentIndex < m_attachments.size()); return m_attachments[attachmentIndex]; diff --git a/include/Nazara/Utility/Enums.hpp b/include/Nazara/Utility/Enums.hpp index 4112ce48b..d2eae1681 100644 --- a/include/Nazara/Utility/Enums.hpp +++ b/include/Nazara/Utility/Enums.hpp @@ -162,6 +162,7 @@ namespace Nz PixelFormatContent_Undefined = -1, PixelFormatContent_ColorRGBA, + PixelFormatContent_Depth, PixelFormatContent_DepthStencil, PixelFormatContent_Stencil, diff --git a/include/Nazara/VulkanRenderer/Utils.hpp b/include/Nazara/VulkanRenderer/Utils.hpp index b337d3d10..88ec90b05 100644 --- a/include/Nazara/VulkanRenderer/Utils.hpp +++ b/include/Nazara/VulkanRenderer/Utils.hpp @@ -39,6 +39,8 @@ namespace Nz inline VkShaderStageFlags ToVulkan(ShaderStageTypeFlags stageType); inline VkStencilOp ToVulkan(StencilOperation stencilOp); inline VkImageLayout ToVulkan(TextureLayout textureLayout); + inline VkImageUsageFlagBits ToVulkan(TextureUsage textureLayout); + inline VkImageUsageFlags ToVulkan(TextureUsageFlags textureLayout); inline VkVertexInputRate ToVulkan(VertexInputRate inputRate); NAZARA_VULKANRENDERER_API std::string TranslateVulkanError(VkResult code); diff --git a/include/Nazara/VulkanRenderer/Utils.inl b/include/Nazara/VulkanRenderer/Utils.inl index a9a872601..336335802 100644 --- a/include/Nazara/VulkanRenderer/Utils.inl +++ b/include/Nazara/VulkanRenderer/Utils.inl @@ -196,9 +196,11 @@ namespace Nz switch (pixelFormat) { case PixelFormat::PixelFormat_BGRA8: return VK_FORMAT_B8G8R8A8_UNORM; + case PixelFormat::PixelFormat_BGRA8_SRGB: return VK_FORMAT_B8G8R8A8_SRGB; case PixelFormat::PixelFormat_Depth24Stencil8: return VK_FORMAT_D24_UNORM_S8_UINT; case PixelFormat::PixelFormat_Depth32: return VK_FORMAT_D32_SFLOAT; case PixelFormat::PixelFormat_RGBA8: return VK_FORMAT_R8G8B8A8_UNORM; + case PixelFormat::PixelFormat_RGBA8_SRGB: return VK_FORMAT_R8G8B8A8_SRGB; default: break; } @@ -336,10 +338,10 @@ namespace Nz { switch (textureLayout) { - case TextureLayout::ColorInput: return VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - case TextureLayout::ColorOutput: return VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR; - case TextureLayout::DepthStencilInput: return VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL; - case TextureLayout::DepthStencilOutput: return VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL; + case TextureLayout::ColorInput: return VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + case TextureLayout::ColorOutput: return VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + case TextureLayout::DepthStencilInput: return VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL; + case TextureLayout::DepthStencilOutput: return VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; case TextureLayout::Present: return VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; case TextureLayout::TransferSource: return VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; case TextureLayout::TransferDestination: return VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; @@ -350,6 +352,35 @@ namespace Nz return {}; } + VkImageUsageFlagBits ToVulkan(TextureUsage textureLayout) + { + switch (textureLayout) + { + case TextureUsage::ColorOutput: return VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + case TextureUsage::DepthStencilOutput: return VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; + case TextureUsage::InputAttachment: return VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; + case TextureUsage::ShaderSampling: return VK_IMAGE_USAGE_SAMPLED_BIT; + case TextureUsage::TransferSource: return VK_IMAGE_USAGE_TRANSFER_SRC_BIT; + case TextureUsage::TransferDestination: return VK_IMAGE_USAGE_TRANSFER_DST_BIT; + } + + NazaraError("Unhandled TextureUsage 0x" + NumberToString(UnderlyingCast(textureLayout), 16)); + return {}; + } + + VkImageUsageFlags ToVulkan(TextureUsageFlags textureLayout) + { + VkImageUsageFlags imageUsageBits = 0; + for (int i = 0; i <= UnderlyingCast(TextureUsage::Max); ++i) + { + TextureUsage textureUsage = static_cast(i); + if (textureLayout.Test(textureUsage)) + imageUsageBits |= ToVulkan(textureUsage); + } + + return imageUsageBits; + } + inline VkVertexInputRate ToVulkan(VertexInputRate inputRate) { switch (inputRate) @@ -359,7 +390,7 @@ namespace Nz } NazaraError("Unhandled VertexInputRate 0x" + NumberToString(UnderlyingCast(inputRate), 16)); - return VK_VERTEX_INPUT_RATE_VERTEX; + return {}; } } diff --git a/include/Nazara/VulkanRenderer/VulkanDevice.hpp b/include/Nazara/VulkanRenderer/VulkanDevice.hpp index 4d47de3bf..ae3439685 100644 --- a/include/Nazara/VulkanRenderer/VulkanDevice.hpp +++ b/include/Nazara/VulkanRenderer/VulkanDevice.hpp @@ -25,6 +25,8 @@ namespace Nz std::shared_ptr InstantiateBuffer(BufferType type) override; std::shared_ptr InstantiateCommandPool(QueueType queueType) override; + std::shared_ptr InstantiateFramebuffer(unsigned int width, unsigned int height, const std::shared_ptr& renderPass, const std::vector>& attachments) override; + std::shared_ptr InstantiateRenderPass(std::vector attachments, std::vector subpassDescriptions, std::vector subpassDependencies) override; std::shared_ptr InstantiateRenderPipeline(RenderPipelineInfo pipelineInfo) override; std::shared_ptr InstantiateRenderPipelineLayout(RenderPipelineLayoutInfo pipelineLayoutInfo) override; std::shared_ptr InstantiateShaderStage(const ShaderAst& shaderAst, const ShaderWriter::States& states) override; diff --git a/include/Nazara/VulkanRenderer/VulkanSingleFramebuffer.hpp b/include/Nazara/VulkanRenderer/VulkanSingleFramebuffer.hpp index 688bf99ba..0edc5d1e3 100644 --- a/include/Nazara/VulkanRenderer/VulkanSingleFramebuffer.hpp +++ b/include/Nazara/VulkanRenderer/VulkanSingleFramebuffer.hpp @@ -8,13 +8,17 @@ #define NAZARA_VULKANRENDERER_VULKANSINGLEFRAMEBUFFER_HPP #include +#include namespace Nz { + class RenderPass; + class Texture; + class NAZARA_VULKANRENDERER_API VulkanSingleFramebuffer final : public VulkanFramebuffer { public: - inline VulkanSingleFramebuffer(Vk::Framebuffer renderPass); + VulkanSingleFramebuffer(Vk::Device& device, unsigned int width, unsigned int height, const std::shared_ptr& renderPass, const std::vector>& attachments); VulkanSingleFramebuffer(const VulkanSingleFramebuffer&) = delete; VulkanSingleFramebuffer(VulkanSingleFramebuffer&&) = delete; ~VulkanSingleFramebuffer() = default; diff --git a/include/Nazara/VulkanRenderer/VulkanSingleFramebuffer.inl b/include/Nazara/VulkanRenderer/VulkanSingleFramebuffer.inl index 19f5e35c1..b9553b998 100644 --- a/include/Nazara/VulkanRenderer/VulkanSingleFramebuffer.inl +++ b/include/Nazara/VulkanRenderer/VulkanSingleFramebuffer.inl @@ -7,12 +7,6 @@ namespace Nz { - inline VulkanSingleFramebuffer::VulkanSingleFramebuffer(Vk::Framebuffer framebuffer) : - VulkanFramebuffer(Type::Single), - m_framebuffer(std::move(framebuffer)) - { - } - inline Vk::Framebuffer& VulkanSingleFramebuffer::GetFramebuffer() { return m_framebuffer; diff --git a/src/Nazara/OpenGLRenderer/OpenGLCommandBuffer.cpp b/src/Nazara/OpenGLRenderer/OpenGLCommandBuffer.cpp index b2bdb985b..6ed855aa4 100644 --- a/src/Nazara/OpenGLRenderer/OpenGLCommandBuffer.cpp +++ b/src/Nazara/OpenGLRenderer/OpenGLCommandBuffer.cpp @@ -106,18 +106,19 @@ namespace Nz for (std::size_t i = 0; i < colorBufferCount; ++i) { Nz::Color color = command.clearValues[i].color; - std::array clearColor = { color.r, color.g, color.b, color.a }; + std::array clearColor = { color.r / 255.f, color.g / 255.f, color.b / 255.f, color.a / 255.f }; - context->glClearBufferuiv(GL_COLOR, GLint(i), clearColor.data()); + context->glClearBufferfv(GL_COLOR, GLint(i), clearColor.data()); } + + context->glClear(GL_DEPTH_BUFFER_BIT); } else { Nz::Color color = command.clearValues[0].color; - context->glClearColor(color.r, color.g, color.b, color.a); + context->glClearColor(color.r / 255.f, color.g / 255.f, color.b / 255.f, color.a / 255.f); + context->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } - - context->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } else static_assert(AlwaysFalse::value, "non-exhaustive visitor"); @@ -131,6 +132,8 @@ namespace Nz states.shaderBindings->Apply(context); states.pipeline->Apply(context); + states.pipeline->FlipY(states.shouldFlipY); + if (states.scissorRegion) context.SetScissorBox(states.scissorRegion->x, states.scissorRegion->y, states.scissorRegion->width, states.scissorRegion->height); diff --git a/src/Nazara/OpenGLRenderer/OpenGLCommandBufferBuilder.cpp b/src/Nazara/OpenGLRenderer/OpenGLCommandBufferBuilder.cpp index e10d0de22..1571ef677 100644 --- a/src/Nazara/OpenGLRenderer/OpenGLCommandBufferBuilder.cpp +++ b/src/Nazara/OpenGLRenderer/OpenGLCommandBufferBuilder.cpp @@ -19,7 +19,7 @@ namespace Nz m_commandBuffer.BeginDebugRegion(regionName, color); } - void OpenGLCommandBufferBuilder::BeginRenderPass(const Framebuffer& framebuffer, const RenderPass& renderPass, Nz::Recti renderRect, std::initializer_list clearValues) + void OpenGLCommandBufferBuilder::BeginRenderPass(const Framebuffer& framebuffer, const RenderPass& renderPass, Nz::Recti /*renderRect*/, std::initializer_list clearValues) { m_commandBuffer.SetFramebuffer(static_cast(framebuffer), renderPass, clearValues); } diff --git a/src/Nazara/OpenGLRenderer/OpenGLDevice.cpp b/src/Nazara/OpenGLRenderer/OpenGLDevice.cpp index 5d2ffa399..205099232 100644 --- a/src/Nazara/OpenGLRenderer/OpenGLDevice.cpp +++ b/src/Nazara/OpenGLRenderer/OpenGLDevice.cpp @@ -6,6 +6,8 @@ #include #include #include +#include +#include #include #include #include @@ -58,6 +60,16 @@ namespace Nz return std::make_shared(); } + std::shared_ptr OpenGLDevice::InstantiateFramebuffer(unsigned int /*width*/, unsigned int /*height*/, const std::shared_ptr& /*renderPass*/, const std::vector>& attachments) + { + return std::make_shared(*this, attachments); + } + + std::shared_ptr OpenGLDevice::InstantiateRenderPass(std::vector attachments, std::vector subpassDescriptions, std::vector subpassDependencies) + { + return std::make_shared(std::move(attachments), std::move(subpassDescriptions), std::move(subpassDependencies)); + } + std::shared_ptr OpenGLDevice::InstantiateRenderPipeline(RenderPipelineInfo pipelineInfo) { return std::make_shared(*this, std::move(pipelineInfo)); diff --git a/src/Nazara/OpenGLRenderer/OpenGLFboFramebuffer.cpp b/src/Nazara/OpenGLRenderer/OpenGLFboFramebuffer.cpp new file mode 100644 index 000000000..f7923472c --- /dev/null +++ b/src/Nazara/OpenGLRenderer/OpenGLFboFramebuffer.cpp @@ -0,0 +1,92 @@ +// Copyright (C) 2020 Jérôme Leclercq +// This file is part of the "Nazara Engine - OpenGL Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include +#include +#include + +namespace Nz +{ + OpenGLFboFramebuffer::OpenGLFboFramebuffer(OpenGLDevice& device, const std::vector>& attachments) : + OpenGLFramebuffer(OpenGLFramebuffer::Type::FBO) + { + if (!m_framebuffer.Create(device)) + throw std::runtime_error("failed to create framebuffer object"); + + std::size_t colorAttachmentCount = 0; + bool hasDepth = false; + bool hasStencil = false; + + for (std::size_t i = 0; i < attachments.size(); ++i) + { + assert(attachments[i]); + const OpenGLTexture& glTexture = static_cast(*attachments[i]); + + PixelFormat textureFormat = glTexture.GetFormat(); + + GLenum attachment; + switch (PixelFormatInfo::GetContent(textureFormat)) + { + case PixelFormatContent_ColorRGBA: + attachment = GL_COLOR_ATTACHMENT0 + colorAttachmentCount; + colorAttachmentCount++; + break; + + case PixelFormatContent_Depth: + if (hasDepth) + throw std::runtime_error("a framebuffer can only have one depth attachment"); + + attachment = GL_DEPTH_ATTACHMENT; + hasDepth = true; + break; + + case PixelFormatContent_DepthStencil: + if (hasDepth) + throw std::runtime_error("a framebuffer can only have one depth attachment"); + + if (hasStencil) + throw std::runtime_error("a framebuffer can only have one stencil attachment"); + + attachment = GL_DEPTH_STENCIL_ATTACHMENT; + hasDepth = true; + hasStencil = true; + break; + + case PixelFormatContent_Stencil: + if (hasStencil) + throw std::runtime_error("a framebuffer can only have one stencil attachment"); + + attachment = GL_STENCIL_ATTACHMENT; + hasStencil = true; + break; + + case PixelFormatContent_Undefined: + default: + throw std::runtime_error("unhandled pixel format " + PixelFormatInfo::GetName(textureFormat)); + } + + m_framebuffer.Texture2D(attachment, ToOpenGL(OpenGLTexture::ToTextureTarget(glTexture.GetType())), glTexture.GetTexture().GetObjectId()); + } + + GLenum status = m_framebuffer.Check(); + if (status != GL_FRAMEBUFFER_COMPLETE) + throw std::runtime_error("invalid framebuffer: 0x" + NumberToString(status, 16)); + + m_colorAttachmentCount = colorAttachmentCount; + } + + void OpenGLFboFramebuffer::Activate() const + { + const GL::Context& context = m_framebuffer.EnsureDeviceContext(); + + context.BindFramebuffer(GL::FramebufferTarget::Draw, m_framebuffer.GetObjectId()); + } + + std::size_t OpenGLFboFramebuffer::GetColorBufferCount() const + { + return m_colorAttachmentCount; + } +} diff --git a/src/Nazara/OpenGLRenderer/OpenGLShaderBinding.cpp b/src/Nazara/OpenGLRenderer/OpenGLShaderBinding.cpp index d8fd7fa44..5bef6dcc7 100644 --- a/src/Nazara/OpenGLRenderer/OpenGLShaderBinding.cpp +++ b/src/Nazara/OpenGLRenderer/OpenGLShaderBinding.cpp @@ -68,7 +68,7 @@ namespace Nz const TextureBinding& texBinding = std::get(binding.content); auto& textureDescriptor = m_owner.GetTextureDescriptor(m_poolIndex, m_bindingIndex, resourceIndex); - textureDescriptor.bindingIndex = binding.bindingIndex; + textureDescriptor.bindingIndex = UInt32(binding.bindingIndex); if (OpenGLTexture* glTexture = static_cast(texBinding.texture)) { @@ -79,29 +79,7 @@ namespace Nz else textureDescriptor.sampler = 0; - switch (glTexture->GetType()) - { - case ImageType_2D: - textureDescriptor.textureTarget = GL::TextureTarget::Target2D; - break; - - case ImageType_2D_Array: - textureDescriptor.textureTarget = GL::TextureTarget::Target2D_Array; - break; - - case ImageType_3D: - textureDescriptor.textureTarget = GL::TextureTarget::Target3D; - break; - - case ImageType_Cubemap: - textureDescriptor.textureTarget = GL::TextureTarget::Cubemap; - break; - - case ImageType_1D: - case ImageType_1D_Array: - default: - throw std::runtime_error("unsupported texture type"); - } + textureDescriptor.textureTarget = OpenGLTexture::ToTextureTarget(glTexture->GetType()); } else { diff --git a/src/Nazara/VulkanRenderer/VkRenderWindow.cpp b/src/Nazara/VulkanRenderer/VkRenderWindow.cpp index 9091e04c2..4dd7e927d 100644 --- a/src/Nazara/VulkanRenderer/VkRenderWindow.cpp +++ b/src/Nazara/VulkanRenderer/VkRenderWindow.cpp @@ -419,7 +419,7 @@ namespace Nz RenderPass::AttachmentReference colorReference = { 0, - TextureLayout::ColorInput + TextureLayout::ColorOutput }; std::vector subpasses = { @@ -475,12 +475,12 @@ namespace Nz AttachmentStoreOp::Discard, AttachmentStoreOp::Discard, TextureLayout::Undefined, - TextureLayout::DepthStencilInput + TextureLayout::DepthStencilOutput }); subpasses.front().depthStencilAttachment = RenderPass::AttachmentReference{ 1, - TextureLayout::DepthStencilInput + TextureLayout::DepthStencilOutput }; } diff --git a/src/Nazara/VulkanRenderer/VulkanDevice.cpp b/src/Nazara/VulkanRenderer/VulkanDevice.cpp index 5f6ed9e3d..0de3132a5 100644 --- a/src/Nazara/VulkanRenderer/VulkanDevice.cpp +++ b/src/Nazara/VulkanRenderer/VulkanDevice.cpp @@ -4,9 +4,11 @@ #include #include +#include #include #include #include +#include #include #include #include @@ -25,6 +27,16 @@ namespace Nz return std::make_shared(*this, queueType); } + std::shared_ptr VulkanDevice::InstantiateFramebuffer(unsigned int width, unsigned int height, const std::shared_ptr& renderPass, const std::vector>& attachments) + { + return std::make_shared(*this, width, height, renderPass, attachments); + } + + std::shared_ptr VulkanDevice::InstantiateRenderPass(std::vector attachments, std::vector subpassDescriptions, std::vector subpassDependencies) + { + return std::make_shared(*this, std::move(attachments), std::move(subpassDescriptions), std::move(subpassDependencies)); + } + std::shared_ptr VulkanDevice::InstantiateRenderPipeline(RenderPipelineInfo pipelineInfo) { return std::make_shared(*this, std::move(pipelineInfo)); diff --git a/src/Nazara/VulkanRenderer/VulkanRenderPass.cpp b/src/Nazara/VulkanRenderer/VulkanRenderPass.cpp index 2d497d6ab..e44b38edd 100644 --- a/src/Nazara/VulkanRenderer/VulkanRenderPass.cpp +++ b/src/Nazara/VulkanRenderer/VulkanRenderPass.cpp @@ -76,9 +76,9 @@ namespace Nz VkSubpassDescriptionFlags(0), VK_PIPELINE_BIND_POINT_GRAPHICS, UInt32(subpassInfo.inputAttachments.size()), - &vkAttachmentReferences[inputAttachmentIndex], + (!subpassInfo.inputAttachments.empty()) ? &vkAttachmentReferences[inputAttachmentIndex] : nullptr, UInt32(subpassInfo.colorAttachment.size()), - &vkAttachmentReferences[colorAttachmentIndex], + (!subpassInfo.colorAttachment.empty()) ? &vkAttachmentReferences[colorAttachmentIndex] : nullptr, nullptr, (subpassInfo.depthStencilAttachment) ? &vkAttachmentReferences[depthStencilAttachmentIndex] : nullptr, 0, diff --git a/src/Nazara/VulkanRenderer/VulkanSingleFramebuffer.cpp b/src/Nazara/VulkanRenderer/VulkanSingleFramebuffer.cpp index a8ecb74ad..e445e2a5f 100644 --- a/src/Nazara/VulkanRenderer/VulkanSingleFramebuffer.cpp +++ b/src/Nazara/VulkanRenderer/VulkanSingleFramebuffer.cpp @@ -3,8 +3,42 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include +#include +#include +#include +#include #include namespace Nz { + VulkanSingleFramebuffer::VulkanSingleFramebuffer(Vk::Device& device, unsigned int width, unsigned int height, const std::shared_ptr& renderPass, const std::vector>& attachments) : + VulkanFramebuffer(Type::Single) + { + assert(renderPass); + const VulkanRenderPass& vkRenderPass = static_cast(*renderPass); + + StackArray imageViews = NazaraStackArrayNoInit(VkImageView, attachments.size()); + for (std::size_t i = 0; i < attachments.size(); ++i) + { + assert(attachments[i]); + + const VulkanTexture& vkTexture = static_cast(*attachments[i]); + imageViews[i] = vkTexture.GetImageView(); + } + + VkFramebufferCreateInfo createInfo = { + VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, + nullptr, + 0, + vkRenderPass.GetRenderPass(), + UInt32(imageViews.size()), + imageViews.data(), + UInt32(width), + UInt32(height), + 1 + }; + + if (!m_framebuffer.Create(device, createInfo)) + throw std::runtime_error("failed to instantiate Vulkan framebuffer: " + TranslateVulkanError(m_framebuffer.GetLastErrorCode())); + } }