--Code changes

-Remove all dependencies on Intel Threading Building Blocks.
 -Write our own version of parallel_for().
This commit is contained in:
Person
2021-12-29 23:10:54 -07:00
parent 5524180d4b
commit ee7ca7065e
50 changed files with 140 additions and 3255 deletions

View File

@ -12,9 +12,29 @@
/// <summary>
/// Ember class.
/// </summary>
namespace EmberNs
{
static void parallel_for(size_t start, size_t end, size_t parlevel, std::function<void(size_t)> func)
{
const auto ct = parlevel == 0 ? EmberNs::Timing::ProcessorCount() : parlevel;
std::vector<std::thread> threads(ct);
const auto chunkSize = (end - start) / ct;
for (size_t i = 0; i < ct; i++)
{
threads.push_back(std::thread([&, i]
{
const auto chunkStart = chunkSize* i;
const auto chunkEnd = std::min(chunkStart + chunkSize, end);
for (size_t j = chunkStart; j < chunkEnd; j++)
func(j);
}));
}
EmberNs::Join(threads);
}
template <typename T> class Interpolater;
/// <summary>

View File

@ -66,12 +66,6 @@
#include "libxml2/libxml/parser.h"
#endif
#if !defined(Q_MOC_RUN)
//Intel's Threading Building Blocks is what's used for all threading.
#include <tbb/parallel_for.h>
#include <tbb/task_scheduler_init.h>
#endif
#define GLM_FORCE_RADIANS 1
#define GLM_ENABLE_EXPERIMENTAL 1
@ -88,7 +82,6 @@
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtx/string_cast.hpp>
using namespace tbb;
using namespace std;
using namespace std::chrono;
using namespace glm;

View File

@ -406,9 +406,9 @@ public:
{
for (size_t j = 0; j < width; j++)
{
v[(width * 3 * i) + (j * 3)] = static_cast<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] = static_cast<byte>(m_Entries[j][1] * T(255));
v[(width * 3 * i) + (j * 3) + 2] = static_cast<byte>(m_Entries[j][2] * T(255));
v[(width * 3 * i) + (j * 3)] = static_cast<byte>(m_Entries[j][0] * static_cast<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] = static_cast<byte>(m_Entries[j][1] * static_cast<T>(255));
v[(width * 3 * i) + (j * 3) + 2] = static_cast<byte>(m_Entries[j][2] * static_cast<T>(255));
}
}
}

View File

