Refactor camera renderer orchestration
This commit is contained in:
@@ -446,6 +446,7 @@ add_library(XCEngine STATIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/Rendering/RenderSurface.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/Rendering/RenderResourceCache.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/Rendering/CameraRenderer.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/Rendering/DirectionalShadowSurfaceCache.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/Rendering/ObjectIdEncoding.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/Rendering/SceneRenderRequestPlanner.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/Rendering/SceneRenderRequestUtils.h
|
||||
@@ -458,6 +459,7 @@ add_library(XCEngine STATIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/Rendering/Passes/BuiltinObjectIdOutlinePass.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/Rendering/Pipelines/BuiltinForwardPipeline.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Rendering/CameraRenderer.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Rendering/DirectionalShadowSurfaceCache.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Rendering/Passes/BuiltinDepthStylePassBase.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Rendering/Passes/BuiltinDepthOnlyPass.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Rendering/Passes/BuiltinShadowCasterPass.cpp
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <XCEngine/Rendering/CameraRenderRequest.h>
|
||||
#include <XCEngine/Rendering/RenderSceneExtractor.h>
|
||||
#include <XCEngine/Rendering/RenderPass.h>
|
||||
#include <XCEngine/Rendering/RenderPipeline.h>
|
||||
|
||||
@@ -12,8 +13,13 @@ class CameraComponent;
|
||||
class Scene;
|
||||
} // namespace Components
|
||||
|
||||
namespace RHI {
|
||||
class RHIResourceView;
|
||||
} // namespace RHI
|
||||
|
||||
namespace Rendering {
|
||||
|
||||
class DirectionalShadowSurfaceCache;
|
||||
class RenderSurface;
|
||||
class RenderPipelineAsset;
|
||||
struct RenderContext;
|
||||
@@ -44,12 +50,19 @@ public:
|
||||
bool Render(const CameraRenderRequest& request);
|
||||
|
||||
private:
|
||||
struct DirectionalShadowSurfaceResources;
|
||||
|
||||
void ResetPipeline(std::unique_ptr<RenderPipeline> pipeline);
|
||||
DirectionalShadowSurfaceResources* AcquireDirectionalShadowSurface(
|
||||
const RenderContext& context,
|
||||
const DirectionalShadowRenderPlan& plan);
|
||||
bool ResolveShadowCasterRequest(
|
||||
const CameraRenderRequest& request,
|
||||
ShadowCasterRenderRequest& outResolvedShadowCaster,
|
||||
RHI::RHIResourceView*& outShadowMapView);
|
||||
bool BuildSceneDataForRequest(
|
||||
const CameraRenderRequest& request,
|
||||
RHI::RHIResourceView* shadowMapView,
|
||||
RenderSceneData& outSceneData);
|
||||
bool ExecuteRenderPlan(
|
||||
const CameraRenderRequest& request,
|
||||
const ShadowCasterRenderRequest& resolvedShadowCaster,
|
||||
const RenderSceneData& sceneData);
|
||||
|
||||
RenderSceneExtractor m_sceneExtractor;
|
||||
std::shared_ptr<const RenderPipelineAsset> m_pipelineAsset;
|
||||
@@ -57,7 +70,7 @@ private:
|
||||
std::unique_ptr<RenderPass> m_objectIdPass;
|
||||
std::unique_ptr<RenderPass> m_depthOnlyPass;
|
||||
std::unique_ptr<RenderPass> m_shadowCasterPass;
|
||||
std::unique_ptr<DirectionalShadowSurfaceResources> m_directionalShadowSurface;
|
||||
std::unique_ptr<DirectionalShadowSurfaceCache> m_directionalShadowSurface;
|
||||
};
|
||||
|
||||
} // namespace Rendering
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
#pragma once
|
||||
|
||||
#include <XCEngine/Rendering/RenderSurface.h>
|
||||
|
||||
namespace XCEngine {
|
||||
namespace RHI {
|
||||
class RHIDevice;
|
||||
class RHIResourceView;
|
||||
class RHITexture;
|
||||
} // namespace RHI
|
||||
|
||||
namespace Rendering {
|
||||
|
||||
struct DirectionalShadowRenderPlan;
|
||||
struct RenderContext;
|
||||
|
||||
class DirectionalShadowSurfaceCache {
|
||||
public:
|
||||
DirectionalShadowSurfaceCache() = default;
|
||||
DirectionalShadowSurfaceCache(const DirectionalShadowSurfaceCache&) = delete;
|
||||
DirectionalShadowSurfaceCache& operator=(const DirectionalShadowSurfaceCache&) = delete;
|
||||
~DirectionalShadowSurfaceCache();
|
||||
|
||||
bool EnsureSurface(const RenderContext& context, const DirectionalShadowRenderPlan& plan);
|
||||
|
||||
const RenderSurface& GetSurface() const { return m_surface; }
|
||||
RHI::RHIResourceView* GetDepthShaderView() const { return m_depthShaderView; }
|
||||
|
||||
private:
|
||||
bool Matches(const RenderContext& context, const DirectionalShadowRenderPlan& plan) const;
|
||||
void Reset();
|
||||
|
||||
RHI::RHIDevice* m_device = nullptr;
|
||||
uint32_t m_width = 0;
|
||||
uint32_t m_height = 0;
|
||||
RHI::RHITexture* m_depthTexture = nullptr;
|
||||
RHI::RHIResourceView* m_depthView = nullptr;
|
||||
RHI::RHIResourceView* m_depthShaderView = nullptr;
|
||||
RenderSurface m_surface = {};
|
||||
};
|
||||
|
||||
} // namespace Rendering
|
||||
} // namespace XCEngine
|
||||
@@ -1,98 +1,20 @@
|
||||
#include "Rendering/CameraRenderer.h"
|
||||
|
||||
#include "Rendering/DirectionalShadowSurfaceCache.h"
|
||||
#include "Rendering/Passes/BuiltinDepthOnlyPass.h"
|
||||
#include "Rendering/Passes/BuiltinObjectIdPass.h"
|
||||
#include "Rendering/Passes/BuiltinShadowCasterPass.h"
|
||||
#include "Rendering/Pipelines/BuiltinForwardPipeline.h"
|
||||
#include "Rendering/RenderPipelineAsset.h"
|
||||
#include "Rendering/RenderSurface.h"
|
||||
#include "RHI/RHIDevice.h"
|
||||
#include "RHI/RHIResourceView.h"
|
||||
#include "RHI/RHITexture.h"
|
||||
#include "Scene/Scene.h"
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Rendering {
|
||||
|
||||
struct CameraRenderer::DirectionalShadowSurfaceResources {
|
||||
RHI::RHIDevice* device = nullptr;
|
||||
uint32_t width = 0;
|
||||
uint32_t height = 0;
|
||||
RHI::RHITexture* depthTexture = nullptr;
|
||||
RHI::RHIResourceView* depthView = nullptr;
|
||||
RHI::RHIResourceView* depthShaderView = nullptr;
|
||||
RenderSurface surface = {};
|
||||
|
||||
DirectionalShadowSurfaceResources() = default;
|
||||
DirectionalShadowSurfaceResources(const DirectionalShadowSurfaceResources&) = delete;
|
||||
DirectionalShadowSurfaceResources& operator=(const DirectionalShadowSurfaceResources&) = delete;
|
||||
|
||||
~DirectionalShadowSurfaceResources() {
|
||||
Reset();
|
||||
}
|
||||
|
||||
bool Matches(const RenderContext& context, const DirectionalShadowRenderPlan& plan) const {
|
||||
return device == context.device &&
|
||||
width == plan.mapWidth &&
|
||||
height == plan.mapHeight &&
|
||||
depthTexture != nullptr &&
|
||||
depthView != nullptr &&
|
||||
depthShaderView != nullptr;
|
||||
}
|
||||
|
||||
void Reset() {
|
||||
if (depthView != nullptr) {
|
||||
depthView->Shutdown();
|
||||
delete depthView;
|
||||
depthView = nullptr;
|
||||
}
|
||||
|
||||
if (depthShaderView != nullptr) {
|
||||
depthShaderView->Shutdown();
|
||||
delete depthShaderView;
|
||||
depthShaderView = nullptr;
|
||||
}
|
||||
|
||||
if (depthTexture != nullptr) {
|
||||
depthTexture->Shutdown();
|
||||
delete depthTexture;
|
||||
depthTexture = nullptr;
|
||||
}
|
||||
|
||||
device = nullptr;
|
||||
width = 0;
|
||||
height = 0;
|
||||
surface = RenderSurface();
|
||||
}
|
||||
};
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr RHI::Format kDirectionalShadowMapFormat = RHI::Format::D32_Float;
|
||||
|
||||
bool InitializePassSequence(
|
||||
RenderPassSequence* sequence,
|
||||
const RenderContext& context,
|
||||
bool& initialized) {
|
||||
if (sequence == nullptr) {
|
||||
initialized = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
initialized = sequence->Initialize(context);
|
||||
if (!initialized) {
|
||||
sequence->Shutdown();
|
||||
}
|
||||
|
||||
return initialized;
|
||||
}
|
||||
|
||||
void ShutdownPassSequence(RenderPassSequence* sequence, bool initialized) {
|
||||
if (sequence != nullptr && initialized) {
|
||||
sequence->Shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<const RenderPipelineAsset> CreateDefaultPipelineAsset() {
|
||||
static const std::shared_ptr<const RenderPipelineAsset> s_defaultPipelineAsset =
|
||||
std::make_shared<Pipelines::BuiltinForwardPipelineAsset>();
|
||||
@@ -188,6 +110,47 @@ bool ExecuteStandalonePass(
|
||||
return pass->Execute(passContext);
|
||||
}
|
||||
|
||||
class ScopedInitializedPassSequence {
|
||||
public:
|
||||
ScopedInitializedPassSequence(
|
||||
RenderPassSequence* sequence,
|
||||
const RenderContext& context)
|
||||
: m_sequence(sequence) {
|
||||
if (m_sequence == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_initialized = m_sequence->Initialize(context);
|
||||
if (!m_initialized) {
|
||||
m_failed = true;
|
||||
m_sequence->Shutdown();
|
||||
m_sequence = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
ScopedInitializedPassSequence(const ScopedInitializedPassSequence&) = delete;
|
||||
ScopedInitializedPassSequence& operator=(const ScopedInitializedPassSequence&) = delete;
|
||||
|
||||
~ScopedInitializedPassSequence() {
|
||||
if (m_sequence != nullptr && m_initialized) {
|
||||
m_sequence->Shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
bool IsReady() const {
|
||||
return !m_failed;
|
||||
}
|
||||
|
||||
bool Execute(const RenderPassContext& context) const {
|
||||
return m_sequence == nullptr || m_sequence->Execute(context);
|
||||
}
|
||||
|
||||
private:
|
||||
RenderPassSequence* m_sequence = nullptr;
|
||||
bool m_initialized = false;
|
||||
bool m_failed = false;
|
||||
};
|
||||
|
||||
RenderDirectionalShadowData BuildDirectionalShadowData(
|
||||
const DirectionalShadowRenderPlan& plan,
|
||||
RHI::RHIResourceView* shadowMapView) {
|
||||
@@ -320,72 +283,121 @@ void CameraRenderer::ResetPipeline(std::unique_ptr<RenderPipeline> pipeline) {
|
||||
}
|
||||
}
|
||||
|
||||
CameraRenderer::DirectionalShadowSurfaceResources* CameraRenderer::AcquireDirectionalShadowSurface(
|
||||
const RenderContext& context,
|
||||
const DirectionalShadowRenderPlan& plan) {
|
||||
if (!context.IsValid() || !plan.IsValid()) {
|
||||
return nullptr;
|
||||
bool CameraRenderer::ResolveShadowCasterRequest(
|
||||
const CameraRenderRequest& request,
|
||||
ShadowCasterRenderRequest& outResolvedShadowCaster,
|
||||
RHI::RHIResourceView*& outShadowMapView) {
|
||||
outResolvedShadowCaster = request.shadowCaster;
|
||||
outShadowMapView = nullptr;
|
||||
|
||||
if (outResolvedShadowCaster.IsRequested()) {
|
||||
return outResolvedShadowCaster.IsValid();
|
||||
}
|
||||
|
||||
if (!request.directionalShadow.IsValid()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (m_directionalShadowSurface == nullptr) {
|
||||
m_directionalShadowSurface = std::make_unique<DirectionalShadowSurfaceResources>();
|
||||
m_directionalShadowSurface = std::make_unique<DirectionalShadowSurfaceCache>();
|
||||
}
|
||||
|
||||
if (!m_directionalShadowSurface->Matches(context, plan)) {
|
||||
RHI::TextureDesc depthDesc = {};
|
||||
depthDesc.width = plan.mapWidth;
|
||||
depthDesc.height = plan.mapHeight;
|
||||
depthDesc.depth = 1;
|
||||
depthDesc.mipLevels = 1;
|
||||
depthDesc.arraySize = 1;
|
||||
depthDesc.format = static_cast<uint32_t>(kDirectionalShadowMapFormat);
|
||||
depthDesc.textureType = static_cast<uint32_t>(RHI::TextureType::Texture2D);
|
||||
depthDesc.sampleCount = 1;
|
||||
depthDesc.sampleQuality = 0;
|
||||
depthDesc.flags = 0;
|
||||
|
||||
RHI::RHITexture* depthTexture = context.device->CreateTexture(depthDesc);
|
||||
if (depthTexture == nullptr) {
|
||||
return nullptr;
|
||||
if (!m_directionalShadowSurface->EnsureSurface(request.context, request.directionalShadow)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RHI::ResourceViewDesc depthViewDesc = {};
|
||||
depthViewDesc.format = static_cast<uint32_t>(kDirectionalShadowMapFormat);
|
||||
depthViewDesc.dimension = RHI::ResourceViewDimension::Texture2D;
|
||||
depthViewDesc.mipLevel = 0;
|
||||
RHI::RHIResourceView* depthView =
|
||||
context.device->CreateDepthStencilView(depthTexture, depthViewDesc);
|
||||
if (depthView == nullptr) {
|
||||
depthTexture->Shutdown();
|
||||
delete depthTexture;
|
||||
return nullptr;
|
||||
outResolvedShadowCaster.surface = m_directionalShadowSurface->GetSurface();
|
||||
outResolvedShadowCaster.clearFlags = RenderClearFlags::Depth;
|
||||
if (!outResolvedShadowCaster.hasCameraDataOverride) {
|
||||
outResolvedShadowCaster.hasCameraDataOverride = true;
|
||||
outResolvedShadowCaster.cameraDataOverride = request.directionalShadow.cameraData;
|
||||
}
|
||||
|
||||
RHI::ResourceViewDesc depthShaderViewDesc = {};
|
||||
depthShaderViewDesc.dimension = RHI::ResourceViewDimension::Texture2D;
|
||||
depthShaderViewDesc.mipLevel = 0;
|
||||
RHI::RHIResourceView* depthShaderView =
|
||||
context.device->CreateShaderResourceView(depthTexture, depthShaderViewDesc);
|
||||
if (depthShaderView == nullptr) {
|
||||
depthView->Shutdown();
|
||||
delete depthView;
|
||||
depthTexture->Shutdown();
|
||||
delete depthTexture;
|
||||
return nullptr;
|
||||
outShadowMapView = m_directionalShadowSurface->GetDepthShaderView();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CameraRenderer::BuildSceneDataForRequest(
|
||||
const CameraRenderRequest& request,
|
||||
RHI::RHIResourceView* shadowMapView,
|
||||
RenderSceneData& outSceneData) {
|
||||
outSceneData = m_sceneExtractor.ExtractForCamera(
|
||||
*request.scene,
|
||||
*request.camera,
|
||||
request.surface.GetRenderAreaWidth(),
|
||||
request.surface.GetRenderAreaHeight());
|
||||
if (!outSceneData.HasCamera()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
m_directionalShadowSurface->Reset();
|
||||
m_directionalShadowSurface->device = context.device;
|
||||
m_directionalShadowSurface->width = plan.mapWidth;
|
||||
m_directionalShadowSurface->height = plan.mapHeight;
|
||||
m_directionalShadowSurface->depthTexture = depthTexture;
|
||||
m_directionalShadowSurface->depthView = depthView;
|
||||
m_directionalShadowSurface->depthShaderView = depthShaderView;
|
||||
m_directionalShadowSurface->surface = RenderSurface(plan.mapWidth, plan.mapHeight);
|
||||
m_directionalShadowSurface->surface.SetDepthAttachment(depthView);
|
||||
if (request.directionalShadow.IsValid()) {
|
||||
outSceneData.lighting.mainDirectionalShadow =
|
||||
BuildDirectionalShadowData(request.directionalShadow, shadowMapView);
|
||||
}
|
||||
|
||||
return m_directionalShadowSurface.get();
|
||||
outSceneData.cameraData.clearFlags = request.clearFlags;
|
||||
if (request.hasClearColorOverride) {
|
||||
outSceneData.cameraData.clearColor = request.clearColorOverride;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CameraRenderer::ExecuteRenderPlan(
|
||||
const CameraRenderRequest& request,
|
||||
const ShadowCasterRenderRequest& resolvedShadowCaster,
|
||||
const RenderSceneData& sceneData) {
|
||||
const RenderPassContext passContext = {
|
||||
request.context,
|
||||
request.surface,
|
||||
sceneData
|
||||
};
|
||||
|
||||
ScopedInitializedPassSequence preScenePasses(request.preScenePasses, request.context);
|
||||
if (!preScenePasses.IsReady() || !preScenePasses.Execute(passContext)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ExecuteScenePassRequest(
|
||||
m_shadowCasterPass.get(),
|
||||
resolvedShadowCaster,
|
||||
request.context,
|
||||
sceneData)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ExecuteScenePassRequest(
|
||||
m_depthOnlyPass.get(),
|
||||
request.depthOnly,
|
||||
request.context,
|
||||
sceneData)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_pipeline->Render(request.context, request.surface, sceneData)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (request.objectId.IsRequested() &&
|
||||
!ExecuteStandalonePass(
|
||||
m_objectIdPass.get(),
|
||||
request.context,
|
||||
request.objectId.surface,
|
||||
sceneData)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ScopedInitializedPassSequence postScenePasses(request.postScenePasses, request.context);
|
||||
if (!postScenePasses.IsReady() || !postScenePasses.Execute(passContext)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ScopedInitializedPassSequence overlayPasses(request.overlayPasses, request.context);
|
||||
if (!overlayPasses.IsReady() || !overlayPasses.Execute(passContext)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CameraRenderer::Render(
|
||||
@@ -407,137 +419,18 @@ bool CameraRenderer::Render(
|
||||
return false;
|
||||
}
|
||||
|
||||
ShadowCasterRenderRequest resolvedShadowCaster = request.shadowCaster;
|
||||
DirectionalShadowSurfaceResources* directionalShadowSurface = nullptr;
|
||||
if (resolvedShadowCaster.IsRequested()) {
|
||||
if (!resolvedShadowCaster.IsValid()) {
|
||||
return false;
|
||||
}
|
||||
} else if (request.directionalShadow.IsValid()) {
|
||||
directionalShadowSurface = AcquireDirectionalShadowSurface(
|
||||
request.context,
|
||||
request.directionalShadow);
|
||||
if (directionalShadowSurface == nullptr) {
|
||||
ShadowCasterRenderRequest resolvedShadowCaster = {};
|
||||
RHI::RHIResourceView* shadowMapView = nullptr;
|
||||
if (!ResolveShadowCasterRequest(request, resolvedShadowCaster, shadowMapView)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
resolvedShadowCaster.surface = directionalShadowSurface->surface;
|
||||
resolvedShadowCaster.clearFlags = RenderClearFlags::Depth;
|
||||
if (!resolvedShadowCaster.hasCameraDataOverride) {
|
||||
resolvedShadowCaster.hasCameraDataOverride = true;
|
||||
resolvedShadowCaster.cameraDataOverride = request.directionalShadow.cameraData;
|
||||
}
|
||||
}
|
||||
|
||||
RenderSceneData sceneData = m_sceneExtractor.ExtractForCamera(
|
||||
*request.scene,
|
||||
*request.camera,
|
||||
request.surface.GetRenderAreaWidth(),
|
||||
request.surface.GetRenderAreaHeight());
|
||||
if (!sceneData.HasCamera()) {
|
||||
RenderSceneData sceneData = {};
|
||||
if (!BuildSceneDataForRequest(request, shadowMapView, sceneData)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (request.directionalShadow.IsValid()) {
|
||||
RHI::RHIResourceView* shadowMapView =
|
||||
directionalShadowSurface != nullptr ? directionalShadowSurface->depthShaderView : nullptr;
|
||||
sceneData.lighting.mainDirectionalShadow =
|
||||
BuildDirectionalShadowData(request.directionalShadow, shadowMapView);
|
||||
}
|
||||
|
||||
sceneData.cameraData.clearFlags = request.clearFlags;
|
||||
if (request.hasClearColorOverride) {
|
||||
sceneData.cameraData.clearColor = request.clearColorOverride;
|
||||
}
|
||||
const RenderPassContext passContext = {
|
||||
request.context,
|
||||
request.surface,
|
||||
sceneData
|
||||
};
|
||||
|
||||
bool preScenePassesInitialized = false;
|
||||
if (!InitializePassSequence(
|
||||
request.preScenePasses,
|
||||
request.context,
|
||||
preScenePassesInitialized)) {
|
||||
return false;
|
||||
}
|
||||
if (request.preScenePasses != nullptr &&
|
||||
!request.preScenePasses->Execute(passContext)) {
|
||||
ShutdownPassSequence(request.preScenePasses, preScenePassesInitialized);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ExecuteScenePassRequest(
|
||||
m_shadowCasterPass.get(),
|
||||
resolvedShadowCaster,
|
||||
request.context,
|
||||
sceneData)) {
|
||||
ShutdownPassSequence(request.preScenePasses, preScenePassesInitialized);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ExecuteScenePassRequest(
|
||||
m_depthOnlyPass.get(),
|
||||
request.depthOnly,
|
||||
request.context,
|
||||
sceneData)) {
|
||||
ShutdownPassSequence(request.preScenePasses, preScenePassesInitialized);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_pipeline->Render(request.context, request.surface, sceneData)) {
|
||||
ShutdownPassSequence(request.preScenePasses, preScenePassesInitialized);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (request.objectId.IsRequested() &&
|
||||
!ExecuteStandalonePass(
|
||||
m_objectIdPass.get(),
|
||||
request.context,
|
||||
request.objectId.surface,
|
||||
sceneData)) {
|
||||
ShutdownPassSequence(request.preScenePasses, preScenePassesInitialized);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool postScenePassesInitialized = false;
|
||||
if (!InitializePassSequence(
|
||||
request.postScenePasses,
|
||||
request.context,
|
||||
postScenePassesInitialized)) {
|
||||
ShutdownPassSequence(request.preScenePasses, preScenePassesInitialized);
|
||||
return false;
|
||||
}
|
||||
if (request.postScenePasses != nullptr &&
|
||||
!request.postScenePasses->Execute(passContext)) {
|
||||
ShutdownPassSequence(request.postScenePasses, postScenePassesInitialized);
|
||||
ShutdownPassSequence(request.preScenePasses, preScenePassesInitialized);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool overlayPassesInitialized = false;
|
||||
if (!InitializePassSequence(
|
||||
request.overlayPasses,
|
||||
request.context,
|
||||
overlayPassesInitialized)) {
|
||||
ShutdownPassSequence(request.postScenePasses, postScenePassesInitialized);
|
||||
ShutdownPassSequence(request.preScenePasses, preScenePassesInitialized);
|
||||
return false;
|
||||
}
|
||||
if (request.overlayPasses != nullptr &&
|
||||
!request.overlayPasses->Execute(passContext)) {
|
||||
ShutdownPassSequence(request.overlayPasses, overlayPassesInitialized);
|
||||
ShutdownPassSequence(request.postScenePasses, postScenePassesInitialized);
|
||||
ShutdownPassSequence(request.preScenePasses, preScenePassesInitialized);
|
||||
return false;
|
||||
}
|
||||
|
||||
ShutdownPassSequence(request.overlayPasses, overlayPassesInitialized);
|
||||
ShutdownPassSequence(request.postScenePasses, postScenePassesInitialized);
|
||||
ShutdownPassSequence(request.preScenePasses, preScenePassesInitialized);
|
||||
|
||||
return true;
|
||||
return ExecuteRenderPlan(request, resolvedShadowCaster, sceneData);
|
||||
}
|
||||
|
||||
} // namespace Rendering
|
||||
|
||||
123
engine/src/Rendering/DirectionalShadowSurfaceCache.cpp
Normal file
123
engine/src/Rendering/DirectionalShadowSurfaceCache.cpp
Normal file
@@ -0,0 +1,123 @@
|
||||
#include "Rendering/DirectionalShadowSurfaceCache.h"
|
||||
|
||||
#include "Rendering/CameraRenderRequest.h"
|
||||
#include "RHI/RHIDevice.h"
|
||||
#include "RHI/RHIResourceView.h"
|
||||
#include "RHI/RHITexture.h"
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Rendering {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr RHI::Format kDirectionalShadowMapFormat = RHI::Format::D32_Float;
|
||||
|
||||
} // namespace
|
||||
|
||||
DirectionalShadowSurfaceCache::~DirectionalShadowSurfaceCache() {
|
||||
Reset();
|
||||
}
|
||||
|
||||
bool DirectionalShadowSurfaceCache::EnsureSurface(
|
||||
const RenderContext& context,
|
||||
const DirectionalShadowRenderPlan& plan) {
|
||||
if (!context.IsValid() || !plan.IsValid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Matches(context, plan)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
RHI::TextureDesc depthDesc = {};
|
||||
depthDesc.width = plan.mapWidth;
|
||||
depthDesc.height = plan.mapHeight;
|
||||
depthDesc.depth = 1;
|
||||
depthDesc.mipLevels = 1;
|
||||
depthDesc.arraySize = 1;
|
||||
depthDesc.format = static_cast<uint32_t>(kDirectionalShadowMapFormat);
|
||||
depthDesc.textureType = static_cast<uint32_t>(RHI::TextureType::Texture2D);
|
||||
depthDesc.sampleCount = 1;
|
||||
depthDesc.sampleQuality = 0;
|
||||
depthDesc.flags = 0;
|
||||
|
||||
RHI::RHITexture* depthTexture = context.device->CreateTexture(depthDesc);
|
||||
if (depthTexture == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RHI::ResourceViewDesc depthViewDesc = {};
|
||||
depthViewDesc.format = static_cast<uint32_t>(kDirectionalShadowMapFormat);
|
||||
depthViewDesc.dimension = RHI::ResourceViewDimension::Texture2D;
|
||||
depthViewDesc.mipLevel = 0;
|
||||
RHI::RHIResourceView* depthView =
|
||||
context.device->CreateDepthStencilView(depthTexture, depthViewDesc);
|
||||
if (depthView == nullptr) {
|
||||
depthTexture->Shutdown();
|
||||
delete depthTexture;
|
||||
return false;
|
||||
}
|
||||
|
||||
RHI::ResourceViewDesc depthShaderViewDesc = {};
|
||||
depthShaderViewDesc.dimension = RHI::ResourceViewDimension::Texture2D;
|
||||
depthShaderViewDesc.mipLevel = 0;
|
||||
RHI::RHIResourceView* depthShaderView =
|
||||
context.device->CreateShaderResourceView(depthTexture, depthShaderViewDesc);
|
||||
if (depthShaderView == nullptr) {
|
||||
depthView->Shutdown();
|
||||
delete depthView;
|
||||
depthTexture->Shutdown();
|
||||
delete depthTexture;
|
||||
return false;
|
||||
}
|
||||
|
||||
Reset();
|
||||
m_device = context.device;
|
||||
m_width = plan.mapWidth;
|
||||
m_height = plan.mapHeight;
|
||||
m_depthTexture = depthTexture;
|
||||
m_depthView = depthView;
|
||||
m_depthShaderView = depthShaderView;
|
||||
m_surface = RenderSurface(plan.mapWidth, plan.mapHeight);
|
||||
m_surface.SetDepthAttachment(depthView);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DirectionalShadowSurfaceCache::Matches(
|
||||
const RenderContext& context,
|
||||
const DirectionalShadowRenderPlan& plan) const {
|
||||
return m_device == context.device &&
|
||||
m_width == plan.mapWidth &&
|
||||
m_height == plan.mapHeight &&
|
||||
m_depthTexture != nullptr &&
|
||||
m_depthView != nullptr &&
|
||||
m_depthShaderView != nullptr;
|
||||
}
|
||||
|
||||
void DirectionalShadowSurfaceCache::Reset() {
|
||||
if (m_depthView != nullptr) {
|
||||
m_depthView->Shutdown();
|
||||
delete m_depthView;
|
||||
m_depthView = nullptr;
|
||||
}
|
||||
|
||||
if (m_depthShaderView != nullptr) {
|
||||
m_depthShaderView->Shutdown();
|
||||
delete m_depthShaderView;
|
||||
m_depthShaderView = nullptr;
|
||||
}
|
||||
|
||||
if (m_depthTexture != nullptr) {
|
||||
m_depthTexture->Shutdown();
|
||||
delete m_depthTexture;
|
||||
m_depthTexture = nullptr;
|
||||
}
|
||||
|
||||
m_device = nullptr;
|
||||
m_width = 0;
|
||||
m_height = 0;
|
||||
m_surface = RenderSurface();
|
||||
}
|
||||
|
||||
} // namespace Rendering
|
||||
} // namespace XCEngine
|
||||
Reference in New Issue
Block a user