From f86c10efca0188d2dd1094dbc5b4958f9ecc3b4b Mon Sep 17 00:00:00 2001 From: Chinmay Garde Date: Tue, 29 Jun 2021 17:27:59 -0700 Subject: [PATCH] Wire up samplers. --- .../src/flutter/impeller/compositor/BUILD.gn | 2 + .../src/flutter/impeller/compositor/context.h | 4 ++ .../flutter/impeller/compositor/context.mm | 11 ++++ .../src/flutter/impeller/compositor/formats.h | 17 +++++ .../impeller/compositor/formats_metal.h | 23 +++++++ .../impeller/compositor/pipeline_library.h | 2 +- .../src/flutter/impeller/compositor/sampler.h | 12 +++- .../flutter/impeller/compositor/sampler.mm | 6 +- .../impeller/compositor/sampler_descriptor.h | 64 +++++++++++++++++++ .../impeller/compositor/sampler_descriptor.mm | 43 +++++++++++++ .../impeller/entity/entity_renderer.mm | 10 ++- .../src/flutter/impeller/primitives/box.frag | 10 ++- .../src/flutter/impeller/primitives/box.vert | 3 + 13 files changed, 200 insertions(+), 7 deletions(-) create mode 100644 engine/src/flutter/impeller/compositor/sampler_descriptor.h create mode 100644 engine/src/flutter/impeller/compositor/sampler_descriptor.mm diff --git a/engine/src/flutter/impeller/compositor/BUILD.gn b/engine/src/flutter/impeller/compositor/BUILD.gn index ebb93652f2c..3e2eec64d6d 100644 --- a/engine/src/flutter/impeller/compositor/BUILD.gn +++ b/engine/src/flutter/impeller/compositor/BUILD.gn @@ -44,6 +44,8 @@ impeller_component("compositor") { "renderer.mm", "sampler.h", "sampler.mm", + "sampler_descriptor.h", + "sampler_descriptor.mm", "shader_function.h", "shader_function.mm", "shader_library.h", diff --git a/engine/src/flutter/impeller/compositor/context.h b/engine/src/flutter/impeller/compositor/context.h index 5d40a251b46..19200cfcc78 100644 --- a/engine/src/flutter/impeller/compositor/context.h +++ b/engine/src/flutter/impeller/compositor/context.h @@ -14,6 +14,7 @@ namespace impeller { class ShaderLibrary; +class SamplerLibrary; class CommandBuffer; class Allocator; @@ -39,6 +40,8 @@ class Context { std::shared_ptr GetShaderLibrary() const; + std::shared_ptr GetSamplerLibrary() const; + std::shared_ptr GetPipelineLibrary() const; std::shared_ptr CreateRenderCommandBuffer() const; @@ -49,6 +52,7 @@ class Context { id transfer_queue_ = nullptr; std::shared_ptr shader_library_; std::shared_ptr pipeline_library_; + std::shared_ptr sampler_library_; std::shared_ptr permanents_allocator_; std::shared_ptr transients_allocator_; bool is_valid_ = false; diff --git a/engine/src/flutter/impeller/compositor/context.mm b/engine/src/flutter/impeller/compositor/context.mm index 4b222b013a5..f02e99f8da6 100644 --- a/engine/src/flutter/impeller/compositor/context.mm +++ b/engine/src/flutter/impeller/compositor/context.mm @@ -8,6 +8,7 @@ #include "flutter/fml/paths.h" #include "impeller/compositor/allocator.h" #include "impeller/compositor/command_buffer.h" +#include "impeller/compositor/sampler_descriptor.h" #include "impeller/compositor/shader_library.h" namespace impeller { @@ -55,6 +56,12 @@ Context::Context(std::string shaders_directory) std::shared_ptr(new PipelineLibrary(device_)); } + // Setup the sampler library. + { // + sampler_library_ = + std::shared_ptr(new SamplerLibrary(device_)); + } + { transients_allocator_ = std::shared_ptr( new Allocator(device_, "Impeller Transients Allocator")); @@ -86,6 +93,10 @@ std::shared_ptr Context::GetPipelineLibrary() const { return pipeline_library_; } +std::shared_ptr Context::GetSamplerLibrary() const { + return sampler_library_; +} + std::shared_ptr Context::CreateRenderCommandBuffer() const { if (!IsValid()) { return nullptr; diff --git a/engine/src/flutter/impeller/compositor/formats.h b/engine/src/flutter/impeller/compositor/formats.h index 1dda35737a4..c970edc1886 100644 --- a/engine/src/flutter/impeller/compositor/formats.h +++ b/engine/src/flutter/impeller/compositor/formats.h @@ -66,6 +66,23 @@ enum class PrimitiveType { // checks. Hence, they are not supported here. }; +enum class MinMagFilter { + /// Select nearest to the sample point. Most widely supported. + kNearest, + /// Select two points and linearly interpolate between them. Some formats may + /// not support this. + kLinear, +}; + +enum class SamplerAddressMode { + kClampToEdge, + kRepeat, + kMirror, + // More modes are almost always supported but they are usually behind + // extensions checks. The ones current in these structs are safe (always + // supported) defaults. +}; + enum class ColorWriteMask : uint64_t { kNone = 0, kRed = 1 << 0, diff --git a/engine/src/flutter/impeller/compositor/formats_metal.h b/engine/src/flutter/impeller/compositor/formats_metal.h index a1d63def214..970b1ad5388 100644 --- a/engine/src/flutter/impeller/compositor/formats_metal.h +++ b/engine/src/flutter/impeller/compositor/formats_metal.h @@ -215,6 +215,29 @@ constexpr StoreAction FromMTLStoreAction(MTLStoreAction action) { return StoreAction::kDontCare; } +constexpr MTLSamplerMinMagFilter ToMTLSamplerMinMagFilter(MinMagFilter filter) { + switch (filter) { + case MinMagFilter::kNearest: + return MTLSamplerMinMagFilterNearest; + case MinMagFilter::kLinear: + return MTLSamplerMinMagFilterLinear; + } + return MTLSamplerMinMagFilterNearest; +} + +constexpr MTLSamplerAddressMode ToMTLSamplerAddressMode( + SamplerAddressMode mode) { + switch (mode) { + case SamplerAddressMode::kClampToEdge: + return MTLSamplerAddressModeClampToEdge; + case SamplerAddressMode::kRepeat: + return MTLSamplerAddressModeRepeat; + case SamplerAddressMode::kMirror: + return MTLSamplerAddressModeMirrorRepeat; + } + return MTLSamplerAddressModeClampToEdge; +} + constexpr MTLClearColor ToMTLClearColor(const Color& color) { return MTLClearColorMake(color.red, color.green, color.blue, color.alpha); } diff --git a/engine/src/flutter/impeller/compositor/pipeline_library.h b/engine/src/flutter/impeller/compositor/pipeline_library.h index bf8b7eda553..b350ac91342 100644 --- a/engine/src/flutter/impeller/compositor/pipeline_library.h +++ b/engine/src/flutter/impeller/compositor/pipeline_library.h @@ -32,7 +32,7 @@ class PipelineLibrary : public std::enable_shared_from_this { std::shared_ptr, ComparableHash, ComparableEqual>; - id device_; + id device_ = nullptr; Pipelines pipelines_; PipelineLibrary(id device); diff --git a/engine/src/flutter/impeller/compositor/sampler.h b/engine/src/flutter/impeller/compositor/sampler.h index de73319410c..b1d875c954e 100644 --- a/engine/src/flutter/impeller/compositor/sampler.h +++ b/engine/src/flutter/impeller/compositor/sampler.h @@ -4,17 +4,27 @@ #pragma once +#include + #include "flutter/fml/macros.h" namespace impeller { +class SamplerLibrary; + class Sampler { public: - Sampler(); + bool IsValid() const; ~Sampler(); private: + friend SamplerLibrary; + + id state_ = nullptr; + + Sampler(id state); + FML_DISALLOW_COPY_AND_ASSIGN(Sampler); }; diff --git a/engine/src/flutter/impeller/compositor/sampler.mm b/engine/src/flutter/impeller/compositor/sampler.mm index 14678d946a1..82c23788992 100644 --- a/engine/src/flutter/impeller/compositor/sampler.mm +++ b/engine/src/flutter/impeller/compositor/sampler.mm @@ -6,8 +6,12 @@ namespace impeller { -Sampler::Sampler() = default; +Sampler::Sampler(id state) : state_(state) {} Sampler::~Sampler() = default; +bool Sampler::IsValid() const { + return state_; +} + } // namespace impeller diff --git a/engine/src/flutter/impeller/compositor/sampler_descriptor.h b/engine/src/flutter/impeller/compositor/sampler_descriptor.h new file mode 100644 index 00000000000..b07bacfe82a --- /dev/null +++ b/engine/src/flutter/impeller/compositor/sampler_descriptor.h @@ -0,0 +1,64 @@ +// 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 + +#include + +#include "flutter/fml/macros.h" +#include "impeller/compositor/comparable.h" +#include "impeller/compositor/formats.h" + +namespace impeller { + +class Sampler; +class Context; + +struct SamplerDescriptor final : public Comparable { + MinMagFilter min_filter = MinMagFilter::kNearest; + MinMagFilter mag_filter = MinMagFilter::kNearest; + + SamplerAddressMode width_address_mode = SamplerAddressMode::kClampToEdge; + SamplerAddressMode height_address_mode = SamplerAddressMode::kClampToEdge; + SamplerAddressMode depth_address_mode = SamplerAddressMode::kClampToEdge; + + // Comparable + std::size_t GetHash() const override { + return fml::HashCombine(min_filter, mag_filter, width_address_mode, + height_address_mode, depth_address_mode); + } + + // Comparable + bool IsEqual(const SamplerDescriptor& o) const override { + return min_filter == o.min_filter && mag_filter == o.mag_filter && + width_address_mode == o.width_address_mode && + height_address_mode == o.height_address_mode && + depth_address_mode == o.depth_address_mode; + } +}; + +class SamplerLibrary { + public: + ~SamplerLibrary(); + + std::shared_ptr GetSampler(SamplerDescriptor descriptor); + + private: + friend Context; + + using Samplers = std::unordered_map, + ComparableHash, + ComparableEqual>; + id device_ = nullptr; + Samplers samplers_; + + SamplerLibrary(id device); + + FML_DISALLOW_COPY_AND_ASSIGN(SamplerLibrary); +}; + +} // namespace impeller diff --git a/engine/src/flutter/impeller/compositor/sampler_descriptor.mm b/engine/src/flutter/impeller/compositor/sampler_descriptor.mm new file mode 100644 index 00000000000..b59dfae8908 --- /dev/null +++ b/engine/src/flutter/impeller/compositor/sampler_descriptor.mm @@ -0,0 +1,43 @@ +// 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/sampler_descriptor.h" + +#include "impeller/compositor/formats_metal.h" +#include "impeller/compositor/sampler.h" + +namespace impeller { + +SamplerLibrary::SamplerLibrary(id device) : device_(device) {} + +SamplerLibrary::~SamplerLibrary() = default; + +std::shared_ptr SamplerLibrary::GetSampler( + SamplerDescriptor descriptor) { + auto found = samplers_.find(descriptor); + if (found != samplers_.end()) { + return found->second; + } + if (!device_) { + return nullptr; + } + auto desc = [[MTLSamplerDescriptor alloc] init]; + desc.minFilter = ToMTLSamplerMinMagFilter(descriptor.min_filter); + desc.magFilter = ToMTLSamplerMinMagFilter(descriptor.mag_filter); + desc.sAddressMode = MTLSamplerAddressMode(descriptor.width_address_mode); + desc.rAddressMode = MTLSamplerAddressMode(descriptor.depth_address_mode); + desc.tAddressMode = MTLSamplerAddressMode(descriptor.height_address_mode); + auto mtl_sampler = [device_ newSamplerStateWithDescriptor:desc]; + if (!mtl_sampler) { + return nullptr; + } + auto sampler = std::shared_ptr(new Sampler(mtl_sampler)); + if (!sampler->IsValid()) { + return nullptr; + } + samplers_[descriptor] = sampler; + return sampler; +} + +} // namespace impeller diff --git a/engine/src/flutter/impeller/entity/entity_renderer.mm b/engine/src/flutter/impeller/entity/entity_renderer.mm index 06df740256d..896faddf9bb 100644 --- a/engine/src/flutter/impeller/entity/entity_renderer.mm +++ b/engine/src/flutter/impeller/entity/entity_renderer.mm @@ -32,9 +32,13 @@ EntityRenderer::EntityRenderer(std::string shaders_directory) VertexBufferBuilder vertex_builder; vertex_builder.SetLabel("Box"); vertex_builder.AddVertices({ - {{0, 0, 0.0}, {Color::Red()}}, // - {{800, 0.0, 0.0}, {Color::Green()}}, // - {{0.0, 600, 0.0}, {Color::Blue()}}, // + {{100, 100, 0.0}, {Color::Red()}}, // 1 + {{800, 100, 0.0}, {Color::Green()}}, // 2 + {{800, 800, 0.0}, {Color::Blue()}}, // 3 + + {{100, 100, 0.0}, {Color::Cyan()}}, // 1 + {{800, 800, 0.0}, {Color::White()}}, // 3 + {{100, 800, 0.0}, {Color::Purple()}}, // 4 }); vertex_buffer_ = diff --git a/engine/src/flutter/impeller/primitives/box.frag b/engine/src/flutter/impeller/primitives/box.frag index 0263c965f29..4a32a059ea3 100644 --- a/engine/src/flutter/impeller/primitives/box.frag +++ b/engine/src/flutter/impeller/primitives/box.frag @@ -3,9 +3,17 @@ // found in the LICENSE file. in vec4 color; +in vec2 interpolated_texture_coordinates; + +uniform sampler2D contents; +// uniform sampler2D texture_sampler2; +// uniform sampler2D texture_sampler3; out vec4 frag_color; void main() { - frag_color = color; + vec4 color1 = texture(contents, interpolated_texture_coordinates); + // vec4 color2 = texture(texture_sampler2, interpolated_texture_coordinates); + // vec4 color3 = texture(texture_sampler3, interpolated_texture_coordinates); + frag_color = color1; } diff --git a/engine/src/flutter/impeller/primitives/box.vert b/engine/src/flutter/impeller/primitives/box.vert index 431c4c04d1f..e764b6267b5 100644 --- a/engine/src/flutter/impeller/primitives/box.vert +++ b/engine/src/flutter/impeller/primitives/box.vert @@ -8,10 +8,13 @@ uniform UniformBuffer { in vec3 vertex_position; in vec4 vertex_color; +in vec2 texture_coordinates; out vec4 color; +out vec2 interpolated_texture_coordinates; void main() { gl_Position = uniforms.mvp * vec4(vertex_position, 1.0); color = vertex_color; + interpolated_texture_coordinates = texture_coordinates; }