Proof of concept

This commit is contained in:
Jérôme Leclercq
2021-10-20 23:50:23 +02:00
parent 58485cfa79
commit e84ec8e4ac
25 changed files with 366 additions and 139 deletions

View File

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

View File

@@ -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*/)
{
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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