refactor: unify builtin forward scene execution
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user