SleakEngine 1.0.0
C++23 multi-backend game engine
Loading...
Searching...
No Matches
DirectX12Renderer.hpp
Go to the documentation of this file.
1#include <Core/OSDef.hpp>
2
3#ifdef PLATFORM_WIN
4
5#ifndef _DIRECTX12RENDERER_H
6#define _DIRECTX12RENDERER_H
7
14#include <Core/Window.hpp>
15#include <d3d12.h>
16#include <d3dcompiler.h>
17#include <dxgi1_4.h>
18#include <wrl/client.h>
19#include <imgui.h>
20#include <backends/imgui_impl_dx12.h>
21
22namespace Sleak {
23namespace RenderEngine {
24
25/// D3D12 backend: explicit command lists, per-frame allocators, and a shared SRV descriptor heap.
26class ENGINE_API DirectX12Renderer : public Renderer, public RenderContext {
27public:
28 DirectX12Renderer(Window* window);
29 virtual ~DirectX12Renderer();
30
31 bool Initialize() override;
32 void BeginRender() override;
33 void EndRender() override;
34 void Cleanup() override;
35 void WaitIdle() override { WaitForGPU(); }
36
37 virtual void Resize(uint32_t width, uint32_t height) override;
38
39 /// True if the current adapter/driver supports D3D12 feature level 11_0.
40 static bool IsSupport();
41
42 virtual bool CreateImGUI() override;
43
44 virtual RenderContext* GetContext() override { return this; }
45
46 // Feature capability mask
47 virtual uint32_t GetFeatureCaps() const override { return CapShadows; }
48
49 // RenderContext interface
50 virtual void Draw(uint32_t vertexCount) override;
51 virtual void DrawIndexed(uint32_t indexCount) override;
52 virtual void DrawInstance(uint32_t instanceCount,
53 uint32_t vertexPerInstance) override;
54 virtual void DrawIndexedInstance(uint32_t instanceCount,
55 uint32_t indexPerInstance) override;
56
57 virtual void SetRenderFace(RenderFace face) override;
58 virtual void SetRenderMode(RenderMode mode) override;
59 virtual void SetViewport(float x, float y, float width, float height,
60 float minDepth = 0.0f,
61 float maxDepth = 1.0f) override;
62 virtual void ClearRenderTarget(float r, float g, float b,
63 float a) override;
64 virtual void ClearDepthStencil(bool clearDepth, bool clearStencil,
65 float depth, uint8_t stencil) override;
66
67 virtual void BindVertexBuffer(RefPtr<BufferBase> buffer,
68 uint32_t slot = 0) override;
69 virtual void BindIndexBuffer(RefPtr<BufferBase> buffer,
70 uint32_t slot = 0) override;
71 virtual void BindConstantBuffer(RefPtr<BufferBase> buffer,
72 uint32_t slot = 0) override;
73
74 virtual BufferBase* CreateBuffer(BufferType Type, uint32_t size,
75 void* data) override;
76 virtual Shader* CreateShader(const std::string& shaderSource) override;
77 virtual Texture* CreateTexture(const std::string& TexturePath) override;
78 virtual Texture* CreateTextureFromData(uint32_t width, uint32_t height,
79 void* data) override;
80
81 /// Loads a cubemap from six face image paths.
82 Texture* CreateCubemapTexture(const std::array<std::string, 6>& facePaths);
83 /// Loads a cubemap by converting a single equirectangular panorama.
84 Texture* CreateCubemapTextureFromPanorama(const std::string& panoramaPath);
85
86 // Lighting/fog UBO (matches ShadowLightUBO from Vulkan path)
87 void UpdateShadowLightUBO(const void* data, uint32_t size) override;
88
89 // Skybox state management
90 virtual void BindTexture(RefPtr<Sleak::Texture> texture, uint32_t slot = 0) override;
91 virtual void BindTextureRaw(Sleak::Texture* texture, uint32_t slot = 0) override;
92 virtual void BeginSkyboxPass() override;
93 virtual void EndSkyboxPass() override;
94 virtual void BeginDebugLinePass() override;
95 virtual void EndDebugLinePass() override;
96
97private:
98 /// Creates the DXGI factory, enumerates adapters, and creates the D3D12 device.
99 bool CreateDevice();
100 bool CreateCommandQueue();
101 /// Creates the swapchain and its per-frame buffers.
102 bool CreateSwapChain();
103 /// Creates per-frame command allocators and the shared graphics command list.
104 bool CreateCommandAllocatorAndList();
105 /// Creates the RTV heap and a render target view for each swapchain buffer.
106 bool CreateRenderTargetViews();
107 bool CreateDepthStencilView();
108 bool CreateFence();
109 bool CreateRootSignature();
110 /// Builds the default opaque-geometry pipeline state object.
111 bool CreatePipelineState();
112 /// Builds a pipeline state object from precompiled vertex/pixel shader bytecode.
113 bool CreatePipelineStateFromShader(ID3DBlob* vertexShaderBlob,
114 ID3DBlob* pixelShaderBlob);
115
116 virtual void ConfigureRenderMode() override;
117 virtual void ConfigureRenderFace() override;
118
119 /// Signals the fence and blocks the CPU until the GPU catches up.
120 void WaitForGPU();
121 /// Logs available DXGI adapters and picks the current one for device creation.
122 void EnumerateDevices(Microsoft::WRL::ComPtr<IDXGIFactory4> factory);
123
124 // Frame count (must be declared before arrays that use it)
125 static constexpr UINT FrameCount = 2;
126
127 // Device and swap chain
128 Microsoft::WRL::ComPtr<ID3D12Device> device;
129 Microsoft::WRL::ComPtr<IDXGISwapChain3> swapChain;
130 Microsoft::WRL::ComPtr<IDXGIAdapter1> adapter;
131
132 // Command objects (per-frame allocators for CPU/GPU overlap)
133 Microsoft::WRL::ComPtr<ID3D12CommandQueue> commandQueue;
134 Microsoft::WRL::ComPtr<ID3D12CommandAllocator> commandAllocators[FrameCount];
135 Microsoft::WRL::ComPtr<ID3D12GraphicsCommandList> commandList;
136
137 // Descriptor heaps
138 Microsoft::WRL::ComPtr<ID3D12DescriptorHeap> rtvHeap;
139 Microsoft::WRL::ComPtr<ID3D12DescriptorHeap> dsvHeap;
140
141 // Render targets and depth
142 Microsoft::WRL::ComPtr<ID3D12Resource> renderTargets[FrameCount];
143 Microsoft::WRL::ComPtr<ID3D12Resource> depthStencilBuffer;
144
145 // Pipeline state
146 Microsoft::WRL::ComPtr<ID3D12RootSignature> rootSignature;
147 Microsoft::WRL::ComPtr<ID3D12PipelineState> pipelineState;
148
149 // Synchronization (per-frame fence values for non-blocking overlap)
150 Microsoft::WRL::ComPtr<ID3D12Fence> fence;
151 HANDLE fenceEvent = nullptr;
152 UINT64 fenceValues[FrameCount] = {};
153
154 // Descriptor sizes
155 UINT rtvDescriptorSize = 0;
156 UINT frameIndex = 0;
157
158 // Window
159 Window* window;
160
161 // Viewport and scissor rect
162 D3D12_VIEWPORT viewport = {};
163 D3D12_RECT scissorRect = {};
164
165 bool m_Initialized = false;
166
167 // Default 1x1 white texture (fallback when no texture is bound)
168 DirectX12Texture* m_defaultTexture = nullptr;
169
170 // Skybox PSO (depth write off, LEQUAL, no cull)
171 Microsoft::WRL::ComPtr<ID3D12PipelineState> m_skyboxPipelineState;
172 /// Builds the skybox PSO (depth write disabled, LEQUAL compare, no culling).
173 bool CreateSkyboxPipelineState();
174
175 // Debug line PSO (line topology)
176 Microsoft::WRL::ComPtr<ID3D12PipelineState> m_debugLinePipelineState;
177 /// Builds the line-topology PSO used for debug line rendering.
178 bool CreateDebugLinePipelineState();
179
180 // Light/fog constant buffer (persistently-mapped upload heap)
181 Microsoft::WRL::ComPtr<ID3D12Resource> m_lightUBO;
182 void* m_lightUBOMapped = nullptr;
183 bool m_lightUBOCreated = false;
184 /// Allocates the persistently-mapped upload-heap buffer backing the light/fog UBO.
185 bool CreateLightUBO();
186
187 // Shadow mapping
188 Microsoft::WRL::ComPtr<ID3D12Resource> m_shadowDepthBuffer;
189 Microsoft::WRL::ComPtr<ID3D12DescriptorHeap> m_shadowDsvHeap;
190 D3D12_CPU_DESCRIPTOR_HANDLE m_shadowDsvHandle = {};
191 UINT m_shadowSrvIndex = 0;
192 bool m_shadowMapCreated = false;
193 float m_lightVP[16] = {};
194 float m_pendingLightVP[16] = {};
195 bool m_hasPendingLightVP = false;
196 bool m_inShadowPass = false;
197 Microsoft::WRL::ComPtr<ID3D12Resource> m_shadowTransformCB;
198 void* m_shadowTransformMapped = nullptr;
199 // Depth-only PSO for shadow pass (no PS, no RTV, CULL_NONE)
200 Microsoft::WRL::ComPtr<ID3D12PipelineState> m_shadowPassPSO;
201 Microsoft::WRL::ComPtr<ID3DBlob> m_cachedVSBlob; // saved for shadow PSO
202 void SetLightVP(const float* mat) override;
203 /// Allocates the shadow-pass depth buffer, DSV, and shared-heap SRV slot.
204 bool CreateShadowMapResources();
205 /// Builds the depth-only PSO (no pixel shader, no RTV, no culling) used for the shadow pass.
206 bool CreateShadowPassPSO();
207 /// Replays cached shadow-caster draws into the depth-only shadow map.
208 void RenderShadowPass();
209
210 // ImGUI
211 Microsoft::WRL::ComPtr<ID3D12DescriptorHeap> imguiSrvHeap;
212
213 // Shared SRV descriptor heap (all textures live here — set once per frame)
214 Microsoft::WRL::ComPtr<ID3D12DescriptorHeap> m_sharedSrvHeap;
215 UINT m_srvDescriptorSize = 0;
216 UINT m_nextSrvSlot = 1; // slot 0 reserved for imgui/default
217 static constexpr UINT MAX_SRV_DESCRIPTORS = 512;
218
219 /// Creates the shared, shader-visible SRV descriptor heap used by all textures/cubemaps.
220 bool CreateSharedSrvHeap();
221public:
222 // Allocate a slot in the shared SRV heap; returns the slot index
223 UINT AllocateSRVSlot();
224 D3D12_CPU_DESCRIPTOR_HANDLE GetSharedSrvCPUHandle(UINT slot) const;
225 D3D12_GPU_DESCRIPTOR_HANDLE GetSharedSrvGPUHandle(UINT slot) const;
226 ID3D12DescriptorHeap* GetSharedSrvHeap() const { return m_sharedSrvHeap.Get(); }
227};
228
229} // namespace RenderEngine
230} // namespace Sleak
231
232#endif // _DIRECTX12RENDERER_H
233
234#else
235namespace Sleak::RenderEngine {
236class DirectX12Renderer;
237}
238
239#endif
int width
int height
Abstract interface for high-level graphics command execution and resource management.
Abstract render backend: swapchain, frame lifecycle, and post-effect toggles.
Definition Renderer.hpp:37
Backend-facing rendering layer shared by the four graphics backends.
Root namespace for everything the engine exposes.
Definition Camera.hpp:10
class ENGINE_API Window