Wire up pipeline library resolution.

This commit is contained in:
Chinmay Garde 2021-05-22 15:18:49 -07:00 committed by Dan Field
parent 5d6dd79bf0
commit e9938a67af
13 changed files with 275 additions and 98 deletions

View File

@ -8,8 +8,8 @@ impeller_component("compositor") {
sources = [
"context.h",
"context.mm",
"pipeline_builder.h",
"pipeline_builder.mm",
"pipeline.h",
"pipeline.mm",
"pipeline_descriptor.h",
"pipeline_descriptor.mm",
"pipeline_library.h",

View File

@ -9,6 +9,7 @@
#include <memory>
#include "flutter/fml/macros.h"
#include "impeller/compositor/pipeline_library.h"
namespace impeller {
@ -28,11 +29,14 @@ class Context {
std::shared_ptr<ShaderLibrary> GetShaderLibrary() const;
std::shared_ptr<PipelineLibrary> GetPipelineLibrary() const;
private:
id<MTLDevice> device_ = nullptr;
id<MTLCommandQueue> render_queue_ = nullptr;
id<MTLCommandQueue> transfer_queue_ = nullptr;
std::shared_ptr<ShaderLibrary> shader_library_;
std::shared_ptr<PipelineLibrary> pipeline_library_;
bool is_valid_ = false;
FML_DISALLOW_COPY_AND_ASSIGN(Context);

View File

@ -0,0 +1,35 @@
// 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.
#pragma once
#include "flutter/fml/macros.h"
#include <Metal/Metal.h>
namespace impeller {
class PipelineLibrary;
class Pipeline {
public:
enum class Type {
kUnknown,
kRender,
};
~Pipeline();
private:
friend class PipelineLibrary;
Type type_ = Type::kUnknown;
id<MTLRenderPipelineState> state_;
Pipeline(id<MTLRenderPipelineState> state);
FML_DISALLOW_COPY_AND_ASSIGN(Pipeline);
};
} // namespace impeller

View File

@ -0,0 +1,17 @@
// 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.
#include "flutter/impeller/impeller/compositor/pipeline.h"
namespace impeller {
Pipeline::Pipeline(id<MTLRenderPipelineState> state) : state_(state) {
if (state_ != nil) {
type_ = Type::kRender;
}
}
Pipeline::~Pipeline() = default;
} // namespace impeller

View File

@ -1,43 +0,0 @@
// 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.
#pragma once
#include <functional>
#include <memory>
#include <type_traits>
#include <unordered_map>
#include "flutter/fml/macros.h"
#include "impeller/compositor/pipeline_descriptor.h"
#include "impeller/compositor/shader_library.h"
#include "impeller/compositor/vertex_descriptor.h"
namespace impeller {
class PipelineBuilder {
public:
PipelineBuilder();
~PipelineBuilder();
PipelineBuilder& SetLabel(const std::string_view& label);
PipelineBuilder& SetSampleCount(size_t samples);
PipelineBuilder& AddStageEntrypoint(std::shared_ptr<ShaderFunction> function);
PipelineBuilder& SetVertexDescriptor(
std::shared_ptr<VertexDescriptor> vertex_descriptor);
private:
std::string label_;
size_t sample_count_ = 1;
std::unordered_map<ShaderStage, std::shared_ptr<ShaderFunction>> entrypoints_;
std::shared_ptr<VertexDescriptor> vertex_descriptor_;
FML_DISALLOW_COPY_AND_ASSIGN(PipelineBuilder);
};
} // namespace impeller

View File

@ -1,44 +0,0 @@
// 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.
#include "impeller/compositor/pipeline_builder.h"
namespace impeller {
PipelineBuilder::PipelineBuilder() = default;
PipelineBuilder::~PipelineBuilder() = default;
PipelineBuilder& PipelineBuilder::SetLabel(const std::string_view& label) {
label_ = {label.data(), label.size()};
return *this;
}
PipelineBuilder& PipelineBuilder::SetSampleCount(size_t samples) {
sample_count_ = samples;
return *this;
}
PipelineBuilder& PipelineBuilder::AddStageEntrypoint(
std::shared_ptr<ShaderFunction> function) {
if (!function) {
return *this;
}
if (function->GetStage() == ShaderStage::kUnknown) {
return *this;
}
entrypoints_[function->GetStage()] = std::move(function);
return *this;
}
PipelineBuilder& PipelineBuilder::SetVertexDescriptor(
std::shared_ptr<VertexDescriptor> vertex_descriptor) {
vertex_descriptor_ = std::move(vertex_descriptor);
return *this;
}
} // namespace impeller

View File

@ -4,17 +4,53 @@
#pragma once
#include <Metal/Metal.h>
#include <functional>
#include <map>
#include <memory>
#include <string>
#include <string_view>
#include <type_traits>
#include "flutter/fml/macros.h"
#include "impeller/shader_glue/shader_types.h"
namespace impeller {
class ShaderFunction;
class VertexDescriptor;
class PipelineDescriptor {
public:
struct HashEqual {
std::size_t operator()(const PipelineDescriptor& des) const;
bool operator()(const PipelineDescriptor& d1,
const PipelineDescriptor& d2) const;
};
PipelineDescriptor();
~PipelineDescriptor();
PipelineDescriptor& SetLabel(const std::string_view& label);
PipelineDescriptor& SetSampleCount(size_t samples);
PipelineDescriptor& AddStageEntrypoint(
std::shared_ptr<const ShaderFunction> function);
PipelineDescriptor& SetVertexDescriptor(
std::shared_ptr<VertexDescriptor> vertex_descriptor);
MTLRenderPipelineDescriptor* GetMTLRenderPipelineDescriptor() const;
private:
std::string label_;
size_t sample_count_ = 1;
std::map<ShaderStage, std::shared_ptr<const ShaderFunction>> entrypoints_;
std::shared_ptr<VertexDescriptor> vertex_descriptor_;
FML_DISALLOW_COPY_AND_ASSIGN(PipelineDescriptor);
};

View File

@ -4,10 +4,75 @@
#include "impeller/compositor/pipeline_descriptor.h"
#include "flutter/fml/hash_combine.h"
#include "impeller/compositor/shader_library.h"
namespace impeller {
PipelineDescriptor::PipelineDescriptor() = default;
PipelineDescriptor::~PipelineDescriptor() = default;
std::size_t PipelineDescriptor::HashEqual::operator()(
const PipelineDescriptor& des) const {
auto seed = fml::HashCombine();
fml::HashCombineSeed(seed, des.label_);
for (const auto& entry : des.entrypoints_) {
fml::HashCombineSeed(seed, entry)
}
}
bool PipelineDescriptor::HashEqual::operator()(
const PipelineDescriptor& d1,
const PipelineDescriptor& d2) const {}
PipelineDescriptor& PipelineDescriptor::SetLabel(
const std::string_view& label) {
label_ = {label.data(), label.size()};
return *this;
}
PipelineDescriptor& PipelineDescriptor::SetSampleCount(size_t samples) {
sample_count_ = samples;
return *this;
}
PipelineDescriptor& PipelineDescriptor::AddStageEntrypoint(
std::shared_ptr<const ShaderFunction> function) {
if (!function) {
return *this;
}
if (function->GetStage() == ShaderStage::kUnknown) {
return *this;
}
entrypoints_[function->GetStage()] = std::move(function);
return *this;
}
PipelineDescriptor& PipelineDescriptor::SetVertexDescriptor(
std::shared_ptr<VertexDescriptor> vertex_descriptor) {
vertex_descriptor_ = std::move(vertex_descriptor);
return *this;
}
MTLRenderPipelineDescriptor*
PipelineDescriptor::GetMTLRenderPipelineDescriptor() const {
auto descriptor = [[MTLRenderPipelineDescriptor alloc] init];
descriptor.label = @(label_.c_str());
descriptor.sampleCount = sample_count_;
for (const auto& entry : entrypoints_) {
if (entry.first == ShaderStage::kVertex) {
descriptor.vertexFunction = entry.second->GetMTLFunction();
}
if (entry.first == ShaderStage::kFragment) {
descriptor.fragmentFunction = entry.second->GetMTLFunction();
}
}
return descriptor;
}
} // namespace impeller

View File

@ -4,17 +4,34 @@
#pragma once
#include <Metal/Metal.h>
#include <future>
#include <unordered_map>
#include "flutter/fml/macros.h"
#include "impeller/compositor/pipeline.h"
#include "impeller/compositor/pipeline_descriptor.h"
namespace impeller {
class PipelineLibrary {
public:
PipelineLibrary();
PipelineLibrary(id<MTLDevice> device);
~PipelineLibrary();
std::future<std::shared_ptr<Pipeline>> GetRenderPipeline(
PipelineDescriptor descriptor);
private:
using Pipelines = std::unordered_map<PipelineDescriptor,
std::shared_ptr<const Pipeline>,
PipelineDescriptor::HashEqual,
PipelineDescriptor::HashEqual>;
id<MTLDevice> device_;
Pipelines pipelines_;
FML_DISALLOW_COPY_AND_ASSIGN(PipelineLibrary);
};

View File

@ -0,0 +1,45 @@
// 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.
#include "impeller/compositor/pipeline_library.h"
#include <memory>
#include "flutter/fml/logging.h"
namespace impeller {
PipelineLibrary::PipelineLibrary(id<MTLDevice> device) : device_(device) {}
PipelineLibrary::~PipelineLibrary() = default;
std::future<std::shared_ptr<Pipeline>> PipelineLibrary::GetRenderPipeline(
PipelineDescriptor descriptor) {
auto promise = std::make_shared<std::promise<std::shared_ptr<Pipeline>>>();
auto future = promise->get_future();
if (auto found = pipelines_.find(descriptor); found != pipelines_.end()) {
promise->set_value(nullptr);
return future;
}
auto completion_handler =
^(id<MTLRenderPipelineState> _Nullable render_pipeline_state,
NSError* _Nullable error) {
if (error != nil) {
FML_LOG(ERROR) << "Could not create render pipeline: "
<< error.localizedDescription.UTF8String;
promise->set_value(nullptr);
} else {
promise->set_value(
std::shared_ptr<Pipeline>(new Pipeline(render_pipeline_state)));
}
};
[device_
newRenderPipelineStateWithDescriptor:descriptor
.GetMTLRenderPipelineDescriptor()
completionHandler:completion_handler];
return future;
}
} // namespace impeller

View File

@ -9,7 +9,9 @@
#include <memory>
#include <string>
#include <string_view>
#include <unordered_map>
#include "flutter/fml/hash_combine.h"
#include "flutter/fml/macros.h"
#include "impeller/shader_glue/shader_types.h"
@ -23,6 +25,8 @@ class ShaderFunction {
ShaderStage GetStage() const;
id<MTLFunction> GetMTLFunction() const;
private:
friend class ShaderLibrary;
@ -38,13 +42,40 @@ class ShaderLibrary {
public:
~ShaderLibrary();
std::shared_ptr<ShaderFunction> GetFunction(const std::string_view& name,
ShaderStage stage);
std::shared_ptr<const ShaderFunction> GetFunction(
const std::string_view& name,
ShaderStage stage);
private:
friend class Context;
struct ShaderKey {
std::string name;
ShaderStage stage = ShaderStage::kUnknown;
ShaderKey(const std::string_view& p_name, ShaderStage p_stage)
: name({p_name.data(), p_name.size()}), stage(p_stage) {}
struct Hash {
size_t operator()(const ShaderKey& key) const {
return fml::HashCombine(key.name, key.stage);
}
};
struct Equal {
constexpr bool operator()(const ShaderKey& k1,
const ShaderKey& k2) const {
return k1.stage == k2.stage && k1.name == k2.name;
}
};
};
id<MTLLibrary> library_ = nullptr;
using Functions = std::unordered_map<ShaderKey,
std::shared_ptr<const ShaderFunction>,
ShaderKey::Hash,
ShaderKey::Equal>;
Functions functions_;
ShaderLibrary(id<MTLLibrary> library);

View File

@ -11,6 +11,10 @@ ShaderFunction::ShaderFunction(id<MTLFunction> function, ShaderStage stage)
ShaderFunction::~ShaderFunction() = default;
id<MTLFunction> ShaderFunction::GetMTLFunction() const {
return function_;
}
ShaderStage ShaderFunction::GetStage() const {
return stage_;
}
@ -19,14 +23,24 @@ ShaderLibrary::ShaderLibrary(id<MTLLibrary> library) : library_(library) {}
ShaderLibrary::~ShaderLibrary() = default;
std::shared_ptr<ShaderFunction> ShaderLibrary::GetFunction(
std::shared_ptr<const ShaderFunction> ShaderLibrary::GetFunction(
const std::string_view& name,
ShaderStage stage) {
ShaderKey key(name, stage);
if (auto found = functions_.find(key); found != functions_.end()) {
return found->second;
}
auto function = [library_ newFunctionWithName:@(name.data())];
if (!function) {
return nullptr;
}
return std::shared_ptr<ShaderFunction>(new ShaderFunction(function, stage));
auto func =
std::shared_ptr<ShaderFunction>(new ShaderFunction(function, stage));
functions_[key] = func;
return func;
}
} // namespace impeller

View File

@ -6,21 +6,21 @@
#include "box.frag.h"
#include "box.vert.h"
#include "impeller/compositor/pipeline_builder.h"
#include "impeller/compositor/pipeline_descriptor.h"
#include "impeller/compositor/shader_library.h"
namespace impeller {
void RenderBox(std::shared_ptr<Context> context) {
PipelineBuilder builder;
auto fragment_function = context->GetShaderLibrary()->GetFunction(
shader::BoxFragmentInfo::kEntrypointName, ShaderStage::kFragment);
auto vertex_function = context->GetShaderLibrary()->GetFunction(
shader::BoxVertexInfo::kEntrypointName, ShaderStage::kVertex);
PipelineDescriptor builder;
builder.SetLabel(shader::BoxVertexInfo::kLabel);
builder.AddStageEntrypoint(vertex_function);
builder.AddStageEntrypoint(fragment_function);
builder.SetLabel(shader::BoxVertexInfo::kLabel);
}
} // namespace impeller