Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Public Member Functions | List of all members
vulkan::VulkanDevice Class Reference

#include <vulkan_device.h>

Public Member Functions

 VulkanDevice (VulkanProcTable &vk, VulkanHandle< VkPhysicalDevice > physical_device, bool enable_validation_layers)
 Create a new VkDevice with a resolved VkQueue suitable for rendering with Skia.
 
 VulkanDevice (VulkanProcTable &vk, VulkanHandle< VkPhysicalDevice > physical_device, VulkanHandle< VkDevice > device, uint32_t queue_family_index, VulkanHandle< VkQueue > queue)
 Wrap an existing VkDevice and VkQueue.
 
 ~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, const 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() [1/2]

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

Create a new VkDevice with a resolved VkQueue suitable for rendering with Skia.

Definition at line 32 of file vulkan_device.cc.

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 if (!physical_device_ || !vk_.AreInstanceProcsSetup()) {
40 return;
41 }
42
43 graphics_queue_index_ = FindGraphicsQueueIndex(GetQueueFamilyProperties());
44
45 if (graphics_queue_index_ == kVulkanInvalidGraphicsQueueIndex) {
46 FML_DLOG(INFO) << "Could not find the graphics queue index.";
47 return;
48 }
49
50 const float priorities[1] = {1.0f};
51
52 const VkDeviceQueueCreateInfo queue_create = {
54 .pNext = nullptr,
55 .flags = 0,
56 .queueFamilyIndex = graphics_queue_index_,
57 .queueCount = 1,
58 .pQueuePriorities = priorities,
59 };
60
61 const char* extensions[] = {
62#if FML_OS_ANDROID
64#endif
65#if OS_FUCHSIA
69 VK_FUCHSIA_EXTERNAL_MEMORY_EXTENSION_NAME,
70 VK_FUCHSIA_EXTERNAL_SEMAPHORE_EXTENSION_NAME,
71 VK_FUCHSIA_BUFFER_COLLECTION_EXTENSION_NAME,
72#endif
73 };
74
75 auto enabled_layers =
76 DeviceLayersToEnable(vk_, physical_device_, enable_validation_layers);
77
78 std::vector<const char*> layers;
79
80 for (size_t i = 0; i < enabled_layers.size(); i++) {
81 layers.push_back(enabled_layers[i].c_str());
82 }
83
84 const VkDeviceCreateInfo create_info = {
86 .pNext = nullptr,
87 .flags = 0,
88 .queueCreateInfoCount = 1,
89 .pQueueCreateInfos = &queue_create,
90 .enabledLayerCount = static_cast<uint32_t>(layers.size()),
91 .ppEnabledLayerNames = layers.data(),
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,
100 nullptr, &device)) != VK_SUCCESS) {
101 FML_DLOG(INFO) << "Could not create device.";
102 return;
103 }
104
105 device_ = VulkanHandle<VkDevice>{
106 device, [this](VkDevice device) { vk_.DestroyDevice(device, nullptr); }};
107
108 if (!vk_.SetupDeviceProcAddresses(device_)) {
109 FML_DLOG(INFO) << "Could not set up 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_ = VulkanHandle<VkQueue>(queue);
123
124 if (!InitializeCommandPool()) {
125 return;
126 }
127
128 valid_ = true;
129}
bool SetupDeviceProcAddresses(const VulkanHandle< VkDevice > &device)
VkPhysicalDevice physical_device
Definition main.cc:51
VkDevice device
Definition main.cc:53
VkQueue queue
Definition main.cc:55
#define FML_DLOG(severity)
Definition logging.h:102
static uint32_t FindGraphicsQueueIndex(const std::vector< VkQueueFamilyProperties > &properties)
constexpr auto kVulkanInvalidGraphicsQueueIndex
std::vector< std::string > DeviceLayersToEnable(const VulkanProcTable &vk, const VulkanHandle< VkPhysicalDevice > &physical_device, bool enable_validation_layers)
VkStructureType sType
VkStructureType sType
#define VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME
#define VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME
#define VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME
@ VK_SUCCESS
#define VK_NULL_HANDLE
Definition vulkan_core.h:46
#define VK_KHR_SWAPCHAIN_EXTENSION_NAME
@ VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO
@ VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO
#define VK_CALL_LOG_ERROR(expression)

◆ VulkanDevice() [2/2]

