From 7b8c1eb302109ea77a173663a6cf14b6d80ab0f7 Mon Sep 17 00:00:00 2001 From: Bo Liu Date: Tue, 8 Jan 2019 20:17:55 -0800 Subject: [PATCH] VkFunctorDrawable implementation Bug: 115613038 Test: Turning on vulkan with appropriate webview apk does not crash and sort of works. Change-Id: If1504da7a35e4bd74a994ab2c2a351e6bc415a18 --- libs/hwui/WebViewFunctorManager.cpp | 20 ++++ libs/hwui/WebViewFunctorManager.h | 9 ++ .../pipeline/skia/SkiaRecordingCanvas.cpp | 2 - libs/hwui/pipeline/skia/VkFunctorDrawable.cpp | 59 +++++++--- libs/hwui/pipeline/skia/VkFunctorDrawable.h | 12 ++- libs/hwui/private/hwui/DrawVkInfo.h | 101 +++++++----------- libs/hwui/private/hwui/WebViewFunctor.h | 13 +-- libs/hwui/renderthread/RenderThread.h | 5 + libs/hwui/renderthread/VulkanManager.cpp | 89 ++++++++------- libs/hwui/renderthread/VulkanManager.h | 9 ++ native/webview/plat_support/draw_fn.h | 31 ++++-- native/webview/plat_support/draw_functor.cpp | 89 ++++++++++++++- 12 files changed, 298 insertions(+), 141 deletions(-) diff --git a/libs/hwui/WebViewFunctorManager.cpp b/libs/hwui/WebViewFunctorManager.cpp index 9170d6d1dc508..68541b4b31f09 100644 --- a/libs/hwui/WebViewFunctorManager.cpp +++ b/libs/hwui/WebViewFunctorManager.cpp @@ -86,6 +86,26 @@ void WebViewFunctor::drawGl(const DrawGlInfo& drawInfo) { mCallbacks.gles.draw(mFunctor, mData, drawInfo); } +void WebViewFunctor::initVk(const VkFunctorInitParams& params) { + ATRACE_NAME("WebViewFunctor::initVk"); + if (!mHasContext) { + mHasContext = true; + } else { + return; + } + mCallbacks.vk.initialize(mFunctor, mData, params); +} + +void WebViewFunctor::drawVk(const VkFunctorDrawParams& params) { + ATRACE_NAME("WebViewFunctor::drawVk"); + mCallbacks.vk.draw(mFunctor, mData, params); +} + +void WebViewFunctor::postDrawVk() { + ATRACE_NAME("WebViewFunctor::postDrawVk"); + mCallbacks.vk.postDraw(mFunctor, mData); +} + void WebViewFunctor::destroyContext() { if (mHasContext) { mHasContext = false; diff --git a/libs/hwui/WebViewFunctorManager.h b/libs/hwui/WebViewFunctorManager.h index 1719ce7cca758..2846cb1f087bf 100644 --- a/libs/hwui/WebViewFunctorManager.h +++ b/libs/hwui/WebViewFunctorManager.h @@ -42,6 +42,12 @@ public: void drawGl(const DrawGlInfo& drawInfo) const { mReference.drawGl(drawInfo); } + void initVk(const VkFunctorInitParams& params) { mReference.initVk(params); } + + void drawVk(const VkFunctorDrawParams& params) { mReference.drawVk(params); } + + void postDrawVk() { mReference.postDrawVk(); } + private: friend class WebViewFunctor; @@ -53,6 +59,9 @@ public: int id() const { return mFunctor; } void sync(const WebViewSyncData& syncData) const; void drawGl(const DrawGlInfo& drawInfo); + void initVk(const VkFunctorInitParams& params); + void drawVk(const VkFunctorDrawParams& params); + void postDrawVk(); void destroyContext(); sp createHandle() { diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp index 6eefed9599137..d54275fe7e19d 100644 --- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp +++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp @@ -125,8 +125,6 @@ void SkiaRecordingCanvas::callDrawGLFunction(Functor* functor, uirenderer::GlFunctorLifecycleListener* listener) { FunctorDrawable* functorDrawable; if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaVulkan) { - // TODO(cblume) use VkFunctorDrawable instead of VkInteropFunctorDrawable here when the - // interop is disabled/moved. functorDrawable = mDisplayList->allocateDrawable( functor, listener, asSkCanvas()); } else { diff --git a/libs/hwui/pipeline/skia/VkFunctorDrawable.cpp b/libs/hwui/pipeline/skia/VkFunctorDrawable.cpp index 156f74a611a7c..2f8d381f15f54 100644 --- a/libs/hwui/pipeline/skia/VkFunctorDrawable.cpp +++ b/libs/hwui/pipeline/skia/VkFunctorDrawable.cpp @@ -17,6 +17,8 @@ #include "VkFunctorDrawable.h" #include +#include "renderthread/VulkanManager.h" +#include "renderthread/RenderThread.h" #include #include #include @@ -31,34 +33,58 @@ namespace android { namespace uirenderer { namespace skiapipeline { -VkFunctorDrawHandler::VkFunctorDrawHandler(Functor* functor) : INHERITED(), mFunctor(functor) {} +VkFunctorDrawHandler::VkFunctorDrawHandler(sp functor_handle, + const SkMatrix& matrix, const SkIRect& clip, + const SkImageInfo& image_info) + : INHERITED() + , mFunctorHandle(functor_handle) + , mMatrix(matrix) + , mClip(clip) + , mImageInfo(image_info) {} VkFunctorDrawHandler::~VkFunctorDrawHandler() { - // TODO(cblume) Fill in the DrawVkInfo parameters. - (*mFunctor)(DrawVkInfo::kModePostComposite, nullptr); + mFunctorHandle->postDrawVk(); } void VkFunctorDrawHandler::draw(const GrBackendDrawableInfo& info) { ATRACE_CALL(); + if (!renderthread::RenderThread::isCurrent()) + LOG_ALWAYS_FATAL("VkFunctorDrawHandler::draw not called on render thread"); GrVkDrawableInfo vulkan_info; if (!info.getVkDrawableInfo(&vulkan_info)) { return; } + renderthread::VulkanManager& vk_manager = + renderthread::RenderThread::getInstance().vulkanManager(); + mFunctorHandle->initVk(vk_manager.getVkFunctorInitParams()); - DrawVkInfo draw_vk_info; - // TODO(cblume) Fill in the rest of the parameters and test the actual call. - draw_vk_info.isLayer = true; + SkMatrix44 mat4(mMatrix); + VkFunctorDrawParams params{ + .width = mImageInfo.width(), + .height = mImageInfo.height(), + .is_layer = false, // TODO(boliu): Populate is_layer. + .color_space_ptr = mImageInfo.colorSpace(), + .clip_left = mClip.fLeft, + .clip_top = mClip.fTop, + .clip_right = mClip.fRight, + .clip_bottom = mClip.fBottom, + }; + mat4.asColMajorf(¶ms.transform[0]); + params.secondary_command_buffer = vulkan_info.fSecondaryCommandBuffer; + params.color_attachment_index = vulkan_info.fColorAttachmentIndex; + params.compatible_render_pass = vulkan_info.fCompatibleRenderPass; + params.format = vulkan_info.fFormat; - (*mFunctor)(DrawVkInfo::kModeComposite, &draw_vk_info); + mFunctorHandle->drawVk(params); + + vulkan_info.fDrawBounds->offset.x = mClip.fLeft; + vulkan_info.fDrawBounds->offset.y = mClip.fTop; + vulkan_info.fDrawBounds->extent.width = mClip.fRight - mClip.fLeft; + vulkan_info.fDrawBounds->extent.height = mClip.fBottom - mClip.fTop; } VkFunctorDrawable::~VkFunctorDrawable() { - if (auto lp = std::get_if(&mAnyFunctor)) { - if (lp->listener) { - lp->listener->onGlFunctorReleased(lp->functor); - } - } } void VkFunctorDrawable::onDraw(SkCanvas* /*canvas*/) { @@ -67,16 +93,17 @@ void VkFunctorDrawable::onDraw(SkCanvas* /*canvas*/) { } std::unique_ptr VkFunctorDrawable::onSnapGpuDrawHandler( - GrBackendApi backendApi, const SkMatrix& matrix) { + GrBackendApi backendApi, const SkMatrix& matrix, const SkIRect& clip, + const SkImageInfo& image_info) { if (backendApi != GrBackendApi::kVulkan) { return nullptr; } std::unique_ptr draw; if (mAnyFunctor.index() == 0) { - LOG_ALWAYS_FATAL("Not implemented"); - return nullptr; + return std::make_unique(std::get<0>(mAnyFunctor).handle, matrix, clip, + image_info); } else { - return std::make_unique(std::get<1>(mAnyFunctor).functor); + LOG_ALWAYS_FATAL("Not implemented"); } } diff --git a/libs/hwui/pipeline/skia/VkFunctorDrawable.h b/libs/hwui/pipeline/skia/VkFunctorDrawable.h index d6fefc1fca060..1a53c8fd55db9 100644 --- a/libs/hwui/pipeline/skia/VkFunctorDrawable.h +++ b/libs/hwui/pipeline/skia/VkFunctorDrawable.h @@ -32,15 +32,18 @@ namespace skiapipeline { */ class VkFunctorDrawHandler : public FunctorDrawable::GpuDrawHandler { public: - explicit VkFunctorDrawHandler(Functor* functor); + VkFunctorDrawHandler(sp functor_handle, const SkMatrix& matrix, + const SkIRect& clip, const SkImageInfo& image_info); ~VkFunctorDrawHandler() override; void draw(const GrBackendDrawableInfo& info) override; private: typedef GpuDrawHandler INHERITED; - - Functor* mFunctor; + sp mFunctorHandle; + const SkMatrix mMatrix; + const SkIRect mClip; + const SkImageInfo mImageInfo; }; /** @@ -57,7 +60,8 @@ protected: // SkDrawable functions: void onDraw(SkCanvas* canvas) override; std::unique_ptr onSnapGpuDrawHandler( - GrBackendApi backendApi, const SkMatrix& matrix) override; + GrBackendApi backendApi, const SkMatrix& matrix, const SkIRect& clip, + const SkImageInfo& image_info) override; }; } // namespace skiapipeline diff --git a/libs/hwui/private/hwui/DrawVkInfo.h b/libs/hwui/private/hwui/DrawVkInfo.h index fd824bd957fd3..abc4dbf9fa1c1 100644 --- a/libs/hwui/private/hwui/DrawVkInfo.h +++ b/libs/hwui/private/hwui/DrawVkInfo.h @@ -17,80 +17,61 @@ #ifndef ANDROID_HWUI_DRAW_VK_INFO_H #define ANDROID_HWUI_DRAW_VK_INFO_H +#include #include namespace android { namespace uirenderer { -/** - * Structure used by VulkanRenderer::callDrawVKFunction() to pass and receive data from Vulkan - * functors. - */ -struct DrawVkInfo { - // Input: current width/height of destination surface - int width; - int height; +struct VkFunctorInitParams { + VkInstance instance; + VkPhysicalDevice physical_device; + VkDevice device; + VkQueue queue; + uint32_t graphics_queue_index; + uint32_t instance_version; + const char* const* enabled_instance_extension_names; + uint32_t enabled_instance_extension_names_length; + const char* const* enabled_device_extension_names; + uint32_t enabled_device_extension_names_length; + const VkPhysicalDeviceFeatures2* device_features_2; +}; - // Input: is the render target an FBO - bool isLayer; +struct VkFunctorDrawParams { + // Input: current width/height of destination surface. + int width; + int height; - // Input: current transform matrix, in OpenGL format - float transform[16]; + // Input: is the render target a FBO + bool is_layer; - // Input: WebView should do its main compositing draws into this. It cannot do anything that - // would require stopping the render pass. - VkCommandBuffer secondaryCommandBuffer; + // Input: current transform matrix + float transform[16]; - // Input: The main color attachment index where secondaryCommandBuffer will eventually be - // submitted. - uint32_t colorAttachmentIndex; + // Input WebView should do its main compositing draws into this. It cannot do + // anything that would require stopping the render pass. + VkCommandBuffer secondary_command_buffer; - // Input: A render pass which will be compatible to the one which the secondaryCommandBuffer - // will be submitted into. - VkRenderPass compatibleRenderPass; + // Input: The main color attachment index where secondary_command_buffer will + // eventually be submitted. + uint32_t color_attachment_index; - // Input: Format of the destination surface. - VkFormat format; + // Input: A render pass which will be compatible to the one which the + // secondary_command_buffer will be submitted into. + VkRenderPass compatible_render_pass; - // Input: Color space - const SkColorSpace* colorSpaceInfo; + // Input: Format of the destination surface. + VkFormat format; - // Input: current clip rect - int clipLeft; - int clipTop; - int clipRight; - int clipBottom; + // Input: Color space. + const SkColorSpace* color_space_ptr; - /** - * Values used as the "what" parameter of the functor. - */ - enum Mode { - // Called once at WebView start - kModeInit, - // Called when things need to be re-created - kModeReInit, - // Notifies the app that the composite functor will be called soon. This allows WebView to - // begin work early. - kModePreComposite, - // Do the actual composite work - kModeComposite, - // This allows WebView to begin using the previously submitted objects in future work. - kModePostComposite, - // Invoked every time the UI thread pushes over a frame to the render thread and the owning - // view has a dirty display list*. This is a signal to sync any data that needs to be - // shared between the UI thread and the render thread. During this time the UI thread is - // blocked. - kModeSync - }; - - /** - * Values used by Vulkan functors to tell the framework what to do next. - */ - enum Status { - // The functor is done - kStatusDone = 0x0, - }; -}; // struct DrawVkInfo + // Input: current clip rect + int clip_left; + int clip_top; + int clip_right; + int clip_bottom; +}; } // namespace uirenderer } // namespace android diff --git a/libs/hwui/private/hwui/WebViewFunctor.h b/libs/hwui/private/hwui/WebViewFunctor.h index da3d06a4d60c5..96da947ace087 100644 --- a/libs/hwui/private/hwui/WebViewFunctor.h +++ b/libs/hwui/private/hwui/WebViewFunctor.h @@ -19,6 +19,7 @@ #include #include +#include namespace android::uirenderer { @@ -52,18 +53,12 @@ struct WebViewFunctorCallbacks { // Called on RenderThread. initialize is guaranteed to happen before this call void (*draw)(int functor, void* data, const DrawGlInfo& params); } gles; - // TODO: VK support. The current DrawVkInfo is monolithic and needs to be split up for - // what params are valid on what callbacks struct { // Called either the first time the functor is used or the first time it's used after // a call to onContextDestroyed. - // void (*initialize)(int functor, const InitParams& params); - // void (*frameStart)(int functor, /* todo: what params are actually needed for this to - // be useful? Is this useful? */) - // void (*draw)(int functor, const CompositeParams& params /* todo: rename - composite - // almost always means something else, and we aren't compositing */); - // void (*frameEnd)(int functor, const PostCompositeParams& params /* todo: same as - // CompositeParams - rename */); + void (*initialize)(int functor, void* data, const VkFunctorInitParams& params); + void (*draw)(int functor, void* data, const VkFunctorDrawParams& params); + void (*postDraw)(int functor, void*); } vk; }; }; diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h index 5272227509c83..1ef83fb26c143 100644 --- a/libs/hwui/renderthread/RenderThread.h +++ b/libs/hwui/renderthread/RenderThread.h @@ -47,6 +47,10 @@ class Readback; class RenderState; class TestUtils; +namespace skiapipeline { +class VkFunctorDrawHandler; +} + namespace renderthread { class CanvasContext; @@ -124,6 +128,7 @@ private: friend class DummyVsyncSource; friend class android::uirenderer::TestUtils; friend class android::uirenderer::WebViewFunctor; + friend class android::uirenderer::skiapipeline::VkFunctorDrawHandler; RenderThread(); virtual ~RenderThread(); diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp index aa7a141f6da36..6c540f627a685 100644 --- a/libs/hwui/renderthread/VulkanManager.cpp +++ b/libs/hwui/renderthread/VulkanManager.cpp @@ -34,6 +34,23 @@ namespace android { namespace uirenderer { namespace renderthread { +static void free_features_extensions_structs(const VkPhysicalDeviceFeatures2& features) { + // All Vulkan structs that could be part of the features chain will start with the + // structure type followed by the pNext pointer. We cast to the CommonVulkanHeader + // so we can get access to the pNext for the next struct. + struct CommonVulkanHeader { + VkStructureType sType; + void* pNext; + }; + + void* pNext = features.pNext; + while (pNext) { + void* current = pNext; + pNext = static_cast(current)->pNext; + free(current); + } +} + #define GET_PROC(F) m##F = (PFN_vk##F)vkGetInstanceProcAddr(VK_NULL_HANDLE, "vk" #F) #define GET_INST_PROC(F) m##F = (PFN_vk##F)vkGetInstanceProcAddr(mInstance, "vk" #F) #define GET_DEV_PROC(F) m##F = (PFN_vk##F)vkGetDeviceProcAddr(mDevice, "vk" #F) @@ -66,6 +83,11 @@ void VulkanManager::destroy() { mDevice = VK_NULL_HANDLE; mPhysicalDevice = VK_NULL_HANDLE; mInstance = VK_NULL_HANDLE; + mInstanceVersion = 0u; + mInstanceExtensions.clear(); + mDeviceExtensions.clear(); + free_features_extensions_structs(mPhysicalDeviceFeatures2); + mPhysicalDeviceFeatures2 = {}; } bool VulkanManager::setupDevice(GrVkExtensions& grExtensions, VkPhysicalDeviceFeatures2& features) { @@ -81,7 +103,6 @@ bool VulkanManager::setupDevice(GrVkExtensions& grExtensions, VkPhysicalDeviceFe VK_MAKE_VERSION(1, 1, 0), // apiVersion }; - std::vector instanceExtensions; { GET_PROC(EnumerateInstanceExtensionProperties); @@ -99,7 +120,7 @@ bool VulkanManager::setupDevice(GrVkExtensions& grExtensions, VkPhysicalDeviceFe bool hasKHRSurfaceExtension = false; bool hasKHRAndroidSurfaceExtension = false; for (uint32_t i = 0; i < extensionCount; ++i) { - instanceExtensions.push_back(extensions[i].extensionName); + mInstanceExtensions.push_back(extensions[i].extensionName); if (!strcmp(extensions[i].extensionName, VK_KHR_SURFACE_EXTENSION_NAME)) { hasKHRSurfaceExtension = true; } @@ -120,8 +141,8 @@ bool VulkanManager::setupDevice(GrVkExtensions& grExtensions, VkPhysicalDeviceFe &app_info, // pApplicationInfo 0, // enabledLayerNameCount nullptr, // ppEnabledLayerNames - (uint32_t) instanceExtensions.size(), // enabledExtensionNameCount - instanceExtensions.data(), // ppEnabledExtensionNames + (uint32_t) mInstanceExtensions.size(), // enabledExtensionNameCount + mInstanceExtensions.data(), // ppEnabledExtensionNames }; GET_PROC(CreateInstance); @@ -201,7 +222,6 @@ bool VulkanManager::setupDevice(GrVkExtensions& grExtensions, VkPhysicalDeviceFe // presentation with any native window. So just use the first one. mPresentQueueIndex = 0; - std::vector deviceExtensions; { uint32_t extensionCount = 0; err = mEnumerateDeviceExtensionProperties(mPhysicalDevice, nullptr, &extensionCount, @@ -220,7 +240,7 @@ bool VulkanManager::setupDevice(GrVkExtensions& grExtensions, VkPhysicalDeviceFe } bool hasKHRSwapchainExtension = false; for (uint32_t i = 0; i < extensionCount; ++i) { - deviceExtensions.push_back(extensions[i].extensionName); + mDeviceExtensions.push_back(extensions[i].extensionName); if (!strcmp(extensions[i].extensionName, VK_KHR_SWAPCHAIN_EXTENSION_NAME)) { hasKHRSwapchainExtension = true; } @@ -237,8 +257,8 @@ bool VulkanManager::setupDevice(GrVkExtensions& grExtensions, VkPhysicalDeviceFe } return vkGetInstanceProcAddr(instance, proc_name); }; - grExtensions.init(getProc, mInstance, mPhysicalDevice, instanceExtensions.size(), - instanceExtensions.data(), deviceExtensions.size(), deviceExtensions.data()); + grExtensions.init(getProc, mInstance, mPhysicalDevice, mInstanceExtensions.size(), + mInstanceExtensions.data(), mDeviceExtensions.size(), mDeviceExtensions.data()); if (!grExtensions.hasExtension(VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME, 1)) { this->destroy(); @@ -308,8 +328,8 @@ bool VulkanManager::setupDevice(GrVkExtensions& grExtensions, VkPhysicalDeviceFe queueInfo, // pQueueCreateInfos 0, // layerCount nullptr, // ppEnabledLayerNames - (uint32_t) deviceExtensions.size(), // extensionCount - deviceExtensions.data(), // ppEnabledExtensionNames + (uint32_t) mDeviceExtensions.size(), // extensionCount + mDeviceExtensions.data(), // ppEnabledExtensionNames nullptr, // ppEnabledFeatures }; @@ -351,36 +371,17 @@ bool VulkanManager::setupDevice(GrVkExtensions& grExtensions, VkPhysicalDeviceFe return true; } -static void free_features_extensions_structs(const VkPhysicalDeviceFeatures2& features) { - // All Vulkan structs that could be part of the features chain will start with the - // structure type followed by the pNext pointer. We cast to the CommonVulkanHeader - // so we can get access to the pNext for the next struct. - struct CommonVulkanHeader { - VkStructureType sType; - void* pNext; - }; - - void* pNext = features.pNext; - while (pNext) { - void* current = pNext; - pNext = static_cast(current)->pNext; - free(current); - } -} - void VulkanManager::initialize() { if (mDevice != VK_NULL_HANDLE) { return; } GET_PROC(EnumerateInstanceVersion); - uint32_t instanceVersion = 0; - LOG_ALWAYS_FATAL_IF(mEnumerateInstanceVersion(&instanceVersion)); - LOG_ALWAYS_FATAL_IF(instanceVersion < VK_MAKE_VERSION(1, 1, 0)); + LOG_ALWAYS_FATAL_IF(mEnumerateInstanceVersion(&mInstanceVersion)); + LOG_ALWAYS_FATAL_IF(mInstanceVersion < VK_MAKE_VERSION(1, 1, 0)); GrVkExtensions extensions; - VkPhysicalDeviceFeatures2 features; - LOG_ALWAYS_FATAL_IF(!this->setupDevice(extensions, features)); + LOG_ALWAYS_FATAL_IF(!this->setupDevice(extensions, mPhysicalDeviceFeatures2)); mGetDeviceQueue(mDevice, mGraphicsQueueIndex, 0, &mGraphicsQueue); @@ -397,9 +398,9 @@ void VulkanManager::initialize() { backendContext.fDevice = mDevice; backendContext.fQueue = mGraphicsQueue; backendContext.fGraphicsQueueIndex = mGraphicsQueueIndex; - backendContext.fInstanceVersion = instanceVersion; + backendContext.fInstanceVersion = mInstanceVersion; backendContext.fVkExtensions = &extensions; - backendContext.fDeviceFeatures2 = &features; + backendContext.fDeviceFeatures2 = &mPhysicalDeviceFeatures2; backendContext.fGetProc = std::move(getProc); // create the command pool for the command buffers @@ -433,13 +434,29 @@ void VulkanManager::initialize() { LOG_ALWAYS_FATAL_IF(!grContext.get()); mRenderThread.setGrContext(grContext); - free_features_extensions_structs(features); - if (Properties::enablePartialUpdates && Properties::useBufferAge) { mSwapBehavior = SwapBehavior::BufferAge; } } +VkFunctorInitParams VulkanManager::getVkFunctorInitParams() const { + return VkFunctorInitParams{ + .instance = mInstance, + .physical_device = mPhysicalDevice, + .device = mDevice, + .queue = mGraphicsQueue, + .graphics_queue_index = mGraphicsQueueIndex, + .instance_version = mInstanceVersion, + .enabled_instance_extension_names = mInstanceExtensions.data(), + .enabled_instance_extension_names_length = + static_cast(mInstanceExtensions.size()), + .enabled_device_extension_names = mDeviceExtensions.data(), + .enabled_device_extension_names_length = + static_cast(mDeviceExtensions.size()), + .device_features_2 = &mPhysicalDeviceFeatures2, + }; +} + // Returns the next BackbufferInfo to use for the next draw. The function will make sure all // previous uses have finished before returning. VulkanSurface::BackbufferInfo* VulkanManager::getAvailableBackbuffer(VulkanSurface* surface) { diff --git a/libs/hwui/renderthread/VulkanManager.h b/libs/hwui/renderthread/VulkanManager.h index 9eb942c9d6ee0..105ee093a0573 100644 --- a/libs/hwui/renderthread/VulkanManager.h +++ b/libs/hwui/renderthread/VulkanManager.h @@ -132,6 +132,9 @@ public: // Creates a fence that is signaled, when all the pending Vulkan commands are flushed. status_t createReleaseFence(sp& nativeFence); + // Returned pointers are owned by VulkanManager. + VkFunctorInitParams getVkFunctorInitParams() const; + private: friend class RenderThread; @@ -234,6 +237,12 @@ private: VkCommandBuffer mDummyCB = VK_NULL_HANDLE; + // Variables saved to populate VkFunctorInitParams. + uint32_t mInstanceVersion = 0u; + std::vector mInstanceExtensions; + std::vector mDeviceExtensions; + VkPhysicalDeviceFeatures2 mPhysicalDeviceFeatures2{}; + enum class SwapBehavior { Discard, BufferAge, diff --git a/native/webview/plat_support/draw_fn.h b/native/webview/plat_support/draw_fn.h index bb2ee9b5da04e..0490e650a7a42 100644 --- a/native/webview/plat_support/draw_fn.h +++ b/native/webview/plat_support/draw_fn.h @@ -74,7 +74,10 @@ struct AwDrawFn_InitVkParams { VkQueue queue; uint32_t graphics_queue_index; uint32_t instance_version; - const char* const* enabled_extension_names; + const char* const* enabled_instance_extension_names; + uint32_t enabled_instance_extension_names_length; + const char* const* enabled_device_extension_names; + uint32_t enabled_device_extension_names_length; // Only one of device_features and device_features_2 should be non-null. // If both are null then no features are enabled. VkPhysicalDeviceFeatures* device_features; @@ -128,15 +131,13 @@ struct AwDrawFn_DrawVkParams { struct AwDrawFn_PostDrawVkParams { int version; - - // Input: Fence for the composite command buffer to signal it has finished its - // work on the GPU. - int fd; }; // Called on render thread while UI thread is blocked. Called for both GL and // VK. -typedef void AwDrawFn_OnSync(int functor, void* data, AwDrawFn_OnSyncParams* params); +typedef void AwDrawFn_OnSync(int functor, + void* data, + AwDrawFn_OnSyncParams* params); // Called on render thread when either the context is destroyed _or_ when the // functor's last reference goes away. Will always be called with an active @@ -150,17 +151,24 @@ typedef void AwDrawFn_OnContextDestroyed(int functor, void* data); typedef void AwDrawFn_OnDestroyed(int functor, void* data); // Only called for GL. -typedef void AwDrawFn_DrawGL(int functor, void* data, AwDrawFn_DrawGLParams* params); +typedef void AwDrawFn_DrawGL(int functor, + void* data, + AwDrawFn_DrawGLParams* params); // Initialize vulkan state. Needs to be called again after any // OnContextDestroyed. Only called for Vulkan. -typedef void AwDrawFn_InitVk(int functor, void* data, AwDrawFn_InitVkParams* params); +typedef void AwDrawFn_InitVk(int functor, + void* data, + AwDrawFn_InitVkParams* params); // Only called for Vulkan. -typedef void AwDrawFn_DrawVk(int functor, void* data, AwDrawFn_DrawVkParams* params); +typedef void AwDrawFn_DrawVk(int functor, + void* data, + AwDrawFn_DrawVkParams* params); // Only called for Vulkan. -typedef void AwDrawFn_PostDrawVk(int functor, void* data, +typedef void AwDrawFn_PostDrawVk(int functor, + void* data, AwDrawFn_PostDrawVkParams* params); struct AwDrawFnFunctorCallbacks { @@ -183,7 +191,8 @@ enum AwDrawFnRenderMode { typedef AwDrawFnRenderMode AwDrawFn_QueryRenderMode(void); // Create a functor. |functor_callbacks| should be valid until OnDestroyed. -typedef int AwDrawFn_CreateFunctor(void* data, AwDrawFnFunctorCallbacks* functor_callbacks); +typedef int AwDrawFn_CreateFunctor(void* data, + AwDrawFnFunctorCallbacks* functor_callbacks); // May be called on any thread to signal that the functor should be destroyed. // The functor will receive an onDestroyed when the last usage of it is diff --git a/native/webview/plat_support/draw_functor.cpp b/native/webview/plat_support/draw_functor.cpp index 6c1ceaba4d463..b97bbc3116244 100644 --- a/native/webview/plat_support/draw_functor.cpp +++ b/native/webview/plat_support/draw_functor.cpp @@ -74,6 +74,79 @@ void draw_gl(int functor, void* data, support->callbacks.draw_gl(functor, support->data, ¶ms); } +void initializeVk(int functor, void* data, + const uirenderer::VkFunctorInitParams& init_vk_params) { + SupportData* support = static_cast(data); + VkPhysicalDeviceFeatures2 device_features_2; + if (init_vk_params.device_features_2) + device_features_2 = *init_vk_params.device_features_2; + + AwDrawFn_InitVkParams params{ + .version = kAwDrawFnVersion, + .instance = init_vk_params.instance, + .physical_device = init_vk_params.physical_device, + .device = init_vk_params.device, + .queue = init_vk_params.queue, + .graphics_queue_index = init_vk_params.graphics_queue_index, + .instance_version = init_vk_params.instance_version, + .enabled_instance_extension_names = + init_vk_params.enabled_instance_extension_names, + .enabled_instance_extension_names_length = + init_vk_params.enabled_instance_extension_names_length, + .enabled_device_extension_names = + init_vk_params.enabled_device_extension_names, + .enabled_device_extension_names_length = + init_vk_params.enabled_device_extension_names_length, + .device_features = nullptr, + .device_features_2 = + init_vk_params.device_features_2 ? &device_features_2 : nullptr, + }; + support->callbacks.init_vk(functor, support->data, ¶ms); +} + +void drawVk(int functor, void* data, const uirenderer::VkFunctorDrawParams& draw_vk_params) { + SupportData* support = static_cast(data); + float gabcdef[7]; + draw_vk_params.color_space_ptr->transferFn(gabcdef); + AwDrawFn_DrawVkParams params{ + .version = kAwDrawFnVersion, + .width = draw_vk_params.width, + .height = draw_vk_params.height, + .is_layer = draw_vk_params.is_layer, + .secondary_command_buffer = draw_vk_params.secondary_command_buffer, + .color_attachment_index = draw_vk_params.color_attachment_index, + .compatible_render_pass = draw_vk_params.compatible_render_pass, + .format = draw_vk_params.format, + .transfer_function_g = gabcdef[0], + .transfer_function_a = gabcdef[1], + .transfer_function_b = gabcdef[2], + .transfer_function_c = gabcdef[3], + .transfer_function_d = gabcdef[4], + .transfer_function_e = gabcdef[5], + .transfer_function_f = gabcdef[6], + .clip_left = draw_vk_params.clip_left, + .clip_top = draw_vk_params.clip_top, + .clip_right = draw_vk_params.clip_right, + .clip_bottom = draw_vk_params.clip_bottom, + }; + COMPILE_ASSERT(sizeof(params.color_space_toXYZD50) == sizeof(skcms_Matrix3x3), + gamut_transform_size_mismatch); + draw_vk_params.color_space_ptr->toXYZD50( + reinterpret_cast(¶ms.color_space_toXYZD50)); + COMPILE_ASSERT(NELEM(params.transform) == NELEM(draw_vk_params.transform), + mismatched_transform_matrix_sizes); + for (int i = 0; i < NELEM(params.transform); ++i) { + params.transform[i] = draw_vk_params.transform[i]; + } + support->callbacks.draw_vk(functor, support->data, ¶ms); +} + +void postDrawVk(int functor, void* data) { + SupportData* support = static_cast(data); + AwDrawFn_PostDrawVkParams params{.version = kAwDrawFnVersion}; + support->callbacks.post_draw_vk(functor, support->data, ¶ms); +} + int CreateFunctor(void* data, AwDrawFnFunctorCallbacks* functor_callbacks) { static bool callbacks_initialized = false; static uirenderer::WebViewFunctorCallbacks webview_functor_callbacks = { @@ -82,9 +155,19 @@ int CreateFunctor(void* data, AwDrawFnFunctorCallbacks* functor_callbacks) { .onDestroyed = &onDestroyed, }; if (!callbacks_initialized) { - // Under uirenderer::RenderMode::Vulkan, whether gles or vk union should - // be populated should match whether the vk-gl interop is used. - webview_functor_callbacks.gles.draw = &draw_gl; + switch (uirenderer::WebViewFunctor_queryPlatformRenderMode()) { + case uirenderer::RenderMode::OpenGL_ES: + webview_functor_callbacks.gles.draw = &draw_gl; + break; + case uirenderer::RenderMode::Vulkan: + webview_functor_callbacks.vk.initialize = &initializeVk; + webview_functor_callbacks.vk.draw = &drawVk; + webview_functor_callbacks.vk.postDraw = &postDrawVk; + // TODO(boliu): Remove this once SkiaRecordingCanvas::drawWebViewFunctor + // no longer uses GL interop. + webview_functor_callbacks.gles.draw = &draw_gl; + break; + } callbacks_initialized = true; } SupportData* support = new SupportData{