Render changes
This commit is contained in:
@@ -331,6 +331,8 @@ set(RENDER_CADENCE_APP_SOURCES
|
|||||||
"${RENDER_CADENCE_APP_DIR}/render/RuntimeShaderRenderer.h"
|
"${RENDER_CADENCE_APP_DIR}/render/RuntimeShaderRenderer.h"
|
||||||
"${RENDER_CADENCE_APP_DIR}/render/RuntimeShaderParams.cpp"
|
"${RENDER_CADENCE_APP_DIR}/render/RuntimeShaderParams.cpp"
|
||||||
"${RENDER_CADENCE_APP_DIR}/render/RuntimeShaderParams.h"
|
"${RENDER_CADENCE_APP_DIR}/render/RuntimeShaderParams.h"
|
||||||
|
"${RENDER_CADENCE_APP_DIR}/render/RuntimeRenderScene.cpp"
|
||||||
|
"${RENDER_CADENCE_APP_DIR}/render/RuntimeRenderScene.h"
|
||||||
"${RENDER_CADENCE_APP_DIR}/render/SimpleMotionRenderer.cpp"
|
"${RENDER_CADENCE_APP_DIR}/render/SimpleMotionRenderer.cpp"
|
||||||
"${RENDER_CADENCE_APP_DIR}/render/SimpleMotionRenderer.h"
|
"${RENDER_CADENCE_APP_DIR}/render/SimpleMotionRenderer.h"
|
||||||
"${RENDER_CADENCE_APP_DIR}/runtime/RuntimeLayerModel.cpp"
|
"${RENDER_CADENCE_APP_DIR}/runtime/RuntimeLayerModel.cpp"
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ Included now:
|
|||||||
- background Slang compile of `shaders/happy-accident`
|
- background Slang compile of `shaders/happy-accident`
|
||||||
- app-owned display/render layer model for shader build readiness
|
- app-owned display/render layer model for shader build readiness
|
||||||
- app-owned submission of a completed shader artifact
|
- app-owned submission of a completed shader artifact
|
||||||
|
- render-thread-owned runtime render scene for ready shader layers
|
||||||
- render-thread-only GL commit once the artifact is ready
|
- render-thread-only GL commit once the artifact is ready
|
||||||
- manifest-driven stateless single-pass shader packages
|
- manifest-driven stateless single-pass shader packages
|
||||||
- HTTP shader list populated from supported stateless single-pass shader packages
|
- HTTP shader list populated from supported stateless single-pass shader packages
|
||||||
@@ -210,7 +211,9 @@ Current runtime shader support is deliberately limited to stateless single-pass
|
|||||||
|
|
||||||
The `/api/state` shader list uses the same support rules as runtime shader compilation and reports only packages this app can run today. Unsupported manifest feature sets such as multipass, temporal, feedback, texture-backed, font-backed, or text-parameter shaders are hidden from the control UI for now.
|
The `/api/state` shader list uses the same support rules as runtime shader compilation and reports only packages this app can run today. Unsupported manifest feature sets such as multipass, temporal, feedback, texture-backed, font-backed, or text-parameter shaders are hidden from the control UI for now.
|
||||||
|
|
||||||
Runtime shaders are exposed through `RuntimeLayerModel` as display layers with manifest parameter defaults. The model also records whether each layer has a render-ready artifact. Stage 1 add/remove POST controls mutate this app-owned model and may start background shader builds, but multi-layer render-scene handoff is not ported yet.
|
Runtime shaders are exposed through `RuntimeLayerModel` as display layers with manifest parameter defaults. The model also records whether each layer has a render-ready artifact. Add/remove POST controls mutate this app-owned model and may start background shader builds.
|
||||||
|
|
||||||
|
When a layer becomes render-ready, the app publishes the ready render-layer snapshot to the render thread. The render thread owns the GL-side `RuntimeRenderScene`, diffs that snapshot at a frame boundary, commits/removes GL programs, and renders the ready layers in order. Current layer rendering is still deliberately simple: each stateless full-frame shader draws to the output target using fallback source textures until proper layer-input texture handoff is designed.
|
||||||
|
|
||||||
Successful handoff signs:
|
Successful handoff signs:
|
||||||
|
|
||||||
@@ -260,6 +263,7 @@ This app keeps the same core behavior but splits it into modules that can grow:
|
|||||||
- `frames/`: system-memory handoff
|
- `frames/`: system-memory handoff
|
||||||
- `platform/`: COM/Win32/hidden GL context support
|
- `platform/`: COM/Win32/hidden GL context support
|
||||||
- `render/`: cadence, simple rendering, PBO readback
|
- `render/`: cadence, simple rendering, PBO readback
|
||||||
|
- `render/RuntimeRenderScene`: render-thread-owned GL scene for ready runtime shader layers
|
||||||
- `runtime/`: app-owned shader layer readiness model, runtime Slang build bridge, and completed artifact handoff
|
- `runtime/`: app-owned shader layer readiness model, runtime Slang build bridge, and completed artifact handoff
|
||||||
- `control/`: local HTTP API edge and runtime-state JSON presentation
|
- `control/`: local HTTP API edge and runtime-state JSON presentation
|
||||||
- `json/`: compact JSON serialization helpers
|
- `json/`: compact JSON serialization helpers
|
||||||
|
|||||||
@@ -237,7 +237,7 @@ private:
|
|||||||
Log("runtime-shader", "Starting background Slang build for shader '" + mConfig.runtimeShaderId + "'.");
|
Log("runtime-shader", "Starting background Slang build for shader '" + mConfig.runtimeShaderId + "'.");
|
||||||
const std::string layerId = FirstRuntimeLayerId();
|
const std::string layerId = FirstRuntimeLayerId();
|
||||||
if (!layerId.empty())
|
if (!layerId.empty())
|
||||||
StartLayerShaderBuild(layerId, mConfig.runtimeShaderId, true);
|
StartLayerShaderBuild(layerId, mConfig.runtimeShaderId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoadSupportedShaderCatalog()
|
void LoadSupportedShaderCatalog()
|
||||||
@@ -279,12 +279,16 @@ private:
|
|||||||
mRuntimeLayerModel.MarkBuildStarted(layerId, message, error);
|
mRuntimeLayerModel.MarkBuildStarted(layerId, message, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MarkRuntimeBuildReady(const RuntimeShaderArtifact& artifact)
|
bool MarkRuntimeBuildReady(const RuntimeShaderArtifact& artifact)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(mRuntimeLayerMutex);
|
std::lock_guard<std::mutex> lock(mRuntimeLayerMutex);
|
||||||
std::string error;
|
std::string error;
|
||||||
if (!mRuntimeLayerModel.MarkBuildReady(artifact, error))
|
if (!mRuntimeLayerModel.MarkBuildReady(artifact, error))
|
||||||
|
{
|
||||||
LogWarning("runtime-shader", error);
|
LogWarning("runtime-shader", error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MarkRuntimeBuildFailed(const std::string& message)
|
void MarkRuntimeBuildFailed(const std::string& message)
|
||||||
@@ -308,7 +312,7 @@ private:
|
|||||||
return mRuntimeLayerModel.FirstLayerId();
|
return mRuntimeLayerModel.FirstLayerId();
|
||||||
}
|
}
|
||||||
|
|
||||||
void StartLayerShaderBuild(const std::string& layerId, const std::string& shaderId, bool submitToRender)
|
void StartLayerShaderBuild(const std::string& layerId, const std::string& shaderId)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(mRuntimeLayerMutex);
|
std::lock_guard<std::mutex> lock(mRuntimeLayerMutex);
|
||||||
@@ -329,10 +333,9 @@ private:
|
|||||||
bridgePtr->Start(
|
bridgePtr->Start(
|
||||||
layerId,
|
layerId,
|
||||||
shaderId,
|
shaderId,
|
||||||
[this, submitToRender](const RuntimeShaderArtifact& artifact) {
|
[this](const RuntimeShaderArtifact& artifact) {
|
||||||
MarkRuntimeBuildReady(artifact);
|
if (MarkRuntimeBuildReady(artifact))
|
||||||
if (submitToRender)
|
PublishRuntimeRenderLayers();
|
||||||
mRenderThread.SubmitRuntimeShaderArtifact(artifact);
|
|
||||||
},
|
},
|
||||||
[this, layerId](const std::string& message) {
|
[this, layerId](const std::string& message) {
|
||||||
MarkRuntimeBuildFailedForLayer(layerId, message);
|
MarkRuntimeBuildFailedForLayer(layerId, message);
|
||||||
@@ -379,7 +382,8 @@ private:
|
|||||||
return { false, error };
|
return { false, error };
|
||||||
}
|
}
|
||||||
|
|
||||||
StartLayerShaderBuild(layerId, shaderId, false);
|
Log("runtime-shader", "Layer added: " + layerId + " shader=" + shaderId);
|
||||||
|
StartLayerShaderBuild(layerId, shaderId);
|
||||||
return { true, std::string() };
|
return { true, std::string() };
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -396,10 +400,22 @@ private:
|
|||||||
return { false, error };
|
return { false, error };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Log("runtime-shader", "Layer removed: " + layerId);
|
||||||
StopLayerShaderBuild(layerId);
|
StopLayerShaderBuild(layerId);
|
||||||
|
PublishRuntimeRenderLayers();
|
||||||
return { true, std::string() };
|
return { true, std::string() };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PublishRuntimeRenderLayers()
|
||||||
|
{
|
||||||
|
std::vector<RuntimeRenderLayerModel> renderLayers;
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(mRuntimeLayerMutex);
|
||||||
|
renderLayers = mRuntimeLayerModel.Snapshot().renderLayers;
|
||||||
|
}
|
||||||
|
mRenderThread.SubmitRuntimeRenderLayers(renderLayers);
|
||||||
|
}
|
||||||
|
|
||||||
static bool ExtractStringField(const std::string& body, const char* fieldName, std::string& value, std::string& error)
|
static bool ExtractStringField(const std::string& body, const char* fieldName, std::string& value, std::string& error)
|
||||||
{
|
{
|
||||||
JsonValue root;
|
JsonValue root;
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include "../platform/HiddenGlWindow.h"
|
#include "../platform/HiddenGlWindow.h"
|
||||||
#include "Bgra8ReadbackPipeline.h"
|
#include "Bgra8ReadbackPipeline.h"
|
||||||
#include "GLExtensions.h"
|
#include "GLExtensions.h"
|
||||||
|
#include "RuntimeRenderScene.h"
|
||||||
#include "RuntimeShaderRenderer.h"
|
#include "RuntimeShaderRenderer.h"
|
||||||
#include "SimpleMotionRenderer.h"
|
#include "SimpleMotionRenderer.h"
|
||||||
|
|
||||||
@@ -94,7 +95,7 @@ void RenderThread::ThreadMain()
|
|||||||
}
|
}
|
||||||
|
|
||||||
SimpleMotionRenderer renderer;
|
SimpleMotionRenderer renderer;
|
||||||
RuntimeShaderRenderer runtimeShaderRenderer;
|
RuntimeRenderScene runtimeRenderScene;
|
||||||
Bgra8ReadbackPipeline readback;
|
Bgra8ReadbackPipeline readback;
|
||||||
if (!renderer.InitializeGl(mConfig.width, mConfig.height) || !readback.Initialize(mConfig.width, mConfig.height, mConfig.pboDepth))
|
if (!renderer.InitializeGl(mConfig.width, mConfig.height) || !readback.Initialize(mConfig.width, mConfig.height, mConfig.pboDepth))
|
||||||
{
|
{
|
||||||
@@ -126,10 +127,10 @@ void RenderThread::ThreadMain()
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
TryCommitReadyRuntimeShader(runtimeShaderRenderer);
|
TryCommitReadyRuntimeShader(runtimeRenderScene);
|
||||||
if (!readback.RenderAndQueue(frameIndex, [this, &renderer, &runtimeShaderRenderer](uint64_t index) {
|
if (!readback.RenderAndQueue(frameIndex, [this, &renderer, &runtimeRenderScene](uint64_t index) {
|
||||||
if (runtimeShaderRenderer.HasProgram())
|
if (runtimeRenderScene.HasLayers())
|
||||||
runtimeShaderRenderer.RenderFrame(index, mConfig.width, mConfig.height);
|
runtimeRenderScene.RenderFrame(index, mConfig.width, mConfig.height);
|
||||||
else
|
else
|
||||||
renderer.RenderFrame(index);
|
renderer.RenderFrame(index);
|
||||||
}))
|
}))
|
||||||
@@ -157,7 +158,7 @@ void RenderThread::ThreadMain()
|
|||||||
}
|
}
|
||||||
|
|
||||||
readback.Shutdown();
|
readback.Shutdown();
|
||||||
runtimeShaderRenderer.ShutdownGl();
|
runtimeRenderScene.ShutdownGl();
|
||||||
renderer.ShutdownGl();
|
renderer.ShutdownGl();
|
||||||
window.ClearCurrent();
|
window.ClearCurrent();
|
||||||
mRunning.store(false, std::memory_order_release);
|
mRunning.store(false, std::memory_order_release);
|
||||||
@@ -204,6 +205,13 @@ void RenderThread::SubmitRuntimeShaderArtifact(const RuntimeShaderArtifact& arti
|
|||||||
mHasPendingShaderArtifact = true;
|
mHasPendingShaderArtifact = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RenderThread::SubmitRuntimeRenderLayers(const std::vector<RenderCadenceCompositor::RuntimeRenderLayerModel>& layers)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(mRenderLayersMutex);
|
||||||
|
mPendingRenderLayers = layers;
|
||||||
|
mHasPendingRenderLayers = true;
|
||||||
|
}
|
||||||
|
|
||||||
bool RenderThread::TryTakePendingRuntimeShaderArtifact(RuntimeShaderArtifact& artifact)
|
bool RenderThread::TryTakePendingRuntimeShaderArtifact(RuntimeShaderArtifact& artifact)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(mShaderArtifactMutex);
|
std::lock_guard<std::mutex> lock(mShaderArtifactMutex);
|
||||||
@@ -216,14 +224,52 @@ bool RenderThread::TryTakePendingRuntimeShaderArtifact(RuntimeShaderArtifact& ar
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderThread::TryCommitReadyRuntimeShader(RuntimeShaderRenderer& runtimeShaderRenderer)
|
bool RenderThread::TryTakePendingRenderLayers(std::vector<RenderCadenceCompositor::RuntimeRenderLayerModel>& layers)
|
||||||
{
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(mRenderLayersMutex);
|
||||||
|
if (!mHasPendingRenderLayers)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
layers = std::move(mPendingRenderLayers);
|
||||||
|
mPendingRenderLayers.clear();
|
||||||
|
mHasPendingRenderLayers = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderThread::TryCommitReadyRuntimeShader(RuntimeRenderScene& runtimeRenderScene)
|
||||||
|
{
|
||||||
|
std::vector<RenderCadenceCompositor::RuntimeRenderLayerModel> layers;
|
||||||
|
std::string commitError;
|
||||||
|
if (TryTakePendingRenderLayers(layers))
|
||||||
|
{
|
||||||
|
if (!runtimeRenderScene.CommitRenderLayers(layers, commitError))
|
||||||
|
{
|
||||||
|
RenderCadenceCompositor::TryLog(
|
||||||
|
RenderCadenceCompositor::LogLevel::Error,
|
||||||
|
"render-thread",
|
||||||
|
"Runtime render-layer commit failed: " + commitError);
|
||||||
|
mShaderBuildFailures.fetch_add(1, std::memory_order_relaxed);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
RenderCadenceCompositor::TryLog(
|
||||||
|
RenderCadenceCompositor::LogLevel::Log,
|
||||||
|
"render-thread",
|
||||||
|
"Runtime render layer snapshot committed.");
|
||||||
|
mShaderBuildsCommitted.fetch_add(1, std::memory_order_relaxed);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
RuntimeShaderArtifact artifact;
|
RuntimeShaderArtifact artifact;
|
||||||
if (!TryTakePendingRuntimeShaderArtifact(artifact))
|
if (!TryTakePendingRuntimeShaderArtifact(artifact))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
std::string commitError;
|
RenderCadenceCompositor::RuntimeRenderLayerModel layer;
|
||||||
if (!runtimeShaderRenderer.CommitShaderArtifact(artifact, commitError))
|
layer.id = artifact.layerId.empty() ? "runtime-layer-1" : artifact.layerId;
|
||||||
|
layer.shaderId = artifact.shaderId;
|
||||||
|
layer.artifact = artifact;
|
||||||
|
layers.push_back(std::move(layer));
|
||||||
|
if (!runtimeRenderScene.CommitRenderLayers(layers, commitError))
|
||||||
{
|
{
|
||||||
RenderCadenceCompositor::TryLog(
|
RenderCadenceCompositor::TryLog(
|
||||||
RenderCadenceCompositor::LogLevel::Error,
|
RenderCadenceCompositor::LogLevel::Error,
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "RenderCadenceClock.h"
|
#include "RenderCadenceClock.h"
|
||||||
|
#include "../runtime/RuntimeLayerModel.h"
|
||||||
#include "../runtime/RuntimeShaderArtifact.h"
|
#include "../runtime/RuntimeShaderArtifact.h"
|
||||||
#include "RuntimeShaderRenderer.h"
|
#include "RuntimeRenderScene.h"
|
||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
@@ -45,6 +46,7 @@ public:
|
|||||||
bool Start(std::string& error);
|
bool Start(std::string& error);
|
||||||
void Stop();
|
void Stop();
|
||||||
void SubmitRuntimeShaderArtifact(const RuntimeShaderArtifact& artifact);
|
void SubmitRuntimeShaderArtifact(const RuntimeShaderArtifact& artifact);
|
||||||
|
void SubmitRuntimeRenderLayers(const std::vector<RenderCadenceCompositor::RuntimeRenderLayerModel>& layers);
|
||||||
|
|
||||||
Metrics GetMetrics() const;
|
Metrics GetMetrics() const;
|
||||||
bool IsRunning() const { return mRunning.load(std::memory_order_acquire); }
|
bool IsRunning() const { return mRunning.load(std::memory_order_acquire); }
|
||||||
@@ -56,8 +58,9 @@ private:
|
|||||||
void CountRendered();
|
void CountRendered();
|
||||||
void CountCompleted();
|
void CountCompleted();
|
||||||
void CountAcquireMiss();
|
void CountAcquireMiss();
|
||||||
void TryCommitReadyRuntimeShader(RuntimeShaderRenderer& runtimeShaderRenderer);
|
void TryCommitReadyRuntimeShader(RuntimeRenderScene& runtimeRenderScene);
|
||||||
bool TryTakePendingRuntimeShaderArtifact(RuntimeShaderArtifact& artifact);
|
bool TryTakePendingRuntimeShaderArtifact(RuntimeShaderArtifact& artifact);
|
||||||
|
bool TryTakePendingRenderLayers(std::vector<RenderCadenceCompositor::RuntimeRenderLayerModel>& layers);
|
||||||
|
|
||||||
SystemFrameExchange& mFrameExchange;
|
SystemFrameExchange& mFrameExchange;
|
||||||
Config mConfig;
|
Config mConfig;
|
||||||
@@ -82,4 +85,8 @@ private:
|
|||||||
std::mutex mShaderArtifactMutex;
|
std::mutex mShaderArtifactMutex;
|
||||||
bool mHasPendingShaderArtifact = false;
|
bool mHasPendingShaderArtifact = false;
|
||||||
RuntimeShaderArtifact mPendingShaderArtifact;
|
RuntimeShaderArtifact mPendingShaderArtifact;
|
||||||
|
|
||||||
|
std::mutex mRenderLayersMutex;
|
||||||
|
bool mHasPendingRenderLayers = false;
|
||||||
|
std::vector<RenderCadenceCompositor::RuntimeRenderLayerModel> mPendingRenderLayers;
|
||||||
};
|
};
|
||||||
|
|||||||
114
apps/RenderCadenceCompositor/render/RuntimeRenderScene.cpp
Normal file
114
apps/RenderCadenceCompositor/render/RuntimeRenderScene.cpp
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
#include "RuntimeRenderScene.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <functional>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
RuntimeRenderScene::~RuntimeRenderScene()
|
||||||
|
{
|
||||||
|
ShutdownGl();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RuntimeRenderScene::CommitRenderLayers(const std::vector<RenderCadenceCompositor::RuntimeRenderLayerModel>& layers, std::string& error)
|
||||||
|
{
|
||||||
|
std::vector<std::string> nextOrder;
|
||||||
|
nextOrder.reserve(layers.size());
|
||||||
|
for (const RenderCadenceCompositor::RuntimeRenderLayerModel& layer : layers)
|
||||||
|
nextOrder.push_back(layer.id);
|
||||||
|
|
||||||
|
for (auto layerIt = mLayers.begin(); layerIt != mLayers.end();)
|
||||||
|
{
|
||||||
|
const bool stillPresent = std::find(nextOrder.begin(), nextOrder.end(), layerIt->layerId) != nextOrder.end();
|
||||||
|
if (stillPresent)
|
||||||
|
{
|
||||||
|
++layerIt;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (layerIt->renderer)
|
||||||
|
layerIt->renderer->ShutdownGl();
|
||||||
|
layerIt = mLayers.erase(layerIt);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const RenderCadenceCompositor::RuntimeRenderLayerModel& layer : layers)
|
||||||
|
{
|
||||||
|
if (layer.artifact.fragmentShaderSource.empty())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const std::string fingerprint = Fingerprint(layer.artifact);
|
||||||
|
LayerProgram* program = FindLayer(layer.id);
|
||||||
|
if (!program)
|
||||||
|
{
|
||||||
|
LayerProgram next;
|
||||||
|
next.layerId = layer.id;
|
||||||
|
next.renderer = std::make_unique<RuntimeShaderRenderer>();
|
||||||
|
mLayers.push_back(std::move(next));
|
||||||
|
program = &mLayers.back();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (program->shaderId == layer.shaderId && program->sourceFingerprint == fingerprint && program->renderer && program->renderer->HasProgram())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
std::unique_ptr<RuntimeShaderRenderer> nextRenderer = std::make_unique<RuntimeShaderRenderer>();
|
||||||
|
if (!nextRenderer->CommitShaderArtifact(layer.artifact, error))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (program->renderer)
|
||||||
|
program->renderer->ShutdownGl();
|
||||||
|
program->shaderId = layer.shaderId;
|
||||||
|
program->sourceFingerprint = fingerprint;
|
||||||
|
program->renderer = std::move(nextRenderer);
|
||||||
|
}
|
||||||
|
|
||||||
|
mLayerOrder = std::move(nextOrder);
|
||||||
|
error.clear();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RuntimeRenderScene::RenderFrame(uint64_t frameIndex, unsigned width, unsigned height)
|
||||||
|
{
|
||||||
|
for (const std::string& layerId : mLayerOrder)
|
||||||
|
{
|
||||||
|
LayerProgram* layer = FindLayer(layerId);
|
||||||
|
if (!layer || !layer->renderer || !layer->renderer->HasProgram())
|
||||||
|
continue;
|
||||||
|
layer->renderer->RenderFrame(frameIndex, width, height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RuntimeRenderScene::ShutdownGl()
|
||||||
|
{
|
||||||
|
for (LayerProgram& layer : mLayers)
|
||||||
|
{
|
||||||
|
if (layer.renderer)
|
||||||
|
layer.renderer->ShutdownGl();
|
||||||
|
}
|
||||||
|
mLayers.clear();
|
||||||
|
mLayerOrder.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
RuntimeRenderScene::LayerProgram* RuntimeRenderScene::FindLayer(const std::string& layerId)
|
||||||
|
{
|
||||||
|
for (LayerProgram& layer : mLayers)
|
||||||
|
{
|
||||||
|
if (layer.layerId == layerId)
|
||||||
|
return &layer;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const RuntimeRenderScene::LayerProgram* RuntimeRenderScene::FindLayer(const std::string& layerId) const
|
||||||
|
{
|
||||||
|
for (const LayerProgram& layer : mLayers)
|
||||||
|
{
|
||||||
|
if (layer.layerId == layerId)
|
||||||
|
return &layer;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string RuntimeRenderScene::Fingerprint(const RuntimeShaderArtifact& artifact)
|
||||||
|
{
|
||||||
|
const std::hash<std::string> hasher;
|
||||||
|
return artifact.shaderId + ":" + std::to_string(artifact.fragmentShaderSource.size()) + ":" + std::to_string(hasher(artifact.fragmentShaderSource));
|
||||||
|
}
|
||||||
39
apps/RenderCadenceCompositor/render/RuntimeRenderScene.h
Normal file
39
apps/RenderCadenceCompositor/render/RuntimeRenderScene.h
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../runtime/RuntimeLayerModel.h"
|
||||||
|
#include "RuntimeShaderRenderer.h"
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class RuntimeRenderScene
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RuntimeRenderScene() = default;
|
||||||
|
RuntimeRenderScene(const RuntimeRenderScene&) = delete;
|
||||||
|
RuntimeRenderScene& operator=(const RuntimeRenderScene&) = delete;
|
||||||
|
~RuntimeRenderScene();
|
||||||
|
|
||||||
|
bool CommitRenderLayers(const std::vector<RenderCadenceCompositor::RuntimeRenderLayerModel>& layers, std::string& error);
|
||||||
|
bool HasLayers() const { return !mLayerOrder.empty(); }
|
||||||
|
void RenderFrame(uint64_t frameIndex, unsigned width, unsigned height);
|
||||||
|
void ShutdownGl();
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct LayerProgram
|
||||||
|
{
|
||||||
|
std::string layerId;
|
||||||
|
std::string shaderId;
|
||||||
|
std::string sourceFingerprint;
|
||||||
|
std::unique_ptr<RuntimeShaderRenderer> renderer;
|
||||||
|
};
|
||||||
|
|
||||||
|
LayerProgram* FindLayer(const std::string& layerId);
|
||||||
|
const LayerProgram* FindLayer(const std::string& layerId) const;
|
||||||
|
static std::string Fingerprint(const RuntimeShaderArtifact& artifact);
|
||||||
|
|
||||||
|
std::vector<LayerProgram> mLayers;
|
||||||
|
std::vector<std::string> mLayerOrder;
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user