diff --git a/Builds/MSVC/Installer/FractoriumInstaller.wixproj b/Builds/MSVC/Installer/FractoriumInstaller.wixproj index 780446d..b7e4885 100644 --- a/Builds/MSVC/Installer/FractoriumInstaller.wixproj +++ b/Builds/MSVC/Installer/FractoriumInstaller.wixproj @@ -6,7 +6,7 @@ 3.7 {c8096c47-e358-438c-a520-146d46b0637d} 2.0 - Fractorium_1.0.0.12 + Fractorium_1.0.0.13 Package $(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets $(MSBuildExtensionsPath)\Microsoft\WiX\v3.x\Wix.targets diff --git a/Builds/MSVC/Installer/Product.wxs b/Builds/MSVC/Installer/Product.wxs index 45f22d7..53f5076 100644 --- a/Builds/MSVC/Installer/Product.wxs +++ b/Builds/MSVC/Installer/Product.wxs @@ -1,6 +1,6 @@ - + @@ -13,7 +13,7 @@ - + ::epsilon()//Apoplugin.h uses -20, but it's more mathematically correct to do it this way. #define ISAAC_SIZE 4 diff --git a/Source/Ember/Renderer.cpp b/Source/Ember/Renderer.cpp index 9bfa595..a348f78 100644 --- a/Source/Ember/Renderer.cpp +++ b/Source/Ember/Renderer.cpp @@ -528,8 +528,15 @@ eRenderStatus Renderer::Run(vector& finalImage, double time, si sampleItersToDo = std::min(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::Run(vector& 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. diff --git a/Source/Ember/RendererBase.h b/Source/Ember/RendererBase.h index df91b7c..4d616e1 100644 --- a/Source/Ember/RendererBase.h +++ b/Source/Ember/RendererBase.h @@ -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; }; diff --git a/Source/EmberCL/RendererCL.cpp b/Source/EmberCL/RendererCL.cpp index ab48dc8..2a90744 100644 --- a/Source/EmberCL/RendererCL.cpp +++ b/Source/EmberCL/RendererCL.cpp @@ -787,9 +787,9 @@ eRenderStatus RendererCL::AccumulatorToFinalImage(vector& pixel template EmberStats RendererCL::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::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::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::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::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::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()); } diff --git a/Source/Fractorium/AboutDialog.ui b/Source/Fractorium/AboutDialog.ui index 114b15c..bf83fcc 100644 --- a/Source/Fractorium/AboutDialog.ui +++ b/Source/Fractorium/AboutDialog.ui @@ -58,7 +58,7 @@ QFrame::NoFrame - <html><head/><body><p align="center">Fractorium 1.0.0.12</p><p align="center"><span style=" font-size:10pt;">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.</span></p><p align="center"><a href="http://fractorium.com"><span style=" text-decoration: underline; color:#0000ff;">fractorium.com</span></a></p></body></html> + <html><head/><body><p align="center">Fractorium 1.0.0.13</p><p align="center"><span style=" font-size:10pt;">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.</span></p><p align="center"><a href="http://fractorium.com"><span style=" text-decoration: underline; color:#0000ff;">fractorium.com</span></a></p></body></html> Qt::RichText diff --git a/Source/Fractorium/FinalRenderDialog.cpp b/Source/Fractorium/FinalRenderDialog.cpp index 3cd5a65..9d149e2 100644 --- a/Source/Fractorium/FinalRenderDialog.cpp +++ b/Source/Fractorium/FinalRenderDialog.cpp @@ -700,6 +700,8 @@ void FractoriumFinalRenderDialog::Pause(bool paused) m_Controller->Pause(false); ui.FinalRenderPauseButton->setText("Pause"); } + + ui.FinalRenderStartButton->setEnabled(!paused); } /// diff --git a/Source/Fractorium/FractoriumRender.cpp b/Source/Fractorium/FractoriumRender.cpp index cc8fcd0..81a267d 100644 --- a/Source/Fractorium/FractoriumRender.cpp +++ b/Source/Fractorium/FractoriumRender.cpp @@ -394,8 +394,9 @@ bool FractoriumEmberController::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::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;