13#include <imgui_internal.h>
16#include <d3dcompiler.h>
24DirectX11Renderer::DirectX11Renderer(
Window* window)
27 deviceContext(nullptr),
29 renderTargetView(nullptr) {
30 this->Type = RendererType::DirectX11;
31 this->cull = D3D11_CULL_FRONT;
33 ResourceManager::RegisterCreateBuffer(
this,&DirectX11Renderer::CreateBuffer);
34 ResourceManager::RegisterCreateShader(
this,&DirectX11Renderer::CreateShader);
35 ResourceManager::RegisterCreateTexture(
this,&DirectX11Renderer::CreateTexture);
36 ResourceManager::RegisterCreateCubemapTexture(
this,&DirectX11Renderer::CreateCubemapTexture);
37 ResourceManager::RegisterCreateCubemapTextureFromPanorama(
this,&DirectX11Renderer::CreateCubemapTextureFromPanorama);
38 ResourceManager::RegisterCreateTextureFromMemory(
39 [
this](
const void* data, uint32_t w, uint32_t h, TextureFormat fmt, uint32_t) -> Texture* {
40 auto* tex =
new DirectX11Texture(device);
41 if (tex->LoadFromMemory(data, w, h, fmt))
return tex;
48DirectX11Renderer::~DirectX11Renderer() {
52bool DirectX11Renderer::Initialize() {
53 HWND hwnd = (HWND)SDL_GetPointerProperty(SDL_GetWindowProperties(window->GetSDLWindow()),
54 SDL_PROP_WINDOW_WIN32_HWND_POINTER, NULL);
56 DXGI_SWAP_CHAIN_DESC swapChainDesc = {};
57 swapChainDesc.BufferCount = 2;
58 swapChainDesc.BufferDesc.Width = Window::GetWidth();
59 swapChainDesc.BufferDesc.Height = Window::GetHeight();
60 swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
61 swapChainDesc.BufferDesc.RefreshRate.Numerator = 60;
62 swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
63 swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
64 swapChainDesc.OutputWindow = hwnd;
65 swapChainDesc.SampleDesc.Count = 1;
66 swapChainDesc.SampleDesc.Quality = 0;
67 swapChainDesc.Windowed = TRUE;
68 swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
70 UINT createDeviceFlags = 0;
72 createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
75 D3D_FEATURE_LEVEL featureLevels[] = { D3D_FEATURE_LEVEL_11_0 };
76 HRESULT hr = D3D11CreateDeviceAndSwapChain(
78 D3D_DRIVER_TYPE_HARDWARE,
97 if (!CreateRenderTargetView() ||
98 !CreateDepthStencilBuffer(window->GetWidth(), window->GetHeight())) {
102 SetViewport(0, 0, window->GetWidth(), window->GetHeight());
104 SLEAK_INFO(
"DirectX 11 has successfully created!");
107 ID3D11InfoQueue* infoQueue;
108 if (SUCCEEDED(device->QueryInterface(__uuidof(ID3D11InfoQueue), (
void**)&infoQueue))) {
111 infoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_CORRUPTION,
true);
113 D3D11_MESSAGE_SEVERITY severities[] = {
114 D3D11_MESSAGE_SEVERITY_INFO
117 D3D11_INFO_QUEUE_FILTER filter = {};
118 filter.DenyList.NumSeverities = _countof(severities);
119 filter.DenyList.pSeverityList = severities;
121 infoQueue->AddStorageFilterEntries(&filter);
122 infoQueue->Release();
126 SetPerformanceCounter(
true);
127 SetRenderMode(RenderMode::Fill);
128 SetRenderFace(RenderFace::Front);
130 ConfigureRenderMode();
136 D3D11_QUERY_DESC queryDesc;
137 queryDesc.Query = D3D11_QUERY::D3D11_QUERY_PIPELINE_STATISTICS;
138 queryDesc.MiscFlags = 0;
139 if(FAILED(device->CreateQuery(&queryDesc,&query)))
140 SLEAK_WARN(
"Could not create pipeline statics object!");
143 if(bEnabledPerformanceCounter){
145 while (deviceContext->GetData(query,
nullptr, 0, 0) == S_FALSE);
146 deviceContext->Begin(query);
149 if (!CreateBlendState())
155void DirectX11Renderer::BeginRender() {
156 if (m_msaaChangeRequested)
160 if (m_hasPendingLightVP) {
161 std::memcpy(m_lightVP, m_pendingLightVP,
sizeof(m_lightVP));
165 if (m_tonemapEnabled && !m_tonemapResourcesCreated)
166 CreateTonemapResources();
169 if (m_tonemapEnabled && m_tonemapResourcesCreated && msaaSampleCount <= 1) {
170 deviceContext->OMSetRenderTargets(1, &m_hdrRTV, depthStencilView);
171 }
else if (msaaSampleCount > 1 && msaaRenderTargetView && msaaDepthStencilView) {
172 deviceContext->OMSetRenderTargets(1, &msaaRenderTargetView, msaaDepthStencilView);
174 deviceContext->OMSetRenderTargets(1, &renderTargetView, depthStencilView);
178 ClearDepthStencil(
true,
false, 1.0, 0);
181 if (m_shadowPassEnabled) {
188 if (m_shadowMapCreated && m_shadowSRV && m_shadowSampler) {
189 deviceContext->PSSetShaderResources(3, 1, &m_shadowSRV);
190 deviceContext->PSSetSamplers(3, 1, &m_shadowSampler);
193 if (bIsLayoutCreated)
194 deviceContext->IASetInputLayout(layout);
197 ImGui_ImplDX11_NewFrame();
198 ImGui_ImplSDL3_NewFrame();
203void DirectX11Renderer::EndRender() {
205 if (msaaSampleCount > 1) {
207 deviceContext->OMSetRenderTargets(1, &renderTargetView, depthStencilView);
212 if (m_tonemapEnabled && m_tonemapResourcesCreated && msaaSampleCount <= 1) {
213 ExecuteTonemapPass();
215 if (bIsLayoutCreated)
216 deviceContext->IASetInputLayout(layout);
220 if (bImInitialized) {
222 deviceContext->OMSetRenderTargets(1, &renderTargetView,
nullptr);
224 ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());
227 swapChain->Present(m_vsync ? 1 : 0, 0);
229 UpdateFrameMetrics();
232void DirectX11Renderer::Cleanup() {
233 bImInitialized =
false;
236 CleanupTonemapResources();
237 CleanupShadowResources();
240 if (msaaRenderTarget) { msaaRenderTarget->Release(); msaaRenderTarget =
nullptr; }
241 if (msaaRenderTargetView) { msaaRenderTargetView->Release(); msaaRenderTargetView =
nullptr; }
242 if (msaaDepthStencilBuffer) { msaaDepthStencilBuffer->Release(); msaaDepthStencilBuffer =
nullptr; }
243 if (msaaDepthStencilView) { msaaDepthStencilView->Release(); msaaDepthStencilView =
nullptr; }
245 if (renderTargetView) {
246 renderTargetView->Release();
247 renderTargetView =
nullptr;
250 swapChain->Release();
254 deviceContext->Release();
255 deviceContext =
nullptr;
258 if (depthStencilView) {
259 depthStencilView->Release();
260 depthStencilView =
nullptr;
262 if (depthStencilBuffer) {
263 depthStencilBuffer->Release();
264 depthStencilBuffer =
nullptr;
266 if (depthStencilState) {
267 depthStencilState->Release();
268 depthStencilState =
nullptr;
272 blendState->Release();
273 blendState =
nullptr;
282 if (bImInitialized) {
283 ImGui_ImplDX11_Shutdown();
284 ImGui_ImplSDL3_Shutdown();
285 ImGui::DestroyContext();
286 bImInitialized =
false;
291 ID3D11Debug* debugDevice;
292 device->QueryInterface(__uuidof(ID3D11Debug), (
void**)&debugDevice);
294 debugDevice->ReportLiveDeviceObjects(D3D11_RLDO_DETAIL);
295 debugDevice->Release();
306bool DirectX11Renderer::CreateDepthStencilBuffer(uint32_t
width,uint32_t
height) {
308 D3D11_TEXTURE2D_DESC depthDesc = {};
309 depthDesc.Width =
width;
310 depthDesc.Height =
height;
311 depthDesc.MipLevels = 1;
312 depthDesc.ArraySize = 1;
313 depthDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
314 depthDesc.SampleDesc.Count = 1;
315 depthDesc.SampleDesc.Quality = 0;
316 depthDesc.Usage = D3D11_USAGE_DEFAULT;
317 depthDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
320 device->CreateTexture2D(&depthDesc,
nullptr, &depthStencilBuffer);
322 SLEAK_ERROR(
"Failed to create depth stencil buffer!");
326 hr = device->CreateDepthStencilView(depthStencilBuffer,
nullptr,
329 SLEAK_ERROR(
"Failed to create depth stencil view!");
333 deviceContext->OMSetRenderTargets(1, &renderTargetView, depthStencilView);
337void DirectX11Renderer::SetDepthStencilState(
bool enableDepth,
338 bool enableStencil) {
339 D3D11_DEPTH_STENCIL_DESC depthStencilDesc = {};
340 depthStencilDesc.DepthEnable = enableDepth;
341 depthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
342 depthStencilDesc.DepthFunc = D3D11_COMPARISON_LESS;
343 depthStencilDesc.StencilEnable = enableStencil;
344 depthStencilDesc.StencilReadMask = 0xFF;
345 depthStencilDesc.StencilWriteMask = 0xFF;
348 depthStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
349 depthStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR;
350 depthStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
351 depthStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
354 depthStencilDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
355 depthStencilDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_DECR;
356 depthStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
357 depthStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
359 HRESULT hr = device->CreateDepthStencilState(&depthStencilDesc, &depthStencilState);
361 SLEAK_ERROR(
"Failed to create depth stencil state!");
365 deviceContext->OMSetDepthStencilState(depthStencilState, 1);
368void DirectX11Renderer::Resize(uint32_t
width, uint32_t
height) {
369 if (swapChain ==
nullptr || device ==
nullptr || deviceContext ==
nullptr) {
375 deviceContext->OMSetRenderTargets(0,
nullptr,
nullptr);
376 deviceContext->ClearState();
377 deviceContext->Flush();
380 if (renderTargetView) {
381 renderTargetView->Release();
382 renderTargetView =
nullptr;
385 if (depthStencilView) {
386 depthStencilView->Release();
387 depthStencilView =
nullptr;
389 if (depthStencilBuffer) {
390 depthStencilBuffer->Release();
391 depthStencilBuffer =
nullptr;
393 if (depthStencilState) {
394 depthStencilState->Release();
395 depthStencilState =
nullptr;
400 HRESULT hr = swapChain->ResizeBuffers(0,
406 SLEAK_ERROR(
"Failed to resize swap chain buffers! HRESULT: 0x{:X}", (
unsigned)hr);
411 if (!CreateRenderTargetView() || !CreateDepthStencilBuffer(
width,
height)) {
416 if (msaaSampleCount > 1) {
417 CreateMSAARenderTarget();
418 CreateMSAADepthStencil();
422 if (m_tonemapResourcesCreated) {
423 CleanupTonemapResources();
424 CreateTonemapResources();
435void DirectX11Renderer::Draw(uint32_t vertexCount) {
436 deviceContext->Draw(vertexCount,0);
439void DirectX11Renderer::DrawIndexed(uint32_t indexCount) {
440 deviceContext->DrawIndexed(indexCount, 0, 0);
441 DrawnVertices += indexCount;
444void DirectX11Renderer::DrawInstance(uint32_t instanceCount,
445 uint32_t vertexPerInstance) {
446 deviceContext->DrawInstanced(vertexPerInstance, instanceCount, 0, 0);
449void DirectX11Renderer::DrawIndexedInstance(uint32_t instanceCount,
450 uint32_t indexPerInstance) {
451 deviceContext->DrawIndexedInstanced(indexPerInstance, instanceCount, 0, 0, 0);
454void DirectX11Renderer::ClearRenderTarget(
float r,
float g,
float b,
float a) {
455 const float clearColor[4] = {r, g, b, a};
457 ID3D11RenderTargetView* target;
458 if (m_tonemapEnabled && m_tonemapResourcesCreated && msaaSampleCount <= 1)
460 else if (msaaSampleCount > 1)
461 target = msaaRenderTargetView;
463 target = renderTargetView;
466 deviceContext->ClearRenderTargetView(target, clearColor);
469void DirectX11Renderer::ClearDepthStencil(
bool clearDepth,
bool clearStencil,
470 float depth, uint8_t stencil) {
472 if (clearDepth) clearFlags |= D3D11_CLEAR_DEPTH;
473 if (clearStencil) clearFlags |= D3D11_CLEAR_STENCIL;
475 ID3D11DepthStencilView* target = (msaaSampleCount > 1 && msaaDepthStencilView)
476 ? msaaDepthStencilView : depthStencilView;
478 deviceContext->ClearDepthStencilView(target, clearFlags, depth, stencil);
483void DirectX11Renderer::BindVertexBuffer(RefPtr<BufferBase> buffer, uint32_t slot) {
492 auto d3d11Buffer =
dynamic_cast<DirectX11Buffer*
>
496 deviceContext->IASetVertexBuffers(slot, 1, &d3d11Buffer, &stride, &offset);
499 catch (std::exception& e)
501 SLEAK_ERROR(
"Failed to cast Vertex Buffer! {}", e.what());
505void DirectX11Renderer::BindIndexBuffer(RefPtr<BufferBase> buffer,
513 dynamic_cast<DirectX11Buffer*
>(buffer.get())->GetD3DBuffer();
515 deviceContext->IASetIndexBuffer(d3d11Buffer, DXGI_FORMAT_R32_UINT, 0);
517 }
catch (std::exception& e) {
518 SLEAK_ERROR(
"Failed to cast Index Buffer! {}", e.what());
522void DirectX11Renderer::BindConstantBuffer(RefPtr<BufferBase> buffer,
525 auto* dx11Buf =
dynamic_cast<DirectX11Buffer*
>(buffer.get());
526 if (!dx11Buf)
return;
529 if (m_inShadowPass && slot == 0 && dx11Buf->GetCPUShadowCopySize() >= 128) {
530 const float* srcWorld =
reinterpret_cast<const float*
>(
531 static_cast<const char*
>(dx11Buf->GetCPUShadowCopy()) + 64);
534 for (
int r = 0; r < 4; ++r) {
535 for (
int c = 0; c < 4; ++c) {
537 for (
int k = 0; k < 4; ++k) {
538 sum += srcWorld[r * 4 + k] * m_lightVP[k * 4 + c];
540 shadowPC[r * 4 + c] = sum;
543 std::memcpy(&shadowPC[16], srcWorld,
sizeof(
float) * 16);
546 if (!m_shadowTransformCB) {
547 D3D11_BUFFER_DESC desc{};
548 desc.ByteWidth = 128;
549 desc.Usage = D3D11_USAGE_DYNAMIC;
550 desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
551 desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
552 device->CreateBuffer(&desc,
nullptr, &m_shadowTransformCB);
556 D3D11_MAPPED_SUBRESOURCE mapped{};
557 if (SUCCEEDED(deviceContext->Map(m_shadowTransformCB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped))) {
558 std::memcpy(mapped.pData, shadowPC,
sizeof(shadowPC));
559 deviceContext->Unmap(m_shadowTransformCB, 0);
561 deviceContext->VSSetConstantBuffers(slot, 1, &m_shadowTransformCB);
562 deviceContext->PSSetConstantBuffers(slot, 1, &m_shadowTransformCB);
566 auto d3d11Buffer = dx11Buf->GetD3DBuffer();
567 deviceContext->VSSetConstantBuffers(slot, 1, &d3d11Buffer);
568 deviceContext->PSSetConstantBuffers(slot, 1, &d3d11Buffer);
570 }
catch (std::exception& e) {
571 SLEAK_ERROR(
"Failed to cast Constant Buffer! {}", e.what());
575void DirectX11Renderer::ConfigureRenderMode() {
578 case RenderMode::Fill:
579 topology = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
580 fillMode = D3D11_FILL_MODE::D3D11_FILL_SOLID;
582 case RenderMode::Points:
583 topology = D3D11_PRIMITIVE_TOPOLOGY_POINTLIST;
584 fillMode = D3D11_FILL_MODE::D3D11_FILL_SOLID;
586 case RenderMode::Wireframe :
587 topology = D3D11_PRIMITIVE_TOPOLOGY_LINELIST;
588 fillMode = D3D11_FILL_MODE::D3D11_FILL_WIREFRAME;
596 deviceContext->IASetPrimitiveTopology(topology);
601void DirectX11Renderer::ConfigureRenderFace() {
603 case RenderFace::None : cull = D3D11_CULL_MODE::D3D11_CULL_NONE;
break;
604 case RenderFace::Front : cull = D3D11_CULL_MODE::D3D11_CULL_FRONT;
break;
605 case RenderFace::Back : cull = D3D11_CULL_MODE::D3D11_CULL_BACK;
break;
606 default: cull = D3D11_CULL_MODE::D3D11_CULL_FRONT;
610bool DirectX11Renderer::SetRasterState() {
611 ID3D11RasterizerState* rasterState;
612 D3D11_RASTERIZER_DESC RasterDesc = {};
613 RasterDesc.AntialiasedLineEnable =
true;
614 RasterDesc.MultisampleEnable =
true;
615 RasterDesc.CullMode = cull;
616 RasterDesc.DepthBias = 0;
617 RasterDesc.DepthBiasClamp = 0.0f;
618 RasterDesc.SlopeScaledDepthBias = 0.0f;
619 RasterDesc.DepthClipEnable =
true;
620 RasterDesc.ScissorEnable =
false;
621 RasterDesc.FillMode = fillMode;
622 RasterDesc.FrontCounterClockwise =
false;
624 if (FAILED(device->CreateRasterizerState(&RasterDesc, &rasterState))) {
627 deviceContext->RSSetState(rasterState);
628 rasterState->Release();
634void DirectX11Renderer::SetRenderMode(RenderMode mode) {
636 ConfigureRenderMode();
639void DirectX11Renderer::SetRenderFace(RenderFace face) {
641 ConfigureRenderFace();
644void DirectX11Renderer::SetViewport(
float x,
float y,
float width,
float height,
647 D3D11_VIEWPORT viewport = {};
648 viewport.Width =
static_cast<float>(
width);
649 viewport.Height =
static_cast<float>(
height);
650 viewport.MinDepth = minDepth;
651 viewport.MaxDepth = maxDepth;
652 viewport.TopLeftX = x;
653 viewport.TopLeftY = y;
654 deviceContext->RSSetViewports(1, &viewport);
658bool DirectX11Renderer::CreateRenderTargetView() {
660 if (renderTargetView) {
661 renderTargetView->Release();
662 renderTargetView =
nullptr;
666 ID3D11Texture2D* backBuffer =
nullptr;
667 HRESULT hr = swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D),
668 reinterpret_cast<void**
>(&backBuffer));
675 hr = device->CreateRenderTargetView(backBuffer,
nullptr, &renderTargetView);
676 backBuffer->Release();
678 SLEAK_ERROR(
"Failed to create render target view!");
683 deviceContext->OMSetRenderTargets(1, &renderTargetView,
nullptr);
685 SLEAK_INFO(
"Render target view created successfully.");
689Texture* DirectX11Renderer::CreateTextureFromData(uint32_t
width, uint32_t
height,
void* data) {
690 DirectX11Texture* texture =
new DirectX11Texture(device);
691 if (texture->LoadFromMemory(data,
width,
height,TextureFormat::RGBA8)) {
697Texture* DirectX11Renderer::CreateTexture(
const std::string& TexturePath) {
698 DirectX11Texture* texture =
new DirectX11Texture(device);
699 if (texture->LoadFromFile(TexturePath)) {
705Texture* DirectX11Renderer::CreateCubemapTexture(
706 const std::array<std::string, 6>& facePaths) {
707 auto* texture =
new DirectX11CubemapTexture(device);
708 if (texture->LoadCubemap(facePaths)) {
715Texture* DirectX11Renderer::CreateCubemapTextureFromPanorama(
716 const std::string& panoramaPath) {
717 auto* texture =
new DirectX11CubemapTexture(device);
718 if (texture->LoadEquirectangular(panoramaPath)) {
725void DirectX11Renderer::SetDepthWrite(
bool enabled) {
726 m_depthWriteEnabled = enabled;
728 D3D11_DEPTH_STENCIL_DESC desc = {};
729 desc.DepthEnable = TRUE;
730 desc.DepthWriteMask = enabled ? D3D11_DEPTH_WRITE_MASK_ALL
731 : D3D11_DEPTH_WRITE_MASK_ZERO;
732 desc.DepthFunc = m_depthFunc;
733 desc.StencilEnable = FALSE;
735 ID3D11DepthStencilState* state =
nullptr;
736 if (SUCCEEDED(device->CreateDepthStencilState(&desc, &state))) {
737 deviceContext->OMSetDepthStencilState(state, 1);
742void DirectX11Renderer::SetDepthCompare(DepthCompare compare) {
744 case DepthCompare::Less: m_depthFunc = D3D11_COMPARISON_LESS;
break;
745 case DepthCompare::LessEqual: m_depthFunc = D3D11_COMPARISON_LESS_EQUAL;
break;
746 case DepthCompare::Greater: m_depthFunc = D3D11_COMPARISON_GREATER;
break;
747 case DepthCompare::GreaterEqual: m_depthFunc = D3D11_COMPARISON_GREATER_EQUAL;
break;
748 case DepthCompare::Equal: m_depthFunc = D3D11_COMPARISON_EQUAL;
break;
749 case DepthCompare::NotEqual: m_depthFunc = D3D11_COMPARISON_NOT_EQUAL;
break;
750 case DepthCompare::Always: m_depthFunc = D3D11_COMPARISON_ALWAYS;
break;
751 case DepthCompare::Never: m_depthFunc = D3D11_COMPARISON_NEVER;
break;
754 D3D11_DEPTH_STENCIL_DESC desc = {};
755 desc.DepthEnable = TRUE;
756 desc.DepthWriteMask = m_depthWriteEnabled ? D3D11_DEPTH_WRITE_MASK_ALL
757 : D3D11_DEPTH_WRITE_MASK_ZERO;
758 desc.DepthFunc = m_depthFunc;
759 desc.StencilEnable = FALSE;
761 ID3D11DepthStencilState* state =
nullptr;
762 if (SUCCEEDED(device->CreateDepthStencilState(&desc, &state))) {
763 deviceContext->OMSetDepthStencilState(state, 1);
768void DirectX11Renderer::SetCullEnabled(
bool enabled) {
770 cull = D3D11_CULL_FRONT;
772 cull = D3D11_CULL_NONE;
777void DirectX11Renderer::BindTexture(RefPtr<Sleak::Texture> texture,
779 if (texture.IsValid()) {
784void DirectX11Renderer::BeginSkyboxPass() {
786 m_savedCullMode = cull;
787 m_savedDepthStencilState = depthStencilState;
788 if (m_savedDepthStencilState) {
789 m_savedDepthStencilState->AddRef();
793void DirectX11Renderer::EndSkyboxPass() {
795 if (m_savedDepthStencilState) {
796 deviceContext->OMSetDepthStencilState(m_savedDepthStencilState, 1);
797 m_savedDepthStencilState->Release();
798 m_savedDepthStencilState =
nullptr;
802 cull = m_savedCullMode;
806 m_depthWriteEnabled =
true;
807 m_depthFunc = D3D11_COMPARISON_LESS;
810void DirectX11Renderer::BeginDebugLinePass() {
811 m_savedTopology = topology;
812 topology = D3D11_PRIMITIVE_TOPOLOGY_LINELIST;
813 deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_LINELIST);
816void DirectX11Renderer::EndDebugLinePass() {
817 topology = m_savedTopology;
818 deviceContext->IASetPrimitiveTopology(topology);
821BufferBase* DirectX11Renderer::CreateBuffer(BufferType Type, uint32_t size,
void* data) {
824 DirectX11Buffer* buffer =
new DirectX11Buffer(device, size, Type);
825 if (!buffer->Initialize(data)) {
829 return static_cast<BufferBase*
>(buffer);
832Shader* DirectX11Renderer::CreateShader(
const std::string& shaderSource) {
833 DirectX11Shader* shader =
new DirectX11Shader(device);
834 if (shader->compile(shaderSource)) {
837 auto* il = shader->createInputLayout();
838 if (!bIsLayoutCreated && il) {
840 bIsLayoutCreated =
true;
842 return static_cast<Shader*
>(shader);
847bool DirectX11Renderer::CreateBlendState() {
852 D3D11_BLEND_DESC desc;
853 desc.AlphaToCoverageEnable =
false;
854 desc.IndependentBlendEnable =
false;
856 desc.RenderTarget[0].BlendEnable =
true;
858 desc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
859 desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
861 desc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
862 desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
864 desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
865 desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
867 desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
869 if (FAILED(device->CreateBlendState(&desc, &blendState)))
875void DirectX11Renderer::SetBlendState(
float r,
float g,
float b,
float a, UINT Mask) {
876 float BlendFactor[4] = {r,g,b,a};
877 deviceContext->OMSetBlendState(blendState, BlendFactor, Mask);
880void DirectX11Renderer::CheckMSAASupport() {
881 m_maxMsaaSampleCount = 1;
882 for (UINT sampleCount = 1;
883 sampleCount <= D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT;
887 HRESULT hr = device->CheckMultisampleQualityLevels(
888 DXGI_FORMAT_R8G8B8A8_UNORM, sampleCount, &quality);
889 if (SUCCEEDED(hr) && quality > 0) {
890 SLEAK_INFO(
"MSAA {}x supported with {} quality levels.",
891 sampleCount, quality);
892 if (sampleCount <= 8)
893 m_maxMsaaSampleCount = sampleCount;
898bool DirectX11Renderer::CreateMSAARenderTarget() {
900 if (msaaRenderTarget) msaaRenderTarget->Release();
901 if (msaaRenderTargetView) msaaRenderTargetView->Release();
903 D3D11_TEXTURE2D_DESC texDesc;
904 texDesc.Width = window->GetWidth();
905 texDesc.Height = window->GetHeight();
906 texDesc.MipLevels = 1;
907 texDesc.ArraySize = 1;
908 texDesc.SampleDesc.Count = msaaSampleCount;
909 texDesc.SampleDesc.Quality = msaaQualityLevel;
910 texDesc.BindFlags = D3D11_BIND_RENDER_TARGET;
911 texDesc.CPUAccessFlags = 0;
912 texDesc.MiscFlags = 0;
913 texDesc.Usage = D3D11_USAGE_DEFAULT;
914 texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
916 if (FAILED(device->CreateTexture2D(&texDesc,
nullptr, &msaaRenderTarget)))
919 if (FAILED(device->CreateRenderTargetView(msaaRenderTarget,
nullptr,&msaaRenderTargetView)))
925bool DirectX11Renderer::CreateMSAADepthStencil() {
926 if (msaaDepthStencilBuffer) msaaDepthStencilBuffer->Release();
927 if (msaaDepthStencilView) msaaDepthStencilView->Release();
929 D3D11_TEXTURE2D_DESC texDesc;
930 texDesc.Width = window->GetWidth();
931 texDesc.Height = window->GetHeight();
932 texDesc.MipLevels = 1;
933 texDesc.ArraySize = 1;
934 texDesc.SampleDesc.Count = msaaSampleCount;
935 texDesc.SampleDesc.Quality = msaaQualityLevel;
936 texDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
937 texDesc.CPUAccessFlags = 0;
938 texDesc.MiscFlags = 0;
939 texDesc.Usage = D3D11_USAGE_DEFAULT;
940 texDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
942 if (FAILED(device->CreateTexture2D(&texDesc,
nullptr,&msaaDepthStencilBuffer)))
return false;
944 if (FAILED(device->CreateDepthStencilView(msaaDepthStencilBuffer,
nullptr,&msaaDepthStencilView)))
return false;
950void DirectX11Renderer::ResolveMSAA() {
951 if (msaaSampleCount <= 1 || msaaSampleCount % 2 != 0)
954 ID3D11Texture2D* back;
955 if (FAILED(swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (
void**)&back))) {
956 SLEAK_ERROR(
"Failed to get back buffer for MSAA!");
959 deviceContext->ResolveSubresource(back,0,msaaRenderTarget,0,DXGI_FORMAT_R8G8B8A8_UNORM);
964void DirectX11Renderer::ApplyMSAAChange() {
965 if (!m_msaaChangeRequested)
967 m_msaaChangeRequested =
false;
969 m_msaaSampleCount = m_pendingMsaaSampleCount;
970 msaaSampleCount = m_pendingMsaaSampleCount;
974 device->CheckMultisampleQualityLevels(DXGI_FORMAT_R8G8B8A8_UNORM,
975 msaaSampleCount, &quality);
976 msaaQualityLevel = (quality > 0) ? quality - 1 : 0;
979 if (msaaRenderTarget) { msaaRenderTarget->Release(); msaaRenderTarget =
nullptr; }
980 if (msaaRenderTargetView) { msaaRenderTargetView->Release(); msaaRenderTargetView =
nullptr; }
981 if (msaaDepthStencilBuffer) { msaaDepthStencilBuffer->Release(); msaaDepthStencilBuffer =
nullptr; }
982 if (msaaDepthStencilView) { msaaDepthStencilView->Release(); msaaDepthStencilView =
nullptr; }
984 if (msaaSampleCount > 1) {
985 CreateMSAARenderTarget();
986 CreateMSAADepthStencil();
989 deviceContext->OMSetRenderTargets(1, &renderTargetView, depthStencilView);
992 SLEAK_INFO(
"DX11 MSAA changed to {}x", msaaSampleCount);
995bool DirectX11Renderer::CreateImGUI()
997 IMGUI_CHECKVERSION();
998 ImCon = ImGui::CreateContext();
999 ImCon->IO.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
1001 ImGui::StyleColorsDark();
1003 if(!ImGui_ImplSDL3_InitForD3D(window->GetSDLWindow()))
1006 if(!ImGui_ImplDX11_Init(device, deviceContext))
1009 if(!ImGui_ImplDX11_CreateDeviceObjects())
1013 bImInitialized =
true;
1021bool DirectX11Renderer::CreateShadowConstantBuffer() {
1022 if (m_shadowCBCreated)
return true;
1024 D3D11_BUFFER_DESC desc{};
1025 desc.ByteWidth =
sizeof(PCSSShadowGPUData);
1026 desc.Usage = D3D11_USAGE_DYNAMIC;
1027 desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
1028 desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
1030 HRESULT hr = device->CreateBuffer(&desc,
nullptr, &m_shadowCB);
1032 SLEAK_ERROR(
"Failed to create shadow constant buffer!");
1036 m_shadowCBCreated =
true;
1040void DirectX11Renderer::CleanupShadowResources() {
1041 if (m_shadowCB) { m_shadowCB->Release(); m_shadowCB =
nullptr; }
1042 m_shadowCBCreated =
false;
1043 if (m_shadowTransformCB) { m_shadowTransformCB->Release(); m_shadowTransformCB =
nullptr; }
1044 if (m_shadowRasterState) { m_shadowRasterState->Release(); m_shadowRasterState =
nullptr; }
1045 if (m_shadowSampler) { m_shadowSampler->Release(); m_shadowSampler =
nullptr; }
1046 if (m_shadowSRV) { m_shadowSRV->Release(); m_shadowSRV =
nullptr; }
1047 if (m_shadowDSV) { m_shadowDSV->Release(); m_shadowDSV =
nullptr; }
1048 if (m_shadowDepthTex) { m_shadowDepthTex->Release(); m_shadowDepthTex =
nullptr; }
1049 m_shadowMapCreated =
false;
1052void DirectX11Renderer::SetLightVP(
const float* mat) {
1054 std::memcpy(m_pendingLightVP, mat,
sizeof(m_pendingLightVP));
1055 m_hasPendingLightVP =
true;
1059bool DirectX11Renderer::CreateShadowMapResources() {
1060 if (m_shadowMapCreated)
return true;
1063 D3D11_TEXTURE2D_DESC texDesc{};
1064 texDesc.Width = m_shadowMapResolution;
1065 texDesc.Height = m_shadowMapResolution;
1066 texDesc.MipLevels = 1;
1067 texDesc.ArraySize = 1;
1068 texDesc.Format = DXGI_FORMAT_R32_TYPELESS;
1069 texDesc.SampleDesc.Count = 1;
1070 texDesc.SampleDesc.Quality = 0;
1071 texDesc.Usage = D3D11_USAGE_DEFAULT;
1072 texDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE;
1074 HRESULT hr = device->CreateTexture2D(&texDesc,
nullptr, &m_shadowDepthTex);
1076 SLEAK_ERROR(
"Failed to create shadow depth texture!");
1081 D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc{};
1082 dsvDesc.Format = DXGI_FORMAT_D32_FLOAT;
1083 dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
1084 hr = device->CreateDepthStencilView(m_shadowDepthTex, &dsvDesc, &m_shadowDSV);
1091 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc{};
1092 srvDesc.Format = DXGI_FORMAT_R32_FLOAT;
1093 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
1094 srvDesc.Texture2D.MipLevels = 1;
1095 hr = device->CreateShaderResourceView(m_shadowDepthTex, &srvDesc, &m_shadowSRV);
1102 D3D11_SAMPLER_DESC sampDesc{};
1103 sampDesc.Filter = D3D11_FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT;
1104 sampDesc.AddressU = D3D11_TEXTURE_ADDRESS_BORDER;
1105 sampDesc.AddressV = D3D11_TEXTURE_ADDRESS_BORDER;
1106 sampDesc.AddressW = D3D11_TEXTURE_ADDRESS_BORDER;
1107 sampDesc.BorderColor[0] = 1.0f;
1108 sampDesc.BorderColor[1] = 1.0f;
1109 sampDesc.BorderColor[2] = 1.0f;
1110 sampDesc.BorderColor[3] = 1.0f;
1111 sampDesc.ComparisonFunc = D3D11_COMPARISON_LESS_EQUAL;
1112 sampDesc.MinLOD = 0;
1113 sampDesc.MaxLOD = 0;
1114 hr = device->CreateSamplerState(&sampDesc, &m_shadowSampler);
1121 D3D11_RASTERIZER_DESC rasterDesc{};
1122 rasterDesc.FillMode = D3D11_FILL_SOLID;
1123 rasterDesc.CullMode = D3D11_CULL_NONE;
1124 rasterDesc.FrontCounterClockwise = FALSE;
1125 rasterDesc.DepthBias = 100;
1126 rasterDesc.SlopeScaledDepthBias = 2.0f;
1127 rasterDesc.DepthBiasClamp = 0.01f;
1128 rasterDesc.DepthClipEnable = TRUE;
1129 hr = device->CreateRasterizerState(&rasterDesc, &m_shadowRasterState);
1131 SLEAK_ERROR(
"Failed to create shadow rasterizer state!");
1135 m_shadowMapCreated =
true;
1136 m_shadowResourcesCreated =
true;
1137 SLEAK_INFO(
"D3D11 shadow map resources created ({}x{})", m_shadowMapResolution, m_shadowMapResolution);
1141void DirectX11Renderer::RenderShadowPass() {
1143 auto* queue = RenderCommandQueue::GetInstance();
1144 if (!queue || !queue->HasCachedShadowDraws())
return;
1146 if (!m_shadowMapCreated) {
1147 if (!CreateShadowMapResources())
return;
1151 ID3D11RenderTargetView* savedRTV =
nullptr;
1152 ID3D11DepthStencilView* savedDSV =
nullptr;
1153 deviceContext->OMGetRenderTargets(1, &savedRTV, &savedDSV);
1155 D3D11_VIEWPORT savedViewport;
1156 UINT numViewports = 1;
1157 deviceContext->RSGetViewports(&numViewports, &savedViewport);
1160 ID3D11ShaderResourceView* nullSRV =
nullptr;
1161 deviceContext->PSSetShaderResources(3, 1, &nullSRV);
1164 ID3D11RenderTargetView* nullRTV =
nullptr;
1165 deviceContext->OMSetRenderTargets(1, &nullRTV, m_shadowDSV);
1168 D3D11_VIEWPORT shadowViewport{};
1169 shadowViewport.Width =
static_cast<float>(m_shadowMapResolution);
1170 shadowViewport.Height =
static_cast<float>(m_shadowMapResolution);
1171 shadowViewport.MinDepth = 0.0f;
1172 shadowViewport.MaxDepth = 1.0f;
1173 deviceContext->RSSetViewports(1, &shadowViewport);
1176 deviceContext->ClearDepthStencilView(m_shadowDSV, D3D11_CLEAR_DEPTH, 1.0f, 0);
1179 deviceContext->RSSetState(m_shadowRasterState);
1182 deviceContext->IASetPrimitiveTopology(topology);
1183 if (bIsLayoutCreated)
1184 deviceContext->IASetInputLayout(layout);
1187 m_inShadowPass =
true;
1189 queue->ExecuteShadowPass(
this);
1191 m_inShadowPass =
false;
1197 deviceContext->OMSetRenderTargets(1, &savedRTV, savedDSV);
1198 deviceContext->RSSetViewports(1, &savedViewport);
1199 if (savedRTV) savedRTV->Release();
1200 if (savedDSV) savedDSV->Release();
1203 deviceContext->PSSetShaderResources(3, 1, &m_shadowSRV);
1204 deviceContext->PSSetSamplers(3, 1, &m_shadowSampler);
1207void DirectX11Renderer::UpdateShadowLightUBO(
const void* data, uint32_t size) {
1208 if (!device || !deviceContext)
return;
1211 if (!m_shadowCBCreated) {
1212 if (!CreateShadowConstantBuffer())
return;
1216 const auto* ubo =
static_cast<const ShadowLightUBO*
>(data);
1218 PCSSShadowGPUData shadowData{};
1219 std::memcpy(shadowData.LightVP, ubo->LightVP,
sizeof(
float) * 16);
1220 shadowData.ShadowBias = ubo->ShadowBias;
1221 shadowData.ShadowStrength = ubo->ShadowStrength;
1222 shadowData.ShadowTexelSize = ubo->ShadowTexelSize;
1223 shadowData.ShadowLightSize = ubo->LightSize;
1224 shadowData.PCSSEnabled = m_pcssEnabled ? 1 : 0;
1225 shadowData.ShadowMapEnabled = m_shadowPassEnabled ? 1 : 0;
1227 D3D11_MAPPED_SUBRESOURCE mapped{};
1228 HRESULT hr = deviceContext->Map(m_shadowCB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped);
1229 if (SUCCEEDED(hr)) {
1230 std::memcpy(mapped.pData, &shadowData,
sizeof(shadowData));
1231 deviceContext->Unmap(m_shadowCB, 0);
1235 deviceContext->VSSetConstantBuffers(5, 1, &m_shadowCB);
1236 deviceContext->PSSetConstantBuffers(5, 1, &m_shadowCB);
1241bool DirectX11Renderer::CreateTonemapResources() {
1242 if (m_tonemapResourcesCreated)
return true;
1243 if (!device)
return false;
1246 ID3D11Texture2D* backBuffer =
nullptr;
1247 swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (
void**)&backBuffer);
1248 if (!backBuffer)
return false;
1250 D3D11_TEXTURE2D_DESC bbDesc{};
1251 backBuffer->GetDesc(&bbDesc);
1252 backBuffer->Release();
1255 D3D11_TEXTURE2D_DESC texDesc{};
1256 texDesc.Width = bbDesc.Width;
1257 texDesc.Height = bbDesc.Height;
1258 texDesc.MipLevels = 1;
1259 texDesc.ArraySize = 1;
1260 texDesc.Format = DXGI_FORMAT_R16G16B16A16_FLOAT;
1261 texDesc.SampleDesc.Count = 1;
1262 texDesc.SampleDesc.Quality = 0;
1263 texDesc.Usage = D3D11_USAGE_DEFAULT;
1264 texDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
1266 HRESULT hr = device->CreateTexture2D(&texDesc,
nullptr, &m_hdrTexture);
1268 SLEAK_ERROR(
"Failed to create HDR texture for tonemapping!");
1272 hr = device->CreateRenderTargetView(m_hdrTexture,
nullptr, &m_hdrRTV);
1273 if (FAILED(hr))
return false;
1275 hr = device->CreateShaderResourceView(m_hdrTexture,
nullptr, &m_hdrSRV);
1276 if (FAILED(hr))
return false;
1279 D3D11_SAMPLER_DESC sampDesc{};
1280 sampDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
1281 sampDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
1282 sampDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
1283 sampDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
1284 hr = device->CreateSamplerState(&sampDesc, &m_pointSampler);
1285 if (FAILED(hr))
return false;
1288 D3D11_BUFFER_DESC cbDesc{};
1289 cbDesc.ByteWidth =
sizeof(PostProcessGPUData);
1290 cbDesc.Usage = D3D11_USAGE_DYNAMIC;
1291 cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
1292 cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
1293 hr = device->CreateBuffer(&cbDesc,
nullptr, &m_postProcessCB);
1294 if (FAILED(hr))
return false;
1297 ID3DBlob* vsBlob =
nullptr;
1298 ID3DBlob* psBlob =
nullptr;
1299 ID3DBlob* errorBlob =
nullptr;
1302 std::string narrowPath =
"assets/shaders/tonemap.hlsl";
1303 std::wstring shaderPath(narrowPath.begin(), narrowPath.end());
1305 hr = D3DCompileFromFile(shaderPath.c_str(),
nullptr, D3D_COMPILE_STANDARD_FILE_INCLUDE,
1306 "VS_Main",
"vs_5_0", D3DCOMPILE_DEBUG, 0, &vsBlob, &errorBlob);
1310 (
const char*)errorBlob->GetBufferPointer());
1311 errorBlob->Release();
1316 hr = D3DCompileFromFile(shaderPath.c_str(),
nullptr, D3D_COMPILE_STANDARD_FILE_INCLUDE,
1317 "PS_Main",
"ps_5_0", D3DCOMPILE_DEBUG, 0, &psBlob, &errorBlob);
1321 (
const char*)errorBlob->GetBufferPointer());
1322 errorBlob->Release();
1328 hr = device->CreateVertexShader(vsBlob->GetBufferPointer(),
1329 vsBlob->GetBufferSize(),
nullptr, &m_tonemapVS);
1331 if (FAILED(hr)) { psBlob->Release();
return false; }
1333 hr = device->CreatePixelShader(psBlob->GetBufferPointer(),
1334 psBlob->GetBufferSize(),
nullptr, &m_tonemapPS);
1336 if (FAILED(hr))
return false;
1338 m_tonemapResourcesCreated =
true;
1339 SLEAK_INFO(
"Tonemapping post-process resources created successfully");
1343void DirectX11Renderer::CleanupTonemapResources() {
1344 if (m_tonemapVS) { m_tonemapVS->Release(); m_tonemapVS =
nullptr; }
1345 if (m_tonemapPS) { m_tonemapPS->Release(); m_tonemapPS =
nullptr; }
1346 if (m_postProcessCB) { m_postProcessCB->Release(); m_postProcessCB =
nullptr; }
1347 if (m_hdrSRV) { m_hdrSRV->Release(); m_hdrSRV =
nullptr; }
1348 if (m_hdrRTV) { m_hdrRTV->Release(); m_hdrRTV =
nullptr; }
1349 if (m_hdrTexture) { m_hdrTexture->Release(); m_hdrTexture =
nullptr; }
1350 if (m_pointSampler) { m_pointSampler->Release(); m_pointSampler =
nullptr; }
1351 m_tonemapResourcesCreated =
false;
1354void DirectX11Renderer::ExecuteTonemapPass() {
1355 if (!m_tonemapResourcesCreated || !m_tonemapVS || !m_tonemapPS)
1359 PostProcessGPUData ppData{};
1360 ppData.Exposure = m_exposure;
1361 ppData.Gamma = m_gamma;
1362 ppData.TonemapEnabled = m_tonemapEnabled ? 1 : 0;
1364 D3D11_MAPPED_SUBRESOURCE mapped{};
1365 HRESULT hr = deviceContext->Map(m_postProcessCB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped);
1366 if (SUCCEEDED(hr)) {
1367 std::memcpy(mapped.pData, &ppData,
sizeof(ppData));
1368 deviceContext->Unmap(m_postProcessCB, 0);
1372 deviceContext->OMSetRenderTargets(1, &renderTargetView,
nullptr);
1375 deviceContext->PSSetShaderResources(0, 1, &m_hdrSRV);
1376 deviceContext->PSSetSamplers(0, 1, &m_pointSampler);
1377 deviceContext->PSSetConstantBuffers(0, 1, &m_postProcessCB);
1380 deviceContext->VSSetShader(m_tonemapVS,
nullptr, 0);
1381 deviceContext->PSSetShader(m_tonemapPS,
nullptr, 0);
1384 deviceContext->IASetInputLayout(
nullptr);
1385 deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
1386 deviceContext->Draw(3, 0);
1389 ID3D11ShaderResourceView* nullSRV =
nullptr;
1390 deviceContext->PSSetShaderResources(0, 1, &nullSRV);
Backend-facing rendering layer shared by the four graphics backends.
Root namespace for everything the engine exposes.