[Impeller] [vulkan] Wire-up command buffer and other bits (flutter/engine#35380)

This commit is contained in:
Kaushik Iska 2022-08-15 13:10:34 -07:00 committed by GitHub
parent de7ef0efad
commit 6efcd51c23
14 changed files with 220 additions and 31 deletions

View File

@ -107,7 +107,8 @@ PlaygroundImpl::WindowHandle PlaygroundImplVK::GetWindowHandle() const {
// |PlaygroundImpl|
std::unique_ptr<Surface> PlaygroundImplVK::AcquireSurfaceFrame(
std::shared_ptr<Context> context) {
FML_UNREACHABLE();
ContextVK* context_vk = reinterpret_cast<ContextVK*>(context_.get());
return context_vk->AcquireSurface();
}
} // namespace impeller

View File

@ -5,30 +5,128 @@
#include "impeller/renderer/backend/vulkan/command_buffer_vk.h"
#include "flutter/fml/logging.h"
#include "impeller/base/validation.h"
#include "impeller/renderer/backend/vulkan/context_vk.h"
#include "impeller/renderer/backend/vulkan/formats_vk.h"
#include "impeller/renderer/backend/vulkan/render_pass_vk.h"
#include "impeller/renderer/command_buffer.h"
#include "impeller/renderer/render_target.h"
namespace impeller {
CommandBufferVK::CommandBufferVK(std::weak_ptr<const Context> context)
: CommandBuffer(std::move(context)) {}
std::shared_ptr<CommandBufferVK> CommandBufferVK::Create(
std::weak_ptr<const Context> context,
vk::Device device,
vk::CommandPool command_pool,
SurfaceProducerVK* surface_producer) {
vk::CommandBufferAllocateInfo allocate_info;
allocate_info.setLevel(vk::CommandBufferLevel::ePrimary);
allocate_info.setCommandBufferCount(1);
allocate_info.setCommandPool(command_pool);
auto res = device.allocateCommandBuffersUnique(allocate_info);
if (res.result != vk::Result::eSuccess) {
VALIDATION_LOG << "Failed to allocate command buffer: "
<< vk::to_string(res.result);
return nullptr;
}
vk::UniqueCommandBuffer cmd = std::move(res.value[0]);
return std::make_shared<CommandBufferVK>(context, device, surface_producer,
std::move(cmd));
}
CommandBufferVK::CommandBufferVK(std::weak_ptr<const Context> context,
vk::Device device,
SurfaceProducerVK* surface_producer,
vk::UniqueCommandBuffer command_buffer)
: CommandBuffer(context),
device_(device),
command_buffer_(std::move(command_buffer)),
surface_producer_(surface_producer) {
is_valid_ = true;
}
CommandBufferVK::~CommandBufferVK() = default;
void CommandBufferVK::SetLabel(const std::string& label) const {
FML_UNREACHABLE();
if (auto context = context_.lock()) {
reinterpret_cast<const ContextVK*>(context.get())
->SetDebugName(*command_buffer_, label);
}
}
bool CommandBufferVK::IsValid() const {
FML_UNREACHABLE();
return is_valid_;
}
bool CommandBufferVK::OnSubmitCommands(CompletionCallback callback) {
FML_UNREACHABLE();
bool result = surface_producer_->Submit(*command_buffer_);
if (callback) {
callback(result ? CommandBuffer::Status::kCompleted
: CommandBuffer::Status::kError);
}
return result;
}
std::shared_ptr<RenderPass> CommandBufferVK::OnCreateRenderPass(
RenderTarget target) const {
FML_UNREACHABLE();
vk::CommandBufferBeginInfo begin_info;
auto res = command_buffer_->begin(begin_info);
if (res != vk::Result::eSuccess) {
VALIDATION_LOG << "Failed to begin command buffer: " << vk::to_string(res);
return nullptr;
}
std::vector<vk::AttachmentDescription> color_attachments;
for (const auto& [k, attachment] : target.GetColorAttachments()) {
const TextureDescriptor& tex_desc =
attachment.texture->GetTextureDescriptor();
vk::AttachmentDescription color_attachment;
color_attachment.setFormat(ToVKImageFormat(tex_desc.format));
color_attachment.setSamples(ToVKSampleCountFlagBits(tex_desc.sample_count));
color_attachment.setLoadOp(ToVKAttachmentLoadOp(attachment.load_action));
color_attachment.setStoreOp(ToVKAttachmentStoreOp(attachment.store_action));
color_attachment.setStencilLoadOp(vk::AttachmentLoadOp::eDontCare);
color_attachment.setStencilStoreOp(vk::AttachmentStoreOp::eDontCare);
color_attachment.setInitialLayout(vk::ImageLayout::eUndefined);
color_attachment.setFinalLayout(vk::ImageLayout::ePresentSrcKHR);
color_attachments.push_back(color_attachment);
}
// TODO (kaushikiska): support depth and stencil attachments.
vk::AttachmentReference color_attachment_ref;
color_attachment_ref.setAttachment(0);
color_attachment_ref.setLayout(vk::ImageLayout::eColorAttachmentOptimal);
vk::SubpassDescription subpass_desc;
subpass_desc.setPipelineBindPoint(vk::PipelineBindPoint::eGraphics);
subpass_desc.setColorAttachmentCount(color_attachments.size());
subpass_desc.setPColorAttachments(&color_attachment_ref);
vk::RenderPassCreateInfo render_pass_create;
render_pass_create.setAttachmentCount(color_attachments.size());
render_pass_create.setPAttachments(color_attachments.data());
render_pass_create.setSubpassCount(1);
render_pass_create.setPSubpasses(&subpass_desc);
auto render_pass_create_res =
device_.createRenderPassUnique(render_pass_create);
if (render_pass_create_res.result != vk::Result::eSuccess) {
VALIDATION_LOG << "Failed to create render pass: "
<< vk::to_string(render_pass_create_res.result);
return nullptr;
}
return std::make_shared<RenderPassVK>(
context_, std::move(target), *command_buffer_,
std::move(render_pass_create_res.value));
}
std::shared_ptr<BlitPass> CommandBufferVK::OnCreateBlitPass() const {

View File

@ -5,19 +5,35 @@
#pragma once
#include "flutter/fml/macros.h"
#include "impeller/renderer/backend/vulkan/surface_producer_vk.h"
#include "impeller/renderer/backend/vulkan/vk.h"
#include "impeller/renderer/command_buffer.h"
namespace impeller {
class CommandBufferVK final : public CommandBuffer {
public:
static std::shared_ptr<CommandBufferVK> Create(
std::weak_ptr<const Context> context,
vk::Device device,
vk::CommandPool command_pool,
SurfaceProducerVK* surface_producer);
CommandBufferVK(std::weak_ptr<const Context> context,
vk::Device device,
SurfaceProducerVK* surface_producer,
vk::UniqueCommandBuffer command_buffer);
// |CommandBuffer|
~CommandBufferVK() override;
private:
friend class ContextMTL;
friend class ContextVK;
explicit CommandBufferVK(std::weak_ptr<const Context> context);
vk::Device device_;
vk::UniqueCommandBuffer command_buffer_;
SurfaceProducerVK* surface_producer_;
bool is_valid_ = false;
// |CommandBuffer|
void SetLabel(const std::string& label) const override;

View File

@ -21,6 +21,10 @@ std::unique_ptr<CommandPoolVK> CommandPoolVK::Create(vk::Device device,
return std::make_unique<CommandPoolVK>(std::move(res.value));
}
vk::CommandPool CommandPoolVK::Get() const {
return *command_pool_;
}
CommandPoolVK::CommandPoolVK(vk::UniqueCommandPool command_pool)
: command_pool_(std::move(command_pool)) {}

View File

@ -18,6 +18,8 @@ class CommandPoolVK {
~CommandPoolVK();
vk::CommandPool Get() const;
private:
vk::UniqueCommandPool command_pool_;

View File

@ -15,6 +15,7 @@
#include "impeller/base/work_queue_common.h"
#include "impeller/renderer/backend/vulkan/allocator_vk.h"
#include "impeller/renderer/backend/vulkan/capabilities_vk.h"
#include "impeller/renderer/backend/vulkan/command_buffer_vk.h"
#include "impeller/renderer/backend/vulkan/surface_producer_vk.h"
#include "impeller/renderer/backend/vulkan/swapchain_details_vk.h"
#include "impeller/renderer/backend/vulkan/vk.h"
@ -462,16 +463,22 @@ std::shared_ptr<WorkQueue> ContextVK::GetWorkQueue() const {
}
std::shared_ptr<CommandBuffer> ContextVK::CreateCommandBuffer() const {
FML_UNREACHABLE();
return CommandBufferVK::Create(weak_from_this(), *device_,
graphics_command_pool_->Get(),
surface_producer_.get());
}
vk::Instance ContextVK::GetInstance() const {
return *instance_;
}
std::unique_ptr<Surface> ContextVK::AcquireSurface() {
return surface_producer_->AcquireSurface();
}
void ContextVK::SetupSwapchain(vk::UniqueSurfaceKHR surface) {
surface_ = std::move(surface);
auto present_queue_out = PickPresentQueue(physical_device_, *surface);
auto present_queue_out = PickPresentQueue(physical_device_, *surface_);
if (!present_queue_out.has_value()) {
return;
}
@ -479,11 +486,11 @@ void ContextVK::SetupSwapchain(vk::UniqueSurfaceKHR surface) {
device_->getQueue(present_queue_out->family, present_queue_out->index);
auto swapchain_details =
SwapchainDetailsVK::Create(physical_device_, *surface);
SwapchainDetailsVK::Create(physical_device_, *surface_);
if (!swapchain_details) {
return;
}
swapchain_ = SwapchainVK::Create(*device_, *surface, *swapchain_details);
swapchain_ = SwapchainVK::Create(*device_, *surface_, *swapchain_details);
auto weak_this = weak_from_this();
surface_producer_ = SurfaceProducerVK::Create(
weak_this, {

View File

@ -61,6 +61,8 @@ class ContextVK final : public Context, public BackendCast<ContextVK, Context> {
void SetupSwapchain(vk::UniqueSurfaceKHR surface);
std::unique_ptr<Surface> AcquireSurface();
private:
std::shared_ptr<fml::ConcurrentTaskRunner> worker_task_runner_;
vk::UniqueInstance instance_;

View File

@ -344,8 +344,13 @@ std::unique_ptr<PipelineCreateInfoVK> PipelineLibraryVK::CreatePipeline(
}
pipeline_info.setLayout(pipeline_layout.value.get());
// TODO(WIP)
// pipeline_info.setPDepthStencilState(&depth_stencil_state_);
vk::PipelineDepthStencilStateCreateInfo depth_stencil_state;
depth_stencil_state.setDepthTestEnable(true);
depth_stencil_state.setDepthWriteEnable(true);
depth_stencil_state.setDepthCompareOp(vk::CompareOp::eLess);
depth_stencil_state.setDepthBoundsTestEnable(false);
depth_stencil_state.setStencilTestEnable(false);
pipeline_info.setPDepthStencilState(&depth_stencil_state);
// See the note in the header about why this is a reader lock.
ReaderLock lock(cache_mutex_);

View File

@ -4,8 +4,49 @@
#include "impeller/renderer/backend/vulkan/render_pass_vk.h"
#include "fml/logging.h"
#include "impeller/renderer/backend/vulkan/texture_vk.h"
namespace impeller {
//
RenderPassVK::RenderPassVK(std::weak_ptr<const Context> context,
RenderTarget target,
vk::CommandBuffer command_buffer,
vk::UniqueRenderPass render_pass)
: RenderPass(context, target),
command_buffer_(command_buffer),
render_pass_(std::move(render_pass)) {
is_valid_ = true;
}
RenderPassVK::~RenderPassVK() = default;
bool RenderPassVK::IsValid() const {
return is_valid_;
}
void RenderPassVK::OnSetLabel(std::string label) {
label_ = std::move(label);
}
bool RenderPassVK::OnEncodeCommands(const Context& context) const {
if (!IsValid()) {
return false;
}
if (commands_.empty()) {
return true;
}
const auto& render_target = GetRenderTarget();
if (!render_target.HasColorAttachment(0u)) {
return false;
}
const auto& color0 = render_target.GetColorAttachments().at(0u);
const auto& depth0 = render_target.GetDepthAttachment();
const auto& stencil0 = render_target.GetStencilAttachment();
auto& wrapped_texture = TextureVK::Cast(*color0.texture);
FML_UNREACHABLE();
}
} // namespace impeller

View File

@ -5,6 +5,7 @@
#pragma once
#include "flutter/fml/macros.h"
#include "impeller/renderer/backend/vulkan/vk.h"
#include "impeller/renderer/render_pass.h"
#include "impeller/renderer/render_target.h"
@ -12,13 +13,21 @@ namespace impeller {
class RenderPassVK final : public RenderPass {
public:
RenderPassVK(std::weak_ptr<const Context> context,
RenderTarget target,
vk::CommandBuffer command_buffer,
vk::UniqueRenderPass render_pass);
// |RenderPass|
~RenderPassVK() override;
private:
friend class CommandBufferVK;
RenderPassVK(RenderTarget target);
vk::CommandBuffer command_buffer_;
vk::UniqueRenderPass render_pass_;
std::string label_ = "";
bool is_valid_ = false;
// |RenderPass|
bool IsValid() const override;

View File

@ -7,6 +7,7 @@
#include <array>
#include "fml/logging.h"
#include "impeller/base/validation.h"
#include "impeller/renderer/backend/vulkan/surface_vk.h"
namespace impeller {
@ -31,8 +32,7 @@ SurfaceProducerVK::SurfaceProducerVK(
SurfaceProducerVK::~SurfaceProducerVK() = default;
std::unique_ptr<Surface> SurfaceProducerVK::AcquireSurface(
vk::CommandBuffer command_buffer) {
std::unique_ptr<Surface> SurfaceProducerVK::AcquireSurface() {
auto fence_wait_res = create_info_.device.waitForFences({*in_flight_fence_},
VK_TRUE, UINT64_MAX);
if (fence_wait_res != vk::Result::eSuccess) {
@ -52,17 +52,19 @@ std::unique_ptr<Surface> SurfaceProducerVK::AcquireSurface(
auto acuire_image_res = create_info_.device.acquireNextImageKHR(
create_info_.swapchain->GetSwapchain(), UINT64_MAX,
*image_available_semaphore_, {}, &image_index);
if (acuire_image_res != vk::Result::eSuccess) {
if (acuire_image_res != vk::Result::eSuccess &&
acuire_image_res != vk::Result::eSuboptimalKHR) {
VALIDATION_LOG << "Failed to acquire next image: "
<< vk::to_string(acuire_image_res);
return nullptr;
}
SurfaceVK::SwapCallback swap_callback = [this, image_index,
command_buffer]() {
if (!Submit(command_buffer)) {
return false;
}
if (acuire_image_res == vk::Result::eSuboptimalKHR) {
VALIDATION_LOG << "Suboptimal image acquired.";
}
SurfaceVK::SwapCallback swap_callback = [this, image_index]() {
return Present(image_index);
};

View File

@ -31,15 +31,15 @@ class SurfaceProducerVK {
~SurfaceProducerVK();
std::unique_ptr<Surface> AcquireSurface(vk::CommandBuffer command_buffer);
std::unique_ptr<Surface> AcquireSurface();
bool Submit(vk::CommandBuffer buffer);
private:
std::weak_ptr<Context> context_;
bool SetupSyncObjects();
bool Submit(vk::CommandBuffer buffer);
bool Present(uint32_t image_index);
const SurfaceProducerCreateInfoVK create_info_;

View File

@ -5,6 +5,7 @@
#include "impeller/renderer/backend/vulkan/surface_vk.h"
#include "impeller/renderer/backend/vulkan/texture_vk.h"
#include "impeller/renderer/surface.h"
namespace impeller {
std::unique_ptr<SurfaceVK> SurfaceVK::WrapSwapchainImage(
@ -68,7 +69,8 @@ std::unique_ptr<SurfaceVK> SurfaceVK::WrapSwapchainImage(
SurfaceVK::SurfaceVK(RenderTarget target,
SwapchainImageVK* swapchain_image,
SwapCallback swap_callback) {}
SwapCallback swap_callback)
: Surface(target) {}
SurfaceVK::~SurfaceVK() = default;

View File

@ -48,12 +48,12 @@ class TextureVK final : public Texture, public BackendCast<TextureVK, Texture> {
bool IsWrapped() const;
vk::Image GetImage() const;
private:
ContextVK* context_;
std::unique_ptr<TextureInfoVK> texture_info_;
vk::Image GetImage() const;
// |Texture|
void SetLabel(std::string_view label) override;