[Impeller] reland:  switch Pipeline to use raw ptr instead of shared ptr for recorded references. (#57086)

Prev: https://github.com/flutter/engine/pull/57015

There is a unit test that is clearing out the pipeline storage, manually null out captured PipelineRef.
diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter
index 476cee8..812ea0e 100644
--- a/ci/licenses_golden/licenses_flutter
+++ b/ci/licenses_golden/licenses_flutter
@@ -42962,6 +42962,8 @@
 ORIGIN: ../../../flutter/impeller/core/platform.h + ../../../flutter/LICENSE
 ORIGIN: ../../../flutter/impeller/core/range.cc + ../../../flutter/LICENSE
 ORIGIN: ../../../flutter/impeller/core/range.h + ../../../flutter/LICENSE
+ORIGIN: ../../../flutter/impeller/core/raw_ptr.cc + ../../../flutter/LICENSE
+ORIGIN: ../../../flutter/impeller/core/raw_ptr.h + ../../../flutter/LICENSE
 ORIGIN: ../../../flutter/impeller/core/resource_binder.cc + ../../../flutter/LICENSE
 ORIGIN: ../../../flutter/impeller/core/resource_binder.h + ../../../flutter/LICENSE
 ORIGIN: ../../../flutter/impeller/core/runtime_types.cc + ../../../flutter/LICENSE
@@ -45891,6 +45893,8 @@
 FILE: ../../../flutter/impeller/core/platform.h
 FILE: ../../../flutter/impeller/core/range.cc
 FILE: ../../../flutter/impeller/core/range.h
+FILE: ../../../flutter/impeller/core/raw_ptr.cc
+FILE: ../../../flutter/impeller/core/raw_ptr.h
 FILE: ../../../flutter/impeller/core/resource_binder.cc
 FILE: ../../../flutter/impeller/core/resource_binder.h
 FILE: ../../../flutter/impeller/core/runtime_types.cc
diff --git a/impeller/core/BUILD.gn b/impeller/core/BUILD.gn
index bb7ef28..f88f90c 100644
--- a/impeller/core/BUILD.gn
+++ b/impeller/core/BUILD.gn
@@ -23,6 +23,8 @@
     "platform.h",
     "range.cc",
     "range.h",
+    "raw_ptr.cc",
+    "raw_ptr.h",
     "resource_binder.cc",
     "resource_binder.h",
     "runtime_types.cc",
diff --git a/impeller/core/raw_ptr.cc b/impeller/core/raw_ptr.cc
new file mode 100644
index 0000000..314c2e0
--- /dev/null
+++ b/impeller/core/raw_ptr.cc
@@ -0,0 +1,11 @@
+// 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/core/raw_ptr.h"
+
+namespace impeller {
+
+//
+
+}
diff --git a/impeller/core/raw_ptr.h b/impeller/core/raw_ptr.h
new file mode 100644
index 0000000..9348cfe
--- /dev/null
+++ b/impeller/core/raw_ptr.h
@@ -0,0 +1,84 @@
+// 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.
+
+#ifndef FLUTTER_IMPELLER_CORE_RAW_PTR_H_
+#define FLUTTER_IMPELLER_CORE_RAW_PTR_H_
+
+#include <memory>
+
+namespace impeller {
+
+/// @brief A wrapper around a raw ptr that adds additional unopt mode only
+/// checks.
+template <typename T>
+class raw_ptr {
+ public:
+  explicit raw_ptr(const std::shared_ptr<T>& ptr)
+      : ptr_(ptr.get())
+#if !NDEBUG
+        ,
+        weak_ptr_(ptr)
+#endif
+  {
+  }
+
+  raw_ptr() : ptr_(nullptr) {}
+
+  T* operator->() {
+#if !NDEBUG
+    FML_CHECK(weak_ptr_.lock());
+#endif
+    return ptr_;
+  }
+
+  const T* operator->() const {
+#if !NDEBUG
+    FML_CHECK(weak_ptr_.lock());
+#endif
+    return ptr_;
+  }
+
+  T* get() {
+#if !NDEBUG
+    FML_CHECK(weak_ptr_.lock());
+#endif
+    return ptr_;
+  }
+
+  T& operator*() {
+#if !NDEBUG
+    FML_CHECK(weak_ptr_.lock());
+#endif
+    return *ptr_;
+  }
+
+  const T& operator*() const {
+#if !NDEBUG
+    FML_CHECK(weak_ptr_.lock());
+#endif
+    return *ptr_;
+  }
+
+  template <class U>
+  inline bool operator==(raw_ptr<U> const& other) const {
+    return ptr_ == other.ptr_;
+  }
+
+  template <class U>
+  inline bool operator!=(raw_ptr<U> const& other) const {
+    return !(*this == other);
+  }
+
+  explicit operator bool() const { return !!ptr_; }
+
+ private:
+  T* ptr_;
+#if !NDEBUG
+  std::weak_ptr<T> weak_ptr_;
+#endif
+};
+
+}  // namespace impeller
+
+#endif  // FLUTTER_IMPELLER_CORE_RAW_PTR_H_
diff --git a/impeller/entity/contents/color_source_contents.h b/impeller/entity/contents/color_source_contents.h
index 76a49ff..17eba81 100644
--- a/impeller/entity/contents/color_source_contents.h
+++ b/impeller/entity/contents/color_source_contents.h
@@ -104,8 +104,7 @@
   using PipelineBuilderMethod = std::shared_ptr<Pipeline<PipelineDescriptor>> (
       impeller::ContentContext::*)(ContentContextOptions) const;
   using PipelineBuilderCallback =
-      std::function<std::shared_ptr<Pipeline<PipelineDescriptor>>(
-          ContentContextOptions)>;
+      std::function<PipelineRef(ContentContextOptions)>;
   using CreateGeometryCallback =
       std::function<GeometryResult(const ContentContext& renderer,
                                    const Entity& entity,
diff --git a/impeller/entity/contents/content_context.cc b/impeller/entity/contents/content_context.cc
index b3cc2d9..a214b43 100644
--- a/impeller/entity/contents/content_context.cc
+++ b/impeller/entity/contents/content_context.cc
@@ -569,8 +569,7 @@
   wireframe_ = wireframe;
 }
 
-std::shared_ptr<Pipeline<PipelineDescriptor>>
-ContentContext::GetCachedRuntimeEffectPipeline(
+PipelineRef ContentContext::GetCachedRuntimeEffectPipeline(
     const std::string& unique_entrypoint_name,
     const ContentContextOptions& options,
     const std::function<std::shared_ptr<Pipeline<PipelineDescriptor>>()>&
@@ -580,7 +579,7 @@
   if (it == runtime_effect_pipelines_.end()) {
     it = runtime_effect_pipelines_.insert(it, {key, create_callback()});
   }
-  return it->second;
+  return raw_ptr(it->second);
 }
 
 void ContentContext::ClearCachedRuntimeEffectPipeline(
diff --git a/impeller/entity/contents/content_context.h b/impeller/entity/contents/content_context.h
index 0cfb4a2..0a0aee3 100644
--- a/impeller/entity/contents/content_context.h
+++ b/impeller/entity/contents/content_context.h
@@ -377,102 +377,93 @@
 
   Tessellator& GetTessellator() const;
 
-  std::shared_ptr<Pipeline<PipelineDescriptor>> GetFastGradientPipeline(
-      ContentContextOptions opts) const {
+  PipelineRef GetFastGradientPipeline(ContentContextOptions opts) const {
     return GetPipeline(fast_gradient_pipelines_, opts);
   }
 
-  std::shared_ptr<Pipeline<PipelineDescriptor>> GetLinearGradientFillPipeline(
-      ContentContextOptions opts) const {
+  PipelineRef GetLinearGradientFillPipeline(ContentContextOptions opts) const {
     return GetPipeline(linear_gradient_fill_pipelines_, opts);
   }
 
-  std::shared_ptr<Pipeline<PipelineDescriptor>>
-  GetLinearGradientUniformFillPipeline(ContentContextOptions opts) const {
+  PipelineRef GetLinearGradientUniformFillPipeline(
+      ContentContextOptions opts) const {
     return GetPipeline(linear_gradient_uniform_fill_pipelines_, opts);
   }
 
-  std::shared_ptr<Pipeline<PipelineDescriptor>>
-  GetRadialGradientUniformFillPipeline(ContentContextOptions opts) const {
+  PipelineRef GetRadialGradientUniformFillPipeline(
+      ContentContextOptions opts) const {
     return GetPipeline(radial_gradient_uniform_fill_pipelines_, opts);
   }
 
-  std::shared_ptr<Pipeline<PipelineDescriptor>>
-  GetConicalGradientUniformFillPipeline(ContentContextOptions opts) const {
+  PipelineRef GetConicalGradientUniformFillPipeline(
+      ContentContextOptions opts) const {
     return GetPipeline(conical_gradient_uniform_fill_pipelines_, opts);
   }
 
-  std::shared_ptr<Pipeline<PipelineDescriptor>>
-  GetSweepGradientUniformFillPipeline(ContentContextOptions opts) const {
+  PipelineRef GetSweepGradientUniformFillPipeline(
+      ContentContextOptions opts) const {
     return GetPipeline(sweep_gradient_uniform_fill_pipelines_, opts);
   }
 
-  std::shared_ptr<Pipeline<PipelineDescriptor>>
-  GetLinearGradientSSBOFillPipeline(ContentContextOptions opts) const {
+  PipelineRef GetLinearGradientSSBOFillPipeline(
+      ContentContextOptions opts) const {
     FML_DCHECK(GetDeviceCapabilities().SupportsSSBO());
     return GetPipeline(linear_gradient_ssbo_fill_pipelines_, opts);
   }
 
-  std::shared_ptr<Pipeline<PipelineDescriptor>>
-  GetRadialGradientSSBOFillPipeline(ContentContextOptions opts) const {
+  PipelineRef GetRadialGradientSSBOFillPipeline(
+      ContentContextOptions opts) const {
     FML_DCHECK(GetDeviceCapabilities().SupportsSSBO());
     return GetPipeline(radial_gradient_ssbo_fill_pipelines_, opts);
   }
 
-  std::shared_ptr<Pipeline<PipelineDescriptor>>
-  GetConicalGradientSSBOFillPipeline(ContentContextOptions opts) const {
+  PipelineRef GetConicalGradientSSBOFillPipeline(
+      ContentContextOptions opts) const {
     FML_DCHECK(GetDeviceCapabilities().SupportsSSBO());
     return GetPipeline(conical_gradient_ssbo_fill_pipelines_, opts);
   }
 
-  std::shared_ptr<Pipeline<PipelineDescriptor>>
-  GetSweepGradientSSBOFillPipeline(ContentContextOptions opts) const {
+  PipelineRef GetSweepGradientSSBOFillPipeline(
+      ContentContextOptions opts) const {
     FML_DCHECK(GetDeviceCapabilities().SupportsSSBO());
     return GetPipeline(sweep_gradient_ssbo_fill_pipelines_, opts);
   }
 
-  std::shared_ptr<Pipeline<PipelineDescriptor>> GetRadialGradientFillPipeline(
-      ContentContextOptions opts) const {
+  PipelineRef GetRadialGradientFillPipeline(ContentContextOptions opts) const {
     return GetPipeline(radial_gradient_fill_pipelines_, opts);
   }
 
-  std::shared_ptr<Pipeline<PipelineDescriptor>> GetConicalGradientFillPipeline(
-      ContentContextOptions opts) const {
+  PipelineRef GetConicalGradientFillPipeline(ContentContextOptions opts) const {
     return GetPipeline(conical_gradient_fill_pipelines_, opts);
   }
 
-  std::shared_ptr<Pipeline<PipelineDescriptor>> GetRRectBlurPipeline(
-      ContentContextOptions opts) const {
+  PipelineRef GetRRectBlurPipeline(ContentContextOptions opts) const {
     return GetPipeline(rrect_blur_pipelines_, opts);
   }
 
-  std::shared_ptr<Pipeline<PipelineDescriptor>> GetSweepGradientFillPipeline(
-      ContentContextOptions opts) const {
+  PipelineRef GetSweepGradientFillPipeline(ContentContextOptions opts) const {
     return GetPipeline(sweep_gradient_fill_pipelines_, opts);
   }
 
-  std::shared_ptr<Pipeline<PipelineDescriptor>> GetSolidFillPipeline(
-      ContentContextOptions opts) const {
+  PipelineRef GetSolidFillPipeline(ContentContextOptions opts) const {
     return GetPipeline(solid_fill_pipelines_, opts);
   }
 
-  std::shared_ptr<Pipeline<PipelineDescriptor>> GetTexturePipeline(
-      ContentContextOptions opts) const {
+  PipelineRef GetTexturePipeline(ContentContextOptions opts) const {
     return GetPipeline(texture_pipelines_, opts);
   }
 
-  std::shared_ptr<Pipeline<PipelineDescriptor>> GetTextureStrictSrcPipeline(
-      ContentContextOptions opts) const {
+  PipelineRef GetTextureStrictSrcPipeline(ContentContextOptions opts) const {
     return GetPipeline(texture_strict_src_pipelines_, opts);
   }
 
 #ifdef IMPELLER_ENABLE_OPENGLES
-  std::shared_ptr<Pipeline<PipelineDescriptor>>
-  GetDownsampleTextureGlesPipeline(ContentContextOptions opts) const {
+  PipelineRef GetDownsampleTextureGlesPipeline(
+      ContentContextOptions opts) const {
     return GetPipeline(texture_downsample_gles_pipelines_, opts);
   }
 
-  std::shared_ptr<Pipeline<PipelineDescriptor>> GetTiledTextureExternalPipeline(
+  PipelineRef GetTiledTextureExternalPipeline(
       ContentContextOptions opts) const {
     FML_DCHECK(GetContext()->GetBackendType() ==
                Context::BackendType::kOpenGLES);
@@ -480,236 +471,208 @@
   }
 #endif  // IMPELLER_ENABLE_OPENGLES
 
-  std::shared_ptr<Pipeline<PipelineDescriptor>> GetTiledTexturePipeline(
-      ContentContextOptions opts) const {
+  PipelineRef GetTiledTexturePipeline(ContentContextOptions opts) const {
     return GetPipeline(tiled_texture_pipelines_, opts);
   }
 
-  std::shared_ptr<Pipeline<PipelineDescriptor>> GetGaussianBlurPipeline(
-      ContentContextOptions opts) const {
+  PipelineRef GetGaussianBlurPipeline(ContentContextOptions opts) const {
     return GetPipeline(gaussian_blur_pipelines_, opts);
   }
 
-  std::shared_ptr<Pipeline<PipelineDescriptor>> GetBorderMaskBlurPipeline(
-      ContentContextOptions opts) const {
+  PipelineRef GetBorderMaskBlurPipeline(ContentContextOptions opts) const {
     return GetPipeline(border_mask_blur_pipelines_, opts);
   }
 
-  std::shared_ptr<Pipeline<PipelineDescriptor>> GetMorphologyFilterPipeline(
-      ContentContextOptions opts) const {
+  PipelineRef GetMorphologyFilterPipeline(ContentContextOptions opts) const {
     return GetPipeline(morphology_filter_pipelines_, opts);
   }
 
-  std::shared_ptr<Pipeline<PipelineDescriptor>>
-  GetColorMatrixColorFilterPipeline(ContentContextOptions opts) const {
+  PipelineRef GetColorMatrixColorFilterPipeline(
+      ContentContextOptions opts) const {
     return GetPipeline(color_matrix_color_filter_pipelines_, opts);
   }
 
-  std::shared_ptr<Pipeline<PipelineDescriptor>> GetLinearToSrgbFilterPipeline(
-      ContentContextOptions opts) const {
+  PipelineRef GetLinearToSrgbFilterPipeline(ContentContextOptions opts) const {
     return GetPipeline(linear_to_srgb_filter_pipelines_, opts);
   }
 
-  std::shared_ptr<Pipeline<PipelineDescriptor>> GetSrgbToLinearFilterPipeline(
-      ContentContextOptions opts) const {
+  PipelineRef GetSrgbToLinearFilterPipeline(ContentContextOptions opts) const {
     return GetPipeline(srgb_to_linear_filter_pipelines_, opts);
   }
 
-  std::shared_ptr<Pipeline<PipelineDescriptor>> GetClipPipeline(
-      ContentContextOptions opts) const {
+  PipelineRef GetClipPipeline(ContentContextOptions opts) const {
     return GetPipeline(clip_pipelines_, opts);
   }
 
-  std::shared_ptr<Pipeline<PipelineDescriptor>> GetGlyphAtlasPipeline(
-      ContentContextOptions opts) const {
+  PipelineRef GetGlyphAtlasPipeline(ContentContextOptions opts) const {
     return GetPipeline(glyph_atlas_pipelines_, opts);
   }
 
-  std::shared_ptr<Pipeline<PipelineDescriptor>> GetYUVToRGBFilterPipeline(
-      ContentContextOptions opts) const {
+  PipelineRef GetYUVToRGBFilterPipeline(ContentContextOptions opts) const {
     return GetPipeline(yuv_to_rgb_filter_pipelines_, opts);
   }
 
-  std::shared_ptr<Pipeline<PipelineDescriptor>> GetPorterDuffBlendPipeline(
-      ContentContextOptions opts) const {
+  PipelineRef GetPorterDuffBlendPipeline(ContentContextOptions opts) const {
     return GetPipeline(porter_duff_blend_pipelines_, opts);
   }
 
   // Advanced blends.
 
-  std::shared_ptr<Pipeline<PipelineDescriptor>> GetBlendColorPipeline(
-      ContentContextOptions opts) const {
+  PipelineRef GetBlendColorPipeline(ContentContextOptions opts) const {
     return GetPipeline(blend_color_pipelines_, opts);
   }
 
-  std::shared_ptr<Pipeline<PipelineDescriptor>> GetBlendColorBurnPipeline(
-      ContentContextOptions opts) const {
+  PipelineRef GetBlendColorBurnPipeline(ContentContextOptions opts) const {
     return GetPipeline(blend_colorburn_pipelines_, opts);
   }
 
-  std::shared_ptr<Pipeline<PipelineDescriptor>> GetBlendColorDodgePipeline(
-      ContentContextOptions opts) const {
+  PipelineRef GetBlendColorDodgePipeline(ContentContextOptions opts) const {
     return GetPipeline(blend_colordodge_pipelines_, opts);
   }
 
-  std::shared_ptr<Pipeline<PipelineDescriptor>> GetBlendDarkenPipeline(
-      ContentContextOptions opts) const {
+  PipelineRef GetBlendDarkenPipeline(ContentContextOptions opts) const {
     return GetPipeline(blend_darken_pipelines_, opts);
   }
 
-  std::shared_ptr<Pipeline<PipelineDescriptor>> GetBlendDifferencePipeline(
-      ContentContextOptions opts) const {
+  PipelineRef GetBlendDifferencePipeline(ContentContextOptions opts) const {
     return GetPipeline(blend_difference_pipelines_, opts);
   }
 
-  std::shared_ptr<Pipeline<PipelineDescriptor>> GetBlendExclusionPipeline(
-      ContentContextOptions opts) const {
+  PipelineRef GetBlendExclusionPipeline(ContentContextOptions opts) const {
     return GetPipeline(blend_exclusion_pipelines_, opts);
   }
 
-  std::shared_ptr<Pipeline<PipelineDescriptor>> GetBlendHardLightPipeline(
-      ContentContextOptions opts) const {
+  PipelineRef GetBlendHardLightPipeline(ContentContextOptions opts) const {
     return GetPipeline(blend_hardlight_pipelines_, opts);
   }
 
-  std::shared_ptr<Pipeline<PipelineDescriptor>> GetBlendHuePipeline(
-      ContentContextOptions opts) const {
+  PipelineRef GetBlendHuePipeline(ContentContextOptions opts) const {
     return GetPipeline(blend_hue_pipelines_, opts);
   }
 
-  std::shared_ptr<Pipeline<PipelineDescriptor>> GetBlendLightenPipeline(
-      ContentContextOptions opts) const {
+  PipelineRef GetBlendLightenPipeline(ContentContextOptions opts) const {
     return GetPipeline(blend_lighten_pipelines_, opts);
   }
 
-  std::shared_ptr<Pipeline<PipelineDescriptor>> GetBlendLuminosityPipeline(
-      ContentContextOptions opts) const {
+  PipelineRef GetBlendLuminosityPipeline(ContentContextOptions opts) const {
     return GetPipeline(blend_luminosity_pipelines_, opts);
   }
 
-  std::shared_ptr<Pipeline<PipelineDescriptor>> GetBlendMultiplyPipeline(
-      ContentContextOptions opts) const {
+  PipelineRef GetBlendMultiplyPipeline(ContentContextOptions opts) const {
     return GetPipeline(blend_multiply_pipelines_, opts);
   }
 
-  std::shared_ptr<Pipeline<PipelineDescriptor>> GetBlendOverlayPipeline(
-      ContentContextOptions opts) const {
+  PipelineRef GetBlendOverlayPipeline(ContentContextOptions opts) const {
     return GetPipeline(blend_overlay_pipelines_, opts);
   }
 
-  std::shared_ptr<Pipeline<PipelineDescriptor>> GetBlendSaturationPipeline(
-      ContentContextOptions opts) const {
+  PipelineRef GetBlendSaturationPipeline(ContentContextOptions opts) const {
     return GetPipeline(blend_saturation_pipelines_, opts);
   }
 
-  std::shared_ptr<Pipeline<PipelineDescriptor>> GetBlendScreenPipeline(
-      ContentContextOptions opts) const {
+  PipelineRef GetBlendScreenPipeline(ContentContextOptions opts) const {
     return GetPipeline(blend_screen_pipelines_, opts);
   }
 
-  std::shared_ptr<Pipeline<PipelineDescriptor>> GetBlendSoftLightPipeline(
-      ContentContextOptions opts) const {
+  PipelineRef GetBlendSoftLightPipeline(ContentContextOptions opts) const {
     return GetPipeline(blend_softlight_pipelines_, opts);
   }
 
-  std::shared_ptr<Pipeline<PipelineDescriptor>> GetDownsamplePipeline(
-      ContentContextOptions opts) const {
+  PipelineRef GetDownsamplePipeline(ContentContextOptions opts) const {
     return GetPipeline(texture_downsample_pipelines_, opts);
   }
 
   // Framebuffer Advanced Blends
-  std::shared_ptr<Pipeline<PipelineDescriptor>>
-  GetFramebufferBlendColorPipeline(ContentContextOptions opts) const {
+  PipelineRef GetFramebufferBlendColorPipeline(
+      ContentContextOptions opts) const {
     FML_DCHECK(GetDeviceCapabilities().SupportsFramebufferFetch());
     return GetPipeline(framebuffer_blend_color_pipelines_, opts);
   }
 
-  std::shared_ptr<Pipeline<PipelineDescriptor>>
-  GetFramebufferBlendColorBurnPipeline(ContentContextOptions opts) const {
+  PipelineRef GetFramebufferBlendColorBurnPipeline(
+      ContentContextOptions opts) const {
     FML_DCHECK(GetDeviceCapabilities().SupportsFramebufferFetch());
     return GetPipeline(framebuffer_blend_colorburn_pipelines_, opts);
   }
 
-  std::shared_ptr<Pipeline<PipelineDescriptor>>
-  GetFramebufferBlendColorDodgePipeline(ContentContextOptions opts) const {
+  PipelineRef GetFramebufferBlendColorDodgePipeline(
+      ContentContextOptions opts) const {
     FML_DCHECK(GetDeviceCapabilities().SupportsFramebufferFetch());
     return GetPipeline(framebuffer_blend_colordodge_pipelines_, opts);
   }
 
-  std::shared_ptr<Pipeline<PipelineDescriptor>>
-  GetFramebufferBlendDarkenPipeline(ContentContextOptions opts) const {
+  PipelineRef GetFramebufferBlendDarkenPipeline(
+      ContentContextOptions opts) const {
     FML_DCHECK(GetDeviceCapabilities().SupportsFramebufferFetch());
     return GetPipeline(framebuffer_blend_darken_pipelines_, opts);
   }
 
-  std::shared_ptr<Pipeline<PipelineDescriptor>>
-  GetFramebufferBlendDifferencePipeline(ContentContextOptions opts) const {
+  PipelineRef GetFramebufferBlendDifferencePipeline(
+      ContentContextOptions opts) const {
     FML_DCHECK(GetDeviceCapabilities().SupportsFramebufferFetch());
     return GetPipeline(framebuffer_blend_difference_pipelines_, opts);
   }
 
-  std::shared_ptr<Pipeline<PipelineDescriptor>>
-  GetFramebufferBlendExclusionPipeline(ContentContextOptions opts) const {
+  PipelineRef GetFramebufferBlendExclusionPipeline(
+      ContentContextOptions opts) const {
     FML_DCHECK(GetDeviceCapabilities().SupportsFramebufferFetch());
     return GetPipeline(framebuffer_blend_exclusion_pipelines_, opts);
   }
 
-  std::shared_ptr<Pipeline<PipelineDescriptor>>
-  GetFramebufferBlendHardLightPipeline(ContentContextOptions opts) const {
+  PipelineRef GetFramebufferBlendHardLightPipeline(
+      ContentContextOptions opts) const {
     FML_DCHECK(GetDeviceCapabilities().SupportsFramebufferFetch());
     return GetPipeline(framebuffer_blend_hardlight_pipelines_, opts);
   }
 
-  std::shared_ptr<Pipeline<PipelineDescriptor>> GetFramebufferBlendHuePipeline(
-      ContentContextOptions opts) const {
+  PipelineRef GetFramebufferBlendHuePipeline(ContentContextOptions opts) const {
     FML_DCHECK(GetDeviceCapabilities().SupportsFramebufferFetch());
     return GetPipeline(framebuffer_blend_hue_pipelines_, opts);
   }
 
-  std::shared_ptr<Pipeline<PipelineDescriptor>>
-  GetFramebufferBlendLightenPipeline(ContentContextOptions opts) const {
+  PipelineRef GetFramebufferBlendLightenPipeline(
+      ContentContextOptions opts) const {
     FML_DCHECK(GetDeviceCapabilities().SupportsFramebufferFetch());
     return GetPipeline(framebuffer_blend_lighten_pipelines_, opts);
   }
 
-  std::shared_ptr<Pipeline<PipelineDescriptor>>
-  GetFramebufferBlendLuminosityPipeline(ContentContextOptions opts) const {
+  PipelineRef GetFramebufferBlendLuminosityPipeline(
+      ContentContextOptions opts) const {
     FML_DCHECK(GetDeviceCapabilities().SupportsFramebufferFetch());
     return GetPipeline(framebuffer_blend_luminosity_pipelines_, opts);
   }
 
-  std::shared_ptr<Pipeline<PipelineDescriptor>>
-  GetFramebufferBlendMultiplyPipeline(ContentContextOptions opts) const {
+  PipelineRef GetFramebufferBlendMultiplyPipeline(
+      ContentContextOptions opts) const {
     FML_DCHECK(GetDeviceCapabilities().SupportsFramebufferFetch());
     return GetPipeline(framebuffer_blend_multiply_pipelines_, opts);
   }
 
-  std::shared_ptr<Pipeline<PipelineDescriptor>>
-  GetFramebufferBlendOverlayPipeline(ContentContextOptions opts) const {
+  PipelineRef GetFramebufferBlendOverlayPipeline(
+      ContentContextOptions opts) const {
     FML_DCHECK(GetDeviceCapabilities().SupportsFramebufferFetch());
     return GetPipeline(framebuffer_blend_overlay_pipelines_, opts);
   }
 
-  std::shared_ptr<Pipeline<PipelineDescriptor>>
-  GetFramebufferBlendSaturationPipeline(ContentContextOptions opts) const {
+  PipelineRef GetFramebufferBlendSaturationPipeline(
+      ContentContextOptions opts) const {
     FML_DCHECK(GetDeviceCapabilities().SupportsFramebufferFetch());
     return GetPipeline(framebuffer_blend_saturation_pipelines_, opts);
   }
 
-  std::shared_ptr<Pipeline<PipelineDescriptor>>
-  GetFramebufferBlendScreenPipeline(ContentContextOptions opts) const {
+  PipelineRef GetFramebufferBlendScreenPipeline(
+      ContentContextOptions opts) const {
     FML_DCHECK(GetDeviceCapabilities().SupportsFramebufferFetch());
     return GetPipeline(framebuffer_blend_screen_pipelines_, opts);
   }
 
-  std::shared_ptr<Pipeline<PipelineDescriptor>>
-  GetFramebufferBlendSoftLightPipeline(ContentContextOptions opts) const {
+  PipelineRef GetFramebufferBlendSoftLightPipeline(
+      ContentContextOptions opts) const {
     FML_DCHECK(GetDeviceCapabilities().SupportsFramebufferFetch());
     return GetPipeline(framebuffer_blend_softlight_pipelines_, opts);
   }
 
-  std::shared_ptr<Pipeline<PipelineDescriptor>> GetDrawVerticesUberShader(
-      ContentContextOptions opts) const {
+  PipelineRef GetDrawVerticesUberShader(ContentContextOptions opts) const {
     return GetPipeline(vertices_uber_shader_, opts);
   }
 
@@ -761,7 +724,7 @@
   ///
   /// The create_callback is synchronously invoked exactly once if a cached
   /// pipeline is not found.
-  std::shared_ptr<Pipeline<PipelineDescriptor>> GetCachedRuntimeEffectPipeline(
+  PipelineRef GetCachedRuntimeEffectPipeline(
       const std::string& unique_entrypoint_name,
       const ContentContextOptions& options,
       const std::function<std::shared_ptr<Pipeline<PipelineDescriptor>>()>&
@@ -992,14 +955,13 @@
   mutable Variants<VerticesUberShader> vertices_uber_shader_;
 
   template <class TypedPipeline>
-  std::shared_ptr<Pipeline<PipelineDescriptor>> GetPipeline(
-      Variants<TypedPipeline>& container,
-      ContentContextOptions opts) const {
+  PipelineRef GetPipeline(Variants<TypedPipeline>& container,
+                          ContentContextOptions opts) const {
     TypedPipeline* pipeline = CreateIfNeeded(container, opts);
     if (!pipeline) {
-      return nullptr;
+      return raw_ptr<Pipeline<PipelineDescriptor>>();
     }
-    return pipeline->WaitAndGet();
+    return raw_ptr(pipeline->WaitAndGet());
   }
 
   template <class RenderPipelineHandleT>
@@ -1023,7 +985,7 @@
     // The default must always be initialized in the constructor.
     FML_CHECK(default_handle != nullptr);
 
-    std::shared_ptr<Pipeline<PipelineDescriptor>> pipeline =
+    const std::shared_ptr<Pipeline<PipelineDescriptor>>& pipeline =
         default_handle->WaitAndGet();
     if (!pipeline) {
       return nullptr;
diff --git a/impeller/entity/contents/filters/blend_filter_contents.cc b/impeller/entity/contents/filters/blend_filter_contents.cc
index b427de9..3f07150 100644
--- a/impeller/entity/contents/filters/blend_filter_contents.cc
+++ b/impeller/entity/contents/filters/blend_filter_contents.cc
@@ -71,8 +71,8 @@
 
 BlendFilterContents::~BlendFilterContents() = default;
 
-using PipelineProc = std::shared_ptr<Pipeline<PipelineDescriptor>> (
-    ContentContext::*)(ContentContextOptions) const;
+using PipelineProc =
+    PipelineRef (ContentContext::*)(ContentContextOptions) const;
 
 template <typename TPipeline>
 static std::optional<Entity> AdvancedBlend(
@@ -170,8 +170,7 @@
     auto options = OptionsFromPass(pass);
     options.primitive_type = PrimitiveType::kTriangleStrip;
     options.blend_mode = BlendMode::kSource;
-    std::shared_ptr<Pipeline<PipelineDescriptor>> pipeline =
-        std::invoke(pipeline_proc, renderer, options);
+    PipelineRef pipeline = std::invoke(pipeline_proc, renderer, options);
 
 #ifdef IMPELLER_DEBUG
     pass.SetCommandLabel(
diff --git a/impeller/entity/contents/test/recording_render_pass.cc b/impeller/entity/contents/test/recording_render_pass.cc
index 39a8f69..9c81b5b 100644
--- a/impeller/entity/contents/test/recording_render_pass.cc
+++ b/impeller/entity/contents/test/recording_render_pass.cc
@@ -15,8 +15,7 @@
     : RenderPass(context, render_target), delegate_(std::move(delegate)) {}
 
 // |RenderPass|
-void RecordingRenderPass::SetPipeline(
-    const std::shared_ptr<Pipeline<PipelineDescriptor>>& pipeline) {
+void RecordingRenderPass::SetPipeline(PipelineRef pipeline) {
   pending_.pipeline = pipeline;
   if (delegate_) {
     delegate_->SetPipeline(pipeline);
diff --git a/impeller/entity/contents/test/recording_render_pass.h b/impeller/entity/contents/test/recording_render_pass.h
index 3fb9b34..4172121 100644
--- a/impeller/entity/contents/test/recording_render_pass.h
+++ b/impeller/entity/contents/test/recording_render_pass.h
@@ -20,8 +20,7 @@
   const std::vector<Command>& GetCommands() const override { return commands_; }
 
   // |RenderPass|
-  void SetPipeline(
-      const std::shared_ptr<Pipeline<PipelineDescriptor>>& pipeline) override;
+  void SetPipeline(PipelineRef pipeline) override;
 
   void SetCommandLabel(std::string_view label) override;
 
diff --git a/impeller/entity/entity_unittests.cc b/impeller/entity/entity_unittests.cc
index ed4af45..968536e 100644
--- a/impeller/entity/entity_unittests.cc
+++ b/impeller/entity/entity_unittests.cc
@@ -15,6 +15,7 @@
 #include "impeller/core/device_buffer.h"
 #include "impeller/core/formats.h"
 #include "impeller/core/host_buffer.h"
+#include "impeller/core/raw_ptr.h"
 #include "impeller/core/texture_descriptor.h"
 #include "impeller/entity/contents/clip_contents.h"
 #include "impeller/entity/contents/conical_gradient_contents.h"
@@ -1696,7 +1697,8 @@
   ASSERT_TRUE(runtime_stage->IsDirty());
 
   bool expect_dirty = true;
-  Pipeline<PipelineDescriptor>* first_pipeline;
+
+  PipelineRef first_pipeline;
   std::unique_ptr<Geometry> geom = Geometry::MakeCover();
 
   auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
@@ -1723,12 +1725,10 @@
     bool result = contents->Render(context, entity, pass);
 
     if (expect_dirty) {
-      EXPECT_NE(first_pipeline, pass.GetCommands().back().pipeline.get());
-      first_pipeline = pass.GetCommands().back().pipeline.get();
+      first_pipeline = pass.GetCommands().back().pipeline;
     } else {
-      EXPECT_EQ(pass.GetCommands().back().pipeline.get(), first_pipeline);
+      EXPECT_EQ(pass.GetCommands().back().pipeline, first_pipeline);
     }
-
     expect_dirty = false;
     return result;
   };
diff --git a/impeller/playground/imgui/imgui_impl_impeller.cc b/impeller/playground/imgui/imgui_impl_impeller.cc
index caf346c..1eb7657 100644
--- a/impeller/playground/imgui/imgui_impl_impeller.cc
+++ b/impeller/playground/imgui/imgui_impl_impeller.cc
@@ -30,7 +30,6 @@
 #include "impeller/geometry/point.h"
 #include "impeller/geometry/rect.h"
 #include "impeller/geometry/size.h"
-#include "impeller/renderer/command.h"
 #include "impeller/renderer/context.h"
 #include "impeller/renderer/pipeline_builder.h"
 #include "impeller/renderer/pipeline_descriptor.h"
diff --git a/impeller/renderer/backend/metal/render_pass_mtl.h b/impeller/renderer/backend/metal/render_pass_mtl.h
index ee244ce..6639de4 100644
--- a/impeller/renderer/backend/metal/render_pass_mtl.h
+++ b/impeller/renderer/backend/metal/render_pass_mtl.h
@@ -58,8 +58,7 @@
   bool OnEncodeCommands(const Context& context) const override;
 
   // |RenderPass|
-  void SetPipeline(
-      const std::shared_ptr<Pipeline<PipelineDescriptor>>& pipeline) override;
+  void SetPipeline(PipelineRef pipeline) override;
 
   // |RenderPass|
   void SetCommandLabel(std::string_view label) override;
diff --git a/impeller/renderer/backend/metal/render_pass_mtl.mm b/impeller/renderer/backend/metal/render_pass_mtl.mm
index 203e97e..73e2054 100644
--- a/impeller/renderer/backend/metal/render_pass_mtl.mm
+++ b/impeller/renderer/backend/metal/render_pass_mtl.mm
@@ -233,8 +233,7 @@
 }
 
 // |RenderPass|
-void RenderPassMTL::SetPipeline(
-    const std::shared_ptr<Pipeline<PipelineDescriptor>>& pipeline) {
+void RenderPassMTL::SetPipeline(PipelineRef pipeline) {
   const PipelineDescriptor& pipeline_desc = pipeline->GetDescriptor();
   primitive_type_ = pipeline_desc.GetPrimitiveType();
   pass_bindings_.SetRenderPipelineState(
diff --git a/impeller/renderer/backend/vulkan/render_pass_vk.cc b/impeller/renderer/backend/vulkan/render_pass_vk.cc
index f8a169a..46315ff 100644
--- a/impeller/renderer/backend/vulkan/render_pass_vk.cc
+++ b/impeller/renderer/backend/vulkan/render_pass_vk.cc
@@ -293,9 +293,8 @@
 }
 
 // |RenderPass|
-void RenderPassVK::SetPipeline(
-    const std::shared_ptr<Pipeline<PipelineDescriptor>>& pipeline) {
-  pipeline_ = pipeline.get();
+void RenderPassVK::SetPipeline(PipelineRef pipeline) {
+  pipeline_ = pipeline;
   if (!pipeline_) {
     return;
   }
@@ -305,7 +304,7 @@
 
   if (pipeline_uses_input_attachments_) {
     if (bound_image_offset_ >= kMaxBindings) {
-      pipeline_ = nullptr;
+      pipeline_ = PipelineRef(nullptr);
       return;
     }
     vk::DescriptorImageInfo image_info;
@@ -464,7 +463,7 @@
   /// Jank can be completely eliminated by pre-populating known YUV conversion
   /// pipelines.
   if (immutable_sampler_) {
-    std::shared_ptr<PipelineVK> pipeline_variant =
+    std::shared_ptr<Pipeline<PipelineDescriptor>> pipeline_variant =
         PipelineVK::Cast(*pipeline_)
             .CreateVariantForImmutableSamplers(immutable_sampler_);
     if (!pipeline_variant) {
@@ -472,7 +471,7 @@
           fml::StatusCode::kAborted,
           "Could not create pipeline variant with immutable sampler.");
     }
-    pipeline_ = pipeline_variant.get();
+    pipeline_ = raw_ptr(pipeline_variant);
   }
 
   const auto& context_vk = ContextVK::Cast(*context_);
@@ -539,7 +538,7 @@
   instance_count_ = 1u;
   base_vertex_ = 0u;
   element_count_ = 0u;
-  pipeline_ = nullptr;
+  pipeline_ = PipelineRef(nullptr);
   pipeline_uses_input_attachments_ = false;
   immutable_sampler_ = nullptr;
   return fml::Status();
diff --git a/impeller/renderer/backend/vulkan/render_pass_vk.h b/impeller/renderer/backend/vulkan/render_pass_vk.h
index d442e08..95219e5 100644
--- a/impeller/renderer/backend/vulkan/render_pass_vk.h
+++ b/impeller/renderer/backend/vulkan/render_pass_vk.h
@@ -49,7 +49,7 @@
   size_t element_count_ = 0u;
   bool has_index_buffer_ = false;
   bool has_label_ = false;
-  const Pipeline<PipelineDescriptor>* pipeline_;
+  PipelineRef pipeline_ = PipelineRef(nullptr);
   bool pipeline_uses_input_attachments_ = false;
   std::shared_ptr<SamplerVK> immutable_sampler_;
 
@@ -58,8 +58,7 @@
                std::shared_ptr<CommandBufferVK> command_buffer);
 
   // |RenderPass|
-  void SetPipeline(
-      const std::shared_ptr<Pipeline<PipelineDescriptor>>& pipeline) override;
+  void SetPipeline(PipelineRef pipeline) override;
 
   // |RenderPass|
   void SetCommandLabel(std::string_view label) override;
diff --git a/impeller/renderer/command.h b/impeller/renderer/command.h
index 24b6471..f23d676 100644
--- a/impeller/renderer/command.h
+++ b/impeller/renderer/command.h
@@ -80,7 +80,7 @@
   //----------------------------------------------------------------------------
   /// The pipeline to use for this command.
   ///
-  std::shared_ptr<Pipeline<PipelineDescriptor>> pipeline;
+  PipelineRef pipeline;
 
   /// An offset into render pass storage where bound buffers/texture metadata is
   /// stored.
diff --git a/impeller/renderer/pipeline.h b/impeller/renderer/pipeline.h
index b3babc3..5c191c1 100644
--- a/impeller/renderer/pipeline.h
+++ b/impeller/renderer/pipeline.h
@@ -8,6 +8,7 @@
 #include <future>
 
 #include "compute_pipeline_descriptor.h"
+#include "impeller/core/raw_ptr.h"
 #include "impeller/renderer/compute_pipeline_builder.h"
 #include "impeller/renderer/compute_pipeline_descriptor.h"
 #include "impeller/renderer/context.h"
@@ -78,6 +79,12 @@
   Pipeline& operator=(const Pipeline&) = delete;
 };
 
+/// @brief A raw ptr to a pipeline object.
+///
+/// These pipeline refs are safe to use as the context will keep the
+/// pipelines alive throughout rendering.
+using PipelineRef = raw_ptr<Pipeline<PipelineDescriptor>>;
+
 extern template class Pipeline<PipelineDescriptor>;
 extern template class Pipeline<ComputePipelineDescriptor>;
 
diff --git a/impeller/renderer/render_pass.cc b/impeller/renderer/render_pass.cc
index a7f00ff..ecafb90 100644
--- a/impeller/renderer/render_pass.cc
+++ b/impeller/renderer/render_pass.cc
@@ -81,9 +81,13 @@
   return context_;
 }
 
+void RenderPass::SetPipeline(PipelineRef pipeline) {
+  pending_.pipeline = pipeline;
+}
+
 void RenderPass::SetPipeline(
     const std::shared_ptr<Pipeline<PipelineDescriptor>>& pipeline) {
-  pending_.pipeline = pipeline;
+  SetPipeline(PipelineRef(pipeline));
 }
 
 void RenderPass::SetCommandLabel(std::string_view label) {
diff --git a/impeller/renderer/render_pass.h b/impeller/renderer/render_pass.h
index 20d8511..2c2c810 100644
--- a/impeller/renderer/render_pass.h
+++ b/impeller/renderer/render_pass.h
@@ -45,7 +45,11 @@
 
   //----------------------------------------------------------------------------
   /// The pipeline to use for this command.
-  virtual void SetPipeline(
+  virtual void SetPipeline(PipelineRef pipeline);
+
+  //----------------------------------------------------------------------------
+  /// The pipeline to use for this command.
+  void SetPipeline(
       const std::shared_ptr<Pipeline<PipelineDescriptor>>& pipeline);
 
   //----------------------------------------------------------------------------
diff --git a/lib/gpu/render_pass.cc b/lib/gpu/render_pass.cc
index b2f43bc..3416ef1 100644
--- a/lib/gpu/render_pass.cc
+++ b/lib/gpu/render_pass.cc
@@ -177,7 +177,7 @@
 }
 
 bool RenderPass::Draw() {
-  render_pass_->SetPipeline(GetOrCreatePipeline());
+  render_pass_->SetPipeline(impeller::PipelineRef(GetOrCreatePipeline()));
 
   for (const auto& [_, buffer] : vertex_uniform_bindings) {
     render_pass_->BindDynamicResource(