data storage
This commit is contained in:
@@ -328,15 +328,6 @@ bool OpenGLComposite::InitOpenGLState()
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mShaderPrograms->CompileLayerPrograms(mVideoIO->InputFrameWidth(), mVideoIO->InputFrameHeight(), sizeof(compilerErrorMessage), compilerErrorMessage))
|
||||
{
|
||||
MessageBoxA(NULL, compilerErrorMessage, "OpenGL shader failed to load or compile", MB_OK);
|
||||
return false;
|
||||
}
|
||||
mCachedLayerRenderStates = mShaderPrograms->CommittedLayerStates();
|
||||
mUseCommittedLayerStates = false;
|
||||
mShaderPrograms->ResetTemporalHistoryState();
|
||||
|
||||
std::string rendererError;
|
||||
if (!mRenderer->InitializeResources(
|
||||
mVideoIO->InputFrameWidth(),
|
||||
@@ -351,6 +342,17 @@ bool OpenGLComposite::InitOpenGLState()
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mShaderPrograms->CompileLayerPrograms(mVideoIO->InputFrameWidth(), mVideoIO->InputFrameHeight(), sizeof(compilerErrorMessage), compilerErrorMessage))
|
||||
{
|
||||
MessageBoxA(NULL, compilerErrorMessage, "OpenGL shader failed to load or compile", MB_OK);
|
||||
return false;
|
||||
}
|
||||
mCachedLayerRenderStates = mShaderPrograms->CommittedLayerStates();
|
||||
mUseCommittedLayerStates = false;
|
||||
|
||||
mShaderPrograms->ResetTemporalHistoryState();
|
||||
mShaderPrograms->ResetShaderFeedbackState();
|
||||
|
||||
broadcastRuntimeState();
|
||||
mRuntimeServices->BeginPolling(*mRuntimeHost);
|
||||
return true;
|
||||
@@ -647,8 +649,8 @@ void OpenGLComposite::renderEffect()
|
||||
[this](const RuntimeRenderState& state, LayerProgram::TextBinding& textBinding, std::string& error) {
|
||||
return mShaderPrograms->UpdateTextBindingTexture(state, textBinding, error);
|
||||
},
|
||||
[this](const RuntimeRenderState& state, unsigned availableSourceHistoryLength, unsigned availableTemporalHistoryLength) {
|
||||
return mShaderPrograms->UpdateGlobalParamsBuffer(state, availableSourceHistoryLength, availableTemporalHistoryLength);
|
||||
[this](const RuntimeRenderState& state, unsigned availableSourceHistoryLength, unsigned availableTemporalHistoryLength, bool feedbackAvailable) {
|
||||
return mShaderPrograms->UpdateGlobalParamsBuffer(state, availableSourceHistoryLength, availableTemporalHistoryLength, feedbackAvailable);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -749,6 +751,7 @@ bool OpenGLComposite::ProcessRuntimePollResults()
|
||||
mUseCommittedLayerStates = false;
|
||||
mCachedLayerRenderStates = mShaderPrograms->CommittedLayerStates();
|
||||
mShaderPrograms->ResetTemporalHistoryState();
|
||||
mShaderPrograms->ResetShaderFeedbackState();
|
||||
broadcastRuntimeState();
|
||||
return true;
|
||||
}
|
||||
@@ -779,6 +782,7 @@ void OpenGLComposite::broadcastRuntimeState()
|
||||
void OpenGLComposite::resetTemporalHistoryState()
|
||||
{
|
||||
mShaderPrograms->ResetTemporalHistoryState();
|
||||
mShaderPrograms->ResetShaderFeedbackState();
|
||||
}
|
||||
|
||||
bool OpenGLComposite::CheckOpenGLExtensions()
|
||||
|
||||
@@ -59,6 +59,7 @@ void OpenGLRenderPass::Render(
|
||||
}
|
||||
|
||||
mRenderer.TemporalHistory().PushSourceFramebuffer(mRenderer.DecodeFramebuffer(), inputFrameWidth, inputFrameHeight);
|
||||
mRenderer.FeedbackBuffers().FinalizeFrame();
|
||||
}
|
||||
|
||||
void OpenGLRenderPass::RenderDecodePass(unsigned inputFrameWidth, unsigned inputFrameHeight, unsigned captureTextureWidth, VideoIOPixelFormat inputPixelFormat)
|
||||
@@ -195,6 +196,7 @@ std::vector<RenderPassDescriptor> OpenGLRenderPass::BuildLayerPassDescriptors(
|
||||
pass.passProgram = &passProgram;
|
||||
pass.layerState = &state;
|
||||
pass.capturePreLayerHistory = passIndex == 0 && state.temporalHistorySource == TemporalHistorySource::PreLayerInput;
|
||||
pass.captureFeedbackWrite = state.feedback.enabled && passProgram.passId == state.feedback.writePassId;
|
||||
passes.push_back(pass);
|
||||
|
||||
// A later pass can reference either the explicit output name or the
|
||||
@@ -236,6 +238,8 @@ void OpenGLRenderPass::RenderLayerPass(
|
||||
|
||||
if (pass.capturePreLayerHistory)
|
||||
mRenderer.TemporalHistory().PushPreLayerFramebuffer(pass.layerId, pass.sourceFramebuffer, inputFrameWidth, inputFrameHeight);
|
||||
if (pass.captureFeedbackWrite)
|
||||
mRenderer.FeedbackBuffers().CaptureFeedbackFramebuffer(pass.layerId, pass.destinationFramebuffer, inputFrameWidth, inputFrameHeight);
|
||||
}
|
||||
|
||||
void OpenGLRenderPass::RenderShaderProgram(
|
||||
@@ -261,14 +265,19 @@ void OpenGLRenderPass::RenderShaderProgram(
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
const std::vector<GLuint> sourceHistoryTextures = mRenderer.TemporalHistory().ResolveSourceHistoryTextures(sourceTexture, state.isTemporal ? historyCap : 0);
|
||||
const std::vector<GLuint> temporalHistoryTextures = mRenderer.TemporalHistory().ResolveTemporalHistoryTextures(state, sourceTexture, state.isTemporal ? historyCap : 0);
|
||||
const GLuint feedbackTexture = mRenderer.FeedbackBuffers().ResolveReadTexture(state);
|
||||
const ShaderTextureBindings::RuntimeTextureBindingPlan texturePlan =
|
||||
mTextureBindings.BuildLayerRuntimeBindingPlan(passProgram, sourceTexture, sourceHistoryTextures, temporalHistoryTextures);
|
||||
mTextureBindings.BuildLayerRuntimeBindingPlan(passProgram, sourceTexture, state, feedbackTexture, sourceHistoryTextures, temporalHistoryTextures);
|
||||
mTextureBindings.BindRuntimeTexturePlan(texturePlan);
|
||||
glBindVertexArray(mRenderer.FullscreenVertexArray());
|
||||
glUseProgram(passProgram.program);
|
||||
// The UBO is shared by every pass in a layer; texture routing is what
|
||||
// changes from pass to pass.
|
||||
updateGlobalParams(state, mRenderer.TemporalHistory().SourceAvailableCount(), mRenderer.TemporalHistory().AvailableCountForLayer(state.layerId));
|
||||
updateGlobalParams(
|
||||
state,
|
||||
mRenderer.TemporalHistory().SourceAvailableCount(),
|
||||
mRenderer.TemporalHistory().AvailableCountForLayer(state.layerId),
|
||||
mRenderer.FeedbackBuffers().FeedbackAvailable(state));
|
||||
glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||
glUseProgram(0);
|
||||
glBindVertexArray(0);
|
||||
|
||||
@@ -16,7 +16,7 @@ public:
|
||||
using LayerProgram = OpenGLRenderer::LayerProgram;
|
||||
using PassProgram = OpenGLRenderer::LayerProgram::PassProgram;
|
||||
using TextBindingUpdater = std::function<bool(const RuntimeRenderState&, LayerProgram::TextBinding&, std::string&)>;
|
||||
using GlobalParamsUpdater = std::function<bool(const RuntimeRenderState&, unsigned, unsigned)>;
|
||||
using GlobalParamsUpdater = std::function<bool(const RuntimeRenderState&, unsigned, unsigned, bool)>;
|
||||
|
||||
explicit OpenGLRenderPass(OpenGLRenderer& renderer);
|
||||
|
||||
|
||||
@@ -36,4 +36,5 @@ struct RenderPassDescriptor
|
||||
OpenGLRenderer::LayerProgram::PassProgram* passProgram = nullptr;
|
||||
const RuntimeRenderState* layerState = nullptr;
|
||||
bool capturePreLayerHistory = false;
|
||||
bool captureFeedbackWrite = false;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,202 @@
|
||||
#include "ShaderFeedbackBuffers.h"
|
||||
|
||||
#include <set>
|
||||
|
||||
namespace
|
||||
{
|
||||
void ConfigureFeedbackTexture(unsigned frameWidth, unsigned frameHeight)
|
||||
{
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, frameWidth, frameHeight, 0, GL_RGBA, GL_FLOAT, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
bool ShaderFeedbackBuffers::EnsureResources(const std::vector<RuntimeRenderState>& layerStates, unsigned frameWidth, unsigned frameHeight, std::string& error)
|
||||
{
|
||||
if (!EnsureZeroTexture())
|
||||
{
|
||||
error = "Failed to initialize shader feedback fallback texture.";
|
||||
return false;
|
||||
}
|
||||
|
||||
std::set<std::string> requiredLayerIds;
|
||||
for (const RuntimeRenderState& state : layerStates)
|
||||
{
|
||||
if (!state.feedback.enabled)
|
||||
continue;
|
||||
|
||||
requiredLayerIds.insert(state.layerId);
|
||||
auto surfaceIt = mSurfacesByLayerId.find(state.layerId);
|
||||
if (surfaceIt == mSurfacesByLayerId.end() ||
|
||||
surfaceIt->second.width != frameWidth ||
|
||||
surfaceIt->second.height != frameHeight)
|
||||
{
|
||||
Surface replacement;
|
||||
if (!CreateSurface(replacement, frameWidth, frameHeight, error))
|
||||
return false;
|
||||
mSurfacesByLayerId[state.layerId] = std::move(replacement);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto it = mSurfacesByLayerId.begin(); it != mSurfacesByLayerId.end();)
|
||||
{
|
||||
if (requiredLayerIds.find(it->first) == requiredLayerIds.end())
|
||||
{
|
||||
DestroySurface(it->second);
|
||||
it = mSurfacesByLayerId.erase(it);
|
||||
}
|
||||
else
|
||||
{
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ShaderFeedbackBuffers::DestroyResources()
|
||||
{
|
||||
for (auto& entry : mSurfacesByLayerId)
|
||||
DestroySurface(entry.second);
|
||||
mSurfacesByLayerId.clear();
|
||||
|
||||
if (mZeroTexture != 0)
|
||||
{
|
||||
glDeleteTextures(1, &mZeroTexture);
|
||||
mZeroTexture = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void ShaderFeedbackBuffers::ResetState()
|
||||
{
|
||||
for (auto& entry : mSurfacesByLayerId)
|
||||
ClearSurfaceState(entry.second);
|
||||
}
|
||||
|
||||
GLuint ShaderFeedbackBuffers::ResolveReadTexture(const RuntimeRenderState& state) const
|
||||
{
|
||||
if (!state.feedback.enabled)
|
||||
return mZeroTexture;
|
||||
|
||||
auto surfaceIt = mSurfacesByLayerId.find(state.layerId);
|
||||
if (surfaceIt == mSurfacesByLayerId.end() || !surfaceIt->second.hasData)
|
||||
return mZeroTexture;
|
||||
|
||||
return surfaceIt->second.slots[surfaceIt->second.readIndex].texture != 0
|
||||
? surfaceIt->second.slots[surfaceIt->second.readIndex].texture
|
||||
: mZeroTexture;
|
||||
}
|
||||
|
||||
bool ShaderFeedbackBuffers::FeedbackAvailable(const RuntimeRenderState& state) const
|
||||
{
|
||||
if (!state.feedback.enabled)
|
||||
return false;
|
||||
|
||||
auto surfaceIt = mSurfacesByLayerId.find(state.layerId);
|
||||
return surfaceIt != mSurfacesByLayerId.end() && surfaceIt->second.hasData;
|
||||
}
|
||||
|
||||
void ShaderFeedbackBuffers::CaptureFeedbackFramebuffer(const std::string& layerId, GLuint sourceFramebuffer, unsigned frameWidth, unsigned frameHeight)
|
||||
{
|
||||
auto surfaceIt = mSurfacesByLayerId.find(layerId);
|
||||
if (surfaceIt == mSurfacesByLayerId.end())
|
||||
return;
|
||||
|
||||
Surface& surface = surfaceIt->second;
|
||||
const unsigned writeIndex = 1u - surface.readIndex;
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, sourceFramebuffer);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, surface.slots[writeIndex].framebuffer);
|
||||
glBlitFramebuffer(0, 0, frameWidth, frameHeight, 0, 0, frameWidth, frameHeight, GL_COLOR_BUFFER_BIT, GL_LINEAR);
|
||||
surface.pendingWrite = true;
|
||||
}
|
||||
|
||||
void ShaderFeedbackBuffers::FinalizeFrame()
|
||||
{
|
||||
for (auto& entry : mSurfacesByLayerId)
|
||||
{
|
||||
Surface& surface = entry.second;
|
||||
if (!surface.pendingWrite)
|
||||
continue;
|
||||
|
||||
surface.readIndex = 1u - surface.readIndex;
|
||||
surface.hasData = true;
|
||||
surface.pendingWrite = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool ShaderFeedbackBuffers::EnsureZeroTexture()
|
||||
{
|
||||
if (mZeroTexture != 0)
|
||||
return true;
|
||||
|
||||
glGenTextures(1, &mZeroTexture);
|
||||
glBindTexture(GL_TEXTURE_2D, mZeroTexture);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
const float zeroPixel[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, 1, 1, 0, GL_RGBA, GL_FLOAT, zeroPixel);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
return mZeroTexture != 0;
|
||||
}
|
||||
|
||||
bool ShaderFeedbackBuffers::CreateSurface(Surface& surface, unsigned frameWidth, unsigned frameHeight, std::string& error)
|
||||
{
|
||||
DestroySurface(surface);
|
||||
|
||||
surface.width = frameWidth;
|
||||
surface.height = frameHeight;
|
||||
for (Slot& slot : surface.slots)
|
||||
{
|
||||
glGenTextures(1, &slot.texture);
|
||||
glBindTexture(GL_TEXTURE_2D, slot.texture);
|
||||
ConfigureFeedbackTexture(frameWidth, frameHeight);
|
||||
|
||||
glGenFramebuffers(1, &slot.framebuffer);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, slot.framebuffer);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, slot.texture, 0);
|
||||
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
|
||||
{
|
||||
error = "Failed to initialize a shader feedback framebuffer.";
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
DestroySurface(surface);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
ClearSurfaceState(surface);
|
||||
return true;
|
||||
}
|
||||
|
||||
void ShaderFeedbackBuffers::DestroySurface(Surface& surface)
|
||||
{
|
||||
for (Slot& slot : surface.slots)
|
||||
{
|
||||
if (slot.framebuffer != 0)
|
||||
glDeleteFramebuffers(1, &slot.framebuffer);
|
||||
if (slot.texture != 0)
|
||||
glDeleteTextures(1, &slot.texture);
|
||||
slot.framebuffer = 0;
|
||||
slot.texture = 0;
|
||||
}
|
||||
|
||||
surface.width = 0;
|
||||
surface.height = 0;
|
||||
surface.readIndex = 0;
|
||||
surface.hasData = false;
|
||||
surface.pendingWrite = false;
|
||||
}
|
||||
|
||||
void ShaderFeedbackBuffers::ClearSurfaceState(Surface& surface)
|
||||
{
|
||||
surface.readIndex = 0;
|
||||
surface.hasData = false;
|
||||
surface.pendingWrite = false;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
|
||||
#include "GLExtensions.h"
|
||||
#include "ShaderTypes.h"
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class ShaderFeedbackBuffers
|
||||
{
|
||||
public:
|
||||
struct Slot
|
||||
{
|
||||
GLuint texture = 0;
|
||||
GLuint framebuffer = 0;
|
||||
};
|
||||
|
||||
struct Surface
|
||||
{
|
||||
Slot slots[2];
|
||||
unsigned width = 0;
|
||||
unsigned height = 0;
|
||||
unsigned readIndex = 0;
|
||||
bool hasData = false;
|
||||
bool pendingWrite = false;
|
||||
};
|
||||
|
||||
bool EnsureResources(const std::vector<RuntimeRenderState>& layerStates, unsigned frameWidth, unsigned frameHeight, std::string& error);
|
||||
void DestroyResources();
|
||||
void ResetState();
|
||||
GLuint ResolveReadTexture(const RuntimeRenderState& state) const;
|
||||
bool FeedbackAvailable(const RuntimeRenderState& state) const;
|
||||
void CaptureFeedbackFramebuffer(const std::string& layerId, GLuint sourceFramebuffer, unsigned frameWidth, unsigned frameHeight);
|
||||
void FinalizeFrame();
|
||||
|
||||
private:
|
||||
bool EnsureZeroTexture();
|
||||
bool CreateSurface(Surface& surface, unsigned frameWidth, unsigned frameHeight, std::string& error);
|
||||
void DestroySurface(Surface& surface);
|
||||
void ClearSurfaceState(Surface& surface);
|
||||
|
||||
private:
|
||||
std::map<std::string, Surface> mSurfacesByLayerId;
|
||||
GLuint mZeroTexture = 0;
|
||||
};
|
||||
@@ -19,7 +19,8 @@ bool TemporalHistoryBuffers::ValidateTextureUnitBudget(const std::vector<Runtime
|
||||
++textTextureCount;
|
||||
}
|
||||
const unsigned totalShaderTextures = static_cast<unsigned>(state.textureAssets.size()) + textTextureCount;
|
||||
const unsigned layerRequiredUnits = kSourceHistoryTextureUnitBase + (state.isTemporal ? historyCap + historyCap : 0u) + totalShaderTextures;
|
||||
const unsigned feedbackTextureCount = state.feedback.enabled ? 1u : 0u;
|
||||
const unsigned layerRequiredUnits = kSourceHistoryTextureUnitBase + (state.isTemporal ? historyCap + historyCap : 0u) + feedbackTextureCount + totalShaderTextures;
|
||||
if (layerRequiredUnits > requiredUnits)
|
||||
requiredUnits = layerRequiredUnits;
|
||||
}
|
||||
|
||||
@@ -63,6 +63,7 @@ bool OpenGLRenderer::InitializeResources(unsigned inputFrameWidth, unsigned inpu
|
||||
glBindBufferBase(GL_UNIFORM_BUFFER, kGlobalParamsBindingPoint, mGlobalParamsUBO);
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, 0);
|
||||
|
||||
mResourcesInitialized = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -157,8 +158,10 @@ void OpenGLRenderer::DestroyResources()
|
||||
mCaptureTexture = 0;
|
||||
mTextureUploadBuffer = 0;
|
||||
mGlobalParamsUBOSize = 0;
|
||||
mResourcesInitialized = false;
|
||||
|
||||
mTemporalHistory.DestroyResources();
|
||||
mFeedbackBuffers.DestroyResources();
|
||||
DestroyLayerPrograms();
|
||||
DestroyDecodeShaderProgram();
|
||||
DestroyOutputPackShaderProgram();
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "GLExtensions.h"
|
||||
#include "RenderTargetPool.h"
|
||||
#include "ShaderFeedbackBuffers.h"
|
||||
#include "ShaderTypes.h"
|
||||
#include "TemporalHistoryBuffers.h"
|
||||
|
||||
@@ -78,6 +79,7 @@ public:
|
||||
GLint OutputPackFormatLocation() const { return mOutputPackFormatLocation; }
|
||||
GLsizeiptr GlobalParamsUBOSize() const { return mGlobalParamsUBOSize; }
|
||||
void SetGlobalParamsUBOSize(GLsizeiptr size) { mGlobalParamsUBOSize = size; }
|
||||
bool ResourcesInitialized() const { return mResourcesInitialized; }
|
||||
void ReplaceLayerPrograms(std::vector<LayerProgram>& newPrograms) { mLayerPrograms.swap(newPrograms); }
|
||||
std::vector<LayerProgram>& LayerPrograms() { return mLayerPrograms; }
|
||||
const std::vector<LayerProgram>& LayerPrograms() const { return mLayerPrograms; }
|
||||
@@ -86,6 +88,8 @@ public:
|
||||
std::size_t TemporaryRenderTargetCount() const { return mRenderTargets.TemporaryTargetCount(); }
|
||||
TemporalHistoryBuffers& TemporalHistory() { return mTemporalHistory; }
|
||||
const TemporalHistoryBuffers& TemporalHistory() const { return mTemporalHistory; }
|
||||
ShaderFeedbackBuffers& FeedbackBuffers() { return mFeedbackBuffers; }
|
||||
const ShaderFeedbackBuffers& FeedbackBuffers() const { return mFeedbackBuffers; }
|
||||
void SetDecodeShaderProgram(GLuint program, GLuint vertexShader, GLuint fragmentShader);
|
||||
void SetOutputPackShaderProgram(GLuint program, GLuint vertexShader, GLuint fragmentShader);
|
||||
bool InitializeResources(unsigned inputFrameWidth, unsigned inputFrameHeight, unsigned captureTextureWidth, unsigned outputFrameWidth, unsigned outputFrameHeight, unsigned outputPackTextureWidth, std::string& error);
|
||||
@@ -117,9 +121,11 @@ private:
|
||||
GLint mOutputPackActiveWordsLocation = -1;
|
||||
GLint mOutputPackFormatLocation = -1;
|
||||
GLsizeiptr mGlobalParamsUBOSize = 0;
|
||||
bool mResourcesInitialized = false;
|
||||
int mViewWidth = 0;
|
||||
int mViewHeight = 0;
|
||||
std::vector<LayerProgram> mLayerPrograms;
|
||||
RenderTargetPool mRenderTargets;
|
||||
TemporalHistoryBuffers mTemporalHistory;
|
||||
ShaderFeedbackBuffers mFeedbackBuffers;
|
||||
};
|
||||
|
||||
@@ -10,7 +10,7 @@ GlobalParamsBuffer::GlobalParamsBuffer(OpenGLRenderer& renderer) :
|
||||
{
|
||||
}
|
||||
|
||||
bool GlobalParamsBuffer::Update(const RuntimeRenderState& state, unsigned availableSourceHistoryLength, unsigned availableTemporalHistoryLength)
|
||||
bool GlobalParamsBuffer::Update(const RuntimeRenderState& state, unsigned availableSourceHistoryLength, unsigned availableTemporalHistoryLength, bool feedbackAvailable)
|
||||
{
|
||||
std::vector<unsigned char>& buffer = mScratchBuffer;
|
||||
buffer.clear();
|
||||
@@ -33,6 +33,7 @@ bool GlobalParamsBuffer::Update(const RuntimeRenderState& state, unsigned availa
|
||||
: 0u;
|
||||
AppendStd140Int(buffer, static_cast<int>(effectiveSourceHistoryLength));
|
||||
AppendStd140Int(buffer, static_cast<int>(effectiveTemporalHistoryLength));
|
||||
AppendStd140Int(buffer, feedbackAvailable ? 1 : 0);
|
||||
|
||||
for (const ShaderParameterDefinition& definition : state.parameterDefinitions)
|
||||
{
|
||||
|
||||
@@ -10,7 +10,7 @@ class GlobalParamsBuffer
|
||||
public:
|
||||
explicit GlobalParamsBuffer(OpenGLRenderer& renderer);
|
||||
|
||||
bool Update(const RuntimeRenderState& state, unsigned availableSourceHistoryLength, unsigned availableTemporalHistoryLength);
|
||||
bool Update(const RuntimeRenderState& state, unsigned availableSourceHistoryLength, unsigned availableTemporalHistoryLength, bool feedbackAvailable);
|
||||
|
||||
private:
|
||||
OpenGLRenderer& mRenderer;
|
||||
|
||||
@@ -52,6 +52,12 @@ bool OpenGLShaderPrograms::CompileLayerPrograms(unsigned inputFrameWidth, unsign
|
||||
CopyErrorMessage(temporalError, errorMessageSize, errorMessage);
|
||||
return false;
|
||||
}
|
||||
if (mRenderer.ResourcesInitialized() &&
|
||||
!mRenderer.FeedbackBuffers().EnsureResources(layerStates, inputFrameWidth, inputFrameHeight, temporalError))
|
||||
{
|
||||
CopyErrorMessage(temporalError, errorMessageSize, errorMessage);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Initial startup still compiles synchronously; auto-reload uses the build
|
||||
// queue so Slang/file work stays off the playback path.
|
||||
@@ -109,6 +115,12 @@ bool OpenGLShaderPrograms::CommitPreparedLayerPrograms(const PreparedShaderBuild
|
||||
CopyErrorMessage(temporalError, errorMessageSize, errorMessage);
|
||||
return false;
|
||||
}
|
||||
if (mRenderer.ResourcesInitialized() &&
|
||||
!mRenderer.FeedbackBuffers().EnsureResources(preparedBuild.layerStates, inputFrameWidth, inputFrameHeight, temporalError))
|
||||
{
|
||||
CopyErrorMessage(temporalError, errorMessageSize, errorMessage);
|
||||
return false;
|
||||
}
|
||||
|
||||
// The prepared build already contains GLSL text for each pass. This commit
|
||||
// step performs the short GL work on the render thread.
|
||||
@@ -176,12 +188,17 @@ void OpenGLShaderPrograms::ResetTemporalHistoryState()
|
||||
mRenderer.TemporalHistory().ResetState();
|
||||
}
|
||||
|
||||
void OpenGLShaderPrograms::ResetShaderFeedbackState()
|
||||
{
|
||||
mRenderer.FeedbackBuffers().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)
|
||||
bool OpenGLShaderPrograms::UpdateGlobalParamsBuffer(const RuntimeRenderState& state, unsigned availableSourceHistoryLength, unsigned availableTemporalHistoryLength, bool feedbackAvailable)
|
||||
{
|
||||
return mGlobalParamsBuffer.Update(state, availableSourceHistoryLength, availableTemporalHistoryLength);
|
||||
return mGlobalParamsBuffer.Update(state, availableSourceHistoryLength, availableTemporalHistoryLength, feedbackAvailable);
|
||||
}
|
||||
|
||||
@@ -25,9 +25,10 @@ public:
|
||||
void DestroySingleLayerProgram(LayerProgram& layerProgram);
|
||||
void DestroyDecodeShaderProgram();
|
||||
void ResetTemporalHistoryState();
|
||||
void ResetShaderFeedbackState();
|
||||
const std::vector<RuntimeRenderState>& CommittedLayerStates() const { return mCommittedLayerStates; }
|
||||
bool UpdateTextBindingTexture(const RuntimeRenderState& state, LayerProgram::TextBinding& textBinding, std::string& error);
|
||||
bool UpdateGlobalParamsBuffer(const RuntimeRenderState& state, unsigned availableSourceHistoryLength, unsigned availableTemporalHistoryLength);
|
||||
bool UpdateGlobalParamsBuffer(const RuntimeRenderState& state, unsigned availableSourceHistoryLength, unsigned availableTemporalHistoryLength, bool feedbackAvailable);
|
||||
|
||||
private:
|
||||
OpenGLRenderer& mRenderer;
|
||||
|
||||
@@ -103,11 +103,16 @@ GLint ShaderTextureBindings::FindSamplerUniformLocation(GLuint program, const st
|
||||
return glGetUniformLocation(program, (samplerName + "_0").c_str());
|
||||
}
|
||||
|
||||
GLuint ShaderTextureBindings::ResolveShaderTextureBase(const RuntimeRenderState& state, unsigned historyCap) const
|
||||
GLuint ShaderTextureBindings::ResolveFeedbackTextureUnit(const RuntimeRenderState& state, unsigned historyCap) const
|
||||
{
|
||||
return state.isTemporal ? kSourceHistoryTextureUnitBase + historyCap + historyCap : kSourceHistoryTextureUnitBase;
|
||||
}
|
||||
|
||||
GLuint ShaderTextureBindings::ResolveShaderTextureBase(const RuntimeRenderState& state, unsigned historyCap) const
|
||||
{
|
||||
return ResolveFeedbackTextureUnit(state, historyCap) + (state.feedback.enabled ? 1u : 0u);
|
||||
}
|
||||
|
||||
void ShaderTextureBindings::AssignLayerSamplerUniforms(GLuint program, const RuntimeRenderState& state, const PassProgram& passProgram, unsigned historyCap) const
|
||||
{
|
||||
const GLuint shaderTextureBase = ResolveShaderTextureBase(state, historyCap);
|
||||
@@ -129,6 +134,13 @@ void ShaderTextureBindings::AssignLayerSamplerUniforms(GLuint program, const Run
|
||||
glUniform1i(temporalSamplerLocation, static_cast<GLint>(kSourceHistoryTextureUnitBase + historyCap + index));
|
||||
}
|
||||
|
||||
if (state.feedback.enabled)
|
||||
{
|
||||
const GLint feedbackSamplerLocation = glGetUniformLocation(program, "gFeedbackState");
|
||||
if (feedbackSamplerLocation >= 0)
|
||||
glUniform1i(feedbackSamplerLocation, static_cast<GLint>(ResolveFeedbackTextureUnit(state, historyCap)));
|
||||
}
|
||||
|
||||
for (std::size_t index = 0; index < passProgram.textureBindings.size(); ++index)
|
||||
{
|
||||
const GLint textureSamplerLocation = FindSamplerUniformLocation(program, passProgram.textureBindings[index].samplerName);
|
||||
@@ -148,6 +160,8 @@ void ShaderTextureBindings::AssignLayerSamplerUniforms(GLuint program, const Run
|
||||
ShaderTextureBindings::RuntimeTextureBindingPlan ShaderTextureBindings::BuildLayerRuntimeBindingPlan(
|
||||
const PassProgram& passProgram,
|
||||
GLuint layerInputTexture,
|
||||
const RuntimeRenderState& state,
|
||||
GLuint feedbackTexture,
|
||||
const std::vector<GLuint>& sourceHistoryTextures,
|
||||
const std::vector<GLuint>& temporalHistoryTextures) const
|
||||
{
|
||||
@@ -175,7 +189,20 @@ ShaderTextureBindings::RuntimeTextureBindingPlan ShaderTextureBindings::BuildLay
|
||||
});
|
||||
}
|
||||
|
||||
const GLuint shaderTextureBase = passProgram.shaderTextureBase != 0 ? passProgram.shaderTextureBase : kSourceHistoryTextureUnitBase;
|
||||
const GLuint feedbackTextureUnit = ResolveFeedbackTextureUnit(state, static_cast<unsigned>(sourceHistoryTextures.size()));
|
||||
if (state.feedback.enabled)
|
||||
{
|
||||
plan.bindings.push_back({
|
||||
"feedbackState",
|
||||
"gFeedbackState",
|
||||
feedbackTexture,
|
||||
feedbackTextureUnit
|
||||
});
|
||||
}
|
||||
|
||||
const GLuint shaderTextureBase = passProgram.shaderTextureBase != 0
|
||||
? passProgram.shaderTextureBase
|
||||
: feedbackTextureUnit + (state.feedback.enabled ? 1u : 0u);
|
||||
for (std::size_t index = 0; index < passProgram.textureBindings.size(); ++index)
|
||||
{
|
||||
const LayerProgram::TextureBinding& textureBinding = passProgram.textureBindings[index];
|
||||
|
||||
@@ -29,11 +29,14 @@ public:
|
||||
void CreateTextBindings(const RuntimeRenderState& state, std::vector<LayerProgram::TextBinding>& textBindings);
|
||||
bool UpdateTextBindingTexture(const RuntimeRenderState& state, LayerProgram::TextBinding& textBinding, std::string& error);
|
||||
GLint FindSamplerUniformLocation(GLuint program, const std::string& samplerName) const;
|
||||
GLuint ResolveFeedbackTextureUnit(const RuntimeRenderState& state, unsigned historyCap) const;
|
||||
GLuint ResolveShaderTextureBase(const RuntimeRenderState& state, unsigned historyCap) const;
|
||||
void AssignLayerSamplerUniforms(GLuint program, const RuntimeRenderState& state, const PassProgram& passProgram, unsigned historyCap) const;
|
||||
RuntimeTextureBindingPlan BuildLayerRuntimeBindingPlan(
|
||||
const PassProgram& passProgram,
|
||||
GLuint layerInputTexture,
|
||||
const RuntimeRenderState& state,
|
||||
GLuint feedbackTexture,
|
||||
const std::vector<GLuint>& sourceHistoryTextures,
|
||||
const std::vector<GLuint>& temporalHistoryTextures) const;
|
||||
void BindRuntimeTexturePlan(const RuntimeTextureBindingPlan& plan) const;
|
||||
|
||||
Reference in New Issue
Block a user