Commit 00771d38 authored by Niklas Haas's avatar Niklas Haas
Browse files

shaders: fall back to mix(vecN, vecN, vecN) on GLSL 120

These platforms don't support mix() with bvec, so we have to fall back
to casting to vecN instead. This works out fine, since true casts to 1.

Back-ported from 5fb5f635
parent 8f7fe445
......@@ -761,3 +761,27 @@ error:
talloc_free(tmp);
return ret;
}
const char *sh_bvec(const struct pl_shader *sh, int dims)
{
static const char *bvecs[] = {
[1] = "bool",
[2] = "bvec2",
[3] = "bvec3",
[4] = "bvec4",
};
static const char *vecs[] = {
[1] = "float",
[2] = "vec2",
[3] = "vec3",
[4] = "vec4",
};
pl_assert(dims > 0 && dims < PL_ARRAY_SIZE(bvecs));
if (sh->ra && sh->ra->glsl.version >= 130) {
return bvecs[dims];
} else {
return vecs[dims];
}
}
......@@ -168,3 +168,8 @@ ident_t sh_lut(struct pl_shader *sh, struct pl_shader_obj **obj,
enum sh_lut_method method, int width, int height, int depth,
bool update, void *priv,
void (*fill)(void *priv, float *data, int w, int h, int d));
// Returns a GLSL-version appropriate "bvec"-like type. For GLSL 130+, this
// returns bvecN. For GLSL 120, this returns vecN instead. The intended use of
// this function is with mix(), which only accepts bvec in GLSL 130+.
const char *sh_bvec(const struct pl_shader *sh, int dims);
......@@ -67,27 +67,30 @@ void pl_shader_decode_color(struct pl_shader *sh, struct pl_color_repr *repr,
// as per the BT.2020 specification, table 4. This is a non-linear
// transformation because (constant) luminance receives non-equal
// contributions from the three different channels.
GLSL("// constant luminance conversion \n"
"color.br = color.br * mix(vec2(1.5816, 0.9936), \n"
" vec2(1.9404, 1.7184), \n"
" lessThanEqual(color.br, vec2(0))) \n"
" + color.gg; \n"
GLSL("// constant luminance conversion \n"
"color.br = color.br * mix(vec2(1.5816, 0.9936), \n"
" vec2(1.9404, 1.7184), \n"
" %s(lessThanEqual(color.br, vec2(0)))) \n"
" + color.gg; \n",
sh_bvec(sh, 2));
// Expand channels to camera-linear light. This shader currently just
// assumes everything uses the BT.2020 12-bit gamma function, since the
// difference between 10 and 12-bit is negligible for anything other
// than 12-bit content.
"color.rgb = mix(color.rgb * vec3(1.0/4.5), \n"
GLSL("color.rgb = mix(color.rgb * vec3(1.0/4.5), \n"
" pow((color.rgb + vec3(0.0993))*vec3(1.0/1.0993), \n"
" vec3(1.0/0.45)), \n"
" lessThanEqual(vec3(0.08145), color.rgb)); \n"
" %s(lessThanEqual(vec3(0.08145), color.rgb))); \n",
sh_bvec(sh, 3));
// Calculate the green channel from the expanded RYcB
// The BT.2020 specification says Yc = 0.2627*R + 0.6780*G + 0.0593*B
"color.g = (color.g - 0.2627*color.r - 0.0593*color.b)*1.0/0.6780; \n"
// Recompress to receive the R'G'B' result, same as other systems
"color.rgb = mix(color.rgb * vec3(4.5), \n"
" vec3(1.0993) * pow(color.rgb, vec3(0.45)) \n"
" - vec3(0.0993), \n"
" lessThanEqual(vec3(0.0181), color.rgb)); \n");
// Then Recompress to receive the R'G'B' result, same as other systems
GLSL("color.g = (color.g - 0.2627*color.r - 0.0593*color.b)*1.0/0.6780; \n"
"color.rgb = mix(color.rgb * vec3(4.5), \n"
" vec3(1.0993) * pow(color.rgb, vec3(0.45)) \n"
" - vec3(0.0993), \n"
" %s(lessThanEqual(vec3(0.0181), color.rgb))); \n",
sh_bvec(sh, 3));
}
if (repr->alpha == PL_ALPHA_INDEPENDENT) {
......@@ -142,7 +145,8 @@ void pl_shader_linearize(struct pl_shader *sh, enum pl_color_transfer trc)
GLSL("color.rgb = mix(color.rgb * vec3(1.0/12.92), \n"
" pow((color.rgb + vec3(0.055))/vec3(1.055), \n"
" vec3(2.4)), \n"
" lessThan(vec3(0.04045), color.rgb)); \n");
" %s(lessThan(vec3(0.04045), color.rgb))); \n",
sh_bvec(sh, 3));
break;
case PL_COLOR_TRC_BT_1886:
GLSL("color.rgb = pow(color.rgb, vec3(2.4));\n");
......@@ -158,9 +162,10 @@ void pl_shader_linearize(struct pl_shader *sh, enum pl_color_transfer trc)
GLSL("color.rgb = pow(color.rgb, vec3(2.8));\n");
break;
case PL_COLOR_TRC_PRO_PHOTO:
GLSL("color.rgb = mix(color.rgb * vec3(1.0/16.0), \n"
" pow(color.rgb, vec3(1.8)), \n"
" lessThan(vec3(0.03125), color.rgb)); \n");
GLSL("color.rgb = mix(color.rgb * vec3(1.0/16.0), \n"
" pow(color.rgb, vec3(1.8)), \n"
" %s(lessThan(vec3(0.03125), color.rgb))); \n",
sh_bvec(sh, 3));
break;
case PL_COLOR_TRC_PQ:
GLSL("color.rgb = pow(color.rgb, vec3(1.0/%f)); \n"
......@@ -176,15 +181,15 @@ void pl_shader_linearize(struct pl_shader *sh, enum pl_color_transfer trc)
GLSL("color.rgb = mix(vec3(4.0) * color.rgb * color.rgb, \n"
" exp((color.rgb - vec3(%f)) * vec3(1.0/%f)) \n"
" + vec3(%f), \n"
" lessThan(vec3(0.5), color.rgb)); \n",
HLG_C, HLG_A, HLG_B);
" %s(lessThan(vec3(0.5), color.rgb))); \n",
HLG_C, HLG_A, HLG_B, sh_bvec(sh, 3));
break;
case PL_COLOR_TRC_V_LOG:
GLSL("color.rgb = mix((color.rgb - vec3(0.125)) * vec3(1.0/5.6), \n"
" pow(vec3(10.0), (color.rgb - vec3(%f)) * vec3(1.0/%f)) \n"
" - vec3(%f), \n"
" lessThanEqual(vec3(0.181), color.rgb)); \n",
VLOG_D, VLOG_C, VLOG_B);
" %s(lessThanEqual(vec3(0.181), color.rgb))); \n",
VLOG_D, VLOG_C, VLOG_B, sh_bvec(sh, 3));
break;
case PL_COLOR_TRC_S_LOG1:
GLSL("color.rgb = pow(vec3(10.0), (color.rgb - vec3(%f)) * vec3(1.0/%f)) \n"
......@@ -195,8 +200,9 @@ void pl_shader_linearize(struct pl_shader *sh, enum pl_color_transfer trc)
GLSL("color.rgb = mix((color.rgb - vec3(%f)) * vec3(1.0/%f), \n"
" (pow(vec3(10.0), (color.rgb - vec3(%f)) * vec3(1.0/%f)) \n"
" - vec3(%f)) * vec3(1.0/%f), \n"
" lessThanEqual(vec3(%f), color.rgb)); \n",
SLOG_Q, SLOG_P, SLOG_C, SLOG_A, SLOG_B, SLOG_K2, SLOG_Q);
" %s(lessThanEqual(vec3(%f), color.rgb))); \n",
SLOG_Q, SLOG_P, SLOG_C, SLOG_A, SLOG_B, SLOG_K2, sh_bvec(sh, 3),
SLOG_Q);
break;
default:
abort();
......@@ -216,10 +222,11 @@ void pl_shader_delinearize(struct pl_shader *sh, enum pl_color_transfer trc)
switch (trc) {
case PL_COLOR_TRC_SRGB:
GLSL("color.rgb = mix(color.rgb * vec3(12.92), \n"
" vec3(1.055) * pow(color.rgb, vec3(1.0/2.4)) \n"
" - vec3(0.055), \n"
" lessThanEqual(vec3(0.0031308), color.rgb)); \n");
GLSL("color.rgb = mix(color.rgb * vec3(12.92), \n"
" vec3(1.055) * pow(color.rgb, vec3(1.0/2.4)) \n"
" - vec3(0.055), \n"
" %s(lessThanEqual(vec3(0.0031308), color.rgb))); \n",
sh_bvec(sh, 3));
break;
case PL_COLOR_TRC_BT_1886:
GLSL("color.rgb = pow(color.rgb, vec3(1.0/2.4));\n");
......@@ -235,9 +242,10 @@ void pl_shader_delinearize(struct pl_shader *sh, enum pl_color_transfer trc)
GLSL("color.rgb = pow(color.rgb, vec3(1.0/2.8));\n");
break;
case PL_COLOR_TRC_PRO_PHOTO:
GLSL("color.rgb = mix(color.rgb * vec3(16.0), \n"
" pow(color.rgb, vec3(1.0/1.8)), \n"
" lessThanEqual(vec3(0.001953), color.rgb)); \n");
GLSL("color.rgb = mix(color.rgb * vec3(16.0), \n"
" pow(color.rgb, vec3(1.0/1.8)), \n"
" %s(lessThanEqual(vec3(0.001953), color.rgb))); \n",
sh_bvec(sh, 3));
break;
case PL_COLOR_TRC_PQ:
GLSL("color.rgb *= vec3(1.0/%f); \n"
......@@ -250,15 +258,15 @@ void pl_shader_delinearize(struct pl_shader *sh, enum pl_color_transfer trc)
case PL_COLOR_TRC_HLG:
GLSL("color.rgb = mix(vec3(0.5) * sqrt(color.rgb), \n"
" vec3(%f) * log(color.rgb - vec3(%f)) + vec3(%f), \n"
" lessThan(vec3(1.0), color.rgb)); \n",
HLG_A, HLG_B, HLG_C);
" %s(lessThan(vec3(1.0), color.rgb))); \n",
HLG_A, HLG_B, HLG_C, sh_bvec(sh, 3));
break;
case PL_COLOR_TRC_V_LOG:
GLSL("color.rgb = mix(vec3(5.6) * color.rgb + vec3(0.125), \n"
" vec3(%f) * log(color.rgb + vec3(%f)) \n"
" + vec3(%f), \n"
" lessThanEqual(vec3(0.01), color.rgb)); \n",
VLOG_C / M_LN10, VLOG_B, VLOG_D);
GLSL("color.rgb = mix(vec3(5.6) * color.rgb + vec3(0.125), \n"
" vec3(%f) * log(color.rgb + vec3(%f)) \n"
" + vec3(%f), \n"
" %s(lessThanEqual(vec3(0.01), color.rgb))); \n",
VLOG_C / M_LN10, VLOG_B, VLOG_D, sh_bvec(sh, 3));
break;
case PL_COLOR_TRC_S_LOG1:
GLSL("color.rgb = vec3(%f) * log(color.rgb + vec3(%f)) + vec3(%f);\n",
......@@ -268,8 +276,9 @@ void pl_shader_delinearize(struct pl_shader *sh, enum pl_color_transfer trc)
GLSL("color.rgb = mix(vec3(%f) * color.rgb + vec3(%f), \n"
" vec3(%f) * log(vec3(%f) * color.rgb + vec3(%f)) \n"
" + vec3(%f), \n"
" lessThanEqual(vec3(0.0), color.rgb)); \n",
SLOG_P, SLOG_Q, SLOG_A / M_LN10, SLOG_K2, SLOG_B, SLOG_C);
" %s(lessThanEqual(vec3(0.0), color.rgb))); \n",
SLOG_P, SLOG_Q, SLOG_A / M_LN10, SLOG_K2, SLOG_B, SLOG_C,
sh_bvec(sh, 3));
break;
default:
abort();
......@@ -304,8 +313,9 @@ static void pl_shader_ootf(struct pl_shader *sh, enum pl_color_light light,
GLSL("color.rgb = mix(color.rgb * vec3(4.5), \n"
" vec3(1.0993) * pow(color.rgb, vec3(0.45)) \n"
" - vec3(0.0993), \n"
" lessThan(vec3(0.0181), color.rgb)); \n"
"color.rgb = pow(color.rgb, vec3(2.4)); \n");
" %s(lessThan(vec3(0.0181), color.rgb))); \n"
"color.rgb = pow(color.rgb, vec3(2.4)); \n",
sh_bvec(sh, 3));
break;
case PL_COLOR_LIGHT_SCENE_1_2:
GLSL("color.rgb = pow(color.rgb, vec3(1.2));\n");
......@@ -337,7 +347,8 @@ static void pl_shader_inverse_ootf(struct pl_shader *sh,
"color.rgb = mix(color.rgb * vec3(1.0/4.5), \n"
" pow((color.rgb + vec3(0.0993)) * vec3(1.0/1.0993), \n"
" vec3(1/0.45)), \n"
" lessThan(vec3(0.08145), color.rgb)); \n");
" %s(lessThan(vec3(0.08145), color.rgb))); \n",
sh_bvec(sh, 3));
break;
case PL_COLOR_LIGHT_SCENE_1_2:
GLSL("color.rgb = pow(color.rgb, vec3(1.0/1.2));\n");
......
......@@ -77,11 +77,11 @@ void pl_shader_deband(struct pl_shader *sh, const struct ra_tex *ra_tex,
// For each iteration, compute the average at a given distance and
// pick it instead of the color if the difference is below the threshold.
for (int i = 1; i <= params->iterations; i++) {
GLSL("avg = %s(pos, %f, %s); \n"
"diff = abs(color - avg); \n"
"color = mix(avg, color, greaterThan(diff, vec4(%f))); \n",
GLSL("avg = %s(pos, %f, %s); \n"
"diff = abs(color - avg); \n"
"color = mix(avg, color, %s(greaterThan(diff, vec4(%f)))); \n",
average, i * params->radius, state,
params->threshold / (1000 * i));
sh_bvec(sh, 4), params->threshold / (1000 * i));
}
// Add some random noise to smooth out residual differences
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment