Commit 6b1ca238 authored by Jonathan Ross's avatar Jonathan Ross Committed by Commit Bot

Reland "vulkan: reuse gl semaphores"

This reverts commit 3bd0e5ef.

Reason for revert: I incorrectly identified this as the cause of crbug.com/1111764

Original change's description:
> Revert "vulkan: reuse gl semaphores"
> 
> This reverts commit 5c8c9a69.
> 
> Reason for revert: Two Vulkan angle_perftests have begun crashing consistently with this change in the blame range. Reverting to confirm if this is the cause.
> 
> Otherwise there is also an Angle roll in the range.
> 
> crbug.com/1111764
> 
> 
> Original change's description:
> > 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: Jonathan Backer <backer@chromium.org>
> > Reviewed-by: Vasiliy Telezhnikov <vasilyt@chromium.org>
> > Cr-Commit-Position: refs/heads/master@{#793398}
> 
> TBR=penghuang@chromium.org,backer@chromium.org,vasilyt@chromium.org
> 
> Change-Id: I63953b02f7f06a6e77a3266e3fc4eadee2f882f3
> No-Presubmit: true
> No-Tree-Checks: true
> No-Try: true
> Bug: 1004772
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2332677
> Reviewed-by: Jonathan Ross <jonross@chromium.org>
> Commit-Queue: Jonathan Ross <jonross@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#793591}

TBR=penghuang@chromium.org,backer@chromium.org,jonross@chromium.org,vasilyt@chromium.org

# Not skipping CQ checks because this is a reland.

Bug: 1004772
Change-Id: I06ccd88922ba2f7163fe553e86529fc550689a87
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2332837Reviewed-by: default avatarJonathan Ross <jonross@chromium.org>
Commit-Queue: Jonathan Ross <jonross@chromium.org>
Cr-Commit-Position: refs/heads/master@{#793657}
parent 051f1395
...@@ -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