Renderer: Implement Framebuffers

This commit is contained in:
Jérôme Leclercq 2021-02-20 19:22:08 +01:00
parent 3ef74d6e1d
commit fb3468854f
32 changed files with 401 additions and 100 deletions

View File

@ -34,6 +34,8 @@ namespace Nz
std::shared_ptr<AbstractBuffer> InstantiateBuffer(BufferType type) override;
std::shared_ptr<CommandPool> InstantiateCommandPool(QueueType queueType) override;
std::shared_ptr<Framebuffer> InstantiateFramebuffer(unsigned int width, unsigned int height, const std::shared_ptr<RenderPass>& renderPass, const std::vector<std::shared_ptr<Texture>>& attachments) override;
std::shared_ptr<RenderPass> InstantiateRenderPass(std::vector<RenderPass::Attachment> attachments, std::vector<RenderPass::SubpassDescription> subpassDescriptions, std::vector<RenderPass::SubpassDependency> subpassDependencies) override;
std::shared_ptr<RenderPipeline> InstantiateRenderPipeline(RenderPipelineInfo pipelineInfo) override;
std::shared_ptr<RenderPipelineLayout> InstantiateRenderPipelineLayout(RenderPipelineLayoutInfo pipelineLayoutInfo) override;
std::shared_ptr<ShaderStage> InstantiateShaderStage(const ShaderAst& shaderAst, const ShaderWriter::States& states) override;
@ -42,6 +44,7 @@ namespace Nz
std::shared_ptr<TextureSampler> 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;

View File

@ -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)

View File

@ -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 <Nazara/Prerequisites.hpp>
#include <Nazara/OpenGLRenderer/OpenGLFramebuffer.hpp>
#include <Nazara/OpenGLRenderer/Wrapper/Framebuffer.hpp>
#include <memory>
#include <vector>
namespace Nz
{
class OpenGLDevice;
class RenderPass;
class Texture;
class NAZARA_OPENGLRENDERER_API OpenGLFboFramebuffer : public OpenGLFramebuffer
{
public:
OpenGLFboFramebuffer(OpenGLDevice& device, const std::vector<std::shared_ptr<Texture>>& 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 <Nazara/OpenGLRenderer/OpenGLFboFramebuffer.hpp>
#endif // NAZARA_OPENGLRENDERER_OpenGLWindowFramebuffer_HPP

View File

@ -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 <Nazara/OpenGLRenderer/OpenGLFramebuffer.hpp>
#include <Nazara/OpenGLRenderer/Debug.hpp>
namespace Nz
{
}
#include <Nazara/OpenGLRenderer/DebugOff.hpp>

View File

@ -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;

View File

@ -3,6 +3,7 @@
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/OpenGLRenderer/OpenGLTexture.hpp>
#include <stdexcept>
#include <Nazara/OpenGLRenderer/Debug.hpp>
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 <Nazara/OpenGLRenderer/DebugOff.hpp>

View File

@ -36,4 +36,4 @@ namespace Nz
#include <Nazara/OpenGLRenderer/OpenGLWindowFramebuffer.inl>
#endif // NAZARA_OPENGLRENDERER_OpenGLWindowFramebuffer_HPP
#endif

View File

@ -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 <Nazara/OpenGLRenderer/OpenGLFramebuffer.hpp>
#include <Nazara/OpenGLRenderer/OpenGLWindowFramebuffer.hpp>
#include <Nazara/OpenGLRenderer/Debug.hpp>
namespace Nz

View File

@ -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;

View File

@ -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)

View File

@ -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) \

View File

@ -9,6 +9,7 @@
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Core/MovablePtr.hpp>
#include <Nazara/Core/MovableValue.hpp>
#include <Nazara/OpenGLRenderer/Wrapper/Context.hpp>
#include <string>
@ -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<OpenGLDevice> m_device;
MovableValue<GLuint> m_objectId;
};

View File

