#include "OpenGLShaderPrograms.h" #include #include #include namespace { void CopyErrorMessage(const std::string& message, int errorMessageSize, char* errorMessage) { if (!errorMessage || errorMessageSize <= 0) return; strncpy_s(errorMessage, errorMessageSize, message.c_str(), _TRUNCATE); } } OpenGLShaderPrograms::OpenGLShaderPrograms(OpenGLRenderer& renderer, RuntimeHost& runtimeHost) : mRenderer(renderer), mRuntimeHost(runtimeHost), mGlobalParamsBuffer(renderer), mCompiler(renderer, runtimeHost, mTextureBindings) { } bool OpenGLShaderPrograms::CompileLayerPrograms(unsigned inputFrameWidth, unsigned inputFrameHeight, int errorMessageSize, char* errorMessage) { const std::vector layerStates = mRuntimeHost.GetLayerRenderStates(inputFrameWidth, inputFrameHeight); std::string temporalError; const unsigned historyCap = mRuntimeHost.GetMaxTemporalHistoryFrames(); if (!mRenderer.TemporalHistory().ValidateTextureUnitBudget(layerStates, historyCap, temporalError)) { CopyErrorMessage(temporalError, errorMessageSize, errorMessage); return false; } if (!mRenderer.TemporalHistory().EnsureResources(layerStates, historyCap, inputFrameWidth, inputFrameHeight, temporalError)) { CopyErrorMessage(temporalError, errorMessageSize, errorMessage); return false; } std::vector newPrograms; newPrograms.reserve(layerStates.size()); for (const RuntimeRenderState& state : layerStates) { LayerProgram layerProgram; if (!mCompiler.CompileLayerProgram(state, layerProgram, errorMessageSize, errorMessage)) { for (LayerProgram& program : newPrograms) DestroySingleLayerProgram(program); return false; } newPrograms.push_back(layerProgram); } DestroyLayerPrograms(); mRenderer.ReplaceLayerPrograms(newPrograms); mCommittedLayerStates = layerStates; mRuntimeHost.SetCompileStatus(true, "Shader layers compiled successfully."); mRuntimeHost.ClearReloadRequest(); return true; } bool OpenGLShaderPrograms::CommitPreparedLayerPrograms(const PreparedShaderBuild& preparedBuild, unsigned inputFrameWidth, unsigned inputFrameHeight, int errorMessageSize, char* errorMessage) { if (!preparedBuild.succeeded) { CopyErrorMessage(preparedBuild.message, errorMessageSize, errorMessage); return false; } std::string temporalError; const unsigned historyCap = mRuntimeHost.GetMaxTemporalHistoryFrames(); if (!mRenderer.TemporalHistory().ValidateTextureUnitBudget(preparedBuild.layerStates, historyCap, temporalError)) { CopyErrorMessage(temporalError, errorMessageSize, errorMessage); return false; } if (!mRenderer.TemporalHistory().EnsureResources(preparedBuild.layerStates, historyCap, inputFrameWidth, inputFrameHeight, temporalError)) { CopyErrorMessage(temporalError, errorMessageSize, errorMessage); return false; } std::vector newPrograms; newPrograms.reserve(preparedBuild.layers.size()); for (const PreparedLayerShader& preparedLayer : preparedBuild.layers) { LayerProgram layerProgram; if (!mCompiler.CompilePreparedLayerProgram(preparedLayer.state, preparedLayer.fragmentShaderSource, layerProgram, errorMessageSize, errorMessage)) { for (LayerProgram& program : newPrograms) DestroySingleLayerProgram(program); return false; } newPrograms.push_back(layerProgram); } DestroyLayerPrograms(); mRenderer.ReplaceLayerPrograms(newPrograms); mCommittedLayerStates = preparedBuild.layerStates; mRuntimeHost.SetCompileStatus(true, "Shader layers compiled successfully."); mRuntimeHost.ClearReloadRequest(); return true; } bool OpenGLShaderPrograms::CompileDecodeShader(int errorMessageSize, char* errorMessage) { return mCompiler.CompileDecodeShader(errorMessageSize, errorMessage); } void OpenGLShaderPrograms::DestroySingleLayerProgram(LayerProgram& layerProgram) { mRenderer.DestroySingleLayerProgram(layerProgram); } void OpenGLShaderPrograms::DestroyLayerPrograms() { mRenderer.DestroyLayerPrograms(); } void OpenGLShaderPrograms::DestroyDecodeShaderProgram() { mRenderer.DestroyDecodeShaderProgram(); } void OpenGLShaderPrograms::ResetTemporalHistoryState() { mRenderer.TemporalHistory().ResetState(); } bool OpenGLShaderPrograms::UpdateTextBindingTexture(const RuntimeRenderState& state, LayerProgram::TextBinding& textBinding, std::string& error) { return mTextureBindings.UpdateTextBindingTexture(state, textBinding, error); } bool OpenGLShaderPrograms::UpdateGlobalParamsBuffer(const RuntimeRenderState& state, unsigned availableSourceHistoryLength, unsigned availableTemporalHistoryLength) { return mGlobalParamsBuffer.Update(state, availableSourceHistoryLength, availableTemporalHistoryLength); }