diff --git a/extensions/EGL_ANGLE_device_mtl.txt b/extensions/EGL_ANGLE_device_mtl.txt new file mode 100644 index 0000000000..933c02d937 --- /dev/null +++ b/extensions/EGL_ANGLE_device_mtl.txt @@ -0,0 +1,90 @@ +Name + + ANGLE_device_mtl + +Name Strings + + EGL_ANGLE_device_mtl + +Contributors + + Le Hoang Quyen + +Contact + + Le Hoang Quyen (lehoangq 'at' gmail.com) + +Status + + Draft + +Version + + Version 1, Jul 19, 2020 + +Number + + EGL Extension #XXX + +Extension Type + + EGL device extension + +Dependencies + + This extension is written against the language of EGL 1.5 as + modified by EGL_EXT_device_query. + + EGL_EXT_device_query is required. + +Overview + + ANGLE has the ability to run GPU commands on a metal device. + This extension defines a mapping from an EGL device to a metal + device, after it's queried from an EGL display. + +IP Status + + No known claims. + +New Types + + None. + +New Procedures and Functions + + None. + +New Tokens + + Accepted as a queried in eglQueryDeviceAttribEXT: + + EGL_MTL_DEVICE_ANGLE 0x33A2 + +Add a new section 2.1.3 (Metal Devices) after 2.1.2 (Devices) + + Somewhat analogous to an EGL device, a Metal device establishes a + namespace for Metal operations. In the Metal APIs, such devices are + represented by pointers. For more details, see the Metal + documentation. + +Changes to section 3.2 (Devices) + + Replace the paragraph immediately following the prototype for + eglQueryDeviceAttribEXT: + + may be EGL_MTL_DEVICE_ANGLE. + On success, EGL_TRUE is returned, and a valid MTLDevice pointer + corresponding to the EGL device is returned in . This handle + is compatible with Metal API functions. If the EGL device is not currently + associated with a Metal device and is EGL_MTL_DEVICE_ANGLE, + EGL_BAD_ATTRIBUTE is returned, and is left unchanged. + +Issues + + None + +Revision History + + Version 1, Jul 19, 2020 (Le Hoang Quyen) + - Initial Draft diff --git a/include/EGL/eglext_angle.h b/include/EGL/eglext_angle.h index 38fdb46129..85ad56540c 100644 --- a/include/EGL/eglext_angle.h +++ b/include/EGL/eglext_angle.h @@ -254,6 +254,11 @@ EGLAPI EGLBoolean EGLAPIENTRY eglQueryDisplayAttribANGLE(EGLDisplay dpy, EGLint #define EGL_CGL_PIXEL_FORMAT_ANGLE 0x3486 #endif +#ifndef EGL_ANGLE_device_mtl +#define EGL_ANGLE_device_mtl 1 +#define EGL_MTL_DEVICE_ANGLE 0x33A2 +#endif /* EGL_ANGLE_device_mtl */ + // clang-format on #endif // INCLUDE_EGL_EGLEXT_ANGLE_ diff --git a/src/libANGLE/Caps.cpp b/src/libANGLE/Caps.cpp index 5d66178d11..860e0b1de9 100644 --- a/src/libANGLE/Caps.cpp +++ b/src/libANGLE/Caps.cpp @@ -1274,6 +1274,7 @@ std::vector DeviceExtensions::getStrings() const // | Extension name | Supported flag | Output vector | InsertExtensionString("EGL_ANGLE_device_d3d", deviceD3D, &extensionStrings); InsertExtensionString("EGL_ANGLE_device_cgl", deviceCGL, &extensionStrings); + InsertExtensionString("EGL_ANGLE_device_mtl", deviceMTL, &extensionStrings); // clang-format on return extensionStrings; diff --git a/src/libANGLE/Caps.h b/src/libANGLE/Caps.h index 7b2767ca8c..846de6dc92 100644 --- a/src/libANGLE/Caps.h +++ b/src/libANGLE/Caps.h @@ -975,6 +975,9 @@ struct DeviceExtensions // EGL_ANGLE_device_cgl bool deviceCGL = false; + + // EGL_ANGLE_device_mtl + bool deviceMTL = false; }; struct ClientExtensions diff --git a/src/libANGLE/renderer/metal/DisplayMtl.mm b/src/libANGLE/renderer/metal/DisplayMtl.mm index fcbd12d53c..7169d7d1fe 100644 --- a/src/libANGLE/renderer/metal/DisplayMtl.mm +++ b/src/libANGLE/renderer/metal/DisplayMtl.mm @@ -11,6 +11,7 @@ #include "libANGLE/Context.h" #include "libANGLE/Display.h" #include "libANGLE/Surface.h" +#include "libANGLE/renderer/DeviceImpl.h" #include "libANGLE/renderer/glslang_wrapper_utils.h" #include "libANGLE/renderer/metal/ContextMtl.h" #include "libANGLE/renderer/metal/SurfaceMtl.h" @@ -43,6 +44,37 @@ bool IsMetalDisplayAvailable() return new DisplayMtl(state); } +// DeviceMTL implementation, implements DeviceImpl +class DeviceMTL : public DeviceImpl +{ + public: + DeviceMTL() {} + ~DeviceMTL() override {} + + egl::Error initialize() override { return egl::NoError(); } + egl::Error getAttribute(const egl::Display *display, EGLint attribute, void **outValue) override + { + DisplayMtl *displayImpl = mtl::GetImpl(display); + + switch (attribute) + { + case EGL_MTL_DEVICE_ANGLE: + *outValue = displayImpl->getMetalDevice(); + break; + default: + return egl::EglBadAttribute(); + } + + return egl::NoError(); + } + EGLint getType() override { return 0; } + void generateExtensions(egl::DeviceExtensions *outExtensions) const override + { + outExtensions->deviceMTL = true; + } +}; + +// DisplayMtl implementation DisplayMtl::DisplayMtl(const egl::DisplayState &state) : DisplayImpl(state), mStateCache(mFeatures), mUtils(this) {} @@ -125,8 +157,7 @@ bool IsMetalDisplayAvailable() DeviceImpl *DisplayMtl::createDevice() { - UNIMPLEMENTED(); - return nullptr; + return new DeviceMTL(); } egl::Error DisplayMtl::waitClient(const gl::Context *context) @@ -237,6 +268,7 @@ bool IsMetalDisplayAvailable() outExtensions->fenceSync = true; outExtensions->waitSync = true; outExtensions->glColorspace = true; + outExtensions->deviceQuery = true; } void DisplayMtl::generateCaps(egl::Caps *outCaps) const {} diff --git a/src/libGLESv2/entry_points_egl_ext.cpp b/src/libGLESv2/entry_points_egl_ext.cpp index 64142dae92..1ddd5a3190 100644 --- a/src/libGLESv2/entry_points_egl_ext.cpp +++ b/src/libGLESv2/entry_points_egl_ext.cpp @@ -301,6 +301,15 @@ EGLBoolean EGLAPIENTRY EGL_QueryDeviceAttribEXT(EGLDeviceEXT device, } error = dev->getAttribute(attribute, value); break; + case EGL_MTL_DEVICE_ANGLE: + if (!dev->getExtensions().deviceMTL) + { + thread->setError(EglBadAttribute(), GetDebug(), "eglQueryDeviceAttribEXT", + GetDeviceIfValid(dev)); + return EGL_FALSE; + } + error = dev->getAttribute(attribute, value); + break; case EGL_CGL_CONTEXT_ANGLE: case EGL_CGL_PIXEL_FORMAT_ANGLE: if (!dev->getExtensions().deviceCGL)