--User changes

-Disable Start button in final render dialog when Pause is clicked.

--Bug fixes
 -Rapidly changing spinner values was causing the OpenCL renderer to report a failure, when it was really just aborting.

--Code changes
 -Renderers never internally set abort to true due to a failure. Abort is only set to true by the calling code.
This commit is contained in:
Person
2018-10-05 19:50:38 -07:00
parent 784bd9cca2
commit a0b658481a
15 changed files with 36 additions and 36 deletions

View File

@ -37,7 +37,7 @@ static void sincos(float x, float* s, float* c)
namespace EmberNs
{
#define EMBER_VERSION "1.0.0.12"
#define EMBER_VERSION "1.0.0.13"
#define EPS6 T(1e-6)
#define EPS std::numeric_limits<T>::epsilon()//Apoplugin.h uses -20, but it's more mathematically correct to do it this way.
#define ISAAC_SIZE 4

View File

@ -528,8 +528,15 @@ eRenderStatus Renderer<T, bucketT>::Run(vector<v4F>& finalImage, double time, si
sampleItersToDo = std::min<size_t>(sampleItersToDo, itersPerTemporalSample - m_LastIter);
EmberStats stats = Iterate(sampleItersToDo, temporalSample);//The heavy work is done here.
//Abort does not indicate an error, it just means the process was interrupted, most likely by the user on the GUI.
if (m_Abort)
{
success = eRenderStatus::RENDER_ABORT;
goto Finish;
}
//If no iters were executed, something went catastrophically wrong.
if (stats.m_Iters == 0)
if (!stats.m_Success && stats.m_Iters == 0)
{
AddToReport("Zero iterations ran, rendering failed, aborting.\n");
success = eRenderStatus::RENDER_ERROR;
@ -537,12 +544,6 @@ eRenderStatus Renderer<T, bucketT>::Run(vector<v4F>& finalImage, double time, si
goto Finish;
}
if (m_Abort)
{
success = eRenderStatus::RENDER_ABORT;
goto Finish;
}
//Accumulate stats whether this batch ran to completion or exited prematurely.
m_LastIter += stats.m_Iters;//Sum of iter count of all threads, reset each temporal sample.
m_Stats.m_Iters += stats.m_Iters;//Sum of iter count of all threads, cumulative from beginning to end.

View File

@ -61,6 +61,7 @@ public:
void Clear()
{
m_Success = true;
m_Iters = 0;
m_Badvals = 0;
m_IterMs = 0;
@ -69,6 +70,7 @@ public:
EmberStats& operator += (const EmberStats& stats)
{
m_Success &= stats.m_Success;
m_Iters += stats.m_Iters;
m_Badvals += stats.m_Badvals;
m_IterMs += stats.m_IterMs;
@ -76,6 +78,7 @@ public:
return *this;
}
bool m_Success = true;
size_t m_Iters, m_Badvals;
double m_IterMs, m_RenderMs;
};

View File

@ -787,9 +787,9 @@ eRenderStatus RendererCL<T, bucketT>::AccumulatorToFinalImage(vector<v4F>& pixel
template <typename T, typename bucketT>
EmberStats RendererCL<T, bucketT>::Iterate(size_t iterCount, size_t temporalSample)
{
bool b = true;
EmberStats stats;//Do not record bad vals with with GPU. If the user needs to investigate bad vals, use the CPU.
static std::string loc = __FUNCTION__;
bool& b = stats.m_Success;
//Only need to do this once on the beginning of a new render. Last iter will always be 0 at the beginning of a full render or temporal sample.
if (m_LastIter == 0)
@ -868,15 +868,10 @@ EmberStats RendererCL<T, bucketT>::Iterate(size_t iterCount, size_t temporalSamp
dev->m_Calls = 0;
b = RunIter(iterCount, temporalSample, stats.m_Iters);
if (!b || stats.m_Iters == 0)//If no iters were executed, something went catastrophically wrong.
m_Abort = true;
stats.m_IterMs = m_IterTimer.Toc();
}
else
{
m_Abort = true;
ErrorStr(loc, "Iiteration failed", nullptr);
}
@ -1000,7 +995,7 @@ bool RendererCL<T, bucketT>::RunIter(size_t iterCount, size_t temporalSample, si
auto& wrapper = m_Devices[dev]->m_Wrapper;
intmax_t itersRemaining = 0;
while (b && (atomLaunchesRan.fetch_add(1) + 1 <= launches) && ((itersRemaining = atomItersRemaining.load()) > 0) && !m_Abort)
while (b && (atomLaunchesRan.fetch_add(1) + 1 <= launches) && ((itersRemaining = atomItersRemaining.load()) > 0) && success && !m_Abort)
{
//Check if the user wanted to suspend the process.
while (Paused())
@ -1053,7 +1048,6 @@ bool RendererCL<T, bucketT>::RunIter(size_t iterCount, size_t temporalSample, si
1)))
{
success = false;
m_Abort = true;
ErrorStr(loc, "Error running iteration program", m_Devices[dev].get());
atomLaunchesRan.fetch_sub(1);
break;
@ -1117,7 +1111,7 @@ bool RendererCL<T, bucketT>::RunIter(size_t iterCount, size_t temporalSample, si
Join(threadVec);
itersRan = atomItersRan.load();
if (m_Devices.size() > 1)//Determine whether/when to sum histograms of secondary devices with the primary.
if (success && m_Devices.size() > 1)//Determine whether/when to sum histograms of secondary devices with the primary.
{
if (((TemporalSamples() == 1) || (temporalSample == TemporalSamples() - 1)) &&//If there are no temporal samples (not animating), or the current one is the last... (probably doesn't matter anymore since we never use multiple renders for a single frame when animating, instead each frame gets its own renderer).
((m_LastIter + itersRan) >= ItersPerTemporalSample()))//...and the required number of iters for that sample have completed...
@ -1270,7 +1264,6 @@ eRenderStatus RendererCL<T, bucketT>::RunDensityFilter()
//t2.Tic();
if (b && !(b = RunDensityFilterPrivate(kernelIndex, gridW, gridH, blockSizeW, blockSizeH, chunkSizeW, chunkSizeH, colChunkPass, rowChunkPass)))
{
m_Abort = true;
ErrorStr(loc, "Running DE filter program for row chunk "s + std::to_string(rowChunkPass) + ", col chunk "s + std::to_string(colChunkPass) + " failed", m_Devices[0].get());
}

View File

@ -58,7 +58,7 @@
<enum>QFrame::NoFrame</enum>
</property>
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;center&quot;&gt;Fractorium 1.0.0.12&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;A Qt-based fractal flame editor which uses a C++ re-write of the flam3 algorithm named Ember and a GPU capable version named EmberCL which implements a portion of the cuburn algorithm in OpenCL.&lt;/span&gt;&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;&lt;a href=&quot;http://fractorium.com&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;fractorium.com&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;center&quot;&gt;Fractorium 1.0.0.13&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;A Qt-based fractal flame editor which uses a C++ re-write of the flam3 algorithm named Ember and a GPU capable version named EmberCL which implements a portion of the cuburn algorithm in OpenCL.&lt;/span&gt;&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;&lt;a href=&quot;http://fractorium.com&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;fractorium.com&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>

View File

@ -700,6 +700,8 @@ void FractoriumFinalRenderDialog::Pause(bool paused)
m_Controller->Pause(false);
ui.FinalRenderPauseButton->setText("Pause");
}
ui.FinalRenderStartButton->setEnabled(!paused);
}
/// <summary>

View File

@ -394,8 +394,9 @@ bool FractoriumEmberController<T>::Render()
{
//if (m_Renderer->Run(m_FinalImage, 0) == RENDER_OK)//Full, non-incremental render for debugging.
bool update = iterBegin || m_Fractorium->m_Settings->ContinuousUpdate();
eRenderStatus result;
if (m_Renderer->Run(m_FinalImage, 0, m_SubBatchCount, update) == eRenderStatus::RENDER_OK)//Force output on iterBegin or if the settings specify to always do it.
if ((result = m_Renderer->Run(m_FinalImage, 0, m_SubBatchCount, update)) == eRenderStatus::RENDER_OK)//Force output on iterBegin or if the settings specify to always do it.
{
//The amount to increment sub batch while rendering proceeds is purely empirical.
//Change later if better values can be derived/observed.
@ -491,7 +492,7 @@ bool FractoriumEmberController<T>::Render()
//}
}
}
else//Something went very wrong, show error report.
else if (result != eRenderStatus::RENDER_ABORT)//If error was returned, something went very wrong, show error report.
{
auto errors = m_Renderer->ErrorReport();
success = false;