From a67a3a210fe5c279096e32acb434f8c7eb43caf5 Mon Sep 17 00:00:00 2001 From: zaki Date: Mon, 20 Mar 2023 11:23:48 +0800 Subject: [PATCH] add vulkan nativebuffer adaptation Signed-off-by: zaki Change-Id: If0b9bf84362df9163ae6408ee632bac741f242a0 --- build/skia/ohos/BUILD.gn | 1 + engine/flutter/vulkan/vulkan_application.cc | 15 +- engine/flutter/vulkan/vulkan_application.h | 2 + engine/flutter/vulkan/vulkan_device.cc | 53 +++- engine/flutter/vulkan/vulkan_device.h | 16 +- engine/flutter/vulkan/vulkan_proc_table.cc | 5 + engine/flutter/vulkan/vulkan_proc_table.h | 5 + engine/flutter/vulkan/vulkan_window.cc | 238 +++++++++++++++++- engine/flutter/vulkan/vulkan_window.h | 18 +- .../third_party/vulkan/vulkan/vulkan_core.h | 1 + skia/src/gpu/vk/GrVkCaps.cpp | 20 ++ skia/src/gpu/vk/GrVkGpu.cpp | 5 + .../src/gpu/vk/GrVkSamplerYcbcrConversion.cpp | 13 + 13 files changed, 379 insertions(+), 13 deletions(-) diff --git a/build/skia/ohos/BUILD.gn b/build/skia/ohos/BUILD.gn index 781e92cd..918c4b8c 100644 --- a/build/skia/ohos/BUILD.gn +++ b/build/skia/ohos/BUILD.gn @@ -181,6 +181,7 @@ skia_common_defines = [ "SK_FORCE_RASTER_PIPELINE_BLITTER", "SK_LEGACY_SKCODEC_NONE_ENUM", "SK_ENABLE_DUMP_GPU", + "SK_BUILD_FOR_OPENHARMONY", ] # ------------------------------------------------ diff --git a/engine/flutter/vulkan/vulkan_application.cc b/engine/flutter/vulkan/vulkan_application.cc index 06d63b77..48a515c2 100644 --- a/engine/flutter/vulkan/vulkan_application.cc +++ b/engine/flutter/vulkan/vulkan_application.cc @@ -13,6 +13,7 @@ #endif #include "flutter/vulkan/vulkan_proc_table.h" #include "flutter/vulkan/vulkan_utilities.h" +#include "vulkan/vulkan_ohos.h" namespace vulkan { @@ -33,6 +34,11 @@ VulkanApplication::VulkanApplication( // Configure extensions. + instanceExtensions.push_back(VK_KHR_SURFACE_EXTENSION_NAME); + instanceExtensions.push_back(VK_OPENHARMONY_OHOS_SURFACE_EXTENSION_NAME); + for (const VkExtensionProperties& extension : supported_extensions) { + instanceExtensions.push_back(extension.extensionName); + } if (enable_instance_debugging) { enabled_extensions.emplace_back(VulkanDebugReport::DebugExtensionName()); } @@ -96,8 +102,8 @@ VulkanApplication::VulkanApplication( .pApplicationInfo = &info, .enabledLayerCount = static_cast(enabled_layers.size()), .ppEnabledLayerNames = layers, - .enabledExtensionCount = static_cast(enabled_extensions.size()), - .ppEnabledExtensionNames = extensions, + .enabledExtensionCount = static_cast(instanceExtensions.size()), + .ppEnabledExtensionNames = instanceExtensions.data(), }; // Perform initialization. @@ -273,4 +279,9 @@ bool VulkanApplication::ExtensionSupported( return false; } +std::vector VulkanApplication::GetInstanceExtensions() const +{ + return instanceExtensions; +} + } // namespace vulkan diff --git a/engine/flutter/vulkan/vulkan_application.h b/engine/flutter/vulkan/vulkan_application.h index 2fb0c2e0..c0169e6c 100644 --- a/engine/flutter/vulkan/vulkan_application.h +++ b/engine/flutter/vulkan/vulkan_application.h @@ -44,6 +44,7 @@ class VulkanApplication { std::unique_ptr AcquireFirstCompatibleLogicalDevice() const; + std::vector GetInstanceExtensions() const; private: VulkanProcTable& vk; VulkanHandle instance_; @@ -51,6 +52,7 @@ class VulkanApplication { std::unique_ptr debug_report_; bool valid_; + std::vector instanceExtensions; std::vector GetPhysicalDevices() const; std::vector GetSupportedInstanceExtensions( const VulkanProcTable& vk) const; diff --git a/engine/flutter/vulkan/vulkan_device.cc b/engine/flutter/vulkan/vulkan_device.cc index 3caf2b0e..ba0bc546 100644 --- a/engine/flutter/vulkan/vulkan_device.cc +++ b/engine/flutter/vulkan/vulkan_device.cc @@ -96,16 +96,45 @@ VulkanDevice::VulkanDevice(VulkanProcTable& p_vk, VulkanHandle layers[i] = enabled_layers[i].c_str(); } + uint32_t extensionCount = 0; + if (VK_CALL_LOG_ERROR(vk.EnumerateDeviceExtensionProperties(physical_device_, + nullptr, &extensionCount, nullptr)) != VK_SUCCESS) { + LOGE("VK CALL EnumerateDeviceExtensionProperties get extensionCount error!"); + } + std::vector deviceExtensionsOwner(extensionCount); + if (VK_CALL_LOG_ERROR(vk.EnumerateDeviceExtensionProperties(physical_device_, + nullptr, &extensionCount, deviceExtensionsOwner.data())) != VK_SUCCESS) { + LOGE("VK CALL EnumerateDeviceExtensionProperties fill deviceExtensionsOwner error!"); + } + for (auto& extension : extensions) { + deviceExtensions.push_back(extension); + } + for (const VkExtensionProperties& extension : deviceExtensionsOwner) { + deviceExtensions.push_back(extension); + } + memset(&physicalDeviceFeatures2, 0, sizeof(VkPhysicalDeviceFeatures2)); + physicalDeviceFeatures2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; + physicalDeviceFeatures2.pNext = nullptr; + void** tailPNext = &physicalDeviceFeatures2.pNext; + + VkPhysicalDeviceSamplerYcbcrConversionFeatures* ycbcrFeatures; + ycbcrFeatures = (VkPhysicalDeviceSamplerYcbcrConversionFeatures*) malloc(sizeof(VkPhysicalDeviceSamplerYcbcrConversionFeatures)); + ycbcrFeatures->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES; + ycbcrFeatures->pNext = nullptr; + *tailPNext = ycbcrFeatures; + tailPNext = &ycbcrFeatures->pNext; + vk.GetPhysicalDeviceFeatures2(physical_device_, &physicalDeviceFeatures2); + const VkDeviceCreateInfo create_info = { .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, - .pNext = nullptr, + .pNext = &physicalDeviceFeatures2, .flags = 0, .queueCreateInfoCount = queue_create.size(), .pQueueCreateInfos = queue_create.data(), .enabledLayerCount = static_cast(enabled_layers.size()), .ppEnabledLayerNames = layers, - .enabledExtensionCount = sizeof(extensions) / sizeof(const char*), - .ppEnabledExtensionNames = extensions, + .enabledExtensionCount = sizeof(deviceExtensions) / sizeof(const char*), + .ppEnabledExtensionNames = deviceExtensions.data(), .pEnabledFeatures = nullptr, }; @@ -272,6 +301,7 @@ VulkanDevice::VulkanDevice(VulkanProcTable& p_vk, VulkanDevice::~VulkanDevice() { #ifdef RS_ENABLE_VK WaitIdle(); + FreeExtensionsMemChain(physicalDeviceFeatures2); #else FML_ALLOW_UNUSED_LOCAL(WaitIdle()); #endif @@ -573,4 +603,21 @@ bool VulkanDevice::QueueSubmit( return true; } +VkPhysicalDeviceFeatures2 VulkanDevice::GetPhysicalDeviceFeatures2() +{ + return &physicalDeviceFeatures2; +} +std::vector VulkanDevice::GetQueueFamilyProperties() +{ + return deviceExtensions; +} +void VulkanDevice::FreeExtensionsMemChain(const VkPhysicalDeviceFeatures2 features2) +{ + void* pNext = features.pNext; + while (pNext) { + void* cur = pNext; + pNext = static_cast(cur)->pNext; + free(cur); + } +} } // namespace vulkan diff --git a/engine/flutter/vulkan/vulkan_device.h b/engine/flutter/vulkan/vulkan_device.h index db9d604f..dc2fe07d 100644 --- a/engine/flutter/vulkan/vulkan_device.h +++ b/engine/flutter/vulkan/vulkan_device.h @@ -39,6 +39,8 @@ class VulkanDevice { void ReleaseDeviceOwnership(); + std::vector GetDeviceExtensions() const; + #ifndef RS_ENABLE_VK FML_WARN_UNUSED_RESULT #endif @@ -83,6 +85,11 @@ class VulkanDevice { #endif bool WaitIdle() const; +#ifndef RS_ENABLE_VK + FML_WARN_UNUSED_RESULT +#endif + VkPhysicalDeviceFeatures2 GetPhysicalDeviceFeatures2() const; + private: VulkanProcTable& vk; VulkanHandle physical_device_; @@ -94,9 +101,14 @@ class VulkanDevice { uint32_t compute_queue_index_; #endif bool valid_; - + struct VKStruct { + VkStructureType sType; + void* pNext; + } + VkPhysicalDeviceFeatures2 physicalDeviceFeatures2{}; + std::vector deviceExtensions; std::vector GetQueueFamilyProperties() const; - + void FreeExtensionsMemChain(const VkPhysicalDeviceFeatures2 features2); #ifndef RS_ENABLE_VK FML_DISALLOW_COPY_AND_ASSIGN(VulkanDevice); #endif diff --git a/engine/flutter/vulkan/vulkan_proc_table.cc b/engine/flutter/vulkan/vulkan_proc_table.cc index 13a2e527..50edd013 100644 --- a/engine/flutter/vulkan/vulkan_proc_table.cc +++ b/engine/flutter/vulkan/vulkan_proc_table.cc @@ -117,6 +117,10 @@ bool VulkanProcTable::SetupInstanceProcAddresses( ACQUIRE_PROC(GetPhysicalDeviceSurfaceSupportKHR, handle); ACQUIRE_PROC(DestroySurfaceKHR, handle); ACQUIRE_PROC(CreateOHOSSurfaceOpenHarmony, handle); + ACQUIRE_PROC(GetPhysicalDeviceMemoryProperties2, handle); + ACQUIRE_PROC(BindImageMemory2, handle); + ACQUIRE_PROC(GetPhysicalDeviceFeatures2, handle); + ACQUIRE_PROC(EnumerateDeviceExtensionProperties, handle); #else ACQUIRE_PROC(GetDeviceProcAddr, handle); ACQUIRE_PROC(GetPhysicalDeviceFeatures, handle); @@ -180,6 +184,7 @@ bool VulkanProcTable::SetupDeviceProcAddresses( ACQUIRE_PROC(DestroySwapchainKHR, handle); ACQUIRE_PROC(GetSwapchainImagesKHR, handle); ACQUIRE_PROC(QueuePresentKHR, handle); + ACQUIRE_PROC(GetOHOSNativeBufferPropertiesOpenHarmony, handle); #else #if OS_ANDROID ACQUIRE_PROC(AcquireNextImageKHR, handle); diff --git a/engine/flutter/vulkan/vulkan_proc_table.h b/engine/flutter/vulkan/vulkan_proc_table.h index 9519a6da..c79eefdc 100644 --- a/engine/flutter/vulkan/vulkan_proc_table.h +++ b/engine/flutter/vulkan/vulkan_proc_table.h @@ -111,6 +111,11 @@ class VulkanProcTable { DEFINE_PROC(GetSwapchainImagesKHR); DEFINE_PROC(QueuePresentKHR); DEFINE_PROC(CreateOHOSSurfaceOpenHarmony); + DEFINE_PROC(GetOHOSNativeBufferPropertiesOpenHarmony); + DEFINE_PROC(GetPhysicalDeviceMemoryProperties2); + DEFINE_PROC(BindImageMemory2); + DEFINE_PROC(GetPhysicalDeviceFeatures2); + DEFINE_PROC(EnumerateDeviceExtensionProperties); #undef DEFINE_PROC diff --git a/engine/flutter/vulkan/vulkan_window.cc b/engine/flutter/vulkan/vulkan_window.cc index e1052b27..f3bf05dd 100644 --- a/engine/flutter/vulkan/vulkan_window.cc +++ b/engine/flutter/vulkan/vulkan_window.cc @@ -7,6 +7,11 @@ #include #include +#include + +#include "vulkan/vulkan_ohos.h" +#include "driver.h" + #include "flutter/vulkan/vulkan_application.h" #include "flutter/vulkan/vulkan_device.h" #ifdef RS_ENABLE_VK @@ -16,17 +21,20 @@ #include "flutter/vulkan/vulkan_surface.h" #include "flutter/vulkan/vulkan_swapchain.h" #include "third_party/skia/include/gpu/GrContext.h" +#include "third_party/skia/src/gpu/vk/GrVkGpu.h" +#include "third_party/skia/src/gpu/vk/GrContextPriv.h" namespace vulkan { #ifdef RS_ENABLE_VK -VulkanProcTable* VulkanWindow::vk; +std::unique_ptr VulkanWindow::vk; std::unique_ptr VulkanWindow::application_; std::unique_ptr VulkanWindow::logical_device_; std::thread::id VulkanWindow::device_thread_; std::vector> VulkanWindow::shared_fences_; uint32_t VulkanWindow::shared_fence_index_; bool VulkanWindow::presenting_ = false; +GrVkExtensions VulkanWindow::mExtensions; void VulkanWindow::InitializeVulkan(size_t thread_num) { @@ -42,8 +50,7 @@ void VulkanWindow::InitializeVulkan(size_t thread_num) LOGI("First Initialize Vulkan"); device_thread_ = std::this_thread::get_id(); - - vk = new VulkanProcTable(); + vk = std::make_unique(); if (!vk->HasAcquiredMandatoryProcAddresses()) { LOGE("Proc table has not acquired mandatory proc addresses."); return; @@ -51,7 +58,7 @@ void VulkanWindow::InitializeVulkan(size_t thread_num) // Create the application instance. std::vector extensions = { - VK_KHR_SURFACE_SPEC_VERSION, // parent extension + VK_KHR_SURFACE_EXTENSION_NAME, // parent extension VK_OPENHARMONY_OHOS_SURFACE_EXTENSION_NAME // child extension }; @@ -83,6 +90,15 @@ VulkanWindow::VulkanWindow(std::unique_ptr native_surface, LOGE("InitializeVulkan failed"); return; } + GrVkGetProc skiaGetProp = [](const char* proc_name, VkInstance instance, VkDevice device) { + if (device != VK_NULL_HANDLE) { + return vk->GetDeviceProcAddr(device, proc_name); + } + return vk->GetInstanceProcAddr(instance, proc_name); + } + mExtensions.init(skiaGetProp, application_->GetInstance(), logical_device_->GetPhysicalDeviceHandle(), + application_->GetInstanceExtensions().size(), application_->GetInstanceExtensions().data(), + logical_device_->GetDeviceExtensions().size(), logical_device_->GetDeviceExtensions().data()); if (!is_offscreen && (native_surface == nullptr || !native_surface->IsValid())) { LOGE("Native surface is invalid."); @@ -243,6 +259,8 @@ bool VulkanWindow::CreateSkiaBackendContext(GrVkBackendContext* context) { context->fQueue = logical_device_->GetQueueHandle(); context->fGraphicsQueueIndex = logical_device_->GetGraphicsQueueIndex(); context->fMinAPIVersion = application_->GetAPIVersion(); + context->fVkExtensions = &mExtensions; + context->fDeviceFeatures2 = logical_device_->GetPhysicalDeviceFeatures2(); #ifdef RS_ENABLE_VK uint32_t extensionFlags = kKHR_surface_GrVkExtensionFlag; if (!is_offscreen_) { @@ -261,6 +279,73 @@ bool VulkanWindow::CreateSkiaBackendContext(GrVkBackendContext* context) { return true; } +GrBackendFormat VulkanWindow::GetBackendFormat(GrContext* context, OH_NativeBuffer* buffer, int32_t format) +{ + GrBackendApi backend = context->backend(); + if (backend != GrBackendApi::kVulkan) { + LOGE("VulkanWindow::GetBackendFormat backend: %{public}d is not vulkan", backend); + return GrBackendFormat(); + } + switch (format) { + case PIXEL_FMT_RGBA_8888: + return GrBackendFormat::MakeVk(VK_FORMAT_R8G8B8A8_UNORM); + case STUB_PIXEL_FMT_RGBA_16161616: + return GrBackendFormat::MakeVk(VK_FORMAT_R16G16B16A16_SFLOAT); + case STUB_PIXEL_FMT_RGBA_1010102: + return GrBackendFormat::MakeVk(VK_FORMAT_A2B10G10R10_UNORM_PACK32); + case PIXEL_FMT_RGBX_8888: + return GrBackendFormat::MakeVk(VK_FORMAT_R8G8B8A8_UNORM); + case PIXEL_FMT_RGB_888: + return GrBackendFormat::MakeVk(VK_FORMAT_R8G8B8_UNORM); + default: { + return CreateDefaultBackendFormat(context); + } + } +} + +GrBackendFormat VulkanWindow::CreateDefaultBackendFormat(GrContext* context, OH_NativeBuffer* buffer) +{ + GrVkGpu* gpu = static_cast(context->priv().getGpu()); + VkDevice device = gpu->device(); + if (!gpu || !device) { + LOGE("VulkanWindow::CreateDefaultBackendFormat gpu or device is nullptr!"); + GrBackendFormat(); + } + VkOHOSNativeBufferFormatPropertiesOpenHarmony hwbFormatProps; + hwbFormatProps.sType = VK_STRUCTURE_TYPE_OHOS_NATIVE_BUFFER_FORMAT_PROPERTIES_OPENHARMONY; + hwbFormatProps.pNext = nullptr; + + VkOHOSNativeBufferPropertiesOpenHarmony hwbProps; + hwbProps.sType = VK_STRUCTURE_TYPE_OHOS_NATIVE_BUFFER_PROPERTIES_OPENHARMONY; + hwbProps.pNext = &hwbFormatProps; + VkResult result = vk->GetOHOSNativeBufferPropertiesOpenHarmony(device, buffer, &hwbProps); + + if (result != VK_SUCCESSS) { + LOGE("VulkanWindow::CreateDefaultBackendFormat VK_CALL GetOHOSNativeBufferPropertiesOpenHarmony error: + %{public}d", result); + return GrBackendFormat(); + } + + if (hwbFormatProps.format != VK_FORMAT_UNDEFINED) { + LOGE("VulkanWindow::CreateDefaultBackendFormat hwbFormatProps.format is not VK_FORMAT_UNDEFINED"); + return GrBackendFormat(); + } + GrVkYcbcrConversionInfo ycbcrInfo; + ycbcrInfo.fYcbcrModel = hwbFormatProps.suggestYcbcrModel; + ycbcrInfo.fYcbcrRange = hwbFormatProps.suggestYcbcrRange; + ycbcrInfo.fYcbcrXChromaOffset = hwbFormatProps.suggestYcbcrXChromaOffset; + ycbcrInfo.fYcbcrYChromaOffset = hwbFormatProps.suggestYcbcrYChromaOffset; + ycbcrInfo.fForceExplicitReconstruction = VK_FALSE; + ycbcrInfo.fExternalFormat = hwbFormatProps.externalFormat; + ycbcrInfo.fFormatFeatures = hwbFormatProps.formatFeatures; + if (VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_FILTER_BIT & hwbFormatProps.formatFeatures) { + ycbcrInfo.fChromaFilter = VK_FILTER_LINEAR; + } else { + ycbcrInfo.fChromaFilter = VK_FILTER_NEAREST; + } + return GrBackendFormat::MakeVk(ycbcrInfo); +} + sk_sp VulkanWindow::AcquireSurface() { #ifdef RS_ENABLE_VK if (is_offscreen_ || !IsValid()) { @@ -435,6 +520,150 @@ bool VulkanWindow::ResetSharedFence() { } #endif +GrBackendTexture VulkanWindow::GetBackendTexture(int32_t width, int32_t height, int32_t format, OH_NativeBuffer* buffer) +{ + GrContext* context = GetSkiaGrContext(); + if (!context) { + LOGE("VulkanWindow::GetBackendTexture GetSkiaGrContext is nullptr!"); + return GrBackendTexture(); + } + GrBackendFormat backendFormat = GetBackendFormat(context, buffer, format); + GrVkGpu* gpu = static_cast(context->priv().getGpu()); + VkDevice device = gpu->device(); + VkPhysicalDevice physicalDevice = gpu->physicalDevice(); + if (!gpu || !device || !physicalDevice) { + LOGE("VulkanWindow::GetBackendTexture gpu or device or physicalDevice is nullptr!"); + GrBackendTexture(); + } + + VkFormat VkFormat; + backendFormat.asVkFormat(&VkFormat); + + VkResult result; + + VkOHOSNativeBufferFormatPropertiesOpenHarmony hwbFormatProps; + hwbFormatProps.sType = VK_STRUCTURE_TYPE_OHOS_NATIVE_BUFFER_FORMAT_PROPERTIES_OPENHARMONY; + hwbFormatProps.pNext = nullptr; + + VkOHOSNativeBufferPropertiesOpenHarmony hwbProps; + hwbProps.sType = VK_STRUCTURE_TYPE_OHOS_NATIVE_BUFFER_PROPERTIES_OPENHARMONY; + hwbProps.pNext = &hwbFormatProps; + result = vk->GetOHOSNativeBufferPropertiesOpenHarmony(device, buffer, &hwbProps); + + if (result != VK_SUCCESSS) { + LOGE("VulkanWindow::GetBackendTexture VK_CALL GetOHOSNativeBufferPropertiesOpenHarmony error: + %{public}d", result); + return GrBackendTexture(); + } + + VkExternalFormatOpenHarmony externalFormat; + externalFormat.sType = VK_STRUCTURE_TYPE_OHOS_NATIVE_BUFFER_PROPERTIES_OPENHARMONY; + externalFormat.pNext = nullptr; + externalFormat.externalFormat = 0; + + const GrVkYcbcrConversionInfo ycbcrInfo = backendFormat.getVkYcbcrConversionInfo(); + if (!ycbcrInfo) { + LOGE("VulkanWindow::GetBackendTexture ycbcrInfo is nullptr"); + return GrBackendTexture(); + } + + if (hwbFormatProps.format == VK_FORMAT_UNDEFINED) { + externalFormat.externalFormat = hwbFormatProps.externalFormat; + } + + const VkExternalMemoryImageCreateInfo externalMemeoryImageInfo { + VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO, + &externalFormat, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_OHOS_NATIVE_BUFFER_BIT_OPENHARMONY + }; + VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_SAMPLED_BIT; + if (vkFormat != VK_FORMAT_UNDEFINED) { + usageFlags = usageFlags | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; + usageFlags = usageFlags | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + } + VkImageTiling tiling = VK_IMAGE_TILING_OPTIMAL; + const VkImageCreateInfo imageCreateInfo = { + VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, + &externalMemoryImageInfo, + 0, + VK_IMAGE_TYPE_2D, + vkFormat, + {(uint32_t)width, (uint32_t)height, 1}, + 1, + 1, + VK_SAMPLE_COUNT_1_BIT, + tiling, + usageFlags, + VK_SHARING_MODE_EXCLUSIVE, + 0, + 0, + VK_IMAGE_LAYOUT_UNDEFINED + }; + VkImage image; + result = vk->CreateImage(device, &imageCreateInfo, nullptr, &image); + if (result != VK_SUCCESS) { + LOGE("VulkanWindow::GetBackendTexture VK_CALL CreateImage error: + %{public}d", result); + return GrBackendTexture(); + } + + uint32_t typeIndex = 0; + VkImportOHOSNativeBufferInfoOpenHarmony hwbImportInfo; + hwbImportInfo.sType = VK_STRUCTURE_TYPE_IMPORT_OHOS_NATIVE_BUFFER_INFO_OPENHARMONY; + hwbImportInfo.pNext = nullptr; + hwbImportInfo.buffer = buffer; + + VkMemoryDedicatedAllocateInfo dedicatedAllocInfo; + dedicatedAllocInfo.sType = VK_MEMORY_DEDICATED_ALLOCATE_INFO; + dedicatedAllocInfo.pNext = &hwbImportInfo; + dedicatedAllocInfo.image = image; + dedicatedAllocInfo.buffer = buffer; + + VkMemoryAllocateInfo allocateInfo = { + VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, + &dedicatedAllocInfo, + hwbProps.allocationSize, + typeIndex + } + + VkDeviceMemory memory; + result = vk->AllocateMemory(device, &allocateInfo, nullptr, &memory); + if (result != VK_SUCCESS) { + LOGE("VulkanWindow::GetBackendTexture VK_CALL AllocateMemory error: + %{public}d", result); + return GrBackendTexture(); + } + VkBindImageMemoryInfo memoryInfo; + memoryInfo.sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO; + memoryInfo.pNext = nullptr; + memoryInfo.image = image; + memoryInfo.memory = memory; + memoryInfo.memoryOffset = 0; + result = vk->BindImageMemory2(device, 1, &memoryInfo); + if (result != VK_SUCCESS) { + LOGE("VulkanWindow::GetBackendTexture VK_CALL BindImageMemory2 error: + %{public}d", result); + return GrBackendTexture(); + } + + GrVkAlloc alloc; + alloc.fMemory = memory; + alloc.fOffset = 0; + alloc.fSize = hwbProps.allocationSize; + alloc.fFlags = 0; + + GrVkImageInfo imageInfo; + imageInfo.fImage = image; + imageInfo.fAlloc = alloc; + imageInfo.fImageTiling = tiling; + imageInfo.fImageLayout = VK_IMAGE_LAYOUT_UNDEFINED; + imageInfo.fFormat = vkFormat; + imageInfo.fLevelCount = 1; + imageInfo.fCurrentQueueFamily = VK_QUEUE_FAMILY_EXTERNAL; + imageInfo.fYcbcrConversionInfo = *ycbcrInfo; + return GrBackendTexture(width, height, imageInfo); +} + bool VulkanWindow::RecreateSwapchain() { #ifdef RS_ENABLE_VK if (is_offscreen_) { @@ -488,5 +717,4 @@ bool VulkanWindow::RecreateSwapchain() { swapchain_ = std::move(swapchain); return true; } - } // namespace vulkan diff --git a/engine/flutter/vulkan/vulkan_window.h b/engine/flutter/vulkan/vulkan_window.h index c2f1b74d..d96a108a 100644 --- a/engine/flutter/vulkan/vulkan_window.h +++ b/engine/flutter/vulkan/vulkan_window.h @@ -11,6 +11,8 @@ #include #include +#include + #ifndef RS_ENABLE_VK #include "flutter/fml/compiler_specific.h" #include "flutter/fml/macros.h" @@ -21,6 +23,9 @@ #include "third_party/skia/include/core/SkSurface.h" #include "third_party/skia/include/gpu/GrContext.h" #include "third_party/skia/include/gpu/vk/GrVkBackendContext.h" +#include "third_party/skia/include/gpu/GrBackendSurface.h" +#include "third_party/skia/include/gpu/vk/GrVkExtensions.h" + namespace vulkan { @@ -60,11 +65,12 @@ class VulkanWindow { static bool WaitForSharedFence(); static bool ResetSharedFence(); #endif + GrBackendTexture GetBackendTexture(int32_t width, int32_t height, int32_t format, OH_NativeBuffer* buffer); private: bool valid_; #ifdef RS_ENABLE_VK - static VulkanProcTable* vk; + static std::unique_ptr vk; static std::unique_ptr application_; static std::unique_ptr logical_device_; bool is_offscreen_ = false; @@ -72,6 +78,7 @@ class VulkanWindow { static std::vector> shared_fences_; static uint32_t shared_fence_index_; static bool presenting_; + static GrVkExtensions mExtensions; #else fml::RefPtr vk; std::unique_ptr application_; @@ -80,11 +87,20 @@ class VulkanWindow { std::unique_ptr surface_; std::unique_ptr swapchain_; sk_sp skia_gr_context_; + enum + { + STUB_PIXEL_FMT_RGBA_16161616 = 0X7fff00001, + STUB_PIXEL_FMT_RGBA_1010102 = 0X7fff00002 + }; bool CreateSkiaGrContext(); bool CreateSkiaBackendContext(GrVkBackendContext* context); + GrBackendFormat GetBackendFormat(GrContext* context, OH_NativeBuffer* buffer, int32_t format); + + GrBackendFormat CreateDefaultBackendFormat(GrContext* context, OH_NativeBuffer* buffer); + #ifndef RS_ENABLE_VK FML_WARN_UNUSED_RESULT #endif diff --git a/skia/include/third_party/vulkan/vulkan/vulkan_core.h b/skia/include/third_party/vulkan/vulkan/vulkan_core.h index 4d8762f8..759706df 100644 --- a/skia/include/third_party/vulkan/vulkan/vulkan_core.h +++ b/skia/include/third_party/vulkan/vulkan/vulkan_core.h @@ -368,6 +368,7 @@ typedef enum VkStructureType { VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID = 1000129003, VK_STRUCTURE_TYPE_MEMORY_GET_ANDROID_HARDWARE_BUFFER_INFO_ANDROID = 1000129004, VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID = 1000129005, + VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_OPENHARMONY = 1000452005, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES_EXT = 1000130000, VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO_EXT = 1000130001, VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT = 1000143000, diff --git a/skia/src/gpu/vk/GrVkCaps.cpp b/skia/src/gpu/vk/GrVkCaps.cpp index 38444810..84e5e5c5 100644 --- a/skia/src/gpu/vk/GrVkCaps.cpp +++ b/skia/src/gpu/vk/GrVkCaps.cpp @@ -1237,11 +1237,31 @@ bool GrVkCaps::isFormatTexturableAndUploadable(GrColorType ct, SkToBool(ctFlags & ColorTypeInfo::kUploadData_Flag); } +#ifdef SK_BUILD_FOR_OPENHARMONY +static bool isExternalBackendFormat(const GrBackendFormat& format) { + const GrVkYcbcrConversionInfo* ycbcrInfo = format.getVkYcbcrConversionInfo(); + SkASSERT(ycbcrInfo); + + // All external formats have a valid ycbcrInfo used for sampling and a non zero external format + if (ycbcrInfo->isValid() && ycbcrInfo->fExternalFormat != 0) { + return true; + } + return false; +} +#endif + bool GrVkCaps::isFormatTexturable(const GrBackendFormat& format) const { VkFormat vkFormat; if (!format.asVkFormat(&vkFormat)) { return false; } +#ifdef SK_BUILD_FOR_OPENHARMONY + if (isExternalBackendFormat(format)) { + // We can always texture from an external format (assuming we have the ycbcr conversion + // info which we require to be passed in.) + return true; + } +#endif return this->isVkFormatTexturable(vkFormat); } diff --git a/skia/src/gpu/vk/GrVkGpu.cpp b/skia/src/gpu/vk/GrVkGpu.cpp index a5b451ad..631bcebf 100644 --- a/skia/src/gpu/vk/GrVkGpu.cpp +++ b/skia/src/gpu/vk/GrVkGpu.cpp @@ -1150,6 +1150,11 @@ static bool check_image_info(const GrVkCaps& caps, } static bool check_tex_image_info(const GrVkCaps& caps, const GrVkImageInfo& info) { +#ifdef SK_BUILD_FOR_OPENHARMONY + if (info.fYcbcrConversionInfo.isValid() && info.fYcbcrConversionInfo.fExternalFormat != 0) { + return true; + } +#endif if (info.fImageTiling == VK_IMAGE_TILING_OPTIMAL) { if (!caps.isVkFormatTexturable(info.fFormat)) { return false; diff --git a/skia/src/gpu/vk/GrVkSamplerYcbcrConversion.cpp b/skia/src/gpu/vk/GrVkSamplerYcbcrConversion.cpp index f33f5216..8e8aa25a 100644 --- a/skia/src/gpu/vk/GrVkSamplerYcbcrConversion.cpp +++ b/skia/src/gpu/vk/GrVkSamplerYcbcrConversion.cpp @@ -9,6 +9,11 @@ #include "src/gpu/vk/GrVkGpu.h" +#ifdef SK_BUILD_FOR_OPENHARMONY +#include "vulkan/vulkan_ohos.h" +#include "vulkan/vulkan_core.h" +#endif + GrVkSamplerYcbcrConversion* GrVkSamplerYcbcrConversion::Create( const GrVkGpu* gpu, const GrVkYcbcrConversionInfo& info) { if (!gpu->vkCaps().supportsYcbcrConversion()) { @@ -61,6 +66,14 @@ GrVkSamplerYcbcrConversion* GrVkSamplerYcbcrConversion::Create( externalFormat.externalFormat = info.fExternalFormat; ycbcrCreateInfo.pNext = &externalFormat; } +#elif defined(SK_BUILD_FOR_OPENHARMONY) + VkExternalFormatOpenHarmony externalFormat; + if (info.fExternalFormat) { + externalFormat.sType = VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_OPENHARMONY; + externalFormat.pNext = nullptr; + externalFormat.externalFormat = info.fExternalFormat; + ycbcrCreateInfo.pNext = &externalFormat; + } #else // External images are supported only on Android; SkASSERT(!info.fExternalFormat); -- Gitee