Commit cb73a634 authored by Peng Huang's avatar Peng Huang Committed by Commit Bot

ExternalVkImage: support interop on Windows.

Tested with AMD GPU on WIndows 10.

Bug: 1067709
Change-Id: I0c7147ef6e2cb9338304f5692f66f6e0715986c9
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2135980Reviewed-by: default avatarVasiliy Telezhnikov <vasilyt@chromium.org>
Commit-Queue: Peng Huang <penghuang@chromium.org>
Cr-Commit-Position: refs/heads/master@{#756465}
parent 60fbe32d
......@@ -37,19 +37,15 @@
#include "gpu/vulkan/fuchsia/vulkan_fuchsia_ext.h"
#endif
#if defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_FUCHSIA)
#define GL_DEDICATED_MEMORY_OBJECT_EXT 0x9581
#define GL_TEXTURE_TILING_EXT 0x9580
#define GL_TILING_TYPES_EXT 0x9583
#define GL_OPTIMAL_TILING_EXT 0x9584
#define GL_LINEAR_TILING_EXT 0x9585
#define GL_HANDLE_TYPE_OPAQUE_FD_EXT 0x9586
#endif
#if defined(OS_FUCHSIA)
#define GL_HANDLE_TYPE_OPAQUE_WIN32_EXT 0x9587
#define GL_HANDLE_TYPE_ZIRCON_VMO_ANGLE 0x93AE
#define GL_HANDLE_TYPE_ZIRCON_EVENT_ANGLE 0x93AF
#endif
namespace gpu {
......@@ -536,8 +532,6 @@ ExternalVkImageBacking::ProduceDawn(SharedImageManager* manager,
}
GLuint ExternalVkImageBacking::ProduceGLTextureInternal() {
#if defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_FUCHSIA) || \
defined(OS_WIN)
GrVkImageInfo image_info;
bool result = backend_texture_.getVkImageInfo(&image_info);
DCHECK(result);
......@@ -558,6 +552,19 @@ GLuint ExternalVkImageBacking::ProduceGLTextureInternal() {
api->glImportMemoryFdEXTFn(memory_object, image_info.fAlloc.fSize,
GL_HANDLE_TYPE_OPAQUE_FD_EXT,
memory_fd.release());
#elif defined(OS_WIN)
auto memory_handle = image_->GetMemoryHandle();
if (!memory_handle.IsValid()) {
return 0;
}
api->glCreateMemoryObjectsEXTFn(1, &memory_object);
int dedicated = GL_TRUE;
api->glMemoryObjectParameterivEXTFn(
memory_object, GL_DEDICATED_MEMORY_OBJECT_EXT, &dedicated);
api->glImportMemoryWin32HandleEXTFn(memory_object, image_info.fAlloc.fSize,
GL_HANDLE_TYPE_OPAQUE_WIN32_EXT,
memory_handle.Take());
#elif defined(OS_FUCHSIA)
zx::vmo vmo = image_->GetMemoryZirconHandle();
if (!vmo)
......@@ -570,10 +577,6 @@ GLuint ExternalVkImageBacking::ProduceGLTextureInternal() {
api->glImportMemoryZirconHandleANGLEFn(
memory_object, image_info.fAlloc.fSize, GL_HANDLE_TYPE_ZIRCON_VMO_ANGLE,
vmo.release());
#elif defined(OS_WIN)
// TODO(penghuang): support interop on Windows
NOTIMPLEMENTED();
return 0;
#else
#error Unsupported OS
#endif
......@@ -608,9 +611,6 @@ GLuint ExternalVkImageBacking::ProduceGLTextureInternal() {
}
api->glBindTextureFn(GL_TEXTURE_2D, old_texture_binding);
return texture_service_id;
#else // !defined(OS_LINUX) && !defined(OS_ANDROID) && !defined(OS_FUCHSIA)
#error Unsupported OS
#endif
}
std::unique_ptr<SharedImageRepresentationGLTexture>
......@@ -622,8 +622,6 @@ ExternalVkImageBacking::ProduceGLTexture(SharedImageManager* manager,
return nullptr;
}
#if defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_FUCHSIA) || \
defined(OS_WIN)
if (!texture_) {
GLuint texture_service_id = ProduceGLTextureInternal();
if (!texture_service_id)
......@@ -651,9 +649,6 @@ ExternalVkImageBacking::ProduceGLTexture(SharedImageManager* manager,
}
return std::make_unique<ExternalVkImageGLRepresentation>(
manager, this, tracker, texture_, texture_->service_id());
#else
#error Unsupported OS
#endif
}
std::unique_ptr<SharedImageRepresentationGLTexturePassthrough>
......@@ -666,8 +661,6 @@ ExternalVkImageBacking::ProduceGLTexturePassthrough(
return nullptr;
}
#if defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_FUCHSIA) || \
defined(OS_WIN)
if (!texture_passthrough_) {
GLuint texture_service_id = ProduceGLTextureInternal();
if (!texture_service_id)
......@@ -684,9 +677,6 @@ ExternalVkImageBacking::ProduceGLTexturePassthrough(
return std::make_unique<ExternalVkImageGLPassthroughRepresentation>(
manager, this, tracker, texture_passthrough_->service_id());
#else
#error Unsupported OS
#endif
}
std::unique_ptr<SharedImageRepresentationSkia>
......
......@@ -24,11 +24,9 @@
#define GL_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_EXT 0x9531
#define GL_HANDLE_TYPE_OPAQUE_FD_EXT 0x9586
#if defined(OS_FUCHSIA)
#define GL_HANDLE_TYPE_OPAQUE_WIN32_EXT 0x9587
#define GL_HANDLE_TYPE_ZIRCON_VMO_ANGLE 0x93AE
#define GL_HANDLE_TYPE_ZIRCON_EVENT_ANGLE 0x93AF
#endif
namespace gpu {
......@@ -202,6 +200,21 @@ GLuint ExternalVkImageGLRepresentationShared::ImportVkSemaphoreIntoGL(
api->glImportSemaphoreFdEXTFn(gl_semaphore, GL_HANDLE_TYPE_OPAQUE_FD_EXT,
fd.release());
return gl_semaphore;
#elif defined(OS_WIN)
if (handle.vk_handle_type() !=
VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT) {
DLOG(ERROR) << "Importing semaphore handle of unexpected type:"
<< handle.vk_handle_type();
return 0;
}
auto win32_handle = handle.TakeHandle();
gl::GLApi* api = gl::g_current_gl_context;
GLuint gl_semaphore;
api->glGenSemaphoresEXTFn(1, &gl_semaphore);
api->glImportSemaphoreWin32HandleEXTFn(
gl_semaphore, GL_HANDLE_TYPE_OPAQUE_WIN32_EXT, win32_handle.Take());
return gl_semaphore;
#elif defined(OS_FUCHSIA)
if (handle.vk_handle_type() !=
......@@ -217,9 +230,6 @@ GLuint ExternalVkImageGLRepresentationShared::ImportVkSemaphoreIntoGL(
api->glImportSemaphoreZirconHandleANGLEFn(
gl_semaphore, GL_HANDLE_TYPE_ZIRCON_EVENT_ANGLE, event.release());
return gl_semaphore;
#elif defined(OS_WIN)
NOTIMPLEMENTED();
return 0;
#else
#error Unsupported OS
#endif
......
......@@ -341,13 +341,13 @@ bool SharedContextState::InitializeGL(
gpu_preferences.use_vulkan ==
gpu::VulkanImplementationName::kForcedNative;
// Swiftshader GL and Vulkan report supporting external objects extensions,
// but they don't.
bool gl_supports_memory_object =
gl::g_current_gl_driver->ext.b_GL_EXT_memory_object_fd ||
gl::g_current_gl_driver->ext.b_GL_EXT_memory_object_win32 ||
gl::g_current_gl_driver->ext.b_GL_ANGLE_memory_object_fuchsia;
bool gl_supports_semaphore =
gl::g_current_gl_driver->ext.b_GL_EXT_semaphore_fd ||
gl::g_current_gl_driver->ext.b_GL_EXT_semaphore_win32 ||
gl::g_current_gl_driver->ext.b_GL_ANGLE_semaphore_fuchsia;
bool vk_supports_external_memory = false;
bool vk_supports_external_semaphore = false;
......@@ -355,16 +355,17 @@ bool SharedContextState::InitializeGL(
if (vk_context_provider_) {
const auto& extensions =
vk_context_provider_->GetDeviceQueue()->enabled_extensions();
#if !defined(OS_FUCHSIA)
#if defined(OS_WIN)
vk_supports_external_memory =
gfx::HasExtension(extensions, VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME) &&
gfx::HasExtension(extensions, VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME);
gfx::HasExtension(extensions,
VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME);
vk_supports_external_semaphore =
gfx::HasExtension(extensions,
VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME) &&
gfx::HasExtension(extensions,
VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME);
#else
VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME);
#elif defined(OS_FUCHSIA)
vk_supports_external_memory =
gfx::HasExtension(extensions, VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME) &&
gfx::HasExtension(extensions,
......@@ -374,10 +375,21 @@ bool SharedContextState::InitializeGL(
VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME) &&
gfx::HasExtension(extensions,
VK_FUCHSIA_EXTERNAL_SEMAPHORE_EXTENSION_NAME);
#else
vk_supports_external_memory =
gfx::HasExtension(extensions, VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME) &&
gfx::HasExtension(extensions, VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME);
vk_supports_external_semaphore =
gfx::HasExtension(extensions,
VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME) &&
gfx::HasExtension(extensions,
VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME);
#endif
}
#endif // BUILDFLAG(ENABLE_VULKAN)
// Swiftshader GL and Vulkan report supporting external objects extensions,
// but they don't.
support_vulkan_external_object_ =
!gl::g_current_gl_version->is_swiftshader && is_native_vulkan &&
gl_supports_memory_object && gl_supports_semaphore &&
......
......@@ -28,6 +28,9 @@ if (enable_vulkan) {
if (is_fuchsia) {
defines = [ "VK_USE_PLATFORM_FUCHSIA" ]
}
if (is_win) {
defines = [ "VK_USE_PLATFORM_WIN32_KHR" ]
}
}
jumbo_component("vulkan") {
......@@ -89,7 +92,10 @@ if (enable_vulkan) {
}
if (is_win) {
sources += [ "vulkan_image_win.cc" ]
sources += [
"vulkan_image_win.cc",
"vulkan_util_win32.cc",
]
}
if (is_fuchsia) {
......
......@@ -15,10 +15,6 @@
#include "gpu/vulkan/vulkan_device_queue.h"
#include "gpu/vulkan/vulkan_function_pointers.h"
#if defined(OS_FUCHSIA)
#include "gpu/vulkan/fuchsia/vulkan_fuchsia_ext.h"
#endif
namespace gpu {
namespace {
......@@ -164,30 +160,7 @@ base::ScopedFD VulkanImage::GetMemoryFd(
return base::ScopedFD(memory_fd);
}
#endif
#if defined(OS_FUCHSIA)
zx::vmo VulkanImage::GetMemoryZirconHandle() {
DCHECK(handle_types_ &
VK_EXTERNAL_MEMORY_HANDLE_TYPE_TEMP_ZIRCON_VMO_BIT_FUCHSIA);
VkMemoryGetZirconHandleInfoFUCHSIA get_handle_info = {
.sType = VK_STRUCTURE_TYPE_TEMP_MEMORY_GET_ZIRCON_HANDLE_INFO_FUCHSIA,
.memory = device_memory_,
.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_TEMP_ZIRCON_VMO_BIT_FUCHSIA,
};
VkDevice device = device_queue_->GetVulkanDevice();
zx::vmo vmo;
VkResult result = vkGetMemoryZirconHandleFUCHSIA(device, &get_handle_info,
vmo.reset_and_get_address());
if (result != VK_SUCCESS) {
DLOG(ERROR) << "vkGetMemoryFuchsiaHandleKHR failed: " << result;
vmo.reset();
}
return vmo;
}
#endif
#endif // defined(OS_POSIX)
bool VulkanImage::Initialize(VulkanDeviceQueue* device_queue,
const gfx::Size& size,
......@@ -300,6 +273,8 @@ bool VulkanImage::InitializeWithExternalMemory(VulkanDeviceQueue* device_queue,
#if defined(OS_FUCHSIA)
constexpr auto kHandleType =
VK_EXTERNAL_MEMORY_HANDLE_TYPE_TEMP_ZIRCON_VMO_BIT_FUCHSIA;
#elif defined(OS_WIN)
constexpr auto kHandleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT;
#else
constexpr auto kHandleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT;
#endif
......
......@@ -16,6 +16,10 @@
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/gpu_memory_buffer.h"
#if defined(OS_WIN)
#include "base/win/scoped_handle.h"
#endif
#if defined(OS_FUCHSIA)
#include <lib/zx/vmo.h>
#endif
......@@ -79,6 +83,12 @@ class VULKAN_EXPORT VulkanImage {
VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT);
#endif
#if defined(OS_WIN)
base::win::ScopedHandle GetMemoryHandle(
VkExternalMemoryHandleTypeFlagBits handle_type =
VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT);
#endif
#if defined(OS_FUCHSIA)
zx::vmo GetMemoryZirconHandle();
#endif
......
......@@ -4,6 +4,10 @@
#include "gpu/vulkan/vulkan_image.h"
#include "gpu/vulkan/fuchsia/vulkan_fuchsia_ext.h"
#include "gpu/vulkan/vulkan_device_queue.h"
#include "gpu/vulkan/vulkan_function_pointers.h"
namespace gpu {
bool VulkanImage::InitializeFromGpuMemoryBufferHandle(
......@@ -18,4 +22,25 @@ bool VulkanImage::InitializeFromGpuMemoryBufferHandle(
return false;
}
zx::vmo VulkanImage::GetMemoryZirconHandle() {
DCHECK(handle_types_ &
VK_EXTERNAL_MEMORY_HANDLE_TYPE_TEMP_ZIRCON_VMO_BIT_FUCHSIA);
VkMemoryGetZirconHandleInfoFUCHSIA get_handle_info = {
.sType = VK_STRUCTURE_TYPE_TEMP_MEMORY_GET_ZIRCON_HANDLE_INFO_FUCHSIA,
.memory = device_memory_,
.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_TEMP_ZIRCON_VMO_BIT_FUCHSIA,
};
VkDevice device = device_queue_->GetVulkanDevice();
zx::vmo vmo;
VkResult result = vkGetMemoryZirconHandleFUCHSIA(device, &get_handle_info,
vmo.reset_and_get_address());
if (result != VK_SUCCESS) {
DLOG(ERROR) << "vkGetMemoryFuchsiaHandleKHR failed: " << result;
vmo.reset();
}
return vmo;
}
} // namespace gpu
......@@ -4,6 +4,9 @@
#include "gpu/vulkan/vulkan_image.h"
#include "gpu/vulkan/vulkan_device_queue.h"
#include "gpu/vulkan/vulkan_function_pointers.h"
namespace gpu {
bool VulkanImage::InitializeFromGpuMemoryBufferHandle(
......@@ -18,4 +21,24 @@ bool VulkanImage::InitializeFromGpuMemoryBufferHandle(
return false;
}
base::win::ScopedHandle VulkanImage::GetMemoryHandle(
VkExternalMemoryHandleTypeFlagBits handle_type) {
VkMemoryGetWin32HandleInfoKHR get_handle_info = {
.sType = VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR,
.memory = device_memory_,
.handleType = handle_type,
};
VkDevice device = device_queue_->GetVulkanDevice();
HANDLE handle = nullptr;
vkGetMemoryWin32HandleKHR(device, &get_handle_info, &handle);
if (handle == nullptr) {
DLOG(ERROR) << "Unable to extract file handle out of external VkImage";
return base::win::ScopedHandle();
}
return base::win::ScopedHandle(handle);
}
} // namespace gpu
// Copyright 2019 The Chromium 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 "gpu/vulkan/vulkan_util.h"
#include "gpu/vulkan/vulkan_function_pointers.h"
namespace gpu {
VkSemaphore ImportVkSemaphoreHandle(VkDevice vk_device,
SemaphoreHandle handle) {
auto handle_type = handle.vk_handle_type();
if (!handle.is_valid() ||
handle_type != VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT) {
return VK_NULL_HANDLE;
}
VkSemaphore semaphore = VK_NULL_HANDLE;
VkSemaphoreCreateInfo info = {VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO};
VkResult result = vkCreateSemaphore(vk_device, &info, nullptr, &semaphore);
if (result != VK_SUCCESS)
return VK_NULL_HANDLE;
auto win32_handle = handle.TakeHandle();
VkImportSemaphoreWin32HandleInfoKHR import = {
.sType = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR,
.semaphore = semaphore,
.handleType = handle_type,
.handle = win32_handle.Get(),
};
result = vkImportSemaphoreWin32HandleKHR(vk_device, &import);
if (result != VK_SUCCESS) {
vkDestroySemaphore(vk_device, semaphore, nullptr);
return VK_NULL_HANDLE;
}
// If import is successful, the VkSemaphore takes the ownership of the fd.
ignore_result(win32_handle.Take());
return semaphore;
}
SemaphoreHandle GetVkSemaphoreHandle(
VkDevice vk_device,
VkSemaphore vk_semaphore,
VkExternalSemaphoreHandleTypeFlagBits handle_type) {
VkSemaphoreGetWin32HandleInfoKHR info = {
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR,
.semaphore = vk_semaphore,
.handleType = handle_type,
};
HANDLE handle = nullptr;
VkResult result = vkGetSemaphoreWin32HandleKHR(vk_device, &info, &handle);
if (result != VK_SUCCESS) {
LOG(ERROR) << "vkGetSemaphoreFdKHR failed : " << result;
return SemaphoreHandle();
}
return SemaphoreHandle(handle_type, base::win::ScopedHandle(handle));
}
} // namespace gpu
......@@ -12,6 +12,7 @@
#include "gpu/vulkan/vulkan_image.h"
#include "gpu/vulkan/vulkan_instance.h"
#include "gpu/vulkan/vulkan_surface.h"
#include "gpu/vulkan/vulkan_util.h"
#include "ui/gfx/gpu_fence.h"
#include "ui/gfx/gpu_memory_buffer.h"
......@@ -25,6 +26,8 @@ VulkanImplementationWin32::~VulkanImplementationWin32() = default;
bool VulkanImplementationWin32::InitializeVulkanInstance(bool using_surface) {
DCHECK(using_surface);
std::vector<const char*> required_extensions = {
VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME,
VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME,
VK_KHR_SURFACE_EXTENSION_NAME,
VK_KHR_WIN32_SURFACE_EXTENSION_NAME,
};
......@@ -87,7 +90,12 @@ VulkanImplementationWin32::GetRequiredDeviceExtensions() {
std::vector<const char*>
VulkanImplementationWin32::GetOptionalDeviceExtensions() {
return {};
return {
VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME,
VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME,
VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME,
VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME,
};
}
VkFence VulkanImplementationWin32::CreateVkFenceForGpuFence(
......@@ -105,21 +113,22 @@ VulkanImplementationWin32::ExportVkFenceToGpuFence(VkDevice vk_device,
VkSemaphore VulkanImplementationWin32::CreateExternalSemaphore(
VkDevice vk_device) {
NOTIMPLEMENTED();
return VK_NULL_HANDLE;
return CreateExternalVkSemaphore(
vk_device, VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT);
}
VkSemaphore VulkanImplementationWin32::ImportSemaphoreHandle(
VkDevice vk_device,
SemaphoreHandle handle) {
NOTIMPLEMENTED();
return VK_NULL_HANDLE;
return ImportVkSemaphoreHandle(vk_device, std::move(handle));
}
SemaphoreHandle VulkanImplementationWin32::GetSemaphoreHandle(
VkDevice vk_device,
VkSemaphore vk_semaphore) {
return SemaphoreHandle();
return GetVkSemaphoreHandle(
vk_device, vk_semaphore,
VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT);
}
VkExternalMemoryHandleTypeFlagBits
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment