提交 1c99b3f4 编写于 作者: F freiling 提交者: GitHub

[content handler] pipeline surface submission to mozart (#3915)

This change basically moves the singaling of the surface acquire event into the gpu driver, eliminating the VkQueueWaitIdle on surface submission

This change depends on https://skia-review.googlesource.com/c/25641/ so do not submit until Flutter has rolled Skia past that point
上级 79332e5c
......@@ -5,6 +5,7 @@
#include "flutter/content_handler/vulkan_surface.h"
#include "flutter/common/threads.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/gpu/GrBackendSemaphore.h"
#include "third_party/skia/include/gpu/GrBackendSurface.h"
#include "third_party/skia/include/gpu/GrContext.h"
#include "third_party/skia/src/gpu/vk/GrVkImage.h"
......@@ -69,11 +70,66 @@ SkISize VulkanSurface::GetSize() const {
return SkISize::Make(sk_surface_->width(), sk_surface_->height());
}
GrBackendSemaphore VulkanSurface::GetAcquireSemaphore() const {
GrBackendSemaphore gr_semaphore;
gr_semaphore.initVulkan(acquire_semaphore_);
return gr_semaphore;
}
vulkan::VulkanHandle<VkSemaphore>
VulkanSurface::SemaphoreFromEvent(const mx::event &event) const {
VkResult result;
VkSemaphore semaphore;
mx::event semaphore_event;
mx_status_t status = event.duplicate(MX_RIGHT_SAME_RIGHTS, &semaphore_event);
if (status != MX_OK) {
FTL_DLOG(ERROR) << "failed to duplicate semaphore event";
return vulkan::VulkanHandle<VkSemaphore>();
}
VkSemaphoreCreateInfo create_info = {
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
};
result = VK_CALL_LOG_ERROR(vk_.CreateSemaphore(
backend_context_->fDevice, &create_info, nullptr, &semaphore));
if (result != VK_SUCCESS) {
return vulkan::VulkanHandle<VkSemaphore>();
}
VkImportSemaphoreFdInfoKHR import_info = {
.sType = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR,
.pNext = nullptr,
.semaphore = semaphore,
.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR,
.fd = semaphore_event.release()};
result = VK_CALL_LOG_ERROR(
vk_.ImportSemaphoreFdKHR(backend_context_->fDevice, &import_info));
if (result != VK_SUCCESS) {
return vulkan::VulkanHandle<VkSemaphore>();
}
return vulkan::VulkanHandle<VkSemaphore>(
semaphore, [this](VkSemaphore semaphore) {
vk_.DestroySemaphore(backend_context_->fDevice, semaphore, nullptr);
});
}
bool VulkanSurface::CreateFences() {
if (mx::event::create(0, &acquire_event_) != MX_OK) {
return false;
}
acquire_semaphore_ = SemaphoreFromEvent(acquire_event_);
if (!acquire_semaphore_) {
FTL_DLOG(ERROR) << "failed to create acquire semaphore";
return false;
}
if (mx::event::create(0, &release_event_) != MX_OK) {
return false;
}
......@@ -295,12 +351,6 @@ void VulkanSurface::SignalWritesFinished(
<< "Attempted to signal a write on the surface when the previous write "
"has not yet been acknowledged by the compositor.";
// Signal the acquire end to the compositor.
if (acquire_event_.signal(0u, MX_EVENT_SIGNALED) != MX_OK) {
on_writes_committed();
return;
}
pending_on_writes_committed_ = on_writes_committed;
}
......@@ -314,6 +364,14 @@ void VulkanSurface::Reset() {
<< "Could not reset fences. The surface is no longer valid.";
}
// Need to make a new acquire semaphore every frame or else validation layers
// get confused about why no one is waiting on it in this VkInstance
acquire_semaphore_.Reset();
acquire_semaphore_ = SemaphoreFromEvent(acquire_event_);
if (!acquire_semaphore_) {
FTL_DLOG(ERROR) << "failed to create acquire semaphore";
}
// It is safe for the caller to collect the surface in the callback.
auto callback = pending_on_writes_committed_;
pending_on_writes_committed_ = nullptr;
......
......@@ -49,7 +49,13 @@ class VulkanSurface : public flow::SceneUpdateContext::SurfaceProducerSurface,
// |flow::SceneUpdateContext::SurfaceProducerSurface|
sk_sp<SkSurface> GetSkiaSurface() const override;
private:
// This transfers ownership of the GrBackendSemaphore but not the underlying
// VkSemaphore (i.e. it is ok to let the returned GrBackendSemaphore go out of
// scope but it is not ok to call VkDestroySemaphore on the underlying
// VkSemaphore)
GrBackendSemaphore GetAcquireSemaphore() const;
private:
vulkan::VulkanProcTable& vk_;
sk_sp<GrVkBackendContext> backend_context_;
scenic_lib::Session* session_;
......@@ -58,6 +64,7 @@ class VulkanSurface : public flow::SceneUpdateContext::SurfaceProducerSurface,
sk_sp<SkSurface> sk_surface_;
std::unique_ptr<scenic_lib::Image> session_image_;
mx::event acquire_event_;
vulkan::VulkanHandle<VkSemaphore> acquire_semaphore_;
mx::event release_event_;
mtl::MessageLoop::HandlerKey event_handler_key_ = 0;
std::function<void(void)> pending_on_writes_committed_;
......@@ -85,6 +92,9 @@ class VulkanSurface : public flow::SceneUpdateContext::SurfaceProducerSurface,
void Reset();
vulkan::VulkanHandle<VkSemaphore>
SemaphoreFromEvent(const mx::event &event) const;
FTL_DISALLOW_COPY_AND_ASSIGN(VulkanSurface);
};
......
......@@ -3,12 +3,13 @@
// found in the LICENSE file.
#include "flutter/content_handler/vulkan_surface_producer.h"
#include <memory>
#include <string>
#include <vector>
#include "third_party/skia/include/gpu/GrBackendSemaphore.h"
#include "third_party/skia/include/gpu/GrContext.h"
#include "third_party/skia/include/gpu/vk/GrVkTypes.h"
#include "third_party/skia/src/gpu/vk/GrVkUtil.h"
#include <memory>
#include <string>
#include <vector>
namespace flutter_runner {
......@@ -25,13 +26,21 @@ VulkanSurfaceProducer::VulkanSurfaceProducer(
}
}
VulkanSurfaceProducer::~VulkanSurfaceProducer() = default;
VulkanSurfaceProducer::~VulkanSurfaceProducer() {
// Make sure queue is idle before we start destroying surfaces
VkResult wait_result =
VK_CALL_LOG_ERROR(vk_->QueueWaitIdle(backend_context_->fQueue));
FTL_DCHECK(wait_result == VK_SUCCESS);
};
bool VulkanSurfaceProducer::Initialize(
scenic_lib::Session* mozart_session) {
vk_ = ftl::MakeRefCounted<vulkan::VulkanProcTable>();
std::vector<std::string> extensions = {VK_KHR_SURFACE_EXTENSION_NAME};
std::vector<std::string> extensions = {
VK_KHR_SURFACE_EXTENSION_NAME,
VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME,
};
application_ = std::make_unique<vulkan::VulkanApplication>(
*vk_, "FlutterContentHandler", std::move(extensions));
......@@ -110,16 +119,18 @@ void VulkanSurfaceProducer::OnSurfacesPresented(
std::vector<
std::unique_ptr<flow::SceneUpdateContext::SurfaceProducerSurface>>
surfaces) {
// Do a single flush for all canvases derived from the context.
context_->flush();
// Do a CPU wait.
// TODO(chinmaygarde): Remove this once we have support for Vulkan semaphores.
VkResult wait_result =
VK_CALL_LOG_ERROR(vk_->QueueWaitIdle(backend_context_->fQueue));
FTL_DCHECK(wait_result == VK_SUCCESS);
std::vector<GrBackendSemaphore> semaphores;
semaphores.reserve(surfaces.size());
for (auto &surface : surfaces) {
auto vk_surface = static_cast<VulkanSurface *>(surface.get());
semaphores.push_back(vk_surface->GetAcquireSemaphore());
}
// Do a single flush for all canvases derived from the context.
context_->flushAndSignalSemaphores(semaphores.size(), semaphores.data());
// Submit surface, this signals acquire events sent along the session.
// Submit surface
for (auto& surface : surfaces) {
SubmitSurface(std::move(surface));
}
......
......@@ -58,10 +58,12 @@ VulkanDevice::VulkanDevice(VulkanProcTable& p_vk,
.pQueuePriorities = priorities,
};
const char* extensions[] = {
VK_KHR_SWAPCHAIN_EXTENSION_NAME,
const char *extensions[] = {
VK_KHR_SWAPCHAIN_EXTENSION_NAME,
#if OS_FUCHSIA
VK_GOOGLE_EXTERNAL_MEMORY_MAGMA_EXTENSION_NAME,
VK_GOOGLE_EXTERNAL_MEMORY_MAGMA_EXTENSION_NAME,
VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME,
VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME,
#endif
};
......
......@@ -55,7 +55,9 @@ class VulkanHandle {
/// the lifetime of the handle extends past the lifetime of this object.
void ReleaseOwnership() { disposer_ = nullptr; }
private:
void Reset() { DisposeIfNecessary(); }
private:
Handle handle_;
Disposer disposer_;
......
......@@ -94,6 +94,7 @@ bool VulkanProcTable::SetupInstanceProcAddresses(
ACQUIRE_PROC(CreateMagmaSurfaceKHR, handle);
ACQUIRE_PROC(ExportDeviceMemoryMAGMA, handle);
ACQUIRE_PROC(GetPhysicalDeviceMagmaPresentationSupportKHR, handle);
ACQUIRE_PROC(ImportSemaphoreFdKHR, handle);
return true;
}();
#endif // OS_FUCHSIA
......@@ -146,6 +147,7 @@ bool VulkanProcTable::SetupDeviceProcAddresses(
ACQUIRE_PROC(WaitForFences, handle);
#if OS_FUCHSIA
ACQUIRE_PROC(ExportDeviceMemoryMAGMA, handle);
ACQUIRE_PROC(ImportSemaphoreFdKHR, handle);
#endif // OS_FUCHSIA
device_ = {handle, nullptr};
return true;
......
......@@ -118,6 +118,7 @@ class VulkanProcTable : public ftl::RefCountedThreadSafe<VulkanProcTable> {
DEFINE_PROC(CreateMagmaSurfaceKHR);
DEFINE_PROC(ExportDeviceMemoryMAGMA);
DEFINE_PROC(GetPhysicalDeviceMagmaPresentationSupportKHR);
DEFINE_PROC(ImportSemaphoreFdKHR);
#endif // OS_FUCHSIA
#undef DEFINE_PROC
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册