mirror of
https://bitbucket.org/mfeemster/fractorium.git
synced 2025-01-21 05:00:06 -05:00
Merge branch 'master' of https://bitbucket.org/mfeemster/fractorium
This commit is contained in:
commit
64d4470b12
@ -48,7 +48,7 @@
|
|||||||
<xform weight="1" color="0.083558" var_color="1" color_speed="0.00745693" symmetry="0.985086" name="Iterator_2" animate="1" pre_gaussian="0.001" linear="1" coefs="0.552956 -0.83321 0.83321 0.552956 -0.400538 -0.0645161" chaos="8.0664 2.29144 1.53027 9.07866 0 0 0.1 " opacity="1"/>
|
<xform weight="1" color="0.083558" var_color="1" color_speed="0.00745693" symmetry="0.985086" name="Iterator_2" animate="1" pre_gaussian="0.001" linear="1" coefs="0.552956 -0.83321 0.83321 0.552956 -0.400538 -0.0645161" chaos="8.0664 2.29144 1.53027 9.07866 0 0 0.1 " opacity="1"/>
|
||||||
<xform weight="1" color="0.462617" var_color="1" color_speed="0.180397" symmetry="0.639206" name="Iterator_3" animate="1" pre_gaussian="0.1" linear="0.9" coefs="0.0393396 0.999226 -0.999226 0.0393396 -0.782258 0.489247" chaos="1.0274 9.05155 1.02313 1.57207 0 1 1 " opacity="1"/>
|
<xform weight="1" color="0.462617" var_color="1" color_speed="0.180397" symmetry="0.639206" name="Iterator_3" animate="1" pre_gaussian="0.1" linear="0.9" coefs="0.0393396 0.999226 -0.999226 0.0393396 -0.782258 0.489247" chaos="1.0274 9.05155 1.02313 1.57207 0 1 1 " opacity="1"/>
|
||||||
<xform weight="0.7" color="0.560664" var_color="1" color_speed="0.013697" symmetry="0.972606" name="Iterator_4" animate="1" linear="0.45" coefs="-0.172916 0.984937 -0.984937 -0.172916 0.876623 -0.655844" chaos="1.23314 6.36522 1.18045 1.0184 1 0 1 " opacity="1"/>
|
<xform weight="0.7" color="0.560664" var_color="1" color_speed="0.013697" symmetry="0.972606" name="Iterator_4" animate="1" linear="0.45" coefs="-0.172916 0.984937 -0.984937 -0.172916 0.876623 -0.655844" chaos="1.23314 6.36522 1.18045 1.0184 1 0 1 " opacity="1"/>
|
||||||
<xform weight="0.1" color="0.324206" var_color="1" color_speed="0.37535" symmetry="0.2493" name="Iterator_5" animate="1" gaussian_blur="0.01" post_hypertile1="1" post_hypertile1_p="3.05" post_hypertile1_q="7" coefs="1 0 6.12323e-17 1 0 0" post="0.808538 -0.588444 0.588444 0.808538 0.0833333 -0.0107527" chaos="1 1 1 1 1 0 1 " opacity="1"/>
|
<xform weight="0.1" color="0.324206" var_color="1" color_speed="0.37535" symmetry="0.2493" name="Iterator_5" animate="1" gaussian_blur="0.01" post_hypertile1="1" post_hypertile1_p="3" post_hypertile1_q="7" coefs="1 0 6.12323e-17 1 0 0" post="0.808538 -0.588444 0.588444 0.808538 0.0833333 -0.0107527" chaos="1 1 1 1 1 0 1 " opacity="1"/>
|
||||||
<xform weight="0.3" color="0.90592" var_color="1" color_speed="0.319324" symmetry="0.361352" name="Iterator_6" animate="1" noise="0.2" coefs="1 0 6.12323e-17 1 0 0" post="1 0 6.12323e-17 1 0.317073 0.280488" chaos="0 0 1 0 0 1 1 " opacity="0"/>
|
<xform weight="0.3" color="0.90592" var_color="1" color_speed="0.319324" symmetry="0.361352" name="Iterator_6" animate="1" noise="0.2" coefs="1 0 6.12323e-17 1 0 0" post="1 0 6.12323e-17 1 0.317073 0.280488" chaos="0 0 1 0 0 1 1 " opacity="0"/>
|
||||||
<xform weight="0.2" color="0.135651" var_color="1" color_speed="0.0443604" symmetry="0.911279" name="Iterator_7" animate="1" gaussian_blur="0.001" coefs="1 0 6.12323e-17 1 0 0" post="1 0 6.12323e-17 1 0.536585 0.298781" opacity="1"/>
|
<xform weight="0.2" color="0.135651" var_color="1" color_speed="0.0443604" symmetry="0.911279" name="Iterator_7" animate="1" gaussian_blur="0.001" coefs="1 0 6.12323e-17 1 0 0" post="1 0 6.12323e-17 1 0.536585 0.298781" opacity="1"/>
|
||||||
<finalxform color="0" var_color="1" color_speed="0" symmetry="1" name="Camera" animate="0" Mobius="1" Mobius_Re_A="1" Mobius_Im_A="2.2" Mobius_Re_B="0.5" Mobius_Im_B="0" Mobius_Re_C="0" Mobius_Im_C="0" Mobius_Re_D="0.9" Mobius_Im_D="-0.4" coefs="1 0 6.12323e-17 1 0 0" opacity="1"/>
|
<finalxform color="0" var_color="1" color_speed="0" symmetry="1" name="Camera" animate="0" Mobius="1" Mobius_Re_A="1" Mobius_Im_A="2.2" Mobius_Re_B="0.5" Mobius_Im_B="0" Mobius_Re_C="0" Mobius_Im_C="0" Mobius_Re_D="0.9" Mobius_Im_D="-0.4" coefs="1 0 6.12323e-17 1 0 0" opacity="1"/>
|
||||||
|
@ -91,6 +91,124 @@ void FinalRenderEmberControllerBase::Output(const QString& s)
|
|||||||
QMetaObject::invokeMethod(m_FinalRenderDialog->ui.FinalRenderTextOutput, "append", Qt::QueuedConnection, Q_ARG(const QString&, s));
|
QMetaObject::invokeMethod(m_FinalRenderDialog->ui.FinalRenderTextOutput, "append", Qt::QueuedConnection, Q_ARG(const QString&, s));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Render a single ember.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ember">The ember to render</param>
|
||||||
|
/// <param name="fullRender">Is this is a FULL_RENDER or if we should KEEP_ITERATING.</param>
|
||||||
|
/// <param name="stripForProgress">Used to report progress when strips.</param>
|
||||||
|
/// <returns>True if rendering succeeded.</returns>
|
||||||
|
template<typename T>
|
||||||
|
bool FinalRenderEmberController<T>::RenderSingleEmber(Ember<T>& ember, bool fullRender, size_t &stripForProgress)
|
||||||
|
{
|
||||||
|
if (!m_Renderer.get()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ember.m_TemporalSamples = 1;//No temporal sampling.
|
||||||
|
|
||||||
|
m_Renderer->SetEmber(ember, fullRender ? eProcessAction::FULL_RENDER : eProcessAction::KEEP_ITERATING, /* updatePointer */ true);
|
||||||
|
|
||||||
|
m_Renderer->PrepFinalAccumVector(m_FinalImage);//Must manually call this first because it could be erroneously made smaller due to strips if called inside Renderer::Run().
|
||||||
|
m_Stats.Clear();
|
||||||
|
m_RenderTimer.Tic();//Toc() is called in RenderComplete().
|
||||||
|
|
||||||
|
StripsRender<T>(m_Renderer.get(), ember, m_FinalImage, 0, m_GuiState.m_Strips, m_GuiState.m_YAxisUp,
|
||||||
|
[&](size_t strip) { stripForProgress = strip; },//Pre strip.
|
||||||
|
[&](size_t strip) { m_Stats += m_Renderer->Stats(); },//Post strip.
|
||||||
|
[&](size_t strip)//Error.
|
||||||
|
{
|
||||||
|
Output("Rendering failed.\n");
|
||||||
|
m_Fractorium->ErrorReportToQTextEdit(m_Renderer->ErrorReport(), m_FinalRenderDialog->ui.FinalRenderTextOutput, false);//Internally calls invoke.
|
||||||
|
},
|
||||||
|
[&](Ember<T>& finalEmber)
|
||||||
|
{
|
||||||
|
m_FinishedImageCount.fetch_add(1);
|
||||||
|
SaveCurrentRender(finalEmber);
|
||||||
|
RenderComplete(finalEmber);
|
||||||
|
HandleFinishedProgress();
|
||||||
|
});//Final strip.
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Render a single ember from a series of embers.
|
||||||
|
/// m_Renderers.SetExternalEmbersPointer should already be set.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="atomfTime">Used to coordinate which frame to render.</param>
|
||||||
|
/// <param name="index">which index into m_Renderers to use.</param>
|
||||||
|
/// <returns>True if rendering succeeded.</returns>
|
||||||
|
template<typename T>
|
||||||
|
bool FinalRenderEmberController<T>::RenderSingleEmberFromSeries(std::atomic<size_t>* atomfTime, size_t index)
|
||||||
|
{
|
||||||
|
if (m_Renderers.size() <= index) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t ftime;
|
||||||
|
size_t finalImageIndex = 0;
|
||||||
|
std::thread writeThread;
|
||||||
|
vector<v4F> finalImages[2];
|
||||||
|
EmberStats stats;
|
||||||
|
EmberImageComments comments;
|
||||||
|
Timing renderTimer;
|
||||||
|
const auto renderer = m_Renderers[index].get();
|
||||||
|
|
||||||
|
//Render each image, cancelling if m_Run ever gets set to false.
|
||||||
|
//The conditions of this loop use atomics to synchronize when running on multiple GPUs.
|
||||||
|
//The order is reversed from the usual loop: rather than compare and increment the counter,
|
||||||
|
//it's incremented, then compared. This is done to ensure the GPU on this thread "claims" this
|
||||||
|
//frame before working on it.
|
||||||
|
//The mechanism for incrementing is:
|
||||||
|
// Do an atomic add, which returns the previous value.
|
||||||
|
// Assign the result to the ftime counter.
|
||||||
|
// Do a < comparison to m_EmberFile.Size() and check m_Run.
|
||||||
|
while (((ftime = (atomfTime->fetch_add(1))) < m_EmberFile.Size()) && m_Run)//Needed to set 1 to claim this iter from other threads, so decrement it below to be zero-indexed here.
|
||||||
|
{
|
||||||
|
Output("Image " + ToString(ftime + 1ULL) + ":\n" + ComposePath(QString::fromStdString(m_EmberFile.Get(ftime)->m_Name)));
|
||||||
|
renderer->Reset();//Have to manually set this since the ember is not set each time through.
|
||||||
|
renderTimer.Tic();//Toc() is called in RenderComplete().
|
||||||
|
|
||||||
|
//Can't use strips render here. Run() must be called directly for animation.
|
||||||
|
if (renderer->Run(finalImages[finalImageIndex], T(ftime)) != eRenderStatus::RENDER_OK)
|
||||||
|
{
|
||||||
|
Output("Rendering failed.\n");
|
||||||
|
m_Fractorium->ErrorReportToQTextEdit(renderer->ErrorReport(), m_FinalRenderDialog->ui.FinalRenderTextOutput, false);//Internally calls invoke.
|
||||||
|
atomfTime->store(m_EmberFile.Size() + 1);//Abort all threads if any of them encounter an error.
|
||||||
|
m_Run = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Join(writeThread);
|
||||||
|
stats = renderer->Stats();
|
||||||
|
comments = renderer->ImageComments(stats, 0, true);
|
||||||
|
writeThread = std::thread([&](size_t tempTime, size_t threadFinalImageIndex)
|
||||||
|
{
|
||||||
|
SaveCurrentRender(*m_EmberFile.Get(tempTime),
|
||||||
|
comments,//These all don't change during the renders, so it's ok to access them in the thread.
|
||||||
|
finalImages[threadFinalImageIndex],
|
||||||
|
renderer->FinalRasW(),
|
||||||
|
renderer->FinalRasH(),
|
||||||
|
m_FinalRenderDialog->Png16Bit(),
|
||||||
|
m_FinalRenderDialog->Transparency());
|
||||||
|
}, ftime, finalImageIndex);
|
||||||
|
m_FinishedImageCount.fetch_add(1);
|
||||||
|
RenderComplete(*m_EmberFile.Get(ftime), stats, renderTimer);
|
||||||
|
|
||||||
|
if (!index)//Only first device has a progress callback, so it also makes sense to only manually set the progress on the first device as well.
|
||||||
|
HandleFinishedProgress();
|
||||||
|
}
|
||||||
|
|
||||||
|
finalImageIndex ^= 1;//Toggle the index.
|
||||||
|
}
|
||||||
|
|
||||||
|
Join(writeThread);//One final check to make sure all writing is done before exiting this thread.
|
||||||
|
return m_Run;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Constructor which accepts a pointer to the final render dialog and passes it to the base.
|
/// Constructor which accepts a pointer to the final render dialog and passes it to the base.
|
||||||
/// The main final rendering lambda function is constructed here.
|
/// The main final rendering lambda function is constructed here.
|
||||||
@ -145,8 +263,6 @@ FinalRenderEmberController<T>::FinalRenderEmberController(FractoriumFinalRenderD
|
|||||||
{
|
{
|
||||||
Ember<T>* prev = nullptr;
|
Ember<T>* prev = nullptr;
|
||||||
vector<Ember<T>> embers;
|
vector<Ember<T>> embers;
|
||||||
vector<std::thread> threadVec;
|
|
||||||
std::atomic<size_t> atomfTime;
|
|
||||||
const auto firstEmber = m_EmberFile.m_Embers.begin();
|
const auto firstEmber = m_EmberFile.m_Embers.begin();
|
||||||
|
|
||||||
//Need to loop through and set all w, h, q, ts, ss and t vals.
|
//Need to loop through and set all w, h, q, ts, ss and t vals.
|
||||||
@ -157,14 +273,13 @@ FinalRenderEmberController<T>::FinalRenderEmberController(FractoriumFinalRenderD
|
|||||||
|
|
||||||
SyncGuiToEmber(it, firstEmber->m_FinalRasW, firstEmber->m_FinalRasH);
|
SyncGuiToEmber(it, firstEmber->m_FinalRasW, firstEmber->m_FinalRasH);
|
||||||
|
|
||||||
if (&it == &(*firstEmber))//First.
|
if (prev == nullptr)//First.
|
||||||
{
|
{
|
||||||
it.m_Time = 0;
|
it.m_Time = 0;
|
||||||
}
|
}
|
||||||
else//All others
|
else if (it.m_Time <= prev->m_Time)
|
||||||
{
|
{
|
||||||
if (it.m_Time <= prev->m_Time)
|
it.m_Time = prev->m_Time + 1;
|
||||||
it.m_Time = prev->m_Time + 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
it.m_TemporalSamples = m_GuiState.m_TemporalSamples;
|
it.m_TemporalSamples = m_GuiState.m_TemporalSamples;
|
||||||
@ -175,83 +290,17 @@ FinalRenderEmberController<T>::FinalRenderEmberController(FractoriumFinalRenderD
|
|||||||
//Shouldn't be a problem because animations will be at max 4k x 2k which will take about 1GB
|
//Shouldn't be a problem because animations will be at max 4k x 2k which will take about 1GB
|
||||||
//even when using double precision, which most cards at the time of this writing already exceed.
|
//even when using double precision, which most cards at the time of this writing already exceed.
|
||||||
m_GuiState.m_Strips = 1;
|
m_GuiState.m_Strips = 1;
|
||||||
atomfTime.store(0);
|
|
||||||
CopyCont(embers, m_EmberFile.m_Embers);
|
CopyCont(embers, m_EmberFile.m_Embers);
|
||||||
std::function<void(size_t)> iterFunc = [&](size_t index)
|
|
||||||
{
|
|
||||||
size_t ftime;
|
|
||||||
size_t finalImageIndex = 0;
|
|
||||||
std::thread writeThread;
|
|
||||||
vector<v4F> finalImages[2];
|
|
||||||
EmberStats stats;
|
|
||||||
EmberImageComments comments;
|
|
||||||
Timing renderTimer;
|
|
||||||
const auto renderer = m_Renderers[index].get();
|
|
||||||
renderer->SetExternalEmbersPointer(&embers);//All will share a pointer to the original vector to conserve memory with large files. Ok because the vec doesn't get modified.
|
|
||||||
|
|
||||||
//Render each image, cancelling if m_Run ever gets set to false.
|
std::atomic<size_t> atomfTime(0);
|
||||||
//Render each image, cancelling if m_Run ever gets set to false.
|
vector<std::thread> threadVec;
|
||||||
//The conditions of this loop use atomics to synchronize when running on multiple GPUs.
|
|
||||||
//The order is reversed from the usual loop: rather than compare and increment the counter,
|
|
||||||
//it's incremented, then compared. This is done to ensure the GPU on this thread "claims" this
|
|
||||||
//frame before working on it.
|
|
||||||
//The mechanism for incrementing is:
|
|
||||||
// Do an atomic add, which returns the previous value.
|
|
||||||
// Add 1 to the return value to mimic what the new atomic value should be.
|
|
||||||
// Assign the result to the ftime counter.
|
|
||||||
// Do a <= comparison to m_EmberFile.Size() and check m_Run.
|
|
||||||
// If true, enter the loop and immediately decrement the counter by 1 to make up for the fact
|
|
||||||
// that it was first incremented before comparing.
|
|
||||||
while (((ftime = (atomfTime.fetch_add(1) + 1)) <= m_EmberFile.Size()) && m_Run)//Needed to set 1 to claim this iter from other threads, so decrement it below to be zero-indexed here.
|
|
||||||
{
|
|
||||||
--ftime;
|
|
||||||
Output("Image " + ToString(ftime + 1ULL) + ":\n" + ComposePath(QString::fromStdString(m_EmberFile.Get(ftime)->m_Name)));
|
|
||||||
renderer->Reset();//Have to manually set this since the ember is not set each time through.
|
|
||||||
renderTimer.Tic();//Toc() is called in RenderComplete().
|
|
||||||
|
|
||||||
//Can't use strips render here. Run() must be called directly for animation.
|
|
||||||
if (renderer->Run(finalImages[finalImageIndex], T(ftime)) != eRenderStatus::RENDER_OK)
|
|
||||||
{
|
|
||||||
Output("Rendering failed.\n");
|
|
||||||
m_Fractorium->ErrorReportToQTextEdit(renderer->ErrorReport(), m_FinalRenderDialog->ui.FinalRenderTextOutput, false);//Internally calls invoke.
|
|
||||||
atomfTime.store(m_EmberFile.Size() + 1);//Abort all threads if any of them encounter an error.
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Join(writeThread);
|
|
||||||
stats = renderer->Stats();
|
|
||||||
comments = renderer->ImageComments(stats, 0, true);
|
|
||||||
writeThread = std::thread([&](size_t tempTime, size_t threadFinalImageIndex)
|
|
||||||
{
|
|
||||||
SaveCurrentRender(*m_EmberFile.Get(tempTime),
|
|
||||||
comments,//These all don't change during the renders, so it's ok to access them in the thread.
|
|
||||||
finalImages[threadFinalImageIndex],
|
|
||||||
renderer->FinalRasW(),
|
|
||||||
renderer->FinalRasH(),
|
|
||||||
m_FinalRenderDialog->Png16Bit(),
|
|
||||||
m_FinalRenderDialog->Transparency());
|
|
||||||
}, ftime, finalImageIndex);
|
|
||||||
m_FinishedImageCount.fetch_add(1);
|
|
||||||
RenderComplete(*m_EmberFile.Get(ftime), stats, renderTimer);
|
|
||||||
|
|
||||||
if (!index)//Only first device has a progress callback, so it also makes sense to only manually set the progress on the first device as well.
|
|
||||||
HandleFinishedProgress();
|
|
||||||
}
|
|
||||||
|
|
||||||
finalImageIndex ^= 1;//Toggle the index.
|
|
||||||
}
|
|
||||||
|
|
||||||
Join(writeThread);//One final check to make sure all writing is done before exiting this thread.
|
|
||||||
};
|
|
||||||
threadVec.reserve(m_Renderers.size());
|
threadVec.reserve(m_Renderers.size());
|
||||||
|
|
||||||
for (size_t r = 0; r < m_Renderers.size(); r++)
|
for (size_t r = 0; r < m_Renderers.size(); r++)
|
||||||
{
|
{
|
||||||
threadVec.push_back(std::thread([&](size_t index)
|
//All will share a pointer to the original vector to conserve memory with large files. Ok because the vec doesn't get modified.
|
||||||
{
|
m_Renderers[r]->SetExternalEmbersPointer(&embers);
|
||||||
iterFunc(index);
|
threadVec.push_back(std::thread(&RenderSingleEmberFromSeries, this, &atomfTime, r));
|
||||||
}, r));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Join(threadVec);
|
Join(threadVec);
|
||||||
@ -266,26 +315,7 @@ FinalRenderEmberController<T>::FinalRenderEmberController(FractoriumFinalRenderD
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
Output("Image " + ToString<qulonglong>(m_FinishedImageCount.load() + 1) + ":\n" + ComposePath(QString::fromStdString(it.m_Name)));
|
Output("Image " + ToString<qulonglong>(m_FinishedImageCount.load() + 1) + ":\n" + ComposePath(QString::fromStdString(it.m_Name)));
|
||||||
it.m_TemporalSamples = 1;//No temporal sampling.
|
RenderSingleEmber(it, /* fullRender */ true, currentStripForProgress);
|
||||||
m_Renderer->SetEmber(it, eProcessAction::FULL_RENDER, true);
|
|
||||||
m_Renderer->PrepFinalAccumVector(m_FinalImage);//Must manually call this first because it could be erroneously made smaller due to strips if called inside Renderer::Run().
|
|
||||||
m_Stats.Clear();
|
|
||||||
m_RenderTimer.Tic();//Toc() is called in RenderComplete().
|
|
||||||
StripsRender<T>(m_Renderer.get(), it, m_FinalImage, 0, m_GuiState.m_Strips, m_GuiState.m_YAxisUp,
|
|
||||||
[&](size_t strip) { currentStripForProgress = strip; },//Pre strip.
|
|
||||||
[&](size_t strip) { m_Stats += m_Renderer->Stats(); },//Post strip.
|
|
||||||
[&](size_t strip)//Error.
|
|
||||||
{
|
|
||||||
Output("Rendering failed.\n");
|
|
||||||
m_Fractorium->ErrorReportToQTextEdit(m_Renderer->ErrorReport(), m_FinalRenderDialog->ui.FinalRenderTextOutput, false);//Internally calls invoke.
|
|
||||||
},
|
|
||||||
[&](Ember<T>& finalEmber)
|
|
||||||
{
|
|
||||||
m_FinishedImageCount.fetch_add(1);
|
|
||||||
SaveCurrentRender(finalEmber);
|
|
||||||
RenderComplete(finalEmber);
|
|
||||||
HandleFinishedProgress();
|
|
||||||
});//Final strip.
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -295,29 +325,13 @@ FinalRenderEmberController<T>::FinalRenderEmberController(FractoriumFinalRenderD
|
|||||||
}
|
}
|
||||||
else if (m_Renderer.get())//Render a single image.
|
else if (m_Renderer.get())//Render a single image.
|
||||||
{
|
{
|
||||||
|
Output(ComposePath(QString::fromStdString(m_Ember->m_Name)));
|
||||||
|
|
||||||
m_ImageCount = 1;
|
m_ImageCount = 1;
|
||||||
m_Ember->m_TemporalSamples = 1;
|
m_Ember->m_TemporalSamples = 1;
|
||||||
m_Fractorium->m_Controller->ParamsToEmber(*m_Ember, true);//Update color and filter params from the main window controls, which only affect the filter and/or final accumulation stage.
|
m_Fractorium->m_Controller->ParamsToEmber(*m_Ember, true);//Update color and filter params from the main window controls, which only affect the filter and/or final accumulation stage.
|
||||||
m_Renderer->SetEmber(*m_Ember, isBump ? eProcessAction::KEEP_ITERATING : eProcessAction::FULL_RENDER, true);
|
|
||||||
m_Renderer->PrepFinalAccumVector(m_FinalImage);//Must manually call this first because it could be erroneously made smaller due to strips if called inside Renderer::Run().
|
RenderSingleEmber(*m_Ember, /* fullRender= */ !isBump, currentStripForProgress);
|
||||||
m_Stats.Clear();
|
|
||||||
Output(ComposePath(QString::fromStdString(m_Ember->m_Name)));
|
|
||||||
m_RenderTimer.Tic();//Toc() is called in RenderComplete().
|
|
||||||
StripsRender<T>(m_Renderer.get(), *m_Ember, m_FinalImage, 0, m_GuiState.m_Strips, m_GuiState.m_YAxisUp,
|
|
||||||
[&](size_t strip) { currentStripForProgress = strip; },//Pre strip.
|
|
||||||
[&](size_t strip) { m_Stats += m_Renderer->Stats(); },//Post strip.
|
|
||||||
[&](size_t strip)//Error.
|
|
||||||
{
|
|
||||||
Output("Rendering failed.\n");
|
|
||||||
m_Fractorium->ErrorReportToQTextEdit(m_Renderer->ErrorReport(), m_FinalRenderDialog->ui.FinalRenderTextOutput, false);//Internally calls invoke.
|
|
||||||
},
|
|
||||||
[&](Ember<T>& finalEmber)
|
|
||||||
{
|
|
||||||
m_FinishedImageCount.fetch_add(1);
|
|
||||||
SaveCurrentRender(finalEmber);
|
|
||||||
RenderComplete(finalEmber);
|
|
||||||
HandleFinishedProgress();
|
|
||||||
});//Final strip.
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -151,6 +151,8 @@ protected:
|
|||||||
void SyncGuiToEmber(Ember<T>& ember, size_t widthOverride = 0, size_t heightOverride = 0, bool dowidth = true, bool doheight = true);
|
void SyncGuiToEmber(Ember<T>& ember, size_t widthOverride = 0, size_t heightOverride = 0, bool dowidth = true, bool doheight = true);
|
||||||
bool SyncGuiToRenderer();
|
bool SyncGuiToRenderer();
|
||||||
void SetProgressComplete(int val);
|
void SetProgressComplete(int val);
|
||||||
|
bool RenderSingleEmber(Ember<T>& ember, bool fullRender, size_t &stripForProgress);
|
||||||
|
bool RenderSingleEmberFromSeries(std::atomic<size_t>* atomfTime, size_t index);
|
||||||
|
|
||||||
Ember<T>* m_Ember;
|
Ember<T>* m_Ember;
|
||||||
EmberFile<T> m_EmberFile;
|
EmberFile<T> m_EmberFile;
|
||||||
|
@ -431,7 +431,7 @@ bool FractoriumEmberController<T>::Render()
|
|||||||
{
|
{
|
||||||
const auto stats = m_Renderer->Stats();
|
const auto stats = m_Renderer->Stats();
|
||||||
auto iters = ToString<qulonglong>(stats.m_Iters);
|
auto iters = ToString<qulonglong>(stats.m_Iters);
|
||||||
auto scaledQuality = ToString(static_cast<intmax_t>(m_Renderer->ScaledQuality()));
|
auto scaledQuality = ToString(static_cast<qulonglong>(m_Renderer->ScaledQuality()));
|
||||||
auto renderTime = m_RenderElapsedTimer.Format(m_RenderElapsedTimer.Toc());
|
auto renderTime = m_RenderElapsedTimer.Format(m_RenderElapsedTimer.Toc());
|
||||||
m_Fractorium->m_ProgressBar->setValue(100);
|
m_Fractorium->m_ProgressBar->setValue(100);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user