@ -871,19 +871,12 @@ bool Renderer<T, bucketT>::Alloc(bool histOnly)
template <typename T, typename bucketT>
bool Renderer<T, bucketT>::ResetBuckets(bool resetHist, bool resetAccum)
{
//parallel_invoke(
//[&]
//{
if (resetHist && !m_HistBuckets.empty())
Memset(m_HistBuckets);
//},
//[&]
//{
if (resetAccum && !m_AccumulatorBuckets.empty())
Memset(m_AccumulatorBuckets);
//});
return resetHist || resetAccum;
}
@ -930,7 +923,7 @@ eRenderStatus Renderer<T, bucketT>::LogScaleDensityFilter(bool forceOutput)
//Timing t(4);
//Original didn't parallelize this, doing so gives a 50-75% speedup.
//The value can be directly assigned, which is quicker than summing.
parallel_for(startRow, endRow, static_cast<size_t>(1), [&](size_t j)
parallel_for(startRow, endRow, m_ThreadsToUse, [&](size_t j)
{
size_t row = j * m_SuperRasW;
size_t rowEnd = row + endCol;
@ -954,11 +947,7 @@ eRenderStatus Renderer<T, bucketT>::LogScaleDensityFilter(bool forceOutput)
}
}
}
}
#if defined(_WIN32) || defined(__APPLE__)
, tbb::static_partitioner()
#endif
);
});
if (m_Callback && !m_Abort)
if (!m_Callback->ProgressFunc(m_Ember, m_ProgressParameter, 100.0, 1, 0))
@ -982,14 +971,13 @@ eRenderStatus Renderer<T, bucketT>::GaussianDensityFilter()
bool scf = !(Supersample() & 1);
intmax_t ss = Floor<T>(Supersample() / static_cast<T>(2));
T scfact = std::pow(Supersample() / (Supersample() + static_cast<T>(1)), static_cast<T>(2));
size_t threads = m_ThreadsToUse;
size_t startRow = Supersample() - 1;
size_t endRow = m_SuperRasH - (Supersample() - 1);//Original did + which is most likely wrong.
intmax_t startCol = Supersample() - 1;
intmax_t endCol = m_SuperRasW - (Supersample() - 1);
size_t chunkSize = static_cast<size_t>(std::ceil(static_cast<double>(endRow - startRow) / static_cast<double>(threads)));
size_t chunkSize = static_cast<size_t>(std::ceil(static_cast<double>(endRow - startRow) / static_cast<double>(m_ThreadsToUse)));
//parallel_for scales very well, dividing the work almost perfectly among all processors.
parallel_for(static_cast<size_t>(0), threads, static_cast<size_t>(1), [&] (size_t threadIndex)
parallel_for(static_cast<size_t>(0), m_ThreadsToUse, m_ThreadsToUse, [&] (size_t threadIndex)
{
size_t pixelNumber = 0;
const auto localStartRow = static_cast<intmax_t>(std::min<size_t>(startRow + (threadIndex * chunkSize), endRow - 1));
@ -1123,11 +1111,7 @@ eRenderStatus Renderer<T, bucketT>::GaussianDensityFilter()
}
}
}
}
#if defined(_WIN32) || defined(__APPLE__)
, tbb::static_partitioner()
#endif
);
});
if (m_Callback && !m_Abort)
m_Callback->ProgressFunc(m_Ember, m_ProgressParameter, 100.0, 1, 0);
@ -1166,7 +1150,7 @@ eRenderStatus Renderer<T, bucketT>::AccumulatorToFinalImage(vector<v4F>& pixels,
//The original does it this way as well and it's roughly 11 times faster to do it this way than inline below with each pixel.
if (EarlyClip())
{
parallel_for(static_cast<size_t>(0), m_SuperRasH, static_cast<size_t>(1), [&](size_t j)
parallel_for(static_cast<size_t>(0), m_SuperRasH, m_ThreadsToUse, [&](size_t j)
{
auto rowStart = m_AccumulatorBuckets.data() + (j * m_SuperRasW);//Pull out of inner loop for optimization.
const auto rowEnd = rowStart + m_SuperRasW;
@ -1176,11 +1160,7 @@ eRenderStatus Renderer<T, bucketT>::AccumulatorToFinalImage(vector<v4F>& pixels,
GammaCorrection(*rowStart, background, g, linRange, vibrancy, false, glm::value_ptr(*rowStart));//Write back in place.
rowStart++;
}
}
#if defined(_WIN32) || defined(__APPLE__)
, tbb::static_partitioner()
#endif
);
});
}
if (m_Abort)
@ -1193,7 +1173,7 @@ eRenderStatus Renderer<T, bucketT>::AccumulatorToFinalImage(vector<v4F>& pixels,
//otherwise artifacts that resemble page tearing will occur in an interactive run. It's
//critical to never exit this loop prematurely.
//for (size_t j = 0; j < FinalRasH(); j++)//Keep around for debugging.
parallel_for(static_cast<size_t>(0), FinalRasH(), static_cast<size_t>(1), [&](size_t j)
parallel_for(static_cast<size_t>(0), FinalRasH(), m_ThreadsToUse, [&](size_t j)
{
Color<bucketT> newBucket;
size_t pixelsRowStart = (m_YAxisUp ? ((FinalRasH() - j) - 1) : j) * FinalRasW();//Pull out of inner loop for optimization.
@ -1226,11 +1206,7 @@ eRenderStatus Renderer<T, bucketT>::AccumulatorToFinalImage(vector<v4F>& pixels,
auto pf = reinterpret_cast<float*>(pv4T);
GammaCorrection(*(reinterpret_cast<tvec4<bucketT, glm::defaultp>*>(&newBucket)), background, g, linRange, vibrancy, true, pf);
}
}
#if defined(_WIN32) || defined(__APPLE__)
, tbb::static_partitioner()
#endif
);
});
//Insert the palette into the image for debugging purposes. Not implemented on the GPU.
if (m_InsertPalette)
@ -1288,7 +1264,7 @@ EmberStats Renderer<T, bucketT>::Iterate(size_t iterCount, size_t temporalSample
m_ThreadEmbers.insert(m_ThreadEmbers.begin(), m_ThreadsToUse, m_Ember);
}
parallel_for(static_cast<size_t>(0), m_ThreadsToUse, static_cast<size_t>(1), [&] (size_t threadIndex)
parallel_for(static_cast<size_t>(0), m_ThreadsToUse, m_ThreadsToUse, [&] (size_t threadIndex)
{
#if defined(_WIN32)
SetThreadPriority(GetCurrentThread(), static_cast<int>(m_Priority));
@ -1375,11 +1351,7 @@ EmberStats Renderer<T, bucketT>::Iterate(size_t iterCount, size_t temporalSample
}
}
}
}
#if defined(_WIN32) || defined(__APPLE__)
, tbb::static_partitioner()
#endif
);
});
stats.m_Iters = std::accumulate(m_SubBatch.begin(), m_SubBatch.end(), 0ULL);//Sum of iter count of all threads.
stats.m_Badvals = std::accumulate(m_BadVals.begin(), m_BadVals.end(), 0ULL);
stats.m_IterMs = m_IterTimer.Toc();

