#include "ProductViewportRenderTargets.h" namespace XCEngine::UI::Editor::App { namespace { template void ShutdownAndDeleteViewportResource(ResourceType*& resource) { if (resource == nullptr) { return; } resource->Shutdown(); delete resource; resource = nullptr; } bool CreateViewportColorResources( ::XCEngine::RHI::RHIDevice& device, ProductViewportRenderTargets& targets) { const auto colorDesc = BuildProductViewportTextureDesc(targets.width, targets.height, ::XCEngine::RHI::Format::R8G8B8A8_UNorm); targets.colorTexture = device.CreateTexture(colorDesc); if (targets.colorTexture == nullptr) { return false; } const auto colorViewDesc = BuildProductViewportTextureViewDesc(::XCEngine::RHI::Format::R8G8B8A8_UNorm); targets.colorView = device.CreateRenderTargetView(targets.colorTexture, colorViewDesc); return targets.colorView != nullptr; } bool CreateViewportDepthResources( ::XCEngine::RHI::RHIDevice& device, ProductViewportRenderTargets& targets) { const auto depthDesc = BuildProductViewportTextureDesc(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 = BuildProductViewportTextureViewDesc(::XCEngine::RHI::Format::D24_UNorm_S8_UInt); targets.depthView = device.CreateDepthStencilView(targets.depthTexture, depthViewDesc); if (targets.depthView == nullptr) { return false; } ::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, ProductViewportRenderTargets& targets) { const auto objectIdDesc = BuildProductViewportTextureDesc(targets.width, targets.height, ::XCEngine::RHI::Format::R8G8B8A8_UNorm); targets.objectIdTexture = device.CreateTexture(objectIdDesc); if (targets.objectIdTexture == nullptr) { return false; } const auto objectIdViewDesc = BuildProductViewportTextureViewDesc(::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 = BuildProductViewportTextureDesc(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 = BuildProductViewportTextureViewDesc(::XCEngine::RHI::Format::D24_UNorm_S8_UInt); targets.objectIdDepthView = device.CreateDepthStencilView( targets.objectIdDepthTexture, objectIdDepthViewDesc); return targets.objectIdDepthView != nullptr; } bool CreateViewportSelectionMaskResources( ::XCEngine::RHI::RHIDevice& device, ProductViewportRenderTargets& targets) { const auto selectionMaskDesc = BuildProductViewportTextureDesc(targets.width, targets.height, ::XCEngine::RHI::Format::R8G8B8A8_UNorm); targets.selectionMaskTexture = device.CreateTexture(selectionMaskDesc); if (targets.selectionMaskTexture == nullptr) { return false; } const auto selectionMaskViewDesc = BuildProductViewportTextureViewDesc(::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 CreateViewportTextureDescriptor( Host::D3D12ShaderResourceDescriptorAllocator& textureDescriptorAllocator, ProductViewportRenderTargets& targets) { if (!textureDescriptorAllocator.CreateTextureDescriptor( targets.colorTexture, &targets.srvCpuHandle, &targets.srvGpuHandle)) { return false; } targets.textureHandle.nativeHandle = static_cast(targets.srvGpuHandle.ptr); targets.textureHandle.width = targets.width; targets.textureHandle.height = targets.height; targets.textureHandle.kind = ::XCEngine::UI::UITextureHandleKind::ShaderResourceView; targets.textureHandle.resourceHandle = reinterpret_cast(targets.colorTexture); return true; } } // namespace ProductViewportResourceReuseQuery BuildProductViewportRenderTargetsReuseQuery( ProductViewportKind kind, const ProductViewportRenderTargets& targets, std::uint32_t requestedWidth, std::uint32_t requestedHeight) { ProductViewportResourceReuseQuery query = {}; query.kind = kind; 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 BuildProductViewportColorSurface( const ProductViewportRenderTargets& targets) { return BuildProductViewportRenderSurface( targets.width, targets.height, targets.colorView, targets.depthView, targets.colorState); } ::XCEngine::Rendering::RenderSurface BuildProductViewportObjectIdSurface( const ProductViewportRenderTargets& targets) { return BuildProductViewportRenderSurface( targets.width, targets.height, targets.objectIdView, targets.objectIdDepthView, targets.objectIdState); } ::XCEngine::Rendering::RenderSurface BuildProductViewportSelectionMaskSurface( const ProductViewportRenderTargets& targets) { return BuildProductViewportRenderSurface( targets.width, targets.height, targets.selectionMaskView, targets.depthView, targets.selectionMaskState); } bool ProductViewportRenderTargetManager::EnsureTargets( ProductViewportKind kind, std::uint32_t width, std::uint32_t height, ::XCEngine::RHI::RHIDevice& device, Host::D3D12ShaderResourceDescriptorAllocator& textureDescriptorAllocator, ProductViewportRenderTargets& targets) const { if (width == 0u || height == 0u) { return false; } DestroyTargets(&textureDescriptorAllocator, targets); targets.width = width; targets.height = height; if (!CreateViewportColorResources(device, targets) || !CreateViewportDepthResources(device, targets) || (ProductViewportRequiresObjectIdResources(kind) && (!CreateViewportObjectIdResources(device, targets) || !CreateViewportSelectionMaskResources(device, targets))) || !CreateViewportTextureDescriptor(textureDescriptorAllocator, targets)) { DestroyTargets(&textureDescriptorAllocator, 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 ProductViewportRenderTargetManager::DestroyTargets( Host::D3D12ShaderResourceDescriptorAllocator* textureDescriptorAllocator, ProductViewportRenderTargets& targets) const { if (textureDescriptorAllocator != nullptr && targets.srvCpuHandle.ptr != 0) { textureDescriptorAllocator->Free(targets.srvCpuHandle, targets.srvGpuHandle); } 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); targets.width = 0; targets.height = 0; targets.srvCpuHandle = {}; targets.srvGpuHandle = {}; targets.textureHandle = {}; targets.colorState = ::XCEngine::RHI::ResourceStates::Common; targets.objectIdState = ::XCEngine::RHI::ResourceStates::Common; targets.selectionMaskState = ::XCEngine::RHI::ResourceStates::Common; targets.hasValidObjectIdFrame = false; } } // namespace XCEngine::UI::Editor::App