mirror of
https://github.com/gnif/LookingGlass.git
synced 2024-11-14 13:07:54 +00:00
[host] dxgi: add preRelease callback
This is meant to avoid freeing the texture before the copy has finished.
This commit is contained in:
parent
5a93f1e00c
commit
68e5b812a9
4 changed files with 74 additions and 8 deletions
|
@ -188,6 +188,11 @@ static void d3d11_unmapTexture(Texture * tex)
|
||||||
tex->map = NULL;
|
tex->map = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void d3d11_preRelease(void)
|
||||||
|
{
|
||||||
|
// Nothing needs to be done.
|
||||||
|
}
|
||||||
|
|
||||||
struct DXGICopyBackend copyBackendD3D11 = {
|
struct DXGICopyBackend copyBackendD3D11 = {
|
||||||
.name = "Direct3D 11",
|
.name = "Direct3D 11",
|
||||||
.create = d3d11_create,
|
.create = d3d11_create,
|
||||||
|
@ -195,4 +200,5 @@ struct DXGICopyBackend copyBackendD3D11 = {
|
||||||
.copyFrame = d3d11_copyFrame,
|
.copyFrame = d3d11_copyFrame,
|
||||||
.mapTexture = d3d11_mapTexture,
|
.mapTexture = d3d11_mapTexture,
|
||||||
.unmapTexture = d3d11_unmapTexture,
|
.unmapTexture = d3d11_unmapTexture,
|
||||||
|
.preRelease = d3d11_preRelease,
|
||||||
};
|
};
|
||||||
|
|
|
@ -29,7 +29,6 @@
|
||||||
|
|
||||||
struct D3D12Texture
|
struct D3D12Texture
|
||||||
{
|
{
|
||||||
ID3D12Resource * src;
|
|
||||||
ID3D12Resource * tex;
|
ID3D12Resource * tex;
|
||||||
ID3D12CommandAllocator * commandAllocator;
|
ID3D12CommandAllocator * commandAllocator;
|
||||||
ID3D12CommandList * commandList;
|
ID3D12CommandList * commandList;
|
||||||
|
@ -43,7 +42,11 @@ struct D3D12Backend
|
||||||
{
|
{
|
||||||
ID3D12Device * device;
|
ID3D12Device * device;
|
||||||
ID3D12CommandQueue * commandQueue;
|
ID3D12CommandQueue * commandQueue;
|
||||||
|
ID3D12Resource * src;
|
||||||
struct D3D12Texture * texture;
|
struct D3D12Texture * texture;
|
||||||
|
UINT64 fenceValue;
|
||||||
|
ID3D12Fence * fence;
|
||||||
|
HANDLE event;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct DXGIInterface * dxgi = NULL;
|
static struct DXGIInterface * dxgi = NULL;
|
||||||
|
@ -122,6 +125,22 @@ static bool d3d12_create(struct DXGIInterface * intf)
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this->event = CreateEvent(NULL, TRUE, TRUE, NULL);
|
||||||
|
if (!this->event)
|
||||||
|
{
|
||||||
|
DEBUG_WINERROR("Failed to create capture event", status);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->fenceValue = 0;
|
||||||
|
status = ID3D12Device_CreateFence(this->device, 0, D3D12_FENCE_FLAG_NONE,
|
||||||
|
&IID_ID3D12Fence, (void **)&this->fence);
|
||||||
|
if (FAILED(status))
|
||||||
|
{
|
||||||
|
DEBUG_WINERROR("Failed to create capture fence", status);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
D3D12_HEAP_PROPERTIES readbackHeapProperties = {
|
D3D12_HEAP_PROPERTIES readbackHeapProperties = {
|
||||||
.Type = D3D12_HEAP_TYPE_READBACK,
|
.Type = D3D12_HEAP_TYPE_READBACK,
|
||||||
};
|
};
|
||||||
|
@ -232,6 +251,15 @@ static void d3d12_free(void)
|
||||||
free(this->texture);
|
free(this->texture);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this->fence)
|
||||||
|
ID3D12Fence_Release(this->fence);
|
||||||
|
|
||||||
|
if (this->event)
|
||||||
|
CloseHandle(this->event);
|
||||||
|
|
||||||
|
if (this->src)
|
||||||
|
ID3D12Resource_Release(this->src);
|
||||||
|
|
||||||
if (this->commandQueue)
|
if (this->commandQueue)
|
||||||
ID3D12CommandQueue_Release(this->commandQueue);
|
ID3D12CommandQueue_Release(this->commandQueue);
|
||||||
|
|
||||||
|
@ -265,7 +293,7 @@ static bool d3d12_copyFrame(Texture * parent, ID3D11Texture2D * src)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
status = ID3D12Device_OpenSharedHandle(this->device, handle, &IID_ID3D12Resource, (void **)&tex->src);
|
status = ID3D12Device_OpenSharedHandle(this->device, handle, &IID_ID3D12Resource, (void **)&this->src);
|
||||||
if (FAILED(status))
|
if (FAILED(status))
|
||||||
{
|
{
|
||||||
DEBUG_WINERROR("Failed to get create shared handle for texture", status);
|
DEBUG_WINERROR("Failed to get create shared handle for texture", status);
|
||||||
|
@ -277,7 +305,7 @@ static bool d3d12_copyFrame(Texture * parent, ID3D11Texture2D * src)
|
||||||
CloseHandle(handle);
|
CloseHandle(handle);
|
||||||
|
|
||||||
D3D12_TEXTURE_COPY_LOCATION srcLoc = {
|
D3D12_TEXTURE_COPY_LOCATION srcLoc = {
|
||||||
.pResource = tex->src,
|
.pResource = this->src,
|
||||||
.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX,
|
.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX,
|
||||||
.SubresourceIndex = 0
|
.SubresourceIndex = 0
|
||||||
};
|
};
|
||||||
|
@ -324,10 +352,27 @@ static bool d3d12_copyFrame(Texture * parent, ID3D11Texture2D * src)
|
||||||
|
|
||||||
ID3D12CommandQueue_ExecuteCommandLists(this->commandQueue, 1, &tex->commandList);
|
ID3D12CommandQueue_ExecuteCommandLists(this->commandQueue, 1, &tex->commandList);
|
||||||
|
|
||||||
|
status = ID3D12CommandQueue_Signal(this->commandQueue, this->fence, ++this->fenceValue);
|
||||||
|
if (FAILED(status))
|
||||||
|
{
|
||||||
|
DEBUG_WINERROR("Failed to signal capture fence", status);
|
||||||
|
fail = true;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
ResetEvent(this->event);
|
||||||
|
status = ID3D12Fence_SetEventOnCompletion(this->fence, this->fenceValue, this->event);
|
||||||
|
if (FAILED(status))
|
||||||
|
{
|
||||||
|
DEBUG_WINERROR("Failed to signal capture fence event", status);
|
||||||
|
fail = true;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
status = ID3D12CommandQueue_Signal(this->commandQueue, tex->fence, ++tex->fenceValue);
|
status = ID3D12CommandQueue_Signal(this->commandQueue, tex->fence, ++tex->fenceValue);
|
||||||
if (FAILED(status))
|
if (FAILED(status))
|
||||||
{
|
{
|
||||||
DEBUG_WINERROR("Failed to signal fence", status);
|
DEBUG_WINERROR("Failed to signal texture fence", status);
|
||||||
fail = true;
|
fail = true;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
@ -335,7 +380,7 @@ static bool d3d12_copyFrame(Texture * parent, ID3D11Texture2D * src)
|
||||||
status = ID3D12Fence_SetEventOnCompletion(tex->fence, tex->fenceValue, tex->event);
|
status = ID3D12Fence_SetEventOnCompletion(tex->fence, tex->fenceValue, tex->event);
|
||||||
if (FAILED(status))
|
if (FAILED(status))
|
||||||
{
|
{
|
||||||
DEBUG_WINERROR("Failed to signal fence event", status);
|
DEBUG_WINERROR("Failed to signal texture fence event", status);
|
||||||
fail = true;
|
fail = true;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
@ -367,8 +412,6 @@ static CaptureResult d3d12_mapTexture(Texture * parent)
|
||||||
return CAPTURE_RESULT_ERROR;
|
return CAPTURE_RESULT_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
ID3D12Resource_Release(tex->src);
|
|
||||||
|
|
||||||
D3D12_RANGE range = { .Begin = 0, .End = dxgi->pitch * dxgi->height };
|
D3D12_RANGE range = { .Begin = 0, .End = dxgi->pitch * dxgi->height };
|
||||||
status = ID3D12Resource_Map(tex->tex, 0, &range, &parent->map);
|
status = ID3D12Resource_Map(tex->tex, 0, &range, &parent->map);
|
||||||
|
|
||||||
|
@ -390,6 +433,17 @@ static void d3d12_unmapTexture(Texture * parent)
|
||||||
parent->map = NULL;
|
parent->map = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void d3d12_preRelease(void)
|
||||||
|
{
|
||||||
|
WaitForSingleObject(this->event, INFINITE);
|
||||||
|
|
||||||
|
if (this->src)
|
||||||
|
{
|
||||||
|
ID3D12Resource_Release(this->src);
|
||||||
|
this->src = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct DXGICopyBackend copyBackendD3D12 = {
|
struct DXGICopyBackend copyBackendD3D12 = {
|
||||||
.name = "Direct3D 12",
|
.name = "Direct3D 12",
|
||||||
.create = d3d12_create,
|
.create = d3d12_create,
|
||||||
|
@ -397,4 +451,5 @@ struct DXGICopyBackend copyBackendD3D12 = {
|
||||||
.copyFrame = d3d12_copyFrame,
|
.copyFrame = d3d12_copyFrame,
|
||||||
.mapTexture = d3d12_mapTexture,
|
.mapTexture = d3d12_mapTexture,
|
||||||
.unmapTexture = d3d12_unmapTexture,
|
.unmapTexture = d3d12_unmapTexture,
|
||||||
|
.preRelease = d3d12_preRelease,
|
||||||
};
|
};
|
||||||
|
|
|
@ -539,6 +539,9 @@ static bool dxgi_deinit(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this->dup)
|
||||||
|
dxgi_releaseFrame();
|
||||||
|
|
||||||
if (this->backend)
|
if (this->backend)
|
||||||
{
|
{
|
||||||
this->backend->free();
|
this->backend->free();
|
||||||
|
@ -553,7 +556,6 @@ static bool dxgi_deinit(void)
|
||||||
|
|
||||||
if (this->dup)
|
if (this->dup)
|
||||||
{
|
{
|
||||||
dxgi_releaseFrame();
|
|
||||||
IDXGIOutputDuplication_Release(this->dup);
|
IDXGIOutputDuplication_Release(this->dup);
|
||||||
this->dup = NULL;
|
this->dup = NULL;
|
||||||
}
|
}
|
||||||
|
@ -1036,6 +1038,8 @@ static CaptureResult dxgi_releaseFrame(void)
|
||||||
if (!this->needsRelease)
|
if (!this->needsRelease)
|
||||||
return CAPTURE_RESULT_OK;
|
return CAPTURE_RESULT_OK;
|
||||||
|
|
||||||
|
this->backend->preRelease();
|
||||||
|
|
||||||
HRESULT status;
|
HRESULT status;
|
||||||
LOCKED({status = IDXGIOutputDuplication_ReleaseFrame(this->dup);});
|
LOCKED({status = IDXGIOutputDuplication_ReleaseFrame(this->dup);});
|
||||||
switch(status)
|
switch(status)
|
||||||
|
|
|
@ -113,6 +113,7 @@ struct DXGICopyBackend
|
||||||
bool (*copyFrame)(Texture * tex, ID3D11Texture2D * src);
|
bool (*copyFrame)(Texture * tex, ID3D11Texture2D * src);
|
||||||
CaptureResult (*mapTexture)(Texture * tex);
|
CaptureResult (*mapTexture)(Texture * tex);
|
||||||
void (*unmapTexture)(Texture * tex);
|
void (*unmapTexture)(Texture * tex);
|
||||||
|
void (*preRelease)(void);
|
||||||
};
|
};
|
||||||
|
|
||||||
const char * GetDXGIFormatStr(DXGI_FORMAT format);
|
const char * GetDXGIFormatStr(DXGI_FORMAT format);
|
||||||
|
|
Loading…
Reference in a new issue