Separate viewport target and descriptor ownership

This commit is contained in:
2026-04-13 19:57:25 +08:00
parent f3fc34898a
commit 5b89c2bb76
10 changed files with 534 additions and 433 deletions

View File

@@ -175,4 +175,6 @@
1. 已新增 `HostRuntimeState`,把宿主 DPI / interactive resize / pending resize / deferred render 状态从 `Application` 中抽离。 1. 已新增 `HostRuntimeState`,把宿主 DPI / interactive resize / pending resize / deferred render 状态从 `Application` 中抽离。
2. 已新增 `WindowMessageDispatcher`,把 `WndProc` 中的宿主消息调度与 deferred render 调度拆到 `Host` 层。 2. 已新增 `WindowMessageDispatcher`,把 `WndProc` 中的宿主消息调度与 deferred render 调度拆到 `Host` 层。
3. 已把 `D3D12WindowRenderLoop` 从悬空 helper 升级为主窗口帧编排入口,开始统一 `BeginFrame / viewport render / UI present / fallback / resize interop` 这条链。 3. 已把 `D3D12WindowRenderLoop` 从悬空 helper 升级为主窗口帧编排入口,开始统一 `BeginFrame / viewport render / UI present / fallback / resize interop` 这条链。
4. 下一步进入阶段 2 主体:继续拆 `NativeRenderer` 中的窗口互操作 / present 组合路径,并把 viewport render target 生命周期从 `ProductViewportHostService` 中收出去。 4. 已把 viewport render target 资源工厂从 `ProductViewportRenderTargets.h` 收成独立 manager`ProductViewportHostService` 只保留请求/返回 frame 的业务外壳。
5. 已把 shader resource descriptor 分配职责从 `D3D12WindowRenderer` 抽到独立的 `D3D12ShaderResourceDescriptorAllocator`,减少窗口呈现器的非 swapchain 职责。
6. 下一步进入阶段 2 主体:继续拆 `NativeRenderer` 中的窗口互操作 / present 组合路径,把 D2D UI 光栅化与 D3D11On12 窗口合成进一步分离。

View File

