268 lines
10 KiB
C++
268 lines
10 KiB
C++
|
|
#include "ProductViewportRenderTargets.h"
|
||
|
|
|
||
|
|
namespace XCEngine::UI::Editor::App {
|
||
|
|
|
||
|
|
namespace {
|
||
|
|
|
||
|
|
template <typename ResourceType>
|
||
|
|
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<std::uintptr_t>(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<std::uintptr_t>(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
|