提交 1b67eb2b 编写于 作者: C Chinmay Garde 提交者: GitHub

Setup a vulkan window with device selection and swapchain setup. (#3033)

上级 e4121f80
......@@ -20,6 +20,7 @@
vars = {
'chromium_git': 'https://chromium.googlesource.com',
'fuchsia_git': 'https://fuchsia.googlesource.com',
'github_git': 'https://github.com',
'mojo_sdk_revision': '6b5fb1227c742f5ecc077486ebc029f2711c61fa',
'base_revision': '672b04e54b937ec899429a6bd5409c5a6300d151',
'skia_revision': '5561e3ddbbf6c3e051075ada4a11ddc70760f03d',
......@@ -114,6 +115,10 @@ deps = {
'src/third_party/libjpeg_turbo':
Var('chromium_git') + '/chromium/deps/libjpeg_turbo.git' + '@' + '7260e4d8b8e1e40b17f03fafdf1cd83296900f76',
# Headers for Vulkan 1.0
'src/third_party/vulkan':
Var('github_git') + '/KhronosGroup/Vulkan-Docs.git' + '@' + 'e29c2489e238509c41aeb8c7bce9d669a496344b',
}
deps_os = {
......
......@@ -135,13 +135,14 @@ if (is_android) {
]
deps = [
":common",
":gpu_direct",
":jni_headers",
"//flutter/lib/jni",
"//flutter/vulkan",
"//mojo/android:libsystem_java",
"//mojo/edk/base_edk",
"//mojo/edk/system",
":common",
":gpu_direct",
":jni_headers",
]
ldflags = [
......
# Copyright 2015 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.
source_set("vulkan") {
sources = [
"vulkan_backbuffer.cc",
"vulkan_backbuffer.h",
"vulkan_handle.cc",
"vulkan_handle.h",
"vulkan_interface.h",
"vulkan_proc_table.cc",
"vulkan_proc_table.h",
"vulkan_window.cc",
"vulkan_window.h",
]
deps = [
"//lib/ftl",
]
}
// 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 "vulkan_backbuffer.h"
#include <limits>
namespace vulkan {
VulkanBackbuffer::VulkanBackbuffer(VulkanProcTable& p_vk,
VulkanHandle<VkDevice>& device,
VulkanHandle<VkCommandPool>& pool,
VulkanHandle<VkImage> image)
: vk(p_vk),
device_(device),
pool_(pool),
image_(std::move(image)),
valid_(false) {
if (!device_ || !pool_ || !image_) {
return;
}
if (!CreateSemaphores()) {
return;
}
if (!CreateTransitionBuffers()) {
return;
}
if (!CreateFences()) {
return;
}
valid_ = true;
}
VulkanBackbuffer::~VulkanBackbuffer() {
WaitFences();
}
bool VulkanBackbuffer::IsValid() const {
return valid_;
}
bool VulkanBackbuffer::CreateSemaphores() {
const VkSemaphoreCreateInfo create_info = {
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
};
auto semaphore_collect = [this](VkSemaphore semaphore) {
vk.destroySemaphore(device_, semaphore, nullptr);
};
for (size_t i = 0; i < semaphores_.size(); i++) {
VkSemaphore semaphore = VK_NULL_HANDLE;
if (vk.createSemaphore(device_, &create_info, nullptr, &semaphore) !=
VK_SUCCESS) {
return false;
}
semaphores_[i] = {semaphore, semaphore_collect};
}
return true;
}
bool VulkanBackbuffer::CreateTransitionBuffers() {
const VkCommandBufferAllocateInfo allocate_info = {
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
.pNext = nullptr,
.commandPool = pool_,
.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
.commandBufferCount = 1,
};
auto buffer_collect = [this](VkCommandBuffer buffer) {
vk.freeCommandBuffers(device_, pool_, 1, &buffer);
};
for (size_t i = 0; i < transition_buffers_.size(); i++) {
VkCommandBuffer buffer = VK_NULL_HANDLE;
if (vk.allocateCommandBuffers(device_, &allocate_info, &buffer) !=
VK_SUCCESS) {
return false;
}
transition_buffers_[i] = {buffer, buffer_collect};
}
return true;
}
bool VulkanBackbuffer::CreateFences() {
const VkFenceCreateInfo create_info = {
.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
.pNext = nullptr,
.flags = VK_FENCE_CREATE_SIGNALED_BIT,
};
auto fence_collect = [this](VkFence fence) {
vk.destroyFence(device_, fence, nullptr);
};
for (size_t i = 0; i < use_fences_.size(); i++) {
VkFence fence = VK_NULL_HANDLE;
if (vk.createFence(device_, &create_info, nullptr, &fence) != VK_SUCCESS) {
return false;
}
use_fences_[i] = {fence, fence_collect};
}
return true;
}
void VulkanBackbuffer::WaitFences() {
VkFence fences[use_fences_.size()];
for (size_t i = 0; i < use_fences_.size(); i++) {
fences[i] = use_fences_[i];
}
vk.waitForFences(device_, static_cast<uint32_t>(use_fences_.size()), fences,
true, std::numeric_limits<uint64_t>::max());
}
} // namespace vulkan
// 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.
#ifndef FLUTTER_VULKAN_VULKAN_BACKBUFFER_H_
#define FLUTTER_VULKAN_VULKAN_BACKBUFFER_H_
#include <array>
#include "lib/ftl/macros.h"
#include "vulkan_proc_table.h"
#include "vulkan_handle.h"
namespace vulkan {
class VulkanBackbuffer {
public:
VulkanBackbuffer(VulkanProcTable& vk,
VulkanHandle<VkDevice>& device,
VulkanHandle<VkCommandPool>& pool,
VulkanHandle<VkImage> image);
~VulkanBackbuffer();
bool IsValid() const;
private:
VulkanProcTable& vk;
VulkanHandle<VkDevice>& device_;
VulkanHandle<VkCommandPool>& pool_;
VulkanHandle<VkImage> image_;
bool valid_;
std::array<VulkanHandle<VkSemaphore>, 2> semaphores_;
std::array<VulkanHandle<VkCommandBuffer>, 2> transition_buffers_;
std::array<VulkanHandle<VkFence>, 2> use_fences_;
bool CreateSemaphores();
bool CreateTransitionBuffers();
bool CreateFences();
void WaitFences();
FTL_DISALLOW_COPY_AND_ASSIGN(VulkanBackbuffer);
};
} // namespace vulkan
#endif // FLUTTER_VULKAN_VULKAN_BACKBUFFER_H_
// 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 "vulkan_handle.h"
namespace vulkan {
//
} // namespace vulkan
// 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.
#ifndef FLUTTER_VULKAN_VULKAN_HANDLE_H_
#define FLUTTER_VULKAN_VULKAN_HANDLE_H_
#include <functional>
#include "lib/ftl/macros.h"
#include "vulkan_interface.h"
#include "lib/ftl/logging.h"
namespace vulkan {
template <class T>
class VulkanHandle {
public:
using Handle = T;
using Disposer = std::function<void(Handle)>;
VulkanHandle() : handle_(VK_NULL_HANDLE) {}
VulkanHandle(Handle handle, Disposer disposer)
: handle_(handle), disposer_(disposer) {}
VulkanHandle(VulkanHandle&& other)
: handle_(other.handle_), disposer_(other.disposer_) {
other.handle_ = VK_NULL_HANDLE;
other.disposer_ = nullptr;
}
~VulkanHandle() { DisposeIfNecessary(); }
VulkanHandle& operator=(VulkanHandle&& other) {
if (handle_ != other.handle_) {
DisposeIfNecessary();
}
handle_ = other.handle_;
disposer_ = other.disposer_;
other.handle_ = VK_NULL_HANDLE;
other.disposer_ = nullptr;
return *this;
}
operator bool() const { return handle_ != VK_NULL_HANDLE; }
operator Handle() const { return handle_; }
private:
Handle handle_;
Disposer disposer_;
void DisposeIfNecessary() {
if (handle_ == VK_NULL_HANDLE) {
return;
}
disposer_(handle_);
handle_ = VK_NULL_HANDLE;
disposer_ = nullptr;
}
FTL_DISALLOW_COPY_AND_ASSIGN(VulkanHandle);
};
} // namespace vulkan
#endif // FLUTTER_VULKAN_VULKAN_HANDLE_H_
// 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.
#ifndef FLUTTER_VULKAN_VULKAN_INTERFACE_H_
#define FLUTTER_VULKAN_VULKAN_INTERFACE_H_
#define VK_NO_PROTOTYPES 1
#include "third_party/vulkan/src/vulkan/vulkan.h"
#define VK_KHR_ANDROID_SURFACE_EXTENSION_NAME "VK_KHR_android_surface"
typedef VkFlags VkAndroidSurfaceCreateFlagsKHR;
typedef struct VkAndroidSurfaceCreateInfoKHR {
VkStructureType sType;
const void* pNext;
VkAndroidSurfaceCreateFlagsKHR flags;
void* window;
} VkAndroidSurfaceCreateInfoKHR;
typedef VkResult(VKAPI_PTR* PFN_vkCreateAndroidSurfaceKHR)(
VkInstance instance,
const VkAndroidSurfaceCreateInfoKHR* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkSurfaceKHR* pSurface);
#endif // FLUTTER_VULKAN_VULKAN_INTERFACE_H_
// 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 "vulkan_proc_table.h"
#include "lib/ftl/logging.h"
#include <dlfcn.h>
namespace vulkan {
VulkanProcTable::VulkanProcTable() : valid_(false), handle_(nullptr) {
if (!OpenLibraryHandle()) {
return;
}
if (!AcquireProcs()) {
return;
}
valid_ = true;
}
VulkanProcTable::~VulkanProcTable() {
CloseLibraryHandle();
}
bool VulkanProcTable::IsValid() const {
return valid_;
}
bool VulkanProcTable::OpenLibraryHandle() {
dlerror(); // clear existing errors on thread.
handle_ = dlopen("libvulkan.so", RTLD_NOW);
if (handle_ == nullptr) {
FTL_DLOG(WARNING) << "Could not open the vulkan library: " << dlerror();
return false;
}
return true;
}
bool VulkanProcTable::CloseLibraryHandle() {
if (handle_ != nullptr) {
dlerror(); // clear existing errors on thread.
if (dlclose(handle_) != 0) {
FTL_DLOG(ERROR) << "Could not close the vulkan library handle. This "
"indicates a leak.";
FTL_DLOG(ERROR) << dlerror();
}
handle_ = nullptr;
}
return handle_ == nullptr;
}
bool VulkanProcTable::AcquireProcs() {
if (handle_ == nullptr) {
return false;
}
#define ACQUIRE_PROC(symbol, name) \
if (!(symbol = reinterpret_cast<decltype(symbol)::Proto>( \
dlsym(handle_, name)))) { \
FTL_DLOG(WARNING) << "Could not acquire proc for function " << name; \
return false; \
}
ACQUIRE_PROC(createInstance, "vkCreateInstance");
ACQUIRE_PROC(destroyInstance, "vkDestroyInstance");
ACQUIRE_PROC(enumeratePhysicalDevices, "vkEnumeratePhysicalDevices");
ACQUIRE_PROC(createDevice, "vkCreateDevice");
ACQUIRE_PROC(destroyDevice, "vkDestroyDevice");
ACQUIRE_PROC(createAndroidSurfaceKHR, "vkCreateAndroidSurfaceKHR");
ACQUIRE_PROC(getDeviceQueue, "vkGetDeviceQueue");
ACQUIRE_PROC(getPhysicalDeviceSurfaceCapabilitiesKHR,
"vkGetPhysicalDeviceSurfaceCapabilitiesKHR");
ACQUIRE_PROC(getPhysicalDeviceSurfaceFormatsKHR,
"vkGetPhysicalDeviceSurfaceFormatsKHR");
ACQUIRE_PROC(createSwapchainKHR, "vkCreateSwapchainKHR");
ACQUIRE_PROC(getSwapchainImagesKHR, "vkGetSwapchainImagesKHR");
ACQUIRE_PROC(getPhysicalDeviceSurfacePresentModesKHR,
"vkGetPhysicalDeviceSurfacePresentModesKHR");
ACQUIRE_PROC(destroySurfaceKHR, "vkDestroySurfaceKHR");
ACQUIRE_PROC(createCommandPool, "createCommandPool");
ACQUIRE_PROC(destroyCommandPool, "destroyCommandPool");
ACQUIRE_PROC(createSemaphore, "vkCreateSemaphore");
ACQUIRE_PROC(destroySemaphore, "vkDestroySemaphore");
ACQUIRE_PROC(allocateCommandBuffers, "vkAllocateCommandBuffers");
ACQUIRE_PROC(freeCommandBuffers, "vkFreeCommandBuffers");
ACQUIRE_PROC(createFence, "vkCreateFence");
ACQUIRE_PROC(destroyFence, "vkDestroyFence");
ACQUIRE_PROC(waitForFences, "vkWaitForFences");
#undef ACQUIRE_PROC
return true;
}
} // namespace vulkan
// 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.
#ifndef FLUTTER_VULKAN_VULKAN_PROC_TABLE_H_
#define FLUTTER_VULKAN_VULKAN_PROC_TABLE_H_
#include "lib/ftl/macros.h"
#include "vulkan_interface.h"
namespace vulkan {
class VulkanProcTable {
public:
template <class T>
class Proc {
public:
using Proto = T;
Proc(T proc = nullptr) : proc_(proc) {}
~Proc() { proc_ = nullptr; }
Proc operator=(T proc) {
proc_ = proc;
return *this;
}
operator bool() const { return proc_ != nullptr; }
operator T() const { return proc_; }
private:
T proc_;
};
VulkanProcTable();
~VulkanProcTable();
bool IsValid() const;
Proc<PFN_vkCreateInstance> createInstance;
Proc<PFN_vkDestroyInstance> destroyInstance;
Proc<PFN_vkEnumeratePhysicalDevices> enumeratePhysicalDevices;
Proc<PFN_vkCreateDevice> createDevice;
Proc<PFN_vkDestroyDevice> destroyDevice;
Proc<PFN_vkCreateAndroidSurfaceKHR> createAndroidSurfaceKHR;
Proc<PFN_vkGetDeviceQueue> getDeviceQueue;
Proc<PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR>
getPhysicalDeviceSurfaceCapabilitiesKHR;
Proc<PFN_vkGetPhysicalDeviceSurfaceFormatsKHR>
getPhysicalDeviceSurfaceFormatsKHR;
Proc<PFN_vkCreateSwapchainKHR> createSwapchainKHR;
Proc<PFN_vkGetSwapchainImagesKHR> getSwapchainImagesKHR;
Proc<PFN_vkGetPhysicalDeviceSurfacePresentModesKHR>
getPhysicalDeviceSurfacePresentModesKHR;
Proc<PFN_vkDestroySurfaceKHR> destroySurfaceKHR;
Proc<PFN_vkDestroySwapchainKHR> destroySwapchainKHR;
Proc<PFN_vkCreateCommandPool> createCommandPool;
Proc<PFN_vkDestroyCommandPool> destroyCommandPool;
Proc<PFN_vkCreateSemaphore> createSemaphore;
Proc<PFN_vkDestroySemaphore> destroySemaphore;
Proc<PFN_vkAllocateCommandBuffers> allocateCommandBuffers;
Proc<PFN_vkFreeCommandBuffers> freeCommandBuffers;
Proc<PFN_vkCreateFence> createFence;
Proc<PFN_vkDestroyFence> destroyFence;
Proc<PFN_vkWaitForFences> waitForFences;
private:
bool valid_;
void* handle_;
bool OpenLibraryHandle();
bool CloseLibraryHandle();
bool AcquireProcs();
FTL_DISALLOW_COPY_AND_ASSIGN(VulkanProcTable);
};
} // namespace vulkan
#endif // FLUTTER_VULKAN_VULKAN_PROC_TABLE_H_
// 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 "vulkan_window.h"
namespace vulkan {
VulkanWindow::VulkanWindow(void* native_window) : valid_(false) {
if (!vk.IsValid()) {
return;
}
if (!CreateInstance()) {
return;
}
if (!CreateSurface(native_window)) {
return;
}
if (!SelectPhysicalDevice()) {
return;
}
if (!CreateLogicalDevice()) {
return;
}
if (!CreateSwapChain()) {
return;
}
if (!AcquireDeviceQueue()) {
return;
}
if (!CreateCommandPool()) {
return;
}
if (!SetupBuffers()) {
return;
}
valid_ = true;
}
VulkanWindow::~VulkanWindow() = default;
bool VulkanWindow::IsValid() const {
return valid_;
}
bool VulkanWindow::CreateInstance() {
const VkApplicationInfo info = {
.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
.pNext = nullptr,
.pApplicationName = "FlutterEngine",
.applicationVersion = VK_MAKE_VERSION(1, 0, 0),
.pEngineName = "FlutterEngine",
.engineVersion = VK_MAKE_VERSION(1, 0, 0),
.apiVersion = VK_MAKE_VERSION(1, 0, 0),
};
const char* extensions[] = {
VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_ANDROID_SURFACE_EXTENSION_NAME,
};
const VkInstanceCreateInfo create_info = {
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
.pApplicationInfo = &info,
.enabledLayerCount = 0,
.ppEnabledLayerNames = nullptr,
.enabledExtensionCount = sizeof(extensions) / sizeof(const char*),
.ppEnabledExtensionNames = extensions,
};
VkInstance instance = VK_NULL_HANDLE;
if (vk.createInstance(&create_info, nullptr, &instance) != VK_SUCCESS) {
return false;
}
instance_ = {instance,
[this](VkInstance i) { vk.destroyInstance(i, nullptr); }};
return true;
}
bool VulkanWindow::CreateSurface(void* native_window) {
if (!instance_) {
return false;
}
const VkAndroidSurfaceCreateInfoKHR create_info = {
.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR,
.pNext = nullptr,
.flags = 0,
.window = native_window,
};
VkSurfaceKHR surface = VK_NULL_HANDLE;
if (vk.createAndroidSurfaceKHR(instance_, &create_info, nullptr, &surface) !=
VK_SUCCESS) {
return false;
}
surface_ = {surface, [this](VkSurfaceKHR surface) {
vk.destroySurfaceKHR(instance_, surface, nullptr);
}};
return true;
}
bool VulkanWindow::SelectPhysicalDevice() {
if (instance_ == nullptr) {
return false;
}
uint32_t device_count = 0;
if (vk.enumeratePhysicalDevices(instance_, &device_count, nullptr) !=
VK_SUCCESS) {
return false;
}
if (device_count == 0) {
// No available devices.
return false;
}
VkPhysicalDevice devices[device_count];
if (vk.enumeratePhysicalDevices(instance_, &device_count, devices) !=
VK_SUCCESS) {
return false;
}
// Pick the first one available.
physical_device_ = {devices[0], {}};
return true;
}
bool VulkanWindow::CreateLogicalDevice() {
if (physical_device_ == nullptr) {
return false;
}
float priorities[] = {1.0f};
const VkDeviceQueueCreateInfo queue_create = {
.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
.queueFamilyIndex = 0,
.queueCount = 1,
.pQueuePriorities = priorities,
};
const char* extensions[] = {
VK_KHR_SWAPCHAIN_EXTENSION_NAME,
};
const VkDeviceCreateInfo create_info = {
.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
.queueCreateInfoCount = 1,
.pQueueCreateInfos = &queue_create,
.enabledLayerCount = 0,
.ppEnabledLayerNames = nullptr,
.enabledExtensionCount = sizeof(extensions) / sizeof(const char*),
.ppEnabledExtensionNames = extensions,
.pEnabledFeatures = nullptr,
};
VkDevice device = VK_NULL_HANDLE;
if (vk.createDevice(physical_device_, &create_info, nullptr, &device) !=
VK_SUCCESS) {
return false;
}
device_ = {device,
[this](VkDevice device) { vk.destroyDevice(device, nullptr); }};
return true;
}
bool VulkanWindow::AcquireDeviceQueue() {
if (device_ == nullptr) {
return false;
}
VkQueue queue = VK_NULL_HANDLE;
vk.getDeviceQueue(device_, 0, 0, &queue);
if (queue == VK_NULL_HANDLE) {
return false;
}
queue_ = {queue, {}};
return true;
}
std::pair<bool, VkSurfaceFormatKHR> VulkanWindow::ChooseSurfaceFormat() {
if (!physical_device_ || !surface_) {
return {false, {}};
}
uint32_t format_count = 0;
if (vk.getPhysicalDeviceSurfaceFormatsKHR(
physical_device_, surface_, &format_count, nullptr) != VK_SUCCESS) {
return {false, {}};
}
if (format_count == 0) {
return {false, {}};
}
VkSurfaceFormatKHR formats[format_count];
if (vk.getPhysicalDeviceSurfaceFormatsKHR(
physical_device_, surface_, &format_count, formats) != VK_SUCCESS) {
return {false, {}};
}
for (uint32_t i = 0; i < format_count; i++) {
if (formats[i].format == VK_FORMAT_R8G8B8A8_UNORM) {
return {true, formats[i]};
}
}
return {false, {}};
}
std::pair<bool, VkPresentModeKHR> VulkanWindow::ChoosePresentMode() {
if (!physical_device_ || !surface_) {
return {false, {}};
}
uint32_t modes_count = 0;
if (vk.getPhysicalDeviceSurfacePresentModesKHR(
physical_device_, surface_, &modes_count, nullptr) != VK_SUCCESS) {
return {false, {}};
}
if (modes_count == 0) {
return {false, {}};
}
VkPresentModeKHR modes[modes_count];
if (vk.getPhysicalDeviceSurfacePresentModesKHR(
physical_device_, surface_, &modes_count, modes) != VK_SUCCESS) {
return {false, {}};
}
for (uint32_t i = 0; i < modes_count; i++) {
if (modes[i] == VK_PRESENT_MODE_MAILBOX_KHR) {
return {true, modes[i]};
}
}
return {true, VK_PRESENT_MODE_FIFO_KHR};
}
bool VulkanWindow::CreateSwapChain() {
if (!device_ || !surface_) {
return false;
}
// Query Capabilities
VkSurfaceCapabilitiesKHR capabilities = {0};
if (vk.getPhysicalDeviceSurfaceCapabilitiesKHR(physical_device_, surface_,
&capabilities) != VK_SUCCESS) {
return false;
}
// Query Format
VkSurfaceFormatKHR format = {};
bool query_result = false;
std::tie(query_result, format) = ChooseSurfaceFormat();
if (!query_result) {
return false;
}
// Query Present Mode
VkPresentModeKHR presentMode = VK_PRESENT_MODE_FIFO_KHR;
std::tie(query_result, presentMode) = ChoosePresentMode();
if (!query_result) {
return false;
}
// Construct the Swapchain
const VkSwapchainCreateInfoKHR create_info = {
.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
.pNext = nullptr,
.flags = 0,
.surface = surface_,
.minImageCount = capabilities.minImageCount,
.imageFormat = format.format,
.imageColorSpace = format.colorSpace,
.imageExtent = capabilities.currentExtent,
.imageArrayLayers = 1,
.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE,
.queueFamilyIndexCount = 0,
.pQueueFamilyIndices = nullptr,
.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR,
.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
.presentMode = presentMode,
.clipped = VK_FALSE,
.oldSwapchain = VK_NULL_HANDLE,
};
VkSwapchainKHR swapchain = VK_NULL_HANDLE;
if (vk.createSwapchainKHR(device_, &create_info, nullptr, &swapchain) !=
VK_SUCCESS) {
return false;
}
swapchain_ = {swapchain, [this](VkSwapchainKHR swapchain) {
vk.destroySwapchainKHR(device_, swapchain, nullptr);
}};
return true;
}
bool VulkanWindow::SetupBuffers() {
if (!device_ || !swapchain_) {
return false;
}
uint32_t count = 0;
if (vk.getSwapchainImagesKHR(device_, swapchain_, &count, nullptr) !=
VK_SUCCESS) {
return false;
}
if (count == 0) {
return false;
}
VkImage images[count];
if (vk.getSwapchainImagesKHR(device_, swapchain_, &count, images) !=
VK_SUCCESS) {
return false;
}
if (count == 0) {
return false;
}
auto image_collector = [](VkImage image) {
// We are only just getting references to images owned by the swapchain.
// There is no ownership change.
};
backbuffers_.clear();
for (uint32_t i = 0; i < count; i++) {
std::unique_ptr<VulkanBackbuffer> backbuffer(new VulkanBackbuffer(
vk, device_, command_pool_, {images[i], image_collector}));
if (!backbuffer->IsValid()) {
return false;
}
backbuffers_.emplace_back(std::move(backbuffer));
}
return true;
}
bool VulkanWindow::CreateCommandPool() {
if (!device_) {
return false;
}
const VkCommandPoolCreateInfo create_info = {
.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
.pNext = nullptr,
.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
.queueFamilyIndex = 0,
};
VkCommandPool command_pool = VK_NULL_HANDLE;
if (vk.createCommandPool(device_, &create_info, nullptr, &command_pool) !=
VK_SUCCESS) {
return false;
}
command_pool_ = {command_pool, [this](VkCommandPool pool) {
vk.destroyCommandPool(device_, pool, nullptr);
}};
return true;
}
} // namespace vulkan
// 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.
#ifndef FLUTTER_VULKAN_VULKAN_WINDOW_H_
#define FLUTTER_VULKAN_VULKAN_WINDOW_H_
#include <utility>
#include <tuple>
#include <vector>
#include "lib/ftl/macros.h"
#include "vulkan_handle.h"
#include "vulkan_proc_table.h"
#include "vulkan_backbuffer.h"
namespace vulkan {
class VulkanWindow {
public:
VulkanWindow(void* native_window);
~VulkanWindow();
bool IsValid() const;
private:
bool valid_;
VulkanProcTable vk;
VulkanHandle<VkInstance> instance_;
VulkanHandle<VkSurfaceKHR> surface_;
VulkanHandle<VkPhysicalDevice> physical_device_;
VulkanHandle<VkDevice> device_;
VulkanHandle<VkQueue> queue_;
VulkanHandle<VkSwapchainKHR> swapchain_;
std::vector<std::unique_ptr<VulkanBackbuffer>> backbuffers_;
VulkanHandle<VkCommandPool> command_pool_;
bool CreateInstance();
bool CreateSurface(void* native_window);
bool SelectPhysicalDevice();
bool CreateLogicalDevice();
bool AcquireDeviceQueue();
bool CreateSwapChain();
bool SetupBuffers();
bool CreateCommandPool();
std::pair<bool, VkSurfaceFormatKHR> ChooseSurfaceFormat();
std::pair<bool, VkPresentModeKHR> ChoosePresentMode();
FTL_DISALLOW_COPY_AND_ASSIGN(VulkanWindow);
};
} // namespace vulkan
#endif // FLUTTER_VULKAN_VULKAN_WINDOW_H_
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册