Refactor camera renderer orchestration

This commit is contained in:
2026-04-05 19:55:37 +08:00
parent 3dd8867a17
commit d52b85aff9
5 changed files with 343 additions and 269 deletions

View File

@@ -446,6 +446,7 @@ add_library(XCEngine STATIC
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/Rendering/RenderSurface.h ${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/RenderResourceCache.h
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/Rendering/CameraRenderer.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/ObjectIdEncoding.h
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/Rendering/SceneRenderRequestPlanner.h ${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/Rendering/SceneRenderRequestPlanner.h
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/Rendering/SceneRenderRequestUtils.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/Passes/BuiltinObjectIdOutlinePass.h
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/Rendering/Pipelines/BuiltinForwardPipeline.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/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/BuiltinDepthStylePassBase.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/Rendering/Passes/BuiltinDepthOnlyPass.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Rendering/Passes/BuiltinDepthOnlyPass.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/Rendering/Passes/BuiltinShadowCasterPass.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Rendering/Passes/BuiltinShadowCasterPass.cpp

View File

@@ -1,6 +1,7 @@
#pragma once #pragma once
#include <XCEngine/Rendering/CameraRenderRequest.h> #include <XCEngine/Rendering/CameraRenderRequest.h>
#include <XCEngine/Rendering/RenderSceneExtractor.h>
#include <XCEngine/Rendering/RenderPass.h> #include <XCEngine/Rendering/RenderPass.h>
#include <XCEngine/Rendering/RenderPipeline.h> #include <XCEngine/Rendering/RenderPipeline.h>
@@ -12,8 +13,13 @@ class CameraComponent;
class Scene; class Scene;
} // namespace Components } // namespace Components
namespace RHI {
class RHIResourceView;
} // namespace RHI
namespace Rendering { namespace Rendering {
class DirectionalShadowSurfaceCache;
class RenderSurface; class RenderSurface;
class RenderPipelineAsset; class RenderPipelineAsset;
struct RenderContext; struct RenderContext;
@@ -44,12 +50,19 @@ public:
bool Render(const CameraRenderRequest& request); bool Render(const CameraRenderRequest& request);
private: private:
struct DirectionalShadowSurfaceResources;
void ResetPipeline(std::unique_ptr<RenderPipeline> pipeline); void ResetPipeline(std::unique_ptr<RenderPipeline> pipeline);
DirectionalShadowSurfaceResources* AcquireDirectionalShadowSurface( bool ResolveShadowCasterRequest(
const RenderContext& context, const CameraRenderRequest& request,
const DirectionalShadowRenderPlan& plan); 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; RenderSceneExtractor m_sceneExtractor;
std::shared_ptr<const RenderPipelineAsset> m_pipelineAsset; std::shared_ptr<const RenderPipelineAsset> m_pipelineAsset;
@@ -57,7 +70,7 @@ private:
std::unique_ptr<RenderPass> m_objectIdPass; std::unique_ptr<RenderPass> m_objectIdPass;
std::unique_ptr<RenderPass> m_depthOnlyPass; std::unique_ptr<RenderPass> m_depthOnlyPass;
std::unique_ptr<RenderPass> m_shadowCasterPass; std::unique_ptr<RenderPass> m_shadowCasterPass;
std::unique_ptr<DirectionalShadowSurfaceResources> m_directionalShadowSurface; std::unique_ptr<DirectionalShadowSurfaceCache> m_directionalShadowSurface;
}; };
} // namespace Rendering } // namespace Rendering

View File

@@ -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

View File

@@ -1,98 +1,20 @@
#include "Rendering/CameraRenderer.h" #include "Rendering/CameraRenderer.h"
#include "Rendering/DirectionalShadowSurfaceCache.h"
#include "Rendering/Passes/BuiltinDepthOnlyPass.h" #include "Rendering/Passes/BuiltinDepthOnlyPass.h"
#include "Rendering/Passes/BuiltinObjectIdPass.h" #include "Rendering/Passes/BuiltinObjectIdPass.h"
#include "Rendering/Passes/BuiltinShadowCasterPass.h" #include "Rendering/Passes/BuiltinShadowCasterPass.h"
#include "Rendering/Pipelines/BuiltinForwardPipeline.h" #include "Rendering/Pipelines/BuiltinForwardPipeline.h"
#include "Rendering/RenderPipelineAsset.h" #include "Rendering/RenderPipelineAsset.h"
#include "Rendering/RenderSurface.h" #include "Rendering/RenderSurface.h"
#include "RHI/RHIDevice.h"
#include "RHI/RHIResourceView.h" #include "RHI/RHIResourceView.h"
#include "RHI/RHITexture.h"
#include "Scene/Scene.h" #include "Scene/Scene.h"
namespace XCEngine { namespace XCEngine {
namespace Rendering { 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 { 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() { std::shared_ptr<const RenderPipelineAsset> CreateDefaultPipelineAsset() {
static const std::shared_ptr<const RenderPipelineAsset> s_defaultPipelineAsset = static const std::shared_ptr<const RenderPipelineAsset> s_defaultPipelineAsset =
std::make_shared<Pipelines::BuiltinForwardPipelineAsset>(); std::make_shared<Pipelines::BuiltinForwardPipelineAsset>();
@@ -188,6 +110,47 @@ bool ExecuteStandalonePass(
return pass->Execute(passContext); 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( RenderDirectionalShadowData BuildDirectionalShadowData(
const DirectionalShadowRenderPlan& plan, const DirectionalShadowRenderPlan& plan,
RHI::RHIResourceView* shadowMapView) { RHI::RHIResourceView* shadowMapView) {
@@ -320,72 +283,121 @@ void CameraRenderer::ResetPipeline(std::unique_ptr<RenderPipeline> pipeline) {
} }
} }
CameraRenderer::DirectionalShadowSurfaceResources* CameraRenderer::AcquireDirectionalShadowSurface( bool CameraRenderer::ResolveShadowCasterRequest(
const RenderContext& context, const CameraRenderRequest& request,
const DirectionalShadowRenderPlan& plan) { ShadowCasterRenderRequest& outResolvedShadowCaster,
if (!context.IsValid() || !plan.IsValid()) { RHI::RHIResourceView*& outShadowMapView) {
return nullptr; outResolvedShadowCaster = request.shadowCaster;
outShadowMapView = nullptr;
if (outResolvedShadowCaster.IsRequested()) {
return outResolvedShadowCaster.IsValid();
}
if (!request.directionalShadow.IsValid()) {
return true;
} }
if (m_directionalShadowSurface == nullptr) { if (m_directionalShadowSurface == nullptr) {
m_directionalShadowSurface = std::make_unique<DirectionalShadowSurfaceResources>(); m_directionalShadowSurface = std::make_unique<DirectionalShadowSurfaceCache>();
} }
if (!m_directionalShadowSurface->Matches(context, plan)) { if (!m_directionalShadowSurface->EnsureSurface(request.context, request.directionalShadow)) {
RHI::TextureDesc depthDesc = {}; return false;
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;
}
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;
}
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;
}
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);
} }
return m_directionalShadowSurface.get(); outResolvedShadowCaster.surface = m_directionalShadowSurface->GetSurface();
outResolvedShadowCaster.clearFlags = RenderClearFlags::Depth;
if (!outResolvedShadowCaster.hasCameraDataOverride) {
outResolvedShadowCaster.hasCameraDataOverride = true;
outResolvedShadowCaster.cameraDataOverride = request.directionalShadow.cameraData;
}
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;
}
if (request.directionalShadow.IsValid()) {
outSceneData.lighting.mainDirectionalShadow =
BuildDirectionalShadowData(request.directionalShadow, shadowMapView);
}
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( bool CameraRenderer::Render(
@@ -407,137 +419,18 @@ bool CameraRenderer::Render(
return false; return false;
} }
ShadowCasterRenderRequest resolvedShadowCaster = request.shadowCaster; ShadowCasterRenderRequest resolvedShadowCaster = {};
DirectionalShadowSurfaceResources* directionalShadowSurface = nullptr; RHI::RHIResourceView* shadowMapView = nullptr;
if (resolvedShadowCaster.IsRequested()) { if (!ResolveShadowCasterRequest(request, resolvedShadowCaster, shadowMapView)) {
if (!resolvedShadowCaster.IsValid()) {
return false;
}
} else if (request.directionalShadow.IsValid()) {
directionalShadowSurface = AcquireDirectionalShadowSurface(
request.context,
request.directionalShadow);
if (directionalShadowSurface == nullptr) {
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()) {
return false; return false;
} }
if (request.directionalShadow.IsValid()) { RenderSceneData sceneData = {};
RHI::RHIResourceView* shadowMapView = if (!BuildSceneDataForRequest(request, shadowMapView, sceneData)) {
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; return false;
} }
if (!ExecuteScenePassRequest( return ExecuteRenderPlan(request, resolvedShadowCaster, sceneData);
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;
} }
} // namespace Rendering } // namespace Rendering

View 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