diff --git a/src/d3d11/d3d11_device.cpp b/src/d3d11/d3d11_device.cpp index 337c3127a..0984f73e0 100644 --- a/src/d3d11/d3d11_device.cpp +++ b/src/d3d11/d3d11_device.cpp @@ -1353,7 +1353,7 @@ namespace dxvk { InitReturnPtr(ppFence); try { - Com fence = new D3D11Fence(this, InitialValue, Flags); + Com fence = new D3D11Fence(this, InitialValue, Flags, INVALID_HANDLE_VALUE); return fence->QueryInterface(riid, ppFence); } catch (const DxvkError& e) { Logger::err(e.message()); @@ -1424,8 +1424,16 @@ namespace dxvk { void** ppFence) { InitReturnPtr(ppFence); - Logger::err("D3D11Device::OpenSharedFence: Not implemented"); - return E_NOTIMPL; + if (ppFence == nullptr) + return S_FALSE; + + try { + Com fence = new D3D11Fence(this, 0, D3D11_FENCE_FLAG_SHARED, hFence); + return fence->QueryInterface(ReturnedInterface, ppFence); + } catch (const DxvkError& e) { + Logger::err(e.message()); + return E_FAIL; + } } diff --git a/src/d3d11/d3d11_fence.cpp b/src/d3d11/d3d11_fence.cpp index 3c802f898..e3c7688b2 100644 --- a/src/d3d11/d3d11_fence.cpp +++ b/src/d3d11/d3d11_fence.cpp @@ -6,12 +6,21 @@ namespace dxvk { D3D11Fence::D3D11Fence( D3D11Device* pDevice, UINT64 InitialValue, - D3D11_FENCE_FLAG Flags) + D3D11_FENCE_FLAG Flags, + HANDLE hFence) : D3D11DeviceChild(pDevice) { DxvkFenceCreateInfo fenceInfo; fenceInfo.initialValue = InitialValue; + m_flags = Flags; - if (Flags) + if (Flags & D3D11_FENCE_FLAG_SHARED) { + fenceInfo.sharedType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D11_FENCE_BIT; + if (hFence == nullptr) + hFence = INVALID_HANDLE_VALUE; + fenceInfo.sharedHandle = hFence; + } + + if (Flags & ~D3D11_FENCE_FLAG_SHARED) Logger::err(str::format("Fence flags 0x", std::hex, Flags, " not supported")); m_fence = pDevice->GetDXVKDevice()->createFence(fenceInfo); @@ -49,14 +58,31 @@ namespace dxvk { DWORD dwAccess, LPCWSTR lpName, HANDLE* pHandle) { - Logger::err("D3D11Fence::CreateSharedHandle: Not implemented"); - return E_NOTIMPL; + if (!(m_flags & D3D11_FENCE_FLAG_SHARED)) + return E_INVALIDARG; + + if (pAttributes) + Logger::warn(str::format("CreateSharedHandle: attributes ", pAttributes, " not handled")); + if (dwAccess) + Logger::warn(str::format("CreateSharedHandle: access ", dwAccess, " not handled")); + if (lpName) + Logger::warn(str::format("CreateSharedHandle: name ", dxvk::str::fromws(lpName), " not handled")); + + HANDLE sharedHandle = m_fence->sharedHandle(); + if (sharedHandle == INVALID_HANDLE_VALUE) + return E_INVALIDARG; + + *pHandle = sharedHandle; + return S_OK; } HRESULT STDMETHODCALLTYPE D3D11Fence::SetEventOnCompletion( UINT64 Value, HANDLE hEvent) { + // TODO in case of rewinds, the stored value may be higher. + // For shared fences, calling vkWaitSemaphores here could alleviate the issue. + m_fence->enqueueWait(Value, [hEvent] { SetEvent(hEvent); }); @@ -66,6 +92,9 @@ namespace dxvk { UINT64 STDMETHODCALLTYPE D3D11Fence::GetCompletedValue() { + // TODO in the case of rewinds, the stored value may be higher. + // For shared fences, calling vkGetSemaphoreCounterValue here could alleviate the issue. + return m_fence->getValue(); } diff --git a/src/d3d11/d3d11_fence.h b/src/d3d11/d3d11_fence.h index b29c0c999..99d42a943 100644 --- a/src/d3d11/d3d11_fence.h +++ b/src/d3d11/d3d11_fence.h @@ -14,7 +14,8 @@ namespace dxvk { D3D11Fence( D3D11Device* pDevice, UINT64 InitialValue, - D3D11_FENCE_FLAG Flags); + D3D11_FENCE_FLAG Flags, + HANDLE hFence); ~D3D11Fence(); @@ -41,6 +42,7 @@ namespace dxvk { private: Rc m_fence; + D3D11_FENCE_FLAG m_flags; };