diff --git a/engine/CMakeLists.txt b/engine/CMakeLists.txt index a55d287f..8fedfcc3 100644 --- a/engine/CMakeLists.txt +++ b/engine/CMakeLists.txt @@ -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 diff --git a/engine/include/XCEngine/Rendering/CameraRenderer.h b/engine/include/XCEngine/Rendering/CameraRenderer.h index 1024664b..9cb6e1d2 100644 --- a/engine/include/XCEngine/Rendering/CameraRenderer.h +++ b/engine/include/XCEngine/Rendering/CameraRenderer.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include @@ -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 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 m_pipelineAsset; @@ -57,7 +70,7 @@ private: std::unique_ptr m_objectIdPass; std::unique_ptr m_depthOnlyPass; std::unique_ptr m_shadowCasterPass; - std::unique_ptr m_directionalShadowSurface; + std::unique_ptr m_directionalShadowSurface; }; } // namespace Rendering diff --git a/engine/include/XCEngine/Rendering/DirectionalShadowSurfaceCache.h b/engine/include/XCEngine/Rendering/DirectionalShadowSurfaceCache.h new file mode 100644 index 00000000..b3beb71e --- /dev/null +++ b/engine/include/XCEngine/Rendering/DirectionalShadowSurfaceCache.h @@ -0,0 +1,43 @@ +#pragma once + +#include + +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 diff --git a/engine/src/Rendering/CameraRenderer.cpp b/engine/src/Rendering/CameraRenderer.cpp index 58c07cbe..c3ba9b52 100644 --- a/engine/src/Rendering/CameraRenderer.cpp +++ b/engine/src/Rendering/CameraRenderer.cpp @@ -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 CreateDefaultPipelineAsset() { static const std::shared_ptr s_defaultPipelineAsset = std::make_shared(); @@ -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 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(); + m_directionalShadowSurface = std::make_unique(); } - 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(kDirectionalShadowMapFormat); - depthDesc.textureType = static_cast(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(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); + if (!m_directionalShadowSurface->EnsureSurface(request.context, request.directionalShadow)) { + return false; } - 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( @@ -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) { - 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()) { + ShadowCasterRenderRequest resolvedShadowCaster = {}; + RHI::RHIResourceView* shadowMapView = nullptr; + if (!ResolveShadowCasterRequest(request, resolvedShadowCaster, shadowMapView)) { 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); + RenderSceneData sceneData = {}; + if (!BuildSceneDataForRequest(request, shadowMapView, sceneData)) { 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 diff --git a/engine/src/Rendering/DirectionalShadowSurfaceCache.cpp b/engine/src/Rendering/DirectionalShadowSurfaceCache.cpp new file mode 100644 index 00000000..12642150 --- /dev/null +++ b/engine/src/Rendering/DirectionalShadowSurfaceCache.cpp @@ -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(kDirectionalShadowMapFormat); + depthDesc.textureType = static_cast(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(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