1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-23 03:02:53 +01:00

d3d12: Get rid of extra garbage collection off

This commit is contained in:
Vincent Lejeune 2015-09-13 20:12:21 +02:00
parent bf04758285
commit 72e5578595
2 changed files with 41 additions and 129 deletions

View File

@ -33,67 +33,6 @@ void SetGetD3DGSFrameCallback(GetGSFrameCb2 value)
GetGSFrame = value; GetGSFrame = value;
} }
GarbageCollectionThread::GarbageCollectionThread()
{
m_askForTermination = false;
m_worker = std::thread([this]() {
std::unique_lock<std::mutex> lock(m_mutex);
while (!m_askForTermination)
{
if (!lock)
{
lock.lock();
continue;
}
if (!m_queue.empty())
{
auto func = std::move(m_queue.front());
m_queue.pop();
if (lock) lock.unlock();
func();
continue;
}
cv.wait(lock);
}
});
}
GarbageCollectionThread::~GarbageCollectionThread()
{
{
std::unique_lock<std::mutex> lock(m_mutex);
m_askForTermination = true;
cv.notify_one();
}
m_worker.join();
}
void GarbageCollectionThread::pushWork(std::function<void()>&& f)
{
{
std::unique_lock<std::mutex> lock(m_mutex);
m_queue.push(f);
}
cv.notify_one();
}
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;
@ -115,6 +54,7 @@ void D3D12GSRender::ResourceStorage::setNewCommandList()
void D3D12GSRender::ResourceStorage::Init(ID3D12Device *device) void D3D12GSRender::ResourceStorage::Init(ID3D12Device *device)
{ {
m_inUse = false;
m_device = device; m_device = device;
m_RAMFramebuffer = nullptr; m_RAMFramebuffer = nullptr;
// Create a global command allocator // Create a global command allocator
@ -149,23 +89,21 @@ void D3D12GSRender::ResourceStorage::Init(ID3D12Device *device)
m_frameFinishedHandle = CreateEventEx(nullptr, FALSE, FALSE, EVENT_ALL_ACCESS); m_frameFinishedHandle = CreateEventEx(nullptr, FALSE, FALSE, EVENT_ALL_ACCESS);
m_fenceValue = 0; m_fenceValue = 0;
ThrowIfFailed(device->CreateFence(m_fenceValue++, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(m_frameFinishedFence.GetAddressOf()))); ThrowIfFailed(device->CreateFence(m_fenceValue++, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(m_frameFinishedFence.GetAddressOf())));
m_isUseable = true;
} }
void D3D12GSRender::ResourceStorage::WaitAndClean(const std::vector<ID3D12Resource *> &dirtyTextures) void D3D12GSRender::ResourceStorage::WaitAndClean()
{ {
if (!m_isUseable) if (m_inUse)
WaitForSingleObjectEx(m_frameFinishedHandle, INFINITE, FALSE); WaitForSingleObjectEx(m_frameFinishedHandle, INFINITE, FALSE);
else else
ThrowIfFailed(m_commandList->Close()); ThrowIfFailed(m_commandList->Close());
Reset(); Reset();
for (auto tmp : dirtyTextures) for (auto tmp : m_dirtyTextures)
tmp->Release(); tmp->Release();
m_RAMFramebuffer = nullptr; m_RAMFramebuffer = nullptr;
m_isUseable.store(true, std::memory_order_release);
} }
void D3D12GSRender::ResourceStorage::Release() void D3D12GSRender::ResourceStorage::Release()
@ -385,9 +323,7 @@ D3D12GSRender::D3D12GSRender()
D3D12GSRender::~D3D12GSRender() D3D12GSRender::~D3D12GSRender()
{ {
while (!getCurrentResourceStorage().m_isUseable.load(std::memory_order_acquire) && getNonCurrentResourceStorage().WaitAndClean();
!getNonCurrentResourceStorage().m_isUseable.load(std::memory_order_acquire))
std::this_thread::yield();
gfxHandler = [this](u32) { return false; }; gfxHandler = [this](u32) { return false; };
m_constantsData.Release(); m_constantsData.Release();
@ -924,49 +860,38 @@ void D3D12GSRender::Flip()
ResourceStorage &storage = getNonCurrentResourceStorage(); ResourceStorage &storage = getNonCurrentResourceStorage();
storage.m_frameFinishedFence->SetEventOnCompletion(storage.m_fenceValue, storage.m_frameFinishedHandle);
m_commandQueueGraphic->Signal(storage.m_frameFinishedFence.Get(), storage.m_fenceValue); m_commandQueueGraphic->Signal(storage.m_frameFinishedFence.Get(), storage.m_fenceValue);
storage.m_frameFinishedFence->SetEventOnCompletion(storage.m_fenceValue, storage.m_frameFinishedHandle);
storage.m_fenceValue++; storage.m_fenceValue++;
storage.m_dirtyTextures = m_texToClean;
storage.m_inUse = true;
m_texToClean.clear();
// Get the put pos - 1. This way after cleaning we can set the get ptr to
// this value, allowing heap to proceed even if we cleant before allocating
// a new value (that's the reason of the -1)
storage.m_getPosConstantsHeap = m_constantsData.getCurrentPutPosMinusOne();
storage.m_getPosVertexIndexHeap = m_vertexIndexData.getCurrentPutPosMinusOne();
storage.m_getPosTextureUploadHeap = m_textureUploadData.getCurrentPutPosMinusOne();
storage.m_getPosReadbackHeap = m_readbackResources.getCurrentPutPosMinusOne();
storage.m_getPosUAVHeap = m_UAVHeap.getCurrentPutPosMinusOne();
// Flush // Flush
m_texturesRTTs.clear(); m_texturesRTTs.clear();
m_vertexCache.clear(); m_vertexCache.clear();
m_vertexConstants.clear(); m_vertexConstants.clear();
// Now get ready for next frame
ResourceStorage &newStorage = getCurrentResourceStorage();
// Get the put pos - 1. This way after cleaning we can set the get ptr to newStorage.WaitAndClean();
// this value, allowing heap to proceed even if we cleant before allocating m_constantsData.m_getPos.store(newStorage.m_getPosConstantsHeap, std::memory_order_release);
// a new value (that's the reason of the -1) m_vertexIndexData.m_getPos.store(newStorage.m_getPosVertexIndexHeap, std::memory_order_release);
size_t newGetPosConstantsHeap = m_constantsData.getCurrentPutPosMinusOne(); m_textureUploadData.m_getPos.store(newStorage.m_getPosTextureUploadHeap, std::memory_order_release);
size_t newGetPosVertexIndexHeap = m_vertexIndexData.getCurrentPutPosMinusOne(); m_readbackResources.m_getPos.store(newStorage.m_getPosReadbackHeap, std::memory_order_release);
size_t newGetPosTextureUploadHeap = m_textureUploadData.getCurrentPutPosMinusOne(); m_UAVHeap.m_getPos.store(newStorage.m_getPosUAVHeap, std::memory_order_release);
size_t newGetPosReadbackHeap = m_readbackResources.getCurrentPutPosMinusOne();
size_t newGetPosUAVHeap = m_UAVHeap.getCurrentPutPosMinusOne();
std::lock_guard<std::mutex> lock(mut);
std::vector<ID3D12Resource *> textoclean = m_texToClean;
m_texToClean.clear();
storage.m_isUseable.store(false);
m_GC.pushWork([&,
textoclean,
newGetPosConstantsHeap,
newGetPosVertexIndexHeap,
newGetPosTextureUploadHeap,
newGetPosReadbackHeap,
newGetPosUAVHeap]()
{
storage.WaitAndClean(textoclean);
m_constantsData.m_getPos.store(newGetPosConstantsHeap, std::memory_order_release);
m_vertexIndexData.m_getPos.store(newGetPosVertexIndexHeap, std::memory_order_release);
m_textureUploadData.m_getPos.store(newGetPosTextureUploadHeap, std::memory_order_release);
m_readbackResources.m_getPos.store(newGetPosReadbackHeap, std::memory_order_release);
m_UAVHeap.m_getPos.store(newGetPosUAVHeap, std::memory_order_release);
});
while (!getCurrentResourceStorage().m_isUseable.load(std::memory_order_acquire))
std::this_thread::yield();
m_frame->Flip(nullptr); m_frame->Flip(nullptr);
ResetTimer(); ResetTimer();
@ -1248,7 +1173,7 @@ void D3D12GSRender::semaphorePGRAPHBackendRelease(u32 offset, u32 value)
//Wait for result //Wait for result
m_commandQueueGraphic->Signal(fence, 1); m_commandQueueGraphic->Signal(fence, 1);
m_GC.pushWork([=]() { auto tmp = [=]() {
WaitForSingleObject(handle, INFINITE); WaitForSingleObject(handle, INFINITE);
CloseHandle(handle); CloseHandle(handle);
fence->Release(); fence->Release();
@ -1356,9 +1281,8 @@ void D3D12GSRender::semaphorePGRAPHBackendRelease(u32 offset, u32 value)
} }
vm::write32(m_label_addr + offset, value); vm::write32(m_label_addr + offset, value);
}); };
tmp();
m_GC.waitForCompletion();
} }
void D3D12GSRender::semaphorePFIFOAcquire(u32 offset, u32 value) void D3D12GSRender::semaphorePFIFOAcquire(u32 offset, u32 value)

