From be4e185fa4cfd87905cf2afec8f2b7b53346a181 Mon Sep 17 00:00:00 2001 From: magicianA Date: Fri, 5 Aug 2022 15:54:05 +0800 Subject: [PATCH] [Impeller] Enforce shader resource limits in impellerc (flutter/engine#35120) --- .../src/flutter/impeller/compiler/compiler.cc | 121 ++++++++++++++++++ .../impeller/compiler/compiler_unittests.cc | 6 + engine/src/flutter/impeller/fixtures/BUILD.gn | 1 + .../impeller/fixtures/resources_limit.vert | 9 ++ 4 files changed, 137 insertions(+) create mode 100644 engine/src/flutter/impeller/fixtures/resources_limit.vert diff --git a/engine/src/flutter/impeller/compiler/compiler.cc b/engine/src/flutter/impeller/compiler/compiler.cc index e5b2018fd26..0d7af022cc3 100644 --- a/engine/src/flutter/impeller/compiler/compiler.cc +++ b/engine/src/flutter/impeller/compiler/compiler.cc @@ -4,6 +4,7 @@ #include "impeller/compiler/compiler.h" +#include #include #include #include @@ -104,6 +105,124 @@ static CompilerBackend CreateCompiler(const spirv_cross::ParsedIR& ir, return compiler; } +static void SetLimitations(shaderc::CompileOptions& compiler_opts) { + using Limit = std::pair; + static constexpr std::array limits = { + Limit{shaderc_limit::shaderc_limit_max_lights, 8}, + Limit{shaderc_limit::shaderc_limit_max_clip_planes, 6}, + Limit{shaderc_limit::shaderc_limit_max_texture_units, 2}, + Limit{shaderc_limit::shaderc_limit_max_texture_coords, 8}, + Limit{shaderc_limit::shaderc_limit_max_vertex_attribs, 16}, + Limit{shaderc_limit::shaderc_limit_max_vertex_uniform_components, 4096}, + Limit{shaderc_limit::shaderc_limit_max_varying_floats, 60}, + Limit{shaderc_limit::shaderc_limit_max_vertex_texture_image_units, 16}, + Limit{shaderc_limit::shaderc_limit_max_combined_texture_image_units, 80}, + Limit{shaderc_limit::shaderc_limit_max_texture_image_units, 16}, + Limit{shaderc_limit::shaderc_limit_max_fragment_uniform_components, 1024}, + Limit{shaderc_limit::shaderc_limit_max_draw_buffers, 8}, + Limit{shaderc_limit::shaderc_limit_max_vertex_uniform_vectors, 256}, + Limit{shaderc_limit::shaderc_limit_max_varying_vectors, 15}, + Limit{shaderc_limit::shaderc_limit_max_fragment_uniform_vectors, 256}, + Limit{shaderc_limit::shaderc_limit_max_vertex_output_vectors, 16}, + Limit{shaderc_limit::shaderc_limit_max_fragment_input_vectors, 15}, + Limit{shaderc_limit::shaderc_limit_min_program_texel_offset, -8}, + Limit{shaderc_limit::shaderc_limit_max_program_texel_offset, 7}, + Limit{shaderc_limit::shaderc_limit_max_clip_distances, 8}, + Limit{shaderc_limit::shaderc_limit_max_compute_work_group_count_x, 65535}, + Limit{shaderc_limit::shaderc_limit_max_compute_work_group_count_y, 65535}, + Limit{shaderc_limit::shaderc_limit_max_compute_work_group_count_z, 65535}, + Limit{shaderc_limit::shaderc_limit_max_compute_work_group_size_x, 1024}, + Limit{shaderc_limit::shaderc_limit_max_compute_work_group_size_y, 1024}, + Limit{shaderc_limit::shaderc_limit_max_compute_work_group_size_z, 64}, + Limit{shaderc_limit::shaderc_limit_max_compute_uniform_components, 512}, + Limit{shaderc_limit::shaderc_limit_max_compute_texture_image_units, 16}, + Limit{shaderc_limit::shaderc_limit_max_compute_image_uniforms, 8}, + Limit{shaderc_limit::shaderc_limit_max_compute_atomic_counters, 8}, + Limit{shaderc_limit::shaderc_limit_max_compute_atomic_counter_buffers, 1}, + Limit{shaderc_limit::shaderc_limit_max_varying_components, 60}, + Limit{shaderc_limit::shaderc_limit_max_vertex_output_components, 64}, + Limit{shaderc_limit::shaderc_limit_max_geometry_input_components, 64}, + Limit{shaderc_limit::shaderc_limit_max_geometry_output_components, 128}, + Limit{shaderc_limit::shaderc_limit_max_fragment_input_components, 128}, + Limit{shaderc_limit::shaderc_limit_max_image_units, 8}, + Limit{shaderc_limit:: + shaderc_limit_max_combined_image_units_and_fragment_outputs, + 8}, + Limit{shaderc_limit::shaderc_limit_max_combined_shader_output_resources, + 8}, + Limit{shaderc_limit::shaderc_limit_max_image_samples, 0}, + Limit{shaderc_limit::shaderc_limit_max_vertex_image_uniforms, 0}, + Limit{shaderc_limit::shaderc_limit_max_tess_control_image_uniforms, 0}, + Limit{shaderc_limit::shaderc_limit_max_tess_evaluation_image_uniforms, 0}, + Limit{shaderc_limit::shaderc_limit_max_geometry_image_uniforms, 0}, + Limit{shaderc_limit::shaderc_limit_max_fragment_image_uniforms, 8}, + Limit{shaderc_limit::shaderc_limit_max_combined_image_uniforms, 8}, + Limit{shaderc_limit::shaderc_limit_max_geometry_texture_image_units, 16}, + Limit{shaderc_limit::shaderc_limit_max_geometry_output_vertices, 256}, + Limit{shaderc_limit::shaderc_limit_max_geometry_total_output_components, + 1024}, + Limit{shaderc_limit::shaderc_limit_max_geometry_uniform_components, 512}, + Limit{shaderc_limit::shaderc_limit_max_geometry_varying_components, 60}, + Limit{shaderc_limit::shaderc_limit_max_tess_control_input_components, + 128}, + Limit{shaderc_limit::shaderc_limit_max_tess_control_output_components, + 128}, + Limit{shaderc_limit::shaderc_limit_max_tess_control_texture_image_units, + 16}, + Limit{shaderc_limit::shaderc_limit_max_tess_control_uniform_components, + 1024}, + Limit{ + shaderc_limit::shaderc_limit_max_tess_control_total_output_components, + 4096}, + Limit{shaderc_limit::shaderc_limit_max_tess_evaluation_input_components, + 128}, + Limit{shaderc_limit::shaderc_limit_max_tess_evaluation_output_components, + 128}, + Limit{ + shaderc_limit::shaderc_limit_max_tess_evaluation_texture_image_units, + 16}, + Limit{shaderc_limit::shaderc_limit_max_tess_evaluation_uniform_components, + 1024}, + Limit{shaderc_limit::shaderc_limit_max_tess_patch_components, 120}, + Limit{shaderc_limit::shaderc_limit_max_patch_vertices, 32}, + Limit{shaderc_limit::shaderc_limit_max_tess_gen_level, 64}, + Limit{shaderc_limit::shaderc_limit_max_viewports, 16}, + Limit{shaderc_limit::shaderc_limit_max_vertex_atomic_counters, 0}, + Limit{shaderc_limit::shaderc_limit_max_tess_control_atomic_counters, 0}, + Limit{shaderc_limit::shaderc_limit_max_tess_evaluation_atomic_counters, + 0}, + Limit{shaderc_limit::shaderc_limit_max_geometry_atomic_counters, 0}, + Limit{shaderc_limit::shaderc_limit_max_fragment_atomic_counters, 8}, + Limit{shaderc_limit::shaderc_limit_max_combined_atomic_counters, 8}, + Limit{shaderc_limit::shaderc_limit_max_atomic_counter_bindings, 1}, + Limit{shaderc_limit::shaderc_limit_max_vertex_atomic_counter_buffers, 0}, + Limit{ + shaderc_limit::shaderc_limit_max_tess_control_atomic_counter_buffers, + 0}, + Limit{shaderc_limit:: + shaderc_limit_max_tess_evaluation_atomic_counter_buffers, + 0}, + Limit{shaderc_limit::shaderc_limit_max_geometry_atomic_counter_buffers, + 0}, + Limit{shaderc_limit::shaderc_limit_max_fragment_atomic_counter_buffers, + 0}, + Limit{shaderc_limit::shaderc_limit_max_combined_atomic_counter_buffers, + 1}, + Limit{shaderc_limit::shaderc_limit_max_atomic_counter_buffer_size, 32}, + Limit{shaderc_limit::shaderc_limit_max_transform_feedback_buffers, 4}, + Limit{shaderc_limit:: + shaderc_limit_max_transform_feedback_interleaved_components, + 64}, + Limit{shaderc_limit::shaderc_limit_max_cull_distances, 8}, + Limit{shaderc_limit::shaderc_limit_max_combined_clip_and_cull_distances, + 8}, + Limit{shaderc_limit::shaderc_limit_max_samples, 4}, + }; + for (auto& [limit, value] : limits) { + compiler_opts.SetLimit(limit, value); + } +} + Compiler::Compiler(const fml::Mapping& source_mapping, SourceOptions source_options, Reflector::Options reflector_options) @@ -139,6 +258,8 @@ Compiler::Compiler(const fml::Mapping& source_mapping, shaderc_source_language::shaderc_source_language_glsl); spirv_options.SetForcedVersionProfile(460, shaderc_profile::shaderc_profile_core); + SetLimitations(spirv_options); + switch (source_options.target_platform) { case TargetPlatform::kMetalDesktop: case TargetPlatform::kMetalIOS: diff --git a/engine/src/flutter/impeller/compiler/compiler_unittests.cc b/engine/src/flutter/impeller/compiler/compiler_unittests.cc index d19d9f00c98..23101e313f9 100644 --- a/engine/src/flutter/impeller/compiler/compiler_unittests.cc +++ b/engine/src/flutter/impeller/compiler/compiler_unittests.cc @@ -50,6 +50,12 @@ TEST_P(CompilerTest, CanCompileComputeShader) { ASSERT_TRUE(CanCompileAndReflect("sample.comp", SourceType::kComputeShader)); } +TEST_P(CompilerTest, MustFailDueToExceedingResourcesLimit) { + ScopedValidationDisable disable_validation; + ASSERT_FALSE( + CanCompileAndReflect("resources_limit.vert", SourceType::kVertexShader)); +} + TEST_P(CompilerTest, MustFailDueToMultipleLocationPerStructMember) { if (GetParam() == TargetPlatform::kFlutterSPIRV) { // This is a failure of reflection which this target doesn't perform. diff --git a/engine/src/flutter/impeller/fixtures/BUILD.gn b/engine/src/flutter/impeller/fixtures/BUILD.gn index d955a90bfa9..3a62e149c86 100644 --- a/engine/src/flutter/impeller/fixtures/BUILD.gn +++ b/engine/src/flutter/impeller/fixtures/BUILD.gn @@ -42,6 +42,7 @@ test_fixtures("file_fixtures") { "boston.jpg", "embarcadero.jpg", "kalimba.jpg", + "resources_limit.vert", "sample.comp", "sample.tesc", "sample.tese", diff --git a/engine/src/flutter/impeller/fixtures/resources_limit.vert b/engine/src/flutter/impeller/fixtures/resources_limit.vert new file mode 100644 index 00000000000..95c84ee8bfc --- /dev/null +++ b/engine/src/flutter/impeller/fixtures/resources_limit.vert @@ -0,0 +1,9 @@ +// 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. + +uniform sampler1D tex; +void main() +{ + vec4 x = textureOffset(tex, 1.0, -10); +}