mirror of
				https://bitbucket.org/mfeemster/fractorium.git
				synced 2025-10-31 09:20:23 -04:00 
			
		
		
		
	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:
		| @ -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> | ||||
|  | ||||
| @ -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 | ||||
|  | ||||
							
								
								
									
										
											BIN
										
									
								
								Data/Bench.xlsx
									
									
									
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								Data/Bench.xlsx
									
									
									
									
									
								
							
										
											Binary file not shown.
										
									
								
							| @ -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. | ||||
|  | ||||
|  | ||||
| @ -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; } | ||||
|  | ||||
| @ -143,9 +143,12 @@ 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); | ||||
| 				AddXform(xform); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		Xform<T> finalXform = *ember.FinalXform();//Will call assignment operator to convert between types T and U. | ||||
|  | ||||
| @ -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 | ||||
|  | ||||
| @ -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,10 +296,10 @@ 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 | ||||
| 	{ | ||||
| @ -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); | ||||
|  | ||||
|  | ||||
| @ -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); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| @ -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" | ||||
|  | ||||
| @ -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" | ||||
|  | ||||
| @ -171,9 +171,12 @@ public: | ||||
| 		for (unsigned int i = 0; i < xform.TotalVariationCount(); i++) | ||||
| 		{ | ||||
| 			Variation<T>* var = NULL; | ||||
|  | ||||
| 			xform.GetVariation(i)->Copy(var);//Will convert from type U to type T. | ||||
| 			AddVariation(var);//Will internally call SetPrecalcFlags(). | ||||
| 			 | ||||
| 			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) | ||||
|  | ||||
| @ -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" | ||||
|  | ||||
| @ -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. | ||||
| } | ||||
|  | ||||
| @ -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" | ||||
|  | ||||
| @ -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" | ||||
|  | ||||
| @ -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()"); | ||||
|  | ||||
| @ -52,7 +52,7 @@ | ||||
|       </font> | ||||
|      </property> | ||||
|      <property name="text"> | ||||
|       <string><html><head/><body><p align="center"><br/><span style=" font-size:12pt;">Fractorium 0.4.1.0 Beta</span></p><p align="center"><span style=" font-size:10pt;"><br/>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"><span style=" font-size:10pt;">Matt Feemster</span></p></body></html></string> | ||||
|       <string><html><head/><body><p align="center"><br/><span style=" font-size:12pt;">Fractorium 0.4.1.1 Beta</span></p><p align="center"><span style=" font-size:10pt;"><br/>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"><span style=" font-size:10pt;">Matt Feemster</span></p></body></html></string> | ||||
|      </property> | ||||
|      <property name="textFormat"> | ||||
|       <enum>Qt::RichText</enum> | ||||
|  | ||||
| @ -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> | ||||
|  | ||||
| @ -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.
										
									
								
							
		Reference in New Issue
	
	Block a user
	 mfeemster
					mfeemster