[Impeller] Provide fragment uniform data through varyings for solid color, glyph atlas, texture shaders. (flutter/engine#43838)

From experimentation, providing these values through varyings runs substantially faster on Pixel devices. Alternative solutions to use f16 or push constants did not improve things substantially.

These subset of shaders are used very heavily and so they benefit from this change more substantially. I don't think this is applicable to all shaders as there is going to be an additional varying interpolation cost.

See also: [go/impeller-slow-fragment-shader](http://goto.google.com/impeller-slow-fragment-shader)
This commit is contained in:
Jonah Williams 2023-07-20 13:47:16 -07:00 committed by GitHub
parent a9eb2fe5f3
commit 949e91bbba
19 changed files with 303 additions and 273 deletions

View File

@ -9,6 +9,12 @@
#extension GL_AMD_gpu_shader_half_float_fetch : enable
#extension GL_EXT_shader_explicit_arithmetic_types_float16 : enable
#ifdef IMPELLER_TARGET_OPENGLES
#define IMPELLER_MAYBE_FLAT
#else
#define IMPELLER_MAYBE_FLAT flat
#endif
#ifndef IMPELLER_TARGET_METAL_IOS
precision mediump sampler2D;

View File

@ -338,16 +338,13 @@ bool AtlasTextureContents::Render(const ContentContext& renderer,
frame_info.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
entity.GetTransformation();
frame_info.texture_sampler_y_coord_scale = texture->GetYCoordScale();
FS::FragInfo frag_info;
frag_info.alpha = alpha_;
frame_info.alpha = alpha_;
auto options = OptionsFromPassAndEntity(pass, entity);
cmd.pipeline = renderer.GetTexturePipeline(options);
cmd.stencil_reference = entity.GetStencilDepth();
cmd.BindVertices(vertex_builder.CreateVertexBuffer(host_buffer));
VS::BindFrameInfo(cmd, host_buffer.EmplaceUniform(frame_info));
FS::BindFragInfo(cmd, host_buffer.EmplaceUniform(frag_info));
FS::BindTextureSampler(cmd, texture,
renderer.GetContext()->GetSamplerLibrary()->GetSampler(
parent_.GetSamplerDescriptor()));

View File

@ -80,16 +80,13 @@ bool ClipContents::Render(const ContentContext& renderer,
const Entity& entity,
RenderPass& pass) const {
using VS = ClipPipeline::VertexShader;
using FS = ClipPipeline::FragmentShader;
VS::FrameInfo info;
Command cmd;
FS::FragInfo frag_info;
// The color really doesn't matter.
frag_info.color = Color::SkyBlue();
FS::BindFragInfo(cmd, pass.GetTransientsBuffer().EmplaceUniform(frag_info));
info.color = Color::SkyBlue();
auto options = OptionsFromPassAndEntity(pass, entity);
cmd.stencil_reference = entity.GetStencilDepth();
@ -182,7 +179,6 @@ bool ClipRestoreContents::Render(const ContentContext& renderer,
const Entity& entity,
RenderPass& pass) const {
using VS = ClipPipeline::VertexShader;
using FS = ClipPipeline::FragmentShader;
Command cmd;
cmd.label = "Restore Clip";
@ -208,13 +204,9 @@ bool ClipRestoreContents::Render(const ContentContext& renderer,
VS::FrameInfo info;
info.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize());
info.color = Color::SkyBlue();
VS::BindFrameInfo(cmd, pass.GetTransientsBuffer().EmplaceUniform(info));
FS::FragInfo frag_info;
// The color really doesn't matter.
frag_info.color = Color::SkyBlue();
FS::BindFragInfo(cmd, pass.GetTransientsBuffer().EmplaceUniform(frag_info));
pass.AddCommand(std::move(cmd));
return true;
}

View File

@ -54,7 +54,6 @@ bool SolidColorContents::Render(const ContentContext& renderer,
const Entity& entity,
RenderPass& pass) const {
using VS = SolidFillPipeline::VertexShader;
using FS = SolidFillPipeline::FragmentShader;
Command cmd;
cmd.label = "Solid Fill";
@ -75,12 +74,9 @@ bool SolidColorContents::Render(const ContentContext& renderer,
VS::FrameInfo frame_info;
frame_info.mvp = geometry_result.transform;
frame_info.color = GetColor().Premultiply();
VS::BindFrameInfo(cmd, pass.GetTransientsBuffer().EmplaceUniform(frame_info));
FS::FragInfo frag_info;
frag_info.color = GetColor().Premultiply();
FS::BindFragInfo(cmd, pass.GetTransientsBuffer().EmplaceUniform(frag_info));
if (!pass.AddCommand(std::move(cmd))) {
return false;
}

View File

@ -125,6 +125,7 @@ bool TextContents::Render(const ContentContext& renderer,
frame_info.is_translation_scale =
entity.GetTransformation().IsTranslationScaleOnly();
frame_info.entity_transform = entity.GetTransformation();
frame_info.text_color = ToVector(color.Premultiply());
VS::BindFrameInfo(cmd, pass.GetTransientsBuffer().EmplaceUniform(frame_info));
@ -143,10 +144,6 @@ bool TextContents::Render(const ContentContext& renderer,
}
sampler_desc.mip_filter = MipFilter::kNearest;
FS::FragInfo frag_info;
frag_info.text_color = ToVector(color.Premultiply());
FS::BindFragInfo(cmd, pass.GetTransientsBuffer().EmplaceUniform(frag_info));
FS::BindGlyphAtlasSampler(
cmd, // command
atlas->GetTexture(), // texture

View File

@ -135,9 +135,7 @@ bool TextureContents::Render(const ContentContext& renderer,
frame_info.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
entity.GetTransformation();
frame_info.texture_sampler_y_coord_scale = texture_->GetYCoordScale();
FS::FragInfo frag_info;
frag_info.alpha = GetOpacity();
frame_info.alpha = GetOpacity();
Command cmd;
cmd.label = "Texture Fill";
@ -155,7 +153,6 @@ bool TextureContents::Render(const ContentContext& renderer,
cmd.stencil_reference = entity.GetStencilDepth();
cmd.BindVertices(vertex_builder.CreateVertexBuffer(host_buffer));
VS::BindFrameInfo(cmd, host_buffer.EmplaceUniform(frame_info));
FS::BindFragInfo(cmd, host_buffer.EmplaceUniform(frag_info));
FS::BindTextureSampler(cmd, texture_,
renderer.GetContext()->GetSamplerLibrary()->GetSampler(
sampler_descriptor_));

View File

@ -136,6 +136,7 @@ bool TiledTextureContents::Render(const ContentContext& renderer,
VS::FrameInfo frame_info;
frame_info.mvp = geometry_result.transform;
frame_info.texture_sampler_y_coord_scale = texture_->GetYCoordScale();
frame_info.alpha = GetOpacityFactor();
Command cmd;
cmd.label = uses_emulated_tile_mode ? "TiledTextureFill" : "TextureFill";
@ -158,13 +159,7 @@ bool TiledTextureContents::Render(const ContentContext& renderer,
FS::FragInfo frag_info;
frag_info.x_tile_mode = static_cast<Scalar>(x_tile_mode_);
frag_info.y_tile_mode = static_cast<Scalar>(y_tile_mode_);
frag_info.alpha = GetOpacityFactor();
FS::BindFragInfo(cmd, host_buffer.EmplaceUniform(frag_info));
} else {
TextureFillFragmentShader::FragInfo frag_info;
frag_info.alpha = GetOpacityFactor();
TextureFillFragmentShader::BindFragInfo(
cmd, host_buffer.EmplaceUniform(frag_info));
}
if (color_filter_) {

View File

@ -144,12 +144,9 @@ bool VerticesUVContents::Render(const ContentContext& renderer,
frame_info.mvp = geometry_result.transform;
frame_info.texture_sampler_y_coord_scale =
snapshot->texture->GetYCoordScale();
frame_info.alpha = alpha_ * snapshot->opacity;
VS::BindFrameInfo(cmd, host_buffer.EmplaceUniform(frame_info));
FS::FragInfo frag_info;
frag_info.alpha = alpha_ * snapshot->opacity;
FS::BindFragInfo(cmd, host_buffer.EmplaceUniform(frag_info));
FS::BindTextureSampler(cmd, snapshot->texture,
renderer.GetContext()->GetSamplerLibrary()->GetSampler(
snapshot->sampler_descriptor));

View File

@ -857,7 +857,6 @@ TEST_P(EntityTest, BlendingModeOptions) {
auto draw_rect = [&context, &pass, &world_matrix](
Rect rect, Color color, BlendMode blend_mode) -> bool {
using VS = SolidFillPipeline::VertexShader;
using FS = SolidFillPipeline::FragmentShader;
VertexBufferBuilder<VS::PerVertexData> vtx_builder;
{
@ -884,14 +883,10 @@ TEST_P(EntityTest, BlendingModeOptions) {
VS::FrameInfo frame_info;
frame_info.mvp =
Matrix::MakeOrthographic(pass.GetRenderTargetSize()) * world_matrix;
frame_info.color = color.Premultiply();
VS::BindFrameInfo(cmd,
pass.GetTransientsBuffer().EmplaceUniform(frame_info));
FS::FragInfo frag_info;
frag_info.color = color.Premultiply();
FS::BindFragInfo(cmd,
pass.GetTransientsBuffer().EmplaceUniform(frag_info));
return pass.AddCommand(std::move(cmd));
};

View File

@ -8,16 +8,13 @@ precision mediump float;
uniform f16sampler2D glyph_atlas_sampler;
uniform FragInfo {
f16vec4 text_color;
}
frag_info;
in highp vec2 v_uv;
IMPELLER_MAYBE_FLAT in f16vec4 v_text_color;
out f16vec4 frag_color;
void main() {
f16vec4 value = texture(glyph_atlas_sampler, v_uv);
frag_color = value.aaaa * frag_info.text_color;
frag_color = value.aaaa * v_text_color;
}

View File

@ -3,12 +3,14 @@
// found in the LICENSE file.
#include <impeller/transform.glsl>
#include <impeller/types.glsl>
uniform FrameInfo {
mat4 mvp;
mat4 entity_transform;
vec2 atlas_size;
vec2 offset;
f16vec4 text_color;
float is_translation_scale;
}
frame_info;
@ -23,6 +25,8 @@ in vec2 glyph_position;
out vec2 v_uv;
IMPELLER_MAYBE_FLAT out f16vec4 v_text_color;
mat4 basis(mat4 m) {
return mat4(m[0][0], m[0][1], m[0][2], 0.0, //
m[1][0], m[1][1], m[1][2], 0.0, //
@ -77,4 +81,5 @@ void main() {
gl_Position = frame_info.mvp * position;
v_uv = uv_origin + unit_position * uv_size;
v_text_color = frame_info.text_color;
}

View File

@ -8,16 +8,13 @@ precision mediump float;
uniform f16sampler2D glyph_atlas_sampler;
uniform FragInfo {
f16vec4 text_color;
}
frag_info;
in highp vec2 v_uv;
IMPELLER_MAYBE_FLAT in f16vec4 v_text_color;
out f16vec4 frag_color;
void main() {
f16vec4 value = texture(glyph_atlas_sampler, v_uv);
frag_color = value * frag_info.text_color.aaaa;
frag_color = value * v_text_color.aaaa;
}

View File

@ -6,13 +6,10 @@ precision mediump float;
#include <impeller/types.glsl>
uniform FragInfo {
f16vec4 color;
}
frag_info;
IMPELLER_MAYBE_FLAT in f16vec4 v_color;
out f16vec4 frag_color;
void main() {
frag_color = frag_info.color;
frag_color = v_color;
}

View File

@ -6,11 +6,15 @@
uniform FrameInfo {
mat4 mvp;
f16vec4 color;
}
frame_info;
in vec2 position;
IMPELLER_MAYBE_FLAT out f16vec4 v_color;
void main() {
v_color = frame_info.color;
gl_Position = frame_info.mvp * vec4(position, 0.0, 1.0);
}

View File

@ -9,17 +9,13 @@ precision mediump float;
uniform f16sampler2D texture_sampler;
uniform FragInfo {
float16_t alpha;
}
frag_info;
in highp vec2 v_texture_coords;
IMPELLER_MAYBE_FLAT in float16_t v_alpha;
out f16vec4 frag_color;
void main() {
f16vec4 sampled =
texture(texture_sampler, v_texture_coords, kDefaultMipBiasHalf);
frag_color = sampled * frag_info.alpha;
frag_color = sampled * v_alpha;
}

View File

@ -8,6 +8,7 @@
uniform FrameInfo {
mat4 mvp;
float texture_sampler_y_coord_scale;
float16_t alpha;
}
frame_info;
@ -15,9 +16,11 @@ in vec2 position;
in vec2 texture_coords;
out vec2 v_texture_coords;
IMPELLER_MAYBE_FLAT out float16_t v_alpha;
void main() {
gl_Position = frame_info.mvp * vec4(position, 0.0, 1.0);
v_alpha = frame_info.alpha;
v_texture_coords =
IPRemapCoords(texture_coords, frame_info.texture_sampler_y_coord_scale);
}

View File

@ -12,11 +12,11 @@ uniform f16sampler2D texture_sampler;
uniform FragInfo {
float16_t x_tile_mode;
float16_t y_tile_mode;
float16_t alpha;
}
frag_info;
in highp vec2 v_texture_coords;
IMPELLER_MAYBE_FLAT in float16_t v_alpha;
out f16vec4 frag_color;
@ -27,5 +27,5 @@ void main() {
frag_info.x_tile_mode, // x tile mode
frag_info.y_tile_mode // y tile mode
) *
frag_info.alpha;
v_alpha;
}

View File

@ -131,7 +131,6 @@ TEST_P(ComputeSubgroupTest, PathPlayground) {
}
using VS = SolidFillPipeline::VertexShader;
using FS = SolidFillPipeline::FragmentShader;
Command cmd;
cmd.label = "Draw Stroke";
@ -164,13 +163,10 @@ TEST_P(ComputeSubgroupTest, PathPlayground) {
auto world_matrix = Matrix::MakeScale(GetContentScale());
frame_info.mvp =
Matrix::MakeOrthographic(pass.GetRenderTargetSize()) * world_matrix;
frame_info.color = Color::Red().Premultiply();
VS::BindFrameInfo(cmd,
pass.GetTransientsBuffer().EmplaceUniform(frame_info));
FS::FragInfo frag_info;
frag_info.color = Color::Red().Premultiply();
FS::BindFragInfo(cmd, pass.GetTransientsBuffer().EmplaceUniform(frag_info));
if (!pass.AddCommand(std::move(cmd))) {
return false;
}
@ -339,7 +335,6 @@ TEST_P(ComputeSubgroupTest, LargePath) {
}
using VS = SolidFillPipeline::VertexShader;
using FS = SolidFillPipeline::FragmentShader;
Command cmd;
cmd.label = "Draw Stroke";
@ -372,13 +367,10 @@ TEST_P(ComputeSubgroupTest, LargePath) {
auto world_matrix = Matrix::MakeScale(GetContentScale());
frame_info.mvp =
Matrix::MakeOrthographic(pass.GetRenderTargetSize()) * world_matrix;
frame_info.color = Color::Red().Premultiply();
VS::BindFrameInfo(cmd,
pass.GetTransientsBuffer().EmplaceUniform(frame_info));
FS::FragInfo frag_info;
frag_info.color = Color::Red().Premultiply();
FS::BindFragInfo(cmd, pass.GetTransientsBuffer().EmplaceUniform(frag_info));
if (!pass.AddCommand(std::move(cmd))) {
return false;
}
@ -427,7 +419,6 @@ TEST_P(ComputeSubgroupTest, QuadAndCubicInOnePath) {
}
using VS = SolidFillPipeline::VertexShader;
using FS = SolidFillPipeline::FragmentShader;
Command cmd;
cmd.label = "Draw Stroke";
@ -460,13 +451,10 @@ TEST_P(ComputeSubgroupTest, QuadAndCubicInOnePath) {
auto world_matrix = Matrix::MakeScale(GetContentScale());
frame_info.mvp =
Matrix::MakeOrthographic(pass.GetRenderTargetSize()) * world_matrix;
frame_info.color = Color::Red().Premultiply();
VS::BindFrameInfo(cmd,
pass.GetTransientsBuffer().EmplaceUniform(frame_info));
FS::FragInfo frag_info;
frag_info.color = Color::Red().Premultiply();
FS::BindFragInfo(cmd, pass.GetTransientsBuffer().EmplaceUniform(frag_info));
if (!pass.AddCommand(std::move(cmd))) {
return false;
}

File diff suppressed because it is too large Load Diff