Skip to content

Instantly share code, notes, and snippets.

@vlj
Created June 27, 2015 16:52
Show Gist options
  • Save vlj/ee5d91d3d41e15fa9235 to your computer and use it in GitHub Desktop.
Save vlj/ee5d91d3d41e15fa9235 to your computer and use it in GitHub Desktop.
/**
* 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::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();
};
GarbageCollectionThread::GarbageCollectionThread()
{
m_worker = std::thread([this]() {
while (true)
{
std::unique_lock<std::mutex> lock(m_mutex);
while (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()
{
m_constantsBufferIndex = 0;
m_currentScaleOffsetBufferIndex = 0;
m_currentTextureIndex = 0;
m_frameFinishedFence = nullptr;
m_frameFinishedHandle = 0;
m_commandAllocator->Reset();
m_textureUploadCommandAllocator->Reset();
m_downloadCommandAllocator->Reset();
for (ID3D12GraphicsCommandList *gfxCommandList : m_inflightCommandList)
gfxCommandList->Release();
m_inflightCommandList.clear();
}
...
ResourceStorage &storage = getNonCurrentResourceStorage();
m_device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&storage.m_frameFinishedFence));
storage.m_frameFinishedHandle = CreateEvent(0, 0, 0, 0);
storage.m_frameFinishedFence->SetEventOnCompletion(1, storage.m_frameFinishedHandle);
m_commandQueueGraphic->Signal(storage.m_frameFinishedFence, 1);
// Flush
m_texturesRTTs.clear();
m_vertexCache.clear();
m_vertexConstants.clear();
std::vector<std::function<void()> > cleaningFunction =
{
m_constantsData.getCleaningFunction(),
m_vertexIndexData.getCleaningFunction(),
m_textureUploadData.getCleaningFunction(),
};
std::lock_guard<std::mutex> lock(mut);
std::vector<ID3D12Resource *> textoclean = m_texToClean;
m_texToClean.clear();
m_GC.pushWork([&, cleaningFunction, textoclean]()
{
WaitForSingleObject(storage.m_frameFinishedHandle, INFINITE);
CloseHandle(storage.m_frameFinishedHandle);
storage.m_frameFinishedFence->Release();
for (auto &cleanFunc : cleaningFunction)
cleanFunc();
storage.Reset();
for (auto tmp : textoclean)
tmp->Release();
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment