7#include <lib/async/cpp/task.h>
8#include <lib/async/default.h>
18#include "third_party/skia/include/core/SkSurface.h"
19#include "third_party/skia/include/gpu/ganesh/GrBackendSemaphore.h"
20#include "third_party/skia/include/gpu/ganesh/GrBackendSurface.h"
21#include "third_party/skia/include/gpu/ganesh/SkSurfaceGanesh.h"
22#include "third_party/skia/include/gpu/ganesh/vk/GrVkBackendSurface.h"
23#include "third_party/skia/include/gpu/ganesh/vk/GrVkDirectContext.h"
24#include "third_party/skia/include/gpu/ganesh/vk/GrVkTypes.h"
25#include "third_party/skia/include/gpu/vk/VulkanBackendContext.h"
26#include "third_party/skia/include/gpu/vk/VulkanExtensions.h"
41constexpr size_t kGrCacheMaxByteSize = 1024 * 600 * 12 * 4;
46 valid_ = Initialize();
49 FML_LOG(FATAL) <<
"VulkanSurfaceProducer: Initialization failed";
57 vk_->QueueWaitIdle(logical_device_->GetQueueHandle()));
62bool VulkanSurfaceProducer::Initialize() {
63 vk_ = fml::MakeRefCounted<vulkan::VulkanProcTable>();
65 std::vector<std::string> extensions = {
66 VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME,
72 application_ = std::make_unique<vulkan::VulkanApplication>(
73 *vk_,
"FlutterRunner", std::move(extensions), VK_MAKE_VERSION(1, 0, 0),
74 VK_MAKE_VERSION(1, 1, 0),
true );
79 FML_LOG(ERROR) <<
"VulkanSurfaceProducer: Instance proc addresses have not "
86 logical_device_ = application_->AcquireFirstCompatibleLogicalDevice();
88 if (logical_device_ ==
nullptr || !logical_device_->IsValid() ||
93 <<
"VulkanSurfaceProducer: Device proc addresses have not been set up.";
99 <<
"VulkanSurfaceProducer: Failed to acquire mandatory proc addresses.";
104 FML_LOG(ERROR) <<
"VulkanSurfaceProducer: VulkanProcTable invalid";
110 if (getProc ==
nullptr) {
111 FML_LOG(ERROR) <<
"VulkanSurfaceProducer: Failed to create skia getProc.";
115 VkPhysicalDeviceFeatures features;
116 if (!logical_device_->GetPhysicalDeviceFeatures(&features)) {
118 <<
"VulkanSurfaceProducer: Failed to get physical device features.";
124 application_->GetAPIVersion(), application_->GetInstance(),
125 logical_device_->GetPhysicalDeviceHandle(), logical_device_->GetHandle(),
128 skgpu::VulkanBackendContext backend_context;
129 backend_context.fInstance = application_->GetInstance();
130 backend_context.fPhysicalDevice = logical_device_->GetPhysicalDeviceHandle();
131 backend_context.fDevice = logical_device_->GetHandle();
132 backend_context.fQueue = logical_device_->GetQueueHandle();
133 backend_context.fGraphicsQueueIndex =
134 logical_device_->GetGraphicsQueueIndex();
135 backend_context.fMaxAPIVersion = application_->GetAPIVersion();
136 backend_context.fDeviceFeatures = &features;
137 backend_context.fGetProc = std::move(getProc);
138 backend_context.fMemoryAllocator = memory_allocator_;
142 const char* device_extensions[] = {
143 VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME,
145 const int device_extensions_count =
146 sizeof(device_extensions) /
sizeof(device_extensions[0]);
147 skgpu::VulkanExtensions vk_extensions;
148 vk_extensions.init(backend_context.fGetProc, backend_context.fInstance,
149 backend_context.fPhysicalDevice, 0,
nullptr,
150 device_extensions_count, device_extensions);
151 backend_context.fVkExtensions = &vk_extensions;
152 GrContextOptions options;
153 options.fReduceOpsTaskSplitting = GrContextOptions::Enable::kNo;
155 context_ = GrDirectContexts::MakeVulkan(backend_context, options);
157 if (context_ ==
nullptr) {
159 <<
"VulkanSurfaceProducer: Failed to create GrDirectContext.";
164 context_->setResourceCacheLimit(kGrCacheMaxByteSize);
166 surface_pool_ = std::make_unique<VulkanSurfacePool>(*
this, context_);
172 std::vector<std::unique_ptr<SurfaceProducerSurface>> surfaces) {
173 TRACE_EVENT0(
"flutter",
"VulkanSurfaceProducer::SubmitSurfaces");
177 TRACE_EVENT0(
"flutter",
"GrDirectContext::flushAndSignalSemaphores");
178 context_->flushAndSubmit();
181 if (!TransitionSurfacesToExternal(surfaces))
182 FML_LOG(ERROR) <<
"TransitionSurfacesToExternal failed";
185 for (
auto&
surface : surfaces) {
186 SubmitSurface(std::move(
surface));
190 surface_pool_->AgeAndCollectOldBuffers();
194 constexpr auto kShouldShrinkThreshold = zx::msec(10 * 16.67);
195 async::PostDelayedTask(
196 async_get_default_dispatcher(),
197 [
self = weak_factory_.GetWeakPtr(), kShouldShrinkThreshold] {
201 auto time_since_last_produce =
202 async::Now(async_get_default_dispatcher()) -
203 self->last_produce_time_;
204 if (time_since_last_produce >= kShouldShrinkThreshold) {
205 self->surface_pool_->ShrinkToFit();
208 kShouldShrinkThreshold);
211bool VulkanSurfaceProducer::TransitionSurfacesToExternal(
212 const std::vector<std::unique_ptr<SurfaceProducerSurface>>& surfaces) {
213 for (
auto& surface : surfaces) {
214 auto vk_surface =
static_cast<VulkanSurface*
>(
surface.get());
220 vk_surface->GetCommandBuffer(logical_device_->GetCommandPool());
221 if (!command_buffer->
Begin())
224 GrBackendRenderTarget backendRT = SkSurfaces::GetBackendRenderTarget(
225 vk_surface->GetSkiaSurface().get(),
226 SkSurfaces::BackendHandleAccess::kFlushRead);
227 if (!backendRT.isValid()) {
230 GrVkImageInfo imageInfo;
231 if (!GrBackendRenderTargets::GetVkImageInfo(backendRT, &imageInfo)) {
235 VkImageMemoryBarrier image_barrier = {
236 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
238 .srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
240 .oldLayout = imageInfo.fImageLayout,
242#if defined(__aarch64__)
243 .newLayout = imageInfo.fImageLayout,
245 .newLayout = VK_IMAGE_LAYOUT_GENERAL,
247 .srcQueueFamilyIndex = 0,
248 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_EXTERNAL_KHR,
249 .image = vk_surface->GetVkImage(),
250 .subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}};
253 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
254 VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
261 GrBackendRenderTargets::SetVkImageLayout(&backendRT,
262 image_barrier.newLayout);
264 if (!command_buffer->
End())
267 if (!logical_device_->QueueSubmit(
268 {}, {}, {vk_surface->GetAcquireVkSemaphore()},
269 {command_buffer->Handle()}, vk_surface->GetCommandBufferFence()))
275std::unique_ptr<SurfaceProducerSurface> VulkanSurfaceProducer::ProduceSurface(
276 const SkISize& size) {
278 last_produce_time_ = async::Now(async_get_default_dispatcher());
279 return surface_pool_->AcquireSurface(size);
282void VulkanSurfaceProducer::SubmitSurface(
283 std::unique_ptr<SurfaceProducerSurface> surface) {
285 surface_pool_->SubmitSurface(std::move(surface));
288std::unique_ptr<SurfaceProducerSurface>
289VulkanSurfaceProducer::ProduceOffscreenSurface(
const SkISize& size) {
290 return surface_pool_->CreateSurface(size);
static sk_sp< VulkanMemoryAllocator > Make(uint32_t vulkan_api_version, VkInstance instance, VkPhysicalDevice physicalDevice, VkDevice device, const fml::RefPtr< vulkan::VulkanProcTable > &vk, bool mustUseCoherentHostVisibleMemory)
void SubmitSurfaces(std::vector< std::unique_ptr< SurfaceProducerSurface > > surfaces) override
~VulkanSurfaceProducer() override
bool InsertPipelineBarrier(VkPipelineStageFlagBits src_stage_flags, VkPipelineStageFlagBits dest_stage_flags, uint32_t dependency_flags, uint32_t memory_barrier_count, const VkMemoryBarrier *memory_barriers, uint32_t buffer_memory_barrier_count, const VkBufferMemoryBarrier *buffer_memory_barriers, uint32_t image_memory_barrier_count, const VkImageMemoryBarrier *image_memory_barriers) const
bool AreDeviceProcsSetup() const
bool HasAcquiredMandatoryProcAddresses() const
bool AreInstanceProcsSetup() const
#define FML_LOG(severity)
#define FML_CHECK(condition)
#define FML_DCHECK(condition)
skgpu::VulkanGetProc CreateSkiaGetProc(const fml::RefPtr< vulkan::VulkanProcTable > &vk)
#define TRACE_EVENT0(category_group, name)
#define VK_CALL_LOG_ERROR(expression)