Graphics: Make use of shader binding sets

This commit is contained in:
Jérôme Leclercq
2021-06-16 14:47:54 +02:00
parent 5559fe1af7
commit 3cd9172f7a
49 changed files with 592 additions and 792 deletions

View File

@@ -16,18 +16,6 @@ namespace Nz
Sphere,
Volume
};
enum class PredefinedShaderBinding
{
TexOverlay,
UboInstanceData,
UboLighData,
UboViewerData,
Max = UboViewerData
};
constexpr std::size_t PredefinedShaderBindingCount = static_cast<std::size_t>(PredefinedShaderBinding::Max) + 1;
}
#endif // NAZARA_ENUMS_GRAPHICS_HPP

View File

@@ -12,12 +12,12 @@
#include <Nazara/Graphics/TextureSamplerCache.hpp>
#include <Nazara/Renderer/Renderer.hpp>
#include <Nazara/Renderer/RenderDevice.hpp>
#include <Nazara/Renderer/RenderPipelineLayout.hpp>
#include <optional>
namespace Nz
{
class AbstractBuffer;
class RenderDevice;
class NAZARA_GRAPHICS_API Graphics : public ModuleBase<Graphics>
{
@@ -31,19 +31,26 @@ namespace Nz
Graphics(Config config);
~Graphics();
inline const std::shared_ptr<RenderPipelineLayout>& GetReferencePipelineLayout() const;
inline const std::shared_ptr<RenderDevice>& GetRenderDevice() const;
inline TextureSamplerCache& GetSamplerCache();
inline const std::shared_ptr<AbstractBuffer>& GetViewerDataUBO();
struct Config
{
bool useDedicatedRenderDevice = true;
};
static constexpr UInt32 MaterialBindingSet = 2;
static constexpr UInt32 ViewerBindingSet = 0;
static constexpr UInt32 WorldBindingSet = 1;
static void FillViewerPipelineLayout(RenderPipelineLayoutInfo& layoutInfo, UInt32 set = ViewerBindingSet);
static void FillWorldPipelineLayout(RenderPipelineLayoutInfo& layoutInfo, UInt32 set = WorldBindingSet);
private:
std::optional<TextureSamplerCache> m_samplerCache;
std::shared_ptr<AbstractBuffer> m_viewerDataUBO;
std::shared_ptr<RenderDevice> m_renderDevice;
std::shared_ptr<RenderPipelineLayout> m_referencePipelineLayout;
static Graphics* s_instance;
};

View File

@@ -7,6 +7,11 @@
namespace Nz
{
inline const std::shared_ptr<RenderPipelineLayout>& Graphics::GetReferencePipelineLayout() const
{
return m_referencePipelineLayout;
}
inline const std::shared_ptr<RenderDevice>& Graphics::GetRenderDevice() const
{
return m_renderDevice;
@@ -16,11 +21,6 @@ namespace Nz
{
return *m_samplerCache;
}
inline const std::shared_ptr<AbstractBuffer>& Graphics::GetViewerDataUBO()
{
return m_viewerDataUBO;
}
}
#include <Nazara/Graphics/DebugOff.hpp>

View File

@@ -13,7 +13,7 @@
namespace Nz
{
class CommandBufferBuilder;
class ModelInstance;
class WorldInstance;
class NAZARA_GRAPHICS_API InstancedRenderable
{
@@ -23,7 +23,7 @@ namespace Nz
InstancedRenderable(InstancedRenderable&&) noexcept = default;
~InstancedRenderable();
virtual void Draw(CommandBufferBuilder& commandBuffer, ModelInstance& instance) const = 0;
virtual void Draw(CommandBufferBuilder& commandBuffer, WorldInstance& instance) const = 0;
InstancedRenderable& operator=(const InstancedRenderable&) = delete;
InstancedRenderable& operator=(InstancedRenderable&&) noexcept = default;

View File

@@ -28,7 +28,7 @@
namespace Nz
{
class CommandBufferBuilder;
class UploadPool;
class RenderFrame;
class NAZARA_GRAPHICS_API Material : public Resource
{
@@ -70,6 +70,7 @@ namespace Nz
inline float GetPointSize() const;
inline const std::shared_ptr<const MaterialSettings>& GetSettings() const;
inline const std::shared_ptr<UberShader>& GetShader(ShaderStageType shaderStage) const;
inline ShaderBinding& GetShaderBinding();
inline const std::shared_ptr<Texture>& GetTexture(std::size_t textureIndex) const;
inline const TextureSamplerInfo& GetTextureSampler(std::size_t textureIndex) const;
inline const std::shared_ptr<AbstractBuffer>& GetUniformBuffer(std::size_t bufferIndex) const;
@@ -103,8 +104,7 @@ namespace Nz
inline void SetTextureSampler(std::size_t textureIndex, TextureSamplerInfo samplerInfo);
inline void SetUniformBuffer(std::size_t bufferIndex, std::shared_ptr<AbstractBuffer> uniformBuffer);
void UpdateBuffers(UploadPool& uploadPool, CommandBufferBuilder& builder);
void UpdateShaderBinding(ShaderBinding& shaderBinding) const;
bool Update(RenderFrame& renderFrame, CommandBufferBuilder& builder);
// Signals:
NazaraSignal(OnMaterialRelease, const Material* /*material*/);
@@ -114,6 +114,7 @@ namespace Nz
inline void InvalidateShaderBinding();
inline void InvalidateTextureSampler(std::size_t textureIndex);
inline void UpdatePipeline() const;
void UpdateShaderBinding();
struct MaterialTexture
{
@@ -135,7 +136,9 @@ namespace Nz
mutable std::shared_ptr<MaterialPipeline> m_pipeline;
UInt64 m_enabledConditions;
mutable MaterialPipelineInfo m_pipelineInfo;
ShaderBindingPtr m_shaderBinding;
mutable bool m_pipelineUpdated;
bool m_shaderBindingUpdated;
bool m_shadowCastingEnabled;
};
}

View File

@@ -94,7 +94,7 @@ namespace Nz
{
if (TestBit<UInt64>(m_enabledConditions, conditionIndex) != enable)
{
m_enabledConditions = SetBit<UInt64>(m_enabledConditions, conditionIndex);
m_enabledConditions = ToggleBit<UInt64>(m_enabledConditions, conditionIndex);
InvalidatePipeline();
}
}
@@ -439,6 +439,12 @@ namespace Nz
return m_pipelineInfo.shaders[UnderlyingCast(shaderStage)].uberShader;
}
inline ShaderBinding& Material::GetShaderBinding()
{
assert(m_shaderBinding);
return *m_shaderBinding;
}
inline const std::shared_ptr<Texture>& Material::GetTexture(std::size_t textureIndex) const
{
NazaraAssert(textureIndex < m_textures.size(), "Invalid texture index");
@@ -725,7 +731,7 @@ namespace Nz
inline void Material::InvalidateShaderBinding()
{
//TODO
m_shaderBindingUpdated = false;
}
inline void Material::InvalidateTextureSampler(std::size_t textureIndex)

View File

@@ -24,7 +24,6 @@ namespace Nz
class MaterialSettings
{
public:
using PredefinedBinding = std::array<std::size_t, PredefinedShaderBindingCount>;
using Shaders = std::array<std::shared_ptr<UberShader>, ShaderStageTypeCount>;
struct Builder;
@@ -42,7 +41,6 @@ namespace Nz
inline const Builder& GetBuilderData() const;
inline const std::vector<Condition>& GetConditions() const;
inline std::size_t GetConditionIndex(const std::string_view& name) const;
inline std::size_t GetPredefinedBindingIndex(PredefinedShaderBinding binding) const;
inline const std::shared_ptr<RenderPipelineLayout>& GetRenderPipelineLayout() const;
inline const std::shared_ptr<UberShader>& GetShader(ShaderStageType stage) const;
inline const Shaders& GetShaders() const;
@@ -62,7 +60,6 @@ namespace Nz
struct Builder
{
PredefinedBinding predefinedBinding;
Shaders shaders;
std::vector<Condition> conditions;
std::vector<Texture> textures;
@@ -84,25 +81,28 @@ namespace Nz
struct SharedUniformBlock
{
UInt32 bindingIndex;
std::string name;
std::string bindingPoint;
std::vector<UniformVariable> uniforms;
ShaderStageTypeFlags shaderStages = ShaderStageType_All;
};
struct Texture
{
std::string bindingPoint;
UInt32 bindingIndex;
std::string name;
ImageType type;
ShaderStageTypeFlags shaderStages = ShaderStageType_All;
};
struct UniformBlock
{
std::size_t blockSize;
UInt32 bindingIndex;
std::string name;
std::string bindingPoint;
std::size_t blockSize;
std::vector<UniformVariable> uniforms;
std::vector<UInt8> defaultValues;
ShaderStageTypeFlags shaderStages = ShaderStageType_All;
};
private:

View File

@@ -18,36 +18,36 @@ namespace Nz
m_data(std::move(data))
{
RenderPipelineLayoutInfo info;
unsigned int bindingIndex = 0;
Graphics::FillViewerPipelineLayout(info);
Graphics::FillWorldPipelineLayout(info);
for (const Texture& textureInfo : m_data.textures)
{
info.bindings.push_back({
//textureInfo.bindingPoint,
Graphics::MaterialBindingSet,
textureInfo.bindingIndex,
ShaderBindingType::Texture,
ShaderStageType_All,
bindingIndex++
textureInfo.shaderStages
});
}
for (const UniformBlock& ubo : m_data.uniformBlocks)
{
info.bindings.push_back({
//ubo.bindingPoint,
Graphics::MaterialBindingSet,
ubo.bindingIndex,
ShaderBindingType::UniformBuffer,
ShaderStageType_All,
bindingIndex++
ubo.shaderStages
});
}
for (const SharedUniformBlock& ubo : m_data.sharedUniformBlocks)
{
info.bindings.push_back({
//ubo.bindingPoint,
Graphics::MaterialBindingSet,
ubo.bindingIndex,
ShaderBindingType::UniformBuffer,
ShaderStageType_All,
bindingIndex++
ubo.shaderStages
});
}
@@ -75,11 +75,6 @@ namespace Nz
return InvalidIndex;
}
inline std::size_t MaterialSettings::GetPredefinedBindingIndex(PredefinedShaderBinding binding) const
{
return m_data.predefinedBinding[UnderlyingCast(binding)];
}
inline const std::shared_ptr<RenderPipelineLayout>& MaterialSettings::GetRenderPipelineLayout() const
{
return m_pipelineLayout;

View File

@@ -28,10 +28,11 @@ namespace Nz
Model(Model&&) noexcept = default;
~Model() = default;
void Draw(CommandBufferBuilder& commandBuffer, ModelInstance& instance) const override;
void Draw(CommandBufferBuilder& commandBuffer, WorldInstance& instance) const override;
const std::shared_ptr<AbstractBuffer>& GetIndexBuffer(std::size_t subMeshIndex) const;
std::size_t GetIndexCount(std::size_t subMeshIndex) const;
const std::shared_ptr<Material>& GetMaterial(std::size_t subMeshIndex) const;
const std::shared_ptr<RenderPipeline>& GetRenderPipeline(std::size_t subMeshIndex) const;
const std::shared_ptr<AbstractBuffer>& GetVertexBuffer(std::size_t subMeshIndex) const;
inline std::size_t GetSubMeshCount() const;

View File

@@ -42,7 +42,6 @@ namespace Nz
std::size_t worldMatrixOffset;
static PredefinedInstanceData GetOffsets();
static MaterialSettings::SharedUniformBlock GetUniformBlock();
};
struct NAZARA_GRAPHICS_API PredefinedViewerData
@@ -59,7 +58,6 @@ namespace Nz
std::size_t viewProjMatrixOffset;
static PredefinedViewerData GetOffsets();
static MaterialSettings::SharedUniformBlock GetUniformBlock();
};
}

View File

@@ -28,7 +28,11 @@ namespace Nz
ViewerInstance(ViewerInstance&&) noexcept = default;
~ViewerInstance() = default;
void UpdateViewBuffer(UploadPool& uploadPool, CommandBufferBuilder& builder);
inline std::shared_ptr<AbstractBuffer>& GetInstanceBuffer();
inline const std::shared_ptr<AbstractBuffer>& GetInstanceBuffer() const;
inline ShaderBinding& GetShaderBinding();
void UpdateBuffers(UploadPool& uploadPool, CommandBufferBuilder& builder);
inline void UpdateProjectionMatrix(const Matrix4f& projectionMatrix);
inline void UpdateProjectionMatrix(const Matrix4f& projectionMatrix, const Matrix4f& invProjectionMatrix);
inline void UpdateProjViewMatrices(const Matrix4f& projectionMatrix, const Matrix4f& viewMatrix);
@@ -42,13 +46,16 @@ namespace Nz
ViewerInstance& operator=(ViewerInstance&&) noexcept = default;
private:
std::shared_ptr<AbstractBuffer> m_viewerDataBuffer;
Matrix4f m_invProjectionMatrix;
Matrix4f m_invViewProjMatrix;
Matrix4f m_invViewMatrix;
Matrix4f m_projectionMatrix;
Matrix4f m_viewProjMatrix;
Matrix4f m_viewMatrix;
ShaderBindingPtr m_shaderBinding;
Vector2f m_targetSize;
bool m_dataInvalided;
};
}

View File

@@ -8,17 +8,36 @@
namespace Nz
{
inline std::shared_ptr<AbstractBuffer>& ViewerInstance::GetInstanceBuffer()
{
return m_viewerDataBuffer;
}
inline const std::shared_ptr<AbstractBuffer>& ViewerInstance::GetInstanceBuffer() const
{
return m_viewerDataBuffer;
}
inline ShaderBinding& ViewerInstance::GetShaderBinding()
{
return *m_shaderBinding;
}
inline void ViewerInstance::UpdateProjectionMatrix(const Matrix4f& projectionMatrix)
{
m_projectionMatrix = projectionMatrix;
if (!m_projectionMatrix.GetInverse(&m_invProjectionMatrix))
NazaraError("failed to inverse projection matrix");
m_dataInvalided = true;
}
inline void ViewerInstance::UpdateProjectionMatrix(const Matrix4f& projectionMatrix, const Matrix4f& invProjectionMatrix)
{
m_projectionMatrix = projectionMatrix;
m_invProjectionMatrix = invProjectionMatrix;
m_dataInvalided = true;
}
inline void ViewerInstance::UpdateProjViewMatrices(const Matrix4f& projectionMatrix, const Matrix4f& viewMatrix)
@@ -30,6 +49,12 @@ namespace Nz
m_viewMatrix = viewMatrix;
if (!m_viewMatrix.GetInverseAffine(&m_invViewMatrix))
NazaraError("failed to inverse view matrix");
m_viewProjMatrix = m_projectionMatrix * m_viewMatrix;
if (!m_viewProjMatrix.GetInverse(&m_invViewProjMatrix))
NazaraError("failed to inverse view proj matrix");
m_dataInvalided = true;
}
inline void ViewerInstance::UpdateProjViewMatrices(const Matrix4f& projectionMatrix, const Matrix4f& invProjectionMatrix, const Matrix4f& viewMatrix, const Matrix4f& invViewMatrix)
@@ -41,6 +66,8 @@ namespace Nz
m_viewProjMatrix = m_viewMatrix * m_projectionMatrix;
m_invViewProjMatrix = m_invProjectionMatrix * m_invViewMatrix;
m_dataInvalided = true;
}
inline void ViewerInstance::UpdateProjViewMatrices(const Matrix4f& projectionMatrix, const Matrix4f& invProjectionMatrix, const Matrix4f& viewMatrix, const Matrix4f& invViewMatrix, const Matrix4f& viewProjMatrix, const Matrix4f& invViewProjMatrix)
@@ -52,11 +79,15 @@ namespace Nz
m_viewProjMatrix = viewProjMatrix;
m_invViewProjMatrix = invViewProjMatrix;
m_dataInvalided = true;
}
inline void ViewerInstance::UpdateTargetSize(const Vector2f& targetSize)
{
m_targetSize = targetSize;
m_dataInvalided = true;
}
inline void ViewerInstance::UpdateViewMatrix(const Matrix4f& viewMatrix)
@@ -67,6 +98,8 @@ namespace Nz
m_viewProjMatrix = m_viewMatrix * m_projectionMatrix;
m_invViewProjMatrix = m_invProjectionMatrix * m_invViewMatrix;
m_dataInvalided = true;
}
inline void ViewerInstance::UpdateViewMatrix(const Matrix4f& viewMatrix, const Matrix4f& invViewMatrix)
@@ -76,6 +109,8 @@ namespace Nz
m_viewProjMatrix = m_viewMatrix * m_projectionMatrix;
m_invViewProjMatrix = m_invProjectionMatrix * m_invViewMatrix;
m_dataInvalided = true;
}
}

