blob: a2554ed61d4769eccd786fbb061cc1dfc70f70ce [file] [log] [blame]
// Copyright 2013 The Flutter 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 "impeller/renderer/backend/vulkan/swapchain_vk.h"
#include "fml/logging.h"
#include "impeller/base/validation.h"
#include "impeller/renderer/backend/vulkan/formats_vk.h"
namespace impeller {
std::unique_ptr<SwapchainVK> SwapchainVK::Create(vk::Device device,
vk::SurfaceKHR surface,
SwapchainDetailsVK& details) {
vk::SurfaceFormatKHR surface_format = details.PickSurfaceFormat();
vk::PresentModeKHR present_mode = details.PickPresentationMode();
vk::Extent2D extent = details.PickExtent();
vk::SwapchainCreateInfoKHR create_info;
create_info.surface = surface;
create_info.imageFormat = surface_format.format;
create_info.imageColorSpace = surface_format.colorSpace;
create_info.presentMode = present_mode;
create_info.imageExtent = extent;
create_info.minImageCount = details.GetImageCount();
create_info.imageArrayLayers = 1;
create_info.imageUsage = vk::ImageUsageFlagBits::eColorAttachment;
create_info.preTransform = details.GetTransform();
create_info.compositeAlpha = details.PickCompositeAlpha();
create_info.clipped = VK_TRUE;
create_info.imageSharingMode = vk::SharingMode::eExclusive;
{
// TODO (kaushikiska): This needs to change if graphics queue is not the
// same as present queue which is rare.
create_info.queueFamilyIndexCount = 0;
create_info.pQueueFamilyIndices = nullptr;
}
create_info.oldSwapchain = nullptr;
auto swapchain_res = device.createSwapchainKHRUnique(create_info);
if (swapchain_res.result != vk::Result::eSuccess) {
VALIDATION_LOG << "Failed to create swapchain: "
<< vk::to_string(swapchain_res.result);
return nullptr;
}
auto swapchain = std::make_unique<SwapchainVK>(
device, std::move(swapchain_res.value), surface_format.format, extent);
if (!swapchain->CreateSwapchainImages()) {
VALIDATION_LOG << "Failed to create swapchain images.";
return nullptr;
}
return swapchain;
}
bool SwapchainVK::CreateSwapchainImages() {
FML_DCHECK(swapchain_images_.empty()) << "Swapchain images already created";
auto res = device_.getSwapchainImagesKHR(*swapchain_);
if (res.result != vk::Result::eSuccess) {
FML_CHECK(false) << "Failed to get swapchain images: "
<< vk::to_string(res.result);
return false;
}
std::vector<vk::Image> images = res.value;
for (const auto& image : images) {
vk::ImageViewCreateInfo create_info;
create_info.image = image;
create_info.viewType = vk::ImageViewType::e2D;
create_info.format = image_format_;
create_info.components.r = vk::ComponentSwizzle::eIdentity;
create_info.components.g = vk::ComponentSwizzle::eIdentity;
create_info.components.b = vk::ComponentSwizzle::eIdentity;
create_info.components.a = vk::ComponentSwizzle::eIdentity;
// TODO (kaushikiska): This has to match up to the texture we will be
// rendering to (TextureVK).
create_info.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eColor;
create_info.subresourceRange.baseMipLevel = 0;
create_info.subresourceRange.levelCount = 1;
create_info.subresourceRange.baseArrayLayer = 0;
create_info.subresourceRange.layerCount = 1;
auto img_view_res = device_.createImageViewUnique(create_info);
if (img_view_res.result != vk::Result::eSuccess) {
VALIDATION_LOG << "Failed to create image view: "
<< vk::to_string(img_view_res.result);
return false;
}
swapchain_images_.push_back(std::make_unique<SwapchainImageVK>(
image, std::move(img_view_res.value), image_format_, extent_));
}
return true;
}
SwapchainVK::SwapchainVK(vk::Device device,
vk::UniqueSwapchainKHR swapchain,
vk::Format image_format,
vk::Extent2D extent)
: device_(device),
swapchain_(std::move(swapchain)),
image_format_(image_format),
extent_(extent) {}
SwapchainVK::~SwapchainVK() = default;
SwapchainImageVK::SwapchainImageVK(vk::Image image,
vk::UniqueImageView image_view,
vk::Format image_format,
vk::Extent2D extent)
: image_(image),
image_view_(std::move(image_view)),
image_format_(image_format),
extent_(extent) {}
vk::SwapchainKHR SwapchainVK::GetSwapchain() const {
return *swapchain_;
}
SwapchainImageVK* SwapchainVK::GetSwapchainImage(uint32_t image_index) const {
FML_DCHECK(image_index < swapchain_images_.size());
return swapchain_images_[image_index].get();
}
PixelFormat SwapchainImageVK::GetPixelFormat() const {
return ToPixelFormat(image_format_);
}
ISize SwapchainImageVK::GetSize() const {
return ISize(extent_.width, extent_.height);
}
vk::Image SwapchainImageVK::GetImage() const {
return image_;
}
vk::ImageView SwapchainImageVK::GetImageView() const {
return image_view_.get();
}
SwapchainImageVK::~SwapchainImageVK() = default;
} // namespace impeller