221 lines
7.5 KiB
C++
221 lines
7.5 KiB
C++
#pragma once
|
|
|
|
#include "ViewportHostSurfaceUtils.h"
|
|
#include "UI/ImGuiBackendBridge.h"
|
|
|
|
#include <XCEngine/RHI/RHIDevice.h>
|
|
#include <XCEngine/RHI/RHIResourceView.h>
|
|
#include <XCEngine/RHI/RHITexture.h>
|
|
#include <XCEngine/UI/Types.h>
|
|
|
|
namespace XCEngine {
|
|
namespace Editor {
|
|
|
|
struct ViewportRenderTargets {
|
|
uint32_t width = 0;
|
|
uint32_t height = 0;
|
|
RHI::RHITexture* colorTexture = nullptr;
|
|
RHI::RHIResourceView* colorView = nullptr;
|
|
RHI::RHITexture* depthTexture = nullptr;
|
|
RHI::RHIResourceView* depthView = nullptr;
|
|
RHI::RHITexture* objectIdTexture = nullptr;
|
|
RHI::RHIResourceView* objectIdView = nullptr;
|
|
RHI::RHIResourceView* objectIdShaderView = nullptr;
|
|
D3D12_CPU_DESCRIPTOR_HANDLE imguiCpuHandle = {};
|
|
D3D12_GPU_DESCRIPTOR_HANDLE imguiGpuHandle = {};
|
|
::XCEngine::UI::UITextureHandle textureHandle = {};
|
|
RHI::ResourceStates colorState = RHI::ResourceStates::Common;
|
|
RHI::ResourceStates objectIdState = RHI::ResourceStates::Common;
|
|
bool hasValidObjectIdFrame = false;
|
|
};
|
|
|
|
inline ViewportHostResourceReuseQuery BuildViewportRenderTargetsReuseQuery(
|
|
EditorViewportKind kind,
|
|
const ViewportRenderTargets& targets,
|
|
uint32_t requestedWidth,
|
|
uint32_t requestedHeight) {
|
|
ViewportHostResourceReuseQuery 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.hasObjectIdTexture = targets.objectIdTexture != nullptr;
|
|
query.resources.hasObjectIdView = targets.objectIdView != nullptr;
|
|
query.resources.hasObjectIdShaderView = targets.objectIdShaderView != nullptr;
|
|
query.resources.hasTextureDescriptor = targets.textureHandle.IsValid();
|
|
return query;
|
|
}
|
|
|
|
inline Rendering::RenderSurface BuildViewportColorSurface(const ViewportRenderTargets& targets) {
|
|
return BuildViewportRenderSurface(
|
|
targets.width,
|
|
targets.height,
|
|
targets.colorView,
|
|
targets.depthView,
|
|
targets.colorState);
|
|
}
|
|
|
|
inline Rendering::RenderSurface BuildViewportObjectIdSurface(const ViewportRenderTargets& targets) {
|
|
return BuildViewportRenderSurface(
|
|
targets.width,
|
|
targets.height,
|
|
targets.objectIdView,
|
|
targets.depthView,
|
|
targets.objectIdState);
|
|
}
|
|
|
|
namespace Detail {
|
|
|
|
template <typename ResourceType>
|
|
inline void ShutdownAndDelete(ResourceType*& resource) {
|
|
if (resource == nullptr) {
|
|
return;
|
|
}
|
|
|
|
resource->Shutdown();
|
|
delete resource;
|
|
resource = nullptr;
|
|
}
|
|
|
|
inline bool CreateViewportColorResources(
|
|
RHI::RHIDevice* device,
|
|
ViewportRenderTargets& targets) {
|
|
const RHI::TextureDesc colorDesc =
|
|
BuildViewportTextureDesc(targets.width, targets.height, RHI::Format::R8G8B8A8_UNorm);
|
|
targets.colorTexture = device->CreateTexture(colorDesc);
|
|
if (targets.colorTexture == nullptr) {
|
|
return false;
|
|
}
|
|
|
|
const RHI::ResourceViewDesc colorViewDesc =
|
|
BuildViewportTextureViewDesc(RHI::Format::R8G8B8A8_UNorm);
|
|
targets.colorView = device->CreateRenderTargetView(targets.colorTexture, colorViewDesc);
|
|
return targets.colorView != nullptr;
|
|
}
|
|
|
|
inline bool CreateViewportDepthResources(
|
|
RHI::RHIDevice* device,
|
|
ViewportRenderTargets& targets) {
|
|
const RHI::TextureDesc depthDesc =
|
|
BuildViewportTextureDesc(targets.width, targets.height, RHI::Format::D24_UNorm_S8_UInt);
|
|
targets.depthTexture = device->CreateTexture(depthDesc);
|
|
if (targets.depthTexture == nullptr) {
|
|
return false;
|
|
}
|
|
|
|
const RHI::ResourceViewDesc depthViewDesc =
|
|
BuildViewportTextureViewDesc(RHI::Format::D24_UNorm_S8_UInt);
|
|
targets.depthView = device->CreateDepthStencilView(targets.depthTexture, depthViewDesc);
|
|
return targets.depthView != nullptr;
|
|
}
|
|
|
|
inline bool CreateViewportObjectIdResources(
|
|
RHI::RHIDevice* device,
|
|
ViewportRenderTargets& targets) {
|
|
const RHI::TextureDesc objectIdDesc =
|
|
BuildViewportTextureDesc(targets.width, targets.height, RHI::Format::R8G8B8A8_UNorm);
|
|
targets.objectIdTexture = device->CreateTexture(objectIdDesc);
|
|
if (targets.objectIdTexture == nullptr) {
|
|
return false;
|
|
}
|
|
|
|
const RHI::ResourceViewDesc objectIdViewDesc =
|
|
BuildViewportTextureViewDesc(RHI::Format::R8G8B8A8_UNorm);
|
|
targets.objectIdView = device->CreateRenderTargetView(
|
|
targets.objectIdTexture,
|
|
objectIdViewDesc);
|
|
if (targets.objectIdView == nullptr) {
|
|
return false;
|
|
}
|
|
|
|
targets.objectIdShaderView = device->CreateShaderResourceView(
|
|
targets.objectIdTexture,
|
|
objectIdViewDesc);
|
|
return targets.objectIdShaderView != nullptr;
|
|
}
|
|
|
|
inline bool CreateViewportTextureDescriptor(
|
|
UI::ImGuiBackendBridge* backend,
|
|
RHI::RHIDevice* device,
|
|
ViewportRenderTargets& targets) {
|
|
ImTextureID imguiTextureId = {};
|
|
if (!backend->CreateTextureDescriptor(
|
|
device,
|
|
targets.colorTexture,
|
|
&targets.imguiCpuHandle,
|
|
&targets.imguiGpuHandle,
|
|
&imguiTextureId)) {
|
|
return false;
|
|
}
|
|
|
|
targets.textureHandle.nativeHandle = static_cast<std::uintptr_t>(targets.imguiGpuHandle.ptr);
|
|
targets.textureHandle.width = targets.width;
|
|
targets.textureHandle.height = targets.height;
|
|
return true;
|
|
}
|
|
|
|
} // namespace Detail
|
|
|
|
inline void DestroyViewportRenderTargets(
|
|
UI::ImGuiBackendBridge* backend,
|
|
ViewportRenderTargets& targets) {
|
|
if (backend != nullptr && targets.imguiCpuHandle.ptr != 0) {
|
|
backend->FreeTextureDescriptor(targets.imguiCpuHandle, targets.imguiGpuHandle);
|
|
}
|
|
|
|
Detail::ShutdownAndDelete(targets.objectIdView);
|
|
Detail::ShutdownAndDelete(targets.objectIdShaderView);
|
|
Detail::ShutdownAndDelete(targets.objectIdTexture);
|
|
Detail::ShutdownAndDelete(targets.depthView);
|
|
Detail::ShutdownAndDelete(targets.depthTexture);
|
|
Detail::ShutdownAndDelete(targets.colorView);
|
|
Detail::ShutdownAndDelete(targets.colorTexture);
|
|
|
|
targets.width = 0;
|
|
targets.height = 0;
|
|
targets.imguiCpuHandle = {};
|
|
targets.imguiGpuHandle = {};
|
|
targets.textureHandle = {};
|
|
targets.colorState = RHI::ResourceStates::Common;
|
|
targets.objectIdState = RHI::ResourceStates::Common;
|
|
targets.hasValidObjectIdFrame = false;
|
|
}
|
|
|
|
inline bool CreateViewportRenderTargets(
|
|
EditorViewportKind kind,
|
|
uint32_t width,
|
|
uint32_t height,
|
|
RHI::RHIDevice* device,
|
|
UI::ImGuiBackendBridge* backend,
|
|
ViewportRenderTargets& targets) {
|
|
if (width == 0 || height == 0 || device == nullptr || backend == nullptr) {
|
|
return false;
|
|
}
|
|
|
|
DestroyViewportRenderTargets(backend, targets);
|
|
targets.width = width;
|
|
targets.height = height;
|
|
|
|
if (!Detail::CreateViewportColorResources(device, targets) ||
|
|
!Detail::CreateViewportDepthResources(device, targets) ||
|
|
(ViewportRequiresObjectIdResources(kind) &&
|
|
!Detail::CreateViewportObjectIdResources(device, targets)) ||
|
|
!Detail::CreateViewportTextureDescriptor(backend, device, targets)) {
|
|
DestroyViewportRenderTargets(backend, targets);
|
|
return false;
|
|
}
|
|
|
|
targets.colorState = RHI::ResourceStates::Common;
|
|
targets.objectIdState = RHI::ResourceStates::Common;
|
|
targets.hasValidObjectIdFrame = false;
|
|
return true;
|
|
}
|
|
|
|
} // namespace Editor
|
|
} // namespace XCEngine
|