Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Impeller] use SSBOs for gradients where supported (metal/vulkan) #37654

Merged
merged 17 commits into from
Nov 18, 2022

Conversation

jonahwilliams
Copy link
Member

@jonahwilliams jonahwilliams commented Nov 16, 2022

Use SSBO to pass the gradient color buffer to the shader, which dramatically improves performance for small gradients. When creating this color buffer, reusing the existing color buffer if the stops are even.

Fixes flutter/flutter#115208 (for iOS).
Fixes flutter/flutter#115523

On Android, any usage of arrays in the fragment shaders leads to a link error with no other messages. Assuming that we're using the gles fragment shaders, I'm not really sure what the issue is exactly - but I assume this has something to do with targeting gles 2.0.

@jonahwilliams jonahwilliams changed the title [Impeller] used fixed size array for small gradients [Impeller] used fixed size array for small gradients on iOS Nov 17, 2022
@jonahwilliams jonahwilliams marked this pull request as ready for review November 17, 2022 02:08
@jonahwilliams
Copy link
Member Author

I have mixed feelings about how I've currently handled the lack of support for this on Android, but also zoom zoom go fast.

@jonahwilliams jonahwilliams marked this pull request as draft November 17, 2022 02:48
@jonahwilliams
Copy link
Member Author

Converting to draft, we should use SSBOs for this

@jonahwilliams jonahwilliams changed the title [Impeller] used fixed size array for small gradients on iOS [Impeller] used SSBOs gradients where supported Nov 17, 2022
@jonahwilliams jonahwilliams changed the title [Impeller] used SSBOs gradients where supported [Impeller] use SSBOs gradients where supported Nov 17, 2022
@@ -66,6 +66,20 @@ impeller_shaders("entity_shaders") {
]
}

impeller_shaders("modern_entity_shaders") {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This almost works, except that I fail to load the fixed_fill shaders at runtime. I suspect something somewhere is hard coded but I haven't found it. If I place these shaders in the entity shaders set (and force the gles_language version to 460 everywhere) it works as expected

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

@@ -150,13 +150,26 @@ ContentContext::ContentContext(std::shared_ptr<Context> context)
if (!context_ || !context_->IsValid()) {
return;
}
#ifdef FML_OS_ANDROID
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TBD: actual feature selection when we have vulkan support

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider having a define for IMPELLER_SUPPORT_SSBO that's just IMPELLER_ENABLE_METAL || IMPELLER_ENABLE_VULKAN. Or just use the more verbose one here. You'll need some runtime detection, so an update to the Context object to have some method or struct or something that says whether SSBOs are allowed.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh I see some of the runtime stuff is started.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to leave this as runtime support as far as I can tell, once Vulkan is on by default. Avoids literring the code base with ifdefs too

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we have this on on impeller::Context instead? You can ask the context for its feature set. That way, only ES will return the legacy stuff.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

/// @brief Lowest common denominator feature sets.
constexpr BackendFeatures kLegacyBackendFeatures = {.ssbo_support = false};

} // namespace impeller
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Newline at EOF.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done


/// @brief A struct for describing available backend features for runtime
/// selection.
struct BackendFeatures {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I was thinking of this being an enum with the modern stuff implying SSBO support. But this is way better.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@@ -150,13 +150,26 @@ ContentContext::ContentContext(std::shared_ptr<Context> context)
if (!context_ || !context_->IsValid()) {
return;
}
#ifdef FML_OS_ANDROID
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we have this on on impeller::Context instead? You can ask the context for its feature set. That way, only ES will return the legacy stuff.

@@ -1285,6 +1286,7 @@ FILE: ../../../flutter/impeller/entity/shaders/glyph_atlas_sdf.frag
FILE: ../../../flutter/impeller/entity/shaders/glyph_atlas_sdf.vert
FILE: ../../../flutter/impeller/entity/shaders/gradient_fill.vert
FILE: ../../../flutter/impeller/entity/shaders/linear_gradient_fill.frag
FILE: ../../../flutter/impeller/entity/shaders/linear_gradient_fixed_fill.frag
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lets call this ssbo_fill perhaps?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@@ -45,10 +45,14 @@ static CompilerBackend CreateGLSLCompiler(const spirv_cross::ParsedIR& ir,
sl_options.force_zero_initialized_variables = true;
sl_options.vertex.fixup_clipspace = true;
if (source_options.target_platform == TargetPlatform::kOpenGLES) {
sl_options.version = 100;
sl_options.version = source_options.gles_language_version > 0
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we should do source language selection based on #version directives now instead of applying command line options. Omitting them was fine when we only had a single version.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that sounds reasonable, but I'm not quite sure how to make make shaderc and spirvcross work together on this. I'll file a bug

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@@ -141,3 +158,4 @@ inline ::testing::AssertionResult ColorBufferNear(
#define ASSERT_SIZE_NEAR(a, b) ASSERT_PRED2(&::SizeNear, a, b)
#define ASSERT_ARRAY_4_NEAR(a, b) ASSERT_PRED2(&::Array4Near, a, b)
#define ASSERT_COLOR_BUFFER_NEAR(a, b) ASSERT_PRED2(&::ColorBufferNear, a, b)
#define ASSERT_COLORS_NEAR(a, b) ASSERT_PRED2(&::ColorsNear, a, b)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Newline at EOF.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@chinmaygarde
Copy link
Member

For clarity, where we support SSBOs, there is no case where we need to use the texture upload thingy right?

@jonahwilliams
Copy link
Member Author

For clarity, where we support SSBOs, there is no case where we need to use the texture upload thingy right?

Not that I can tell.

for (size_t i = 1; i < stops.size(); i++) {
auto value = stops[i] - stops[i - 1];
// Smaller than kEhCloseEnough
if (value < 0.0001) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Curious, why not just use the constant instead of hardcoding the value?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

context was sort of #36218

TLDR, if you have really close stops you need a smaller number

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in the future, we'll need to stop computing the gradients on the CPU for certain stop values

@chinmaygarde
Copy link
Member

Using purely the SSBO approach on Metal and following up with the jumbo textures thing on legacy backends sounds good to me.

I reviewed the rest of the patch and it looks good to me barring the comments (mostly nits) already added. lgtm after it moves out of draft status.

@jonahwilliams
Copy link
Member Author

Needs more tests still, and need to figure out why I can't find the shaders at runtime

@jonahwilliams
Copy link
Member Author

Fun times:

gen/flutter/impeller/entity/radial_gradient_ssbo_fill.frag.cc(22,1): error: static assertion failed due to requirement 'sizeof(impeller::RadialGradientSsboFillFragmentShader::ColorData<0>) == 0'
static_assert(sizeof(Shader::ColorData<0>) == 0);
^             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
gen/flutter/impeller/entity/radial_gradient_ssbo_fill.frag.cc(22,44): note: expression evaluates to '4 == 0'
static_assert(sizeof(Shader::ColorData<0>) == 0);

@jonahwilliams jonahwilliams marked this pull request as ready for review November 17, 2022 21:07
@@ -202,7 +202,6 @@ using Shader = {{camel_case(shader_name)}}{{camel_case(shader_stage)}}Shader;
// Sanity checks for {{def.name}}
{% if last(def.members).array_elements == 0 %}
static_assert(std::is_standard_layout_v<Shader::{{def.name}}<0>>);
static_assert(sizeof(Shader::{{def.name}}<0>) == {{def.byte_length}});
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This assert appears to be invalid on windows hosts, which claim this always has a sizeof 4.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I suppose having platform specific differences here is possible. Was the shader name in the generated shaders correct though?

@jonahwilliams jonahwilliams changed the title [Impeller] use SSBOs gradients where supported [Impeller] use SSBOs for gradients where supported (metal/vulkan) Nov 17, 2022
@jonahwilliams
Copy link
Member Author

This is ready 😄

@@ -202,7 +202,6 @@ using Shader = {{camel_case(shader_name)}}{{camel_case(shader_stage)}}Shader;
// Sanity checks for {{def.name}}
{% if last(def.members).array_elements == 0 %}
static_assert(std::is_standard_layout_v<Shader::{{def.name}}<0>>);
static_assert(sizeof(Shader::{{def.name}}<0>) == {{def.byte_length}});
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I suppose having platform specific differences here is possible. Was the shader name in the generated shaders correct though?

@jonahwilliams
Copy link
Member Author

Yes all of the generated code worked correctly. Though TBH I didn't find a way to use the struct generated for the SSBO, since it is dynamically sized - so I ended up creating a BufferView myself. I think that is OK though

@jonahwilliams jonahwilliams added the autosubmit Merge PR when tree becomes green via auto submit App label Nov 18, 2022
@auto-submit auto-submit bot merged commit aeb2cd9 into flutter:main Nov 18, 2022
@jonahwilliams jonahwilliams deleted the ssbo_gradient branch November 18, 2022 19:02
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Nov 18, 2022
auto-submit bot pushed a commit to flutter/flutter that referenced this pull request Nov 18, 2022
…115672)

* a76ec9158 Roll Fuchsia Linux SDK from lnmSnyJi-2H07tBnV... to WdtwlLEce90PjFJ9z... (flutter/engine#37747)

* 44e2f5854 [Impeller] Change texture upload pipeline in Vulkan (flutter/engine#37623)

* 6a3ad3c14 Roll Skia from 345bceacd298 to 5270b1d26b5f (4 revisions) (flutter/engine#37748)

* 01271891c Do not abort if a MultiFrameCodec is unable to allocate a bitmap buffer (flutter/engine#37534)

* 54232a4c3 Roll Skia from 5270b1d26b5f to cf967e6b1c00 (5 revisions) (flutter/engine#37751)

* 30aa3cc38 [fuchsia][a11y] Set explicit hit regions in flatland embedder (flutter/engine#37338)

* da07c33d2 Make NotifyIdle reject close and past deadlines. (flutter/engine#37737)

* e3844cc1e Add third_party/dart/third_party/binaryen/src as a dependency (flutter/engine#37749)

* aeb2cd95b [Impeller] use SSBOs for gradients where supported (metal/vulkan) (flutter/engine#37654)

* e8aa1c192 Roll Skia from cf967e6b1c00 to f1f59de17204 (2 revisions) (flutter/engine#37756)

* 4311774fb [Impeller] register modern shaders on Vulkan too (flutter/engine#37757)

* 8e4a718d0 Made FlutterTextField that outlive FlutterTextPlatformNode not crash (flutter/engine#37735)

* 446a09dfc [macOS] Use consistent filenames for tests (flutter/engine#37755)

* 7a390f97c Roll Skia from f1f59de17204 to 12f01bc5b57e (1 revision) (flutter/engine#37760)
shogohida pushed a commit to shogohida/flutter that referenced this pull request Dec 7, 2022
…lutter#115672)

* a76ec9158 Roll Fuchsia Linux SDK from lnmSnyJi-2H07tBnV... to WdtwlLEce90PjFJ9z... (flutter/engine#37747)

* 44e2f5854 [Impeller] Change texture upload pipeline in Vulkan (flutter/engine#37623)

* 6a3ad3c14 Roll Skia from 345bceacd298 to 5270b1d26b5f (4 revisions) (flutter/engine#37748)

* 01271891c Do not abort if a MultiFrameCodec is unable to allocate a bitmap buffer (flutter/engine#37534)

* 54232a4c3 Roll Skia from 5270b1d26b5f to cf967e6b1c00 (5 revisions) (flutter/engine#37751)

* 30aa3cc38 [fuchsia][a11y] Set explicit hit regions in flatland embedder (flutter/engine#37338)

* da07c33d2 Make NotifyIdle reject close and past deadlines. (flutter/engine#37737)

* e3844cc1e Add third_party/dart/third_party/binaryen/src as a dependency (flutter/engine#37749)

* aeb2cd95b [Impeller] use SSBOs for gradients where supported (metal/vulkan) (flutter/engine#37654)

* e8aa1c192 Roll Skia from cf967e6b1c00 to f1f59de17204 (2 revisions) (flutter/engine#37756)

* 4311774fb [Impeller] register modern shaders on Vulkan too (flutter/engine#37757)

* 8e4a718d0 Made FlutterTextField that outlive FlutterTextPlatformNode not crash (flutter/engine#37735)

* 446a09dfc [macOS] Use consistent filenames for tests (flutter/engine#37755)

* 7a390f97c Roll Skia from f1f59de17204 to 12f01bc5b57e (1 revision) (flutter/engine#37760)
gspencergoog pushed a commit to gspencergoog/flutter that referenced this pull request Jan 19, 2023
…lutter#115672)

* a76ec9158 Roll Fuchsia Linux SDK from lnmSnyJi-2H07tBnV... to WdtwlLEce90PjFJ9z... (flutter/engine#37747)

* 44e2f5854 [Impeller] Change texture upload pipeline in Vulkan (flutter/engine#37623)

* 6a3ad3c14 Roll Skia from 345bceacd298 to 5270b1d26b5f (4 revisions) (flutter/engine#37748)

* 01271891c Do not abort if a MultiFrameCodec is unable to allocate a bitmap buffer (flutter/engine#37534)

* 54232a4c3 Roll Skia from 5270b1d26b5f to cf967e6b1c00 (5 revisions) (flutter/engine#37751)

* 30aa3cc38 [fuchsia][a11y] Set explicit hit regions in flatland embedder (flutter/engine#37338)

* da07c33d2 Make NotifyIdle reject close and past deadlines. (flutter/engine#37737)

* e3844cc1e Add third_party/dart/third_party/binaryen/src as a dependency (flutter/engine#37749)

* aeb2cd95b [Impeller] use SSBOs for gradients where supported (metal/vulkan) (flutter/engine#37654)

* e8aa1c192 Roll Skia from cf967e6b1c00 to f1f59de17204 (2 revisions) (flutter/engine#37756)

* 4311774fb [Impeller] register modern shaders on Vulkan too (flutter/engine#37757)

* 8e4a718d0 Made FlutterTextField that outlive FlutterTextPlatformNode not crash (flutter/engine#37735)

* 446a09dfc [macOS] Use consistent filenames for tests (flutter/engine#37755)

* 7a390f97c Roll Skia from f1f59de17204 to 12f01bc5b57e (1 revision) (flutter/engine#37760)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
autosubmit Merge PR when tree becomes green via auto submit App e: impeller
Projects
No open projects
Archived in project
3 participants