vulkan::VulkanDevice::VulkanDevice ( VulkanProcTable vk,
VulkanHandle< VkPhysicalDevice >  physical_device,
VulkanHandle< VkDevice >  device,
uint32_t  queue_family_index,
VulkanHandle< VkQueue >  queue 
)

Wrap an existing VkDevice and VkQueue.

Definition at line 131 of file vulkan_device.cc.

136 : vk_(p_vk),
137 physical_device_(std::move(physical_device)),
138 device_(std::move(device)),
139 queue_(std::move(queue)),
140 graphics_queue_index_(queue_family_index),
141 valid_(false) {
142 if (!physical_device_ || !vk_.AreInstanceProcsSetup()) {
143 return;
144 }
145
146 if (!InitializeCommandPool()) {
147 return;
148 }
149
150 valid_ = true;
151}
uint32_t queue_family_index
Definition main.cc:54

◆ ~VulkanDevice()

vulkan::VulkanDevice::~VulkanDevice ( )

Definition at line 177 of file vulkan_device.cc.

177 {
179}
#define FML_ALLOW_UNUSED_LOCAL(x)

Member Function Documentation

◆ ChoosePresentMode()

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

Definition at line 349 of file vulkan_device.cc.

350 {
351 if (!surface.IsValid() || present_mode == nullptr) {
352 return false;
353 }
354
355 // https://github.com/LunarG/VulkanSamples/issues/98 indicates that
356 // VK_PRESENT_MODE_FIFO_KHR is preferable on mobile platforms. The problems
357 // mentioned in the ticket w.r.t the application being faster that the refresh
358 // rate of the screen should not be faced by any Flutter platforms as they are
359 // powered by Vsync pulses instead of depending the submit to block.
360 // However, for platforms that don't have VSync providers set up, it is better
361 // to fall back to FIFO. For platforms that do have VSync providers, there
362 // should be little difference. In case there is a need for a mode other than
363 // FIFO, availability checks must be performed here before returning the
364 // result. FIFO is always present.
365 *present_mode = VK_PRESENT_MODE_FIFO_KHR;
366 return true;
367}
VkSurfaceKHR surface
Definition main.cc:49
@ VK_PRESENT_MODE_FIFO_KHR

◆ ChooseSurfaceFormat()

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

Definition at line 303 of file vulkan_device.cc.

306 {
307#if FML_OS_ANDROID
308 if (!surface.IsValid() || format == nullptr) {
309 return -1;
310 }
311
312 uint32_t format_count = 0;
313 if (VK_CALL_LOG_ERROR(vk_.GetPhysicalDeviceSurfaceFormatsKHR(
314 physical_device_, surface.Handle(), &format_count, nullptr)) !=
315 VK_SUCCESS) {
316 return -1;
317 }
318
319 if (format_count == 0) {
320 return -1;
321 }
322
323 std::vector<VkSurfaceFormatKHR> formats;
324 formats.resize(format_count);
325
326 if (VK_CALL_LOG_ERROR(vk_.GetPhysicalDeviceSurfaceFormatsKHR(
327 physical_device_, surface.Handle(), &format_count, formats.data())) !=
328 VK_SUCCESS) {
329 return -1;
330 }
331
332 std::map<VkFormat, VkSurfaceFormatKHR> supported_formats;
333 for (uint32_t i = 0; i < format_count; i++) {
334 supported_formats[formats[i].format] = formats[i];
335 }
336
337 // Try to find the first supported format in the list of desired formats.
338 for (size_t i = 0; i < desired_formats.size(); ++i) {
339 auto found = supported_formats.find(desired_formats[i]);
340 if (found != supported_formats.end()) {
341 *format = found->second;
342 return static_cast<int>(i);
343 }
344 }
345#endif
346 return -1;
347}
uint32_t uint32_t * format

◆ GetCommandPool()

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

Definition at line 206 of file vulkan_device.cc.

206 {
207 return command_pool_;
208}

◆ GetGraphicsQueueIndex()

uint32_t vulkan::VulkanDevice::GetGraphicsQueueIndex ( ) const

Definition at line 210 of file vulkan_device.cc.

210 {
211 return graphics_queue_index_;
212}

◆ GetHandle()

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

Definition at line 189 of file vulkan_device.cc.

189 {
190 return device_;
191}

◆ GetPhysicalDeviceFeatures()

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

Definition at line 252 of file vulkan_device.cc.

253 {
254 if (features == nullptr || !physical_device_) {
255 return false;
256 }
257 vk_.GetPhysicalDeviceFeatures(physical_device_, features);
258 return true;
259}

◆ GetPhysicalDeviceFeaturesSkia()

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

Definition at line 261 of file vulkan_device.cc.

261 {
262 if (sk_features == nullptr) {
263 return false;
264 }
265
267
268 if (!GetPhysicalDeviceFeatures(&features)) {
269 return false;
270 }
271
272 uint32_t flags = 0;
273
274 if (features.geometryShader) {
276 }
277 if (features.dualSrcBlend) {
279 }
280 if (features.sampleRateShading) {
282 }
283
284 *sk_features = flags;
285 return true;
286}
@ kSampleRateShading_GrVkFeatureFlag
@ kDualSrcBlend_GrVkFeatureFlag
@ kGeometryShader_GrVkFeatureFlag
bool GetPhysicalDeviceFeatures(VkPhysicalDeviceFeatures *features) const
FlutterSemanticsFlag flags

◆ GetPhysicalDeviceHandle()

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

Definition at line 197 of file vulkan_device.cc.

198 {
199 return physical_device_;
200}

◆ GetQueueHandle()

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

Definition at line 202 of file vulkan_device.cc.

202 {
203 return queue_;
204}

◆ GetSurfaceCapabilities()

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

Definition at line 214 of file vulkan_device.cc.

216 {
217#if FML_OS_ANDROID
218 if (!surface.IsValid() || capabilities == nullptr) {
219 return false;
220 }
221
222 bool success =
223 VK_CALL_LOG_ERROR(vk_.GetPhysicalDeviceSurfaceCapabilitiesKHR(
224 physical_device_, surface.Handle(), capabilities)) == VK_SUCCESS;
225
226 if (!success) {
227 return false;
228 }
229
230 // Check if the physical device surface capabilities are valid. If so, there
231 // is nothing more to do.
232 if (capabilities->currentExtent.width != 0xFFFFFFFF &&
233 capabilities->currentExtent.height != 0xFFFFFFFF) {
234 return true;
235 }
236
237 // Ask the native surface for its size as a fallback.
238 SkISize size = surface.GetSize();
239
240 if (size.width() == 0 || size.height() == 0) {
241 return false;
242 }
243
244 capabilities->currentExtent.width = size.width();
245 capabilities->currentExtent.height = size.height();
246 return true;
247#else
248 return false;
249#endif
250}
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition switches.h:259
uint32_t width
uint32_t height

◆ IsValid()

bool vulkan::VulkanDevice::IsValid ( ) const

Definition at line 181 of file vulkan_device.cc.

181 {
182 return valid_;
183}

◆ 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 369 of file vulkan_device.cc.

374 {
375 if (wait_semaphores.size() != wait_dest_pipeline_stages.size()) {
376 return false;
377 }
378
379 const VkSubmitInfo submit_info = {
381 .pNext = nullptr,
382 .waitSemaphoreCount = static_cast<uint32_t>(wait_semaphores.size()),
383 .pWaitSemaphores = wait_semaphores.data(),
384 .pWaitDstStageMask = wait_dest_pipeline_stages.data(),
385 .commandBufferCount = static_cast<uint32_t>(command_buffers.size()),
386 .pCommandBuffers = command_buffers.data(),
387 .signalSemaphoreCount = static_cast<uint32_t>(signal_semaphores.size()),
388 .pSignalSemaphores = signal_semaphores.data(),
389 };
390
391 if (VK_CALL_LOG_ERROR(vk_.QueueSubmit(queue_, 1, &submit_info, fence)) !=
392 VK_SUCCESS) {
393 return false;
394 }
395
396 return true;
397}
VkStructureType sType
@ VK_STRUCTURE_TYPE_SUBMIT_INFO

◆ ReleaseDeviceOwnership()

void vulkan::VulkanDevice::ReleaseDeviceOwnership ( )

Definition at line 193 of file vulkan_device.cc.

193 {
194 device_.ReleaseOwnership();
195}

◆ WaitIdle()

bool vulkan::VulkanDevice::WaitIdle ( ) const

Definition at line 185 of file vulkan_device.cc.

185 {
186 return VK_CALL_LOG_ERROR(vk_.DeviceWaitIdle(device_)) == VK_SUCCESS;
187}

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