#include "RuntimeRenderScene.h" #include "../../platform/HiddenGlWindow.h" #include #include #include RuntimeRenderScene::~RuntimeRenderScene() { ShutdownGl(); } bool RuntimeRenderScene::StartPrepareWorker(std::unique_ptr sharedWindow, std::string& error) { return mPrepareWorker.Start(std::move(sharedWindow), error); } bool RuntimeRenderScene::CommitRenderLayers(const std::vector& layers, std::string& error) { ConsumePreparedPrograms(); std::vector nextOrder; std::vector layersToPrepare; 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(); mLayers.push_back(std::move(next)); program = &mLayers.back(); } if (program->shaderId == layer.shaderId && program->sourceFingerprint == fingerprint && program->renderer && program->renderer->HasProgram()) continue; if (program->pendingFingerprint == fingerprint) continue; program->shaderId = layer.shaderId; program->pendingFingerprint = fingerprint; layersToPrepare.push_back(layer); } mLayerOrder = std::move(nextOrder); if (!layersToPrepare.empty()) mPrepareWorker.Submit(layersToPrepare); error.clear(); return true; } bool RuntimeRenderScene::HasLayers() { ConsumePreparedPrograms(); for (const std::string& layerId : mLayerOrder) { const LayerProgram* layer = FindLayer(layerId); if (layer && layer->renderer && layer->renderer->HasProgram()) return true; } return false; } void RuntimeRenderScene::RenderFrame(uint64_t frameIndex, unsigned width, unsigned height) { ConsumePreparedPrograms(); 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() { mPrepareWorker.Stop(); for (LayerProgram& layer : mLayers) { if (layer.renderer) layer.renderer->ShutdownGl(); } mLayers.clear(); mLayerOrder.clear(); } void RuntimeRenderScene::ConsumePreparedPrograms() { RuntimePreparedShaderProgram preparedProgram; while (mPrepareWorker.TryConsume(preparedProgram)) { if (!preparedProgram.succeeded) { preparedProgram.ReleaseGl(); continue; } LayerProgram* layer = FindLayer(preparedProgram.layerId); if (!layer || layer->pendingFingerprint != preparedProgram.sourceFingerprint) { preparedProgram.ReleaseGl(); continue; } std::unique_ptr nextRenderer = std::make_unique(); std::string error; if (!nextRenderer->CommitPreparedProgram(preparedProgram, error)) { preparedProgram.ReleaseGl(); continue; } if (layer->renderer) layer->renderer->ShutdownGl(); layer->renderer = std::move(nextRenderer); layer->shaderId = preparedProgram.shaderId; layer->sourceFingerprint = preparedProgram.sourceFingerprint; layer->pendingFingerprint.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 hasher; return artifact.shaderId + ":" + std::to_string(artifact.fragmentShaderSource.size()) + ":" + std::to_string(hasher(artifact.fragmentShaderSource)); }