refactor: unify builtin forward scene execution

This commit is contained in:
2026-04-10 02:56:36 +08:00
parent ff6d6d31fe
commit 57331c1c25
2 changed files with 126 additions and 126 deletions

View File

@@ -36,11 +36,13 @@ namespace Rendering {
class RenderSurface;
namespace Pipelines {
namespace Detail {
class BuiltinForwardOpaquePass;
class BuiltinForwardSkyboxPass;
class BuiltinForwardTransparentPass;
} // namespace Detail
} // namespace Pipelines
namespace Passes {
class BuiltinVolumetricPass;
} // namespace Passes
namespace Pipelines {
class BuiltinForwardPipeline : public RenderPipeline {
public:
@@ -57,10 +59,6 @@ public:
const RenderSceneData& sceneData) override;
private:
friend class Detail::BuiltinForwardOpaquePass;
friend class Detail::BuiltinForwardSkyboxPass;
friend class Detail::BuiltinForwardTransparentPass;
struct OwnedDescriptorSet {
RHI::RHIDescriptorPool* pool = nullptr;
RHI::RHIDescriptorSet* set = nullptr;
@@ -189,12 +187,22 @@ private:
const Resources::Shader* shader = nullptr;
Containers::String passName;
Containers::String keywordSignature;
Core::uint32 renderTargetCount = 0;
std::array<Core::uint32, 8> renderTargetFormats = {};
Core::uint32 depthStencilFormat = 0;
Core::uint32 sampleCount = 1;
Core::uint32 sampleQuality = 0;
bool operator==(const PipelineStateKey& other) const {
return renderState == other.renderState &&
shader == other.shader &&
passName == other.passName &&
keywordSignature == other.keywordSignature;
keywordSignature == other.keywordSignature &&
renderTargetCount == other.renderTargetCount &&
renderTargetFormats == other.renderTargetFormats &&
depthStencilFormat == other.depthStencilFormat &&
sampleCount == other.sampleCount &&
sampleQuality == other.sampleQuality;
}
};
@@ -208,6 +216,46 @@ private:
combine(reinterpret_cast<size_t>(key.shader));
combine(std::hash<Containers::String>{}(key.passName));
combine(std::hash<Containers::String>{}(key.keywordSignature));
combine(std::hash<Core::uint32>{}(key.renderTargetCount));
for (Core::uint32 format : key.renderTargetFormats) {
combine(std::hash<Core::uint32>{}(format));
}
combine(std::hash<Core::uint32>{}(key.depthStencilFormat));
combine(std::hash<Core::uint32>{}(key.sampleCount));
combine(std::hash<Core::uint32>{}(key.sampleQuality));
return hash;
}
};
struct SkyboxPipelineStateKey {
Core::uint32 renderTargetCount = 0;
std::array<Core::uint32, 8> renderTargetFormats = {};
Core::uint32 depthStencilFormat = 0;
Core::uint32 sampleCount = 1;
Core::uint32 sampleQuality = 0;
bool operator==(const SkyboxPipelineStateKey& other) const {
return renderTargetCount == other.renderTargetCount &&
renderTargetFormats == other.renderTargetFormats &&
depthStencilFormat == other.depthStencilFormat &&
sampleCount == other.sampleCount &&
sampleQuality == other.sampleQuality;
}
};
struct SkyboxPipelineStateKeyHash {
size_t operator()(const SkyboxPipelineStateKey& key) const noexcept {
size_t hash = std::hash<Core::uint32>{}(key.renderTargetCount);
auto combine = [&hash](size_t value) {
hash ^= value + 0x9e3779b9u + (hash << 6) + (hash >> 2);
};
for (Core::uint32 format : key.renderTargetFormats) {
combine(std::hash<Core::uint32>{}(format));
}
combine(std::hash<Core::uint32>{}(key.depthStencilFormat));
combine(std::hash<Core::uint32>{}(key.sampleCount));
combine(std::hash<Core::uint32>{}(key.sampleQuality));
return hash;
}
};
@@ -226,8 +274,12 @@ private:
const ResolvedShaderPass& resolvedShaderPass);
RHI::RHIPipelineState* GetOrCreatePipelineState(
const RenderContext& context,
const RenderSurface& surface,
const RenderSceneData& sceneData,
const Resources::Material* material);
RHI::RHIPipelineState* GetOrCreateSkyboxPipelineState(
const RenderContext& context,
const RenderSurface& surface);
bool CreateOwnedDescriptorSet(
const BuiltinPassSetLayoutMetadata& setLayout,
OwnedDescriptorSet& descriptorSet);
@@ -263,10 +315,12 @@ private:
bool ExecuteForwardTransparentPass(const RenderPassContext& context);
bool DrawVisibleItems(
const RenderContext& context,
const RenderSurface& surface,
const RenderSceneData& sceneData,
bool drawTransparentItems);
bool DrawVisibleItem(
const RenderContext& context,
const RenderSurface& surface,
const RenderSceneData& sceneData,
const VisibleRenderItem& visibleItem);
bool EnsureSkyboxResources(const RenderContext& context);
@@ -292,7 +346,8 @@ private:
RHI::RHITexture* m_fallbackTextureCube = nullptr;
RHI::RHIResourceView* m_fallbackTextureCubeView = nullptr;
RHI::RHIPipelineLayout* m_skyboxPipelineLayout = nullptr;
RHI::RHIPipelineState* m_skyboxPipelineState = nullptr;
Containers::String m_skyboxPassName;
std::unordered_map<SkyboxPipelineStateKey, RHI::RHIPipelineState*, SkyboxPipelineStateKeyHash> m_skyboxPipelineStates;
OwnedDescriptorSet m_skyboxEnvironmentSet = {};
OwnedDescriptorSet m_skyboxMaterialSet = {};
OwnedDescriptorSet m_skyboxPanoramicTextureSet = {};
@@ -300,7 +355,7 @@ private:
OwnedDescriptorSet m_skyboxSamplerSet = {};
RHI::RHIResourceView* m_skyboxBoundPanoramicTextureView = nullptr;
RHI::RHIResourceView* m_skyboxBoundCubemapTextureView = nullptr;
RenderPassSequence m_passSequence;
std::unique_ptr<Passes::BuiltinVolumetricPass> m_volumetricPass;
};
class BuiltinForwardPipelineAsset final : public RenderPipelineAsset {

View File

@@ -15,88 +15,6 @@
namespace XCEngine {
namespace Rendering {
namespace Pipelines {
namespace Internal {
class BuiltinForwardOpaquePass final : public RenderPass {
public:
explicit BuiltinForwardOpaquePass(BuiltinForwardPipeline& pipeline)
: m_pipeline(pipeline) {
}
const char* GetName() const override {
return "BuiltinForwardOpaquePass";
}
bool Initialize(const RenderContext& context) override {
return m_pipeline.EnsureInitialized(context);
}
void Shutdown() override {
m_pipeline.DestroyPipelineResources();
}
bool Execute(const RenderPassContext& context) override {
return m_pipeline.ExecuteForwardOpaquePass(context);
}
private:
BuiltinForwardPipeline& m_pipeline;
};
class BuiltinForwardSkyboxPass final : public RenderPass {
public:
explicit BuiltinForwardSkyboxPass(BuiltinForwardPipeline& pipeline)
: m_pipeline(pipeline) {
}
const char* GetName() const override {
return "BuiltinForwardSkyboxPass";
}
bool Initialize(const RenderContext& context) override {
return m_pipeline.EnsureInitialized(context);
}
void Shutdown() override {
m_pipeline.DestroyPipelineResources();
}
bool Execute(const RenderPassContext& context) override {
return m_pipeline.ExecuteForwardSkyboxPass(context);
}
private:
BuiltinForwardPipeline& m_pipeline;
};
class BuiltinForwardTransparentPass final : public RenderPass {
public:
explicit BuiltinForwardTransparentPass(BuiltinForwardPipeline& pipeline)
: m_pipeline(pipeline) {
}
const char* GetName() const override {
return "BuiltinForwardTransparentPass";
}
bool Initialize(const RenderContext& context) override {
return m_pipeline.EnsureInitialized(context);
}
void Shutdown() override {
m_pipeline.DestroyPipelineResources();
}
bool Execute(const RenderPassContext& context) override {
return m_pipeline.ExecuteForwardTransparentPass(context);
}
private:
BuiltinForwardPipeline& m_pipeline;
};
} // namespace Internal
namespace {
bool IsDepthFormat(RHI::Format format) {
@@ -104,6 +22,30 @@ bool IsDepthFormat(RHI::Format format) {
format == RHI::Format::D32_Float;
}
bool ShouldSampleMainDirectionalShadowMap(const RenderSceneData& sceneData) {
return sceneData.lighting.HasMainDirectionalShadow() &&
sceneData.lighting.mainDirectionalShadow.shadowMap != nullptr &&
IsDepthFormat(sceneData.lighting.mainDirectionalShadow.shadowMap->GetFormat());
}
void TransitionMainDirectionalShadowForSampling(
const RenderContext& context,
const RenderSceneData& sceneData) {
context.commandList->TransitionBarrier(
sceneData.lighting.mainDirectionalShadow.shadowMap,
RHI::ResourceStates::DepthWrite,
RHI::ResourceStates::PixelShaderResource);
}
void RestoreMainDirectionalShadowAfterSampling(
const RenderContext& context,
const RenderSceneData& sceneData) {
context.commandList->TransitionBarrier(
sceneData.lighting.mainDirectionalShadow.shadowMap,
RHI::ResourceStates::PixelShaderResource,
RHI::ResourceStates::DepthWrite);
}
std::vector<RHI::RHIResourceView*> CollectSurfaceColorAttachments(const RenderSurface& surface) {
std::vector<RHI::RHIResourceView*> renderTargets;
const Core::uint32 colorAttachmentCount =
@@ -124,10 +66,7 @@ std::vector<RHI::RHIResourceView*> CollectSurfaceColorAttachments(const RenderSu
} // namespace
BuiltinForwardPipeline::BuiltinForwardPipeline() {
m_passSequence.AddPass(std::make_unique<Internal::BuiltinForwardOpaquePass>(*this));
m_passSequence.AddPass(std::make_unique<Internal::BuiltinForwardSkyboxPass>(*this));
m_passSequence.AddPass(std::make_unique<Passes::BuiltinVolumetricPass>());
m_passSequence.AddPass(std::make_unique<Internal::BuiltinForwardTransparentPass>(*this));
m_volumetricPass = std::make_unique<Passes::BuiltinVolumetricPass>();
}
BuiltinForwardPipeline::~BuiltinForwardPipeline() {
@@ -169,11 +108,16 @@ RHI::InputLayoutDesc BuiltinForwardPipeline::BuildInputLayout() {
}
bool BuiltinForwardPipeline::Initialize(const RenderContext& context) {
return m_passSequence.Initialize(context);
return EnsureInitialized(context) &&
m_volumetricPass != nullptr &&
m_volumetricPass->Initialize(context);
}
void BuiltinForwardPipeline::Shutdown() {
m_passSequence.Shutdown();
if (m_volumetricPass != nullptr) {
m_volumetricPass->Shutdown();
}
DestroyPipelineResources();
}
bool BuiltinForwardPipeline::Render(
@@ -193,7 +137,32 @@ bool BuiltinForwardPipeline::Render(
RHI::ResourceStates::Common
};
return m_passSequence.Execute(passContext);
if (!BeginForwardScenePass(passContext)) {
return false;
}
const bool sampledDirectionalShadow = ShouldSampleMainDirectionalShadowMap(sceneData);
if (sampledDirectionalShadow) {
TransitionMainDirectionalShadowForSampling(context, sceneData);
}
bool renderResult = ExecuteForwardOpaquePass(passContext);
if (renderResult) {
renderResult = ExecuteForwardSkyboxPass(passContext);
}
if (renderResult && m_volumetricPass != nullptr) {
renderResult = m_volumetricPass->Execute(passContext);
}
if (renderResult) {
renderResult = ExecuteForwardTransparentPass(passContext);
}
if (sampledDirectionalShadow) {
RestoreMainDirectionalShadowAfterSampling(context, sceneData);
}
EndForwardScenePass(passContext);
return renderResult;
}
bool BuiltinForwardPipeline::BeginForwardScenePass(const RenderPassContext& passContext) {
@@ -309,18 +278,6 @@ bool BuiltinForwardPipeline::ExecuteForwardOpaquePass(const RenderPassContext& p
const RenderSurface& surface = passContext.surface;
const RenderSceneData& sceneData = passContext.sceneData;
if (!BeginForwardScenePass(passContext)) {
return false;
}
if (sceneData.lighting.HasMainDirectionalShadow() &&
IsDepthFormat(sceneData.lighting.mainDirectionalShadow.shadowMap->GetFormat())) {
context.commandList->TransitionBarrier(
sceneData.lighting.mainDirectionalShadow.shadowMap,
RHI::ResourceStates::DepthWrite,
RHI::ResourceStates::PixelShaderResource);
}
return DrawVisibleItems(context, surface, sceneData, false);
}
@@ -329,19 +286,7 @@ bool BuiltinForwardPipeline::ExecuteForwardTransparentPass(const RenderPassConte
const RenderSurface& surface = passContext.surface;
const RenderSceneData& sceneData = passContext.sceneData;
const bool drawResult = DrawVisibleItems(context, surface, sceneData, true);
if (sceneData.lighting.HasMainDirectionalShadow() &&
IsDepthFormat(sceneData.lighting.mainDirectionalShadow.shadowMap->GetFormat())) {
context.commandList->TransitionBarrier(
sceneData.lighting.mainDirectionalShadow.shadowMap,
RHI::ResourceStates::PixelShaderResource,
RHI::ResourceStates::DepthWrite);
}
EndForwardScenePass(passContext);
return drawResult;
return DrawVisibleItems(context, surface, sceneData, true);
}
bool BuiltinForwardPipeline::DrawVisibleItems(