|
| 1 | +// D3D12 hook: init + render + ExecuteCommandLists |
| 2 | +#include "hook_common.h" |
| 3 | + |
| 4 | +namespace DX12 { |
| 5 | + ID3D12Device* Device = nullptr; |
| 6 | + ID3D12DescriptorHeap* RTVHeap = nullptr, *SRVHeap = nullptr; |
| 7 | + ID3D12GraphicsCommandList* CmdList = nullptr; |
| 8 | + ID3D12CommandQueue* CmdQueue = nullptr; |
| 9 | + UINT BufCount = 0; FCtx* Frames = nullptr; |
| 10 | + |
| 11 | + void Init(IDXGISwapChain* sc) { |
| 12 | + DEBUG_LOG("D3D12::Init: starting, sc=%p", sc); |
| 13 | + HRESULT hr = sc->GetDevice(__uuidof(ID3D12Device), (void**)&Device); |
| 14 | + if (FAILED(hr)) { |
| 15 | + IUnknown* unk = nullptr; |
| 16 | + if (SUCCEEDED(sc->GetDevice(IID_IUnknown, (void**)&unk)) && unk) { |
| 17 | + hr = unk->QueryInterface(__uuidof(ID3D12Device), (void**)&Device); unk->Release(); |
| 18 | + } |
| 19 | + } |
| 20 | + if (FAILED(hr)) { DEBUG_LOG("D3D12::Init: GetDevice FAILED hr=0x%08X", hr); return; } |
| 21 | + DXGI_SWAP_CHAIN_DESC sd; sc->GetDesc(&sd); |
| 22 | + BufCount = sd.BufferCount; Frames = new FCtx[BufCount]; |
| 23 | + DEBUG_LOG("D3D12::Init: device=%p bufCount=%u wxh=%ux%u", Device, BufCount, sd.BufferDesc.Width, sd.BufferDesc.Height); |
| 24 | + |
| 25 | + D3D12_DESCRIPTOR_HEAP_DESC srvDh = { D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, BufCount, D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE }; |
| 26 | + if (Device->CreateDescriptorHeap(&srvDh, IID_PPV_ARGS(&SRVHeap)) != S_OK) { DEBUG_LOG("D3D12::Init: SRV heap FAILED"); return; } |
| 27 | + DEBUG_LOG("D3D12::Init: SRV heap=%p", SRVHeap); |
| 28 | + |
| 29 | + ID3D12CommandAllocator* alloc; |
| 30 | + if (Device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&alloc)) != S_OK) { DEBUG_LOG("D3D12::Init: CommandAllocator FAILED"); return; } |
| 31 | + for (UINT i = 0; i < BufCount; i++) Frames[i].Alloc = alloc; |
| 32 | + |
| 33 | + if (Device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, alloc, nullptr, IID_PPV_ARGS(&CmdList)) != S_OK || CmdList->Close() != S_OK) { |
| 34 | + DEBUG_LOG("D3D12::Init: CommandList FAILED"); return; |
| 35 | + } |
| 36 | + DEBUG_LOG("D3D12::Init: CmdList=%p", CmdList); |
| 37 | + |
| 38 | + D3D12_DESCRIPTOR_HEAP_DESC rtvDh = { D3D12_DESCRIPTOR_HEAP_TYPE_RTV, BufCount, D3D12_DESCRIPTOR_HEAP_FLAG_NONE, 1 }; |
| 39 | + if (Device->CreateDescriptorHeap(&rtvDh, IID_PPV_ARGS(&RTVHeap)) != S_OK) { DEBUG_LOG("D3D12::Init: RTV heap FAILED"); return; } |
| 40 | + DEBUG_LOG("D3D12::Init: RTV heap=%p", RTVHeap); |
| 41 | + |
| 42 | + UINT rtvSize = Device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); |
| 43 | + D3D12_CPU_DESCRIPTOR_HANDLE rtvH = RTVHeap->GetCPUDescriptorHandleForHeapStart(); |
| 44 | + for (UINT i = 0; i < BufCount; i++) { |
| 45 | + ID3D12Resource* buf = nullptr; Frames[i].Handle = rtvH; |
| 46 | + sc->GetBuffer(i, IID_PPV_ARGS(&buf)); Device->CreateRenderTargetView(buf, nullptr, rtvH); |
| 47 | + Frames[i].Res = buf; rtvH.ptr += rtvSize; |
| 48 | + } |
| 49 | + DEBUG_LOG("D3D12::Init: %u RTVs created", BufCount); |
| 50 | + |
| 51 | + imgui_callbacks.init_callback(); |
| 52 | + ImGui_ImplWin32_Init(g_GameWindow); |
| 53 | + |
| 54 | + static int srvIdx = 0; |
| 55 | + ImGui_ImplDX12_InitInfo info = {}; |
| 56 | + info.Device = Device; info.CommandQueue = CmdQueue; |
| 57 | + info.NumFramesInFlight = (int)BufCount; info.RTVFormat = DXGI_FORMAT_R8G8B8A8_UNORM; |
| 58 | + info.SrvDescriptorHeap = SRVHeap; |
| 59 | + info.SrvDescriptorAllocFn = [](ImGui_ImplDX12_InitInfo* i, D3D12_CPU_DESCRIPTOR_HANDLE* c, D3D12_GPU_DESCRIPTOR_HANDLE* g) { |
| 60 | + UINT inc = i->Device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); |
| 61 | + *c = i->SrvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(); c->ptr += inc * (++srvIdx); |
| 62 | + *g = i->SrvDescriptorHeap->GetGPUDescriptorHandleForHeapStart(); g->ptr += inc * srvIdx; |
| 63 | + }; |
| 64 | + info.SrvDescriptorFreeFn = [](ImGui_ImplDX12_InitInfo*, D3D12_CPU_DESCRIPTOR_HANDLE, D3D12_GPU_DESCRIPTOR_HANDLE) {}; |
| 65 | + ImGui_ImplDX12_Init(&info); |
| 66 | + ImGui_ImplDX12_CreateDeviceObjects(); |
| 67 | + DEBUG_LOG("D3D12::Init: ImGui DX12 backend initialized, CmdQueue=%p", CmdQueue); |
| 68 | + } |
| 69 | + |
| 70 | + void Render(IDXGISwapChain* sc) { |
| 71 | + if (!CmdQueue) { DEBUG_LOG("D3D12::Render: CmdQueue is null, skipping"); return; } |
| 72 | + ImGui_ImplDX12_NewFrame(); |
| 73 | + if (imgui_callbacks.render_callback) imgui_callbacks.render_callback(); |
| 74 | + |
| 75 | + static UINT frameIdx = 0; |
| 76 | + auto& ctx = Frames[frameIdx++ % BufCount]; |
| 77 | + ctx.Alloc->Reset(); |
| 78 | + D3D12_RESOURCE_BARRIER bar = { D3D12_RESOURCE_BARRIER_TYPE_TRANSITION }; |
| 79 | + bar.Transition = { ctx.Res, D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES, D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET }; |
| 80 | + CmdList->Reset(ctx.Alloc, nullptr); |
| 81 | + CmdList->ResourceBarrier(1, &bar); |
| 82 | + CmdList->OMSetRenderTargets(1, &ctx.Handle, FALSE, nullptr); |
| 83 | + CmdList->SetDescriptorHeaps(1, &SRVHeap); |
| 84 | + ImGui_ImplDX12_RenderDrawData(igGetDrawData(), CmdList); |
| 85 | + bar.Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET; |
| 86 | + bar.Transition.StateAfter = D3D12_RESOURCE_STATE_PRESENT; |
| 87 | + CmdList->ResourceBarrier(1, &bar); |
| 88 | + CmdList->Close(); |
| 89 | + CmdQueue->ExecuteCommandLists(1, reinterpret_cast<ID3D12CommandList* const*>(&CmdList)); |
| 90 | + } |
| 91 | +} |
| 92 | + |
| 93 | +void APIENTRY hkExecuteCommandLists(ID3D12CommandQueue* queue, UINT n, ID3D12CommandList* lists) { |
| 94 | + if (!DX12::CmdQueue) { DX12::CmdQueue = queue; DEBUG_LOG("hkExecuteCommandLists: CmdQueue captured=%p", queue); } |
| 95 | + oExecuteCommandLists(queue, n, lists); |
| 96 | +} |
0 commit comments