Formalize chained fullscreen post-process execution
This commit is contained in:
@@ -461,6 +461,7 @@ add_library(XCEngine STATIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/Rendering/Pipelines/BuiltinForwardPipeline.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Rendering/Execution/CameraRenderer.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Rendering/Caches/DirectionalShadowSurfaceCache.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Rendering/Caches/FullscreenPassSurfaceCache.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Rendering/Passes/BuiltinDepthStylePassBase.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Rendering/Passes/BuiltinDepthStylePassBaseResources.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Rendering/Passes/BuiltinDepthOnlyPass.cpp
|
||||
|
||||
@@ -20,6 +20,7 @@ class RHIResourceView;
|
||||
namespace Rendering {
|
||||
|
||||
class DirectionalShadowSurfaceCache;
|
||||
class FullscreenPassSurfaceCache;
|
||||
class RenderSurface;
|
||||
class RenderPipelineAsset;
|
||||
struct RenderContext;
|
||||
@@ -71,6 +72,8 @@ private:
|
||||
std::unique_ptr<RenderPass> m_depthOnlyPass;
|
||||
std::unique_ptr<RenderPass> m_shadowCasterPass;
|
||||
std::unique_ptr<DirectionalShadowSurfaceCache> m_directionalShadowSurface;
|
||||
std::unique_ptr<FullscreenPassSurfaceCache> m_postProcessSurfaceCache;
|
||||
std::unique_ptr<FullscreenPassSurfaceCache> m_finalOutputSurfaceCache;
|
||||
};
|
||||
|
||||
} // namespace Rendering
|
||||
|
||||
@@ -14,6 +14,10 @@ class CameraComponent;
|
||||
class Scene;
|
||||
} // namespace Components
|
||||
|
||||
namespace RHI {
|
||||
class RHIResourceView;
|
||||
} // namespace RHI
|
||||
|
||||
namespace Rendering {
|
||||
|
||||
enum class CameraFrameStage : uint8_t {
|
||||
@@ -143,16 +147,26 @@ struct ObjectIdRenderRequest {
|
||||
|
||||
struct FullscreenPassRenderRequest {
|
||||
RenderSurface sourceSurface;
|
||||
RHI::RHIResourceView* sourceColorView = nullptr;
|
||||
RenderSurface destinationSurface;
|
||||
RenderPassSequence* passes = nullptr;
|
||||
|
||||
size_t GetPassCount() const {
|
||||
return passes != nullptr ? passes->GetPassCount() : 0u;
|
||||
}
|
||||
|
||||
bool IsRequested() const {
|
||||
return passes != nullptr;
|
||||
}
|
||||
|
||||
bool RequiresIntermediateSurface() const {
|
||||
return GetPassCount() > 1u;
|
||||
}
|
||||
|
||||
bool IsValid() const {
|
||||
return passes != nullptr &&
|
||||
HasValidColorTarget(sourceSurface) &&
|
||||
sourceColorView != nullptr &&
|
||||
HasValidColorTarget(destinationSurface);
|
||||
}
|
||||
};
|
||||
@@ -295,6 +309,17 @@ struct CameraRenderRequest {
|
||||
}
|
||||
}
|
||||
|
||||
RHI::RHIResourceView* GetSourceColorView(CameraFrameStage stage) const {
|
||||
switch (stage) {
|
||||
case CameraFrameStage::PostProcess:
|
||||
return postProcess.IsRequested() ? postProcess.sourceColorView : nullptr;
|
||||
case CameraFrameStage::FinalOutput:
|
||||
return finalOutput.IsRequested() ? finalOutput.sourceColorView : nullptr;
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool RequiresIntermediateSceneColor() const {
|
||||
return postProcess.IsRequested() || finalOutput.IsRequested();
|
||||
}
|
||||
|
||||
@@ -7,6 +7,10 @@
|
||||
#include <vector>
|
||||
|
||||
namespace XCEngine {
|
||||
namespace RHI {
|
||||
class RHIResourceView;
|
||||
} // namespace RHI
|
||||
|
||||
namespace Rendering {
|
||||
|
||||
struct RenderSceneData;
|
||||
@@ -17,6 +21,7 @@ struct RenderPassContext {
|
||||
const RenderSurface& surface;
|
||||
const RenderSceneData& sceneData;
|
||||
const RenderSurface* sourceSurface = nullptr;
|
||||
RHI::RHIResourceView* sourceColorView = nullptr;
|
||||
};
|
||||
|
||||
class RenderPass {
|
||||
@@ -47,6 +52,10 @@ public:
|
||||
return m_passes.size();
|
||||
}
|
||||
|
||||
bool Empty() const {
|
||||
return m_passes.empty();
|
||||
}
|
||||
|
||||
bool Initialize(const RenderContext& context) {
|
||||
for (const std::unique_ptr<RenderPass>& pass : m_passes) {
|
||||
if (pass == nullptr) {
|
||||
@@ -83,6 +92,14 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ExecutePass(size_t index, const RenderPassContext& context) {
|
||||
if (index >= m_passes.size() || m_passes[index] == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return m_passes[index]->Execute(context);
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<std::unique_ptr<RenderPass>> m_passes;
|
||||
};
|
||||
|
||||
156
engine/src/Rendering/Caches/FullscreenPassSurfaceCache.cpp
Normal file
156
engine/src/Rendering/Caches/FullscreenPassSurfaceCache.cpp
Normal file
@@ -0,0 +1,156 @@
|
||||
#include "Rendering/Caches/FullscreenPassSurfaceCache.h"
|
||||
|
||||
#include "Rendering/RenderContext.h"
|
||||
#include "RHI/RHIDevice.h"
|
||||
#include "RHI/RHIResourceView.h"
|
||||
#include "RHI/RHITexture.h"
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Rendering {
|
||||
|
||||
namespace {
|
||||
|
||||
void DestroySurfaceEntry(FullscreenPassSurfaceCache::SurfaceEntry& entry) {
|
||||
if (entry.renderTargetView != nullptr) {
|
||||
entry.renderTargetView->Shutdown();
|
||||
delete entry.renderTargetView;
|
||||
entry.renderTargetView = nullptr;
|
||||
}
|
||||
|
||||
if (entry.shaderResourceView != nullptr) {
|
||||
entry.shaderResourceView->Shutdown();
|
||||
delete entry.shaderResourceView;
|
||||
entry.shaderResourceView = nullptr;
|
||||
}
|
||||
|
||||
if (entry.texture != nullptr) {
|
||||
entry.texture->Shutdown();
|
||||
delete entry.texture;
|
||||
entry.texture = nullptr;
|
||||
}
|
||||
|
||||
entry.surface = RenderSurface();
|
||||
entry.currentColorState = RHI::ResourceStates::Common;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
FullscreenPassSurfaceCache::~FullscreenPassSurfaceCache() {
|
||||
Reset();
|
||||
}
|
||||
|
||||
bool FullscreenPassSurfaceCache::EnsureSurfaces(
|
||||
const RenderContext& context,
|
||||
uint32_t width,
|
||||
uint32_t height,
|
||||
RHI::Format format,
|
||||
size_t surfaceCount) {
|
||||
if (!context.IsValid() ||
|
||||
width == 0 ||
|
||||
height == 0 ||
|
||||
format == RHI::Format::Unknown ||
|
||||
surfaceCount == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Matches(context, width, height, format, surfaceCount)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<SurfaceEntry> newEntries(surfaceCount);
|
||||
for (size_t index = 0; index < surfaceCount; ++index) {
|
||||
SurfaceEntry& entry = newEntries[index];
|
||||
|
||||
RHI::TextureDesc textureDesc = {};
|
||||
textureDesc.width = width;
|
||||
textureDesc.height = height;
|
||||
textureDesc.depth = 1;
|
||||
textureDesc.mipLevels = 1;
|
||||
textureDesc.arraySize = 1;
|
||||
textureDesc.format = static_cast<uint32_t>(format);
|
||||
textureDesc.textureType = static_cast<uint32_t>(RHI::TextureType::Texture2D);
|
||||
textureDesc.sampleCount = 1;
|
||||
textureDesc.sampleQuality = 0;
|
||||
textureDesc.flags = 0;
|
||||
|
||||
entry.texture = context.device->CreateTexture(textureDesc);
|
||||
if (entry.texture == nullptr) {
|
||||
for (SurfaceEntry& createdEntry : newEntries) {
|
||||
DestroySurfaceEntry(createdEntry);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
RHI::ResourceViewDesc viewDesc = {};
|
||||
viewDesc.format = static_cast<uint32_t>(format);
|
||||
viewDesc.dimension = RHI::ResourceViewDimension::Texture2D;
|
||||
viewDesc.mipLevel = 0;
|
||||
|
||||
entry.renderTargetView = context.device->CreateRenderTargetView(entry.texture, viewDesc);
|
||||
if (entry.renderTargetView == nullptr) {
|
||||
for (SurfaceEntry& createdEntry : newEntries) {
|
||||
DestroySurfaceEntry(createdEntry);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
entry.shaderResourceView = context.device->CreateShaderResourceView(entry.texture, viewDesc);
|
||||
if (entry.shaderResourceView == nullptr) {
|
||||
for (SurfaceEntry& createdEntry : newEntries) {
|
||||
DestroySurfaceEntry(createdEntry);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
entry.surface = RenderSurface(width, height);
|
||||
entry.surface.SetColorAttachment(entry.renderTargetView);
|
||||
entry.surface.SetAutoTransitionEnabled(true);
|
||||
entry.surface.SetColorStateBefore(RHI::ResourceStates::Common);
|
||||
entry.surface.SetColorStateAfter(RHI::ResourceStates::PixelShaderResource);
|
||||
entry.currentColorState = RHI::ResourceStates::Common;
|
||||
}
|
||||
|
||||
Reset();
|
||||
m_device = context.device;
|
||||
m_width = width;
|
||||
m_height = height;
|
||||
m_format = format;
|
||||
m_entries = std::move(newEntries);
|
||||
return true;
|
||||
}
|
||||
|
||||
FullscreenPassSurfaceCache::SurfaceEntry* FullscreenPassSurfaceCache::GetSurfaceEntry(size_t index) {
|
||||
return index < m_entries.size() ? &m_entries[index] : nullptr;
|
||||
}
|
||||
|
||||
const FullscreenPassSurfaceCache::SurfaceEntry* FullscreenPassSurfaceCache::GetSurfaceEntry(size_t index) const {
|
||||
return index < m_entries.size() ? &m_entries[index] : nullptr;
|
||||
}
|
||||
|
||||
bool FullscreenPassSurfaceCache::Matches(
|
||||
const RenderContext& context,
|
||||
uint32_t width,
|
||||
uint32_t height,
|
||||
RHI::Format format,
|
||||
size_t surfaceCount) const {
|
||||
return m_device == context.device &&
|
||||
m_width == width &&
|
||||
m_height == height &&
|
||||
m_format == format &&
|
||||
m_entries.size() == surfaceCount;
|
||||
}
|
||||
|
||||
void FullscreenPassSurfaceCache::Reset() {
|
||||
for (SurfaceEntry& entry : m_entries) {
|
||||
DestroySurfaceEntry(entry);
|
||||
}
|
||||
|
||||
m_entries.clear();
|
||||
m_device = nullptr;
|
||||
m_width = 0;
|
||||
m_height = 0;
|
||||
m_format = RHI::Format::Unknown;
|
||||
}
|
||||
|
||||
} // namespace Rendering
|
||||
} // namespace XCEngine
|
||||
63
engine/src/Rendering/Caches/FullscreenPassSurfaceCache.h
Normal file
63
engine/src/Rendering/Caches/FullscreenPassSurfaceCache.h
Normal file
@@ -0,0 +1,63 @@
|
||||
#pragma once
|
||||
|
||||
#include "Rendering/RenderSurface.h"
|
||||
#include "RHI/RHIEnums.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <vector>
|
||||
|
||||
namespace XCEngine {
|
||||
namespace RHI {
|
||||
class RHIDevice;
|
||||
class RHIResourceView;
|
||||
class RHITexture;
|
||||
} // namespace RHI
|
||||
|
||||
namespace Rendering {
|
||||
|
||||
struct RenderContext;
|
||||
|
||||
class FullscreenPassSurfaceCache {
|
||||
public:
|
||||
struct SurfaceEntry {
|
||||
RenderSurface surface = {};
|
||||
RHI::RHITexture* texture = nullptr;
|
||||
RHI::RHIResourceView* renderTargetView = nullptr;
|
||||
RHI::RHIResourceView* shaderResourceView = nullptr;
|
||||
RHI::ResourceStates currentColorState = RHI::ResourceStates::Common;
|
||||
};
|
||||
|
||||
FullscreenPassSurfaceCache() = default;
|
||||
FullscreenPassSurfaceCache(const FullscreenPassSurfaceCache&) = delete;
|
||||
FullscreenPassSurfaceCache& operator=(const FullscreenPassSurfaceCache&) = delete;
|
||||
~FullscreenPassSurfaceCache();
|
||||
|
||||
bool EnsureSurfaces(
|
||||
const RenderContext& context,
|
||||
uint32_t width,
|
||||
uint32_t height,
|
||||
RHI::Format format,
|
||||
size_t surfaceCount);
|
||||
|
||||
size_t GetSurfaceCount() const { return m_entries.size(); }
|
||||
SurfaceEntry* GetSurfaceEntry(size_t index);
|
||||
const SurfaceEntry* GetSurfaceEntry(size_t index) const;
|
||||
|
||||
private:
|
||||
bool Matches(
|
||||
const RenderContext& context,
|
||||
uint32_t width,
|
||||
uint32_t height,
|
||||
RHI::Format format,
|
||||
size_t surfaceCount) const;
|
||||
void Reset();
|
||||
|
||||
RHI::RHIDevice* m_device = nullptr;
|
||||
uint32_t m_width = 0;
|
||||
uint32_t m_height = 0;
|
||||
RHI::Format m_format = RHI::Format::Unknown;
|
||||
std::vector<SurfaceEntry> m_entries;
|
||||
};
|
||||
|
||||
} // namespace Rendering
|
||||
} // namespace XCEngine
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "Components/CameraComponent.h"
|
||||
#include "Rendering/Caches/DirectionalShadowSurfaceCache.h"
|
||||
#include "Rendering/Caches/FullscreenPassSurfaceCache.h"
|
||||
#include "Rendering/Passes/BuiltinDepthOnlyPass.h"
|
||||
#include "Rendering/Passes/BuiltinObjectIdPass.h"
|
||||
#include "Rendering/Passes/BuiltinShadowCasterPass.h"
|
||||
@@ -11,6 +12,8 @@
|
||||
#include "RHI/RHIResourceView.h"
|
||||
#include "Scene/Scene.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Rendering {
|
||||
|
||||
@@ -135,9 +138,10 @@ public:
|
||||
ScopedInitializedPassSequence& operator=(const ScopedInitializedPassSequence&) = delete;
|
||||
|
||||
~ScopedInitializedPassSequence() {
|
||||
if (m_sequence != nullptr && m_initialized) {
|
||||
m_sequence->Shutdown();
|
||||
}
|
||||
// Request-owned pass sequences may record GPU work that executes only after the
|
||||
// caller closes/submits the command list. Do not destroy sequence-owned GPU
|
||||
// resources here; the sequence owner must shut them down explicitly when the
|
||||
// sequence is no longer needed.
|
||||
}
|
||||
|
||||
bool IsReady() const {
|
||||
@@ -159,6 +163,8 @@ struct CameraFrameExecutionState {
|
||||
RenderPass* objectIdPass = nullptr;
|
||||
RenderPass* depthOnlyPass = nullptr;
|
||||
RenderPass* shadowCasterPass = nullptr;
|
||||
FullscreenPassSurfaceCache* postProcessSurfaceCache = nullptr;
|
||||
FullscreenPassSurfaceCache* finalOutputSurfaceCache = nullptr;
|
||||
std::unique_ptr<ScopedInitializedPassSequence> preScenePasses;
|
||||
std::unique_ptr<ScopedInitializedPassSequence> postProcessPasses;
|
||||
std::unique_ptr<ScopedInitializedPassSequence> finalOutputPasses;
|
||||
@@ -175,6 +181,94 @@ bool ExecutePassSequenceStage(
|
||||
return activeSequence->IsReady() && activeSequence->Execute(passContext);
|
||||
}
|
||||
|
||||
void CopyIntermediateSurfaceLayout(
|
||||
const RenderSurface& templateSurface,
|
||||
RenderSurface& destinationSurface) {
|
||||
destinationSurface.SetSize(templateSurface.GetWidth(), templateSurface.GetHeight());
|
||||
if (templateSurface.HasCustomRenderArea()) {
|
||||
destinationSurface.SetRenderArea(templateSurface.GetRenderArea());
|
||||
} else {
|
||||
destinationSurface.ResetRenderArea();
|
||||
}
|
||||
|
||||
destinationSurface.ClearClearColorOverride();
|
||||
destinationSurface.SetAutoTransitionEnabled(true);
|
||||
}
|
||||
|
||||
bool ExecuteFullscreenPassSequenceStage(
|
||||
std::unique_ptr<ScopedInitializedPassSequence>& activeSequence,
|
||||
RenderPassSequence* sequence,
|
||||
const RenderContext& context,
|
||||
const RenderPassContext& passContext,
|
||||
FullscreenPassSurfaceCache* surfaceCache) {
|
||||
activeSequence = std::make_unique<ScopedInitializedPassSequence>(sequence, context);
|
||||
if (!activeSequence->IsReady()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sequence == nullptr || sequence->GetPassCount() <= 1u) {
|
||||
return activeSequence->Execute(passContext);
|
||||
}
|
||||
|
||||
if (surfaceCache == nullptr ||
|
||||
passContext.sourceSurface == nullptr ||
|
||||
passContext.sourceColorView == nullptr ||
|
||||
!HasValidColorTarget(passContext.surface)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const std::vector<RHI::RHIResourceView*>& colorAttachments = passContext.surface.GetColorAttachments();
|
||||
const RHI::Format outputFormat = colorAttachments[0]->GetFormat();
|
||||
const size_t intermediateSurfaceCount = std::min<size_t>(2u, sequence->GetPassCount() - 1u);
|
||||
if (!surfaceCache->EnsureSurfaces(
|
||||
context,
|
||||
passContext.surface.GetWidth(),
|
||||
passContext.surface.GetHeight(),
|
||||
outputFormat,
|
||||
intermediateSurfaceCount)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const RenderSurface* currentSourceSurface = passContext.sourceSurface;
|
||||
RHI::RHIResourceView* currentSourceColorView = passContext.sourceColorView;
|
||||
|
||||
for (size_t passIndex = 0; passIndex < sequence->GetPassCount(); ++passIndex) {
|
||||
const bool isLastPass = (passIndex + 1u) == sequence->GetPassCount();
|
||||
const RenderSurface* outputSurface = &passContext.surface;
|
||||
FullscreenPassSurfaceCache::SurfaceEntry* intermediateEntry = nullptr;
|
||||
if (!isLastPass) {
|
||||
intermediateEntry = surfaceCache->GetSurfaceEntry(passIndex % intermediateSurfaceCount);
|
||||
if (intermediateEntry == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CopyIntermediateSurfaceLayout(passContext.surface, intermediateEntry->surface);
|
||||
intermediateEntry->surface.SetColorStateBefore(intermediateEntry->currentColorState);
|
||||
intermediateEntry->surface.SetColorStateAfter(RHI::ResourceStates::PixelShaderResource);
|
||||
outputSurface = &intermediateEntry->surface;
|
||||
}
|
||||
|
||||
const RenderPassContext chainedContext = {
|
||||
context,
|
||||
*outputSurface,
|
||||
passContext.sceneData,
|
||||
currentSourceSurface,
|
||||
currentSourceColorView
|
||||
};
|
||||
if (!sequence->ExecutePass(passIndex, chainedContext)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (intermediateEntry != nullptr) {
|
||||
intermediateEntry->currentColorState = RHI::ResourceStates::PixelShaderResource;
|
||||
currentSourceSurface = &intermediateEntry->surface;
|
||||
currentSourceColorView = intermediateEntry->shaderResourceView;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
RenderPassContext BuildFrameStagePassContext(
|
||||
CameraFrameStage stage,
|
||||
const CameraRenderRequest& request,
|
||||
@@ -184,7 +278,8 @@ RenderPassContext BuildFrameStagePassContext(
|
||||
request.context,
|
||||
outputSurface != nullptr ? *outputSurface : request.surface,
|
||||
sceneData,
|
||||
request.GetSourceSurface(stage)
|
||||
request.GetSourceSurface(stage),
|
||||
request.GetSourceColorView(stage)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -219,17 +314,19 @@ bool ExecuteFrameStage(
|
||||
return executionState.pipeline != nullptr &&
|
||||
executionState.pipeline->Render(request.context, passContext.surface, sceneData);
|
||||
case CameraFrameStage::PostProcess:
|
||||
return ExecutePassSequenceStage(
|
||||
return ExecuteFullscreenPassSequenceStage(
|
||||
executionState.postProcessPasses,
|
||||
request.GetPassSequence(stage),
|
||||
request.context,
|
||||
passContext);
|
||||
passContext,
|
||||
executionState.postProcessSurfaceCache);
|
||||
case CameraFrameStage::FinalOutput:
|
||||
return ExecutePassSequenceStage(
|
||||
return ExecuteFullscreenPassSequenceStage(
|
||||
executionState.finalOutputPasses,
|
||||
request.GetPassSequence(stage),
|
||||
request.context,
|
||||
passContext);
|
||||
passContext,
|
||||
executionState.finalOutputSurfaceCache);
|
||||
case CameraFrameStage::ObjectId:
|
||||
return !request.objectId.IsRequested() ||
|
||||
ExecuteStandalonePass(
|
||||
@@ -319,7 +416,9 @@ CameraRenderer::CameraRenderer(
|
||||
: m_pipelineAsset(nullptr)
|
||||
, m_objectIdPass(std::move(objectIdPass))
|
||||
, m_depthOnlyPass(std::move(depthOnlyPass))
|
||||
, m_shadowCasterPass(std::move(shadowCasterPass)) {
|
||||
, m_shadowCasterPass(std::move(shadowCasterPass))
|
||||
, m_postProcessSurfaceCache(std::make_unique<FullscreenPassSurfaceCache>())
|
||||
, m_finalOutputSurfaceCache(std::make_unique<FullscreenPassSurfaceCache>()) {
|
||||
if (m_objectIdPass == nullptr) {
|
||||
m_objectIdPass = std::make_unique<Passes::BuiltinObjectIdPass>();
|
||||
}
|
||||
@@ -336,7 +435,9 @@ CameraRenderer::CameraRenderer(std::shared_ptr<const RenderPipelineAsset> pipeli
|
||||
: m_pipelineAsset(std::move(pipelineAsset))
|
||||
, m_objectIdPass(std::make_unique<Passes::BuiltinObjectIdPass>())
|
||||
, m_depthOnlyPass(CreateDefaultDepthOnlyPass())
|
||||
, m_shadowCasterPass(CreateDefaultShadowCasterPass()) {
|
||||
, m_shadowCasterPass(CreateDefaultShadowCasterPass())
|
||||
, m_postProcessSurfaceCache(std::make_unique<FullscreenPassSurfaceCache>())
|
||||
, m_finalOutputSurfaceCache(std::make_unique<FullscreenPassSurfaceCache>()) {
|
||||
SetPipelineAsset(m_pipelineAsset);
|
||||
}
|
||||
|
||||
@@ -481,6 +582,8 @@ bool CameraRenderer::ExecuteRenderPlan(
|
||||
executionState.objectIdPass = m_objectIdPass.get();
|
||||
executionState.depthOnlyPass = m_depthOnlyPass.get();
|
||||
executionState.shadowCasterPass = m_shadowCasterPass.get();
|
||||
executionState.postProcessSurfaceCache = m_postProcessSurfaceCache.get();
|
||||
executionState.finalOutputSurfaceCache = m_finalOutputSurfaceCache.get();
|
||||
|
||||
for (const CameraFrameStageInfo& stageInfo : kOrderedCameraFrameStages) {
|
||||
if (!request.HasFrameStage(stageInfo.stage) &&
|
||||
|
||||
Reference in New Issue
Block a user