Proof of concept
This commit is contained in:
parent
58485cfa79
commit
e84ec8e4ac
|
|
@ -19,6 +19,7 @@ namespace Nz
|
|||
class CommandBufferBuilder;
|
||||
class RenderElement;
|
||||
class RenderFrame;
|
||||
class ViewerInstance;
|
||||
struct ElementRendererData;
|
||||
|
||||
class NAZARA_GRAPHICS_API ElementRenderer
|
||||
|
|
@ -28,8 +29,8 @@ namespace Nz
|
|||
virtual ~ElementRenderer();
|
||||
|
||||
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 Prepare(const ViewerInstance& viewerInstance, ElementRendererData& rendererData, RenderFrame& currentFrame, const Pointer<const RenderElement>* elements, std::size_t elementCount);
|
||||
virtual void Render(const ViewerInstance& viewerInstance, ElementRendererData& rendererData, CommandBufferBuilder& commandBuffer, const Pointer<const RenderElement>* elements, std::size_t elementCount) = 0;
|
||||
virtual void Reset(ElementRendererData& rendererData, RenderFrame& currentFrame);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ namespace Nz
|
|||
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(std::size_t passIndex) const;
|
||||
inline const std::shared_ptr<MaterialPass>& GetPass(std::size_t passIndex) const;
|
||||
|
||||
inline bool HasPass(std::size_t passIndex) const;
|
||||
|
||||
|
|
|
|||
|
|
@ -21,17 +21,23 @@ namespace Nz
|
|||
return AddPass(registry.GetPassIndex(passName), std::move(pass));
|
||||
}
|
||||
|
||||
inline MaterialPass* Material::GetPass(std::size_t passIndex) const
|
||||
inline const std::shared_ptr<MaterialPass>& Material::GetPass(std::size_t passIndex) const
|
||||
{
|
||||
if (passIndex >= m_passes.size())
|
||||
return nullptr;
|
||||
{
|
||||
static std::shared_ptr<MaterialPass> dummy;
|
||||
return dummy;
|
||||
}
|
||||
|
||||
return m_passes[passIndex].get();
|
||||
return m_passes[passIndex];
|
||||
}
|
||||
|
||||
inline bool Material::HasPass(std::size_t passIndex) const
|
||||
{
|
||||
return GetPass(passIndex) != nullptr;
|
||||
if (passIndex >= m_passes.size())
|
||||
return false;
|
||||
|
||||
return m_passes[passIndex] != nullptr;
|
||||
}
|
||||
|
||||
inline void Material::RemovePass(std::size_t passIndex)
|
||||
|
|
|
|||
|
|
@ -52,6 +52,8 @@ namespace Nz
|
|||
|
||||
inline void EnsurePipelineUpdate() const;
|
||||
|
||||
void FillShaderBinding(std::vector<ShaderBinding::Binding>& bindings) const;
|
||||
|
||||
inline RendererComparison GetDepthCompareFunc() const;
|
||||
inline BlendEquation GetBlendAlphaModeEquation() const;
|
||||
inline BlendEquation GetBlendColorModeEquation() const;
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ namespace Nz
|
|||
inline const Builder& GetBuilderData() const;
|
||||
inline const std::vector<Option>& GetOptions() const;
|
||||
inline std::size_t GetOptionIndex(const std::string_view& name) const;
|
||||
inline std::size_t GetPredefinedBinding(PredefinedShaderBinding shaderBinding) const;
|
||||
inline const std::shared_ptr<RenderPipelineLayout>& GetRenderPipelineLayout() const;
|
||||
inline const std::shared_ptr<UberShader>& GetShader(ShaderStageType stage) const;
|
||||
inline const std::vector<std::shared_ptr<UberShader>>& GetShaders() const;
|
||||
|
|
@ -60,6 +61,8 @@ namespace Nz
|
|||
|
||||
struct Builder
|
||||
{
|
||||
inline Builder();
|
||||
|
||||
std::vector<std::shared_ptr<UberShader>> shaders;
|
||||
std::vector<Option> options;
|
||||
std::vector<Texture> textures;
|
||||
|
|
|
|||
|
|
@ -73,6 +73,11 @@ namespace Nz
|
|||
return InvalidIndex;
|
||||
}
|
||||
|
||||
inline std::size_t MaterialSettings::GetPredefinedBinding(PredefinedShaderBinding shaderBinding) const
|
||||
{
|
||||
return m_data.predefinedBindings[UnderlyingCast(shaderBinding)];
|
||||
}
|
||||
|
||||
inline const std::shared_ptr<RenderPipelineLayout>& MaterialSettings::GetRenderPipelineLayout() const
|
||||
{
|
||||
return m_pipelineLayout;
|
||||
|
|
@ -190,6 +195,11 @@ namespace Nz
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
inline MaterialSettings::Builder::Builder()
|
||||
{
|
||||
predefinedBindings.fill(InvalidIndex);
|
||||
}
|
||||
}
|
||||
|
||||
#include <Nazara/Graphics/DebugOff.hpp>
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ namespace Nz
|
|||
class RenderSpriteChain : public RenderElement
|
||||
{
|
||||
public:
|
||||
inline RenderSpriteChain(int renderLayer, std::shared_ptr<MaterialPass> materialPass, std::shared_ptr<RenderPipeline> renderPipeline, const ViewerInstance& viewerInstance, const WorldInstance& worldInstance, std::shared_ptr<VertexDeclaration> vertexDeclaration, std::shared_ptr<Texture> textureOverlay, std::size_t spriteCount, const void* spriteData);
|
||||
inline RenderSpriteChain(int renderLayer, std::shared_ptr<MaterialPass> materialPass, std::shared_ptr<RenderPipeline> renderPipeline, const WorldInstance& worldInstance, std::shared_ptr<VertexDeclaration> vertexDeclaration, std::shared_ptr<Texture> textureOverlay, std::size_t spriteCount, const void* spriteData);
|
||||
~RenderSpriteChain() = default;
|
||||
|
||||
inline UInt64 ComputeSortingScore(const Frustumf& frustum, const RenderQueueRegistry& registry) const override;
|
||||
|
|
@ -36,7 +36,6 @@ namespace Nz
|
|||
inline const void* GetSpriteData() const;
|
||||
inline const Texture* GetTextureOverlay() const;
|
||||
inline const VertexDeclaration* GetVertexDeclaration() const;
|
||||
inline const ViewerInstance& GetViewerInstance() const;
|
||||
inline const WorldInstance& GetWorldInstance() const;
|
||||
|
||||
inline void Register(RenderQueueRegistry& registry) const override;
|
||||
|
|
@ -48,7 +47,6 @@ namespace Nz
|
|||
std::shared_ptr<Texture> m_textureOverlay;
|
||||
std::size_t m_spriteCount;
|
||||
const void* m_spriteData;
|
||||
const ViewerInstance& m_viewerInstance;
|
||||
const WorldInstance& m_worldInstance;
|
||||
int m_renderLayer;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
namespace Nz
|
||||
{
|
||||
inline RenderSpriteChain::RenderSpriteChain(int renderLayer, std::shared_ptr<MaterialPass> materialPass, std::shared_ptr<RenderPipeline> renderPipeline, const ViewerInstance& viewerInstance, const WorldInstance& worldInstance, std::shared_ptr<VertexDeclaration> vertexDeclaration, std::shared_ptr<Texture> textureOverlay, std::size_t spriteCount, const void* spriteData) :
|
||||
inline RenderSpriteChain::RenderSpriteChain(int renderLayer, std::shared_ptr<MaterialPass> materialPass, std::shared_ptr<RenderPipeline> renderPipeline, const WorldInstance& worldInstance, std::shared_ptr<VertexDeclaration> vertexDeclaration, std::shared_ptr<Texture> textureOverlay, std::size_t spriteCount, const void* spriteData) :
|
||||
RenderElement(BasicRenderElement::SpriteChain),
|
||||
m_materialPass(std::move(materialPass)),
|
||||
m_renderPipeline(std::move(renderPipeline)),
|
||||
|
|
@ -16,7 +16,6 @@ namespace Nz
|
|||
m_textureOverlay(std::move(textureOverlay)),
|
||||
m_spriteCount(spriteCount),
|
||||
m_spriteData(spriteData),
|
||||
m_viewerInstance(viewerInstance),
|
||||
m_worldInstance(worldInstance),
|
||||
m_renderLayer(renderLayer)
|
||||
{
|
||||
|
|
@ -96,11 +95,6 @@ namespace Nz
|
|||
return m_vertexDeclaration.get();
|
||||
}
|
||||
|
||||
inline const ViewerInstance& RenderSpriteChain::GetViewerInstance() const
|
||||
{
|
||||
return m_viewerInstance;
|
||||
}
|
||||
|
||||
inline const WorldInstance& RenderSpriteChain::GetWorldInstance() const
|
||||
{
|
||||
return m_worldInstance;
|
||||
|
|
|
|||
|
|
@ -17,33 +17,33 @@
|
|||
namespace Nz
|
||||
{
|
||||
class AbstractBuffer;
|
||||
class MaterialPass;
|
||||
class RenderPipeline;
|
||||
class ShaderBinding;
|
||||
|
||||
class RenderSubmesh : public RenderElement
|
||||
{
|
||||
public:
|
||||
inline RenderSubmesh(int renderLayer, std::shared_ptr<RenderPipeline> renderPipeline, std::size_t indexCount, std::shared_ptr<AbstractBuffer> indexBuffer, std::shared_ptr<AbstractBuffer> vertexBuffer, const WorldInstance& worldInstance, const ShaderBinding& materialBinding, const MaterialPassFlags& matFlags);
|
||||
inline RenderSubmesh(int renderLayer, std::shared_ptr<MaterialPass> materialPass, std::shared_ptr<RenderPipeline> renderPipeline, const WorldInstance& worldInstance, std::size_t indexCount, std::shared_ptr<AbstractBuffer> indexBuffer, std::shared_ptr<AbstractBuffer> vertexBuffer);
|
||||
~RenderSubmesh() = default;
|
||||
|
||||
inline UInt64 ComputeSortingScore(const Nz::Frustumf& frustum, const RenderQueueRegistry& registry) const override;
|
||||
inline UInt64 ComputeSortingScore(const Frustumf& frustum, const RenderQueueRegistry& registry) const override;
|
||||
|
||||
inline const AbstractBuffer* GetIndexBuffer() const;
|
||||
inline std::size_t GetIndexCount() const;
|
||||
inline const MaterialPass& GetMaterialPass() const;
|
||||
inline const RenderPipeline* GetRenderPipeline() const;
|
||||
inline const ShaderBinding& GetInstanceBinding() const;
|
||||
inline const ShaderBinding& GetMaterialBinding() const;
|
||||
inline const AbstractBuffer* GetVertexBuffer() const;
|
||||
inline const WorldInstance& GetWorldInstance() const;
|
||||
|
||||
inline void Register(RenderQueueRegistry& registry) const override;
|
||||
|
||||
private:
|
||||
std::shared_ptr<AbstractBuffer> m_indexBuffer;
|
||||
std::shared_ptr<AbstractBuffer> m_vertexBuffer;
|
||||
std::shared_ptr<MaterialPass> m_materialPass;
|
||||
std::shared_ptr<RenderPipeline> m_renderPipeline;
|
||||
std::size_t m_indexCount;
|
||||
MaterialPassFlags m_matFlags;
|
||||
const ShaderBinding& m_materialBinding;
|
||||
const WorldInstance& m_worldInstance;
|
||||
int m_renderLayer;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -4,31 +4,31 @@
|
|||
|
||||
#include <Nazara/Graphics/RenderSubmesh.hpp>
|
||||
#include <Nazara/Graphics/Algorithm.hpp>
|
||||
#include <Nazara/Graphics/MaterialPass.hpp>
|
||||
#include <Nazara/Graphics/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
inline RenderSubmesh::RenderSubmesh(int renderLayer, std::shared_ptr<RenderPipeline> renderPipeline, std::size_t indexCount, std::shared_ptr<AbstractBuffer> indexBuffer, std::shared_ptr<AbstractBuffer> vertexBuffer, const WorldInstance& worldInstance, const ShaderBinding& materialBinding, const MaterialPassFlags& matFlags) :
|
||||
inline RenderSubmesh::RenderSubmesh(int renderLayer, std::shared_ptr<MaterialPass> materialPass, std::shared_ptr<RenderPipeline> renderPipeline, const WorldInstance& worldInstance, std::size_t indexCount, std::shared_ptr<AbstractBuffer> indexBuffer, std::shared_ptr<AbstractBuffer> vertexBuffer) :
|
||||
RenderElement(BasicRenderElement::Submesh),
|
||||
m_indexBuffer(std::move(indexBuffer)),
|
||||
m_vertexBuffer(std::move(vertexBuffer)),
|
||||
m_materialPass(std::move(materialPass)),
|
||||
m_renderPipeline(std::move(renderPipeline)),
|
||||
m_indexCount(indexCount),
|
||||
m_matFlags(matFlags),
|
||||
m_materialBinding(materialBinding),
|
||||
m_worldInstance(worldInstance),
|
||||
m_renderLayer(renderLayer)
|
||||
{
|
||||
}
|
||||
|
||||
inline UInt64 RenderSubmesh::ComputeSortingScore(const Nz::Frustumf& frustum, const RenderQueueRegistry& registry) const
|
||||
inline UInt64 RenderSubmesh::ComputeSortingScore(const Frustumf& frustum, const RenderQueueRegistry& registry) const
|
||||
{
|
||||
UInt64 layerIndex = registry.FetchLayerIndex(m_renderLayer);
|
||||
UInt64 elementType = GetElementType();
|
||||
UInt64 pipelineIndex = registry.FetchPipelineIndex(m_renderPipeline.get());
|
||||
UInt64 vertexBufferIndex = registry.FetchVertexBuffer(m_vertexBuffer.get());
|
||||
|
||||
if (m_matFlags.Test(MaterialPassFlag::Transparent))
|
||||
if (m_materialPass->IsFlagEnabled(MaterialPassFlag::Transparent))
|
||||
{
|
||||
UInt64 matFlags = 1;
|
||||
|
||||
|
|
@ -74,26 +74,26 @@ namespace Nz
|
|||
return m_indexCount;
|
||||
}
|
||||
|
||||
inline const MaterialPass& RenderSubmesh::GetMaterialPass() const
|
||||
{
|
||||
return *m_materialPass;
|
||||
}
|
||||
|
||||
inline const RenderPipeline* RenderSubmesh::GetRenderPipeline() const
|
||||
{
|
||||
return m_renderPipeline.get();
|
||||
}
|
||||
|
||||
inline const ShaderBinding& RenderSubmesh::GetInstanceBinding() const
|
||||
{
|
||||
return m_worldInstance.GetShaderBinding();
|
||||
}
|
||||
|
||||
inline const ShaderBinding& RenderSubmesh::GetMaterialBinding() const
|
||||
{
|
||||
return m_materialBinding;
|
||||
}
|
||||
|
||||
inline const AbstractBuffer* RenderSubmesh::GetVertexBuffer() const
|
||||
{
|
||||
return m_vertexBuffer.get();
|
||||
}
|
||||
|
||||
inline const WorldInstance& RenderSubmesh::GetWorldInstance() const
|
||||
{
|
||||
return m_worldInstance;
|
||||
}
|
||||
|
||||
inline void RenderSubmesh::Register(RenderQueueRegistry& registry) const
|
||||
{
|
||||
registry.RegisterLayer(m_renderLayer);
|
||||
|
|
|
|||
|
|
@ -30,8 +30,8 @@ namespace Nz
|
|||
~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 Prepare(const ViewerInstance& viewerInstance, ElementRendererData& rendererData, RenderFrame& currentFrame, const Pointer<const RenderElement>* elements, std::size_t elementCount);
|
||||
void Render(const ViewerInstance& viewerInstance, ElementRendererData& rendererData, CommandBufferBuilder& commandBuffer, const Pointer<const RenderElement>* elements, std::size_t elementCount) override;
|
||||
void Reset(ElementRendererData& rendererData, RenderFrame& currentFrame);
|
||||
|
||||
private:
|
||||
|
|
@ -52,6 +52,7 @@ namespace Nz
|
|||
std::size_t m_maxVertexBufferSize;
|
||||
std::size_t m_maxVertexCount;
|
||||
std::vector<BufferCopy> m_pendingCopies;
|
||||
std::vector<ShaderBinding::Binding> m_bindingCache;
|
||||
RenderDevice& m_device;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,10 @@
|
|||
|
||||
namespace Nz
|
||||
{
|
||||
class AbstractBuffer;
|
||||
class RenderPipeline;
|
||||
class ShaderBinding;
|
||||
|
||||
class NAZARA_GRAPHICS_API SubmeshRenderer : public ElementRenderer
|
||||
{
|
||||
public:
|
||||
|
|
@ -20,10 +24,27 @@ namespace Nz
|
|||
~SubmeshRenderer() = default;
|
||||
|
||||
std::unique_ptr<ElementRendererData> InstanciateData();
|
||||
void Render(ElementRendererData& rendererData, CommandBufferBuilder& commandBuffer, const Pointer<const RenderElement>* elements, std::size_t elementCount) override;
|
||||
void Prepare(const ViewerInstance& viewerInstance, ElementRendererData& rendererData, RenderFrame& currentFrame, const Pointer<const RenderElement>* elements, std::size_t elementCount);
|
||||
void Render(const ViewerInstance& viewerInstance, ElementRendererData& rendererData, CommandBufferBuilder& commandBuffer, const Pointer<const RenderElement>* elements, std::size_t elementCount) override;
|
||||
void Reset(ElementRendererData& rendererData, RenderFrame& currentFrame);
|
||||
|
||||
private:
|
||||
ShaderBindingPtr m_renderDataBinding;
|
||||
std::vector<ShaderBinding::Binding> m_bindingCache;
|
||||
};
|
||||
|
||||
struct SubmeshRendererData : public ElementRendererData
|
||||
{
|
||||
struct DrawCall
|
||||
{
|
||||
const AbstractBuffer* indexBuffer;
|
||||
const AbstractBuffer* vertexBuffer;
|
||||
const RenderPipeline* renderPipeline;
|
||||
const ShaderBinding* shaderBinding;
|
||||
std::size_t indexCount;
|
||||
};
|
||||
|
||||
std::vector<DrawCall> drawCalls;
|
||||
std::vector<ShaderBindingPtr> shaderBindings;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,8 +33,8 @@ namespace Nz
|
|||
inline const Matrix4f& GetProjectionMatrix() const;
|
||||
inline const Matrix4f& GetViewMatrix() const;
|
||||
inline const Matrix4f& GetViewProjMatrix() const;
|
||||
inline std::shared_ptr<AbstractBuffer>& GetInstanceBuffer();
|
||||
inline const std::shared_ptr<AbstractBuffer>& GetInstanceBuffer() const;
|
||||
inline std::shared_ptr<AbstractBuffer>& GetViewerBuffer();
|
||||
inline const std::shared_ptr<AbstractBuffer>& GetViewerBuffer() const;
|
||||
|
||||
void UpdateBuffers(UploadPool& uploadPool, CommandBufferBuilder& builder);
|
||||
inline void UpdateProjectionMatrix(const Matrix4f& projectionMatrix);
|
||||
|
|
|
|||
|
|
@ -38,12 +38,12 @@ namespace Nz
|
|||
return m_viewProjMatrix;
|
||||
}
|
||||
|
||||
inline std::shared_ptr<AbstractBuffer>& ViewerInstance::GetInstanceBuffer()
|
||||
inline std::shared_ptr<AbstractBuffer>& ViewerInstance::GetViewerBuffer()
|
||||
{
|
||||
return m_viewerDataBuffer;
|
||||
}
|
||||
|
||||
inline const std::shared_ptr<AbstractBuffer>& ViewerInstance::GetInstanceBuffer() const
|
||||
inline const std::shared_ptr<AbstractBuffer>& ViewerInstance::GetViewerBuffer() const
|
||||
{
|
||||
return m_viewerDataBuffer;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -162,6 +162,10 @@ namespace Nz
|
|||
settings.sharedUniformBlocks.push_back(PredefinedInstanceData::GetUniformBlock(4, ShaderStageType::Vertex));
|
||||
settings.sharedUniformBlocks.push_back(PredefinedViewerData::GetUniformBlock(5, ShaderStageType_All));
|
||||
|
||||
settings.predefinedBindings[UnderlyingCast(PredefinedShaderBinding::InstanceDataUbo)] = 4;
|
||||
settings.predefinedBindings[UnderlyingCast(PredefinedShaderBinding::OverlayTexture)] = 3;
|
||||
settings.predefinedBindings[UnderlyingCast(PredefinedShaderBinding::ViewerDataUbo)] = 5;
|
||||
|
||||
settings.shaders = std::move(uberShaders);
|
||||
|
||||
for (std::shared_ptr<UberShader> uberShader : settings.shaders)
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ namespace Nz
|
|||
{
|
||||
ElementRenderer::~ElementRenderer() = default;
|
||||
|
||||
void ElementRenderer::Prepare(ElementRendererData& /*rendererData*/, RenderFrame& /*currentFrame*/, const Pointer<const RenderElement>* /*elements*/, std::size_t /*elementCount*/)
|
||||
void ElementRenderer::Prepare(const ViewerInstance& /*viewerInstance*/, ElementRendererData& /*rendererData*/, RenderFrame& /*currentFrame*/, const Pointer<const RenderElement>* /*elements*/, std::size_t /*elementCount*/)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -61,21 +61,21 @@ namespace Nz
|
|||
{
|
||||
if (newMaterial)
|
||||
{
|
||||
if (MaterialPass* pass = newMaterial->GetPass(m_depthPassIndex))
|
||||
RegisterMaterialPass(pass);
|
||||
if (const auto& pass = newMaterial->GetPass(m_depthPassIndex))
|
||||
RegisterMaterialPass(pass.get());
|
||||
|
||||
if (MaterialPass* pass = newMaterial->GetPass(m_forwardPassIndex))
|
||||
RegisterMaterialPass(pass);
|
||||
if (const auto& pass = newMaterial->GetPass(m_forwardPassIndex))
|
||||
RegisterMaterialPass(pass.get());
|
||||
}
|
||||
|
||||
const auto& prevMaterial = instancedRenderable->GetMaterial(materialIndex);
|
||||
if (prevMaterial)
|
||||
{
|
||||
if (MaterialPass* pass = prevMaterial->GetPass(m_depthPassIndex))
|
||||
UnregisterMaterialPass(pass);
|
||||
if (const auto& pass = prevMaterial->GetPass(m_depthPassIndex))
|
||||
UnregisterMaterialPass(pass.get());
|
||||
|
||||
if (MaterialPass* pass = prevMaterial->GetPass(m_forwardPassIndex))
|
||||
UnregisterMaterialPass(pass);
|
||||
if (const auto& pass = prevMaterial->GetPass(m_forwardPassIndex))
|
||||
UnregisterMaterialPass(pass.get());
|
||||
}
|
||||
|
||||
for (auto&& [viewer, viewerData] : m_viewers)
|
||||
|
|
@ -90,11 +90,11 @@ namespace Nz
|
|||
{
|
||||
if (Material* mat = instancedRenderable->GetMaterial(i).get())
|
||||
{
|
||||
if (MaterialPass* pass = mat->GetPass(m_depthPassIndex))
|
||||
RegisterMaterialPass(pass);
|
||||
if (const auto& pass = mat->GetPass(m_depthPassIndex))
|
||||
RegisterMaterialPass(pass.get());
|
||||
|
||||
if (MaterialPass* pass = mat->GetPass(m_forwardPassIndex))
|
||||
RegisterMaterialPass(pass);
|
||||
if (const auto& pass = mat->GetPass(m_forwardPassIndex))
|
||||
RegisterMaterialPass(pass.get());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -283,20 +283,22 @@ namespace Nz
|
|||
}
|
||||
}
|
||||
|
||||
for (auto&& [_, viewerData] : m_viewers)
|
||||
for (auto&& [viewer, viewerData] : m_viewers)
|
||||
{
|
||||
auto& rendererData = viewerData.elementRendererData;
|
||||
|
||||
const auto& viewerInstance = viewer->GetViewerInstance();
|
||||
|
||||
ProcessRenderQueue(viewerData.depthPrepassRenderQueue, [&](std::size_t elementType, const Pointer<const RenderElement>* elements, std::size_t elementCount)
|
||||
{
|
||||
ElementRenderer& elementRenderer = *m_elementRenderers[elementType];
|
||||
elementRenderer.Prepare(*rendererData[elementType], renderFrame, elements, elementCount);
|
||||
elementRenderer.Prepare(viewerInstance, *rendererData[elementType], renderFrame, elements, elementCount);
|
||||
});
|
||||
|
||||
ProcessRenderQueue(viewerData.forwardRenderQueue, [&](std::size_t elementType, const Pointer<const RenderElement>* elements, std::size_t elementCount)
|
||||
{
|
||||
ElementRenderer& elementRenderer = *m_elementRenderers[elementType];
|
||||
elementRenderer.Prepare(*rendererData[elementType], renderFrame, elements, elementCount);
|
||||
elementRenderer.Prepare(viewerInstance, *rendererData[elementType], renderFrame, elements, elementCount);
|
||||
});
|
||||
|
||||
viewerData.rebuildForwardPass = true;
|
||||
|
|
@ -386,17 +388,17 @@ namespace Nz
|
|||
else
|
||||
{
|
||||
m_removedWorldInstances.insert(worldInstance);
|
||||
m_renderables.erase(instanceIt);;
|
||||
m_renderables.erase(instanceIt);
|
||||
}
|
||||
|
||||
std::size_t matCount = instancedRenderable->GetMaterialCount();
|
||||
for (std::size_t i = 0; i < matCount; ++i)
|
||||
{
|
||||
if (MaterialPass* pass = instancedRenderable->GetMaterial(i)->GetPass(m_depthPassIndex))
|
||||
UnregisterMaterialPass(pass);
|
||||
if (const auto& pass = instancedRenderable->GetMaterial(i)->GetPass(m_depthPassIndex))
|
||||
UnregisterMaterialPass(pass.get());
|
||||
|
||||
if (MaterialPass* pass = instancedRenderable->GetMaterial(i)->GetPass(m_forwardPassIndex))
|
||||
UnregisterMaterialPass(pass);
|
||||
if (const auto& pass = instancedRenderable->GetMaterial(i)->GetPass(m_forwardPassIndex))
|
||||
UnregisterMaterialPass(pass.get());
|
||||
}
|
||||
|
||||
for (auto&& [viewer, viewerData] : m_viewers)
|
||||
|
|
@ -452,12 +454,12 @@ namespace Nz
|
|||
builder.SetScissor(viewport);
|
||||
builder.SetViewport(viewport);
|
||||
|
||||
builder.BindShaderBinding(Graphics::ViewerBindingSet, viewer->GetViewerInstance().GetShaderBinding());
|
||||
const auto& viewerInstance = viewer->GetViewerInstance();
|
||||
|
||||
ProcessRenderQueue(viewerData.depthPrepassRenderQueue, [&](std::size_t elementType, const Pointer<const RenderElement>* elements, std::size_t elementCount)
|
||||
{
|
||||
ElementRenderer& elementRenderer = *m_elementRenderers[elementType];
|
||||
elementRenderer.Render(*viewerData.elementRendererData[elementType], builder, elements, elementCount);
|
||||
elementRenderer.Render(viewerInstance, *viewerData.elementRendererData[elementType], builder, elements, elementCount);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -484,12 +486,12 @@ namespace Nz
|
|||
builder.SetScissor(viewport);
|
||||
builder.SetViewport(viewport);
|
||||
|
||||
builder.BindShaderBinding(Graphics::ViewerBindingSet, viewer->GetViewerInstance().GetShaderBinding());
|
||||
|
||||
const auto& viewerInstance = viewer->GetViewerInstance();
|
||||
|
||||
ProcessRenderQueue(viewerData.forwardRenderQueue, [&](std::size_t elementType, const Pointer<const RenderElement>* elements, std::size_t elementCount)
|
||||
{
|
||||
ElementRenderer& elementRenderer = *m_elementRenderers[elementType];
|
||||
elementRenderer.Render(*viewerData.elementRendererData[elementType], builder, elements, elementCount);
|
||||
elementRenderer.Render(viewerInstance , *viewerData.elementRendererData[elementType], builder, elements, elementCount);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,6 +61,52 @@ namespace Nz
|
|||
}
|
||||
}
|
||||
|
||||
void MaterialPass::FillShaderBinding(std::vector<ShaderBinding::Binding>& bindings) const
|
||||
{
|
||||
const auto& textureSettings = m_settings->GetTextures();
|
||||
const auto& uboSettings = m_settings->GetUniformBlocks();
|
||||
|
||||
// Textures
|
||||
for (std::size_t i = 0; i < m_textures.size(); ++i)
|
||||
{
|
||||
const auto& textureSetting = textureSettings[i];
|
||||
const auto& textureSlot = m_textures[i];
|
||||
|
||||
if (!textureSlot.sampler)
|
||||
{
|
||||
TextureSamplerCache& samplerCache = Graphics::Instance()->GetSamplerCache();
|
||||
textureSlot.sampler = samplerCache.Get(textureSlot.samplerInfo);
|
||||
}
|
||||
|
||||
//TODO: Use "missing" texture
|
||||
if (textureSlot.texture)
|
||||
{
|
||||
bindings.push_back({
|
||||
textureSetting.bindingIndex,
|
||||
ShaderBinding::TextureBinding {
|
||||
textureSlot.texture.get(), textureSlot.sampler.get()
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Shared UBO (TODO)
|
||||
|
||||
// Owned UBO
|
||||
for (std::size_t i = 0; i < m_uniformBuffers.size(); ++i)
|
||||
{
|
||||
const auto& uboSetting = uboSettings[i];
|
||||
const auto& uboSlot = m_uniformBuffers[i];
|
||||
|
||||
bindings.push_back({
|
||||
uboSetting.bindingIndex,
|
||||
ShaderBinding::UniformBufferBinding {
|
||||
uboSlot.buffer.get(), 0, uboSlot.buffer->GetSize()
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
bool MaterialPass::Update(RenderFrame& renderFrame, CommandBufferBuilder& builder)
|
||||
{
|
||||
UploadPool& uploadPool = renderFrame.GetUploadPool();
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ namespace Nz
|
|||
{
|
||||
const auto& submeshData = m_submeshes[i];
|
||||
|
||||
MaterialPass* materialPass = submeshData.material->GetPass(passIndex);
|
||||
const auto& materialPass = submeshData.material->GetPass(passIndex);
|
||||
if (!materialPass)
|
||||
continue;
|
||||
|
||||
|
|
@ -45,7 +45,7 @@ namespace Nz
|
|||
const auto& vertexBuffer = m_graphicalMesh->GetVertexBuffer(i);
|
||||
const auto& renderPipeline = materialPass->GetPipeline()->GetRenderPipeline(submeshData.vertexBufferData);
|
||||
|
||||
elements.emplace_back(std::make_unique<RenderSubmesh>(0, renderPipeline, m_graphicalMesh->GetIndexCount(i), indexBuffer, vertexBuffer, worldInstance, materialPass->GetShaderBinding(), materialPass->GetFlags()));
|
||||
elements.emplace_back(std::make_unique<RenderSubmesh>(0, materialPass, renderPipeline, worldInstance, m_graphicalMesh->GetIndexCount(i), indexBuffer, vertexBuffer));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -40,12 +40,12 @@ struct ViewerData
|
|||
|
||||
external
|
||||
{
|
||||
[set(0), binding(0)] viewerData: uniform<ViewerData>,
|
||||
[set(1), binding(0)] instanceData: uniform<InstanceData>,
|
||||
[set(2), binding(0)] TextureOverlay: sampler2D<f32>,
|
||||
[set(3), binding(0)] settings: uniform<BasicSettings>,
|
||||
[set(3), binding(2)] MaterialAlphaMap: sampler2D<f32>,
|
||||
[set(3), binding(1)] MaterialDiffuseMap: sampler2D<f32>
|
||||
[binding(0)] settings: uniform<BasicSettings>,
|
||||
[binding(1)] MaterialDiffuseMap: sampler2D<f32>,
|
||||
[binding(2)] MaterialAlphaMap: sampler2D<f32>,
|
||||
[binding(3)] TextureOverlay: sampler2D<f32>,
|
||||
[binding(4)] instanceData: uniform<InstanceData>,
|
||||
[binding(5)] viewerData: uniform<ViewerData>,
|
||||
}
|
||||
|
||||
// Fragment stage
|
||||
|
|
|
|||
|
|
@ -34,12 +34,12 @@ struct ViewerData
|
|||
|
||||
external
|
||||
{
|
||||
[set(0), binding(0)] viewerData: uniform<ViewerData>,
|
||||
[set(1), binding(0)] instanceData: uniform<InstanceData>,
|
||||
[set(2), binding(0)] TextureOverlay: sampler2D<f32>,
|
||||
[set(3), binding(0)] settings: uniform<BasicSettings>,
|
||||
[set(3), binding(2)] MaterialAlphaMap: sampler2D<f32>,
|
||||
[set(3), binding(1)] MaterialDiffuseMap: sampler2D<f32>
|
||||
[binding(0)] settings: uniform<BasicSettings>,
|
||||
[binding(1)] MaterialDiffuseMap: sampler2D<f32>,
|
||||
[binding(2)] MaterialAlphaMap: sampler2D<f32>,
|
||||
[binding(3)] TextureOverlay: sampler2D<f32>,
|
||||
[binding(4)] instanceData: uniform<InstanceData>,
|
||||
[binding(5)] viewerData: uniform<ViewerData>,
|
||||
}
|
||||
|
||||
// Fragment stage
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ namespace Nz
|
|||
|
||||
void Sprite::BuildElement(std::size_t passIndex, const WorldInstance& worldInstance, std::vector<std::unique_ptr<RenderElement>>& elements) const
|
||||
{
|
||||
MaterialPass* materialPass = m_material->GetPass(passIndex);
|
||||
const auto& materialPass = m_material->GetPass(passIndex);
|
||||
if (!materialPass)
|
||||
return;
|
||||
|
||||
|
|
@ -42,7 +42,7 @@ namespace Nz
|
|||
|
||||
const auto& whiteTexture = Graphics::Instance()->GetDefaultTextures().whiteTexture2d;
|
||||
|
||||
elements.emplace_back(std::make_unique<RenderSpriteChain>(0, renderPipeline, vertexDeclaration, whiteTexture, 1, m_vertices.data(), materialPass->GetShaderBinding(), worldInstance, materialPass->GetFlags()));
|
||||
elements.emplace_back(std::make_unique<RenderSpriteChain>(0, materialPass, renderPipeline, worldInstance, vertexDeclaration, whiteTexture, 1, m_vertices.data()));
|
||||
}
|
||||
|
||||
inline const Color& Sprite::GetColor() const
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
#include <Nazara/Graphics/SpriteChainRenderer.hpp>
|
||||
#include <Nazara/Graphics/Graphics.hpp>
|
||||
#include <Nazara/Graphics/RenderSpriteChain.hpp>
|
||||
#include <Nazara/Graphics/ViewerInstance.hpp>
|
||||
#include <Nazara/Renderer/CommandBufferBuilder.hpp>
|
||||
#include <Nazara/Renderer/RenderFrame.hpp>
|
||||
#include <Nazara/Renderer/UploadPool.hpp>
|
||||
|
|
@ -52,7 +53,7 @@ namespace Nz
|
|||
return std::make_unique<SpriteChainRendererData>();
|
||||
}
|
||||
|
||||
void SpriteChainRenderer::Prepare(ElementRendererData& rendererData, RenderFrame& currentFrame, const Pointer<const RenderElement>* elements, std::size_t elementCount)
|
||||
void SpriteChainRenderer::Prepare(const ViewerInstance& viewerInstance, ElementRendererData& rendererData, RenderFrame& currentFrame, const Pointer<const RenderElement>* elements, std::size_t elementCount)
|
||||
{
|
||||
Graphics* graphics = Graphics::Instance();
|
||||
|
||||
|
|
@ -67,7 +68,6 @@ namespace Nz
|
|||
const RenderPipeline* currentPipeline = nullptr;
|
||||
const ShaderBinding* currentShaderBinding = nullptr;
|
||||
const Texture* currentTextureOverlay = nullptr;
|
||||
const ViewerInstance* currentViewerInstance = nullptr;
|
||||
const WorldInstance* currentWorldInstance = nullptr;
|
||||
|
||||
auto FlushDrawCall = [&]()
|
||||
|
|
@ -128,17 +128,11 @@ namespace Nz
|
|||
currentPipeline = &spriteChain.GetRenderPipeline();
|
||||
}
|
||||
|
||||
if (currentViewerInstance != &spriteChain.GetViewerInstance())
|
||||
{
|
||||
FlushDrawCall();
|
||||
currentViewerInstance = &spriteChain.GetViewerInstance();
|
||||
}
|
||||
|
||||
if (currentWorldInstance != &spriteChain.GetWorldInstance())
|
||||
{
|
||||
// TODO: Flushing draw calls on instance binding means we can have e.g. 1000 sprites rendered using a draw call for each one
|
||||
// which is far from being efficient, using some bindless could help (or at least instancing?)
|
||||
FlushDrawCall();
|
||||
FlushDrawData();
|
||||
currentWorldInstance = &spriteChain.GetWorldInstance();
|
||||
}
|
||||
|
||||
|
|
@ -179,15 +173,48 @@ namespace Nz
|
|||
|
||||
if (!currentShaderBinding)
|
||||
{
|
||||
m_bindingCache.clear();
|
||||
|
||||
const MaterialPass& materialPass = spriteChain.GetMaterialPass();
|
||||
materialPass.FillShaderBinding(m_bindingCache);
|
||||
|
||||
// Predefined shader bindings
|
||||
const auto& matSettings = materialPass.GetSettings();
|
||||
if (std::size_t bindingIndex = matSettings->GetPredefinedBinding(PredefinedShaderBinding::InstanceDataUbo); bindingIndex != MaterialSettings::InvalidIndex)
|
||||
{
|
||||
const auto& instanceBuffer = currentWorldInstance->GetInstanceBuffer();
|
||||
|
||||
auto& bindingEntry = m_bindingCache.emplace_back();
|
||||
bindingEntry.bindingIndex = bindingIndex;
|
||||
bindingEntry.content = ShaderBinding::UniformBufferBinding{
|
||||
instanceBuffer.get(),
|
||||
0, instanceBuffer->GetSize()
|
||||
};
|
||||
}
|
||||
|
||||
if (std::size_t bindingIndex = matSettings->GetPredefinedBinding(PredefinedShaderBinding::ViewerDataUbo); bindingIndex != MaterialSettings::InvalidIndex)
|
||||
{
|
||||
const auto& viewerBuffer = viewerInstance.GetViewerBuffer();
|
||||
|
||||
auto& bindingEntry = m_bindingCache.emplace_back();
|
||||
bindingEntry.bindingIndex = bindingIndex;
|
||||
bindingEntry.content = ShaderBinding::UniformBufferBinding{
|
||||
viewerBuffer.get(),
|
||||
0, viewerBuffer->GetSize()
|
||||
};
|
||||
}
|
||||
|
||||
if (std::size_t bindingIndex = matSettings->GetPredefinedBinding(PredefinedShaderBinding::OverlayTexture); bindingIndex != MaterialSettings::InvalidIndex)
|
||||
{
|
||||
auto& bindingEntry = m_bindingCache.emplace_back();
|
||||
bindingEntry.bindingIndex = bindingIndex;
|
||||
bindingEntry.content = ShaderBinding::TextureBinding{
|
||||
currentTextureOverlay, defaultSampler.get()
|
||||
};
|
||||
}
|
||||
|
||||
ShaderBindingPtr drawDataBinding = currentPipeline->GetPipelineInfo().pipelineLayout->AllocateShaderBinding(0);
|
||||
drawDataBinding->Update({
|
||||
{
|
||||
0,
|
||||
ShaderBinding::TextureBinding {
|
||||
currentTextureOverlay, defaultSampler.get()
|
||||
}
|
||||
}
|
||||
});
|
||||
drawDataBinding->Update(m_bindingCache.data(), m_bindingCache.size());
|
||||
|
||||
currentShaderBinding = drawDataBinding.get();
|
||||
|
||||
|
|
@ -253,7 +280,7 @@ namespace Nz
|
|||
}
|
||||
}
|
||||
|
||||
void SpriteChainRenderer::Render(ElementRendererData& rendererData, CommandBufferBuilder& commandBuffer, const Pointer<const RenderElement>* elements, std::size_t /*elementCount*/)
|
||||
void SpriteChainRenderer::Render(const ViewerInstance& viewerInstance, ElementRendererData& rendererData, CommandBufferBuilder& commandBuffer, const Pointer<const RenderElement>* elements, std::size_t /*elementCount*/)
|
||||
{
|
||||
auto& data = static_cast<SpriteChainRendererData&>(rendererData);
|
||||
|
||||
|
|
|
|||
|
|
@ -5,41 +5,48 @@
|
|||
#include <Nazara/Graphics/SubmeshRenderer.hpp>
|
||||
#include <Nazara/Graphics/Graphics.hpp>
|
||||
#include <Nazara/Graphics/RenderSubmesh.hpp>
|
||||
#include <Nazara/Graphics/ViewerInstance.hpp>
|
||||
#include <Nazara/Renderer/CommandBufferBuilder.hpp>
|
||||
#include <Nazara/Renderer/RenderFrame.hpp>
|
||||
#include <Nazara/Graphics/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
SubmeshRenderer::SubmeshRenderer()
|
||||
{
|
||||
Graphics* graphics = Graphics::Instance();
|
||||
const auto& whiteTexture = graphics->GetDefaultTextures().whiteTexture2d;
|
||||
const auto& defaultSampler = graphics->GetSamplerCache().Get({});
|
||||
|
||||
m_renderDataBinding = graphics->GetReferencePipelineLayout()->AllocateShaderBinding(Graphics::DrawDataBindingSet);
|
||||
m_renderDataBinding->Update({
|
||||
{
|
||||
0,
|
||||
ShaderBinding::TextureBinding {
|
||||
whiteTexture.get(), defaultSampler.get()
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
std::unique_ptr<ElementRendererData> SubmeshRenderer::InstanciateData()
|
||||
{
|
||||
return {};
|
||||
return std::make_unique<SubmeshRendererData>();
|
||||
}
|
||||
|
||||
void SubmeshRenderer::Render(ElementRendererData& /*rendererData*/, CommandBufferBuilder& commandBuffer, const Pointer<const RenderElement>* elements, std::size_t elementCount)
|
||||
void SubmeshRenderer::Prepare(const ViewerInstance& viewerInstance, ElementRendererData& rendererData, RenderFrame& /*currentFrame*/, const Pointer<const RenderElement>* elements, std::size_t elementCount)
|
||||
{
|
||||
Graphics* graphics = Graphics::Instance();
|
||||
|
||||
auto& data = static_cast<SubmeshRendererData&>(rendererData);
|
||||
|
||||
const AbstractBuffer* currentIndexBuffer = nullptr;
|
||||
const AbstractBuffer* currentVertexBuffer = nullptr;
|
||||
const RenderPipeline* currentPipeline = nullptr;
|
||||
const ShaderBinding* currentMaterialBinding = nullptr;
|
||||
const ShaderBinding* currentShaderBinding = nullptr;
|
||||
const WorldInstance* currentWorldInstance = nullptr;
|
||||
|
||||
commandBuffer.BindShaderBinding(Graphics::DrawDataBindingSet, *m_renderDataBinding);
|
||||
auto FlushDrawCall = [&]()
|
||||
{
|
||||
// Does nothing for now (but will serve once instancing is implemented)
|
||||
};
|
||||
|
||||
auto FlushDrawData = [&]()
|
||||
{
|
||||
FlushDrawCall();
|
||||
|
||||
currentShaderBinding = nullptr;
|
||||
};
|
||||
|
||||
const auto& whiteTexture = Graphics::Instance()->GetDefaultTextures().whiteTexture2d;
|
||||
const auto& defaultSampler = graphics->GetSamplerCache().Get({});
|
||||
|
||||
for (std::size_t i = 0; i < elementCount; ++i)
|
||||
{
|
||||
|
|
@ -48,34 +55,139 @@ namespace Nz
|
|||
|
||||
if (const RenderPipeline* pipeline = submesh.GetRenderPipeline(); currentPipeline != pipeline)
|
||||
{
|
||||
commandBuffer.BindPipeline(*pipeline);
|
||||
FlushDrawCall();
|
||||
currentPipeline = pipeline;
|
||||
}
|
||||
|
||||
if (const ShaderBinding* materialBinding = &submesh.GetMaterialBinding(); currentMaterialBinding != materialBinding)
|
||||
{
|
||||
commandBuffer.BindShaderBinding(Graphics::MaterialBindingSet, *materialBinding);
|
||||
currentMaterialBinding = materialBinding;
|
||||
}
|
||||
|
||||
if (const AbstractBuffer* indexBuffer = submesh.GetIndexBuffer(); currentIndexBuffer != indexBuffer)
|
||||
{
|
||||
commandBuffer.BindIndexBuffer(*indexBuffer);
|
||||
FlushDrawCall();
|
||||
currentIndexBuffer = indexBuffer;
|
||||
}
|
||||
|
||||
if (const AbstractBuffer* vertexBuffer = submesh.GetVertexBuffer(); currentVertexBuffer != vertexBuffer)
|
||||
{
|
||||
commandBuffer.BindVertexBuffer(0, *vertexBuffer);
|
||||
FlushDrawCall();
|
||||
currentVertexBuffer = vertexBuffer;
|
||||
}
|
||||
|
||||
commandBuffer.BindShaderBinding(Graphics::WorldBindingSet, submesh.GetInstanceBinding());
|
||||
if (currentWorldInstance != &submesh.GetWorldInstance())
|
||||
{
|
||||
// TODO: Flushing draw calls on instance binding means we can have e.g. 1000 sprites rendered using a draw call for each one
|
||||
// which is far from being efficient, using some bindless could help (or at least instancing?)
|
||||
FlushDrawData();
|
||||
currentWorldInstance = &submesh.GetWorldInstance();
|
||||
}
|
||||
|
||||
if (currentIndexBuffer)
|
||||
commandBuffer.DrawIndexed(submesh.GetIndexCount());
|
||||
else
|
||||
commandBuffer.Draw(submesh.GetIndexCount());
|
||||
if (!currentShaderBinding)
|
||||
{
|
||||
m_bindingCache.clear();
|
||||
|
||||
const MaterialPass& materialPass = submesh.GetMaterialPass();
|
||||
materialPass.FillShaderBinding(m_bindingCache);
|
||||
|
||||
// Predefined shader bindings
|
||||
const auto& matSettings = materialPass.GetSettings();
|
||||
if (std::size_t bindingIndex = matSettings->GetPredefinedBinding(PredefinedShaderBinding::InstanceDataUbo); bindingIndex != MaterialSettings::InvalidIndex)
|
||||
{
|
||||
const auto& instanceBuffer = currentWorldInstance->GetInstanceBuffer();
|
||||
|
||||
auto& bindingEntry = m_bindingCache.emplace_back();
|
||||
bindingEntry.bindingIndex = bindingIndex;
|
||||
bindingEntry.content = ShaderBinding::UniformBufferBinding{
|
||||
instanceBuffer.get(),
|
||||
0, instanceBuffer->GetSize()
|
||||
};
|
||||
}
|
||||
|
||||
if (std::size_t bindingIndex = matSettings->GetPredefinedBinding(PredefinedShaderBinding::ViewerDataUbo); bindingIndex != MaterialSettings::InvalidIndex)
|
||||
{
|
||||
const auto& viewerBuffer = viewerInstance.GetViewerBuffer();
|
||||
|
||||
auto& bindingEntry = m_bindingCache.emplace_back();
|
||||
bindingEntry.bindingIndex = bindingIndex;
|
||||
bindingEntry.content = ShaderBinding::UniformBufferBinding{
|
||||
viewerBuffer.get(),
|
||||
0, viewerBuffer->GetSize()
|
||||
};
|
||||
}
|
||||
|
||||
if (std::size_t bindingIndex = matSettings->GetPredefinedBinding(PredefinedShaderBinding::OverlayTexture); bindingIndex != MaterialSettings::InvalidIndex)
|
||||
{
|
||||
auto& bindingEntry = m_bindingCache.emplace_back();
|
||||
bindingEntry.bindingIndex = bindingIndex;
|
||||
bindingEntry.content = ShaderBinding::TextureBinding{
|
||||
whiteTexture.get(), defaultSampler.get()
|
||||
};
|
||||
}
|
||||
|
||||
ShaderBindingPtr drawDataBinding = currentPipeline->GetPipelineInfo().pipelineLayout->AllocateShaderBinding(0);
|
||||
drawDataBinding->Update(m_bindingCache.data(), m_bindingCache.size());
|
||||
|
||||
currentShaderBinding = drawDataBinding.get();
|
||||
|
||||
data.shaderBindings.emplace_back(std::move(drawDataBinding));
|
||||
}
|
||||
|
||||
auto& drawCall = data.drawCalls.emplace_back();
|
||||
drawCall.indexBuffer = currentIndexBuffer;
|
||||
drawCall.indexCount = submesh.GetIndexCount();
|
||||
drawCall.renderPipeline = currentPipeline;
|
||||
drawCall.shaderBinding = currentShaderBinding;
|
||||
drawCall.vertexBuffer = currentVertexBuffer;
|
||||
}
|
||||
}
|
||||
|
||||
void SubmeshRenderer::Render(const ViewerInstance& /*viewerInstance*/, ElementRendererData& rendererData, CommandBufferBuilder& commandBuffer, const Pointer<const RenderElement>* /*elements*/, std::size_t /*elementCount*/)
|
||||
{
|
||||
auto& data = static_cast<SubmeshRendererData&>(rendererData);
|
||||
|
||||
const AbstractBuffer* currentIndexBuffer = nullptr;
|
||||
const AbstractBuffer* currentVertexBuffer = nullptr;
|
||||
const RenderPipeline* currentPipeline = nullptr;
|
||||
const ShaderBinding* currentShaderBinding = nullptr;
|
||||
|
||||
for (const auto& drawData : data.drawCalls)
|
||||
{
|
||||
if (currentPipeline != drawData.renderPipeline)
|
||||
{
|
||||
commandBuffer.BindPipeline(*drawData.renderPipeline);
|
||||
currentPipeline = drawData.renderPipeline;
|
||||
}
|
||||
|
||||
if (currentShaderBinding != drawData.shaderBinding)
|
||||
{
|
||||
commandBuffer.BindShaderBinding(0, *drawData.shaderBinding);
|
||||
currentShaderBinding = drawData.shaderBinding;
|
||||
}
|
||||
|
||||
if (currentIndexBuffer != drawData.indexBuffer)
|
||||
{
|
||||
commandBuffer.BindIndexBuffer(*drawData.indexBuffer);
|
||||
currentIndexBuffer = drawData.indexBuffer;
|
||||
}
|
||||
|
||||
if (currentVertexBuffer != drawData.vertexBuffer)
|
||||
{
|
||||
commandBuffer.BindVertexBuffer(0, *drawData.vertexBuffer);
|
||||
currentVertexBuffer = drawData.vertexBuffer;
|
||||
}
|
||||
|
||||
if (currentIndexBuffer)
|
||||
commandBuffer.DrawIndexed(drawData.indexCount);
|
||||
else
|
||||
commandBuffer.Draw(drawData.indexCount);
|
||||
}
|
||||
}
|
||||
|
||||
void SubmeshRenderer::Reset(ElementRendererData& rendererData, RenderFrame& currentFrame)
|
||||
{
|
||||
auto& data = static_cast<SubmeshRendererData&>(rendererData);
|
||||
|
||||
for (auto& shaderBinding : data.shaderBindings)
|
||||
currentFrame.PushForRelease(std::move(shaderBinding));
|
||||
data.shaderBindings.clear();
|
||||
|
||||
data.drawCalls.clear();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ namespace Nz
|
|||
|
||||
void TextSprite::BuildElement(std::size_t passIndex, const WorldInstance& worldInstance, std::vector<std::unique_ptr<RenderElement>>& elements) const
|
||||
{
|
||||
MaterialPass* materialPass = m_material->GetPass(passIndex);
|
||||
const auto& materialPass = m_material->GetPass(passIndex);
|
||||
if (!materialPass)
|
||||
return;
|
||||
|
||||
|
|
@ -42,7 +42,7 @@ namespace Nz
|
|||
RenderIndices& indices = pair.second;
|
||||
|
||||
if (indices.count > 0)
|
||||
elements.emplace_back(std::make_unique<RenderSpriteChain>(0, renderPipeline, vertexDeclaration, key.texture->shared_from_this(), indices.count, &m_vertices[indices.first * 4], materialPass->GetShaderBinding(), worldInstance, materialPass->GetFlags()));
|
||||
elements.emplace_back(std::make_unique<RenderSpriteChain>(0, materialPass, renderPipeline, worldInstance, vertexDeclaration, key.texture->shared_from_this(), indices.count, &m_vertices[indices.first * 4]));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue