restructure

This commit is contained in:
Aiden
2026-05-12 15:47:59 +10:00
parent 6a33bd02ab
commit 02b221f481
21 changed files with 40 additions and 33 deletions

View File

@@ -0,0 +1,158 @@
#include "RuntimeShaderPrepareWorker.h"
#include "../../platform/HiddenGlWindow.h"
#include "RuntimeShaderRenderer.h"
#include <algorithm>
#include <chrono>
#include <functional>
#include <utility>
RuntimeShaderPrepareWorker::~RuntimeShaderPrepareWorker()
{
Stop();
}
bool RuntimeShaderPrepareWorker::Start(std::unique_ptr<HiddenGlWindow> sharedWindow, std::string& error)
{
if (mThread.joinable())
return true;
if (!sharedWindow || sharedWindow->DeviceContext() == nullptr || sharedWindow->Context() == nullptr)
{
error = "Runtime shader prepare worker needs an existing shared GL context.";
return false;
}
mWindow = std::move(sharedWindow);
mStopping.store(false, std::memory_order_release);
mStarted.store(false, std::memory_order_release);
{
std::lock_guard<std::mutex> lock(mMutex);
mStartupReady = false;
mStartupError.clear();
}
mThread = std::thread([this]() { ThreadMain(); });
std::unique_lock<std::mutex> lock(mMutex);
if (!mStartupCondition.wait_for(lock, std::chrono::seconds(3), [this]() {
return mStartupReady || !mStartupError.empty();
}))
{
error = "Timed out starting runtime shader prepare worker.";
lock.unlock();
Stop();
return false;
}
if (!mStartupError.empty())
{
error = mStartupError;
lock.unlock();
Stop();
return false;
}
return true;
}
void RuntimeShaderPrepareWorker::Stop()
{
mStopping.store(true, std::memory_order_release);
mCondition.notify_all();
if (mThread.joinable())
mThread.join();
std::deque<RuntimePreparedShaderProgram> completed;
{
std::lock_guard<std::mutex> lock(mMutex);
mRequests.clear();
completed.swap(mCompleted);
}
for (RuntimePreparedShaderProgram& program : completed)
program.ReleaseGl();
mWindow.reset();
mStarted.store(false, std::memory_order_release);
}
void RuntimeShaderPrepareWorker::Submit(const std::vector<RenderCadenceCompositor::RuntimeRenderLayerModel>& layers)
{
std::lock_guard<std::mutex> lock(mMutex);
for (const RenderCadenceCompositor::RuntimeRenderLayerModel& layer : layers)
{
if (layer.artifact.fragmentShaderSource.empty())
continue;
PrepareRequest request;
request.layerId = layer.id;
request.shaderId = layer.shaderId;
request.sourceFingerprint = Fingerprint(layer.artifact);
request.artifact = layer.artifact;
auto sameLayer = [&request](const PrepareRequest& existing) {
return existing.layerId == request.layerId;
};
mRequests.erase(std::remove_if(mRequests.begin(), mRequests.end(), sameLayer), mRequests.end());
mRequests.push_back(std::move(request));
}
mCondition.notify_one();
}
bool RuntimeShaderPrepareWorker::TryConsume(RuntimePreparedShaderProgram& preparedProgram)
{
std::lock_guard<std::mutex> lock(mMutex);
if (mCompleted.empty())
return false;
preparedProgram = std::move(mCompleted.front());
mCompleted.pop_front();
return true;
}
void RuntimeShaderPrepareWorker::ThreadMain()
{
if (!mWindow || !mWindow->MakeCurrent())
{
std::lock_guard<std::mutex> lock(mMutex);
mStartupError = "Runtime shader prepare worker could not make shared GL context current.";
mStartupCondition.notify_all();
return;
}
{
std::lock_guard<std::mutex> lock(mMutex);
mStartupReady = true;
}
mStarted.store(true, std::memory_order_release);
mStartupCondition.notify_all();
while (!mStopping.load(std::memory_order_acquire))
{
PrepareRequest request;
{
std::unique_lock<std::mutex> lock(mMutex);
mCondition.wait(lock, [this]() {
return mStopping.load(std::memory_order_acquire) || !mRequests.empty();
});
if (mStopping.load(std::memory_order_acquire))
break;
request = std::move(mRequests.front());
mRequests.pop_front();
}
RuntimePreparedShaderProgram preparedProgram;
RuntimeShaderRenderer::BuildPreparedProgram(
request.layerId,
request.sourceFingerprint,
request.artifact,
preparedProgram);
glFlush();
std::lock_guard<std::mutex> lock(mMutex);
mCompleted.push_back(std::move(preparedProgram));
}
mWindow->ClearCurrent();
}
std::string RuntimeShaderPrepareWorker::Fingerprint(const RuntimeShaderArtifact& artifact)
{
const std::hash<std::string> hasher;
return artifact.shaderId + ":" + std::to_string(artifact.fragmentShaderSource.size()) + ":" + std::to_string(hasher(artifact.fragmentShaderSource));
}