@@ -124,6 +124,7 @@ target_link_libraries(XCUIEditorLib PUBLIC
add_library(XCUIEditorHost STATIC add_library(XCUIEditorHost STATIC
app/Host/AutoScreenshot.cpp app/Host/AutoScreenshot.cpp
app/Host/D3D12ShaderResourceDescriptorAllocator.cpp
app/Host/D3D12WindowRenderer.cpp app/Host/D3D12WindowRenderer.cpp
app/Host/D3D12WindowRenderLoop.cpp app/Host/D3D12WindowRenderLoop.cpp
app/Host/NativeRenderer.cpp app/Host/NativeRenderer.cpp
@@ -166,6 +167,7 @@ if(XCENGINE_BUILD_XCUI_EDITOR_APP)
app/Project/ProductProjectBrowserModel.cpp app/Project/ProductProjectBrowserModel.cpp
app/Shell/ProductShellAsset.cpp app/Shell/ProductShellAsset.cpp
app/Viewport/ProductViewportHostService.cpp app/Viewport/ProductViewportHostService.cpp
app/Viewport/ProductViewportRenderTargetManager.cpp
app/Viewport/ProductViewportRenderTargets.cpp app/Viewport/ProductViewportRenderTargets.cpp
app/Workspace/ProductEditorWorkspace.cpp app/Workspace/ProductEditorWorkspace.cpp
app/Workspace/ProductEditorWorkspaceEventRouter.cpp app/Workspace/ProductEditorWorkspaceEventRouter.cpp

View File

@@ -0,0 +1,169 @@
#include "D3D12ShaderResourceDescriptorAllocator.h"
#include <XCEngine/RHI/RHITypes.h>
namespace XCEngine::UI::Editor::Host {
namespace {
using ::XCEngine::RHI::D3D12DescriptorHeap;
using ::XCEngine::RHI::D3D12Device;
using ::XCEngine::RHI::D3D12Texture;
using ::XCEngine::RHI::DescriptorHeapType;
using ::XCEngine::RHI::DescriptorPoolDesc;
using ::XCEngine::RHI::RHIDevice;
using ::XCEngine::RHI::RHITexture;
} // namespace
bool D3D12ShaderResourceDescriptorAllocator::Initialize(RHIDevice& device, UINT descriptorCount) {
Shutdown();
DescriptorPoolDesc descriptorPoolDesc = {};
descriptorPoolDesc.type = DescriptorHeapType::CBV_SRV_UAV;
descriptorPoolDesc.descriptorCount = descriptorCount;
descriptorPoolDesc.shaderVisible = true;
m_descriptorPool = device.CreateDescriptorPool(descriptorPoolDesc);
m_descriptorHeap = dynamic_cast<D3D12DescriptorHeap*>(m_descriptorPool);
if (m_descriptorPool == nullptr || m_descriptorHeap == nullptr) {
Shutdown();
return false;
}
m_device = &device;
m_descriptorSize = m_descriptorHeap->GetDescriptorSize();
m_descriptorCount = descriptorCount;
m_descriptorUsage.assign(descriptorCount, false);
return true;
}
void D3D12ShaderResourceDescriptorAllocator::Shutdown() {
if (m_descriptorPool != nullptr) {
m_descriptorPool->Shutdown();
delete m_descriptorPool;
m_descriptorPool = nullptr;
}
m_device = nullptr;
m_descriptorHeap = nullptr;
m_descriptorUsage.clear();
m_descriptorSize = 0u;
m_descriptorCount = 0u;
}
bool D3D12ShaderResourceDescriptorAllocator::IsInitialized() const {
return m_device != nullptr &&
m_descriptorHeap != nullptr &&
m_descriptorSize > 0u &&
!m_descriptorUsage.empty();
}
ID3D12DescriptorHeap* D3D12ShaderResourceDescriptorAllocator::GetDescriptorHeap() const {
return m_descriptorHeap != nullptr ? m_descriptorHeap->GetDescriptorHeap() : nullptr;
}
UINT D3D12ShaderResourceDescriptorAllocator::GetDescriptorSize() const {
return m_descriptorSize;
}
UINT D3D12ShaderResourceDescriptorAllocator::GetDescriptorCount() const {
return m_descriptorCount;
}
void D3D12ShaderResourceDescriptorAllocator::Allocate(
D3D12_CPU_DESCRIPTOR_HANDLE* outCpuHandle,
D3D12_GPU_DESCRIPTOR_HANDLE* outGpuHandle) {
AllocateInternal(outCpuHandle, outGpuHandle);
}
bool D3D12ShaderResourceDescriptorAllocator::CreateTextureDescriptor(
RHITexture* texture,
D3D12_CPU_DESCRIPTOR_HANDLE* outCpuHandle,
D3D12_GPU_DESCRIPTOR_HANDLE* outGpuHandle) {
if (m_device == nullptr ||
texture == nullptr ||
outCpuHandle == nullptr ||
outGpuHandle == nullptr) {
return false;
}
*outCpuHandle = {};
*outGpuHandle = {};
auto* nativeDevice = dynamic_cast<D3D12Device*>(m_device);
auto* nativeTexture = dynamic_cast<D3D12Texture*>(texture);
if (nativeDevice == nullptr ||
nativeTexture == nullptr ||
nativeTexture->GetResource() == nullptr) {
return false;
}
AllocateInternal(outCpuHandle, outGpuHandle);
if (outCpuHandle->ptr == 0 || outGpuHandle->ptr == 0) {
*outCpuHandle = {};
*outGpuHandle = {};
return false;
}
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
srvDesc.Texture2D.MipLevels = 1;
nativeDevice->GetDevice()->CreateShaderResourceView(
nativeTexture->GetResource(),
&srvDesc,
*outCpuHandle);
return true;
}
void D3D12ShaderResourceDescriptorAllocator::Free(
D3D12_CPU_DESCRIPTOR_HANDLE cpuHandle,
D3D12_GPU_DESCRIPTOR_HANDLE) {
if (m_descriptorHeap == nullptr ||
m_descriptorSize == 0u ||
cpuHandle.ptr < m_descriptorHeap->GetCPUDescriptorHandleForHeapStart().ptr) {
return;
}
const SIZE_T offset =
cpuHandle.ptr - m_descriptorHeap->GetCPUDescriptorHandleForHeapStart().ptr;
const std::size_t index =
static_cast<std::size_t>(offset / m_descriptorSize);
if (index < m_descriptorUsage.size()) {
m_descriptorUsage[index] = false;
}
}
void D3D12ShaderResourceDescriptorAllocator::AllocateInternal(
D3D12_CPU_DESCRIPTOR_HANDLE* outCpuHandle,
D3D12_GPU_DESCRIPTOR_HANDLE* outGpuHandle) {
if (outCpuHandle == nullptr || outGpuHandle == nullptr) {
return;
}
*outCpuHandle = {};
*outGpuHandle = {};
if (m_descriptorHeap == nullptr ||
m_descriptorSize == 0u ||
m_descriptorUsage.empty()) {
return;
}
for (std::size_t index = 0; index < m_descriptorUsage.size(); ++index) {
if (m_descriptorUsage[index]) {
continue;
}
m_descriptorUsage[index] = true;
outCpuHandle->ptr =
m_descriptorHeap->GetCPUDescriptorHandleForHeapStart().ptr +
static_cast<SIZE_T>(index) * m_descriptorSize;
outGpuHandle->ptr =
m_descriptorHeap->GetGPUDescriptorHandleForHeapStart().ptr +
static_cast<UINT64>(index) * m_descriptorSize;
return;
}
}
} // namespace XCEngine::UI::Editor::Host

View File

@@ -0,0 +1,55 @@
#pragma once
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <XCEngine/RHI/D3D12/D3D12DescriptorHeap.h>
#include <XCEngine/RHI/D3D12/D3D12Device.h>
#include <XCEngine/RHI/D3D12/D3D12Texture.h>
#include <XCEngine/RHI/RHIDescriptorPool.h>
#include <XCEngine/RHI/RHIDevice.h>
#include <XCEngine/RHI/RHITexture.h>
#include <d3d12.h>
#include <windows.h>
#include <vector>
namespace XCEngine::UI::Editor::Host {
class D3D12ShaderResourceDescriptorAllocator {
public:
bool Initialize(::XCEngine::RHI::RHIDevice& device, UINT descriptorCount = 64u);
void Shutdown();
bool IsInitialized() const;
ID3D12DescriptorHeap* GetDescriptorHeap() const;
UINT GetDescriptorSize() const;
UINT GetDescriptorCount() const;
void Allocate(
D3D12_CPU_DESCRIPTOR_HANDLE* outCpuHandle,
D3D12_GPU_DESCRIPTOR_HANDLE* outGpuHandle);
bool CreateTextureDescriptor(
::XCEngine::RHI::RHITexture* texture,
D3D12_CPU_DESCRIPTOR_HANDLE* outCpuHandle,
D3D12_GPU_DESCRIPTOR_HANDLE* outGpuHandle);
void Free(
D3D12_CPU_DESCRIPTOR_HANDLE cpuHandle,
D3D12_GPU_DESCRIPTOR_HANDLE gpuHandle);
private:
void AllocateInternal(
D3D12_CPU_DESCRIPTOR_HANDLE* outCpuHandle,
D3D12_GPU_DESCRIPTOR_HANDLE* outGpuHandle);
::XCEngine::RHI::RHIDevice* m_device = nullptr;
::XCEngine::RHI::RHIDescriptorPool* m_descriptorPool = nullptr;
::XCEngine::RHI::D3D12DescriptorHeap* m_descriptorHeap = nullptr;
std::vector<bool> m_descriptorUsage = {};
UINT m_descriptorSize = 0u;
UINT m_descriptorCount = 0u;
};
} // namespace XCEngine::UI::Editor::Host

View File

@@ -8,11 +8,8 @@ namespace XCEngine::UI::Editor::Host {
using ::XCEngine::RHI::CommandListDesc; using ::XCEngine::RHI::CommandListDesc;
using ::XCEngine::RHI::CommandQueueDesc; using ::XCEngine::RHI::CommandQueueDesc;
using ::XCEngine::RHI::DescriptorHeapType;
using ::XCEngine::RHI::DescriptorPoolDesc;
using ::XCEngine::RHI::D3D12CommandList; using ::XCEngine::RHI::D3D12CommandList;
using ::XCEngine::RHI::D3D12CommandQueue; using ::XCEngine::RHI::D3D12CommandQueue;
using ::XCEngine::RHI::D3D12DescriptorHeap;
using ::XCEngine::RHI::D3D12Device; using ::XCEngine::RHI::D3D12Device;
using ::XCEngine::RHI::D3D12SwapChain; using ::XCEngine::RHI::D3D12SwapChain;
using ::XCEngine::RHI::D3D12Texture; using ::XCEngine::RHI::D3D12Texture;
@@ -101,20 +98,6 @@ bool D3D12WindowRenderer::Initialize(HWND hwnd, int width, int height) {
return false; return false;
} }
DescriptorPoolDesc srvPoolDesc = {};
srvPoolDesc.type = DescriptorHeapType::CBV_SRV_UAV;
srvPoolDesc.descriptorCount = kSrvDescriptorCount;
srvPoolDesc.shaderVisible = true;
m_srvPool = m_device->CreateDescriptorPool(srvPoolDesc);
m_srvHeap = dynamic_cast<D3D12DescriptorHeap*>(m_srvPool);
if (m_srvPool == nullptr || m_srvHeap == nullptr) {
m_lastError = "Failed to create the D3D12 SRV descriptor heap.";
Shutdown();
return false;
}
m_srvDescriptorSize = m_srvHeap->GetDescriptorSize();
m_srvUsage.assign(kSrvDescriptorCount, false);
if (!RecreateBackBufferViews()) { if (!RecreateBackBufferViews()) {
m_lastError = "Failed to create swap chain back buffer views."; m_lastError = "Failed to create swap chain back buffer views.";
Shutdown(); Shutdown();
@@ -137,14 +120,6 @@ void D3D12WindowRenderer::Shutdown() {
ReleaseFrameCompletionFence(); ReleaseFrameCompletionFence();
ReleaseBackBufferViews(); ReleaseBackBufferViews();
if (m_srvPool != nullptr) {
m_srvPool->Shutdown();
delete m_srvPool;
m_srvPool = nullptr;
}
m_srvHeap = nullptr;
m_srvUsage.clear();
if (m_swapChain != nullptr) { if (m_swapChain != nullptr) {
m_swapChain->Shutdown(); m_swapChain->Shutdown();
delete m_swapChain; delete m_swapChain;
@@ -175,7 +150,6 @@ void D3D12WindowRenderer::Shutdown() {
m_width = 0; m_width = 0;
m_height = 0; m_height = 0;
m_activeBackBufferIndex = 0u; m_activeBackBufferIndex = 0u;
m_srvDescriptorSize = 0;
m_lastError.clear(); m_lastError.clear();
} }
@@ -250,8 +224,8 @@ bool D3D12WindowRenderer::Resize(int width, int height) {
} }
bool D3D12WindowRenderer::BeginFrame() { bool D3D12WindowRenderer::BeginFrame() {
if (m_swapChain == nullptr || m_srvHeap == nullptr) { if (m_swapChain == nullptr) {
m_lastError = "BeginFrame requires a swap chain, command list, and SRV heap."; m_lastError = "BeginFrame requires an initialized swap chain.";
return false; return false;
} }
@@ -355,10 +329,6 @@ ID3D12Device* D3D12WindowRenderer::GetDevice() const {
return device != nullptr ? device->GetDevice() : nullptr; return device != nullptr ? device->GetDevice() : nullptr;
} }
ID3D12DescriptorHeap* D3D12WindowRenderer::GetSrvHeap() const {
return m_srvHeap != nullptr ? m_srvHeap->GetDescriptorHeap() : nullptr;
}
ID3D12CommandQueue* D3D12WindowRenderer::GetCommandQueue() const { ID3D12CommandQueue* D3D12WindowRenderer::GetCommandQueue() const {
const D3D12CommandQueue* queue = GetD3D12CommandQueue(); const D3D12CommandQueue* queue = GetD3D12CommandQueue();
return queue != nullptr ? queue->GetCommandQueue() : nullptr; return queue != nullptr ? queue->GetCommandQueue() : nullptr;
@@ -368,68 +338,6 @@ const std::string& D3D12WindowRenderer::GetLastError() const {
return m_lastError; return m_lastError;
} }
void D3D12WindowRenderer::AllocateShaderResourceDescriptor(
D3D12_CPU_DESCRIPTOR_HANDLE* outCpuHandle,
D3D12_GPU_DESCRIPTOR_HANDLE* outGpuHandle) {
AllocateShaderResourceDescriptorInternal(outCpuHandle, outGpuHandle);
}
bool D3D12WindowRenderer::CreateShaderResourceTextureDescriptor(
RHIDevice* device,
::XCEngine::RHI::RHITexture* texture,
D3D12_CPU_DESCRIPTOR_HANDLE* outCpuHandle,
D3D12_GPU_DESCRIPTOR_HANDLE* outGpuHandle) {
if (device == nullptr ||
texture == nullptr ||
outCpuHandle == nullptr ||
outGpuHandle == nullptr) {
return false;
}
*outCpuHandle = {};
*outGpuHandle = {};
auto* nativeDevice = dynamic_cast<D3D12Device*>(device);
auto* nativeTexture = dynamic_cast<D3D12Texture*>(texture);
if (nativeDevice == nullptr ||
nativeTexture == nullptr ||
nativeTexture->GetResource() == nullptr) {
return false;
}
AllocateShaderResourceDescriptorInternal(outCpuHandle, outGpuHandle);
if (outCpuHandle->ptr == 0 || outGpuHandle->ptr == 0) {
*outCpuHandle = {};
*outGpuHandle = {};
return false;
}
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
srvDesc.Texture2D.MipLevels = 1;
nativeDevice->GetDevice()->CreateShaderResourceView(
nativeTexture->GetResource(),
&srvDesc,
*outCpuHandle);
return true;
}
void D3D12WindowRenderer::FreeShaderResourceDescriptor(
D3D12_CPU_DESCRIPTOR_HANDLE cpuHandle,
D3D12_GPU_DESCRIPTOR_HANDLE gpuHandle) {
FreeShaderResourceDescriptorInternal(cpuHandle, gpuHandle);
}
UINT D3D12WindowRenderer::GetSrvDescriptorSize() const {
return m_srvDescriptorSize;
}
UINT D3D12WindowRenderer::GetSrvDescriptorCount() const {
return kSrvDescriptorCount;
}
RHIDevice* D3D12WindowRenderer::GetRHIDevice() const { RHIDevice* D3D12WindowRenderer::GetRHIDevice() const {
return m_device; return m_device;
} }
@@ -504,55 +412,6 @@ D3D12SwapChain* D3D12WindowRenderer::GetD3D12SwapChain() const {
: nullptr; : nullptr;
} }
void D3D12WindowRenderer::AllocateShaderResourceDescriptorInternal(
D3D12_CPU_DESCRIPTOR_HANDLE* outCpuHandle,
D3D12_GPU_DESCRIPTOR_HANDLE* outGpuHandle) {
if (outCpuHandle == nullptr || outGpuHandle == nullptr) {
return;
}
*outCpuHandle = {};
*outGpuHandle = {};
if (m_srvHeap == nullptr ||
m_srvDescriptorSize == 0 ||
m_srvUsage.empty()) {
return;
}
for (std::size_t index = 0; index < m_srvUsage.size(); ++index) {
if (m_srvUsage[index]) {
continue;
}
m_srvUsage[index] = true;
outCpuHandle->ptr =
m_srvHeap->GetCPUDescriptorHandleForHeapStart().ptr +
static_cast<SIZE_T>(index) * m_srvDescriptorSize;
outGpuHandle->ptr =
m_srvHeap->GetGPUDescriptorHandleForHeapStart().ptr +
static_cast<UINT64>(index) * m_srvDescriptorSize;
return;
}
}
void D3D12WindowRenderer::FreeShaderResourceDescriptorInternal(
D3D12_CPU_DESCRIPTOR_HANDLE cpuHandle,
D3D12_GPU_DESCRIPTOR_HANDLE) {
if (m_srvHeap == nullptr ||
m_srvDescriptorSize == 0 ||
cpuHandle.ptr < m_srvHeap->GetCPUDescriptorHandleForHeapStart().ptr) {
return;
}
const SIZE_T offset =
cpuHandle.ptr - m_srvHeap->GetCPUDescriptorHandleForHeapStart().ptr;
const std::size_t index =
static_cast<std::size_t>(offset / m_srvDescriptorSize);
if (index < m_srvUsage.size()) {
m_srvUsage[index] = false;
}
}
bool D3D12WindowRenderer::InitializeFrameCompletionFence() { bool D3D12WindowRenderer::InitializeFrameCompletionFence() {
ReleaseFrameCompletionFence(); ReleaseFrameCompletionFence();

View File

@@ -8,7 +8,6 @@
#include <XCEngine/Rendering/RenderSurface.h> #include <XCEngine/Rendering/RenderSurface.h>
#include <XCEngine/RHI/D3D12/D3D12CommandList.h> #include <XCEngine/RHI/D3D12/D3D12CommandList.h>
#include <XCEngine/RHI/D3D12/D3D12CommandQueue.h> #include <XCEngine/RHI/D3D12/D3D12CommandQueue.h>
#include <XCEngine/RHI/D3D12/D3D12DescriptorHeap.h>
#include <XCEngine/RHI/D3D12/D3D12Device.h> #include <XCEngine/RHI/D3D12/D3D12Device.h>
#include <XCEngine/RHI/D3D12/D3D12SwapChain.h> #include <XCEngine/RHI/D3D12/D3D12SwapChain.h>
#include <XCEngine/RHI/D3D12/D3D12Texture.h> #include <XCEngine/RHI/D3D12/D3D12Texture.h>
@@ -32,7 +31,6 @@ namespace XCEngine::UI::Editor::Host {
class D3D12WindowRenderer { class D3D12WindowRenderer {
public: public:
static constexpr UINT kSrvDescriptorCount = 64;
static constexpr std::uint32_t kSwapChainBufferCount = 3; static constexpr std::uint32_t kSwapChainBufferCount = 3;
bool Initialize(HWND hwnd, int width, int height); bool Initialize(HWND hwnd, int width, int height);
@@ -45,22 +43,8 @@ public:
bool PresentFrame(); bool PresentFrame();
ID3D12Device* GetDevice() const; ID3D12Device* GetDevice() const;
ID3D12DescriptorHeap* GetSrvHeap() const;
ID3D12CommandQueue* GetCommandQueue() const; ID3D12CommandQueue* GetCommandQueue() const;
const std::string& GetLastError() const; const std::string& GetLastError() const;
void AllocateShaderResourceDescriptor(
D3D12_CPU_DESCRIPTOR_HANDLE* outCpuHandle,
D3D12_GPU_DESCRIPTOR_HANDLE* outGpuHandle);
bool CreateShaderResourceTextureDescriptor(
::XCEngine::RHI::RHIDevice* device,
::XCEngine::RHI::RHITexture* texture,
D3D12_CPU_DESCRIPTOR_HANDLE* outCpuHandle,
D3D12_GPU_DESCRIPTOR_HANDLE* outGpuHandle);
void FreeShaderResourceDescriptor(
D3D12_CPU_DESCRIPTOR_HANDLE cpuHandle,
D3D12_GPU_DESCRIPTOR_HANDLE gpuHandle);
UINT GetSrvDescriptorSize() const;
UINT GetSrvDescriptorCount() const;
::XCEngine::RHI::RHIDevice* GetRHIDevice() const; ::XCEngine::RHI::RHIDevice* GetRHIDevice() const;
::XCEngine::RHI::RHISwapChain* GetSwapChain() const; ::XCEngine::RHI::RHISwapChain* GetSwapChain() const;
const ::XCEngine::Rendering::RenderSurface* GetCurrentRenderSurface() const; const ::XCEngine::Rendering::RenderSurface* GetCurrentRenderSurface() const;
@@ -75,12 +59,6 @@ private:
::XCEngine::RHI::D3D12CommandList* GetD3D12CommandList() const; ::XCEngine::RHI::D3D12CommandList* GetD3D12CommandList() const;
::XCEngine::RHI::D3D12SwapChain* GetD3D12SwapChain() const; ::XCEngine::RHI::D3D12SwapChain* GetD3D12SwapChain() const;
::XCEngine::RHI::RHICommandList* GetCurrentCommandList() const; ::XCEngine::RHI::RHICommandList* GetCurrentCommandList() const;
void AllocateShaderResourceDescriptorInternal(
D3D12_CPU_DESCRIPTOR_HANDLE* outCpuHandle,
D3D12_GPU_DESCRIPTOR_HANDLE* outGpuHandle);
void FreeShaderResourceDescriptorInternal(
D3D12_CPU_DESCRIPTOR_HANDLE cpuHandle,
D3D12_GPU_DESCRIPTOR_HANDLE gpuHandle);
bool InitializeFrameCompletionFence(); bool InitializeFrameCompletionFence();
void ReleaseFrameCompletionFence(); void ReleaseFrameCompletionFence();
void WaitForBackBufferFrame(std::uint32_t backBufferIndex); void WaitForBackBufferFrame(std::uint32_t backBufferIndex);
@@ -97,9 +75,6 @@ private:
::XCEngine::RHI::RHICommandQueue* m_commandQueue = nullptr; ::XCEngine::RHI::RHICommandQueue* m_commandQueue = nullptr;
std::array<::XCEngine::RHI::RHICommandList*, kSwapChainBufferCount> m_commandLists = {}; std::array<::XCEngine::RHI::RHICommandList*, kSwapChainBufferCount> m_commandLists = {};
::XCEngine::RHI::RHISwapChain* m_swapChain = nullptr; ::XCEngine::RHI::RHISwapChain* m_swapChain = nullptr;
::XCEngine::RHI::RHIDescriptorPool* m_srvPool = nullptr;
::XCEngine::RHI::D3D12DescriptorHeap* m_srvHeap = nullptr;
std::vector<bool> m_srvUsage = {};
std::vector<::XCEngine::RHI::RHIResourceView*> m_backBufferViews = {}; std::vector<::XCEngine::RHI::RHIResourceView*> m_backBufferViews = {};
std::vector<::XCEngine::Rendering::RenderSurface> m_backBufferSurfaces = {}; std::vector<::XCEngine::Rendering::RenderSurface> m_backBufferSurfaces = {};
Microsoft::WRL::ComPtr<ID3D12Fence> m_frameCompletionFence = {}; Microsoft::WRL::ComPtr<ID3D12Fence> m_frameCompletionFence = {};
@@ -108,7 +83,6 @@ private:
std::uint32_t m_activeBackBufferIndex = 0u; std::uint32_t m_activeBackBufferIndex = 0u;
std::uint64_t m_lastSubmittedFrameValue = 0; std::uint64_t m_lastSubmittedFrameValue = 0;
std::string m_lastError = {}; std::string m_lastError = {};
UINT m_srvDescriptorSize = 0;
}; };
} // namespace XCEngine::UI::Editor::Host } // namespace XCEngine::UI::Editor::Host

View File

@@ -14,12 +14,18 @@ void ProductViewportHostService::AttachWindowRenderer(
Host::D3D12WindowRenderer& windowRenderer) { Host::D3D12WindowRenderer& windowRenderer) {
if (m_windowRenderer == &windowRenderer) { if (m_windowRenderer == &windowRenderer) {
m_device = windowRenderer.GetRHIDevice(); m_device = windowRenderer.GetRHIDevice();
if (m_device != nullptr && !m_textureDescriptorAllocator.IsInitialized()) {
m_textureDescriptorAllocator.Initialize(*m_device);
}
return; return;
} }
Shutdown(); Shutdown();
m_windowRenderer = &windowRenderer; m_windowRenderer = &windowRenderer;
m_device = windowRenderer.GetRHIDevice(); m_device = windowRenderer.GetRHIDevice();
if (m_device != nullptr) {
m_textureDescriptorAllocator.Initialize(*m_device);
}
} }
void ProductViewportHostService::DetachWindowRenderer() { void ProductViewportHostService::DetachWindowRenderer() {
@@ -35,6 +41,7 @@ void ProductViewportHostService::Shutdown() {
DestroyViewportEntry(entry); DestroyViewportEntry(entry);
} }
m_textureDescriptorAllocator.Shutdown();
m_windowRenderer = nullptr; m_windowRenderer = nullptr;
m_device = nullptr; m_device = nullptr;
m_surfacePresentationEnabled = false; m_surfacePresentationEnabled = false;
@@ -113,7 +120,7 @@ const ProductViewportHostService::ViewportEntry& ProductViewportHostService::Get
} }
void ProductViewportHostService::DestroyViewportEntry(ViewportEntry& entry) { void ProductViewportHostService::DestroyViewportEntry(ViewportEntry& entry) {
DestroyProductViewportRenderTargets(m_windowRenderer, entry.renderTargets); m_renderTargetManager.DestroyTargets(&m_textureDescriptorAllocator, entry.renderTargets);
entry = {}; entry = {};
} }
@@ -135,12 +142,12 @@ bool ProductViewportHostService::EnsureViewportResources(ViewportEntry& entry) {
return false; return false;
} }
return CreateProductViewportRenderTargets( return m_renderTargetManager.EnsureTargets(
entry.kind, entry.kind,
entry.requestedWidth, entry.requestedWidth,
entry.requestedHeight, entry.requestedHeight,
m_device, *m_device,
*m_windowRenderer, m_textureDescriptorAllocator,
entry.renderTargets); entry.renderTargets);
} }

View File

@@ -3,6 +3,7 @@
#include "ProductViewportRenderTargets.h" #include "ProductViewportRenderTargets.h"
#include <Host/D3D12WindowRenderer.h> #include <Host/D3D12WindowRenderer.h>
#include <Host/D3D12ShaderResourceDescriptorAllocator.h>
#include <XCEngine/Rendering/RenderContext.h> #include <XCEngine/Rendering/RenderContext.h>
#include <XCEngine/UI/Types.h> #include <XCEngine/UI/Types.h>
@@ -57,6 +58,8 @@ private:
Host::D3D12WindowRenderer* m_windowRenderer = nullptr; Host::D3D12WindowRenderer* m_windowRenderer = nullptr;
::XCEngine::RHI::RHIDevice* m_device = nullptr; ::XCEngine::RHI::RHIDevice* m_device = nullptr;
Host::D3D12ShaderResourceDescriptorAllocator m_textureDescriptorAllocator = {};
ProductViewportRenderTargetManager m_renderTargetManager = {};
bool m_surfacePresentationEnabled = false; bool m_surfacePresentationEnabled = false;
std::array<ViewportEntry, 2> m_entries = {}; std::array<ViewportEntry, 2> m_entries = {};
}; };

View File

@@ -0,0 +1,267 @@
#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

View File

@@ -2,7 +2,7 @@
#include "ProductViewportSurfaceUtils.h" #include "ProductViewportSurfaceUtils.h"
#include <Host/D3D12WindowRenderer.h> #include <Host/D3D12ShaderResourceDescriptorAllocator.h>
#include <XCEngine/RHI/RHIDevice.h> #include <XCEngine/RHI/RHIDevice.h>
#include <XCEngine/RHI/RHIResourceView.h> #include <XCEngine/RHI/RHIResourceView.h>
@@ -36,268 +36,31 @@ struct ProductViewportRenderTargets {
bool hasValidObjectIdFrame = false; bool hasValidObjectIdFrame = false;
}; };
inline ProductViewportResourceReuseQuery BuildProductViewportRenderTargetsReuseQuery( ProductViewportResourceReuseQuery BuildProductViewportRenderTargetsReuseQuery(
ProductViewportKind kind, ProductViewportKind kind,
const ProductViewportRenderTargets& targets, const ProductViewportRenderTargets& targets,
std::uint32_t requestedWidth, std::uint32_t requestedWidth,
std::uint32_t requestedHeight) { 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;
}
inline ::XCEngine::Rendering::RenderSurface BuildProductViewportColorSurface( ::XCEngine::Rendering::RenderSurface BuildProductViewportColorSurface(
const ProductViewportRenderTargets& targets) { const ProductViewportRenderTargets& targets);
return BuildProductViewportRenderSurface( ::XCEngine::Rendering::RenderSurface BuildProductViewportObjectIdSurface(
targets.width, const ProductViewportRenderTargets& targets);
targets.height, ::XCEngine::Rendering::RenderSurface BuildProductViewportSelectionMaskSurface(
targets.colorView, const ProductViewportRenderTargets& targets);
targets.depthView,
targets.colorState);
}
inline ::XCEngine::Rendering::RenderSurface BuildProductViewportObjectIdSurface( class ProductViewportRenderTargetManager {
const ProductViewportRenderTargets& targets) { public:
return BuildProductViewportRenderSurface( bool EnsureTargets(
targets.width,
targets.height,
targets.objectIdView,
targets.objectIdDepthView,
targets.objectIdState);
}
inline ::XCEngine::Rendering::RenderSurface BuildProductViewportSelectionMaskSurface(
const ProductViewportRenderTargets& targets) {
return BuildProductViewportRenderSurface(
targets.width,
targets.height,
targets.selectionMaskView,
targets.depthView,
targets.selectionMaskState);
}
namespace Internal {
template <typename ResourceType>
inline void ShutdownAndDeleteViewportResource(ResourceType*& resource) {
if (resource == nullptr) {
return;
}
resource->Shutdown();
delete resource;
resource = nullptr;
}
inline 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;
}
inline 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;
}
inline 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;
}
inline 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;
}
inline bool CreateViewportTextureDescriptor(
Host::D3D12WindowRenderer& windowRenderer,
::XCEngine::RHI::RHIDevice* device,
ProductViewportRenderTargets& targets) {
if (!windowRenderer.CreateShaderResourceTextureDescriptor(
device,
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 Internal
inline void DestroyProductViewportRenderTargets(
Host::D3D12WindowRenderer* windowRenderer,
ProductViewportRenderTargets& targets) {
if (windowRenderer != nullptr && targets.srvCpuHandle.ptr != 0) {
windowRenderer->FreeShaderResourceDescriptor(targets.srvCpuHandle, targets.srvGpuHandle);
}
Internal::ShutdownAndDeleteViewportResource(targets.objectIdView);
Internal::ShutdownAndDeleteViewportResource(targets.objectIdShaderView);
Internal::ShutdownAndDeleteViewportResource(targets.objectIdDepthView);
Internal::ShutdownAndDeleteViewportResource(targets.objectIdDepthTexture);
Internal::ShutdownAndDeleteViewportResource(targets.objectIdTexture);
Internal::ShutdownAndDeleteViewportResource(targets.selectionMaskView);
Internal::ShutdownAndDeleteViewportResource(targets.selectionMaskShaderView);
Internal::ShutdownAndDeleteViewportResource(targets.selectionMaskTexture);
Internal::ShutdownAndDeleteViewportResource(targets.depthShaderView);
Internal::ShutdownAndDeleteViewportResource(targets.depthView);
Internal::ShutdownAndDeleteViewportResource(targets.depthTexture);
Internal::ShutdownAndDeleteViewportResource(targets.colorView);
Internal::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;
}
inline bool CreateProductViewportRenderTargets(
ProductViewportKind kind, ProductViewportKind kind,
std::uint32_t width, std::uint32_t width,
std::uint32_t height, std::uint32_t height,
::XCEngine::RHI::RHIDevice* device, ::XCEngine::RHI::RHIDevice& device,
Host::D3D12WindowRenderer& windowRenderer, Host::D3D12ShaderResourceDescriptorAllocator& textureDescriptorAllocator,
ProductViewportRenderTargets& targets) { ProductViewportRenderTargets& targets) const;
if (width == 0u || height == 0u || device == nullptr) { void DestroyTargets(
return false; Host::D3D12ShaderResourceDescriptorAllocator* textureDescriptorAllocator,
} ProductViewportRenderTargets& targets) const;
};
DestroyProductViewportRenderTargets(&windowRenderer, targets);
targets.width = width;
targets.height = height;
if (!Internal::CreateViewportColorResources(device, targets) ||
!Internal::CreateViewportDepthResources(device, targets) ||
(ProductViewportRequiresObjectIdResources(kind) &&
(!Internal::CreateViewportObjectIdResources(device, targets) ||
!Internal::CreateViewportSelectionMaskResources(device, targets))) ||
!Internal::CreateViewportTextureDescriptor(windowRenderer, device, targets)) {
DestroyProductViewportRenderTargets(&windowRenderer, 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;
}
} // namespace XCEngine::UI::Editor::App } // namespace XCEngine::UI::Editor::App