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:
parent
bf04758285
commit
72e5578595
@ -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)
|
||||||
|
@ -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();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user