Flutter Engine
vulkan::VulkanDevice Class Reference

#include <vulkan_device.h>

Public Member Functions

 VulkanDevice (VulkanProcTable &vk, VulkanHandle< VkPhysicalDevice > physical_device, bool enable_validation_layers)
 
 ~VulkanDevice ()
 
bool IsValid () const
 
const VulkanHandle< VkDevice > & GetHandle () const
 
const VulkanHandle< VkPhysicalDevice > & GetPhysicalDeviceHandle () const
 
const VulkanHandle< VkQueue > & GetQueueHandle () const
 
const VulkanHandle< VkCommandPool > & GetCommandPool () const
 
uint32_t GetGraphicsQueueIndex () const
 
void ReleaseDeviceOwnership ()
 
bool GetSurfaceCapabilities (const VulkanSurface &surface, VkSurfaceCapabilitiesKHR *capabilities) const
 
bool GetPhysicalDeviceFeatures (VkPhysicalDeviceFeatures *features) const
 
bool GetPhysicalDeviceFeaturesSkia (uint32_t *features) const
 
int ChooseSurfaceFormat (const VulkanSurface &surface, std::vector< VkFormat > desired_formats, VkSurfaceFormatKHR *format) const
 
bool ChoosePresentMode (const VulkanSurface &surface, VkPresentModeKHR *present_mode) const
 
bool QueueSubmit (std::vector< VkPipelineStageFlags > wait_dest_pipeline_stages, const std::vector< VkSemaphore > &wait_semaphores, const std::vector< VkSemaphore > &signal_semaphores, const std::vector< VkCommandBuffer > &command_buffers, const VulkanHandle< VkFence > &fence) const
 
bool WaitIdle () const
 

Detailed Description

Definition at line 19 of file vulkan_device.h.

Constructor & Destructor Documentation

◆ VulkanDevice()

vulkan::VulkanDevice::VulkanDevice ( VulkanProcTable vk,
VulkanHandle< VkPhysicalDevice >  physical_device,
bool  enable_validation_layers 
)

Definition at line 32 of file vulkan_device.cc.

References vulkan::VulkanProcTable::AreInstanceProcsSetup(), vulkan::DeviceLayersToEnable(), vulkan::FindGraphicsQueueIndex(), FML_DLOG, vulkan::VulkanProcTable::SetupDeviceProcAddresses(), and VK_CALL_LOG_ERROR.

