Render changes
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
#include "../platform/HiddenGlWindow.h"
|
||||
#include "Bgra8ReadbackPipeline.h"
|
||||
#include "GLExtensions.h"
|
||||
#include "RuntimeRenderScene.h"
|
||||
#include "RuntimeShaderRenderer.h"
|
||||
#include "SimpleMotionRenderer.h"
|
||||
|
||||
@@ -94,7 +95,7 @@ void RenderThread::ThreadMain()
|
||||
}
|
||||
|
||||
SimpleMotionRenderer renderer;
|
||||
RuntimeShaderRenderer runtimeShaderRenderer;
|
||||
RuntimeRenderScene runtimeRenderScene;
|
||||
Bgra8ReadbackPipeline readback;
|
||||
if (!renderer.InitializeGl(mConfig.width, mConfig.height) || !readback.Initialize(mConfig.width, mConfig.height, mConfig.pboDepth))
|
||||
{
|
||||
@@ -126,10 +127,10 @@ void RenderThread::ThreadMain()
|
||||
continue;
|
||||
}
|
||||
|
||||
TryCommitReadyRuntimeShader(runtimeShaderRenderer);
|
||||
if (!readback.RenderAndQueue(frameIndex, [this, &renderer, &runtimeShaderRenderer](uint64_t index) {
|
||||
if (runtimeShaderRenderer.HasProgram())
|
||||
runtimeShaderRenderer.RenderFrame(index, mConfig.width, mConfig.height);
|
||||
TryCommitReadyRuntimeShader(runtimeRenderScene);
|
||||
if (!readback.RenderAndQueue(frameIndex, [this, &renderer, &runtimeRenderScene](uint64_t index) {
|
||||
if (runtimeRenderScene.HasLayers())
|
||||
runtimeRenderScene.RenderFrame(index, mConfig.width, mConfig.height);
|
||||
else
|
||||
renderer.RenderFrame(index);
|
||||
}))
|
||||
@@ -157,7 +158,7 @@ void RenderThread::ThreadMain()
|
||||
}
|
||||
|
||||
readback.Shutdown();
|
||||
runtimeShaderRenderer.ShutdownGl();
|
||||
runtimeRenderScene.ShutdownGl();
|
||||
renderer.ShutdownGl();
|
||||
window.ClearCurrent();
|
||||
mRunning.store(false, std::memory_order_release);
|
||||
@@ -204,6 +205,13 @@ void RenderThread::SubmitRuntimeShaderArtifact(const RuntimeShaderArtifact& arti
|
||||
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)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mShaderArtifactMutex);
|
||||
@@ -216,14 +224,52 @@ bool RenderThread::TryTakePendingRuntimeShaderArtifact(RuntimeShaderArtifact& ar
|
||||
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;
|
||||
if (!TryTakePendingRuntimeShaderArtifact(artifact))
|
||||
return;
|
||||
|
||||
std::string commitError;
|
||||
if (!runtimeShaderRenderer.CommitShaderArtifact(artifact, commitError))
|
||||
RenderCadenceCompositor::RuntimeRenderLayerModel layer;
|
||||
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::LogLevel::Error,
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "RenderCadenceClock.h"
|
||||
#include "../runtime/RuntimeLayerModel.h"
|
||||
#include "../runtime/RuntimeShaderArtifact.h"
|
||||
#include "RuntimeShaderRenderer.h"
|
||||
#include "RuntimeRenderScene.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <condition_variable>
|
||||
@@ -45,6 +46,7 @@ public:
|
||||
bool Start(std::string& error);
|
||||
void Stop();
|
||||
void SubmitRuntimeShaderArtifact(const RuntimeShaderArtifact& artifact);
|
||||
void SubmitRuntimeRenderLayers(const std::vector<RenderCadenceCompositor::RuntimeRenderLayerModel>& layers);
|
||||
|
||||
Metrics GetMetrics() const;
|
||||
bool IsRunning() const { return mRunning.load(std::memory_order_acquire); }
|
||||
@@ -56,8 +58,9 @@ private:
|
||||
void CountRendered();
|
||||
void CountCompleted();
|
||||
void CountAcquireMiss();
|
||||
void TryCommitReadyRuntimeShader(RuntimeShaderRenderer& runtimeShaderRenderer);
|
||||
void TryCommitReadyRuntimeShader(RuntimeRenderScene& runtimeRenderScene);
|
||||
bool TryTakePendingRuntimeShaderArtifact(RuntimeShaderArtifact& artifact);
|
||||
bool TryTakePendingRenderLayers(std::vector<RenderCadenceCompositor::RuntimeRenderLayerModel>& layers);
|
||||
|
||||
SystemFrameExchange& mFrameExchange;
|
||||
Config mConfig;
|
||||
@@ -82,4 +85,8 @@ private:
|
||||
std::mutex mShaderArtifactMutex;
|
||||
bool mHasPendingShaderArtifact = false;
|
||||
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