Hot reload
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
#include "HttpControlServer.h"
|
||||
#include "RuntimeControlCommand.h"
|
||||
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
@@ -170,6 +171,16 @@ void TestGenericPostCallbackHandlesControlRoutes()
|
||||
Expect(response.body.find("\"ok\":true") != std::string::npos, "generic control callback returns action success");
|
||||
}
|
||||
|
||||
void TestReloadRouteParsesAsControlCommand()
|
||||
{
|
||||
using namespace RenderCadenceCompositor;
|
||||
|
||||
RuntimeControlCommand command;
|
||||
std::string error;
|
||||
Expect(ParseRuntimeControlCommand("/api/reload", "{}", command, error), "reload route parses as a control command");
|
||||
Expect(command.type == RuntimeControlCommandType::ReloadShaders, "reload route maps to reload command type");
|
||||
}
|
||||
|
||||
void TestUnknownEndpointReturns404()
|
||||
{
|
||||
using namespace RenderCadenceCompositor;
|
||||
@@ -193,6 +204,7 @@ int main()
|
||||
TestKnownPostEndpointReturnsActionError();
|
||||
TestLayerPostEndpointsUseCallbacks();
|
||||
TestGenericPostCallbackHandlesControlRoutes();
|
||||
TestReloadRouteParsesAsControlCommand();
|
||||
TestUnknownEndpointReturns404();
|
||||
|
||||
if (gFailures != 0)
|
||||
|
||||
@@ -34,28 +34,42 @@ void WriteFile(const std::filesystem::path& path, const std::string& contents)
|
||||
output << contents;
|
||||
}
|
||||
|
||||
RenderCadenceCompositor::SupportedShaderCatalog MakeCatalog(std::filesystem::path& root)
|
||||
std::string SolidShaderManifest(double gainDefault, bool includeMix)
|
||||
{
|
||||
root = MakeTestRoot();
|
||||
WriteFile(root / "solid" / "shader.slang", "float4 shadeVideo(float2 uv) { return float4(uv, 0.0, 1.0); }\n");
|
||||
WriteFile(root / "solid" / "shader.json", R"({
|
||||
std::string parameters =
|
||||
"{ \"id\": \"gain\", \"label\": \"Gain\", \"type\": \"float\", \"default\": " + std::to_string(gainDefault) + " },\n"
|
||||
"\t\t\t{ \"id\": \"drop\", \"label\": \"Drop\", \"type\": \"trigger\" }";
|
||||
if (includeMix)
|
||||
parameters += ",\n\t\t\t{ \"id\": \"mix\", \"label\": \"Mix\", \"type\": \"float\", \"default\": 0.25 }";
|
||||
|
||||
return R"({
|
||||
"id": "solid",
|
||||
"name": "Solid",
|
||||
"description": "Solid test shader",
|
||||
"category": "Tests",
|
||||
"entryPoint": "shadeVideo",
|
||||
"parameters": [
|
||||
{ "id": "gain", "label": "Gain", "type": "float", "default": 0.5 },
|
||||
{ "id": "drop", "label": "Drop", "type": "trigger" }
|
||||
)" + parameters + R"(
|
||||
]
|
||||
})");
|
||||
})";
|
||||
}
|
||||
|
||||
RenderCadenceCompositor::SupportedShaderCatalog LoadCatalog(const std::filesystem::path& root)
|
||||
{
|
||||
RenderCadenceCompositor::SupportedShaderCatalog catalog;
|
||||
std::string error;
|
||||
Expect(catalog.Load(root, 4, error), error.empty() ? "catalog loads test shader" : error);
|
||||
return catalog;
|
||||
}
|
||||
|
||||
RenderCadenceCompositor::SupportedShaderCatalog MakeCatalog(std::filesystem::path& root)
|
||||
{
|
||||
root = MakeTestRoot();
|
||||
WriteFile(root / "solid" / "shader.slang", "float4 shadeVideo(float2 uv) { return float4(uv, 0.0, 1.0); }\n");
|
||||
WriteFile(root / "solid" / "shader.json", SolidShaderManifest(0.5, false));
|
||||
return LoadCatalog(root);
|
||||
}
|
||||
|
||||
void TestSingleLayerLifecycle()
|
||||
{
|
||||
std::filesystem::path root;
|
||||
@@ -196,6 +210,31 @@ void TestLayerControlsUpdateDisplayAndRenderModels()
|
||||
|
||||
std::filesystem::remove_all(root);
|
||||
}
|
||||
|
||||
void TestReloadRefreshesChangedShaderMetadataAndPreservesValues()
|
||||
{
|
||||
std::filesystem::path root;
|
||||
RenderCadenceCompositor::SupportedShaderCatalog catalog = MakeCatalog(root);
|
||||
|
||||
RenderCadenceCompositor::RuntimeLayerModel model;
|
||||
std::string error;
|
||||
std::string layerId;
|
||||
Expect(model.AddLayer(catalog, "solid", layerId, error), "reload test layer can be added");
|
||||
Expect(model.UpdateParameter(layerId, "gain", JsonValue(0.75), error), "reload test parameter can be customized");
|
||||
|
||||
WriteFile(root / "solid" / "shader.json", SolidShaderManifest(0.1, true));
|
||||
RenderCadenceCompositor::SupportedShaderCatalog reloadedCatalog = LoadCatalog(root);
|
||||
std::vector<std::pair<std::string, std::string>> buildsToStart;
|
||||
Expect(model.ReloadFromCatalog(reloadedCatalog, buildsToStart, error), "reload refreshes model from changed catalog");
|
||||
Expect(buildsToStart.size() == 1 && buildsToStart[0].first == layerId && buildsToStart[0].second == "solid", "changed shader queues a layer rebuild");
|
||||
|
||||
RenderCadenceCompositor::RuntimeLayerModelSnapshot snapshot = model.Snapshot();
|
||||
Expect(snapshot.displayLayers[0].parameterDefinitions.size() == 3, "reload exposes new JSON parameter definitions to UI");
|
||||
Expect(snapshot.displayLayers[0].parameterValues.at("gain").numberValues.front() == 0.75, "reload preserves compatible parameter values");
|
||||
Expect(snapshot.displayLayers[0].parameterValues.at("mix").numberValues.front() == 0.25, "reload initializes newly added parameters");
|
||||
|
||||
std::filesystem::remove_all(root);
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
@@ -205,6 +244,7 @@ int main()
|
||||
TestBuildFailureStaysDisplaySide();
|
||||
TestAddAndRemoveLayers();
|
||||
TestLayerControlsUpdateDisplayAndRenderModels();
|
||||
TestReloadRefreshesChangedShaderMetadataAndPreservesValues();
|
||||
|
||||
if (gFailures != 0)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user