re organisation
This commit is contained in:
@@ -0,0 +1,134 @@
|
||||
#include "ShaderBuildQueue.h"
|
||||
|
||||
#include "RuntimeHost.h"
|
||||
|
||||
#include <chrono>
|
||||
#include <utility>
|
||||
|
||||
namespace
|
||||
{
|
||||
constexpr auto kShaderBuildDebounce = std::chrono::milliseconds(400);
|
||||
}
|
||||
|
||||
ShaderBuildQueue::ShaderBuildQueue(RuntimeHost& runtimeHost) :
|
||||
mRuntimeHost(runtimeHost),
|
||||
mWorkerThread([this]() { WorkerLoop(); })
|
||||
{
|
||||
}
|
||||
|
||||
ShaderBuildQueue::~ShaderBuildQueue()
|
||||
{
|
||||
Stop();
|
||||
}
|
||||
|
||||
void ShaderBuildQueue::RequestBuild(unsigned outputWidth, unsigned outputHeight)
|
||||
{
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mMutex);
|
||||
mHasRequest = true;
|
||||
++mRequestedGeneration;
|
||||
mRequestedOutputWidth = outputWidth;
|
||||
mRequestedOutputHeight = outputHeight;
|
||||
mHasReadyBuild = false;
|
||||
}
|
||||
mCondition.notify_one();
|
||||
}
|
||||
|
||||
bool ShaderBuildQueue::TryConsumeReadyBuild(PreparedShaderBuild& build)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mMutex);
|
||||
if (!mHasReadyBuild)
|
||||
return false;
|
||||
|
||||
build = std::move(mReadyBuild);
|
||||
mReadyBuild = PreparedShaderBuild();
|
||||
mHasReadyBuild = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void ShaderBuildQueue::Stop()
|
||||
{
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mMutex);
|
||||
if (mStopping)
|
||||
return;
|
||||
mStopping = true;
|
||||
}
|
||||
mCondition.notify_one();
|
||||
if (mWorkerThread.joinable())
|
||||
mWorkerThread.join();
|
||||
}
|
||||
|
||||
void ShaderBuildQueue::WorkerLoop()
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
uint64_t generation = 0;
|
||||
unsigned outputWidth = 0;
|
||||
unsigned outputHeight = 0;
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(mMutex);
|
||||
mCondition.wait(lock, [this]() { return mStopping || mHasRequest; });
|
||||
if (mStopping)
|
||||
return;
|
||||
|
||||
generation = mRequestedGeneration;
|
||||
outputWidth = mRequestedOutputWidth;
|
||||
outputHeight = mRequestedOutputHeight;
|
||||
mHasRequest = false;
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(mMutex);
|
||||
if (mCondition.wait_for(lock, kShaderBuildDebounce, [this, generation]() {
|
||||
return mStopping || (mHasRequest && mRequestedGeneration != generation);
|
||||
}))
|
||||
{
|
||||
if (mStopping)
|
||||
return;
|
||||
|
||||
generation = mRequestedGeneration;
|
||||
outputWidth = mRequestedOutputWidth;
|
||||
outputHeight = mRequestedOutputHeight;
|
||||
mHasRequest = false;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
PreparedShaderBuild build = Build(generation, outputWidth, outputHeight);
|
||||
|
||||
std::lock_guard<std::mutex> lock(mMutex);
|
||||
if (mStopping)
|
||||
return;
|
||||
if (generation != mRequestedGeneration)
|
||||
continue;
|
||||
mReadyBuild = std::move(build);
|
||||
mHasReadyBuild = true;
|
||||
}
|
||||
}
|
||||
|
||||
PreparedShaderBuild ShaderBuildQueue::Build(uint64_t generation, unsigned outputWidth, unsigned outputHeight)
|
||||
{
|
||||
PreparedShaderBuild build;
|
||||
build.generation = generation;
|
||||
build.layerStates = mRuntimeHost.GetLayerRenderStates(outputWidth, outputHeight);
|
||||
build.layers.reserve(build.layerStates.size());
|
||||
|
||||
for (const RuntimeRenderState& state : build.layerStates)
|
||||
{
|
||||
PreparedLayerShader layer;
|
||||
layer.state = state;
|
||||
if (!mRuntimeHost.BuildLayerFragmentShaderSource(state.layerId, layer.fragmentShaderSource, build.message))
|
||||
{
|
||||
build.succeeded = false;
|
||||
return build;
|
||||
}
|
||||
build.layers.push_back(std::move(layer));
|
||||
}
|
||||
|
||||
build.succeeded = true;
|
||||
build.message = "Shader layers prepared successfully.";
|
||||
return build;
|
||||
}
|
||||
Reference in New Issue
Block a user