looking-glass/host/platform/Windows/capture/D12/command_group.c
2024-02-05 02:49:08 +11:00

161 lines
4.2 KiB
C

/**
* 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;
}