mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-10 08:51:28 +12:00
d3d12: Async semaphore leads to deadlock, make it sync, but do resource garbage collection async
This commit is contained in:
parent
10b92d45d1
commit
2d0dbf4949
2 changed files with 83 additions and 37 deletions
|
@ -79,6 +79,44 @@ void DataHeap::Release()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GarbageCollectionThread::GarbageCollectionThread()
|
||||||
|
{
|
||||||
|
m_worker = std::thread([this]() {
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lock(m_mutex);
|
||||||
|
if (m_queue.empty())
|
||||||
|
cv.wait(lock);
|
||||||
|
m_queue.front()();
|
||||||
|
m_queue.pop();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
m_worker.detach();
|
||||||
|
}
|
||||||
|
|
||||||
|
GarbageCollectionThread::~GarbageCollectionThread()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void GarbageCollectionThread::pushWork(std::function<void()>&& f)
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lock(m_mutex);
|
||||||
|
m_queue.push(f);
|
||||||
|
cv.notify_all();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GarbageCollectionThread::waitForCompletion()
|
||||||
|
{
|
||||||
|
pushWork([]() {});
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
std::this_thread::yield();
|
||||||
|
std::unique_lock<std::mutex> lock(m_mutex);
|
||||||
|
if (m_queue.empty())
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void D3D12GSRender::ResourceStorage::Reset()
|
void D3D12GSRender::ResourceStorage::Reset()
|
||||||
{
|
{
|
||||||
m_constantsBufferIndex = 0;
|
m_constantsBufferIndex = 0;
|
||||||
|
@ -1128,40 +1166,45 @@ void D3D12GSRender::Flip()
|
||||||
check(m_swapChain->Present(Ini.GSVSyncEnable.GetValue() ? 1 : 0, 0));
|
check(m_swapChain->Present(Ini.GSVSyncEnable.GetValue() ? 1 : 0, 0));
|
||||||
// Add an event signaling queue completion
|
// Add an event signaling queue completion
|
||||||
|
|
||||||
m_device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&getNonCurrentResourceStorage().m_frameFinishedFence));
|
ResourceStorage &storage = getNonCurrentResourceStorage();
|
||||||
getNonCurrentResourceStorage().m_frameFinishedHandle = CreateEvent(0, 0, 0, 0);
|
|
||||||
getNonCurrentResourceStorage().m_frameFinishedFence->SetEventOnCompletion(1, getNonCurrentResourceStorage().m_frameFinishedHandle);
|
m_device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&storage.m_frameFinishedFence));
|
||||||
m_commandQueueGraphic->Signal(getNonCurrentResourceStorage().m_frameFinishedFence, 1);
|
storage.m_frameFinishedHandle = CreateEvent(0, 0, 0, 0);
|
||||||
|
storage.m_frameFinishedFence->SetEventOnCompletion(1, storage.m_frameFinishedHandle);
|
||||||
|
m_commandQueueGraphic->Signal(storage.m_frameFinishedFence, 1);
|
||||||
|
|
||||||
// Flush
|
// Flush
|
||||||
m_texturesCache.clear();
|
m_texturesCache.clear();
|
||||||
m_texturesRTTs.clear();
|
m_texturesRTTs.clear();
|
||||||
getNonCurrentResourceStorage().m_inUseConstantsBuffers = m_constantsData.m_resourceStoredSinceLastSync;
|
|
||||||
|
storage.m_inUseConstantsBuffers = m_constantsData.m_resourceStoredSinceLastSync;
|
||||||
m_constantsData.m_resourceStoredSinceLastSync.clear();
|
m_constantsData.m_resourceStoredSinceLastSync.clear();
|
||||||
getNonCurrentResourceStorage().m_inUseVertexIndexBuffers = m_vertexIndexData.m_resourceStoredSinceLastSync;
|
storage.m_inUseVertexIndexBuffers = m_vertexIndexData.m_resourceStoredSinceLastSync;
|
||||||
m_vertexIndexData.m_resourceStoredSinceLastSync.clear();
|
m_vertexIndexData.m_resourceStoredSinceLastSync.clear();
|
||||||
getNonCurrentResourceStorage().m_inUseTextureUploadBuffers = m_textureUploadData.m_resourceStoredSinceLastSync;
|
storage.m_inUseTextureUploadBuffers = m_textureUploadData.m_resourceStoredSinceLastSync;
|
||||||
m_textureUploadData.m_resourceStoredSinceLastSync.clear();
|
m_textureUploadData.m_resourceStoredSinceLastSync.clear();
|
||||||
getNonCurrentResourceStorage().m_inUseTexture2D = m_textureData.m_resourceStoredSinceLastSync;
|
storage.m_inUseTexture2D = m_textureData.m_resourceStoredSinceLastSync;
|
||||||
m_textureData.m_resourceStoredSinceLastSync.clear();
|
m_textureData.m_resourceStoredSinceLastSync.clear();
|
||||||
|
|
||||||
if (getCurrentResourceStorage().m_frameFinishedHandle)
|
m_GC.pushWork([&]()
|
||||||
{
|
{
|
||||||
WaitForSingleObject(getCurrentResourceStorage().m_frameFinishedHandle, INFINITE);
|
WaitForSingleObject(storage.m_frameFinishedHandle, INFINITE);
|
||||||
CloseHandle(getCurrentResourceStorage().m_frameFinishedHandle);
|
CloseHandle(storage.m_frameFinishedHandle);
|
||||||
getCurrentResourceStorage().m_frameFinishedFence->Release();
|
storage.m_frameFinishedFence->Release();
|
||||||
|
|
||||||
for (auto tmp : getCurrentResourceStorage().m_inUseConstantsBuffers)
|
for (auto tmp : storage.m_inUseConstantsBuffers)
|
||||||
m_constantsData.m_getPos = std::get<0>(tmp);
|
m_constantsData.m_getPos = std::get<0>(tmp);
|
||||||
for (auto tmp : getCurrentResourceStorage().m_inUseVertexIndexBuffers)
|
for (auto tmp : storage.m_inUseVertexIndexBuffers)
|
||||||
m_vertexIndexData.m_getPos = std::get<0>(tmp);
|
m_vertexIndexData.m_getPos = std::get<0>(tmp);
|
||||||
for (auto tmp : getCurrentResourceStorage().m_inUseTextureUploadBuffers)
|
for (auto tmp : storage.m_inUseTextureUploadBuffers)
|
||||||
m_textureUploadData.m_getPos = std::get<0>(tmp);
|
m_textureUploadData.m_getPos = std::get<0>(tmp);
|
||||||
for (auto tmp : getCurrentResourceStorage().m_inUseTexture2D)
|
for (auto tmp : storage.m_inUseTexture2D)
|
||||||
m_textureData.m_getPos = std::get<0>(tmp);
|
m_textureData.m_getPos = std::get<0>(tmp);
|
||||||
getCurrentResourceStorage().Reset();
|
storage.Reset();
|
||||||
}
|
});
|
||||||
|
|
||||||
|
while (getCurrentResourceStorage().m_frameFinishedHandle)
|
||||||
|
std::this_thread::yield();
|
||||||
m_frame->Flip(nullptr);
|
m_frame->Flip(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1446,7 +1489,7 @@ void D3D12GSRender::semaphorePGRAPHBackendRelease(u32 offset, u32 value)
|
||||||
//Wait for result
|
//Wait for result
|
||||||
m_commandQueueGraphic->Signal(fence, 1);
|
m_commandQueueGraphic->Signal(fence, 1);
|
||||||
|
|
||||||
std::thread valueChangerThread([=]() {
|
m_GC.pushWork([=]() {
|
||||||
WaitForSingleObject(handle, INFINITE);
|
WaitForSingleObject(handle, INFINITE);
|
||||||
CloseHandle(handle);
|
CloseHandle(handle);
|
||||||
fence->Release();
|
fence->Release();
|
||||||
|
@ -1561,28 +1604,17 @@ void D3D12GSRender::semaphorePGRAPHBackendRelease(u32 offset, u32 value)
|
||||||
|
|
||||||
vm::write32(m_label_addr + offset, value);
|
vm::write32(m_label_addr + offset, value);
|
||||||
});
|
});
|
||||||
valueChangerThread.detach();
|
|
||||||
|
m_GC.waitForCompletion();
|
||||||
}
|
}
|
||||||
|
|
||||||
void D3D12GSRender::semaphorePFIFOAcquire(u32 offset, u32 value)
|
void D3D12GSRender::semaphorePFIFOAcquire(u32 offset, u32 value)
|
||||||
{
|
{
|
||||||
ID3D12Fence *fence;
|
while (true)
|
||||||
check(
|
{
|
||||||
m_device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&fence))
|
u32 val = vm::read32(m_label_addr + offset);
|
||||||
);
|
if (val == value) break;
|
||||||
m_commandQueueGraphic->Wait(fence, 1);
|
std::this_thread::yield();
|
||||||
|
|
||||||
std::thread valueChangerThread([=]() {
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
u32 val = vm::read32(m_label_addr + offset);
|
|
||||||
if (val == value) break;
|
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
|
||||||
}
|
|
||||||
fence->Signal(1);
|
|
||||||
fence->Release();
|
|
||||||
}
|
}
|
||||||
);
|
|
||||||
valueChangerThread.detach();
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -61,9 +61,23 @@ struct DataHeap
|
||||||
void Release();
|
void Release();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct GarbageCollectionThread
|
||||||
|
{
|
||||||
|
std::mutex m_mutex;
|
||||||
|
std::condition_variable cv;
|
||||||
|
std::queue<std::function<void()> > m_queue;
|
||||||
|
std::thread m_worker;
|
||||||
|
|
||||||
|
GarbageCollectionThread();
|
||||||
|
~GarbageCollectionThread();
|
||||||
|
void pushWork(std::function<void()>&& f);
|
||||||
|
void waitForCompletion();
|
||||||
|
};
|
||||||
|
|
||||||
class D3D12GSRender : public GSRender
|
class D3D12GSRender : public GSRender
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
GarbageCollectionThread m_GC;
|
||||||
// Copy of RTT to be used as texture
|
// Copy of RTT to be used as texture
|
||||||
std::unordered_map<u32, ID3D12Resource* > m_texturesRTTs;
|
std::unordered_map<u32, ID3D12Resource* > m_texturesRTTs;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue