From 3aa6eb3a66a623fba3371cfda8963a1ec9bdf4ff Mon Sep 17 00:00:00 2001 From: Hajime Hoshi Date: Sun, 17 Feb 2019 19:01:43 +0900 Subject: [PATCH] graphicsdriver: Optimize shaders for the case of FILTER_SCREEN Assume a color matrix or color vertex values are not used when the filter is FILTER_SCREEN. --- internal/graphicsdriver/metal/driver.go | 63 +++++++++++++++--------- internal/graphicsdriver/opengl/shader.go | 13 +++-- 2 files changed, 49 insertions(+), 27 deletions(-) diff --git a/internal/graphicsdriver/metal/driver.go b/internal/graphicsdriver/metal/driver.go index e53e7ebb4..2073996a9 100644 --- a/internal/graphicsdriver/metal/driver.go +++ b/internal/graphicsdriver/metal/driver.go @@ -115,10 +115,10 @@ inline float2 AdjustTexelByAddress(float2 p, float4 tex_region) } template -struct GetColorFromTexel; +struct ColorFromTexel; template -struct GetColorFromTexel { +struct ColorFromTexel { inline float4 Do(VertexOut v, texture2d texture, constant float2& source_size, float scale) { float2 p = AdjustTexelByAddress
(v.tex, v.tex_region); if (v.tex_region[0] <= p.x && @@ -133,7 +133,7 @@ struct GetColorFromTexel { }; template -struct GetColorFromTexel { +struct ColorFromTexel { inline float4 Do(VertexOut v, texture2d texture, constant float2& source_size, float scale) { constexpr sampler texture_sampler(filter::nearest); const float2 texel_size = 1 / source_size; @@ -172,7 +172,7 @@ struct GetColorFromTexel { }; template -struct GetColorFromTexel { +struct ColorFromTexel { inline float4 Do(VertexOut v, texture2d texture, constant float2& source_size, float scale) { constexpr sampler texture_sampler(filter::nearest); const float2 texel_size = 1 / source_size; @@ -193,26 +193,41 @@ struct GetColorFromTexel { }; template -float4 FragmentShaderImpl( - VertexOut v, - texture2d texture, - constant float2& source_size, - constant float4x4& color_matrix_body, - constant float4& color_matrix_translation, - constant float& scale) { - float4 c = GetColorFromTexel().Do(v, texture, source_size, scale); - if (useColorM) { - c.rgb /= c.a + (1.0 - sign(c.a)); - c = (color_matrix_body * c) + color_matrix_translation; - c *= v.color; - c.rgb *= c.a; - } else { - float4 s = v.color; - c *= float4(s.r, s.g, s.b, 1.0) * s.a; +struct FragmentShaderImpl { + inline float4 Do( + VertexOut v, + texture2d texture, + constant float2& source_size, + constant float4x4& color_matrix_body, + constant float4& color_matrix_translation, + constant float& scale) { + float4 c = ColorFromTexel().Do(v, texture, source_size, scale); + if (useColorM) { + c.rgb /= c.a + (1.0 - sign(c.a)); + c = (color_matrix_body * c) + color_matrix_translation; + c *= v.color; + c.rgb *= c.a; + } else { + float4 s = v.color; + c *= float4(s.r, s.g, s.b, 1.0) * s.a; + } + c = min(c, c.a); + return c; } - c = min(c, c.a); - return c; -} +}; + +template +struct FragmentShaderImpl { + inline float4 Do( + VertexOut v, + texture2d texture, + constant float2& source_size, + constant float4x4& color_matrix_body, + constant float4& color_matrix_translation, + constant float& scale) { + return ColorFromTexel().Do(v, texture, source_size, scale); + } +}; // Define Foo and FooCp macros to force macro replacement. // See "6.10.3.1 Argument substitution" in ISO/IEC 9899. @@ -228,7 +243,7 @@ float4 FragmentShaderImpl( constant float4x4& color_matrix_body [[buffer(3)]], \ constant float4& color_matrix_translation [[buffer(4)]], \ constant float& scale [[buffer(5)]]) { \ - return FragmentShaderImpl( \ + return FragmentShaderImpl().Do( \ v, texture, source_size, color_matrix_body, color_matrix_translation, scale); \ } diff --git a/internal/graphicsdriver/opengl/shader.go b/internal/graphicsdriver/opengl/shader.go index a4f44692f..8d52f3c9a 100644 --- a/internal/graphicsdriver/opengl/shader.go +++ b/internal/graphicsdriver/opengl/shader.go @@ -197,12 +197,13 @@ void main(void) { #if defined(FILTER_NEAREST) pos = adjustTexelByAddress(pos, varying_tex_region); - color = vec4(0, 0, 0, 0); if (varying_tex_region[0] <= pos.x && varying_tex_region[1] <= pos.y && pos.x < varying_tex_region[2] && pos.y < varying_tex_region[3]) { color = texture2D(texture, pos); + } else { + color = vec4(0, 0, 0, 0); } #endif @@ -240,6 +241,7 @@ void main(void) { #endif #if defined(FILTER_SCREEN) + highp vec2 p0 = pos - texel_size / 2.0 / scale; highp vec2 p1 = pos + texel_size / 2.0 / scale; @@ -253,8 +255,10 @@ void main(void) { vec2 rateCenter = vec2(1.0, 1.0) - texel_size / 2.0 / scale; vec2 rate = clamp(((fract(p0 * source_size) - rateCenter) * scale) + rateCenter, 0.0, 1.0); - color = mix(mix(c0, c1, rate.x), mix(c2, c3, rate.x), rate.y); -#endif + gl_FragColor = mix(mix(c0, c1, rate.x), mix(c2, c3, rate.x), rate.y); + // Assume that a color matrix and color vector values are not used with FILTER_SCREEN. + +#else #if defined(USE_COLOR_MATRIX) // Un-premultiply alpha. @@ -273,6 +277,9 @@ void main(void) { color = min(color, color.a); gl_FragColor = color; + +#endif + } ` )