Flutter Impeller
context_vk.h
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef FLUTTER_IMPELLER_RENDERER_BACKEND_VULKAN_CONTEXT_VK_H_
6 #define FLUTTER_IMPELLER_RENDERER_BACKEND_VULKAN_CONTEXT_VK_H_
7 
8 #include <memory>
9 
10 #include "flutter/fml/concurrent_message_loop.h"
11 #include "flutter/fml/mapping.h"
12 #include "flutter/fml/unique_fd.h"
14 #include "impeller/base/strings.h"
15 #include "impeller/core/formats.h"
29 
30 namespace impeller {
31 
32 bool HasValidationLayers();
33 
34 class CommandEncoderFactoryVK;
35 class CommandEncoderVK;
36 class CommandPoolRecyclerVK;
37 class DebugReportVK;
38 class FenceWaiterVK;
39 class ResourceManagerVK;
40 class SurfaceContextVK;
41 class GPUTracerVK;
42 class DescriptorPoolRecyclerVK;
43 class CommandQueueVK;
44 class DescriptorPoolVK;
45 
46 class IdleWaiterVK : public IdleWaiter {
47  public:
48  explicit IdleWaiterVK(std::weak_ptr<DeviceHolderVK> device_holder)
49  : device_holder_(std::move(device_holder)) {}
50 
51  void WaitIdle() const override {
52  std::shared_ptr<DeviceHolderVK> strong_device_holder_ =
53  device_holder_.lock();
54  if (strong_device_holder_ && strong_device_holder_->GetDevice()) {
55  [[maybe_unused]] auto result =
56  strong_device_holder_->GetDevice().waitIdle();
57  }
58  }
59 
60  private:
61  std::weak_ptr<DeviceHolderVK> device_holder_;
62 };
63 
64 class ContextVK final : public Context,
65  public BackendCast<ContextVK, Context>,
66  public std::enable_shared_from_this<ContextVK> {
67  public:
68  /// Embedder Stuff
69  struct EmbedderData {
70  VkInstance instance;
71  VkPhysicalDevice physical_device;
72  VkDevice device;
74  VkQueue queue;
75  std::vector<std::string> instance_extensions;
76  std::vector<std::string> device_extensions;
77  };
78 
79  struct Settings {
80  PFN_vkGetInstanceProcAddr proc_address_callback = nullptr;
81  std::vector<std::shared_ptr<fml::Mapping>> shader_libraries_data;
82  fml::UniqueFD cache_directory;
83  bool enable_validation = false;
84  bool enable_gpu_tracing = false;
85  bool enable_surface_control = false;
86  /// If validations are requested but cannot be enabled, log a fatal error.
88 
89  std::optional<EmbedderData> embedder_data;
90 
91  Settings() = default;
92 
93  Settings(Settings&&) = default;
94  };
95 
96  /// Choose the number of worker threads the context_vk will create.
97  ///
98  /// Visible for testing.
99  static size_t ChooseThreadCountForWorkers(size_t hardware_concurrency);
100 
101  static std::shared_ptr<ContextVK> Create(Settings settings);
102 
103  uint64_t GetHash() const { return hash_; }
104 
105  // |Context|
106  ~ContextVK() override;
107 
108  // |Context|
109  BackendType GetBackendType() const override;
110 
111  // |Context|
112  std::string DescribeGpuModel() const override;
113 
114  // |Context|
115  bool IsValid() const override;
116 
117  // |Context|
118  std::shared_ptr<Allocator> GetResourceAllocator() const override;
119 
120  // |Context|
121  std::shared_ptr<ShaderLibrary> GetShaderLibrary() const override;
122 
123  // |Context|
124  std::shared_ptr<SamplerLibrary> GetSamplerLibrary() const override;
125 
126  // |Context|
127  std::shared_ptr<PipelineLibrary> GetPipelineLibrary() const override;
128 
129  // |Context|
130  std::shared_ptr<CommandBuffer> CreateCommandBuffer() const override;
131 
132  // |Context|
133  const std::shared_ptr<const Capabilities>& GetCapabilities() const override;
134 
135  // |Context|
136  virtual bool SubmitOnscreen(
137  std::shared_ptr<CommandBuffer> cmd_buffer) override;
138 
139  const std::shared_ptr<YUVConversionLibraryVK>& GetYUVConversionLibrary()
140  const;
141 
142  // |Context|
143  void Shutdown() override;
144 
145  const WorkaroundsVK& GetWorkarounds() const;
146 
147  void SetOffscreenFormat(PixelFormat pixel_format);
148 
149  template <typename T>
150  bool SetDebugName(T handle, std::string_view label) const {
151  return SetDebugName(GetDevice(), handle, label);
152  }
153 
154  template <typename T>
155  bool SetDebugName(T handle,
156  std::string_view label,
157  std::string_view trailing) const {
158  if (!HasValidationLayers()) {
159  // No-op if validation layers are not enabled.
160  return true;
161  }
162  std::string combined = SPrintF("%s %s", label.data(), trailing.data());
163  return SetDebugName(GetDevice(), handle, combined);
164  }
165 
166  template <typename T>
167  static bool SetDebugName(const vk::Device& device,
168  T handle,
169  std::string_view label) {
170  if (!HasValidationLayers()) {
171  // No-op if validation layers are not enabled.
172  return true;
173  }
174 
175  auto c_handle = static_cast<typename T::CType>(handle);
176 
177  vk::DebugUtilsObjectNameInfoEXT info;
178  info.objectType = T::objectType;
179  info.pObjectName = label.data();
180  info.objectHandle = reinterpret_cast<decltype(info.objectHandle)>(c_handle);
181 
182  if (device.setDebugUtilsObjectNameEXT(info) != vk::Result::eSuccess) {
183  VALIDATION_LOG << "Unable to set debug name: " << label;
184  return false;
185  }
186 
187  return true;
188  }
189 
190  std::shared_ptr<DeviceHolderVK> GetDeviceHolder() const {
191  return device_holder_;
192  }
193 
194  vk::Instance GetInstance() const;
195 
196  const vk::Device& GetDevice() const;
197 
198  const std::unique_ptr<DriverInfoVK>& GetDriverInfo() const;
199 
200  const std::shared_ptr<fml::ConcurrentTaskRunner>
202 
203  std::shared_ptr<SurfaceContextVK> CreateSurfaceContext();
204 
205  const std::shared_ptr<QueueVK>& GetGraphicsQueue() const;
206 
207  vk::PhysicalDevice GetPhysicalDevice() const;
208 
209  std::shared_ptr<FenceWaiterVK> GetFenceWaiter() const;
210 
211  std::shared_ptr<ResourceManagerVK> GetResourceManager() const;
212 
213  std::shared_ptr<CommandPoolRecyclerVK> GetCommandPoolRecycler() const;
214 
215  std::shared_ptr<DescriptorPoolRecyclerVK> GetDescriptorPoolRecycler() const;
216 
217  std::shared_ptr<CommandQueue> GetCommandQueue() const override;
218 
219  std::shared_ptr<GPUTracerVK> GetGPUTracer() const;
220 
221  void RecordFrameEndTime() const;
222 
223  // |Context|
224  void InitializeCommonlyUsedShadersIfNeeded() const override;
225 
226  // |Context|
227  void DisposeThreadLocalCachedResources() override;
228 
229  /// @brief Whether the Android Surface control based swapchain should be
230  /// enabled
232 
233  // | Context |
235  std::shared_ptr<CommandBuffer> command_buffer) override;
236 
237  // | Context |
238  bool FlushCommandBuffers() override;
239 
241 
242  std::shared_ptr<const IdleWaiter> GetIdleWaiter() const override {
243  return idle_waiter_vk_;
244  }
245 
246  private:
247  struct DeviceHolderImpl : public DeviceHolderVK {
248  // |DeviceHolder|
249  const vk::Device& GetDevice() const override { return device.get(); }
250  // |DeviceHolder|
251  const vk::PhysicalDevice& GetPhysicalDevice() const override {
252  return physical_device;
253  }
254 
255  ~DeviceHolderImpl() {
256  if (!owned) {
257  instance.release();
258  device.release();
259  }
260  }
261 
262  vk::UniqueInstance instance;
263  vk::PhysicalDevice physical_device;
264  vk::UniqueDevice device;
265  bool owned = true;
266  };
267 
268  std::shared_ptr<DeviceHolderImpl> device_holder_;
269  std::unique_ptr<DriverInfoVK> driver_info_;
270  std::unique_ptr<DebugReportVK> debug_report_;
271  std::shared_ptr<Allocator> allocator_;
272  std::shared_ptr<ShaderLibraryVK> shader_library_;
273  std::shared_ptr<SamplerLibraryVK> sampler_library_;
274  std::shared_ptr<PipelineLibraryVK> pipeline_library_;
275  std::shared_ptr<YUVConversionLibraryVK> yuv_conversion_library_;
276  QueuesVK queues_;
277  std::shared_ptr<const Capabilities> device_capabilities_;
278  std::shared_ptr<FenceWaiterVK> fence_waiter_;
279  std::shared_ptr<ResourceManagerVK> resource_manager_;
280  std::shared_ptr<DescriptorPoolRecyclerVK> descriptor_pool_recycler_;
281  std::shared_ptr<CommandPoolRecyclerVK> command_pool_recycler_;
282  std::string device_name_;
283  std::shared_ptr<fml::ConcurrentMessageLoop> raster_message_loop_;
284  std::shared_ptr<GPUTracerVK> gpu_tracer_;
285  std::shared_ptr<CommandQueue> command_queue_vk_;
286  std::shared_ptr<const IdleWaiter> idle_waiter_vk_;
287  WorkaroundsVK workarounds_;
288 
289  using DescriptorPoolMap =
290  std::unordered_map<std::thread::id, std::shared_ptr<DescriptorPoolVK>>;
291 
292  mutable Mutex desc_pool_mutex_;
293  mutable DescriptorPoolMap IPLR_GUARDED_BY(desc_pool_mutex_)
294  cached_descriptor_pool_;
295  bool should_enable_surface_control_ = false;
296  bool should_batch_cmd_buffers_ = false;
297  std::vector<std::shared_ptr<CommandBuffer>> pending_command_buffers_;
298 
299  const uint64_t hash_;
300 
301  bool is_valid_ = false;
302 
303  ContextVK();
304 
305  void Setup(Settings settings);
306 
307  ContextVK(const ContextVK&) = delete;
308 
309  ContextVK& operator=(const ContextVK&) = delete;
310 };
311 
312 } // namespace impeller
313 
314 #endif // FLUTTER_IMPELLER_RENDERER_BACKEND_VULKAN_CONTEXT_VK_H_
To do anything rendering related with Impeller, you need a context.
Definition: context.h:46
void SetOffscreenFormat(PixelFormat pixel_format)
Definition: context_vk.cc:504
std::shared_ptr< Allocator > GetResourceAllocator() const override
Returns the allocator used to create textures and buffers on the device.
Definition: context_vk.cc:517
std::shared_ptr< ResourceManagerVK > GetResourceManager() const
Definition: context_vk.cc:628
vk::PhysicalDevice GetPhysicalDevice() const
Definition: context_vk.cc:620
const std::shared_ptr< YUVConversionLibraryVK > & GetYUVConversionLibrary() const
Definition: context_vk.cc:725
bool SetDebugName(T handle, std::string_view label) const
Definition: context_vk.h:150
std::shared_ptr< const IdleWaiter > GetIdleWaiter() const override
Definition: context_vk.h:242
bool EnqueueCommandBuffer(std::shared_ptr< CommandBuffer > command_buffer) override
Enqueue command_buffer for submission by the end of the frame.
Definition: context_vk.cc:650
void RecordFrameEndTime() const
const vk::Device & GetDevice() const
Definition: context_vk.cc:587
bool FlushCommandBuffers() override
Flush all pending command buffers.
Definition: context_vk.cc:660
bool IsValid() const override
Determines if a context is valid. If the caller ever receives an invalid context, they must discard i...
Definition: context_vk.cc:513
const std::unique_ptr< DriverInfoVK > & GetDriverInfo() const
Definition: context_vk.cc:729
void DisposeThreadLocalCachedResources() override
Definition: context_vk.cc:716
std::shared_ptr< CommandBuffer > CreateCommandBuffer() const override
Create a new command buffer. Command buffers can be used to encode graphics, blit,...
Definition: context_vk.cc:533
virtual bool SubmitOnscreen(std::shared_ptr< CommandBuffer > cmd_buffer) override
Submit the command buffer that renders to the onscreen surface.
Definition: context_vk.cc:741
std::shared_ptr< SamplerLibrary > GetSamplerLibrary() const override
Returns the library of combined image samplers used in shaders.
Definition: context_vk.cc:525
static std::shared_ptr< ContextVK > Create(Settings settings)
Definition: context_vk.cc:105
std::shared_ptr< PipelineLibrary > GetPipelineLibrary() const override
Returns the library of pipelines used by render or compute commands.
Definition: context_vk.cc:529
const std::shared_ptr< QueueVK > & GetGraphicsQueue() const
Definition: context_vk.cc:616
const std::shared_ptr< const Capabilities > & GetCapabilities() const override
Get the capabilities of Impeller context. All optionally supported feature of the platform,...
Definition: context_vk.cc:612
RuntimeStageBackend GetRuntimeStageBackend() const override
Retrieve the runtime stage for this context type.
Definition: context_vk.cc:737
std::shared_ptr< CommandPoolRecyclerVK > GetCommandPoolRecycler() const
Definition: context_vk.cc:632
std::shared_ptr< CommandQueue > GetCommandQueue() const override
Return the graphics queue for submitting command buffers.
Definition: context_vk.cc:646
void InitializeCommonlyUsedShadersIfNeeded() const override
Definition: context_vk.cc:677
std::shared_ptr< FenceWaiterVK > GetFenceWaiter() const
Definition: context_vk.cc:624
bool GetShouldEnableSurfaceControlSwapchain() const
Whether the Android Surface control based swapchain should be enabled.
Definition: context_vk.cc:733
std::shared_ptr< GPUTracerVK > GetGPUTracer() const
Definition: context_vk.cc:637
BackendType GetBackendType() const override
Get the graphics backend of an Impeller context.
Definition: context_vk.cc:139
~ContextVK() override
Definition: context_vk.cc:132
std::string DescribeGpuModel() const override
Definition: context_vk.cc:509
static bool SetDebugName(const vk::Device &device, T handle, std::string_view label)
Definition: context_vk.h:167
const WorkaroundsVK & GetWorkarounds() const
Definition: context_vk.cc:745
const std::shared_ptr< fml::ConcurrentTaskRunner > GetConcurrentWorkerTaskRunner() const
Definition: context_vk.cc:592
static size_t ChooseThreadCountForWorkers(size_t hardware_concurrency)
Definition: context_vk.cc:115
std::shared_ptr< ShaderLibrary > GetShaderLibrary() const override
Returns the library of shaders used to specify the programmable stages of a pipeline.
Definition: context_vk.cc:521
vk::Instance GetInstance() const
Definition: context_vk.cc:583
std::shared_ptr< DeviceHolderVK > GetDeviceHolder() const
Definition: context_vk.h:190
bool SetDebugName(T handle, std::string_view label, std::string_view trailing) const
Definition: context_vk.h:155
uint64_t GetHash() const
Definition: context_vk.h:103
void Shutdown() override
Force all pending asynchronous work to finish. This is achieved by deleting all owned concurrent mess...
Definition: context_vk.cc:596
std::shared_ptr< DescriptorPoolRecyclerVK > GetDescriptorPoolRecycler() const
Definition: context_vk.cc:641
std::shared_ptr< SurfaceContextVK > CreateSurfaceContext()
Definition: context_vk.cc:608
Holds a strong reference to the underlying logical Vulkan device. This comes in handy when the contex...
IdleWaiterVK(std::weak_ptr< DeviceHolderVK > device_holder)
Definition: context_vk.h:48
void WaitIdle() const override
Definition: context_vk.h:51
bool HasValidationLayers()
Definition: context_vk.cc:53
std::string SPrintF(const char *format,...)
Definition: strings.cc:12
PixelFormat
The Pixel formats supported by Impeller. The naming convention denotes the usage of the component,...
Definition: formats.h:99
Definition: comparable.h:95
std::vector< std::string > device_extensions
Definition: context_vk.h:76
VkPhysicalDevice physical_device
Definition: context_vk.h:71
std::vector< std::string > instance_extensions
Definition: context_vk.h:75
Settings(Settings &&)=default
std::vector< std::shared_ptr< fml::Mapping > > shader_libraries_data
Definition: context_vk.h:81
PFN_vkGetInstanceProcAddr proc_address_callback
Definition: context_vk.h:80
bool fatal_missing_validations
If validations are requested but cannot be enabled, log a fatal error.
Definition: context_vk.h:87
std::optional< EmbedderData > embedder_data
Definition: context_vk.h:89
fml::UniqueFD cache_directory
Definition: context_vk.h:82
A non-exhaustive set of driver specific workarounds.
#define VALIDATION_LOG
Definition: validation.h:91