From b933599f00c1ec3a9c4fe0ab34710bad10063aa6 Mon Sep 17 00:00:00 2001 From: thedmd Date: Sat, 27 Sep 2025 15:09:52 +0200 Subject: [PATCH] Backends: DirectX12: added helpers to switch to Linear sampler (yet not made public, but intended to be forward declared). (#9173) --- backends/imgui_impl_dx12.cpp | 63 +++++++++++++++++++++++++++++------- 1 file changed, 51 insertions(+), 12 deletions(-) diff --git a/backends/imgui_impl_dx12.cpp b/backends/imgui_impl_dx12.cpp index 056d23a6c..a5420782a 100644 --- a/backends/imgui_impl_dx12.cpp +++ b/backends/imgui_impl_dx12.cpp @@ -93,8 +93,10 @@ struct ImGui_ImplDX12_Data ImGui_ImplDX12_InitInfo InitInfo; IDXGIFactory5* pdxgiFactory; ID3D12Device* pd3dDevice; - ID3D12RootSignature* pRootSignature; - ID3D12PipelineState* pPipelineState; + ID3D12RootSignature* pRootSignatureLinear; + ID3D12RootSignature* pRootSignatureNearest; + ID3D12PipelineState* pPipelineStateLinear; + ID3D12PipelineState* pPipelineStateNearest; ID3D12CommandQueue* pCommandQueue; bool commandQueueOwned; DXGI_FORMAT RTVFormat; @@ -140,11 +142,27 @@ struct VERTEX_CONSTANT_BUFFER_DX12 float mvp[4][4]; }; +// FIXME-WIP: Allow user to forward declare those two, for until we come up with a backend agnostic API to do this. (#9173) +void ImGui_ImplDX12_SetupSamplerLinear(ID3D12GraphicsCommandList* command_list); +void ImGui_ImplDX12_SetupSamplerNearest(ID3D12GraphicsCommandList* command_list); + // Functions -static void ImGui_ImplDX12_SetupRenderState(ImDrawData* draw_data, ID3D12GraphicsCommandList* command_list, ImGui_ImplDX12_RenderBuffers* fr) +void ImGui_ImplDX12_SetupSamplerLinear(ID3D12GraphicsCommandList* command_list) { ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData(); + command_list->SetPipelineState(bd->pPipelineStateLinear); + command_list->SetGraphicsRootSignature(bd->pRootSignatureLinear); +} +void ImGui_ImplDX12_SetupSamplerNearest(ID3D12GraphicsCommandList* command_list) +{ + ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData(); + command_list->SetPipelineState(bd->pPipelineStateNearest); + command_list->SetGraphicsRootSignature(bd->pRootSignatureNearest); +} + +static void ImGui_ImplDX12_SetupRenderState(ImDrawData* draw_data, ID3D12GraphicsCommandList* command_list, ImGui_ImplDX12_RenderBuffers* fr) +{ // Setup orthographic projection matrix into our constant buffer // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). VERTEX_CONSTANT_BUFFER_DX12 vertex_constant_buffer; @@ -186,8 +204,7 @@ static void ImGui_ImplDX12_SetupRenderState(ImDrawData* draw_data, ID3D12Graphic ibv.Format = sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT; command_list->IASetIndexBuffer(&ibv); command_list->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - command_list->SetPipelineState(bd->pPipelineState); - command_list->SetGraphicsRootSignature(bd->pRootSignature); + ImGui_ImplDX12_SetupSamplerLinear(command_list); command_list->SetGraphicsRoot32BitConstants(0, 16, &vertex_constant_buffer, 0); // Setup blend factor @@ -555,7 +572,7 @@ bool ImGui_ImplDX12_CreateDeviceObjects() ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData(); if (!bd || !bd->pd3dDevice) return false; - if (bd->pPipelineState) + if (bd->pPipelineStateLinear) ImGui_ImplDX12_InvalidateDeviceObjects(); HRESULT hr = ::CreateDXGIFactory1(IID_PPV_ARGS(&bd->pdxgiFactory)); @@ -644,7 +661,15 @@ bool ImGui_ImplDX12_CreateDeviceObjects() if (D3D12SerializeRootSignatureFn(&desc, D3D_ROOT_SIGNATURE_VERSION_1, &blob, nullptr) != S_OK) return false; - bd->pd3dDevice->CreateRootSignature(0, blob->GetBufferPointer(), blob->GetBufferSize(), IID_PPV_ARGS(&bd->pRootSignature)); + bd->pd3dDevice->CreateRootSignature(0, blob->GetBufferPointer(), blob->GetBufferSize(), IID_PPV_ARGS(&bd->pRootSignatureLinear)); + blob->Release(); + + // Root Signature for ImDrawCallback_SetSamplerNearest + staticSampler[0].Filter = D3D12_FILTER_MIN_MAG_MIP_POINT; + if (D3D12SerializeRootSignatureFn(&desc, D3D_ROOT_SIGNATURE_VERSION_1, &blob, nullptr) != S_OK) + return false; + + bd->pd3dDevice->CreateRootSignature(0, blob->GetBufferPointer(), blob->GetBufferSize(), IID_PPV_ARGS(&bd->pRootSignatureNearest)); blob->Release(); } @@ -657,7 +682,7 @@ bool ImGui_ImplDX12_CreateDeviceObjects() D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {}; psoDesc.NodeMask = 1; psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; - psoDesc.pRootSignature = bd->pRootSignature; + psoDesc.pRootSignature = bd->pRootSignatureLinear; psoDesc.SampleMask = UINT_MAX; psoDesc.NumRenderTargets = 1; psoDesc.RTVFormats[0] = bd->RTVFormat; @@ -780,7 +805,18 @@ bool ImGui_ImplDX12_CreateDeviceObjects() desc.BackFace = desc.FrontFace; } - HRESULT result_pipeline_state = bd->pd3dDevice->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&bd->pPipelineState)); + HRESULT result_pipeline_state = bd->pd3dDevice->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&bd->pPipelineStateLinear)); + if (result_pipeline_state != S_OK) + { + vertexShaderBlob->Release(); + pixelShaderBlob->Release(); + return false; + } + + // Pipeline State for ImDrawCallback_SetSamplerNearest + psoDesc.pRootSignature = bd->pRootSignatureNearest; + + result_pipeline_state = bd->pd3dDevice->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&bd->pPipelineStateNearest)); vertexShaderBlob->Release(); pixelShaderBlob->Release(); if (result_pipeline_state != S_OK) @@ -813,8 +849,11 @@ void ImGui_ImplDX12_InvalidateDeviceObjects() if (bd->commandQueueOwned) SafeRelease(bd->pCommandQueue); bd->commandQueueOwned = false; - SafeRelease(bd->pRootSignature); - SafeRelease(bd->pPipelineState); + SafeRelease(bd->pRootSignatureLinear); + SafeRelease(bd->pRootSignatureNearest); + SafeRelease(bd->pPipelineStateLinear); + SafeRelease(bd->pPipelineStateNearest); + if (bd->pTexUploadBufferMapped) { D3D12_RANGE range = { 0, bd->pTexUploadBufferSize }; @@ -961,7 +1000,7 @@ void ImGui_ImplDX12_NewFrame() ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData(); IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplDX12_Init()?"); - if (!bd->pPipelineState) + if (!bd->pPipelineStateLinear) if (!ImGui_ImplDX12_CreateDeviceObjects()) IM_ASSERT(0 && "ImGui_ImplDX12_CreateDeviceObjects() failed!"); }