From 778fc113b604ecbb6ce70503cdc22d73b195c1be Mon Sep 17 00:00:00 2001 From: Chinmay Garde Date: Mon, 15 Nov 2021 13:59:09 -0800 Subject: [PATCH] Allow shader libraries to look at multiple shader dylibs. --- impeller/playground/playground.mm | 14 ++++- impeller/renderer/backend/metal/context_mtl.h | 2 +- .../renderer/backend/metal/context_mtl.mm | 57 +++++++++++-------- .../backend/metal/shader_library_mtl.h | 9 ++- .../backend/metal/shader_library_mtl.mm | 28 +++++++-- impeller/renderer/shader_library.h | 2 + 6 files changed, 77 insertions(+), 35 deletions(-) diff --git a/impeller/playground/playground.mm b/impeller/playground/playground.mm index a0d9dcbeacf6f..dad34f622e110 100644 --- a/impeller/playground/playground.mm +++ b/impeller/playground/playground.mm @@ -35,9 +35,19 @@ return fml::paths::JoinPaths({path_result.second, "shaders"}); } +static std::vector ShaderLibraryPathsForPlayground() { + std::vector paths; + paths.emplace_back(fml::paths::JoinPaths( + {ShaderLibraryDirectory(), "shader_fixtures.metallib"})); + paths.emplace_back( + fml::paths::JoinPaths({fml::paths::GetExecutableDirectoryPath().second, + "shaders", "entity.metallib"})); + return paths; +} + Playground::Playground() - : renderer_(std::make_shared(ShaderLibraryDirectory(), - "shader_fixtures.metallib")) {} + : renderer_( + std::make_shared(ShaderLibraryPathsForPlayground())) {} Playground::~Playground() = default; diff --git a/impeller/renderer/backend/metal/context_mtl.h b/impeller/renderer/backend/metal/context_mtl.h index fc07f5f7b7a01..4572128c8be0b 100644 --- a/impeller/renderer/backend/metal/context_mtl.h +++ b/impeller/renderer/backend/metal/context_mtl.h @@ -22,7 +22,7 @@ namespace impeller { class ContextMTL final : public Context, public BackendCast { public: - ContextMTL(std::string shaders_directory, std::string main_library_file_name); + ContextMTL(const std::vector& shader_libraries); // |Context| ~ContextMTL() override; diff --git a/impeller/renderer/backend/metal/context_mtl.mm b/impeller/renderer/backend/metal/context_mtl.mm index c84c17cc1e9b6..19d91acb33197 100644 --- a/impeller/renderer/backend/metal/context_mtl.mm +++ b/impeller/renderer/backend/metal/context_mtl.mm @@ -4,6 +4,8 @@ #include "impeller/renderer/backend/metal/context_mtl.h" +#include + #include "flutter/fml/file.h" #include "flutter/fml/logging.h" #include "flutter/fml/paths.h" @@ -12,8 +14,30 @@ namespace impeller { -ContextMTL::ContextMTL(std::string shaders_directory, - std::string main_library_file_name) +static NSArray>* ShaderLibrariesFromFiles( + id device, + const std::vector& libraries_paths) { + NSMutableArray>* found_libraries = [NSMutableArray array]; + for (const auto& library_path : libraries_paths) { + if (!fml::IsFile(library_path)) { + FML_LOG(ERROR) << "Shader library does not exist at path '" + << library_path << "'"; + continue; + } + NSError* shader_library_error = nil; + auto library = [device newLibraryWithFile:@(library_path.c_str()) + error:&shader_library_error]; + if (!library) { + FML_LOG(ERROR) << "Could not create shader library: " + << shader_library_error.localizedDescription.UTF8String; + continue; + } + [found_libraries addObject:library]; + } + return found_libraries; +} + +ContextMTL::ContextMTL(const std::vector& libraries_paths) : device_(::MTLCreateSystemDefaultDevice()) { // Setup device. if (!device_) { @@ -33,31 +57,14 @@ // Setup the shader library. { - NSError* shader_library_error = nil; - auto shader_library_path = - fml::paths::JoinPaths({shaders_directory, main_library_file_name}); - - auto library_exists = fml::IsFile(shader_library_path); - - if (!library_exists) { - FML_LOG(ERROR) << "Shader library does not exist at path '" - << shader_library_path - << "'. No piplines can be created in this context."; - } - auto library = - library_exists - ? [device_ newLibraryWithFile:@(shader_library_path.c_str()) - error:&shader_library_error] - : [device_ newDefaultLibrary]; - if (!library && shader_library_error) { - FML_LOG(ERROR) << "Could not create shader library: " - << shader_library_error.localizedDescription.UTF8String; + // std::make_shared disallowed because of private friend ctor. + auto library = std::shared_ptr(new ShaderLibraryMTL( + ShaderLibrariesFromFiles(device_, libraries_paths))); + if (!library->IsValid()) { + FML_DLOG(ERROR) << "Could not create valid Metal shader library."; return; } - - // std::make_shared disallowed because of private friend ctor. - shader_library_ = - std::shared_ptr(new ShaderLibraryMTL(library)); + shader_library_ = std::move(library); } // Setup the pipeline library. diff --git a/impeller/renderer/backend/metal/shader_library_mtl.h b/impeller/renderer/backend/metal/shader_library_mtl.h index fe10dfd657b2f..b09b4cda33a1b 100644 --- a/impeller/renderer/backend/metal/shader_library_mtl.h +++ b/impeller/renderer/backend/metal/shader_library_mtl.h @@ -4,6 +4,7 @@ #pragma once +#include #include #include @@ -23,6 +24,9 @@ class ShaderLibraryMTL final : public ShaderLibrary { // |ShaderLibrary| ~ShaderLibraryMTL() override; + // |ShaderLibrary| + bool IsValid() const override; + private: friend class ContextMTL; @@ -53,10 +57,11 @@ class ShaderLibraryMTL final : public ShaderLibrary { ShaderKey::Equal>; UniqueID library_id_; - id library_ = nullptr; + NSArray>* libraries_ = nullptr; Functions functions_; + bool is_valid_ = false; - ShaderLibraryMTL(id library); + ShaderLibraryMTL(NSArray>* libraries); // |ShaderLibrary| std::shared_ptr GetFunction( diff --git a/impeller/renderer/backend/metal/shader_library_mtl.mm b/impeller/renderer/backend/metal/shader_library_mtl.mm index 5167e4cb7cd57..6844f4e463d6a 100644 --- a/impeller/renderer/backend/metal/shader_library_mtl.mm +++ b/impeller/renderer/backend/metal/shader_library_mtl.mm @@ -8,15 +8,25 @@ namespace impeller { -ShaderLibraryMTL::ShaderLibraryMTL(id library) - : library_(library) {} +ShaderLibraryMTL::ShaderLibraryMTL(NSArray>* libraries) + : libraries_(libraries) { + if (libraries_ == nil || libraries_.count == 0) { + return; + } + + is_valid_ = true; +} ShaderLibraryMTL::~ShaderLibraryMTL() = default; +bool ShaderLibraryMTL::IsValid() const { + return is_valid_; +} + std::shared_ptr ShaderLibraryMTL::GetFunction( const std::string_view& name, ShaderStage stage) { - if (!library_) { + if (!IsValid()) { return nullptr; } @@ -26,8 +36,16 @@ return found->second; } - auto function = [library_ newFunctionWithName:@(name.data())]; - if (!function) { + id function = nil; + + for (size_t i = 0, count = [libraries_ count]; i < count; i++) { + function = [libraries_[i] newFunctionWithName:@(name.data())]; + if (function) { + break; + } + } + + if (function == nil) { return nullptr; } diff --git a/impeller/renderer/shader_library.h b/impeller/renderer/shader_library.h index 357be584cfc91..256e614254813 100644 --- a/impeller/renderer/shader_library.h +++ b/impeller/renderer/shader_library.h @@ -19,6 +19,8 @@ class ShaderLibrary { public: virtual ~ShaderLibrary(); + virtual bool IsValid() const = 0; + virtual std::shared_ptr GetFunction( const std::string_view& name, ShaderStage stage) = 0;