@ -46,6 +46,24 @@ namespace Nz::GL
}
}
template<typename C, GLenum ObjectType, typename... CreateArgs>
const Context& DeviceObject<C, ObjectType, CreateArgs...>::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<typename C, GLenum ObjectType, typename... CreateArgs>
bool DeviceObject<C, ObjectType, CreateArgs...>::IsValid() const
{
@ -72,24 +90,6 @@ namespace Nz::GL
if (context.glObjectLabel)
context.glObjectLabel(ObjectType, m_objectId, name.size(), name.data());
}
template<typename C, GLenum ObjectType, typename... CreateArgs>
const Context& DeviceObject<C, ObjectType, CreateArgs...>::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 <Nazara/OpenGLRenderer/DebugOff.hpp>

View File

@ -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 <Nazara/Prerequisites.hpp>
#include <Nazara/OpenGLRenderer/Wrapper/DeviceObject.hpp>
namespace Nz
namespace Nz::GL
{
namespace Vk
class Framebuffer : public DeviceObject<Framebuffer, GL_FRAMEBUFFER>
{
class Framebuffer : public DeviceObject<Framebuffer, VkFramebuffer, VkFramebufferCreateInfo, VK_OBJECT_TYPE_FRAMEBUFFER>
{
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 <Nazara/OpenGLRenderer/Wrapper/Framebuffer.inl>
#endif // NAZARA_OPENGLRENDERER_VKFRAMEBUFFER_HPP
#endif

View File

@ -3,21 +3,51 @@
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/OpenGLRenderer/Wrapper/Framebuffer.hpp>
#include <Nazara/OpenGLRenderer/OpenGLDevice.hpp>
#include <Nazara/OpenGLRenderer/Debug.hpp>
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);
}
}

View File

@ -10,6 +10,8 @@
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Renderer/Config.hpp>
#include <Nazara/Renderer/Enums.hpp>
#include <Nazara/Renderer/Framebuffer.hpp>
#include <Nazara/Renderer/RenderPass.hpp>
#include <Nazara/Renderer/RenderPipeline.hpp>
#include <Nazara/Renderer/RenderPipelineLayout.hpp>
#include <Nazara/Renderer/Texture.hpp>
@ -33,6 +35,8 @@ namespace Nz
virtual std::shared_ptr<AbstractBuffer> InstantiateBuffer(BufferType type) = 0;
virtual std::shared_ptr<CommandPool> InstantiateCommandPool(QueueType queueType) = 0;
virtual std::shared_ptr<Framebuffer> InstantiateFramebuffer(unsigned int width, unsigned int height, const std::shared_ptr<RenderPass>& renderPass, const std::vector<std::shared_ptr<Texture>>& attachments) = 0;
virtual std::shared_ptr<RenderPass> InstantiateRenderPass(std::vector<RenderPass::Attachment> attachments, std::vector<RenderPass::SubpassDescription> subpassDescriptions, std::vector<RenderPass::SubpassDependency> subpassDependencies) = 0;
virtual std::shared_ptr<RenderPipeline> InstantiateRenderPipeline(RenderPipelineInfo pipelineInfo) = 0;
virtual std::shared_ptr<RenderPipelineLayout> InstantiateRenderPipelineLayout(RenderPipelineLayoutInfo pipelineLayoutInfo) = 0;
virtual std::shared_ptr<ShaderStage> InstantiateShaderStage(const ShaderAst& shaderAst, const ShaderWriter::States& states) = 0;

View File

@ -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];

View File

@ -162,6 +162,7 @@ namespace Nz
PixelFormatContent_Undefined = -1,
PixelFormatContent_ColorRGBA,
PixelFormatContent_Depth,
PixelFormatContent_DepthStencil,
PixelFormatContent_Stencil,

View File

@ -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);

View File

@ -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<TextureUsage>(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 {};
}
}

View File

