Graphics: Add MaterialPassRegistry

This commit is contained in:
Jérôme Leclercq
2021-07-29 20:16:06 +02:00
parent 5b1123b971
commit 9a311da2c8
20 changed files with 181 additions and 52 deletions

View File

@@ -9,6 +9,7 @@
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Core/Algorithm.hpp>
#include <Nazara/Graphics/Config.hpp>
#include <Nazara/Graphics/Enums.hpp>
#include <memory>
#include <vector>
@@ -18,7 +19,7 @@ namespace Nz
class CommandBufferBuilder;
class RenderElement;
class ElementRenderer
class NAZARA_GRAPHICS_API ElementRenderer
{
public:
ElementRenderer() = default;

View File

@@ -73,6 +73,8 @@ namespace Nz
ShaderBindingPtr blitShaderBinding;
};
std::size_t m_depthPassIndex;
std::size_t m_forwardPassIndex;
std::unordered_map<AbstractViewer*, ViewerData> m_viewers;
std::unordered_map<MaterialPass*, MaterialData> m_materials;
std::unordered_map<WorldInstancePtr, std::unordered_map<const InstancedRenderable*, RenderableData>> m_renderables;

View File

@@ -9,6 +9,7 @@
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Graphics/Config.hpp>
#include <Nazara/Graphics/MaterialPassRegistry.hpp>
#include <Nazara/Graphics/TextureSamplerCache.hpp>
#include <Nazara/Renderer/Renderer.hpp>
#include <Nazara/Renderer/RenderDevice.hpp>
@@ -36,6 +37,8 @@ namespace Nz
inline const std::shared_ptr<RenderPipelineLayout>& GetBlitPipelineLayout() const;
inline const std::shared_ptr<AbstractBuffer>& GetFullscreenVertexBuffer() const;
inline const std::shared_ptr<VertexDeclaration>& GetFullscreenVertexDeclaration() const;
inline MaterialPassRegistry& GetMaterialPassRegistry();
inline const MaterialPassRegistry& GetMaterialPassRegistry() const;
inline PixelFormat GetPreferredDepthStencilFormat() const;
inline const std::shared_ptr<RenderPipelineLayout>& GetReferencePipelineLayout() const;
inline const std::shared_ptr<RenderDevice>& GetRenderDevice() const;
@@ -58,6 +61,7 @@ namespace Nz
private:
void BuildBlitPipeline();
void BuildFullscreenVertexBuffer();
void RegisterMaterialPasses();
void SelectDepthStencilFormats();
std::optional<RenderPassCache> m_renderPassCache;
@@ -68,6 +72,7 @@ namespace Nz
std::shared_ptr<RenderPipelineLayout> m_blitPipelineLayout;
std::shared_ptr<RenderPipelineLayout> m_referencePipelineLayout;
std::shared_ptr<VertexDeclaration> m_fullscreenVertexDeclaration;
MaterialPassRegistry m_materialPassRegistry;
PixelFormat m_preferredDepthStencilFormat;
static Graphics* s_instance;

View File

@@ -27,6 +27,16 @@ namespace Nz
return m_fullscreenVertexDeclaration;
}
inline MaterialPassRegistry& Graphics::GetMaterialPassRegistry()
{
return m_materialPassRegistry;
}
inline const MaterialPassRegistry& Graphics::GetMaterialPassRegistry() const
{
return m_materialPassRegistry;
}
inline PixelFormat Graphics::GetPreferredDepthStencilFormat() const
{
return m_preferredDepthStencilFormat;

View File

@@ -27,7 +27,7 @@ namespace Nz
InstancedRenderable(InstancedRenderable&&) noexcept = default;
~InstancedRenderable();
virtual void BuildElement(const std::string& pass, WorldInstance& worldInstance, std::vector<std::unique_ptr<RenderElement>>& elements) const = 0;
virtual void BuildElement(std::size_t passIndex, WorldInstance& worldInstance, std::vector<std::unique_ptr<RenderElement>>& elements) const = 0;
virtual const std::shared_ptr<Material>& GetMaterial(std::size_t i) const = 0;
virtual std::size_t GetMaterialCount() const = 0;

View File

@@ -8,6 +8,7 @@
#define NAZARA_MATERIAL_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Graphics/Graphics.hpp>
#include <Nazara/Graphics/MaterialPass.hpp>
namespace Nz
@@ -18,16 +19,18 @@ namespace Nz
Material();
~Material() = default;
void AddPass(std::string name, std::shared_ptr<MaterialPass> pass);
inline void AddPass(std::size_t passIndex, std::shared_ptr<MaterialPass> pass);
inline void AddPass(std::string passName, std::shared_ptr<MaterialPass> pass);
inline MaterialPass* GetPass(const std::string& name) const;
inline MaterialPass* GetPass(std::size_t passIndex) const;
bool HasPass(const std::string& name) const;
inline bool HasPass(std::size_t passIndex) const;
void RemovePass(const std::string& name);
inline void RemovePass(std::size_t passIndex);
inline void RemovePass(const std::string& passName);
private:
std::unordered_map<std::string, std::shared_ptr<MaterialPass>> m_passes;
std::vector<std::shared_ptr<MaterialPass>> m_passes;
};
}

View File

