mirror of
https://github.com/OpenMW/openmw.git
synced 2025-02-05 14:45:39 +00:00
Merge branch 'threading_gone_wrong' into 'master'
[Postprocessing] Fix race condition when techniques are dirtied See merge request OpenMW/openmw!1979
This commit is contained in:
commit
5aeee0a520
6 changed files with 34 additions and 34 deletions
|
@ -9,8 +9,6 @@ namespace MWRender
|
||||||
{
|
{
|
||||||
PingPongCanvas::PingPongCanvas(Shader::ShaderManager& shaderManager)
|
PingPongCanvas::PingPongCanvas(Shader::ShaderManager& shaderManager)
|
||||||
: mFallbackStateSet(new osg::StateSet)
|
: mFallbackStateSet(new osg::StateSet)
|
||||||
, mQueuedDispatchArray(std::nullopt)
|
|
||||||
, mQueuedDispatchFrameId(0)
|
|
||||||
{
|
{
|
||||||
setUseDisplayList(false);
|
setUseDisplayList(false);
|
||||||
setUseVertexBufferObjects(true);
|
setUseVertexBufferObjects(true);
|
||||||
|
@ -37,9 +35,6 @@ namespace MWRender
|
||||||
|
|
||||||
void PingPongCanvas::setCurrentFrameData(size_t frameId, fx::DispatchArray&& data)
|
void PingPongCanvas::setCurrentFrameData(size_t frameId, fx::DispatchArray&& data)
|
||||||
{
|
{
|
||||||
mQueuedDispatchArray = fx::DispatchArray(data);
|
|
||||||
mQueuedDispatchFrameId = !frameId;
|
|
||||||
|
|
||||||
mBufferData[frameId].data = std::move(data);
|
mBufferData[frameId].data = std::move(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,20 +60,12 @@ namespace MWRender
|
||||||
|
|
||||||
auto& bufferData = mBufferData[frameId];
|
auto& bufferData = mBufferData[frameId];
|
||||||
|
|
||||||
if (mQueuedDispatchArray && mQueuedDispatchFrameId == frameId)
|
|
||||||
{
|
|
||||||
mBufferData[frameId].data = std::move(mQueuedDispatchArray.value());
|
|
||||||
mQueuedDispatchArray = std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto& data = bufferData.data;
|
const auto& data = bufferData.data;
|
||||||
|
|
||||||
std::vector<size_t> filtered;
|
std::vector<size_t> filtered;
|
||||||
|
|
||||||
filtered.reserve(data.size());
|
filtered.reserve(data.size());
|
||||||
|
|
||||||
const fx::DispatchNode::SubPass* resolvePass = nullptr;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < data.size(); ++i)
|
for (size_t i = 0; i < data.size(); ++i)
|
||||||
{
|
{
|
||||||
const auto& node = data[i];
|
const auto& node = data[i];
|
||||||
|
@ -86,15 +73,6 @@ namespace MWRender
|
||||||
if (bufferData.mask & node.mFlags)
|
if (bufferData.mask & node.mFlags)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (auto it = node.mPasses.crbegin(); it != node.mPasses.crend(); ++it)
|
|
||||||
{
|
|
||||||
if (!(*it).mRenderTarget)
|
|
||||||
{
|
|
||||||
resolvePass = &(*it);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
filtered.push_back(i);
|
filtered.push_back(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,10 +91,9 @@ namespace MWRender
|
||||||
else
|
else
|
||||||
mLoggedLastError = false;
|
mLoggedLastError = false;
|
||||||
|
|
||||||
mFallbackStateSet->setTextureAttributeAndModes(0, bufferData.sceneTex);
|
|
||||||
|
|
||||||
state.pushStateSet(mFallbackStateSet);
|
state.pushStateSet(mFallbackStateSet);
|
||||||
state.apply();
|
state.apply();
|
||||||
|
state.applyTextureAttribute(0, bufferData.sceneTex);
|
||||||
viewport->apply(state);
|
viewport->apply(state);
|
||||||
|
|
||||||
drawGeometry(renderInfo);
|
drawGeometry(renderInfo);
|
||||||
|
@ -223,7 +200,7 @@ namespace MWRender
|
||||||
|
|
||||||
lastApplied = pass.mRenderTarget->getHandle(state.getContextID());;
|
lastApplied = pass.mRenderTarget->getHandle(state.getContextID());;
|
||||||
}
|
}
|
||||||
else if (&pass == resolvePass)
|
else if (pass.mResolve && index == filtered.back())
|
||||||
{
|
{
|
||||||
bindDestinationFbo();
|
bindDestinationFbo();
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,9 +80,6 @@ namespace MWRender
|
||||||
mutable std::array<BufferData, 2> mBufferData;
|
mutable std::array<BufferData, 2> mBufferData;
|
||||||
mutable std::array<osg::ref_ptr<osg::FrameBufferObject>, 3> mFbos;
|
mutable std::array<osg::ref_ptr<osg::FrameBufferObject>, 3> mFbos;
|
||||||
|
|
||||||
mutable std::optional<fx::DispatchArray> mQueuedDispatchArray;
|
|
||||||
mutable size_t mQueuedDispatchFrameId;
|
|
||||||
|
|
||||||
mutable bool mLoggedLastError = false;
|
mutable bool mLoggedLastError = false;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -419,6 +419,8 @@ namespace MWRender
|
||||||
createTexturesAndCamera(frameId);
|
createTexturesAndCamera(frameId);
|
||||||
createObjectsForFrame(frameId);
|
createObjectsForFrame(frameId);
|
||||||
mDirty = false;
|
mDirty = false;
|
||||||
|
|
||||||
|
mPingPongCanvas->setCurrentFrameData(frameId, fx::DispatchArray(mTemplateData));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((mNormalsSupported && mNormals != mPrevNormals) || (mPassLights != mPrevPassLights))
|
if ((mNormalsSupported && mNormals != mPrevNormals) || (mPassLights != mPrevPassLights))
|
||||||
|
@ -520,7 +522,12 @@ namespace MWRender
|
||||||
if (!isEnabled())
|
if (!isEnabled())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
fx::DispatchArray data;
|
size_t frameId = frame() % 2;
|
||||||
|
|
||||||
|
mDirty = true;
|
||||||
|
mDirtyFrameId = !frameId;
|
||||||
|
|
||||||
|
mTemplateData = {};
|
||||||
|
|
||||||
bool sunglare = true;
|
bool sunglare = true;
|
||||||
mHDR = false;
|
mHDR = false;
|
||||||
|
@ -632,12 +639,12 @@ namespace MWRender
|
||||||
node.mPasses.emplace_back(std::move(subPass));
|
node.mPasses.emplace_back(std::move(subPass));
|
||||||
}
|
}
|
||||||
|
|
||||||
data.emplace_back(std::move(node));
|
node.compile();
|
||||||
|
|
||||||
|
mTemplateData.emplace_back(std::move(node));
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t frameId = frame() % 2;
|
mPingPongCanvas->setCurrentFrameData(frameId, fx::DispatchArray(mTemplateData));
|
||||||
|
|
||||||
mPingPongCanvas->setCurrentFrameData(frameId, std::move(data));
|
|
||||||
|
|
||||||
if (auto hud = MWBase::Environment::get().getWindowManager()->getPostProcessorHud())
|
if (auto hud = MWBase::Environment::get().getWindowManager()->getPostProcessorHud())
|
||||||
hud->updateTechniques();
|
hud->updateTechniques();
|
||||||
|
|
|
@ -251,6 +251,8 @@ namespace MWRender
|
||||||
|
|
||||||
int mWidth;
|
int mWidth;
|
||||||
int mHeight;
|
int mHeight;
|
||||||
|
|
||||||
|
fx::DispatchArray mTemplateData;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -59,9 +59,11 @@ namespace fx
|
||||||
osg::ref_ptr<osg::StateSet> mStateSet = new osg::StateSet;
|
osg::ref_ptr<osg::StateSet> mStateSet = new osg::StateSet;
|
||||||
osg::ref_ptr<osg::FrameBufferObject> mRenderTarget;
|
osg::ref_ptr<osg::FrameBufferObject> mRenderTarget;
|
||||||
osg::ref_ptr<osg::Texture2D> mRenderTexture;
|
osg::ref_ptr<osg::Texture2D> mRenderTexture;
|
||||||
|
bool mResolve = false;
|
||||||
|
|
||||||
SubPass(const SubPass& other, const osg::CopyOp& copyOp = osg::CopyOp::SHALLOW_COPY)
|
SubPass(const SubPass& other, const osg::CopyOp& copyOp = osg::CopyOp::SHALLOW_COPY)
|
||||||
: mStateSet(new osg::StateSet(*other.mStateSet, copyOp))
|
: mStateSet(new osg::StateSet(*other.mStateSet, copyOp))
|
||||||
|
, mResolve(other.mResolve)
|
||||||
{
|
{
|
||||||
if (other.mRenderTarget)
|
if (other.mRenderTarget)
|
||||||
mRenderTarget = new osg::FrameBufferObject(*other.mRenderTarget, copyOp);
|
mRenderTarget = new osg::FrameBufferObject(*other.mRenderTarget, copyOp);
|
||||||
|
@ -70,6 +72,18 @@ namespace fx
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void compile()
|
||||||
|
{
|
||||||
|
for (auto rit = mPasses.rbegin(); rit != mPasses.rend(); ++rit)
|
||||||
|
{
|
||||||
|
if (!rit->mRenderTarget)
|
||||||
|
{
|
||||||
|
rit->mResolve = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// not safe to read/write in draw thread
|
// not safe to read/write in draw thread
|
||||||
std::shared_ptr<fx::Technique> mHandle = nullptr;
|
std::shared_ptr<fx::Technique> mHandle = nullptr;
|
||||||
|
|
||||||
|
|
|
@ -87,6 +87,7 @@ namespace fx
|
||||||
mValueLabel->setCaption(std::to_string(mValue));
|
mValueLabel->setCaption(std::to_string(mValue));
|
||||||
|
|
||||||
float range = 0.f;
|
float range = 0.f;
|
||||||
|
float min = 0.f;
|
||||||
|
|
||||||
if (auto uniform = mUniform.lock())
|
if (auto uniform = mUniform.lock())
|
||||||
{
|
{
|
||||||
|
@ -94,6 +95,7 @@ namespace fx
|
||||||
{
|
{
|
||||||
uniform->template setValue<UType>(mValue);
|
uniform->template setValue<UType>(mValue);
|
||||||
range = uniform->template getMax<UType>() - uniform->template getMin<UType>();
|
range = uniform->template getMax<UType>() - uniform->template getMin<UType>();
|
||||||
|
min = uniform->template getMin<UType>();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -101,10 +103,11 @@ namespace fx
|
||||||
uvalue[mIndex] = mValue;
|
uvalue[mIndex] = mValue;
|
||||||
uniform->template setValue<UType>(uvalue);
|
uniform->template setValue<UType>(uvalue);
|
||||||
range = uniform->template getMax<UType>()[mIndex] - uniform->template getMin<UType>()[mIndex];
|
range = uniform->template getMax<UType>()[mIndex] - uniform->template getMin<UType>()[mIndex];
|
||||||
|
min = uniform->template getMin<UType>()[mIndex];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
float fill = (range == 0.f) ? 1.f : mValue / range;
|
float fill = (range == 0.f) ? 1.f : (mValue - min) / range;
|
||||||
mFill->setRealSize(fill, 1.0);
|
mFill->setRealSize(fill, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue