Skip to content

Commit

Permalink
Allow shader libraries to look at multiple shader dylibs.
Browse files Browse the repository at this point in the history
  • Loading branch information
chinmaygarde authored and dnfield committed Apr 27, 2022
1 parent 97455db commit 778fc11
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 35 deletions.
14 changes: 12 additions & 2 deletions impeller/playground/playground.mm
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,19 @@
return fml::paths::JoinPaths({path_result.second, "shaders"});
}

static std::vector<std::string> ShaderLibraryPathsForPlayground() {
std::vector<std::string> 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<ContextMTL>(ShaderLibraryDirectory(),
"shader_fixtures.metallib")) {}
: renderer_(
std::make_shared<ContextMTL>(ShaderLibraryPathsForPlayground())) {}

Playground::~Playground() = default;

Expand Down
2 changes: 1 addition & 1 deletion impeller/renderer/backend/metal/context_mtl.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ namespace impeller {
class ContextMTL final : public Context,
public BackendCast<ContextMTL, Context> {
public:
ContextMTL(std::string shaders_directory, std::string main_library_file_name);
ContextMTL(const std::vector<std::string>& shader_libraries);

// |Context|
~ContextMTL() override;
Expand Down
57 changes: 32 additions & 25 deletions impeller/renderer/backend/metal/context_mtl.mm
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

#include "impeller/renderer/backend/metal/context_mtl.h"

#include <Foundation/Foundation.h>

#include "flutter/fml/file.h"
#include "flutter/fml/logging.h"
#include "flutter/fml/paths.h"
Expand All @@ -12,8 +14,30 @@

namespace impeller {

ContextMTL::ContextMTL(std::string shaders_directory,
std::string main_library_file_name)
static NSArray<id<MTLLibrary>>* ShaderLibrariesFromFiles(
id<MTLDevice> device,
const std::vector<std::string>& libraries_paths) {
NSMutableArray<id<MTLLibrary>>* 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<std::string>& libraries_paths)
: device_(::MTLCreateSystemDefaultDevice()) {
// Setup device.
if (!device_) {
Expand All @@ -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<ShaderLibraryMTL>(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<ShaderLibraryMTL>(new ShaderLibraryMTL(library));
shader_library_ = std::move(library);
}

// Setup the pipeline library.
Expand Down
9 changes: 7 additions & 2 deletions impeller/renderer/backend/metal/shader_library_mtl.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#pragma once

#include <Foundation/Foundation.h>
#include <Metal/Metal.h>

#include <memory>
Expand All @@ -23,6 +24,9 @@ class ShaderLibraryMTL final : public ShaderLibrary {
// |ShaderLibrary|
~ShaderLibraryMTL() override;

// |ShaderLibrary|
bool IsValid() const override;

private:
friend class ContextMTL;

Expand Down Expand Up @@ -53,10 +57,11 @@ class ShaderLibraryMTL final : public ShaderLibrary {
ShaderKey::Equal>;

UniqueID library_id_;
id<MTLLibrary> library_ = nullptr;
NSArray<id<MTLLibrary>>* libraries_ = nullptr;
Functions functions_;
bool is_valid_ = false;

ShaderLibraryMTL(id<MTLLibrary> library);
ShaderLibraryMTL(NSArray<id<MTLLibrary>>* libraries);

// |ShaderLibrary|
std::shared_ptr<const ShaderFunction> GetFunction(
Expand Down
28 changes: 23 additions & 5 deletions impeller/renderer/backend/metal/shader_library_mtl.mm
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,25 @@

namespace impeller {

ShaderLibraryMTL::ShaderLibraryMTL(id<MTLLibrary> library)
: library_(library) {}
ShaderLibraryMTL::ShaderLibraryMTL(NSArray<id<MTLLibrary>>* 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<const ShaderFunction> ShaderLibraryMTL::GetFunction(
const std::string_view& name,
ShaderStage stage) {
if (!library_) {
if (!IsValid()) {
return nullptr;
}

Expand All @@ -26,8 +36,16 @@
return found->second;
}

auto function = [library_ newFunctionWithName:@(name.data())];
if (!function) {
id<MTLFunction> 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;
}

Expand Down
2 changes: 2 additions & 0 deletions impeller/renderer/shader_library.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ class ShaderLibrary {
public:
virtual ~ShaderLibrary();

virtual bool IsValid() const = 0;

virtual std::shared_ptr<const ShaderFunction> GetFunction(
const std::string_view& name,
ShaderStage stage) = 0;
Expand Down

0 comments on commit 778fc11

Please sign in to comment.