Render udpates
This commit is contained in:
@@ -11,6 +11,7 @@
|
||||
#include "SimpleMotionRenderer.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <thread>
|
||||
|
||||
RenderThread::RenderThread(SystemFrameExchange& frameExchange, Config config) :
|
||||
@@ -83,11 +84,22 @@ void RenderThread::ThreadMain()
|
||||
RenderCadenceCompositor::TryLog(RenderCadenceCompositor::LogLevel::Log, "render-thread", "Render thread starting.");
|
||||
HiddenGlWindow window;
|
||||
std::string error;
|
||||
if (!window.Create(mConfig.width, mConfig.height, error) || !window.MakeCurrent())
|
||||
if (!window.Create(mConfig.width, mConfig.height, error))
|
||||
{
|
||||
SignalStartupFailure(error.empty() ? "OpenGL context creation failed." : error);
|
||||
return;
|
||||
}
|
||||
std::unique_ptr<HiddenGlWindow> prepareWindow = std::make_unique<HiddenGlWindow>();
|
||||
if (!prepareWindow->CreateShared(mConfig.width, mConfig.height, window.DeviceContext(), window.Context(), error))
|
||||
{
|
||||
SignalStartupFailure(error.empty() ? "Runtime shader prepare shared context creation failed." : error);
|
||||
return;
|
||||
}
|
||||
if (!window.MakeCurrent())
|
||||
{
|
||||
SignalStartupFailure("OpenGL context creation failed.");
|
||||
return;
|
||||
}
|
||||
if (!ResolveGLExtensions())
|
||||
{
|
||||
SignalStartupFailure("OpenGL extension resolution failed.");
|
||||
@@ -97,6 +109,11 @@ void RenderThread::ThreadMain()
|
||||
SimpleMotionRenderer renderer;
|
||||
RuntimeRenderScene runtimeRenderScene;
|
||||
Bgra8ReadbackPipeline readback;
|
||||
if (!runtimeRenderScene.StartPrepareWorker(std::move(prepareWindow), error))
|
||||
{
|
||||
SignalStartupFailure(error.empty() ? "Runtime shader prepare worker initialization failed." : error);
|
||||
return;
|
||||
}
|
||||
if (!renderer.InitializeGl(mConfig.width, mConfig.height) || !readback.Initialize(mConfig.width, mConfig.height, mConfig.pboDepth))
|
||||
{
|
||||
SignalStartupFailure("Render pipeline initialization failed.");
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#include "RuntimeRenderScene.h"
|
||||
|
||||
#include "../platform/HiddenGlWindow.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
@@ -9,9 +11,17 @@ RuntimeRenderScene::~RuntimeRenderScene()
|
||||
ShutdownGl();
|
||||
}
|
||||
|
||||
bool RuntimeRenderScene::StartPrepareWorker(std::unique_ptr<HiddenGlWindow> sharedWindow, std::string& error)
|
||||
{
|
||||
return mPrepareWorker.Start(std::move(sharedWindow), error);
|
||||
}
|
||||
|
||||
bool RuntimeRenderScene::CommitRenderLayers(const std::vector<RenderCadenceCompositor::RuntimeRenderLayerModel>& layers, std::string& error)
|
||||
{
|
||||
ConsumePreparedPrograms();
|
||||
|
||||
std::vector<std::string> nextOrder;
|
||||
std::vector<RenderCadenceCompositor::RuntimeRenderLayerModel> layersToPrepare;
|
||||
nextOrder.reserve(layers.size());
|
||||
for (const RenderCadenceCompositor::RuntimeRenderLayerModel& layer : layers)
|
||||
nextOrder.push_back(layer.id);
|
||||
@@ -48,25 +58,38 @@ bool RuntimeRenderScene::CommitRenderLayers(const std::vector<RenderCadenceCompo
|
||||
|
||||
if (program->shaderId == layer.shaderId && program->sourceFingerprint == fingerprint && program->renderer && program->renderer->HasProgram())
|
||||
continue;
|
||||
if (program->pendingFingerprint == fingerprint)
|
||||
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);
|
||||
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);
|
||||
@@ -78,6 +101,7 @@ void RuntimeRenderScene::RenderFrame(uint64_t frameIndex, unsigned width, unsign
|
||||
|
||||
void RuntimeRenderScene::ShutdownGl()
|
||||
{
|
||||
mPrepareWorker.Stop();
|
||||
for (LayerProgram& layer : mLayers)
|
||||
{
|
||||
if (layer.renderer)
|
||||
@@ -87,6 +111,41 @@ void RuntimeRenderScene::ShutdownGl()
|
||||
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<RuntimeShaderRenderer> nextRenderer = std::make_unique<RuntimeShaderRenderer>();
|
||||
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)
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include "../runtime/RuntimeLayerModel.h"
|
||||
#include "RuntimeShaderPrepareWorker.h"
|
||||
#include "RuntimeShaderRenderer.h"
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
@@ -16,8 +19,9 @@ public:
|
||||
RuntimeRenderScene& operator=(const RuntimeRenderScene&) = delete;
|
||||
~RuntimeRenderScene();
|
||||
|
||||
bool StartPrepareWorker(std::unique_ptr<HiddenGlWindow> sharedWindow, std::string& error);
|
||||
bool CommitRenderLayers(const std::vector<RenderCadenceCompositor::RuntimeRenderLayerModel>& layers, std::string& error);
|
||||
bool HasLayers() const { return !mLayerOrder.empty(); }
|
||||
bool HasLayers();
|
||||
void RenderFrame(uint64_t frameIndex, unsigned width, unsigned height);
|
||||
void ShutdownGl();
|
||||
|
||||
@@ -27,13 +31,16 @@ private:
|
||||
std::string layerId;
|
||||
std::string shaderId;
|
||||
std::string sourceFingerprint;
|
||||
std::string pendingFingerprint;
|
||||
std::unique_ptr<RuntimeShaderRenderer> renderer;
|
||||
};
|
||||
|
||||
void ConsumePreparedPrograms();
|
||||
LayerProgram* FindLayer(const std::string& layerId);
|
||||
const LayerProgram* FindLayer(const std::string& layerId) const;
|
||||
static std::string Fingerprint(const RuntimeShaderArtifact& artifact);
|
||||
|
||||
RuntimeShaderPrepareWorker mPrepareWorker;
|
||||
std::vector<LayerProgram> mLayers;
|
||||
std::vector<std::string> mLayerOrder;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,158 @@
|
||||
#include "RuntimeShaderPrepareWorker.h"
|
||||
|
||||
#include "../platform/HiddenGlWindow.h"
|
||||
#include "RuntimeShaderRenderer.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
|
||||
RuntimeShaderPrepareWorker::~RuntimeShaderPrepareWorker()
|
||||
{
|
||||
Stop();
|
||||
}
|
||||
|
||||
bool RuntimeShaderPrepareWorker::Start(std::unique_ptr<HiddenGlWindow> sharedWindow, std::string& error)
|
||||
{
|
||||
if (mThread.joinable())
|
||||
return true;
|
||||
if (!sharedWindow || sharedWindow->DeviceContext() == nullptr || sharedWindow->Context() == nullptr)
|
||||
{
|
||||
error = "Runtime shader prepare worker needs an existing shared GL context.";
|
||||
return false;
|
||||
}
|
||||
|
||||
mWindow = std::move(sharedWindow);
|
||||
mStopping.store(false, std::memory_order_release);
|
||||
mStarted.store(false, std::memory_order_release);
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mMutex);
|
||||
mStartupReady = false;
|
||||
mStartupError.clear();
|
||||
}
|
||||
mThread = std::thread([this]() { ThreadMain(); });
|
||||
|
||||
std::unique_lock<std::mutex> lock(mMutex);
|
||||
if (!mStartupCondition.wait_for(lock, std::chrono::seconds(3), [this]() {
|
||||
return mStartupReady || !mStartupError.empty();
|
||||
}))
|
||||
{
|
||||
error = "Timed out starting runtime shader prepare worker.";
|
||||
lock.unlock();
|
||||
Stop();
|
||||
return false;
|
||||
}
|
||||
if (!mStartupError.empty())
|
||||
{
|
||||
error = mStartupError;
|
||||
lock.unlock();
|
||||
Stop();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void RuntimeShaderPrepareWorker::Stop()
|
||||
{
|
||||
mStopping.store(true, std::memory_order_release);
|
||||
mCondition.notify_all();
|
||||
if (mThread.joinable())
|
||||
mThread.join();
|
||||
|
||||
std::deque<RuntimePreparedShaderProgram> completed;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mMutex);
|
||||
mRequests.clear();
|
||||
completed.swap(mCompleted);
|
||||
}
|
||||
for (RuntimePreparedShaderProgram& program : completed)
|
||||
program.ReleaseGl();
|
||||
mWindow.reset();
|
||||
mStarted.store(false, std::memory_order_release);
|
||||
}
|
||||
|
||||
void RuntimeShaderPrepareWorker::Submit(const std::vector<RenderCadenceCompositor::RuntimeRenderLayerModel>& layers)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mMutex);
|
||||
for (const RenderCadenceCompositor::RuntimeRenderLayerModel& layer : layers)
|
||||
{
|
||||
if (layer.artifact.fragmentShaderSource.empty())
|
||||
continue;
|
||||
|
||||
PrepareRequest request;
|
||||
request.layerId = layer.id;
|
||||
request.shaderId = layer.shaderId;
|
||||
request.sourceFingerprint = Fingerprint(layer.artifact);
|
||||
request.artifact = layer.artifact;
|
||||
|
||||
auto sameLayer = [&request](const PrepareRequest& existing) {
|
||||
return existing.layerId == request.layerId;
|
||||
};
|
||||
mRequests.erase(std::remove_if(mRequests.begin(), mRequests.end(), sameLayer), mRequests.end());
|
||||
mRequests.push_back(std::move(request));
|
||||
}
|
||||
mCondition.notify_one();
|
||||
}
|
||||
|
||||
bool RuntimeShaderPrepareWorker::TryConsume(RuntimePreparedShaderProgram& preparedProgram)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mMutex);
|
||||
if (mCompleted.empty())
|
||||
return false;
|
||||
|
||||
preparedProgram = std::move(mCompleted.front());
|
||||
mCompleted.pop_front();
|
||||
return true;
|
||||
}
|
||||
|
||||
void RuntimeShaderPrepareWorker::ThreadMain()
|
||||
{
|
||||
if (!mWindow || !mWindow->MakeCurrent())
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mMutex);
|
||||
mStartupError = "Runtime shader prepare worker could not make shared GL context current.";
|
||||
mStartupCondition.notify_all();
|
||||
return;
|
||||
}
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mMutex);
|
||||
mStartupReady = true;
|
||||
}
|
||||
mStarted.store(true, std::memory_order_release);
|
||||
mStartupCondition.notify_all();
|
||||
|
||||
while (!mStopping.load(std::memory_order_acquire))
|
||||
{
|
||||
PrepareRequest request;
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(mMutex);
|
||||
mCondition.wait(lock, [this]() {
|
||||
return mStopping.load(std::memory_order_acquire) || !mRequests.empty();
|
||||
});
|
||||
if (mStopping.load(std::memory_order_acquire))
|
||||
break;
|
||||
request = std::move(mRequests.front());
|
||||
mRequests.pop_front();
|
||||
}
|
||||
|
||||
RuntimePreparedShaderProgram preparedProgram;
|
||||
RuntimeShaderRenderer::BuildPreparedProgram(
|
||||
request.layerId,
|
||||
request.sourceFingerprint,
|
||||
request.artifact,
|
||||
preparedProgram);
|
||||
glFlush();
|
||||
|
||||
std::lock_guard<std::mutex> lock(mMutex);
|
||||
mCompleted.push_back(std::move(preparedProgram));
|
||||
}
|
||||
|
||||
mWindow->ClearCurrent();
|
||||
}
|
||||
|
||||
std::string RuntimeShaderPrepareWorker::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));
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
#pragma once
|
||||
|
||||
#include "RuntimeShaderProgram.h"
|
||||
#include "../runtime/RuntimeLayerModel.h"
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <condition_variable>
|
||||
#include <deque>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
class HiddenGlWindow;
|
||||
|
||||
class RuntimeShaderPrepareWorker
|
||||
{
|
||||
public:
|
||||
RuntimeShaderPrepareWorker() = default;
|
||||
RuntimeShaderPrepareWorker(const RuntimeShaderPrepareWorker&) = delete;
|
||||
RuntimeShaderPrepareWorker& operator=(const RuntimeShaderPrepareWorker&) = delete;
|
||||
~RuntimeShaderPrepareWorker();
|
||||
|
||||
bool Start(std::unique_ptr<HiddenGlWindow> sharedWindow, std::string& error);
|
||||
void Stop();
|
||||
|
||||
void Submit(const std::vector<RenderCadenceCompositor::RuntimeRenderLayerModel>& layers);
|
||||
bool TryConsume(RuntimePreparedShaderProgram& preparedProgram);
|
||||
|
||||
private:
|
||||
struct PrepareRequest
|
||||
{
|
||||
std::string layerId;
|
||||
std::string shaderId;
|
||||
std::string sourceFingerprint;
|
||||
RuntimeShaderArtifact artifact;
|
||||
};
|
||||
|
||||
void ThreadMain();
|
||||
static std::string Fingerprint(const RuntimeShaderArtifact& artifact);
|
||||
|
||||
std::unique_ptr<HiddenGlWindow> mWindow;
|
||||
std::mutex mMutex;
|
||||
std::condition_variable mCondition;
|
||||
std::deque<PrepareRequest> mRequests;
|
||||
std::deque<RuntimePreparedShaderProgram> mCompleted;
|
||||
std::condition_variable mStartupCondition;
|
||||
std::thread mThread;
|
||||
std::atomic<bool> mStopping{ false };
|
||||
std::atomic<bool> mStarted{ false };
|
||||
bool mStartupReady = false;
|
||||
std::string mStartupError;
|
||||
};
|
||||
32
apps/RenderCadenceCompositor/render/RuntimeShaderProgram.h
Normal file
32
apps/RenderCadenceCompositor/render/RuntimeShaderProgram.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include "GLExtensions.h"
|
||||
#include "../runtime/RuntimeShaderArtifact.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
struct RuntimePreparedShaderProgram
|
||||
{
|
||||
std::string layerId;
|
||||
std::string shaderId;
|
||||
std::string sourceFingerprint;
|
||||
RuntimeShaderArtifact artifact;
|
||||
GLuint program = 0;
|
||||
GLuint vertexShader = 0;
|
||||
GLuint fragmentShader = 0;
|
||||
bool succeeded = false;
|
||||
std::string error;
|
||||
|
||||
void ReleaseGl()
|
||||
{
|
||||
if (program != 0)
|
||||
glDeleteProgram(program);
|
||||
if (vertexShader != 0)
|
||||
glDeleteShader(vertexShader);
|
||||
if (fragmentShader != 0)
|
||||
glDeleteShader(fragmentShader);
|
||||
program = 0;
|
||||
vertexShader = 0;
|
||||
fragmentShader = 0;
|
||||
}
|
||||
};
|
||||
@@ -71,6 +71,62 @@ bool RuntimeShaderRenderer::CommitShaderArtifact(const RuntimeShaderArtifact& ar
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RuntimeShaderRenderer::CommitPreparedProgram(RuntimePreparedShaderProgram& preparedProgram, std::string& error)
|
||||
{
|
||||
if (!preparedProgram.succeeded || preparedProgram.program == 0)
|
||||
{
|
||||
error = preparedProgram.error.empty() ? "Prepared runtime shader program is not valid." : preparedProgram.error;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!EnsureStaticGlResources(error))
|
||||
return false;
|
||||
|
||||
DestroyProgram();
|
||||
mProgram = preparedProgram.program;
|
||||
mVertexShader = preparedProgram.vertexShader;
|
||||
mFragmentShader = preparedProgram.fragmentShader;
|
||||
mArtifact = preparedProgram.artifact;
|
||||
preparedProgram.program = 0;
|
||||
preparedProgram.vertexShader = 0;
|
||||
preparedProgram.fragmentShader = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RuntimeShaderRenderer::BuildPreparedProgram(
|
||||
const std::string& layerId,
|
||||
const std::string& sourceFingerprint,
|
||||
const RuntimeShaderArtifact& artifact,
|
||||
RuntimePreparedShaderProgram& preparedProgram)
|
||||
{
|
||||
preparedProgram = RuntimePreparedShaderProgram();
|
||||
preparedProgram.layerId = layerId;
|
||||
preparedProgram.shaderId = artifact.shaderId;
|
||||
preparedProgram.sourceFingerprint = sourceFingerprint;
|
||||
preparedProgram.artifact = artifact;
|
||||
|
||||
if (artifact.fragmentShaderSource.empty())
|
||||
{
|
||||
preparedProgram.error = "Cannot prepare an empty fragment shader.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!BuildProgram(
|
||||
artifact.fragmentShaderSource,
|
||||
preparedProgram.program,
|
||||
preparedProgram.vertexShader,
|
||||
preparedProgram.fragmentShader,
|
||||
preparedProgram.error))
|
||||
{
|
||||
preparedProgram.ReleaseGl();
|
||||
return false;
|
||||
}
|
||||
|
||||
preparedProgram.succeeded = true;
|
||||
AssignSamplerUniforms(preparedProgram.program);
|
||||
return true;
|
||||
}
|
||||
|
||||
void RuntimeShaderRenderer::RenderFrame(uint64_t frameIndex, unsigned width, unsigned height)
|
||||
{
|
||||
if (mProgram == 0)
|
||||
@@ -175,7 +231,7 @@ bool RuntimeShaderRenderer::BuildProgram(const std::string& fragmentShaderSource
|
||||
return true;
|
||||
}
|
||||
|
||||
void RuntimeShaderRenderer::AssignSamplerUniforms(GLuint program) const
|
||||
void RuntimeShaderRenderer::AssignSamplerUniforms(GLuint program)
|
||||
{
|
||||
glUseProgram(program);
|
||||
const GLint videoInputLocation = glGetUniformLocation(program, "gVideoInput");
|
||||
@@ -219,7 +275,7 @@ void RuntimeShaderRenderer::BindRuntimeTextures()
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
}
|
||||
|
||||
bool RuntimeShaderRenderer::CompileShader(GLenum shaderType, const char* source, GLuint& shader, std::string& error) const
|
||||
bool RuntimeShaderRenderer::CompileShader(GLenum shaderType, const char* source, GLuint& shader, std::string& error)
|
||||
{
|
||||
shader = glCreateShader(shaderType);
|
||||
glShaderSource(shader, 1, &source, nullptr);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "GLExtensions.h"
|
||||
#include "RuntimeShaderProgram.h"
|
||||
#include "../runtime/RuntimeShaderArtifact.h"
|
||||
|
||||
#include <cstdint>
|
||||
@@ -17,15 +18,22 @@ public:
|
||||
|
||||
bool CommitFragmentShader(const std::string& fragmentShaderSource, std::string& error);
|
||||
bool CommitShaderArtifact(const RuntimeShaderArtifact& artifact, std::string& error);
|
||||
bool CommitPreparedProgram(RuntimePreparedShaderProgram& preparedProgram, std::string& error);
|
||||
bool HasProgram() const { return mProgram != 0; }
|
||||
void RenderFrame(uint64_t frameIndex, unsigned width, unsigned height);
|
||||
void ShutdownGl();
|
||||
|
||||
static bool BuildPreparedProgram(
|
||||
const std::string& layerId,
|
||||
const std::string& sourceFingerprint,
|
||||
const RuntimeShaderArtifact& artifact,
|
||||
RuntimePreparedShaderProgram& preparedProgram);
|
||||
|
||||
private:
|
||||
bool EnsureStaticGlResources(std::string& error);
|
||||
bool CompileShader(GLenum shaderType, const char* source, GLuint& shader, std::string& error) const;
|
||||
bool BuildProgram(const std::string& fragmentShaderSource, GLuint& program, GLuint& vertexShader, GLuint& fragmentShader, std::string& error);
|
||||
void AssignSamplerUniforms(GLuint program) const;
|
||||
static bool CompileShader(GLenum shaderType, const char* source, GLuint& shader, std::string& error);
|
||||
static bool BuildProgram(const std::string& fragmentShaderSource, GLuint& program, GLuint& vertexShader, GLuint& fragmentShader, std::string& error);
|
||||
static void AssignSamplerUniforms(GLuint program);
|
||||
void UpdateGlobalParams(uint64_t frameIndex, unsigned width, unsigned height);
|
||||
void BindRuntimeTextures();
|
||||
void DestroyProgram();
|
||||
|
||||
Reference in New Issue
Block a user