/** * Looking Glass * Copyright © 2017-2024 The Looking Glass Authors * https://looking-glass.io * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., 59 * Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "command_group.h" #include "d12.h" #include "com_ref.h" #include "common/debug.h" #include "common/windebug.h" bool d12_commandGroupCreate(ID3D12Device3 * device, D3D12_COMMAND_LIST_TYPE type, D12CommandGroup * dst, LPCWSTR name) { bool result = false; HRESULT hr; comRef_scopePush(10); comRef_defineLocal(ID3D12CommandAllocator, allocator); hr = ID3D12Device3_CreateCommandAllocator( device, type, &IID_ID3D12CommandAllocator, (void **)allocator); if (FAILED(hr)) { DEBUG_ERROR("Failed to create the ID3D12CommandAllocator"); goto exit; } ID3D12CommandAllocator_SetName(*allocator, name); comRef_defineLocal(ID3D12GraphicsCommandList, gfxList); hr = ID3D12Device3_CreateCommandList( device, 0, type, *allocator, NULL, &IID_ID3D12GraphicsCommandList, (void **)gfxList); if (FAILED(hr)) { DEBUG_WINERROR("Failed to create ID3D12GraphicsCommandList", hr); goto exit; } ID3D12GraphicsCommandList_SetName(*gfxList, name); comRef_defineLocal(ID3D12CommandList, cmdList); hr = ID3D12GraphicsCommandList_QueryInterface( *gfxList, &IID_ID3D12CommandList, (void **)cmdList); if (FAILED(hr)) { DEBUG_WINERROR("Failed to query the ID3D12CommandList interface", hr); goto exit; } comRef_defineLocal(ID3D12Fence, fence); hr = ID3D12Device3_CreateFence( device, 0, D3D12_FENCE_FLAG_NONE, &IID_ID3D12Fence, (void **)fence); if (FAILED(hr)) { DEBUG_WINERROR("Failed to create ID3D12Fence", hr); goto exit; } // Create the completion event for the fence HANDLE event = CreateEvent(NULL, FALSE, FALSE, NULL); if (!event) { DEBUG_WINERROR("Failed to create the completion event", GetLastError()); goto exit; } comRef_toGlobal(dst->allocator, allocator); comRef_toGlobal(dst->gfxList , gfxList ); comRef_toGlobal(dst->cmdList , cmdList ); comRef_toGlobal(dst->fence , fence ); dst->event = event; dst->fenceValue = 0; result = true; exit: comRef_scopePop(); return result; } void d12_commandGroupFree(D12CommandGroup * grp) { // only the handle needs to be free'd, the rest is handled by comRef if (grp->event) { CloseHandle(grp->event); grp->event = NULL; } } bool d12_commandGroupExecute(ID3D12CommandQueue * queue, D12CommandGroup * grp) { HRESULT hr = ID3D12GraphicsCommandList_Close(*grp->gfxList); if (FAILED(hr)) { DEBUG_WINERROR("Failed to close the command list", hr); return false; } ID3D12CommandQueue_ExecuteCommandLists(queue, 1, grp->cmdList); hr = ID3D12CommandQueue_Signal(queue, *grp->fence, ++grp->fenceValue); if (FAILED(hr)) { DEBUG_WINERROR("Failed to set the fence signal", hr); return false; } return true; } void d12_commandGroupWait(D12CommandGroup * grp) { if (ID3D12Fence_GetCompletedValue(*grp->fence) >= grp->fenceValue) return; ID3D12Fence_SetEventOnCompletion(*grp->fence, grp->fenceValue, grp->event); WaitForSingleObject(grp->event, INFINITE); } bool d12_commandGroupReset(D12CommandGroup * grp) { HRESULT hr = ID3D12CommandAllocator_Reset(*grp->allocator); if (FAILED(hr)) { DEBUG_WINERROR("Failed to reset the command allocator", hr); return false; } hr = ID3D12GraphicsCommandList_Reset(*grp->gfxList, *grp->allocator, NULL); if (FAILED(hr)) { DEBUG_WINERROR("Failed to reset the graphics command list", hr); return false; } return true; }