mirror of
https://bitbucket.org/mfeemster/fractorium.git
synced 2025-07-02 06:16:17 -04:00
Remove ReadMe.txt from all project files.
Add Curves.h, and CurvesGraphicsView.h/cpp to support bezier color curves. Add Curves member to Ember. Add curves capability to EmberCL. Remove some unused variables in the kernel created in RendererCL::CreateFinalAccumKernelString(). Use glm namespace for vec classes if GLM_VERSION >= 96, else use glm::detail. As a result of using glm namespace, all instances of min and max had to be qualified with std:: Split ComputeCamera into that and ComputeQuality(). Reduce the amount of ComputeCamera() and MakeDmap() calls on each incremental iter that doesn't use temporal samples. Fix clamping bug with DE filter widths. Provide functions to return the kernels from RendererCL to assist with diagnostics and debugging. Prevent extra newline in EmberRender when only rendering a single image. Add the ability to delete an ember at a given index in EmberFile. Allow deleting/focusing ember in library tab with delete and enter keys. Reorder some code in Fractorium.h to match the tabs order. Add and call ClearFinalImages() to clear buffers in controller to fix bug where previous CPU render would be shown for a split second when switching from OpenCL back to CPU. Refactor ember library pointer syncing to a function SyncPointers(). Add the ability to save ember Xmls to an unique automatically generated name after the first time the user has specified a name.
This commit is contained in:
@ -140,6 +140,21 @@ static const char* CalcAlphaFunctionString =
|
||||
"}\n"
|
||||
"\n";
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// OpenCL equivalent of Renderer::CurveAdjust().
|
||||
/// Only use float here instead of real_t because the output will be passed to write_imagef()
|
||||
/// during final accumulation, which only takes floats.
|
||||
/// </summary>
|
||||
static const char* CurveAdjustFunctionString =
|
||||
"static inline void CurveAdjust(__constant real4reals* csa, float* a, uint index)\n"
|
||||
"{\n"
|
||||
" uint tempIndex = (uint)Clamp(*a, 0.0, (float)COLORMAP_LENGTH_MINUS_1);\n"
|
||||
" uint tempIndex2 = (uint)Clamp(csa[tempIndex].m_Real4.x, 0.0, (real_t)COLORMAP_LENGTH_MINUS_1);\n"
|
||||
"\n"
|
||||
" *a = (float)round(csa[tempIndex2].m_Reals[index]);\n"
|
||||
"}\n";
|
||||
|
||||
/// <summary>
|
||||
/// Use MWC 64 from David Thomas at the Imperial College of London for
|
||||
/// random numbers in OpenCL, instead of ISAAC which was used
|
||||
|
@ -197,6 +197,7 @@ string FinalAccumOpenCLKernelCreator<T>::CreateFinalAccumKernelString(bool early
|
||||
RgbToHsvFunctionString <<
|
||||
HsvToRgbFunctionString <<
|
||||
CalcAlphaFunctionString <<
|
||||
CurveAdjustFunctionString <<
|
||||
SpatialFilterCLStructString;
|
||||
|
||||
if (earlyClip)
|
||||
@ -231,6 +232,8 @@ string FinalAccumOpenCLKernelCreator<T>::CreateFinalAccumKernelString(bool early
|
||||
" __write_only image2d_t pixels,\n"
|
||||
" __constant SpatialFilterCL* spatialFilter,\n"
|
||||
" __constant real_t* filterCoefs,\n"
|
||||
" __constant real4reals* csa,\n"
|
||||
" const uint doCurves,\n"
|
||||
" const real_t alphaBase,\n"
|
||||
" const real_t alphaScale\n"
|
||||
"\t)\n"
|
||||
@ -245,14 +248,11 @@ string FinalAccumOpenCLKernelCreator<T>::CreateFinalAccumKernelString(bool early
|
||||
" finalCoord.x = GLOBAL_ID_X;\n"
|
||||
" finalCoord.y = (int)((spatialFilter->m_YAxisUp == 1) ? ((spatialFilter->m_FinalRasH - GLOBAL_ID_Y) - 1) : GLOBAL_ID_Y);\n"
|
||||
" float4floats finalColor;\n"
|
||||
" real_t alpha, ls;\n"
|
||||
" int ii, jj;\n"
|
||||
" uint filterKRowIndex;\n"
|
||||
" const __global real4reals* accumBucket;\n"
|
||||
" real4reals newBucket;\n"
|
||||
" newBucket.m_Real4 = 0;\n"
|
||||
" real4reals newRgb;\n"
|
||||
" newRgb.m_Real4 = 0;\n"
|
||||
"\n"
|
||||
" for (jj = 0; jj < spatialFilter->m_FilterWidth; jj++)\n"
|
||||
" {\n"
|
||||
@ -269,7 +269,7 @@ string FinalAccumOpenCLKernelCreator<T>::CreateFinalAccumKernelString(bool early
|
||||
"\n";
|
||||
|
||||
//Not supporting 2 bytes per channel on the GPU. If the user wants it, run on the CPU.
|
||||
if (earlyClip)//If early clip, simply assign values directly to the temp uint4 since they've been gamma corrected already, then write it straight to the output image below.
|
||||
if (earlyClip)//If early clip, simply assign values directly to the temp float4 since they've been gamma corrected already, then write it straight to the output image below.
|
||||
{
|
||||
os <<
|
||||
" finalColor.m_Float4.x = (float)newBucket.m_Real4.x;\n"//CPU side clamps, skip here because write_imagef() does the clamping for us.
|
||||
@ -307,6 +307,14 @@ string FinalAccumOpenCLKernelCreator<T>::CreateFinalAccumKernelString(bool early
|
||||
}
|
||||
|
||||
os <<
|
||||
"\n"
|
||||
" if (doCurves)\n"
|
||||
" {\n"
|
||||
" CurveAdjust(csa, &(finalColor.m_Floats[0]), 1);\n"
|
||||
" CurveAdjust(csa, &(finalColor.m_Floats[1]), 2);\n"
|
||||
" CurveAdjust(csa, &(finalColor.m_Floats[2]), 3);\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" finalColor.m_Float4 /= 255.0f;\n"
|
||||
" write_imagef(pixels, finalCoord, finalColor.m_Float4);\n"//Use write_imagef instead of write_imageui because only the former works when sharing with an OpenGL texture.
|
||||
" barrier(CLK_GLOBAL_MEM_FENCE);\n"//Required, or else page tearing will occur during interactive rendering.
|
||||
|
@ -33,6 +33,7 @@ RendererCL<T>::RendererCL(uint platform, uint device, bool shared, GLuint output
|
||||
m_DEWidthsBufferName = "DEWidths";
|
||||
m_DECoefIndicesBufferName = "DECoefIndices";
|
||||
m_SpatialFilterCoefsBufferName = "SpatialFilterCoefs";
|
||||
m_CurvesCsaName = "CurvesCsa";
|
||||
m_HistBufferName = "Hist";
|
||||
m_AccumBufferName = "Accum";
|
||||
m_FinalImageName = "Final";
|
||||
@ -282,6 +283,21 @@ bool RendererCL<T>::WriteRandomPoints()
|
||||
template <typename T>
|
||||
string RendererCL<T>::IterKernel() { return m_IterKernel; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get the kernel string for the last built density filtering program.
|
||||
/// </summary>
|
||||
/// <returns>The string representation of the kernel for the last built density filtering program.</returns>
|
||||
template <typename T>
|
||||
string RendererCL<T>::DEKernel() { return m_DEOpenCLKernelCreator.GaussianDEKernel(Supersample(), m_DensityFilterCL.m_FilterWidth); }
|
||||
|
||||
/// <summary>
|
||||
/// Get the kernel string for the last built final accumulation program.
|
||||
/// </summary>
|
||||
/// <returns>The string representation of the kernel for the last built final accumulation program.</returns>
|
||||
template <typename T>
|
||||
string RendererCL<T>::FinalAccumKernel() { return m_FinalAccumOpenCLKernelCreator.FinalAccumKernel(EarlyClip(), Renderer<T, T>::NumChannels(), Transparency()); }
|
||||
|
||||
/// <summary>
|
||||
/// Virtual functions overridden from RendererCLBase.
|
||||
/// </summary>
|
||||
@ -551,17 +567,17 @@ bool RendererCL<T>::Alloc()
|
||||
size_t accumLength = SuperSize() * sizeof(v4T);
|
||||
const char* loc = __FUNCTION__;
|
||||
|
||||
if (b && !(b = m_Wrapper.AddBuffer(m_EmberBufferName, sizeof(m_EmberCL)))) { m_ErrorReport.push_back(loc); }
|
||||
if (b && !(b = m_Wrapper.AddBuffer(m_XformsBufferName, SizeOf(m_XformsCL)))) { m_ErrorReport.push_back(loc); }
|
||||
if (b && !(b = m_Wrapper.AddBuffer(m_ParVarsBufferName, 128 * sizeof(T)))) { m_ErrorReport.push_back(loc); }
|
||||
if (b && !(b = m_Wrapper.AddBuffer(m_DistBufferName, CHOOSE_XFORM_GRAIN))) { m_ErrorReport.push_back(loc); }//Will be resized for xaos.
|
||||
if (b && !(b = m_Wrapper.AddBuffer(m_CarToRasBufferName, sizeof(m_CarToRasCL)))) { m_ErrorReport.push_back(loc); }
|
||||
if (b && !(b = m_Wrapper.AddBuffer(m_DEFilterParamsBufferName, sizeof(m_DensityFilterCL)))) { m_ErrorReport.push_back(loc); }
|
||||
if (b && !(b = m_Wrapper.AddBuffer(m_SpatialFilterParamsBufferName, sizeof(m_SpatialFilterCL)))) { m_ErrorReport.push_back(loc); }
|
||||
|
||||
if (b && !(b = m_Wrapper.AddBuffer(m_HistBufferName, histLength))) { m_ErrorReport.push_back(loc); }//Histogram. Will memset to zero later.
|
||||
if (b && !(b = m_Wrapper.AddBuffer(m_AccumBufferName, accumLength))) { m_ErrorReport.push_back(loc); }//Accum buffer.
|
||||
if (b && !(b = m_Wrapper.AddBuffer(m_PointsBufferName, IterGridKernelCount() * sizeof(PointCL<T>)))) { m_ErrorReport.push_back(loc); }//Points between iter calls.
|
||||
if (b && !(b = m_Wrapper.AddBuffer(m_EmberBufferName, sizeof(m_EmberCL)))) { m_ErrorReport.push_back(loc); }
|
||||
if (b && !(b = m_Wrapper.AddBuffer(m_XformsBufferName, SizeOf(m_XformsCL)))) { m_ErrorReport.push_back(loc); }
|
||||
if (b && !(b = m_Wrapper.AddBuffer(m_ParVarsBufferName, 128 * sizeof(T)))) { m_ErrorReport.push_back(loc); }
|
||||
if (b && !(b = m_Wrapper.AddBuffer(m_DistBufferName, CHOOSE_XFORM_GRAIN))) { m_ErrorReport.push_back(loc); }//Will be resized for xaos.
|
||||
if (b && !(b = m_Wrapper.AddBuffer(m_CarToRasBufferName, sizeof(m_CarToRasCL)))) { m_ErrorReport.push_back(loc); }
|
||||
if (b && !(b = m_Wrapper.AddBuffer(m_DEFilterParamsBufferName, sizeof(m_DensityFilterCL)))) { m_ErrorReport.push_back(loc); }
|
||||
if (b && !(b = m_Wrapper.AddBuffer(m_SpatialFilterParamsBufferName, sizeof(m_SpatialFilterCL)))) { m_ErrorReport.push_back(loc); }
|
||||
if (b && !(b = m_Wrapper.AddBuffer(m_CurvesCsaName, SizeOf(m_Csa.m_Entries)))) { m_ErrorReport.push_back(loc); }
|
||||
if (b && !(b = m_Wrapper.AddBuffer(m_HistBufferName, histLength))) { m_ErrorReport.push_back(loc); }//Histogram. Will memset to zero later.
|
||||
if (b && !(b = m_Wrapper.AddBuffer(m_AccumBufferName, accumLength))) { m_ErrorReport.push_back(loc); }//Accum buffer.
|
||||
if (b && !(b = m_Wrapper.AddBuffer(m_PointsBufferName, IterGridKernelCount() * sizeof(PointCL<T>)))) { m_ErrorReport.push_back(loc); }//Points between iter calls.
|
||||
|
||||
LeaveResize();
|
||||
|
||||
@ -809,8 +825,8 @@ bool RendererCL<T>::RunIter(size_t iterCount, size_t temporalSample, size_t& ite
|
||||
//fuse = ((m_Calls % 4) == 0 ? 100u : 0u);
|
||||
#endif
|
||||
itersRemaining = iterCount - itersRan;
|
||||
uint gridW = uint(min(ceil(double(itersRemaining) / double(iterCountPerBlock)), double(IterGridBlockWidth())));
|
||||
uint gridH = uint(min(ceil(double(itersRemaining) / double(gridW * iterCountPerBlock)), double(IterGridBlockHeight())));
|
||||
uint gridW = uint(std::min(ceil(double(itersRemaining) / double(iterCountPerBlock)), double(IterGridBlockWidth())));
|
||||
uint gridH = uint(std::min(ceil(double(itersRemaining) / double(gridW * iterCountPerBlock)), double(IterGridBlockHeight())));
|
||||
uint iterCountThisLaunch = iterCountPerBlock * gridW * gridH;
|
||||
|
||||
//Similar to what's done in the base class.
|
||||
@ -1071,6 +1087,7 @@ eRenderStatus RendererCL<T>::RunFinalAccum()
|
||||
uint gridH;
|
||||
uint blockW;
|
||||
uint blockH;
|
||||
uint curvesSet = m_CurvesSet ? 1 : 0;
|
||||
const char* loc = __FUNCTION__;
|
||||
|
||||
if (!m_Abort && accumKernelIndex != -1)
|
||||
@ -1079,6 +1096,7 @@ eRenderStatus RendererCL<T>::RunFinalAccum()
|
||||
m_SpatialFilterCL = ConvertSpatialFilter();
|
||||
|
||||
if (b && !(b = m_Wrapper.AddAndWriteBuffer(m_SpatialFilterParamsBufferName, reinterpret_cast<void*>(&m_SpatialFilterCL), sizeof(m_SpatialFilterCL)))) { m_ErrorReport.push_back(loc); }
|
||||
if (b && !(b = m_Wrapper.AddAndWriteBuffer(m_CurvesCsaName, m_Csa.m_Entries.data(), SizeOf(m_Csa.m_Entries)))) { m_ErrorReport.push_back(loc); }
|
||||
|
||||
//Since early clip requires gamma correcting the entire accumulator first,
|
||||
//it can't be done inside of the normal final accumulation kernel, so
|
||||
@ -1119,6 +1137,9 @@ eRenderStatus RendererCL<T>::RunFinalAccum()
|
||||
if (b && !(b = m_Wrapper.SetImageArg (accumKernelIndex, argIndex++, m_Wrapper.Shared(), m_FinalImageName))) { m_ErrorReport.push_back(loc); }//Final image.
|
||||
if (b && !(b = m_Wrapper.SetBufferArg(accumKernelIndex, argIndex++, m_SpatialFilterParamsBufferName))) { m_ErrorReport.push_back(loc); }//SpatialFilterCL.
|
||||
if (b && !(b = m_Wrapper.SetBufferArg(accumKernelIndex, argIndex++, m_SpatialFilterCoefsBufferName))) { m_ErrorReport.push_back(loc); }//Filter coefs.
|
||||
if (b && !(b = m_Wrapper.SetBufferArg(accumKernelIndex, argIndex++, m_CurvesCsaName))) { m_ErrorReport.push_back(loc); }//Curve points.
|
||||
|
||||
if (b && !(b = m_Wrapper.SetArg (accumKernelIndex, argIndex++, curvesSet))) { m_ErrorReport.push_back(loc); }//Do curves.
|
||||
if (b && !(b = m_Wrapper.SetArg (accumKernelIndex, argIndex++, alphaBase))) { m_ErrorReport.push_back(loc); }//Alpha base.
|
||||
if (b && !(b = m_Wrapper.SetArg (accumKernelIndex, argIndex++, alphaScale))) { m_ErrorReport.push_back(loc); }//Alpha scale.
|
||||
|
||||
|
@ -121,6 +121,8 @@ public:
|
||||
bool WriteRandomPoints();
|
||||
#endif
|
||||
string IterKernel();
|
||||
string DEKernel();
|
||||
string FinalAccumKernel();
|
||||
|
||||
//Virtual functions overridden from RendererCLBase.
|
||||
virtual bool ReadFinal(byte* pixels);
|
||||
@ -193,6 +195,7 @@ private:
|
||||
string m_CarToRasBufferName;
|
||||
string m_DEFilterParamsBufferName;
|
||||
string m_SpatialFilterParamsBufferName;
|
||||
string m_CurvesCsaName;
|
||||
string m_DECoefsBufferName;
|
||||
string m_DEWidthsBufferName;
|
||||
string m_DECoefIndicesBufferName;
|
||||
|
Reference in New Issue
Block a user