From da2eeac15b2dc4dc3967b80754bdea487e669dce Mon Sep 17 00:00:00 2001 From: Zachary Anderson Date: Thu, 4 Aug 2022 12:10:38 -0700 Subject: [PATCH] [impellerc] Namespace user functions (flutter/engine#35155) --- .../flutter/impeller/compiler/spirv_sksl.cc | 26 +++++++++++++ .../flutter/impeller/compiler/spirv_sksl.h | 2 + .../fixtures/shaders/general_shaders/BUILD.gn | 1 + .../no_builtin_redefinition.frag | 38 +++++++++++++++++++ .../testing/dart/fragment_shader_test.dart | 10 +++++ 5 files changed, 77 insertions(+) create mode 100644 engine/src/flutter/lib/ui/fixtures/shaders/general_shaders/no_builtin_redefinition.frag diff --git a/engine/src/flutter/impeller/compiler/spirv_sksl.cc b/engine/src/flutter/impeller/compiler/spirv_sksl.cc index 977f593ccbd..42fbeeb4a5e 100644 --- a/engine/src/flutter/impeller/compiler/spirv_sksl.cc +++ b/engine/src/flutter/impeller/compiler/spirv_sksl.cc @@ -38,6 +38,8 @@ std::string CompilerSkSL::compile() { backend.use_array_constructor = true; backend.workgroup_size_is_hidden = true; + fixup_user_functions(); + fixup_anonymous_struct_names(); fixup_type_alias(); reorder_type_alias(); @@ -72,6 +74,30 @@ std::string CompilerSkSL::compile() { return buffer.str(); } +void CompilerSkSL::fixup_user_functions() { + const std::string prefix = "__flutter_local_"; + ir.for_each_typed_id([&](uint32_t, const SPIRFunction& func) { + const auto& original_name = get_name(func.self); + // Just in case. Don't add the prefix a second time. + if (original_name.rfind(prefix, 0) == 0) { + return; + } + std::string new_name = prefix + original_name; + set_name(func.self, new_name); + }); + + ir.for_each_typed_id( + [&](uint32_t, const SPIRFunctionPrototype& func) { + const auto& original_name = get_name(func.self); + // Just in case. Don't add the prefix a second time. + if (original_name.rfind(prefix, 0) == 0) { + return; + } + std::string new_name = prefix + original_name; + set_name(func.self, new_name); + }); +} + void CompilerSkSL::emit_header() { statement("// This SkSL shader is autogenerated by spirv-cross."); statement(""); diff --git a/engine/src/flutter/impeller/compiler/spirv_sksl.h b/engine/src/flutter/impeller/compiler/spirv_sksl.h index 3fbe4cc1fdc..7469ba37df4 100644 --- a/engine/src/flutter/impeller/compiler/spirv_sksl.h +++ b/engine/src/flutter/impeller/compiler/spirv_sksl.h @@ -38,6 +38,8 @@ class CompilerSkSL : public spirv_cross::CompilerGLSL { void emit_uniform(const spirv_cross::SPIRVariable& var) override; + void fixup_user_functions(); + void detect_unsupported_resources(); bool emit_constant_resources(); bool emit_struct_resources(); diff --git a/engine/src/flutter/lib/ui/fixtures/shaders/general_shaders/BUILD.gn b/engine/src/flutter/lib/ui/fixtures/shaders/general_shaders/BUILD.gn index 548b3b0499d..c99d06320ba 100644 --- a/engine/src/flutter/lib/ui/fixtures/shaders/general_shaders/BUILD.gn +++ b/engine/src/flutter/lib/ui/fixtures/shaders/general_shaders/BUILD.gn @@ -11,6 +11,7 @@ if (enable_unittests) { "blue_green_sampler.frag", "children_and_uniforms.frag", "functions.frag", + "no_builtin_redefinition.frag", "no_uniforms.frag", "simple.frag", "uniforms.frag", diff --git a/engine/src/flutter/lib/ui/fixtures/shaders/general_shaders/no_builtin_redefinition.frag b/engine/src/flutter/lib/ui/fixtures/shaders/general_shaders/no_builtin_redefinition.frag new file mode 100644 index 00000000000..4e74fe27b86 --- /dev/null +++ b/engine/src/flutter/lib/ui/fixtures/shaders/general_shaders/no_builtin_redefinition.frag @@ -0,0 +1,38 @@ +#version 320 es + +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +precision highp float; + +layout ( location = 0 ) out vec4 oColor; + +layout ( location = 0 ) uniform float a; // should be 1.0 + +float saturate(float x) { + return clamp(x, 0.0, 1.0); +} + +float addA(float x) { + return x + a; +} + +vec2 pairWithA(float x) { + return vec2(x, a); +} + +vec3 composedFunction(float x) { + return vec3(addA(x), pairWithA(x)); +} + +float multiParam(float x, float y, float z) { + return x * y * z * a; +} + +void main() { + float x = saturate(addA(0.0)); // x = 0 + 1; + vec3 v3 = composedFunction(x); // v3 = vec3(2, 1, 1); + x = multiParam(v3.x, v3.y, v3.z); // x = 2 * 1 * 1 * 1; + oColor = vec4(0.0, x / 2.0, 0.0, 1.0); // vec4(0, 1, 0, 1); +} diff --git a/engine/src/flutter/testing/dart/fragment_shader_test.dart b/engine/src/flutter/testing/dart/fragment_shader_test.dart index d77e7b68359..d19a59c0173 100644 --- a/engine/src/flutter/testing/dart/fragment_shader_test.dart +++ b/engine/src/flutter/testing/dart/fragment_shader_test.dart @@ -118,6 +118,16 @@ void main() async { expect(throws, equals(true)); }); + test('user defined functions do not redefine builtins', () async { + final FragmentProgram program = await FragmentProgram.fromAsset( + 'no_builtin_redefinition.frag.iplr', + ); + final Shader shader = program.shader( + floatUniforms: Float32List.fromList([1.0]), + ); + await _expectShaderRendersGreen(shader); + }); + test('fromAsset accepts a shader with no uniforms', () async { final FragmentProgram program = await FragmentProgram.fromAsset( 'no_uniforms.frag.iplr',