Skip to content

Commit

Permalink
[host] d12: adjust backend API to allow multiple instances
Browse files Browse the repository at this point in the history
  • Loading branch information
gnif committed Jan 30, 2024
1 parent 462d818 commit c07b728
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 51 deletions.
34 changes: 26 additions & 8 deletions host/platform/Windows/capture/D12/backend.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@
#include <d3d12.h>
#include "interface/capture.h"

typedef struct D12Backend
typedef struct D12Backend D12Backend;

struct D12Backend
{
// friendly name
const char * name;
Expand All @@ -34,21 +36,37 @@ typedef struct D12Backend
const char * codeName;

// creation/init/free
bool (*create)(unsigned frameBuffers);
bool (*create)(D12Backend ** instance, unsigned frameBuffers);
bool (*init)(
D12Backend * instance,
bool debug,
ID3D12Device3 * device,
IDXGIAdapter1 * adapter,
IDXGIOutput * output);
bool (*deinit)(void);
void (*free)(void);
bool (*deinit)(D12Backend * instance);
void (*free)(D12Backend ** instance);

// capture callbacks
CaptureResult (*capture)(unsigned frameBufferIndex);
CaptureResult (*sync )(ID3D12CommandQueue * commandQueue);
ID3D12Resource * (*fetch )(unsigned frameBufferIndex);
CaptureResult (*capture)(D12Backend * instance,
unsigned frameBufferIndex);

CaptureResult (*sync)(D12Backend * instance,
ID3D12CommandQueue * commandQueue);

ID3D12Resource * (*fetch)(D12Backend * instance,
unsigned frameBufferIndex);
};

// helpers for the interface

static inline bool d12_createBackend(
D12Backend * backend, D12Backend ** instance, unsigned frameBuffers)
{
if (!backend->create(instance, frameBuffers))
return false;
memcpy(*instance, backend, sizeof(*backend));
return true;
}
D12Backend;

// apis for the backend
void d12_updatePointer(
Expand Down
89 changes: 55 additions & 34 deletions host/platform/Windows/capture/D12/backend/dd.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,10 @@ typedef struct DDCacheInfo
}
DDCacheInfo;

struct DDInstance
typedef struct DDInstance
{
D12Backend base;

ComScope * comScope;

HDESK desktop;
Expand All @@ -49,51 +51,55 @@ struct DDInstance

void * shapeBuffer;
unsigned shapeBufferSize;
};

struct DDInstance * this = NULL;
}
DDInstance;

#define comRef_toGlobal(dst, src) \
_comRef_toGlobal(this->comScope, dst, src)

static void d12_dd_openDesktop(void);
static bool d12_dd_handleFrameUpdate(IDXGIResource * res);
static void d12_dd_openDesktop(DDInstance * this);
static bool d12_dd_handleFrameUpdate(DDInstance * this, IDXGIResource * res);

static void d12_dd_handlePointerMovement(DXGI_OUTDUPL_POINTER_POSITION * pos,
CapturePointer * pointer, bool * changed);
static void d12_dd_handlePointerShape(
static void d12_dd_handlePointerMovement(DDInstance * this,
DXGI_OUTDUPL_POINTER_POSITION * pos, CapturePointer * pointer, bool * changed);
static void d12_dd_handlePointerShape(DDInstance * this,
CapturePointer * pointer, size_t size, bool * changed);

static bool d12_dd_getCache(ID3D11Texture2D * srcTex, DDCacheInfo ** result);
static bool d12_dd_convertResource(ID3D11Texture2D * srcTex,
DDCacheInfo * cache);
static bool d12_dd_getCache(DDInstance * this,
ID3D11Texture2D * srcTex, DDCacheInfo ** result);
static bool d12_dd_convertResource(DDInstance * this,
ID3D11Texture2D * srcTex, DDCacheInfo * cache);

static bool d12_dd_create(unsigned frameBuffers)
static bool d12_dd_create(D12Backend ** instance, unsigned frameBuffers)
{
this = calloc(1, sizeof(*this));
DDInstance * this = calloc(1, sizeof(*this));
if (!this)
{
DEBUG_ERROR("out of memory");
return false;
}

*instance = &this->base;
return true;
}

static bool d12_dd_init(
D12Backend * instance,
bool debug,
ID3D12Device3 * device,
IDXGIAdapter1 * adapter,
IDXGIOutput * output)
{
DDInstance * this = UPCAST(DDInstance, instance);

bool result = false;
HRESULT hr;

comRef_initGlobalScope(10 + CACHE_SIZE * 2, this->comScope);
comRef_scopePush(10);

// try to open the desktop so we can capture the secure desktop
d12_dd_openDesktop();
d12_dd_openDesktop(this);

comRef_defineLocal(IDXGIAdapter, _adapter);
hr = IDXGIAdapter1_QueryInterface(
Expand Down Expand Up @@ -249,8 +255,10 @@ static bool d12_dd_init(
return result;
}

static bool d12_dd_deinit(void)
static bool d12_dd_deinit(D12Backend * instance)
{
DDInstance * this = UPCAST(DDInstance, instance);

if (this->release)
{
IDXGIOutputDuplication_ReleaseFrame(*this->dup);
Expand All @@ -264,15 +272,17 @@ static bool d12_dd_deinit(void)
}

comRef_freeScope(&this->comScope);
memset(this, 0, sizeof(*this));
memset(this->cache, 0, sizeof(this->cache));
return true;
}

static void d12_dd_free(void)
static void d12_dd_free(D12Backend ** instance)
{
DDInstance * this = UPCAST(DDInstance, *instance);

free(this->shapeBuffer);
free(this);
this = NULL;
*instance = NULL;
}

static CaptureResult d12_dd_hResultToCaptureResult(const HRESULT status)
Expand All @@ -295,8 +305,11 @@ static CaptureResult d12_dd_hResultToCaptureResult(const HRESULT status)
}
}

static CaptureResult d12_dd_capture(unsigned frameBufferIndex)
static CaptureResult d12_dd_capture(D12Backend * instance,
unsigned frameBufferIndex)
{
DDInstance * this = UPCAST(DDInstance, instance);

HRESULT hr;
CaptureResult result = CAPTURE_RESULT_ERROR;
comRef_scopePush(10);
Expand Down Expand Up @@ -337,7 +350,7 @@ static CaptureResult d12_dd_capture(unsigned frameBufferIndex)

// if we have a new frame
if (frameInfo.LastPresentTime.QuadPart != 0)
if (!d12_dd_handleFrameUpdate(*res))
if (!d12_dd_handleFrameUpdate(this, *res))
{
result = CAPTURE_RESULT_ERROR;
goto exit;
Expand All @@ -348,12 +361,12 @@ static CaptureResult d12_dd_capture(unsigned frameBufferIndex)

// if the pointer has moved
if (frameInfo.LastMouseUpdateTime.QuadPart != 0)
d12_dd_handlePointerMovement(
d12_dd_handlePointerMovement(this,
&frameInfo.PointerPosition, &pointer, &postPointer);

// if the pointer shape has changed
if (frameInfo.PointerShapeBufferSize > 0)
d12_dd_handlePointerShape(
d12_dd_handlePointerShape(this,
&pointer, frameInfo.PointerShapeBufferSize, &postPointer);

if (postPointer)
Expand All @@ -368,8 +381,11 @@ static CaptureResult d12_dd_capture(unsigned frameBufferIndex)
return result;
}

static CaptureResult d12_dd_sync(ID3D12CommandQueue * commandQueue)
static CaptureResult d12_dd_sync(D12Backend * instance,
ID3D12CommandQueue * commandQueue)
{
DDInstance * this = UPCAST(DDInstance, instance);

if (!this->current)
return CAPTURE_RESULT_TIMEOUT;

Expand All @@ -380,16 +396,19 @@ static CaptureResult d12_dd_sync(ID3D12CommandQueue * commandQueue)
return CAPTURE_RESULT_OK;
}

static ID3D12Resource * d12_dd_fetch(unsigned frameBufferIndex)
static ID3D12Resource * d12_dd_fetch(D12Backend * instance,
unsigned frameBufferIndex)
{
DDInstance * this = UPCAST(DDInstance, instance);

if (!this->current)
return NULL;

ID3D12Resource_AddRef(*this->current->d12Res);
return *this->current->d12Res;
}

static void d12_dd_openDesktop(void)
static void d12_dd_openDesktop(DDInstance * this)
{
this->desktop = OpenInputDesktop(0, FALSE, GENERIC_READ);
if (!this->desktop)
Expand All @@ -415,7 +434,7 @@ static void d12_dd_openDesktop(void)
}
}

static bool d12_dd_handleFrameUpdate(IDXGIResource * res)
static bool d12_dd_handleFrameUpdate(DDInstance * this, IDXGIResource * res)
{
bool result = false;
comRef_scopePush(1);
Expand All @@ -429,7 +448,7 @@ static bool d12_dd_handleFrameUpdate(IDXGIResource * res)
goto exit;
}

if (!d12_dd_getCache(*srcTex, &this->current))
if (!d12_dd_getCache(this, *srcTex, &this->current))
goto exit;

/**
Expand All @@ -447,8 +466,8 @@ static bool d12_dd_handleFrameUpdate(IDXGIResource * res)
return result;
}

static void d12_dd_handlePointerMovement(DXGI_OUTDUPL_POINTER_POSITION * pos,
CapturePointer * pointer, bool * changed)
static void d12_dd_handlePointerMovement(DDInstance * this,
DXGI_OUTDUPL_POINTER_POSITION * pos, CapturePointer * pointer, bool * changed)
{
bool setPos = false;

Expand Down Expand Up @@ -488,7 +507,7 @@ static void d12_dd_handlePointerMovement(DXGI_OUTDUPL_POINTER_POSITION * pos,
this->lastPosValid = true;
}

static void d12_dd_handlePointerShape(
static void d12_dd_handlePointerShape(DDInstance * this,
CapturePointer * pointer, size_t size, bool * changed)
{
HRESULT hr;
Expand Down Expand Up @@ -556,7 +575,8 @@ static void d12_dd_handlePointerShape(
*changed = true;
}

static bool d12_dd_getCache(ID3D11Texture2D * srcTex, DDCacheInfo ** result)
static bool d12_dd_getCache(DDInstance * this,
ID3D11Texture2D * srcTex, DDCacheInfo ** result)
{
*result = NULL;
D3D11_TEXTURE2D_DESC srcDesc;
Expand Down Expand Up @@ -597,15 +617,16 @@ static bool d12_dd_getCache(ID3D11Texture2D * srcTex, DDCacheInfo ** result)
return false;

// convert the resource
if (!d12_dd_convertResource(srcTex, &this->cache[freeSlot]))
if (!d12_dd_convertResource(this, srcTex, &this->cache[freeSlot]))
return false;

// return the new cache entry
*result = &this->cache[freeSlot];
return true;
}

static bool d12_dd_convertResource(ID3D11Texture2D * srcTex, DDCacheInfo * cache)
static bool d12_dd_convertResource(DDInstance * this,
ID3D11Texture2D * srcTex, DDCacheInfo * cache)
{
bool result = false;
HRESULT hr;
Expand Down
18 changes: 9 additions & 9 deletions host/platform/Windows/capture/D12/d12.c
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,7 @@ static bool d12_create(
this->getPointerBufferFn = getPointerBufferFn;
this->postPointerBufferFn = postPointerBufferFn;

this->backend = &D12Backend_DD;
if (!this->backend->create(frameBuffers))
if (!d12_createBackend(&D12Backend_DD, &this->backend, frameBuffers))
{
DEBUG_ERROR("backend \"%s\" failed to create", this->backend->codeName);
CloseHandle(this->d3d12);
Expand Down Expand Up @@ -279,7 +278,8 @@ static bool d12_init(void * ivshmemBase, unsigned * alignSize)
*alignSize = heapDesc.Alignment;

// initialize the backend
if (!this->backend->init(this->debug, *device, *adapter, *output))
if (!this->backend->init(this->backend,
this->debug, *device, *adapter, *output))
goto exit;

comRef_toGlobal(this->factory , factory );
Expand All @@ -304,7 +304,7 @@ static void d12_stop(void)
static bool d12_deinit(void)
{
bool result = true;
if (!this->backend->deinit())
if (!this->backend->deinit(this->backend))
result = false;

d12_freeCommandGroup(&this->copyCommand);
Expand All @@ -314,7 +314,7 @@ static bool d12_deinit(void)

static void d12_free(void)
{
this->backend->free();
this->backend->free(&this->backend);
FreeLibrary(this->d3d12);
free(this);
this = NULL;
Expand All @@ -323,7 +323,7 @@ static void d12_free(void)
static CaptureResult d12_capture(
unsigned frameBufferIndex, FrameBuffer * frameBuffer)
{
return this->backend->capture(frameBufferIndex);
return this->backend->capture(this->backend, frameBufferIndex);
}

static CaptureResult d12_waitFrame(unsigned frameBufferIndex,
Expand All @@ -333,7 +333,7 @@ static CaptureResult d12_waitFrame(unsigned frameBufferIndex,
comRef_scopePush(1);

comRef_defineLocal(ID3D12Resource, src);
*src = this->backend->fetch(frameBufferIndex);
*src = this->backend->fetch(this->backend, frameBufferIndex);
if (!*src)
{
DEBUG_ERROR("D12 backend failed to produce an expected frame: %u",
Expand Down Expand Up @@ -383,7 +383,7 @@ static CaptureResult d12_getFrame(unsigned frameBufferIndex,
comRef_scopePush(2);

comRef_defineLocal(ID3D12Resource, src);
*src = this->backend->fetch(frameBufferIndex);
*src = this->backend->fetch(this->backend, frameBufferIndex);
if (!*src)
{
DEBUG_ERROR("D12 backend failed to produce an expected frame: %u",
Expand Down Expand Up @@ -427,7 +427,7 @@ static CaptureResult d12_getFrame(unsigned frameBufferIndex,
*this->copyCommand.gfxList, &dstLoc, 0, 0, 0, &srcLoc, NULL);

// allow the backend to insert a fence into the command queue if it needs it
result = this->backend->sync(*this->commandQueue);
result = this->backend->sync(this->backend, *this->commandQueue);
if (result != CAPTURE_RESULT_OK)
goto exit;

Expand Down

0 comments on commit c07b728

Please sign in to comment.