--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

@ -6,7 +6,7 @@
<ProductVersion>3.7</ProductVersion> <ProductVersion>3.7</ProductVersion>
<ProjectGuid>{c8096c47-e358-438c-a520-146d46b0637d}</ProjectGuid> <ProjectGuid>{c8096c47-e358-438c-a520-146d46b0637d}</ProjectGuid>
<SchemaVersion>2.0</SchemaVersion> <SchemaVersion>2.0</SchemaVersion>
<OutputName>Fractorium_1.0.0.12</OutputName> <OutputName>Fractorium_1.0.0.13</OutputName>
<OutputType>Package</OutputType> <OutputType>Package</OutputType>
<WixTargetsPath Condition=" '$(WixTargetsPath)' == '' AND '$(MSBuildExtensionsPath32)' != '' ">$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets</WixTargetsPath> <WixTargetsPath Condition=" '$(WixTargetsPath)' == '' AND '$(MSBuildExtensionsPath32)' != '' ">$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets</WixTargetsPath>
<WixTargetsPath Condition=" '$(WixTargetsPath)' == '' ">$(MSBuildExtensionsPath)\Microsoft\WiX\v3.x\Wix.targets</WixTargetsPath> <WixTargetsPath Condition=" '$(WixTargetsPath)' == '' ">$(MSBuildExtensionsPath)\Microsoft\WiX\v3.x\Wix.targets</WixTargetsPath>

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"> <Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<?define ProductVersion="1.0.0.12" ?> <?define ProductVersion="1.0.0.13" ?>
<?define ProductName="Fractorium $(var.ProductVersion) ($(var.GpuType))" ?> <?define ProductName="Fractorium $(var.ProductVersion) ($(var.GpuType))" ?>
<?define UpgradeCode="{4714cd15-bfba-44f6-8059-9e1466ebfa6e}"?> <?define UpgradeCode="{4714cd15-bfba-44f6-8059-9e1466ebfa6e}"?>
<?define Manufacturer="Fractorium"?> <?define Manufacturer="Fractorium"?>
@ -13,7 +13,7 @@
<!-- <!--
Change this for every release. Change this for every release.
--> -->
<?define ProductCode="{B4D001AE-F268-41A2-9B33-CAFB26056DC3}"?> <?define ProductCode="{E78B38F9-F4BC-408A-A36B-5C494FA88D21}"?>
<Product Id="$(var.ProductCode)" Name="$(var.ProductName)" Language="1033" Version="$(var.ProductVersion)" Manufacturer="$(var.Manufacturer)" UpgradeCode="$(var.UpgradeCode)"> <Product Id="$(var.ProductCode)" Name="$(var.ProductName)" Language="1033" Version="$(var.ProductVersion)" Manufacturer="$(var.Manufacturer)" UpgradeCode="$(var.UpgradeCode)">
<Package <Package

Binary file not shown.

View File

@ -49,8 +49,8 @@
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 1, 0, 0, 12 FILEVERSION 1, 0, 0, 13
PRODUCTVERSION 1, 0, 0, 12 PRODUCTVERSION 1, 0, 0, 13
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@ -67,12 +67,12 @@
BEGIN BEGIN
VALUE "CompanyName", "Open Source" VALUE "CompanyName", "Open Source"
VALUE "FileDescription", "Renders fractal flames as animations with motion blur" VALUE "FileDescription", "Renders fractal flames as animations with motion blur"
VALUE "FileVersion", "1.0.0.12" VALUE "FileVersion", "1, 0, 0, 13"
VALUE "InternalName", "EmberAnimate.exe" VALUE "InternalName", "EmberAnimate.exe"
VALUE "LegalCopyright", "Copyright (C) Matt Feemster 2018, GPL v3" VALUE "LegalCopyright", "Copyright (C) Matt Feemster 2018, GPL v3"
VALUE "OriginalFilename", "EmberAnimate.exe" VALUE "OriginalFilename", "EmberAnimate.exe"
VALUE "ProductName", "Ember Animate" VALUE "ProductName", "Ember Animate"
VALUE "ProductVersion", "1.0.0.12" VALUE "ProductVersion", "1, 0, 0, 13"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"

Binary file not shown.

View File

@ -49,8 +49,8 @@
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 1, 0, 0, 12 FILEVERSION 1, 0, 0, 13
PRODUCTVERSION 1, 0, 0, 12 PRODUCTVERSION 1, 0, 0, 13
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@ -67,12 +67,12 @@
BEGIN BEGIN
VALUE "CompanyName", "Open Source" VALUE "CompanyName", "Open Source"
VALUE "FileDescription", "Manipulates fractal flames parameter files" VALUE "FileDescription", "Manipulates fractal flames parameter files"
VALUE "FileVersion", "1.0.0.12" VALUE "FileVersion", "1, 0, 0, 13"
VALUE "InternalName", "EmberGenome.exe" VALUE "InternalName", "EmberGenome.exe"
VALUE "LegalCopyright", "Copyright (C) Matt Feemster 2018, GPL v3" VALUE "LegalCopyright", "Copyright (C) Matt Feemster 2018, GPL v3"
VALUE "OriginalFilename", "EmberGenome.exe" VALUE "OriginalFilename", "EmberGenome.exe"
VALUE "ProductName", "Ember Genome" VALUE "ProductName", "Ember Genome"
VALUE "ProductVersion", "1.0.0.12" VALUE "ProductVersion", "1, 0, 0, 13"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"

View File

@ -49,8 +49,8 @@
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 1, 0, 0, 12 FILEVERSION 1, 0, 0, 13
PRODUCTVERSION 1, 0, 0, 12 PRODUCTVERSION 1, 0, 0, 13
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@ -67,12 +67,12 @@
BEGIN BEGIN
VALUE "CompanyName", "Open Source" VALUE "CompanyName", "Open Source"
VALUE "FileDescription", "Renders fractal flames as single images" VALUE "FileDescription", "Renders fractal flames as single images"
VALUE "FileVersion", "1.0.0.12" VALUE "FileVersion", "1, 0, 0, 13"
VALUE "InternalName", "EmberRender.exe" VALUE "InternalName", "EmberRender.exe"
VALUE "LegalCopyright", "Copyright (C) Matt Feemster 2018, GPL v3" VALUE "LegalCopyright", "Copyright (C) Matt Feemster 2018, GPL v3"
VALUE "OriginalFilename", "EmberRender.exe" VALUE "OriginalFilename", "EmberRender.exe"
VALUE "ProductName", "Ember Render" VALUE "ProductName", "Ember Render"
VALUE "ProductVersion", "1.0.0.12" VALUE "ProductVersion", "1, 0, 0, 13"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"

Binary file not shown.

View File

@ -37,7 +37,7 @@ static void sincos(float x, float* s, float* c)
namespace EmberNs namespace EmberNs
{ {
#define EMBER_VERSION "1.0.0.12" #define EMBER_VERSION "1.0.0.13"
#define EPS6 T(1e-6) #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 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 #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); sampleItersToDo = std::min<size_t>(sampleItersToDo, itersPerTemporalSample - m_LastIter);
EmberStats stats = Iterate(sampleItersToDo, temporalSample);//The heavy work is done here. 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 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"); AddToReport("Zero iterations ran, rendering failed, aborting.\n");
success = eRenderStatus::RENDER_ERROR; success = eRenderStatus::RENDER_ERROR;
@ -537,12 +544,6 @@ eRenderStatus Renderer<T, bucketT>::Run(vector<v4F>& finalImage, double time, si
goto Finish; goto Finish;
} }
if (m_Abort)
{
success = eRenderStatus::RENDER_ABORT;
goto Finish;
}
//Accumulate stats whether this batch ran to completion or exited prematurely. //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_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. 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() void Clear()
{ {
m_Success = true;
m_Iters = 0; m_Iters = 0;
m_Badvals = 0; m_Badvals = 0;
m_IterMs = 0; m_IterMs = 0;
@ -69,6 +70,7 @@ public:
EmberStats& operator += (const EmberStats& stats) EmberStats& operator += (const EmberStats& stats)
{ {
m_Success &= stats.m_Success;
m_Iters += stats.m_Iters; m_Iters += stats.m_Iters;
m_Badvals += stats.m_Badvals; m_Badvals += stats.m_Badvals;
m_IterMs += stats.m_IterMs; m_IterMs += stats.m_IterMs;
@ -76,6 +78,7 @@ public:
return *this; return *this;
} }
bool m_Success = true;
size_t m_Iters, m_Badvals; size_t m_Iters, m_Badvals;
double m_IterMs, m_RenderMs; double m_IterMs, m_RenderMs;
}; };

View File

@ -787,9 +787,9 @@ eRenderStatus RendererCL<T, bucketT>::AccumulatorToFinalImage(vector<v4F>& pixel
template <typename T, typename bucketT> template <typename T, typename bucketT>
EmberStats RendererCL<T, bucketT>::Iterate(size_t iterCount, size_t temporalSample) 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. 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__; 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. //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) if (m_LastIter == 0)
@ -868,15 +868,10 @@ EmberStats RendererCL<T, bucketT>::Iterate(size_t iterCount, size_t temporalSamp
dev->m_Calls = 0; dev->m_Calls = 0;
b = RunIter(iterCount, temporalSample, stats.m_Iters); 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(); stats.m_IterMs = m_IterTimer.Toc();
} }
else else
{ {
m_Abort = true;
ErrorStr(loc, "Iiteration failed", nullptr); 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; auto& wrapper = m_Devices[dev]->m_Wrapper;
intmax_t itersRemaining = 0; 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. //Check if the user wanted to suspend the process.
while (Paused()) while (Paused())
@ -1053,7 +1048,6 @@ bool RendererCL<T, bucketT>::RunIter(size_t iterCount, size_t temporalSample, si
1))) 1)))
{ {
success = false; success = false;
m_Abort = true;
ErrorStr(loc, "Error running iteration program", m_Devices[dev].get()); ErrorStr(loc, "Error running iteration program", m_Devices[dev].get());
atomLaunchesRan.fetch_sub(1); atomLaunchesRan.fetch_sub(1);
break; break;
@ -1117,7 +1111,7 @@ bool RendererCL<T, bucketT>::RunIter(size_t iterCount, size_t temporalSample, si
Join(threadVec); Join(threadVec);
itersRan = atomItersRan.load(); 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). 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... ((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(); //t2.Tic();
if (b && !(b = RunDensityFilterPrivate(kernelIndex, gridW, gridH, blockSizeW, blockSizeH, chunkSizeW, chunkSizeH, colChunkPass, rowChunkPass))) 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()); 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> <enum>QFrame::NoFrame</enum>
</property> </property>
<property name="text"> <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>
<property name="textFormat"> <property name="textFormat">
<enum>Qt::RichText</enum> <enum>Qt::RichText</enum>

View File

@ -700,6 +700,8 @@ void FractoriumFinalRenderDialog::Pause(bool paused)
m_Controller->Pause(false); m_Controller->Pause(false);
ui.FinalRenderPauseButton->setText("Pause"); ui.FinalRenderPauseButton->setText("Pause");
} }
ui.FinalRenderStartButton->setEnabled(!paused);
} }
/// <summary> /// <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. //if (m_Renderer->Run(m_FinalImage, 0) == RENDER_OK)//Full, non-incremental render for debugging.
bool update = iterBegin || m_Fractorium->m_Settings->ContinuousUpdate(); 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. //The amount to increment sub batch while rendering proceeds is purely empirical.
//Change later if better values can be derived/observed. //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(); auto errors = m_Renderer->ErrorReport();
success = false; success = false;