#include "RuntimeLayerController.h" #include "AppConfigProvider.h" #include "../logging/Logger.h" #include namespace RenderCadenceCompositor { void RuntimeLayerController::LoadSupportedShaderCatalog(const std::string& shaderLibrary, unsigned maxTemporalHistoryFrames) { const std::filesystem::path shaderRoot = FindRepoPath(shaderLibrary); std::string error; if (!mShaderCatalog.Load(shaderRoot, maxTemporalHistoryFrames, error)) { LogWarning("runtime-shader", "Supported shader catalog is empty: " + error); return; } Log("runtime-shader", "Supported shader catalog loaded with " + std::to_string(mShaderCatalog.Shaders().size()) + " shader(s)."); } void RuntimeLayerController::InitializeLayerModel(std::string& runtimeShaderId) { std::lock_guard lock(mRuntimeLayerMutex); std::string error; if (!mRuntimeLayerModel.InitializeSingleLayer(mShaderCatalog, runtimeShaderId, error)) { LogWarning("runtime-shader", error + " Runtime shader build disabled."); runtimeShaderId.clear(); mRuntimeLayerModel.Clear(); } } void RuntimeLayerController::StartLayerShaderBuild(const std::string& layerId, const std::string& shaderId) { CleanupRetiredShaderBuilds(); RetireLayerShaderBuild(layerId); { std::lock_guard lock(mRuntimeLayerMutex); std::string error; mRuntimeLayerModel.MarkBuildStarted(layerId, "Runtime Slang build started for shader '" + shaderId + "'.", error); } auto bridge = std::make_unique(); RuntimeShaderBridge* bridgePtr = bridge.get(); { std::lock_guard lock(mShaderBuildMutex); mShaderBuilds[layerId] = std::move(bridge); } bridgePtr->Start( layerId, shaderId, [this](const RuntimeShaderArtifact& artifact) { if (MarkRuntimeBuildReady(artifact)) PublishRuntimeRenderLayers(); }, [this, layerId](const std::string& message) { MarkRuntimeBuildFailedForLayer(layerId, message); LogError("runtime-shader", "Runtime Slang build failed: " + message); }); } void RuntimeLayerController::RetireLayerShaderBuild(const std::string& layerId) { std::unique_ptr bridge; { std::lock_guard lock(mShaderBuildMutex); auto bridgeIt = mShaderBuilds.find(layerId); if (bridgeIt == mShaderBuilds.end()) return; bridge = std::move(bridgeIt->second); mShaderBuilds.erase(bridgeIt); bridge->RequestStop(); mRetiredShaderBuilds.push_back(std::move(bridge)); } } void RuntimeLayerController::CleanupRetiredShaderBuilds() { std::vector> readyToStop; { std::lock_guard lock(mShaderBuildMutex); for (auto it = mRetiredShaderBuilds.begin(); it != mRetiredShaderBuilds.end();) { if ((*it)->CanStopWithoutWaiting()) { readyToStop.push_back(std::move(*it)); it = mRetiredShaderBuilds.erase(it); continue; } ++it; } } for (std::unique_ptr& bridge : readyToStop) bridge->Stop(); } void RuntimeLayerController::StopAllRuntimeShaderBuilds() { std::map> builds; std::vector> retiredBuilds; { std::lock_guard lock(mShaderBuildMutex); builds.swap(mShaderBuilds); retiredBuilds.swap(mRetiredShaderBuilds); } for (auto& entry : builds) entry.second->Stop(); for (auto& bridge : retiredBuilds) bridge->Stop(); } std::string RuntimeLayerController::FirstRuntimeLayerId() const { std::lock_guard lock(mRuntimeLayerMutex); return mRuntimeLayerModel.FirstLayerId(); } }