Graphics: Add SpriteChainRenderer

This commit is contained in:
Jérôme Leclercq
2021-09-05 15:50:17 +02:00
parent a18d505ae2
commit 938d965e06
18 changed files with 705 additions and 14 deletions

View File

@@ -18,6 +18,8 @@ namespace Nz
{
class CommandBufferBuilder;
class RenderElement;
class RenderFrame;
struct ElementRendererData;
class NAZARA_GRAPHICS_API ElementRenderer
{
@@ -25,7 +27,16 @@ namespace Nz
ElementRenderer() = default;
virtual ~ElementRenderer();
virtual void Render(CommandBufferBuilder& commandBuffer, const Pointer<const RenderElement>* elements, std::size_t elementCount) = 0;
virtual std::unique_ptr<ElementRendererData> InstanciateData() = 0;
virtual void Prepare(ElementRendererData& rendererData, RenderFrame& currentFrame, const Pointer<const RenderElement>* elements, std::size_t elementCount);
virtual void Render(ElementRendererData& rendererData, CommandBufferBuilder& commandBuffer, const Pointer<const RenderElement>* elements, std::size_t elementCount) = 0;
virtual void Reset(ElementRendererData& rendererData, RenderFrame& currentFrame);
};
struct NAZARA_GRAPHICS_API ElementRendererData
{
ElementRendererData() = default;
virtual ~ElementRendererData();
};
}

View File

@@ -7,13 +7,20 @@
#ifndef NAZARA_ENUMS_GRAPHICS_HPP
#define NAZARA_ENUMS_GRAPHICS_HPP
#include <Nazara/Core/Algorithm.hpp>
namespace Nz
{
enum class BasicRenderElement
{
Submesh = 0,
SpriteChain = 0,
Submesh = 1,
Max = Submesh
};
constexpr std::size_t BasicRenderElementCount = UnderlyingCast(BasicRenderElement::Max) + 1;
enum class CullTest
{
Box,

View File

@@ -25,6 +25,8 @@
namespace Nz
{
class RenderFrame;
class NAZARA_GRAPHICS_API ForwardFramePipeline : public FramePipeline
{
public:
@@ -51,7 +53,7 @@ namespace Nz
BakedFrameGraph BuildFrameGraph();
void RegisterMaterialPass(MaterialPass* material);
void ProcessRenderQueue(CommandBufferBuilder& builder, const RenderQueue<RenderElement*>& renderQueue);
template<typename F> void ProcessRenderQueue(const RenderQueue<RenderElement*>& renderQueue, F&& callback);
void UnregisterMaterialPass(MaterialPass* material);
struct MaterialData
@@ -79,6 +81,7 @@ namespace Nz
std::size_t visibilityHash = 0;
std::vector<std::unique_ptr<RenderElement>> depthPrepassRenderElements;
std::vector<std::unique_ptr<RenderElement>> forwardRenderElements;
std::vector<std::unique_ptr<ElementRendererData>> elementRendererData;
RenderQueueRegistry depthPrepassRegistry;
RenderQueueRegistry forwardRegistry;
RenderQueue<RenderElement*> depthPrepassRenderQueue;
@@ -100,6 +103,7 @@ namespace Nz
std::vector<std::unique_ptr<ElementRenderer>> m_elementRenderers;
std::vector<VisibleRenderable> m_visibleRenderables;
BakedFrameGraph m_bakedFrameGraph;
RenderFrame* m_currentRenderFrame;
bool m_rebuildFrameGraph;
};
}

View File

@@ -14,6 +14,7 @@ namespace Nz
{
class AbstractBuffer;
class RenderPipeline;
class VertexDeclaration;
class RenderQueueRegistry
{
@@ -26,15 +27,18 @@ namespace Nz
inline std::size_t FetchLayerIndex(int renderLayer) const;
inline std::size_t FetchPipelineIndex(const RenderPipeline* pipeline) const;
inline std::size_t FetchVertexBuffer(const AbstractBuffer* vertexBuffer) const;
inline std::size_t FetchVertexDeclaration(const VertexDeclaration* vertexDeclaration) const;
inline void RegisterLayer(int renderLayer);
inline void RegisterPipeline(const RenderPipeline* pipeline);
inline void RegisterVertexBuffer(const AbstractBuffer* vertexBuffer);
inline void RegisterVertexDeclaration(const VertexDeclaration* vertexDeclaration);
private:
robin_hood::unordered_map<int, std::size_t> m_renderLayerRegistry;
robin_hood::unordered_map<const RenderPipeline*, std::size_t> m_pipelineRegistry;
robin_hood::unordered_map<const AbstractBuffer*, std::size_t> m_vertexBufferRegistry;
robin_hood::unordered_map<const VertexDeclaration*, std::size_t> m_vertexDeclarationRegistry;
};
}

View File

@@ -38,6 +38,14 @@ namespace Nz
return it->second;
}
inline std::size_t RenderQueueRegistry::FetchVertexDeclaration(const VertexDeclaration* vertexDeclaration) const
{
auto it = m_vertexDeclarationRegistry.find(vertexDeclaration);
assert(it != m_vertexDeclarationRegistry.end());
return it->second;
}
inline void RenderQueueRegistry::RegisterLayer(int renderLayer)
{
m_renderLayerRegistry.try_emplace(renderLayer, m_renderLayerRegistry.size());
@@ -52,6 +60,11 @@ namespace Nz
{
m_vertexBufferRegistry.try_emplace(vertexBuffer, m_vertexBufferRegistry.size());
}
inline void RenderQueueRegistry::RegisterVertexDeclaration(const VertexDeclaration* vertexDeclaration)
{
m_vertexDeclarationRegistry.try_emplace(vertexDeclaration, m_vertexDeclarationRegistry.size());
}
}
#include <Nazara/Graphics/DebugOff.hpp>

View File

@@ -0,0 +1,53 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_RENDERSUBMESH_HPP
#define NAZARA_RENDERSUBMESH_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Graphics/RenderElement.hpp>
#include <Nazara/Graphics/RenderQueueRegistry.hpp>
#include <memory>
#include <vector>
namespace Nz
{
class AbstractBuffer;
class RenderPipeline;
class ShaderBinding;
class VertexDeclaration;
class RenderSpriteChain : public RenderElement
{
public:
inline RenderSpriteChain(int renderLayer, std::shared_ptr<RenderPipeline> renderPipeline, std::shared_ptr<VertexDeclaration> vertexDeclaration, std::size_t spriteCount, const void* spriteData, const ShaderBinding& materialBinding, const ShaderBinding& instanceBinding);
~RenderSpriteChain() = default;
inline UInt64 ComputeSortingScore(const RenderQueueRegistry& registry) const override;
inline const ShaderBinding& GetInstanceBinding() const;
inline const ShaderBinding& GetMaterialBinding() const;
inline const RenderPipeline* GetRenderPipeline() const;
inline std::size_t GetSpriteCount() const;
inline const void* GetSpriteData() const;
inline const VertexDeclaration* GetVertexDeclaration() const;
inline void Register(RenderQueueRegistry& registry) const override;
private:
std::shared_ptr<RenderPipeline> m_renderPipeline;
std::shared_ptr<VertexDeclaration> m_vertexDeclaration;
std::size_t m_spriteCount;
const void* m_spriteData;
const ShaderBinding& m_instanceBinding;
const ShaderBinding& m_materialBinding;
int m_renderLayer;
};
}
#include <Nazara/Graphics/RenderSpriteChain.inl>
#endif

View File

@@ -0,0 +1,80 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Graphics/RenderSpriteChain.hpp>
#include <Nazara/Graphics/Debug.hpp>
namespace Nz
{
inline RenderSpriteChain::RenderSpriteChain(int renderLayer, std::shared_ptr<RenderPipeline> renderPipeline, std::shared_ptr<VertexDeclaration> vertexDeclaration, std::size_t spriteCount, const void* spriteData, const ShaderBinding& materialBinding, const ShaderBinding& instanceBinding) :
RenderElement(BasicRenderElement::SpriteChain),
m_renderPipeline(std::move(renderPipeline)),
m_vertexDeclaration(std::move(vertexDeclaration)),
m_spriteCount(spriteCount),
m_spriteData(spriteData),
m_instanceBinding(instanceBinding),
m_materialBinding(materialBinding),
m_renderLayer(renderLayer)
{
}
inline UInt64 RenderSpriteChain::ComputeSortingScore(const RenderQueueRegistry& registry) const
{
UInt64 layerIndex = registry.FetchLayerIndex(m_renderLayer);
UInt64 elementType = GetElementType();
UInt64 pipelineIndex = registry.FetchPipelineIndex(m_renderPipeline.get());
UInt64 vertexDeclarationIndex = registry.FetchVertexDeclaration(m_vertexDeclaration.get());
// RQ index:
// - Layer (8bits)
// - Element type (4bits)
// - Pipeline (16bits)
// - VertexDeclaration (8bits)
// - ?? (24bits) - Depth?
return (layerIndex & 0xFF) << 60 |
(elementType & 0xF) << 52 |
(pipelineIndex & 0xFFFF) << 36 |
(vertexDeclarationIndex & 0xFF) << 24;
}
inline const ShaderBinding& RenderSpriteChain::GetInstanceBinding() const
{
return m_instanceBinding;
}
inline const ShaderBinding& RenderSpriteChain::GetMaterialBinding() const
{
return m_materialBinding;
}
inline const RenderPipeline* RenderSpriteChain::GetRenderPipeline() const
{
return m_renderPipeline.get();
}
inline std::size_t RenderSpriteChain::GetSpriteCount() const
{
return m_spriteCount;
}
inline const void* RenderSpriteChain::GetSpriteData() const
{
return m_spriteData;
}
inline const VertexDeclaration* RenderSpriteChain::GetVertexDeclaration() const
{
return m_vertexDeclaration.get();
}
inline void RenderSpriteChain::Register(RenderQueueRegistry& registry) const
{
registry.RegisterLayer(m_renderLayer);
registry.RegisterPipeline(m_renderPipeline.get());
registry.RegisterVertexDeclaration(m_vertexDeclaration.get());
}
}
#include <Nazara/Graphics/DebugOff.hpp>

View File

@@ -27,8 +27,8 @@ namespace Nz
UInt64 vertexBufferIndex = registry.FetchVertexBuffer(m_vertexBuffer.get());
// RQ index:
// - Element type (4bits)
// - Layer (8bits)
// - Element type (4bits)
// - Pipeline (16bits)
// - VertexBuffer (8bits)
// - ?? (24bits) - Depth?

View File

@@ -0,0 +1,46 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_SPRITE_HPP
#define NAZARA_SPRITE_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Graphics/Config.hpp>
#include <Nazara/Graphics/InstancedRenderable.hpp>
#include <Nazara/Renderer/RenderPipeline.hpp>
#include <Nazara/Utility/VertexDeclaration.hpp>
#include <Nazara/Utility/VertexStruct.hpp>
#include <array>
namespace Nz
{
class NAZARA_GRAPHICS_API Sprite : public InstancedRenderable
{
public:
Sprite(std::shared_ptr<Material> material);
Sprite(const Sprite&) = delete;
Sprite(Sprite&&) noexcept = default;
~Sprite() = default;
void BuildElement(std::size_t passIndex, const WorldInstance& worldInstance, std::vector<std::unique_ptr<RenderElement>>& elements) const override;
const std::shared_ptr<Material>& GetMaterial(std::size_t i) const;
std::size_t GetMaterialCount() const;
inline void SetMaterial(std::shared_ptr<Material> material);
Sprite& operator=(const Sprite&) = delete;
Sprite& operator=(Sprite&&) noexcept = default;
private:
std::array<VertexStruct_XYZ_Color_UV, 4> m_vertices;
std::shared_ptr<Material> m_material;
};
}
#include <Nazara/Graphics/Sprite.inl>
#endif

View File

@@ -0,0 +1,17 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Graphics/Sprite.hpp>
#include <cassert>
#include <Nazara/Graphics/Debug.hpp>
namespace Nz
{
inline void Sprite::SetMaterial(std::shared_ptr<Material> material)
{
m_material = std::move(material);
}
}
#include <Nazara/Graphics/DebugOff.hpp>

View File

@@ -0,0 +1,68 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_SPRITECHAINRENDERER_HPP
#define NAZARA_SPRITECHAINRENDERER_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Graphics/ElementRenderer.hpp>
#include <memory>
#include <unordered_map>
#include <vector>
namespace Nz
{
class AbstractBuffer;
class RenderDevice;
class RenderPipeline;
class RenderSpriteChain;
class ShaderBinding;
class NAZARA_GRAPHICS_API SpriteChainRenderer : public ElementRenderer
{
public:
SpriteChainRenderer(RenderDevice& device, std::size_t maxVertexBufferSize = 32 * 1024);
~SpriteChainRenderer() = default;
std::unique_ptr<ElementRendererData> InstanciateData();
void Prepare(ElementRendererData& rendererData, RenderFrame& currentFrame, const Pointer<const RenderElement>* elements, std::size_t elementCount);
void Render(ElementRendererData& rendererData, CommandBufferBuilder& commandBuffer, const Pointer<const RenderElement>* elements, std::size_t elementCount) override;
void Reset(ElementRendererData& rendererData, RenderFrame& currentFrame);
private:
std::shared_ptr<AbstractBuffer> m_indexBuffer;
std::size_t m_maxVertexBufferSize;
std::size_t m_maxVertexCount;
RenderDevice& m_device;
};
struct SpriteChainRendererData : public ElementRendererData
{
struct DrawCall
{
const AbstractBuffer* vertexBuffer;
const RenderPipeline* renderPipeline;
const ShaderBinding* instanceBinding;
const ShaderBinding* materialBinding;
std::size_t firstIndex;
std::size_t quadCount;
};
struct DrawCallIndices
{
std::size_t start;
std::size_t count;
};
std::unordered_map<const RenderSpriteChain*, DrawCallIndices> drawCallPerElement;
std::vector<DrawCall> drawCalls;
std::vector<std::shared_ptr<AbstractBuffer>> vertexBuffers;
};
}
#include <Nazara/Graphics/SpriteChainRenderer.inl>
#endif

View File

@@ -0,0 +1,12 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Graphics/SpriteChainRenderer.hpp>
#include <Nazara/Graphics/Debug.hpp>
namespace Nz
{
}
#include <Nazara/Graphics/DebugOff.hpp>

View File

@@ -18,7 +18,8 @@ namespace Nz
SubmeshRenderer() = default;
~SubmeshRenderer() = default;
void Render(CommandBufferBuilder& commandBuffer, const Pointer<const RenderElement>* elements, std::size_t elementCount) override;
std::unique_ptr<ElementRendererData> InstanciateData();
void Render(ElementRendererData& rendererData, CommandBufferBuilder& commandBuffer, const Pointer<const RenderElement>* elements, std::size_t elementCount) override;
};
}