Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion engine/src/build_overrides/vulkan_headers.gni
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@
# set anything.

if (is_linux) {
vulkan_use_x11 = true
vulkan_use_x11 = false
vulkan_use_wayland = true
}
2 changes: 1 addition & 1 deletion engine/src/flutter/impeller/tools/args.gni
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ declare_args() {
enable_unittests) && target_os != "fuchsia"

# Whether the Vulkan backend is enabled.
impeller_enable_vulkan = (is_win || is_android || is_mac ||
impeller_enable_vulkan = (is_linux || is_win || is_android || is_mac ||
enable_unittests) && target_os != "fuchsia"
}

Expand Down
4 changes: 4 additions & 0 deletions engine/src/flutter/shell/platform/embedder/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,8 @@ template("embedder_source_set") {

if (embedder_enable_vulkan) {
sources += [
"embedder_external_texture_vulkan.cc",
"embedder_external_texture_vulkan.h",
"embedder_surface_vulkan.cc",
"embedder_surface_vulkan.h",
]
Expand All @@ -175,6 +177,8 @@ template("embedder_source_set") {
sources += [
"embedder_surface_vulkan_impeller.cc",
"embedder_surface_vulkan_impeller.h",
"embedder_external_texture_source_vulkan.cc",
"embedder_external_texture_source_vulkan.h",
]
}

Expand Down
22 changes: 22 additions & 0 deletions engine/src/flutter/shell/platform/embedder/embedder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2338,6 +2338,28 @@ FlutterEngineResult FlutterEngineInitialize(size_t version,
external_texture_metal_callback);
}
}
#endif
#ifdef SHELL_ENABLE_VULKAN
flutter::EmbedderExternalTextureVulkan::ExternalTextureCallback
external_texture_vulkan_callback;
if (config->type == kVulkan) {
const FlutterVulkanRendererConfig* vulkan_config = &config->vulkan;
if (SAFE_ACCESS(vulkan_config, external_texture_frame_callback, nullptr)) {
external_texture_vulkan_callback =
[ptr = vulkan_config->external_texture_frame_callback, user_data](
int64_t texture_identifier, size_t width,
size_t height) -> std::unique_ptr<FlutterVulkanTexture> {
std::unique_ptr<FlutterVulkanTexture> texture =
std::make_unique<FlutterVulkanTexture>();
if (!ptr(user_data, texture_identifier, width, height, texture.get())) {
return nullptr;
}
return texture;
};
external_texture_resolver = std::make_unique<ExternalTextureResolver>(
external_texture_vulkan_callback);
}
}
#endif
auto custom_task_runners = SAFE_ACCESS(args, custom_task_runners, nullptr);
auto thread_config_callback = [&custom_task_runners](
Expand Down
45 changes: 44 additions & 1 deletion engine/src/flutter/shell/platform/embedder/embedder.h
Original file line number Diff line number Diff line change
Expand Up @@ -832,6 +832,9 @@ typedef void* FlutterVulkanQueueHandle;
/// Alias for VkImage.
typedef uint64_t FlutterVulkanImageHandle;

/// Alias for VkDeviceMemory.
typedef uint64_t FlutterVulkanDeviceMemoryHandle;

typedef struct {
/// The size of this struct. Must be sizeof(FlutterVulkanImage).
size_t struct_size;
Expand Down Expand Up @@ -860,6 +863,42 @@ typedef bool (*FlutterVulkanPresentCallback)(
void* /* user data */,
const FlutterVulkanImage* /* image */);

typedef struct {
/// Handle to the VkImage that is owned by the embedder. The engine will
/// bind this image for writing the frame.
FlutterVulkanImageHandle image;
/// The VkDeviceMemory that backs the iamge.
FlutterVulkanDeviceMemoryHandle image_memory;
/// The VkFormat of the image (for example: VK_FORMAT_R8G8B8A8_UNORM).
uint32_t format;
/// The linear tiling features of the image (for example:
/// VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT).
uint32_t format_features;

uint64_t alloc_size;

/// User data to be returned on the invocation of the destruction callback.
void* user_data;
/// Callback invoked (on an engine managed thread) that asks the embedder to
/// collect the texture.
VoidCallback destruction_callback;
/// Optional parameters for texture height/width, default is 0, non-zero means
/// the texture has the specified width/height.
/// Width of the texture.
size_t width;
/// Height of the texture.
size_t height;
} FlutterVulkanTexture;

/// Callback to provide an external texture for a given texture_id.
/// See: external_texture_frame_callback.
typedef bool (*FlutterVulkanTextureFrameCallback)(
void* /* user data */,
int64_t /* texture identifier */,
size_t /* width */,
size_t /* height */,
FlutterVulkanTexture* /* texture out */);

typedef struct {
/// The size of this struct. Must be sizeof(FlutterVulkanRendererConfig).
size_t struct_size;
Expand Down Expand Up @@ -923,7 +962,11 @@ typedef struct {
/// without any additional synchronization.
/// Not used if a FlutterCompositor is supplied in FlutterProjectArgs.
FlutterVulkanPresentCallback present_image_callback;

/// When the embedder specifies that a texture has a frame available, the
/// engine will call this method (on an internal engine managed thread) so
/// that external texture details can be supplied to the engine for subsequent
/// composition.
FlutterVulkanTextureFrameCallback external_texture_frame_callback;
} FlutterVulkanRendererConfig;

typedef struct {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ EmbedderExternalTextureResolver::EmbedderExternalTextureResolver(
: metal_callback_(std::move(metal_callback)) {}
#endif

#ifdef SHELL_ENABLE_VULKAN
EmbedderExternalTextureResolver::EmbedderExternalTextureResolver(
EmbedderExternalTextureVulkan::ExternalTextureCallback vulkan_callback)
: vulkan_callback_(std::move(vulkan_callback)) {}
#endif

std::unique_ptr<Texture>
EmbedderExternalTextureResolver::ResolveExternalTexture(int64_t texture_id) {
#ifdef SHELL_ENABLE_GL
Expand All @@ -37,6 +43,13 @@ EmbedderExternalTextureResolver::ResolveExternalTexture(int64_t texture_id) {
}
#endif

#ifdef SHELL_ENABLE_VULKAN
if (vulkan_callback_) {
return std::make_unique<EmbedderExternalTextureVulkan>(
texture_id, vulkan_callback_);
}
#endif

return nullptr;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@
#include "flutter/shell/platform/embedder/embedder_external_texture_metal.h"
#endif

#ifdef SHELL_ENABLE_VULKAN
#include "flutter/shell/platform/embedder/embedder_external_texture_vulkan.h"
#endif

namespace flutter {
class EmbedderExternalTextureResolver {
public:
Expand All @@ -34,6 +38,11 @@ class EmbedderExternalTextureResolver {
EmbedderExternalTextureMetal::ExternalTextureCallback metal_callback);
#endif

#ifdef SHELL_ENABLE_VULKAN
explicit EmbedderExternalTextureResolver(
EmbedderExternalTextureVulkan::ExternalTextureCallback vulkan_callback);
#endif

std::unique_ptr<Texture> ResolveExternalTexture(int64_t texture_id);

bool SupportsExternalTextures();
Expand All @@ -47,6 +56,9 @@ class EmbedderExternalTextureResolver {
EmbedderExternalTextureMetal::ExternalTextureCallback metal_callback_;
#endif

#ifdef SHELL_ENABLE_VULKAN
EmbedderExternalTextureVulkan::ExternalTextureCallback vulkan_callback_;
#endif
FML_DISALLOW_COPY_AND_ASSIGN(EmbedderExternalTextureResolver);
};
} // namespace flutter
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "flutter/shell/platform/embedder/embedder_external_texture_source_vulkan.h"

#include "impeller/renderer/backend/vulkan/allocator_vk.h"
#include "impeller/renderer/backend/vulkan/context_vk.h"
#include "impeller/renderer/backend/vulkan/texture_source_vk.h"
#include "impeller/renderer/backend/vulkan/yuv_conversion_library_vk.h"
#include "vulkan/vulkan.hpp"

namespace flutter {

EmbedderExternalTextureSourceVulkan::EmbedderExternalTextureSourceVulkan(
const std::shared_ptr<impeller::Context>& p_context,
FlutterVulkanTexture* embedder_desc)
: TextureSourceVK(ToTextureDescriptor(embedder_desc)) {
const auto& context = impeller::ContextVK::Cast(*p_context);
const auto& device = context.GetDevice();
texture_image_ =
impeller::vk::Image(reinterpret_cast<VkImage>(embedder_desc->image));
texture_device_memory_ = impeller::vk::DeviceMemory(
reinterpret_cast<VkDeviceMemory>(embedder_desc->image_memory));
// Figure out how to perform YUV conversions.
auto yuv_conversion = CreateYUVConversion(context, embedder_desc);
if (!yuv_conversion || !yuv_conversion->IsValid()) {
VALIDATION_LOG << "Fail to create yuv conversion";
return;
}

// Create image view for the newly created image.
if (!CreateTextureImageView(device)) {
VALIDATION_LOG << "Fail to create texture image view";
return;
}

yuv_conversion_ = std::move(yuv_conversion);
is_valid_ = true;
}

impeller::PixelFormat ToPixelFormat(int32_t vk_format) {
switch (vk_format) {
case VK_FORMAT_UNDEFINED:
return impeller::PixelFormat::kUnknown;
case VK_FORMAT_R8G8B8A8_UNORM:
return impeller::PixelFormat::kR8G8B8A8UNormInt;
case VK_FORMAT_R8G8B8A8_SRGB:
return impeller::PixelFormat::kR8G8B8A8UNormIntSRGB;
case VK_FORMAT_B8G8R8A8_UNORM:
return impeller::PixelFormat::kB8G8R8A8UNormInt;
case VK_FORMAT_B8G8R8A8_SRGB:
return impeller::PixelFormat::kB8G8R8A8UNormIntSRGB;
case VK_FORMAT_R32G32B32A32_SFLOAT:
return impeller::PixelFormat::kR32G32B32A32Float;
case VK_FORMAT_R16G16B16A16_SFLOAT:
return impeller::PixelFormat::kR16G16B16A16Float;
case VK_FORMAT_S8_UINT:
return impeller::PixelFormat::kS8UInt;
case VK_FORMAT_D24_UNORM_S8_UINT:
return impeller::PixelFormat::kD24UnormS8Uint;
case VK_FORMAT_D32_SFLOAT_S8_UINT:
return impeller::PixelFormat::kD32FloatS8UInt;
case VK_FORMAT_R8_UNORM:
return impeller::PixelFormat::kR8UNormInt;
case VK_FORMAT_R8G8_UNORM:
return impeller::PixelFormat::kR8G8UNormInt;
default:
return impeller::PixelFormat::kUnknown;
}
}

impeller::TextureDescriptor
EmbedderExternalTextureSourceVulkan::ToTextureDescriptor(
FlutterVulkanTexture* embedder_desc) {
const auto size =
impeller::ISize{embedder_desc->width, embedder_desc->height};
impeller::TextureDescriptor desc;
desc.storage_mode = impeller::StorageMode::kDevicePrivate;
desc.format = ToPixelFormat(embedder_desc->format);
desc.size = size;
desc.type = impeller::TextureType::kTexture2D;
desc.sample_count = impeller::SampleCount::kCount1;
desc.compression_type = impeller::CompressionType::kLossless;
desc.mip_count = 1u;
desc.usage = impeller::TextureUsage::kRenderTarget;
return desc;
}

std::shared_ptr<impeller::YUVConversionVK>
EmbedderExternalTextureSourceVulkan::CreateYUVConversion(
const impeller::ContextVK& context,
FlutterVulkanTexture* embedder_desc) {
impeller::YUVConversionDescriptorVK conversion_chain;
auto& conversion_info = conversion_chain.get();

conversion_info.format =
static_cast<impeller::vk::Format>(embedder_desc->format);
conversion_info.ycbcrModel =
impeller::vk::SamplerYcbcrModelConversion::eYcbcr709;
conversion_info.ycbcrRange = impeller::vk::SamplerYcbcrRange::eItuFull;
conversion_info.components = {impeller::vk::ComponentSwizzle::eIdentity,
impeller::vk::ComponentSwizzle::eIdentity,
impeller::vk::ComponentSwizzle::eIdentity,
impeller::vk::ComponentSwizzle::eIdentity};
conversion_info.xChromaOffset = impeller::vk::ChromaLocation::eCositedEven;
conversion_info.yChromaOffset = impeller::vk::ChromaLocation::eCositedEven;
conversion_info.chromaFilter = impeller::vk::Filter::eNearest;
conversion_info.forceExplicitReconstruction = false;
return context.GetYUVConversionLibrary()->GetConversion(conversion_chain);
}

bool EmbedderExternalTextureSourceVulkan::CreateTextureImageView(
const impeller::vk::Device& device) {
impeller::vk::StructureChain<impeller::vk::ImageViewCreateInfo,
impeller::vk::SamplerYcbcrConversionInfo>
view_chain;
auto& view_info = view_chain.get();
view_info.image = texture_image_;
view_info.viewType = impeller::vk::ImageViewType::e2D;
view_info.format = impeller::vk::Format::eR8G8B8A8Srgb;
view_info.subresourceRange.aspectMask =
impeller::vk::ImageAspectFlagBits::eColor;
view_info.subresourceRange.baseMipLevel = 0u;
view_info.subresourceRange.baseArrayLayer = 0u;
view_info.subresourceRange.levelCount = 1;
view_info.subresourceRange.layerCount = 1;
auto image_view = device.createImageViewUnique(view_info);
if (image_view.result != impeller::vk::Result::eSuccess) {
VALIDATION_LOG << "Could not create external image view: "
<< impeller::vk::to_string(image_view.result);
return false;
}
texture_image_view_ = std::move(image_view.value);
return true;
}

// |TextureSourceVK|
EmbedderExternalTextureSourceVulkan::~EmbedderExternalTextureSourceVulkan() =
default;

bool EmbedderExternalTextureSourceVulkan::IsValid() const {
return is_valid_;
}

// |TextureSourceVK|
impeller::vk::Image EmbedderExternalTextureSourceVulkan::GetImage() const {
return texture_image_;
}

// |TextureSourceVK|
impeller::vk::ImageView EmbedderExternalTextureSourceVulkan::GetImageView()
const {
return texture_image_view_.get();
}

// |TextureSourceVK|
impeller::vk::ImageView
EmbedderExternalTextureSourceVulkan::GetRenderTargetView() const {
return texture_image_view_.get();
}

// |TextureSourceVK|
bool EmbedderExternalTextureSourceVulkan::IsSwapchainImage() const {
return is_swapchain_image_;
}

// |TextureSourceVK|
std::shared_ptr<impeller::YUVConversionVK>
EmbedderExternalTextureSourceVulkan::GetYUVConversion() const {
return needs_yuv_conversion_ ? yuv_conversion_ : nullptr;
}

} // namespace flutter
Loading
Loading