Flutter Engine
The Flutter Engine
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. More...
 
 VulkanDevice (VulkanProcTable &vk, VulkanHandle< VkPhysicalDevice > physical_device, VulkanHandle< VkDevice > device, uint32_t queue_family_index, VulkanHandle< VkQueue > queue)
 Wrap an existing VkDevice and VkQueue. More...
 
 ~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
 
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 AreInstanceProcsSetup() const
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 float max(float r, float g, float b)
Definition: hsl.cpp:49
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
Definition: vulkan_core.h:3258
VkStructureType sType
Definition: vulkan_core.h:3249
#define VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME
Definition: vulkan_core.h:8788
#define VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME
Definition: vulkan_core.h:8708
#define VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME
Definition: vulkan_core.h:9396
@ VK_SUCCESS
Definition: vulkan_core.h:141
#define VK_NULL_HANDLE
Definition: vulkan_core.h:46
#define VK_KHR_SWAPCHAIN_EXTENSION_NAME
Definition: vulkan_core.h:7707
@ VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO
Definition: vulkan_core.h:204
@ VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO
Definition: vulkan_core.h:205
#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 322 of file vulkan_device.cc.

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

◆ ChooseSurfaceFormat()

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

Definition at line 276 of file vulkan_device.cc.

279 {
280#if FML_OS_ANDROID
281 if (!surface.IsValid() || format == nullptr) {
282 return -1;
283 }
284
285 uint32_t format_count = 0;
286 if (VK_CALL_LOG_ERROR(vk_.GetPhysicalDeviceSurfaceFormatsKHR(
287 physical_device_, surface.Handle(), &format_count, nullptr)) !=
288 VK_SUCCESS) {
289 return -1;
290 }
291
292 if (format_count == 0) {
293 return -1;
294 }
295
296 std::vector<VkSurfaceFormatKHR> formats;
297 formats.resize(format_count);
298
299 if (VK_CALL_LOG_ERROR(vk_.GetPhysicalDeviceSurfaceFormatsKHR(
300 physical_device_, surface.Handle(), &format_count, formats.data())) !=
301 VK_SUCCESS) {
302 return -1;
303 }
304
305 std::map<VkFormat, VkSurfaceFormatKHR> supported_formats;
306 for (uint32_t i = 0; i < format_count; i++) {
307 supported_formats[formats[i].format] = formats[i];
308 }
309
310 // Try to find the first supported format in the list of desired formats.
311 for (size_t i = 0; i < desired_formats.size(); ++i) {
312 auto found = supported_formats.find(desired_formats[i]);
313 if (found != supported_formats.end()) {
314 *format = found->second;
315 return static_cast<int>(i);
316 }
317 }
318#endif
319 return -1;
320}
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}

◆ 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
Definition: SkSize.h:16
uint32_t width
Definition: vulkan_core.h:2858
uint32_t height
Definition: vulkan_core.h:2859

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

347 {
348 if (wait_semaphores.size() != wait_dest_pipeline_stages.size()) {
349 return false;
350 }
351
352 const VkSubmitInfo submit_info = {
354 .pNext = nullptr,
355 .waitSemaphoreCount = static_cast<uint32_t>(wait_semaphores.size()),
356 .pWaitSemaphores = wait_semaphores.data(),
357 .pWaitDstStageMask = wait_dest_pipeline_stages.data(),
358 .commandBufferCount = static_cast<uint32_t>(command_buffers.size()),
359 .pCommandBuffers = command_buffers.data(),
360 .signalSemaphoreCount = static_cast<uint32_t>(signal_semaphores.size()),
361 .pSignalSemaphores = signal_semaphores.data(),
362 };
363
364 if (VK_CALL_LOG_ERROR(vk_.QueueSubmit(queue_, 1, &submit_info, fence)) !=
365 VK_SUCCESS) {
366 return false;
367 }
368
369 return true;
370}
VkStructureType sType
Definition: vulkan_core.h:3283
@ VK_STRUCTURE_TYPE_SUBMIT_INFO
Definition: vulkan_core.h:206

◆ 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: