This commit is contained in:
2026-05-02 17:13:53 +10:00
parent 1a4c33b9dc
commit fb1bf01fef
19 changed files with 780 additions and 69 deletions

View File

@@ -149,6 +149,9 @@ RuntimeHost::RuntimeHost()
mHasSignal(false),
mSignalWidth(0),
mSignalHeight(0),
mFrameBudgetMilliseconds(0.0),
mRenderMilliseconds(0.0),
mSmoothedRenderMilliseconds(0.0),
mServerPort(8080),
mAutoReloadEnabled(true),
mMixAmount(1.0),
@@ -332,8 +335,25 @@ bool RuntimeHost::UpdateParameter(const std::string& shaderId, const std::string
return false;
mPersistentState.parameterValuesByShader[shaderId][parameterId] = normalized;
if (shaderId == mActiveShaderId)
mReloadRequested = true;
return SavePersistentState(error);
}
bool RuntimeHost::ResetParameters(const std::string& shaderId, std::string& error)
{
std::lock_guard<std::mutex> lock(mMutex);
auto shaderIt = mPackagesById.find(shaderId);
if (shaderIt == mPackagesById.end())
{
error = "Unknown shader id: " + shaderId;
return false;
}
std::map<std::string, ShaderParameterValue>& shaderValues = mPersistentState.parameterValuesByShader[shaderId];
shaderValues.clear();
for (const ShaderParameterDefinition& definition : shaderIt->second.parameters)
shaderValues[definition.id] = DefaultValueForDefinition(definition);
return SavePersistentState(error);
}
@@ -376,6 +396,17 @@ void RuntimeHost::SetSignalStatus(bool hasSignal, unsigned width, unsigned heigh
mSignalModeName = modeName;
}
void RuntimeHost::SetPerformanceStats(double frameBudgetMilliseconds, double renderMilliseconds)
{
std::lock_guard<std::mutex> lock(mMutex);
mFrameBudgetMilliseconds = std::max(frameBudgetMilliseconds, 0.0);
mRenderMilliseconds = std::max(renderMilliseconds, 0.0);
if (mSmoothedRenderMilliseconds <= 0.0)
mSmoothedRenderMilliseconds = mRenderMilliseconds;
else
mSmoothedRenderMilliseconds = mSmoothedRenderMilliseconds * 0.9 + mRenderMilliseconds * 0.1;
}
void RuntimeHost::AdvanceFrame()
{
std::lock_guard<std::mutex> lock(mMutex);
@@ -944,65 +975,17 @@ std::string RuntimeHost::BuildWrapperSlangSource(const ShaderPackage& shaderPack
source << "\t" << SlangTypeForParameter(definition.type).substr(strlen("uniform ")) << " " << definition.id << ";\n";
source << "};\n\n";
source << "Sampler2D<float4> gVideoInput;\n\n";
source << "float4 rec709YCbCr2rgba(float Y, float Cb, float Cr, float a)\n";
source << "{\n";
source << "\tY = (Y * 256.0 - 16.0) / 219.0;\n";
source << "\tCb = (Cb * 256.0 - 16.0) / 224.0 - 0.5;\n";
source << "\tCr = (Cr * 256.0 - 16.0) / 224.0 - 0.5;\n";
source << "\treturn float4(Y + 1.5748 * Cr, Y - 0.1873 * Cb - 0.4681 * Cr, Y + 1.8556 * Cb, a);\n";
source << "}\n\n";
source << "float4 bilinear(float4 W, float4 X, float4 Y, float4 Z, float2 weight)\n";
source << "{\n";
source << "\tfloat4 m0 = lerp(W, Z, weight.x);\n";
source << "\tfloat4 m1 = lerp(X, Y, weight.x);\n";
source << "\treturn lerp(m0, m1, weight.y);\n";
source << "}\n\n";
source << "void textureGatherYUV(Sampler2D<float4> textureSampler, float2 tc, out float4 W, out float4 X, out float4 Y, out float4 Z)\n";
source << "{\n";
source << "\tuint width = 0;\n";
source << "\tuint height = 0;\n";
source << "\ttextureSampler.GetDimensions(width, height);\n";
source << "\tint2 tx = int2(tc * float2(width, height));\n";
source << "\tint2 tmin = int2(0, 0);\n";
source << "\tint2 tmax = int2(int(width), int(height)) - int2(1, 1);\n";
source << "\tW = textureSampler.Load(int3(tx, 0));\n";
source << "\tX = textureSampler.Load(int3(clamp(tx + int2(0, 1), tmin, tmax), 0));\n";
source << "\tY = textureSampler.Load(int3(clamp(tx + int2(1, 1), tmin, tmax), 0));\n";
source << "\tZ = textureSampler.Load(int3(clamp(tx + int2(1, 0), tmin, tmax), 0));\n";
source << "}\n\n";
source << "float4 sampleVideo(float2 tc)\n";
source << "{\n";
source << "\tfloat4 macro, macroU, macroR, macroUR;\n";
source << "\ttextureGatherYUV(gVideoInput, tc, macro, macroU, macroUR, macroR);\n";
source << "\tuint width = 0;\n";
source << "\tuint height = 0;\n";
source << "\tgVideoInput.GetDimensions(width, height);\n";
source << "\tfloat2 off = frac(tc * float2(width, height));\n";
source << "\tfloat4 pixel, pixelR, pixelU, pixelUR;\n";
source << "\tif (off.x > 0.5)\n";
source << "\t{\n";
source << "\t\tpixel = rec709YCbCr2rgba(macro.a, macro.b, macro.r, 1.0);\n";
source << "\t\tpixelR = rec709YCbCr2rgba(macroR.g, macroR.b, macroR.r, 1.0);\n";
source << "\t\tpixelU = rec709YCbCr2rgba(macroU.a, macroU.b, macroU.r, 1.0);\n";
source << "\t\tpixelUR = rec709YCbCr2rgba(macroUR.g, macroUR.b, macroUR.r, 1.0);\n";
source << "\t}\n";
source << "\telse\n";
source << "\t{\n";
source << "\t\tpixel = rec709YCbCr2rgba(macro.g, macro.b, macro.r, 1.0);\n";
source << "\t\tpixelR = rec709YCbCr2rgba(macro.a, macro.b, macro.r, 1.0);\n";
source << "\t\tpixelU = rec709YCbCr2rgba(macroU.g, macroU.b, macroU.r, 1.0);\n";
source << "\t\tpixelUR = rec709YCbCr2rgba(macroU.a, macroU.b, macroU.r, 1.0);\n";
source << "\t}\n";
source << "\treturn bilinear(pixel, pixelU, pixelUR, pixelR, off);\n";
source << "\treturn gVideoInput.Sample(tc);\n";
source << "}\n\n";
source << "#include \"" << shaderPackage.shaderPath.generic_string() << "\"\n\n";
source << "[shader(\"fragment\")]\n";
source << "float4 fragmentMain(FragmentInput input) : SV_Target\n";
source << "{\n";
source << "\tShaderContext context;\n";
source << "\tfloat2 correctedUv = float2(input.texCoord.x, 1.0 - input.texCoord.y);\n";
source << "\tcontext.uv = correctedUv;\n";
source << "\tcontext.sourceColor = sampleVideo(correctedUv);\n";
source << "\tcontext.uv = input.texCoord;\n";
source << "\tcontext.sourceColor = sampleVideo(context.uv);\n";
source << "\tcontext.inputResolution = gInputResolution;\n";
source << "\tcontext.outputResolution = gOutputResolution;\n";
source << "\tcontext.time = gTime;\n";
@@ -1184,6 +1167,13 @@ JsonValue RuntimeHost::BuildStateValue() const
video.set("modeName", JsonValue(mSignalModeName));
root.set("video", video);
JsonValue performance = JsonValue::MakeObject();
performance.set("frameBudgetMs", JsonValue(mFrameBudgetMilliseconds));
performance.set("renderMs", JsonValue(mRenderMilliseconds));
performance.set("smoothedRenderMs", JsonValue(mSmoothedRenderMilliseconds));
performance.set("budgetUsedPercent", JsonValue(mFrameBudgetMilliseconds > 0.0 ? (mSmoothedRenderMilliseconds / mFrameBudgetMilliseconds) * 100.0 : 0.0));
root.set("performance", performance);
JsonValue shaders = JsonValue::MakeArray();
for (const std::string& shaderId : mPackageOrder)
{