|  | // Copyright 2017 The Fuchsia Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #ifndef SRC_UI_LIB_ESCHER_VK_VULKAN_DEVICE_QUEUES_H_ | 
|  | #define SRC_UI_LIB_ESCHER_VK_VULKAN_DEVICE_QUEUES_H_ | 
|  |  | 
|  | #include <set> | 
|  | #include <string> | 
|  |  | 
|  | #include "src/lib/fxl/memory/ref_counted.h" | 
|  | #include "src/ui/lib/escher/util/debug_print.h" | 
|  | #include "src/ui/lib/escher/vk/vulkan_context.h" | 
|  | #include "src/ui/lib/escher/vk/vulkan_instance.h" | 
|  |  | 
|  | #include <vulkan/vulkan.hpp> | 
|  |  | 
|  | namespace escher { | 
|  |  | 
|  | class VulkanDeviceQueues; | 
|  | using VulkanDeviceQueuesPtr = fxl::RefPtr<VulkanDeviceQueues>; | 
|  |  | 
|  | // Convenient wrapper for creating and managing the lifecycle of a VkDevice | 
|  | // and a set of VkQueues that are suitable for use by Escher. | 
|  | class VulkanDeviceQueues : public fxl::RefCountedThreadSafe<VulkanDeviceQueues> { | 
|  | public: | 
|  | // Parameters used to construct a new Vulkan Device and Queues. | 
|  | struct Params { | 
|  | std::set<std::string> required_extension_names; | 
|  | std::set<std::string> desired_extension_names; | 
|  | vk::SurfaceKHR surface; | 
|  |  | 
|  | enum FlagBits { | 
|  | // When picking a queue, don't filter out those that do not support presentation. | 
|  | kDisableQueueFilteringForPresent = 1 << 0, | 
|  | // Create protected capable Vulkan resources. | 
|  | kAllowProtectedMemory = 1 << 1, | 
|  | }; | 
|  | using Flags = uint32_t; | 
|  | Flags flags = 0; | 
|  | }; | 
|  |  | 
|  | // Device capabilities. | 
|  | struct Caps { | 
|  | uint32_t max_image_width = 0; | 
|  | uint32_t max_image_height = 0; | 
|  | std::set<vk::Format> depth_stencil_formats; | 
|  | std::set<size_t> msaa_sample_counts; | 
|  | std::set<std::string> extensions; | 
|  | uint32_t device_api_version; | 
|  | bool allow_protected_memory; | 
|  | bool allow_ycbcr; | 
|  |  | 
|  | vk::PhysicalDeviceFeatures enabled_features; | 
|  |  | 
|  | // This function returns vk::eSuccess and the format if there is a matching | 
|  | // depth-stencil format; otherwise it returns vk::eErrorFeatureNotPresent. | 
|  | vk::ResultValue<vk::Format> GetMatchingDepthStencilFormat( | 
|  | const std::vector<vk::Format>& formats) const; | 
|  |  | 
|  | vk::ResultValue<size_t> GetMatchingSampleCount(const std::vector<size_t>& counts) const; | 
|  |  | 
|  | vk::ResultValue<vk::Format> GetMatchingDepthStencilFormat() const { | 
|  | return GetMatchingDepthStencilFormat( | 
|  | {vk::Format::eD16UnormS8Uint, vk::Format::eD24UnormS8Uint, vk::Format::eD32SfloatS8Uint}); | 
|  | } | 
|  |  | 
|  | vk::ResultValue<vk::Format> GetMatchingDepthFormat() const { | 
|  | return GetMatchingDepthStencilFormat({vk::Format::eD16Unorm, vk::Format::eD32Sfloat}); | 
|  | } | 
|  |  | 
|  | std::set<vk::Format> GetAllMatchingDepthStencilFormats( | 
|  | const std::set<vk::Format>& formats) const; | 
|  |  | 
|  | std::set<size_t> GetAllMatchingSampleCounts(const std::set<size_t>& counts) const; | 
|  |  | 
|  | Caps() = default; | 
|  | Caps(vk::PhysicalDevice device); | 
|  | }; | 
|  |  | 
|  | // Contains dynamically-obtained addresses of device-specific functions. | 
|  | struct ProcAddrs { | 
|  | PFN_vkCreateSwapchainKHR CreateSwapchainKHR = nullptr; | 
|  | PFN_vkDestroySwapchainKHR DestroySwapchainKHR = nullptr; | 
|  | PFN_vkGetSwapchainImagesKHR GetSwapchainImagesKHR = nullptr; | 
|  | PFN_vkAcquireNextImageKHR AcquireNextImageKHR = nullptr; | 
|  | PFN_vkQueuePresentKHR QueuePresentKHR = nullptr; | 
|  | }; | 
|  |  | 
|  | // Constructor. | 
|  | static fxl::RefPtr<VulkanDeviceQueues> New(VulkanInstancePtr instance, Params params); | 
|  |  | 
|  | ~VulkanDeviceQueues(); | 
|  |  | 
|  | // Enumerate the available extensions for the specified physical device. | 
|  | // Return true if all required extensions are present, and false otherwise. | 
|  | // NOTE: if an extension isn't found at first, we look in all required layers | 
|  | // to see if it is implemented there. | 
|  | static bool ValidateExtensions(vk::PhysicalDevice device, | 
|  | const std::set<std::string>& required_extension_names, | 
|  | const std::set<std::string>& required_layer_names); | 
|  |  | 
|  | vk::Device vk_device() const { return device_; } | 
|  | vk::PhysicalDevice vk_physical_device() const { return physical_device_; } | 
|  | vk::Queue vk_main_queue() const { return main_queue_; } | 
|  | uint32_t vk_main_queue_family() const { return main_queue_family_; } | 
|  | vk::Queue vk_transfer_queue() const { return transfer_queue_; } | 
|  | uint32_t vk_transfer_queue_family() const { return transfer_queue_family_; } | 
|  | vk::SurfaceKHR vk_surface() const { return params_.surface; } | 
|  | const vk::DispatchLoaderDynamic& dispatch_loader() const { return dispatch_loader_; } | 
|  |  | 
|  | // Return the parameters that were used to create this device and queues. | 
|  | const Params& params() const { return params_; } | 
|  |  | 
|  | // Return the capabilities of this device (e.g. max image width/height, etc.). | 
|  | const Caps& caps() const { return caps_; } | 
|  |  | 
|  | // Return per-device functions that were dynamically looked up. | 
|  | const ProcAddrs& proc_addrs() const { return proc_addrs_; } | 
|  |  | 
|  | // Return a VulkanContext, which contains most of the same information as | 
|  | // this object, but is what Escher pervasively passes around internally. | 
|  | // TODO: Get rid of VulkanContext, and use this object instead. | 
|  | VulkanContext GetVulkanContext() const; | 
|  |  | 
|  | private: | 
|  | VulkanDeviceQueues(vk::Device device, vk::PhysicalDevice physical_device, vk::Queue main_queue, | 
|  | uint32_t main_queue_family, vk::Queue transfer_queue, | 
|  | uint32_t transfer_queue_family, VulkanInstancePtr instance, Params params, | 
|  | Caps caps); | 
|  |  | 
|  | vk::Device device_; | 
|  | vk::PhysicalDevice physical_device_; | 
|  | vk::DispatchLoaderDynamic dispatch_loader_; | 
|  | vk::Queue main_queue_; | 
|  | uint32_t main_queue_family_; | 
|  | vk::Queue transfer_queue_; | 
|  | uint32_t transfer_queue_family_; | 
|  | vk::SurfaceKHR surface_; | 
|  | VulkanInstancePtr instance_; | 
|  | Params params_; | 
|  | Caps caps_; | 
|  | ProcAddrs proc_addrs_; | 
|  | }; | 
|  |  | 
|  | ESCHER_DEBUG_PRINTABLE(VulkanDeviceQueues::Caps); | 
|  |  | 
|  | };  // namespace escher | 
|  |  | 
|  | #endif  // SRC_UI_LIB_ESCHER_VK_VULKAN_DEVICE_QUEUES_H_ |