@@ -7,13 +7,45 @@
namespace Nz
{
inline MaterialPass* Material::GetPass(const std::string& name) const
inline void Material::AddPass(std::size_t passIndex, std::shared_ptr<MaterialPass> pass)
{
auto it = m_passes.find(name);
if (it == m_passes.end())
if (passIndex >= m_passes.size())
m_passes.resize(passIndex + 1);
m_passes[passIndex] = std::move(pass);
}
inline void Material::AddPass(std::string passName, std::shared_ptr<MaterialPass> pass)
{
auto& registry = Graphics::Instance()->GetMaterialPassRegistry();
return AddPass(registry.GetPassIndex(passName), std::move(pass));
}
inline MaterialPass* Material::GetPass(std::size_t passIndex) const
{
if (passIndex >= m_passes.size())
return nullptr;
return it->second.get();
return m_passes[passIndex].get();
}
inline bool Material::HasPass(std::size_t passIndex) const
{
return GetPass(passIndex) != nullptr;
}
inline void Material::RemovePass(std::size_t passIndex)
{
if (passIndex >= m_passes.size())
return;
m_passes[passIndex].reset();
}
inline void Material::RemovePass(const std::string& passName)
{
auto& registry = Graphics::Instance()->GetMaterialPassRegistry();
return RemovePass(registry.GetPassIndex(passName));
}
}

View File

@@ -133,6 +133,7 @@ namespace Nz
UInt64 m_enabledOptions;
mutable MaterialPipelineInfo m_pipelineInfo;
ShaderBindingPtr m_shaderBinding;
bool m_forceCommandBufferRegeneration;
mutable bool m_pipelineUpdated;
bool m_shaderBindingUpdated;
};

View File

@@ -621,13 +621,17 @@ namespace Nz
inline void MaterialPass::InvalidatePipeline()
{
m_forceCommandBufferRegeneration = true;
m_pipelineUpdated = false;
OnMaterialInvalidated(this);
}
inline void MaterialPass::InvalidateShaderBinding()
{
m_forceCommandBufferRegeneration = true;
m_shaderBindingUpdated = false;
OnMaterialInvalidated(this);
}

View File

@@ -0,0 +1,38 @@
// 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_MATERIAL_PASS_REGISTRY_HPP
#define NAZARA_MATERIAL_PASS_REGISTRY_HPP
#include <Nazara/Prerequisites.hpp>
#include <string>
#include <unordered_map>
namespace Nz
{
class MaterialPassRegistry
{
public:
MaterialPassRegistry() = default;
MaterialPassRegistry(const MaterialPassRegistry&) = default;
MaterialPassRegistry(MaterialPassRegistry&&) = default;
~MaterialPassRegistry() = default;
inline std::size_t GetPassIndex(const std::string& passName) const;
inline std::size_t RegisterPass(std::string passName);
MaterialPassRegistry& operator=(const MaterialPassRegistry&) = default;
MaterialPassRegistry& operator=(MaterialPassRegistry&&) = default;
private:
std::unordered_map<std::string, std::size_t> m_passIndex;
};
}
#include <Nazara/Graphics/MaterialPassRegistry.inl>
#endif

View File

@@ -0,0 +1,32 @@
// 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/MaterialPassRegistry.hpp>
#include <stdexcept>
#include <Nazara/Graphics/Debug.hpp>
namespace Nz
{
std::size_t MaterialPassRegistry::GetPassIndex(const std::string& passName) const
{
auto it = m_passIndex.find(passName);
if (it == m_passIndex.end())
throw std::runtime_error("pass " + passName + " must be registered before being used");
return it->second;
}
inline std::size_t MaterialPassRegistry::RegisterPass(std::string passName)
{
if (m_passIndex.find(passName) != m_passIndex.end())
throw std::runtime_error("pass " + passName + " is already registered");
std::size_t passIndex = m_passIndex.size();
m_passIndex.emplace(std::move(passName), passIndex);
return passIndex;
}
}
#include <Nazara/Graphics/DebugOff.hpp>

View File

@@ -28,7 +28,7 @@ namespace Nz
Model(Model&&) noexcept = default;
~Model() = default;
void BuildElement(const std::string& pass, WorldInstance& worldInstance, std::vector<std::unique_ptr<RenderElement>>& elements) const override;
void BuildElement(std::size_t passIndex, WorldInstance& worldInstance, std::vector<std::unique_ptr<RenderElement>>& elements) const override;
const std::shared_ptr<AbstractBuffer>& GetIndexBuffer(std::size_t subMeshIndex) const;
std::size_t GetIndexCount(std::size_t subMeshIndex) const;

View File

@@ -21,8 +21,8 @@ namespace Nz
inline UInt64 RenderSubmesh::ComputeSortingScore(const RenderQueueRegistry& registry) const
{
UInt64 elementType = GetElementType();
UInt64 layerIndex = registry.FetchLayerIndex(m_renderLayer);
UInt64 elementType = GetElementType();
UInt64 pipelineIndex = registry.FetchPipelineIndex(m_renderPipeline.get());
UInt64 vertexBufferIndex = registry.FetchVertexBuffer(m_vertexBuffer.get());
@@ -33,8 +33,8 @@ namespace Nz
// - VertexBuffer (8bits)
// - ?? (24bits) - Depth?
return (elementType & 0xF) << 60 |
(layerIndex & 0xFF) << 52 |
return (layerIndex & 0xFF) << 60 |
(elementType & 0xF) << 52 |
(pipelineIndex & 0xFFFF) << 36 |
(vertexBufferIndex & 0xFF) << 24;
}

View File

@@ -12,7 +12,7 @@
namespace Nz
{
class SubmeshRenderer : public ElementRenderer
class NAZARA_GRAPHICS_API SubmeshRenderer : public ElementRenderer
{
public:
SubmeshRenderer() = default;