diff --git a/impeller/playground/backend/vulkan/playground_impl_vk.cc b/impeller/playground/backend/vulkan/playground_impl_vk.cc index f154f5326fd23..4334149260e51 100644 --- a/impeller/playground/backend/vulkan/playground_impl_vk.cc +++ b/impeller/playground/backend/vulkan/playground_impl_vk.cc @@ -107,7 +107,8 @@ PlaygroundImpl::WindowHandle PlaygroundImplVK::GetWindowHandle() const { // |PlaygroundImpl| std::unique_ptr PlaygroundImplVK::AcquireSurfaceFrame( std::shared_ptr context) { - FML_UNREACHABLE(); + ContextVK* context_vk = reinterpret_cast(context_.get()); + return context_vk->AcquireSurface(); } } // namespace impeller diff --git a/impeller/renderer/backend/vulkan/command_buffer_vk.cc b/impeller/renderer/backend/vulkan/command_buffer_vk.cc index e560ba9e652c8..c06701d515f18 100644 --- a/impeller/renderer/backend/vulkan/command_buffer_vk.cc +++ b/impeller/renderer/backend/vulkan/command_buffer_vk.cc @@ -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 context) - : CommandBuffer(std::move(context)) {} +std::shared_ptr CommandBufferVK::Create( + std::weak_ptr 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(context, device, surface_producer, + std::move(cmd)); +} + +CommandBufferVK::CommandBufferVK(std::weak_ptr 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(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 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 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( + context_, std::move(target), *command_buffer_, + std::move(render_pass_create_res.value)); } std::shared_ptr CommandBufferVK::OnCreateBlitPass() const { diff --git a/impeller/renderer/backend/vulkan/command_buffer_vk.h b/impeller/renderer/backend/vulkan/command_buffer_vk.h index a4525382fc9a5..ee5cb0bfec2b0 100644 --- a/impeller/renderer/backend/vulkan/command_buffer_vk.h +++ b/impeller/renderer/backend/vulkan/command_buffer_vk.h @@ -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 Create( + std::weak_ptr context, + vk::Device device, + vk::CommandPool command_pool, + SurfaceProducerVK* surface_producer); + + CommandBufferVK(std::weak_ptr 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 context); + vk::Device device_; + vk::UniqueCommandBuffer command_buffer_; + SurfaceProducerVK* surface_producer_; + bool is_valid_ = false; // |CommandBuffer| void SetLabel(const std::string& label) const override; diff --git a/impeller/renderer/backend/vulkan/command_pool_vk.cc b/impeller/renderer/backend/vulkan/command_pool_vk.cc index 58fb3f45c4ed2..065582402419b 100644 --- a/impeller/renderer/backend/vulkan/command_pool_vk.cc +++ b/impeller/renderer/backend/vulkan/command_pool_vk.cc @@ -21,6 +21,10 @@ std::unique_ptr CommandPoolVK::Create(vk::Device device, return std::make_unique(std::move(res.value)); } +vk::CommandPool CommandPoolVK::Get() const { + return *command_pool_; +} + CommandPoolVK::CommandPoolVK(vk::UniqueCommandPool command_pool) : command_pool_(std::move(command_pool)) {} diff --git a/impeller/renderer/backend/vulkan/command_pool_vk.h b/impeller/renderer/backend/vulkan/command_pool_vk.h index 3e57556fc53fd..034813ed49acf 100644 --- a/impeller/renderer/backend/vulkan/command_pool_vk.h +++ b/impeller/renderer/backend/vulkan/command_pool_vk.h @@ -18,6 +18,8 @@ class CommandPoolVK { ~CommandPoolVK(); + vk::CommandPool Get() const; + private: vk::UniqueCommandPool command_pool_; diff --git a/impeller/renderer/backend/vulkan/context_vk.cc b/impeller/renderer/backend/vulkan/context_vk.cc index 6c3c0b3e0eac9..e5ff5257373af 100644 --- a/impeller/renderer/backend/vulkan/context_vk.cc +++ b/impeller/renderer/backend/vulkan/context_vk.cc @@ -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 ContextVK::GetWorkQueue() const { } std::shared_ptr 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 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, { diff --git a/impeller/renderer/backend/vulkan/context_vk.h b/impeller/renderer/backend/vulkan/context_vk.h index 1741c6782743f..f8a4ce6211318 100644 --- a/impeller/renderer/backend/vulkan/context_vk.h +++ b/impeller/renderer/backend/vulkan/context_vk.h @@ -61,6 +61,8 @@ class ContextVK final : public Context, public BackendCast { void SetupSwapchain(vk::UniqueSurfaceKHR surface); + std::unique_ptr AcquireSurface(); + private: std::shared_ptr worker_task_runner_; vk::UniqueInstance instance_; diff --git a/impeller/renderer/backend/vulkan/pipeline_library_vk.cc b/impeller/renderer/backend/vulkan/pipeline_library_vk.cc index f89d22bfb6884..931181c23b373 100644 --- a/impeller/renderer/backend/vulkan/pipeline_library_vk.cc +++ b/impeller/renderer/backend/vulkan/pipeline_library_vk.cc @@ -344,8 +344,13 @@ std::unique_ptr 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_); diff --git a/impeller/renderer/backend/vulkan/render_pass_vk.cc b/impeller/renderer/backend/vulkan/render_pass_vk.cc index 2db32a77b01ab..70da066fdbb40 100644 --- a/impeller/renderer/backend/vulkan/render_pass_vk.cc +++ b/impeller/renderer/backend/vulkan/render_pass_vk.cc @@ -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 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 diff --git a/impeller/renderer/backend/vulkan/render_pass_vk.h b/impeller/renderer/backend/vulkan/render_pass_vk.h index 42cec8935329d..595765c7902d8 100644 --- a/impeller/renderer/backend/vulkan/render_pass_vk.h +++ b/impeller/renderer/backend/vulkan/render_pass_vk.h @@ -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 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; diff --git a/impeller/renderer/backend/vulkan/surface_producer_vk.cc b/impeller/renderer/backend/vulkan/surface_producer_vk.cc index d0fad4b56ca94..da23dad77df1e 100644 --- a/impeller/renderer/backend/vulkan/surface_producer_vk.cc +++ b/impeller/renderer/backend/vulkan/surface_producer_vk.cc @@ -7,6 +7,7 @@ #include #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 SurfaceProducerVK::AcquireSurface( - vk::CommandBuffer command_buffer) { +std::unique_ptr 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 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); }; diff --git a/impeller/renderer/backend/vulkan/surface_producer_vk.h b/impeller/renderer/backend/vulkan/surface_producer_vk.h index 6d3ed2e116b97..debd9236f3d2f 100644 --- a/impeller/renderer/backend/vulkan/surface_producer_vk.h +++ b/impeller/renderer/backend/vulkan/surface_producer_vk.h @@ -31,15 +31,15 @@ class SurfaceProducerVK { ~SurfaceProducerVK(); - std::unique_ptr AcquireSurface(vk::CommandBuffer command_buffer); + std::unique_ptr AcquireSurface(); + + bool Submit(vk::CommandBuffer buffer); private: std::weak_ptr context_; bool SetupSyncObjects(); - bool Submit(vk::CommandBuffer buffer); - bool Present(uint32_t image_index); const SurfaceProducerCreateInfoVK create_info_; diff --git a/impeller/renderer/backend/vulkan/surface_vk.cc b/impeller/renderer/backend/vulkan/surface_vk.cc index f87a36aeb9ed8..9319d814bbeb5 100644 --- a/impeller/renderer/backend/vulkan/surface_vk.cc +++ b/impeller/renderer/backend/vulkan/surface_vk.cc @@ -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::WrapSwapchainImage( @@ -68,7 +69,8 @@ std::unique_ptr SurfaceVK::WrapSwapchainImage( SurfaceVK::SurfaceVK(RenderTarget target, SwapchainImageVK* swapchain_image, - SwapCallback swap_callback) {} + SwapCallback swap_callback) + : Surface(target) {} SurfaceVK::~SurfaceVK() = default; diff --git a/impeller/renderer/backend/vulkan/texture_vk.h b/impeller/renderer/backend/vulkan/texture_vk.h index e3e667c19564b..832133c972b71 100644 --- a/impeller/renderer/backend/vulkan/texture_vk.h +++ b/impeller/renderer/backend/vulkan/texture_vk.h @@ -48,12 +48,12 @@ class TextureVK final : public Texture, public BackendCast { bool IsWrapped() const; + vk::Image GetImage() const; + private: ContextVK* context_; std::unique_ptr texture_info_; - vk::Image GetImage() const; - // |Texture| void SetLabel(std::string_view label) override;