mirror of
https://bitbucket.org/mfeemster/fractorium.git
synced 2025-01-21 21:20:07 -05:00
Report memory required in final render dialog.
Fix broken state of ember during failed render with strips.
This commit is contained in:
parent
9263906cb5
commit
3e70b8eec6
@ -1,3 +1,15 @@
|
||||
--User changes
|
||||
Use actual strips count when computing memory requirements in the final render dialog.
|
||||
Output CL_DEVICE_ADDRESS_BITS when passing --openclinfo to command line programs.
|
||||
Warn if single/total allocations are greater than the max allowed for OpenCL in the final render dialog.
|
||||
|
||||
--Bug Fixes
|
||||
Fix bad values left in an ember when a render with strips > 1 fails in the final render dialog.
|
||||
|
||||
--Code Changes
|
||||
Break RendererBase::MemoryRequired() into two functions, it and HistMemRequired() and return a tuple.
|
||||
Add GlobalMemSize() and MaxAllocSize() functions in OpenCLWrapper.
|
||||
|
||||
0.4.1.6 Beta 11/29/2014
|
||||
--User Changes
|
||||
None.
|
||||
|
@ -116,12 +116,10 @@ void RendererBase::ChangeVal(std::function<void(void)> func, eProcessAction acti
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the amount of memory needed to render the current ember.
|
||||
/// Optionally include the memory needed for the final output image.
|
||||
/// Return the amount of memory needed for the histogram.
|
||||
/// </summary>
|
||||
/// <param name="includeFinal">If true include the memory needed for the final output image, else don't.</param>
|
||||
/// <returns>The memory required to render the current ember</returns>
|
||||
size_t RendererBase::MemoryRequired(size_t strips, bool includeFinal)
|
||||
/// <returns>The memory required for the histogram to render the current ember</returns>
|
||||
size_t RendererBase::HistMemoryRequired(size_t strips)
|
||||
{
|
||||
bool newFilterAlloc = false;
|
||||
|
||||
@ -130,9 +128,24 @@ size_t RendererBase::MemoryRequired(size_t strips, bool includeFinal)
|
||||
ComputeBounds();
|
||||
|
||||
//Because ComputeBounds() was called, this includes gutter.
|
||||
size_t histSize = (SuperSize() * HistBucketSize()) / strips;
|
||||
return (SuperSize() * HistBucketSize()) / strips;
|
||||
}
|
||||
|
||||
return (histSize * 2) + (includeFinal ? FinalBufferSize() : 0);//Multiply hist by 2 to account for the density filtering buffer which is the same size as the histogram.
|
||||
/// <summary>
|
||||
/// Return a pair whose first member contains the amount of memory needed for the histogram,
|
||||
/// and whose second member contains the total the amount of memory needed to render the current ember.
|
||||
/// Optionally include the memory needed for the final output image in pair.second.
|
||||
/// </summary>
|
||||
/// <param name="includeFinal">If true include the memory needed for the final output image, else don't.</param>
|
||||
/// <returns>The histogram memory required in first, and the total memory required in second</returns>
|
||||
pair<size_t, size_t> RendererBase::MemoryRequired(size_t strips, bool includeFinal)
|
||||
{
|
||||
pair<size_t, size_t> p;
|
||||
|
||||
p.first = HistMemoryRequired(strips);
|
||||
p.second = (p.first * 2) + (includeFinal ? FinalBufferSize() : 0);//Multiply hist by 2 to account for the density filtering buffer which is the same size as the histogram.
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -98,7 +98,8 @@ public:
|
||||
|
||||
//Non-virtual processing functions.
|
||||
void ChangeVal(std::function<void(void)> func, eProcessAction action);
|
||||
size_t MemoryRequired(size_t strips, bool includeFinal);
|
||||
size_t HistMemoryRequired(size_t strips);
|
||||
pair<size_t, size_t> MemoryRequired(size_t strips, bool includeFinal);
|
||||
vector<QTIsaac<ISAAC_SIZE, ISAAC_INT>> RandVec();
|
||||
bool PrepFinalAccumVector(vector<byte>& pixels);
|
||||
|
||||
|
@ -554,13 +554,13 @@ int OpenCLWrapper::FindImageIndex(const string& name, bool shared)
|
||||
{
|
||||
for (size_t i = 0; i < m_GLImages.size(); i++)
|
||||
if (m_GLImages[i].m_Name == name)
|
||||
return i;
|
||||
return int(i);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (size_t i = 0; i < m_Images.size(); i++)
|
||||
if (m_Images[i].m_Name == name)
|
||||
return i;
|
||||
return int(i);
|
||||
}
|
||||
|
||||
return -1;
|
||||
@ -966,7 +966,7 @@ bool OpenCLWrapper::RunKernel(uint kernelIndex, uint totalGridWidth, uint totalG
|
||||
/// <param name="name">The device field/feature to query</param>
|
||||
/// <returns>The value of the field</returns>
|
||||
template<typename T>
|
||||
T OpenCLWrapper::GetInfo(size_t platform, size_t device, cl_device_info name)
|
||||
T OpenCLWrapper::GetInfo(size_t platform, size_t device, cl_device_info name) const
|
||||
{
|
||||
T val;
|
||||
|
||||
@ -1094,6 +1094,7 @@ string OpenCLWrapper::DumpInfo()
|
||||
os << "CL_DEVICE_MAX_READ_IMAGE_ARGS: " << GetInfo<cl_uint> (platform, device, CL_DEVICE_MAX_READ_IMAGE_ARGS) << endl;
|
||||
os << "CL_DEVICE_MAX_WRITE_IMAGE_ARGS: " << GetInfo<cl_uint> (platform, device, CL_DEVICE_MAX_WRITE_IMAGE_ARGS) << endl;
|
||||
os << "CL_DEVICE_MAX_MEM_ALLOC_SIZE: " << GetInfo<cl_ulong>(platform, device, CL_DEVICE_MAX_MEM_ALLOC_SIZE) << endl;
|
||||
os << "CL_DEVICE_ADDRESS_BITS: " << GetInfo<cl_uint> (platform, device, CL_DEVICE_ADDRESS_BITS) << endl;
|
||||
|
||||
os << "CL_DEVICE_GLOBAL_MEM_CACHE_TYPE: " << GetInfo<cl_uint> (platform, device, CL_DEVICE_GLOBAL_MEM_CACHE_TYPE) << endl;
|
||||
os << "CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE: " << GetInfo<cl_uint> (platform, device, CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE) << endl;
|
||||
@ -1126,7 +1127,9 @@ bool OpenCLWrapper::Shared() const { return m_Shared; }
|
||||
cl::Context OpenCLWrapper::Context() const { return m_Context; }
|
||||
uint OpenCLWrapper::PlatformIndex() const { return m_PlatformIndex; }
|
||||
uint OpenCLWrapper::DeviceIndex() const { return m_DeviceIndex; }
|
||||
size_t OpenCLWrapper::GlobalMemSize() const { return GetInfo<cl_ulong>(PlatformIndex(), DeviceIndex(), CL_DEVICE_GLOBAL_MEM_SIZE); }
|
||||
uint OpenCLWrapper::LocalMemSize() const { return m_LocalMemSize; }
|
||||
size_t OpenCLWrapper::MaxAllocSize() const { return GetInfo<cl_ulong>(PlatformIndex(), DeviceIndex(), CL_DEVICE_MAX_MEM_ALLOC_SIZE); }
|
||||
|
||||
/// <summary>
|
||||
/// Makes the even grid dims.
|
||||
|
@ -175,7 +175,7 @@ public:
|
||||
|
||||
//Info.
|
||||
template<typename T>
|
||||
T GetInfo(size_t platform, size_t device, cl_device_info name);
|
||||
T GetInfo(size_t platform, size_t device, cl_device_info name) const;
|
||||
string PlatformName(size_t platform);
|
||||
vector<string> PlatformNames();
|
||||
string DeviceName(size_t platform, size_t device);
|
||||
@ -190,6 +190,8 @@ public:
|
||||
uint PlatformIndex() const;
|
||||
uint DeviceIndex() const;
|
||||
uint LocalMemSize() const;
|
||||
size_t GlobalMemSize() const;
|
||||
size_t MaxAllocSize() const;
|
||||
|
||||
static void MakeEvenGridDims(uint blockW, uint blockH, uint& gridW, uint& gridH);
|
||||
|
||||
|
@ -281,7 +281,7 @@ static bool StripsRender(RendererBase* renderer, Ember<T>& ember, vector<byte>&
|
||||
std::function<void(size_t strip)> perStripError,
|
||||
std::function<void(Ember<T>& finalEmber)> allStripsFinished)
|
||||
{
|
||||
bool success = true;
|
||||
bool success = false;
|
||||
size_t origHeight, realHeight = ember.m_FinalRasH;
|
||||
T centerY = ember.m_CenterY;
|
||||
T floatStripH = T(ember.m_FinalRasH) / T(strips);
|
||||
@ -321,32 +321,29 @@ static bool StripsRender(RendererBase* renderer, Ember<T>& ember, vector<byte>&
|
||||
renderer->SetEmber(ember);//Set one final time after modifications for strips.
|
||||
}
|
||||
|
||||
if ((renderer->Run(finalImage, time, 0, false, stripOffset) != RENDER_OK) || renderer->Aborted() || finalImage.empty())
|
||||
{
|
||||
perStripError(strip);
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
else
|
||||
if ((renderer->Run(finalImage, time, 0, false, stripOffset) == RENDER_OK) && !renderer->Aborted() && !finalImage.empty())
|
||||
{
|
||||
perStripFinish(strip);
|
||||
}
|
||||
else
|
||||
{
|
||||
perStripError(strip);
|
||||
break;
|
||||
}
|
||||
|
||||
if (strip == strips - 1)
|
||||
{
|
||||
//Restore the ember values to their original values.
|
||||
if (strips > 1)
|
||||
{
|
||||
ember.m_Quality /= strips;
|
||||
ember.m_FinalRasH = realHeight;
|
||||
ember.m_CenterY = centerY;
|
||||
renderer->SetEmber(ember);//Further processing will require the dimensions to match the original ember, so re-assign.
|
||||
}
|
||||
|
||||
allStripsFinished(ember);
|
||||
}
|
||||
success = true;
|
||||
}
|
||||
|
||||
//Restore the ember values to their original values.
|
||||
ember.m_Quality /= strips;
|
||||
ember.m_FinalRasH = realHeight;
|
||||
ember.m_CenterY = centerY;
|
||||
renderer->SetEmber(ember);//Further processing will require the dimensions to match the original ember, so re-assign.
|
||||
|
||||
if (success)
|
||||
allStripsFinished(ember);
|
||||
|
||||
Memset(finalImage);
|
||||
|
||||
return success;
|
||||
|
@ -330,6 +330,7 @@ int _tmain(int argc, _TCHAR* argv[])
|
||||
//This must be done in the application and not in the EmberCL DLL.
|
||||
#ifdef WIN32
|
||||
_putenv_s("GPU_MAX_ALLOC_PERCENT", "100");
|
||||
//_putenv_s("GPU_FORCE_64BIT_PTR", "1");
|
||||
#else
|
||||
putenv(const_cast<char*>("GPU_MAX_ALLOC_PERCENT=100"));
|
||||
#endif
|
||||
|
@ -708,10 +708,48 @@ bool FractoriumFinalRenderDialog::SetMemory()
|
||||
{
|
||||
if (isVisible() && CreateControllerFromGUI(true))
|
||||
{
|
||||
pair<size_t, size_t> p = m_Controller->SyncAndComputeMemory();
|
||||
bool error = false;
|
||||
tuple<size_t, size_t, size_t> p = m_Controller->SyncAndComputeMemory();
|
||||
|
||||
ui.FinalRenderParamsTable->item(m_MemoryCellIndex, 1)->setText(ToString(get<1>(p)));
|
||||
ui.FinalRenderParamsTable->item(m_ItersCellIndex, 1)->setText(ToString(get<2>(p)));
|
||||
|
||||
if (OpenCL())
|
||||
{
|
||||
if (!m_Wrapper.Ok() || PlatformIndex() != m_Wrapper.PlatformIndex() || DeviceIndex() != m_Wrapper.DeviceIndex())
|
||||
m_Wrapper.Init(PlatformIndex(), DeviceIndex());
|
||||
|
||||
if (m_Wrapper.Ok())
|
||||
{
|
||||
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)
|
||||
{
|
||||
s = "Histogram/Accumulator memory size of " + ToString(histSize) +
|
||||
" is greater than the max OpenCL allocation size of " + ToString(maxAlloc);
|
||||
}
|
||||
|
||||
if (totalSize > totalAvail)
|
||||
{
|
||||
s += "\n\nTotal required memory size of " + ToString(totalSize) +
|
||||
" is greater than the max OpenCL available memory of " + ToString(totalAvail);
|
||||
}
|
||||
|
||||
if (!s.isEmpty())
|
||||
{
|
||||
error = true;
|
||||
ui.FinalRenderTextOutput->setText(s + ".\n\nRendering will most likely fail.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!error)
|
||||
ui.FinalRenderTextOutput->clear();
|
||||
|
||||
ui.FinalRenderParamsTable->item(m_MemoryCellIndex, 1)->setText(ToString(p.first));
|
||||
ui.FinalRenderParamsTable->item(m_ItersCellIndex, 1)->setText(ToString(p.second));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -151,8 +151,9 @@ FinalRenderEmberController<T>::FinalRenderEmberController(FractoriumFinalRenderD
|
||||
{
|
||||
m_Run = true;
|
||||
m_TotalTimer.Tic();//Begin timing for progress of all operations.
|
||||
size_t i;
|
||||
m_GuiState = m_FinalRenderDialog->State();//Cache render settings from the GUI before running.
|
||||
|
||||
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.
|
||||
QString path = doAll ? ComposePath(QString::fromStdString(m_EmberFile.m_Embers[0].m_Name)) : ComposePath(Name());
|
||||
@ -566,8 +567,9 @@ void FinalRenderEmberController<T>::ResetProgress(bool total)
|
||||
/// </summary>
|
||||
/// <returns>If successful, memory required in bytes, else zero.</returns>
|
||||
template <typename T>
|
||||
pair<size_t, size_t> FinalRenderEmberController<T>::SyncAndComputeMemory()
|
||||
tuple<size_t, size_t, size_t> FinalRenderEmberController<T>::SyncAndComputeMemory()
|
||||
{
|
||||
size_t iterCount;
|
||||
pair<size_t, size_t> p(0, 0);
|
||||
|
||||
if (m_Renderer.get())
|
||||
@ -587,11 +589,12 @@ pair<size_t, size_t> FinalRenderEmberController<T>::SyncAndComputeMemory()
|
||||
m_Renderer->ComputeCamera();
|
||||
CancelPreviewRender();
|
||||
m_FinalPreviewRenderFunc();
|
||||
p.first = m_Renderer->MemoryRequired(m_FinalRenderDialog->Strips(), true);
|
||||
p.second = m_Renderer->TotalIterCount(strips);
|
||||
|
||||
p = m_Renderer->MemoryRequired(strips, true);
|
||||
iterCount = m_Renderer->TotalIterCount(strips);
|
||||
}
|
||||
|
||||
return p;
|
||||
return tuple<size_t, size_t, size_t>(p.first, p.second, iterCount);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -63,7 +63,7 @@ public:
|
||||
virtual void SyncGuiToEmbers(size_t widthOverride = 0, size_t heightOverride = 0) { }
|
||||
virtual void SyncCurrentToSizeSpinners(bool scale, bool size) { }
|
||||
virtual void ResetProgress(bool total = true) { }
|
||||
virtual pair<size_t, size_t> SyncAndComputeMemory() { return pair<size_t, size_t>(0, 0); }
|
||||
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 ""; }
|
||||
|
||||
@ -121,7 +121,7 @@ public:
|
||||
virtual void SyncGuiToEmbers(size_t widthOverride = 0, size_t heightOverride = 0) override;
|
||||
virtual void SyncCurrentToSizeSpinners(bool scale, bool size) override;
|
||||
virtual void ResetProgress(bool total = true) override;
|
||||
virtual pair<size_t, size_t> SyncAndComputeMemory() override;
|
||||
virtual tuple<size_t, size_t, size_t> SyncAndComputeMemory() override;
|
||||
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;
|
||||
|
Loading…
Reference in New Issue
Block a user