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.
89 
90  std::optional<EmbedderData> embedder_data;
91 
92  Settings() = default;
93 
94  Settings(Settings&&) = default;
95  };
96 
97  /// Choose the number of worker threads the context_vk will create.
98  ///
99  /// Visible for testing.
100  static size_t ChooseThreadCountForWorkers(size_t hardware_concurrency);
101 
102  static std::shared_ptr<ContextVK> Create(Settings settings);
103 
104  uint64_t GetHash() const { return hash_; }
105 
106  // |Context|
107  ~ContextVK() override;
108 
109  // |Context|
110  BackendType GetBackendType() const override;
111 
112  // |Context|
113  std::string DescribeGpuModel() const override;
114 
115  // |Context|
116  bool IsValid() const override;
117 
118  // |Context|
119  std::shared_ptr<Allocator> GetResourceAllocator() const override;
120 
121  // |Context|
122  std::shared_ptr<ShaderLibrary> GetShaderLibrary() const override;
123 
124  // |Context|
125  std::shared_ptr<SamplerLibrary> GetSamplerLibrary() const override;
126 
127  // |Context|
128  std::shared_ptr<PipelineLibrary> GetPipelineLibrary() const override;
129 
130  // |Context|
131  std::shared_ptr<CommandBuffer> CreateCommandBuffer() const override;
132 
133  // |Context|
134  const std::shared_ptr<const Capabilities>& GetCapabilities() const override;
135 
136  // |Context|
137  virtual bool SubmitOnscreen(
138  std::shared_ptr<CommandBuffer> cmd_buffer) override;
139 
140  const std::shared_ptr<YUVConversionLibraryVK>& GetYUVConversionLibrary()
141  const;
142 
143  // |Context|
144  void Shutdown() override;
145 
146  const WorkaroundsVK& GetWorkarounds() const;
147 
148  void SetOffscreenFormat(PixelFormat pixel_format);
149 
150  template <typename T>
151  bool SetDebugName(T handle, std::string_view label) const {
152  return SetDebugName(GetDevice(), handle, label);
153  }
154 
155  template <typename T>
156  bool SetDebugName(T handle,
157  std::string_view label,
158  std::string_view trailing) const {
159  if (!HasValidationLayers()) {
160  // No-op if validation layers are not enabled.
161  return true;
162  }
163  std::string combined = SPrintF("%s %s", label.data(), trailing.data());
164  return SetDebugName(GetDevice(), handle, combined);
165  }
166 
167  template <typename T>
168  static bool SetDebugName(const vk::Device& device,
169  T handle,
170  std::string_view label) {
171  if (!HasValidationLayers()) {
172  // No-op if validation layers are not enabled.
173  return true;
174  }
175 
176  auto c_handle = static_cast<typename T::CType>(handle);
177 
178  vk::DebugUtilsObjectNameInfoEXT info;
179  info.objectType = T::objectType;
180  info.pObjectName = label.data();
181  info.objectHandle = reinterpret_cast<decltype(info.objectHandle)>(c_handle);
182 
183  if (device.setDebugUtilsObjectNameEXT(info) != vk::Result::eSuccess) {
184  VALIDATION_LOG << "Unable to set debug name: " << label;
185  return false;
186  }
187 
188  return true;
189  }
190 
191  std::shared_ptr<DeviceHolderVK> GetDeviceHolder() const {
192  return device_holder_;
193  }
194 
195  vk::Instance GetInstance() const;
196 
197  const vk::Device& GetDevice() const;
198 
199  const std::unique_ptr<DriverInfoVK>& GetDriverInfo() const;
200 
201  const std::shared_ptr<fml::ConcurrentTaskRunner>
203 
204  std::shared_ptr<SurfaceContextVK> CreateSurfaceContext();
205 
206  const std::shared_ptr<QueueVK>& GetGraphicsQueue() const;
207 
208  vk::PhysicalDevice GetPhysicalDevice() const;
209 
210  std::shared_ptr<FenceWaiterVK> GetFenceWaiter() const;
211 
212  std::shared_ptr<ResourceManagerVK> GetResourceManager() const;
213 
214  std::shared_ptr<CommandPoolRecyclerVK> GetCommandPoolRecycler() const;
215 
216  std::shared_ptr<DescriptorPoolRecyclerVK> GetDescriptorPoolRecycler() const;
217 
218  std::shared_ptr<CommandQueue> GetCommandQueue() const override;
219 
220  std::shared_ptr<GPUTracerVK> GetGPUTracer() const;
221 
222  void RecordFrameEndTime() const;
223 
224  // |Context|
225  void InitializeCommonlyUsedShadersIfNeeded() const override;
226 
227  // |Context|
228  void DisposeThreadLocalCachedResources() override;
229 
230  /// @brief Whether the Android Surface control based swapchain should be
231  /// enabled
233 
234  // | Context |
236  std::shared_ptr<CommandBuffer> command_buffer) override;
237 
238  // | Context |
239  bool FlushCommandBuffers() override;
240 
242 
243  std::shared_ptr<const IdleWaiter> GetIdleWaiter() const override {
244  return idle_waiter_vk_;
245  }
246 
247  private:
248  struct DeviceHolderImpl : public DeviceHolderVK {
249  // |DeviceHolder|
250  const vk::Device& GetDevice() const override { return device.get(); }
251  // |DeviceHolder|
252  const vk::PhysicalDevice& GetPhysicalDevice() const override {
253  return physical_device;
254  }
255 
256  ~DeviceHolderImpl() {
257  if (!owned) {
258  instance.release();
259  device.release();
260  }
261  }
262 
263  vk::UniqueInstance instance;
264  vk::PhysicalDevice physical_device;
265  vk::UniqueDevice device;
266  bool owned = true;
267  };
268 
269  std::shared_ptr<DeviceHolderImpl> device_holder_;
270  std::unique_ptr<DriverInfoVK> driver_info_;
271  std::unique_ptr<DebugReportVK> debug_report_;
272  std::shared_ptr<Allocator> allocator_;
273  std::shared_ptr<ShaderLibraryVK> shader_library_;
274  std::shared_ptr<SamplerLibraryVK> sampler_library_;
275  std::shared_ptr<PipelineLibraryVK> pipeline_library_;
276  std::shared_ptr<YUVConversionLibraryVK> yuv_conversion_library_;
277  QueuesVK queues_;
278  std::shared_ptr<const Capabilities> device_capabilities_;
279  std::shared_ptr<FenceWaiterVK> fence_waiter_;
280  std::shared_ptr<ResourceManagerVK> resource_manager_;
281  std::shared_ptr<DescriptorPoolRecyclerVK> descriptor_pool_recycler_;
282  std::shared_ptr<CommandPoolRecyclerVK> command_pool_recycler_;
283  std::string device_name_;
284  std::shared_ptr<fml::ConcurrentMessageLoop> raster_message_loop_;
285  std::shared_ptr<GPUTracerVK> gpu_tracer_;
286  std::shared_ptr<CommandQueue> command_queue_vk_;
287  std::shared_ptr<const IdleWaiter> idle_waiter_vk_;
288  WorkaroundsVK workarounds_;
289 
290  using DescriptorPoolMap =
291  std::unordered_map<std::thread::id, std::shared_ptr<DescriptorPoolVK>>;
292 
293  mutable Mutex desc_pool_mutex_;
294  mutable DescriptorPoolMap IPLR_GUARDED_BY(desc_pool_mutex_)
295  cached_descriptor_pool_;
296  bool should_enable_surface_control_ = false;
297  bool should_batch_cmd_buffers_ = false;
298  std::vector<std::shared_ptr<CommandBuffer>> pending_command_buffers_;
299 
300  const uint64_t hash_;
301 
302  bool is_valid_ = false;
303 
304  explicit ContextVK(const Flags& flags);
305 
306  void Setup(Settings settings);
307 
308  ContextVK(const ContextVK&) = delete;
309 
310  ContextVK& operator=(const ContextVK&) = delete;
311 };
312 
313 } // namespace impeller
314 
315 #endif // FLUTTER_IMPELLER_RENDERER_BACKEND_VULKAN_CONTEXT_VK_H_
To do anything rendering related with Impeller, you need a context.
Definition: context.h:65
void SetOffscreenFormat(PixelFormat pixel_format)
Definition: context_vk.cc:507
std::shared_ptr< Allocator > GetResourceAllocator() const override
Returns the allocator used to create textures and buffers on the device.
Definition: context_vk.cc:520
std::shared_ptr< ResourceManagerVK > GetResourceManager() const
Definition: context_vk.cc:630
vk::PhysicalDevice GetPhysicalDevice() const
Definition: context_vk.cc:622
const std::shared_ptr< YUVConversionLibraryVK > & GetYUVConversionLibrary() const
Definition: context_vk.cc:727
bool SetDebugName(T handle, std::string_view label) const
Definition: context_vk.h:151
std::shared_ptr< const IdleWaiter > GetIdleWaiter() const override
Definition: context_vk.h:243
bool EnqueueCommandBuffer(std::shared_ptr< CommandBuffer > command_buffer) override
Enqueue command_buffer for submission by the end of the frame.
Definition: context_vk.cc:652
void RecordFrameEndTime() const
const vk::Device & GetDevice() const
Definition: context_vk.cc:589
bool FlushCommandBuffers() override
Flush all pending command buffers.
Definition: context_vk.cc:662
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:516
const std::unique_ptr< DriverInfoVK > & GetDriverInfo() const
Definition: context_vk.cc:731
void DisposeThreadLocalCachedResources() override
Definition: context_vk.cc:718
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:536
virtual bool SubmitOnscreen(std::shared_ptr< CommandBuffer > cmd_buffer) override
Submit the command buffer that renders to the onscreen surface.
Definition: context_vk.cc:745
std::shared_ptr< SamplerLibrary > GetSamplerLibrary() const override
Returns the library of combined image samplers used in shaders.
Definition: context_vk.cc:528
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:532
const std::shared_ptr< QueueVK > & GetGraphicsQueue() const
Definition: context_vk.cc:618
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:614
RuntimeStageBackend GetRuntimeStageBackend() const override
Retrieve the runtime stage for this context type.
Definition: context_vk.cc:741
std::shared_ptr< CommandPoolRecyclerVK > GetCommandPoolRecycler() const
Definition: context_vk.cc:634
std::shared_ptr< CommandQueue > GetCommandQueue() const override
Return the graphics queue for submitting command buffers.
Definition: context_vk.cc:648
void InitializeCommonlyUsedShadersIfNeeded() const override
Definition: context_vk.cc:679
std::shared_ptr< FenceWaiterVK > GetFenceWaiter() const
Definition: context_vk.cc:626
bool GetShouldEnableSurfaceControlSwapchain() const
Whether the Android Surface control based swapchain should be enabled.
Definition: context_vk.cc:735
std::shared_ptr< GPUTracerVK > GetGPUTracer() const
Definition: context_vk.cc:639
BackendType GetBackendType() const override
Get the graphics backend of an Impeller context.
Definition: context_vk.cc:140
~ContextVK() override
Definition: context_vk.cc:131
std::string DescribeGpuModel() const override
Definition: context_vk.cc:512
static bool SetDebugName(const vk::Device &device, T handle, std::string_view label)
Definition: context_vk.h:168
const WorkaroundsVK & GetWorkarounds() const
Definition: context_vk.cc:749
const std::shared_ptr< fml::ConcurrentTaskRunner > GetConcurrentWorkerTaskRunner() const
Definition: context_vk.cc:594
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:524
vk::Instance GetInstance() const
Definition: context_vk.cc:585
std::shared_ptr< DeviceHolderVK > GetDeviceHolder() const
Definition: context_vk.h:191
bool SetDebugName(T handle, std::string_view label, std::string_view trailing) const
Definition: context_vk.h:156
uint64_t GetHash() const
Definition: context_vk.h:104
void Shutdown() override
Force all pending asynchronous work to finish. This is achieved by deleting all owned concurrent mess...
Definition: context_vk.cc:598
std::shared_ptr< DescriptorPoolRecyclerVK > GetDescriptorPoolRecycler() const
Definition: context_vk.cc:643
std::shared_ptr< SurfaceContextVK > CreateSurfaceContext()
Definition: context_vk.cc:610
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:90
fml::UniqueFD cache_directory
Definition: context_vk.h:82
A non-exhaustive set of driver specific workarounds.
#define VALIDATION_LOG
Definition: validation.h:91