--Bug fixes

-Fix crash when using Lanczos2 filter with color curves due to negative numbers. Fix by passing abs() of first argument to pow() in Renderer::GammaCorrection().
 -Fix crash in hexes with SP. Rounding error caused out of bounds index.
This commit is contained in:
mfeemster 2016-02-23 21:01:02 -08:00
parent c282ee4c2c
commit 32d6982210
4 changed files with 202 additions and 218 deletions

View File

@ -1629,7 +1629,7 @@ void Renderer<T, bucketT>::GammaCorrection(tvec4<bucketT, glm::defaultp>& bucket
for (glm::length_t rgbi = 0; rgbi < 3; rgbi++) for (glm::length_t rgbi = 0; rgbi < 3; rgbi++)
{ {
a = newRgb[rgbi] + ((1 - vibrancy) * 255 * std::pow(bucket[rgbi], g)); a = newRgb[rgbi] + ((1 - vibrancy) * 255 * std::pow(std::abs(bucket[rgbi]), g));//Must use abs(), else it it could be a negative value and return NAN.
if (NumChannels() <= 3 || !Transparency()) if (NumChannels() <= 3 || !Transparency())
{ {

View File

@ -2393,9 +2393,10 @@ public:
virtual void Precalc() override virtual void Precalc() override
{ {
m_InvN = m_Dist / m_Power; auto zp = Zeps(m_Power);
m_Inv2PiN = M_2PI / m_Power; m_InvN = m_Dist / zp;
m_Cn = m_Dist / m_Power / 2; m_Inv2PiN = M_2PI / zp;
m_Cn = m_Dist / zp / 2;
} }
protected: protected:
@ -2405,7 +2406,7 @@ protected:
m_Params.clear(); m_Params.clear();
m_Params.push_back(ParamWithName<T>(&m_Power, prefix + "phoenix_julia_power", 2)); m_Params.push_back(ParamWithName<T>(&m_Power, prefix + "phoenix_julia_power", 2));
m_Params.push_back(ParamWithName<T>(&m_Dist, prefix + "phoenix_julia_dist", 1)); m_Params.push_back(ParamWithName<T>(&m_Dist, prefix + "phoenix_julia_dist", 1));
m_Params.push_back(ParamWithName<T>(&m_XDistort, prefix + "phoenix_julia_x_distort", T(-T(0.5))));//Original omitted phoenix_ prefix. m_Params.push_back(ParamWithName<T>(&m_XDistort, prefix + "phoenix_julia_x_distort", T(-0.5)));//Original omitted phoenix_ prefix.
m_Params.push_back(ParamWithName<T>(&m_YDistort, prefix + "phoenix_julia_y_distort")); m_Params.push_back(ParamWithName<T>(&m_YDistort, prefix + "phoenix_julia_y_distort"));
m_Params.push_back(ParamWithName<T>(true, &m_Cn, prefix + "phoenix_julia_cn"));//Precalc. m_Params.push_back(ParamWithName<T>(true, &m_Cn, prefix + "phoenix_julia_cn"));//Precalc.
m_Params.push_back(ParamWithName<T>(true, &m_InvN, prefix + "phoenix_julia_invn")); m_Params.push_back(ParamWithName<T>(true, &m_InvN, prefix + "phoenix_julia_invn"));

View File

@ -36,7 +36,7 @@ public:
static const T AYoXh = T(1.7320508075688772935 / 2.0); static const T AYoXh = T(1.7320508075688772935 / 2.0);
static const T AYoYh = T(1.7320508075688772935 / 2.0); static const T AYoYh = T(1.7320508075688772935 / 2.0);
static const v2T offset[4] { { 0, 0 }, { 0, 1 }, { 1, 0 }, { 1, 1 } }; static const v2T offset[4] { { 0, 0 }, { 0, 1 }, { 1, 0 }, { 1, 1 } };
int i = 0; int i, j;
T di, dj; T di, dj;
T XCh, YCh, XCo, YCo, DXo, DYo, L, L1, L2, R, s, trgL; T XCh, YCh, XCo, YCo, DXo, DYo, L, L1, L2, R, s, trgL;
v2T u, v; v2T u, v;
@ -60,13 +60,12 @@ public:
YCh = T(Floor((AYhXo * u.x + AYhYo * u.y) / s)); YCh = T(Floor((AYhXo * u.x + AYhYo * u.y) / s));
// Get a set of 4 hex center points, based around the one above // Get a set of 4 hex center points, based around the one above
for (di = XCh; di < XCh + T(1.1); di += 1) for (i = 0, di = XCh; i < 2; di += 1, i++)//Note that in SP mode, these numbers won't advance if they are on the boundary of what can be represented with an DP number...
{ {
for (dj = YCh; dj < YCh + T(1.1); dj += 1) for (j = 0, dj = YCh; j < 2; dj += 1, j++)//...which is why the check uses i and j.
{ {
P[i].x = (AXoXh * di + AXoYh * dj) * s; P[(i * 2) + j].x = (AXoXh * di + AXoYh * dj) * s;
P[i].y = (AYoXh * di + AYoYh * dj) * s; P[(i * 2) + j].y = (AYoXh * di + AYoYh * dj) * s;
i++;
} }
} }
@ -151,7 +150,7 @@ public:
string rotsin = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string rotsin = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string rotcos = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string rotcos = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
ss << "\t{\n" ss << "\t{\n"
<< "\t\tint i = 0;\n" << "\t\tint i, j;\n"
<< "\t\treal_t di, dj;\n" << "\t\treal_t di, dj;\n"
<< "\t\treal_t XCh, YCh, XCo, YCo, DXo, DYo, L, L1, L2, R, s, trgL, Vx, Vy;\n" << "\t\treal_t XCh, YCh, XCo, YCo, DXo, DYo, L, L1, L2, R, s, trgL, Vx, Vy;\n"
<< "\t\treal2 U;\n" << "\t\treal2 U;\n"
@ -173,13 +172,12 @@ public:
<< "\t\tXCh = floor((AXhXo * U.x + AXhYo * U.y) / s);\n" << "\t\tXCh = floor((AXhXo * U.x + AXhYo * U.y) / s);\n"
<< "\t\tYCh = floor((AYhXo * U.x + AYhYo * U.y) / s);\n" << "\t\tYCh = floor((AYhXo * U.x + AYhYo * U.y) / s);\n"
<< "\n" << "\n"
<< "\t\tfor (di = XCh; di < XCh + 1.1; di += 1)\n" << "\t\tfor (i = 0, di = XCh; i < 2; di += 1, i++)\n"
<< "\t\t{\n" << "\t\t{\n"
<< "\t\t for (dj = YCh; dj < YCh + 1.1; dj += 1)\n" << "\t\t for (j = 0, dj = YCh; j < 2; dj += 1, j++)\n"
<< "\t\t {\n" << "\t\t {\n"
<< "\t\t P[i].x = (AXoXh * di + AXoYh * dj) * s;\n" << "\t\t P[(i * 2) + j].x = (AXoXh * di + AXoYh * dj) * s;\n"
<< "\t\t P[i].y = (AYoXh * di + AYoYh * dj) * s;\n" << "\t\t P[(i * 2) + j].y = (AYoXh * di + AYoYh * dj) * s;\n"
<< "\t\t i++;\n"
<< "\t\t }\n" << "\t\t }\n"
<< "\t\t}\n" << "\t\t}\n"
<< "\n" << "\n"

View File

@ -12,22 +12,17 @@ FinalAccumOpenCLKernelCreator::FinalAccumOpenCLKernelCreator(bool doublePrecisio
m_DoublePrecision = doublePrecision; m_DoublePrecision = doublePrecision;
m_GammaCorrectionWithAlphaCalcEntryPoint = "GammaCorrectionWithAlphaCalcKernel"; m_GammaCorrectionWithAlphaCalcEntryPoint = "GammaCorrectionWithAlphaCalcKernel";
m_GammaCorrectionWithoutAlphaCalcEntryPoint = "GammaCorrectionWithoutAlphaCalcKernel"; m_GammaCorrectionWithoutAlphaCalcEntryPoint = "GammaCorrectionWithoutAlphaCalcKernel";
m_GammaCorrectionWithAlphaCalcKernel = CreateGammaCorrectionKernelString(true); m_GammaCorrectionWithAlphaCalcKernel = CreateGammaCorrectionKernelString(true);
m_GammaCorrectionWithoutAlphaCalcKernel = CreateGammaCorrectionKernelString(false); m_GammaCorrectionWithoutAlphaCalcKernel = CreateGammaCorrectionKernelString(false);
m_FinalAccumEarlyClipEntryPoint = "FinalAccumEarlyClipKernel"; m_FinalAccumEarlyClipEntryPoint = "FinalAccumEarlyClipKernel";
m_FinalAccumEarlyClipWithAlphaCalcWithAlphaAccumEntryPoint = "FinalAccumEarlyClipWithAlphaCalcWithAlphaAccumKernel"; m_FinalAccumEarlyClipWithAlphaCalcWithAlphaAccumEntryPoint = "FinalAccumEarlyClipWithAlphaCalcWithAlphaAccumKernel";
m_FinalAccumEarlyClipWithoutAlphaCalcWithAlphaAccumEntryPoint = "FinalAccumEarlyClipWithoutAlphaCalcWithAlphaAccumKernel"; m_FinalAccumEarlyClipWithoutAlphaCalcWithAlphaAccumEntryPoint = "FinalAccumEarlyClipWithoutAlphaCalcWithAlphaAccumKernel";
m_FinalAccumEarlyClipKernel = CreateFinalAccumKernelString(true, false, false); m_FinalAccumEarlyClipKernel = CreateFinalAccumKernelString(true, false, false);
m_FinalAccumEarlyClipWithAlphaCalcWithAlphaAccumKernel = CreateFinalAccumKernelString(true, true, true); m_FinalAccumEarlyClipWithAlphaCalcWithAlphaAccumKernel = CreateFinalAccumKernelString(true, true, true);
m_FinalAccumEarlyClipWithoutAlphaCalcWithAlphaAccumKernel = CreateFinalAccumKernelString(true, false, true); m_FinalAccumEarlyClipWithoutAlphaCalcWithAlphaAccumKernel = CreateFinalAccumKernelString(true, false, true);
m_FinalAccumLateClipEntryPoint = "FinalAccumLateClipKernel"; m_FinalAccumLateClipEntryPoint = "FinalAccumLateClipKernel";
m_FinalAccumLateClipWithAlphaCalcWithAlphaAccumEntryPoint = "FinalAccumLateClipWithAlphaCalcWithAlphaAccumKernel"; m_FinalAccumLateClipWithAlphaCalcWithAlphaAccumEntryPoint = "FinalAccumLateClipWithAlphaCalcWithAlphaAccumKernel";
m_FinalAccumLateClipWithoutAlphaCalcWithAlphaAccumEntryPoint = "FinalAccumLateClipWithoutAlphaCalcWithAlphaAccumKernel"; m_FinalAccumLateClipWithoutAlphaCalcWithAlphaAccumEntryPoint = "FinalAccumLateClipWithoutAlphaCalcWithAlphaAccumKernel";
m_FinalAccumLateClipKernel = CreateFinalAccumKernelString(false, false, false); m_FinalAccumLateClipKernel = CreateFinalAccumKernelString(false, false, false);
m_FinalAccumLateClipWithAlphaCalcWithAlphaAccumKernel = CreateFinalAccumKernelString(false, true, true); m_FinalAccumLateClipWithAlphaCalcWithAlphaAccumKernel = CreateFinalAccumKernelString(false, true, true);
m_FinalAccumLateClipWithoutAlphaCalcWithAlphaAccumKernel = CreateFinalAccumKernelString(false, false, true); m_FinalAccumLateClipWithoutAlphaCalcWithAlphaAccumKernel = CreateFinalAccumKernelString(false, false, true);
@ -183,7 +178,6 @@ string FinalAccumOpenCLKernelCreator::CreateFinalAccumKernelString(bool earlyCli
{ {
ostringstream os; ostringstream os;
string channels = alphaAccum ? "4" : "3"; string channels = alphaAccum ? "4" : "3";
os << os <<
ConstantDefinesString(m_DoublePrecision) << ConstantDefinesString(m_DoublePrecision) <<
UnionCLStructString << UnionCLStructString <<
@ -313,7 +307,6 @@ string FinalAccumOpenCLKernelCreator::CreateFinalAccumKernelString(bool earlyCli
" barrier(CLK_GLOBAL_MEM_FENCE);\n"//Required, or else page tearing will occur during interactive rendering. " barrier(CLK_GLOBAL_MEM_FENCE);\n"//Required, or else page tearing will occur during interactive rendering.
"}\n" "}\n"
; ;
return os.str(); return os.str();
} }
@ -332,10 +325,8 @@ string FinalAccumOpenCLKernelCreator::CreateGammaCorrectionFunctionString(bool g
string dataType; string dataType;
string unionMember; string unionMember;
dataType = "real_bucket_t"; dataType = "real_bucket_t";
//Use real_t for all cases, early clip and final accum. //Use real_t for all cases, early clip and final accum.
os << "void GammaCorrectionFloats(" << (globalBucket ? "__global " : "") << "real4reals_bucket* bucket, __constant real_bucket_t* background, real_bucket_t g, real_bucket_t linRange, real_bucket_t vibrancy, real_bucket_t highlightPower, real_bucket_t alphaBase, real_bucket_t alphaScale, " << (finalOut ? "" : "__global") << " real_bucket_t* correctedChannels)\n"; os << "void GammaCorrectionFloats(" << (globalBucket ? "__global " : "") << "real4reals_bucket* bucket, __constant real_bucket_t* background, real_bucket_t g, real_bucket_t linRange, real_bucket_t vibrancy, real_bucket_t highlightPower, real_bucket_t alphaBase, real_bucket_t alphaScale, " << (finalOut ? "" : "__global") << " real_bucket_t* correctedChannels)\n";
os os
<< "{\n" << "{\n"
<< " real_bucket_t alpha, ls, tmp, a;\n" << " real_bucket_t alpha, ls, tmp, a;\n"
@ -358,7 +349,7 @@ string FinalAccumOpenCLKernelCreator::CreateGammaCorrectionFunctionString(bool g
<< "\n" << "\n"
<< " for (uint rgbi = 0; rgbi < 3; rgbi++)\n" << " for (uint rgbi = 0; rgbi < 3; rgbi++)\n"
<< " {\n" << " {\n"
<< " a = newRgb.m_Reals[rgbi] + ((1.0 - vibrancy) * 256.0 * pow(bucket->m_Reals[rgbi], g));\n" << " a = newRgb.m_Reals[rgbi] + ((1.0 - vibrancy) * 256.0 * pow(fabs(bucket->m_Reals[rgbi]), g));\n"
<< "\n"; << "\n";
if (!alphaCalc) if (!alphaCalc)
@ -399,7 +390,6 @@ string FinalAccumOpenCLKernelCreator::CreateGammaCorrectionFunctionString(bool g
os << os <<
"}\n" "}\n"
"\n"; "\n";
return os.str(); return os.str();
} }
@ -411,7 +401,6 @@ string FinalAccumOpenCLKernelCreator::CreateGammaCorrectionFunctionString(bool g
string FinalAccumOpenCLKernelCreator::CreateCalcNewRgbFunctionString(bool globalBucket) string FinalAccumOpenCLKernelCreator::CreateCalcNewRgbFunctionString(bool globalBucket)
{ {
ostringstream os; ostringstream os;
os << os <<
"static void CalcNewRgb(" << (globalBucket ? "__global " : "") << "real4reals_bucket* oldRgb, real_bucket_t ls, real_bucket_t highPow, real4reals_bucket* newRgb)\n" "static void CalcNewRgb(" << (globalBucket ? "__global " : "") << "real4reals_bucket* oldRgb, real_bucket_t ls, real_bucket_t highPow, real4reals_bucket* newRgb)\n"
"{\n" "{\n"
@ -467,7 +456,6 @@ string FinalAccumOpenCLKernelCreator::CreateCalcNewRgbFunctionString(bool global
" }\n" " }\n"
"}\n" "}\n"
"\n"; "\n";
return os.str(); return os.str();
} }
@ -480,7 +468,6 @@ string FinalAccumOpenCLKernelCreator::CreateGammaCorrectionKernelString(bool alp
{ {
ostringstream os; ostringstream os;
string dataType; string dataType;
os << os <<
ConstantDefinesString(m_DoublePrecision) << ConstantDefinesString(m_DoublePrecision) <<
UnionCLStructString << UnionCLStructString <<
@ -490,7 +477,6 @@ string FinalAccumOpenCLKernelCreator::CreateGammaCorrectionKernelString(bool alp
CreateCalcNewRgbFunctionString(true) << CreateCalcNewRgbFunctionString(true) <<
SpatialFilterCLStructString << SpatialFilterCLStructString <<
CreateGammaCorrectionFunctionString(true, alphaCalc, true, false);//Will only be used with float in this case, early clip. Will always alpha accum. CreateGammaCorrectionFunctionString(true, alphaCalc, true, false);//Will only be used with float in this case, early clip. Will always alpha accum.
os << "__kernel void " << (alphaCalc ? m_GammaCorrectionWithAlphaCalcEntryPoint : m_GammaCorrectionWithoutAlphaCalcEntryPoint) << "(\n" << os << "__kernel void " << (alphaCalc ? m_GammaCorrectionWithAlphaCalcEntryPoint : m_GammaCorrectionWithoutAlphaCalcEntryPoint) << "(\n" <<
" __global real4reals_bucket* accumulator,\n" " __global real4reals_bucket* accumulator,\n"
" __constant SpatialFilterCL* spatialFilter\n" " __constant SpatialFilterCL* spatialFilter\n"
@ -507,7 +493,6 @@ string FinalAccumOpenCLKernelCreator::CreateGammaCorrectionKernelString(bool alp
" GammaCorrectionFloats(bucket, &(spatialFilter->m_Background[0]), spatialFilter->m_Gamma, spatialFilter->m_LinRange, spatialFilter->m_Vibrancy, spatialFilter->m_HighlightPower, 0.0, 1.0, &(bucket->m_Reals[0]));\n" " GammaCorrectionFloats(bucket, &(spatialFilter->m_Background[0]), spatialFilter->m_Gamma, spatialFilter->m_LinRange, spatialFilter->m_Vibrancy, spatialFilter->m_HighlightPower, 0.0, 1.0, &(bucket->m_Reals[0]));\n"
"}\n" "}\n"
; ;
return os.str(); return os.str();
} }
} }