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>
struct GetColorFromTexel;
struct ColorFromTexel;
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) {
float2 p = AdjustTexelByAddress<address>(v.tex, v.tex_region);
if (v.tex_region[0] <= p.x &&
@ -133,7 +133,7 @@ struct GetColorFromTexel<FILTER_NEAREST, 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) {
constexpr sampler texture_sampler(filter::nearest);
const float2 texel_size = 1 / source_size;
@ -172,7 +172,7 @@ struct GetColorFromTexel<FILTER_LINEAR, 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) {
constexpr sampler texture_sampler(filter::nearest);
const float2 texel_size = 1 / source_size;
@ -193,14 +193,15 @@ struct GetColorFromTexel<FILTER_SCREEN, address> {
};
template<bool useColorM, uint8_t filter, uint8_t address>
float4 FragmentShaderImpl(
struct FragmentShaderImpl {
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) {
float4 c = GetColorFromTexel<filter, address>().Do(v, texture, source_size, scale);
float4 c = ColorFromTexel<filter, address>().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;
@ -212,7 +213,21 @@ float4 FragmentShaderImpl(
}
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.
// 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<useColorM, filter, address>( \
return FragmentShaderImpl<useColorM, filter, address>().Do( \
v, texture, source_size, color_matrix_body, color_matrix_translation, scale); \
}

View File

@ -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
}
`
)