Skip to content

Commit

Permalink
[content handler] pipeline surface submission to mozart (flutter#3915)
Browse files Browse the repository at this point in the history
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
  • Loading branch information
freiling authored Sep 5, 2017
1 parent 79332e5 commit 1c99b3f
Show file tree
Hide file tree
Showing 7 changed files with 110 additions and 24 deletions.
70 changes: 64 additions & 6 deletions content_handler/vulkan_surface.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
}

Expand All @@ -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;
Expand Down
12 changes: 11 additions & 1 deletion content_handler/vulkan_surface.h
Original file line number Diff line number Diff line change
Expand Up @@ -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_;
Expand All @@ -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_;
Expand Down Expand Up @@ -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);
};

Expand Down
37 changes: 24 additions & 13 deletions content_handler/vulkan_surface_producer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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 {

Expand All @@ -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));

Expand Down Expand Up @@ -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));
}
Expand Down
8 changes: 5 additions & 3 deletions vulkan/vulkan_device.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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
};

Expand Down
4 changes: 3 additions & 1 deletion vulkan/vulkan_handle.h
Original file line number Diff line number Diff line change
Expand Up @@ -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_;

Expand Down
2 changes: 2 additions & 0 deletions vulkan/vulkan_proc_table.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions vulkan/vulkan_proc_table.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 1c99b3f

Please sign in to comment.