mirror of
https://gitea.wildfiregames.com/0ad/0ad
synced 2026-08-15 14:43:32 -07:00
Removes smart pointers from ModelRenderer
We don't need to use pointers because we know lifetimes of all renderers. And its list statically defined. A new renderer should follow DOD and use a separate submission list with a separate inplace renderer.
This commit is contained in:
parent
fa90ddc8b6
commit
4a7b7e7df1
6 changed files with 78 additions and 63 deletions
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 2025 Wildfire Games.
|
||||
/* Copyright (C) 2026 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
|
|
@ -33,7 +33,7 @@ namespace Renderer::Backend { class IDeviceCommandContext; }
|
|||
* This computes and binds per-vertex data; the modifier is responsible
|
||||
* for setting any shader uniforms etc.
|
||||
*/
|
||||
class CPUSkinnedModelVertexRenderer : public ModelVertexRenderer
|
||||
class CPUSkinnedModelVertexRenderer final : public ModelVertexRenderer
|
||||
{
|
||||
public:
|
||||
CPUSkinnedModelVertexRenderer();
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 2025 Wildfire Games.
|
||||
/* Copyright (C) 2026 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
|
|
@ -34,7 +34,7 @@ namespace Renderer::Backend { class IShaderProgram; }
|
|||
* This computes and binds per-vertex data; the modifier is responsible
|
||||
* for setting any shader uniforms etc.
|
||||
*/
|
||||
class GPUSkinnedModelModelRenderer : public ModelVertexRenderer
|
||||
class GPUSkinnedModelModelRenderer final : public ModelVertexRenderer
|
||||
{
|
||||
public:
|
||||
GPUSkinnedModelModelRenderer();
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ struct InstancingModelRendererInternals;
|
|||
* This computes and binds per-vertex data; the modifier is responsible
|
||||
* for setting any shader uniforms etc (including the instancing transform).
|
||||
*/
|
||||
class InstancingModelRenderer : public ModelVertexRenderer
|
||||
class InstancingModelRenderer final : public ModelVertexRenderer
|
||||
{
|
||||
public:
|
||||
InstancingModelRenderer();
|
||||
|
|
|
|||
|
|
@ -306,7 +306,7 @@ struct SMRCompareTechBucket
|
|||
|
||||
void ModelRenderer::Render(
|
||||
Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
|
||||
ModelVertexRenderer& modelVertexRenderer, const RenderModifierPtr& modifier, const CShaderDefines& context,
|
||||
ModelVertexRenderer& modelVertexRenderer, RenderModifier& modifier, const CShaderDefines& context,
|
||||
int cullGroup, int flags, const ERenderMode renderMode, std::span<CModel*> submissions)
|
||||
{
|
||||
if (submissions.empty())
|
||||
|
|
@ -573,7 +573,7 @@ void ModelRenderer::Render(
|
|||
|
||||
Renderer::Backend::IShaderProgram* shader = currentTech->GetShader(pass);
|
||||
|
||||
modifier->BeginPass(deviceCommandContext, shader);
|
||||
modifier.BeginPass(deviceCommandContext, shader);
|
||||
|
||||
// TODO: Use a more generic approach to handle bound queries.
|
||||
bool boundTime = false;
|
||||
|
|
@ -703,7 +703,7 @@ void ModelRenderer::Render(
|
|||
}
|
||||
}
|
||||
|
||||
modifier->PrepareModel(deviceCommandContext, model);
|
||||
modifier.PrepareModel(deviceCommandContext, model);
|
||||
|
||||
CModelRData* rdata = static_cast<CModelRData*>(model->GetRenderData());
|
||||
ENSURE(rdata->GetKey() == &modelVertexRenderer);
|
||||
|
|
|
|||
|
|
@ -40,14 +40,8 @@ namespace Renderer::Backend { class IDeviceCommandContext; }
|
|||
struct SColor4ub;
|
||||
template <typename T> class VertexArrayIterator;
|
||||
|
||||
class RenderModifier;
|
||||
typedef std::shared_ptr<RenderModifier> RenderModifierPtr;
|
||||
|
||||
class LitRenderModifier;
|
||||
typedef std::shared_ptr<LitRenderModifier> LitRenderModifierPtr;
|
||||
|
||||
class ModelVertexRenderer;
|
||||
typedef std::shared_ptr<ModelVertexRenderer> ModelVertexRendererPtr;
|
||||
class RenderModifier;
|
||||
|
||||
/**
|
||||
* Class CModelRData: Render data that is maintained per CModel.
|
||||
|
|
@ -108,7 +102,7 @@ public:
|
|||
*/
|
||||
void Render(
|
||||
Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
|
||||
ModelVertexRenderer& modelVertexRenderer, const RenderModifierPtr& modifier, const CShaderDefines& context,
|
||||
ModelVertexRenderer& modelVertexRenderer, RenderModifier& modifier, const CShaderDefines& context,
|
||||
int cullGroup, int flags, const ERenderMode renderMode, std::span<CModel*> submissions);
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -68,6 +68,7 @@
|
|||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <optional>
|
||||
|
||||
struct SScreenRect
|
||||
{
|
||||
|
|
@ -115,7 +116,7 @@ public:
|
|||
|
||||
SilhouetteRenderer silhouetteRenderer;
|
||||
|
||||
/// Various model renderers
|
||||
// Various model renderers
|
||||
struct Models
|
||||
{
|
||||
// Submitted models are split on two axes:
|
||||
|
|
@ -127,10 +128,12 @@ public:
|
|||
|
||||
struct Submissions
|
||||
{
|
||||
ModelVertexRenderer* modelVertexRenderer{nullptr};
|
||||
std::vector<CModel*> submissions[CSceneRenderer::CULL_MAX];
|
||||
};
|
||||
|
||||
// Unskinned submissions should be prepared and rendered with
|
||||
// VertexInstancingShader. Skinned - with Vertex*SkinningShader
|
||||
// depending on whether GPU skinning is enabled.
|
||||
Submissions OpaqueSkinned;
|
||||
Submissions OpaqueUnskinned;
|
||||
Submissions TransparentSkinned;
|
||||
|
|
@ -138,11 +141,15 @@ public:
|
|||
|
||||
ModelRenderer modelRenderer;
|
||||
|
||||
ModelVertexRendererPtr VertexInstancingShader;
|
||||
ModelVertexRendererPtr VertexCPUSkinningShader;
|
||||
ModelVertexRendererPtr VertexGPUSkinningShader;
|
||||
InstancingModelRenderer VertexInstancingShader;
|
||||
CPUSkinnedModelVertexRenderer VertexCPUSkinningShader;
|
||||
// We can't create GPU skinning renderer for renderer devices without
|
||||
// its support.
|
||||
std::optional<GPUSkinnedModelModelRenderer> VertexGPUSkinningShader;
|
||||
|
||||
LitRenderModifierPtr ModShader;
|
||||
ShaderRenderModifier ModShader;
|
||||
|
||||
bool GPUSkinningEnabled{false};
|
||||
} Model;
|
||||
|
||||
CShaderDefines globalContext;
|
||||
|
|
@ -157,12 +164,21 @@ public:
|
|||
{
|
||||
PROFILE3("upload models");
|
||||
|
||||
ModelVertexRenderer& modelVertexSkinningRenderer{
|
||||
Model.GPUSkinningEnabled
|
||||
? static_cast<ModelVertexRenderer&>(*Model.VertexGPUSkinningShader)
|
||||
: static_cast<ModelVertexRenderer&>(Model.VertexCPUSkinningShader)};
|
||||
|
||||
for (int cullGroup{0}; cullGroup < CSceneRenderer::CULL_MAX; ++cullGroup)
|
||||
{
|
||||
Model.OpaqueSkinned.modelVertexRenderer->UploadModelsData(deviceCommandContext, Model.OpaqueSkinned.submissions[cullGroup]);
|
||||
Model.TransparentSkinned.modelVertexRenderer->UploadModelsData(deviceCommandContext, Model.TransparentSkinned.submissions[cullGroup]);
|
||||
Model.OpaqueUnskinned.modelVertexRenderer->UploadModelsData(deviceCommandContext, Model.OpaqueUnskinned.submissions[cullGroup]);
|
||||
Model.TransparentUnskinned.modelVertexRenderer->UploadModelsData(deviceCommandContext, Model.TransparentUnskinned.submissions[cullGroup]);
|
||||
modelVertexSkinningRenderer.UploadModelsData(deviceCommandContext, Model.OpaqueSkinned.submissions[cullGroup]);
|
||||
modelVertexSkinningRenderer.UploadModelsData(deviceCommandContext, Model.TransparentSkinned.submissions[cullGroup]);
|
||||
}
|
||||
|
||||
for (int cullGroup{0}; cullGroup < CSceneRenderer::CULL_MAX; ++cullGroup)
|
||||
{
|
||||
Model.VertexInstancingShader.UploadModelsData(deviceCommandContext, Model.OpaqueUnskinned.submissions[cullGroup]);
|
||||
Model.VertexInstancingShader.UploadModelsData(deviceCommandContext, Model.TransparentUnskinned.submissions[cullGroup]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -178,12 +194,21 @@ public:
|
|||
{
|
||||
PROFILE3("prepare models");
|
||||
|
||||
ModelVertexRenderer& modelVertexSkinningRenderer{
|
||||
Model.GPUSkinningEnabled
|
||||
? static_cast<ModelVertexRenderer&>(*Model.VertexGPUSkinningShader)
|
||||
: static_cast<ModelVertexRenderer&>(Model.VertexCPUSkinningShader)};
|
||||
|
||||
for (int cullGroup{0}; cullGroup < CSceneRenderer::CULL_MAX; ++cullGroup)
|
||||
{
|
||||
PrepareModels(deviceCommandContext, *Model.OpaqueSkinned.modelVertexRenderer, Model.OpaqueSkinned.submissions[cullGroup]);
|
||||
PrepareModels(deviceCommandContext, *Model.TransparentSkinned.modelVertexRenderer, Model.TransparentSkinned.submissions[cullGroup]);
|
||||
PrepareModels(deviceCommandContext, *Model.OpaqueUnskinned.modelVertexRenderer, Model.OpaqueUnskinned.submissions[cullGroup]);
|
||||
PrepareModels(deviceCommandContext, *Model.TransparentUnskinned.modelVertexRenderer, Model.TransparentUnskinned.submissions[cullGroup]);
|
||||
PrepareModels(deviceCommandContext, modelVertexSkinningRenderer, Model.OpaqueSkinned.submissions[cullGroup]);
|
||||
PrepareModels(deviceCommandContext, modelVertexSkinningRenderer, Model.TransparentSkinned.submissions[cullGroup]);
|
||||
}
|
||||
|
||||
for (int cullGroup{0}; cullGroup < CSceneRenderer::CULL_MAX; ++cullGroup)
|
||||
{
|
||||
PrepareModels(deviceCommandContext, Model.VertexInstancingShader, Model.OpaqueUnskinned.submissions[cullGroup]);
|
||||
PrepareModels(deviceCommandContext, Model.VertexInstancingShader, Model.TransparentUnskinned.submissions[cullGroup]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -242,14 +267,19 @@ public:
|
|||
Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
|
||||
const CShaderDefines& context, int cullGroup, int flags, const ERenderMode renderMode)
|
||||
{
|
||||
ModelVertexRenderer& modelVertexSkinningRenderer{
|
||||
Model.GPUSkinningEnabled
|
||||
? static_cast<ModelVertexRenderer&>(*Model.VertexGPUSkinningShader)
|
||||
: static_cast<ModelVertexRenderer&>(Model.VertexCPUSkinningShader)};
|
||||
|
||||
CShaderDefines contextSkinned = context;
|
||||
if (g_RenderingOptions.GetGPUSkinning())
|
||||
if (Model.GPUSkinningEnabled)
|
||||
contextSkinned.Add(str_USE_INSTANCING, str_1);
|
||||
Model.modelRenderer.Render(deviceCommandContext, *Model.OpaqueSkinned.modelVertexRenderer, Model.ModShader, contextSkinned, cullGroup, flags, renderMode, Model.OpaqueSkinned.submissions[cullGroup]);
|
||||
Model.modelRenderer.Render(deviceCommandContext, modelVertexSkinningRenderer, Model.ModShader, contextSkinned, cullGroup, flags, renderMode, Model.OpaqueSkinned.submissions[cullGroup]);
|
||||
|
||||
CShaderDefines contextUnskinned = context;
|
||||
contextUnskinned.Add(str_USE_INSTANCING, str_1);
|
||||
Model.modelRenderer.Render(deviceCommandContext, *Model.OpaqueUnskinned.modelVertexRenderer, Model.ModShader, contextUnskinned, cullGroup, flags, renderMode, Model.OpaqueUnskinned.submissions[cullGroup]);
|
||||
Model.modelRenderer.Render(deviceCommandContext, Model.VertexInstancingShader, Model.ModShader, contextUnskinned, cullGroup, flags, renderMode, Model.OpaqueUnskinned.submissions[cullGroup]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -259,14 +289,19 @@ public:
|
|||
Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
|
||||
const CShaderDefines& context, int cullGroup, int flags, const ERenderMode renderMode)
|
||||
{
|
||||
ModelVertexRenderer& modelVertexSkinningRenderer{
|
||||
Model.GPUSkinningEnabled
|
||||
? static_cast<ModelVertexRenderer&>(*Model.VertexGPUSkinningShader)
|
||||
: static_cast<ModelVertexRenderer&>(Model.VertexCPUSkinningShader)};
|
||||
|
||||
CShaderDefines contextSkinned = context;
|
||||
if (g_RenderingOptions.GetGPUSkinning())
|
||||
if (Model.GPUSkinningEnabled)
|
||||
contextSkinned.Add(str_USE_INSTANCING, str_1);
|
||||
Model.modelRenderer.Render(deviceCommandContext, *Model.TransparentSkinned.modelVertexRenderer, Model.ModShader, contextSkinned, cullGroup, flags, renderMode, Model.TransparentSkinned.submissions[cullGroup]);
|
||||
Model.modelRenderer.Render(deviceCommandContext, modelVertexSkinningRenderer, Model.ModShader, contextSkinned, cullGroup, flags, renderMode, Model.TransparentSkinned.submissions[cullGroup]);
|
||||
|
||||
CShaderDefines contextUnskinned = context;
|
||||
contextUnskinned.Add(str_USE_INSTANCING, str_1);
|
||||
Model.modelRenderer.Render(deviceCommandContext, *Model.TransparentUnskinned.modelVertexRenderer, Model.ModShader, contextUnskinned, cullGroup, flags, renderMode, Model.TransparentUnskinned.submissions[cullGroup]);
|
||||
Model.modelRenderer.Render(deviceCommandContext, Model.VertexInstancingShader, Model.ModShader, contextUnskinned, cullGroup, flags, renderMode, Model.TransparentUnskinned.submissions[cullGroup]);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -319,26 +354,12 @@ void CSceneRenderer::ReloadShaders([[maybe_unused]] Renderer::Backend::IDevice*
|
|||
m->globalContext.Add(str_RENDER_DEBUG_MODE,
|
||||
RenderDebugModeEnum::ToString(g_RenderingOptions.GetRenderDebugMode()));
|
||||
|
||||
m->Model.ModShader = LitRenderModifierPtr(new ShaderRenderModifier());
|
||||
|
||||
m->Model.VertexCPUSkinningShader = ModelVertexRendererPtr(new CPUSkinnedModelVertexRenderer());
|
||||
m->Model.VertexInstancingShader = ModelVertexRendererPtr(new InstancingModelRenderer());
|
||||
|
||||
if (g_RenderingOptions.GetGPUSkinning())
|
||||
m->Model.GPUSkinningEnabled = g_RenderingOptions.GetGPUSkinning();
|
||||
if (m->Model.GPUSkinningEnabled)
|
||||
{
|
||||
m->Model.VertexGPUSkinningShader = ModelVertexRendererPtr(new GPUSkinnedModelModelRenderer());
|
||||
m->Model.OpaqueSkinned.modelVertexRenderer = m->Model.VertexGPUSkinningShader.get();
|
||||
m->Model.TransparentSkinned.modelVertexRenderer = m->Model.VertexGPUSkinningShader.get();
|
||||
if (!m->Model.VertexGPUSkinningShader.has_value())
|
||||
m->Model.VertexGPUSkinningShader.emplace();
|
||||
}
|
||||
else
|
||||
{
|
||||
m->Model.VertexGPUSkinningShader.reset();
|
||||
m->Model.OpaqueSkinned.modelVertexRenderer = m->Model.VertexCPUSkinningShader.get();
|
||||
m->Model.TransparentSkinned.modelVertexRenderer = m->Model.VertexCPUSkinningShader.get();
|
||||
}
|
||||
|
||||
m->Model.OpaqueUnskinned.modelVertexRenderer = m->Model.VertexInstancingShader.get();
|
||||
m->Model.TransparentUnskinned.modelVertexRenderer = m->Model.VertexInstancingShader.get();
|
||||
}
|
||||
|
||||
void CSceneRenderer::Initialize()
|
||||
|
|
@ -362,8 +383,8 @@ void CSceneRenderer::Resize(int /*width*/, int /*height*/)
|
|||
void CSceneRenderer::BeginFrame()
|
||||
{
|
||||
// choose model renderers for this frame
|
||||
m->Model.ModShader->SetShadowMap(&m->shadow);
|
||||
m->Model.ModShader->SetLightEnv(m_LightEnv);
|
||||
m->Model.ModShader.SetShadowMap(&m->shadow);
|
||||
m->Model.ModShader.SetLightEnv(m_LightEnv);
|
||||
}
|
||||
|
||||
void CSceneRenderer::SetSimulation(CSimulation2* simulation)
|
||||
|
|
@ -1095,23 +1116,23 @@ void CSceneRenderer::SubmitNonRecursive(CModel* model)
|
|||
|
||||
const bool requiresSkinning{model->GetModelDef()->GetNumBones() != 0};
|
||||
ModelVertexRenderer& modelVertexSkinningRenderer{
|
||||
g_RenderingOptions.GetGPUSkinning() ? *m->Model.VertexGPUSkinningShader : *m->Model.VertexCPUSkinningShader};
|
||||
ModelVertexRenderer& modelVertexRenderer{
|
||||
requiresSkinning ? modelVertexSkinningRenderer : *m->Model.VertexInstancingShader};
|
||||
m->Model.GPUSkinningEnabled
|
||||
? static_cast<ModelVertexRenderer&>(*m->Model.VertexGPUSkinningShader)
|
||||
: static_cast<ModelVertexRenderer&>(m->Model.VertexCPUSkinningShader)};
|
||||
|
||||
if (model->GetMaterial().UsesAlphaBlending())
|
||||
{
|
||||
if (requiresSkinning)
|
||||
m->Submit(m_CurrentCullGroup, modelVertexRenderer, m->Model.TransparentSkinned, model);
|
||||
m->Submit(m_CurrentCullGroup, modelVertexSkinningRenderer, m->Model.TransparentSkinned, model);
|
||||
else
|
||||
m->Submit(m_CurrentCullGroup, modelVertexRenderer, m->Model.TransparentUnskinned, model);
|
||||
m->Submit(m_CurrentCullGroup, m->Model.VertexInstancingShader, m->Model.TransparentUnskinned, model);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (requiresSkinning)
|
||||
m->Submit(m_CurrentCullGroup, modelVertexRenderer, m->Model.OpaqueSkinned, model);
|
||||
m->Submit(m_CurrentCullGroup, modelVertexSkinningRenderer, m->Model.OpaqueSkinned, model);
|
||||
else
|
||||
m->Submit(m_CurrentCullGroup, modelVertexRenderer, m->Model.OpaqueUnskinned, model);
|
||||
m->Submit(m_CurrentCullGroup, m->Model.VertexInstancingShader, m->Model.OpaqueUnskinned, model);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue