[host] dxgi: fix d3d12 backend resource leak

The handle is only needed so we can open the resource, once we have
it we can close the handle. We then cache the shared resource for
future reuse if possible.
This commit is contained in:
Geoffrey McRae 2023-10-27 21:56:49 +11:00
parent 0510d06c4b
commit 2206752b66

View File

@ -44,25 +44,25 @@ struct D3D12Texture
HANDLE event; HANDLE event;
}; };
struct SharedCache
{
ID3D11Texture2D * tex;
ID3D12Resource ** d12src;
};
struct D3D12Backend struct D3D12Backend
{ {
float copySleep; float copySleep;
ID3D12Device ** device; ID3D12Device ** device;
ID3D12CommandQueue ** commandQueue; ID3D12CommandQueue ** commandQueue;
ID3D12Resource ** src;
struct D3D12Texture * texture; struct D3D12Texture * texture;
UINT64 fenceValue; UINT64 fenceValue;
ID3D12Fence ** fence; ID3D12Fence ** fence;
HANDLE event; HANDLE event;
// shared handle cache // shared handle cache
struct struct SharedCache sharedCache[10];
{ int sharedCacheCount;
ID3D11Texture2D * tex;
HANDLE handle;
}
handleCache[10];
int handleCacheCount;
}; };
static struct DXGIInterface * dxgi = NULL; static struct DXGIInterface * dxgi = NULL;
@ -283,8 +283,7 @@ static bool d3d12_create(struct DXGIInterface * intf)
dxgi->texture[i].impl = this->texture + i; dxgi->texture[i].impl = this->texture + i;
} }
comRef_newGlobal(&this->src); // dxgi->useAcquireLock = false;
dxgi->useAcquireLock = false;
return true; return true;
fail: fail:
@ -310,9 +309,6 @@ static void d3d12_free(void)
if (this->event) if (this->event)
CloseHandle(this->event); CloseHandle(this->event);
for(int i = 0; i < this->handleCacheCount; ++i)
CloseHandle(this->handleCache[i].handle);
free(this); free(this);
this = NULL; this = NULL;
} }
@ -324,25 +320,24 @@ static bool d3d12_copyFrame(Texture * parent, ID3D11Texture2D * src)
struct D3D12Texture * tex = parent->impl; struct D3D12Texture * tex = parent->impl;
bool fail = true; bool fail = true;
comRef_defineLocal(IDXGIResource1, res1); comRef_defineLocal(IDXGIResource1, res1);
ID3D12Resource * d12src = NULL;
HRESULT status; HRESULT status;
if (this->copySleep > 0) if (this->copySleep > 0)
nsleep((uint64_t)(this->copySleep * 1000000)); nsleep((uint64_t)(this->copySleep * 1000000));
HANDLE handle = INVALID_HANDLE_VALUE; if (this->sharedCacheCount > -1)
if (this->handleCacheCount > -1)
{ {
// see if there is a cached handle already available for this texture // see if there is a cached handle already available for this texture
for(int i = 0; i < this->handleCacheCount; ++i) for(int i = 0; i < this->sharedCacheCount; ++i)
if (this->handleCache[i].tex == src) if (this->sharedCache[i].tex == src)
{ {
handle = this->handleCache[i].handle; d12src = *this->sharedCache[i].d12src;
break; break;
} }
} }
if (handle == INVALID_HANDLE_VALUE) if (!d12src)
{ {
status = ID3D11Texture2D_QueryInterface(src, status = ID3D11Texture2D_QueryInterface(src,
&IID_IDXGIResource1, (void **)res1); &IID_IDXGIResource1, (void **)res1);
@ -353,47 +348,48 @@ static bool d3d12_copyFrame(Texture * parent, ID3D11Texture2D * src)
goto cleanup; goto cleanup;
} }
HANDLE handle;
status = IDXGIResource1_CreateSharedHandle(*res1, status = IDXGIResource1_CreateSharedHandle(*res1,
NULL, DXGI_SHARED_RESOURCE_READ, NULL, &handle); NULL, DXGI_SHARED_RESOURCE_READ, NULL, &handle);
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);
fail = true;
goto cleanup; goto cleanup;
} }
// store the handle for later use status = ID3D12Device_OpenSharedHandle(*this->device,
if (this->handleCacheCount < ARRAY_LENGTH(this->handleCache)) handle, &IID_ID3D12Resource, (void **)&d12src);
CloseHandle(handle);
if (FAILED(status))
{ {
this->handleCache[this->handleCacheCount].tex = src; DEBUG_WINERROR("Failed to open the shared handle for texture", status);
this->handleCache[this->handleCacheCount].handle = handle; goto cleanup;
++this->handleCacheCount; }
// store the texture for later use
if (this->sharedCacheCount < ARRAY_LENGTH(this->sharedCache))
{
struct SharedCache *cache = &this->sharedCache[this->sharedCacheCount++];
cache->tex = src;
*comRef_newGlobal(&cache->d12src) = (IUnknown *)d12src;
} }
else else
{ {
// too many handles to cache, disable the cache entirely // too many handles to cache, disable the cache entirely
for(int i = 0; i < this->handleCacheCount; ++i) for(int i = 0; i < this->sharedCacheCount; ++i)
CloseHandle(this->handleCache[i].handle); {
this->handleCacheCount = -1; struct SharedCache *cache = &this->sharedCache[this->sharedCacheCount++];
comRef_release(cache->d12src);
}
this->sharedCacheCount = -1;
} }
} }
status = ID3D12Device_OpenSharedHandle(*this->device,
handle, &IID_ID3D12Resource, (void **)this->src);
if (this->handleCacheCount == -1)
CloseHandle(handle);
if (FAILED(status))
{
DEBUG_WINERROR("Failed to get create shared handle for texture", status);
goto cleanup;
}
D3D12_TEXTURE_COPY_LOCATION srcLoc = D3D12_TEXTURE_COPY_LOCATION srcLoc =
{ {
.pResource = *this->src, .pResource = d12src,
.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX, .Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX,
.SubresourceIndex = 0 .SubresourceIndex = 0
}; };