mirror of
https://bitbucket.org/mfeemster/fractorium.git
synced 2025-07-01 22:06:10 -04:00
--User changes
-Add support for multiple GPU devices. --These options are present in the command line and in Fractorium. -Change scheme of specifying devices from platform,device to just total device index. --Single number on the command line. --Change from combo boxes for device selection to a table of all devices in Fractorium. -Temporal samples defaults to 100 instead of 1000 which was needless overkill. --Bug fixes -EmberAnimate, EmberRender, FractoriumSettings, FinalRenderDialog: Fix wrong order of arguments to Clamp() when assigning thread priority. -VariationsDC.h: Fix NVidia OpenCL compilation error in DCTriangleVariation. -FractoriumXformsColor.cpp: Checking for null pixmap pointer is not enough, must also check if the underlying buffer is null via call to QPixmap::isNull(). --Code changes -Ember.h: Add case for FLAME_MOTION_NONE and default in ApplyFlameMotion(). -EmberMotion.h: Call base constructor. -EmberPch.h: #pragma once only on Windows. -EmberToXml.h: --Handle different types of exceptions. --Add default cases to ToString(). -Isaac.h: Remove unused variable in constructor. -Point.h: Call base constructor in Color(). -Renderer.h/cpp: --Add bool to Alloc() to only allocate memory for the histogram. Needed for multi-GPU. --Make CoordMap() return a const ref, not a pointer. -SheepTools.h: --Use 64-bit types like the rest of the code already does. --Fix some comment misspellings. -Timing.h: Make BeginTime(), EndTime(), ElapsedTime() and Format() be const functions. -Utils.h: --Add new functions Equal() and Split(). --Handle more exception types in ReadFile(). --Get rid of most legacy blending of C and C++ argument parsing. -XmlToEmber.h: --Get rid of most legacy blending of C and C++ code from flam3. --Remove some unused variables. -EmberAnimate: --Support multi-GPU processing that alternates full frames between devices. --Use OpenCLInfo instead of OpenCLWrapper for --openclinfo option. --Remove bucketT template parameter, and hard code float in its place. --If a render fails, exit since there is no point in continuing an animation with a missing frame. --Pass variables to threaded save better, which most likely fixes a very subtle bug that existed before. --Remove some unused variables. -EmberGenome, EmberRender: --Support multi-GPU processing that alternates full frames between devices. --Use OpenCLInfo instead of OpenCLWrapper for --openclinfo option. --Remove bucketT template parameter, and hard code float in its place. -EmberRender: --Support multi-GPU processing that alternates full frames between devices. --Use OpenCLInfo instead of OpenCLWrapper for --openclinfo option. --Remove bucketT template parameter, and hard code float in its place. --Only print values when not rendering with OpenCL, since they're always 0 in that case. -EmberCLPch.h: --#pragma once only on Windows. --#include <atomic>. -IterOpenCLKernelCreator.h: Add new kernel for summing two histograms. This is needed for multi-GPU. -OpenCLWrapper.h: --Move all OpenCL info related code into its own class OpenCLInfo. --Add members to cache the values of global memory size and max allocation size. -RendererCL.h/cpp: --Redesign to accomodate multi-GPU. --Constructor now takes a vector of devices. --Remove DumpErrorReport() function, it's handled in the base. --ClearBuffer(), ReadPoints(), WritePoints(), ReadHist() and WriteHist() now optionally take a device index as a parameter. --MakeDmap() override and m_DmapCL member removed because it no longer applies since the histogram is always float since the last commit. --Add new function SumDeviceHist() to sum histograms from two devices by first copying to a temporary on the host, then a temporary on the device, then summing. --m_Calls member removed, as it's now per-device. --OpenCLWrapper removed. --m_Seeds member is now a vector of vector of seeds, to accomodate a separate and different array of seeds for each device. --Added member m_Devices, a vector of unique_ptr of RendererCLDevice. -EmberCommon.h --Added Devices() function to convert from a vector of device indices to a vector of platform,device indices. --Changed CreateRenderer() to accept a vector of devices to create a single RendererCL which will split work across multiple devices. --Added CreateRenderers() function to accept a vector of devices to create multiple RendererCL, each which will render on a single device. --Add more comments to some existing functions. -EmberCommonPch.h: #pragma once only on Windows. -EmberOptions.h: --Remove --platform option, it's just sequential device number now with the --device option. --Make --out be OPT_USE_RENDER instead of OPT_RENDER_ANIM since it's an error condition when animating. It makes no sense to write all frames to a single image. --Add Devices() function to parse comma separated --device option string and return a vector of device indices. --Make int and uint types be 64-bit, so intmax_t and size_t. --Make better use of macros. -JpegUtils.h: Make string parameters to WriteJpeg() and WritePng() be const ref. -All project files: Turn off buffer security check option in Visual Studio (/Gs-) -deployment.pri: Remove the line OTHER_FILES +=, it's pointless and was causing problems. -Ember.pro, EmberCL.pro: Add CONFIG += plugin, otherwise it wouldn't link. -EmberCL.pro: Add new files for multi-GPU support. -build_all.sh: use -j4 and QMAKE=${QMAKE:/usr/bin/qmake} -shared_settings.pri: -Add version string. -Remove old DESTDIR definitions. -Add the following lines or else nothing would build: 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)) LIBS += -L/usr/lib -lpthread -AboutDialog.ui: Another futile attempt to make it look correct on Linux. -FinalRenderDialog.h/cpp: --Add support for multi-GPU. --Change from combo boxes for device selection to a table of all devices. --Ensure device selection makes sense. --Remove "FinalRender" prefix of various function names, it's implied given the context. -FinalRenderEmberController.h/cpp: --Add support for multi-GPU. --Change m_FinishedImageCount to be atomic. --Move CancelRender() from the base to FinalRenderEmberController<T>. --Refactor RenderComplete() to omit any progress related functionality or image saving since it can be potentially ran in a thread. --Consolidate setting various renderer fields into SyncGuiToRenderer(). -Fractorium.cpp: Allow for resizing of the options dialog to show the entire device table. -FractoriumCommon.h: Add various functions to handle a table showing the available OpenCL devices on the system. -FractoriumEmberController.h/cpp: Remove m_FinalImageIndex, it's no longer needed. -FractoriumRender.cpp: Scale the interactive sub batch count and quality by the number of devices used. -FractoriumSettings.h/cpp: --Temporal samples defaults to 100 instead of 1000 which was needless overkill. --Add multi-GPU support, remove old device,platform pair. -FractoriumToolbar.cpp: Disable OpenCL toolbar button if there are no devices present on the system. -FractoriumOptionsDialog.h/cpp: --Add support for multi-GPU. --Consolidate more assignments in DataToGui(). --Enable/disable CPU/OpenCL items in response to OpenCL checkbox event. -Misc: Convert almost everything to size_t for unsigned, intmax_t for signed.
This commit is contained in:
@ -6,12 +6,12 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>488</width>
|
||||
<height>595</height>
|
||||
<width>596</width>
|
||||
<height>622</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="MinimumExpanding">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
@ -31,223 +31,248 @@
|
||||
<property name="windowTitle">
|
||||
<string>About</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
<property name="sizeGripEnabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<widget class="QLabel" name="DescriptionLabel">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>6</x>
|
||||
<y>5</y>
|
||||
<width>583</width>
|
||||
<height>151</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>12</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="DescriptionLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>12</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><html><head/><body><p align="center"><br/>Fractorium 0.4.1.9 Beta</p><p align="center"><span style=" font-size:10pt;"><br/>A Qt-based fractal flame editor which uses a C++ re-write of the flam3 algorithm named Ember and a GPU capable version named EmberCL which implements a portion of the cuburn algorithm in OpenCL.</span></p><p align="center"><span style=" font-size:10pt;">Lead: Matt Feemster</span></p><p align="center"><span style=" font-size:10pt;">Contributors: Simon Detheridge</span></p></body></html></string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::RichText</enum>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="CodeCopiedGroupBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Code Copied</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="topMargin">
|
||||
<number>4</number>
|
||||
<property name="text">
|
||||
<string><html><head/><body><p align="center"><br/>Fractorium 0.4.1.9 Beta</p><p align="center"><span style=" font-size:10pt;">A Qt-based fractal flame editor which uses a C++ re-write of the flam3 algorithm named Ember and a GPU capable version named EmberCL which implements a portion of the cuburn algorithm in OpenCL.</span></p><p align="center"><span style=" font-size:10pt;">Lead: Matt Feemster<br/>Contributors: Simon Detheridge</span></p></body></html></string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::RichText</enum>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QWidget" name="verticalLayoutWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>5</x>
|
||||
<y>156</y>
|
||||
<width>585</width>
|
||||
<height>458</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="CodeCopiedGroupBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Code Copied</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="topMargin">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="CodeCopiedLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><html><head/><body><p><a href="http://code.google.com/p/flam3"><span style=" text-decoration: underline; color:#0000ff;">flam3</span></a>: Scott Draves, Erik Reckase (GPL v2)<br/><a href="http://github.com/stevenrobertson/cuburn"><span style=" text-decoration: underline; color:#0000ff;">cuburn</span></a>: Steven Robertson, Michael Semeniuk, Matthew Znoj, Nicolas Mejia (GPL v3)<br/><a href="http://fractron9000.sourceforge.net"><span style=" text-decoration: underline; color:#0000ff;">Fractron 9000</span></a>: Mike Thiesen (GPL)<br/><a href="http://sourceforge.net/projects/apophysis7x"><span style=" text-decoration: underline; color:#0000ff;">Apophysis</span></a>: Mark Townsend, Ronald Hordijk, Peter Sdobnov, Piotr Borys, Georg Kiehne (GPL)<br/><a href="http://jwildfire.org/"><span style=" text-decoration: underline; color:#0000ff;">JWildfire</span></a>: Andreas Maschke (LGPL)<br/>Numerous Apophysis plugin developers (GPL)</p></body></html></string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::RichText</enum>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="LibrariesLinkedGroupBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Libraries Linked</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<property name="topMargin">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="LibrariesLinkedLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><html><head/><body><p><a href="http://qt-project.org"><span style=" text-decoration: underline; color:#0000ff;">Qt</span></a>: Digia Plc (GPL v3, LGPL v2)<br/><a href="http://g-truc.net"><span style=" text-decoration: underline; color:#0000ff;">glm</span></a>: Christophe Riccio (MIT License)<br/><a href="http://threadingbuildingblocks.org"><span style=" text-decoration: underline; color:#0000ff;">Threading Building Blocks</span></a>: Intel Corporation (GPLv2)<br/><a href="http://libjpeg.sourceforge.net"><span style=" text-decoration: underline; color:#0000ff;">libjpeg</span></a>: Independent JPEG Group (Free Software License)<br/><a href="http://libpng.org"><span style=" text-decoration: underline; color:#0000ff;">libpng</span></a>: Glenn Randers-Pehrson et al (Libpng License)<br/><a href="http://xmlsoft.org"><span style=" text-decoration: underline; color:#0000ff;">libxml2</span></a>: Daniel Veillard (MIT License)<br/><a href="http://zlib.net"><span style=" text-decoration: underline; color:#0000ff;">zlib</span></a>: Jean-loup Gailly, Mark Adler (Zlib License)<br/><a href="http://burtleburtle.net/bob/rand/isaac.html"><span style=" text-decoration: underline; color:#0000ff;">QTIsaac</span></a>: Robert J. Jenkins, Quinn Tyler Jackson (Public Domain)<br/><a href="http://cas.ee.ic.ac.uk/people/dt10/index.html"><span style=" text-decoration: underline; color:#0000ff;">MWC64X Random Number Generator</span></a>: David Thomas (Public Domain)<br/><a href="http://code.jellycan.com/simpleopt/"><span style=" text-decoration: underline; color:#0000ff;">SimpleOpt</span></a>: Brodie Thiesfield (MIT License)</p></body></html></string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::RichText</enum>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="IconsUsedGroupBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Icons Used</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<property name="topMargin">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="IconsUsedLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><html><head/><body><p><a href="http://famfamfam.com"><span style=" text-decoration: underline; color:#0000ff;">Silk</span></a>: Mark James (Creative Commons Attribution 2.5 License)<br/><a href="http://momentumdesignlab.com"><span style=" text-decoration: underline; color:#0000ff;">Momentum</span></a>: Momentum Design Lab (Creative Commons Attribution-ShareAlike 3.5 License)<br/><a href="http://everaldo.com"><span style=" text-decoration: underline; color:#0000ff;">Crystal Clear</span></a>: Everaldo Coelho (LGPL)<br/><a href="http://openiconlibrary.sourceforge.net"><span style=" text-decoration: underline; color:#0000ff;">Open Icon Library</span></a>: Jeff Israel (GPL, LGPL, Creative Commons, Public Domain)<br/><a href="http://icons.mysitemyway.com/category/3d-transparent-glass-icons/"><span style=" text-decoration: underline; color:#0000ff;">3D Transparent Glass</span></a>: iconsETC (Public Domain)<br/><a href="http://p.yusukekamiyamane.com"><span style=" text-decoration: underline; color:#0000ff;">Fugue</span></a>: Yusuke Kamiyamane (Creative Commons Attribution 3.0 License)</p></body></html></string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::RichText</enum>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout" rowminimumheight="0">
|
||||
<property name="verticalSpacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="CodeCopiedLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QPushButton" name="okButton">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<width>100</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><html><head/><body><p><a href="http://code.google.com/p/flam3"><span style=" text-decoration: underline; color:#0000ff;">flam3</span></a>: Scott Draves, Erik Reckase (GPL v2)<br/><a href="http://github.com/stevenrobertson/cuburn"><span style=" text-decoration: underline; color:#0000ff;">cuburn</span></a>: Steven Robertson, Michael Semeniuk, Matthew Znoj, Nicolas Mejia (GPL v3)<br/><a href="http://fractron9000.sourceforge.net"><span style=" text-decoration: underline; color:#0000ff;">Fractron 9000</span></a>: Mike Thiesen (GPL)<br/><a href="http://sourceforge.net/projects/apophysis7x"><span style=" text-decoration: underline; color:#0000ff;">Apophysis</span></a>: Mark Townsend, Ronald Hordijk, Peter Sdobnov, Piotr Borys, Georg Kiehne (GPL)<br/><a href="http://jwildfire.org/"><span style=" text-decoration: underline; color:#0000ff;">JWildfire</span></a>: Andreas Maschke (LGPL)<br/>Numerous Apophysis plugin developers (GPL)</p></body></html></string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::RichText</enum>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
<string>OK</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="LibrariesLinkedGroupBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Libraries Linked</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<property name="topMargin">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="LibrariesLinkedLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><html><head/><body><p><a href="http://qt-project.org"><span style=" text-decoration: underline; color:#0000ff;">Qt</span></a>: Digia Plc (GPL v3, LGPL v2)<br/><a href="http://g-truc.net"><span style=" text-decoration: underline; color:#0000ff;">glm</span></a>: Christophe Riccio (MIT License)<br/><a href="http://threadingbuildingblocks.org"><span style=" text-decoration: underline; color:#0000ff;">Threading Building Blocks</span></a>: Intel Corporation (GPLv2)<br/><a href="http://libjpeg.sourceforge.net"><span style=" text-decoration: underline; color:#0000ff;">libjpeg</span></a>: Independent JPEG Group (Free Software License)<br/><a href="http://libpng.org"><span style=" text-decoration: underline; color:#0000ff;">libpng</span></a>: Glenn Randers-Pehrson et al (Libpng License)<br/><a href="http://xmlsoft.org"><span style=" text-decoration: underline; color:#0000ff;">libxml2</span></a>: Daniel Veillard (MIT License)<br/><a href="http://zlib.net"><span style=" text-decoration: underline; color:#0000ff;">zlib</span></a>: Jean-loup Gailly, Mark Adler (Zlib License)<br/><a href="http://burtleburtle.net/bob/rand/isaac.html"><span style=" text-decoration: underline; color:#0000ff;">QTIsaac</span></a>: Robert J. Jenkins, Quinn Tyler Jackson (Public Domain)<br/><a href="http://cas.ee.ic.ac.uk/people/dt10/index.html"><span style=" text-decoration: underline; color:#0000ff;">MWC64X Random Number Generator</span></a>: David Thomas (Public Domain)<br/><a href="http://code.jellycan.com/simpleopt/"><span style=" text-decoration: underline; color:#0000ff;">SimpleOpt</span></a>: Brodie Thiesfield (MIT License)</p></body></html></string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::RichText</enum>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="IconsUsedGroupBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Icons Used</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<property name="topMargin">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="IconsUsedLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><html><head/><body><p><a href="http://famfamfam.com"><span style=" text-decoration: underline; color:#0000ff;">Silk</span></a>: Mark James (Creative Commons Attribution 2.5 License)<br/><a href="http://momentumdesignlab.com"><span style=" text-decoration: underline; color:#0000ff;">Momentum</span></a>: Momentum Design Lab (Creative Commons Attribution-ShareAlike 3.5 License)<br/><a href="http://everaldo.com"><span style=" text-decoration: underline; color:#0000ff;">Crystal Clear</span></a>: Everaldo Coelho (LGPL)<br/><a href="http://openiconlibrary.sourceforge.net"><span style=" text-decoration: underline; color:#0000ff;">Open Icon Library</span></a>: Jeff Israel (GPL, LGPL, Creative Commons, Public Domain)<br/><a href="http://icons.mysitemyway.com/category/3d-transparent-glass-icons/"><span style=" text-decoration: underline; color:#0000ff;">3D Transparent Glass</span></a>: iconsETC (Public Domain)<br/><a href="http://p.yusukekamiyamane.com"><span style=" text-decoration: underline; color:#0000ff;">Fugue</span></a>: Yusuke Kamiyamane (Creative Commons Attribution 3.0 License)</p></body></html></string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::RichText</enum>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout" rowminimumheight="0">
|
||||
<property name="verticalSpacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QPushButton" name="okButton">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>OK</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
|
@ -124,7 +124,7 @@ void CurvesGraphicsView::Set(int curveIndex, int pointIndex, const QPointF& poin
|
||||
/// <param name="curveIndex">The curve to set</param>
|
||||
void CurvesGraphicsView::SetTop(CurveIndex curveIndex)
|
||||
{
|
||||
int index;
|
||||
size_t index;
|
||||
|
||||
switch (curveIndex)
|
||||
{
|
||||
@ -142,7 +142,7 @@ void CurvesGraphicsView::SetTop(CurveIndex curveIndex)
|
||||
index = 3;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
for (size_t i = 0; i < 4; i++)
|
||||
{
|
||||
if (i == index)
|
||||
{
|
||||
|
@ -76,7 +76,7 @@ public:
|
||||
/// <param name="param">The name of the parameter this is for</param>
|
||||
/// <param name="h">The height of the spin box. Default: 16.</param>
|
||||
/// <param name="step">The step used to increment/decrement the spin box when using the mouse wheel. Default: 0.05.</param>
|
||||
explicit VariationTreeDoubleSpinBox(QWidget* p, VariationTreeWidgetItem* widgetItem, eVariationId id, string param, int h = 16, double step = 0.05)
|
||||
explicit VariationTreeDoubleSpinBox(QWidget* p, VariationTreeWidgetItem* widgetItem, eVariationId id, const string& param, int h = 16, double step = 0.05)
|
||||
: DoubleSpinBox(p, h, step)
|
||||
{
|
||||
m_WidgetItem = widgetItem;
|
||||
|
@ -11,7 +11,8 @@
|
||||
/// <param name="p">The parent widget</param>
|
||||
/// <param name="f">The window flags. Default: 0.</param>
|
||||
FractoriumFinalRenderDialog::FractoriumFinalRenderDialog(FractoriumSettings* settings, QWidget* p, Qt::WindowFlags f)
|
||||
: QDialog(p, f)
|
||||
: QDialog(p, f),
|
||||
m_Info(OpenCLInfo::Instance())
|
||||
{
|
||||
ui.setupUi(this);
|
||||
|
||||
@ -29,18 +30,18 @@ FractoriumFinalRenderDialog::FractoriumFinalRenderDialog(FractoriumSettings* set
|
||||
connect(ui.FinalRenderTransparencyCheckBox, SIGNAL(stateChanged(int)), this, SLOT(OnTransparencyCheckBoxStateChanged(int)), Qt::QueuedConnection);
|
||||
connect(ui.FinalRenderOpenCLCheckBox, SIGNAL(stateChanged(int)), this, SLOT(OnOpenCLCheckBoxStateChanged(int)), Qt::QueuedConnection);
|
||||
connect(ui.FinalRenderDoublePrecisionCheckBox, SIGNAL(stateChanged(int)), this, SLOT(OnDoublePrecisionCheckBoxStateChanged(int)), Qt::QueuedConnection);
|
||||
connect(ui.FinalRenderPlatformCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(OnPlatformComboCurrentIndexChanged(int)), Qt::QueuedConnection);
|
||||
connect(ui.FinalRenderDoAllCheckBox, SIGNAL(stateChanged(int)), this, SLOT(OnDoAllCheckBoxStateChanged(int)), Qt::QueuedConnection);
|
||||
connect(ui.FinalRenderDoSequenceCheckBox, SIGNAL(stateChanged(int)), this, SLOT(OnDoSequenceCheckBoxStateChanged(int)), Qt::QueuedConnection);
|
||||
connect(ui.FinalRenderCurrentSpin, SIGNAL(valueChanged(int)), this, SLOT(OnFinalRenderCurrentSpinChanged(int)), Qt::QueuedConnection);
|
||||
connect(ui.FinalRenderCurrentSpin, SIGNAL(valueChanged(int)), this, SLOT(OnCurrentSpinChanged(int)), Qt::QueuedConnection);
|
||||
connect(ui.FinalRenderApplyToAllCheckBox, SIGNAL(stateChanged(int)), this, SLOT(OnApplyAllCheckBoxStateChanged(int)), Qt::QueuedConnection);
|
||||
connect(ui.FinalRenderKeepAspectCheckBox, SIGNAL(stateChanged(int)), this, SLOT(OnKeepAspectCheckBoxStateChanged(int)), Qt::QueuedConnection);
|
||||
connect(ui.FinalRenderScaleNoneRadioButton, SIGNAL(toggled(bool)), this, SLOT(OnScaleRadioButtonChanged(bool)), Qt::QueuedConnection);
|
||||
connect(ui.FinalRenderScaleWidthRadioButton, SIGNAL(toggled(bool)), this, SLOT(OnScaleRadioButtonChanged(bool)), Qt::QueuedConnection);
|
||||
connect(ui.FinalRenderScaleHeightRadioButton, SIGNAL(toggled(bool)), this, SLOT(OnScaleRadioButtonChanged(bool)), Qt::QueuedConnection);
|
||||
|
||||
SetupSpinner<DoubleSpinBox, double>(ui.FinalRenderSizeTable, this, row, 1, m_WidthScaleSpin, spinHeight, 0.001, 99.99, 0.1, SIGNAL(valueChanged(double)), SLOT(OnFinalRenderWidthScaleChanged(double)), true, 1.0, 1.0, 1.0);
|
||||
SetupSpinner<DoubleSpinBox, double>(ui.FinalRenderSizeTable, this, row, 1, m_HeightScaleSpin, spinHeight, 0.001, 99.99, 0.1, SIGNAL(valueChanged(double)), SLOT(OnFinalRenderHeightScaleChanged(double)), true, 1.0, 1.0, 1.0);
|
||||
connect(ui.DeviceTable, SIGNAL(cellChanged(int, int)), this, SLOT(OnDeviceTableCellChanged(int, int)), Qt::QueuedConnection);
|
||||
|
||||
SetupSpinner<DoubleSpinBox, double>(ui.FinalRenderSizeTable, this, row, 1, m_WidthScaleSpin, spinHeight, 0.001, 99.99, 0.1, SIGNAL(valueChanged(double)), SLOT(OnWidthScaleChanged(double)), true, 1.0, 1.0, 1.0);
|
||||
SetupSpinner<DoubleSpinBox, double>(ui.FinalRenderSizeTable, this, row, 1, m_HeightScaleSpin, spinHeight, 0.001, 99.99, 0.1, SIGNAL(valueChanged(double)), SLOT(OnHeightScaleChanged(double)), true, 1.0, 1.0, 1.0);
|
||||
m_WidthScaleSpin->setDecimals(3);
|
||||
m_HeightScaleSpin->setDecimals(3);
|
||||
m_WidthScaleSpin->setSuffix(" ( )");
|
||||
@ -68,43 +69,35 @@ FractoriumFinalRenderDialog::FractoriumFinalRenderDialog(FractoriumSettings* set
|
||||
table->item(row++, 1)->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter);
|
||||
connect(m_Tbcw->m_Button1, SIGNAL(clicked(bool)), this, SLOT(OnFileButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(m_Tbcw->m_Button2, SIGNAL(clicked(bool)), this, SLOT(OnShowFolderButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(m_Tbcw->m_Combo, SIGNAL(currentIndexChanged(int)), this, SLOT(OnFinalRenderExtIndexChanged(int)), Qt::QueuedConnection);
|
||||
connect(m_Tbcw->m_Combo, SIGNAL(currentIndexChanged(int)), this, SLOT(OnExtIndexChanged(int)), Qt::QueuedConnection);
|
||||
|
||||
m_PrefixEdit = new QLineEdit(table);
|
||||
table->setCellWidget(row++, 1, m_PrefixEdit);
|
||||
|
||||
m_SuffixEdit = new QLineEdit(table);
|
||||
table->setCellWidget(row++, 1, m_SuffixEdit);
|
||||
connect(m_PrefixEdit, SIGNAL(textChanged(const QString&)), this, SLOT(OnFinalRenderPrefixChanged(const QString&)), Qt::QueuedConnection);
|
||||
connect(m_SuffixEdit, SIGNAL(textChanged(const QString&)), this, SLOT(OnFinalRenderSuffixChanged(const QString&)), Qt::QueuedConnection);
|
||||
connect(m_PrefixEdit, SIGNAL(textChanged(const QString&)), this, SLOT(OnPrefixChanged(const QString&)), Qt::QueuedConnection);
|
||||
connect(m_SuffixEdit, SIGNAL(textChanged(const QString&)), this, SLOT(OnSuffixChanged(const QString&)), Qt::QueuedConnection);
|
||||
|
||||
ui.StartRenderButton->disconnect(SIGNAL(clicked(bool)));
|
||||
connect(ui.StartRenderButton, SIGNAL(clicked(bool)), this, SLOT(OnRenderClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.StopRenderButton, SIGNAL(clicked(bool)), this, SLOT(OnCancelRenderClicked(bool)), Qt::QueuedConnection);
|
||||
|
||||
if (m_Wrapper.CheckOpenCL())
|
||||
table = ui.DeviceTable;
|
||||
|
||||
if (m_Info.Ok() && !m_Info.Devices().empty())
|
||||
{
|
||||
vector<string> platforms = m_Wrapper.PlatformNames();
|
||||
SetupDeviceTable(table, m_Settings->FinalDevices());
|
||||
|
||||
//Populate combo boxes with available OpenCL platforms and devices.
|
||||
for (i = 0; i < platforms.size(); i++)
|
||||
ui.FinalRenderPlatformCombo->addItem(QString::fromStdString(platforms[i]));
|
||||
for (int i = 0; i < table->rowCount(); i++)
|
||||
if (auto radio = qobject_cast<QRadioButton*>(table->cellWidget(i, 1)))
|
||||
connect(radio, SIGNAL(toggled(bool)), this, SLOT(OnDeviceTableRadioToggled(bool)), Qt::QueuedConnection);
|
||||
|
||||
//If init succeeds, set the selected platform and device combos to match what was saved in the settings.
|
||||
if (m_Wrapper.Init(m_Settings->FinalPlatformIndex(), m_Settings->FinalDeviceIndex()))
|
||||
{
|
||||
ui.FinalRenderOpenCLCheckBox->setChecked( m_Settings->FinalOpenCL());
|
||||
ui.FinalRenderPlatformCombo->setCurrentIndex(m_Settings->FinalPlatformIndex());
|
||||
ui.FinalRenderDeviceCombo->setCurrentIndex( m_Settings->FinalDeviceIndex());
|
||||
}
|
||||
else
|
||||
{
|
||||
OnPlatformComboCurrentIndexChanged(0);
|
||||
ui.FinalRenderOpenCLCheckBox->setChecked(false);
|
||||
}
|
||||
ui.FinalRenderOpenCLCheckBox->setChecked(m_Settings->FinalOpenCL());
|
||||
}
|
||||
else
|
||||
{
|
||||
table->setEnabled(false);
|
||||
ui.FinalRenderOpenCLCheckBox->setChecked(false);
|
||||
ui.FinalRenderOpenCLCheckBox->setEnabled(false);
|
||||
}
|
||||
@ -128,7 +121,7 @@ FractoriumFinalRenderDialog::FractoriumFinalRenderDialog(FractoriumSettings* set
|
||||
else if (m_Settings->FinalThreadPriority() == THREAD_PRIORITY_HIGHEST)
|
||||
ui.FinalRenderThreadPriorityComboBox->setCurrentIndex(tpc);
|
||||
else
|
||||
ui.FinalRenderThreadPriorityComboBox->setCurrentIndex(Clamp<int>(0, tpc, m_Settings->FinalThreadPriority() / 25));
|
||||
ui.FinalRenderThreadPriorityComboBox->setCurrentIndex(Clamp<int>(m_Settings->FinalThreadPriority() / 25, 0, tpc));
|
||||
#endif
|
||||
|
||||
m_QualitySpin->setValue(m_Settings->FinalQuality());
|
||||
@ -167,8 +160,7 @@ FractoriumFinalRenderDialog::FractoriumFinalRenderDialog(FractoriumSettings* set
|
||||
w = SetTabOrder(this, w, ui.FinalRenderDoAllCheckBox);
|
||||
w = SetTabOrder(this, w, ui.FinalRenderDoSequenceCheckBox);
|
||||
w = SetTabOrder(this, w, ui.FinalRenderCurrentSpin);
|
||||
w = SetTabOrder(this, w, ui.FinalRenderPlatformCombo);
|
||||
w = SetTabOrder(this, w, ui.FinalRenderDeviceCombo);
|
||||
w = SetTabOrder(this, w, ui.DeviceTable);
|
||||
w = SetTabOrder(this, w, ui.FinalRenderThreadCountSpin);
|
||||
w = SetTabOrder(this, w, ui.FinalRenderThreadPriorityComboBox);
|
||||
w = SetTabOrder(this, w, ui.FinalRenderApplyToAllCheckBox);
|
||||
@ -214,8 +206,6 @@ void FractoriumFinalRenderDialog::Path(const QString& s) { ui.FinalRenderParamsT
|
||||
QString FractoriumFinalRenderDialog::Prefix() { return m_PrefixEdit->text(); }
|
||||
QString FractoriumFinalRenderDialog::Suffix() { return m_SuffixEdit->text(); }
|
||||
uint FractoriumFinalRenderDialog::Current() { return ui.FinalRenderCurrentSpin->value(); }
|
||||
uint FractoriumFinalRenderDialog::PlatformIndex() { return ui.FinalRenderPlatformCombo->currentIndex(); }
|
||||
uint FractoriumFinalRenderDialog::DeviceIndex() { return ui.FinalRenderDeviceCombo->currentIndex(); }
|
||||
uint FractoriumFinalRenderDialog::ThreadCount() { return ui.FinalRenderThreadCountSpin->value(); }
|
||||
#ifdef _WIN32
|
||||
int FractoriumFinalRenderDialog::ThreadPriority() { return ui.FinalRenderThreadPriorityComboBox->currentIndex() - 2; }
|
||||
@ -236,6 +226,7 @@ double FractoriumFinalRenderDialog::Quality() { return m_QualitySpin->value(); }
|
||||
uint FractoriumFinalRenderDialog::TemporalSamples() { return m_TemporalSamplesSpin->value(); }
|
||||
uint FractoriumFinalRenderDialog::Supersample() { return m_SupersampleSpin->value(); }
|
||||
uint FractoriumFinalRenderDialog::Strips() { return m_StripsSpin->value(); }
|
||||
QList<QVariant> FractoriumFinalRenderDialog::Devices() { return DeviceTableToSettings(ui.DeviceTable); }
|
||||
|
||||
/// <summary>
|
||||
/// Capture the current state of the Gui.
|
||||
@ -260,8 +251,7 @@ FinalRenderGuiState FractoriumFinalRenderDialog::State()
|
||||
state.m_Ext = Ext();
|
||||
state.m_Prefix = Prefix();
|
||||
state.m_Suffix = Suffix();
|
||||
state.m_PlatformIndex = PlatformIndex();
|
||||
state.m_DeviceIndex = DeviceIndex();
|
||||
state.m_Devices = Devices();
|
||||
state.m_ThreadCount = ThreadCount();
|
||||
state.m_ThreadPriority = ThreadPriority();
|
||||
state.m_WidthScale = WidthScale();
|
||||
@ -348,14 +338,14 @@ void FractoriumFinalRenderDialog::OnTransparencyCheckBoxStateChanged(int state)
|
||||
|
||||
/// <summary>
|
||||
/// Set whether to use OpenCL in the rendering process or not.
|
||||
/// Also disable or enable the CPU and OpenCL related controls based on the state passed in.
|
||||
/// </summary>
|
||||
/// <param name="state">Use OpenCL if state == Qt::Checked, else don't.</param>
|
||||
void FractoriumFinalRenderDialog::OnOpenCLCheckBoxStateChanged(int state)
|
||||
{
|
||||
bool checked = state == Qt::Checked;
|
||||
|
||||
ui.FinalRenderPlatformCombo->setEnabled(checked);
|
||||
ui.FinalRenderDeviceCombo->setEnabled(checked);
|
||||
ui.DeviceTable->setEnabled(checked);
|
||||
ui.FinalRenderThreadCountSpin->setEnabled(!checked);
|
||||
ui.FinalRenderThreadPriorityComboBox->setEnabled(!checked);
|
||||
SetMemory();
|
||||
@ -379,6 +369,9 @@ void FractoriumFinalRenderDialog::OnDoublePrecisionCheckBoxStateChanged(int stat
|
||||
/// <param name="state">The state of the checkbox</param>
|
||||
void FractoriumFinalRenderDialog::OnDoAllCheckBoxStateChanged(int state)
|
||||
{
|
||||
if (!state)
|
||||
ui.FinalRenderDoSequenceCheckBox->setChecked(false);
|
||||
|
||||
ui.FinalRenderDoSequenceCheckBox->setEnabled(ui.FinalRenderDoAllCheckBox->isChecked());
|
||||
}
|
||||
|
||||
@ -390,36 +383,28 @@ void FractoriumFinalRenderDialog::OnDoAllCheckBoxStateChanged(int state)
|
||||
/// <param name="state">The state of the checkbox</param>
|
||||
void FractoriumFinalRenderDialog::OnDoSequenceCheckBoxStateChanged(int state)
|
||||
{
|
||||
m_TemporalSamplesSpin->setEnabled(ui.FinalRenderDoSequenceCheckBox->isChecked());
|
||||
bool checked = ui.FinalRenderDoSequenceCheckBox->isChecked();
|
||||
|
||||
m_TemporalSamplesSpin->setEnabled(checked);
|
||||
|
||||
if (checked)
|
||||
m_StripsSpin->setValue(1);
|
||||
|
||||
m_StripsSpin->setEnabled(!checked);
|
||||
SetMemory();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The current ember spinner was changed, update fields.
|
||||
/// </summary>
|
||||
/// <param name="d">Ignored</param>
|
||||
void FractoriumFinalRenderDialog::OnFinalRenderCurrentSpinChanged(int d)
|
||||
void FractoriumFinalRenderDialog::OnCurrentSpinChanged(int d)
|
||||
{
|
||||
m_Controller->SetEmber(d - 1);
|
||||
m_Controller->SyncCurrentToGui();
|
||||
SetMemory();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Populate the the device combo box with all available
|
||||
/// OpenCL devices for the selected platform.
|
||||
/// Called when the platform combo box index changes.
|
||||
/// </summary>
|
||||
/// <param name="index">The selected index of the combo box</param>
|
||||
void FractoriumFinalRenderDialog::OnPlatformComboCurrentIndexChanged(int index)
|
||||
{
|
||||
vector<string> devices = m_Wrapper.DeviceNames(index);
|
||||
|
||||
ui.FinalRenderDeviceCombo->clear();
|
||||
|
||||
for (auto& device : devices)
|
||||
ui.FinalRenderDeviceCombo->addItem(QString::fromStdString(device));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The apply all checkbox was changed.
|
||||
/// If checked, set values for all embers in the file to the values specified in the GUI.
|
||||
@ -437,7 +422,7 @@ void FractoriumFinalRenderDialog::OnApplyAllCheckBoxStateChanged(int state)
|
||||
/// the height spinner as well to be in proportion.
|
||||
/// </summary>
|
||||
/// <param name="d">Ignored</param>
|
||||
void FractoriumFinalRenderDialog::OnFinalRenderWidthScaleChanged(double d)
|
||||
void FractoriumFinalRenderDialog::OnWidthScaleChanged(double d)
|
||||
{
|
||||
if (ui.FinalRenderKeepAspectCheckBox->isChecked() && m_Controller.get())
|
||||
m_HeightScaleSpin->SetValueStealth(m_WidthScaleSpin->value());
|
||||
@ -452,7 +437,7 @@ void FractoriumFinalRenderDialog::OnFinalRenderWidthScaleChanged(double d)
|
||||
/// the width spinner as well to be in proportion.
|
||||
/// </summary>
|
||||
/// <param name="d">Ignored</param>
|
||||
void FractoriumFinalRenderDialog::OnFinalRenderHeightScaleChanged(double d)
|
||||
void FractoriumFinalRenderDialog::OnHeightScaleChanged(double d)
|
||||
{
|
||||
if (ui.FinalRenderKeepAspectCheckBox->isChecked() && m_Controller.get())
|
||||
m_WidthScaleSpin->SetValueStealth(m_HeightScaleSpin->value());
|
||||
@ -484,6 +469,50 @@ void FractoriumFinalRenderDialog::OnScaleRadioButtonChanged(bool checked)
|
||||
SetMemory();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The check state of one of the OpenCL devices was changed.
|
||||
/// This does a special check to always ensure at least one device,
|
||||
/// as well as one primary is checked.
|
||||
/// </summary>
|
||||
/// <param name="row">The row of the cell</param>
|
||||
/// <param name="col">The column of the cell</param>
|
||||
void FractoriumFinalRenderDialog::OnDeviceTableCellChanged(int row, int col)
|
||||
{
|
||||
if (auto item = ui.DeviceTable->item(row, col))
|
||||
{
|
||||
HandleDeviceTableCheckChanged(ui.DeviceTable, row, col);
|
||||
SetMemory();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The primary device radio button selection was changed.
|
||||
/// If the device was specified as primary, but was not selected
|
||||
/// for inclusion, it will automatically be selected for inclusion.
|
||||
/// </summary>
|
||||
/// <param name="checked">The state of the radio button</param>
|
||||
void FractoriumFinalRenderDialog::OnDeviceTableRadioToggled(bool checked)
|
||||
{
|
||||
int row;
|
||||
auto s = sender();
|
||||
auto table = ui.DeviceTable;
|
||||
QRadioButton* radio = nullptr;
|
||||
|
||||
if (s)
|
||||
{
|
||||
for (row = 0; row < table->rowCount(); row++)
|
||||
if (radio = qobject_cast<QRadioButton*>(table->cellWidget(row, 1)))
|
||||
if (s == radio)
|
||||
{
|
||||
HandleDeviceTableCheckChanged(ui.DeviceTable, row, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (checked)
|
||||
SetMemory();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The quality spinner was changed, recompute required memory.
|
||||
/// </summary>
|
||||
@ -558,7 +587,7 @@ void FractoriumFinalRenderDialog::OnShowFolderButtonClicked(bool checked)
|
||||
/// number of channels used in the final output buffer.
|
||||
/// </summary>
|
||||
/// <param name="d">Ignored</param>
|
||||
void FractoriumFinalRenderDialog::OnFinalRenderExtIndexChanged(int d)
|
||||
void FractoriumFinalRenderDialog::OnExtIndexChanged(int d)
|
||||
{
|
||||
if (SetMemory())
|
||||
Path(m_Controller->ComposePath(m_Controller->Name()));
|
||||
@ -568,7 +597,7 @@ void FractoriumFinalRenderDialog::OnFinalRenderExtIndexChanged(int d)
|
||||
/// Change the prefix prepended to the output file name.
|
||||
/// </summary>
|
||||
/// <param name="s">Ignored</param>
|
||||
void FractoriumFinalRenderDialog::OnFinalRenderPrefixChanged(const QString& s)
|
||||
void FractoriumFinalRenderDialog::OnPrefixChanged(const QString& s)
|
||||
{
|
||||
Path(m_Controller->ComposePath(m_Controller->Name()));
|
||||
}
|
||||
@ -577,7 +606,7 @@ void FractoriumFinalRenderDialog::OnFinalRenderPrefixChanged(const QString& s)
|
||||
/// Change the suffix appended to the output file name.
|
||||
/// </summary>
|
||||
/// <param name="s">Ignored</param>
|
||||
void FractoriumFinalRenderDialog::OnFinalRenderSuffixChanged(const QString& s)
|
||||
void FractoriumFinalRenderDialog::OnSuffixChanged(const QString& s)
|
||||
{
|
||||
Path(m_Controller->ComposePath(m_Controller->Name()));
|
||||
}
|
||||
@ -637,7 +666,7 @@ void FractoriumFinalRenderDialog::showEvent(QShowEvent* e)
|
||||
ui.FinalRenderCurrentSpin->blockSignals(true);
|
||||
ui.FinalRenderCurrentSpin->setValue(index);//Set the currently selected ember to the one that was being edited.
|
||||
ui.FinalRenderCurrentSpin->blockSignals(false);
|
||||
OnFinalRenderCurrentSpinChanged(index);//Force update in case the ember was new, but at the same index as the previous one.
|
||||
OnCurrentSpinChanged(index);//Force update in case the ember was new, but at the same index as the previous one.
|
||||
m_Controller->m_ImageCount = 0;
|
||||
SetMemory();
|
||||
m_Controller->ResetProgress();
|
||||
@ -655,7 +684,7 @@ void FractoriumFinalRenderDialog::showEvent(QShowEvent* e)
|
||||
/// <summary>
|
||||
/// Close the dialog without running, or if running, cancel and exit.
|
||||
/// Settings will not be saved.
|
||||
/// Control will be returned to Fractorium::OnActionFinalRender().
|
||||
/// Control will be returned to Fractorium::OnActiOn().
|
||||
/// </summary>
|
||||
void FractoriumFinalRenderDialog::reject()
|
||||
{
|
||||
@ -736,48 +765,58 @@ bool FractoriumFinalRenderDialog::CreateControllerFromGUI(bool createRenderer)
|
||||
/// <summary>
|
||||
/// Compute the amount of memory needed via call to SyncAndComputeMemory(), then
|
||||
/// assign the result to the table cell as text.
|
||||
/// Report errors if not enough memory is available for any of the selected devices.
|
||||
/// </summary>
|
||||
/// <returns>True devices and a controller is present, else false.</returns>
|
||||
bool FractoriumFinalRenderDialog::SetMemory()
|
||||
{
|
||||
if (isVisible() && CreateControllerFromGUI(true))
|
||||
{
|
||||
bool error = false;
|
||||
tuple<size_t, size_t, size_t> p = m_Controller->SyncAndComputeMemory();
|
||||
QString s;
|
||||
|
||||
ui.FinalRenderParamsTable->item(m_MemoryCellIndex, 1)->setText(ToString<qulonglong>(get<1>(p)));
|
||||
ui.FinalRenderParamsTable->item(m_ItersCellIndex, 1)->setText(ToString<qulonglong>(get<2>(p)));
|
||||
|
||||
if (OpenCL())
|
||||
|
||||
if (OpenCL() && !m_Wrappers.empty())
|
||||
{
|
||||
if (!m_Wrapper.Ok() || PlatformIndex() != m_Wrapper.PlatformIndex() || DeviceIndex() != m_Wrapper.DeviceIndex())
|
||||
m_Wrapper.Init(PlatformIndex(), DeviceIndex());
|
||||
auto devices = Devices();
|
||||
|
||||
if (m_Wrapper.Ok())
|
||||
for (size_t i = 0; i < m_Wrappers.size(); i++)
|
||||
{
|
||||
size_t histSize = get<0>(p);
|
||||
size_t totalSize = get<1>(p);
|
||||
size_t maxAlloc = m_Wrapper.MaxAllocSize();
|
||||
size_t totalAvail = m_Wrapper.GlobalMemSize();
|
||||
QString s;
|
||||
|
||||
if (histSize > maxAlloc)
|
||||
if (devices.contains(int(i)))
|
||||
{
|
||||
s = "Histogram/Accumulator memory size of " + ToString<qulonglong>(histSize) +
|
||||
" is greater than the max OpenCL allocation size of " + ToString<qulonglong>(maxAlloc);
|
||||
}
|
||||
size_t histSize = get<0>(p);
|
||||
size_t totalSize = get<1>(p);
|
||||
size_t maxAlloc = m_Wrappers[i].MaxAllocSize();
|
||||
size_t totalAvail = m_Wrappers[i].GlobalMemSize();
|
||||
QString temp;
|
||||
|
||||
if (totalSize > totalAvail)
|
||||
{
|
||||
s += "\n\nTotal required memory size of " + ToString<qulonglong>(totalSize) +
|
||||
" is greater than the max OpenCL available memory of " + ToString<qulonglong>(totalAvail);
|
||||
}
|
||||
if (histSize > maxAlloc)
|
||||
{
|
||||
temp = "Histogram/Accumulator memory size of " + ToString<qulonglong>(histSize) +
|
||||
" is greater than the max OpenCL allocation size of " + ToString<qulonglong>(maxAlloc);
|
||||
}
|
||||
|
||||
if (!s.isEmpty())
|
||||
{
|
||||
error = true;
|
||||
ui.FinalRenderTextOutput->setText(s + ".\n\nRendering will most likely fail.");
|
||||
if (totalSize > totalAvail)
|
||||
{
|
||||
temp += "\n\nTotal required memory size of " + ToString<qulonglong>(totalSize) +
|
||||
" is greater than the max OpenCL available memory of " + ToString<qulonglong>(totalAvail);
|
||||
}
|
||||
|
||||
if (!temp.isEmpty())
|
||||
{
|
||||
error = true;
|
||||
s += QString::fromStdString(m_Wrappers[i].DeviceName()) + ":\n" + temp + "\n\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!s.isEmpty())
|
||||
s += "Rendering will most likely fail.";
|
||||
|
||||
ui.FinalRenderTextOutput->setText(s);
|
||||
}
|
||||
|
||||
if (!error)
|
||||
|
@ -65,8 +65,6 @@ public:
|
||||
QString Prefix();
|
||||
QString Suffix();
|
||||
uint Current();
|
||||
uint PlatformIndex();
|
||||
uint DeviceIndex();
|
||||
uint ThreadCount();
|
||||
int ThreadPriority();
|
||||
double WidthScale();
|
||||
@ -75,6 +73,7 @@ public:
|
||||
uint TemporalSamples();
|
||||
uint Supersample();
|
||||
uint Strips();
|
||||
QList<QVariant> Devices();
|
||||
FinalRenderGuiState State();
|
||||
|
||||
public slots:
|
||||
@ -86,22 +85,23 @@ public slots:
|
||||
void OnDoublePrecisionCheckBoxStateChanged(int state);
|
||||
void OnDoAllCheckBoxStateChanged(int state);
|
||||
void OnDoSequenceCheckBoxStateChanged(int state);
|
||||
void OnFinalRenderCurrentSpinChanged(int d);
|
||||
void OnPlatformComboCurrentIndexChanged(int index);
|
||||
void OnCurrentSpinChanged(int d);
|
||||
void OnApplyAllCheckBoxStateChanged(int state);
|
||||
void OnFinalRenderWidthScaleChanged(double d);
|
||||
void OnFinalRenderHeightScaleChanged(double d);
|
||||
void OnWidthScaleChanged(double d);
|
||||
void OnHeightScaleChanged(double d);
|
||||
void OnKeepAspectCheckBoxStateChanged(int state);
|
||||
void OnScaleRadioButtonChanged(bool checked);
|
||||
void OnDeviceTableCellChanged(int row, int col);
|
||||
void OnDeviceTableRadioToggled(bool checked);
|
||||
void OnQualityChanged(double d);
|
||||
void OnTemporalSamplesChanged(int d);
|
||||
void OnSupersampleChanged(int d);
|
||||
void OnStripsChanged(int d);
|
||||
void OnFileButtonClicked(bool checked);
|
||||
void OnShowFolderButtonClicked(bool checked);
|
||||
void OnFinalRenderExtIndexChanged(int d);
|
||||
void OnFinalRenderPrefixChanged(const QString& s);
|
||||
void OnFinalRenderSuffixChanged(const QString& s);
|
||||
void OnExtIndexChanged(int d);
|
||||
void OnPrefixChanged(const QString& s);
|
||||
void OnSuffixChanged(const QString& s);
|
||||
void OnRenderClicked(bool checked);
|
||||
void OnCancelRenderClicked(bool checked);
|
||||
virtual void reject() override;
|
||||
@ -116,7 +116,6 @@ private:
|
||||
int m_MemoryCellIndex;
|
||||
int m_ItersCellIndex;
|
||||
int m_PathCellIndex;
|
||||
OpenCLWrapper m_Wrapper;
|
||||
Timing m_RenderTimer;
|
||||
DoubleSpinBox* m_WidthScaleSpin;
|
||||
DoubleSpinBox* m_HeightScaleSpin;
|
||||
@ -129,6 +128,8 @@ private:
|
||||
QLineEdit* m_SuffixEdit;
|
||||
FractoriumSettings* m_Settings;
|
||||
Fractorium* m_Fractorium;
|
||||
OpenCLInfo& m_Info;
|
||||
vector<OpenCLWrapper> m_Wrappers;
|
||||
unique_ptr<FinalRenderEmberControllerBase> m_Controller;
|
||||
Ui::FinalRenderDialog ui;
|
||||
};
|
||||
|
@ -7,7 +7,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>519</width>
|
||||
<height>897</height>
|
||||
<height>899</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
@ -64,7 +64,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>507</width>
|
||||
<height>885</height>
|
||||
<height>887</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
@ -240,9 +240,9 @@
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="FinalRenderPlatformCombo">
|
||||
<widget class="QTableWidget" name="DeviceTable">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
@ -250,37 +250,81 @@
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
<height>91</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
<height>91</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="FinalRenderDeviceCombo">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::NoEditTriggers</set>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::NoSelection</enum>
|
||||
</property>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
</property>
|
||||
<property name="showGrid">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="columnCount">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<attribute name="horizontalHeaderDefaultSectionSize">
|
||||
<number>60</number>
|
||||
</attribute>
|
||||
<attribute name="horizontalHeaderStretchLastSection">
|
||||
<bool>true</bool>
|
||||
</attribute>
|
||||
<attribute name="verticalHeaderVisible">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<attribute name="verticalHeaderDefaultSectionSize">
|
||||
<number>22</number>
|
||||
</attribute>
|
||||
<attribute name="verticalHeaderHighlightSections">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<attribute name="verticalHeaderMinimumSectionSize">
|
||||
<number>22</number>
|
||||
</attribute>
|
||||
<row>
|
||||
<property name="text">
|
||||
<string>AMD</string>
|
||||
</property>
|
||||
</row>
|
||||
<row>
|
||||
<property name="text">
|
||||
<string>Nvidia</string>
|
||||
</property>
|
||||
</row>
|
||||
<row>
|
||||
<property name="text">
|
||||
<string>Intel</string>
|
||||
</property>
|
||||
</row>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Use</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Primary</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Device</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
@ -1119,8 +1163,6 @@
|
||||
<tabstop>FinalRenderYAxisUpCheckBox</tabstop>
|
||||
<tabstop>FinalRenderTransparencyCheckBox</tabstop>
|
||||
<tabstop>FinalRenderOpenCLCheckBox</tabstop>
|
||||
<tabstop>FinalRenderPlatformCombo</tabstop>
|
||||
<tabstop>FinalRenderDeviceCombo</tabstop>
|
||||
<tabstop>FinalRenderParamsTable</tabstop>
|
||||
<tabstop>FinalRenderTextOutput</tabstop>
|
||||
<tabstop>StartRenderButton</tabstop>
|
||||
|
@ -15,7 +15,7 @@ FinalRenderEmberControllerBase::FinalRenderEmberControllerBase(FractoriumFinalRe
|
||||
m_Run = false;
|
||||
m_PreviewRun = false;
|
||||
m_ImageCount = 0;
|
||||
m_FinishedImageCount = 0;
|
||||
m_FinishedImageCount.store(0);
|
||||
m_FinalRenderDialog = finalRenderDialog;
|
||||
m_Settings = m_Fractorium->m_Settings;
|
||||
}
|
||||
@ -26,7 +26,8 @@ FinalRenderEmberControllerBase::FinalRenderEmberControllerBase(FractoriumFinalRe
|
||||
/// It should never take longer than a few milliseconds because the
|
||||
/// renderer checks the m_Abort flag in many places during the process.
|
||||
/// </summary>
|
||||
void FinalRenderEmberControllerBase::CancelRender()
|
||||
template <typename T>
|
||||
void FinalRenderEmberController<T>::CancelRender()
|
||||
{
|
||||
if (m_Result.isRunning())
|
||||
{
|
||||
@ -48,6 +49,21 @@ void FinalRenderEmberControllerBase::CancelRender()
|
||||
m_Renderer->LeaveFinalAccum();
|
||||
m_Renderer->LeaveRender();
|
||||
}
|
||||
else
|
||||
{
|
||||
for (auto& renderer : m_Renderers)
|
||||
{
|
||||
renderer->Abort();
|
||||
|
||||
while (renderer->InRender())
|
||||
QApplication::processEvents();
|
||||
|
||||
renderer->EnterRender();
|
||||
renderer->EnterFinalAccum();
|
||||
renderer->LeaveFinalAccum();
|
||||
renderer->LeaveRender();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
g.wait();
|
||||
@ -66,11 +82,11 @@ void FinalRenderEmberControllerBase::CancelRender()
|
||||
/// <returns>True if a valid renderer is created or if no action is taken, else false.</returns>
|
||||
bool FinalRenderEmberControllerBase::CreateRendererFromGUI()
|
||||
{
|
||||
bool useOpenCL = m_Wrapper.CheckOpenCL() && m_FinalRenderDialog->OpenCL();
|
||||
bool useOpenCL = m_Info.Ok() && m_FinalRenderDialog->OpenCL();
|
||||
auto v = Devices(m_FinalRenderDialog->Devices());
|
||||
|
||||
return CreateRenderer(useOpenCL ? OPENCL_RENDERER : CPU_RENDERER,
|
||||
m_FinalRenderDialog->PlatformIndex(),
|
||||
m_FinalRenderDialog->DeviceIndex(),
|
||||
return CreateRenderer((useOpenCL && !v.empty()) ? OPENCL_RENDERER : CPU_RENDERER,
|
||||
v,
|
||||
false);//Not shared.
|
||||
}
|
||||
|
||||
@ -102,9 +118,9 @@ FinalRenderEmberController<T>::FinalRenderEmberController(FractoriumFinalRenderD
|
||||
m_PreviewRun = true;
|
||||
m_FinalPreviewRenderer->Abort();
|
||||
|
||||
QLabel* widget = m_FinalRenderDialog->ui.FinalRenderPreviewLabel;
|
||||
size_t maxDim = 100;
|
||||
T scalePercentage;
|
||||
size_t maxDim = 100;
|
||||
QLabel* widget = m_FinalRenderDialog->ui.FinalRenderPreviewLabel;
|
||||
|
||||
//Determine how to scale the scaled ember to fit in the label with a max of 100x100.
|
||||
if (m_Ember->m_FinalRasW >= m_Ember->m_FinalRasH)
|
||||
@ -125,7 +141,7 @@ FinalRenderEmberController<T>::FinalRenderEmberController(FractoriumFinalRenderD
|
||||
m_FinalPreviewRenderer->SetEmber(m_PreviewEmber);
|
||||
m_FinalPreviewRenderer->PrepFinalAccumVector(m_PreviewFinalImage);//Must manually call this first because it could be erroneously made smaller due to strips if called inside Renderer::Run().
|
||||
|
||||
uint strips = VerifyStrips(m_PreviewEmber.m_FinalRasH, m_FinalRenderDialog->Strips(),
|
||||
auto strips = VerifyStrips(m_PreviewEmber.m_FinalRasH, m_FinalRenderDialog->Strips(),
|
||||
[&](const string& s) { }, [&](const string& s) { }, [&](const string& s) { });
|
||||
|
||||
StripsRender<T>(m_FinalPreviewRenderer.get(), m_PreviewEmber, m_PreviewFinalImage, 0, strips, m_FinalRenderDialog->YAxisUp(),
|
||||
@ -152,11 +168,10 @@ FinalRenderEmberController<T>::FinalRenderEmberController(FractoriumFinalRenderD
|
||||
m_Run = true;
|
||||
m_TotalTimer.Tic();//Begin timing for progress of all operations.
|
||||
m_GuiState = m_FinalRenderDialog->State();//Cache render settings from the GUI before running.
|
||||
m_FinalImageIndex = 0;
|
||||
|
||||
size_t i;
|
||||
bool doAll = m_GuiState.m_DoAll && m_EmberFile.Size() > 1;
|
||||
uint currentStripForProgress = 0;//Sort of a hack to get the strip value to the progress function.
|
||||
size_t currentStripForProgress = 0;//Sort of a hack to get the strip value to the progress function.
|
||||
QString path = doAll ? ComposePath(QString::fromStdString(m_EmberFile.m_Embers[0].m_Name)) : ComposePath(Name());
|
||||
QString backup = path + "_backup.flame";
|
||||
|
||||
@ -166,32 +181,23 @@ FinalRenderEmberController<T>::FinalRenderEmberController(FractoriumFinalRenderD
|
||||
else
|
||||
m_XmlWriter.Save(backup.toStdString().c_str(), *m_Ember, 0, true, false, true);
|
||||
|
||||
m_FinishedImageCount = 0;
|
||||
m_Renderer->EarlyClip(m_GuiState.m_EarlyClip);
|
||||
m_Renderer->YAxisUp(m_GuiState.m_YAxisUp);
|
||||
m_Renderer->ThreadCount(m_GuiState.m_ThreadCount);
|
||||
m_Renderer->Priority((eThreadPriority)m_GuiState.m_ThreadPriority);
|
||||
m_Renderer->Transparency(m_GuiState.m_Transparency);
|
||||
m_Renderer->m_ProgressParameter = reinterpret_cast<void*>(¤tStripForProgress);
|
||||
|
||||
if (path.endsWith(".png", Qt::CaseInsensitive) || m_Renderer->RendererType() == OPENCL_RENDERER)
|
||||
m_Renderer->NumChannels(4);
|
||||
else
|
||||
m_Renderer->NumChannels(3);
|
||||
m_FinishedImageCount.store(0);
|
||||
SyncGuiToRenderer();
|
||||
FirstOrDefaultRenderer()->m_ProgressParameter = reinterpret_cast<void*>(¤tStripForProgress);//When animating, only the first (primary) device has a progress parameter.
|
||||
|
||||
m_GuiState.m_Strips = VerifyStrips(m_Ember->m_FinalRasH, m_GuiState.m_Strips,
|
||||
[&](const string& s) { Output(QString::fromStdString(s)); },//Greater than height.
|
||||
[&](const string& s) { Output(QString::fromStdString(s)); },//Mod height != 0.
|
||||
[&](const string& s) { Output(QString::fromStdString(s) + "\n"); });//Final strips value to be set.
|
||||
ResetProgress();
|
||||
|
||||
//The rendering process is different between doing a single image, and doing multiple.
|
||||
if (doAll)
|
||||
{
|
||||
m_ImageCount = m_EmberFile.Size();
|
||||
ResetProgress();
|
||||
|
||||
//Different action required for rendering as animation or not.
|
||||
if (m_GuiState.m_DoSequence)
|
||||
if (m_GuiState.m_DoSequence && !m_Renderers.empty())
|
||||
{
|
||||
Ember<T>* firstEmber = &m_EmberFile.m_Embers[0];
|
||||
|
||||
@ -213,58 +219,107 @@ FinalRenderEmberController<T>::FinalRenderEmberController(FractoriumFinalRenderD
|
||||
m_EmberFile.m_Embers[i].m_TemporalSamples = m_GuiState.m_TemporalSamples;
|
||||
}
|
||||
|
||||
//Not supporting strips with motion blur.
|
||||
//Shouldn't be a problem because animations will be at max 4k x 4k which will take about 1.1GB
|
||||
//even when using double precision, which most cards at the time of this writing already exceed.
|
||||
std::atomic<size_t> atomfTime;
|
||||
vector<std::thread> threadVec;
|
||||
|
||||
//Not supporting strips with animation.
|
||||
//Shouldn't be a problem because animations will be at max 4k x 2k which will take about 1GB
|
||||
//even when using double precision, which most cards at the time of this writing already exceed.
|
||||
m_GuiState.m_Strips = 1;
|
||||
m_Renderer->SetEmber(m_EmberFile.m_Embers);//Copy all embers to the local storage inside the renderer.
|
||||
uint finalImageIndex = m_FinalImageIndex;
|
||||
atomfTime.store(0);
|
||||
|
||||
//Render each image, cancelling if m_Run ever gets set to false.
|
||||
for (i = 0; i < m_EmberFile.Size() && m_Run; i++)
|
||||
std::function<void(size_t)> iterFunc = [&](size_t index)
|
||||
{
|
||||
Output("Image " + ToString(m_FinishedImageCount) + ":\n" + ComposePath(QString::fromStdString(m_EmberFile.m_Embers[i].m_Name)));
|
||||
m_Renderer->Reset();//Have to manually set this since the ember is not set each time through.
|
||||
m_RenderTimer.Tic();//Toc() is called in RenderComplete().
|
||||
size_t ftime;
|
||||
size_t finalImageIndex = 0;
|
||||
std::thread writeThread;
|
||||
vector<byte> finalImages[2];
|
||||
EmberStats stats;
|
||||
EmberImageComments comments;
|
||||
Timing renderTimer;
|
||||
auto renderer = m_Renderers[index].get();
|
||||
renderer->SetEmber(m_EmberFile.m_Embers);//Copy all embers to the local storage inside the renderer.
|
||||
|
||||
//Can't use strips render here. Run() must be called directly for animation.
|
||||
if (m_Renderer->Run(m_FinalImage[finalImageIndex], i) != RENDER_OK)
|
||||
//Render each image, cancelling if m_Run ever gets set to false.
|
||||
while (atomfTime.fetch_add(1), ((ftime = atomfTime.load() - 1) < m_EmberFile.Size()) && m_Run)//Needed to set 1 to claim this iter from other threads, so decrement it to be zero-indexed here.
|
||||
{
|
||||
Output("Rendering failed.\n");
|
||||
m_Fractorium->ErrorReportToQTextEdit(m_Renderer->ErrorReport(), m_FinalRenderDialog->ui.FinalRenderTextOutput, false);//Internally calls invoke.
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_WriteThread.joinable())
|
||||
m_WriteThread.join();
|
||||
T localTime = T(ftime);
|
||||
|
||||
SetProgressComplete(100);
|
||||
m_Stats = m_Renderer->Stats();
|
||||
m_FinalImageIndex = finalImageIndex;//Will be used inside of RenderComplete(). Set here when no threads are running.
|
||||
//RenderComplete(m_EmberFile.m_Embers[i]);//Non-threaded version for testing.
|
||||
m_WriteThread = std::thread([&] { RenderComplete(m_EmberFile.m_Embers[i]); });
|
||||
Output("Image " + ToString(ftime + 1ULL) + ":\n" + ComposePath(QString::fromStdString(m_EmberFile.m_Embers[ftime].m_Name)));
|
||||
renderer->Reset();//Have to manually set this since the ember is not set each time through.
|
||||
renderTimer.Tic();//Toc() is called in RenderComplete().
|
||||
|
||||
//Can't use strips render here. Run() must be called directly for animation.
|
||||
if (renderer->Run(finalImages[finalImageIndex], localTime) != RENDER_OK)
|
||||
{
|
||||
Output("Rendering failed.\n");
|
||||
m_Fractorium->ErrorReportToQTextEdit(renderer->ErrorReport(), m_FinalRenderDialog->ui.FinalRenderTextOutput, false);//Internally calls invoke.
|
||||
atomfTime.store(m_EmberFile.Size() + 1);//Abort all threads if any of them encounter an error.
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (writeThread.joinable())
|
||||
writeThread.join();
|
||||
|
||||
stats = renderer->Stats();
|
||||
comments = renderer->ImageComments(stats, 0, false, true);
|
||||
|
||||
writeThread = std::thread([&](size_t tempTime, size_t threadFinalImageIndex)
|
||||
{
|
||||
SaveCurrentRender(m_EmberFile.m_Embers[tempTime],
|
||||
comments,//These all don't change during the renders, so it's ok to access them in the thread.
|
||||
finalImages[threadFinalImageIndex],
|
||||
renderer->FinalRasW(),
|
||||
renderer->FinalRasH(),
|
||||
renderer->NumChannels(),
|
||||
renderer->BytesPerChannel());
|
||||
}, ftime, finalImageIndex);
|
||||
|
||||
m_FinishedImageCount.fetch_add(1);
|
||||
RenderComplete(m_EmberFile.m_Embers[ftime], stats, renderTimer);
|
||||
|
||||
if (!index)//Only first device has a progress callback, so it also makes sense to only manually set the progress on the first device as well.
|
||||
HandleFinishedProgress();
|
||||
}
|
||||
|
||||
finalImageIndex ^= 1;//Toggle the index.
|
||||
}
|
||||
|
||||
finalImageIndex ^= 1;//Toggle the index.
|
||||
if (writeThread.joinable())//One final check to make sure all writing is done before exiting this thread.
|
||||
writeThread.join();
|
||||
};
|
||||
|
||||
threadVec.reserve(m_Renderers.size());
|
||||
|
||||
for (size_t r = 0; r < m_Renderers.size(); r++)
|
||||
{
|
||||
threadVec.push_back(std::thread([&](size_t index)
|
||||
{
|
||||
iterFunc(index);
|
||||
}, r));
|
||||
}
|
||||
|
||||
if (m_WriteThread.joinable())
|
||||
m_WriteThread.join();
|
||||
for (auto& th : threadVec)
|
||||
if (th.joinable())
|
||||
th.join();
|
||||
|
||||
HandleFinishedProgress();//One final check that all images were finished.
|
||||
}
|
||||
else//Render all images, but not as an animation sequence (without temporal samples motion blur).
|
||||
else if (m_Renderer.get())//Make sure a renderer was created and render all images, but not as an animation sequence (without temporal samples motion blur).
|
||||
{
|
||||
//Render each image, cancelling if m_Run ever gets set to false.
|
||||
for (i = 0; i < m_EmberFile.Size() && m_Run; i++)
|
||||
{
|
||||
Output("Image " + ToString(m_FinishedImageCount) + ":\n" + ComposePath(QString::fromStdString(m_EmberFile.m_Embers[i].m_Name)));
|
||||
Output("Image " + ToString<qulonglong>(m_FinishedImageCount.load() + 1) + ":\n" + ComposePath(QString::fromStdString(m_EmberFile.m_Embers[i].m_Name)));
|
||||
m_EmberFile.m_Embers[i].m_TemporalSamples = 1;//No temporal sampling.
|
||||
m_Renderer->SetEmber(m_EmberFile.m_Embers[i]);
|
||||
m_Renderer->PrepFinalAccumVector(m_FinalImage[m_FinalImageIndex]);//Must manually call this first because it could be erroneously made smaller due to strips if called inside Renderer::Run().
|
||||
m_Renderer->PrepFinalAccumVector(m_FinalImage);//Must manually call this first because it could be erroneously made smaller due to strips if called inside Renderer::Run().
|
||||
m_Stats.Clear();
|
||||
Memset(m_FinalImage[m_FinalImageIndex]);
|
||||
Memset(m_FinalImage);
|
||||
m_RenderTimer.Tic();//Toc() is called in RenderComplete().
|
||||
|
||||
StripsRender<T>(m_Renderer.get(), m_EmberFile.m_Embers[i], m_FinalImage[m_FinalImageIndex], 0, m_GuiState.m_Strips, m_GuiState.m_YAxisUp,
|
||||
StripsRender<T>(m_Renderer.get(), m_EmberFile.m_Embers[i], m_FinalImage, 0, m_GuiState.m_Strips, m_GuiState.m_YAxisUp,
|
||||
[&](size_t strip) { currentStripForProgress = strip; },//Pre strip.
|
||||
[&](size_t strip) { m_Stats += m_Renderer->Stats(); },//Post strip.
|
||||
[&](size_t strip)//Error.
|
||||
@ -272,23 +327,32 @@ FinalRenderEmberController<T>::FinalRenderEmberController(FractoriumFinalRenderD
|
||||
Output("Rendering failed.\n");
|
||||
m_Fractorium->ErrorReportToQTextEdit(m_Renderer->ErrorReport(), m_FinalRenderDialog->ui.FinalRenderTextOutput, false);//Internally calls invoke.
|
||||
},
|
||||
[&](Ember<T>& finalEmber) { RenderComplete(finalEmber); });//Final strip.
|
||||
[&](Ember<T>& finalEmber)
|
||||
{
|
||||
m_FinishedImageCount.fetch_add(1);
|
||||
SaveCurrentRender(finalEmber);
|
||||
RenderComplete(finalEmber);
|
||||
HandleFinishedProgress();
|
||||
});//Final strip.
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Output("No renderer present, aborting.");
|
||||
}
|
||||
}
|
||||
else//Render a single image.
|
||||
else if (m_Renderer.get())//Render a single image.
|
||||
{
|
||||
m_ImageCount = 1;
|
||||
ResetProgress();
|
||||
m_Ember->m_TemporalSamples = 1;
|
||||
m_Renderer->SetEmber(*m_Ember);
|
||||
m_Renderer->PrepFinalAccumVector(m_FinalImage[m_FinalImageIndex]);//Must manually call this first because it could be erroneously made smaller due to strips if called inside Renderer::Run().
|
||||
m_Renderer->PrepFinalAccumVector(m_FinalImage);//Must manually call this first because it could be erroneously made smaller due to strips if called inside Renderer::Run().
|
||||
m_Stats.Clear();
|
||||
Memset(m_FinalImage[m_FinalImageIndex]);
|
||||
Memset(m_FinalImage);
|
||||
Output(ComposePath(QString::fromStdString(m_Ember->m_Name)));
|
||||
m_RenderTimer.Tic();//Toc() is called in RenderComplete().
|
||||
|
||||
StripsRender<T>(m_Renderer.get(), *m_Ember, m_FinalImage[m_FinalImageIndex], 0, m_GuiState.m_Strips, m_GuiState.m_YAxisUp,
|
||||
StripsRender<T>(m_Renderer.get(), *m_Ember, m_FinalImage, 0, m_GuiState.m_Strips, m_GuiState.m_YAxisUp,
|
||||
[&](size_t strip) { currentStripForProgress = strip; },//Pre strip.
|
||||
[&](size_t strip) { m_Stats += m_Renderer->Stats(); },//Post strip.
|
||||
[&](size_t strip)//Error.
|
||||
@ -296,10 +360,19 @@ FinalRenderEmberController<T>::FinalRenderEmberController(FractoriumFinalRenderD
|
||||
Output("Rendering failed.\n");
|
||||
m_Fractorium->ErrorReportToQTextEdit(m_Renderer->ErrorReport(), m_FinalRenderDialog->ui.FinalRenderTextOutput, false);//Internally calls invoke.
|
||||
},
|
||||
[&](Ember<T>& finalEmber) { RenderComplete(finalEmber); });//Final strip.
|
||||
[&](Ember<T>& finalEmber)
|
||||
{
|
||||
m_FinishedImageCount.fetch_add(1);
|
||||
SaveCurrentRender(finalEmber);
|
||||
RenderComplete(finalEmber);
|
||||
HandleFinishedProgress();
|
||||
});//Final strip.
|
||||
}
|
||||
else
|
||||
{
|
||||
Output("No renderer present, aborting.");
|
||||
}
|
||||
|
||||
m_FinalImageIndex = 0;
|
||||
QString totalTimeString = "All renders completed in: " + QString::fromStdString(m_TotalTimer.Format(m_TotalTimer.Toc())) + ".";
|
||||
Output(totalTimeString);
|
||||
|
||||
@ -403,35 +476,43 @@ bool FinalRenderEmberController<T>::Render()
|
||||
/// Stop rendering and initialize a new renderer, using the specified type and the options on the final render dialog.
|
||||
/// </summary>
|
||||
/// <param name="renderType">The type of render to create</param>
|
||||
/// <param name="platform">The index platform of the platform to use</param>
|
||||
/// <param name="device">The index device of the device to use</param>
|
||||
/// <param name="outputTexID">The texture ID of the shared OpenGL texture if shared</param>
|
||||
/// <param name="shared">True if shared with OpenGL, else false. Default: true.</param>
|
||||
/// <param name="devices">The platform,device index pairs of the devices to use</param>
|
||||
/// <param name="shared">True if shared with OpenGL, else false. Always false in this case.</param>
|
||||
/// <returns>True if nothing went wrong, else false.</returns>
|
||||
template <typename T>
|
||||
bool FinalRenderEmberController<T>::CreateRenderer(eRendererType renderType, uint platform, uint device, bool shared)
|
||||
bool FinalRenderEmberController<T>::CreateRenderer(eRendererType renderType, const vector<pair<size_t, size_t>>& devices, bool shared)
|
||||
{
|
||||
bool ok = true;
|
||||
uint channels = m_FinalRenderDialog->Ext() == "png" ? 4 : 3;
|
||||
bool deviceDiff = false;
|
||||
//uint channels = m_FinalRenderDialog->Ext().endsWith("png", Qt::CaseInsensitive) ? 4 : 3;
|
||||
bool renderTypeMismatch = (m_Renderer.get() && (m_Renderer->RendererType() != renderType)) ||
|
||||
(!m_Renderers.empty() && (m_Renderers[0]->RendererType() != renderType));
|
||||
|
||||
CancelRender();
|
||||
|
||||
if (!m_Renderer.get() ||
|
||||
!m_Renderer->Ok() ||
|
||||
m_Renderer->RendererType() != renderType ||
|
||||
m_Platform != platform ||
|
||||
m_Device != device ||
|
||||
m_Shared != shared)
|
||||
if ((!m_FinalRenderDialog->DoSequence() && (!m_Renderer.get() || !m_Renderer->Ok())) ||
|
||||
(m_FinalRenderDialog->DoSequence() && m_Renderers.empty()) ||
|
||||
renderTypeMismatch ||
|
||||
!Equal(m_Devices, devices))
|
||||
{
|
||||
EmberReport emberReport;
|
||||
vector<string> errorReport;
|
||||
|
||||
m_Platform = platform;//Store values for re-creation later on.
|
||||
m_Device = device;
|
||||
m_Devices = devices;//Store values for re-creation later on.
|
||||
m_OutputTexID = 0;//Don't care about tex ID when doing final render.
|
||||
m_Shared = shared;
|
||||
m_Shared = shared;//So shared is of course false.
|
||||
|
||||
if (m_FinalRenderDialog->DoSequence())
|
||||
{
|
||||
m_Renderer.reset();
|
||||
m_Renderers = ::CreateRenderers<T>(renderType, m_Devices, shared, m_OutputTexID, emberReport);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Renderers.clear();
|
||||
m_Renderer = unique_ptr<EmberNs::RendererBase>(::CreateRenderer<T>(renderType, m_Devices, shared, m_OutputTexID, emberReport));
|
||||
}
|
||||
|
||||
m_Renderer = unique_ptr<EmberNs::RendererBase>(::CreateRenderer<T, float>(renderType, platform, device, shared, m_OutputTexID, emberReport));
|
||||
errorReport = emberReport.ErrorReport();
|
||||
|
||||
if (!errorReport.empty())
|
||||
@ -442,30 +523,13 @@ bool FinalRenderEmberController<T>::CreateRenderer(eRendererType renderType, uin
|
||||
}
|
||||
}
|
||||
|
||||
if (m_Renderer.get())
|
||||
{
|
||||
if (m_Renderer->RendererType() == OPENCL_RENDERER)
|
||||
channels = 4;//Always using 4 since the GL texture is RGBA.
|
||||
|
||||
m_Renderer->Callback(this);
|
||||
m_Renderer->NumChannels(channels);
|
||||
m_Renderer->EarlyClip(m_FinalRenderDialog->EarlyClip());
|
||||
m_Renderer->YAxisUp(m_FinalRenderDialog->YAxisUp());
|
||||
m_Renderer->ThreadCount(m_FinalRenderDialog->ThreadCount());
|
||||
m_Renderer->Transparency(m_FinalRenderDialog->Transparency());
|
||||
}
|
||||
else
|
||||
{
|
||||
ok = false;
|
||||
m_Fractorium->ShowCritical("Renderer Creation Error", "Could not create renderer, aborting. See info tab for details.");
|
||||
}
|
||||
|
||||
return ok;
|
||||
return SyncGuiToRenderer() && ok;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Progress function.
|
||||
/// Take special action to sync options upon finishing.
|
||||
/// Note this is only called on the primary renderer.
|
||||
/// </summary>
|
||||
/// <param name="ember">The ember currently being rendered</param>
|
||||
/// <param name="foo">An extra dummy parameter</param>
|
||||
@ -477,7 +541,7 @@ template <typename T>
|
||||
int FinalRenderEmberController<T>::ProgressFunc(Ember<T>& ember, void* foo, double fraction, int stage, double etaMs)
|
||||
{
|
||||
static int count = 0;
|
||||
uint strip = *(reinterpret_cast<uint*>(m_Renderer->m_ProgressParameter));
|
||||
size_t strip = *(reinterpret_cast<size_t*>(FirstOrDefaultRenderer()->m_ProgressParameter));
|
||||
double fracPerStrip = ceil(100.0 / m_GuiState.m_Strips);
|
||||
double stripsfrac = ceil(fracPerStrip * strip) + ceil(fraction / m_GuiState.m_Strips);
|
||||
int intFract = int(stripsfrac);
|
||||
@ -489,7 +553,7 @@ int FinalRenderEmberController<T>::ProgressFunc(Ember<T>& ember, void* foo, doub
|
||||
else if (stage == 2)
|
||||
QMetaObject::invokeMethod(m_FinalRenderDialog->ui.FinalRenderAccumProgress, "setValue", Qt::QueuedConnection, Q_ARG(int, intFract));
|
||||
|
||||
QMetaObject::invokeMethod(m_FinalRenderDialog->ui.FinalRenderImageCountLabel, "setText", Qt::QueuedConnection, Q_ARG(const QString&, ToString(m_FinishedImageCount) + " / " + ToString(m_ImageCount) + " Eta: " + QString::fromStdString(m_RenderTimer.Format(etaMs))));
|
||||
QMetaObject::invokeMethod(m_FinalRenderDialog->ui.FinalRenderImageCountLabel, "setText", Qt::QueuedConnection, Q_ARG(const QString&, ToString<qulonglong>(m_FinishedImageCount.load() + 1) + " / " + ToString<qulonglong>(m_ImageCount) + " Eta: " + QString::fromStdString(m_RenderTimer.Format(etaMs))));
|
||||
QMetaObject::invokeMethod(m_FinalRenderDialog->ui.FinalRenderTextOutput, "update", Qt::QueuedConnection);
|
||||
|
||||
return m_Run ? 1 : 0;
|
||||
@ -533,6 +597,53 @@ void FinalRenderEmberController<T>::SyncGuiToEmbers(size_t widthOverride, size_t
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copy GUI values to the renderers.
|
||||
/// </summary>
|
||||
template <typename T>
|
||||
bool FinalRenderEmberController<T>::SyncGuiToRenderer()
|
||||
{
|
||||
bool ok = true;
|
||||
uint channels = m_FinalRenderDialog->Ext().endsWith("png", Qt::CaseInsensitive) ? 4 : 3;
|
||||
|
||||
if (m_Renderer.get())
|
||||
{
|
||||
if (m_Renderer->RendererType() == OPENCL_RENDERER)
|
||||
channels = 4;//Always using 4 since the GL texture is RGBA.
|
||||
|
||||
m_Renderer->Callback(this);
|
||||
m_Renderer->NumChannels(channels);
|
||||
m_Renderer->EarlyClip(m_FinalRenderDialog->EarlyClip());
|
||||
m_Renderer->YAxisUp(m_FinalRenderDialog->YAxisUp());
|
||||
m_Renderer->ThreadCount(m_FinalRenderDialog->ThreadCount());
|
||||
m_Renderer->Priority((eThreadPriority)m_FinalRenderDialog->ThreadPriority());
|
||||
m_Renderer->Transparency(m_FinalRenderDialog->Transparency());
|
||||
}
|
||||
else if (!m_Renderers.empty())
|
||||
{
|
||||
for (size_t i = 0; i < m_Renderers.size(); i++)
|
||||
{
|
||||
if (m_Renderers[i]->RendererType() == OPENCL_RENDERER)
|
||||
channels = 4;//Always using 4 since the GL texture is RGBA.
|
||||
|
||||
m_Renderers[i]->Callback(!i ? this : nullptr);
|
||||
m_Renderers[i]->NumChannels(channels);
|
||||
m_Renderers[i]->EarlyClip(m_FinalRenderDialog->EarlyClip());
|
||||
m_Renderers[i]->YAxisUp(m_FinalRenderDialog->YAxisUp());
|
||||
m_Renderers[i]->ThreadCount(m_FinalRenderDialog->ThreadCount());
|
||||
m_Renderers[i]->Priority((eThreadPriority)m_FinalRenderDialog->ThreadPriority());
|
||||
m_Renderers[i]->Transparency(m_FinalRenderDialog->Transparency());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ok = false;
|
||||
m_Fractorium->ShowCritical("Renderer Creation Error", "No renderer present, aborting. See info tab for details.");
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set values for scale spinners based on the ratio of the original dimensions to the current dimensions
|
||||
/// of the current ember. Also update the size suffix text.
|
||||
@ -564,7 +675,7 @@ void FinalRenderEmberController<T>::ResetProgress(bool total)
|
||||
{
|
||||
if (total)
|
||||
{
|
||||
QMetaObject::invokeMethod(m_FinalRenderDialog->ui.FinalRenderImageCountLabel, "setText", Qt::QueuedConnection, Q_ARG(const QString&, "0 / " + ToString(m_ImageCount)));
|
||||
QMetaObject::invokeMethod(m_FinalRenderDialog->ui.FinalRenderImageCountLabel, "setText", Qt::QueuedConnection, Q_ARG(const QString&, "0 / " + ToString<qulonglong>(m_ImageCount)));
|
||||
QMetaObject::invokeMethod(m_FinalRenderDialog->ui.FinalRenderTotalProgress, "setValue", Qt::QueuedConnection, Q_ARG(int, 0));
|
||||
}
|
||||
|
||||
@ -574,7 +685,7 @@ void FinalRenderEmberController<T>::ResetProgress(bool total)
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set various parameters in the renderer and current ember with the values
|
||||
/// Set various parameters in the renderers and current ember with the values
|
||||
/// specified in the widgets and compute the amount of memory required to render.
|
||||
/// This includes the memory needed for the final output image.
|
||||
/// </summary>
|
||||
@ -584,16 +695,17 @@ tuple<size_t, size_t, size_t> FinalRenderEmberController<T>::SyncAndComputeMemor
|
||||
{
|
||||
size_t iterCount;
|
||||
pair<size_t, size_t> p(0, 0);
|
||||
|
||||
size_t strips;
|
||||
bool b = false;
|
||||
uint channels = m_FinalRenderDialog->Ext() == "png" ? 4 : 3;//4 channels for Png, else 3.
|
||||
|
||||
SyncGuiToEmbers();
|
||||
|
||||
if (m_Renderer.get())
|
||||
{
|
||||
bool b = false;
|
||||
uint channels = m_FinalRenderDialog->Ext() == "png" ? 4 : 3;//4 channels for Png, else 3.
|
||||
size_t strips = VerifyStrips(m_Ember->m_FinalRasH, m_FinalRenderDialog->Strips(),
|
||||
[&](const string& s) { }, [&](const string& s) { }, [&](const string& s) { });
|
||||
strips = VerifyStrips(m_Ember->m_FinalRasH, m_FinalRenderDialog->Strips(),
|
||||
[&](const string& s) {}, [&](const string& s) {}, [&](const string& s) {});
|
||||
|
||||
SyncGuiToEmbers();
|
||||
m_FinalRenderDialog->m_StripsSpin->setSuffix(" (" + ToString<qulonglong>(strips) + ")");
|
||||
m_Renderer->SetEmber(*m_Ember);
|
||||
m_Renderer->CreateSpatialFilter(b);
|
||||
m_Renderer->CreateTemporalFilter(b);
|
||||
@ -607,6 +719,28 @@ tuple<size_t, size_t, size_t> FinalRenderEmberController<T>::SyncAndComputeMemor
|
||||
p = m_Renderer->MemoryRequired(strips, true, m_FinalRenderDialog->DoSequence());
|
||||
iterCount = m_Renderer->TotalIterCount(strips);
|
||||
}
|
||||
else if (!m_Renderers.empty())
|
||||
{
|
||||
for (auto& renderer : m_Renderers)
|
||||
{
|
||||
renderer->SetEmber(*m_Ember);
|
||||
renderer->CreateSpatialFilter(b);
|
||||
renderer->CreateTemporalFilter(b);
|
||||
renderer->NumChannels(channels);
|
||||
renderer->ComputeBounds();
|
||||
renderer->ComputeQuality();
|
||||
renderer->ComputeCamera();
|
||||
}
|
||||
|
||||
CancelPreviewRender();
|
||||
m_FinalPreviewRenderFunc();
|
||||
|
||||
strips = 1;
|
||||
p = m_Renderers[0]->MemoryRequired(1, true, m_FinalRenderDialog->DoSequence());
|
||||
iterCount = m_Renderers[0]->TotalIterCount(strips);
|
||||
}
|
||||
|
||||
m_FinalRenderDialog->m_StripsSpin->setSuffix(" (" + ToString<qulonglong>(strips) +")");
|
||||
|
||||
return tuple<size_t, size_t, size_t>(p.first, p.second, iterCount);
|
||||
}
|
||||
@ -631,6 +765,25 @@ QString FinalRenderEmberController<T>::ComposePath(const QString& name)
|
||||
/// Non-virtual functions declared in FinalRenderEmberController<T>.
|
||||
/// </summary>
|
||||
|
||||
/// <summary>
|
||||
/// Return either m_Renderer in the case of running a CPU renderer, else
|
||||
/// m_Renderers[0] in the case of running OpenCL.
|
||||
/// </summary>
|
||||
/// <returns>The primary renderer</returns>
|
||||
template <typename T>
|
||||
EmberNs::Renderer<T, float>* FinalRenderEmberController<T>::FirstOrDefaultRenderer()
|
||||
{
|
||||
if (m_Renderer.get())
|
||||
return dynamic_cast<EmberNs::Renderer<T, float>*>(m_Renderer.get());
|
||||
else if (!m_Renderers.empty())
|
||||
return dynamic_cast<EmberNs::Renderer<T, float>*>(m_Renderers[0].get());
|
||||
else
|
||||
{
|
||||
throw "No final renderer, exiting.";
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stop the preview renderer.
|
||||
/// This is meant to only be called programatically and never by the user.
|
||||
@ -645,40 +798,80 @@ void FinalRenderEmberController<T>::CancelPreviewRender()
|
||||
while (m_FinalPreviewResult.isRunning()) { QApplication::processEvents(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Save the output of the render.
|
||||
/// </summary>
|
||||
/// <param name="ember">The ember whose rendered output will be saved</param>
|
||||
template<typename T>
|
||||
void FinalRenderEmberController<T>::SaveCurrentRender(Ember<T>& ember)
|
||||
{
|
||||
auto comments = m_Renderer->ImageComments(m_Stats, 0, false, true);
|
||||
SaveCurrentRender(ember, comments, m_FinalImage, m_Renderer->FinalRasW(), m_Renderer->FinalRasH(), m_Renderer->NumChannels(), m_Renderer->BytesPerChannel());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Save the output of the render.
|
||||
/// </summary>
|
||||
/// <param name="ember">The ember whose rendered output will be saved</param>
|
||||
/// <param name="comments">The comments to save in the png or jpg</param>
|
||||
/// <param name="pixels">The buffer containing the pixels</param>
|
||||
/// <param name="width">The width in pixels of the image</param>
|
||||
/// <param name="height">The height in pixels of the image</param>
|
||||
/// <param name="channels">The number of channels, 3 or 4.</param>
|
||||
/// <param name="bpc">The bytes per channel, almost always 1.</param>
|
||||
template<typename T>
|
||||
void FinalRenderEmberController<T>::SaveCurrentRender(Ember<T>& ember, const EmberImageComments& comments, vector<byte>& pixels, size_t width, size_t height, size_t channels, size_t bpc)
|
||||
{
|
||||
QString filename = ComposePath(QString::fromStdString(ember.m_Name));
|
||||
FractoriumEmberControllerBase::SaveCurrentRender(filename, comments, pixels, width, height, channels, bpc);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Action to take when rendering an image completes.
|
||||
/// Thin wrapper around the function of the same name that takes more arguments.
|
||||
/// Just passes m_Renderer and m_FinalImage.
|
||||
/// </summary>
|
||||
/// <param name="ember">The ember currently being rendered</param>
|
||||
template<typename T>
|
||||
void FinalRenderEmberController<T>::RenderComplete(Ember<T>& ember)
|
||||
{
|
||||
string renderTimeString = m_RenderTimer.Format(m_RenderTimer.Toc()), totalTimeString;
|
||||
if (auto renderer = dynamic_cast<EmberNs::Renderer<T, float>*>(m_Renderer.get()))
|
||||
RenderComplete(ember, m_Stats, m_RenderTimer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle setting the appropriate progress bar values when an image render has finished.
|
||||
/// This handles single image, animations, and strips.
|
||||
/// </summary>
|
||||
template<typename T>
|
||||
void FinalRenderEmberController<T>::HandleFinishedProgress()
|
||||
{
|
||||
auto finishedCountCached = m_FinishedImageCount.load();//Make sure to use the same value throughout this function even if the atomic is changing.
|
||||
|
||||
if (m_FinishedImageCount.load() != m_ImageCount)
|
||||
ResetProgress(false);
|
||||
else
|
||||
SetProgressComplete(100);//Just to be safe.
|
||||
|
||||
QMetaObject::invokeMethod(m_FinalRenderDialog->ui.FinalRenderTotalProgress, "setValue", Qt::QueuedConnection, Q_ARG(int, int((float(finishedCountCached) / float(m_ImageCount)) * 100)));
|
||||
QMetaObject::invokeMethod(m_FinalRenderDialog->ui.FinalRenderImageCountLabel, "setText", Qt::QueuedConnection, Q_ARG(const QString&, ToString<qulonglong>(finishedCountCached) + " / " + ToString<qulonglong>(m_ImageCount)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Action to take when rendering an image completes.
|
||||
/// </summary>
|
||||
/// <param name="ember">The ember currently being rendered</param>
|
||||
/// <param name="stats">The renderer stats</param>
|
||||
/// <param name="pixels">The timer which was started at the beginning of the render</param>
|
||||
template<typename T>
|
||||
void FinalRenderEmberController<T>::RenderComplete(Ember<T>& ember, const EmberStats& stats, Timing& renderTimer)
|
||||
{
|
||||
m_ProgressCs.Enter();
|
||||
string renderTimeString = renderTimer.Format(renderTimer.Toc()), totalTimeString;
|
||||
QString status, filename = ComposePath(QString::fromStdString(ember.m_Name));
|
||||
QString itersString = ToString<qulonglong>(m_Stats.m_Iters);
|
||||
QString itersPerSecString = ToString<qulonglong>(size_t(m_Stats.m_Iters / (m_Stats.m_IterMs / 1000.0)));
|
||||
|
||||
//Save whatever options were specified on the GUI to the settings.
|
||||
m_Settings->FinalEarlyClip(m_GuiState.m_EarlyClip);
|
||||
m_Settings->FinalYAxisUp(m_GuiState.m_YAxisUp);
|
||||
m_Settings->FinalTransparency(m_GuiState.m_Transparency);
|
||||
m_Settings->FinalOpenCL(m_GuiState.m_OpenCL);
|
||||
m_Settings->FinalDouble(m_GuiState.m_Double);
|
||||
m_Settings->FinalPlatformIndex(m_GuiState.m_PlatformIndex);
|
||||
m_Settings->FinalDeviceIndex(m_GuiState.m_DeviceIndex);
|
||||
m_Settings->FinalSaveXml(m_GuiState.m_SaveXml);
|
||||
m_Settings->FinalDoAll(m_GuiState.m_DoAll);
|
||||
m_Settings->FinalDoSequence(m_GuiState.m_DoSequence);
|
||||
m_Settings->FinalKeepAspect(m_GuiState.m_KeepAspect);
|
||||
m_Settings->FinalScale(m_GuiState.m_Scale);
|
||||
m_Settings->FinalExt(m_GuiState.m_Ext);
|
||||
m_Settings->FinalThreadCount(m_GuiState.m_ThreadCount);
|
||||
m_Settings->FinalThreadPriority(m_GuiState.m_ThreadPriority);
|
||||
m_Settings->FinalQuality(m_GuiState.m_Quality);
|
||||
m_Settings->FinalTemporalSamples(m_GuiState.m_TemporalSamples);
|
||||
m_Settings->FinalSupersample(m_GuiState.m_Supersample);
|
||||
m_Settings->FinalStrips(m_GuiState.m_Strips);
|
||||
SaveCurrentRender(filename, false);//Don't pull from the card, the rendering process already did it.
|
||||
|
||||
QString itersString = ToString<qulonglong>(stats.m_Iters);
|
||||
QString itersPerSecString = ToString<qulonglong>(size_t(stats.m_Iters / (stats.m_IterMs / 1000.0)));
|
||||
|
||||
if (m_GuiState.m_SaveXml)
|
||||
{
|
||||
QFileInfo xmlFileInfo(filename);//Create another one in case it was modified for batch rendering.
|
||||
@ -692,31 +885,38 @@ void FinalRenderEmberController<T>::RenderComplete(Ember<T>& ember)
|
||||
xmlFreeDoc(tempEdit);
|
||||
}
|
||||
|
||||
m_FinishedImageCount++;
|
||||
|
||||
//In a thread if animating, so don't set to complete because it'll be out of sync with the rest of the progress bars.
|
||||
if (!m_GuiState.m_DoSequence)
|
||||
{
|
||||
SetProgressComplete(100);//Just to be safe.
|
||||
}
|
||||
|
||||
QMetaObject::invokeMethod(m_FinalRenderDialog->ui.FinalRenderTotalProgress, "setValue", Qt::QueuedConnection, Q_ARG(int, int((float(m_FinishedImageCount) / float(m_ImageCount)) * 100)));
|
||||
QMetaObject::invokeMethod(m_FinalRenderDialog->ui.FinalRenderImageCountLabel, "setText", Qt::QueuedConnection, Q_ARG(const QString&, ToString(m_FinishedImageCount) + " / " + ToString(m_ImageCount)));
|
||||
|
||||
status = "Pure render time: " + QString::fromStdString(renderTimeString);
|
||||
Output(status);
|
||||
|
||||
totalTimeString = m_RenderTimer.Format(m_RenderTimer.Toc());
|
||||
totalTimeString = renderTimer.Format(renderTimer.Toc());
|
||||
status = "Total time: " + QString::fromStdString(totalTimeString) + "\nTotal iters: " + itersString + "\nIters/second: " + itersPerSecString + "\n";
|
||||
Output(status);
|
||||
QMetaObject::invokeMethod(m_FinalRenderDialog, "MoveCursorToEnd", Qt::QueuedConnection);
|
||||
|
||||
if (m_FinishedImageCount != m_ImageCount)
|
||||
if (m_FinishedImageCount.load() == m_ImageCount)//Finished, save whatever options were specified on the GUI to the settings.
|
||||
{
|
||||
ResetProgress(false);
|
||||
m_Settings->FinalEarlyClip(m_GuiState.m_EarlyClip);
|
||||
m_Settings->FinalYAxisUp(m_GuiState.m_YAxisUp);
|
||||
m_Settings->FinalTransparency(m_GuiState.m_Transparency);
|
||||
m_Settings->FinalOpenCL(m_GuiState.m_OpenCL);
|
||||
m_Settings->FinalDouble(m_GuiState.m_Double);
|
||||
m_Settings->FinalDevices(m_GuiState.m_Devices);
|
||||
m_Settings->FinalSaveXml(m_GuiState.m_SaveXml);
|
||||
m_Settings->FinalDoAll(m_GuiState.m_DoAll);
|
||||
m_Settings->FinalDoSequence(m_GuiState.m_DoSequence);
|
||||
m_Settings->FinalKeepAspect(m_GuiState.m_KeepAspect);
|
||||
m_Settings->FinalScale(m_GuiState.m_Scale);
|
||||
m_Settings->FinalExt(m_GuiState.m_Ext);
|
||||
m_Settings->FinalThreadCount(m_GuiState.m_ThreadCount);
|
||||
m_Settings->FinalThreadPriority(m_GuiState.m_ThreadPriority);
|
||||
m_Settings->FinalQuality(m_GuiState.m_Quality);
|
||||
m_Settings->FinalTemporalSamples(m_GuiState.m_TemporalSamples);
|
||||
m_Settings->FinalSupersample(m_GuiState.m_Supersample);
|
||||
m_Settings->FinalStrips(m_GuiState.m_Strips);
|
||||
}
|
||||
|
||||
QMetaObject::invokeMethod(m_FinalRenderDialog->ui.FinalRenderTextOutput, "update", Qt::QueuedConnection);
|
||||
m_ProgressCs.Leave();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -35,8 +35,7 @@ struct FinalRenderGuiState
|
||||
QString m_Ext;
|
||||
QString m_Prefix;
|
||||
QString m_Suffix;
|
||||
uint m_PlatformIndex;
|
||||
uint m_DeviceIndex;
|
||||
QList<QVariant> m_Devices;
|
||||
uint m_ThreadCount;
|
||||
int m_ThreadPriority;
|
||||
double m_WidthScale;
|
||||
@ -68,16 +67,16 @@ public:
|
||||
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) { return ""; }
|
||||
virtual void CancelRender() { }
|
||||
|
||||
void CancelRender();
|
||||
bool CreateRendererFromGUI();
|
||||
void Output(const QString& s);
|
||||
|
||||
protected:
|
||||
bool m_Run;
|
||||
bool m_PreviewRun;
|
||||
uint m_ImageCount;
|
||||
uint m_FinishedImageCount;
|
||||
size_t m_ImageCount;
|
||||
std::atomic<size_t> m_FinishedImageCount;
|
||||
|
||||
QFuture<void> m_Result;
|
||||
QFuture<void> m_FinalPreviewResult;
|
||||
@ -87,15 +86,14 @@ protected:
|
||||
FractoriumSettings* m_Settings;
|
||||
FractoriumFinalRenderDialog* m_FinalRenderDialog;
|
||||
FinalRenderGuiState m_GuiState;
|
||||
OpenCLWrapper m_Wrapper;
|
||||
CriticalSection m_PreviewCs;
|
||||
CriticalSection m_PreviewCs, m_ProgressCs;
|
||||
Timing m_RenderTimer;
|
||||
Timing m_TotalTimer;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Templated derived class which implements all interaction functionality between the embers
|
||||
/// of a specific template type and the final render dialog;
|
||||
/// of a specific template type and the final render dialog.
|
||||
/// </summary>
|
||||
template<typename T>
|
||||
class FinalRenderEmberController : public FinalRenderEmberControllerBase
|
||||
@ -113,7 +111,7 @@ public:
|
||||
#endif
|
||||
virtual void SetEmber(size_t index) override;
|
||||
virtual bool Render() override;
|
||||
virtual bool CreateRenderer(eRendererType renderType, uint platform, uint device, bool shared = true) override;
|
||||
virtual bool CreateRenderer(eRendererType renderType, const vector<pair<size_t, size_t>>& devices, bool shared = true) override;
|
||||
virtual int ProgressFunc(Ember<T>& ember, void* foo, double fraction, int stage, double etaMs) override;
|
||||
virtual size_t Index() const override { return m_Ember->m_Index; }
|
||||
virtual uint SizeOfT() const override { return sizeof(T); }
|
||||
@ -127,11 +125,20 @@ public:
|
||||
virtual double OriginalAspect() override { return double(m_Ember->m_OrigFinalRasW) / m_Ember->m_OrigFinalRasH; }
|
||||
virtual QString Name() const override { return QString::fromStdString(m_Ember->m_Name); }
|
||||
virtual QString ComposePath(const QString& name) override;
|
||||
|
||||
virtual void CancelRender() override;
|
||||
|
||||
//Non Virtual functions.
|
||||
EmberNs::Renderer<T, float>* FirstOrDefaultRenderer();
|
||||
|
||||
protected:
|
||||
void CancelPreviewRender();
|
||||
void HandleFinishedProgress();
|
||||
void SaveCurrentRender(Ember<T>& ember);
|
||||
void SaveCurrentRender(Ember<T>& ember, const EmberImageComments& comments, vector<byte>& pixels, size_t width, size_t height, size_t channels, size_t bpc);
|
||||
void RenderComplete(Ember<T>& ember);
|
||||
void RenderComplete(Ember<T>& ember, const EmberStats& stats, Timing& renderTimer);
|
||||
void SyncGuiToEmber(Ember<T>& ember, size_t widthOverride = 0, size_t heightOverride = 0);
|
||||
bool SyncGuiToRenderer();
|
||||
void SetProgressComplete(int val);
|
||||
|
||||
Ember<T>* m_Ember;
|
||||
@ -139,5 +146,6 @@ protected:
|
||||
EmberFile<T> m_EmberFile;
|
||||
EmberToXml<T> m_XmlWriter;
|
||||
unique_ptr<EmberNs::Renderer<T, float>> m_FinalPreviewRenderer;
|
||||
vector<unique_ptr<EmberNs::Renderer<T, float>>> m_Renderers;
|
||||
};
|
||||
|
||||
|
@ -14,7 +14,8 @@
|
||||
/// </summary>
|
||||
/// <param name="p">The parent widget of this item</param>
|
||||
Fractorium::Fractorium(QWidget* p)
|
||||
: QMainWindow(p)
|
||||
: QMainWindow(p),
|
||||
m_Info(OpenCLInfo::Instance())
|
||||
{
|
||||
int spinHeight = 20, iconSize_ = 9;
|
||||
size_t i = 0;
|
||||
@ -58,9 +59,6 @@ Fractorium::Fractorium(QWidget* p)
|
||||
const QRect screen = QApplication::desktop()->screenGeometry();
|
||||
m_AboutDialog->move(screen.center() - m_AboutDialog->rect().center());
|
||||
|
||||
//The options dialog should be a fixed size without a size grip, however even if it's here, it still shows up. Perhaps Qt will fix it some day.
|
||||
m_OptionsDialog->layout()->setSizeConstraint(QLayout::SetFixedSize);
|
||||
m_OptionsDialog->setSizeGripEnabled(false);
|
||||
connect(m_ColorDialog, SIGNAL(colorSelected(const QColor&)), this, SLOT(OnColorSelected(const QColor&)), Qt::QueuedConnection);
|
||||
|
||||
m_XformComboColors[i++] = QColor(0XFF, 0X00, 0X00);
|
||||
@ -119,8 +117,8 @@ Fractorium::Fractorium(QWidget* p)
|
||||
m_Controller->SetupVariationTree();
|
||||
m_Controller->FilteredVariations();
|
||||
|
||||
if (m_Wrapper.CheckOpenCL() && m_Settings->OpenCL() && m_QualitySpin->value() < 30)
|
||||
m_QualitySpin->setValue(30);
|
||||
if (m_Info.Ok() && m_Settings->OpenCL() && m_QualitySpin->value() < (30 * m_Settings->Devices().size()))
|
||||
m_QualitySpin->setValue(30 * m_Settings->Devices().size());
|
||||
|
||||
int statusBarHeight = 20 * devicePixelRatio();
|
||||
ui.statusBar->setMinimumHeight(statusBarHeight);
|
||||
|
@ -369,7 +369,7 @@ private:
|
||||
void ShutdownAndRecreateFromOptions();
|
||||
bool CreateRendererFromOptions();
|
||||
bool CreateControllerFromOptions();
|
||||
|
||||
|
||||
//Dialogs.
|
||||
QStringList SetupOpenXmlDialog();
|
||||
QString SetupSaveXmlDialog(const QString& defaultFilename);
|
||||
@ -495,7 +495,7 @@ private:
|
||||
int m_VarSortMode;
|
||||
int m_PaletteSortMode;
|
||||
int m_PreviousPaletteRow;
|
||||
OpenCLWrapper m_Wrapper;
|
||||
OpenCLInfo& m_Info;
|
||||
unique_ptr<FractoriumEmberControllerBase> m_Controller;
|
||||
Ui::FractoriumClass ui;
|
||||
};
|
||||
|
@ -185,4 +185,175 @@ static intmax_t IsXformLinked(Ember<T>& ember, Xform<T>* xform)
|
||||
}
|
||||
|
||||
return linked;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert the passed in QList<QVariant> of absolute device indices to a vector<pair<size_t, size_t>> of platform,device
|
||||
/// index pairs.
|
||||
/// </summary>
|
||||
/// <param name="selectedDevices">The absolute device indices</param>
|
||||
/// <returns>The converted device vector of platform,device index pairs</returns>
|
||||
static vector<pair<size_t, size_t>> Devices(const QList<QVariant>& selectedDevices)
|
||||
{
|
||||
vector<pair<size_t, size_t>> vec;
|
||||
OpenCLInfo& info = OpenCLInfo::Instance();
|
||||
auto& devices = info.DeviceIndices();
|
||||
|
||||
vec.reserve(selectedDevices.size());
|
||||
|
||||
for (size_t i = 0; i < selectedDevices.size(); i++)
|
||||
{
|
||||
auto index = selectedDevices[i].toUInt();
|
||||
|
||||
if (index < devices.size())
|
||||
vec.push_back(devices[index]);
|
||||
}
|
||||
|
||||
return vec;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Setup a table showing all available OpenCL devices on the system.
|
||||
/// Create checkboxes and radio buttons which allow the user to specify
|
||||
/// which devices to use, and which one to make the primary device.
|
||||
/// Used in the options dialog and the final render dialog.
|
||||
/// </summary>
|
||||
/// <param name="table">The QTableWidget to setup</param>
|
||||
/// <param name="settingsDevices">The absolute indices of the devices to use, with the first being the primary.</param>
|
||||
static void SetupDeviceTable(QTableWidget* table, const QList<QVariant>& settingsDevices)
|
||||
{
|
||||
bool primary = false;
|
||||
auto& deviceNames = OpenCLInfo::Instance().AllDeviceNames();
|
||||
|
||||
table->clearContents();
|
||||
table->setRowCount(deviceNames.size());
|
||||
|
||||
for (size_t i = 0; i < deviceNames.size(); i++)
|
||||
{
|
||||
auto checkItem = new QTableWidgetItem();
|
||||
auto radio = new QRadioButton();
|
||||
auto deviceItem = new QTableWidgetItem(QString::fromStdString(deviceNames[i]));
|
||||
|
||||
table->setItem(i, 0, checkItem);
|
||||
table->setCellWidget(i, 1, radio);
|
||||
table->setItem(i, 2, deviceItem);
|
||||
|
||||
if (settingsDevices.contains(QVariant::fromValue(i)))
|
||||
{
|
||||
checkItem->setCheckState(Qt::Checked);
|
||||
|
||||
if (!primary)
|
||||
{
|
||||
radio->setChecked(true);
|
||||
primary = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
checkItem->setCheckState(Qt::Unchecked);
|
||||
}
|
||||
|
||||
if (!primary && table->rowCount() > 0)//Primary was never set, so just default to the first device and hope it was the one detected as the main display.
|
||||
{
|
||||
table->item(0, 0)->setCheckState(Qt::Checked);
|
||||
qobject_cast<QRadioButton*>(table->cellWidget(0, 1))->setChecked(true);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copy the passed in selected absolute device indices to the controls on the passed in table.
|
||||
/// Used in the options dialog and the final render dialog.
|
||||
/// </summary>
|
||||
/// <param name="table">The QTableWidget to copy values to</param>
|
||||
/// <param name="settingsDevices">The absolute indices of the devices to use, with the first being the primary.</param>
|
||||
static void SettingsToDeviceTable(QTableWidget* table, QList<QVariant>& settingsDevices)
|
||||
{
|
||||
if (settingsDevices.empty() && table->rowCount() > 0)
|
||||
{
|
||||
table->item(0, 0)->setCheckState(Qt::Checked);
|
||||
qobject_cast<QRadioButton*>(table->cellWidget(0, 1))->setChecked(true);
|
||||
|
||||
for (int row = 1; row < table->rowCount(); row++)
|
||||
if (auto item = table->item(row, 0))
|
||||
item->setCheckState(Qt::Unchecked);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int row = 0; row < table->rowCount(); row++)
|
||||
{
|
||||
if (auto item = table->item(row, 0))
|
||||
{
|
||||
if (settingsDevices.contains(row))
|
||||
{
|
||||
item->setCheckState(Qt::Checked);
|
||||
|
||||
if (!settingsDevices.indexOf(QVariant::fromValue(row)))
|
||||
if (auto radio = qobject_cast<QRadioButton*>(table->cellWidget(row, 1)))
|
||||
radio->setChecked(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
item->setCheckState(Qt::Unchecked);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copy the values of the controls on the passed in table to a list of absolute device indices.
|
||||
/// Used in the options dialog and the final render dialog.
|
||||
/// </summary>
|
||||
/// <param name="table">The QTableWidget to copy values from</param>
|
||||
/// <returns>The list of absolute device indices</returns>
|
||||
static QList<QVariant> DeviceTableToSettings(QTableWidget* table)
|
||||
{
|
||||
QList<QVariant> devices;
|
||||
auto rows = table->rowCount();
|
||||
|
||||
for (int row = 0; row < rows; row++)
|
||||
{
|
||||
auto checkItem = table->item(row, 0);
|
||||
auto radio = qobject_cast<QRadioButton*>(table->cellWidget(row, 1));
|
||||
|
||||
if (checkItem->checkState() == Qt::Checked)
|
||||
{
|
||||
if (radio && radio->isChecked())
|
||||
devices.push_front(row);
|
||||
else
|
||||
devices.push_back(row);
|
||||
}
|
||||
}
|
||||
|
||||
return devices;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ensure device selection on the passed in table make sense.
|
||||
/// </summary>
|
||||
/// <param name="table">The QTableWidget to setup</param>
|
||||
/// <param name="row">The row of the cell</param>
|
||||
/// <param name="col">The column of the cell</param>
|
||||
static void HandleDeviceTableCheckChanged(QTableWidget* table, int row, int col)
|
||||
{
|
||||
int primaryRow = -1;
|
||||
QRadioButton* primaryRadio = nullptr;
|
||||
|
||||
for (int i = 0; i < table->rowCount(); i++)
|
||||
{
|
||||
if (auto radio = qobject_cast<QRadioButton*>(table->cellWidget(i, 1)))
|
||||
{
|
||||
if (radio->isChecked())
|
||||
{
|
||||
primaryRow = i;
|
||||
primaryRadio = radio;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (primaryRow == -1) primaryRow = 0;
|
||||
|
||||
if (auto primaryItem = table->item(primaryRow, 0))
|
||||
if (primaryItem->checkState() == Qt::Unchecked)
|
||||
primaryItem->setCheckState(Qt::Checked);
|
||||
}
|
||||
|
@ -11,19 +11,17 @@
|
||||
/// </summary>
|
||||
/// <param name="fractorium">Pointer to the main window.</param>
|
||||
FractoriumEmberControllerBase::FractoriumEmberControllerBase(Fractorium* fractorium)
|
||||
: m_Info(OpenCLInfo::Instance())
|
||||
{
|
||||
Timing t;
|
||||
|
||||
m_Rendering = false;
|
||||
m_Shared = true;
|
||||
m_Platform = 0;
|
||||
m_Device = 0;
|
||||
m_FailedRenders = 0;
|
||||
m_UndoIndex = 0;
|
||||
m_RenderType = CPU_RENDERER;
|
||||
m_OutputTexID = 0;
|
||||
m_SubBatchCount = 1;//Will be ovewritten by the options on first render.
|
||||
m_FinalImageIndex = 0;
|
||||
m_Fractorium = fractorium;
|
||||
m_RenderTimer = nullptr;
|
||||
m_RenderRestartTimer = nullptr;
|
||||
|
@ -72,16 +72,16 @@ public:
|
||||
virtual size_t TotalXformCount() const { return 0; }
|
||||
virtual QString Name() const { return ""; }
|
||||
virtual void Name(const string& s) { }
|
||||
virtual uint FinalRasW() const { return 0; }
|
||||
virtual void FinalRasW(uint w) { }
|
||||
virtual uint FinalRasH() const { return 0; }
|
||||
virtual void FinalRasH(uint h) { }
|
||||
virtual size_t FinalRasW() const { return 0; }
|
||||
virtual void FinalRasW(size_t w) { }
|
||||
virtual size_t FinalRasH() const { return 0; }
|
||||
virtual void FinalRasH(size_t h) { }
|
||||
virtual size_t Index() const { return 0; }
|
||||
virtual void AddSymmetry(int sym, QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand) { }
|
||||
virtual void CalcNormalizedWeights() { }
|
||||
|
||||
//Menu.
|
||||
virtual void NewFlock(uint count) { }//File.
|
||||
virtual void NewFlock(size_t count) { }//File.
|
||||
virtual void NewEmptyFlameInCurrentFile() { }
|
||||
virtual void NewRandomFlameInCurrentFile() { }
|
||||
virtual void CopyFlameInCurrentFile() { }
|
||||
@ -209,7 +209,7 @@ public:
|
||||
|
||||
//Rendering/progress.
|
||||
virtual bool Render() { return false; }
|
||||
virtual bool CreateRenderer(eRendererType renderType, uint platform, uint device, bool shared = true) { return false; }
|
||||
virtual bool CreateRenderer(eRendererType renderType, const vector<pair<size_t, size_t>>& devices, bool shared = true) { return false; }
|
||||
virtual uint SizeOfT() const { return 0; }
|
||||
virtual void ClearUndo() { }
|
||||
virtual GLEmberControllerBase* GLController() { return nullptr; }
|
||||
@ -221,10 +221,11 @@ public:
|
||||
void Shutdown();
|
||||
void UpdateRender(eProcessAction action = FULL_RENDER);
|
||||
void DeleteRenderer();
|
||||
void SaveCurrentRender(const QString& filename, bool forcePull);
|
||||
void SaveCurrentRender(const QString& filename, const EmberImageComments& comments, vector<byte>& pixels, size_t width, size_t height, size_t channels, size_t bpc);
|
||||
RendererBase* Renderer() { return m_Renderer.get(); }
|
||||
vector<byte>* FinalImage() { return &(m_FinalImage[m_FinalImageIndex]); }
|
||||
vector<byte>* FinalImage() { return &(m_FinalImage); }
|
||||
vector<byte>* PreviewFinalImage() { return &m_PreviewFinalImage; }
|
||||
EmberStats Stats() { return m_Stats; }
|
||||
|
||||
protected:
|
||||
//Rendering/progress.
|
||||
@ -236,9 +237,7 @@ protected:
|
||||
bool m_Rendering;
|
||||
bool m_Shared;
|
||||
bool m_LastEditWasUndoRedo;
|
||||
uint m_FinalImageIndex;
|
||||
uint m_Platform;
|
||||
uint m_Device;
|
||||
vector<pair<size_t, size_t>> m_Devices;
|
||||
uint m_SubBatchCount;
|
||||
uint m_FailedRenders;
|
||||
uint m_UndoIndex;
|
||||
@ -253,7 +252,7 @@ protected:
|
||||
string m_CurrentPaletteFilePath;
|
||||
CriticalSection m_Cs;
|
||||
std::thread m_WriteThread;
|
||||
vector<byte> m_FinalImage[2];
|
||||
vector<byte> m_FinalImage;
|
||||
vector<byte> m_PreviewFinalImage;
|
||||
vector<eProcessAction> m_ProcessActions;
|
||||
vector<eVariationId> m_FilteredVariations;
|
||||
@ -262,6 +261,7 @@ protected:
|
||||
Fractorium* m_Fractorium;
|
||||
QTimer* m_RenderTimer;
|
||||
QTimer* m_RenderRestartTimer;
|
||||
OpenCLInfo& m_Info;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
@ -306,10 +306,10 @@ public:
|
||||
virtual size_t TotalXformCount() const override { return m_Ember.TotalXformCount(); }
|
||||
virtual QString Name() const override { return QString::fromStdString(m_Ember.m_Name); }
|
||||
virtual void Name(const string& s) override { m_Ember.m_Name = s; }
|
||||
virtual uint FinalRasW() const override { return m_Ember.m_FinalRasW; }
|
||||
virtual void FinalRasW(uint w) override { m_Ember.m_FinalRasW = w; }
|
||||
virtual uint FinalRasH() const override { return m_Ember.m_FinalRasH; }
|
||||
virtual void FinalRasH(uint h) override { m_Ember.m_FinalRasH = h; }
|
||||
virtual size_t FinalRasW() const override { return m_Ember.m_FinalRasW; }
|
||||
virtual void FinalRasW(size_t w) override { m_Ember.m_FinalRasW = w; }
|
||||
virtual size_t FinalRasH() const override { return m_Ember.m_FinalRasH; }
|
||||
virtual void FinalRasH(size_t h) override { m_Ember.m_FinalRasH = h; }
|
||||
virtual size_t Index() const override { return m_Ember.m_Index; }
|
||||
virtual void AddSymmetry(int sym, QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand) override { m_Ember.AddSymmetry(sym, rand); }
|
||||
virtual void CalcNormalizedWeights() override { m_Ember.CalcNormalizedWeights(m_NormalizedWeights); }
|
||||
@ -317,7 +317,7 @@ public:
|
||||
Ember<T>* CurrentEmber();
|
||||
|
||||
//Menu.
|
||||
virtual void NewFlock(uint count) override;
|
||||
virtual void NewFlock(size_t count) override;
|
||||
virtual void NewEmptyFlameInCurrentFile() override;
|
||||
virtual void NewRandomFlameInCurrentFile() override;
|
||||
virtual void CopyFlameInCurrentFile() override;
|
||||
@ -447,7 +447,7 @@ public:
|
||||
|
||||
//Rendering/progress.
|
||||
virtual bool Render() override;
|
||||
virtual bool CreateRenderer(eRendererType renderType, uint platform, uint device, bool shared = true) override;
|
||||
virtual bool CreateRenderer(eRendererType renderType, const vector<pair<size_t, size_t>>& devices, bool shared = true) override;
|
||||
virtual uint SizeOfT() const override { return sizeof(T); }
|
||||
virtual int ProgressFunc(Ember<T>& ember, void* foo, double fraction, int stage, double etaMs) override;
|
||||
virtual void ClearUndo() override;
|
||||
|
@ -33,7 +33,7 @@ void Fractorium::InitInfoUI()
|
||||
/// <param name="newSize">Ignored</param>
|
||||
void Fractorium::OnSummaryTableHeaderResized(int logicalIndex, int oldSize, int newSize)
|
||||
{
|
||||
QPixmap pixmap = QPixmap::fromImage(m_Controller->FinalPaletteImage());//Create a QPixmap out of the QImage.
|
||||
QPixmap pixmap = QPixmap::fromImage(m_Controller->FinalPaletteImage());//Create a QPixmap out of the QImage, will be empty on startup.
|
||||
SetPaletteTableItem(&pixmap, ui.SummaryTableWidget, m_InfoPaletteItem, 1, 0);
|
||||
}
|
||||
|
||||
|
@ -240,7 +240,7 @@ void FractoriumEmberController<T>::EmberTreeItemChanged(QTreeWidgetItem* item, i
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(std::exception& e)
|
||||
catch(const std::exception& e)
|
||||
{
|
||||
qDebug() << "FractoriumEmberController<T>::EmberTreeItemChanged() : Exception thrown: " << e.what();
|
||||
}
|
||||
|
@ -19,13 +19,13 @@ void Fractorium::InitMenusUI()
|
||||
connect(ui.ActionExit, SIGNAL(triggered(bool)), this, SLOT(OnActionExit(bool)), Qt::QueuedConnection);
|
||||
|
||||
//Edit menu.
|
||||
connect(ui.ActionUndo, SIGNAL(triggered(bool)), this, SLOT(OnActionUndo(bool)), Qt::QueuedConnection);
|
||||
connect(ui.ActionRedo, SIGNAL(triggered(bool)), this, SLOT(OnActionRedo(bool)), Qt::QueuedConnection);
|
||||
connect(ui.ActionCopyXml, SIGNAL(triggered(bool)), this, SLOT(OnActionCopyXml(bool)), Qt::QueuedConnection);
|
||||
connect(ui.ActionCopyAllXml, SIGNAL(triggered(bool)), this, SLOT(OnActionCopyAllXml(bool)), Qt::QueuedConnection);
|
||||
connect(ui.ActionPasteXmlAppend, SIGNAL(triggered(bool)), this, SLOT(OnActionPasteXmlAppend(bool)), Qt::QueuedConnection);
|
||||
connect(ui.ActionPasteXmlOver, SIGNAL(triggered(bool)), this, SLOT(OnActionPasteXmlOver(bool)), Qt::QueuedConnection);
|
||||
connect(ui.ActionCopySelectedXforms, SIGNAL(triggered(bool)), this, SLOT(OnActionCopySelectedXforms(bool)), Qt::QueuedConnection);
|
||||
connect(ui.ActionUndo, SIGNAL(triggered(bool)), this, SLOT(OnActionUndo(bool)), Qt::QueuedConnection);
|
||||
connect(ui.ActionRedo, SIGNAL(triggered(bool)), this, SLOT(OnActionRedo(bool)), Qt::QueuedConnection);
|
||||
connect(ui.ActionCopyXml, SIGNAL(triggered(bool)), this, SLOT(OnActionCopyXml(bool)), Qt::QueuedConnection);
|
||||
connect(ui.ActionCopyAllXml, SIGNAL(triggered(bool)), this, SLOT(OnActionCopyAllXml(bool)), Qt::QueuedConnection);
|
||||
connect(ui.ActionPasteXmlAppend, SIGNAL(triggered(bool)), this, SLOT(OnActionPasteXmlAppend(bool)), Qt::QueuedConnection);
|
||||
connect(ui.ActionPasteXmlOver, SIGNAL(triggered(bool)), this, SLOT(OnActionPasteXmlOver(bool)), Qt::QueuedConnection);
|
||||
connect(ui.ActionCopySelectedXforms, SIGNAL(triggered(bool)), this, SLOT(OnActionCopySelectedXforms(bool)), Qt::QueuedConnection);
|
||||
connect(ui.ActionPasteSelectedXforms, SIGNAL(triggered(bool)), this, SLOT(OnActionPasteSelectedXforms(bool)), Qt::QueuedConnection);
|
||||
ui.ActionPasteSelectedXforms->setEnabled(false);
|
||||
|
||||
@ -54,7 +54,7 @@ void Fractorium::InitMenusUI()
|
||||
/// </summary>
|
||||
/// <param name="count">The number of embers to include in the flock</param>
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::NewFlock(uint count)
|
||||
void FractoriumEmberController<T>::NewFlock(size_t count)
|
||||
{
|
||||
Ember<T> ember;
|
||||
|
||||
@ -63,12 +63,12 @@ void FractoriumEmberController<T>::NewFlock(uint count)
|
||||
m_EmberFile.m_Embers.reserve(count);
|
||||
m_EmberFile.m_Filename = EmberFile<T>::DefaultFilename();
|
||||
|
||||
for (uint i = 0; i < count; i++)
|
||||
for (size_t i = 0; i < count; i++)
|
||||
{
|
||||
m_SheepTools->Random(ember, m_FilteredVariations, static_cast<int>(QTIsaac<ISAAC_SIZE, ISAAC_INT>::GlobalRand->Frand<T>(-2, 2)), 0);
|
||||
m_SheepTools->Random(ember, m_FilteredVariations, static_cast<intmax_t>(QTIsaac<ISAAC_SIZE, ISAAC_INT>::GlobalRand->Frand<T>(-2, 2)), 0);
|
||||
ParamsToEmber(ember);
|
||||
ember.m_Index = i;
|
||||
ember.m_Name = m_EmberFile.m_Filename.toStdString() + "-" + ToString(i + 1).toStdString();
|
||||
ember.m_Name = m_EmberFile.m_Filename.toStdString() + "-" + ToString(i + 1ULL).toStdString();
|
||||
m_EmberFile.m_Embers.push_back(ember);
|
||||
}
|
||||
|
||||
@ -353,8 +353,22 @@ void Fractorium::OnActionSaveEntireFileAsXml(bool checked) { m_Controller->SaveE
|
||||
void Fractorium::OnActionSaveCurrentScreen(bool checked)
|
||||
{
|
||||
QString filename = SetupSaveImageDialog(m_Controller->Name());
|
||||
auto renderer = m_Controller->Renderer();
|
||||
auto& pixels = *m_Controller->FinalImage();
|
||||
RendererCLBase* rendererCL = dynamic_cast<RendererCLBase*>(m_Controller->Renderer());
|
||||
auto stats = m_Controller->Stats();
|
||||
EmberImageComments comments = renderer->ImageComments(stats, 0, false, true);
|
||||
|
||||
m_Controller->SaveCurrentRender(filename, true);
|
||||
if (rendererCL && renderer->PrepFinalAccumVector(pixels))
|
||||
{
|
||||
if (!rendererCL->ReadFinal(pixels.data()))
|
||||
{
|
||||
ShowCritical("GPU Read Error", "Could not read image from the GPU, aborting image save.", false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
m_Controller->SaveCurrentRender(filename, comments, pixels, renderer->FinalRasW(), renderer->FinalRasH(), renderer->NumChannels(), renderer->BytesPerChannel());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -341,7 +341,7 @@ void Fractorium::OnPaletteFilterLineEditTextChanged(const QString& text)
|
||||
|
||||
table->setUpdatesEnabled(false);
|
||||
|
||||
for (uint i = 0; i < uint(table->rowCount()); i++)
|
||||
for (int i = 0; i < table->rowCount(); i++)
|
||||
{
|
||||
if (auto item = table->item(i, 0))
|
||||
{
|
||||
|
@ -78,8 +78,7 @@ void FractoriumEmberControllerBase::Shutdown()
|
||||
/// </summary>
|
||||
void FractoriumEmberControllerBase::ClearFinalImages()
|
||||
{
|
||||
Memset(m_FinalImage[0]);
|
||||
Memset(m_FinalImage[1]);
|
||||
Memset(m_FinalImage);
|
||||
//Unsure if we should also call RendererCL::ClearFinal() as well. At the moment it seems unnecessary.
|
||||
}
|
||||
|
||||
@ -114,48 +113,42 @@ void FractoriumEmberControllerBase::DeleteRenderer()
|
||||
|
||||
/// <summary>
|
||||
/// Save the current render results to a file.
|
||||
/// This could benefit from QImageWriter, however it's compression capabilities are
|
||||
/// This could benefit from QImageWriter, however its compression capabilities are
|
||||
/// severely lacking. A Png file comes out larger than a bitmap, so instead use the
|
||||
/// Png and Jpg wrapper functions from the command line programs.
|
||||
/// This will embed the id, url and nick fields from the options in the image comments.
|
||||
/// </summary>
|
||||
/// <param name="filename">The full path and filename</param>
|
||||
void FractoriumEmberControllerBase::SaveCurrentRender(const QString& filename, bool forcePull)
|
||||
/// <param name="comments">The comments to save in the png or jpg</param>
|
||||
/// <param name="pixels">The buffer containing the pixels</param>
|
||||
/// <param name="width">The width in pixels of the image</param>
|
||||
/// <param name="height">The height in pixels of the image</param>
|
||||
/// <param name="channels">The number of channels, 3 or 4.</param>
|
||||
/// <param name="bpc">The bytes per channel, almost always 1.</param>
|
||||
void FractoriumEmberControllerBase::SaveCurrentRender(const QString& filename, const EmberImageComments& comments, vector<byte>& pixels, size_t width, size_t height, size_t channels, size_t bpc)
|
||||
{
|
||||
if (filename != "")
|
||||
{
|
||||
bool b = false;
|
||||
uint i, j;
|
||||
uint width = m_Renderer->FinalRasW();
|
||||
uint height = m_Renderer->FinalRasH();
|
||||
byte* data = nullptr;
|
||||
vector<byte> vecRgb;
|
||||
QFileInfo fileInfo(filename);
|
||||
QString suffix = fileInfo.suffix();
|
||||
FractoriumSettings* settings = m_Fractorium->m_Settings;
|
||||
RendererCLBase* rendererCL = dynamic_cast<RendererCLBase*>(m_Renderer.get());
|
||||
|
||||
if (forcePull && rendererCL && m_Renderer->PrepFinalAccumVector(m_FinalImage[m_FinalImageIndex]))
|
||||
{
|
||||
if (!rendererCL->ReadFinal(m_FinalImage[m_FinalImageIndex].data()))
|
||||
{
|
||||
m_Fractorium->ShowCritical("GPU Read Error", "Could not read image from the GPU, aborting image save.", true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//Ensure dimensions are valid.
|
||||
if (m_FinalImage[m_FinalImageIndex].size() < (width * height * m_Renderer->NumChannels() * m_Renderer->BytesPerChannel()))
|
||||
if (pixels.size() < (width * height * channels * bpc))
|
||||
{
|
||||
m_Fractorium->ShowCritical("Save Failed", "Dimensions didn't match, not saving.", true);
|
||||
return;
|
||||
}
|
||||
|
||||
data = m_FinalImage[m_FinalImageIndex].data();//Png and channels == 4.
|
||||
data = pixels.data();//Png and channels == 4.
|
||||
|
||||
if ((suffix == "jpg" || suffix == "bmp") && m_Renderer->NumChannels() == 4)
|
||||
if ((suffix == "jpg" || suffix == "bmp") && channels)
|
||||
{
|
||||
RgbaToRgb(m_FinalImage[m_FinalImageIndex], vecRgb, width, height);
|
||||
RgbaToRgb(pixels, vecRgb, width, height);
|
||||
|
||||
data = vecRgb.data();
|
||||
}
|
||||
@ -164,7 +157,6 @@ void FractoriumEmberControllerBase::SaveCurrentRender(const QString& filename, b
|
||||
string id = settings->Id().toStdString();
|
||||
string url = settings->Url().toStdString();
|
||||
string nick = settings->Nick().toStdString();
|
||||
EmberImageComments comments = m_Renderer->ImageComments(m_Stats, 0, false, true);
|
||||
|
||||
if (suffix == "png")
|
||||
b = WritePng(s.c_str(), data, width, height, 1, true, comments, id, url, nick);
|
||||
@ -369,14 +361,14 @@ bool FractoriumEmberController<T>::Render()
|
||||
if (ProcessState() != ACCUM_DONE)
|
||||
{
|
||||
//if (m_Renderer->Run(m_FinalImage, 0) == RENDER_OK)//Full, non-incremental render for debugging.
|
||||
if (m_Renderer->Run(m_FinalImage[m_FinalImageIndex], 0, m_SubBatchCount, (iterBegin || m_Fractorium->m_Settings->ContinuousUpdate())) == RENDER_OK)//Force output on iterBegin or if the settings specify to always do it.
|
||||
if (m_Renderer->Run(m_FinalImage, 0, m_SubBatchCount, (iterBegin || m_Fractorium->m_Settings->ContinuousUpdate())) == RENDER_OK)//Force output on iterBegin or if the settings specify to always do it.
|
||||
{
|
||||
//The amount to increment sub batch while rendering proceeds is purely empirical.
|
||||
//Change later if better values can be derived/observed.
|
||||
if (m_Renderer->RendererType() == OPENCL_RENDERER)
|
||||
{
|
||||
if (m_SubBatchCount < 3)//More than 3 with OpenCL gives a sluggish UI.
|
||||
m_SubBatchCount++;
|
||||
if (m_SubBatchCount < (4 * m_Devices.size()))//More than 3 with OpenCL gives a sluggish UI.
|
||||
m_SubBatchCount += m_Devices.size();
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -445,7 +437,7 @@ bool FractoriumEmberController<T>::Render()
|
||||
//Update it on finish because the rendering process is completely done.
|
||||
if (iterBegin || ProcessState() == ACCUM_DONE)
|
||||
{
|
||||
if (m_FinalImage[m_FinalImageIndex].size() == m_Renderer->FinalBufferSize())//Make absolutely sure the correct amount of data is passed.
|
||||
if (m_FinalImage.size() == m_Renderer->FinalBufferSize())//Make absolutely sure the correct amount of data is passed.
|
||||
gl->update();
|
||||
//gl->repaint();
|
||||
|
||||
@ -504,19 +496,17 @@ bool FractoriumEmberController<T>::Render()
|
||||
/// Rendering will be left in a stopped state. The caller is responsible for restarting the render loop again.
|
||||
/// </summary>
|
||||
/// <param name="renderType">The type of render to create</param>
|
||||
/// <param name="platform">The index platform of the platform to use</param>
|
||||
/// <param name="device">The index device of the device to use</param>
|
||||
/// <param name="outputTexID">The texture ID of the shared OpenGL texture if shared</param>
|
||||
/// <param name="devices">The platform,device index pairs of the devices to use</param>
|
||||
/// <param name="shared">True if shared with OpenGL, else false. Default: true.</param>
|
||||
/// <returns>True if nothing went wrong, else false.</returns>
|
||||
template <typename T>
|
||||
bool FractoriumEmberController<T>::CreateRenderer(eRendererType renderType, uint platform, uint device, bool shared)
|
||||
bool FractoriumEmberController<T>::CreateRenderer(eRendererType renderType, const vector<pair<size_t, size_t>>& devices, bool shared)
|
||||
{
|
||||
bool ok = true;
|
||||
FractoriumSettings* s = m_Fractorium->m_Settings;
|
||||
GLWidget* gl = m_Fractorium->ui.GLDisplay;
|
||||
|
||||
if (!m_Renderer.get() || (m_Renderer->RendererType() != renderType) || (m_Platform != platform) || (m_Device != device))
|
||||
if (!m_Renderer.get() || (m_Renderer->RendererType() != renderType) || !Equal(m_Devices, devices))
|
||||
{
|
||||
EmberReport emberReport;
|
||||
vector<string> errorReport;
|
||||
@ -524,13 +514,12 @@ bool FractoriumEmberController<T>::CreateRenderer(eRendererType renderType, uint
|
||||
DeleteRenderer();//Delete the renderer and refresh the textures.
|
||||
//Before starting, must take care of allocations.
|
||||
gl->Allocate(true);//Forcing a realloc of the texture is necessary on AMD, but not on nVidia.
|
||||
m_Renderer = unique_ptr<EmberNs::RendererBase>(::CreateRenderer<T, float>(renderType, platform, device, shared, gl->OutputTexID(), emberReport));//Always make bucket type float.
|
||||
m_Renderer = unique_ptr<EmberNs::RendererBase>(::CreateRenderer<T>(renderType, devices, shared, gl->OutputTexID(), emberReport));//Always make bucket type float.
|
||||
errorReport = emberReport.ErrorReport();
|
||||
|
||||
if (errorReport.empty())
|
||||
{
|
||||
m_Platform = platform;//Store values for re-creation later on.
|
||||
m_Device = device;
|
||||
m_Devices = devices;
|
||||
m_OutputTexID = gl->OutputTexID();
|
||||
m_Shared = shared;
|
||||
}
|
||||
@ -548,11 +537,13 @@ bool FractoriumEmberController<T>::CreateRenderer(eRendererType renderType, uint
|
||||
|
||||
if (m_RenderType == OPENCL_RENDERER)
|
||||
{
|
||||
m_Fractorium->m_QualitySpin->DoubleClickZero(30);
|
||||
m_Fractorium->m_QualitySpin->DoubleClickNonZero(30);
|
||||
auto val = 30 * m_Fractorium->m_Settings->Devices().size();
|
||||
|
||||
if (m_Fractorium->m_QualitySpin->value() < 30)
|
||||
m_Fractorium->m_QualitySpin->setValue(30);
|
||||
m_Fractorium->m_QualitySpin->DoubleClickZero(val);
|
||||
m_Fractorium->m_QualitySpin->DoubleClickNonZero(val);
|
||||
|
||||
if (m_Fractorium->m_QualitySpin->value() < val)
|
||||
m_Fractorium->m_QualitySpin->setValue(val);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -618,12 +609,11 @@ void Fractorium::ShutdownAndRecreateFromOptions()
|
||||
bool Fractorium::CreateRendererFromOptions()
|
||||
{
|
||||
bool ok = true;
|
||||
bool useOpenCL = m_Wrapper.CheckOpenCL() && m_Settings->OpenCL();
|
||||
|
||||
bool useOpenCL = m_Info.Ok() && m_Settings->OpenCL();
|
||||
auto v = Devices(m_Settings->Devices());
|
||||
|
||||
//The most important option to process is what kind of renderer is desired, so do it first.
|
||||
if (!m_Controller->CreateRenderer(useOpenCL ? OPENCL_RENDERER : CPU_RENDERER,
|
||||
m_Settings->PlatformIndex(),
|
||||
m_Settings->DeviceIndex()))
|
||||
if (!m_Controller->CreateRenderer((useOpenCL && !v.empty()) ? OPENCL_RENDERER : CPU_RENDERER, v))
|
||||
{
|
||||
//If using OpenCL, will only get here if creating RendererCL failed, but creating a backup CPU Renderer succeeded.
|
||||
ShowCritical("Renderer Creation Error", "Error creating renderer, most likely a GPU problem. Using CPU instead.");
|
||||
|
@ -21,7 +21,7 @@ void FractoriumSettings::EnsureDefaults()
|
||||
FinalQuality(1000);
|
||||
|
||||
if (FinalTemporalSamples() == 0)
|
||||
FinalTemporalSamples(1000);
|
||||
FinalTemporalSamples(100);
|
||||
|
||||
if (FinalSupersample() == 0)
|
||||
FinalSupersample(2);
|
||||
@ -30,7 +30,7 @@ void FractoriumSettings::EnsureDefaults()
|
||||
FinalStrips(1);
|
||||
|
||||
if (XmlTemporalSamples() == 0)
|
||||
XmlTemporalSamples(1000);
|
||||
XmlTemporalSamples(100);
|
||||
|
||||
if (XmlQuality() == 0)
|
||||
XmlQuality(1000);
|
||||
@ -44,7 +44,7 @@ void FractoriumSettings::EnsureDefaults()
|
||||
if (FinalThreadCount() == 0 || FinalThreadCount() > Timing::ProcessorCount())
|
||||
FinalThreadCount(Timing::ProcessorCount());
|
||||
|
||||
FinalThreadPriority(Clamp<int>((int)eThreadPriority::LOWEST, (int)eThreadPriority::HIGHEST, FinalThreadPriority()));
|
||||
FinalThreadPriority(Clamp<int>(FinalThreadPriority(), (int)eThreadPriority::LOWEST, (int)eThreadPriority::HIGHEST));
|
||||
|
||||
if (CpuSubBatch() < 1)
|
||||
CpuSubBatch(1);
|
||||
@ -52,24 +52,9 @@ void FractoriumSettings::EnsureDefaults()
|
||||
if (OpenCLSubBatch() < 1)
|
||||
OpenCLSubBatch(1);
|
||||
|
||||
//There normally wouldn't be any more than 10 OpenCL platforms and devices
|
||||
//on the system, so if a value greater than that is read, then the settings file
|
||||
//was corrupted.
|
||||
if (PlatformIndex() > 10)
|
||||
PlatformIndex(0);
|
||||
|
||||
if (DeviceIndex() > 10)
|
||||
DeviceIndex(0);
|
||||
|
||||
if (FinalScale() > SCALE_HEIGHT)
|
||||
FinalScale(0);
|
||||
|
||||
if (FinalPlatformIndex() > 10)
|
||||
FinalPlatformIndex(0);
|
||||
|
||||
if (FinalDeviceIndex() > 10)
|
||||
FinalDeviceIndex(0);
|
||||
|
||||
if (OpenXmlExt() == "")
|
||||
OpenXmlExt("Flame (*.flame)");
|
||||
|
||||
@ -101,155 +86,149 @@ void FractoriumSettings::EnsureDefaults()
|
||||
/// Interactive renderer settings.
|
||||
/// </summary>
|
||||
|
||||
bool FractoriumSettings::EarlyClip() { return value(EARLYCLIP).toBool(); }
|
||||
void FractoriumSettings::EarlyClip(bool b) { setValue(EARLYCLIP, b); }
|
||||
bool FractoriumSettings::EarlyClip() { return value(EARLYCLIP).toBool(); }
|
||||
void FractoriumSettings::EarlyClip(bool b) { setValue(EARLYCLIP, b); }
|
||||
|
||||
bool FractoriumSettings::YAxisUp() { return value(YAXISUP).toBool(); }
|
||||
void FractoriumSettings::YAxisUp(bool b) { setValue(YAXISUP, b); }
|
||||
|
||||
bool FractoriumSettings::Transparency() { return value(TRANSPARENCY).toBool(); }
|
||||
void FractoriumSettings::Transparency(bool b) { setValue(TRANSPARENCY, b); }
|
||||
|
||||
bool FractoriumSettings::OpenCL() { return value(OPENCL).toBool(); }
|
||||
void FractoriumSettings::OpenCL(bool b) { setValue(OPENCL, b); }
|
||||
|
||||
bool FractoriumSettings::Double() { return value(DOUBLEPRECISION).toBool(); }
|
||||
void FractoriumSettings::Double(bool b) { setValue(DOUBLEPRECISION, b); }
|
||||
|
||||
bool FractoriumSettings::ShowAllXforms() { return value(SHOWALLXFORMS).toBool(); }
|
||||
void FractoriumSettings::ShowAllXforms(bool b) { setValue(SHOWALLXFORMS, b); }
|
||||
|
||||
bool FractoriumSettings::ContinuousUpdate() { return value(CONTUPDATE).toBool(); }
|
||||
void FractoriumSettings::ContinuousUpdate(bool b) { setValue(CONTUPDATE, b); }
|
||||
|
||||
bool FractoriumSettings::YAxisUp() { return value(YAXISUP).toBool(); }
|
||||
void FractoriumSettings::YAxisUp(bool b) { setValue(YAXISUP, b); }
|
||||
QList<QVariant> FractoriumSettings::Devices() { return value(DEVICES).toList(); }
|
||||
void FractoriumSettings::Devices(const QList<QVariant>& devices) { setValue(DEVICES, devices); }
|
||||
|
||||
bool FractoriumSettings::Transparency() { return value(TRANSPARENCY).toBool(); }
|
||||
void FractoriumSettings::Transparency(bool b) { setValue(TRANSPARENCY, b); }
|
||||
|
||||
bool FractoriumSettings::OpenCL() { return value(OPENCL).toBool(); }
|
||||
void FractoriumSettings::OpenCL(bool b) { setValue(OPENCL, b); }
|
||||
|
||||
bool FractoriumSettings::Double() { return value(DOUBLEPRECISION).toBool(); }
|
||||
void FractoriumSettings::Double(bool b) { setValue(DOUBLEPRECISION, b); }
|
||||
|
||||
bool FractoriumSettings::ShowAllXforms() { return value(SHOWALLXFORMS).toBool(); }
|
||||
void FractoriumSettings::ShowAllXforms(bool b) { setValue(SHOWALLXFORMS, b); }
|
||||
|
||||
bool FractoriumSettings::ContinuousUpdate() { return value(CONTUPDATE).toBool(); }
|
||||
void FractoriumSettings::ContinuousUpdate(bool b) { setValue(CONTUPDATE, b); }
|
||||
|
||||
uint FractoriumSettings::PlatformIndex() { return value(PLATFORMINDEX).toUInt(); }
|
||||
void FractoriumSettings::PlatformIndex(uint i) { setValue(PLATFORMINDEX, i); }
|
||||
|
||||
uint FractoriumSettings::DeviceIndex() { return value(DEVICEINDEX).toUInt(); }
|
||||
void FractoriumSettings::DeviceIndex(uint i) { setValue(DEVICEINDEX, i); }
|
||||
|
||||
uint FractoriumSettings::ThreadCount() { return value(THREADCOUNT).toUInt(); }
|
||||
void FractoriumSettings::ThreadCount(uint i) { setValue(THREADCOUNT, i); }
|
||||
|
||||
bool FractoriumSettings::CpuDEFilter() { return value(CPUDEFILTER).toBool(); }
|
||||
void FractoriumSettings::CpuDEFilter(bool b) { setValue(CPUDEFILTER, b); }
|
||||
|
||||
bool FractoriumSettings::OpenCLDEFilter() { return value(OPENCLDEFILTER).toBool(); }
|
||||
void FractoriumSettings::OpenCLDEFilter(bool b) { setValue(OPENCLDEFILTER, b); }
|
||||
|
||||
uint FractoriumSettings::CpuSubBatch() { return value(CPUSUBBATCH).toUInt(); }
|
||||
void FractoriumSettings::CpuSubBatch(uint b) { setValue(CPUSUBBATCH, b); }
|
||||
|
||||
uint FractoriumSettings::OpenCLSubBatch() { return value(OPENCLSUBBATCH).toUInt(); }
|
||||
void FractoriumSettings::OpenCLSubBatch(uint b) { setValue(OPENCLSUBBATCH, b); }
|
||||
uint FractoriumSettings::ThreadCount() { return value(THREADCOUNT).toUInt(); }
|
||||
void FractoriumSettings::ThreadCount(uint i) { setValue(THREADCOUNT, i); }
|
||||
|
||||
bool FractoriumSettings::CpuDEFilter() { return value(CPUDEFILTER).toBool(); }
|
||||
void FractoriumSettings::CpuDEFilter(bool b) { setValue(CPUDEFILTER, b); }
|
||||
|
||||
bool FractoriumSettings::OpenCLDEFilter() { return value(OPENCLDEFILTER).toBool(); }
|
||||
void FractoriumSettings::OpenCLDEFilter(bool b) { setValue(OPENCLDEFILTER, b); }
|
||||
|
||||
uint FractoriumSettings::CpuSubBatch() { return value(CPUSUBBATCH).toUInt(); }
|
||||
void FractoriumSettings::CpuSubBatch(uint i) { setValue(CPUSUBBATCH, i); }
|
||||
|
||||
uint FractoriumSettings::OpenCLSubBatch() { return value(OPENCLSUBBATCH).toUInt(); }
|
||||
void FractoriumSettings::OpenCLSubBatch(uint i) { setValue(OPENCLSUBBATCH, i); }
|
||||
|
||||
/// <summary>
|
||||
/// Final render settings.
|
||||
/// </summary>
|
||||
|
||||
bool FractoriumSettings::FinalEarlyClip() { return value(FINALEARLYCLIP).toBool(); }
|
||||
void FractoriumSettings::FinalEarlyClip(bool b) { setValue(FINALEARLYCLIP, b); }
|
||||
|
||||
bool FractoriumSettings::FinalYAxisUp() { return value(FINALYAXISUP).toBool(); }
|
||||
void FractoriumSettings::FinalYAxisUp(bool b) { setValue(FINALYAXISUP, b); }
|
||||
|
||||
bool FractoriumSettings::FinalTransparency() { return value(FINALTRANSPARENCY).toBool(); }
|
||||
void FractoriumSettings::FinalTransparency(bool b) { setValue(FINALTRANSPARENCY, b); }
|
||||
|
||||
bool FractoriumSettings::FinalOpenCL() { return value(FINALOPENCL).toBool(); }
|
||||
void FractoriumSettings::FinalOpenCL(bool b) { setValue(FINALOPENCL, b); }
|
||||
bool FractoriumSettings::FinalEarlyClip() { return value(FINALEARLYCLIP).toBool(); }
|
||||
void FractoriumSettings::FinalEarlyClip(bool b) { setValue(FINALEARLYCLIP, b); }
|
||||
|
||||
bool FractoriumSettings::FinalYAxisUp() { return value(FINALYAXISUP).toBool(); }
|
||||
void FractoriumSettings::FinalYAxisUp(bool b) { setValue(FINALYAXISUP, b); }
|
||||
|
||||
bool FractoriumSettings::FinalTransparency() { return value(FINALTRANSPARENCY).toBool(); }
|
||||
void FractoriumSettings::FinalTransparency(bool b) { setValue(FINALTRANSPARENCY, b); }
|
||||
|
||||
bool FractoriumSettings::FinalOpenCL() { return value(FINALOPENCL).toBool(); }
|
||||
void FractoriumSettings::FinalOpenCL(bool b) { setValue(FINALOPENCL, b); }
|
||||
|
||||
bool FractoriumSettings::FinalDouble() { return value(FINALDOUBLEPRECISION).toBool(); }
|
||||
void FractoriumSettings::FinalDouble(bool b) { setValue(FINALDOUBLEPRECISION, b); }
|
||||
|
||||
bool FractoriumSettings::FinalSaveXml() { return value(FINALSAVEXML).toBool(); }
|
||||
void FractoriumSettings::FinalSaveXml(bool b) { setValue(FINALSAVEXML, b); }
|
||||
|
||||
bool FractoriumSettings::FinalDoAll() { return value(FINALDOALL).toBool(); }
|
||||
void FractoriumSettings::FinalDoAll(bool b) { setValue(FINALDOALL, b); }
|
||||
|
||||
bool FractoriumSettings::FinalDoSequence() { return value(FINALDOSEQUENCE).toBool(); }
|
||||
void FractoriumSettings::FinalDoSequence(bool b) { setValue(FINALDOSEQUENCE, b); }
|
||||
|
||||
bool FractoriumSettings::FinalKeepAspect() { return value(FINALKEEPASPECT).toBool(); }
|
||||
void FractoriumSettings::FinalKeepAspect(bool b) { setValue(FINALKEEPASPECT, b); }
|
||||
|
||||
uint FractoriumSettings::FinalScale() { return value(FINALSCALE).toUInt(); }
|
||||
void FractoriumSettings::FinalScale(uint i) { setValue(FINALSCALE, i); }
|
||||
|
||||
QString FractoriumSettings::FinalExt() { return value(FINALEXT).toString(); }
|
||||
void FractoriumSettings::FinalExt(const QString& s) { setValue(FINALEXT, s); }
|
||||
|
||||
bool FractoriumSettings::FinalDouble() { return value(FINALDOUBLEPRECISION).toBool(); }
|
||||
void FractoriumSettings::FinalDouble(bool b) { setValue(FINALDOUBLEPRECISION, b); }
|
||||
QList<QVariant> FractoriumSettings::FinalDevices() { return value(FINALDEVICES).toList(); }
|
||||
void FractoriumSettings::FinalDevices(const QList<QVariant>& devices) { setValue(FINALDEVICES, devices); }
|
||||
|
||||
bool FractoriumSettings::FinalSaveXml() { return value(FINALSAVEXML).toBool(); }
|
||||
void FractoriumSettings::FinalSaveXml(bool b) { setValue(FINALSAVEXML, b); }
|
||||
|
||||
bool FractoriumSettings::FinalDoAll() { return value(FINALDOALL).toBool(); }
|
||||
void FractoriumSettings::FinalDoAll(bool b) { setValue(FINALDOALL, b); }
|
||||
|
||||
bool FractoriumSettings::FinalDoSequence() { return value(FINALDOSEQUENCE).toBool(); }
|
||||
void FractoriumSettings::FinalDoSequence(bool b) { setValue(FINALDOSEQUENCE, b); }
|
||||
|
||||
bool FractoriumSettings::FinalKeepAspect() { return value(FINALKEEPASPECT).toBool(); }
|
||||
void FractoriumSettings::FinalKeepAspect(bool b) { setValue(FINALKEEPASPECT, b); }
|
||||
|
||||
uint FractoriumSettings::FinalScale() { return value(FINALSCALE).toUInt(); }
|
||||
void FractoriumSettings::FinalScale(uint i) { setValue(FINALSCALE, i); }
|
||||
|
||||
QString FractoriumSettings::FinalExt() { return value(FINALEXT).toString(); }
|
||||
void FractoriumSettings::FinalExt(const QString& s) { setValue(FINALEXT, s); }
|
||||
|
||||
uint FractoriumSettings::FinalPlatformIndex() { return value(FINALPLATFORMINDEX).toUInt(); }
|
||||
void FractoriumSettings::FinalPlatformIndex(uint i) { setValue(FINALPLATFORMINDEX, i); }
|
||||
|
||||
uint FractoriumSettings::FinalDeviceIndex() { return value(FINALDEVICEINDEX).toUInt(); }
|
||||
void FractoriumSettings::FinalDeviceIndex(uint i) { setValue(FINALDEVICEINDEX, i); }
|
||||
|
||||
uint FractoriumSettings::FinalThreadCount() { return value(FINALTHREADCOUNT).toUInt(); }
|
||||
void FractoriumSettings::FinalThreadCount(uint i) { setValue(FINALTHREADCOUNT, i); }
|
||||
|
||||
uint FractoriumSettings::FinalThreadPriority() { return value(FINALTHREADPRIORITY).toInt(); }
|
||||
void FractoriumSettings::FinalThreadPriority(int i) { setValue(FINALTHREADPRIORITY, i); }
|
||||
|
||||
uint FractoriumSettings::FinalQuality() { return value(FINALQUALITY).toUInt(); }
|
||||
void FractoriumSettings::FinalQuality(uint i) { setValue(FINALQUALITY, i); }
|
||||
|
||||
uint FractoriumSettings::FinalTemporalSamples() { return value(FINALTEMPORALSAMPLES).toUInt(); }
|
||||
void FractoriumSettings::FinalTemporalSamples(uint i) { setValue(FINALTEMPORALSAMPLES, i); }
|
||||
|
||||
uint FractoriumSettings::FinalSupersample() { return value(FINALSUPERSAMPLE).toUInt(); }
|
||||
void FractoriumSettings::FinalSupersample(uint i) { setValue(FINALSUPERSAMPLE, i); }
|
||||
|
||||
uint FractoriumSettings::FinalStrips() { return value(FINALSTRIPS).toUInt(); }
|
||||
void FractoriumSettings::FinalStrips(uint i) { setValue(FINALSTRIPS, i); }
|
||||
uint FractoriumSettings::FinalThreadCount() { return value(FINALTHREADCOUNT).toUInt(); }
|
||||
void FractoriumSettings::FinalThreadCount(uint i) { setValue(FINALTHREADCOUNT, i); }
|
||||
|
||||
int FractoriumSettings::FinalThreadPriority() { return value(FINALTHREADPRIORITY).toInt(); }
|
||||
void FractoriumSettings::FinalThreadPriority(int i) { setValue(FINALTHREADPRIORITY, i); }
|
||||
|
||||
uint FractoriumSettings::FinalQuality() { return value(FINALQUALITY).toUInt(); }
|
||||
void FractoriumSettings::FinalQuality(uint i) { setValue(FINALQUALITY, i); }
|
||||
|
||||
uint FractoriumSettings::FinalTemporalSamples() { return value(FINALTEMPORALSAMPLES).toUInt(); }
|
||||
void FractoriumSettings::FinalTemporalSamples(uint i) { setValue(FINALTEMPORALSAMPLES, i); }
|
||||
|
||||
uint FractoriumSettings::FinalSupersample() { return value(FINALSUPERSAMPLE).toUInt(); }
|
||||
void FractoriumSettings::FinalSupersample(uint i) { setValue(FINALSUPERSAMPLE, i); }
|
||||
|
||||
uint FractoriumSettings::FinalStrips() { return value(FINALSTRIPS).toUInt(); }
|
||||
void FractoriumSettings::FinalStrips(uint i) { setValue(FINALSTRIPS, i); }
|
||||
|
||||
/// <summary>
|
||||
/// Xml file saving settings.
|
||||
/// </summary>
|
||||
|
||||
uint FractoriumSettings::XmlTemporalSamples() { return value(XMLTEMPORALSAMPLES).toUInt(); }
|
||||
void FractoriumSettings::XmlTemporalSamples(uint i) { setValue(XMLTEMPORALSAMPLES, i); }
|
||||
uint FractoriumSettings::XmlTemporalSamples() { return value(XMLTEMPORALSAMPLES).toUInt(); }
|
||||
void FractoriumSettings::XmlTemporalSamples(uint i) { setValue(XMLTEMPORALSAMPLES, i); }
|
||||
|
||||
uint FractoriumSettings::XmlQuality() { return value(XMLQUALITY).toUInt(); }
|
||||
void FractoriumSettings::XmlQuality(uint i) { setValue(XMLQUALITY, i); }
|
||||
uint FractoriumSettings::XmlQuality() { return value(XMLQUALITY).toUInt(); }
|
||||
void FractoriumSettings::XmlQuality(uint i) { setValue(XMLQUALITY, i); }
|
||||
|
||||
uint FractoriumSettings::XmlSupersample() { return value(XMLSUPERSAMPLE).toUInt(); }
|
||||
void FractoriumSettings::XmlSupersample(uint i) { setValue(XMLSUPERSAMPLE, i); }
|
||||
uint FractoriumSettings::XmlSupersample() { return value(XMLSUPERSAMPLE).toUInt(); }
|
||||
void FractoriumSettings::XmlSupersample(uint i) { setValue(XMLSUPERSAMPLE, i); }
|
||||
|
||||
QString FractoriumSettings::Id() { return value(IDENTITYID).toString(); }
|
||||
void FractoriumSettings::Id(const QString& s) { setValue(IDENTITYID, s); }
|
||||
QString FractoriumSettings::Id() { return value(IDENTITYID).toString(); }
|
||||
void FractoriumSettings::Id(const QString& s) { setValue(IDENTITYID, s); }
|
||||
|
||||
QString FractoriumSettings::Url() { return value(IDENTITYURL).toString(); }
|
||||
void FractoriumSettings::Url(const QString& s) { setValue(IDENTITYURL, s); }
|
||||
QString FractoriumSettings::Url() { return value(IDENTITYURL).toString(); }
|
||||
void FractoriumSettings::Url(const QString& s) { setValue(IDENTITYURL, s); }
|
||||
|
||||
QString FractoriumSettings::Nick() { return value(IDENTITYNICK).toString(); }
|
||||
void FractoriumSettings::Nick(const QString& s) { setValue(IDENTITYNICK, s); }
|
||||
QString FractoriumSettings::Nick() { return value(IDENTITYNICK).toString(); }
|
||||
void FractoriumSettings::Nick(const QString& s) { setValue(IDENTITYNICK, s); }
|
||||
|
||||
/// <summary>
|
||||
/// General operations settings.
|
||||
/// </summary>
|
||||
|
||||
QString FractoriumSettings::OpenFolder() { return value(OPENFOLDER).toString(); }
|
||||
void FractoriumSettings::OpenFolder(const QString& s) { setValue(OPENFOLDER, s); }
|
||||
QString FractoriumSettings::OpenFolder() { return value(OPENFOLDER).toString(); }
|
||||
void FractoriumSettings::OpenFolder(const QString& s) { setValue(OPENFOLDER, s); }
|
||||
|
||||
QString FractoriumSettings::SaveFolder() { return value(SAVEFOLDER).toString(); }
|
||||
void FractoriumSettings::SaveFolder(const QString& s) { setValue(SAVEFOLDER, s); }
|
||||
QString FractoriumSettings::SaveFolder() { return value(SAVEFOLDER).toString(); }
|
||||
void FractoriumSettings::SaveFolder(const QString& s) { setValue(SAVEFOLDER, s); }
|
||||
|
||||
QString FractoriumSettings::OpenXmlExt() { return value(OPENXMLEXT).toString(); }
|
||||
void FractoriumSettings::OpenXmlExt(const QString& s) { setValue(OPENXMLEXT, s); }
|
||||
QString FractoriumSettings::OpenXmlExt() { return value(OPENXMLEXT).toString(); }
|
||||
void FractoriumSettings::OpenXmlExt(const QString& s) { setValue(OPENXMLEXT, s); }
|
||||
|
||||
QString FractoriumSettings::SaveXmlExt() { return value(SAVEXMLEXT).toString(); }
|
||||
void FractoriumSettings::SaveXmlExt(const QString& s) { setValue(SAVEXMLEXT, s); }
|
||||
QString FractoriumSettings::SaveXmlExt() { return value(SAVEXMLEXT).toString(); }
|
||||
void FractoriumSettings::SaveXmlExt(const QString& s) { setValue(SAVEXMLEXT, s); }
|
||||
|
||||
QString FractoriumSettings::OpenImageExt() { return value(OPENIMAGEEXT).toString(); }
|
||||
void FractoriumSettings::OpenImageExt(const QString& s) { setValue(OPENIMAGEEXT, s); }
|
||||
QString FractoriumSettings::OpenImageExt() { return value(OPENIMAGEEXT).toString(); }
|
||||
void FractoriumSettings::OpenImageExt(const QString& s) { setValue(OPENIMAGEEXT, s); }
|
||||
|
||||
QString FractoriumSettings::SaveImageExt() { return value(SAVEIMAGEEXT).toString(); }
|
||||
void FractoriumSettings::SaveImageExt(const QString& s) { setValue(SAVEIMAGEEXT, s); }
|
||||
QString FractoriumSettings::SaveImageExt() { return value(SAVEIMAGEEXT).toString(); }
|
||||
void FractoriumSettings::SaveImageExt(const QString& s) { setValue(SAVEIMAGEEXT, s); }
|
||||
|
||||
bool FractoriumSettings::SaveAutoUnique() { return value(AUTOUNIQUE).toBool(); }
|
||||
void FractoriumSettings::SaveAutoUnique(bool b) { setValue(AUTOUNIQUE, b); }
|
||||
bool FractoriumSettings::SaveAutoUnique() { return value(AUTOUNIQUE).toBool(); }
|
||||
void FractoriumSettings::SaveAutoUnique(bool b) { setValue(AUTOUNIQUE, b); }
|
||||
|
||||
QMap<QString, QVariant> FractoriumSettings::Variations() { return value(UIVARIATIONS).toMap(); }
|
||||
void FractoriumSettings::Variations(const QMap<QString, QVariant>& m) { setValue(UIVARIATIONS, m); }
|
||||
QMap<QString, QVariant> FractoriumSettings::Variations() { return value(UIVARIATIONS).toMap(); }
|
||||
void FractoriumSettings::Variations(const QMap<QString, QVariant>& m) { setValue(UIVARIATIONS, m); }
|
||||
|
@ -13,8 +13,7 @@
|
||||
#define DOUBLEPRECISION "render/dp64"
|
||||
#define CONTUPDATE "render/continuousupdate"
|
||||
#define SHOWALLXFORMS "render/dragshowallxforms"
|
||||
#define PLATFORMINDEX "render/platformindex"
|
||||
#define DEVICEINDEX "render/deviceindex"
|
||||
#define DEVICES "render/devices"
|
||||
#define THREADCOUNT "render/threadcount"
|
||||
#define CPUDEFILTER "render/cpudefilter"
|
||||
#define OPENCLDEFILTER "render/opencldefilter"
|
||||
@ -32,8 +31,7 @@
|
||||
#define FINALKEEPASPECT "finalrender/keepaspect"
|
||||
#define FINALSCALE "finalrender/scale"
|
||||
#define FINALEXT "finalrender/ext"
|
||||
#define FINALPLATFORMINDEX "finalrender/platformindex"
|
||||
#define FINALDEVICEINDEX "finalrender/deviceindex"
|
||||
#define FINALDEVICES "finalrender/devices"
|
||||
#define FINALTHREADCOUNT "finalrender/threadcount"
|
||||
#define FINALTHREADPRIORITY "finalrender/threadpriority"
|
||||
#define FINALQUALITY "finalrender/quality"
|
||||
@ -95,14 +93,11 @@ public:
|
||||
bool ContinuousUpdate();
|
||||
void ContinuousUpdate(bool b);
|
||||
|
||||
uint PlatformIndex();
|
||||
void PlatformIndex(uint b);
|
||||
|
||||
uint DeviceIndex();
|
||||
void DeviceIndex(uint b);
|
||||
QList<QVariant> Devices();
|
||||
void Devices(const QList<QVariant>& devices);
|
||||
|
||||
uint ThreadCount();
|
||||
void ThreadCount(uint b);
|
||||
void ThreadCount(uint i);
|
||||
|
||||
bool CpuDEFilter();
|
||||
void CpuDEFilter(bool b);
|
||||
@ -111,10 +106,10 @@ public:
|
||||
void OpenCLDEFilter(bool b);
|
||||
|
||||
uint CpuSubBatch();
|
||||
void CpuSubBatch(uint b);
|
||||
void CpuSubBatch(uint i);
|
||||
|
||||
uint OpenCLSubBatch();
|
||||
void OpenCLSubBatch(uint b);
|
||||
void OpenCLSubBatch(uint i);
|
||||
|
||||
bool FinalEarlyClip();
|
||||
void FinalEarlyClip(bool b);
|
||||
@ -149,16 +144,13 @@ public:
|
||||
QString FinalExt();
|
||||
void FinalExt(const QString& s);
|
||||
|
||||
uint FinalPlatformIndex();
|
||||
void FinalPlatformIndex(uint b);
|
||||
|
||||
uint FinalDeviceIndex();
|
||||
void FinalDeviceIndex(uint b);
|
||||
QList<QVariant> FinalDevices();
|
||||
void FinalDevices(const QList<QVariant>& devices);
|
||||
|
||||
uint FinalThreadCount();
|
||||
void FinalThreadCount(uint b);
|
||||
void FinalThreadCount(uint i);
|
||||
|
||||
uint FinalThreadPriority();
|
||||
int FinalThreadPriority();
|
||||
void FinalThreadPriority(int b);
|
||||
|
||||
uint FinalQuality();
|
||||
|
@ -79,7 +79,14 @@ void Fractorium::OnActionDP(bool checked)
|
||||
/// </summary>
|
||||
void Fractorium::SyncOptionsToToolbar()
|
||||
{
|
||||
if (m_Settings->OpenCL())
|
||||
static bool openCL = !OpenCLInfo::Instance().Devices().empty();
|
||||
|
||||
if (!openCL)
|
||||
{
|
||||
ui.ActionCL->setEnabled(false);
|
||||
}
|
||||
|
||||
if (openCL && m_Settings->OpenCL())
|
||||
{
|
||||
ui.ActionCpu->setChecked(false);
|
||||
ui.ActionCL->setChecked(true);
|
||||
|
@ -240,9 +240,9 @@ void FractoriumEmberController<T>::FillCurvesControl()
|
||||
{
|
||||
m_Fractorium->ui.CurvesView->blockSignals(true);
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
for (size_t i = 0; i < 4; i++)
|
||||
{
|
||||
for (int j = 1; j < 3; j++)//Only do middle points.
|
||||
for (size_t j = 1; j < 3; j++)//Only do middle points.
|
||||
{
|
||||
QPointF point(m_Ember.m_Curves.m_Points[i][j].x, m_Ember.m_Curves.m_Points[i][j].y);
|
||||
|
||||
@ -280,7 +280,7 @@ void FractoriumEmberController<T>::FillColorWithXform(Xform<T>* xform)
|
||||
/// <param name="col">The column of the cell</param>
|
||||
void Fractorium::SetPaletteTableItem(QPixmap* pixmap, QTableWidget* table, QTableWidgetItem* item, int row, int col)
|
||||
{
|
||||
if (pixmap)
|
||||
if (pixmap && !pixmap->isNull())
|
||||
{
|
||||
QSize size(table->columnWidth(col), table->rowHeight(row) + 1);
|
||||
item->setData(Qt::DecorationRole, pixmap->scaled(size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
|
||||
|
@ -50,7 +50,7 @@ void FractoriumEmberController<T>::Filter(const QString& text)
|
||||
|
||||
tree->setUpdatesEnabled(false);
|
||||
|
||||
for (uint i = 0; i < uint(tree->topLevelItemCount()); i++)
|
||||
for (int i = 0; i < tree->topLevelItemCount(); i++)
|
||||
{
|
||||
if (auto item = dynamic_cast<VariationTreeWidgetItem*>(tree->topLevelItem(i)))
|
||||
{
|
||||
@ -181,14 +181,14 @@ void FractoriumEmberController<T>::ClearVariationsTree()
|
||||
{
|
||||
QTreeWidget* tree = m_Fractorium->ui.VariationsTree;
|
||||
|
||||
for (uint i = 0; i < tree->topLevelItemCount(); i++)
|
||||
for (int i = 0; i < tree->topLevelItemCount(); i++)
|
||||
{
|
||||
QTreeWidgetItem* item = tree->topLevelItem(i);
|
||||
auto* spinBox = dynamic_cast<VariationTreeDoubleSpinBox*>(tree->itemWidget(item, 1));
|
||||
|
||||
spinBox->SetValueStealth(0);
|
||||
|
||||
for (uint j = 0; j < item->childCount(); j++)//Iterate through all of the children, which will be the params.
|
||||
for (int j = 0; j < item->childCount(); j++)//Iterate through all of the children, which will be the params.
|
||||
{
|
||||
if ((spinBox = dynamic_cast<VariationTreeDoubleSpinBox*>(tree->itemWidget(item->child(j), 1))))//Cast the child widget to the VariationTreeDoubleSpinBox type.
|
||||
spinBox->SetValueStealth(0);
|
||||
@ -301,7 +301,7 @@ void FractoriumEmberController<T>::FillVariationTreeWithXform(Xform<T>* xform)
|
||||
tree->blockSignals(true);
|
||||
m_Fractorium->Filter();
|
||||
|
||||
for (uint i = 0; i < tree->topLevelItemCount(); i++)
|
||||
for (int i = 0; i < tree->topLevelItemCount(); i++)
|
||||
{
|
||||
auto item = dynamic_cast<VariationTreeWidgetItem*>(tree->topLevelItem(i));
|
||||
auto var = xform->GetVariationById(item->Id());//See if this variation in the tree was contained in the xform.
|
||||
@ -317,7 +317,7 @@ void FractoriumEmberController<T>::FillVariationTreeWithXform(Xform<T>* xform)
|
||||
//item->setBackgroundColor(0, var ? Qt::darkGray : Qt::lightGray);//Ensure background is always white if the value goes to zero, else gray if var present.
|
||||
item->setBackgroundColor(0, var ? QColor(200, 200, 200) : QColor(255, 255, 255));//Ensure background is always white if the value goes to zero, else gray if var present.
|
||||
|
||||
for (uint j = 0; j < item->childCount(); j++)//Iterate through all of the children, which will be the params if it was a parametric variation.
|
||||
for (int j = 0; j < item->childCount(); j++)//Iterate through all of the children, which will be the params if it was a parametric variation.
|
||||
{
|
||||
T* param = nullptr;
|
||||
auto childItem = item->child(j);//Get the child.
|
||||
|
@ -252,13 +252,13 @@ void GLEmberController<T>::QueryMatrices(bool print)
|
||||
|
||||
if (print)
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
for (size_t i = 0; i < 4; i++)
|
||||
qDebug() << "Viewport[" << i << "] = " << m_Viewport[i] << endl;
|
||||
|
||||
for (int i = 0; i < 16; i++)
|
||||
for (size_t i = 0; i < 16; i++)
|
||||
qDebug() << "Modelview[" << i << "] = " << glm::value_ptr(m_Modelview)[i] << endl;
|
||||
|
||||
for (int i = 0; i < 16; i++)
|
||||
for (size_t i = 0; i < 16; i++)
|
||||
qDebug() << "Projection[" << i << "] = " << glm::value_ptr(m_Projection)[i] << endl;
|
||||
}
|
||||
}
|
||||
|
@ -313,7 +313,7 @@ void GLEmberController<T>::DrawAffines(bool pre, bool post)
|
||||
{
|
||||
if (pre && m_Fractorium->DrawAllPre())//Draw all pre affine if specified.
|
||||
{
|
||||
for (uint i = 0; i < ember->TotalXformCount(); i++)
|
||||
for (size_t i = 0; i < ember->TotalXformCount(); i++)
|
||||
{
|
||||
Xform<T>* xform = ember->GetTotalXform(i);
|
||||
bool selected = dragging ? (m_SelectedXform == xform) : (m_HoverXform == xform);
|
||||
@ -328,7 +328,7 @@ void GLEmberController<T>::DrawAffines(bool pre, bool post)
|
||||
|
||||
if (post && m_Fractorium->DrawAllPost())//Draw all post affine if specified.
|
||||
{
|
||||
for (uint i = 0; i < ember->TotalXformCount(); i++)
|
||||
for (size_t i = 0; i < ember->TotalXformCount(); i++)
|
||||
{
|
||||
Xform<T>* xform = ember->GetTotalXform(i);
|
||||
bool selected = dragging ? (m_SelectedXform == xform) : (m_HoverXform == xform);
|
||||
@ -1025,7 +1025,7 @@ void GLWidget::DrawAffineHelper(int index, bool selected, bool pre, bool final,
|
||||
|
||||
if (selected)
|
||||
{
|
||||
for (int i = 1; i <= 64; i++)//The circle.
|
||||
for (size_t i = 1; i <= 64; i++)//The circle.
|
||||
{
|
||||
float theta = float(M_PI) * 2.0f * float(i % 64) / 64.0f;
|
||||
float fx = float(cos(theta));
|
||||
@ -1100,7 +1100,7 @@ int GLEmberController<T>::UpdateHover(v3T& glCoords)
|
||||
}
|
||||
|
||||
//Check all xforms.
|
||||
for (uint i = 0; i < ember->TotalXformCount(); i++)
|
||||
for (size_t i = 0; i < ember->TotalXformCount(); i++)
|
||||
{
|
||||
Xform<T>* xform = ember->GetTotalXform(i);
|
||||
|
||||
|
@ -90,6 +90,10 @@ int main(int argc, char *argv[])
|
||||
a.installEventFilter(&w);
|
||||
rv = a.exec();
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
QMessageBox::critical(0, "Fatal Error", QString::fromStdString(e.what()));
|
||||
}
|
||||
catch (const char* e)
|
||||
{
|
||||
QMessageBox::critical(0, "Fatal Error", e);
|
||||
|
@ -9,17 +9,17 @@
|
||||
/// <param name="p">The parent widget. Default: nullptr.</param>
|
||||
/// <param name="f">The window flags. Default: 0.</param>
|
||||
FractoriumOptionsDialog::FractoriumOptionsDialog(FractoriumSettings* settings, QWidget* p, Qt::WindowFlags f)
|
||||
: QDialog(p, f)
|
||||
: QDialog(p, f),
|
||||
m_Info(OpenCLInfo::Instance())
|
||||
{
|
||||
int row = 0, spinHeight = 20;
|
||||
uint i;
|
||||
int i, row = 0, spinHeight = 20;
|
||||
|
||||
ui.setupUi(this);
|
||||
m_Settings = settings;
|
||||
QTableWidget* table = ui.OptionsXmlSavingTable;
|
||||
ui.ThreadCountSpin->setRange(1, Timing::ProcessorCount());
|
||||
connect(ui.OpenCLCheckBox, SIGNAL(stateChanged(int)), this, SLOT(OnOpenCLCheckBoxStateChanged(int)), Qt::QueuedConnection);
|
||||
connect(ui.PlatformCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(OnPlatformComboCurrentIndexChanged(int)), Qt::QueuedConnection);
|
||||
connect(ui.OpenCLCheckBox, SIGNAL(stateChanged(int)), this, SLOT(OnOpenCLCheckBoxStateChanged(int)), Qt::QueuedConnection);
|
||||
connect(ui.DeviceTable, SIGNAL(cellChanged(int, int)), this, SLOT(OnDeviceTableCellChanged(int, int)), Qt::QueuedConnection);
|
||||
|
||||
SetupSpinner<SpinBox, int>(table, this, row, 1, m_XmlTemporalSamplesSpin, spinHeight, 1, 1000, 100, "", "", true, 1000);
|
||||
SetupSpinner<SpinBox, int>(table, this, row, 1, m_XmlQualitySpin, spinHeight, 1, 200000, 50, "", "", true, 1000);
|
||||
@ -34,63 +34,28 @@ FractoriumOptionsDialog::FractoriumOptionsDialog(FractoriumSettings* settings, Q
|
||||
m_NickEdit = new QLineEdit(ui.OptionsIdentityTable);
|
||||
ui.OptionsIdentityTable->setCellWidget(2, 1, m_NickEdit);
|
||||
|
||||
m_IdEdit->setText(m_Settings->Id());
|
||||
m_UrlEdit->setText(m_Settings->Url());
|
||||
m_NickEdit->setText(m_Settings->Nick());
|
||||
table = ui.DeviceTable;
|
||||
|
||||
if (m_Wrapper.CheckOpenCL())
|
||||
if (m_Info.Ok() && !m_Info.Devices().empty())
|
||||
{
|
||||
vector<string> platforms = m_Wrapper.PlatformNames();
|
||||
SetupDeviceTable(table, m_Settings->Devices());
|
||||
|
||||
//Populate combo boxes with available OpenCL platforms and devices.
|
||||
for (i = 0; i < platforms.size(); i++)
|
||||
ui.PlatformCombo->addItem(QString::fromStdString(platforms[i]));
|
||||
|
||||
//If init succeeds, set the selected platform and device combos to match what was saved in the settings.
|
||||
if (m_Wrapper.Init(m_Settings->PlatformIndex(), m_Settings->DeviceIndex()))
|
||||
{
|
||||
ui.OpenCLCheckBox->setChecked( m_Settings->OpenCL());
|
||||
ui.PlatformCombo->setCurrentIndex(m_Settings->PlatformIndex());
|
||||
ui.DeviceCombo->setCurrentIndex( m_Settings->DeviceIndex());
|
||||
}
|
||||
else
|
||||
{
|
||||
OnPlatformComboCurrentIndexChanged(0);
|
||||
ui.OpenCLCheckBox->setChecked(false);
|
||||
}
|
||||
for (i = 0; i < table->rowCount(); i++)
|
||||
if (auto radio = qobject_cast<QRadioButton*>(table->cellWidget(i, 1)))
|
||||
connect(radio, SIGNAL(toggled(bool)), this, SLOT(OnDeviceTableRadioToggled(bool)), Qt::QueuedConnection);
|
||||
}
|
||||
else
|
||||
{
|
||||
ui.DeviceTable->setEnabled(false);
|
||||
ui.OpenCLCheckBox->setChecked(false);
|
||||
ui.OpenCLCheckBox->setEnabled(false);
|
||||
ui.OpenCLSubBatchSpin->setEnabled(false);
|
||||
ui.OpenCLFilteringDERadioButton->setEnabled(false);
|
||||
ui.OpenCLFilteringLogRadioButton->setEnabled(false);
|
||||
ui.InteraciveGpuFilteringGroupBox->setEnabled(false);
|
||||
}
|
||||
|
||||
ui.EarlyClipCheckBox->setChecked( m_Settings->EarlyClip());
|
||||
ui.YAxisUpCheckBox->setChecked( m_Settings->YAxisUp());
|
||||
ui.TransparencyCheckBox->setChecked( m_Settings->Transparency());
|
||||
ui.ContinuousUpdateCheckBox->setChecked(m_Settings->ContinuousUpdate());
|
||||
ui.DoublePrecisionCheckBox->setChecked( m_Settings->Double());
|
||||
ui.ShowAllXformsCheckBox->setChecked( m_Settings->ShowAllXforms());
|
||||
ui.ThreadCountSpin->setValue( m_Settings->ThreadCount());
|
||||
|
||||
if (m_Settings->CpuDEFilter())
|
||||
ui.CpuFilteringDERadioButton->setChecked(true);
|
||||
else
|
||||
ui.CpuFilteringLogRadioButton->setChecked(true);
|
||||
|
||||
if (m_Settings->OpenCLDEFilter())
|
||||
ui.OpenCLFilteringDERadioButton->setChecked(true);
|
||||
else
|
||||
ui.OpenCLFilteringLogRadioButton->setChecked(true);
|
||||
|
||||
ui.CpuSubBatchSpin->setValue(m_Settings->CpuSubBatch());
|
||||
ui.OpenCLSubBatchSpin->setValue(m_Settings->OpenCLSubBatch());
|
||||
|
||||
m_XmlTemporalSamplesSpin->setValue(m_Settings->XmlTemporalSamples());
|
||||
m_XmlQualitySpin->setValue(m_Settings->XmlQuality());
|
||||
m_XmlSupersampleSpin->setValue(m_Settings->XmlSupersample());
|
||||
ui.AutoUniqueCheckBox->setChecked(m_Settings->SaveAutoUnique());
|
||||
|
||||
DataToGui();
|
||||
OnOpenCLCheckBoxStateChanged(ui.OpenCLCheckBox->isChecked());
|
||||
}
|
||||
|
||||
@ -106,12 +71,48 @@ bool FractoriumOptionsDialog::OpenCL() { return ui.OpenCLCheckBox->isChecked();
|
||||
bool FractoriumOptionsDialog::Double() { return ui.DoublePrecisionCheckBox->isChecked(); }
|
||||
bool FractoriumOptionsDialog::ShowAllXforms() { return ui.ShowAllXformsCheckBox->isChecked(); }
|
||||
bool FractoriumOptionsDialog::AutoUnique() { return ui.AutoUniqueCheckBox->isChecked(); }
|
||||
uint FractoriumOptionsDialog::PlatformIndex() { return ui.PlatformCombo->currentIndex(); }
|
||||
uint FractoriumOptionsDialog::DeviceIndex() { return ui.DeviceCombo->currentIndex(); }
|
||||
uint FractoriumOptionsDialog::ThreadCount() { return ui.ThreadCountSpin->value(); }
|
||||
|
||||
/// <summary>
|
||||
/// Disable or enable the OpenCL related controls based on the state passed in.
|
||||
/// The check state of one of the OpenCL devices was changed.
|
||||
/// This does a special check to always ensure at least one device,
|
||||
/// as well as one primary is checked.
|
||||
/// </summary>
|
||||
/// <param name="row">The row of the cell</param>
|
||||
/// <param name="col">The column of the cell</param>
|
||||
void FractoriumOptionsDialog::OnDeviceTableCellChanged(int row, int col)
|
||||
{
|
||||
if (auto item = ui.DeviceTable->item(row, col))
|
||||
HandleDeviceTableCheckChanged(ui.DeviceTable, row, col);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The primary device radio button selection was changed.
|
||||
/// If the device was specified as primary, but was not selected
|
||||
/// for inclusion, it will automatically be selected for inclusion.
|
||||
/// </summary>
|
||||
/// <param name="checked">The state of the radio button</param>
|
||||
void FractoriumOptionsDialog::OnDeviceTableRadioToggled(bool checked)
|
||||
{
|
||||
int row;
|
||||
auto s = sender();
|
||||
auto table = ui.DeviceTable;
|
||||
QRadioButton* radio = nullptr;
|
||||
|
||||
if (s)
|
||||
{
|
||||
for (row = 0; row < table->rowCount(); row++)
|
||||
if (radio = qobject_cast<QRadioButton*>(table->cellWidget(row, 1)))
|
||||
if (s == radio)
|
||||
{
|
||||
HandleDeviceTableCheckChanged(ui.DeviceTable, row, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disable or enable the CPU and OpenCL related controls based on the state passed in.
|
||||
/// Called when the state of the OpenCL checkbox is changed.
|
||||
/// </summary>
|
||||
/// <param name="state">The state of the checkbox</param>
|
||||
@ -119,28 +120,15 @@ void FractoriumOptionsDialog::OnOpenCLCheckBoxStateChanged(int state)
|
||||
{
|
||||
bool checked = state == Qt::Checked;
|
||||
|
||||
ui.PlatformCombo->setEnabled(checked);
|
||||
ui.DeviceCombo->setEnabled(checked);
|
||||
ui.DeviceTable->setEnabled(checked);
|
||||
ui.ThreadCountSpin->setEnabled(!checked);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Populate the the device combo box with all available
|
||||
/// OpenCL devices for the selected platform.
|
||||
/// Called when the platform combo box index changes.
|
||||
/// </summary>
|
||||
/// <param name="index">The selected index of the combo box</param>
|
||||
void FractoriumOptionsDialog::OnPlatformComboCurrentIndexChanged(int index)
|
||||
{
|
||||
vector<string> devices = m_Wrapper.DeviceNames(index);
|
||||
|
||||
ui.DeviceCombo->clear();
|
||||
|
||||
for (auto& device : devices)
|
||||
ui.DeviceCombo->addItem(QString::fromStdString(device));
|
||||
|
||||
if (ui.PlatformCombo->currentIndex() == m_Settings->PlatformIndex())
|
||||
ui.DeviceCombo->setCurrentIndex(m_Settings->DeviceIndex());
|
||||
ui.CpuSubBatchSpin->setEnabled(!checked);
|
||||
ui.OpenCLSubBatchSpin->setEnabled(checked);
|
||||
ui.CpuFilteringDERadioButton->setEnabled(!checked);
|
||||
ui.CpuFilteringLogRadioButton->setEnabled(!checked);
|
||||
ui.OpenCLFilteringDERadioButton->setEnabled(checked);
|
||||
ui.OpenCLFilteringLogRadioButton->setEnabled(checked);
|
||||
ui.InteraciveGpuFilteringGroupBox->setEnabled(checked);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -187,13 +175,12 @@ void FractoriumOptionsDialog::GuiToData()
|
||||
m_Settings->OpenCL(OpenCL());
|
||||
m_Settings->Double(Double());
|
||||
m_Settings->ShowAllXforms(ShowAllXforms());
|
||||
m_Settings->PlatformIndex(PlatformIndex());
|
||||
m_Settings->DeviceIndex(DeviceIndex());
|
||||
m_Settings->ThreadCount(ThreadCount());
|
||||
m_Settings->CpuSubBatch(ui.CpuSubBatchSpin->value());
|
||||
m_Settings->OpenCLSubBatch(ui.OpenCLSubBatchSpin->value());
|
||||
m_Settings->CpuDEFilter(ui.CpuFilteringDERadioButton->isChecked());
|
||||
m_Settings->OpenCLDEFilter(ui.OpenCLFilteringDERadioButton->isChecked());
|
||||
m_Settings->Devices(DeviceTableToSettings(ui.DeviceTable));
|
||||
|
||||
//Xml saving.
|
||||
m_Settings->XmlTemporalSamples(m_XmlTemporalSamplesSpin->value());
|
||||
@ -213,6 +200,8 @@ void FractoriumOptionsDialog::GuiToData()
|
||||
void FractoriumOptionsDialog::DataToGui()
|
||||
{
|
||||
//Interactive rendering.
|
||||
auto devices = m_Settings->Devices();
|
||||
|
||||
ui.EarlyClipCheckBox->setChecked(m_Settings->EarlyClip());
|
||||
ui.YAxisUpCheckBox->setChecked(m_Settings->YAxisUp());
|
||||
ui.TransparencyCheckBox->setChecked(m_Settings->Transparency());
|
||||
@ -220,13 +209,20 @@ void FractoriumOptionsDialog::DataToGui()
|
||||
ui.OpenCLCheckBox->setChecked(m_Settings->OpenCL());
|
||||
ui.DoublePrecisionCheckBox->setChecked(m_Settings->Double());
|
||||
ui.ShowAllXformsCheckBox->setChecked(m_Settings->ShowAllXforms());
|
||||
ui.PlatformCombo->setCurrentIndex(m_Settings->PlatformIndex());
|
||||
ui.DeviceCombo->setCurrentIndex(m_Settings->DeviceIndex());
|
||||
ui.ThreadCountSpin->setValue(m_Settings->ThreadCount());
|
||||
ui.CpuSubBatchSpin->setValue(m_Settings->CpuSubBatch());
|
||||
ui.OpenCLSubBatchSpin->setValue(m_Settings->OpenCLSubBatch());
|
||||
ui.CpuFilteringDERadioButton->setChecked(m_Settings->CpuDEFilter());
|
||||
ui.OpenCLFilteringDERadioButton->setChecked(m_Settings->OpenCLDEFilter());
|
||||
SettingsToDeviceTable(ui.DeviceTable, devices);
|
||||
|
||||
if (m_Settings->CpuDEFilter())
|
||||
ui.CpuFilteringDERadioButton->setChecked(true);
|
||||
else
|
||||
ui.CpuFilteringLogRadioButton->setChecked(true);
|
||||
|
||||
if (m_Settings->OpenCLDEFilter())
|
||||
ui.OpenCLFilteringDERadioButton->setChecked(true);
|
||||
else
|
||||
ui.OpenCLFilteringLogRadioButton->setChecked(true);
|
||||
|
||||
//Xml saving.
|
||||
m_XmlTemporalSamplesSpin->setValue(m_Settings->XmlTemporalSamples());
|
||||
@ -238,4 +234,4 @@ void FractoriumOptionsDialog::DataToGui()
|
||||
m_IdEdit->setText(m_Settings->Id());
|
||||
m_UrlEdit->setText(m_Settings->Url());
|
||||
m_NickEdit->setText(m_Settings->Nick());
|
||||
}
|
||||
}
|
||||
|
@ -28,7 +28,8 @@ public:
|
||||
|
||||
public slots:
|
||||
void OnOpenCLCheckBoxStateChanged(int state);
|
||||
void OnPlatformComboCurrentIndexChanged(int index);
|
||||
void OnDeviceTableCellChanged(int row, int col);
|
||||
void OnDeviceTableRadioToggled(bool checked);
|
||||
virtual void accept() override;
|
||||
virtual void reject() override;
|
||||
|
||||
@ -45,14 +46,12 @@ private:
|
||||
bool Double();
|
||||
bool ShowAllXforms();
|
||||
bool AutoUnique();
|
||||
uint PlatformIndex();
|
||||
uint DeviceIndex();
|
||||
uint ThreadCount();
|
||||
void DataToGui();
|
||||
void GuiToData();
|
||||
|
||||
Ui::OptionsDialog ui;
|
||||
OpenCLWrapper m_Wrapper;
|
||||
OpenCLInfo& m_Info;
|
||||
SpinBox* m_XmlTemporalSamplesSpin;
|
||||
SpinBox* m_XmlQualitySpin;
|
||||
SpinBox* m_XmlSupersampleSpin;
|
||||
|
@ -6,31 +6,34 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>300</width>
|
||||
<height>368</height>
|
||||
<width>427</width>
|
||||
<height>415</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>300</width>
|
||||
<height>368</height>
|
||||
<width>427</width>
|
||||
<height>415</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>300</width>
|
||||
<height>368</height>
|
||||
<width>16777215</width>
|
||||
<height>415</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Options</string>
|
||||
</property>
|
||||
<property name="sizeGripEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
@ -72,6 +75,9 @@
|
||||
<string>Interactive Rendering</string>
|
||||
</attribute>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<property name="fieldGrowthPolicy">
|
||||
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
|
||||
</property>
|
||||
<property name="verticalSpacing">
|
||||
<number>4</number>
|
||||
</property>
|
||||
@ -103,6 +109,36 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QCheckBox" name="OpenCLCheckBox">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Use OpenCL to render if your video card supports it.</p><p>This is highly recommended as it will give fluid, real-time interactive editing.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Use OpenCL</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="YAxisUpCheckBox">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Checked: Positive Y direction is up.</p><p>Unchecked: Positive Y direction is down.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Positive Y Up</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QCheckBox" name="DoublePrecisionCheckBox">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Checked: use 64-bit double precision numbers (slower, but better image quality).</p><p>Unchecked: use 32-bit single precision numbers (faster, but worse image quality).</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Use Double Precision</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QCheckBox" name="TransparencyCheckBox">
|
||||
<property name="toolTip">
|
||||
@ -113,13 +149,115 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QCheckBox" name="ShowAllXformsCheckBox">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Checked: show all xforms while dragging.</p><p>Unchecked: only show current xform while dragging.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Show All Xforms</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QCheckBox" name="ContinuousUpdateCheckBox">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Continually update output image during interactive rendering.</p><p>This will slow down performance, but will give continuous updates on how the final render will look. Note that only log scale filtering is applied on each update. Full DE is not applied until iteration is complete.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Continuous Update</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0" colspan="2">
|
||||
<widget class="QComboBox" name="PlatformCombo"/>
|
||||
<widget class="QTableWidget" name="DeviceTable">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>91</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>91</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::NoEditTriggers</set>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::NoSelection</enum>
|
||||
</property>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
</property>
|
||||
<property name="showGrid">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="columnCount">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<attribute name="horizontalHeaderDefaultSectionSize">
|
||||
<number>60</number>
|
||||
</attribute>
|
||||
<attribute name="horizontalHeaderStretchLastSection">
|
||||
<bool>true</bool>
|
||||
</attribute>
|
||||
<attribute name="verticalHeaderVisible">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<attribute name="verticalHeaderDefaultSectionSize">
|
||||
<number>22</number>
|
||||
</attribute>
|
||||
<attribute name="verticalHeaderHighlightSections">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<attribute name="verticalHeaderMinimumSectionSize">
|
||||
<number>22</number>
|
||||
</attribute>
|
||||
<row>
|
||||
<property name="text">
|
||||
<string>AMD</string>
|
||||
</property>
|
||||
</row>
|
||||
<row>
|
||||
<property name="text">
|
||||
<string>Nvidia</string>
|
||||
</property>
|
||||
</row>
|
||||
<row>
|
||||
<property name="text">
|
||||
<string>Intel</string>
|
||||
</property>
|
||||
</row>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Use</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Primary</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Device</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0" colspan="2">
|
||||
<widget class="QComboBox" name="DeviceCombo"/>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<item row="7" column="0">
|
||||
<widget class="QSpinBox" name="ThreadCountSpin">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The number of threads to use with CPU rendering.</p><p>Decrease for more responsive editing, increase for better performance.</p></body></html></string>
|
||||
@ -135,7 +273,41 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="0">
|
||||
<item row="8" column="0">
|
||||
<widget class="QSpinBox" name="CpuSubBatchSpin">
|
||||
<property name="toolTip">
|
||||
<string>The number of 10,000 iteration chunks ran per thread on the CPU
|
||||
in interactive mode for each mouse movement</string>
|
||||
</property>
|
||||
<property name="prefix">
|
||||
<string>CPU Sub Batch </string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="0">
|
||||
<widget class="QSpinBox" name="OpenCLSubBatchSpin">
|
||||
<property name="toolTip">
|
||||
<string>The number of ~8M iteration chunks ran using OpenCL
|
||||
in interactive mode for each mouse movement</string>
|
||||
</property>
|
||||
<property name="prefix">
|
||||
<string>OpenCL Sub Batch </string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="0">
|
||||
<widget class="QGroupBox" name="InteraciveCpuFilteringGroupBox">
|
||||
<property name="title">
|
||||
<string>CPU Filtering</string>
|
||||
@ -182,7 +354,7 @@
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="0">
|
||||
<item row="11" column="0">
|
||||
<widget class="QGroupBox" name="InteraciveGpuFilteringGroupBox">
|
||||
<property name="title">
|
||||
<string>OpenCL Filtering</string>
|
||||
@ -226,90 +398,6 @@
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="0">
|
||||
<widget class="QSpinBox" name="CpuSubBatchSpin">
|
||||
<property name="toolTip">
|
||||
<string>The number of 10,000 iteration chunks ran per thread on the CPU
|
||||
in interactive mode for each mouse movement</string>
|
||||
</property>
|
||||
<property name="prefix">
|
||||
<string>CPU Sub Batch </string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="0">
|
||||
<widget class="QSpinBox" name="OpenCLSubBatchSpin">
|
||||
<property name="toolTip">
|
||||
<string>The number of ~8M iteration chunks ran using OpenCL
|
||||
in interactive mode for each mouse movement</string>
|
||||
</property>
|
||||
<property name="prefix">
|
||||
<string>OpenCL Sub Batch </string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="YAxisUpCheckBox">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Checked: Positive Y direction is up.</p><p>Unchecked: Positive Y direction is down.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Positive Y Up</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QCheckBox" name="OpenCLCheckBox">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Use OpenCL to render if your video card supports it.</p><p>This is highly recommended as it will give fluid, real-time interactive editing.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Use OpenCL</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QCheckBox" name="DoublePrecisionCheckBox">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Checked: use 64-bit double precision numbers (slower, but better image quality).</p><p>Unchecked: use 32-bit single precision numbers (faster, but worse image quality).</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Use Double Precision</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QCheckBox" name="ShowAllXformsCheckBox">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Checked: show all xforms while dragging.</p><p>Unchecked: only show current xform while dragging.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Show All Xforms</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QCheckBox" name="ContinuousUpdateCheckBox">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Continually update output image during interactive rendering.</p><p>This will slow down performance, but will give continuous updates on how the final render will look. Note that only log scale filtering is applied on each update. Full DE is not applied until iteration is complete.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Continuous Update</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="OptionsXmlSavingTab">
|
||||
@ -732,8 +820,6 @@ in interactive mode for each mouse movement</string>
|
||||
<tabstop>TransparencyCheckBox</tabstop>
|
||||
<tabstop>ShowAllXformsCheckBox</tabstop>
|
||||
<tabstop>ContinuousUpdateCheckBox</tabstop>
|
||||
<tabstop>PlatformCombo</tabstop>
|
||||
<tabstop>DeviceCombo</tabstop>
|
||||
<tabstop>ThreadCountSpin</tabstop>
|
||||
<tabstop>CpuSubBatchSpin</tabstop>
|
||||
<tabstop>OpenCLSubBatchSpin</tabstop>
|
||||
|
Reference in New Issue
Block a user