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:
Geoff Lang 2021-09-17 12:57:14 -04:00 коммит произвёл Angle LUCI CQ
Родитель 48b605d845
Коммит d2c01d2ce5
23 изменённых файлов: 201 добавлений и 257 удалений

Просмотреть файл

@ -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 &params)
{
PlatformParameters withNoVirtualContexts = params;
withNoVirtualContexts.eglParameters.contextVirtualization = EGL_FALSE;
return withNoVirtualContexts;
}
inline PlatformParameters WithNoFixture(const PlatformParameters &params)
{
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 &params);
// 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);