0.4.1.1 Beta 08/03/2014

--Bug Fixes
Spatial filter would not be correctly recreated on subsequent runs of
differing supersample values during final render.
Fix DCBubble, Funnel, SphericalN,
Wrong logic with some usage of DO_DOUBLE. Only relevant for testing.
Use uint64 for iters/sec calculation on final render dialog. int was
overflowing on extremely fast GPU renders.

--Code Changes
Make density, spatial and temporal filters preserve the values they were
created with. This helps in determining when a new instance is needed.
Better NULL checks when copying embers and xforms.
Rename members in FractoriumEmberControllerBase.h to omit duplicating
the members declared in the base.
This commit is contained in:
mfeemster 2014-08-03 16:16:10 -07:00
parent 152318a567
commit 570d3bcf1d
21 changed files with 135 additions and 80 deletions

View File

@ -6,7 +6,7 @@
<ProductVersion>3.7</ProductVersion>
<ProjectGuid>{c8096c47-e358-438c-a520-146d46b0637d}</ProjectGuid>
<SchemaVersion>2.0</SchemaVersion>
<OutputName>Fractorium_Beta_0.4.1.0</OutputName>
<OutputName>Fractorium_Beta_0.4.1.1</OutputName>
<OutputType>Package</OutputType>
<WixTargetsPath Condition=" '$(WixTargetsPath)' == '' AND '$(MSBuildExtensionsPath32)' != '' ">$(MSBuildExtensionsPath32)\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"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<?define ProductVersion="0.4.1.0" ?>
<?define ProductVersion="0.4.1.1" ?>
<?define ProductName="Fractorium Beta $(var.ProductVersion) ($(var.GpuType))" ?>
<?define UpgradeCode="{4714cd15-bfba-44f6-8059-9e1466ebfa6e}"?>
<?define Manufacturer="Fractorium"?>
@ -13,7 +13,7 @@
<!--
Change this for every release.
-->
<?define ProductCode="{11E92742-0C6F-4FBB-9F24-5B94984AFCC9}"?>
<?define ProductCode="{478E2A85-97E3-4F2D-90AE-6509209D9240}"?>
<Product Id="$(var.ProductCode)" Name="$(var.ProductName)" Language="1033" Version="$(var.ProductVersion)" Manufacturer="$(var.Manufacturer)" UpgradeCode="$(var.UpgradeCode)">
<Package

Binary file not shown.

View File

@ -1,4 +1,15 @@
0.4.0.9 Beta 07/29/2014
0.4.1.1 Beta 08/03/2014
--Bug Fixes
Spatial filter would not be correctly recreated on subsequent runs of differing supersample values during final render.
Fix DCBubble, Funnel, SphericalN,
Wrong logic with some usage of DO_DOUBLE. Only relevant for testing.
--Code Changes
Make density, spatial and temporal filters preserve the values they were created with. This helps in determining when a new instance is needed.
Better NULL checks when copying embers and xforms.
Rename members in FractoriumEmberControllerBase.h to omit duplicating the members declared in the base.
0.4.1.0 Beta 07/29/2014
--Bug Fixes
Final render dialog didn't create the renderer properly on first run when more than one platform was present.

View File

@ -312,6 +312,7 @@ public:
inline T MinRad() const { return m_MinRad; }
inline T MaxRad() const { return m_MaxRad; }
inline T Curve() const { return m_Curve; }
inline unsigned int Supersample() const { return m_Supersample; }
inline unsigned int KernelSize() const { return m_KernelSize; }
inline unsigned int MaxFilterIndex() const { return m_MaxFilterIndex; }
inline unsigned int MaxFilteredCounts() const { return m_MaxFilteredCounts; }

View File

@ -143,10 +143,13 @@ public:
for (unsigned int i = 0; i < ember.XformCount(); i++)
{
Xform<T> xform = *ember.GetXform(i);//Will call assignment operator to convert between types T and U.
if (Xform<U>* p = ember.GetXform(i))
{
Xform<T> xform = *p;//Will call assignment operator to convert between types T and U.
AddXform(xform);
}
}
Xform<T> finalXform = *ember.FinalXform();//Will call assignment operator to convert between types T and U.

