diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/common/logging/backend.cpp | 1 | ||||
| -rw-r--r-- | src/common/logging/log.h | 1 | ||||
| -rw-r--r-- | src/video_core/CMakeLists.txt | 10 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/declarations.h | 45 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_device.cpp | 231 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_device.h | 116 |
6 files changed, 404 insertions, 0 deletions
diff --git a/src/common/logging/backend.cpp b/src/common/logging/backend.cpp index 12f6d0114..a5e031189 100644 --- a/src/common/logging/backend.cpp +++ b/src/common/logging/backend.cpp | |||
| @@ -232,6 +232,7 @@ void DebuggerBackend::Write(const Entry& entry) { | |||
| 232 | CLS(Render) \ | 232 | CLS(Render) \ |
| 233 | SUB(Render, Software) \ | 233 | SUB(Render, Software) \ |
| 234 | SUB(Render, OpenGL) \ | 234 | SUB(Render, OpenGL) \ |
| 235 | SUB(Render, Vulkan) \ | ||
| 235 | CLS(Audio) \ | 236 | CLS(Audio) \ |
| 236 | SUB(Audio, DSP) \ | 237 | SUB(Audio, DSP) \ |
| 237 | SUB(Audio, Sink) \ | 238 | SUB(Audio, Sink) \ |
diff --git a/src/common/logging/log.h b/src/common/logging/log.h index d4ec31ec3..8ed6d5050 100644 --- a/src/common/logging/log.h +++ b/src/common/logging/log.h | |||
| @@ -112,6 +112,7 @@ enum class Class : ClassType { | |||
| 112 | Render, ///< Emulator video output and hardware acceleration | 112 | Render, ///< Emulator video output and hardware acceleration |
| 113 | Render_Software, ///< Software renderer backend | 113 | Render_Software, ///< Software renderer backend |
| 114 | Render_OpenGL, ///< OpenGL backend | 114 | Render_OpenGL, ///< OpenGL backend |
| 115 | Render_Vulkan, ///< Vulkan backend | ||
| 115 | Audio, ///< Audio emulation | 116 | Audio, ///< Audio emulation |
| 116 | Audio_DSP, ///< The HLE implementation of the DSP | 117 | Audio_DSP, ///< The HLE implementation of the DSP |
| 117 | Audio_Sink, ///< Emulator audio output backend | 118 | Audio_Sink, ///< Emulator audio output backend |
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index 1db0d031d..d35a738d5 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt | |||
| @@ -101,6 +101,16 @@ add_library(video_core STATIC | |||
| 101 | video_core.h | 101 | video_core.h |
| 102 | ) | 102 | ) |
| 103 | 103 | ||
| 104 | if (ENABLE_VULKAN) | ||
| 105 | target_sources(video_core PRIVATE | ||
| 106 | renderer_vulkan/declarations.h | ||
| 107 | renderer_vulkan/vk_device.cpp | ||
| 108 | renderer_vulkan/vk_device.h) | ||
| 109 | |||
| 110 | target_include_directories(video_core PRIVATE ../../externals/Vulkan-Headers/include) | ||
| 111 | target_compile_definitions(video_core PRIVATE HAS_VULKAN) | ||
| 112 | endif() | ||
| 113 | |||
| 104 | create_target_directory_groups(video_core) | 114 | create_target_directory_groups(video_core) |
| 105 | 115 | ||
| 106 | target_link_libraries(video_core PUBLIC common core) | 116 | target_link_libraries(video_core PUBLIC common core) |
diff --git a/src/video_core/renderer_vulkan/declarations.h b/src/video_core/renderer_vulkan/declarations.h new file mode 100644 index 000000000..ba25b5bc7 --- /dev/null +++ b/src/video_core/renderer_vulkan/declarations.h | |||
| @@ -0,0 +1,45 @@ | |||
| 1 | // Copyright 2019 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <vulkan/vulkan.hpp> | ||
| 8 | |||
| 9 | namespace Vulkan { | ||
| 10 | |||
| 11 | // vulkan.hpp unique handlers use DispatchLoaderStatic | ||
| 12 | template <typename T> | ||
| 13 | using UniqueHandle = vk::UniqueHandle<T, vk::DispatchLoaderDynamic>; | ||
| 14 | |||
| 15 | using UniqueAccelerationStructureNV = UniqueHandle<vk::AccelerationStructureNV>; | ||
| 16 | using UniqueBuffer = UniqueHandle<vk::Buffer>; | ||
| 17 | using UniqueBufferView = UniqueHandle<vk::BufferView>; | ||
| 18 | using UniqueCommandBuffer = UniqueHandle<vk::CommandBuffer>; | ||
| 19 | using UniqueCommandPool = UniqueHandle<vk::CommandPool>; | ||
| 20 | using UniqueDescriptorPool = UniqueHandle<vk::DescriptorPool>; | ||
| 21 | using UniqueDescriptorSet = UniqueHandle<vk::DescriptorSet>; | ||
| 22 | using UniqueDescriptorSetLayout = UniqueHandle<vk::DescriptorSetLayout>; | ||
| 23 | using UniqueDescriptorUpdateTemplate = UniqueHandle<vk::DescriptorUpdateTemplate>; | ||
| 24 | using UniqueDevice = UniqueHandle<vk::Device>; | ||
| 25 | using UniqueDeviceMemory = UniqueHandle<vk::DeviceMemory>; | ||
| 26 | using UniqueEvent = UniqueHandle<vk::Event>; | ||
| 27 | using UniqueFence = UniqueHandle<vk::Fence>; | ||
| 28 | using UniqueFramebuffer = UniqueHandle<vk::Framebuffer>; | ||
| 29 | using UniqueImage = UniqueHandle<vk::Image>; | ||
| 30 | using UniqueImageView = UniqueHandle<vk::ImageView>; | ||
| 31 | using UniqueIndirectCommandsLayoutNVX = UniqueHandle<vk::IndirectCommandsLayoutNVX>; | ||
| 32 | using UniqueObjectTableNVX = UniqueHandle<vk::ObjectTableNVX>; | ||
| 33 | using UniquePipeline = UniqueHandle<vk::Pipeline>; | ||
| 34 | using UniquePipelineCache = UniqueHandle<vk::PipelineCache>; | ||
| 35 | using UniquePipelineLayout = UniqueHandle<vk::PipelineLayout>; | ||
| 36 | using UniqueQueryPool = UniqueHandle<vk::QueryPool>; | ||
| 37 | using UniqueRenderPass = UniqueHandle<vk::RenderPass>; | ||
| 38 | using UniqueSampler = UniqueHandle<vk::Sampler>; | ||
| 39 | using UniqueSamplerYcbcrConversion = UniqueHandle<vk::SamplerYcbcrConversion>; | ||
| 40 | using UniqueSemaphore = UniqueHandle<vk::Semaphore>; | ||
| 41 | using UniqueShaderModule = UniqueHandle<vk::ShaderModule>; | ||
| 42 | using UniqueSwapchainKHR = UniqueHandle<vk::SwapchainKHR>; | ||
| 43 | using UniqueValidationCacheEXT = UniqueHandle<vk::ValidationCacheEXT>; | ||
| 44 | |||
| 45 | } // namespace Vulkan | ||
diff --git a/src/video_core/renderer_vulkan/vk_device.cpp b/src/video_core/renderer_vulkan/vk_device.cpp new file mode 100644 index 000000000..78a4e5f0e --- /dev/null +++ b/src/video_core/renderer_vulkan/vk_device.cpp | |||
| @@ -0,0 +1,231 @@ | |||
| 1 | // Copyright 2018 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <map> | ||
| 6 | #include <optional> | ||
| 7 | #include <set> | ||
| 8 | #include <vector> | ||
| 9 | #include "common/assert.h" | ||
| 10 | #include "video_core/renderer_vulkan/declarations.h" | ||
| 11 | #include "video_core/renderer_vulkan/vk_device.h" | ||
| 12 | |||
| 13 | namespace Vulkan { | ||
| 14 | |||
| 15 | namespace Alternatives { | ||
| 16 | |||
| 17 | constexpr std::array<vk::Format, 3> Depth24UnormS8Uint = { | ||
| 18 | vk::Format::eD32SfloatS8Uint, vk::Format::eD16UnormS8Uint, {}}; | ||
| 19 | constexpr std::array<vk::Format, 3> Depth16UnormS8Uint = { | ||
| 20 | vk::Format::eD24UnormS8Uint, vk::Format::eD32SfloatS8Uint, {}}; | ||
| 21 | |||
| 22 | } // namespace Alternatives | ||
| 23 | |||
| 24 | constexpr const vk::Format* GetFormatAlternatives(vk::Format format) { | ||
| 25 | switch (format) { | ||
| 26 | case vk::Format::eD24UnormS8Uint: | ||
| 27 | return Alternatives::Depth24UnormS8Uint.data(); | ||
| 28 | case vk::Format::eD16UnormS8Uint: | ||
| 29 | return Alternatives::Depth16UnormS8Uint.data(); | ||
| 30 | default: | ||
| 31 | return nullptr; | ||
| 32 | } | ||
| 33 | } | ||
| 34 | |||
| 35 | constexpr vk::FormatFeatureFlags GetFormatFeatures(vk::FormatProperties properties, | ||
| 36 | FormatType format_type) { | ||
| 37 | switch (format_type) { | ||
| 38 | case FormatType::Linear: | ||
| 39 | return properties.linearTilingFeatures; | ||
| 40 | case FormatType::Optimal: | ||
| 41 | return properties.optimalTilingFeatures; | ||
| 42 | case FormatType::Buffer: | ||
| 43 | return properties.bufferFeatures; | ||
| 44 | default: | ||
| 45 | return {}; | ||
| 46 | } | ||
| 47 | } | ||
| 48 | |||
| 49 | VKDevice::VKDevice(const vk::DispatchLoaderDynamic& dldi, vk::PhysicalDevice physical, | ||
| 50 | vk::SurfaceKHR surface) | ||
| 51 | : physical{physical}, format_properties{GetFormatProperties(dldi, physical)} { | ||
| 52 | SetupFamilies(dldi, surface); | ||
| 53 | SetupProperties(dldi); | ||
| 54 | } | ||
| 55 | |||
| 56 | VKDevice::~VKDevice() = default; | ||
| 57 | |||
| 58 | bool VKDevice::Create(const vk::DispatchLoaderDynamic& dldi, vk::Instance instance) { | ||
| 59 | const auto queue_cis = GetDeviceQueueCreateInfos(); | ||
| 60 | vk::PhysicalDeviceFeatures device_features{}; | ||
| 61 | |||
| 62 | const std::vector<const char*> extensions = {VK_KHR_SWAPCHAIN_EXTENSION_NAME}; | ||
| 63 | const vk::DeviceCreateInfo device_ci({}, static_cast<u32>(queue_cis.size()), queue_cis.data(), | ||
| 64 | 0, nullptr, static_cast<u32>(extensions.size()), | ||
| 65 | extensions.data(), &device_features); | ||
| 66 | vk::Device dummy_logical; | ||
| 67 | if (physical.createDevice(&device_ci, nullptr, &dummy_logical, dldi) != vk::Result::eSuccess) { | ||
| 68 | LOG_CRITICAL(Render_Vulkan, "Logical device failed to be created!"); | ||
| 69 | return false; | ||
| 70 | } | ||
| 71 | |||
| 72 | dld.init(instance, dldi.vkGetInstanceProcAddr, dummy_logical, dldi.vkGetDeviceProcAddr); | ||
| 73 | logical = UniqueDevice( | ||
| 74 | dummy_logical, vk::ObjectDestroy<vk::NoParent, vk::DispatchLoaderDynamic>(nullptr, dld)); | ||
| 75 | |||
| 76 | graphics_queue = logical->getQueue(graphics_family, 0, dld); | ||
| 77 | present_queue = logical->getQueue(present_family, 0, dld); | ||
| 78 | return true; | ||
| 79 | } | ||
| 80 | |||
| 81 | vk::Format VKDevice::GetSupportedFormat(vk::Format wanted_format, | ||
| 82 | vk::FormatFeatureFlags wanted_usage, | ||
| 83 | FormatType format_type) const { | ||
| 84 | if (IsFormatSupported(wanted_format, wanted_usage, format_type)) { | ||
| 85 | return wanted_format; | ||
| 86 | } | ||
| 87 | // The wanted format is not supported by hardware, search for alternatives | ||
| 88 | const vk::Format* alternatives = GetFormatAlternatives(wanted_format); | ||
| 89 | if (alternatives == nullptr) { | ||
| 90 | LOG_CRITICAL(Render_Vulkan, | ||
| 91 | "Format={} with usage={} and type={} has no defined alternatives and host " | ||
| 92 | "hardware does not support it", | ||
| 93 | static_cast<u32>(wanted_format), static_cast<u32>(wanted_usage), | ||
| 94 | static_cast<u32>(format_type)); | ||
| 95 | UNREACHABLE(); | ||
| 96 | return wanted_format; | ||
| 97 | } | ||
| 98 | |||
| 99 | std::size_t i = 0; | ||
| 100 | for (vk::Format alternative = alternatives[0]; alternative != vk::Format{}; | ||
| 101 | alternative = alternatives[++i]) { | ||
| 102 | if (!IsFormatSupported(alternative, wanted_usage, format_type)) | ||
| 103 | continue; | ||
| 104 | LOG_WARNING(Render_Vulkan, | ||
| 105 | "Emulating format={} with alternative format={} with usage={} and type={}", | ||
| 106 | static_cast<u32>(wanted_format), static_cast<u32>(alternative), | ||
| 107 | static_cast<u32>(wanted_usage), static_cast<u32>(format_type)); | ||
| 108 | return alternative; | ||
| 109 | } | ||
| 110 | |||
| 111 | // No alternatives found, panic | ||
| 112 | LOG_CRITICAL(Render_Vulkan, | ||
| 113 | "Format={} with usage={} and type={} is not supported by the host hardware and " | ||
| 114 | "doesn't support any of the alternatives", | ||
| 115 | static_cast<u32>(wanted_format), static_cast<u32>(wanted_usage), | ||
| 116 | static_cast<u32>(format_type)); | ||
| 117 | UNREACHABLE(); | ||
| 118 | return wanted_format; | ||
| 119 | } | ||
| 120 | |||
| 121 | bool VKDevice::IsFormatSupported(vk::Format wanted_format, vk::FormatFeatureFlags wanted_usage, | ||
| 122 | FormatType format_type) const { | ||
| 123 | const auto it = format_properties.find(wanted_format); | ||
| 124 | if (it == format_properties.end()) { | ||
| 125 | LOG_CRITICAL(Render_Vulkan, "Unimplemented format query={}", | ||
| 126 | static_cast<u32>(wanted_format)); | ||
| 127 | UNREACHABLE(); | ||
| 128 | return true; | ||
| 129 | } | ||
| 130 | const vk::FormatFeatureFlags supported_usage = GetFormatFeatures(it->second, format_type); | ||
| 131 | return (supported_usage & wanted_usage) == wanted_usage; | ||
| 132 | } | ||
| 133 | |||
| 134 | bool VKDevice::IsSuitable(const vk::DispatchLoaderDynamic& dldi, vk::PhysicalDevice physical, | ||
| 135 | vk::SurfaceKHR surface) { | ||
| 136 | const std::string swapchain_extension = VK_KHR_SWAPCHAIN_EXTENSION_NAME; | ||
| 137 | |||
| 138 | bool has_swapchain{}; | ||
| 139 | for (const auto& prop : physical.enumerateDeviceExtensionProperties(nullptr, dldi)) { | ||
| 140 | has_swapchain |= prop.extensionName == swapchain_extension; | ||
| 141 | } | ||
| 142 | if (!has_swapchain) { | ||
| 143 | // The device doesn't support creating swapchains. | ||
| 144 | return false; | ||
| 145 | } | ||
| 146 | |||
| 147 | bool has_graphics{}, has_present{}; | ||
| 148 | const auto queue_family_properties = physical.getQueueFamilyProperties(dldi); | ||
| 149 | for (u32 i = 0; i < static_cast<u32>(queue_family_properties.size()); ++i) { | ||
| 150 | const auto& family = queue_family_properties[i]; | ||
| 151 | if (family.queueCount == 0) | ||
| 152 | continue; | ||
| 153 | |||
| 154 | has_graphics |= | ||
| 155 | (family.queueFlags & vk::QueueFlagBits::eGraphics) != static_cast<vk::QueueFlagBits>(0); | ||
| 156 | has_present |= physical.getSurfaceSupportKHR(i, surface, dldi) != 0; | ||
| 157 | } | ||
| 158 | if (!has_graphics || !has_present) { | ||
| 159 | // The device doesn't have a graphics and present queue. | ||
| 160 | return false; | ||
| 161 | } | ||
| 162 | |||
| 163 | // TODO(Rodrigo): Check if the device matches all requeriments. | ||
| 164 | const vk::PhysicalDeviceProperties props = physical.getProperties(dldi); | ||
| 165 | if (props.limits.maxUniformBufferRange < 65536) { | ||
| 166 | return false; | ||
| 167 | } | ||
| 168 | |||
| 169 | // Device is suitable. | ||
| 170 | return true; | ||
| 171 | } | ||
| 172 | |||
| 173 | void VKDevice::SetupFamilies(const vk::DispatchLoaderDynamic& dldi, vk::SurfaceKHR surface) { | ||
| 174 | std::optional<u32> graphics_family_, present_family_; | ||
| 175 | |||
| 176 | const auto queue_family_properties = physical.getQueueFamilyProperties(dldi); | ||
| 177 | for (u32 i = 0; i < static_cast<u32>(queue_family_properties.size()); ++i) { | ||
| 178 | if (graphics_family_ && present_family_) | ||
| 179 | break; | ||
| 180 | |||
| 181 | const auto& queue_family = queue_family_properties[i]; | ||
| 182 | if (queue_family.queueCount == 0) | ||
| 183 | continue; | ||
| 184 | |||
| 185 | if (queue_family.queueFlags & vk::QueueFlagBits::eGraphics) | ||
| 186 | graphics_family_ = i; | ||
| 187 | if (physical.getSurfaceSupportKHR(i, surface, dldi)) | ||
| 188 | present_family_ = i; | ||
| 189 | } | ||
| 190 | ASSERT(graphics_family_ && present_family_); | ||
| 191 | |||
| 192 | graphics_family = *graphics_family_; | ||
| 193 | present_family = *present_family_; | ||
| 194 | } | ||
| 195 | |||
| 196 | void VKDevice::SetupProperties(const vk::DispatchLoaderDynamic& dldi) { | ||
| 197 | const vk::PhysicalDeviceProperties props = physical.getProperties(dldi); | ||
| 198 | device_type = props.deviceType; | ||
| 199 | uniform_buffer_alignment = static_cast<u64>(props.limits.minUniformBufferOffsetAlignment); | ||
| 200 | } | ||
| 201 | |||
| 202 | std::vector<vk::DeviceQueueCreateInfo> VKDevice::GetDeviceQueueCreateInfos() const { | ||
| 203 | static const float QUEUE_PRIORITY = 1.f; | ||
| 204 | |||
| 205 | std::set<u32> unique_queue_families = {graphics_family, present_family}; | ||
| 206 | std::vector<vk::DeviceQueueCreateInfo> queue_cis; | ||
| 207 | |||
| 208 | for (u32 queue_family : unique_queue_families) | ||
| 209 | queue_cis.push_back({{}, queue_family, 1, &QUEUE_PRIORITY}); | ||
| 210 | |||
| 211 | return queue_cis; | ||
| 212 | } | ||
| 213 | |||
| 214 | std::map<vk::Format, vk::FormatProperties> VKDevice::GetFormatProperties( | ||
| 215 | const vk::DispatchLoaderDynamic& dldi, vk::PhysicalDevice physical) { | ||
| 216 | std::map<vk::Format, vk::FormatProperties> format_properties; | ||
| 217 | |||
| 218 | const auto AddFormatQuery = [&format_properties, &dldi, physical](vk::Format format) { | ||
| 219 | format_properties.emplace(format, physical.getFormatProperties(format, dldi)); | ||
| 220 | }; | ||
| 221 | AddFormatQuery(vk::Format::eA8B8G8R8UnormPack32); | ||
| 222 | AddFormatQuery(vk::Format::eR5G6B5UnormPack16); | ||
| 223 | AddFormatQuery(vk::Format::eD32Sfloat); | ||
| 224 | AddFormatQuery(vk::Format::eD16UnormS8Uint); | ||
| 225 | AddFormatQuery(vk::Format::eD24UnormS8Uint); | ||
| 226 | AddFormatQuery(vk::Format::eD32SfloatS8Uint); | ||
| 227 | |||
| 228 | return format_properties; | ||
| 229 | } | ||
| 230 | |||
| 231 | } // namespace Vulkan | ||
diff --git a/src/video_core/renderer_vulkan/vk_device.h b/src/video_core/renderer_vulkan/vk_device.h new file mode 100644 index 000000000..e87c7a508 --- /dev/null +++ b/src/video_core/renderer_vulkan/vk_device.h | |||
| @@ -0,0 +1,116 @@ | |||
| 1 | // Copyright 2018 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <map> | ||
| 8 | #include <vector> | ||
| 9 | #include "common/common_types.h" | ||
| 10 | #include "video_core/renderer_vulkan/declarations.h" | ||
| 11 | |||
| 12 | namespace Vulkan { | ||
| 13 | |||
| 14 | /// Format usage descriptor | ||
| 15 | enum class FormatType { Linear, Optimal, Buffer }; | ||
| 16 | |||
| 17 | /// Handles data specific to a physical device. | ||
| 18 | class VKDevice final { | ||
| 19 | public: | ||
| 20 | explicit VKDevice(const vk::DispatchLoaderDynamic& dldi, vk::PhysicalDevice physical, | ||
| 21 | vk::SurfaceKHR surface); | ||
| 22 | ~VKDevice(); | ||
| 23 | |||
| 24 | /// Initializes the device. Returns true on success. | ||
| 25 | bool Create(const vk::DispatchLoaderDynamic& dldi, vk::Instance instance); | ||
| 26 | |||
| 27 | /** | ||
| 28 | * Returns a format supported by the device for the passed requeriments. | ||
| 29 | * @param wanted_format The ideal format to be returned. It may not be the returned format. | ||
| 30 | * @param wanted_usage The usage that must be fulfilled even if the format is not supported. | ||
| 31 | * @param format_type Format type usage. | ||
| 32 | * @returns A format supported by the device. | ||
| 33 | */ | ||
| 34 | vk::Format GetSupportedFormat(vk::Format wanted_format, vk::FormatFeatureFlags wanted_usage, | ||
| 35 | FormatType format_type) const; | ||
| 36 | |||
| 37 | /// Returns the dispatch loader with direct function pointers of the device | ||
| 38 | const vk::DispatchLoaderDynamic& GetDispatchLoader() const { | ||
| 39 | return dld; | ||
| 40 | } | ||
| 41 | |||
| 42 | /// Returns the logical device | ||
| 43 | vk::Device GetLogical() const { | ||
| 44 | return logical.get(); | ||
| 45 | } | ||
| 46 | |||
| 47 | /// Returns the physical device. | ||
| 48 | vk::PhysicalDevice GetPhysical() const { | ||
| 49 | return physical; | ||
| 50 | } | ||
| 51 | |||
| 52 | /// Returns the main graphics queue. | ||
| 53 | vk::Queue GetGraphicsQueue() const { | ||
| 54 | return graphics_queue; | ||
| 55 | } | ||
| 56 | |||
| 57 | /// Returns the main present queue. | ||
| 58 | vk::Queue GetPresentQueue() const { | ||
| 59 | return present_queue; | ||
| 60 | } | ||
| 61 | |||
| 62 | /// Returns main graphics queue family index. | ||
| 63 | u32 GetGraphicsFamily() const { | ||
| 64 | return graphics_family; | ||
| 65 | } | ||
| 66 | |||
| 67 | /// Returns main present queue family index. | ||
| 68 | u32 GetPresentFamily() const { | ||
| 69 | return present_family; | ||
| 70 | } | ||
| 71 | |||
| 72 | /// Returns if the device is integrated with the host CPU | ||
| 73 | bool IsIntegrated() const { | ||
| 74 | return device_type == vk::PhysicalDeviceType::eIntegratedGpu; | ||
| 75 | } | ||
| 76 | |||
| 77 | /// Returns uniform buffer alignment requeriment | ||
| 78 | u64 GetUniformBufferAlignment() const { | ||
| 79 | return uniform_buffer_alignment; | ||
| 80 | } | ||
| 81 | |||
| 82 | /// Checks if the physical device is suitable. | ||
| 83 | static bool IsSuitable(const vk::DispatchLoaderDynamic& dldi, vk::PhysicalDevice physical, | ||
| 84 | vk::SurfaceKHR surface); | ||
| 85 | |||
| 86 | private: | ||
| 87 | /// Sets up queue families. | ||
| 88 | void SetupFamilies(const vk::DispatchLoaderDynamic& dldi, vk::SurfaceKHR surface); | ||
| 89 | |||
| 90 | /// Sets up device properties. | ||
| 91 | void SetupProperties(const vk::DispatchLoaderDynamic& dldi); | ||
| 92 | |||
| 93 | /// Returns a list of queue initialization descriptors. | ||
| 94 | std::vector<vk::DeviceQueueCreateInfo> GetDeviceQueueCreateInfos() const; | ||
| 95 | |||
| 96 | /// Returns true if a format is supported. | ||
| 97 | bool IsFormatSupported(vk::Format wanted_format, vk::FormatFeatureFlags wanted_usage, | ||
| 98 | FormatType format_type) const; | ||
| 99 | |||
| 100 | /// Returns the device properties for Vulkan formats. | ||
| 101 | static std::map<vk::Format, vk::FormatProperties> GetFormatProperties( | ||
| 102 | const vk::DispatchLoaderDynamic& dldi, vk::PhysicalDevice physical); | ||
| 103 | |||
| 104 | const vk::PhysicalDevice physical; ///< Physical device | ||
| 105 | vk::DispatchLoaderDynamic dld; ///< Device function pointers | ||
| 106 | UniqueDevice logical; ///< Logical device | ||
| 107 | vk::Queue graphics_queue; ///< Main graphics queue | ||
| 108 | vk::Queue present_queue; ///< Main present queue | ||
| 109 | u32 graphics_family{}; ///< Main graphics queue family index | ||
| 110 | u32 present_family{}; ///< Main present queue family index | ||
| 111 | vk::PhysicalDeviceType device_type; ///< Physical device type | ||
| 112 | u64 uniform_buffer_alignment{}; ///< Uniform buffer alignment requeriment | ||
| 113 | std::map<vk::Format, vk::FormatProperties> format_properties; ///< Format properties dictionary | ||
| 114 | }; | ||
| 115 | |||
| 116 | } // namespace Vulkan | ||