View File

@ -192,26 +192,6 @@ struct DataHeap
} }
}; };
/**
* Wrapper for a worker thread that executes lambda functions
* in the order they were submitted during its lifetime.
* Used mostly to release data that are not needed anymore.
*/
struct GarbageCollectionThread
{
std::atomic<bool> m_askForTermination;
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();
};
/** /**
* Structure used to load/unload D3D12 lib. * Structure used to load/unload D3D12 lib.
*/ */
@ -245,7 +225,6 @@ private:
std::vector<ID3D12Resource *> m_texToClean; std::vector<ID3D12Resource *> m_texToClean;
bool invalidateTexture(u32 addr); bool invalidateTexture(u32 addr);
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;
@ -299,7 +278,7 @@ private:
*/ */
struct ResourceStorage struct ResourceStorage
{ {
std::atomic<int> m_isUseable; bool m_inUse; // False until command list has been populated at least once
ComPtr<ID3D12Fence> m_frameFinishedFence; ComPtr<ID3D12Fence> m_frameFinishedFence;
UINT64 m_fenceValue; UINT64 m_fenceValue;
HANDLE m_frameFinishedHandle; HANDLE m_frameFinishedHandle;
@ -328,10 +307,19 @@ private:
std::vector<ComPtr<ID3D12Resource> > m_singleFrameLifetimeResources; std::vector<ComPtr<ID3D12Resource> > m_singleFrameLifetimeResources;
/// Texture that were invalidated
std::vector<ID3D12Resource *> m_dirtyTextures;
size_t m_getPosConstantsHeap;
size_t m_getPosVertexIndexHeap;
size_t m_getPosTextureUploadHeap;
size_t m_getPosReadbackHeap;
size_t m_getPosUAVHeap;
void Reset(); void Reset();
void Init(ID3D12Device *device); void Init(ID3D12Device *device);
void setNewCommandList(); void setNewCommandList();
void WaitAndClean(const std::vector<ID3D12Resource *> &dirtyTextures); void WaitAndClean();
void Release(); void Release();
}; };