GLES2 / GLES3 - Use gl_FragColor temporary
On some hardware, modifying gl_FragColor multiple times can cause large performance drops. This PR writes to a standard temporary variable instead, and copies across to gl_FragColor once only at the end of the fragment shader. This could potentially lead to large gains in performance on affected hardware.
This commit is contained in:
parent
23c142afe7
commit
ed3d029f5d
6 changed files with 51 additions and 25 deletions
|
@ -126,6 +126,13 @@ uniform float camera_z_far;
|
|||
uniform float camera_z_near;
|
||||
|
||||
void main() {
|
||||
// Instead of writing directly to gl_FragColor,
|
||||
// we use an intermediate, and only write
|
||||
// to gl_FragColor ONCE at the end of the shader.
|
||||
// This is because some hardware can have huge
|
||||
// slowdown if you modify gl_FragColor multiple times.
|
||||
vec4 frag_color;
|
||||
|
||||
#ifdef GLOW_GAUSSIAN_HORIZONTAL
|
||||
vec2 pix_size = pixel_size;
|
||||
pix_size *= 0.5; //reading from larger buffer, so use more samples
|
||||
|
@ -164,7 +171,7 @@ void main() {
|
|||
#endif //USE_GLOW_HIGH_QUALITY
|
||||
|
||||
color *= glow_strength;
|
||||
gl_FragColor = color;
|
||||
frag_color = color;
|
||||
#endif //GLOW_GAUSSIAN_HORIZONTAL
|
||||
|
||||
#ifdef GLOW_GAUSSIAN_VERTICAL
|
||||
|
@ -174,7 +181,7 @@ void main() {
|
|||
color += texture2DLod(source_color, uv_interp + vec2(0.0, -1.0) * pixel_size, lod) * 0.233062;
|
||||
color += texture2DLod(source_color, uv_interp + vec2(0.0, -2.0) * pixel_size, lod) * 0.122581;
|
||||
color *= glow_strength;
|
||||
gl_FragColor = color;
|
||||
frag_color = color;
|
||||
#endif
|
||||
|
||||
#ifndef USE_GLES_OVER_GL
|
||||
|
@ -280,7 +287,7 @@ void main() {
|
|||
color_accum /= k_accum;
|
||||
}
|
||||
|
||||
gl_FragColor = color_accum; ///k_accum;
|
||||
frag_color = color_accum; ///k_accum;
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -329,16 +336,17 @@ void main() {
|
|||
}
|
||||
color_accum.a = max(color_accum.a, sqrt(max_accum));
|
||||
|
||||
gl_FragColor = color_accum;
|
||||
frag_color = color_accum;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef GLOW_FIRST_PASS
|
||||
|
||||
float luminance = max(gl_FragColor.r, max(gl_FragColor.g, gl_FragColor.b));
|
||||
float luminance = max(frag_color.r, max(frag_color.g, frag_color.b));
|
||||
float feedback = max(smoothstep(glow_hdr_threshold, glow_hdr_threshold + glow_hdr_scale, luminance), glow_bloom);
|
||||
|
||||
gl_FragColor = min(gl_FragColor * feedback, vec4(luminance_cap));
|
||||
frag_color = min(frag_color * feedback, vec4(luminance_cap));
|
||||
|
||||
#endif
|
||||
gl_FragColor = frag_color;
|
||||
}
|
||||
|
|
|
@ -2380,11 +2380,18 @@ FRAGMENT_SHADER_CODE
|
|||
|
||||
#endif // !USE_SHADOW_TO_OPACITY
|
||||
|
||||
// Instead of writing directly to gl_FragColor,
|
||||
// we use an intermediate, and only write
|
||||
// to gl_FragColor ONCE at the end of the shader.
|
||||
// This is because some hardware can have huge
|
||||
// slowdown if you modify gl_FragColor multiple times.
|
||||
vec4 frag_color;
|
||||
|
||||
#ifndef RENDER_DEPTH
|
||||
|
||||
#ifdef SHADELESS
|
||||
|
||||
gl_FragColor = vec4(albedo, alpha);
|
||||
frag_color = vec4(albedo, alpha);
|
||||
#else
|
||||
|
||||
ambient_light *= albedo;
|
||||
|
@ -2399,13 +2406,13 @@ FRAGMENT_SHADER_CODE
|
|||
diffuse_light *= 1.0 - metallic;
|
||||
ambient_light *= 1.0 - metallic;
|
||||
|
||||
gl_FragColor = vec4(ambient_light + diffuse_light + specular_light, alpha);
|
||||
frag_color = vec4(ambient_light + diffuse_light + specular_light, alpha);
|
||||
|
||||
//add emission if in base pass
|
||||
#ifdef BASE_PASS
|
||||
gl_FragColor.rgb += emission;
|
||||
frag_color.rgb += emission;
|
||||
#endif
|
||||
// gl_FragColor = vec4(normal, 1.0);
|
||||
// frag_color = vec4(normal, 1.0);
|
||||
|
||||
//apply fog
|
||||
#if defined(FOG_DEPTH_ENABLED) || defined(FOG_HEIGHT_ENABLED)
|
||||
|
@ -2413,9 +2420,9 @@ FRAGMENT_SHADER_CODE
|
|||
#if defined(USE_VERTEX_LIGHTING)
|
||||
|
||||
#if defined(BASE_PASS)
|
||||
gl_FragColor.rgb = mix(gl_FragColor.rgb, fog_interp.rgb, fog_interp.a);
|
||||
frag_color.rgb = mix(frag_color.rgb, fog_interp.rgb, fog_interp.a);
|
||||
#else
|
||||
gl_FragColor.rgb *= (1.0 - fog_interp.a);
|
||||
frag_color.rgb *= (1.0 - fog_interp.a);
|
||||
#endif // BASE_PASS
|
||||
|
||||
#else //pixel based fog
|
||||
|
@ -2436,7 +2443,7 @@ FRAGMENT_SHADER_CODE
|
|||
fog_amount = pow(fog_z, fog_depth_curve) * fog_color_base.a;
|
||||
|
||||
if (fog_transmit_enabled) {
|
||||
vec3 total_light = gl_FragColor.rgb;
|
||||
vec3 total_light = frag_color.rgb;
|
||||
float transmit = pow(fog_z, fog_transmit_curve);
|
||||
fog_color = mix(max(total_light, fog_color), fog_color, transmit);
|
||||
}
|
||||
|
@ -2451,9 +2458,9 @@ FRAGMENT_SHADER_CODE
|
|||
#endif
|
||||
|
||||
#if defined(BASE_PASS)
|
||||
gl_FragColor.rgb = mix(gl_FragColor.rgb, fog_color, fog_amount);
|
||||
frag_color.rgb = mix(frag_color.rgb, fog_color, fog_amount);
|
||||
#else
|
||||
gl_FragColor.rgb *= (1.0 - fog_amount);
|
||||
frag_color.rgb *= (1.0 - fog_amount);
|
||||
#endif // BASE_PASS
|
||||
|
||||
#endif //use vertex lit
|
||||
|
@ -2464,7 +2471,7 @@ FRAGMENT_SHADER_CODE
|
|||
|
||||
#ifdef OUTPUT_LINEAR
|
||||
// sRGB -> linear
|
||||
gl_FragColor.rgb = mix(pow((gl_FragColor.rgb + vec3(0.055)) * (1.0 / (1.0 + 0.055)), vec3(2.4)), gl_FragColor.rgb * (1.0 / 12.92), vec3(lessThan(gl_FragColor.rgb, vec3(0.04045))));
|
||||
frag_color.rgb = mix(pow((frag_color.rgb + vec3(0.055)) * (1.0 / (1.0 + 0.055)), vec3(2.4)), frag_color.rgb * (1.0 / 12.92), vec3(lessThan(frag_color.rgb, vec3(0.04045))));
|
||||
#endif
|
||||
|
||||
#else // not RENDER_DEPTH
|
||||
|
@ -2474,8 +2481,10 @@ FRAGMENT_SHADER_CODE
|
|||
highp float depth = ((position_interp.z / position_interp.w) + 1.0) * 0.5 + 0.0; // bias
|
||||
highp vec4 comp = fract(depth * vec4(255.0 * 255.0 * 255.0, 255.0 * 255.0, 255.0, 1.0));
|
||||
comp -= comp.xxyz * vec4(0.0, 1.0 / 255.0, 1.0 / 255.0, 1.0 / 255.0);
|
||||
gl_FragColor = comp;
|
||||
frag_color = comp;
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
gl_FragColor = frag_color;
|
||||
}
|
||||
|
|
|
@ -376,9 +376,9 @@ void main() {
|
|||
color.rgb = apply_color_correction(color.rgb, color_correction);
|
||||
#endif
|
||||
|
||||
gl_FragColor = color;
|
||||
|
||||
#ifdef DISABLE_ALPHA
|
||||
gl_FragColor.a = 1.0;
|
||||
color.a = 1.0;
|
||||
#endif
|
||||
|
||||
gl_FragColor = color;
|
||||
}
|
||||
|
|
|
@ -41,7 +41,8 @@ uniform sampler2D source_ssao; //texunit:1
|
|||
uniform float lod;
|
||||
uniform vec2 pixel_size;
|
||||
|
||||
layout(location = 0) out vec4 frag_color;
|
||||
layout(location = 0) out vec4 frag_color_final;
|
||||
vec4 frag_color;
|
||||
|
||||
#ifdef SSAO_MERGE
|
||||
|
||||
|
@ -315,4 +316,5 @@ void main() {
|
|||
frag_color = vec4(mix(color.rgb, color.rgb * mix(ssao_color.rgb, vec3(1.0), ssao), color.a), 1.0);
|
||||
|
||||
#endif
|
||||
frag_color_final = frag_color;
|
||||
}
|
||||
|
|
|
@ -911,7 +911,8 @@ uniform highp sampler2D screen_texture; // texunit:-8
|
|||
|
||||
#endif
|
||||
|
||||
layout(location = 0) out vec4 frag_color;
|
||||
layout(location = 0) out vec4 frag_color_final;
|
||||
vec4 frag_color;
|
||||
|
||||
#ifdef USE_MULTIPLE_RENDER_TARGETS //ubershader-skip
|
||||
|
||||
|
@ -2447,6 +2448,12 @@ FRAGMENT_SHADER_CODE
|
|||
#endif //ubershader-runtime
|
||||
#endif //SHADELESS //ubershader-runtime
|
||||
|
||||
// Write to the final output once and only once.
|
||||
// Use a temporary in the rest of the shader.
|
||||
// This is for drivers that have a performance drop
|
||||
// when the output is read during the shader.
|
||||
frag_color_final = frag_color;
|
||||
|
||||
#endif //USE_MULTIPLE_RENDER_TARGETS //ubershader-runtime
|
||||
|
||||
#endif //RENDER_DEPTH //ubershader-runtime
|
||||
|
|
|
@ -507,9 +507,9 @@ void main() {
|
|||
color.rgb += screen_space_dither(gl_FragCoord.xy);
|
||||
#endif
|
||||
|
||||
frag_color = color;
|
||||
|
||||
#ifdef DISABLE_ALPHA
|
||||
frag_color.a = 1.0;
|
||||
color.a = 1.0;
|
||||
#endif
|
||||
|
||||
frag_color = color;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue