зеркало из https://github.com/AvaloniaUI/angle.git
GL: Allow selecting virtualization groups at context creation
Rewrite EGL_ANGLE_platform_angle_context_virtualization to EGL_ANGLE_context_virtualization, changing the context virtualization parameter to an identifier for what virtualization group the frontend context should be added to. This allows ANGLE's GL backend to be used by multiple threads if the user creates contexts with different virtualization groups. Bug: angleproject:6406 Change-Id: I7414d4705ce10bdf63a9b824043d5dd040dad875 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3169193 Reviewed-by: Jonah Ryan-Davis <jonahr@google.com> Reviewed-by: Jamie Madill <jmadill@chromium.org> Commit-Queue: Geoff Lang <geofflang@chromium.org>
This commit is contained in:
Родитель
48b605d845
Коммит
d2c01d2ce5
|
@ -0,0 +1,79 @@
|
|||
Name
|
||||
|
||||
ANGLE_context_virtualization
|
||||
|
||||
Name Strings
|
||||
|
||||
EGL_ANGLE_context_virtualization
|
||||
|
||||
Contributors
|
||||
|
||||
Geoff Lang, Google
|
||||
|
||||
Contacts
|
||||
|
||||
Geoff Lang, Google (geofflang 'at' chromium 'dot' org)
|
||||
|
||||
Status
|
||||
|
||||
Draft
|
||||
|
||||
Version
|
||||
|
||||
Version 2, 2021-09-17
|
||||
|
||||
Number
|
||||
|
||||
EGL Extension XXX
|
||||
|
||||
Extension Type
|
||||
|
||||
EGL display extension
|
||||
|
||||
Dependencies
|
||||
|
||||
None
|
||||
|
||||
Overview
|
||||
|
||||
This extension allows the client to create contexts that are internally
|
||||
virtualized on a single native context for performance or stability.
|
||||
|
||||
New Types
|
||||
|
||||
None
|
||||
|
||||
New Procedures and Functions
|
||||
|
||||
None
|
||||
|
||||
New Tokens
|
||||
|
||||
Accepted as an attribute name in the <attrib_list> argument of
|
||||
eglCreateContext:
|
||||
|
||||
EGL_CONTEXT_VIRTUALIZATION_GROUP_ANGLE 0x3481
|
||||
|
||||
Additions to the EGL Specification
|
||||
|
||||
None.
|
||||
|
||||
New Behavior
|
||||
|
||||
To request that a context should be part of a virtualization group,
|
||||
use the attribute EGL_CONTEXT_VIRTUALIZATION_GROUP_ANGLE. EGL_DONT_CARE
|
||||
can be used to allow the implementation to decide what virtualization
|
||||
group is used. The default value of EGL_CONTEXT_VIRTUALIZATION_GROUP_ANGLE
|
||||
is EGL_DONT_CARE. It is undefined behaviour to have multiple contexts from
|
||||
the same virtualization group current different threads simultaneously.
|
||||
|
||||
Issues
|
||||
|
||||
None
|
||||
|
||||
Revision History
|
||||
|
||||
Version 1, 2018-06-11 (Geoff Lang)
|
||||
- Initial draft
|
||||
Version 2, 2021-09-17 (Geoff Lang)
|
||||
- Change to context creation attribute
|
|
@ -1,80 +0,0 @@
|
|||
Name
|
||||
|
||||
ANGLE_platform_angle_context_virtualization
|
||||
|
||||
Name Strings
|
||||
|
||||
EGL_ANGLE_platform_angle_context_virtualization
|
||||
|
||||
Contributors
|
||||
|
||||
Geoff Lang, Google
|
||||
|
||||
Contacts
|
||||
|
||||
Geoff Lang, Google (geofflang 'at' chromium 'dot' org)
|
||||
|
||||
Status
|
||||
|
||||
Draft
|
||||
|
||||
Version
|
||||
|
||||
Version 1, 2018-06-11
|
||||
|
||||
Number
|
||||
|
||||
EGL Extension XXX
|
||||
|
||||
Extension Type
|
||||
|
||||
EGL client extension
|
||||
|
||||
Dependencies
|
||||
|
||||
Requires ANGLE_platform_angle.
|
||||
|
||||
Overview
|
||||
|
||||
This extension allows the client to request a Display that internally
|
||||
virtualizes contexts. Requesting virtualized contexts may impact
|
||||
performance or ability to render from multiple threads simultaneously.
|
||||
|
||||
New Types
|
||||
|
||||
None
|
||||
|
||||
New Procedures and Functions
|
||||
|
||||
None
|
||||
|
||||
New Tokens
|
||||
|
||||
Accepted as an attribute name in the <attrib_list> argument of
|
||||
eglGetPlatformDisplayEXT:
|
||||
|
||||
EGL_PLATFORM_ANGLE_CONTEXT_VIRTUALIZATION_ANGLE 0x3481
|
||||
|
||||
Additions to the EGL Specification
|
||||
|
||||
None.
|
||||
|
||||
New Behavior
|
||||
|
||||
To request a display that internally utilizes context virtualization,
|
||||
use the attribute EGL_PLATFORM_ANGLE_CONTEXT_VIRTUALIZATION_ANGLE.
|
||||
EGL_TRUE enables context virtualization and EGL false disables it.
|
||||
If it is set to EGL_DONT_CARE, the default setting depends on the
|
||||
implementation. Any value other than these will result in an error.
|
||||
The default value for EGL_PLATFORM_ANGLE_CONTEXT_VIRTUALIZATION_ANGLE
|
||||
is EGL_DONT_CARE. Display creation may fail if hardware limitations
|
||||
prohibit the requested setting.
|
||||
|
||||
Issues
|
||||
|
||||
None
|
||||
|
||||
Revision History
|
||||
|
||||
Version 1, 2018-06-11 (Geoff Lang)
|
||||
- Initial draft
|
|
@ -115,10 +115,10 @@
|
|||
#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_EGL_ANGLE 0x348E
|
||||
#endif /* EGL_ANGLE_platform_angle_device_type_egl_angle */
|
||||
|
||||
#ifndef EGL_ANGLE_platform_angle_context_virtualization
|
||||
#define EGL_ANGLE_platform_angle_context_virtualization 1
|
||||
#define EGL_PLATFORM_ANGLE_CONTEXT_VIRTUALIZATION_ANGLE 0x3481
|
||||
#endif /* EGL_ANGLE_platform_angle_context_virtualization */
|
||||
#ifndef EGL_ANGLE_context_virtualization
|
||||
#define EGL_ANGLE_context_virtualization 1
|
||||
#define EGL_CONTEXT_VIRTUALIZATION_GROUP_ANGLE 0x3481
|
||||
#endif /* EGL_ANGLE_context_virtualization */
|
||||
|
||||
#ifndef EGL_ANGLE_platform_angle_device_context_volatile_eagl
|
||||
#define EGL_ANGLE_platform_angle_device_context_volatile_eagl 1
|
||||
|
|
|
@ -1290,6 +1290,7 @@ std::vector<std::string> DisplayExtensions::getStrings() const
|
|||
InsertExtensionString("EGL_KHR_mutable_render_buffer", mutableRenderBufferKHR, &extensionStrings);
|
||||
InsertExtensionString("EGL_EXT_protected_content", protectedContentEXT, &extensionStrings);
|
||||
InsertExtensionString("EGL_ANGLE_create_surface_swap_interval", createSurfaceSwapIntervalANGLE, &extensionStrings);
|
||||
InsertExtensionString("EGL_ANGLE_context_virtualization", contextVirtualizationANGLE, &extensionStrings);
|
||||
// clang-format on
|
||||
|
||||
return extensionStrings;
|
||||
|
@ -1335,7 +1336,6 @@ std::vector<std::string> ClientExtensions::getStrings() const
|
|||
InsertExtensionString("EGL_ANGLE_platform_angle_null", platformANGLENULL, &extensionStrings);
|
||||
InsertExtensionString("EGL_ANGLE_platform_angle_vulkan", platformANGLEVulkan, &extensionStrings);
|
||||
InsertExtensionString("EGL_ANGLE_platform_angle_metal", platformANGLEMetal, &extensionStrings);
|
||||
InsertExtensionString("EGL_ANGLE_platform_angle_context_virtualization", platformANGLEContextVirtualization, &extensionStrings);
|
||||
InsertExtensionString("EGL_ANGLE_platform_device_context_volatile_eagl", platformANGLEDeviceContextVolatileEagl, &extensionStrings);
|
||||
InsertExtensionString("EGL_ANGLE_platform_device_context_volatile_cgl", platformANGLEDeviceContextVolatileCgl, &extensionStrings);
|
||||
InsertExtensionString("EGL_ANGLE_device_creation", deviceCreation, &extensionStrings);
|
||||
|
|
|
@ -633,6 +633,9 @@ struct DisplayExtensions
|
|||
|
||||
// EGL_ANGLE_create_surface_swap_interval
|
||||
bool createSurfaceSwapIntervalANGLE = false;
|
||||
|
||||
// EGL_ANGLE_context_virtualization
|
||||
bool contextVirtualizationANGLE = false;
|
||||
};
|
||||
|
||||
struct DeviceExtensions
|
||||
|
@ -693,9 +696,6 @@ struct ClientExtensions
|
|||
// EGL_ANGLE_platform_angle_metal
|
||||
bool platformANGLEMetal = false;
|
||||
|
||||
// EGL_ANGLE_platform_angle_context_virtualization
|
||||
bool platformANGLEContextVirtualization = false;
|
||||
|
||||
// EGL_ANGLE_platform_angle_device_context_volatile_eagl
|
||||
bool platformANGLEDeviceContextVolatileEagl = false;
|
||||
|
||||
|
|
|
@ -1733,9 +1733,6 @@ static ClientExtensions GenerateClientExtensions()
|
|||
|
||||
#if defined(ANGLE_ENABLE_OPENGL)
|
||||
extensions.platformANGLEOpenGL = true;
|
||||
|
||||
// Selecting context virtualization is currently only supported in the OpenGL backend.
|
||||
extensions.platformANGLEContextVirtualization = true;
|
||||
#endif
|
||||
|
||||
#if defined(ANGLE_ENABLE_NULL)
|
||||
|
|
|
@ -109,11 +109,7 @@ void WorkerContextEGL::unmakeCurrent()
|
|||
namespace rx
|
||||
{
|
||||
|
||||
static constexpr bool kDefaultEGLVirtualizedContexts = true;
|
||||
|
||||
DisplayEGL::DisplayEGL(const egl::DisplayState &state)
|
||||
: DisplayGL(state), mVirtualizedContexts(kDefaultEGLVirtualizedContexts)
|
||||
{}
|
||||
DisplayEGL::DisplayEGL(const egl::DisplayState &state) : DisplayGL(state) {}
|
||||
|
||||
DisplayEGL::~DisplayEGL() {}
|
||||
|
||||
|
@ -253,9 +249,7 @@ egl::Error DisplayEGL::initializeContext(EGLContext shareContext,
|
|||
egl::Error DisplayEGL::initialize(egl::Display *display)
|
||||
{
|
||||
mDisplayAttributes = display->getAttributeMap();
|
||||
mVirtualizedContexts =
|
||||
ShouldUseVirtualizedContexts(mDisplayAttributes, kDefaultEGLVirtualizedContexts);
|
||||
mEGL = new FunctionsEGLDL();
|
||||
mEGL = new FunctionsEGLDL();
|
||||
|
||||
void *eglHandle =
|
||||
reinterpret_cast<void *>(mDisplayAttributes.get(EGL_PLATFORM_ANGLE_EGL_HANDLE_ANGLE, 0));
|
||||
|
@ -402,6 +396,7 @@ void DisplayEGL::terminate()
|
|||
}
|
||||
|
||||
mRenderer.reset();
|
||||
mVirtualizationGroups.clear();
|
||||
|
||||
mCurrentNativeContexts.clear();
|
||||
|
||||
|
@ -497,36 +492,47 @@ ContextImpl *DisplayEGL::createContext(const gl::State &state,
|
|||
const gl::Context *shareContext,
|
||||
const egl::AttributeMap &attribs)
|
||||
{
|
||||
std::shared_ptr<RendererEGL> renderer;
|
||||
bool usingExternalContext = attribs.get(EGL_EXTERNAL_CONTEXT_ANGLE, EGL_FALSE) == EGL_TRUE;
|
||||
if (mVirtualizedContexts && !usingExternalContext)
|
||||
{
|
||||
renderer = mRenderer;
|
||||
}
|
||||
else
|
||||
{
|
||||
EGLContext nativeShareContext = EGL_NO_CONTEXT;
|
||||
if (usingExternalContext)
|
||||
{
|
||||
ASSERT(!shareContext);
|
||||
}
|
||||
else if (shareContext)
|
||||
{
|
||||
ContextEGL *shareContextEGL = GetImplAs<ContextEGL>(shareContext);
|
||||
nativeShareContext = shareContextEGL->getContext();
|
||||
}
|
||||
EGLAttrib virtualizationGroup =
|
||||
attribs.get(EGL_CONTEXT_VIRTUALIZATION_GROUP_ANGLE, EGL_DONT_CARE);
|
||||
|
||||
// Create a new renderer for this context. It only needs to share with the user's requested
|
||||
// share context because there are no internal resources in DisplayEGL that are shared
|
||||
// at the GL level.
|
||||
egl::Error error =
|
||||
createRenderer(nativeShareContext, false, usingExternalContext, &renderer);
|
||||
std::shared_ptr<RendererEGL> renderer = mRenderer;
|
||||
if (usingExternalContext)
|
||||
{
|
||||
ASSERT(!shareContext);
|
||||
egl::Error error = createRenderer(EGL_NO_CONTEXT, false, true, &renderer);
|
||||
if (error.isError())
|
||||
{
|
||||
ERR() << "Failed to create a shared renderer: " << error.getMessage();
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
else if (virtualizationGroup != EGL_DONT_CARE)
|
||||
{
|
||||
renderer = mVirtualizationGroups[virtualizationGroup].lock();
|
||||
if (!renderer)
|
||||
{
|
||||
EGLContext nativeShareContext = EGL_NO_CONTEXT;
|
||||
if (shareContext)
|
||||
{
|
||||
ContextEGL *shareContextEGL = GetImplAs<ContextEGL>(shareContext);
|
||||
nativeShareContext = shareContextEGL->getContext();
|
||||
}
|
||||
|
||||
// Create a new renderer for this context. It only needs to share with the user's
|
||||
// requested share context because there are no internal resources in DisplayEGL that
|
||||
// are shared at the GL level.
|
||||
egl::Error error = createRenderer(nativeShareContext, false, false, &renderer);
|
||||
if (error.isError())
|
||||
{
|
||||
ERR() << "Failed to create a shared renderer: " << error.getMessage();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
mVirtualizationGroups[virtualizationGroup] = renderer;
|
||||
}
|
||||
}
|
||||
ASSERT(renderer);
|
||||
|
||||
RobustnessVideoMemoryPurgeStatus robustnessVideoMemoryPurgeStatus =
|
||||
GetRobustnessVideoMemoryPurge(attribs);
|
||||
|
@ -764,31 +770,6 @@ egl::Error DisplayEGL::makeCurrent(egl::Display *display,
|
|||
return DisplayGL::makeCurrent(display, drawSurface, readSurface, context);
|
||||
}
|
||||
|
||||
// The context should never change when context virtualization is being used unless binding a
|
||||
// null context.
|
||||
if (mVirtualizedContexts && newContext != EGL_NO_CONTEXT)
|
||||
{
|
||||
ASSERT(currentContext.context == EGL_NO_CONTEXT || newContext == currentContext.context);
|
||||
|
||||
newContext = mRenderer->getContext();
|
||||
|
||||
// If we know that we're only running on one thread (mVirtualizedContexts == true) and
|
||||
// EGL_NO_SURFACE is going to be bound, we can optimize this case by not changing the
|
||||
// surface binding and emulate the surfaceless extension in the frontend.
|
||||
if (newSurface == EGL_NO_SURFACE)
|
||||
{
|
||||
newSurface = currentContext.surface;
|
||||
}
|
||||
|
||||
// It's possible that no surface has been created yet and the driver doesn't support
|
||||
// surfaceless, bind the mock pbuffer.
|
||||
if (newSurface == EGL_NO_SURFACE && !mSupportsSurfaceless)
|
||||
{
|
||||
newSurface = mMockPbuffer;
|
||||
ASSERT(newSurface != EGL_NO_SURFACE);
|
||||
}
|
||||
}
|
||||
|
||||
if (newSurface != currentContext.surface || newContext != currentContext.context)
|
||||
{
|
||||
if (mEGL->makeCurrent(newSurface, newContext) == EGL_FALSE)
|
||||
|
@ -900,10 +881,12 @@ void DisplayEGL::generateExtensions(egl::DisplayExtensions *outExtensions) const
|
|||
|
||||
// Surfaceless can be support if the native driver supports it or we know that we are running on
|
||||
// a single thread (mVirtualizedContexts == true)
|
||||
outExtensions->surfacelessContext = mSupportsSurfaceless || mVirtualizedContexts;
|
||||
outExtensions->surfacelessContext = mSupportsSurfaceless;
|
||||
|
||||
outExtensions->externalContextAndSurface = true;
|
||||
|
||||
outExtensions->contextVirtualizationANGLE = true;
|
||||
|
||||
DisplayGL::generateExtensions(outExtensions);
|
||||
}
|
||||
|
||||
|
|
|
@ -138,6 +138,8 @@ class DisplayEGL : public DisplayGL
|
|||
const U &defaultValue) const;
|
||||
|
||||
std::shared_ptr<RendererEGL> mRenderer;
|
||||
std::map<EGLAttrib, std::weak_ptr<RendererEGL>> mVirtualizationGroups;
|
||||
|
||||
FunctionsEGLDL *mEGL = nullptr;
|
||||
EGLConfig mConfig = EGL_NO_CONFIG_KHR;
|
||||
egl::AttributeMap mDisplayAttributes;
|
||||
|
@ -160,8 +162,6 @@ class DisplayEGL : public DisplayGL
|
|||
bool mHasEXTCreateContextRobustness = false;
|
||||
bool mHasNVRobustnessVideoMemoryPurge = false;
|
||||
|
||||
bool mVirtualizedContexts = false;
|
||||
|
||||
bool mSupportsSurfaceless = false;
|
||||
bool mSupportsNoConfigContexts = false;
|
||||
|
||||
|
|
|
@ -461,20 +461,6 @@ bool ShouldUseDebugLayers(const egl::AttributeMap &attribs)
|
|||
#endif // defined(ANGLE_ENABLE_ASSERTS)
|
||||
}
|
||||
|
||||
bool ShouldUseVirtualizedContexts(const egl::AttributeMap &attribs, bool defaultValue)
|
||||
{
|
||||
EGLAttrib virtualizedContextRequest =
|
||||
attribs.get(EGL_PLATFORM_ANGLE_CONTEXT_VIRTUALIZATION_ANGLE, EGL_DONT_CARE);
|
||||
if (defaultValue)
|
||||
{
|
||||
return (virtualizedContextRequest != EGL_FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
return (virtualizedContextRequest == EGL_TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
void CopyImageCHROMIUM(const uint8_t *sourceData,
|
||||
size_t sourceRowPitch,
|
||||
size_t sourcePixelBytes,
|
||||
|
|
|
@ -174,7 +174,6 @@ struct LoadTextureBorderFunctionInfo
|
|||
using LoadTextureBorderFunctionMap = LoadTextureBorderFunctionInfo (*)();
|
||||
|
||||
bool ShouldUseDebugLayers(const egl::AttributeMap &attribs);
|
||||
bool ShouldUseVirtualizedContexts(const egl::AttributeMap &attribs, bool defaultValue);
|
||||
|
||||
void CopyImageCHROMIUM(const uint8_t *sourceData,
|
||||
size_t sourceRowPitch,
|
||||
|
|
|
@ -695,31 +695,6 @@ bool ValidateGetPlatformDisplayCommon(const ValidationContext *val,
|
|||
}
|
||||
break;
|
||||
|
||||
case EGL_PLATFORM_ANGLE_CONTEXT_VIRTUALIZATION_ANGLE:
|
||||
if (!clientExtensions.platformANGLEContextVirtualization)
|
||||
{
|
||||
val->setError(EGL_BAD_ATTRIBUTE,
|
||||
"EGL_ANGLE_platform_angle_context_"
|
||||
"virtualization extension not active");
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (value)
|
||||
{
|
||||
case EGL_DONT_CARE:
|
||||
case EGL_FALSE:
|
||||
case EGL_TRUE:
|
||||
break;
|
||||
|
||||
default:
|
||||
val->setError(EGL_BAD_ATTRIBUTE,
|
||||
"Invalid value for "
|
||||
"EGL_PLATFORM_ANGLE_CONTEXT_VIRTUALIZATION_"
|
||||
"ANGLE attrib");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case EGL_PLATFORM_ANGLE_D3D_LUID_HIGH_ANGLE:
|
||||
case EGL_PLATFORM_ANGLE_D3D_LUID_LOW_ANGLE:
|
||||
luidSpecified = true;
|
||||
|
@ -2004,6 +1979,16 @@ bool ValidateCreateContext(const ValidationContext *val,
|
|||
}
|
||||
break;
|
||||
|
||||
case EGL_CONTEXT_VIRTUALIZATION_GROUP_ANGLE:
|
||||
if (!display->getExtensions().contextVirtualizationANGLE)
|
||||
{
|
||||
val->setError(EGL_BAD_ATTRIBUTE,
|
||||
"Attribute EGL_CONTEXT_VIRTUALIZATION_GROUP_ANGLE requires "
|
||||
"extension EGL_ANGLE_context_virtualization.");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
val->setError(EGL_BAD_ATTRIBUTE, "Unknown attribute: 0x%04" PRIxPTR "X", attribute);
|
||||
return false;
|
||||
|
|
|
@ -484,7 +484,7 @@ TEST_P(EGLContextSharingTest, DeleteReaderOfSharedTexture)
|
|||
surface[t] = eglCreatePbufferSurface(dpy, config, pbufferAttributes);
|
||||
EXPECT_EGL_SUCCESS();
|
||||
|
||||
ctx[t] = window->createContext(t == 0 ? EGL_NO_CONTEXT : ctx[0]);
|
||||
ctx[t] = window->createContext(t == 0 ? EGL_NO_CONTEXT : ctx[0], nullptr);
|
||||
EXPECT_NE(EGL_NO_CONTEXT, ctx[t]);
|
||||
}
|
||||
|
||||
|
@ -949,4 +949,4 @@ ANGLE_INSTANTIATE_TEST(EGLContextSharingTestNoFixture,
|
|||
WithNoFixture(ES2_OPENGL()),
|
||||
WithNoFixture(ES3_OPENGL()),
|
||||
WithNoFixture(ES2_VULKAN()),
|
||||
WithNoFixture(ES3_VULKAN()));
|
||||
WithNoFixture(ES3_VULKAN()));
|
||||
|
|
|
@ -63,8 +63,8 @@ TEST_P(EGLMultiContextTest, TestContextDestroySimple)
|
|||
EGLWindow *window = getEGLWindow();
|
||||
EGLDisplay dpy = window->getDisplay();
|
||||
|
||||
EGLContext context1 = window->createContext(EGL_NO_CONTEXT);
|
||||
EGLContext context2 = window->createContext(EGL_NO_CONTEXT);
|
||||
EGLContext context1 = window->createContext(EGL_NO_CONTEXT, nullptr);
|
||||
EGLContext context2 = window->createContext(EGL_NO_CONTEXT, nullptr);
|
||||
|
||||
EXPECT_EGL_TRUE(eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, context1));
|
||||
EXPECT_EGL_TRUE(eglDestroyContext(dpy, context2));
|
||||
|
@ -101,7 +101,7 @@ TEST_P(EGLMultiContextTest, ComputeShaderOkayWithRendering)
|
|||
surface[t] = eglCreatePbufferSurface(dpy, config, pbufferAttributes);
|
||||
EXPECT_EGL_SUCCESS();
|
||||
|
||||
ctx[t] = window->createContext(EGL_NO_CONTEXT);
|
||||
ctx[t] = window->createContext(EGL_NO_CONTEXT, nullptr);
|
||||
EXPECT_NE(EGL_NO_CONTEXT, ctx[t]);
|
||||
}
|
||||
|
||||
|
|
|
@ -378,7 +378,7 @@ TEST_P(EGLSyncTest, AndroidNativeFence_WaitSync)
|
|||
{
|
||||
EXPECT_EGL_TRUE(eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
|
||||
|
||||
EGLContext context2 = getEGLWindow()->createContext(EGL_NO_CONTEXT);
|
||||
EGLContext context2 = getEGLWindow()->createContext(EGL_NO_CONTEXT, nullptr);
|
||||
EXPECT_EGL_TRUE(eglMakeCurrent(display, surface, surface, context2));
|
||||
|
||||
// We can eglWaitSync on this - import FD from first sync.
|
||||
|
@ -462,7 +462,7 @@ TEST_P(EGLSyncTest, AndroidNativeFence_withFences)
|
|||
{
|
||||
EXPECT_EGL_TRUE(eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
|
||||
|
||||
EGLContext context2 = getEGLWindow()->createContext(EGL_NO_CONTEXT);
|
||||
EGLContext context2 = getEGLWindow()->createContext(EGL_NO_CONTEXT, nullptr);
|
||||
EXPECT_EGL_TRUE(eglMakeCurrent(display, surface, surface, context2));
|
||||
|
||||
// check that Fence and Android fences work together
|
||||
|
|
|
@ -41,6 +41,19 @@ class MultithreadingTest : public ANGLETest
|
|||
}
|
||||
bool hasGLSyncExtension() const { return IsGLExtensionEnabled("GL_OES_EGL_sync"); }
|
||||
|
||||
EGLContext createMultithreadedContext(EGLWindow *window, EGLContext shareCtx)
|
||||
{
|
||||
EGLint attribs[] = {EGL_CONTEXT_VIRTUALIZATION_GROUP_ANGLE, mVirtualizationGroup++,
|
||||
EGL_NONE};
|
||||
if (!IsEGLDisplayExtensionEnabled(getEGLWindow()->getDisplay(),
|
||||
"EGL_ANGLE_context_virtualization"))
|
||||
{
|
||||
attribs[0] = EGL_NONE;
|
||||
}
|
||||
|
||||
return window->createContext(shareCtx, attribs);
|
||||
}
|
||||
|
||||
void runMultithreadedGLTest(
|
||||
std::function<void(EGLSurface surface, size_t threadIndex)> testBody,
|
||||
size_t threadCount)
|
||||
|
@ -70,7 +83,7 @@ class MultithreadingTest : public ANGLETest
|
|||
surface = eglCreatePbufferSurface(dpy, config, pbufferAttributes);
|
||||
EXPECT_EGL_SUCCESS();
|
||||
|
||||
ctx = window->createContext(EGL_NO_CONTEXT);
|
||||
ctx = createMultithreadedContext(window, EGL_NO_CONTEXT);
|
||||
EXPECT_NE(EGL_NO_CONTEXT, ctx);
|
||||
|
||||
EXPECT_EGL_TRUE(eglMakeCurrent(dpy, surface, surface, ctx));
|
||||
|
@ -98,6 +111,8 @@ class MultithreadingTest : public ANGLETest
|
|||
thread.join();
|
||||
}
|
||||
}
|
||||
|
||||
std::atomic<EGLint> mVirtualizationGroup;
|
||||
};
|
||||
|
||||
class MultithreadingTestES3 : public MultithreadingTest
|
||||
|
@ -234,8 +249,8 @@ TEST_P(MultithreadingTest, MultiContextDeleteDraw)
|
|||
// 5000 is chosen here as it reliably reproduces the former crash.
|
||||
for (int i = 0; i < 5000; i++)
|
||||
{
|
||||
EGLContext ctx1 = window->createContext(EGL_NO_CONTEXT);
|
||||
EGLContext ctx2 = window->createContext(EGL_NO_CONTEXT);
|
||||
EGLContext ctx1 = createMultithreadedContext(window, EGL_NO_CONTEXT);
|
||||
EGLContext ctx2 = createMultithreadedContext(window, EGL_NO_CONTEXT);
|
||||
|
||||
EXPECT_EGL_TRUE(eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, ctx2));
|
||||
EXPECT_EGL_TRUE(eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, ctx1));
|
||||
|
@ -253,7 +268,7 @@ TEST_P(MultithreadingTest, MultiContextDeleteDraw)
|
|||
EGLSurface surface = eglCreatePbufferSurface(dpy, config, pbufferAttributes);
|
||||
EXPECT_EGL_SUCCESS();
|
||||
|
||||
auto ctx = window->createContext(EGL_NO_CONTEXT);
|
||||
auto ctx = createMultithreadedContext(window, EGL_NO_CONTEXT);
|
||||
EXPECT_EGL_TRUE(eglMakeCurrent(dpy, surface, surface, ctx));
|
||||
|
||||
constexpr size_t kIterationsPerThread = 512;
|
||||
|
@ -469,7 +484,7 @@ TEST_P(MultithreadingTest, MultiCreateContext)
|
|||
threads[threadIdx] = std::thread([&, threadIdx]() {
|
||||
contexts[threadIdx] = EGL_NO_CONTEXT;
|
||||
{
|
||||
contexts[threadIdx] = window->createContext(EGL_NO_CONTEXT);
|
||||
contexts[threadIdx] = createMultithreadedContext(window, EGL_NO_CONTEXT);
|
||||
EXPECT_NE(EGL_NO_CONTEXT, contexts[threadIdx]);
|
||||
|
||||
barrier++;
|
||||
|
@ -511,7 +526,7 @@ void MultithreadingTestES3::textureThreadFunction(bool useDraw)
|
|||
EXPECT_EGL_SUCCESS();
|
||||
EXPECT_NE(EGL_NO_SURFACE, surface);
|
||||
|
||||
ctx = window->createContext(window->getContext());
|
||||
ctx = createMultithreadedContext(window, window->getContext());
|
||||
EXPECT_NE(EGL_NO_CONTEXT, ctx);
|
||||
|
||||
EXPECT_EGL_TRUE(eglMakeCurrent(dpy, surface, surface, ctx));
|
||||
|
@ -791,7 +806,7 @@ TEST_P(MultithreadingTest, CreateFenceThreadAClientWaitSyncThreadBDelayedFlush)
|
|||
surface = eglCreatePbufferSurface(dpy, config, pbufferAttributes);
|
||||
EXPECT_EGL_SUCCESS();
|
||||
// Create 2 shared contexts, one for each thread
|
||||
context = window->createContext(EGL_NO_CONTEXT);
|
||||
context = window->createContext(EGL_NO_CONTEXT, nullptr);
|
||||
EXPECT_NE(EGL_NO_CONTEXT, context);
|
||||
// Sync object
|
||||
EGLSyncKHR sync = EGL_NO_SYNC_KHR;
|
||||
|
@ -883,21 +898,21 @@ TEST_P(MultithreadingTest, CreateFenceThreadAClientWaitSyncThreadBDelayedFlush)
|
|||
// TODO(geofflang): Test sharing a program between multiple shared contexts on multiple threads
|
||||
|
||||
ANGLE_INSTANTIATE_TEST(MultithreadingTest,
|
||||
WithNoVirtualContexts(ES2_OPENGL()),
|
||||
WithNoVirtualContexts(ES3_OPENGL()),
|
||||
WithNoVirtualContexts(ES2_OPENGLES()),
|
||||
WithNoVirtualContexts(ES3_OPENGLES()),
|
||||
WithNoVirtualContexts(ES3_VULKAN()),
|
||||
WithNoVirtualContexts(ES3_VULKAN_SWIFTSHADER()),
|
||||
WithNoVirtualContexts(ES2_D3D11()),
|
||||
WithNoVirtualContexts(ES3_D3D11()));
|
||||
ES2_OPENGL(),
|
||||
ES3_OPENGL(),
|
||||
ES2_OPENGLES(),
|
||||
ES3_OPENGLES(),
|
||||
ES3_VULKAN(),
|
||||
ES3_VULKAN_SWIFTSHADER(),
|
||||
ES2_D3D11(),
|
||||
ES3_D3D11());
|
||||
|
||||
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(MultithreadingTestES3);
|
||||
ANGLE_INSTANTIATE_TEST(MultithreadingTestES3,
|
||||
WithNoVirtualContexts(ES3_OPENGL()),
|
||||
WithNoVirtualContexts(ES3_OPENGLES()),
|
||||
WithNoVirtualContexts(ES3_VULKAN()),
|
||||
WithNoVirtualContexts(ES3_VULKAN_SWIFTSHADER()),
|
||||
WithNoVirtualContexts(ES3_D3D11()));
|
||||
ES3_OPENGL(),
|
||||
ES3_OPENGLES(),
|
||||
ES3_VULKAN(),
|
||||
ES3_VULKAN_SWIFTSHADER(),
|
||||
ES3_D3D11());
|
||||
|
||||
} // namespace angle
|
||||
|
|
|
@ -6905,7 +6905,7 @@ void main()
|
|||
EGLConfig config = window->getConfig();
|
||||
EGLint pbufferAttributes[] = {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE, EGL_NONE};
|
||||
EGLSurface surface = eglCreatePbufferSurface(dpy, config, pbufferAttributes);
|
||||
EGLContext ctx = window->createContext(EGL_NO_CONTEXT);
|
||||
EGLContext ctx = window->createContext(EGL_NO_CONTEXT, nullptr);
|
||||
EXPECT_EGL_SUCCESS();
|
||||
std::thread flushThread = std::thread([&]() {
|
||||
EXPECT_EGL_TRUE(eglMakeCurrent(dpy, surface, surface, ctx));
|
||||
|
|
|
@ -88,7 +88,7 @@ class VulkanMultithreadingTest : public ANGLETest
|
|||
surface = eglCreatePbufferSurface(dpy, config, pbufferAttributes);
|
||||
EXPECT_EGL_SUCCESS();
|
||||
|
||||
ctx = window->createContext(EGL_NO_CONTEXT);
|
||||
ctx = window->createContext(EGL_NO_CONTEXT, nullptr);
|
||||
EXPECT_NE(EGL_NO_CONTEXT, ctx);
|
||||
|
||||
EXPECT_EGL_TRUE(eglMakeCurrent(dpy, surface, surface, ctx));
|
||||
|
|
|
@ -1222,7 +1222,10 @@ void ANGLETestBase::draw3DTexturedQuad(GLfloat positionAttribZ,
|
|||
|
||||
bool ANGLETestBase::platformSupportsMultithreading() const
|
||||
{
|
||||
return (IsOpenGLES() && IsAndroid()) || IsVulkan();
|
||||
return (mFixture && mFixture->eglWindow &&
|
||||
IsEGLDisplayExtensionEnabled(mFixture->eglWindow->getDisplay(),
|
||||
"EGL_ANGLE_context_virtualization")) ||
|
||||
IsVulkan();
|
||||
}
|
||||
|
||||
void ANGLETestBase::checkD3D11SDKLayersMessages()
|
||||
|
|
|
@ -196,11 +196,6 @@ std::ostream &operator<<(std::ostream &stream, const PlatformParameters &pp)
|
|||
stream << "_NoFixture";
|
||||
}
|
||||
|
||||
if (pp.eglParameters.contextVirtualization == EGL_FALSE)
|
||||
{
|
||||
stream << "_NoVirtual";
|
||||
}
|
||||
|
||||
if (pp.eglParameters.transformFeedbackFeature == EGL_FALSE)
|
||||
{
|
||||
stream << "_NoTransformFeedback";
|
||||
|
|
|
@ -191,13 +191,6 @@ PlatformParameters ES3_EGL();
|
|||
|
||||
const char *GetNativeEGLLibraryNameWithExtension();
|
||||
|
||||
inline PlatformParameters WithNoVirtualContexts(const PlatformParameters ¶ms)
|
||||
{
|
||||
PlatformParameters withNoVirtualContexts = params;
|
||||
withNoVirtualContexts.eglParameters.contextVirtualization = EGL_FALSE;
|
||||
return withNoVirtualContexts;
|
||||
}
|
||||
|
||||
inline PlatformParameters WithNoFixture(const PlatformParameters ¶ms)
|
||||
{
|
||||
PlatformParameters withNoFixture = params;
|
||||
|
|
|
@ -59,10 +59,10 @@ struct EGLPlatformParameters
|
|||
auto tie() const
|
||||
{
|
||||
return std::tie(renderer, majorVersion, minorVersion, deviceType, presentPath,
|
||||
debugLayersEnabled, contextVirtualization, transformFeedbackFeature,
|
||||
allocateNonZeroMemoryFeature, emulateCopyTexImage2DFromRenderbuffers,
|
||||
shaderStencilOutputFeature, genMultipleMipsPerPassFeature, platformMethods,
|
||||
robustness, emulatedPrerotation, asyncCommandQueueFeatureVulkan,
|
||||
debugLayersEnabled, transformFeedbackFeature, allocateNonZeroMemoryFeature,
|
||||
emulateCopyTexImage2DFromRenderbuffers, shaderStencilOutputFeature,
|
||||
genMultipleMipsPerPassFeature, platformMethods, robustness,
|
||||
emulatedPrerotation, asyncCommandQueueFeatureVulkan,
|
||||
hasExplicitMemBarrierFeatureMtl, hasCheapRenderPassFeatureMtl,
|
||||
forceBufferGPUStorageFeatureMtl, supportsVulkanViewportFlip, emulatedVAOs,
|
||||
generateSPIRVThroughGlslang, captureLimits, forceRobustResourceInit,
|
||||
|
@ -75,7 +75,6 @@ struct EGLPlatformParameters
|
|||
EGLint deviceType = EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE;
|
||||
EGLint presentPath = EGL_DONT_CARE;
|
||||
EGLint debugLayersEnabled = EGL_DONT_CARE;
|
||||
EGLint contextVirtualization = EGL_DONT_CARE;
|
||||
EGLint robustness = EGL_DONT_CARE;
|
||||
EGLint transformFeedbackFeature = EGL_DONT_CARE;
|
||||
EGLint allocateNonZeroMemoryFeature = EGL_DONT_CARE;
|
||||
|
|
|
@ -188,23 +188,6 @@ bool EGLWindow::initializeDisplay(OSWindow *osWindow,
|
|||
displayAttributes.push_back(params.debugLayersEnabled);
|
||||
}
|
||||
|
||||
const bool hasFeatureVirtualizationANGLE =
|
||||
strstr(extensionString, "EGL_ANGLE_platform_angle_context_virtualization") != nullptr;
|
||||
|
||||
if (params.contextVirtualization != EGL_DONT_CARE)
|
||||
{
|
||||
if (hasFeatureVirtualizationANGLE)
|
||||
{
|
||||
displayAttributes.push_back(EGL_PLATFORM_ANGLE_CONTEXT_VIRTUALIZATION_ANGLE);
|
||||
displayAttributes.push_back(params.contextVirtualization);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,
|
||||
"EGL_ANGLE_platform_angle_context_virtualization extension not active\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (params.platformMethods)
|
||||
{
|
||||
static_assert(sizeof(EGLAttrib) == sizeof(params.platformMethods),
|
||||
|
@ -515,10 +498,10 @@ GLWindowContext EGLWindow::getCurrentContextGeneric()
|
|||
GLWindowContext EGLWindow::createContextGeneric(GLWindowContext share)
|
||||
{
|
||||
EGLContext shareContext = reinterpret_cast<EGLContext>(share);
|
||||
return reinterpret_cast<GLWindowContext>(createContext(shareContext));
|
||||
return reinterpret_cast<GLWindowContext>(createContext(shareContext, nullptr));
|
||||
}
|
||||
|
||||
EGLContext EGLWindow::createContext(EGLContext share)
|
||||
EGLContext EGLWindow::createContext(EGLContext share, EGLint *extraAttributes)
|
||||
{
|
||||
const char *displayExtensions = eglQueryString(mDisplay, EGL_EXTENSIONS);
|
||||
|
||||
|
@ -605,6 +588,13 @@ EGLContext EGLWindow::createContext(EGLContext share)
|
|||
}
|
||||
|
||||
std::vector<EGLint> contextAttributes;
|
||||
for (EGLint *extraAttrib = extraAttributes;
|
||||
extraAttrib != nullptr && extraAttrib[0] != EGL_NONE; extraAttrib += 2)
|
||||
{
|
||||
contextAttributes.push_back(extraAttrib[0]);
|
||||
contextAttributes.push_back(extraAttrib[1]);
|
||||
}
|
||||
|
||||
if (hasKHRCreateContext)
|
||||
{
|
||||
contextAttributes.push_back(EGL_CONTEXT_MAJOR_VERSION_KHR);
|
||||
|
@ -703,7 +693,7 @@ EGLContext EGLWindow::createContext(EGLContext share)
|
|||
|
||||
bool EGLWindow::initializeContext()
|
||||
{
|
||||
mContext = createContext(EGL_NO_CONTEXT);
|
||||
mContext = createContext(EGL_NO_CONTEXT, nullptr);
|
||||
if (mContext == EGL_NO_CONTEXT)
|
||||
{
|
||||
destroyGL();
|
||||
|
|
|
@ -174,7 +174,7 @@ class ANGLE_UTIL_EXPORT EGLWindow : public GLWindowBase
|
|||
const ConfigParameters ¶ms);
|
||||
|
||||
// Create an EGL context with this window's configuration
|
||||
EGLContext createContext(EGLContext share);
|
||||
EGLContext createContext(EGLContext share, EGLint *extraAttributes);
|
||||
// Make the EGL context current
|
||||
bool makeCurrent(EGLContext context);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче