mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
226 lines
6.6 KiB
C++
226 lines
6.6 KiB
C++
// Copyright 2016 The Chromium Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#include "flutter/vulkan/vulkan_application.h"
|
|
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
#include "flutter/vulkan/vulkan_device.h"
|
|
#include "flutter/vulkan/vulkan_proc_table.h"
|
|
#include "flutter/vulkan/vulkan_utilities.h"
|
|
|
|
namespace vulkan {
|
|
|
|
VulkanApplication::VulkanApplication(
|
|
VulkanProcTable& p_vk,
|
|
const std::string& application_name,
|
|
std::vector<std::string> enabled_extensions,
|
|
uint32_t application_version,
|
|
uint32_t api_version)
|
|
: vk(p_vk), api_version_(api_version), valid_(false) {
|
|
// Check if we want to enable debugging.
|
|
std::vector<VkExtensionProperties> supported_extensions =
|
|
GetSupportedInstanceExtensions(vk);
|
|
bool enable_instance_debugging =
|
|
IsDebuggingEnabled() &&
|
|
ExtensionSupported(supported_extensions,
|
|
VulkanDebugReport::DebugExtensionName());
|
|
|
|
// Configure extensions.
|
|
|
|
if (enable_instance_debugging) {
|
|
enabled_extensions.emplace_back(VulkanDebugReport::DebugExtensionName());
|
|
}
|
|
#if OS_FUCHSIA
|
|
if (ExtensionSupported(supported_extensions,
|
|
VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME)) {
|
|
// VK_KHR_get_physical_device_properties2 is a dependency of the memory
|
|
// capabilities extension, so the validation layers require that it be
|
|
// enabled.
|
|
enabled_extensions.emplace_back(
|
|
VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
|
|
enabled_extensions.emplace_back(
|
|
VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME);
|
|
}
|
|
#endif
|
|
|
|
const char* extensions[enabled_extensions.size()];
|
|
|
|
for (size_t i = 0; i < enabled_extensions.size(); i++) {
|
|
extensions[i] = enabled_extensions[i].c_str();
|
|
}
|
|
|
|
// Configure layers.
|
|
|
|
const std::vector<std::string> enabled_layers = InstanceLayersToEnable(vk);
|
|
|
|
const char* layers[enabled_layers.size()];
|
|
|
|
for (size_t i = 0; i < enabled_layers.size(); i++) {
|
|
layers[i] = enabled_layers[i].c_str();
|
|
}
|
|
|
|
// Configure init structs.
|
|
|
|
const VkApplicationInfo info = {
|
|
.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
|
|
.pNext = nullptr,
|
|
.pApplicationName = application_name.c_str(),
|
|
.applicationVersion = application_version,
|
|
.pEngineName = "FlutterEngine",
|
|
.engineVersion = VK_MAKE_VERSION(1, 0, 0),
|
|
.apiVersion = api_version_,
|
|
};
|
|
|
|
const VkInstanceCreateInfo create_info = {
|
|
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
|
|
.pNext = nullptr,
|
|
.flags = 0,
|
|
.pApplicationInfo = &info,
|
|
.enabledLayerCount = static_cast<uint32_t>(enabled_layers.size()),
|
|
.ppEnabledLayerNames = layers,
|
|
.enabledExtensionCount = static_cast<uint32_t>(enabled_extensions.size()),
|
|
.ppEnabledExtensionNames = extensions,
|
|
};
|
|
|
|
// Perform initialization.
|
|
|
|
VkInstance instance = VK_NULL_HANDLE;
|
|
|
|
if (VK_CALL_LOG_ERROR(vk.CreateInstance(&create_info, nullptr, &instance)) !=
|
|
VK_SUCCESS) {
|
|
FML_DLOG(INFO) << "Could not create application instance.";
|
|
return;
|
|
}
|
|
|
|
// Now that we have an instance, setup instance proc table entries.
|
|
if (!vk.SetupInstanceProcAddresses(instance)) {
|
|
FML_DLOG(INFO) << "Could not setup instance proc addresses.";
|
|
return;
|
|
}
|
|
|
|
instance_ = {instance, [this](VkInstance i) {
|
|
FML_LOG(INFO) << "Destroying Vulkan instance";
|
|
vk.DestroyInstance(i, nullptr);
|
|
}};
|
|
|
|
if (enable_instance_debugging) {
|
|
auto debug_report = std::make_unique<VulkanDebugReport>(vk, instance_);
|
|
if (!debug_report->IsValid()) {
|
|
FML_LOG(INFO) << "Vulkan debugging was enabled but could not be setup "
|
|
"for this instance.";
|
|
} else {
|
|
debug_report_ = std::move(debug_report);
|
|
FML_DLOG(INFO) << "Debug reporting is enabled.";
|
|
}
|
|
}
|
|
|
|
valid_ = true;
|
|
}
|
|
|
|
VulkanApplication::~VulkanApplication() = default;
|
|
|
|
bool VulkanApplication::IsValid() const {
|
|
return valid_;
|
|
}
|
|
|
|
uint32_t VulkanApplication::GetAPIVersion() const {
|
|
return api_version_;
|
|
}
|
|
|
|
const VulkanHandle<VkInstance>& VulkanApplication::GetInstance() const {
|
|
return instance_;
|
|
}
|
|
|
|
void VulkanApplication::ReleaseInstanceOwnership() {
|
|
instance_.ReleaseOwnership();
|
|
}
|
|
|
|
std::vector<VkPhysicalDevice> VulkanApplication::GetPhysicalDevices() const {
|
|
if (!IsValid()) {
|
|
return {};
|
|
}
|
|
|
|
uint32_t device_count = 0;
|
|
if (VK_CALL_LOG_ERROR(vk.EnumeratePhysicalDevices(instance_, &device_count,
|
|
nullptr)) != VK_SUCCESS) {
|
|
FML_DLOG(INFO) << "Could not enumerate physical device.";
|
|
return {};
|
|
}
|
|
|
|
if (device_count == 0) {
|
|
// No available devices.
|
|
FML_DLOG(INFO) << "No physical devices found.";
|
|
return {};
|
|
}
|
|
|
|
std::vector<VkPhysicalDevice> physical_devices;
|
|
|
|
physical_devices.resize(device_count);
|
|
|
|
if (VK_CALL_LOG_ERROR(vk.EnumeratePhysicalDevices(
|
|
instance_, &device_count, physical_devices.data())) != VK_SUCCESS) {
|
|
FML_DLOG(INFO) << "Could not enumerate physical device.";
|
|
return {};
|
|
}
|
|
|
|
return physical_devices;
|
|
}
|
|
|
|
std::unique_ptr<VulkanDevice>
|
|
VulkanApplication::AcquireFirstCompatibleLogicalDevice() const {
|
|
for (auto device_handle : GetPhysicalDevices()) {
|
|
auto logical_device = std::make_unique<VulkanDevice>(vk, device_handle);
|
|
if (logical_device->IsValid()) {
|
|
return logical_device;
|
|
}
|
|
}
|
|
FML_DLOG(INFO) << "Could not acquire compatible logical device.";
|
|
return nullptr;
|
|
}
|
|
|
|
std::vector<VkExtensionProperties>
|
|
VulkanApplication::GetSupportedInstanceExtensions(
|
|
const VulkanProcTable& vk) const {
|
|
if (!vk.EnumerateInstanceExtensionProperties) {
|
|
return std::vector<VkExtensionProperties>();
|
|
}
|
|
|
|
uint32_t count = 0;
|
|
if (VK_CALL_LOG_ERROR(vk.EnumerateInstanceExtensionProperties(
|
|
nullptr, &count, nullptr)) != VK_SUCCESS) {
|
|
return std::vector<VkExtensionProperties>();
|
|
}
|
|
|
|
if (count == 0) {
|
|
return std::vector<VkExtensionProperties>();
|
|
}
|
|
|
|
std::vector<VkExtensionProperties> properties;
|
|
properties.resize(count);
|
|
if (VK_CALL_LOG_ERROR(vk.EnumerateInstanceExtensionProperties(
|
|
nullptr, &count, properties.data())) != VK_SUCCESS) {
|
|
return std::vector<VkExtensionProperties>();
|
|
}
|
|
|
|
return properties;
|
|
}
|
|
|
|
bool VulkanApplication::ExtensionSupported(
|
|
const std::vector<VkExtensionProperties>& supported_instance_extensions,
|
|
std::string extension_name) {
|
|
uint32_t count = supported_instance_extensions.size();
|
|
for (size_t i = 0; i < count; i++) {
|
|
if (strncmp(supported_instance_extensions[i].extensionName,
|
|
extension_name.c_str(), extension_name.size()) == 0) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
} // namespace vulkan
|