diff --git a/Builds/MSVC/VS2013/Ember.vcxproj b/Builds/MSVC/VS2013/Ember.vcxproj
index 25d86c3..7576e09 100644
--- a/Builds/MSVC/VS2013/Ember.vcxproj
+++ b/Builds/MSVC/VS2013/Ember.vcxproj
@@ -232,6 +232,7 @@
Precise
true
false
+ false
Windows
diff --git a/Builds/MSVC/VS2013/EmberAnimate.vcxproj b/Builds/MSVC/VS2013/EmberAnimate.vcxproj
index 9b36f5a..704de76 100644
--- a/Builds/MSVC/VS2013/EmberAnimate.vcxproj
+++ b/Builds/MSVC/VS2013/EmberAnimate.vcxproj
@@ -250,6 +250,7 @@ xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\flam3-palettes.xml" "$(OutDir)"
true
true
false
+ false
Console
diff --git a/Builds/MSVC/VS2013/EmberCL.vcxproj b/Builds/MSVC/VS2013/EmberCL.vcxproj
index 6787428..659f9d7 100644
--- a/Builds/MSVC/VS2013/EmberCL.vcxproj
+++ b/Builds/MSVC/VS2013/EmberCL.vcxproj
@@ -235,6 +235,7 @@
true
false
true
+ false
Windows
@@ -298,8 +299,10 @@
+
+
@@ -307,9 +310,11 @@
+
+
diff --git a/Builds/MSVC/VS2013/EmberCL.vcxproj.filters b/Builds/MSVC/VS2013/EmberCL.vcxproj.filters
index 7db175f..45bf595 100644
--- a/Builds/MSVC/VS2013/EmberCL.vcxproj.filters
+++ b/Builds/MSVC/VS2013/EmberCL.vcxproj.filters
@@ -36,6 +36,12 @@
Kernel Creators
+
+ Source Files
+
+
+ Source Files
+
@@ -62,5 +68,11 @@
Kernel Creators
+
+ Header Files
+
+
+ Header Files
+
\ No newline at end of file
diff --git a/Builds/MSVC/VS2013/EmberGenome.vcxproj b/Builds/MSVC/VS2013/EmberGenome.vcxproj
index 92d2585..e99eb28 100644
--- a/Builds/MSVC/VS2013/EmberGenome.vcxproj
+++ b/Builds/MSVC/VS2013/EmberGenome.vcxproj
@@ -250,6 +250,7 @@ xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\flam3-palettes.xml" "$(OutDir)"
true
true
false
+ false
Console
diff --git a/Builds/MSVC/VS2013/EmberRender.vcxproj b/Builds/MSVC/VS2013/EmberRender.vcxproj
index 7b32cf8..36d597f 100644
--- a/Builds/MSVC/VS2013/EmberRender.vcxproj
+++ b/Builds/MSVC/VS2013/EmberRender.vcxproj
@@ -251,6 +251,7 @@ xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\flam3-palettes.xml" "$(OutDir)"
true
false
true
+ false
Console
diff --git a/Builds/MSVC/VS2013/EmberTester.vcxproj b/Builds/MSVC/VS2013/EmberTester.vcxproj
index b51d7c5..fdf9396 100644
--- a/Builds/MSVC/VS2013/EmberTester.vcxproj
+++ b/Builds/MSVC/VS2013/EmberTester.vcxproj
@@ -250,6 +250,7 @@ xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\flam3-palettes.xml" "$(OutDir)"
true
true
false
+ false
Console
diff --git a/Builds/MSVC/VS2013/Fractorium.vcxproj b/Builds/MSVC/VS2013/Fractorium.vcxproj
index 5170ca0..1656e9b 100644
--- a/Builds/MSVC/VS2013/Fractorium.vcxproj
+++ b/Builds/MSVC/VS2013/Fractorium.vcxproj
@@ -246,6 +246,7 @@ xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\flam3-palettes.xml" "$(OutDir)"
true
false
/bigobj -Zm150 %(AdditionalOptions)
+ false
Windows
diff --git a/Builds/QtCreator/Ember/Ember.pro b/Builds/QtCreator/Ember/Ember.pro
index f4da780..df6ed2f 100644
--- a/Builds/QtCreator/Ember/Ember.pro
+++ b/Builds/QtCreator/Ember/Ember.pro
@@ -1,4 +1,5 @@
TEMPLATE = lib
+CONFIG += plugin
CONFIG += shared
CONFIG -= app_bundle
CONFIG -= qt
diff --git a/Builds/QtCreator/Ember/deployment.pri b/Builds/QtCreator/Ember/deployment.pri
index f9403df..6376a82 100644
--- a/Builds/QtCreator/Ember/deployment.pri
+++ b/Builds/QtCreator/Ember/deployment.pri
@@ -188,6 +188,3 @@ export (DEPLOYMENT)
export (LIBS)
export (QMAKE_EXTRA_TARGETS)
}
-
-OTHER_FILES +=
-
diff --git a/Builds/QtCreator/EmberCL/EmberCL.pro b/Builds/QtCreator/EmberCL/EmberCL.pro
index d0dbb39..24277d3 100644
--- a/Builds/QtCreator/EmberCL/EmberCL.pro
+++ b/Builds/QtCreator/EmberCL/EmberCL.pro
@@ -1,4 +1,5 @@
TEMPLATE = lib
+CONFIG += plugin
CONFIG += shared
CONFIG -= app_bundle
CONFIG -= qt
@@ -14,23 +15,27 @@ QMAKE_CXXFLAGS += -D_CONSOLE
QMAKE_CXXFLAGS += -BUILDING_EMBERCL
SOURCES += \
- ../../../Source/EmberCL/DllMain.cpp \
- ../../../Source/EmberCL/FinalAccumOpenCLKernelCreator.cpp \
- ../../../Source/EmberCL/IterOpenCLKernelCreator.cpp \
- ../../../Source/EmberCL/OpenCLWrapper.cpp \
- ../../../Source/EmberCL/RendererCL.cpp \
- ../../../Source/EmberCL/DEOpenCLKernelCreator.cpp
+ ../../../Source/EmberCL/DllMain.cpp \
+ ../../../Source/EmberCL/DEOpenCLKernelCreator.cpp \
+ ../../../Source/EmberCL/FinalAccumOpenCLKernelCreator.cpp \
+ ../../../Source/EmberCL/IterOpenCLKernelCreator.cpp \
+ ../../../Source/EmberCL/OpenCLInfo.cpp \
+ ../../../Source/EmberCL/OpenCLWrapper.cpp \
+ ../../../Source/EmberCL/RendererCL.cpp \
+ ../../../Source/EmberCL/RendererCLDevice.cpp
include(deployment.pri)
qtcAddDeployment()
HEADERS += \
- ../../../Source/EmberCL/DEOpenCLKernelCreator.h \
- ../../../Source/EmberCL/EmberCLFunctions.h \
- ../../../Source/EmberCL/EmberCLPch.h \
- ../../../Source/EmberCL/EmberCLStructs.h \
- ../../../Source/EmberCL/FinalAccumOpenCLKernelCreator.h \
- ../../../Source/EmberCL/IterOpenCLKernelCreator.h \
- ../../../Source/EmberCL/OpenCLWrapper.h \
- ../../../Source/EmberCL/RendererCL.h
+ ../../../Source/EmberCL/DEOpenCLKernelCreator.h \
+ ../../../Source/EmberCL/EmberCLFunctions.h \
+ ../../../Source/EmberCL/EmberCLPch.h \
+ ../../../Source/EmberCL/EmberCLStructs.h \
+ ../../../Source/EmberCL/FinalAccumOpenCLKernelCreator.h \
+ ../../../Source/EmberCL/IterOpenCLKernelCreator.h \
+ ../../../Source/EmberCL/OpenCLInfo.h \
+ ../../../Source/EmberCL/OpenCLWrapper.h \
+ ../../../Source/EmberCL/RendererCL.h \
+ ../../../Source/EmberCL/RendererCLDevice.h
diff --git a/Builds/QtCreator/build_all.sh b/Builds/QtCreator/build_all.sh
index a71eb9e..11af667 100644
--- a/Builds/QtCreator/build_all.sh
+++ b/Builds/QtCreator/build_all.sh
@@ -3,8 +3,8 @@
REBUILD=''
NVIDIA=''
NATIVE=''
-CONCURRENCY='-j9'
-QMAKE=${QMAKE:-qmake}
+CONCURRENCY='-j4'
+QMAKE=${QMAKE:/usr/bin/qmake}
RELEASE='CONFIG+=release CONFIG-=debug'
while test $# -gt 0
diff --git a/Builds/QtCreator/shared_settings.pri b/Builds/QtCreator/shared_settings.pri
index b5dc4ce..e2493ed 100644
--- a/Builds/QtCreator/shared_settings.pri
+++ b/Builds/QtCreator/shared_settings.pri
@@ -1,5 +1,15 @@
-CONFIG += warn_off
-VERSION = 0.1.4.7
+VERSION = 0.1.4.9
+
+CONFIG(release, debug|release) {
+ CONFIG += warn_off
+ DESTDIR = ../../../Bin/release
+}
+
+CONFIG(debug, debug|release) {
+ DESTDIR = ../../../Bin/debug
+}
+
+QMAKE_POST_LINK += $$quote(cp --update ../../../Data/flam3-palettes.xml $${DESTDIR}$$escape_expand(\n\t))
macx {
LIBS += -framework OpenGL
@@ -33,9 +43,6 @@ native {
QMAKE_CXXFLAGS += -march=k8
}
-release:DESTDIR = ../../../release
-debug:DESTDIR = ../../../debug
-
OBJECTS_DIR = $$DESTDIR/.obj
MOC_DIR = $$DESTDIR/.moc
RCC_DIR = $$DESTDIR/.qrc
@@ -44,6 +51,7 @@ UI_DIR = $$DESTDIR/.ui
LIBS += -L/usr/lib -ljpeg
LIBS += -L/usr/lib -lpng
LIBS += -L/usr/lib -ltbb
+LIBS += -L/usr/lib -lpthread
LIBS += -L/usr/lib/x86_64-linux-gnu -lxml2
CMAKE_CXXFLAGS += -DCL_USE_DEPRECATED_OPENCL_1_1_APIS
diff --git a/Source/Ember/Affine2D.cpp b/Source/Ember/Affine2D.cpp
index b02839a..1d15e3c 100644
--- a/Source/Ember/Affine2D.cpp
+++ b/Source/Ember/Affine2D.cpp
@@ -293,7 +293,7 @@ template
typename m4T Affine2D::ToMat4ColMajor(bool center) const
{
m4T mat(A(), B(), 0, center ? 0 : C(), //Col0...
- D(), E(), 0, center ? 0 : F(), //1
+ D(), E(), 0, center ? 0 : F(), //1
0, 0, 1, 0, //2
0, 0, 0, 1);//3
@@ -309,7 +309,7 @@ template
typename m4T Affine2D::ToMat4RowMajor(bool center) const
{
m4T mat(A(), D(), 0, 0,
- B(), E(), 0, 0,
+ B(), E(), 0, 0,
0, 0, 1, 0,
center ? 0 : C(), center ? 0 : F(), 0, 1);
diff --git a/Source/Ember/Curves.h b/Source/Ember/Curves.h
index 391ad95..0323dba 100644
--- a/Source/Ember/Curves.h
+++ b/Source/Ember/Curves.h
@@ -69,7 +69,7 @@ public:
template
Curves& operator = (const Curves& curves)
{
- for (uint i = 0; i < 4; i++)
+ for (size_t i = 0; i < 4; i++)
{
m_Points[i][0].x = T(curves.m_Points[i][0].x); m_Points[i][0].y = T(curves.m_Points[i][0].y); m_Weights[i].x = T(curves.m_Weights[i].x);
m_Points[i][1].x = T(curves.m_Points[i][1].x); m_Points[i][1].y = T(curves.m_Points[i][1].y); m_Weights[i].y = T(curves.m_Weights[i].y);
@@ -87,7 +87,7 @@ public:
/// Reference to updated self
Curves& operator += (const Curves& curves)
{
- for (uint i = 0; i < 4; i++)
+ for (size_t i = 0; i < 4; i++)
{
m_Points[i][0] += curves.m_Points[i][0];
m_Points[i][1] += curves.m_Points[i][1];
@@ -107,7 +107,7 @@ public:
/// Reference to updated self
Curves& operator *= (const Curves& curves)
{
- for (uint i = 0; i < 4; i++)
+ for (size_t i = 0; i < 4; i++)
{
m_Points[i][0] *= curves.m_Points[i][0];
m_Points[i][1] *= curves.m_Points[i][1];
@@ -127,7 +127,7 @@ public:
/// Reference to updated self
Curves& operator *= (const T& t)
{
- for (uint i = 0; i < 4; i++)
+ for (size_t i = 0; i < 4; i++)
{
m_Points[i][0] *= t;
m_Points[i][1] *= t;
@@ -145,7 +145,7 @@ public:
///
void Init()
{
- for (uint i = 0; i < 4; i++)
+ for (size_t i = 0; i < 4; i++)
{
m_Points[i][0] = v2T(0);//0,0 -> 0,0 -> 1,1 -> 1,1.
m_Points[i][1] = v2T(0);
@@ -173,7 +173,7 @@ public:
{
bool set = false;
- for (uint i = 0; i < 4; i++)
+ for (size_t i = 0; i < 4; i++)
{
if ((m_Points[i][0] != v2T(0)) ||
(m_Points[i][1] != v2T(0)) ||
@@ -257,7 +257,7 @@ Curves operator * (const Curves& curves, const T& t)
{
Curves c(curves);
- for (uint i = 0; i < 4; i++)
+ for (size_t i = 0; i < 4; i++)
{
c.m_Points[i][0] *= t;
c.m_Points[i][1] *= t;
diff --git a/Source/Ember/Ember.h b/Source/Ember/Ember.h
index ccaacaf..abb7238 100644
--- a/Source/Ember/Ember.h
+++ b/Source/Ember/Ember.h
@@ -1075,14 +1075,15 @@ public:
///
/// The type of symmetry to add
/// The random context to use for generating random symmetry
- void AddSymmetry(int sym, QTIsaac& rand)
+ void AddSymmetry(intmax_t sym, QTIsaac& rand)
{
- size_t i, k, result = 0;
+ intmax_t k;
+ size_t i, result = 0;
T a;
if (sym == 0)
{
- static int symDistrib[] = {
+ static intmax_t symDistrib[] = {
-4, -3,
-2, -2, -2,
-1, -1, -1,
@@ -1356,6 +1357,9 @@ public:
case FLAME_MOTION_VIBRANCY:
APP_FMP(m_Vibrancy);
break;
+ case FLAME_MOTION_NONE:
+ default:
+ break;
}
}
}
@@ -1581,7 +1585,7 @@ public:
//Whether or not any symmetry was added. This field is in a bit of a state of conflict right now as flam3 has a severe bug.
//Xml field: "symmetry".
- int m_Symmetry;
+ intmax_t m_Symmetry;
//The number of iterations per pixel of the final output image. Note this is not affected by the increase in pixels in the
//histogram and DE filtering buffer due to supersampling. It can be affected by a non-zero zoom value though.
diff --git a/Source/Ember/EmberMotion.h b/Source/Ember/EmberMotion.h
index f3ae001..f672ec1 100644
--- a/Source/Ember/EmberMotion.h
+++ b/Source/Ember/EmberMotion.h
@@ -36,6 +36,7 @@ public:
///
/// The MotionParam object to copy
MotionParam(const MotionParam& other)
+ : pair ()
{
operator=(other);
}
@@ -70,8 +71,8 @@ public:
template
MotionParam &operator = (const MotionParam& other)
{
- this->first = other.first;
- this->second = T(other.second);
+ this->first = other.first;
+ this->second = T(other.second);
return *this;
}
diff --git a/Source/Ember/EmberPch.h b/Source/Ember/EmberPch.h
index 650afbe..3952f53 100644
--- a/Source/Ember/EmberPch.h
+++ b/Source/Ember/EmberPch.h
@@ -1,4 +1,6 @@
-#pragma once
+#ifdef WIN32
+ #pragma once
+#endif
///
/// Precompiled header file. Place all system includes here with appropriate #defines for different operating systems and compilers.
diff --git a/Source/Ember/EmberToXml.h b/Source/Ember/EmberToXml.h
index 37a0301..b288126 100644
--- a/Source/Ember/EmberToXml.h
+++ b/Source/Ember/EmberToXml.h
@@ -104,13 +104,19 @@ public:
b = false;
}
}
- catch (...)
+ catch (const std::exception& e)
{
- if (f.is_open())
- f.close();
-
+ cout << "Error: Writing flame " << filename << " failed: " << e.what() << endl;
b = false;
}
+ catch (...)
+ {
+ cout << "Error: Writing flame " << filename << " failed." << endl;
+ b = false;
+ }
+
+ if (f.is_open())
+ f.close();
return b;
}
@@ -125,7 +131,7 @@ public:
/// If true use integers instead of floating point numbers when embedding a non-hex formatted palette, else use floating point numbers.
/// If true, embed a hexadecimal palette instead of Xml Color tags, else use Xml color tags.
/// The Xml string representation of the passed in ember
- string ToString(Ember& ember, string extraAttributes, size_t printEditDepth, bool doEdits, bool intPalette, bool hexPalette = true)
+ string ToString(Ember& ember, const string& extraAttributes, size_t printEditDepth, bool doEdits, bool intPalette, bool hexPalette = true)
{
size_t i, j;
string s;
@@ -313,7 +319,7 @@ public:
/// The sheep generation used if > 0. Default: 0.
/// The sheep id used if > 0. Default: 0.
///
- xmlDocPtr CreateNewEditdoc(Ember* parent0, Ember* parent1, string action, string nick, string url, string id, string comment, int sheepGen = 0, int sheepId = 0)
+ xmlDocPtr CreateNewEditdoc(Ember* parent0, Ember* parent1, const string& action, const string& nick, const string& url, const string& id, const string& comment, intmax_t sheepGen = 0, intmax_t sheepId = 0)
{
char timeString[128];
time_t myTime;
@@ -750,6 +756,7 @@ private:
case MOTION_TRIANGLE:
os << "\"triangle\"";
break;
+ default:
case MOTION_SAW:
os << "\"saw\"";
break;
@@ -761,7 +768,7 @@ private:
T cx = 0.0;
T cy = 0.0;
- for (int i = 0; i < motion.m_MotionParams.size(); ++i)
+ for (size_t i = 0; i < motion.m_MotionParams.size(); ++i)
{
switch(motion.m_MotionParams[i].first)
{
@@ -816,6 +823,9 @@ private:
case FLAME_MOTION_VIBRANCY:
os << " vibrancy=\"" << motion.m_MotionParams[i].second << "\"";
break;
+ case FLAME_MOTION_NONE:
+ default:
+ break;
}
}
diff --git a/Source/Ember/Isaac.h b/Source/Ember/Isaac.h
index 2e4de38..9da06ee 100644
--- a/Source/Ember/Isaac.h
+++ b/Source/Ember/Isaac.h
@@ -57,7 +57,7 @@ class EMBER_API QTIsaac
public:
enum { N = (1 << ALPHA) };
UintBytes m_Cache;
- int m_LastIndex;
+ size_t m_LastIndex;
///
/// Global ISAAC RNG to be used from anywhere. This is not thread safe, so take caution to only
@@ -94,7 +94,7 @@ public:
Srand(a, b, c, s);
m_LastIndex = 0;
m_Cache.Uint = Rand();
- T temp = RandByte();//Need to call at least once so other libraries can link.
+ RandByte();//Need to call at least once so other libraries can link.
}
///
@@ -291,12 +291,12 @@ public:
{
if (s == nullptr)//Default to using time plus index as the seed if s was nullptr.
{
- for (int i = 0; i < N; i++)
- m_Rc.randrsl[i] = static_cast(NowMs()) + i;
+ for (size_t i = 0; i < N; i++)
+ m_Rc.randrsl[i] = static_cast(NowMs() + i);
}
else
{
- for (int i = 0; i < N; i++)
+ for (size_t i = 0; i < N; i++)
m_Rc.randrsl[i] = s[i];
}
diff --git a/Source/Ember/Palette.h b/Source/Ember/Palette.h
index f339649..713ca3e 100644
--- a/Source/Ember/Palette.h
+++ b/Source/Ember/Palette.h
@@ -39,7 +39,7 @@ public:
/// The index in the palette file
/// The size of the palette which should be 256
/// A pointer to 256 color entries
- Palette(const string& name, int index, uint size, v4T* xmlPaletteEntries)
+ Palette(const string& name, int index, size_t size, v4T* xmlPaletteEntries)
{
m_Name = name;
m_Index = index;
@@ -86,7 +86,7 @@ public:
0x00, 0x81, 0x96, 0x8d, 0x00, 0x81, 0x9a, 0x8d, 0x00, 0x85, 0x9a, 0x8d, 0x00, 0x89, 0x9e, 0x8d, 0x00, 0x89, 0x9e, 0x8d, 0x00, 0x8d, 0xa2, 0x97, 0x00, 0x95, 0xa2, 0x97, 0x00, 0x8d, 0xa2, 0x97,
0x00, 0x96, 0xa6, 0x8d, 0x00, 0x9a, 0xa1, 0x8d, 0x00, 0x9e, 0xa9, 0x84, 0x00, 0x9e, 0xa6, 0x7a, 0x00, 0xa2, 0xa5, 0x71, 0x00, 0x9e, 0xa6, 0x71, 0x00, 0x9a, 0xa6, 0x71, 0x00, 0x95, 0x9d, 0x71 };
- for (uint i = 0; i < size; i++)
+ for (size_t i = 0; i < size; i++)
{
m_Entries[i].a = T(palette15[i * 4 + 0]);
m_Entries[i].r = T(palette15[i * 4 + 1]);
@@ -208,7 +208,7 @@ public:
palette.m_Filename = m_Filename;
palette.m_Entries.resize(Size());
- for (uint i = 0; i < Size(); i++)
+ for (size_t i = 0; i < Size(); i++)
{
size_t ii = (i * 256) / COLORMAP_LENGTH;
T rgb[3], hsv[3];
@@ -348,7 +348,7 @@ public:
if (palette.Size() != Size())
palette.m_Entries.resize(Size());
- for (uint j = 0; j < palette.Size(); j++)
+ for (size_t j = 0; j < palette.Size(); j++)
{
palette.m_Entries[j] = m_Entries[j] * colorScalar;
palette.m_Entries[j].a = 1;
@@ -362,16 +362,16 @@ public:
///
/// The height of the output block
/// A vector holding the color values
- vector MakeRgbPaletteBlock(uint height)
+ vector MakeRgbPaletteBlock(size_t height)
{
size_t width = Size();
vector v(height * width * 3);
if (v.size() == (height * Size() * 3))
{
- for (uint i = 0; i < height; i++)
+ for (size_t i = 0; i < height; i++)
{
- for (uint j = 0; j < width; j++)
+ for (size_t j = 0; j < width; j++)
{
v[(width * 3 * i) + (j * 3)] = byte(m_Entries[j][0] * T(255));//Palettes are as [0..1], so convert to [0..255] here since it's for GUI display.
v[(width * 3 * i) + (j * 3) + 1] = byte(m_Entries[j][1] * T(255));
@@ -443,7 +443,7 @@ public:
/// Blue 0 - 1
static void HsvToRgb(T h, T s, T v, T& r, T& g, T& b)
{
- int j;
+ intmax_t j;
T f, p, q, t;
while (h >= 6)
@@ -522,7 +522,7 @@ public:
template
static void CalcNewRgb(bucketT* cBuf, T ls, T highPow, bucketT* newRgb)
{
- int rgbi;
+ size_t rgbi;
T newls, lsratio;
bucketT newhsv[3];
T maxa, maxc;
diff --git a/Source/Ember/PaletteList.h b/Source/Ember/PaletteList.h
index 37070e5..8a8d7a5 100644
--- a/Source/Ember/PaletteList.h
+++ b/Source/Ember/PaletteList.h
@@ -80,7 +80,7 @@ public:
Palette* GetRandomPalette()
{
auto p = m_Palettes.begin();
- int i = 0, paletteFileIndex = QTIsaac::GlobalRand->Rand() % Size();
+ size_t i = 0, paletteFileIndex = QTIsaac::GlobalRand->Rand() % Size();
//Move p forward i elements.
while (i < paletteFileIndex && p != m_Palettes.end())
@@ -91,7 +91,7 @@ public:
if (i < Size())
{
- int paletteIndex = QTIsaac::GlobalRand->Rand() % p->second.size();
+ size_t paletteIndex = QTIsaac::GlobalRand->Rand() % p->second.size();
if (paletteIndex < p->second.size())
return &p->second[paletteIndex];
@@ -106,11 +106,11 @@ public:
/// The filename of the palette to retrieve
/// The index of the palette to read. A value of -1 indicates a random palette.
/// A pointer to the requested palette if the index was in range, else nullptr.
- Palette* GetPalette(const string& filename, int i)
+ Palette* GetPalette(const string& filename, size_t i)
{
auto& palettes = m_Palettes[filename];
- if (!palettes.empty() && i < int(palettes.size()))
+ if (!palettes.empty() && i < palettes.size())
return &palettes[i];
return nullptr;
@@ -142,7 +142,7 @@ public:
/// The hue adjustment to apply
/// The palette to store the output
/// True if successful, else false.
- bool GetHueAdjustedPalette(const string& filename, int i, T hue, Palette& palette)
+ bool GetHueAdjustedPalette(const string& filename, size_t i, T hue, Palette& palette)
{
bool b = false;
diff --git a/Source/Ember/Point.h b/Source/Ember/Point.h
index a60cd62..d4e8274 100644
--- a/Source/Ember/Point.h
+++ b/Source/Ember/Point.h
@@ -151,6 +151,7 @@ public:
///
/// The Color object to copy
Color(const Color& color)
+ : v4T()
{
Color::operator=(color);
}
diff --git a/Source/Ember/Renderer.cpp b/Source/Ember/Renderer.cpp
index 294f63f..50ba671 100644
--- a/Source/Ember/Renderer.cpp
+++ b/Source/Ember/Renderer.cpp
@@ -671,7 +671,7 @@ Finish:
/// If true, embed a hexadecimal palette instead of Xml Color tags, else use Xml color tags.
/// The EmberImageComments object with image comments filled out
template
-EmberImageComments Renderer::ImageComments(EmberStats& stats, size_t printEditDepth, bool intPalette, bool hexPalette)
+EmberImageComments Renderer::ImageComments(const EmberStats& stats, size_t printEditDepth, bool intPalette, bool hexPalette)
{
ostringstream ss;
EmberImageComments comments;
@@ -708,7 +708,7 @@ void Renderer::MakeDmap(T colorScalar)
///
/// True if success, else false
template
-bool Renderer::Alloc()
+bool Renderer::Alloc(bool histOnly)
{
bool b = true;
bool lock =
@@ -730,6 +730,14 @@ bool Renderer::Alloc()
b &= (m_HistBuckets.size() == m_SuperSize);
}
+ if (histOnly)
+ {
+ if (lock)
+ LeaveResize();
+
+ return b;
+ }
+
if (m_SuperSize != m_AccumulatorBuckets.size())
{
m_AccumulatorBuckets.resize(m_SuperSize);
@@ -1224,7 +1232,7 @@ EmberStats Renderer::Iterate(size_t iterCount, size_t temporalSample
sp.sched_priority = m_Priority;
pthread_setschedparam(pthread_self(), SCHED_RR, &sp);
#else
- pthread_setschedprio(pthread_self(), (int)m_Priority);
+ pthread_setschedprio(pthread_self(), int(m_Priority));
#endif
//Timing t;
IterParams params;
@@ -1268,7 +1276,6 @@ EmberStats Renderer::Iterate(size_t iterCount, size_t temporalSample
if (m_Callback && threadIndex == 0)
{
percent = 100.0 *
-
double
(
double
@@ -1342,7 +1349,7 @@ template T Renderer::PixelsP
template T Renderer::PixelsPerUnitY() const { return m_PixelsPerUnitY; }
template bucketT Renderer::K1() const { return m_K1; }
template bucketT Renderer::K2() const { return m_K2; }
-template const CarToRas* Renderer::CoordMap() const { return &m_CarToRas; }
+template const CarToRas& Renderer::CoordMap() const { return m_CarToRas; }
template tvec4* Renderer::HistBuckets() { return m_HistBuckets.data(); }
template tvec4* Renderer::AccumulatorBuckets() { return m_AccumulatorBuckets.data(); }
template SpatialFilter* Renderer::GetSpatialFilter() { return m_SpatialFilter.get(); }
diff --git a/Source/Ember/Renderer.h b/Source/Ember/Renderer.h
index c0ded37..6c33fb8 100644
--- a/Source/Ember/Renderer.h
+++ b/Source/Ember/Renderer.h
@@ -38,9 +38,7 @@ namespace EmberNs
/// for every single function in this class, saying it can't find the implementation. This warning
/// can be safely ignored.
/// Template argument T expected to be float or double.
-/// Template argument bucketT was originally used to experiment with different types for the histogram, however
-/// the only types that work are float and double, so it's useless and should always match what T is.
-/// Mismatched types between T and bucketT are undefined.
+/// Template argument bucketT must always be float.
///
template
class EMBER_API Renderer : public RendererBase
@@ -65,12 +63,12 @@ public:
virtual bool CreateTemporalFilter(bool& newAlloc) override;
virtual size_t HistBucketSize() const override { return sizeof(tvec4); }
virtual eRenderStatus Run(vector& finalImage, double time = 0, size_t subBatchCountOverride = 0, bool forceOutput = false, size_t finalOffset = 0) override;
- virtual EmberImageComments ImageComments(EmberStats& stats, size_t printEditDepth = 0, bool intPalette = false, bool hexPalette = true) override;
+ virtual EmberImageComments ImageComments(const EmberStats& stats, size_t printEditDepth = 0, bool intPalette = false, bool hexPalette = true) override;
protected:
//New virtual functions to be overridden in derived renderers that use the GPU, but not accessed outside.
virtual void MakeDmap(T colorScalar);
- virtual bool Alloc();
+ virtual bool Alloc(bool histOnly = false);
virtual bool ResetBuckets(bool resetHist = true, bool resetAccum = true);
virtual eRenderStatus LogScaleDensityFilter();
virtual eRenderStatus GaussianDensityFilter();
@@ -89,7 +87,7 @@ public:
inline T PixelsPerUnitY() const;
inline bucketT K1() const;
inline bucketT K2() const;
- inline const CarToRas* CoordMap() const;
+ inline const CarToRas& CoordMap() const;
inline tvec4* HistBuckets();
inline tvec4* AccumulatorBuckets();
inline SpatialFilter* GetSpatialFilter();
diff --git a/Source/Ember/RendererBase.h b/Source/Ember/RendererBase.h
index 670cb32..7c45898 100644
--- a/Source/Ember/RendererBase.h
+++ b/Source/Ember/RendererBase.h
@@ -120,7 +120,7 @@ public:
virtual void ComputeQuality() = 0;
virtual void ComputeCamera() = 0;
virtual eRenderStatus Run(vector& finalImage, double time = 0, size_t subBatchCountOverride = 0, bool forceOutput = false, size_t finalOffset = 0) = 0;
- virtual EmberImageComments ImageComments(EmberStats& stats, size_t printEditDepth = 0, bool intPalette = false, bool hexPalette = true) = 0;
+ virtual EmberImageComments ImageComments(const EmberStats& stats, size_t printEditDepth = 0, bool intPalette = false, bool hexPalette = true) = 0;
virtual DensityFilterBase* GetDensityFilter() = 0;
//Non-virtual renderer properties, getters only.
diff --git a/Source/Ember/SheepTools.h b/Source/Ember/SheepTools.h
index d9472eb..a9b12f0 100644
--- a/Source/Ember/SheepTools.h
+++ b/Source/Ember/SheepTools.h
@@ -44,7 +44,7 @@ enum eCrossMode
/// Most functions in this class perform a particular action and return
/// a string describing what it did so it can be recorded in an Xml edit doc
/// to be saved with the ember when converting to Xml.
-/// Since it's members can occupy significant memory space and also have
+/// Since its members can occupy significant memory space and also have
/// hefty initialization sequences, it's important to declare one instance
/// and reuse it for the duration of the program instead of creating and deleting
/// them as local variables.
@@ -186,11 +186,10 @@ public:
/// The type of symmetry to add if random specified. If 0, it will be added randomly.
/// The speed to multiply the pre affine transforms by if the mutate mode is MUTATE_ALL_COEFS, else ignored.
/// A string describing what was done
- string Mutate(Ember& ember, eMutateMode mode, vector& useVars, int sym, T speed)
+ string Mutate(Ember& ember, eMutateMode mode, vector& useVars, intmax_t sym, T speed)
{
bool done = false;
size_t modXform;
- char ministr[32];
T randSelect;
ostringstream os;
Ember mutation;
@@ -285,14 +284,13 @@ public:
else if (mode == MUTATE_POST_XFORMS)
{
bool same = (m_Rand.Rand() & 3) > 0;//25% chance of using the same post for all of them.
- uint b = 1 + m_Rand.Rand() % 6;
+ size_t b = 1 + m_Rand.Rand() % 6;
- sprintf_s(ministr, 32, "(%d%s)", b, same ? " same" : "");
- os << "mutate post xforms " << ministr;
+ os << "mutate post xforms " << b << (same ? " same" : "");
for (size_t i = 0; i < ember.TotalXformCount(); i++)
{
- int copy = (i > 0) && same;
+ bool copy = (i > 0) && same;
Xform* xform = ember.GetTotalXform(i);
if (copy)//Copy the post from the first xform to the rest of them.
@@ -605,7 +603,7 @@ public:
{
vector useVars;
- Random(ember, useVars, static_cast(m_Rand.Frand(-2, 2)), 0);
+ Random(ember, useVars, static_cast(m_Rand.Frand(-2, 2)), 0);
}
///
@@ -615,7 +613,7 @@ public:
/// A list of variations to use. If empty, any variation can be used.
/// The symmetry type to use from -2 to 2
/// The number of xforms to use. If 0, a quasi random count is used.
- void Random(Ember& ember, vector& useVars, int sym, size_t specXforms)
+ void Random(Ember& ember, vector& useVars, intmax_t sym, size_t specXforms)
{
bool postid, addfinal = false;
int var, samed, multid, samepost;
@@ -806,9 +804,9 @@ public:
/// The number of test renders to try before giving up
/// Change palette if true, else keep trying with the same palette.
/// The resolution of the test histogram. This value ^ 3 will be used for the total size. Common value is 10.
- void ImproveColors(Ember& ember, int tries, bool changePalette, int colorResolution)
+ void ImproveColors(Ember& ember, size_t tries, bool changePalette, size_t colorResolution)
{
- int i;
+ size_t i;
T best, b;
Ember bestEmber = ember;
@@ -847,7 +845,7 @@ public:
/// The ember to render
/// The resolution of the test histogram. This value ^ 3 will be used for the total size. Common value is 10.
/// The number of histogram cells that weren't black
- T TryColors(Ember& ember, int colorResolution)
+ T TryColors(Ember& ember, size_t colorResolution)
{
byte* p;
size_t i, hits = 0, res = colorResolution;
@@ -903,7 +901,7 @@ public:
}
///
- /// Change around color coordinates. Optionall change out the entire palette.
+ /// Change around color coordinates. Optionally change out the entire palette.
///
/// The ember whose xform's color coordinates will be changed
/// Change palette if true, else don't
@@ -1071,7 +1069,7 @@ public:
/// The result of the spin
/// The frame in the sequence to be stored in the m_Time member of result
/// The interpolation time
- void Spin(Ember& parent, Ember* templ, Ember& result, int frame, T blend)
+ void Spin(Ember& parent, Ember* templ, Ember& result, size_t frame, T blend)
{
char temp[50];
@@ -1112,7 +1110,7 @@ public:
/// The frame in the sequence to be stored in the m_Time member of result
/// True if embers points to the first or last ember in the entire sequence, else false.
/// The interpolation time
- void SpinInter(Ember* parents, Ember* templ, Ember& result, int frame, bool seqFlag, T blend)
+ void SpinInter(Ember* parents, Ember* templ, Ember& result, size_t frame, bool seqFlag, T blend)
{
char temp[50];
@@ -1286,8 +1284,8 @@ public:
m_Samples.resize(samples);
params.m_Count = samples;
params.m_Skip = 20;
- //params.m_OneColDiv2 = m_Renderer->CoordMap()->OneCol() / 2;
- //params.m_OneRowDiv2 = m_Renderer->CoordMap()->OneRow() / 2;
+ //params.m_OneColDiv2 = m_Renderer->CoordMap().OneCol() / 2;
+ //params.m_OneRowDiv2 = m_Renderer->CoordMap().OneRow() / 2;
size_t bv = m_Iterator->Iterate(ember, params, m_Samples.data(), m_Rand);//Use a special fuse of 20, all other calls to this will use 15, or 100.
@@ -1349,7 +1347,7 @@ public:
/// The comment to include
/// The sheep generation used if > 0. Default: 0.
/// The sheep id used if > 0. Default: 0.
- void SetSpinParams(bool smooth, T stagger, T offsetX, T offsetY, string nick, string url, string id, string comment, int sheepGen, int sheepId)
+ void SetSpinParams(bool smooth, T stagger, T offsetX, T offsetY, const string& nick, const string& url, const string& id, const string& comment, intmax_t sheepGen, intmax_t sheepId)
{
m_Smooth = smooth;
m_SheepGen = sheepGen;
@@ -1365,8 +1363,8 @@ public:
private:
bool m_Smooth;
- int m_SheepGen;
- int m_SheepId;
+ intmax_t m_SheepGen;
+ intmax_t m_SheepId;
T m_Stagger;
T m_OffsetX;
T m_OffsetY;
diff --git a/Source/Ember/Timing.h b/Source/Ember/Timing.h
index ec829aa..bdd5fdf 100644
--- a/Source/Ember/Timing.h
+++ b/Source/Ember/Timing.h
@@ -62,19 +62,19 @@ public:
/// Return the begin time as a double.
///
///
- double BeginTime() { return static_cast(m_BeginTime.time_since_epoch().count()); }
+ double BeginTime() const { return static_cast(m_BeginTime.time_since_epoch().count()); }
///
/// Return the end time as a double.
///
///
- double EndTime() { return static_cast(m_EndTime.time_since_epoch().count()); }
+ double EndTime() const { return static_cast(m_EndTime.time_since_epoch().count()); }
///
/// Return the elapsed time in milliseconds.
///
/// The elapsed time in milliseconds as a double
- double ElapsedTime()
+ double ElapsedTime() const
{
duration elapsed = duration_cast(m_EndTime - m_BeginTime);
@@ -89,7 +89,7 @@ public:
///
/// The ms
/// The formatted string
- string Format(double ms)
+ string Format(double ms) const
{
stringstream ss;
diff --git a/Source/Ember/Utils.h b/Source/Ember/Utils.h
index 5af5f82..b225c1a 100644
--- a/Source/Ember/Utils.h
+++ b/Source/Ember/Utils.h
@@ -213,13 +213,19 @@ static bool ReadFile(const char* filename, string& buf, bool nullTerminate = tru
fclose(f);
}
}
- catch (...)
+ catch (const std::exception& e)
{
- if (f != nullptr)
- fclose(f);
-
+ cout << "Error: Reading file " << filename << " failed: " << e.what() << endl;
b = false;
}
+ catch (...)
+ {
+ cout << "Error: Reading file " << filename << " failed." << endl;
+ b = false;
+ }
+
+ if (f != nullptr)
+ fclose(f);
return b;
}
@@ -270,7 +276,7 @@ static void CopyVec(vector& dest, const vector& source, std::function
static void ClearVec(vector& vec, bool arrayDelete = false)
{
- for (uint i = 0; i < vec.size(); i++)
+ for (size_t i = 0; i < vec.size(); i++)
{
if (vec[i] != nullptr)
{
@@ -286,6 +292,32 @@ static void ClearVec(vector& vec, bool arrayDelete = false)
vec.clear();
}
+///
+/// Determine whether all elements in two containers are equal.
+///
+/// The first collection to compare
+/// The second collection to compare
+/// True if the sizes and all elements in both collections are equal, else false.
+template
+static bool Equal(const T& c1, const T& c2)
+{
+ bool equal = c1.size() == c2.size();
+
+ if (equal)
+ {
+ for (auto it1 = c1.begin(), it2 = c2.begin(); it1 != c1.end(); ++it1, ++it2)
+ {
+ if (*it1 != *it2)
+ {
+ equal = false;
+ break;
+ }
+ }
+ }
+
+ return equal;
+}
+
///
/// Thin wrapper around passing a vector to memset() to relieve
/// the caller of having to pass the size.
@@ -305,15 +337,15 @@ static inline void Memset(vector& vec, int val = 0)
/// The value to return the floor of
/// The floored value
template
-static inline int Floor(T val)
+static inline intmax_t Floor(T val)
{
if (val >= 0)
{
- return static_cast(val);
+ return static_cast(val);
}
else
{
- int i = static_cast(val);//Truncate.
+ intmax_t i = static_cast(val);//Truncate.
return i - (i > val);//Convert trunc to floor.
}
}
@@ -862,25 +894,9 @@ static string GetPath(const string& filename)
/// The value of the specified environment variable if found, else default
template
static inline T Arg(char* name, T def)
-{
- T t;
- return t;
-}
-
-///
-/// Template specialization for Arg<>() with a type of int.
-///
-/// The name of the environment variable to query
-/// The default value to return if the environment variable was not present
-/// The value of the specified environment variable if found, else default
-template <>
-#ifdef _WIN32
-static
-#endif
-int Arg(char* name, int def)
{
char* ch;
- int returnVal;
+ T returnVal;
#ifdef WIN32
size_t len;
errno_t err = _dupenv_s(&ch, &len, name);
@@ -892,7 +908,17 @@ int Arg(char* name, int def)
if (err || !ch)
returnVal = def;
else
- returnVal = atoi(ch);
+ {
+ T tempVal;
+ istringstream istr(ch);
+
+ istr >> tempVal;
+
+ if (!istr.bad() && !istr.fail())
+ returnVal = tempVal;
+ else
+ returnVal = def;
+ }
#ifdef WIN32
free(ch);
@@ -900,21 +926,6 @@ int Arg(char* name, int def)
return returnVal;
}
-///
-/// Template specialization for Arg<>() with a type of uint.
-///
-/// The name of the environment variable to query
-/// The default value to return if the environment variable was not present
-/// The value of the specified environment variable if found, else default
-template <>
-#ifdef _WIN32
-static
-#endif
-uint Arg(char* name, uint def)
-{
- return Arg(name, static_cast(def));
-}
-
///
/// Template specialization for Arg<>() with a type of bool.
///
@@ -930,39 +941,6 @@ bool Arg(char* name, bool def)
return (Arg(name, -999) != -999) ? true : def;
}
-///
-/// Template specialization for Arg<>() with a type of double.
-///
-/// The name of the environment variable to query
-/// The default value to return if the environment variable was not present
-/// The value of the specified environment variable if found, else default
-template <>
-#ifdef _WIN32
-static
-#endif
-double Arg(char* name, double def)
-{
- char* ch;
- double returnVal;
-#ifdef WIN32
- size_t len;
- errno_t err = _dupenv_s(&ch, &len, name);
-#else
- int err = 1;
- ch = getenv(name);
-#endif
-
- if (err || !ch)
- returnVal = def;
- else
- returnVal = atof(ch);
-
-#ifdef WIN32
- free(ch);
-#endif
- return returnVal;
-}
-
///
/// Template specialization for Arg<>() with a type of string.
///
@@ -1031,6 +1009,24 @@ static uint FindAndReplace(T& source, const T& find, const T& replace)
return replaceCount;
}
+///
+/// Split a string into tokens and place them in a vector.
+///
+/// The string to split
+/// The delimiter to split the string on
+/// The split strings, each as an element in a vector.
+static vector Split(const string& str, char del)
+{
+ string tok;
+ vector vec;
+ stringstream ss(str);
+
+ while (getline(ss, tok, del))
+ vec.push_back(tok);
+
+ return vec;
+}
+
///
/// Return a character pointer to a version string composed of the EMBER_OS and EMBER_VERSION values.
///
diff --git a/Source/Ember/Variation.h b/Source/Ember/Variation.h
index 2f44f26..4bc6aed 100644
--- a/Source/Ember/Variation.h
+++ b/Source/Ember/Variation.h
@@ -1428,7 +1428,7 @@ public:
/// The type of the parameter
/// The minimum value the parameter can be
/// The maximum value the parameter can be
- ParamWithName(T* param, string name, T def = 0, eParamType type = REAL, T min = TLOW, T max = TMAX)
+ ParamWithName(T* param, const string& name, T def = 0, eParamType type = REAL, T min = TLOW, T max = TMAX)
{
Init(param, name, def, type, min, max);
}
@@ -1481,7 +1481,7 @@ public:
/// The minimum value the parameter can be
/// The maximum value the parameter can be
/// Whether the parameter is actually a precalculated value. Default: false.
- void Init(T* param, string name, T def = 0, eParamType type = REAL, T min = TLOW, T max = TMAX, bool isPrecalc = false)
+ void Init(T* param, const string& name, T def = 0, eParamType type = REAL, T min = TLOW, T max = TMAX, bool isPrecalc = false)
{
m_Param = param;
m_Def = def;
diff --git a/Source/Ember/VariationList.h b/Source/Ember/VariationList.h
index 9e53a53..24c8727 100644
--- a/Source/Ember/VariationList.h
+++ b/Source/Ember/VariationList.h
@@ -355,7 +355,7 @@ public:
//Keep a list of which variations derive from ParametricVariation.
//Note that these are not new copies, rather just pointers to the original instances in m_Variations.
- for (uint i = 0; i < m_Variations.size(); i++)
+ for (size_t i = 0; i < m_Variations.size(); i++)
{
if (ParametricVariation* parVar = dynamic_cast*>(m_Variations[i]))
m_ParametricVariations.push_back(parVar);
@@ -412,7 +412,7 @@ public:
/// A pointer to the variation if found, else nullptr.
const Variation* GetVariation(eVariationId id) const
{
- for (uint i = 0; i < m_Variations.size() && m_Variations[i] != nullptr; i++)
+ for (size_t i = 0; i < m_Variations.size() && m_Variations[i] != nullptr; i++)
if (id == m_Variations[i]->VariationId())
return m_Variations[i];
@@ -435,7 +435,7 @@ public:
/// A pointer to the variation if found, else nullptr.
const Variation* GetVariation(const string& name) const
{
- for (uint i = 0; i < m_Variations.size() && m_Variations[i] != nullptr; i++)
+ for (size_t i = 0; i < m_Variations.size() && m_Variations[i] != nullptr; i++)
if (!_stricmp(name.c_str(), m_Variations[i]->Name().c_str()))
return m_Variations[i];
@@ -466,7 +466,7 @@ public:
/// The parametric variation with a matching name, else nullptr.
const ParametricVariation* GetParametricVariation(const string& name) const
{
- for (uint i = 0; i < m_ParametricVariations.size() && m_ParametricVariations[i] != nullptr; i++)
+ for (size_t i = 0; i < m_ParametricVariations.size() && m_ParametricVariations[i] != nullptr; i++)
if (!_stricmp(name.c_str(), m_ParametricVariations[i]->Name().c_str()))
return m_ParametricVariations[i];
@@ -480,9 +480,9 @@ public:
/// The index of the variation with the matching name, else -1
int GetVariationIndex(const string& name)
{
- for (uint i = 0; i < m_Variations.size() && m_Variations[i] != nullptr; i++)
+ for (size_t i = 0; i < m_Variations.size() && m_Variations[i] != nullptr; i++)
if (!_stricmp(name.c_str(), m_Variations[i]->Name().c_str()))
- return i;
+ return int(i);
return -1;
}
diff --git a/Source/Ember/Variations03.h b/Source/Ember/Variations03.h
index 90f39d5..99ba5a7 100644
--- a/Source/Ember/Variations03.h
+++ b/Source/Ember/Variations03.h
@@ -277,7 +277,7 @@ public:
virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
{
T r = Zeps(pow(helper.m_PrecalcSqrtSumSquares, m_Dist));
- int n = Floor(m_Power * rand.Frand01());
+ intmax_t n = Floor(m_Power * rand.Frand01());
T alpha = helper.m_PrecalcAtanyx + n * M_2PI / Zeps(T(Floor(m_Power)));
T sina = sin(alpha);
T cosa = cos(alpha);
@@ -2571,7 +2571,7 @@ public:
virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
{
- int n;
+ intmax_t n;
T z = 4 * m_Dist / m_Power;
T r = pow(helper.m_PrecalcSqrtSumSquares, z);
diff --git a/Source/Ember/Variations04.h b/Source/Ember/Variations04.h
index e5184d0..43faed3 100644
--- a/Source/Ember/Variations04.h
+++ b/Source/Ember/Variations04.h
@@ -1372,12 +1372,13 @@ public:
virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
{
- int i, j, l, k, m, m1, n, n1;
+ intmax_t l, k;
+ int i, j, m, m1, n, n1;
T r, rMin, offsetX, offsetY, x0 = 0, y0 = 0, x, y;
rMin = 20;
- m = Floor(helper.In.x / m_Step);
- n = Floor(helper.In.y / m_Step);
+ m = int(Floor(helper.In.x / m_Step));
+ n = int(Floor(helper.In.y / m_Step));
for (i = -1; i < 2; i++)
{
diff --git a/Source/Ember/Variations05.h b/Source/Ember/Variations05.h
index 76958f8..0f59d9c 100644
--- a/Source/Ember/Variations05.h
+++ b/Source/Ember/Variations05.h
@@ -95,8 +95,8 @@ public:
virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
{
- int m = Floor(T(0.5) * helper.In.x / m_Sc);
- int n = Floor(T(0.5) * helper.In.y / m_Sc);
+ int m = int(Floor(T(0.5) * helper.In.x / m_Sc));
+ int n = int(Floor(T(0.5) * helper.In.y / m_Sc));
T x = helper.In.x - (m * 2 + 1) * m_Sc;
T y = helper.In.y - (n * 2 + 1) * m_Sc;
T u = Zeps(Hypot(x, y));
@@ -277,7 +277,7 @@ public:
virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
{
- int m, n, iters = 0;
+ intmax_t m, n, iters = 0;
T x, y, u;
do
@@ -293,7 +293,7 @@ public:
if (++iters > 10)
break;
}
- while ((DiscreteNoise2(int(m + m_Seed), n) > m_Dens) || (u > (T(0.3) + T(0.7) * DiscreteNoise2(m + 10, n + 3)) * m_Sc));
+ while ((DiscreteNoise2(int(m + m_Seed), int(n)) > m_Dens) || (u > (T(0.3) + T(0.7) * DiscreteNoise2(int(m + 10), int(n + 3))) * m_Sc));
helper.Out.x = m_Weight * (x + (m * 2 + 1) * m_Sc);
helper.Out.y = m_Weight * (y + (n * 2 + 1) * m_Sc);
@@ -406,14 +406,14 @@ public:
Trans(m_X, m_Y, helper.In.x, helper.In.y, &ux, &uy);
- int m = Floor(T(0.5) * ux / m_Sc);
- int n = Floor(T(0.5) * uy / m_Sc);
+ intmax_t m = Floor(T(0.5) * ux / m_Sc);
+ intmax_t n = Floor(T(0.5) * uy / m_Sc);
x = ux - (m * 2 + 1) * m_Sc;
y = uy - (n * 2 + 1) * m_Sc;
u = Hypot(x, y);
- if ((DiscreteNoise2(int(m + m_Seed), n) > m_Dens) || (u > (T(0.3) + T(0.7) * DiscreteNoise2(m + 10, n + 3)) * m_Sc))
+ if ((DiscreteNoise2(int(m + m_Seed), int(n)) > m_Dens) || (u > (T(0.3) + T(0.7) * DiscreteNoise2(int(m + 10), int(n + 3))) * m_Sc))
{
ux = ux;
uy = uy;
@@ -548,7 +548,7 @@ private:
void CircleR(T* ux, T* vy, QTIsaac& rand)
{
- int m, n, iters = 0;
+ intmax_t m, n, iters = 0;
T x, y, alpha, u;
do
@@ -558,14 +558,14 @@ private:
m = Floor(T(0.5) * x / m_Sc);
n = Floor(T(0.5) * y / m_Sc);
alpha = M_2PI * rand.Frand01();
- u = T(0.3) + T(0.7) * DiscreteNoise2(m + 10, n + 3);
+ u = T(0.3) + T(0.7) * DiscreteNoise2(int(m + 10), int(n + 3));
x = u * cos(alpha);
y = u * sin(alpha);
if (++iters > 10)
break;
}
- while (DiscreteNoise2(int(m + m_Seed), n) > m_Dens);
+ while (DiscreteNoise2(int(m + m_Seed), int(n)) > m_Dens);
*ux = x + (m * 2 + 1) * m_Sc;
*vy = y + (n * 2 + 1) * m_Sc;
@@ -2704,7 +2704,7 @@ public:
virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
{
- int m, n;
+ intmax_t m, n;
T alpha, beta, offsetAl, offsetBe, offsetGa, x, y;
//Transfer to trilinear coordinates, normalized to real distances from triangle sides.
diff --git a/Source/Ember/VariationsDC.h b/Source/Ember/VariationsDC.h
index 81070c9..a7464e4 100644
--- a/Source/Ember/VariationsDC.h
+++ b/Source/Ember/VariationsDC.h
@@ -878,7 +878,7 @@ public:
<< "\t\t inside = 1;\n"
<< "\t\t}\n"
<< "\n"
- << "\t\tif (" << zeroEdges << " && !inside)\n"
+ << "\t\tif (" << zeroEdges << " != 0.0 && !inside)\n"
<< "\t\t{\n"
<< "\t\t u = v = 0;\n"
<< "\t\t}\n"
diff --git a/Source/Ember/XmlToEmber.h b/Source/Ember/XmlToEmber.h
index 87afb53..1a4d6d4 100644
--- a/Source/Ember/XmlToEmber.h
+++ b/Source/Ember/XmlToEmber.h
@@ -315,7 +315,7 @@ public:
//An adjustment of +/- 360 degrees is made until this is true.
if (emberSize > 1)
{
- for (uint i = 1; i < emberSize; i++)
+ for (size_t i = 1; i < emberSize; i++)
{
//Only do this adjustment if not in compat mode..
if (embers[i - 1].m_AffineInterp != INTERP_COMPAT && embers[i - 1].m_AffineInterp != INTERP_OLDER)
@@ -362,79 +362,22 @@ public:
}
///
- /// Convert the string to a floating point value and return a bool indicating success.
+ /// Thin wrapper around converting the string to a numeric value and return a bool indicating success.
/// See error report for errors.
///
/// The string to convert
/// The converted value
/// True if success, else false.
- bool Atof(const char* str, T& val)
+ template
+ bool Aton(const char* str, valT& val)
{
bool b = true;
- char* endp;
const char* loc = __FUNCTION__;
+ std::istringstream istr(str);
- //Reset errno.
- errno = 0;//Note that this is not thread-safe.
+ istr >> val;
- //Convert the string using strtod().
- val = T(strtod(str, &endp));
-
- //Check errno & return string.
- if (endp != str + strlen(str))
- {
- m_ErrorReport.push_back(string(loc) + " : Error converting " + string(str) + ", extra chars");
- b = false;
- }
-
- if (errno)
- {
- m_ErrorReport.push_back(string(loc) + " : Error converting " + string(str));
- b = false;
- }
-
- return b;
- }
-
- ///
- /// Thin wrapper around Atoi().
- /// See error report for errors.
- ///
- /// The string to convert
- /// The converted uinteger value
- /// True if success, else false.
- bool Atoi(const char* str, uint& val)
- {
- return Atoi(str, reinterpret_cast(val));
- }
-
- ///
- /// Convert the string to an uinteger value and return a bool indicating success.
- /// See error report for errors.
- ///
- /// The string to convert
- /// The converted uinteger value
- /// True if success, else false.
- bool Atoi(const char* str, int& val)
- {
- bool b = true;
- char* endp;
- const char* loc = __FUNCTION__;
-
- //Reset errno.
- errno = 0;//Note that this is not thread-safe.
-
- //Convert the string using strtod().
- val = strtol(str, &endp, 10);
-
- //Check errno & return string.
- if (endp != str + strlen(str))
- {
- m_ErrorReport.push_back(string(loc) + " : Error converting " + string(str) + ", extra chars");
- b = false;
- }
-
- if (errno)
+ if (istr.bad() || istr.fail())
{
m_ErrorReport.push_back(string(loc) + " : Error converting " + string(str));
b = false;
@@ -443,6 +386,7 @@ public:
return b;
}
+
///
/// Convert an integer to a string.
/// Just a wrapper around _itoa_s() which wraps the result in a std::string.
@@ -554,11 +498,11 @@ private:
{
bool ret = true;
bool fromEmber = false;
- uint newLinear = 0;
+ size_t newLinear = 0;
char* attStr;
const char* loc = __FUNCTION__;
int soloXform = -1;
- uint i, j, count, index = 0;
+ size_t i, count, index = 0;
double vals[16];
xmlAttrPtr att, curAtt;
xmlNodePtr editNode, childNode, motionNode;
@@ -577,38 +521,38 @@ private:
attStr = reinterpret_cast(xmlGetProp(emberNode, curAtt->name));
//First parse out simple float reads.
- if (ParseAndAssignFloat(curAtt->name, attStr, "time", currentEmber.m_Time, ret)) { }
- else if (ParseAndAssignFloat(curAtt->name, attStr, "scale", currentEmber.m_PixelsPerUnit, ret)) { currentEmber.m_OrigPixPerUnit = currentEmber.m_PixelsPerUnit; }
- else if (ParseAndAssignFloat(curAtt->name, attStr, "rotate", currentEmber.m_Rotate, ret)) { }
- else if (ParseAndAssignFloat(curAtt->name, attStr, "zoom", currentEmber.m_Zoom, ret)) { }
- else if (ParseAndAssignFloat(curAtt->name, attStr, "filter", currentEmber.m_SpatialFilterRadius, ret)) { }
- else if (ParseAndAssignFloat(curAtt->name, attStr, "temporal_filter_width", currentEmber.m_TemporalFilterWidth, ret)) { }
- else if (ParseAndAssignFloat(curAtt->name, attStr, "temporal_filter_exp", currentEmber.m_TemporalFilterExp, ret)) { }
- else if (ParseAndAssignFloat(curAtt->name, attStr, "quality", currentEmber.m_Quality, ret)) { }
- else if (ParseAndAssignFloat(curAtt->name, attStr, "brightness", currentEmber.m_Brightness, ret)) { }
- else if (ParseAndAssignFloat(curAtt->name, attStr, "gamma", currentEmber.m_Gamma, ret)) { }
- else if (ParseAndAssignFloat(curAtt->name, attStr, "highlight_power", currentEmber.m_HighlightPower, ret)) { }
- else if (ParseAndAssignFloat(curAtt->name, attStr, "vibrancy", currentEmber.m_Vibrancy, ret)) { }
- else if (ParseAndAssignFloat(curAtt->name, attStr, "estimator_radius", currentEmber.m_MaxRadDE, ret)) { }
- else if (ParseAndAssignFloat(curAtt->name, attStr, "estimator_minimum", currentEmber.m_MinRadDE, ret)) { }
- else if (ParseAndAssignFloat(curAtt->name, attStr, "estimator_curve", currentEmber.m_CurveDE, ret)) { }
- else if (ParseAndAssignFloat(curAtt->name, attStr, "gamma_threshold", currentEmber.m_GammaThresh, ret)) { }
- else if (ParseAndAssignFloat(curAtt->name, attStr, "cam_zpos", currentEmber.m_CamZPos, ret)) { }
- else if (ParseAndAssignFloat(curAtt->name, attStr, "cam_persp", currentEmber.m_CamPerspective, ret)) { }
- else if (ParseAndAssignFloat(curAtt->name, attStr, "cam_perspective", currentEmber.m_CamPerspective, ret)) { }//Apo bug.
- else if (ParseAndAssignFloat(curAtt->name, attStr, "cam_yaw", currentEmber.m_CamYaw, ret)) { }
- else if (ParseAndAssignFloat(curAtt->name, attStr, "cam_pitch", currentEmber.m_CamPitch, ret)) { }
- else if (ParseAndAssignFloat(curAtt->name, attStr, "cam_dof", currentEmber.m_CamDepthBlur, ret)) { }
+ if (ParseAndAssign(curAtt->name, attStr, "time", currentEmber.m_Time, ret)) { }
+ else if (ParseAndAssign(curAtt->name, attStr, "scale", currentEmber.m_PixelsPerUnit, ret)) { currentEmber.m_OrigPixPerUnit = currentEmber.m_PixelsPerUnit; }
+ else if (ParseAndAssign(curAtt->name, attStr, "rotate", currentEmber.m_Rotate, ret)) { }
+ else if (ParseAndAssign(curAtt->name, attStr, "zoom", currentEmber.m_Zoom, ret)) { }
+ else if (ParseAndAssign(curAtt->name, attStr, "filter", currentEmber.m_SpatialFilterRadius, ret)) { }
+ else if (ParseAndAssign(curAtt->name, attStr, "temporal_filter_width", currentEmber.m_TemporalFilterWidth, ret)) { }
+ else if (ParseAndAssign(curAtt->name, attStr, "temporal_filter_exp", currentEmber.m_TemporalFilterExp, ret)) { }
+ else if (ParseAndAssign(curAtt->name, attStr, "quality", currentEmber.m_Quality, ret)) { }
+ else if (ParseAndAssign(curAtt->name, attStr, "brightness", currentEmber.m_Brightness, ret)) { }
+ else if (ParseAndAssign(curAtt->name, attStr, "gamma", currentEmber.m_Gamma, ret)) { }
+ else if (ParseAndAssign(curAtt->name, attStr, "highlight_power", currentEmber.m_HighlightPower, ret)) { }
+ else if (ParseAndAssign(curAtt->name, attStr, "vibrancy", currentEmber.m_Vibrancy, ret)) { }
+ else if (ParseAndAssign(curAtt->name, attStr, "estimator_radius", currentEmber.m_MaxRadDE, ret)) { }
+ else if (ParseAndAssign(curAtt->name, attStr, "estimator_minimum", currentEmber.m_MinRadDE, ret)) { }
+ else if (ParseAndAssign(curAtt->name, attStr, "estimator_curve", currentEmber.m_CurveDE, ret)) { }
+ else if (ParseAndAssign(curAtt->name, attStr, "gamma_threshold", currentEmber.m_GammaThresh, ret)) { }
+ else if (ParseAndAssign(curAtt->name, attStr, "cam_zpos", currentEmber.m_CamZPos, ret)) { }
+ else if (ParseAndAssign(curAtt->name, attStr, "cam_persp", currentEmber.m_CamPerspective, ret)) { }
+ else if (ParseAndAssign(curAtt->name, attStr, "cam_perspective", currentEmber.m_CamPerspective, ret)) { }//Apo bug.
+ else if (ParseAndAssign(curAtt->name, attStr, "cam_yaw", currentEmber.m_CamYaw, ret)) { }
+ else if (ParseAndAssign(curAtt->name, attStr, "cam_pitch", currentEmber.m_CamPitch, ret)) { }
+ else if (ParseAndAssign(curAtt->name, attStr, "cam_dof", currentEmber.m_CamDepthBlur, ret)) { }
//Parse simple int reads.
- else if (ParseAndAssignInt(curAtt->name, attStr, "palette", currentEmber.m_Palette.m_Index, ret)) { }
- else if (ParseAndAssignInt(curAtt->name, attStr, "oversample", currentEmber.m_Supersample , ret)) { }
- else if (ParseAndAssignInt(curAtt->name, attStr, "supersample", currentEmber.m_Supersample , ret)) { }
- else if (ParseAndAssignInt(curAtt->name, attStr, "temporal_samples", currentEmber.m_TemporalSamples, ret)) { }
- else if (ParseAndAssignInt(curAtt->name, attStr, "sub_batch_size", currentEmber.m_SubBatchSize , ret)) { }
- else if (ParseAndAssignInt(curAtt->name, attStr, "fuse", currentEmber.m_FuseCount , ret)) { }
- else if (ParseAndAssignInt(curAtt->name, attStr, "soloxform", soloXform , ret)) { }
- else if (ParseAndAssignInt(curAtt->name, attStr, "new_linear", newLinear , ret)) { }
+ else if (ParseAndAssign(curAtt->name, attStr, "palette", currentEmber.m_Palette.m_Index, ret)) { }
+ else if (ParseAndAssign(curAtt->name, attStr, "oversample", currentEmber.m_Supersample , ret)) { }
+ else if (ParseAndAssign(curAtt->name, attStr, "supersample", currentEmber.m_Supersample , ret)) { }
+ else if (ParseAndAssign(curAtt->name, attStr, "temporal_samples", currentEmber.m_TemporalSamples, ret)) { }
+ else if (ParseAndAssign(curAtt->name, attStr, "sub_batch_size", currentEmber.m_SubBatchSize , ret)) { }
+ else if (ParseAndAssign(curAtt->name, attStr, "fuse", currentEmber.m_FuseCount , ret)) { }
+ else if (ParseAndAssign(curAtt->name, attStr, "soloxform", soloXform , ret)) { }
+ else if (ParseAndAssign(curAtt->name, attStr, "new_linear", newLinear , ret)) { }
//Parse more complicated reads that have multiple possible values.
else if (!Compare(curAtt->name, "interpolation"))
@@ -718,7 +662,7 @@ private:
for (i = 0; i < 4; i++)
{
- for (j = 0; j < 4; j++)
+ for (glm::length_t j = 0; j < 4; j++)
{
ss >> currentEmber.m_Curves.m_Points[i][j].x;
ss >> currentEmber.m_Curves.m_Points[i][j].y;
@@ -759,7 +703,7 @@ private:
if (!Compare(curAtt->name, "index"))
{
- Atoi(attStr, index);
+ Aton(attStr, index);
}
else if(!Compare(curAtt->name, "rgb"))
{
@@ -819,7 +763,7 @@ private:
if (!Compare(curAtt->name, "count"))
{
- Atoi(attStr, count);
+ Aton(attStr, count);
}
else if (!Compare(curAtt->name, "data"))
{
@@ -842,11 +786,6 @@ private:
//Make sure BOTH are not specified, otherwise either are ok.
int numColors = 0;
int numBytes = 0;
- int index0, index1;
- T hue0, hue1;
- T blend = 0.5;
- index0 = index1 = -1;
- hue0 = hue1 = 0.0;
//Loop through the attributes of the palette element.
att = childNode->properties;
@@ -863,7 +802,7 @@ private:
if (!Compare(curAtt->name, "count"))
{
- Atoi(attStr, numColors);
+ Aton(attStr, numColors);
}
else if (!Compare(curAtt->name, "format"))
{
@@ -915,7 +854,7 @@ private:
if (!Compare(curAtt->name, "kind"))
{
- Atoi(attStr, symKind);
+ Aton(attStr, symKind);
}
else
{
@@ -1016,8 +955,8 @@ private:
{
attStr = reinterpret_cast(xmlGetProp(childNode, curAtt->name));
- if (ParseAndAssignFloat(curAtt->name, attStr, "motion_frequency", motion.m_MotionFreq, ret)) { }
- else if (ParseAndAssignFloat(curAtt->name, attStr, "motion_offset", motion.m_MotionOffset, ret)) { }
+ if (ParseAndAssign(curAtt->name, attStr, "motion_frequency", motion.m_MotionFreq, ret)) { }
+ else if (ParseAndAssign(curAtt->name, attStr, "motion_offset", motion.m_MotionOffset, ret)) { }
else if (!Compare(curAtt->name, "motion_function"))
{
string func(attStr);
@@ -1135,7 +1074,7 @@ private:
bool r = false;
T val = 0.0;
- if (Atof(attStr, val))
+ if (Aton(attStr, val))
{
motion.m_MotionParams.push_back(MotionParam(param, val));
r = true;
@@ -1160,7 +1099,7 @@ private:
bool success = true;
char* attStr;
const char* loc = __FUNCTION__;
- uint j;
+ size_t j;
T temp;
double a, b, c, d, e, f;
double vals[10];
@@ -1180,13 +1119,13 @@ private:
attStr = reinterpret_cast(xmlGetProp(childNode, curAtt->name));
//First parse out simple float reads.
- if (ParseAndAssignFloat(curAtt->name, attStr, "weight", xform.m_Weight, success)) { }
- else if (ParseAndAssignFloat(curAtt->name, attStr, "color_speed", xform.m_ColorSpeed, success)) { }
- else if (ParseAndAssignFloat(curAtt->name, attStr, "animate", xform.m_Animate, success)) { }
- else if (ParseAndAssignFloat(curAtt->name, attStr, "opacity", xform.m_Opacity, success)) { }
- else if (ParseAndAssignFloat(curAtt->name, attStr, "var_color", xform.m_DirectColor, success)) { }
- else if (ParseAndAssignFloat(curAtt->name, attStr, "motion_frequency", xform.m_MotionFreq, success)) { }
- else if (ParseAndAssignFloat(curAtt->name, attStr, "motion_offset", xform.m_MotionOffset, success)) { }
+ if (ParseAndAssign(curAtt->name, attStr, "weight", xform.m_Weight, success)) { }
+ else if (ParseAndAssign(curAtt->name, attStr, "color_speed", xform.m_ColorSpeed, success)) { }
+ else if (ParseAndAssign(curAtt->name, attStr, "animate", xform.m_Animate, success)) { }
+ else if (ParseAndAssign(curAtt->name, attStr, "opacity", xform.m_Opacity, success)) { }
+ else if (ParseAndAssign(curAtt->name, attStr, "var_color", xform.m_DirectColor, success)) { }
+ else if (ParseAndAssign(curAtt->name, attStr, "motion_frequency", xform.m_MotionFreq, success)) { }
+ else if (ParseAndAssign(curAtt->name, attStr, "motion_offset", xform.m_MotionOffset, success)) { }
//Parse more complicated reads that have multiple possible values.
else if (!Compare(curAtt->name, "name"))
@@ -1198,7 +1137,7 @@ private:
{
//Deprecated, set both color_speed and animate to this value.
//Huh? Either set it or not?
- Atof(attStr, temp);
+ Aton(attStr, temp);
xform.m_ColorSpeed = (1 - temp) / 2;
xform.m_Animate = T(temp > 0 ? 0 : 1);
}
@@ -1297,7 +1236,7 @@ private:
{
auto varCopy = var->Copy();
- Atof(attStr, varCopy->m_Weight);
+ Aton(attStr, varCopy->m_Weight);
xform.AddVariation(varCopy);
}
//else
@@ -1321,7 +1260,7 @@ private:
for (j = 0; j < xform.TotalVariationCount(); j++)
xform.GetVariation(j)->m_Weight = 0;
- if (Atof(attStr, temp))
+ if (Aton(attStr, temp))
{
uint iTemp = static_cast(temp);
@@ -1349,7 +1288,7 @@ private:
{
attStr = reinterpret_cast(xmlGetProp(childNode, curAtt->name));
- if (Atof(attStr, temp))
+ if (Aton(attStr, temp))
{
for (j = 0; j < xform.TotalVariationCount(); j++)
xform.GetVariation(j)->m_Weight = temp;
@@ -1366,7 +1305,7 @@ private:
}
//Now that all xforms have been parsed, go through and try to find params for the parametric variations.
- for (uint i = 0; i < xform.TotalVariationCount(); i++)
+ for (size_t i = 0; i < xform.TotalVariationCount(); i++)
{
if (ParametricVariation* parVar = dynamic_cast*>(xform.GetVariation(i)))
{
@@ -1381,7 +1320,7 @@ private:
T val = 0;
attStr = CX(xmlGetProp(childNode, curAtt->name));
- if (Atof(attStr, val))
+ if (Aton(attStr, val))
{
parVar->SetParamVal(name, val);
}
@@ -1476,14 +1415,14 @@ private:
/// The number of colors present
/// The number of channels in each color
/// True if there were no errors, else false.
- bool ParseHexColors(char* colstr, Ember& ember, int numColors, int chan)
+ bool ParseHexColors(char* colstr, Ember& ember, size_t numColors, intmax_t chan)
{
- int colorIndex = 0;
- int colorCount = 0;
+ size_t colorIndex = 0;
+ size_t colorCount = 0;
uint r, g, b, a;
int ret;
char tmps[2];
- int skip = static_cast(abs(chan));
+ size_t skip = std::abs(chan);
bool ok = true;
const char* loc = __FUNCTION__;
@@ -1539,47 +1478,25 @@ private:
}
///
- /// Wrapper to parse a floating point Xml value and convert it to float.
+ /// Wrapper to parse a numeric Xml string value and convert it.
///
/// The xml tag to parse
/// The name of the Xml attribute
/// The name of the Xml tag
/// The parsed value
- /// Bitwise ANDed with true if name matched str and the call to Atof() succeeded, else false. Used for keeping a running value between successive calls.
- /// True if the tag was matched, else false
- bool ParseAndAssignFloat(const xmlChar* name, const char* attStr, const char* str, T& val, bool& b)
+ /// Bitwise ANDed with true if name matched str and the conversion succeeded, else false. Used for keeping a running value between successive calls.
+ /// True if the tag was matched and the conversion succeeded, else false
+ template
+ bool ParseAndAssign(const xmlChar* name, const char* attStr, const char* str, valT& val, bool& b)
{
bool ret = false;
if (!Compare(name, str))
{
- b &= Atof(attStr, val);
- ret = true;//Means the strcmp() was right, but doesn't necessarily mean the conversion went ok.
- }
+ istringstream istr(attStr);
- return ret;
- }
-
- ///
- /// Wrapper to parse an int Xml string value and convert it to an int.
- ///
- /// The xml tag to parse
- /// The name of the Xml attribute
- /// The name of the Xml tag
- /// The parsed value
- /// Bitwise ANDed with true if name matched str and the call to Atoi() succeeded, else false. Used for keeping a running value between successive calls.
- /// True if the tag was matched, else false
- template
- bool ParseAndAssignInt(const xmlChar* name, const char* attStr, const char* str, intT& val, bool& b)
- {
- bool ret = false;
- T fval = 0;
-
- if (!Compare(name, str))
- {
- b &= Atof(attStr, fval);
- val = static_cast(fval);
- ret = true;//Means the strcmp() was right, but doesn't necessarily mean the conversion went ok.
+ istr >> val;
+ ret = !istr.bad() && !istr.fail();//Means the Compare() was right, and the conversion succeeded.
}
return ret;
diff --git a/Source/EmberAnimate/EmberAnimate.cpp b/Source/EmberAnimate/EmberAnimate.cpp
index e36ed1b..c03fc44 100644
--- a/Source/EmberAnimate/EmberAnimate.cpp
+++ b/Source/EmberAnimate/EmberAnimate.cpp
@@ -8,10 +8,10 @@
///
/// A populated EmberOptions object which specifies all program options to be used
/// True if success, else false.
-template
+template
bool EmberAnimate(EmberOptions& opt)
{
- OpenCLWrapper wrapper;
+ OpenCLInfo& info(OpenCLInfo::Instance());
std::cout.imbue(std::locale(""));
@@ -21,53 +21,93 @@ bool EmberAnimate(EmberOptions& opt)
if (opt.OpenCLInfo())
{
cout << "\nOpenCL Info: " << endl;
- cout << wrapper.DumpInfo();
+ cout << info.DumpInfo();
return true;
}
//Regular variables.
Timing t;
bool unsorted = false;
- bool startXml = false;
- bool finishXml = false;
- bool appendXml = false;
- uint finalImageIndex = 0;
- uint i, channels, ftime, padding;
- string s, flameName, filename, inputPath = GetPath(opt.Input());
- ostringstream os;
+ uint channels, padding;
+ size_t i;
+ string inputPath = GetPath(opt.Input());
vector> embers;
- EmberStats stats;
- EmberReport emberReport;
- EmberImageComments comments;
- Ember centerEmber;
XmlToEmber parser;
EmberToXml emberToXml;
- vector finalImages[2];
- std::thread writeThread;
- unique_ptr> progress(new RenderProgress());
- unique_ptr> renderer(CreateRenderer(opt.EmberCL() ? OPENCL_RENDERER : CPU_RENDERER, opt.Platform(), opt.Device(), false, 0, emberReport));
- vector errorReport = emberReport.ErrorReport();
+ EmberReport emberReport;
+ const vector> devices = Devices(opt.Devices());
+ std::atomic atomfTime;
+ vector threadVec;
+ unique_ptr> progress;
+ vector>> renderers;
+ vector errorReport;
+ CriticalSection verboseCs;
- if (!errorReport.empty())
- emberReport.DumpErrorReport();
-
- if (!renderer.get())
+ if (opt.EmberCL())
{
- cout << "Renderer creation failed, exiting." << endl;
- return false;
+ renderers = CreateRenderers(OPENCL_RENDERER, devices, false, 0, emberReport);
+ errorReport = emberReport.ErrorReport();
+
+ if (!errorReport.empty())
+ emberReport.DumpErrorReport();
+
+ if (!renderers.size() || renderers.size() != devices.size())
+ {
+ cout << "Only created " << renderers.size() << " renderers out of " << devices.size() << " requested, exiting." << endl;
+ return false;
+ }
+
+ if (opt.DoProgress())
+ {
+ progress = unique_ptr>(new RenderProgress());
+ renderers[0]->Callback(progress.get());
+ }
+
+ cout << "Using OpenCL to render." << endl;
+
+ if (opt.Verbose())
+ {
+ for (auto& device : devices)
+ {
+ cout << "Platform: " << info.PlatformName(device.first) << endl;
+ cout << "Device: " << info.DeviceName(device.first, device.second) << endl;
+ }
+ }
+
+ if (opt.ThreadCount() > 1)
+ cout << "Cannot specify threads with OpenCL, using 1 thread." << endl;
+
+ opt.ThreadCount(1);
+
+ for (auto& r : renderers)
+ r->ThreadCount(opt.ThreadCount(), opt.IsaacSeed() != "" ? opt.IsaacSeed().c_str() : nullptr);
+
+ if (opt.BitsPerChannel() != 8)
+ {
+ cout << "Bits per channel cannot be anything other than 8 with OpenCL, setting to 8." << endl;
+ opt.BitsPerChannel(8);
+ }
}
-
- if (opt.EmberCL() && renderer->RendererType() != OPENCL_RENDERER)//OpenCL init failed, so fall back to CPU.
- opt.EmberCL(false);
-
- if (!InitPaletteList(opt.PalettePath()))
- return false;
-
- if (!ParseEmberFile(parser, opt.Input(), embers))
- return false;
-
- if (!opt.EmberCL())
+ else
{
+ unique_ptr> tempRenderer(CreateRenderer(CPU_RENDERER, devices, false, 0, emberReport));
+ errorReport = emberReport.ErrorReport();
+
+ if (!errorReport.empty())
+ emberReport.DumpErrorReport();
+
+ if (!tempRenderer.get())
+ {
+ cout << "Renderer creation failed, exiting." << endl;
+ return false;
+ }
+
+ if (opt.DoProgress())
+ {
+ progress = unique_ptr>(new RenderProgress());
+ tempRenderer->Callback(progress.get());
+ }
+
if (opt.ThreadCount() == 0)
{
cout << "Using " << Timing::ProcessorCount() << " automatically detected threads." << endl;
@@ -78,30 +118,15 @@ bool EmberAnimate(EmberOptions& opt)
cout << "Using " << opt.ThreadCount() << " manually specified threads." << endl;
}
- renderer->ThreadCount(opt.ThreadCount(), opt.IsaacSeed() != "" ? opt.IsaacSeed().c_str() : nullptr);
+ tempRenderer->ThreadCount(opt.ThreadCount(), opt.IsaacSeed() != "" ? opt.IsaacSeed().c_str() : nullptr);
+ renderers.push_back(std::move(tempRenderer));
}
- else
- {
- cout << "Using OpenCL to render." << endl;
- if (opt.Verbose())
- {
- cout << "Platform: " << wrapper.PlatformName(opt.Platform()) << endl;
- cout << "Device: " << wrapper.DeviceName(opt.Platform(), opt.Device()) << endl;
- }
+ if (!InitPaletteList(opt.PalettePath()))
+ return false;
- if (opt.ThreadCount() > 1)
- cout << "Cannot specify threads with OpenCL, using 1 thread." << endl;
-
- opt.ThreadCount(1);
- renderer->ThreadCount(opt.ThreadCount(), opt.IsaacSeed() != "" ? opt.IsaacSeed().c_str() : nullptr);
-
- if (opt.BitsPerChannel() != 8)
- {
- cout << "Bits per channel cannot be anything other than 8 with OpenCL, setting to 8." << endl;
- opt.BitsPerChannel(8);
- }
- }
+ if (!ParseEmberFile(parser, opt.Input(), embers))
+ return false;
if (opt.Format() != "jpg" &&
opt.Format() != "png" &&
@@ -196,7 +221,7 @@ bool EmberAnimate(EmberOptions& opt)
//Cast to double in case the value exceeds 2^32.
double imageMem = double(channels) * double(embers[i].m_FinalRasW)
- * double(embers[i].m_FinalRasH) * double(renderer->BytesPerChannel());
+ * double(embers[i].m_FinalRasH) * double(renderers[0]->BytesPerChannel());
double maxMem = pow(2.0, double((sizeof(void*) * 8) - 1));
if (imageMem > maxMem)//Ensure the max amount of memory for a process isn't exceeded.
@@ -236,128 +261,168 @@ bool EmberAnimate(EmberOptions& opt)
opt.FirstFrame(int(embers[0].m_Time));
if (opt.LastFrame() == UINT_MAX)
- opt.LastFrame(ClampGte(uint(embers.back().m_Time - 1), opt.FirstFrame()));
+ opt.LastFrame(ClampGte(size_t(embers.back().m_Time - 1), opt.FirstFrame()));
}
if (!opt.Out().empty())
{
- appendXml = true;
- filename = opt.Out();
- cout << "Single output file " << opt.Out() << " specified for multiple images. They will be all overwritten and only the last image will remain." << endl;
+ cout << "Single output file " << opt.Out() << " specified for multiple images. They would be all overwritten and only the last image will remain, exiting." << endl;
+ return false;
}
//Final setup steps before running.
- os.imbue(std::locale(""));
- padding = uint(log10((double)embers.size())) + 1;
- renderer->SetEmber(embers);
- renderer->EarlyClip(opt.EarlyClip());
- renderer->YAxisUp(opt.YAxisUp());
- renderer->LockAccum(opt.LockAccum());
- renderer->InsertPalette(opt.InsertPalette());
- renderer->PixelAspectRatio(T(opt.AspectRatio()));
- renderer->Transparency(opt.Transparency());
- renderer->NumChannels(channels);
- renderer->BytesPerChannel(opt.BitsPerChannel() / 8);
- renderer->Priority((eThreadPriority)Clamp((int)eThreadPriority::LOWEST, (int)eThreadPriority::HIGHEST, opt.Priority()));
- renderer->Callback(opt.DoProgress() ? progress.get() : nullptr);
+ padding = uint(log10(double(embers.size()))) + 1;
- std::function saveFunc = [&](uint threadVecIndex)
+ for (auto& r : renderers)
+ {
+ r->SetEmber(embers);
+ r->EarlyClip(opt.EarlyClip());
+ r->YAxisUp(opt.YAxisUp());
+ r->LockAccum(opt.LockAccum());
+ r->InsertPalette(opt.InsertPalette());
+ r->PixelAspectRatio(T(opt.AspectRatio()));
+ r->Transparency(opt.Transparency());
+ r->NumChannels(channels);
+ r->BytesPerChannel(opt.BitsPerChannel() / 8);
+ r->Priority(eThreadPriority(Clamp(int(opt.Priority()), int(eThreadPriority::LOWEST), int(eThreadPriority::HIGHEST))));
+ }
+
+ std::function&, string, EmberImageComments, size_t, size_t, size_t)> saveFunc = [&](vector& finalImage,
+ string filename,//These are copies because this will be launched in a thread.
+ EmberImageComments comments,
+ size_t w,
+ size_t h,
+ size_t chan)
{
bool writeSuccess = false;
- byte* finalImagep = finalImages[threadVecIndex].data();
+ byte* finalImagep = finalImage.data();
- if ((opt.Format() == "jpg" || opt.Format() == "bmp") && renderer->NumChannels() == 4)
- RgbaToRgb(finalImages[threadVecIndex], finalImages[threadVecIndex], renderer->FinalRasW(), renderer->FinalRasH());
+ if ((opt.Format() == "jpg" || opt.Format() == "bmp") && chan == 4)
+ RgbaToRgb(finalImage, finalImage, w, h);
if (opt.Format() == "png")
- writeSuccess = WritePng(filename.c_str(), finalImagep, renderer->FinalRasW(), renderer->FinalRasH(), opt.BitsPerChannel() / 8, opt.PngComments(), comments, opt.Id(), opt.Url(), opt.Nick());
+ writeSuccess = WritePng(filename.c_str(), finalImagep, w, h, opt.BitsPerChannel() / 8, opt.PngComments(), comments, opt.Id(), opt.Url(), opt.Nick());
else if (opt.Format() == "jpg")
- writeSuccess = WriteJpeg(filename.c_str(), finalImagep, renderer->FinalRasW(), renderer->FinalRasH(), opt.JpegQuality(), opt.JpegComments(), comments, opt.Id(), opt.Url(), opt.Nick());
+ writeSuccess = WriteJpeg(filename.c_str(), finalImagep, w, h, int(opt.JpegQuality()), opt.JpegComments(), comments, opt.Id(), opt.Url(), opt.Nick());
else if (opt.Format() == "ppm")
- writeSuccess = WritePpm(filename.c_str(), finalImagep, renderer->FinalRasW(), renderer->FinalRasH());
+ writeSuccess = WritePpm(filename.c_str(), finalImagep, w, h);
else if (opt.Format() == "bmp")
- writeSuccess = WriteBmp(filename.c_str(), finalImagep, renderer->FinalRasW(), renderer->FinalRasH());
+ writeSuccess = WriteBmp(filename.c_str(), finalImagep, w, h);
if (!writeSuccess)
- cout << "Error writing " << filename << endl;/**/
+ cout << "Error writing " << filename << endl;
};
+
+ atomfTime.store(opt.FirstFrame());
- //Begin run.
- for (ftime = opt.FirstFrame(); ftime <= opt.LastFrame(); ftime += opt.Dtime())
+ std::function iterFunc = [&](size_t index)
{
- T localTime = T(ftime);
+ size_t ftime, finalImageIndex = 0;
+ string filename, flameName;
+ RendererBase* renderer = renderers[index].get();
+ ostringstream fnstream, os;
+ EmberStats stats;
+ EmberImageComments comments;
+ Ember centerEmber;
+ vector finalImages[2];
+ std::thread writeThread;
- if ((opt.LastFrame() - opt.FirstFrame()) / opt.Dtime() >= 1)
- VerbosePrint("Time = " << ftime << " / " << opt.LastFrame() << " / " << opt.Dtime());
+ os.imbue(std::locale(""));
- renderer->Reset();
-
- if ((renderer->Run(finalImages[finalImageIndex], localTime) != RENDER_OK) || renderer->Aborted() || finalImages[finalImageIndex].empty())
+ while (atomfTime.fetch_add(opt.Dtime()), ((ftime = atomfTime.load()) <= opt.LastFrame()))
{
- cout << "Error: image rendering failed, skipping to next image." << endl;
- renderer->DumpErrorReport();//Something went wrong, print errors.
- continue;
- }
+ T localTime = T(ftime) - 1;
- if (opt.Out().empty())
- {
- ostringstream fnstream;
+ if (opt.Verbose() && ((opt.LastFrame() - opt.FirstFrame()) / opt.Dtime() >= 1))
+ {
+ verboseCs.Enter();
+ cout << "Time = " << ftime << " / " << opt.LastFrame() << " / " << opt.Dtime() << endl;
+ verboseCs.Leave();
+ }
+
+ renderer->Reset();
+
+ if ((renderer->Run(finalImages[finalImageIndex], localTime) != RENDER_OK) || renderer->Aborted() || finalImages[finalImageIndex].empty())
+ {
+ cout << "Error: image rendering failed, skipping to next image." << endl;
+ renderer->DumpErrorReport();//Something went wrong, print errors.
+ atomfTime.store(opt.LastFrame() + 1);//Abort all threads if any of them encounter an error.
+ break;
+ }
fnstream << inputPath << opt.Prefix() << setfill('0') << setw(padding) << ftime << opt.Suffix() << "." << opt.Format();
filename = fnstream.str();
- }
+ fnstream.str("");
- if (opt.WriteGenome())
- {
- flameName = filename.substr(0, filename.find_last_of('.')) + ".flam3";
- VerbosePrint("Writing " + flameName);
- Interpolater::Interpolate(embers, localTime, 0, centerEmber);//Get center flame.
-
- if (appendXml)
+ if (opt.WriteGenome())
{
- startXml = ftime == opt.FirstFrame();
- finishXml = ftime == opt.LastFrame();
+ flameName = filename.substr(0, filename.find_last_of('.')) + ".flam3";
+
+ if (opt.Verbose())
+ {
+ verboseCs.Enter();
+ cout << "Writing " << flameName << endl;
+ verboseCs.Leave();
+ }
+
+ Interpolater::Interpolate(embers, localTime, 0, centerEmber);//Get center flame.
+ emberToXml.Save(flameName, centerEmber, opt.PrintEditDepth(), true, opt.IntPalette(), opt.HexPalette(), true, false, false);
+ centerEmber.Clear();
}
- emberToXml.Save(flameName, centerEmber, opt.PrintEditDepth(), true, opt.IntPalette(), opt.HexPalette(), true, startXml, finishXml);
+ stats = renderer->Stats();
+ comments = renderer->ImageComments(stats, opt.PrintEditDepth(), opt.IntPalette(), opt.HexPalette());
+ os.str("");
+ size_t iterCount = renderer->TotalIterCount(1);
+ os << comments.m_NumIters << " / " << iterCount << " (" << std::fixed << std::setprecision(2) << ((double(stats.m_Iters) / double(iterCount)) * 100) << "%)";
+
+ if (opt.Verbose())
+ {
+ verboseCs.Enter();
+ cout << "\nIters ran/requested: " + os.str() << endl;
+ if (!opt.EmberCL()) cout << "Bad values: " << stats.m_Badvals << endl;
+ cout << "Render time: " << t.Format(stats.m_RenderMs) << endl;
+ cout << "Pure iter time: " << t.Format(stats.m_IterMs) << endl;
+ cout << "Iters/sec: " << size_t(stats.m_Iters / (stats.m_IterMs / 1000.0)) << endl;
+ cout << "Writing " << filename << endl << endl;
+ verboseCs.Leave();
+ }
+
+ //Run image writing in a thread. Although doing it this way duplicates the final output memory, it saves a lot of time
+ //when running with OpenCL. Call join() to ensure the previous thread call has completed.
+ if (writeThread.joinable())
+ writeThread.join();
+
+ auto threadVecIndex = finalImageIndex;//Cache before launching thread.
+
+ if (opt.ThreadedWrite())//Copies are passed of all but the first parameter to saveFunc(), to avoid conflicting with those values changing when starting the render for the next image.
+ {
+ writeThread = std::thread(saveFunc, std::ref(finalImages[threadVecIndex]), filename, comments, renderer->FinalRasW(), renderer->FinalRasH(), renderer->NumChannels());
+ finalImageIndex ^= 1;//Toggle the index.
+ }
+ else
+ saveFunc(finalImages[threadVecIndex], filename, comments, renderer->FinalRasW(), renderer->FinalRasH(), renderer->NumChannels());//Will always use the first index, thereby not requiring more memory.
}
- stats = renderer->Stats();
- comments = renderer->ImageComments(stats, opt.PrintEditDepth(), opt.IntPalette(), opt.HexPalette());
- os.str("");
- size_t iterCount = renderer->TotalIterCount(1);
- os << comments.m_NumIters << " / " << iterCount << " (" << std::fixed << std::setprecision(2) << ((double(stats.m_Iters) / double(iterCount)) * 100) << "%)";
-
- VerbosePrint("\nIters ran/requested: " + os.str());
- VerbosePrint("Bad values: " << stats.m_Badvals);
- VerbosePrint("Render time: " + t.Format(stats.m_RenderMs));
- VerbosePrint("Pure iter time: " + t.Format(stats.m_IterMs));
- VerbosePrint("Iters/sec: " << size_t(stats.m_Iters / (stats.m_IterMs / 1000.0)) << endl);
- VerbosePrint("Writing " + filename);
-
- //Run image writing in a thread. Although doing it this way duplicates the final output memory, it saves a lot of time
- //when running with OpenCL. Call join() to ensure the previous thread call has completed.
- if (writeThread.joinable())
+ if (writeThread.joinable())//One final check to make sure all writing is done before exiting this thread.
writeThread.join();
+ };
- uint threadVecIndex = finalImageIndex;//Cache before launching thread.
+ threadVec.reserve(renderers.size());
- if (opt.ThreadedWrite())
- writeThread = std::thread(saveFunc, threadVecIndex);
- else
- saveFunc(threadVecIndex);
-
- centerEmber.Clear();
- finalImageIndex ^= 1;//Toggle the index.
+ for (size_t r = 0; r < renderers.size(); r++)
+ {
+ threadVec.push_back(std::thread([&](size_t dev)
+ {
+ iterFunc(dev);
+ }, r));
}
- if (writeThread.joinable())
- writeThread.join();
+ for (auto& th : threadVec)
+ if (th.joinable())
+ th.join();
- VerbosePrint("Done.\n");
-
- if (opt.Verbose())
- t.Toc("\nTotal time: ", true);
+ t.Toc("\nFinished in: ", true);
return true;
}
@@ -387,18 +452,18 @@ int _tmain(int argc, _TCHAR* argv[])
#ifdef DO_DOUBLE
if (opt.Bits() == 64)
{
- b = EmberAnimate(opt);
+ b = EmberAnimate(opt);
}
else
#endif
if (opt.Bits() == 33)
{
- b = EmberAnimate(opt);
+ b = EmberAnimate(opt);
}
else if (opt.Bits() == 32)
{
cout << "Bits 32/int histogram no longer supported. Using bits == 33 (float)." << endl;
- b = EmberAnimate(opt);
+ b = EmberAnimate(opt);
}
}
diff --git a/Source/EmberCL/EmberCLPch.h b/Source/EmberCL/EmberCLPch.h
index 7fd5a95..2de2606 100644
--- a/Source/EmberCL/EmberCLPch.h
+++ b/Source/EmberCL/EmberCLPch.h
@@ -1,4 +1,6 @@
-#pragma once
+#ifdef WIN32
+ #pragma once
+#endif
///
/// Precompiled header file. Place all system includes here with appropriate #defines for different operating systems and compilers.
@@ -37,6 +39,7 @@
#include
#include
+#include
#include
#include
#include
diff --git a/Source/EmberCL/IterOpenCLKernelCreator.cpp b/Source/EmberCL/IterOpenCLKernelCreator.cpp
index d634152..7de6067 100644
--- a/Source/EmberCL/IterOpenCLKernelCreator.cpp
+++ b/Source/EmberCL/IterOpenCLKernelCreator.cpp
@@ -15,7 +15,9 @@ IterOpenCLKernelCreator::IterOpenCLKernelCreator()
{
m_IterEntryPoint = "IterateKernel";
m_ZeroizeEntryPoint = "ZeroizeKernel";
+ m_SumHistEntryPoint = "SumHisteKernel";
m_ZeroizeKernel = CreateZeroizeKernelString();
+ m_SumHistKernel = CreateSumHistKernelString();
}
///
@@ -24,6 +26,8 @@ IterOpenCLKernelCreator::IterOpenCLKernelCreator()
template const string& IterOpenCLKernelCreator::ZeroizeKernel() const { return m_ZeroizeKernel; }
template const string& IterOpenCLKernelCreator::ZeroizeEntryPoint() const { return m_ZeroizeEntryPoint; }
+template const string& IterOpenCLKernelCreator::SumHistKernel() const { return m_SumHistKernel; }
+template const string& IterOpenCLKernelCreator::SumHistEntryPoint() const { return m_SumHistEntryPoint; }
template const string& IterOpenCLKernelCreator::IterEntryPoint() const { return m_IterEntryPoint; }
///
@@ -703,6 +707,30 @@ string IterOpenCLKernelCreator::CreateZeroizeKernelString()
return os.str();
}
+template
+string IterOpenCLKernelCreator::CreateSumHistKernelString()
+{
+ ostringstream os;
+
+ os <<
+ ConstantDefinesString(typeid(T) == typeid(double)) </Double precision doesn't matter here since it's not used.
+ "__kernel void " << m_SumHistEntryPoint << "(__global real4_bucket* source, __global real4_bucket* dest, uint width, uint height, uint clear)\n"
+ "{\n"
+ " if (GLOBAL_ID_X >= width || GLOBAL_ID_Y >= height)\n"
+ " return;\n"
+ "\n"
+ " dest[(GLOBAL_ID_Y * width) + GLOBAL_ID_X] += source[(GLOBAL_ID_Y * width) + GLOBAL_ID_X];\n"//Can't use INDEX_IN_GRID_2D here because the grid might be larger than the buffer to make even dimensions.
+ "\n"
+ " if (clear)\n"
+ " source[(GLOBAL_ID_Y * width) + GLOBAL_ID_X] = 0;\n"
+ "\n"
+ " barrier(CLK_GLOBAL_MEM_FENCE);\n"//Just to be safe.
+ "}\n"
+ "\n";
+
+ return os.str();
+}
+
///
/// Create the string for 3D projection based on the 3D values of the ember.
/// Projection is done on the second point.
diff --git a/Source/EmberCL/IterOpenCLKernelCreator.h b/Source/EmberCL/IterOpenCLKernelCreator.h
index 9054ce1..fdb5db5 100644
--- a/Source/EmberCL/IterOpenCLKernelCreator.h
+++ b/Source/EmberCL/IterOpenCLKernelCreator.h
@@ -26,6 +26,8 @@ public:
IterOpenCLKernelCreator();
const string& ZeroizeKernel() const;
const string& ZeroizeEntryPoint() const;
+ const string& SumHistKernel() const;
+ const string& SumHistEntryPoint() const;
const string& IterEntryPoint() const;
string CreateIterKernelString(Ember& ember, string& parVarDefines, bool lockAccum = false, bool doAccum = true);
static void ParVarIndexDefines(Ember& ember, pair>& params, bool doVals = true, bool doString = true);
@@ -33,18 +35,21 @@ public:
private:
string CreateZeroizeKernelString();
+ string CreateSumHistKernelString();
string CreateProjectionString(Ember& ember);
string m_IterEntryPoint;
string m_ZeroizeKernel;
string m_ZeroizeEntryPoint;
+ string m_SumHistKernel;
+ string m_SumHistEntryPoint;
};
#ifdef OPEN_CL_TEST_AREA
-typedef void (*KernelFuncPointer) (uint gridWidth, uint gridHeight, uint blockWidth, uint blockHeight,
- uint BLOCK_ID_X, uint BLOCK_ID_Y, uint THREAD_ID_X, uint THREAD_ID_Y);
+typedef void (*KernelFuncPointer) (size_t gridWidth, size_t gridHeight, size_t blockWidth, size_t blockHeight,
+ size_t BLOCK_ID_X, size_t BLOCK_ID_Y, size_t THREAD_ID_X, size_t THREAD_ID_Y);
-static void OpenCLSim(uint gridWidth, uint gridHeight, uint blockWidth, uint blockHeight, KernelFuncPointer func)
+static void OpenCLSim(size_t gridWidth, size_t gridHeight, size_t blockWidth, size_t blockHeight, KernelFuncPointer func)
{
cout << "OpenCLSim(): " << endl;
cout << " Params: " << endl;
@@ -53,13 +58,13 @@ static void OpenCLSim(uint gridWidth, uint gridHeight, uint blockWidth, uint blo
cout << " blockW: " << blockWidth << endl;
cout << " blockH: " << blockHeight << endl;
- for (uint i = 0; i < gridHeight; i += blockHeight)
+ for (size_t i = 0; i < gridHeight; i += blockHeight)
{
- for (uint j = 0; j < gridWidth; j += blockWidth)
+ for (size_t j = 0; j < gridWidth; j += blockWidth)
{
- for (uint k = 0; k < blockHeight; k++)
+ for (size_t k = 0; k < blockHeight; k++)
{
- for (uint l = 0; l < blockWidth; l++)
+ for (size_t l = 0; l < blockWidth; l++)
{
func(gridWidth, gridHeight, blockWidth, blockHeight, j / blockWidth, i / blockHeight, l, k);
}
diff --git a/Source/EmberCL/OpenCLInfo.cpp b/Source/EmberCL/OpenCLInfo.cpp
new file mode 100644
index 0000000..2e70d44
--- /dev/null
+++ b/Source/EmberCL/OpenCLInfo.cpp
@@ -0,0 +1,406 @@
+#include "EmberCLPch.h"
+#include "OpenCLInfo.h"
+
+namespace EmberCLns
+{
+///
+/// Initialize and return a reference to the one and only OpenCLInfo object.
+///
+/// A reference to the only OpenCLInfo object.
+OpenCLInfo& OpenCLInfo::Instance()
+{
+ static OpenCLInfo instance;
+
+ return instance;
+}
+
+///
+/// Initialize the all platforms and devices and keep information about them in lists.
+///
+OpenCLInfo::OpenCLInfo()
+{
+ cl_int err;
+ vector platforms;
+ vector> devices;
+ intmax_t workingPlatformIndex = -1;
+
+ m_Init = false;
+ cl::Platform::get(&platforms);
+ devices.resize(platforms.size());
+ m_Platforms.reserve(platforms.size());
+ m_Devices.reserve(platforms.size());
+ m_DeviceNames.reserve(platforms.size());
+ m_AllDeviceNames.reserve(platforms.size());
+ m_DeviceIndices.reserve(platforms.size());
+
+ for (size_t i = 0; i < platforms.size(); i++)
+ platforms[i].getDevices(CL_DEVICE_TYPE_ALL, &devices[i]);
+
+ for (size_t platform = 0; platform < platforms.size(); platform++)
+ {
+ bool platformOk = false;
+ bool deviceOk = false;
+ cl::Context context;
+
+ if (CreateContext(platforms[platform], context, false))//Platform is ok, now do context. Unshared by default.
+ {
+ size_t workingDeviceIndex = 0;
+
+ for (size_t device = 0; device < devices[platform].size(); device++)//Context is ok, now do devices.
+ {
+ auto q = cl::CommandQueue(context, devices[platform][device], 0, &err);//At least one GPU device is present, so create a command queue.
+
+ if (CheckCL(err, "cl::CommandQueue()"))
+ {
+ if (!platformOk)
+ {
+ m_Platforms.push_back(platforms[platform]);
+ m_PlatformNames.push_back(platforms[platform].getInfo(nullptr) + " " + platforms[platform].getInfo(nullptr) + " " + platforms[platform].getInfo(nullptr));
+ workingPlatformIndex++;
+ platformOk = true;
+ }
+
+ if (!deviceOk)
+ {
+ m_Devices.push_back(vector());
+ m_DeviceNames.push_back(vector());
+ m_Devices.back().reserve(devices[platform].size());
+ m_DeviceNames.back().reserve(devices[platform].size());
+ deviceOk = true;
+ }
+
+ m_Devices.back().push_back(devices[platform][device]);
+ m_DeviceNames.back().push_back(devices[platform][device].getInfo(nullptr) + " " + devices[platform][device].getInfo(nullptr));// + " " + devices[platform][device].getInfo());
+ m_AllDeviceNames.push_back(m_DeviceNames.back().back());
+ m_DeviceIndices.push_back(pair(workingPlatformIndex, workingDeviceIndex++));
+ m_Init = true;//If at least one platform and device succeeded, OpenCL is ok. It's now ok to begin building and running programs.
+ }
+ }
+ }
+ }
+}
+
+///
+/// Get a const reference to the vector of available platforms.
+///
+/// A const reference to the vector of available platforms
+const vector& OpenCLInfo::Platforms() const
+{
+ return m_Platforms;
+}
+
+///
+/// Get a const reference to the platform name at the specified index.
+///
+/// The platform index to get the name of
+/// The platform name if found, else empty string
+const string& OpenCLInfo::PlatformName(size_t platform) const
+{
+ static string s;
+ return platform < m_PlatformNames.size() ? m_PlatformNames[platform] : s;
+}
+
+///
+/// Get a const reference to a vector of all available platform names on the system as a vector of strings.
+///
+/// All available platform names on the system as a vector of strings
+const vector& OpenCLInfo::PlatformNames() const
+{
+ return m_PlatformNames;
+}
+
+///
+/// Get a const reference to a vector of vectors of all available devices on the system.
+/// Each outer vector is a different platform.
+///
+/// All available devices on the system, grouped by platform.
+const vector>& OpenCLInfo::Devices() const
+{
+ return m_Devices;
+}
+
+///
+/// Get a const reference to the device name at the specified index on the platform
+/// at the specified index.
+///
+/// The platform index of the device
+/// The device index
+/// The name of the device if found, else empty string
+const string& OpenCLInfo::DeviceName(size_t platform, size_t device) const
+{
+ static string s;
+
+ if (platform < m_Platforms.size() && platform < m_Devices.size())
+ if (device < m_Devices[platform].size())
+ return m_DeviceNames[platform][device];
+
+ return s;
+}
+
+///
+/// Get a const reference to a vector of pairs of uints which contain the platform,device
+/// indices of all available devices on the system.
+///
+/// All available devices on the system as platform,device index pairs
+const vector>& OpenCLInfo::DeviceIndices() const
+{
+ return m_DeviceIndices;
+}
+
+///
+/// Get a const reference to a vector of all available device names on the system as a vector of strings.
+///
+/// All available device names on the system as a vector of strings
+const vector& OpenCLInfo::AllDeviceNames() const
+{
+ return m_AllDeviceNames;
+}
+
+///
+/// Get a const reference to a vector of all available device names on the platform
+/// at the specified index as a vector of strings.
+///
+/// The platform index whose devices names will be returned
+/// All available device names on the platform at the specified index as a vector of strings if within range, else empty vector.
+const vector& OpenCLInfo::DeviceNames(size_t platform) const
+{
+ static vector v;
+
+ if (platform < m_DeviceNames.size())
+ return m_DeviceNames[platform];
+
+ return v;
+}
+
+///
+/// Get the total device index at the specified platform and device index.
+///
+/// The platform index of the device
+/// The device index within the platform
+/// The total device index if found, else 0
+size_t OpenCLInfo::TotalDeviceIndex(size_t platform, size_t device) const
+{
+ size_t index = 0;
+ pair p{ platform, device };
+
+ for (size_t i = 0; i < m_DeviceIndices.size(); i++)
+ {
+ if (p == m_DeviceIndices[i])
+ {
+ index = i;
+ break;
+ }
+ }
+
+ return index;
+}
+
+///
+/// Create a context that is optionally shared with OpenGL and plact it in the
+/// passed in context ref parameter.
+///
+/// The platform object to create the context on
+/// The context object to store the result in
+/// True if shared with OpenGL, else not shared.
+/// True if success, else false.
+bool OpenCLInfo::CreateContext(const cl::Platform& platform, cl::Context& context, bool shared)
+{
+ cl_int err;
+
+ if (shared)
+ {
+ //Define OS-specific context properties and create the OpenCL context.
+ #if defined (__APPLE__) || defined(MACOSX)
+ CGLContextObj kCGLContext = CGLGetCurrentContext();
+ CGLShareGroupObj kCGLShareGroup = CGLGetShareGroup(kCGLContext);
+ cl_context_properties props[] =
+ {
+ CL_CONTEXT_PROPERTY_USE_CGL_SHAREGROUP_APPLE, (cl_context_properties)kCGLShareGroup,
+ 0
+ };
+
+ context = cl::Context(CL_DEVICE_TYPE_GPU, props, nullptr, nullptr, &err);//May need to tinker with this on Mac.
+ #else
+ #if defined WIN32
+ cl_context_properties props[] =
+ {
+ CL_GL_CONTEXT_KHR, (cl_context_properties)wglGetCurrentContext(),
+ CL_WGL_HDC_KHR, (cl_context_properties)wglGetCurrentDC(),
+ CL_CONTEXT_PLATFORM, reinterpret_cast((platform)()),
+ 0
+ };
+
+ context = cl::Context(CL_DEVICE_TYPE_GPU, props, nullptr, nullptr, &err);
+ #else
+ cl_context_properties props[] =
+ {
+ CL_GL_CONTEXT_KHR, cl_context_properties(glXGetCurrentContext()),
+ CL_GLX_DISPLAY_KHR, cl_context_properties(glXGetCurrentDisplay()),
+ CL_CONTEXT_PLATFORM, reinterpret_cast((platform)()),
+ 0
+ };
+
+ context = cl::Context(CL_DEVICE_TYPE_GPU, props, nullptr, nullptr, &err);
+ #endif
+ #endif
+ }
+ else
+ {
+ cl_context_properties props[3] =
+ {
+ CL_CONTEXT_PLATFORM,
+ reinterpret_cast((platform)()),
+ 0
+ };
+
+ context = cl::Context(CL_DEVICE_TYPE_ALL, props, nullptr, nullptr, &err);
+ }
+
+ return CheckCL(err, "cl::Context()");
+}
+
+///
+/// Return whether at least one device has been found and properly initialized.
+///
+/// True if success, else false.
+bool OpenCLInfo::Ok() const
+{
+ return m_Init;
+}
+
+///
+/// Get all information about all platforms and devices.
+///
+/// A string with all information about all platforms and devices
+string OpenCLInfo::DumpInfo() const
+{
+ ostringstream os;
+ vector sizes;
+
+ os.imbue(locale(""));
+
+ for (size_t platform = 0; platform < m_Platforms.size(); platform++)
+ {
+ os << "Platform " << platform << ": " << PlatformName(platform) << endl;
+
+ for (size_t device = 0; device < m_Devices[platform].size(); device++)
+ {
+ os << "Device " << device << ": " << DeviceName(platform, device) << endl;
+ os << "CL_DEVICE_OPENCL_C_VERSION: " << GetInfo(platform, device, CL_DEVICE_OPENCL_C_VERSION) << endl;
+ os << "CL_DEVICE_LOCAL_MEM_SIZE: " << GetInfo(platform, device, CL_DEVICE_LOCAL_MEM_SIZE) << endl;
+ os << "CL_DEVICE_LOCAL_MEM_TYPE: " << GetInfo(platform, device, CL_DEVICE_LOCAL_MEM_TYPE) << endl;
+ os << "CL_DEVICE_MAX_COMPUTE_UNITS: " << GetInfo(platform, device, CL_DEVICE_MAX_COMPUTE_UNITS) << endl;
+ os << "CL_DEVICE_MAX_READ_IMAGE_ARGS: " << GetInfo(platform, device, CL_DEVICE_MAX_READ_IMAGE_ARGS) << endl;
+ os << "CL_DEVICE_MAX_WRITE_IMAGE_ARGS: " << GetInfo(platform, device, CL_DEVICE_MAX_WRITE_IMAGE_ARGS) << endl;
+ os << "CL_DEVICE_MAX_MEM_ALLOC_SIZE: " << GetInfo