Files
XCEngine/editor/app/Rendering/D3D12/D3D12UiRenderer.h
2026-04-25 16:46:01 +08:00

173 lines
5.9 KiB
C++

#pragma once
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include "D3D12UiTextSystem.h"
#include "D3D12UiTextureHost.h"
#include <Rendering/D3D12/D3D12WindowRenderer.h>
#include <XCEngine/Rendering/RenderContext.h>
#include <XCEngine/Rendering/RenderSurface.h>
#include <XCEngine/RHI/RHIDescriptorPool.h>
#include <XCEngine/RHI/RHIDescriptorSet.h>
#include <XCEngine/RHI/RHIBuffer.h>
#include <XCEngine/RHI/RHIPipelineLayout.h>
#include <XCEngine/RHI/RHIPipelineState.h>
#include <XCEngine/RHI/RHIResourceView.h>
#include <XCEngine/RHI/RHISampler.h>
#include <XCEngine/UI/DrawData.h>
#include <array>
#include <cstdint>
#include <string>
#include <unordered_map>
#include <vector>
namespace XCEngine::UI::Editor::Host {
class D3D12UiRenderer {
public:
struct UiPrimitiveInstance {
float origin[2] = {};
float axisX[2] = {};
float axisY[2] = {};
float uvMin[2] = {};
float uvMax[2] = {};
float color[4] = {};
float secondaryColor[4] = {};
float params[4] = {};
float aux0[4] = {};
float aux1[4] = {};
};
struct UiBatch {
std::uint32_t firstInstance = 0u;
std::uint32_t instanceCount = 0u;
D3D12_GPU_DESCRIPTOR_HANDLE textureHandle = {};
::XCEngine::RHI::Rect scissorRect = {};
};
bool Initialize(
D3D12WindowRenderer& windowRenderer,
D3D12UiTextureHost& textureHost,
D3D12UiTextSystem& textSystem);
void Shutdown();
void SetDpiScale(float dpiScale);
float GetDpiScale() const;
const std::string& GetLastError() const;
bool Render(
const ::XCEngine::UI::UIDrawData& drawData,
const ::XCEngine::Rendering::RenderContext& renderContext,
const ::XCEngine::Rendering::RenderSurface& surface);
private:
struct FrameResources {
::XCEngine::RHI::RHIBuffer* primitiveInstanceBuffer = nullptr;
::XCEngine::RHI::RHIResourceView* primitiveInstanceBufferView = nullptr;
std::uint64_t primitiveInstanceCapacityBytes = 0u;
};
struct TextRunCacheKey {
std::string text = {};
int fontSizeTenths = 0;
int dpiScaleMilli = 0;
bool operator==(const TextRunCacheKey& other) const;
};
struct TextRunCacheKeyHash {
std::size_t operator()(const TextRunCacheKey& key) const;
};
struct CachedTextRun {
::XCEngine::UI::UITextureHandle texture = {};
D3D12_GPU_DESCRIPTOR_HANDLE textureHandle = {};
float offsetX = 0.0f;
float offsetY = 0.0f;
float width = 0.0f;
float height = 0.0f;
bool hasPixels = false;
std::uint64_t lastUsedFrame = 0u;
};
struct CompiledDrawListKey {
std::uint64_t contentHash = 0u;
std::uint32_t renderWidth = 0u;
std::uint32_t renderHeight = 0u;
int dpiScaleMilli = 0;
bool operator==(const CompiledDrawListKey& other) const;
};
struct CompiledDrawListKeyHash {
std::size_t operator()(const CompiledDrawListKey& key) const;
};
struct CompiledDrawList {
std::vector<UiPrimitiveInstance> instances = {};
std::vector<UiBatch> batches = {};
std::uint64_t lastUsedFrame = 0u;
};
bool EnsureInitialized(
const ::XCEngine::Rendering::RenderContext& renderContext,
const ::XCEngine::Rendering::RenderSurface& surface);
bool CreateResources(
const ::XCEngine::Rendering::RenderContext& renderContext,
const ::XCEngine::Rendering::RenderSurface& surface);
void DestroyResources();
bool EnsureFrameBufferCapacity(
std::uint32_t frameSlot,
std::size_t primitiveInstanceBytes);
void DestroyFrameResources(FrameResources& frameResources);
bool EnsureWhiteTexture();
const CachedTextRun* ResolveTextRun(
std::string_view text,
float fontSize,
std::uint64_t currentFrameId);
void ReleaseTextRunCache();
void PruneTextRunCache(std::uint64_t currentFrameId);
void ReleaseCompiledDrawListCache();
bool BuildDrawBatches(
const ::XCEngine::UI::UIDrawData& drawData,
const ::XCEngine::Rendering::RenderSurface& surface,
std::vector<UiPrimitiveInstance>& outPrimitiveInstances,
std::vector<UiBatch>& outBatches);
D3D12WindowRenderer* m_windowRenderer = nullptr;
D3D12UiTextureHost* m_textureHost = nullptr;
D3D12UiTextSystem* m_textSystem = nullptr;
::XCEngine::RHI::RHIDevice* m_device = nullptr;
::XCEngine::RHI::RHIType m_backendType = ::XCEngine::RHI::RHIType::D3D12;
::XCEngine::RHI::RHIPipelineLayout* m_pipelineLayout = nullptr;
::XCEngine::RHI::RHIPipelineState* m_primitivePipelineState = nullptr;
::XCEngine::RHI::RHIDescriptorPool* m_constantPool = nullptr;
::XCEngine::RHI::RHIDescriptorSet* m_constantSet = nullptr;
::XCEngine::RHI::RHIDescriptorPool* m_samplerPool = nullptr;
::XCEngine::RHI::RHIDescriptorSet* m_samplerSet = nullptr;
::XCEngine::RHI::RHISampler* m_sampler = nullptr;
D3D12_GPU_DESCRIPTOR_HANDLE m_samplerGpuHandle = {};
::XCEngine::UI::UITextureHandle m_whiteTexture = {};
::XCEngine::RHI::RHIBuffer* m_quadVertexBuffer = nullptr;
::XCEngine::RHI::RHIResourceView* m_quadVertexBufferView = nullptr;
::XCEngine::RHI::RHIBuffer* m_quadIndexBuffer = nullptr;
::XCEngine::RHI::RHIResourceView* m_quadIndexBufferView = nullptr;
std::array<FrameResources, D3D12WindowRenderer::kFrameContextCount> m_frameResources = {};
std::unordered_map<TextRunCacheKey, CachedTextRun, TextRunCacheKeyHash> m_textRunCache = {};
std::unordered_map<CompiledDrawListKey, CompiledDrawList, CompiledDrawListKeyHash>
m_compiledDrawListCache = {};
std::uint64_t m_compiledDrawListFrameCounter = 0u;
::XCEngine::RHI::Format m_renderTargetFormat = ::XCEngine::RHI::Format::Unknown;
std::uint32_t m_renderTargetSampleCount = 1u;
std::uint32_t m_renderTargetSampleQuality = 0u;
float m_dpiScale = 1.0f;
std::string m_lastError = {};
};
} // namespace XCEngine::UI::Editor::Host