Commit 5c8c9a69 authored by Peng Huang's avatar Peng Huang Committed by Commit Bot

vulkan: reuse gl semaphores

For passthrough, with extension EGL_ANGLE_display_semaphore_share_group,
semaphores are shared globally.
For GLES2Decoder, all GL contexts are in the same shared group, so
semaphores are also shared globally.
So we can reused GL semaphores cross GL contexts.

Bug: 1004772
Change-Id: I1d23cdc991b2e99d6fe70fdd0560c97dafe73e7c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2319368
Commit-Queue: Peng Huang <penghuang@chromium.org>
Reviewed-by: default avatarJonathan Backer <backer@chromium.org>
Reviewed-by: default avatarVasiliy Telezhnikov <vasilyt@chromium.org>
Cr-Commit-Position: refs/heads/master@{#793398}
parent d1f8824d
...@@ -165,7 +165,12 @@ void ExternalSemaphore::Reset() { ...@@ -165,7 +165,12 @@ void ExternalSemaphore::Reset() {
} }
if (gl_semaphore_ != 0) { if (gl_semaphore_ != 0) {
if (gl::GLApi* api = gl::g_current_gl_context) auto* current_gl = gl::g_current_gl_context_tls->Get();
auto* api = current_gl->Driver ? current_gl->Api : nullptr;
// We assume there is always one GL context current. If there isn't a
// GL context current, we assume the last GL context is destroyed, in that
// case, we will skip glDeleteSemaphoresEXT().
if (api)
api->glDeleteSemaphoresEXTFn(1, &gl_semaphore_); api->glDeleteSemaphoresEXTFn(1, &gl_semaphore_);
} }
...@@ -183,12 +188,6 @@ unsigned int ExternalSemaphore::GetGLSemaphore() { ...@@ -183,12 +188,6 @@ unsigned int ExternalSemaphore::GetGLSemaphore() {
return gl_semaphore_; return gl_semaphore_;
} }
unsigned int ExternalSemaphore::TakeGLSemaphore() {
auto gl_semaphore = GetGLSemaphore();
gl_semaphore_ = 0;
return gl_semaphore;
}
VkSemaphore ExternalSemaphore::GetVkSemaphore() { VkSemaphore ExternalSemaphore::GetVkSemaphore() {
DCHECK(handle_.is_valid()); DCHECK(handle_.is_valid());
if (semaphore_ == VK_NULL_HANDLE) { if (semaphore_ == VK_NULL_HANDLE) {
......
...@@ -39,9 +39,8 @@ class ExternalSemaphore { ...@@ -39,9 +39,8 @@ class ExternalSemaphore {
void Reset(); void Reset();
// Take the GL semaphore. The ownership is transferred to caller. The caller // Get the GL semaphore. The ownership is not transferred to caller.
// is responsible for releasing it. unsigned int GetGLSemaphore();
unsigned int TakeGLSemaphore();
// Get a VkSemaphore. The ownership is not transferred to caller. // Get a VkSemaphore. The ownership is not transferred to caller.
VkSemaphore GetVkSemaphore(); VkSemaphore GetVkSemaphore();
...@@ -50,13 +49,6 @@ class ExternalSemaphore { ...@@ -50,13 +49,6 @@ class ExternalSemaphore {
SemaphoreHandle handle() { return handle_.Duplicate(); } SemaphoreHandle handle() { return handle_.Duplicate(); }
private: private:
// GL semaphore cannot be shared between passthrough GL contexts,
// since gl contexts are not created with the same global shared group with
// passthrough. So we cannot reuse GL semaphores safely.
// TODO(penghuang): share GL semaphore across GL contexts and reuse
// GL semaphores.
unsigned int GetGLSemaphore();
viz::VulkanContextProvider* context_provider_ = nullptr; viz::VulkanContextProvider* context_provider_ = nullptr;
VkSemaphore semaphore_ = VK_NULL_HANDLE; VkSemaphore semaphore_ = VK_NULL_HANDLE;
SemaphoreHandle handle_; SemaphoreHandle handle_;
......
...@@ -6,9 +6,11 @@ ...@@ -6,9 +6,11 @@
#include "build/build_config.h" #include "build/build_config.h"
#include "components/viz/common/gpu/vulkan_context_provider.h" #include "components/viz/common/gpu/vulkan_context_provider.h"
#include "gpu/command_buffer/service/shared_context_state.h"
#include "gpu/vulkan/vulkan_device_queue.h" #include "gpu/vulkan/vulkan_device_queue.h"
#include "gpu/vulkan/vulkan_fence_helper.h" #include "gpu/vulkan/vulkan_fence_helper.h"
#include "gpu/vulkan/vulkan_implementation.h" #include "gpu/vulkan/vulkan_implementation.h"
#include "ui/gl/gl_context.h"
namespace gpu { namespace gpu {
namespace { namespace {
...@@ -26,8 +28,8 @@ constexpr size_t kMaxSemaphoresInPool = 16; ...@@ -26,8 +28,8 @@ constexpr size_t kMaxSemaphoresInPool = 16;
} // namespace } // namespace
ExternalSemaphorePool::ExternalSemaphorePool( ExternalSemaphorePool::ExternalSemaphorePool(
viz::VulkanContextProvider* context_provider) SharedContextState* shared_context_state)
: context_provider_(context_provider) {} : shared_context_state_(shared_context_state) {}
ExternalSemaphorePool::~ExternalSemaphorePool() = default; ExternalSemaphorePool::~ExternalSemaphorePool() = default;
...@@ -37,7 +39,8 @@ ExternalSemaphore ExternalSemaphorePool::GetOrCreateSemaphore() { ...@@ -37,7 +39,8 @@ ExternalSemaphore ExternalSemaphorePool::GetOrCreateSemaphore() {
semaphores_.pop_front(); semaphores_.pop_front();
return semaphore; return semaphore;
} }
return ExternalSemaphore::Create(context_provider_); return ExternalSemaphore::Create(
shared_context_state_->vk_context_provider());
} }
void ExternalSemaphorePool::ReturnSemaphore(ExternalSemaphore semaphore) { void ExternalSemaphorePool::ReturnSemaphore(ExternalSemaphore semaphore) {
...@@ -50,16 +53,19 @@ void ExternalSemaphorePool::ReturnSemaphores( ...@@ -50,16 +53,19 @@ void ExternalSemaphorePool::ReturnSemaphores(
std::vector<ExternalSemaphore> semaphores) { std::vector<ExternalSemaphore> semaphores) {
DCHECK_LE(semaphores_.size(), kMaxSemaphoresInPool); DCHECK_LE(semaphores_.size(), kMaxSemaphoresInPool);
#if DCHECK_IS_ON() while (!semaphores.empty() && semaphores_.size() < kMaxSemaphoresInPool) {
for (auto& semaphore : semaphores) auto& semaphore = semaphores.back();
DCHECK(semaphore); DCHECK(semaphore);
#endif semaphores_.emplace_back(std::move(semaphore));
semaphores.pop_back();
}
std::move( if (semaphores.empty())
semaphores.begin(), return;
semaphores.begin() + std::min(kMaxSemaphoresInPool - semaphores_.size(),
semaphores.size()), // Need a GL context current for releasing semaphores.
std::back_inserter(semaphores_)); if (!gl::GLContext::GetCurrent())
shared_context_state_->MakeCurrent(/*surface=*/nullptr, /*needs_gl=*/true);
} }
void ExternalSemaphorePool::ReturnSemaphoresWithFenceHelper( void ExternalSemaphorePool::ReturnSemaphoresWithFenceHelper(
...@@ -71,7 +77,10 @@ void ExternalSemaphorePool::ReturnSemaphoresWithFenceHelper( ...@@ -71,7 +77,10 @@ void ExternalSemaphorePool::ReturnSemaphoresWithFenceHelper(
if (semaphores.empty()) if (semaphores.empty())
return; return;
auto* fence_helper = context_provider_->GetDeviceQueue()->GetFenceHelper();
auto* fence_helper = shared_context_state_->vk_context_provider()
->GetDeviceQueue()
->GetFenceHelper();
fence_helper->EnqueueCleanupTaskForSubmittedWork(base::BindOnce( fence_helper->EnqueueCleanupTaskForSubmittedWork(base::BindOnce(
[](base::WeakPtr<ExternalSemaphorePool> pool, [](base::WeakPtr<ExternalSemaphorePool> pool,
std::vector<ExternalSemaphore> semaphores, std::vector<ExternalSemaphore> semaphores,
......
...@@ -13,15 +13,13 @@ ...@@ -13,15 +13,13 @@
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "gpu/command_buffer/service/external_semaphore.h" #include "gpu/command_buffer/service/external_semaphore.h"
namespace viz {
class VulkanContextProvider;
}
namespace gpu { namespace gpu {
class SharedContextState;
class ExternalSemaphorePool { class ExternalSemaphorePool {
public: public:
explicit ExternalSemaphorePool(viz::VulkanContextProvider* context_provider); explicit ExternalSemaphorePool(SharedContextState* shared_context_state);
~ExternalSemaphorePool(); ~ExternalSemaphorePool();
ExternalSemaphorePool(const ExternalSemaphorePool&) = delete; ExternalSemaphorePool(const ExternalSemaphorePool&) = delete;
...@@ -43,7 +41,7 @@ class ExternalSemaphorePool { ...@@ -43,7 +41,7 @@ class ExternalSemaphorePool {
std::vector<ExternalSemaphore> semaphores); std::vector<ExternalSemaphore> semaphores);
private: private:
viz::VulkanContextProvider* const context_provider_; SharedContextState* const shared_context_state_;
base::circular_deque<ExternalSemaphore> semaphores_; base::circular_deque<ExternalSemaphore> semaphores_;
base::WeakPtrFactory<ExternalSemaphorePool> weak_ptr_factory_{this}; base::WeakPtrFactory<ExternalSemaphorePool> weak_ptr_factory_{this};
}; };
......
...@@ -400,7 +400,8 @@ bool ExternalVkImageBacking::BeginAccess( ...@@ -400,7 +400,8 @@ bool ExternalVkImageBacking::BeginAccess(
GLuint texture_id = texture_passthrough_ GLuint texture_id = texture_passthrough_
? texture_passthrough_->service_id() ? texture_passthrough_->service_id()
: texture_->service_id(); : texture_->service_id();
context_state()->MakeCurrent(/*gl_surface=*/nullptr, /*needs_gl=*/true); if (!gl::GLContext::GetCurrent())
context_state()->MakeCurrent(/*gl_surface=*/nullptr, /*needs_gl=*/true);
GrVkImageInfo info; GrVkImageInfo info;
auto result = backend_texture_.getVkImageInfo(&info); auto result = backend_texture_.getVkImageInfo(&info);
...@@ -482,7 +483,8 @@ void ExternalVkImageBacking::EndAccess(bool readonly, ...@@ -482,7 +483,8 @@ void ExternalVkImageBacking::EndAccess(bool readonly,
GLuint texture_id = texture_passthrough_ GLuint texture_id = texture_passthrough_
? texture_passthrough_->service_id() ? texture_passthrough_->service_id()
: texture_->service_id(); : texture_->service_id();
context_state()->MakeCurrent(/*gl_surface=*/nullptr, /*needs_gl=*/true); if (!gl::GLContext::GetCurrent())
context_state()->MakeCurrent(/*gl_surface=*/nullptr, /*needs_gl=*/true);
std::vector<ExternalSemaphore> external_semaphores; std::vector<ExternalSemaphore> external_semaphores;
BeginAccessInternal(true, &external_semaphores); BeginAccessInternal(true, &external_semaphores);
DCHECK_LE(external_semaphores.size(), 1u); DCHECK_LE(external_semaphores.size(), 1u);
...@@ -538,10 +540,18 @@ void ExternalVkImageBacking::AddSemaphoresToPendingListOrRelease( ...@@ -538,10 +540,18 @@ void ExternalVkImageBacking::AddSemaphoresToPendingListOrRelease(
// signalling but have not been signalled. In that case, we have to release // signalling but have not been signalled. In that case, we have to release
// them via fence helper to make sure all submitted GPU works is finished // them via fence helper to make sure all submitted GPU works is finished
// before releasing them. // before releasing them.
fence_helper()->EnqueueCleanupTaskForSubmittedWork( // |context_state_| is out live fence_helper, so it is safe to use
base::BindOnce([](std::vector<ExternalSemaphore>, // base::Unretained(context_state_).
VulkanDeviceQueue* device_queue, bool device_lost) {}, fence_helper()->EnqueueCleanupTaskForSubmittedWork(base::BindOnce(
std::move(semaphores))); [](SharedContextState* shared_context_state,
std::vector<ExternalSemaphore>, VulkanDeviceQueue* device_queue,
bool device_lost) {
if (!gl::GLContext::GetCurrent()) {
shared_context_state->MakeCurrent(/*surface=*/nullptr,
/*needs_gl=*/true);
}
},
base::Unretained(context_state_), std::move(semaphores)));
} }
} }
......
...@@ -58,13 +58,12 @@ void ExternalVkImageGLRepresentationShared::AcquireTexture( ...@@ -58,13 +58,12 @@ void ExternalVkImageGLRepresentationShared::AcquireTexture(
ExternalSemaphore* semaphore, ExternalSemaphore* semaphore,
GLuint texture_id, GLuint texture_id,
VkImageLayout src_layout) { VkImageLayout src_layout) {
GLuint gl_semaphore = semaphore->TakeGLSemaphore(); GLuint gl_semaphore = semaphore->GetGLSemaphore();
if (gl_semaphore) { if (gl_semaphore) {
GLenum gl_layout = ToGLImageLayout(src_layout); GLenum gl_layout = ToGLImageLayout(src_layout);
auto* api = gl::g_current_gl_context; auto* api = gl::g_current_gl_context;
api->glWaitSemaphoreEXTFn(gl_semaphore, 0, nullptr, 1, &texture_id, api->glWaitSemaphoreEXTFn(gl_semaphore, 0, nullptr, 1, &texture_id,
&gl_layout); &gl_layout);
api->glDeleteSemaphoresEXTFn(1, &gl_semaphore);
} }
} }
...@@ -83,7 +82,7 @@ ExternalSemaphore ExternalVkImageGLRepresentationShared::ReleaseTexture( ...@@ -83,7 +82,7 @@ ExternalSemaphore ExternalVkImageGLRepresentationShared::ReleaseTexture(
return {}; return {};
} }
GLuint gl_semaphore = semaphore.TakeGLSemaphore(); GLuint gl_semaphore = semaphore.GetGLSemaphore();
if (!gl_semaphore) { if (!gl_semaphore) {
// TODO(crbug.com/933452): We should be able to semaphore_handle this // TODO(crbug.com/933452): We should be able to semaphore_handle this
// failure more gracefully rather than shutting down the whole process. // failure more gracefully rather than shutting down the whole process.
...@@ -97,7 +96,6 @@ ExternalSemaphore ExternalVkImageGLRepresentationShared::ReleaseTexture( ...@@ -97,7 +96,6 @@ ExternalSemaphore ExternalVkImageGLRepresentationShared::ReleaseTexture(
auto* api = gl::g_current_gl_context; auto* api = gl::g_current_gl_context;
api->glSignalSemaphoreEXTFn(gl_semaphore, 0, nullptr, 1, &texture_id, api->glSignalSemaphoreEXTFn(gl_semaphore, 0, nullptr, 1, &texture_id,
&gl_layout); &gl_layout);
api->glDeleteSemaphoresEXTFn(1, &gl_semaphore);
// Base on the spec, the glSignalSemaphoreEXT() call just inserts signal // Base on the spec, the glSignalSemaphoreEXT() call just inserts signal
// semaphore command in the gl context. It may or may not flush the context // semaphore command in the gl context. It may or may not flush the context
// which depends on the implementation. So to make it safe, we always call // which depends on the implementation. So to make it safe, we always call
......
...@@ -55,9 +55,10 @@ gl::GLContextAttribs GenerateGLContextAttribs( ...@@ -55,9 +55,10 @@ gl::GLContextAttribs GenerateGLContextAttribs(
attribs.webgl_compatibility_context = attribs.webgl_compatibility_context =
IsWebGLContextType(attribs_helper.context_type); IsWebGLContextType(attribs_helper.context_type);
// Always use the global texture share group for the passthrough command // Always use the global texture and semaphore share group for the
// decoder // passthrough command decoder
attribs.global_texture_share_group = true; attribs.global_texture_share_group = true;
attribs.global_semaphore_share_group = true;
attribs.robust_resource_initialization = true; attribs.robust_resource_initialization = true;
attribs.robust_buffer_access = true; attribs.robust_buffer_access = true;
......
...@@ -139,7 +139,7 @@ SharedContextState::SharedContextState( ...@@ -139,7 +139,7 @@ SharedContextState::SharedContextState(
#if BUILDFLAG(ENABLE_VULKAN) #if BUILDFLAG(ENABLE_VULKAN)
gr_context_ = vk_context_provider_->GetGrContext(); gr_context_ = vk_context_provider_->GetGrContext();
external_semaphore_pool_ = external_semaphore_pool_ =
std::make_unique<ExternalSemaphorePool>(vk_context_provider_); std::make_unique<ExternalSemaphorePool>(this);
#endif #endif
use_virtualized_gl_contexts_ = false; use_virtualized_gl_contexts_ = false;
DCHECK(gr_context_); DCHECK(gr_context_);
......
...@@ -82,6 +82,7 @@ struct GL_EXPORT GLContextAttribs { ...@@ -82,6 +82,7 @@ struct GL_EXPORT GLContextAttribs {
bool bind_generates_resource = true; bool bind_generates_resource = true;
bool webgl_compatibility_context = false; bool webgl_compatibility_context = false;
bool global_texture_share_group = false; bool global_texture_share_group = false;
bool global_semaphore_share_group = false;
bool robust_resource_initialization = false; bool robust_resource_initialization = false;
bool robust_buffer_access = false; bool robust_buffer_access = false;
int client_major_es_version = 3; int client_major_es_version = 3;
......
...@@ -35,6 +35,11 @@ ...@@ -35,6 +35,11 @@
#define EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE 0x33AF #define EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE 0x33AF
#endif /* EGL_ANGLE_display_texture_share_group */ #endif /* EGL_ANGLE_display_texture_share_group */
#ifndef EGL_ANGLE_display_semaphore_share_group
#define EGL_ANGLE_display_semaphore_share_group 1
#define EGL_DISPLAY_SEMAPHORE_SHARE_GROUP_ANGLE 0x348D
#endif /* EGL_ANGLE_display_semaphore_share_group */
#ifndef EGL_ANGLE_create_context_client_arrays #ifndef EGL_ANGLE_create_context_client_arrays
#define EGL_ANGLE_create_context_client_arrays 1 #define EGL_ANGLE_create_context_client_arrays 1
#define EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE 0x3452 #define EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE 0x3452
...@@ -183,6 +188,14 @@ bool GLContextEGL::Initialize(GLSurface* compatible_surface, ...@@ -183,6 +188,14 @@ bool GLContextEGL::Initialize(GLSurface* compatible_surface,
DCHECK(!attribs.global_texture_share_group); DCHECK(!attribs.global_texture_share_group);
} }
if (GLSurfaceEGL::IsDisplaySemaphoreShareGroupSupported()) {
context_attributes.push_back(EGL_DISPLAY_SEMAPHORE_SHARE_GROUP_ANGLE);
context_attributes.push_back(
attribs.global_semaphore_share_group ? EGL_TRUE : EGL_FALSE);
} else {
DCHECK(!attribs.global_semaphore_share_group);
}
if (GLSurfaceEGL::IsCreateContextClientArraysSupported()) { if (GLSurfaceEGL::IsCreateContextClientArraysSupported()) {
// Disable client arrays if the context supports it // Disable client arrays if the context supports it
context_attributes.push_back(EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE); context_attributes.push_back(EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE);
......
...@@ -188,6 +188,7 @@ bool g_egl_ext_colorspace_display_p3_passthrough = false; ...@@ -188,6 +188,7 @@ bool g_egl_ext_colorspace_display_p3_passthrough = false;
bool g_egl_flexible_surface_compatibility_supported = false; bool g_egl_flexible_surface_compatibility_supported = false;
bool g_egl_robust_resource_init_supported = false; bool g_egl_robust_resource_init_supported = false;
bool g_egl_display_texture_share_group_supported = false; bool g_egl_display_texture_share_group_supported = false;
bool g_egl_display_semaphore_share_group_supported = false;
bool g_egl_create_context_client_arrays_supported = false; bool g_egl_create_context_client_arrays_supported = false;
bool g_egl_android_native_fence_sync_supported = false; bool g_egl_android_native_fence_sync_supported = false;
bool g_egl_ext_pixel_format_float_supported = false; bool g_egl_ext_pixel_format_float_supported = false;
...@@ -943,6 +944,8 @@ bool GLSurfaceEGL::InitializeOneOffCommon() { ...@@ -943,6 +944,8 @@ bool GLSurfaceEGL::InitializeOneOffCommon() {
g_egl_display_texture_share_group_supported = g_egl_display_texture_share_group_supported =
HasEGLExtension("EGL_ANGLE_display_texture_share_group"); HasEGLExtension("EGL_ANGLE_display_texture_share_group");
g_egl_display_semaphore_share_group_supported =
HasEGLExtension("EGL_ANGLE_display_semaphore_share_group");
g_egl_create_context_client_arrays_supported = g_egl_create_context_client_arrays_supported =
HasEGLExtension("EGL_ANGLE_create_context_client_arrays"); HasEGLExtension("EGL_ANGLE_create_context_client_arrays");
g_egl_robust_resource_init_supported = g_egl_robust_resource_init_supported =
...@@ -1115,6 +1118,10 @@ bool GLSurfaceEGL::IsDisplayTextureShareGroupSupported() { ...@@ -1115,6 +1118,10 @@ bool GLSurfaceEGL::IsDisplayTextureShareGroupSupported() {
return g_egl_display_texture_share_group_supported; return g_egl_display_texture_share_group_supported;
} }
bool GLSurfaceEGL::IsDisplaySemaphoreShareGroupSupported() {
return g_egl_display_semaphore_share_group_supported;
}
bool GLSurfaceEGL::IsCreateContextClientArraysSupported() { bool GLSurfaceEGL::IsCreateContextClientArraysSupported() {
return g_egl_create_context_client_arrays_supported; return g_egl_create_context_client_arrays_supported;
} }
......
...@@ -113,6 +113,7 @@ class GL_EXPORT GLSurfaceEGL : public GLSurface { ...@@ -113,6 +113,7 @@ class GL_EXPORT GLSurfaceEGL : public GLSurface {
static bool IsEGLFlexibleSurfaceCompatibilitySupported(); static bool IsEGLFlexibleSurfaceCompatibilitySupported();
static bool IsRobustResourceInitSupported(); static bool IsRobustResourceInitSupported();
static bool IsDisplayTextureShareGroupSupported(); static bool IsDisplayTextureShareGroupSupported();
static bool IsDisplaySemaphoreShareGroupSupported();
static bool IsCreateContextClientArraysSupported(); static bool IsCreateContextClientArraysSupported();
static bool IsAndroidNativeFenceSyncSupported(); static bool IsAndroidNativeFenceSyncSupported();
static bool IsPixelFormatFloatSupported(); static bool IsPixelFormatFloatSupported();
......
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