diff --git a/SHADER_CONTRACT.md b/SHADER_CONTRACT.md index 64320ab..ec90fcb 100644 --- a/SHADER_CONTRACT.md +++ b/SHADER_CONTRACT.md @@ -152,10 +152,23 @@ Pass fields: - `id`: required pass identifier. It must be a valid shader identifier and unique inside the package. - `source`: required Slang source path relative to the package directory. - `entryPoint`: optional Slang function for this pass. Defaults to the package-level `entryPoint`. -- `inputs`: optional list of named inputs. Current reserved names include `layerInput` and future pass output names. +- `inputs`: optional list of named inputs. The first input is used as the pass input texture. - `output`: optional output name. Use `layerOutput` for the final visible layer result. -Current runtime note: pass manifests are parsed and every declared pass is Slang-validated/compiled, but execution still uses the first pass until multipass render-target routing is enabled. Existing single-pass shaders are unaffected. +Pass input names: + +- `layerInput`: the input to this layer, before any of its passes run. +- `previousPass`: the previous pass output in this layer. If there is no previous pass, this falls back to `layerInput`. +- Any earlier pass `id` or `output` name from the same layer. + +If `inputs` is omitted, the first pass samples `layerInput` and later passes sample `previousPass`. + +Pass output names: + +- `layerOutput`: the final visible output of this layer. +- Any other name creates an intermediate 16-bit float render target that later passes may sample. + +If the final declared pass does not explicitly output `layerOutput`, the runtime still treats that final pass as the visible layer output. Existing single-pass shaders are unaffected. ## Slang Entry Point diff --git a/apps/LoopThroughWithOpenGLCompositing/gl/pipeline/OpenGLRenderPass.cpp b/apps/LoopThroughWithOpenGLCompositing/gl/pipeline/OpenGLRenderPass.cpp index 810e6fc..51451ac 100644 --- a/apps/LoopThroughWithOpenGLCompositing/gl/pipeline/OpenGLRenderPass.cpp +++ b/apps/LoopThroughWithOpenGLCompositing/gl/pipeline/OpenGLRenderPass.cpp @@ -2,6 +2,8 @@ #include "GlRenderConstants.h" +#include + OpenGLRenderPass::OpenGLRenderPass(OpenGLRenderer& renderer) : mRenderer(renderer) { @@ -93,7 +95,10 @@ std::vector OpenGLRenderPass::BuildLayerPassDescriptors( { std::vector passes; const std::size_t passCount = layerStates.size() < layerPrograms.size() ? layerStates.size() : layerPrograms.size(); - passes.reserve(passCount); + std::size_t descriptorCount = 0; + for (std::size_t index = 0; index < passCount; ++index) + descriptorCount += layerPrograms[index].passes.size(); + passes.reserve(descriptorCount); GLuint sourceTexture = mRenderer.DecodedTexture(); GLuint sourceFramebuffer = mRenderer.DecodeFramebuffer(); @@ -105,25 +110,90 @@ std::vector OpenGLRenderPass::BuildLayerPassDescriptors( continue; const std::size_t remaining = layerStates.size() - index; const bool writeToMain = (remaining % 2) == 1; + const GLuint layerOutputTexture = writeToMain ? mRenderer.CompositeTexture() : mRenderer.LayerTempTexture(); + const GLuint layerOutputFramebuffer = writeToMain ? mRenderer.CompositeFramebuffer() : mRenderer.LayerTempFramebuffer(); + const RenderPassOutputTarget layerOutputTarget = writeToMain ? RenderPassOutputTarget::Composite : RenderPassOutputTarget::LayerTemp; - RenderPassDescriptor pass; - pass.kind = RenderPassKind::LayerEffect; - pass.outputTarget = writeToMain ? RenderPassOutputTarget::Composite : RenderPassOutputTarget::LayerTemp; - pass.passIndex = index; - pass.passId = state.layerId; - pass.layerId = state.layerId; - pass.shaderId = state.shaderId; - pass.sourceTexture = sourceTexture; - pass.sourceFramebuffer = sourceFramebuffer; - pass.destinationFramebuffer = writeToMain ? mRenderer.CompositeFramebuffer() : mRenderer.LayerTempFramebuffer(); - pass.layerProgram = &layerProgram; - pass.passProgram = &layerProgram.passes.front(); - pass.layerState = &state; - pass.capturePreLayerHistory = state.temporalHistorySource == TemporalHistorySource::PreLayerInput; - passes.push_back(pass); + const GLuint layerInputTexture = sourceTexture; + const GLuint layerInputFramebuffer = sourceFramebuffer; + GLuint previousPassTexture = layerInputTexture; + GLuint previousPassFramebuffer = layerInputFramebuffer; + std::map> namedOutputs; + std::size_t temporaryTargetIndex = 0; - sourceTexture = writeToMain ? mRenderer.CompositeTexture() : mRenderer.LayerTempTexture(); - sourceFramebuffer = writeToMain ? mRenderer.CompositeFramebuffer() : mRenderer.LayerTempFramebuffer(); + for (std::size_t passIndex = 0; passIndex < layerProgram.passes.size(); ++passIndex) + { + PassProgram& passProgram = layerProgram.passes[passIndex]; + const bool lastPassForLayer = passIndex + 1 == layerProgram.passes.size(); + const std::string outputName = passProgram.outputName.empty() ? passProgram.passId : passProgram.outputName; + const bool writesLayerOutput = outputName == "layerOutput" || lastPassForLayer; + + GLuint passSourceTexture = previousPassTexture; + GLuint passSourceFramebuffer = previousPassFramebuffer; + if (!passProgram.inputNames.empty()) + { + const std::string& inputName = passProgram.inputNames.front(); + if (inputName == "layerInput") + { + passSourceTexture = layerInputTexture; + passSourceFramebuffer = layerInputFramebuffer; + } + else if (inputName == "previousPass") + { + passSourceTexture = previousPassTexture; + passSourceFramebuffer = previousPassFramebuffer; + } + else + { + auto namedOutputIt = namedOutputs.find(inputName); + if (namedOutputIt != namedOutputs.end()) + { + passSourceTexture = namedOutputIt->second.first; + passSourceFramebuffer = namedOutputIt->second.second; + } + } + } + + GLuint passDestinationTexture = layerOutputTexture; + GLuint passDestinationFramebuffer = layerOutputFramebuffer; + RenderPassOutputTarget outputTarget = layerOutputTarget; + if (!writesLayerOutput) + { + if (temporaryTargetIndex < mRenderer.TemporaryRenderTargetCount()) + { + const RenderTarget& temporaryTarget = mRenderer.TemporaryRenderTarget(temporaryTargetIndex); + ++temporaryTargetIndex; + passDestinationTexture = temporaryTarget.texture; + passDestinationFramebuffer = temporaryTarget.framebuffer; + outputTarget = RenderPassOutputTarget::Temporary; + } + } + + RenderPassDescriptor pass; + pass.kind = RenderPassKind::LayerEffect; + pass.outputTarget = outputTarget; + pass.passIndex = passes.size(); + pass.passId = passProgram.passId; + pass.layerId = state.layerId; + pass.shaderId = state.shaderId; + pass.sourceTexture = passSourceTexture; + pass.sourceFramebuffer = passIndex == 0 ? layerInputFramebuffer : passSourceFramebuffer; + pass.destinationTexture = passDestinationTexture; + pass.destinationFramebuffer = passDestinationFramebuffer; + pass.layerProgram = &layerProgram; + pass.passProgram = &passProgram; + pass.layerState = &state; + pass.capturePreLayerHistory = passIndex == 0 && state.temporalHistorySource == TemporalHistorySource::PreLayerInput; + passes.push_back(pass); + + namedOutputs[outputName] = std::make_pair(passDestinationTexture, passDestinationFramebuffer); + namedOutputs[passProgram.passId] = std::make_pair(passDestinationTexture, passDestinationFramebuffer); + previousPassTexture = passDestinationTexture; + previousPassFramebuffer = passDestinationFramebuffer; + } + + sourceTexture = layerOutputTexture; + sourceFramebuffer = layerOutputFramebuffer; } return passes; diff --git a/apps/LoopThroughWithOpenGLCompositing/gl/pipeline/RenderPassDescriptor.h b/apps/LoopThroughWithOpenGLCompositing/gl/pipeline/RenderPassDescriptor.h index 3f53fc9..e682ca1 100644 --- a/apps/LoopThroughWithOpenGLCompositing/gl/pipeline/RenderPassDescriptor.h +++ b/apps/LoopThroughWithOpenGLCompositing/gl/pipeline/RenderPassDescriptor.h @@ -15,6 +15,7 @@ enum class RenderPassKind enum class RenderPassOutputTarget { + Temporary, LayerTemp, Composite }; @@ -29,6 +30,7 @@ struct RenderPassDescriptor std::string shaderId; GLuint sourceTexture = 0; GLuint sourceFramebuffer = 0; + GLuint destinationTexture = 0; GLuint destinationFramebuffer = 0; OpenGLRenderer::LayerProgram* layerProgram = nullptr; OpenGLRenderer::LayerProgram::PassProgram* passProgram = nullptr; diff --git a/apps/LoopThroughWithOpenGLCompositing/gl/renderer/OpenGLRenderer.cpp b/apps/LoopThroughWithOpenGLCompositing/gl/renderer/OpenGLRenderer.cpp index 08e2c26..3c2465f 100644 --- a/apps/LoopThroughWithOpenGLCompositing/gl/renderer/OpenGLRenderer.cpp +++ b/apps/LoopThroughWithOpenGLCompositing/gl/renderer/OpenGLRenderer.cpp @@ -80,6 +80,11 @@ void OpenGLRenderer::SetOutputPackShaderProgram(GLuint program, GLuint vertexSha mOutputPackFragmentShader = fragmentShader; } +bool OpenGLRenderer::ReserveTemporaryRenderTargets(std::size_t count, unsigned width, unsigned height, std::string& error) +{ + return mRenderTargets.ReserveTemporaryTargets(count, width, height, GL_RGBA16F, GL_RGBA, GL_FLOAT, error); +} + void OpenGLRenderer::ResizeView(int width, int height) { mViewWidth = width; diff --git a/apps/LoopThroughWithOpenGLCompositing/gl/renderer/OpenGLRenderer.h b/apps/LoopThroughWithOpenGLCompositing/gl/renderer/OpenGLRenderer.h index b4c9989..4712dc9 100644 --- a/apps/LoopThroughWithOpenGLCompositing/gl/renderer/OpenGLRenderer.h +++ b/apps/LoopThroughWithOpenGLCompositing/gl/renderer/OpenGLRenderer.h @@ -41,6 +41,8 @@ public: struct PassProgram { std::string passId; + std::vector inputNames; + std::string outputName; GLuint shaderTextureBase = 0; GLuint program = 0; GLuint vertexShader = 0; @@ -73,6 +75,9 @@ public: void ReplaceLayerPrograms(std::vector& newPrograms) { mLayerPrograms.swap(newPrograms); } std::vector& LayerPrograms() { return mLayerPrograms; } const std::vector& LayerPrograms() const { return mLayerPrograms; } + bool ReserveTemporaryRenderTargets(std::size_t count, unsigned width, unsigned height, std::string& error); + const RenderTarget& TemporaryRenderTarget(std::size_t index) const { return mRenderTargets.TemporaryTarget(index); } + std::size_t TemporaryRenderTargetCount() const { return mRenderTargets.TemporaryTargetCount(); } TemporalHistoryBuffers& TemporalHistory() { return mTemporalHistory; } const TemporalHistoryBuffers& TemporalHistory() const { return mTemporalHistory; } void SetDecodeShaderProgram(GLuint program, GLuint vertexShader, GLuint fragmentShader); diff --git a/apps/LoopThroughWithOpenGLCompositing/gl/renderer/RenderTargetPool.cpp b/apps/LoopThroughWithOpenGLCompositing/gl/renderer/RenderTargetPool.cpp index 012e39e..bbc3cea 100644 --- a/apps/LoopThroughWithOpenGLCompositing/gl/renderer/RenderTargetPool.cpp +++ b/apps/LoopThroughWithOpenGLCompositing/gl/renderer/RenderTargetPool.cpp @@ -69,11 +69,10 @@ bool RenderTargetPool::ReserveTemporaryTargets( GLenum pixelType, std::string& error) { - if (!mTemporaryTargets.empty()) - { - error = "Temporary render targets were already initialized."; - return false; - } + if (mTemporaryTargets.size() == count) + return true; + + DestroyTemporaryTargets(); mTemporaryTargets.resize(count); for (std::size_t index = 0; index < mTemporaryTargets.size(); ++index) @@ -105,6 +104,18 @@ bool RenderTargetPool::ReserveTemporaryTargets( return true; } +void RenderTargetPool::DestroyTemporaryTargets() +{ + for (RenderTarget& target : mTemporaryTargets) + { + if (target.framebuffer != 0) + glDeleteFramebuffers(1, &target.framebuffer); + if (target.texture != 0) + glDeleteTextures(1, &target.texture); + } + mTemporaryTargets.clear(); +} + void RenderTargetPool::Destroy() { for (RenderTarget& target : mTargets) @@ -116,14 +127,7 @@ void RenderTargetPool::Destroy() target = RenderTarget(); } - for (RenderTarget& target : mTemporaryTargets) - { - if (target.framebuffer != 0) - glDeleteFramebuffers(1, &target.framebuffer); - if (target.texture != 0) - glDeleteTextures(1, &target.texture); - } - mTemporaryTargets.clear(); + DestroyTemporaryTargets(); } const RenderTarget& RenderTargetPool::Target(RenderTargetId id) const diff --git a/apps/LoopThroughWithOpenGLCompositing/gl/renderer/RenderTargetPool.h b/apps/LoopThroughWithOpenGLCompositing/gl/renderer/RenderTargetPool.h index 6ca08d6..ef85d3c 100644 --- a/apps/LoopThroughWithOpenGLCompositing/gl/renderer/RenderTargetPool.h +++ b/apps/LoopThroughWithOpenGLCompositing/gl/renderer/RenderTargetPool.h @@ -47,6 +47,7 @@ public: GLenum pixelFormat, GLenum pixelType, std::string& error); + void DestroyTemporaryTargets(); void Destroy(); GLuint Texture(RenderTargetId id) const { return Target(id).texture; } diff --git a/apps/LoopThroughWithOpenGLCompositing/gl/shader/OpenGLShaderPrograms.cpp b/apps/LoopThroughWithOpenGLCompositing/gl/shader/OpenGLShaderPrograms.cpp index 3cf09eb..48dacb8 100644 --- a/apps/LoopThroughWithOpenGLCompositing/gl/shader/OpenGLShaderPrograms.cpp +++ b/apps/LoopThroughWithOpenGLCompositing/gl/shader/OpenGLShaderPrograms.cpp @@ -2,7 +2,6 @@ #include #include -#include #include namespace @@ -14,6 +13,18 @@ void CopyErrorMessage(const std::string& message, int errorMessageSize, char* er strncpy_s(errorMessage, errorMessageSize, message.c_str(), _TRUNCATE); } + +std::size_t RequiredTemporaryRenderTargets(const std::vector& layerPrograms) +{ + std::size_t requiredTargets = 0; + for (const OpenGLRenderer::LayerProgram& layerProgram : layerPrograms) + { + const std::size_t internalPasses = layerProgram.passes.size() > 0 ? layerProgram.passes.size() - 1 : 0; + if (internalPasses > requiredTargets) + requiredTargets = internalPasses; + } + return requiredTargets; +} } OpenGLShaderPrograms::OpenGLShaderPrograms(OpenGLRenderer& renderer, RuntimeHost& runtimeHost) : @@ -55,6 +66,15 @@ bool OpenGLShaderPrograms::CompileLayerPrograms(unsigned inputFrameWidth, unsign newPrograms.push_back(layerProgram); } + std::string targetError; + if (!mRenderer.ReserveTemporaryRenderTargets(RequiredTemporaryRenderTargets(newPrograms), inputFrameWidth, inputFrameHeight, targetError)) + { + for (LayerProgram& program : newPrograms) + DestroySingleLayerProgram(program); + CopyErrorMessage(targetError, errorMessageSize, errorMessage); + return false; + } + DestroyLayerPrograms(); mRenderer.ReplaceLayerPrograms(newPrograms); mCommittedLayerStates = layerStates; @@ -92,11 +112,7 @@ bool OpenGLShaderPrograms::CommitPreparedLayerPrograms(const PreparedShaderBuild for (const PreparedLayerShader& preparedLayer : preparedBuild.layers) { LayerProgram layerProgram; - std::vector> passSources; - passSources.reserve(preparedLayer.passes.size()); - for (const PreparedLayerShader::Pass& pass : preparedLayer.passes) - passSources.push_back(std::make_pair(pass.passId, pass.fragmentShaderSource)); - if (!mCompiler.CompilePreparedLayerProgram(preparedLayer.state, passSources, layerProgram, errorMessageSize, errorMessage)) + if (!mCompiler.CompilePreparedLayerProgram(preparedLayer.state, preparedLayer.passes, layerProgram, errorMessageSize, errorMessage)) { for (LayerProgram& program : newPrograms) DestroySingleLayerProgram(program); @@ -105,6 +121,15 @@ bool OpenGLShaderPrograms::CommitPreparedLayerPrograms(const PreparedShaderBuild newPrograms.push_back(layerProgram); } + std::string targetError; + if (!mRenderer.ReserveTemporaryRenderTargets(RequiredTemporaryRenderTargets(newPrograms), inputFrameWidth, inputFrameHeight, targetError)) + { + for (LayerProgram& program : newPrograms) + DestroySingleLayerProgram(program); + CopyErrorMessage(targetError, errorMessageSize, errorMessage); + return false; + } + DestroyLayerPrograms(); mRenderer.ReplaceLayerPrograms(newPrograms); mCommittedLayerStates = preparedBuild.layerStates; diff --git a/apps/LoopThroughWithOpenGLCompositing/gl/shader/ShaderBuildQueue.cpp b/apps/LoopThroughWithOpenGLCompositing/gl/shader/ShaderBuildQueue.cpp index e5a4e8a..801279a 100644 --- a/apps/LoopThroughWithOpenGLCompositing/gl/shader/ShaderBuildQueue.cpp +++ b/apps/LoopThroughWithOpenGLCompositing/gl/shader/ShaderBuildQueue.cpp @@ -120,15 +120,11 @@ PreparedShaderBuild ShaderBuildQueue::Build(uint64_t generation, unsigned output { PreparedLayerShader layer; layer.state = state; - std::vector> passSources; - if (!mRuntimeHost.BuildLayerPassFragmentShaderSources(state.layerId, passSources, build.message)) + if (!mRuntimeHost.BuildLayerPassFragmentShaderSources(state.layerId, layer.passes, build.message)) { build.succeeded = false; return build; } - layer.passes.reserve(passSources.size()); - for (auto& passSource : passSources) - layer.passes.push_back({ std::move(passSource.first), std::move(passSource.second) }); build.layers.push_back(std::move(layer)); } diff --git a/apps/LoopThroughWithOpenGLCompositing/gl/shader/ShaderBuildQueue.h b/apps/LoopThroughWithOpenGLCompositing/gl/shader/ShaderBuildQueue.h index 250a12d..513a2cd 100644 --- a/apps/LoopThroughWithOpenGLCompositing/gl/shader/ShaderBuildQueue.h +++ b/apps/LoopThroughWithOpenGLCompositing/gl/shader/ShaderBuildQueue.h @@ -13,14 +13,8 @@ class RuntimeHost; struct PreparedLayerShader { - struct Pass - { - std::string passId; - std::string fragmentShaderSource; - }; - RuntimeRenderState state; - std::vector passes; + std::vector passes; }; struct PreparedShaderBuild diff --git a/apps/LoopThroughWithOpenGLCompositing/gl/shader/ShaderProgramCompiler.cpp b/apps/LoopThroughWithOpenGLCompositing/gl/shader/ShaderProgramCompiler.cpp index 7910415..92798e9 100644 --- a/apps/LoopThroughWithOpenGLCompositing/gl/shader/ShaderProgramCompiler.cpp +++ b/apps/LoopThroughWithOpenGLCompositing/gl/shader/ShaderProgramCompiler.cpp @@ -28,7 +28,7 @@ ShaderProgramCompiler::ShaderProgramCompiler(OpenGLRenderer& renderer, RuntimeHo bool ShaderProgramCompiler::CompileLayerProgram(const RuntimeRenderState& state, LayerProgram& layerProgram, int errorMessageSize, char* errorMessage) { - std::vector> passSources; + std::vector passSources; std::string loadError; if (!mRuntimeHost.BuildLayerPassFragmentShaderSources(state.layerId, passSources, loadError)) @@ -42,12 +42,16 @@ bool ShaderProgramCompiler::CompileLayerProgram(const RuntimeRenderState& state, bool ShaderProgramCompiler::CompilePreparedLayerProgram(const RuntimeRenderState& state, const std::string& fragmentShaderSource, LayerProgram& layerProgram, int errorMessageSize, char* errorMessage) { - std::vector> passSources; - passSources.push_back(std::make_pair(std::string("main"), fragmentShaderSource)); + std::vector passSources; + ShaderPassBuildSource passSource; + passSource.passId = "main"; + passSource.fragmentShaderSource = fragmentShaderSource; + passSource.outputName = "layerOutput"; + passSources.push_back(std::move(passSource)); return CompilePreparedLayerProgram(state, passSources, layerProgram, errorMessageSize, errorMessage); } -bool ShaderProgramCompiler::CompilePreparedLayerProgram(const RuntimeRenderState& state, const std::vector>& passSources, LayerProgram& layerProgram, int errorMessageSize, char* errorMessage) +bool ShaderProgramCompiler::CompilePreparedLayerProgram(const RuntimeRenderState& state, const std::vector& passSources, LayerProgram& layerProgram, int errorMessageSize, char* errorMessage) { GLsizei errorBufferSize = 0; std::string loadError; @@ -61,7 +65,7 @@ bool ShaderProgramCompiler::CompilePreparedLayerProgram(const RuntimeRenderState { GLint compileResult = GL_FALSE; GLint linkResult = GL_FALSE; - const char* fragmentSource = passSource.second.c_str(); + const char* fragmentSource = passSource.fragmentShaderSource.c_str(); ScopedGlShader newVertexShader(glCreateShader(GL_VERTEX_SHADER)); glShaderSource(newVertexShader.get(), 1, (const GLchar**)&vertexSource, NULL); @@ -121,7 +125,9 @@ bool ShaderProgramCompiler::CompilePreparedLayerProgram(const RuntimeRenderState mTextureBindings.CreateTextBindings(state, textBindings); PassProgram passProgram; - passProgram.passId = passSource.first; + passProgram.passId = passSource.passId; + passProgram.inputNames = passSource.inputNames; + passProgram.outputName = passSource.outputName; passProgram.shaderTextureBase = mTextureBindings.ResolveShaderTextureBase(state, mRuntimeHost.GetMaxTemporalHistoryFrames()); passProgram.textureBindings.swap(textureBindings); passProgram.textBindings.swap(textBindings); diff --git a/apps/LoopThroughWithOpenGLCompositing/gl/shader/ShaderProgramCompiler.h b/apps/LoopThroughWithOpenGLCompositing/gl/shader/ShaderProgramCompiler.h index 68fdf6c..40330ea 100644 --- a/apps/LoopThroughWithOpenGLCompositing/gl/shader/ShaderProgramCompiler.h +++ b/apps/LoopThroughWithOpenGLCompositing/gl/shader/ShaderProgramCompiler.h @@ -5,7 +5,6 @@ #include "ShaderTextureBindings.h" #include -#include #include class ShaderProgramCompiler @@ -18,7 +17,7 @@ public: bool CompileLayerProgram(const RuntimeRenderState& state, LayerProgram& layerProgram, int errorMessageSize, char* errorMessage); bool CompilePreparedLayerProgram(const RuntimeRenderState& state, const std::string& fragmentShaderSource, LayerProgram& layerProgram, int errorMessageSize, char* errorMessage); - bool CompilePreparedLayerProgram(const RuntimeRenderState& state, const std::vector>& passSources, LayerProgram& layerProgram, int errorMessageSize, char* errorMessage); + bool CompilePreparedLayerProgram(const RuntimeRenderState& state, const std::vector& passSources, LayerProgram& layerProgram, int errorMessageSize, char* errorMessage); bool CompileDecodeShader(int errorMessageSize, char* errorMessage); bool CompileOutputPackShader(int errorMessageSize, char* errorMessage); diff --git a/apps/LoopThroughWithOpenGLCompositing/runtime/RuntimeHost.cpp b/apps/LoopThroughWithOpenGLCompositing/runtime/RuntimeHost.cpp index 6621db4..18f367c 100644 --- a/apps/LoopThroughWithOpenGLCompositing/runtime/RuntimeHost.cpp +++ b/apps/LoopThroughWithOpenGLCompositing/runtime/RuntimeHost.cpp @@ -1302,7 +1302,7 @@ bool RuntimeHost::TryAdvanceFrame() bool RuntimeHost::BuildLayerFragmentShaderSource(const std::string& layerId, std::string& fragmentShaderSource, std::string& error) { - std::vector> passSources; + std::vector passSources; if (!BuildLayerPassFragmentShaderSources(layerId, passSources, error)) return false; if (passSources.empty()) @@ -1310,11 +1310,11 @@ bool RuntimeHost::BuildLayerFragmentShaderSource(const std::string& layerId, std error = "Shader layer produced no compiled passes: " + layerId; return false; } - fragmentShaderSource = passSources.front().second; + fragmentShaderSource = passSources.front().fragmentShaderSource; return true; } -bool RuntimeHost::BuildLayerPassFragmentShaderSources(const std::string& layerId, std::vector>& passSources, std::string& error) +bool RuntimeHost::BuildLayerPassFragmentShaderSources(const std::string& layerId, std::vector& passSources, std::string& error) { try { @@ -1342,10 +1342,13 @@ bool RuntimeHost::BuildLayerPassFragmentShaderSources(const std::string& layerId passSources.reserve(shaderPackage.passes.size()); for (const ShaderPassDefinition& pass : shaderPackage.passes) { - std::string fragmentShaderSource; - if (!compiler.BuildPassFragmentShaderSource(shaderPackage, pass, fragmentShaderSource, error)) + ShaderPassBuildSource passSource; + passSource.passId = pass.id; + passSource.inputNames = pass.inputNames; + passSource.outputName = pass.outputName; + if (!compiler.BuildPassFragmentShaderSource(shaderPackage, pass, passSource.fragmentShaderSource, error)) return false; - passSources.push_back(std::make_pair(pass.id, std::move(fragmentShaderSource))); + passSources.push_back(std::move(passSource)); } return true; } diff --git a/apps/LoopThroughWithOpenGLCompositing/runtime/RuntimeHost.h b/apps/LoopThroughWithOpenGLCompositing/runtime/RuntimeHost.h index 0f39157..a9c6dbf 100644 --- a/apps/LoopThroughWithOpenGLCompositing/runtime/RuntimeHost.h +++ b/apps/LoopThroughWithOpenGLCompositing/runtime/RuntimeHost.h @@ -52,7 +52,7 @@ public: bool TryAdvanceFrame(); bool BuildLayerFragmentShaderSource(const std::string& layerId, std::string& fragmentShaderSource, std::string& error); - bool BuildLayerPassFragmentShaderSources(const std::string& layerId, std::vector>& passSources, std::string& error); + bool BuildLayerPassFragmentShaderSources(const std::string& layerId, std::vector& passSources, std::string& error); std::vector GetLayerRenderStates(unsigned outputWidth, unsigned outputHeight) const; bool TryGetLayerRenderStates(unsigned outputWidth, unsigned outputHeight, std::vector& states) const; void RefreshDynamicRenderStateFields(std::vector& states) const; diff --git a/apps/LoopThroughWithOpenGLCompositing/shader/ShaderTypes.h b/apps/LoopThroughWithOpenGLCompositing/shader/ShaderTypes.h index 62ffa90..ab39cb9 100644 --- a/apps/LoopThroughWithOpenGLCompositing/shader/ShaderTypes.h +++ b/apps/LoopThroughWithOpenGLCompositing/shader/ShaderTypes.h @@ -86,6 +86,14 @@ struct ShaderPassDefinition std::string outputName; }; +struct ShaderPassBuildSource +{ + std::string passId; + std::string fragmentShaderSource; + std::vector inputNames; + std::string outputName; +}; + struct ShaderPackage { std::string id;