diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp index e93824dfbd30e..01126860b3ba5 100644 --- a/libs/hwui/renderthread/VulkanManager.cpp +++ b/libs/hwui/renderthread/VulkanManager.cpp @@ -336,6 +336,7 @@ void VulkanManager::setupDevice(GrVkExtensions& grExtensions, VkPhysicalDeviceFe GET_DEV_PROC(ResetCommandBuffer); GET_DEV_PROC(ResetFences); GET_DEV_PROC(WaitForFences); + GET_DEV_PROC(FrameBoundaryANDROID); } void VulkanManager::initialize() { @@ -516,6 +517,25 @@ void VulkanManager::finishFrame(SkSurface* surface) { if (semaphore != VK_NULL_HANDLE) { if (submitted == GrSemaphoresSubmitted::kYes) { mSwapSemaphore = semaphore; + if (mFrameBoundaryANDROID) { + // retrieve VkImage used as render target + VkImage image = VK_NULL_HANDLE; + GrBackendRenderTarget backendRenderTarget = + surface->getBackendRenderTarget(SkSurface::kFlushRead_BackendHandleAccess); + if (backendRenderTarget.isValid()) { + GrVkImageInfo info; + if (backendRenderTarget.getVkImageInfo(&info)) { + image = info.fImage; + } else { + ALOGE("Frame boundary: backend is not vulkan"); + } + } else { + ALOGE("Frame boundary: invalid backend render target"); + } + // frameBoundaryANDROID needs to know about mSwapSemaphore, but + // it won't wait on it. + mFrameBoundaryANDROID(mDevice, mSwapSemaphore, image); + } } else { destroy_semaphore(mDestroySemaphoreContext); mDestroySemaphoreContext = nullptr; diff --git a/libs/hwui/renderthread/VulkanManager.h b/libs/hwui/renderthread/VulkanManager.h index 0912369b611d6..7b5fe19c64f5e 100644 --- a/libs/hwui/renderthread/VulkanManager.h +++ b/libs/hwui/renderthread/VulkanManager.h @@ -31,6 +31,21 @@ #include #include +// VK_ANDROID_frame_boundary is a bespoke extension defined by AGI +// (https://github.com/google/agi) to enable profiling of apps rendering via +// HWUI. This extension is not defined in Khronos, hence the need to declare it +// manually here. There's a superseding extension (VK_EXT_frame_boundary) being +// discussed in Khronos, but in the meantime we use the bespoke +// VK_ANDROID_frame_boundary. This is a device extension that is implemented by +// AGI's Vulkan capture layer, such that it is only supported by devices when +// AGI is doing a capture of the app. +// +// TODO(b/182165045): use the Khronos blessed VK_EXT_frame_boudary once it has +// landed in the spec. +typedef void(VKAPI_PTR* PFN_vkFrameBoundaryANDROID)(VkDevice device, VkSemaphore semaphore, + VkImage image); +#define VK_ANDROID_FRAME_BOUNDARY_EXTENSION_NAME "VK_ANDROID_frame_boundary" + #include "Frame.h" #include "IRenderPipeline.h" #include "VulkanSurface.h" @@ -160,6 +175,7 @@ private: VkPtr mDestroyFence; VkPtr mWaitForFences; VkPtr mResetFences; + VkPtr mFrameBoundaryANDROID; VkInstance mInstance = VK_NULL_HANDLE; VkPhysicalDevice mPhysicalDevice = VK_NULL_HANDLE;