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