Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
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::UniqueImageView image_view,
30 : TextureSourceVK(desc),
31 image_(image),
32 image_view_(std::move(image_view)) {}
33
34 ~WrappedTextureSourceVK() override = default;
35
36 private:
37 impeller::vk::Image GetImage() const override { return image_; }
38
39 impeller::vk::ImageView GetImageView() const override {
40 return image_view_.get();
41 }
42
43 impeller::vk::ImageView GetRenderTargetView() const override {
44 return image_view_.get();
45 }
46
47 bool IsSwapchainImage() const override { return true; }
48
49 impeller::vk::Image image_;
50 impeller::vk::UniqueImageView image_view_;
51};
52
55 std::shared_ptr<impeller::Context> context)
56 : delegate_(delegate) {
57 if (!context || !context->IsValid()) {
58 return;
59 }
60
61 auto aiks_context = std::make_shared<impeller::AiksContext>(
63 if (!aiks_context->IsValid()) {
64 return;
65 }
66
67 impeller_context_ = std::move(context);
68 aiks_context_ = std::move(aiks_context);
69 is_valid_ = !!aiks_context_;
70}
71
72// |Surface|
74
75// |Surface|
77 return is_valid_;
78}
79
80// |Surface|
81std::unique_ptr<SurfaceFrame> GPUSurfaceVulkanImpeller::AcquireFrame(
82 const DlISize& size) {
83 if (!IsValid()) {
84 FML_LOG(ERROR) << "Vulkan surface was invalid.";
85 return nullptr;
86 }
87
88 if (size.IsEmpty()) {
89 FML_LOG(ERROR) << "Vulkan surface was asked for an empty frame.";
90 return nullptr;
91 }
92
93 if (delegate_ == nullptr) {
94 auto& context_vk = impeller::SurfaceContextVK::Cast(*impeller_context_);
95 std::unique_ptr<impeller::Surface> surface =
96 context_vk.AcquireNextSurface();
97
98 if (!surface) {
99 FML_LOG(ERROR) << "No surface available.";
100 return nullptr;
101 }
102
103 impeller::RenderTarget render_target = surface->GetRenderTarget();
104 auto cull_rect =
106
107 SurfaceFrame::EncodeCallback encode_callback = [aiks_context =
108 aiks_context_, //
109 render_target,
110 cull_rect //
111 ](SurfaceFrame& surface_frame, DlCanvas* canvas) mutable -> bool {
112 if (!aiks_context) {
113 return false;
114 }
115
116 auto display_list = surface_frame.BuildDisplayList();
117 if (!display_list) {
118 FML_LOG(ERROR) << "Could not build display list for surface frame.";
119 return false;
120 }
121
123 aiks_context->GetContentContext(), //
124 render_target, //
125 display_list, //
126 cull_rect, //
127 /*reset_host_buffer=*/surface_frame.submit_info().frame_boundary //
128 );
129 };
130
131 return std::make_unique<SurfaceFrame>(
132 nullptr, // surface
133 SurfaceFrame::FramebufferInfo{}, // framebuffer info
134 encode_callback, // encode callback
135 fml::MakeCopyable([surface = std::move(surface)](const SurfaceFrame&) {
136 return surface->Present();
137 }), // submit callback
138 size, // frame size
139 nullptr, // context result
140 true // display list fallback
141 );
142 } else {
143 FlutterVulkanImage flutter_image = delegate_->AcquireImage(size);
144 if (!flutter_image.image) {
145 FML_LOG(ERROR) << "Invalid VkImage given by the embedder.";
146 return nullptr;
147 }
148 impeller::vk::Format vk_format =
149 static_cast<impeller::vk::Format>(flutter_image.format);
150 std::optional<impeller::PixelFormat> format =
152 if (!format.has_value()) {
153 FML_LOG(ERROR) << "Unsupported pixel format: "
154 << impeller::vk::to_string(vk_format);
155 return nullptr;
156 }
157
158 impeller::ContextVK& context_vk =
159 impeller::ContextVK::Cast(*impeller_context_);
160
162
163 impeller::vk::Image vk_image =
164 impeller::vk::Image(reinterpret_cast<VkImage>(flutter_image.image));
165
167 desc.format = format.value();
168 desc.size = impeller::ISize{size.width, size.height};
170 desc.mip_count = 1;
173
174 impeller::vk::ImageViewCreateInfo view_info = {};
175 view_info.viewType = impeller::vk::ImageViewType::e2D;
176 view_info.format = ToVKImageFormat(desc.format);
177 view_info.subresourceRange.aspectMask =
178 impeller::vk::ImageAspectFlagBits::eColor;
179 view_info.subresourceRange.baseMipLevel = 0u;
180 view_info.subresourceRange.baseArrayLayer = 0u;
181 view_info.subresourceRange.levelCount = 1;
182 view_info.subresourceRange.layerCount = 1;
183 view_info.image = vk_image;
184
185 auto [result, image_view] =
186 context_vk.GetDevice().createImageViewUnique(view_info);
187 if (result != impeller::vk::Result::eSuccess) {
188 FML_LOG(ERROR) << "Failed to create image view for provided image: "
189 << impeller::vk::to_string(result);
190 return nullptr;
191 }
192
193 impeller::ISize frame_size{size.width, size.height};
194 if (transients_ == nullptr || transients_size_ != frame_size) {
195 transients_ = std::make_shared<impeller::SwapchainTransientsVK>(
196 impeller_context_, desc,
197 /*enable_msaa=*/true);
198 transients_size_ = frame_size;
199 }
200
201 auto wrapped_onscreen = std::make_shared<WrappedTextureSourceVK>(
202 vk_image, std::move(image_view), desc);
204 transients_, wrapped_onscreen, [&]() -> bool { return true; });
205 impeller::RenderTarget render_target = surface->GetRenderTarget();
206 auto cull_rect =
207 impeller::Rect::MakeSize(render_target.GetRenderTargetSize());
208
209 SurfaceFrame::EncodeCallback encode_callback = [aiks_context =
210 aiks_context_, //
211 render_target,
212 cull_rect //
213 ](SurfaceFrame& surface_frame, DlCanvas* canvas) mutable -> bool {
214 if (!aiks_context) {
215 return false;
216 }
217
218 auto display_list = surface_frame.BuildDisplayList();
219 if (!display_list) {
220 FML_LOG(ERROR) << "Could not build display list for surface frame.";
221 return false;
222 }
223
224 return impeller::RenderToTarget(aiks_context->GetContentContext(), //
225 render_target, //
226 display_list, //
227 cull_rect, //
228 /*reset_host_buffer=*/true //
229 );
230 };
231
232 SurfaceFrame::SubmitCallback submit_callback =
233 [image = flutter_image, delegate = delegate_,
234 impeller_context = impeller_context_,
235 wrapped_onscreen](const SurfaceFrame&) -> bool {
236 TRACE_EVENT0("flutter", "GPUSurfaceVulkan::PresentImage");
237
238 {
239 const auto& context = impeller::ContextVK::Cast(*impeller_context);
240
241 //----------------------------------------------------------------------------
242 /// Transition the image to color-attachment-optimal.
243 ///
244 auto cmd_buffer = context.CreateCommandBuffer();
245
246 auto vk_final_cmd_buffer =
248 {
249 impeller::BarrierVK barrier;
250 barrier.new_layout =
251 impeller::vk::ImageLayout::eColorAttachmentOptimal;
252 barrier.cmd_buffer = vk_final_cmd_buffer;
253 barrier.src_access =
254 impeller::vk::AccessFlagBits::eColorAttachmentWrite;
255 barrier.src_stage =
256 impeller::vk::PipelineStageFlagBits::eColorAttachmentOutput;
257 barrier.dst_access = {};
258 barrier.dst_stage =
259 impeller::vk::PipelineStageFlagBits::eBottomOfPipe;
260
261 if (!wrapped_onscreen->SetLayout(barrier).ok()) {
262 return false;
263 }
264 }
265 if (!context.GetCommandQueue()->Submit({cmd_buffer}).ok()) {
266 return false;
267 }
268 }
269
270 return delegate->PresentImage(reinterpret_cast<VkImage>(image.image),
271 static_cast<VkFormat>(image.format));
272 };
273
274 SurfaceFrame::FramebufferInfo framebuffer_info{.supports_readback = true};
275
276 return std::make_unique<SurfaceFrame>(nullptr, // surface
277 framebuffer_info, // framebuffer info
278 encode_callback, // encode callback
279 submit_callback,
280 size, // frame size
281 nullptr, // context result
282 true // display list fallback
283 );
284 }
285}
286
287// |Surface|
288DlMatrix GPUSurfaceVulkanImpeller::GetRootTransformation() const {
289 // This backend does not currently support root surface transformations. Just
290 // return identity.
291 return {};
292}
293
294// |Surface|
295GrDirectContext* GPUSurfaceVulkanImpeller::GetContext() {
296 // Impeller != Skia.
297 return nullptr;
298}
299
300// |Surface|
301std::unique_ptr<GLContextResult>
302GPUSurfaceVulkanImpeller::MakeRenderContextCurrent() {
303 // This backend has no such concept.
304 return std::make_unique<GLContextDefaultResult>(true);
305}
306
307// |Surface|
308bool GPUSurfaceVulkanImpeller::EnableRasterCache() const {
309 return false;
310}
311
312// |Surface|
313std::shared_ptr<impeller::AiksContext>
314GPUSurfaceVulkanImpeller::GetAiksContext() const {
315 return aiks_context_;
316}
317
318} // 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::UniqueImageView image_view, impeller::TextureDescriptor desc)
~WrappedTextureSourceVK() override=default
static SurfaceContextVK & Cast(Context &base)
vk::CommandBuffer GetCommandBuffer() const
Retrieve the native command buffer from this object.
const vk::Device & GetDevice() const
void DisposeThreadLocalCachedResources() override
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.
Definition ref_ptr.h:261
flutter::DlCanvas DlCanvas
FlutterVulkanImageHandle image
Definition embedder.h:938
uint32_t format
The VkFormat of the image (for example: VK_FORMAT_R8G8B8A8_UNORM).
Definition embedder.h:940
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)