Flutter Engine
 
Loading...
Searching...
No Matches
gpu_surface_vulkan_impeller.cc
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
6
7#include <memory>
8
11#include "fml/trace_event.h"
22
23namespace flutter {
24
26 public:
27 explicit WrappedTextureSourceVK(impeller::vk::Image image,
28 impeller::vk::ImageView image_view,
30 : TextureSourceVK(desc), image_(image), image_view_(image_view) {}
31
33
34 private:
35 impeller::vk::Image GetImage() const override { return image_; }
36
37 impeller::vk::ImageView GetImageView() const override { return image_view_; }
38
39 impeller::vk::ImageView GetRenderTargetView() const override {
40 return image_view_;
41 }
42
43 bool IsSwapchainImage() const override { return true; }
44
45 impeller::vk::Image image_;
46 impeller::vk::ImageView image_view_;
47};
48
51 std::shared_ptr<impeller::Context> context)
52 : delegate_(delegate) {
53 if (!context || !context->IsValid()) {
54 return;
55 }
56
57 auto aiks_context = std::make_shared<impeller::AiksContext>(
59 if (!aiks_context->IsValid()) {
60 return;
61 }
62
63 impeller_context_ = std::move(context);
64 aiks_context_ = std::move(aiks_context);
65 is_valid_ = !!aiks_context_;
66}
67
68// |Surface|
70
71// |Surface|
73 return is_valid_;
74}
75
76// |Surface|
77std::unique_ptr<SurfaceFrame> GPUSurfaceVulkanImpeller::AcquireFrame(
78 const DlISize& size) {
79 if (!IsValid()) {
80 FML_LOG(ERROR) << "Vulkan surface was invalid.";
81 return nullptr;
82 }
83
84 if (size.IsEmpty()) {
85 FML_LOG(ERROR) << "Vulkan surface was asked for an empty frame.";
86 return nullptr;
87 }
88
89 if (delegate_ == nullptr) {
90 auto& context_vk = impeller::SurfaceContextVK::Cast(*impeller_context_);
91 std::unique_ptr<impeller::Surface> surface =
92 context_vk.AcquireNextSurface();
93
94 if (!surface) {
95 FML_LOG(ERROR) << "No surface available.";
96 return nullptr;
97 }
98
99 impeller::RenderTarget render_target = surface->GetRenderTarget();
100 auto cull_rect =
102
103 SurfaceFrame::EncodeCallback encode_callback = [aiks_context =
104 aiks_context_, //
105 render_target,
106 cull_rect //
107 ](SurfaceFrame& surface_frame, DlCanvas* canvas) mutable -> bool {
108 if (!aiks_context) {
109 return false;
110 }
111
112 auto display_list = surface_frame.BuildDisplayList();
113 if (!display_list) {
114 FML_LOG(ERROR) << "Could not build display list for surface frame.";
115 return false;
116 }
117
119 aiks_context->GetContentContext(), //
120 render_target, //
121 display_list, //
122 cull_rect, //
123 /*reset_host_buffer=*/surface_frame.submit_info().frame_boundary //
124 );
125 };
126
127 return std::make_unique<SurfaceFrame>(
128 nullptr, // surface
129 SurfaceFrame::FramebufferInfo{}, // framebuffer info
130 encode_callback, // encode callback
131 fml::MakeCopyable([surface = std::move(surface)](const SurfaceFrame&) {
132 return surface->Present();
133 }), // submit callback
134 size, // frame size
135 nullptr, // context result
136 true // display list fallback
137 );
138 } else {
139 FlutterVulkanImage flutter_image = delegate_->AcquireImage(size);
140 if (!flutter_image.image) {
141 FML_LOG(ERROR) << "Invalid VkImage given by the embedder.";
142 return nullptr;
143 }
144 impeller::vk::Format vk_format =
145 static_cast<impeller::vk::Format>(flutter_image.format);
146 std::optional<impeller::PixelFormat> format =
148 if (!format.has_value()) {
149 FML_LOG(ERROR) << "Unsupported pixel format: "
150 << impeller::vk::to_string(vk_format);
151 return nullptr;
152 }
153
154 impeller::vk::Image vk_image =
155 impeller::vk::Image(reinterpret_cast<VkImage>(flutter_image.image));
156
158 desc.format = format.value();
159 desc.size = impeller::ISize{size.width, size.height};
161 desc.mip_count = 1;
164
165 impeller::ContextVK& context_vk =
166 impeller::ContextVK::Cast(*impeller_context_);
167
168 impeller::vk::ImageViewCreateInfo view_info = {};
169 view_info.viewType = impeller::vk::ImageViewType::e2D;
170 view_info.format = ToVKImageFormat(desc.format);
171 view_info.subresourceRange.aspectMask =
172 impeller::vk::ImageAspectFlagBits::eColor;
173 view_info.subresourceRange.baseMipLevel = 0u;
174 view_info.subresourceRange.baseArrayLayer = 0u;
175 view_info.subresourceRange.levelCount = 1;
176 view_info.subresourceRange.layerCount = 1;
177 view_info.image = vk_image;
178
179 auto [result, image_view] =
180 context_vk.GetDevice().createImageView(view_info);
181 if (result != impeller::vk::Result::eSuccess) {
182 FML_LOG(ERROR) << "Failed to create image view for provided image: "
183 << impeller::vk::to_string(result);
184 return nullptr;
185 }
186
187 if (transients_ == nullptr) {
188 transients_ = std::make_shared<impeller::SwapchainTransientsVK>(
189 impeller_context_, desc,
190 /*enable_msaa=*/true);
191 }
192
193 auto wrapped_onscreen =
194 std::make_shared<WrappedTextureSourceVK>(vk_image, image_view, desc);
196 transients_, wrapped_onscreen, [&]() -> bool { return true; });
197 impeller::RenderTarget render_target = surface->GetRenderTarget();
198 auto cull_rect =
199 impeller::Rect::MakeSize(render_target.GetRenderTargetSize());
200
201 SurfaceFrame::EncodeCallback encode_callback = [aiks_context =
202 aiks_context_, //
203 render_target,
204 cull_rect //
205 ](SurfaceFrame& surface_frame, DlCanvas* canvas) mutable -> bool {
206 if (!aiks_context) {
207 return false;
208 }
209
210 auto display_list = surface_frame.BuildDisplayList();
211 if (!display_list) {
212 FML_LOG(ERROR) << "Could not build display list for surface frame.";
213 return false;
214 }
215
216 return impeller::RenderToTarget(aiks_context->GetContentContext(), //
217 render_target, //
218 display_list, //
219 cull_rect, //
220 /*reset_host_buffer=*/true //
221 );
222 };
223
224 SurfaceFrame::SubmitCallback submit_callback =
225 [image = flutter_image, delegate = delegate_,
226 impeller_context = impeller_context_,
227 wrapped_onscreen](const SurfaceFrame&) -> bool {
228 TRACE_EVENT0("flutter", "GPUSurfaceVulkan::PresentImage");
229
230 {
231 const auto& context = impeller::ContextVK::Cast(*impeller_context);
232
233 //----------------------------------------------------------------------------
234 /// Transition the image to color-attachment-optimal.
235 ///
236 auto cmd_buffer = context.CreateCommandBuffer();
237
238 auto vk_final_cmd_buffer =
240 {
241 impeller::BarrierVK barrier;
242 barrier.new_layout =
243 impeller::vk::ImageLayout::eColorAttachmentOptimal;
244 barrier.cmd_buffer = vk_final_cmd_buffer;
245 barrier.src_access =
246 impeller::vk::AccessFlagBits::eColorAttachmentWrite;
247 barrier.src_stage =
248 impeller::vk::PipelineStageFlagBits::eColorAttachmentOutput;
249 barrier.dst_access = {};
250 barrier.dst_stage =
251 impeller::vk::PipelineStageFlagBits::eBottomOfPipe;
252
253 if (!wrapped_onscreen->SetLayout(barrier).ok()) {
254 return false;
255 }
256 }
257 if (!context.GetCommandQueue()->Submit({cmd_buffer}).ok()) {
258 return false;
259 }
260 }
261
262 return delegate->PresentImage(reinterpret_cast<VkImage>(image.image),
263 static_cast<VkFormat>(image.format));
264 };
265
266 SurfaceFrame::FramebufferInfo framebuffer_info{.supports_readback = true};
267
268 return std::make_unique<SurfaceFrame>(nullptr, // surface
269 framebuffer_info, // framebuffer info
270 encode_callback, // encode callback
271 submit_callback,
272 size, // frame size
273 nullptr, // context result
274 true // display list fallback
275 );
276 }
277}
278
279// |Surface|
280DlMatrix GPUSurfaceVulkanImpeller::GetRootTransformation() const {
281 // This backend does not currently support root surface transformations. Just
282 // return identity.
283 return {};
284}
285
286// |Surface|
287GrDirectContext* GPUSurfaceVulkanImpeller::GetContext() {
288 // Impeller != Skia.
289 return nullptr;
290}
291
292// |Surface|
293std::unique_ptr<GLContextResult>
294GPUSurfaceVulkanImpeller::MakeRenderContextCurrent() {
295 // This backend has no such concept.
296 return std::make_unique<GLContextDefaultResult>(true);
297}
298
299// |Surface|
300bool GPUSurfaceVulkanImpeller::EnableRasterCache() const {
301 return false;
302}
303
304// |Surface|
305std::shared_ptr<impeller::AiksContext>
306GPUSurfaceVulkanImpeller::GetAiksContext() const {
307 return aiks_context_;
308}
309
310} // namespace flutter
Interface implemented by all platform surfaces that can present a Vulkan backing store to the "screen...
virtual FlutterVulkanImage AcquireImage(const DlISize &size)=0
Called by the engine to fetch a VkImage for writing the next frame.
GPUSurfaceVulkanImpeller(GPUSurfaceVulkanDelegate *delegate, std::shared_ptr< impeller::Context > context)
std::function< bool(SurfaceFrame &surface_frame, DlCanvas *canvas)> EncodeCallback
std::function< bool(SurfaceFrame &surface_frame)> SubmitCallback
WrappedTextureSourceVK(impeller::vk::Image image, impeller::vk::ImageView image_view, impeller::TextureDescriptor desc)
static SurfaceContextVK & Cast(Context &base)
vk::CommandBuffer GetCommandBuffer() const
Retrieve the native command buffer from this object.
const vk::Device & GetDevice() const
ISize GetRenderTargetSize() const
static std::unique_ptr< SurfaceVK > WrapSwapchainImage(const std::shared_ptr< SwapchainTransientsVK > &transients, const std::shared_ptr< TextureSourceVK > &swapchain_image, SwapCallback swap_callback)
Wrap the swapchain image in a Surface, which provides the additional configuration required for usage...
Definition surface_vk.cc:13
Abstract base class that represents a vkImage and an vkImageView.
static std::shared_ptr< TypographerContext > Make()
FlutterVulkanImage * image
MockDelegate delegate_
VkSurfaceKHR surface
Definition main.cc:65
uint32_t uint32_t * format
#define FML_LOG(severity)
Definition logging.h:101
impeller::Matrix DlMatrix
it will be possible to load the file into Perfetto s trace viewer use test Running tests that layout and measure text will not yield consistent results across various platforms Enabling this option will make font resolution default to the Ahem test font on all disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
internal::CopyableLambda< T > MakeCopyable(T lambda)
constexpr std::optional< PixelFormat > VkFormatToImpellerFormat(vk::Format format)
Definition formats_vk.h:20
constexpr vk::Format ToVKImageFormat(PixelFormat format)
Definition formats_vk.h:146
bool RenderToTarget(ContentContext &context, RenderTarget render_target, const sk_sp< flutter::DisplayList > &display_list, Rect cull_rect, bool reset_host_buffer, bool is_onscreen)
Render the provided display list to the render target.
flutter::DlCanvas DlCanvas
FlutterVulkanImageHandle image
Definition embedder.h:931
uint32_t format
The VkFormat of the image (for example: VK_FORMAT_R8G8B8A8_UNORM).
Definition embedder.h:933
Defines an operations and memory access barrier on a resource.
Definition barrier_vk.h:27
vk::CommandBuffer cmd_buffer
Definition barrier_vk.h:28
vk::AccessFlags src_access
Definition barrier_vk.h:39
vk::PipelineStageFlags dst_stage
Definition barrier_vk.h:44
vk::ImageLayout new_layout
Definition barrier_vk.h:29
vk::PipelineStageFlags src_stage
Definition barrier_vk.h:34
vk::AccessFlags dst_access
Definition barrier_vk.h:49
static constexpr TRect MakeSize(const TSize< U > &size)
Definition rect.h:150
Type width
Definition size.h:28
A lightweight object that describes the attributes of a texture that can then used an allocator to cr...
#define TRACE_EVENT0(category_group, name)