#include "Rendering/Viewport/ViewportRenderTargets.h" #include "Ports/ViewportRenderPort.h" namespace XCEngine::UI::Editor::App { namespace { bool CreateViewportColorResources( ::XCEngine::RHI::RHIDevice& device, ViewportRenderTargets& targets) { const auto colorDesc = BuildViewportTextureDesc(targets.width, targets.height, ::XCEngine::RHI::Format::R8G8B8A8_UNorm); targets.colorTexture = device.CreateTexture(colorDesc); if (targets.colorTexture == nullptr) { return false; } const auto colorViewDesc = BuildViewportTextureViewDesc(::XCEngine::RHI::Format::R8G8B8A8_UNorm); targets.colorView = device.CreateRenderTargetView(targets.colorTexture, colorViewDesc); return targets.colorView != nullptr; } bool CreateViewportDepthResources( ::XCEngine::RHI::RHIDevice& device, ViewportRenderTargets& targets, bool createShaderView) { const auto depthDesc = BuildViewportTextureDesc(targets.width, targets.height, ::XCEngine::RHI::Format::D24_UNorm_S8_UInt); targets.depthTexture = device.CreateTexture(depthDesc); if (targets.depthTexture == nullptr) { return false; } const auto depthViewDesc = BuildViewportTextureViewDesc(::XCEngine::RHI::Format::D24_UNorm_S8_UInt); targets.depthView = device.CreateDepthStencilView(targets.depthTexture, depthViewDesc); if (targets.depthView == nullptr) { return false; } if (!createShaderView) { return true; } ::XCEngine::RHI::ResourceViewDesc depthShaderViewDesc = {}; depthShaderViewDesc.dimension = ::XCEngine::RHI::ResourceViewDimension::Texture2D; depthShaderViewDesc.mipLevel = 0; targets.depthShaderView = device.CreateShaderResourceView( targets.depthTexture, depthShaderViewDesc); return targets.depthShaderView != nullptr; } bool CreateViewportObjectIdResources( ::XCEngine::RHI::RHIDevice& device, ViewportRenderTargets& targets) { const auto objectIdDesc = BuildViewportTextureDesc(targets.width, targets.height, ::XCEngine::RHI::Format::R8G8B8A8_UNorm); targets.objectIdTexture = device.CreateTexture(objectIdDesc); if (targets.objectIdTexture == nullptr) { return false; } const auto objectIdViewDesc = BuildViewportTextureViewDesc(::XCEngine::RHI::Format::R8G8B8A8_UNorm); targets.objectIdView = device.CreateRenderTargetView(targets.objectIdTexture, objectIdViewDesc); if (targets.objectIdView == nullptr) { return false; } targets.objectIdShaderView = device.CreateShaderResourceView( targets.objectIdTexture, objectIdViewDesc); if (targets.objectIdShaderView == nullptr) { return false; } const auto objectIdDepthDesc = BuildViewportTextureDesc(targets.width, targets.height, ::XCEngine::RHI::Format::D24_UNorm_S8_UInt); targets.objectIdDepthTexture = device.CreateTexture(objectIdDepthDesc); if (targets.objectIdDepthTexture == nullptr) { return false; } const auto objectIdDepthViewDesc = BuildViewportTextureViewDesc(::XCEngine::RHI::Format::D24_UNorm_S8_UInt); targets.objectIdDepthView = device.CreateDepthStencilView( targets.objectIdDepthTexture, objectIdDepthViewDesc); return targets.objectIdDepthView != nullptr; } bool CreateViewportSelectionMaskResources( ::XCEngine::RHI::RHIDevice& device, ViewportRenderTargets& targets) { const auto selectionMaskDesc = BuildViewportTextureDesc(targets.width, targets.height, ::XCEngine::RHI::Format::R8G8B8A8_UNorm); targets.selectionMaskTexture = device.CreateTexture(selectionMaskDesc); if (targets.selectionMaskTexture == nullptr) { return false; } const auto selectionMaskViewDesc = BuildViewportTextureViewDesc(::XCEngine::RHI::Format::R8G8B8A8_UNorm); targets.selectionMaskView = device.CreateRenderTargetView( targets.selectionMaskTexture, selectionMaskViewDesc); if (targets.selectionMaskView == nullptr) { return false; } targets.selectionMaskShaderView = device.CreateShaderResourceView( targets.selectionMaskTexture, selectionMaskViewDesc); return targets.selectionMaskShaderView != nullptr; } bool CreateViewportTextureHandle( Ports::ViewportRenderPort& renderHost, ViewportRenderTargets& targets) { if (targets.colorTexture == nullptr) { return false; } return renderHost.CreateViewportTextureHandle( *targets.colorTexture, targets.width, targets.height, targets.textureHandle); } template void ShutdownAndDeleteViewportResource(ResourceType*& resource) { if (resource == nullptr) { return; } resource->Shutdown(); delete resource; resource = nullptr; } void ResetViewportTargetMetadata(ViewportRenderTargets& targets) { targets.width = 0; targets.height = 0; targets.textureHandle = {}; targets.colorState = ::XCEngine::RHI::ResourceStates::Common; targets.objectIdState = ::XCEngine::RHI::ResourceStates::Common; targets.selectionMaskState = ::XCEngine::RHI::ResourceStates::Common; targets.hasValidObjectIdFrame = false; } } // namespace ViewportResourceReuseQuery BuildViewportRenderTargetsReuseQuery( const ViewportResourceRequirements& requirements, const ViewportRenderTargets& targets, std::uint32_t requestedWidth, std::uint32_t requestedHeight) { ViewportResourceReuseQuery query = {}; query.requirements = requirements; query.width = targets.width; query.height = targets.height; query.requestedWidth = requestedWidth; query.requestedHeight = requestedHeight; query.resources.hasColorTexture = targets.colorTexture != nullptr; query.resources.hasColorView = targets.colorView != nullptr; query.resources.hasDepthTexture = targets.depthTexture != nullptr; query.resources.hasDepthView = targets.depthView != nullptr; query.resources.hasDepthShaderView = targets.depthShaderView != nullptr; query.resources.hasObjectIdTexture = targets.objectIdTexture != nullptr; query.resources.hasObjectIdDepthTexture = targets.objectIdDepthTexture != nullptr; query.resources.hasObjectIdDepthView = targets.objectIdDepthView != nullptr; query.resources.hasObjectIdView = targets.objectIdView != nullptr; query.resources.hasObjectIdShaderView = targets.objectIdShaderView != nullptr; query.resources.hasSelectionMaskTexture = targets.selectionMaskTexture != nullptr; query.resources.hasSelectionMaskView = targets.selectionMaskView != nullptr; query.resources.hasSelectionMaskShaderView = targets.selectionMaskShaderView != nullptr; query.resources.hasTextureDescriptor = targets.textureHandle.IsValid(); return query; } ::XCEngine::Rendering::RenderSurface BuildViewportColorSurface( const ViewportRenderTargets& targets) { return BuildViewportRenderSurface( targets.width, targets.height, targets.colorView, targets.depthView, targets.colorState); } ::XCEngine::Rendering::RenderSurface BuildViewportObjectIdSurface( const ViewportRenderTargets& targets) { return BuildViewportRenderSurface( targets.width, targets.height, targets.objectIdView, targets.objectIdDepthView, targets.objectIdState); } ::XCEngine::Rendering::RenderSurface BuildViewportSelectionMaskSurface( const ViewportRenderTargets& targets) { return BuildViewportRenderSurface( targets.width, targets.height, targets.selectionMaskView, targets.depthView, targets.selectionMaskState); } bool ViewportRenderTargetManager::EnsureTargets( const ViewportResourceRequirements& requirements, std::uint32_t width, std::uint32_t height, ::XCEngine::RHI::RHIDevice& device, Ports::ViewportRenderPort& renderHost, ViewportRenderTargets& targets) const { if (width == 0u || height == 0u) { return false; } DestroyTargets(&renderHost, targets); targets.width = width; targets.height = height; if (!CreateViewportColorResources(device, targets) || !CreateViewportDepthResources( device, targets, requirements.requiresDepthSampling) || (requirements.requiresObjectIdSurface && !CreateViewportObjectIdResources(device, targets)) || (requirements.requiresSelectionMaskSurface && !CreateViewportSelectionMaskResources(device, targets)) || !CreateViewportTextureHandle(renderHost, targets)) { DestroyTargets(&renderHost, targets); return false; } targets.colorState = ::XCEngine::RHI::ResourceStates::Common; targets.objectIdState = ::XCEngine::RHI::ResourceStates::Common; targets.selectionMaskState = ::XCEngine::RHI::ResourceStates::Common; targets.hasValidObjectIdFrame = false; return true; } void ViewportRenderTargetManager::DestroyTargets( Ports::ViewportRenderPort* renderHost, ViewportRenderTargets& targets) const { if (renderHost != nullptr && targets.textureHandle.IsValid()) { renderHost->ReleaseViewportTextureHandle(targets.textureHandle); } ShutdownAndDeleteViewportResource(targets.objectIdView); ShutdownAndDeleteViewportResource(targets.objectIdShaderView); ShutdownAndDeleteViewportResource(targets.objectIdDepthView); ShutdownAndDeleteViewportResource(targets.objectIdDepthTexture); ShutdownAndDeleteViewportResource(targets.objectIdTexture); ShutdownAndDeleteViewportResource(targets.selectionMaskView); ShutdownAndDeleteViewportResource(targets.selectionMaskShaderView); ShutdownAndDeleteViewportResource(targets.selectionMaskTexture); ShutdownAndDeleteViewportResource(targets.depthShaderView); ShutdownAndDeleteViewportResource(targets.depthView); ShutdownAndDeleteViewportResource(targets.depthTexture); ShutdownAndDeleteViewportResource(targets.colorView); ShutdownAndDeleteViewportResource(targets.colorTexture); ResetViewportTargetMetadata(targets); } } // namespace XCEngine::UI::Editor::App