35  : vk(p_vk),
36  physical_device_(std::move(physical_device)),
37  graphics_queue_index_(std::numeric_limits<uint32_t>::max()),
38  valid_(false),
39  enable_validation_layers_(enable_validation_layers) {
40  if (!physical_device_ || !vk.AreInstanceProcsSetup()) {
41  return;
42  }
43 
44  graphics_queue_index_ = FindGraphicsQueueIndex(GetQueueFamilyProperties());
45 
46  if (graphics_queue_index_ == kVulkanInvalidGraphicsQueueIndex) {
47  FML_DLOG(INFO) << "Could not find the graphics queue index.";
48  return;
49  }
50 
51  const float priorities[1] = {1.0f};
52 
53  const VkDeviceQueueCreateInfo queue_create = {
54  .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
55  .pNext = nullptr,
56  .flags = 0,
57  .queueFamilyIndex = graphics_queue_index_,
58  .queueCount = 1,
59  .pQueuePriorities = priorities,
60  };
61 
62  const char* extensions[] = {
63 #if OS_ANDROID
64  VK_KHR_SWAPCHAIN_EXTENSION_NAME,
65 #endif
66 #if OS_FUCHSIA
67  VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME,
68  VK_FUCHSIA_EXTERNAL_MEMORY_EXTENSION_NAME,
69  VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME,
70  VK_FUCHSIA_EXTERNAL_SEMAPHORE_EXTENSION_NAME,
71  VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME,
72 #endif
73  };
74 
75  auto enabled_layers =
76  DeviceLayersToEnable(vk, physical_device_, enable_validation_layers_);
77 
78  const char* layers[enabled_layers.size()];
79 
80  for (size_t i = 0; i < enabled_layers.size(); i++) {
81  layers[i] = enabled_layers[i].c_str();
82  }
83 
84  const VkDeviceCreateInfo create_info = {
85  .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
86  .pNext = nullptr,
87  .flags = 0,
88  .queueCreateInfoCount = 1,
89  .pQueueCreateInfos = &queue_create,
90  .enabledLayerCount = static_cast<uint32_t>(enabled_layers.size()),
91  .ppEnabledLayerNames = layers,
92  .enabledExtensionCount = sizeof(extensions) / sizeof(const char*),
93  .ppEnabledExtensionNames = extensions,
94  .pEnabledFeatures = nullptr,
95  };
96 
97  VkDevice device = VK_NULL_HANDLE;
98 
99  if (VK_CALL_LOG_ERROR(vk.CreateDevice(physical_device_, &create_info, nullptr,
100  &device)) != VK_SUCCESS) {
101  FML_DLOG(INFO) << "Could not create device.";
102  return;
103  }
104 
105  device_ = {device,
106  [this](VkDevice device) { vk.DestroyDevice(device, nullptr); }};
107 
108  if (!vk.SetupDeviceProcAddresses(device_)) {
109  FML_DLOG(INFO) << "Could not setup device proc addresses.";
110  return;
111  }
112 
113  VkQueue queue = VK_NULL_HANDLE;
114 
115  vk.GetDeviceQueue(device_, graphics_queue_index_, 0, &queue);
116 
117  if (queue == VK_NULL_HANDLE) {
118  FML_DLOG(INFO) << "Could not get the device queue handle.";
119  return;
120  }
121 
122  queue_ = queue;
123 
124  const VkCommandPoolCreateInfo command_pool_create_info = {
125  .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
126  .pNext = nullptr,
127  .flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
128  .queueFamilyIndex = 0,
129  };
130 
131  VkCommandPool command_pool = VK_NULL_HANDLE;
132  if (VK_CALL_LOG_ERROR(vk.CreateCommandPool(device_, &command_pool_create_info,
133  nullptr, &command_pool)) !=
134  VK_SUCCESS) {
135  FML_DLOG(INFO) << "Could not create the command pool.";
136  return;
137  }
138 
139  command_pool_ = {command_pool, [this](VkCommandPool pool) {
140  vk.DestroyCommandPool(device_, pool, nullptr);
141  }};
142 
143  valid_ = true;
144 }
bool SetupDeviceProcAddresses(const VulkanHandle< VkDevice > &device)
bool AreInstanceProcsSetup() const
constexpr auto kVulkanInvalidGraphicsQueueIndex
#define VK_CALL_LOG_ERROR(expression)
std::vector< std::string > DeviceLayersToEnable(const VulkanProcTable &vk, const VulkanHandle< VkPhysicalDevice > &physical_device, bool enable_validation_layers)
static uint32_t FindGraphicsQueueIndex(const std::vector< VkQueueFamilyProperties > &properties)
#define FML_DLOG(severity)
Definition: logging.h:85

◆ ~VulkanDevice()

vulkan::VulkanDevice::~VulkanDevice ( )

Definition at line 146 of file vulkan_device.cc.

References FML_ALLOW_UNUSED_LOCAL, and WaitIdle().

146  {
148 }
#define FML_ALLOW_UNUSED_LOCAL(x)

Member Function Documentation

◆ ChoosePresentMode()

bool vulkan::VulkanDevice::ChoosePresentMode ( const VulkanSurface surface,
VkPresentModeKHR *  present_mode 
) const

Definition at line 315 of file vulkan_device.cc.

References vulkan::VulkanSurface::IsValid().

316  {
317  if (!surface.IsValid() || present_mode == nullptr) {
318  return false;
319  }
320 
321  // https://github.com/LunarG/VulkanSamples/issues/98 indicates that
322  // VK_PRESENT_MODE_FIFO_KHR is preferable on mobile platforms. The problems
323  // mentioned in the ticket w.r.t the application being faster that the refresh
324  // rate of the screen should not be faced by any Flutter platforms as they are
325  // powered by Vsync pulses instead of depending the submit to block.
326  // However, for platforms that don't have VSync providers setup, it is better
327  // to fall back to FIFO. For platforms that do have VSync providers, there
328  // should be little difference. In case there is a need for a mode other than
329  // FIFO, availability checks must be performed here before returning the
330  // result. FIFO is always present.
331  *present_mode = VK_PRESENT_MODE_FIFO_KHR;
332  return true;
333 }

◆ ChooseSurfaceFormat()

int vulkan::VulkanDevice::ChooseSurfaceFormat ( const VulkanSurface surface,
std::vector< VkFormat >  desired_formats,
VkSurfaceFormatKHR *  format 
) const

Definition at line 272 of file vulkan_device.cc.

References vulkan::VulkanSurface::Handle(), vulkan::VulkanSurface::IsValid(), and VK_CALL_LOG_ERROR.

