diff --git a/engine/src/flutter/impeller/compiler/compiler.cc b/engine/src/flutter/impeller/compiler/compiler.cc index 9d7fdbf152..a751f5f6dd 100644 --- a/engine/src/flutter/impeller/compiler/compiler.cc +++ b/engine/src/flutter/impeller/compiler/compiler.cc @@ -32,6 +32,11 @@ constexpr const char* kEGLImageExternalExtension300 = "GL_OES_EGL_image_external_essl3"; } // namespace +// This value should be <= 7372. UBOs can be larger on some devices but a +// performance cost will be paid. +// https://docs.qualcomm.com/bundle/publicresource/topics/80-78185-2/best_practices.html?product=1601111740035277#buffer-best-practices +static const uint32_t kMaxUniformBufferSize = 6208; + static uint32_t ParseMSLVersion(const std::string& msl_version) { std::stringstream sstream(msl_version); std::string version_part; @@ -257,6 +262,21 @@ static CompilerBackend CreateCompiler(const spirv_cross::ParsedIR& ir, return compiler; } +namespace { +uint32_t CalculateUBOSize(const spirv_cross::Compiler* compiler) { + spirv_cross::ShaderResources resources = compiler->get_shader_resources(); + uint32_t result = 0; + for (const spirv_cross::Resource& ubo : resources.uniform_buffers) { + const spirv_cross::SPIRType& ubo_type = + compiler->get_type(ubo.base_type_id); + uint32_t size = compiler->get_declared_struct_size(ubo_type); + result += size; + } + return result; +} + +} // namespace + Compiler::Compiler(const std::shared_ptr& source_mapping, const SourceOptions& source_options, Reflector::Options reflector_options) @@ -410,6 +430,13 @@ Compiler::Compiler(const std::shared_ptr& source_mapping, return; } + uint32_t ubo_size = CalculateUBOSize(sl_compiler.GetCompiler()); + if (ubo_size > kMaxUniformBufferSize) { + COMPILER_ERROR(error_stream_) << "Uniform buffer size exceeds max (" + << kMaxUniformBufferSize << "): " << ubo_size; + return; + } + // We need to invoke the compiler even if we don't use the SL mapping later // for Vulkan. The reflector needs information that is only valid after a // successful compilation call.