@ -25,6 +25,8 @@ namespace Nz
std::shared_ptr<AbstractBuffer> InstantiateBuffer(BufferType type) override;
std::shared_ptr<CommandPool> InstantiateCommandPool(QueueType queueType) override;
std::shared_ptr<Framebuffer> InstantiateFramebuffer(unsigned int width, unsigned int height, const std::shared_ptr<RenderPass>& renderPass, const std::vector<std::shared_ptr<Texture>>& attachments) override;
std::shared_ptr<RenderPass> InstantiateRenderPass(std::vector<RenderPass::Attachment> attachments, std::vector<RenderPass::SubpassDescription> subpassDescriptions, std::vector<RenderPass::SubpassDependency> subpassDependencies) override;
std::shared_ptr<RenderPipeline> InstantiateRenderPipeline(RenderPipelineInfo pipelineInfo) override;
std::shared_ptr<RenderPipelineLayout> InstantiateRenderPipelineLayout(RenderPipelineLayoutInfo pipelineLayoutInfo) override;
std::shared_ptr<ShaderStage> InstantiateShaderStage(const ShaderAst& shaderAst, const ShaderWriter::States& states) override;

View File

@ -8,13 +8,17 @@
#define NAZARA_VULKANRENDERER_VULKANSINGLEFRAMEBUFFER_HPP
#include <Nazara/VulkanRenderer/VulkanFramebuffer.hpp>
#include <memory>
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>& renderPass, const std::vector<std::shared_ptr<Texture>>& attachments);
VulkanSingleFramebuffer(const VulkanSingleFramebuffer&) = delete;
VulkanSingleFramebuffer(VulkanSingleFramebuffer&&) = delete;
~VulkanSingleFramebuffer() = default;

View File

@ -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;

View File

@ -106,18 +106,19 @@ namespace Nz
for (std::size_t i = 0; i < colorBufferCount; ++i)
{
Nz::Color color = command.clearValues[i].color;
std::array<GLuint, 4> clearColor = { color.r, color.g, color.b, color.a };
std::array<GLfloat, 4> 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<T>::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);

View File

@ -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> clearValues)
void OpenGLCommandBufferBuilder::BeginRenderPass(const Framebuffer& framebuffer, const RenderPass& renderPass, Nz::Recti /*renderRect*/, std::initializer_list<ClearValues> clearValues)
{
m_commandBuffer.SetFramebuffer(static_cast<const OpenGLFramebuffer&>(framebuffer), renderPass, clearValues);
}

View File

