mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
[Impeller] [vulkan] Wire-up command buffer and other bits (flutter/engine#35380)
This commit is contained in:
parent
de7ef0efad
commit
6efcd51c23
@ -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
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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)) {}
|
||||
|
||||
|
||||
@ -18,6 +18,8 @@ class CommandPoolVK {
|
||||
|
||||
~CommandPoolVK();
|
||||
|
||||
vk::CommandPool Get() const;
|
||||
|
||||
private:
|
||||
vk::UniqueCommandPool command_pool_;
|
||||
|
||||
|
||||
@ -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, {
|
||||
|
||||
@ -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_;
|
||||
|
||||
@ -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_);
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
};
|
||||
|
||||
|
||||
@ -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_;
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user