View File

@ -163,6 +163,7 @@ private:
m_Option.nId = 0;
m_Option.pszArg = _T("--fillmein");
m_Option.nArgType = SO_NONE;
m_Val = T();
}
public:

View File

@ -22,7 +22,7 @@ static std::recursive_mutex fileCs;
static bool WriteJpeg(const char* filename, byte* image, size_t width, size_t height, int quality, bool enableComments, const EmberImageComments& comments, const string& id, const string& url, const string& nick)
{
bool b = false;
FILE* file;
FILE* file = nullptr;
errno_t fileResult;
//Just to be extra safe.
@ -114,7 +114,10 @@ static bool WriteJpeg(const char* filename, byte* image, size_t width, size_t he
jpeg_finish_compress(&info);
jpeg_destroy_compress(&info);
fclose(file);
if (file != nullptr)
fclose(file);
b = true;
}
@ -138,7 +141,7 @@ static bool WriteJpeg(const char* filename, byte* image, size_t width, size_t he
static bool WritePng(const char* filename, byte* image, size_t width, size_t height, size_t bytesPerChannel, bool enableComments, const EmberImageComments& comments, const string& id, const string& url, const string& nick)
{
bool b = false;
FILE* file;
FILE* file = nullptr;
errno_t fileResult;
//Just to be extra safe.
@ -220,7 +223,10 @@ static bool WritePng(const char* filename, byte* image, size_t width, size_t hei
png_write_image(png_ptr, rows.data());
png_write_end(png_ptr, info_ptr);
png_destroy_write_struct(&png_ptr, &info_ptr);
fclose(file);
if (file != nullptr)
fclose(file);
b = true;
}
@ -313,7 +319,9 @@ static bool SaveBmp(const char* filename, const byte* image, size_t width, size_
if ((file = CreateFileA(filename, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL)) == NULL)
{
CloseHandle(file);
if (file != 0)
CloseHandle(file);
return false;
}
}
@ -389,7 +397,7 @@ static bool WriteExr16(const char* filename, Rgba* image, size_t width, size_t h
try
{
rlg l(fileCs);
file = std::make_unique<RgbaOutputFile>(filename, iw, ih, WRITE_RGBA);
file = std::make_unique<RgbaOutputFile>(filename, iw, ih, RgbaChannels::WRITE_RGBA);
}
catch (std::exception)
{

View File

@ -47,7 +47,7 @@ public:
/// <param name="height">The height of the image in pixels</param>
void SetImage(vector<byte>& v, uint width, uint height)
{
const auto size = 64;
constexpr auto size = 64;
m_Image = QImage(width, height, QImage::Format_RGBA8888);
memcpy(m_Image.scanLine(0), v.data(), SizeOf(v));//Memcpy the data in.
m_Pixmap = QPixmap::fromImage(m_Image).scaled(QSize(size, size), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);//Create a QPixmap out of the QImage, scaled to size.

View File

@ -66,10 +66,10 @@ public:
virtual void SyncGuiToEmbers(size_t widthOverride = 0, size_t heightOverride = 0, bool dowidth = true, bool doheight = true) { }
virtual void SyncCurrentToSizeSpinners(bool scale, bool size, bool doWidth = true, bool doHeight = true) { }
virtual void ResetProgress(bool total = true) { }
virtual tuple<size_t, size_t, size_t> SyncAndComputeMemory() { return tuple<size_t, size_t, size_t>(0, 0, 0); }
virtual double OriginalAspect() { return 1; }
virtual tuple<size_t, size_t, size_t> SyncAndComputeMemory() { return tuple<size_t, size_t, size_t>(0, 0, 0); }
virtual double OriginalAspect() { return 1; }
virtual QString ComposePath(const QString& name, bool unique = true) { return ""; }
virtual bool BumpQualityRender(double d) { return false; }
virtual bool BumpQualityRender(double d) { return false; }
virtual QString SaveCurrentAgain() { return ""; }
virtual void CancelRender() { }
virtual QString CheckMemory(const tuple<size_t, size_t, size_t>& p) { return ""; }
@ -118,7 +118,7 @@ public:
void SetEmber(size_t index, bool verbatim) override;
void SaveCurrentAsXml(QString filename = "") override;
bool Render() override;
bool BumpQualityRender(double d) override;
bool BumpQualityRender(double d) override;
bool CreateRenderer(eRendererType renderType, const vector<pair<size_t, size_t>>& devices, bool updatePreviews, bool shared = true) override;
int ProgressFunc(Ember<T>& ember, void* foo, double fraction, int stage, double etaMs) override;
size_t Index() const override { return m_Ember->m_Index; }

View File

@ -136,7 +136,7 @@ static bool Exists(const QString& s)
/// <returns>The converted color</returns>
static QColor VisibleColor(const QColor& color)
{
const auto threshold = 105;
constexpr int threshold = 105;
const auto delta = (color.red() * 0.299) + //Magic numbers gotten from a Stack Overflow post.
(color.green() * 0.587) +
(color.blue() * 0.114);

View File

@ -397,7 +397,7 @@ void TreePreviewRenderer<T>::PreviewRenderFunc(uint start, uint end)
{
if (const auto treeItem = dynamic_cast<EmberTreeWidgetItemBase*>(top->child(int(i))))
{
//It is critical that Qt::BlockingQueuedConnection is passed because this is running on a different thread than the UI.
//It is critical that Qt::DirectConnection is passed because this is running on a different thread than the UI.
//This ensures the events are processed in order as each preview is updated, and that control does not return here
//until the update is complete.
if (m_PreviewRun)

View File

@ -22,7 +22,7 @@ enum class eXformUpdate : et { UPDATE_SPECIFIC, UPDATE_CURRENT, UPDATE_SELECTED,
/// An enum representing the type of synchronizing to do between the list of Embers kept in memory
/// and the widgets in the library tree.
/// </summary>
enum eLibraryUpdate { INDEX = 1, NAME = 2, POINTER = 4 };
enum class eLibraryUpdate { INDEX = 1, NAME = 2, POINTER = 4 };
/// <summary>
/// FractoriumEmberController and Fractorium need each other, but each can't include the other.
@ -628,6 +628,10 @@ public:
{
}
virtual ~PreviewRenderer()
{
}
void Render(uint start, uint end)
{
Stop();
@ -700,7 +704,7 @@ public:
m_Tree(tree),
m_EmberFile(emberFile)
{
auto f = m_Controller->m_Fractorium;
const auto f = m_Controller->m_Fractorium;
m_PreviewRenderer.Callback(nullptr);
m_PreviewRenderer.EarlyClip(f->m_Settings->EarlyClip());
m_PreviewRenderer.YAxisUp(f->m_Settings->YAxisUp());

View File

@ -151,13 +151,13 @@ void FractoriumEmberController<T>::SyncLibrary(eLibraryUpdate update)
{
if (auto item = dynamic_cast<EmberTreeWidgetItem<T>*>(top->child(i)))//Cast the child widget to the EmberTreeWidgetItem type.
{
if (update & eLibraryUpdate::INDEX)
if (static_cast<uint>(update) & static_cast<uint>(eLibraryUpdate::INDEX))
it->m_Index = i;
if (update & eLibraryUpdate::NAME)
if (static_cast<uint>(update) & static_cast<uint>(eLibraryUpdate::NAME))
item->setText(0, QString::fromStdString(it->m_Name));
if (update & eLibraryUpdate::POINTER)
if (static_cast<uint>(update) & static_cast<uint>(eLibraryUpdate::POINTER))
item->SetEmberPointer(&(*it));
if (item->checkState(0) == Qt::Checked)
@ -367,7 +367,7 @@ void FractoriumEmberController<T>::MoveLibraryItems(const QModelIndexList& items
return false;
});
tree->update();
SyncLibrary(eLibraryUpdate(eLibraryUpdate::INDEX | eLibraryUpdate::POINTER));
SyncLibrary(eLibraryUpdate(static_cast<uint>(eLibraryUpdate::INDEX) | static_cast<uint>(eLibraryUpdate::POINTER)));
//SyncLibrary(eLibraryUpdate(eLibraryUpdate::INDEX | eLibraryUpdate::POINTER | eLibraryUpdate::NAME));
}

View File

@ -125,7 +125,7 @@ void FractoriumEmberControllerBase::SaveCurrentRender(const QString& filename, c
if (filename != "")
{
bool ret = false;
auto size = width * height;
const auto size = width * height;
auto settings = m_Fractorium->m_Settings;
QFileInfo fileInfo(filename);
QString suffix = fileInfo.suffix();
@ -245,7 +245,7 @@ template <typename T>
int FractoriumEmberController<T>::ProgressFunc(Ember<T>& ember, void* foo, double fraction, int stage, double etaMs)
{
QString status;
m_Fractorium->m_ProgressBar->setValue(int(fraction));//Only really applies to iter and filter, because final accum only gives progress 0 and 100.
QMetaObject::invokeMethod(m_Fractorium->m_ProgressBar, "setValue", Qt::QueuedConnection, Q_ARG(const int, int(fraction)));//Only really applies to iter and filter, because final accum only gives progress 0 and 100.
if (stage == 0)
status = "Iterating";
@ -254,7 +254,7 @@ int FractoriumEmberController<T>::ProgressFunc(Ember<T>& ember, void* foo, doubl
else if (stage == 2)
status = "Spatial Filtering + Final Accumulation";
m_Fractorium->m_RenderStatusLabel->setText(status);
QMetaObject::invokeMethod(m_Fractorium->m_RenderStatusLabel, "setText", Qt::QueuedConnection, Q_ARG(const QString&, status));
return m_ProcessActions.empty() ? 1 : 0;//If they've done anything, abort.
}
@ -289,10 +289,10 @@ bool FractoriumEmberController<T>::SyncSizes()
auto gl = m_Fractorium->ui.GLDisplay;
RendererCL<T, float>* rendererCL = nullptr;
if (!m_GLController->SizesMatch())
if (gl && !m_GLController->SizesMatch())
{
m_GLController->ClearWindow();
gl->SetDimensions(int(m_Ember.m_FinalRasW), int(m_Ember.m_FinalRasH));
gl->SetDimensions(static_cast<int>(m_Ember.m_FinalRasW), static_cast<int>(m_Ember.m_FinalRasH));
gl->Allocate();
gl->SetViewport();
@ -321,12 +321,12 @@ bool FractoriumEmberController<T>::Render()
bool success = true;
auto gl = m_Fractorium->ui.GLDisplay;
RendererCL<T, float>* rendererCL = nullptr;
eProcessAction qualityAction, action;
eProcessAction qualityAction = eProcessAction::NOTHING, action = eProcessAction::NOTHING;
//Quality is the only parameter we update inside the timer.
//This is to allow the user to rapidly increase the quality spinner
//without fully resetting the render. Instead, it will just keep iterating
//where it last left off in response to an increase.
T d = T(m_Fractorium->m_QualitySpin->value());
T d = static_cast<T>(m_Fractorium->m_QualitySpin->value());
if (d < m_Ember.m_Quality)//Full restart if quality decreased.
{
@ -358,8 +358,8 @@ bool FractoriumEmberController<T>::Render()
if (action != eProcessAction::NOTHING)
{
size_t i = 0;
int solo = m_Ember.m_Solo;
bool forceFinal = m_Fractorium->HaveFinal();
const auto solo = m_Ember.m_Solo;
const bool forceFinal = m_Fractorium->HaveFinal();
if (solo != -1)
{
@ -388,7 +388,7 @@ bool FractoriumEmberController<T>::Render()
}
//Determining if a completely new rendering process is being started.
bool iterBegin = ProcessState() == eProcessState::NONE;
const auto iterBegin = ProcessState() == eProcessState::NONE;
if (iterBegin)
{
@ -398,14 +398,15 @@ bool FractoriumEmberController<T>::Render()
m_SubBatchCount = m_Fractorium->m_Settings->OpenCLSubBatch();
m_Fractorium->m_ProgressBar->setValue(0);
m_Fractorium->m_RenderStatusLabel->setText("Starting");
const QString status = "Starting";
QMetaObject::invokeMethod(m_Fractorium->m_RenderStatusLabel, "setText", Qt::QueuedConnection, Q_ARG(const QString&, status));
}
//If the rendering process hasn't finished, render with the current specified action.
if (ProcessState() != eProcessState::ACCUM_DONE)
{
//if (m_Renderer->Run(m_FinalImage, 0) == RENDER_OK)//Full, non-incremental render for debugging.
bool update = iterBegin || m_Fractorium->m_Settings->ContinuousUpdate();
const bool update = iterBegin || m_Fractorium->m_Settings->ContinuousUpdate();
eRenderStatus result;
if ((result = m_Renderer->Run(m_FinalImage, 0, m_SubBatchCount, update)) == eRenderStatus::RENDER_OK)//Force output on iterBegin or if the settings specify to always do it.
@ -428,23 +429,25 @@ bool FractoriumEmberController<T>::Render()
//Rendering has finished, update final stats.
if (ProcessState() == eProcessState::ACCUM_DONE)
{
auto stats = m_Renderer->Stats();
const auto stats = m_Renderer->Stats();
auto iters = ToString<qulonglong>(stats.m_Iters);
auto scaledQuality = ToString(uint(m_Renderer->ScaledQuality()));
auto scaledQuality = ToString(static_cast<intmax_t>(m_Renderer->ScaledQuality()));
auto renderTime = m_RenderElapsedTimer.Format(m_RenderElapsedTimer.Toc());
m_Fractorium->m_ProgressBar->setValue(100);
//Only certain stats can be reported with OpenCL.
if (m_Renderer->RendererType() == eRendererType::OPENCL_RENDERER)
{
m_Fractorium->m_RenderStatusLabel->setText("Iters: " + iters + ". Scaled quality: " + scaledQuality + ". Total time: " + QString::fromStdString(renderTime) + ".");
const QString status = "Iters: " + iters + ". Scaled quality: " + scaledQuality + ". Total time: " + QString::fromStdString(renderTime) + ".";
QMetaObject::invokeMethod(m_Fractorium->m_RenderStatusLabel, "setText", Qt::QueuedConnection, Q_ARG(const QString&, status));
}
else
{
double percent = double(stats.m_Badvals) / double(stats.m_Iters);
const auto percent = static_cast<double>(stats.m_Badvals) / static_cast<double>(stats.m_Iters);
auto badVals = ToString<qulonglong>(stats.m_Badvals);
auto badPercent = QLocale::system().toString(percent * 100, 'f', 2);
m_Fractorium->m_RenderStatusLabel->setText("Iters: " + iters + ". Scaled quality: " + scaledQuality + ". Bad values: " + badVals + " (" + badPercent + "%). Total time: " + QString::fromStdString(renderTime) + ".");
const QString status = "Iters: " + iters + ". Scaled quality: " + scaledQuality + ". Bad values: " + badVals + " (" + badPercent + "%). Total time: " + QString::fromStdString(renderTime) + ".";
QMetaObject::invokeMethod(m_Fractorium->m_RenderStatusLabel, "setText", Qt::QueuedConnection, Q_ARG(const QString&, status));
}
if (m_LastEditWasUndoRedo && (m_UndoIndex == m_UndoList.size() - 1))//Traversing through undo list, reached the end, so put back in regular edit mode.
@ -453,7 +456,7 @@ bool FractoriumEmberController<T>::Render()
}
else if (m_EditState == eEditUndoState::REGULAR_EDIT)//Regular edit, just add to the end of the undo list.
{
auto btn = QApplication::mouseButtons();
const auto btn = QApplication::mouseButtons();
if ((action == eProcessAction::ACCUM_ONLY || action == eProcessAction::FILTER_AND_ACCUM) ||
(!btn.testFlag(Qt::LeftButton) && !btn.testFlag(Qt::RightButton) && !btn.testFlag(Qt::MiddleButton)))
@ -512,7 +515,8 @@ bool FractoriumEmberController<T>::Render()
auto errors = m_Renderer->ErrorReport();
success = false;
m_FailedRenders++;
m_Fractorium->m_RenderStatusLabel->setText("Rendering failed, see info tab. Try changing parameters.");
const QString status = "Rendering failed, see info tab. Try changing parameters.";
QMetaObject::invokeMethod(m_Fractorium->m_RenderStatusLabel, "setText", Qt::QueuedConnection, Q_ARG(const QString&, status));
m_Fractorium->ErrorReportToQTextEdit(errors, m_Fractorium->ui.InfoRenderingTextEdit);
m_Renderer->ClearErrorReport();
@ -520,7 +524,8 @@ bool FractoriumEmberController<T>::Render()
{
m_Rendering = false;
StopRenderTimer(true);
m_Fractorium->m_RenderStatusLabel->setText("Rendering failed 3 or more times, stopping all rendering, see info tab. Try changing renderer types.");
const QString status2 = "Rendering failed 3 or more times, stopping all rendering, see info tab. Try changing renderer types.";
QMetaObject::invokeMethod(m_Fractorium->m_RenderStatusLabel, "setText", Qt::QueuedConnection, Q_ARG(const QString&, status2));
ClearFinalImages();
m_GLController->ClearWindow();
@ -604,11 +609,11 @@ bool FractoriumEmberController<T>::CreateRenderer(eRendererType renderType, cons
m_Fractorium->m_QualitySpin->setValue(val);
if (auto rendererCL = dynamic_cast<RendererCL<T, float>*>(m_Renderer.get()))
rendererCL->SubBatchPercentPerThread(float(s->OpenCLSubBatchPct()));
rendererCL->SubBatchPercentPerThread(static_cast<float>(s->OpenCLSubBatchPct()));
}
else
{
auto quality = m_Fractorium->m_Settings->CpuQuality();
const auto quality = m_Fractorium->m_Settings->CpuQuality();
m_Fractorium->m_QualitySpin->DoubleClickZero(quality);
m_Fractorium->m_QualitySpin->DoubleClickNonZero(quality);
@ -684,9 +689,9 @@ void Fractorium::ShutdownAndRecreateFromOptions(bool updatePreviews)
bool Fractorium::CreateRendererFromOptions(bool updatePreviews)
{
bool ok = true;
bool useOpenCL = m_Info->Ok() && m_Settings->OpenCL();
const auto useOpenCL = m_Info->Ok() && m_Settings->OpenCL();
auto v = Devices(m_Settings->Devices());
bool doOpenCL = useOpenCL && !v.empty();
const auto doOpenCL = useOpenCL && !v.empty();
ui.ActionCopyKernel->setEnabled(doOpenCL);
//The most important option to process is what kind of renderer is desired, so do it first.
@ -712,8 +717,9 @@ bool Fractorium::CreateRendererFromOptions(bool updatePreviews)
{
rendererCL->m_CompileBegun = [&]()
{
m_RenderStatusLabel->setText("Compiling OpenCL kernel...");
m_RenderStatusLabel->repaint();
const QString status = "Compiling OpenCL kernel...";
QMetaObject::invokeMethod(m_RenderStatusLabel, "setText", Qt::QueuedConnection, Q_ARG(const QString&, status));
//m_RenderStatusLabel->repaint();
QApplication::processEvents();
};
}
@ -728,7 +734,7 @@ bool Fractorium::CreateRendererFromOptions(bool updatePreviews)
/// <returns>True if successful, else false.</returns>
bool Fractorium::CreateControllerFromOptions()
{
size_t elementSize =
const size_t elementSize =
#ifdef DO_DOUBLE
m_Settings->Double() ? sizeof(double) :
#endif
@ -736,14 +742,14 @@ bool Fractorium::CreateControllerFromOptions()
if (!m_Controller.get() || (m_Controller->SizeOfT() != elementSize))
{
auto hue = m_PaletteHueSpin->value();
auto sat = m_PaletteSaturationSpin->value();
auto bright = m_PaletteBrightnessSpin->value();
auto con = m_PaletteContrastSpin->value();
auto blur = m_PaletteBlurSpin->value();
auto freq = m_PaletteFrequencySpin->value();
auto rot = m_PreviewPaletteRotation;
double scale;
const auto hue = m_PaletteHueSpin->value();
const auto sat = m_PaletteSaturationSpin->value();
const auto bright = m_PaletteBrightnessSpin->value();
const auto con = m_PaletteContrastSpin->value();
const auto blur = m_PaletteBlurSpin->value();
const auto freq = m_PaletteFrequencySpin->value();
const auto rot = m_PreviewPaletteRotation;
double scale = 0;
uint current = 0;
#ifdef DO_DOUBLE
EmberFile<double> efd;
@ -752,7 +758,7 @@ bool Fractorium::CreateControllerFromOptions()
EmberFile<float> efd;
Palette<float> tempPalette;
#endif
QModelIndex index = ui.LibraryTree->currentIndex();
const QModelIndex index = ui.LibraryTree->currentIndex();
ui.LibraryTree->clear();//This must be here before FillLibraryTree() is called below, else a spurious EmberTreeItemChanged event will be called on a deleted object.
//First check if a controller has already been created, and if so, save its embers and gracefully shut it down.
@ -822,7 +828,7 @@ void Fractorium::StartRenderTimer(bool updatePreviews)
{
//Starting the render timer, either for the first time
//or from a paused state, such as resizing or applying new options.
bool newController = CreateControllerFromOptions();
const auto newController = CreateControllerFromOptions();
if (m_Controller.get())
{

View File

@ -102,7 +102,7 @@ public:
TopArrow(int width, size_t index)
{
QPolygon area;
const auto center = 10;
constexpr int center = 10;
const auto mid = width / 2;
const auto left = center - mid;
const auto right = center + mid;

View File

@ -44,14 +44,10 @@ protected:
if (e->type() == QEvent::MouseMove)
{
if (const auto me = dynamic_cast<QMouseEvent*>(e))
{
emit MouseDragged(me->localPos(), me->globalPos());
}
}
else if (e->type() == QEvent::MouseButtonRelease)
{
emit MouseReleased();
}
return QTableWidget::eventFilter(obj, e);
}