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.
This commit is contained in:
Hajime Hoshi 2019-02-17 19:01:43 +09:00
parent cbb0a1da95
commit 3aa6eb3a66
2 changed files with 49 additions and 27 deletions

View File

@ -115,10 +115,10 @@ inline float2 AdjustTexelByAddress<ADDRESS_REPEAT>(float2 p, float4 tex_region)
} }
template<uint8_t filter, uint8_t address> template<uint8_t filter, uint8_t address>
struct GetColorFromTexel; struct ColorFromTexel;
template<uint8_t address> template<uint8_t address>
struct GetColorFromTexel<FILTER_NEAREST, address> { struct ColorFromTexel<FILTER_NEAREST, address> {
inline float4 Do(VertexOut v, texture2d<float> texture, constant float2& source_size, float scale) { inline float4 Do(VertexOut v, texture2d<float> texture, constant float2& source_size, float scale) {
float2 p = AdjustTexelByAddress<address>(v.tex, v.tex_region); float2 p = AdjustTexelByAddress<address>(v.tex, v.tex_region);
if (v.tex_region[0] <= p.x && if (v.tex_region[0] <= p.x &&
@ -133,7 +133,7 @@ struct GetColorFromTexel<FILTER_NEAREST, address> {
}; };
template<uint8_t address> template<uint8_t address>
struct GetColorFromTexel<FILTER_LINEAR, address> { struct ColorFromTexel<FILTER_LINEAR, address> {
inline float4 Do(VertexOut v, texture2d<float> texture, constant float2& source_size, float scale) { inline float4 Do(VertexOut v, texture2d<float> texture, constant float2& source_size, float scale) {
constexpr sampler texture_sampler(filter::nearest); constexpr sampler texture_sampler(filter::nearest);
const float2 texel_size = 1 / source_size; const float2 texel_size = 1 / source_size;
@ -172,7 +172,7 @@ struct GetColorFromTexel<FILTER_LINEAR, address> {
}; };
template<uint8_t address> template<uint8_t address>
struct GetColorFromTexel<FILTER_SCREEN, address> { struct ColorFromTexel<FILTER_SCREEN, address> {
inline float4 Do(VertexOut v, texture2d<float> texture, constant float2& source_size, float scale) { inline float4 Do(VertexOut v, texture2d<float> texture, constant float2& source_size, float scale) {
constexpr sampler texture_sampler(filter::nearest); constexpr sampler texture_sampler(filter::nearest);
const float2 texel_size = 1 / source_size; const float2 texel_size = 1 / source_size;
@ -193,26 +193,41 @@ struct GetColorFromTexel<FILTER_SCREEN, address> {
}; };
template<bool useColorM, uint8_t filter, uint8_t address> template<bool useColorM, uint8_t filter, uint8_t address>
float4 FragmentShaderImpl( struct FragmentShaderImpl {
VertexOut v, inline float4 Do(
texture2d<float> texture, VertexOut v,
constant float2& source_size, texture2d<float> texture,
constant float4x4& color_matrix_body, constant float2& source_size,
constant float4& color_matrix_translation, constant float4x4& color_matrix_body,
constant float& scale) { constant float4& color_matrix_translation,
float4 c = GetColorFromTexel<filter, address>().Do(v, texture, source_size, scale); constant float& scale) {
if (useColorM) { float4 c = ColorFromTexel<filter, address>().Do(v, texture, source_size, scale);
c.rgb /= c.a + (1.0 - sign(c.a)); if (useColorM) {
c = (color_matrix_body * c) + color_matrix_translation; c.rgb /= c.a + (1.0 - sign(c.a));
c *= v.color; c = (color_matrix_body * c) + color_matrix_translation;
c.rgb *= c.a; c *= v.color;
} else { c.rgb *= c.a;
float4 s = v.color; } else {
c *= float4(s.r, s.g, s.b, 1.0) * s.a; 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<bool useColorM, uint8_t address>
struct FragmentShaderImpl<useColorM, FILTER_SCREEN, address> {
inline float4 Do(
VertexOut v,
texture2d<float> texture,
constant float2& source_size,
constant float4x4& color_matrix_body,
constant float4& color_matrix_translation,
constant float& scale) {
return ColorFromTexel<FILTER_SCREEN, address>().Do(v, texture, source_size, scale);
}
};
// Define Foo and FooCp macros to force macro replacement. // Define Foo and FooCp macros to force macro replacement.
// See "6.10.3.1 Argument substitution" in ISO/IEC 9899. // 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 float4x4& color_matrix_body [[buffer(3)]], \
constant float4& color_matrix_translation [[buffer(4)]], \ constant float4& color_matrix_translation [[buffer(4)]], \
constant float& scale [[buffer(5)]]) { \ constant float& scale [[buffer(5)]]) { \
return FragmentShaderImpl<useColorM, filter, address>( \ return FragmentShaderImpl<useColorM, filter, address>().Do( \
v, texture, source_size, color_matrix_body, color_matrix_translation, scale); \ v, texture, source_size, color_matrix_body, color_matrix_translation, scale); \
} }

View File

@ -197,12 +197,13 @@ void main(void) {
#if defined(FILTER_NEAREST) #if defined(FILTER_NEAREST)
pos = adjustTexelByAddress(pos, varying_tex_region); pos = adjustTexelByAddress(pos, varying_tex_region);
color = vec4(0, 0, 0, 0);
if (varying_tex_region[0] <= pos.x && if (varying_tex_region[0] <= pos.x &&
varying_tex_region[1] <= pos.y && varying_tex_region[1] <= pos.y &&
pos.x < varying_tex_region[2] && pos.x < varying_tex_region[2] &&
pos.y < varying_tex_region[3]) { pos.y < varying_tex_region[3]) {
color = texture2D(texture, pos); color = texture2D(texture, pos);
} else {
color = vec4(0, 0, 0, 0);
} }
#endif #endif
@ -240,6 +241,7 @@ void main(void) {
#endif #endif
#if defined(FILTER_SCREEN) #if defined(FILTER_SCREEN)
highp vec2 p0 = pos - texel_size / 2.0 / scale; highp vec2 p0 = pos - texel_size / 2.0 / scale;
highp vec2 p1 = 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 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); 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); gl_FragColor = mix(mix(c0, c1, rate.x), mix(c2, c3, rate.x), rate.y);
#endif // Assume that a color matrix and color vector values are not used with FILTER_SCREEN.
#else
#if defined(USE_COLOR_MATRIX) #if defined(USE_COLOR_MATRIX)
// Un-premultiply alpha. // Un-premultiply alpha.
@ -273,6 +277,9 @@ void main(void) {
color = min(color, color.a); color = min(color, color.a);
gl_FragColor = color; gl_FragColor = color;
#endif
} }
` `
) )