View File

@ -25,7 +25,7 @@ namespace EmberNs
extern void sincos(double x, double *s, double *c);
#endif
#define EMBER_VERSION "0.4.1.0"
#define EMBER_VERSION "0.4.1.1"
#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

@ -263,12 +263,12 @@ bool Renderer<T, bucketT>::CreateTemporalFilter(bool& newAlloc)
newAlloc = false;
//Use intelligent testing so it isn't created every time a new ember is passed in.
if ((m_TemporalFilter.get() == NULL) ||
(m_Ember.m_Passes != m_LastEmber.m_Passes) ||
(m_Ember.m_TemporalSamples != m_LastEmber.m_TemporalSamples) ||
if ((!m_TemporalFilter.get()) ||
(m_Ember.m_Passes != m_TemporalFilter->Passes()) ||
(m_Ember.m_TemporalSamples != m_TemporalFilter->TemporalSamples()) ||
(m_Ember.m_TemporalFilterType != m_TemporalFilter->FilterType()) ||
(m_Ember.m_TemporalFilterWidth != m_LastEmber.m_TemporalFilterWidth) ||
(m_Ember.m_TemporalFilterExp != m_LastEmber.m_TemporalFilterExp))
(m_Ember.m_TemporalFilterWidth != m_TemporalFilter->FilterWidth()) ||
(m_Ember.m_TemporalFilterExp != m_TemporalFilter->FilterExp()))
{
m_TemporalFilter = auto_ptr<TemporalFilter<T>>(
TemporalFilterCreator<T>::Create(m_Ember.m_TemporalFilterType, m_Ember.m_Passes, m_Ember.m_TemporalSamples, m_Ember.m_TemporalFilterWidth, m_Ember.m_TemporalFilterExp));
@ -296,11 +296,11 @@ bool Renderer<T, bucketT>::PrepFinalAccumVector(vector<unsigned char>& pixels)
if (m_ReclaimOnResize)
{
if (pixels.size() != size)
{
pixels.resize(size);
if (m_ReclaimOnResize)
pixels.shrink_to_fit();
}
}
else
{
if (pixels.size() < size)
@ -850,11 +850,11 @@ bool Renderer<T, bucketT>::CreateDEFilter(bool& newAlloc)
if (m_Ember.m_MaxRadDE > 0)
{
//Use intelligent testing so it isn't created every time a new ember is passed in.
if ((m_DensityFilter.get() == NULL) ||
if ((!m_DensityFilter.get()) ||
(m_Ember.m_MinRadDE != m_DensityFilter->MinRad()) ||
(m_Ember.m_MaxRadDE != m_DensityFilter->MaxRad()) ||
(m_Ember.m_CurveDE != m_DensityFilter->Curve()) ||
(m_Ember.m_Supersample != m_LastEmber.m_Supersample))
(m_Ember.m_Supersample != m_DensityFilter->Supersample()))
{
m_DensityFilter = auto_ptr<DensityFilter<T>>(new DensityFilter<T>(m_Ember.m_MinRadDE, m_Ember.m_MaxRadDE, m_Ember.m_CurveDE, m_Ember.m_Supersample));
newAlloc = true;
@ -889,10 +889,10 @@ bool Renderer<T, bucketT>::CreateSpatialFilter(bool& newAlloc)
newAlloc = false;
//Use intelligent testing so it isn't created every time a new ember is passed in.
if ((m_SpatialFilter.get() == NULL) ||
if ((!m_SpatialFilter.get()) ||
(m_Ember.m_SpatialFilterType != m_SpatialFilter->FilterType()) ||
(m_Ember.m_SpatialFilterRadius != m_SpatialFilter->FilterRadius()) ||
(m_Ember.m_Supersample != m_LastEmber.m_Supersample) ||
(m_Ember.m_Supersample != m_SpatialFilter->Supersample()) ||
(m_PixelAspectRatio != m_SpatialFilter->PixelAspectRatio()))
{
m_SpatialFilter = auto_ptr<SpatialFilter<T>>(
@ -1007,7 +1007,7 @@ void Renderer<T, bucketT>::ThreadCount(unsigned int threads, const char* seedStr
#ifdef ISAAC_FLAM3_DEBUG
QTIsaac<ISAAC_SIZE, ISAAC_INT> isaac(0, 0, 0, seeds);
#else
QTIsaac<ISAAC_SIZE, ISAAC_INT> isaac(newSize, newSize * newSize, newSize * newSize * newSize, seeds);
QTIsaac<ISAAC_SIZE, ISAAC_INT> isaac(newSize, newSize * 2, newSize * 3, seeds);
#endif
m_Rand.push_back(isaac);

View File

@ -40,9 +40,13 @@ public:
{
unsigned int i, steps = passes * temporalSamples;
m_Passes = passes;
m_TemporalSamples = temporalSamples;
m_FilterWidth = filterWidth;
m_Deltas.resize(steps);
m_Filter.resize(steps);
m_FilterType = filterType;
m_FilterExp = 1;
if (steps == 1)
{
@ -83,6 +87,10 @@ public:
{
if (this != &filter)
{
m_Passes = filter.m_Passes;
m_TemporalSamples = filter.m_TemporalSamples;
m_FilterWidth = filter.m_FilterWidth;
m_FilterExp = filter.m_FilterExp;
m_SumFilt = filter.m_SumFilt;
m_Deltas = filter.m_Deltas;
m_Filter = filter.m_Filter;
@ -127,6 +135,10 @@ public:
/// Accessors.
/// </summary>
size_t Size() const { return m_Filter.size(); }
unsigned int Passes() const { return m_Passes; }
unsigned int TemporalSamples() const { return m_TemporalSamples; }
T FilterWidth() const { return m_FilterWidth; }
T FilterExp() const { return m_FilterExp; }
T SumFilt() const { return m_SumFilt; }
T* Deltas() { return &m_Deltas[0]; }
T* Filter() { return &m_Filter[0]; }
@ -151,6 +163,10 @@ protected:
}
T m_SumFilt;//The sum of all filter values.
T m_FilterWidth;
T m_FilterExp;
unsigned int m_Passes;
unsigned int m_TemporalSamples;
vector<T> m_Deltas;//Delta vector.
vector<T> m_Filter;//Filter vector.
eTemporalFilterType m_FilterType;//The type of filter this is.
@ -192,6 +208,7 @@ public:
maxFilt = m_Filter[i];
}
m_FilterExp = filterExp;
FinishFilter(maxFilt);
}
}

View File

@ -20,7 +20,7 @@ public:
void Func(IteratorHelper<T>& helper, Point<T>& outPoint, QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand)
{
T temp = 1 / cos(helper.In.y) + m_Effect * T(M_PI);
T temp = 1 / Zeps(cos(helper.In.y)) + m_Effect * T(M_PI);
helper.Out.x = m_Weight * (tanh(helper.In.x) * temp);
helper.Out.y = m_Weight * (tanh(helper.In.y) * temp);
@ -36,7 +36,7 @@ public:
string effect = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
ss << "\t{\n"
<< "\t\treal_t temp = 1 / cos(vIn.y) + " << effect << " * M_PI;\n"
<< "\t\treal_t temp = 1 / Zeps(cos(vIn.y)) + " << effect << " * M_PI;\n"
<< "\n"
<< "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * (tanh(vIn.x) * temp);\n"
<< "\t\tvOut.y = xform->m_VariationWeights[" << varIndex << "] * (tanh(vIn.y) * temp);\n"
@ -276,11 +276,9 @@ public:
void Func(IteratorHelper<T>& helper, Point<T>& outPoint, QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand)
{
T r = pow(helper.m_PrecalcSqrtSumSquares, m_Dist);
T r = Zeps(pow(helper.m_PrecalcSqrtSumSquares, m_Dist));
int n = Floor<T>(m_Power * rand.Frand01<T>());
T alpha = helper.m_PrecalcAtanyx + n * M_2PI / Floor<T>(m_Power);
//int n = (int)floor(m_Power * rand.Frand01<T>());
//T alpha = helper.m_PrecalcAtanyx + n * M_2PI / floor(m_Power);
T alpha = helper.m_PrecalcAtanyx + n * M_2PI / Zeps<T>((T)Floor<T>(m_Power));
T sina = sin(alpha);
T cosa = cos(alpha);
@ -299,9 +297,9 @@ public:
string dist = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
ss << "\t{\n"
<< "\t\treal_t r = pow(precalcSqrtSumSquares, " << dist << ");\n"
<< "\t\treal_t r = Zeps(pow(precalcSqrtSumSquares, " << dist << "));\n"
<< "\t\tint n = floor(" << power << " * MwcNext01(mwc));\n"
<< "\t\treal_t alpha = precalcAtanyx + n * M_2PI / floor(" << power << ");\n"
<< "\t\treal_t alpha = precalcAtanyx + n * M_2PI / Zeps(floor(" << power << "));\n"
<< "\t\treal_t sina = sin(alpha);\n"
<< "\t\treal_t cosa = cos(alpha);\n"
<< "\n"

View File

@ -23,7 +23,7 @@ public:
void Func(IteratorHelper<T>& helper, Point<T>& outPoint, QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand)
{
T r = helper.m_PrecalcSumSquares;
T r4_1 = r / 4 + 1;
T r4_1 = Zeps(r / 4 + 1);
r4_1 = m_Weight / r4_1;
helper.Out.x = r4_1 * helper.In.x;
@ -49,7 +49,7 @@ public:
ss << "\t{\n"
<< "\t\treal_t r = precalcSumSquares;\n"
<< "\t\treal_t r4_1 = r / 4 + 1;\n"
<< "\t\treal_t r4_1 = Zeps(r / 4 + 1);\n"
<< "\t\tr4_1 = xform->m_VariationWeights[" << varIndex << "] / r4_1;\n"
<< "\n"
<< "\t\tvOut.x = r4_1 * vIn.x;\n"

View File

@ -172,9 +172,12 @@ public:
{
Variation<T>* var = NULL;
xform.GetVariation(i)->Copy(var);//Will convert from type U to type T.
if (Variation<U>* varOrig = xform.GetVariation(i))
{
varOrig->Copy(var);//Will convert from type U to type T.
AddVariation(var);//Will internally call SetPrecalcFlags().
}
}
if (TotalVariationCount() == 0)
SetPrecalcFlags();

View File

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

View File

@ -49,7 +49,7 @@ RendererCL<T>::RendererCL(unsigned int platform, unsigned int device, bool share
m_PaletteFormat.image_channel_order = CL_RGBA;
m_PaletteFormat.image_channel_data_type = CL_FLOAT;
m_FinalFormat.image_channel_order = CL_RGBA;
m_FinalFormat.image_channel_data_type = CL_UNORM_INT8;//Change if this ever supports 2BPP outputs for PNG.
m_FinalFormat.image_channel_data_type = CL_UNORM_INT8;//Change if this ever supports 2BPC outputs for PNG.
Init(platform, device, shared, outputTexID);//Init OpenCL upon construction and create programs that will not change.
}

View File

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

View File

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

View File

@ -1074,6 +1074,28 @@ bool TestVarAssignVals()
return success;
}
bool TestZepsFloor()
{
bool success = true;
VariationList<float> vlf;
vector<string> zeps;
zeps.push_back("Zeps(floor");
for (size_t i = 0; i < vlf.Size(); i++)
{
Variation<float>* var = vlf.GetVariation(i);
if (SearchVar(var, zeps, false))
{
cout << "Variation " << var->Name() << " contains Zeps(floor()). This is fine for the GPU, but ensure the CPU uses Zeps<T>((T)Floor<T>())." << endl;
success = false;
}
}
return success;
}
bool TestConstants()
{
bool success = true;
@ -1864,6 +1886,10 @@ int _tmain(int argc, _TCHAR* argv[])
TestVarAssignVals();
t.Toc("TestVarAssignVals()");
t.Tic();
TestZepsFloor();
t.Toc("TestZepsFloor()");
t.Tic();
TestConstants();
t.Toc("TestConstants()");

View File

@ -52,7 +52,7 @@
</font>
</property>
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;center&quot;&gt;&lt;br/&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;Fractorium 0.4.1.0 Beta&lt;/span&gt;&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;&lt;br/&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;span style=&quot; font-size:10pt;&quot;&gt;Matt Feemster&lt;/span&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;&lt;br/&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;Fractorium 0.4.1.1 Beta&lt;/span&gt;&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;&lt;br/&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;span style=&quot; font-size:10pt;&quot;&gt;Matt Feemster&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>

View File

@ -83,16 +83,16 @@ template<typename T>
FinalRenderEmberController<T>::FinalRenderEmberController(FractoriumFinalRenderDialog* finalRender)
: FinalRenderEmberControllerBase(finalRender)
{
m_PreviewRenderer = auto_ptr<EmberNs::Renderer<T, T>>(new EmberNs::Renderer<T, T>());
m_PreviewRenderer->Callback(NULL);
m_PreviewRenderer->NumChannels(4);
m_PreviewRenderer->ReclaimOnResize(true);
m_FinalPreviewRenderer = auto_ptr<EmberNs::Renderer<T, T>>(new EmberNs::Renderer<T, T>());
m_FinalPreviewRenderer->Callback(NULL);
m_FinalPreviewRenderer->NumChannels(4);
m_FinalPreviewRenderer->ReclaimOnResize(true);
m_PreviewRenderFunc = [&]()
m_FinalPreviewRenderFunc = [&]()
{
m_PreviewCs.Enter();//Thread prep.
m_PreviewRun = true;
m_PreviewRenderer->Abort();
m_FinalPreviewRenderer->Abort();
QLabel* widget = m_FinalRender->ui.FinalRenderPreviewLabel;
unsigned int maxDim = 100u;
@ -106,21 +106,20 @@ FinalRenderEmberController<T>::FinalRenderEmberController(FractoriumFinalRenderD
m_PreviewEmber = m_Ember;
m_PreviewEmber.m_Quality = 100;
m_PreviewEmber.m_Supersample = 1;
m_PreviewEmber.m_TemporalSamples = 1;
m_PreviewEmber.m_FinalRasW = min(maxDim, unsigned int(scalePercentage * m_Ember.m_FinalRasW));
m_PreviewEmber.m_FinalRasH = min(maxDim, unsigned int(scalePercentage * m_Ember.m_FinalRasH));
m_PreviewEmber.m_PixelsPerUnit = scalePercentage * m_Ember.m_PixelsPerUnit;
while (!m_PreviewRenderer->Aborted() || m_PreviewRenderer->InRender())
while (!m_FinalPreviewRenderer->Aborted() || m_FinalPreviewRenderer->InRender())
QApplication::processEvents();
m_PreviewRenderer->EarlyClip(m_FinalRender->EarlyClip());
m_PreviewRenderer->YAxisUp(m_FinalRender->YAxisUp());
m_PreviewRenderer->Transparency(m_FinalRender->Transparency());
m_PreviewRenderer->SetEmber(m_PreviewEmber);
m_FinalPreviewRenderer->EarlyClip(m_FinalRender->EarlyClip());
m_FinalPreviewRenderer->YAxisUp(m_FinalRender->YAxisUp());
m_FinalPreviewRenderer->Transparency(m_FinalRender->Transparency());
m_FinalPreviewRenderer->SetEmber(m_PreviewEmber);
if (m_PreviewRenderer->Run(m_PreviewFinalImage) == RENDER_OK)
if (m_FinalPreviewRenderer->Run(m_PreviewFinalImage) == RENDER_OK)
{
QImage image(m_PreviewEmber.m_FinalRasW, m_PreviewEmber.m_FinalRasH, QImage::Format_RGBA8888);//The label wants RGBA.
memcpy(image.scanLine(0), m_PreviewFinalImage.data(), m_PreviewFinalImage.size() * sizeof(m_PreviewFinalImage[0]));//Memcpy the data in.
@ -135,7 +134,7 @@ FinalRenderEmberController<T>::FinalRenderEmberController(FractoriumFinalRenderD
//The main rendering function which will be called in a Qt thread.
//A backup Xml is made before the rendering process starts just in case it crashes before finishing.
//If it finishes successfully, delete the backup file.
m_RenderFunc = [&]()
m_FinalRenderFunc = [&]()
{
size_t i;
@ -243,6 +242,7 @@ FinalRenderEmberController<T>::FinalRenderEmberController(FractoriumFinalRenderD
m_Ember.m_TemporalSamples = 1;
m_Renderer->SetEmber(m_Ember);
m_PureIterTime = 0;
memset(m_FinalImage.data(), 0, m_FinalImage.size() * sizeof(m_FinalImage[0]));
m_RenderTimer.Tic();//Toc() is called in the progress function.
if (m_Renderer->Run(m_FinalImage) != RENDER_OK)
@ -266,6 +266,7 @@ template <typename T> void FinalRenderEmberController<T>::SetEmber(const Ember<f
template <typename T> void FinalRenderEmberController<T>::CopyEmber(Ember<float>& ember) { ember = m_Ember; }
template <typename T> void FinalRenderEmberController<T>::SetEmberFile(const EmberFile<float>& emberFile) { m_EmberFile = emberFile; }
template <typename T> void FinalRenderEmberController<T>::CopyEmberFile(EmberFile<float>& emberFile) { emberFile = m_EmberFile; }
template <typename T> void FinalRenderEmberController<T>::SetOriginalEmber(Ember<float>& ember) { m_OriginalEmber = ember; }
template <typename T> double FinalRenderEmberController<T>::OriginalAspect() { return double(m_OriginalEmber.m_OrigFinalRasW) / m_OriginalEmber.m_OrigFinalRasH; }
#ifdef DO_DOUBLE
template <typename T> void FinalRenderEmberController<T>::SetEmber(const Ember<double>& ember, bool verbatim) { m_Ember = ember; }
@ -273,8 +274,6 @@ template <typename T> void FinalRenderEmberController<T>::CopyEmber(Ember<double
template <typename T> void FinalRenderEmberController<T>::SetEmberFile(const EmberFile<double>& emberFile) { m_EmberFile = emberFile; }
template <typename T> void FinalRenderEmberController<T>::CopyEmberFile(EmberFile<double>& emberFile) { emberFile = m_EmberFile; }
template <typename T> void FinalRenderEmberController<T>::SetOriginalEmber(Ember<double>& ember) { m_OriginalEmber = ember; }
#else
template <typename T> void FinalRenderEmberController<T>::SetOriginalEmber(Ember<float>& ember) { m_OriginalEmber = ember; }
#endif
/// <summary>
@ -313,7 +312,7 @@ int FinalRenderEmberController<T>::ProgressFunc(Ember<T>& ember, void* foo, doub
QFileInfo original(filename);
EmberStats stats = m_Renderer->Stats();
QString iters = QLocale(QLocale::English).toString(stats.m_Iters);
QString itersPerSec = QLocale(QLocale::English).toString(int(stats.m_Iters / (m_PureIterTime / 1000.0)));
QString itersPerSec = QLocale(QLocale::English).toString(unsigned __int64(stats.m_Iters / (m_PureIterTime / 1000.0)));
if (m_GuiState.m_DoAll && m_EmberFile.m_Embers.size() > 1)
filename = original.absolutePath() + QDir::separator() + m_GuiState.m_Prefix + QString::fromStdString(m_EmberFile.m_Embers[m_FinishedImageCount].m_Name) + m_GuiState.m_Suffix + "." + m_GuiState.m_DoAllExt;
@ -409,7 +408,7 @@ bool FinalRenderEmberController<T>::Render()
//parallel iteration loops inside of the CPU renderer to finish. The result is that
//the renderer ends up using ThreadCount - 1 to iterate, instead of ThreadCount.
//By using a Qt thread here, and tbb inside the renderer, all cores can be maxed out.
m_Result = QtConcurrent::run(m_RenderFunc);
m_Result = QtConcurrent::run(m_FinalRenderFunc);
m_Settings->sync();
return true;
}
@ -469,7 +468,7 @@ bool FinalRenderEmberController<T>::CreateRenderer(eRendererType renderType, uns
m_Renderer->Callback(this);
m_Renderer->NumChannels(channels);
m_Renderer->ReclaimOnResize(false);
m_Renderer->ReclaimOnResize(true);
m_Renderer->EarlyClip(m_FinalRender->EarlyClip());
m_Renderer->YAxisUp(m_FinalRender->YAxisUp());
m_Renderer->ThreadCount(m_FinalRender->ThreadCount());
@ -506,9 +505,9 @@ unsigned __int64 FinalRenderEmberController<T>::SyncAndComputeMemory()
m_Renderer->NumChannels(channels);
m_Renderer->ComputeBounds();
CancelPreviewRender();
//m_PreviewResult = QtConcurrent::run(m_PreviewRenderFunc);
//while (!m_PreviewResult.isRunning()) { QApplication::processEvents(); }//Wait for it to start up.
m_PreviewRenderFunc();
//m_FinalPreviewResult = QtConcurrent::run(m_PreviewRenderFunc);
//while (!m_FinalPreviewResult.isRunning()) { QApplication::processEvents(); }//Wait for it to start up.
m_FinalPreviewRenderFunc();
return m_Renderer->MemoryRequired(true);
}
@ -536,11 +535,11 @@ void FinalRenderEmberController<T>::ResetProgress(bool total)
template <typename T>
void FinalRenderEmberController<T>::CancelPreviewRender()
{
m_PreviewRenderer->Abort();
m_FinalPreviewRenderer->Abort();
while (m_PreviewRenderer->InRender()) { QApplication::processEvents(); }
while (m_FinalPreviewRenderer->InRender()) { QApplication::processEvents(); }
while (m_PreviewRun) { QApplication::processEvents(); }
while (m_PreviewResult.isRunning()) { QApplication::processEvents(); }
while (m_FinalPreviewResult.isRunning()) { QApplication::processEvents(); }
}
/// <summary>

View File

@ -61,10 +61,9 @@ public:
virtual unsigned __int64 SyncAndComputeMemory() { return 0; }
virtual QString Name() const { return ""; }
virtual void ResetProgress(bool total = true) { }
virtual void SetOriginalEmber(Ember<float>& ember) { }
#ifdef DO_DOUBLE
virtual void SetOriginalEmber(Ember<double>& ember) { }
#else
virtual void SetOriginalEmber(Ember<float>& ember) { }
#endif
virtual double OriginalAspect() { return 1; }
@ -79,10 +78,9 @@ protected:
double m_PureIterTime;
QFuture<void> m_Result;
QFuture<void> m_PreviewResult;
std::function<void (void)> m_RenderFunc;
std::function<void (void)> m_PreviewRenderFunc;
vector<unsigned char> m_PreviewFinalImage;
QFuture<void> m_FinalPreviewResult;
std::function<void (void)> m_FinalRenderFunc;
std::function<void (void)> m_FinalPreviewRenderFunc;
FractoriumSettings* m_Settings;
FractoriumFinalRenderDialog* m_FinalRender;
@ -108,14 +106,13 @@ public:
virtual void CopyEmber(Ember<float>& ember);
virtual void SetEmberFile(const EmberFile<float>& emberFile);
virtual void CopyEmberFile(EmberFile<float>& emberFile);
virtual void SetOriginalEmber(Ember<float>& ember);
#ifdef DO_DOUBLE
virtual void SetEmber(const Ember<double>& ember, bool verbatim = false);
virtual void CopyEmber(Ember<double>& ember);
virtual void SetEmberFile(const EmberFile<double>& emberFile);
virtual void CopyEmberFile(EmberFile<double>& emberFile);
virtual void SetOriginalEmber(Ember<double>& ember);
#else
virtual void SetOriginalEmber(Ember<float>& ember);
#endif
virtual double OriginalAspect();
virtual int ProgressFunc(Ember<T>& ember, void* foo, double fraction, int stage, double etaMs);
@ -135,7 +132,7 @@ protected:
Ember<T> m_PreviewEmber;
EmberFile<T> m_EmberFile;
EmberToXml<T> m_XmlWriter;
auto_ptr<EmberNs::Renderer<T, T>> m_PreviewRenderer;
auto_ptr<EmberNs::Renderer<T, T>> m_FinalPreviewRenderer;
};
template class FinalRenderEmberController<float>;

Binary file not shown.