fix threading issue when dispatching frame dependent data

fix/shrink_builds
glassmancody.info 3 years ago
parent c7449dc272
commit acc209c294

@ -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();
}
size_t frameId = frame() % 2; mTemplateData.emplace_back(std::move(node));
}
mPingPongCanvas->setCurrentFrameData(frameId, std::move(data)); mPingPongCanvas->setCurrentFrameData(frameId, fx::DispatchArray(mTemplateData));
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…
Cancel
Save