View File

@@ -20,13 +20,13 @@ namespace Nz
class MaterialSettings;
class UploadPool;
class NAZARA_GRAPHICS_API ModelInstance
class NAZARA_GRAPHICS_API WorldInstance
{
public:
ModelInstance(const std::shared_ptr<const MaterialSettings>& settings);
ModelInstance(const ModelInstance&) = delete;
ModelInstance(ModelInstance&&) noexcept = default;
~ModelInstance() = default;
WorldInstance();
WorldInstance(const WorldInstance&) = delete;
WorldInstance(WorldInstance&&) noexcept = default;
~WorldInstance() = default;
inline std::shared_ptr<AbstractBuffer>& GetInstanceBuffer();
inline const std::shared_ptr<AbstractBuffer>& GetInstanceBuffer() const;
@@ -36,8 +36,8 @@ namespace Nz
inline void UpdateWorldMatrix(const Matrix4f& worldMatrix);
inline void UpdateWorldMatrix(const Matrix4f& worldMatrix, const Matrix4f& invWorldMatrix);
ModelInstance& operator=(const ModelInstance&) = delete;
ModelInstance& operator=(ModelInstance&&) noexcept = default;
WorldInstance& operator=(const WorldInstance&) = delete;
WorldInstance& operator=(WorldInstance&&) noexcept = default;
private:
std::shared_ptr<AbstractBuffer> m_instanceDataBuffer;
@@ -48,6 +48,6 @@ namespace Nz
};
}
#include <Nazara/Graphics/ModelInstance.inl>
#include <Nazara/Graphics/WorldInstance.inl>
#endif // NAZARA_MODELINSTANCE_HPP

View File

@@ -2,28 +2,28 @@
// 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/ModelInstance.hpp>
#include <Nazara/Graphics/WorldInstance.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Graphics/Debug.hpp>
namespace Nz
{
inline std::shared_ptr<AbstractBuffer>& ModelInstance::GetInstanceBuffer()
inline std::shared_ptr<AbstractBuffer>& WorldInstance::GetInstanceBuffer()
{
return m_instanceDataBuffer;
}
inline const std::shared_ptr<AbstractBuffer>& ModelInstance::GetInstanceBuffer() const
inline const std::shared_ptr<AbstractBuffer>& WorldInstance::GetInstanceBuffer() const
{
return m_instanceDataBuffer;
}
inline ShaderBinding& ModelInstance::GetShaderBinding()
inline ShaderBinding& WorldInstance::GetShaderBinding()
{
return *m_shaderBinding;
}
inline void ModelInstance::UpdateWorldMatrix(const Matrix4f& worldMatrix)
inline void WorldInstance::UpdateWorldMatrix(const Matrix4f& worldMatrix)
{
m_worldMatrix = worldMatrix;
if (!m_worldMatrix.GetInverseAffine(&m_invWorldMatrix))
@@ -32,7 +32,7 @@ namespace Nz
m_dataInvalided = true;
}
inline void ModelInstance::UpdateWorldMatrix(const Matrix4f& worldMatrix, const Matrix4f& invWorldMatrix)
inline void WorldInstance::UpdateWorldMatrix(const Matrix4f& worldMatrix, const Matrix4f& invWorldMatrix)
{
m_worldMatrix = worldMatrix;
m_invWorldMatrix = invWorldMatrix;