@ -6,6 +6,8 @@
#include <Nazara/Renderer/CommandPool.hpp>
#include <Nazara/OpenGLRenderer/OpenGLBuffer.hpp>
#include <Nazara/OpenGLRenderer/OpenGLCommandPool.hpp>
#include <Nazara/OpenGLRenderer/OpenGLFboFramebuffer.hpp>
#include <Nazara/OpenGLRenderer/OpenGLRenderPass.hpp>
#include <Nazara/OpenGLRenderer/OpenGLRenderPipeline.hpp>
#include <Nazara/OpenGLRenderer/OpenGLRenderPipelineLayout.hpp>
#include <Nazara/OpenGLRenderer/OpenGLShaderStage.hpp>
@ -58,6 +60,16 @@ namespace Nz
return std::make_shared<OpenGLCommandPool>();
}
std::shared_ptr<Framebuffer> OpenGLDevice::InstantiateFramebuffer(unsigned int /*width*/, unsigned int /*height*/, const std::shared_ptr<RenderPass>& /*renderPass*/, const std::vector<std::shared_ptr<Texture>>& attachments)
{
return std::make_shared<OpenGLFboFramebuffer>(*this, attachments);
}
std::shared_ptr<RenderPass> OpenGLDevice::InstantiateRenderPass(std::vector<RenderPass::Attachment> attachments, std::vector<RenderPass::SubpassDescription> subpassDescriptions, std::vector<RenderPass::SubpassDependency> subpassDependencies)
{
return std::make_shared<OpenGLRenderPass>(std::move(attachments), std::move(subpassDescriptions), std::move(subpassDependencies));
}
std::shared_ptr<RenderPipeline> OpenGLDevice::InstantiateRenderPipeline(RenderPipelineInfo pipelineInfo)
{
return std::make_shared<OpenGLRenderPipeline>(*this, std::move(pipelineInfo));

View File

@ -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 <Nazara/OpenGLRenderer/OpenGLFboFramebuffer.hpp>
#include <Nazara/OpenGLRenderer/OpenGLRenderPass.hpp>
#include <Nazara/OpenGLRenderer/OpenGLTexture.hpp>
#include <stdexcept>
#include <Nazara/OpenGLRenderer/Debug.hpp>
namespace Nz
{
OpenGLFboFramebuffer::OpenGLFboFramebuffer(OpenGLDevice& device, const std::vector<std::shared_ptr<Texture>>& 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<const OpenGLTexture&>(*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;
}
}

View File

@ -68,7 +68,7 @@ namespace Nz
const TextureBinding& texBinding = std::get<TextureBinding>(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<OpenGLTexture*>(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
{

View File

@ -419,7 +419,7 @@ namespace Nz
RenderPass::AttachmentReference colorReference = {
0,
TextureLayout::ColorInput
TextureLayout::ColorOutput
};
std::vector<RenderPass::SubpassDescription> 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
};
}

View File

@ -4,9 +4,11 @@
#include <Nazara/VulkanRenderer/VulkanDevice.hpp>
#include <Nazara/VulkanRenderer/VulkanCommandPool.hpp>
#include <Nazara/VulkanRenderer/VulkanRenderPass.hpp>
#include <Nazara/VulkanRenderer/VulkanRenderPipeline.hpp>
#include <Nazara/VulkanRenderer/VulkanRenderPipelineLayout.hpp>
#include <Nazara/VulkanRenderer/VulkanShaderStage.hpp>
#include <Nazara/VulkanRenderer/VulkanSingleFramebuffer.hpp>
#include <Nazara/VulkanRenderer/VulkanTexture.hpp>
#include <Nazara/VulkanRenderer/VulkanTextureSampler.hpp>
#include <Nazara/VulkanRenderer/Debug.hpp>
@ -25,6 +27,16 @@ namespace Nz
return std::make_shared<VulkanCommandPool>(*this, queueType);
}
std::shared_ptr<Framebuffer> VulkanDevice::InstantiateFramebuffer(unsigned int width, unsigned int height, const std::shared_ptr<RenderPass>& renderPass, const std::vector<std::shared_ptr<Texture>>& attachments)
{
return std::make_shared<VulkanSingleFramebuffer>(*this, width, height, renderPass, attachments);
}
std::shared_ptr<RenderPass> VulkanDevice::InstantiateRenderPass(std::vector<RenderPass::Attachment> attachments, std::vector<RenderPass::SubpassDescription> subpassDescriptions, std::vector<RenderPass::SubpassDependency> subpassDependencies)
{
return std::make_shared<VulkanRenderPass>(*this, std::move(attachments), std::move(subpassDescriptions), std::move(subpassDependencies));
}
std::shared_ptr<RenderPipeline> VulkanDevice::InstantiateRenderPipeline(RenderPipelineInfo pipelineInfo)
{
return std::make_shared<VulkanRenderPipeline>(*this, std::move(pipelineInfo));

View File

@ -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,

View File

@ -3,8 +3,42 @@
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/VulkanRenderer/VulkanSingleFramebuffer.hpp>
#include <Nazara/Core/StackArray.hpp>
#include <Nazara/VulkanRenderer/VulkanRenderPass.hpp>
#include <Nazara/VulkanRenderer/VulkanTexture.hpp>
#include <stdexcept>
#include <Nazara/VulkanRenderer/Debug.hpp>
namespace Nz
{
VulkanSingleFramebuffer::VulkanSingleFramebuffer(Vk::Device& device, unsigned int width, unsigned int height, const std::shared_ptr<RenderPass>& renderPass, const std::vector<std::shared_ptr<Texture>>& attachments) :
VulkanFramebuffer(Type::Single)
{
assert(renderPass);
const VulkanRenderPass& vkRenderPass = static_cast<const VulkanRenderPass&>(*renderPass);
StackArray<VkImageView> imageViews = NazaraStackArrayNoInit(VkImageView, attachments.size());
for (std::size_t i = 0; i < attachments.size(); ++i)
{
assert(attachments[i]);
const VulkanTexture& vkTexture = static_cast<const VulkanTexture&>(*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()));
}
}