274  {
275 #if OS_ANDROID
276  if (!surface.IsValid() || format == nullptr) {
277  return -1;
278  }
279 
280  uint32_t format_count = 0;
281  if (VK_CALL_LOG_ERROR(vk.GetPhysicalDeviceSurfaceFormatsKHR(
282  physical_device_, surface.Handle(), &format_count, nullptr)) !=
283  VK_SUCCESS) {
284  return -1;
285  }
286 
287  if (format_count == 0) {
288  return -1;
289  }
290 
291  VkSurfaceFormatKHR formats[format_count];
292  if (VK_CALL_LOG_ERROR(vk.GetPhysicalDeviceSurfaceFormatsKHR(
293  physical_device_, surface.Handle(), &format_count, formats)) !=
294  VK_SUCCESS) {
295  return -1;
296  }
297 
298  std::map<VkFormat, VkSurfaceFormatKHR> supported_formats;
299  for (uint32_t i = 0; i < format_count; i++) {
300  supported_formats[formats[i].format] = formats[i];
301  }
302 
303  // Try to find the first supported format in the list of desired formats.
304  for (size_t i = 0; i < desired_formats.size(); ++i) {
305  auto found = supported_formats.find(desired_formats[i]);
306  if (found != supported_formats.end()) {
307  *format = found->second;
308  return static_cast<int>(i);
309  }
310  }
311 #endif
312  return -1;
313 }
#define VK_CALL_LOG_ERROR(expression)

◆ GetCommandPool()

const VulkanHandle< VkCommandPool > & vulkan::VulkanDevice::GetCommandPool ( ) const

Definition at line 175 of file vulkan_device.cc.

175  {
176  return command_pool_;
177 }

◆ GetGraphicsQueueIndex()

uint32_t vulkan::VulkanDevice::GetGraphicsQueueIndex ( ) const

Definition at line 179 of file vulkan_device.cc.

179  {
180  return graphics_queue_index_;
181 }

◆ GetHandle()

const VulkanHandle< VkDevice > & vulkan::VulkanDevice::GetHandle ( ) const

Definition at line 158 of file vulkan_device.cc.

158  {
159  return device_;
160 }

◆ GetPhysicalDeviceFeatures()

bool vulkan::VulkanDevice::GetPhysicalDeviceFeatures ( VkPhysicalDeviceFeatures *  features) const

Definition at line 221 of file vulkan_device.cc.

Referenced by GetPhysicalDeviceFeaturesSkia().

222  {
223  if (features == nullptr || !physical_device_) {
224  return false;
225  }
226  vk.GetPhysicalDeviceFeatures(physical_device_, features);
227  return true;
228 }

◆ GetPhysicalDeviceFeaturesSkia()

bool vulkan::VulkanDevice::GetPhysicalDeviceFeaturesSkia ( uint32_t *  features) const

Definition at line 230 of file vulkan_device.cc.

References flutter::flags, and GetPhysicalDeviceFeatures().

230  {
231  if (sk_features == nullptr) {
232  return false;
233  }
234 
235  VkPhysicalDeviceFeatures features;
236 
237  if (!GetPhysicalDeviceFeatures(&features)) {
238  return false;
239  }
240 
241  uint32_t flags = 0;
242 
243  if (features.geometryShader) {
244  flags |= kGeometryShader_GrVkFeatureFlag;
245  }
246  if (features.dualSrcBlend) {
247  flags |= kDualSrcBlend_GrVkFeatureFlag;
248  }
249  if (features.sampleRateShading) {
250  flags |= kSampleRateShading_GrVkFeatureFlag;
251  }
252 
253  *sk_features = flags;
254  return true;
255 }
bool GetPhysicalDeviceFeatures(VkPhysicalDeviceFeatures *features) const
DEF_SWITCHES_START snapshot asset Path to the directory containing the four files specified by VmSnapshotInstructions and IsolateSnapshotInstructions vm snapshot The VM instructions snapshot that will be memory mapped as read and executable SnapshotAssetPath must be present isolate snapshot The isolate instructions snapshot that will be memory mapped as read and executable SnapshotAssetPath must be present icu symbol Prefix for the symbols representing ICU data linked into the Flutter library dart flags
Definition: switches.h:66

◆ GetPhysicalDeviceHandle()

const VulkanHandle< VkPhysicalDevice > & vulkan::VulkanDevice::GetPhysicalDeviceHandle ( ) const

Definition at line 166 of file vulkan_device.cc.

167  {
168  return physical_device_;
169 }

◆ GetQueueHandle()

const VulkanHandle< VkQueue > & vulkan::VulkanDevice::GetQueueHandle ( ) const

Definition at line 171 of file vulkan_device.cc.

171  {
172  return queue_;
173 }

◆ GetSurfaceCapabilities()

bool vulkan::VulkanDevice::GetSurfaceCapabilities ( const VulkanSurface surface,
VkSurfaceCapabilitiesKHR *  capabilities 
) const

Definition at line 183 of file vulkan_device.cc.

References vulkan::VulkanSurface::GetSize(), vulkan::VulkanSurface::Handle(), vulkan::VulkanSurface::IsValid(), fml::size(), and VK_CALL_LOG_ERROR.

185  {
186 #if OS_ANDROID
187  if (!surface.IsValid() || capabilities == nullptr) {
188  return false;
189  }
190 
191  bool success =
192  VK_CALL_LOG_ERROR(vk.GetPhysicalDeviceSurfaceCapabilitiesKHR(
193  physical_device_, surface.Handle(), capabilities)) == VK_SUCCESS;
194 
195  if (!success) {
196  return false;
197  }
198 
199  // Check if the physical device surface capabilities are valid. If so, there
200  // is nothing more to do.
201  if (capabilities->currentExtent.width != 0xFFFFFFFF &&
202  capabilities->currentExtent.height != 0xFFFFFFFF) {
203  return true;
204  }
205 
206  // Ask the native surface for its size as a fallback.
207  SkISize size = surface.GetSize();
208 
209  if (size.width() == 0 || size.height() == 0) {
210  return false;
211  }
212 
213  capabilities->currentExtent.width = size.width();
214  capabilities->currentExtent.height = size.height();
215  return true;
216 #else
217  return false;
218 #endif
219 }
constexpr std::size_t size(T(&array)[N])
Definition: size.h:13
#define VK_CALL_LOG_ERROR(expression)

◆ IsValid()

bool vulkan::VulkanDevice::IsValid ( ) const

Definition at line 150 of file vulkan_device.cc.

150  {
151  return valid_;
152 }

◆ QueueSubmit()

bool vulkan::VulkanDevice::QueueSubmit ( std::vector< VkPipelineStageFlags >  wait_dest_pipeline_stages,
const std::vector< VkSemaphore > &  wait_semaphores,
const std::vector< VkSemaphore > &  signal_semaphores,
const std::vector< VkCommandBuffer > &  command_buffers,
const VulkanHandle< VkFence > &  fence 
) const

Definition at line 335 of file vulkan_device.cc.

References VK_CALL_LOG_ERROR.

340  {
341  if (wait_semaphores.size() != wait_dest_pipeline_stages.size()) {
342  return false;
343  }
344 
345  const VkSubmitInfo submit_info = {
346  .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
347  .pNext = nullptr,
348  .waitSemaphoreCount = static_cast<uint32_t>(wait_semaphores.size()),
349  .pWaitSemaphores = wait_semaphores.data(),
350  .pWaitDstStageMask = wait_dest_pipeline_stages.data(),
351  .commandBufferCount = static_cast<uint32_t>(command_buffers.size()),
352  .pCommandBuffers = command_buffers.data(),
353  .signalSemaphoreCount = static_cast<uint32_t>(signal_semaphores.size()),
354  .pSignalSemaphores = signal_semaphores.data(),
355  };
356 
357  if (VK_CALL_LOG_ERROR(vk.QueueSubmit(queue_, 1, &submit_info, fence)) !=
358  VK_SUCCESS) {
359  return false;
360  }
361 
362  return true;
363 }
#define VK_CALL_LOG_ERROR(expression)

◆ ReleaseDeviceOwnership()

void vulkan::VulkanDevice::ReleaseDeviceOwnership ( )

Definition at line 162 of file vulkan_device.cc.

References vulkan::VulkanHandle< T >::ReleaseOwnership().

162  {
163  device_.ReleaseOwnership();
164 }

◆ WaitIdle()

bool vulkan::VulkanDevice::WaitIdle ( ) const

Definition at line 154 of file vulkan_device.cc.

References VK_CALL_LOG_ERROR.

Referenced by ~VulkanDevice().

154  {
155  return VK_CALL_LOG_ERROR(vk.DeviceWaitIdle(device_)) == VK_SUCCESS;
156 }
#define VK_CALL_LOG_ERROR(expression)

The documentation for this class was generated from the following files: