188 lines
9.0 KiB
C++
188 lines
9.0 KiB
C++
#pragma once
|
|
|
|
#include "RuntimeJson.h"
|
|
#include "ShaderTypes.h"
|
|
|
|
#include <atomic>
|
|
#include <chrono>
|
|
#include <filesystem>
|
|
#include <map>
|
|
#include <mutex>
|
|
#include <string>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
class RuntimeHost
|
|
{
|
|
public:
|
|
RuntimeHost();
|
|
|
|
bool Initialize(std::string& error);
|
|
|
|
bool PollFileChanges(bool& registryChanged, bool& reloadRequested, std::string& error);
|
|
bool ManualReloadRequested();
|
|
void ClearReloadRequest();
|
|
|
|
bool AddLayer(const std::string& shaderId, std::string& error);
|
|
bool RemoveLayer(const std::string& layerId, std::string& error);
|
|
bool MoveLayer(const std::string& layerId, int direction, std::string& error);
|
|
bool MoveLayerToIndex(const std::string& layerId, std::size_t targetIndex, std::string& error);
|
|
bool SetLayerBypass(const std::string& layerId, bool bypassed, std::string& error);
|
|
bool SetLayerShader(const std::string& layerId, const std::string& shaderId, std::string& error);
|
|
bool UpdateLayerParameter(const std::string& layerId, const std::string& parameterId, const JsonValue& newValue, std::string& error);
|
|
bool UpdateLayerParameterByControlKey(const std::string& layerKey, const std::string& parameterKey, const JsonValue& newValue, std::string& error);
|
|
bool ResetLayerParameters(const std::string& layerId, std::string& error);
|
|
bool SaveStackPreset(const std::string& presetName, std::string& error) const;
|
|
bool LoadStackPreset(const std::string& presetName, std::string& error);
|
|
|
|
void SetCompileStatus(bool succeeded, const std::string& message);
|
|
void SetSignalStatus(bool hasSignal, unsigned width, unsigned height, const std::string& modeName);
|
|
bool TrySetSignalStatus(bool hasSignal, unsigned width, unsigned height, const std::string& modeName);
|
|
void SetDeckLinkOutputStatus(const std::string& modelName, bool supportsInternalKeying, bool supportsExternalKeying,
|
|
bool keyerInterfaceAvailable, bool externalKeyingRequested, bool externalKeyingActive, const std::string& statusMessage);
|
|
void SetVideoIOStatus(const std::string& backendName, const std::string& modelName, bool supportsInternalKeying, bool supportsExternalKeying,
|
|
bool keyerInterfaceAvailable, bool externalKeyingRequested, bool externalKeyingActive, const std::string& statusMessage);
|
|
void SetPerformanceStats(double frameBudgetMilliseconds, double renderMilliseconds);
|
|
bool TrySetPerformanceStats(double frameBudgetMilliseconds, double renderMilliseconds);
|
|
void SetFramePacingStats(double completionIntervalMilliseconds, double smoothedCompletionIntervalMilliseconds,
|
|
double maxCompletionIntervalMilliseconds, uint64_t lateFrameCount, uint64_t droppedFrameCount, uint64_t flushedFrameCount);
|
|
bool TrySetFramePacingStats(double completionIntervalMilliseconds, double smoothedCompletionIntervalMilliseconds,
|
|
double maxCompletionIntervalMilliseconds, uint64_t lateFrameCount, uint64_t droppedFrameCount, uint64_t flushedFrameCount);
|
|
void AdvanceFrame();
|
|
bool TryAdvanceFrame();
|
|
|
|
bool BuildLayerPassFragmentShaderSources(const std::string& layerId, std::vector<ShaderPassBuildSource>& passSources, std::string& error);
|
|
std::vector<RuntimeRenderState> GetLayerRenderStates(unsigned outputWidth, unsigned outputHeight) const;
|
|
bool TryGetLayerRenderStates(unsigned outputWidth, unsigned outputHeight, std::vector<RuntimeRenderState>& states) const;
|
|
void RefreshDynamicRenderStateFields(std::vector<RuntimeRenderState>& states) const;
|
|
std::string BuildStateJson() const;
|
|
uint64_t GetRenderStateVersion() const { return mRenderStateVersion.load(std::memory_order_relaxed); }
|
|
|
|
const std::filesystem::path& GetRepoRoot() const { return mRepoRoot; }
|
|
const std::filesystem::path& GetUiRoot() const { return mUiRoot; }
|
|
const std::filesystem::path& GetDocsRoot() const { return mDocsRoot; }
|
|
const std::filesystem::path& GetRuntimeRoot() const { return mRuntimeRoot; }
|
|
unsigned short GetServerPort() const { return mServerPort; }
|
|
unsigned short GetOscPort() const { return mConfig.oscPort; }
|
|
unsigned GetMaxTemporalHistoryFrames() const { return mConfig.maxTemporalHistoryFrames; }
|
|
bool ExternalKeyingEnabled() const { return mConfig.enableExternalKeying; }
|
|
const std::string& GetInputVideoFormat() const { return mConfig.inputVideoFormat; }
|
|
const std::string& GetInputFrameRate() const { return mConfig.inputFrameRate; }
|
|
const std::string& GetOutputVideoFormat() const { return mConfig.outputVideoFormat; }
|
|
const std::string& GetOutputFrameRate() const { return mConfig.outputFrameRate; }
|
|
void SetServerPort(unsigned short port);
|
|
bool AutoReloadEnabled() const { return mAutoReloadEnabled; }
|
|
|
|
private:
|
|
struct AppConfig
|
|
{
|
|
std::string shaderLibrary = "shaders";
|
|
unsigned short serverPort = 8080;
|
|
unsigned short oscPort = 9000;
|
|
bool autoReload = true;
|
|
unsigned maxTemporalHistoryFrames = 4;
|
|
bool enableExternalKeying = false;
|
|
std::string inputVideoFormat = "1080p";
|
|
std::string inputFrameRate = "59.94";
|
|
std::string outputVideoFormat = "1080p";
|
|
std::string outputFrameRate = "59.94";
|
|
};
|
|
|
|
struct DeckLinkOutputStatus
|
|
{
|
|
std::string backendName = "decklink";
|
|
std::string modelName;
|
|
bool supportsInternalKeying = false;
|
|
bool supportsExternalKeying = false;
|
|
bool keyerInterfaceAvailable = false;
|
|
bool externalKeyingRequested = false;
|
|
bool externalKeyingActive = false;
|
|
std::string statusMessage;
|
|
};
|
|
|
|
struct LayerPersistentState
|
|
{
|
|
std::string id;
|
|
std::string shaderId;
|
|
bool bypass = false;
|
|
std::map<std::string, ShaderParameterValue> parameterValues;
|
|
};
|
|
|
|
struct PersistentState
|
|
{
|
|
std::vector<LayerPersistentState> layers;
|
|
};
|
|
|
|
bool LoadConfig(std::string& error);
|
|
bool LoadPersistentState(std::string& error);
|
|
bool SavePersistentState(std::string& error) const;
|
|
bool ScanShaderPackages(std::string& error);
|
|
bool NormalizeAndValidateValue(const ShaderParameterDefinition& definition, const JsonValue& value, ShaderParameterValue& normalizedValue, std::string& error) const;
|
|
ShaderParameterValue DefaultValueForDefinition(const ShaderParameterDefinition& definition) const;
|
|
void EnsureLayerDefaultsLocked(LayerPersistentState& layerState, const ShaderPackage& shaderPackage) const;
|
|
std::string ReadTextFile(const std::filesystem::path& path, std::string& error) const;
|
|
bool WriteTextFile(const std::filesystem::path& path, const std::string& contents, std::string& error) const;
|
|
bool ResolvePaths(std::string& error);
|
|
void BuildLayerRenderStatesLocked(unsigned outputWidth, unsigned outputHeight, std::vector<RuntimeRenderState>& states) const;
|
|
JsonValue BuildStateValue() const;
|
|
JsonValue SerializeLayerStackLocked() const;
|
|
bool DeserializeLayerStackLocked(const JsonValue& layersValue, std::vector<LayerPersistentState>& layers, std::string& error);
|
|
void NormalizePersistentLayerIdsLocked();
|
|
std::vector<std::string> GetStackPresetNamesLocked() const;
|
|
std::string MakeSafePresetFileStem(const std::string& presetName) const;
|
|
JsonValue SerializeParameterValue(const ShaderParameterDefinition& definition, const ShaderParameterValue& value) const;
|
|
std::string TemporalHistorySourceToString(TemporalHistorySource source) const;
|
|
LayerPersistentState* FindLayerById(const std::string& layerId);
|
|
const LayerPersistentState* FindLayerById(const std::string& layerId) const;
|
|
std::string GenerateLayerId();
|
|
void SetSignalStatusLocked(bool hasSignal, unsigned width, unsigned height, const std::string& modeName);
|
|
void MarkRenderStateDirtyLocked();
|
|
void SetPerformanceStatsLocked(double frameBudgetMilliseconds, double renderMilliseconds);
|
|
void SetFramePacingStatsLocked(double completionIntervalMilliseconds, double smoothedCompletionIntervalMilliseconds,
|
|
double maxCompletionIntervalMilliseconds, uint64_t lateFrameCount, uint64_t droppedFrameCount, uint64_t flushedFrameCount);
|
|
|
|
private:
|
|
mutable std::mutex mMutex;
|
|
AppConfig mConfig;
|
|
PersistentState mPersistentState;
|
|
std::filesystem::path mRepoRoot;
|
|
std::filesystem::path mUiRoot;
|
|
std::filesystem::path mDocsRoot;
|
|
std::filesystem::path mShaderRoot;
|
|
std::filesystem::path mRuntimeRoot;
|
|
std::filesystem::path mPresetRoot;
|
|
std::filesystem::path mRuntimeStatePath;
|
|
std::filesystem::path mConfigPath;
|
|
std::filesystem::path mWrapperPath;
|
|
std::filesystem::path mGeneratedGlslPath;
|
|
std::filesystem::path mPatchedGlslPath;
|
|
std::map<std::string, ShaderPackage> mPackagesById;
|
|
std::vector<std::string> mPackageOrder;
|
|
std::vector<ShaderPackageStatus> mPackageStatuses;
|
|
bool mReloadRequested;
|
|
bool mCompileSucceeded;
|
|
std::string mCompileMessage;
|
|
bool mHasSignal;
|
|
unsigned mSignalWidth;
|
|
unsigned mSignalHeight;
|
|
std::string mSignalModeName;
|
|
double mFrameBudgetMilliseconds;
|
|
double mRenderMilliseconds;
|
|
double mSmoothedRenderMilliseconds;
|
|
double mCompletionIntervalMilliseconds;
|
|
double mSmoothedCompletionIntervalMilliseconds;
|
|
double mMaxCompletionIntervalMilliseconds;
|
|
double mStartupRandom;
|
|
uint64_t mLateFrameCount;
|
|
uint64_t mDroppedFrameCount;
|
|
uint64_t mFlushedFrameCount;
|
|
DeckLinkOutputStatus mDeckLinkOutputStatus;
|
|
unsigned short mServerPort;
|
|
bool mAutoReloadEnabled;
|
|
std::chrono::steady_clock::time_point mStartTime;
|
|
std::chrono::steady_clock::time_point mLastScanTime;
|
|
std::atomic<uint64_t> mFrameCounter{ 0 };
|
|
std::atomic<uint64_t> mRenderStateVersion{ 0 };
|
|
uint64_t mNextLayerId;
|
|
};
|