• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1//
2// Copyright (c) 2019 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// DisplayMtl.mm: Metal implementation of DisplayImpl
8
9#include "libANGLE/renderer/metal/DisplayMtl.h"
10
11#include "libANGLE/Context.h"
12#include "libANGLE/Display.h"
13#include "libANGLE/Surface.h"
14#include "libANGLE/renderer/glslang_wrapper_utils.h"
15#include "libANGLE/renderer/metal/ContextMtl.h"
16#include "libANGLE/renderer/metal/SurfaceMtl.h"
17#include "libANGLE/renderer/metal/mtl_common.h"
18#include "libANGLE/renderer/metal/shaders/compiled/mtl_default_shaders.inc"
19#include "libANGLE/renderer/metal/shaders/mtl_default_shaders_src_autogen.inc"
20#include "platform/Platform.h"
21
22#include "EGL/eglext.h"
23
24namespace rx
25{
26
27bool IsMetalDisplayAvailable()
28{
29    // We only support macos 10.13+ and 11 for now. Since they are requirements for Metal 2.0.
30#if TARGET_OS_SIMULATOR
31    if (ANGLE_APPLE_AVAILABLE_XCI(10.13, 13.0, 13))
32#else
33    if (ANGLE_APPLE_AVAILABLE_XCI(10.13, 13.0, 11))
34#endif
35    {
36        return true;
37    }
38    return false;
39}
40
41DisplayImpl *CreateMetalDisplay(const egl::DisplayState &state)
42{
43    return new DisplayMtl(state);
44}
45
46DisplayMtl::DisplayMtl(const egl::DisplayState &state)
47    : DisplayImpl(state), mUtils(this), mGlslangInitialized(false)
48{}
49
50DisplayMtl::~DisplayMtl() {}
51
52egl::Error DisplayMtl::initialize(egl::Display *display)
53{
54    ASSERT(IsMetalDisplayAvailable());
55
56    angle::Result result = initializeImpl(display);
57    if (result != angle::Result::Continue)
58    {
59        return egl::EglNotInitialized();
60    }
61    return egl::NoError();
62}
63
64angle::Result DisplayMtl::initializeImpl(egl::Display *display)
65{
66    ANGLE_MTL_OBJC_SCOPE
67    {
68        mMetalDevice = [MTLCreateSystemDefaultDevice() ANGLE_MTL_AUTORELEASE];
69        if (!mMetalDevice)
70        {
71            return angle::Result::Stop;
72        }
73
74        mCmdQueue.set([[mMetalDevice.get() newCommandQueue] ANGLE_MTL_AUTORELEASE]);
75
76        mCapsInitialized = false;
77
78        if (!mGlslangInitialized)
79        {
80            GlslangInitialize();
81            mGlslangInitialized = true;
82        }
83
84        if (!mState.featuresAllDisabled)
85        {
86            initializeFeatures();
87        }
88
89        ANGLE_TRY(mFormatTable.initialize(this));
90        ANGLE_TRY(initializeShaderLibrary());
91
92        return mUtils.initialize();
93    }
94}
95
96void DisplayMtl::terminate()
97{
98    mUtils.onDestroy();
99    mCmdQueue.reset();
100    mDefaultShaders  = nil;
101    mMetalDevice     = nil;
102    mCapsInitialized = false;
103
104    if (mGlslangInitialized)
105    {
106        GlslangRelease();
107        mGlslangInitialized = false;
108    }
109}
110
111bool DisplayMtl::testDeviceLost()
112{
113    return false;
114}
115
116egl::Error DisplayMtl::restoreLostDevice(const egl::Display *display)
117{
118    return egl::NoError();
119}
120
121std::string DisplayMtl::getVendorString() const
122{
123    ANGLE_MTL_OBJC_SCOPE
124    {
125        std::string vendorString = "Google Inc.";
126        if (mMetalDevice)
127        {
128            vendorString += " Metal Renderer: ";
129            vendorString += mMetalDevice.get().name.UTF8String;
130        }
131
132        return vendorString;
133    }
134}
135
136DeviceImpl *DisplayMtl::createDevice()
137{
138    UNIMPLEMENTED();
139    return nullptr;
140}
141
142egl::Error DisplayMtl::waitClient(const gl::Context *context)
143{
144    auto contextMtl      = GetImplAs<ContextMtl>(context);
145    angle::Result result = contextMtl->finishCommandBuffer();
146
147    if (result != angle::Result::Continue)
148    {
149        return egl::EglBadAccess();
150    }
151    return egl::NoError();
152}
153
154egl::Error DisplayMtl::waitNative(const gl::Context *context, EGLint engine)
155{
156    UNIMPLEMENTED();
157    return egl::EglBadAccess();
158}
159
160SurfaceImpl *DisplayMtl::createWindowSurface(const egl::SurfaceState &state,
161                                             EGLNativeWindowType window,
162                                             const egl::AttributeMap &attribs)
163{
164    return new SurfaceMtl(this, state, window, attribs);
165}
166
167SurfaceImpl *DisplayMtl::createPbufferSurface(const egl::SurfaceState &state,
168                                              const egl::AttributeMap &attribs)
169{
170    UNIMPLEMENTED();
171    return static_cast<SurfaceImpl *>(0);
172}
173
174SurfaceImpl *DisplayMtl::createPbufferFromClientBuffer(const egl::SurfaceState &state,
175                                                       EGLenum buftype,
176                                                       EGLClientBuffer clientBuffer,
177                                                       const egl::AttributeMap &attribs)
178{
179    UNIMPLEMENTED();
180    return static_cast<SurfaceImpl *>(0);
181}
182
183SurfaceImpl *DisplayMtl::createPixmapSurface(const egl::SurfaceState &state,
184                                             NativePixmapType nativePixmap,
185                                             const egl::AttributeMap &attribs)
186{
187    UNIMPLEMENTED();
188    return static_cast<SurfaceImpl *>(0);
189}
190
191ImageImpl *DisplayMtl::createImage(const egl::ImageState &state,
192                                   const gl::Context *context,
193                                   EGLenum target,
194                                   const egl::AttributeMap &attribs)
195{
196    UNIMPLEMENTED();
197    return nullptr;
198}
199
200rx::ContextImpl *DisplayMtl::createContext(const gl::State &state,
201                                           gl::ErrorSet *errorSet,
202                                           const egl::Config *configuration,
203                                           const gl::Context *shareContext,
204                                           const egl::AttributeMap &attribs)
205{
206    return new ContextMtl(state, errorSet, this);
207}
208
209StreamProducerImpl *DisplayMtl::createStreamProducerD3DTexture(
210    egl::Stream::ConsumerType consumerType,
211    const egl::AttributeMap &attribs)
212{
213    UNIMPLEMENTED();
214    return nullptr;
215}
216
217ShareGroupImpl *DisplayMtl::createShareGroup()
218{
219    return new ShareGroupMtl();
220}
221
222gl::Version DisplayMtl::getMaxSupportedESVersion() const
223{
224    return mtl::kMaxSupportedGLVersion;
225}
226
227gl::Version DisplayMtl::getMaxConformantESVersion() const
228{
229    return std::min(getMaxSupportedESVersion(), gl::Version(2, 0));
230}
231
232EGLSyncImpl *DisplayMtl::createSync(const egl::AttributeMap &attribs)
233{
234    UNIMPLEMENTED();
235    return nullptr;
236}
237
238egl::Error DisplayMtl::makeCurrent(egl::Surface *drawSurface,
239                                   egl::Surface *readSurface,
240                                   gl::Context *context)
241{
242    if (!context)
243    {
244        return egl::NoError();
245    }
246
247    return egl::NoError();
248}
249
250void DisplayMtl::generateExtensions(egl::DisplayExtensions *outExtensions) const
251{
252    outExtensions->flexibleSurfaceCompatibility = true;
253}
254
255void DisplayMtl::generateCaps(egl::Caps *outCaps) const {}
256
257void DisplayMtl::populateFeatureList(angle::FeatureList *features) {}
258
259egl::ConfigSet DisplayMtl::generateConfigs()
260{
261    // NOTE(hqle): generate more config permutations
262    egl::ConfigSet configs;
263
264    const gl::Version &maxVersion = getMaxSupportedESVersion();
265    ASSERT(maxVersion >= gl::Version(2, 0));
266    bool supportsES3 = maxVersion >= gl::Version(3, 0);
267
268    egl::Config config;
269
270    // Native stuff
271    config.nativeVisualID   = 0;
272    config.nativeVisualType = 0;
273    config.nativeRenderable = EGL_TRUE;
274
275    config.colorBufferType = EGL_RGB_BUFFER;
276    config.luminanceSize   = 0;
277    config.alphaMaskSize   = 0;
278
279    config.transparentType = EGL_NONE;
280
281    // Pbuffer
282    config.maxPBufferWidth  = 4096;
283    config.maxPBufferHeight = 4096;
284    config.maxPBufferPixels = 4096 * 4096;
285
286    // Caveat
287    config.configCaveat = EGL_NONE;
288
289    // Misc
290    config.sampleBuffers     = 0;
291    config.samples           = 0;
292    config.level             = 0;
293    config.bindToTextureRGB  = EGL_FALSE;
294    config.bindToTextureRGBA = EGL_FALSE;
295
296    config.surfaceType = EGL_WINDOW_BIT;
297
298    config.minSwapInterval = 1;
299    config.maxSwapInterval = 1;
300
301    config.renderTargetFormat = GL_RGBA8;
302    config.depthStencilFormat = GL_DEPTH24_STENCIL8;
303
304    config.conformant     = EGL_OPENGL_ES2_BIT | (supportsES3 ? EGL_OPENGL_ES3_BIT_KHR : 0);
305    config.renderableType = config.conformant;
306
307    config.matchNativePixmap = EGL_NONE;
308
309    config.colorComponentType = EGL_COLOR_COMPONENT_TYPE_FIXED_EXT;
310
311    // Buffer sizes
312    config.redSize    = 8;
313    config.greenSize  = 8;
314    config.blueSize   = 8;
315    config.alphaSize  = 8;
316    config.bufferSize = config.redSize + config.greenSize + config.blueSize + config.alphaSize;
317
318    // With DS
319    config.depthSize   = 24;
320    config.stencilSize = 8;
321    configs.add(config);
322
323    // With D
324    config.depthSize   = 24;
325    config.stencilSize = 0;
326    configs.add(config);
327
328    // With S
329    config.depthSize   = 0;
330    config.stencilSize = 8;
331    configs.add(config);
332
333    // No DS
334    config.depthSize   = 0;
335    config.stencilSize = 0;
336    configs.add(config);
337
338    return configs;
339}
340
341bool DisplayMtl::isValidNativeWindow(EGLNativeWindowType window) const
342{
343    NSObject *layer = (__bridge NSObject *)(window);
344    return [layer isKindOfClass:[CALayer class]];
345}
346
347std::string DisplayMtl::getRendererDescription() const
348{
349    ANGLE_MTL_OBJC_SCOPE
350    {
351        std::string desc = "Metal Renderer";
352
353        if (mMetalDevice)
354        {
355            desc += ": ";
356            desc += mMetalDevice.get().name.UTF8String;
357        }
358
359        return desc;
360    }
361}
362
363gl::Caps DisplayMtl::getNativeCaps() const
364{
365    ensureCapsInitialized();
366    return mNativeCaps;
367}
368const gl::TextureCapsMap &DisplayMtl::getNativeTextureCaps() const
369{
370    ensureCapsInitialized();
371    return mNativeTextureCaps;
372}
373const gl::Extensions &DisplayMtl::getNativeExtensions() const
374{
375    ensureCapsInitialized();
376    return mNativeExtensions;
377}
378
379void DisplayMtl::ensureCapsInitialized() const
380{
381    if (mCapsInitialized)
382    {
383        return;
384    }
385
386    mCapsInitialized = true;
387
388    // Reset
389    mNativeCaps = gl::Caps();
390
391    // Fill extension and texture caps
392    initializeExtensions();
393    initializeTextureCaps();
394
395    // https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf
396    mNativeCaps.maxElementIndex  = std::numeric_limits<GLuint>::max() - 1;
397    mNativeCaps.max3DTextureSize = 2048;
398#if TARGET_OS_OSX || TARGET_OS_MACCATALYST
399    mNativeCaps.max2DTextureSize          = 16384;
400    mNativeCaps.maxVaryingVectors         = 31;
401    mNativeCaps.maxVertexOutputComponents = 124;
402#else
403    if ([getMetalDevice() supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily3_v1])
404    {
405        mNativeCaps.max2DTextureSize          = 16384;
406        mNativeCaps.maxVertexOutputComponents = 124;
407        mNativeCaps.maxVaryingVectors         = mNativeCaps.maxVertexOutputComponents / 4;
408    }
409    else
410    {
411        mNativeCaps.max2DTextureSize          = 8192;
412        mNativeCaps.maxVertexOutputComponents = 60;
413        mNativeCaps.maxVaryingVectors         = mNativeCaps.maxVertexOutputComponents / 4;
414    }
415#endif
416
417    mNativeCaps.maxArrayTextureLayers = 2048;
418    mNativeCaps.maxLODBias            = 0;
419    mNativeCaps.maxCubeMapTextureSize = mNativeCaps.max2DTextureSize;
420    mNativeCaps.maxRenderbufferSize   = mNativeCaps.max2DTextureSize;
421    mNativeCaps.minAliasedPointSize   = 1;
422    mNativeCaps.maxAliasedPointSize   = 511;
423
424    mNativeCaps.minAliasedLineWidth = 1.0f;
425    mNativeCaps.maxAliasedLineWidth = 1.0f;
426
427    mNativeCaps.maxDrawBuffers       = mtl::kMaxRenderTargets;
428    mNativeCaps.maxFramebufferWidth  = mNativeCaps.max2DTextureSize;
429    mNativeCaps.maxFramebufferHeight = mNativeCaps.max2DTextureSize;
430    mNativeCaps.maxColorAttachments  = mtl::kMaxRenderTargets;
431    mNativeCaps.maxViewportWidth     = mNativeCaps.max2DTextureSize;
432    mNativeCaps.maxViewportHeight    = mNativeCaps.max2DTextureSize;
433
434    // NOTE(hqle): MSAA
435    mNativeCaps.maxSampleMaskWords     = 0;
436    mNativeCaps.maxColorTextureSamples = 1;
437    mNativeCaps.maxDepthTextureSamples = 1;
438    mNativeCaps.maxIntegerSamples      = 1;
439
440    mNativeCaps.maxVertexAttributes           = mtl::kMaxVertexAttribs;
441    mNativeCaps.maxVertexAttribBindings       = mtl::kMaxVertexAttribs;
442    mNativeCaps.maxVertexAttribRelativeOffset = std::numeric_limits<GLint>::max();
443    mNativeCaps.maxVertexAttribStride         = std::numeric_limits<GLint>::max();
444
445    mNativeCaps.maxElementsIndices  = std::numeric_limits<GLuint>::max();
446    mNativeCaps.maxElementsVertices = std::numeric_limits<GLuint>::max();
447
448    // Looks like all floats are IEEE according to the docs here:
449    mNativeCaps.vertexHighpFloat.setIEEEFloat();
450    mNativeCaps.vertexMediumpFloat.setIEEEFloat();
451    mNativeCaps.vertexLowpFloat.setIEEEFloat();
452    mNativeCaps.fragmentHighpFloat.setIEEEFloat();
453    mNativeCaps.fragmentMediumpFloat.setIEEEFloat();
454    mNativeCaps.fragmentLowpFloat.setIEEEFloat();
455
456    mNativeCaps.vertexHighpInt.setTwosComplementInt(32);
457    mNativeCaps.vertexMediumpInt.setTwosComplementInt(32);
458    mNativeCaps.vertexLowpInt.setTwosComplementInt(32);
459    mNativeCaps.fragmentHighpInt.setTwosComplementInt(32);
460    mNativeCaps.fragmentMediumpInt.setTwosComplementInt(32);
461    mNativeCaps.fragmentLowpInt.setTwosComplementInt(32);
462
463    GLuint maxUniformVectors = mtl::kDefaultUniformsMaxSize / (sizeof(GLfloat) * 4);
464
465    const GLuint maxUniformComponents = maxUniformVectors * 4;
466
467    // Uniforms are implemented using a uniform buffer, so the max number of uniforms we can
468    // support is the max buffer range divided by the size of a single uniform (4X float).
469    mNativeCaps.maxVertexUniformVectors                              = maxUniformVectors;
470    mNativeCaps.maxShaderUniformComponents[gl::ShaderType::Vertex]   = maxUniformComponents;
471    mNativeCaps.maxFragmentUniformVectors                            = maxUniformVectors;
472    mNativeCaps.maxShaderUniformComponents[gl::ShaderType::Fragment] = maxUniformComponents;
473
474    // NOTE(hqle): support UBO (ES 3.0 feature)
475    mNativeCaps.maxShaderUniformBlocks[gl::ShaderType::Vertex]   = 0;
476    mNativeCaps.maxShaderUniformBlocks[gl::ShaderType::Fragment] = 0;
477    mNativeCaps.maxCombinedUniformBlocks                         = 0;
478
479    // Note that we currently implement textures as combined image+samplers, so the limit is
480    // the minimum of supported samplers and sampled images.
481    mNativeCaps.maxCombinedTextureImageUnits                         = mtl::kMaxGLSamplerBindings;
482    mNativeCaps.maxShaderTextureImageUnits[gl::ShaderType::Fragment] = mtl::kMaxShaderSamplers;
483    mNativeCaps.maxShaderTextureImageUnits[gl::ShaderType::Vertex]   = mtl::kMaxShaderSamplers;
484
485    // NOTE(hqle): support storage buffer.
486    const uint32_t maxPerStageStorageBuffers                     = 0;
487    mNativeCaps.maxShaderStorageBlocks[gl::ShaderType::Vertex]   = maxPerStageStorageBuffers;
488    mNativeCaps.maxShaderStorageBlocks[gl::ShaderType::Fragment] = maxPerStageStorageBuffers;
489    mNativeCaps.maxCombinedShaderStorageBlocks                   = maxPerStageStorageBuffers;
490
491    // Fill in additional limits for UBOs and SSBOs.
492    mNativeCaps.maxUniformBufferBindings     = 0;
493    mNativeCaps.maxUniformBlockSize          = 0;
494    mNativeCaps.uniformBufferOffsetAlignment = 0;
495
496    mNativeCaps.maxShaderStorageBufferBindings     = 0;
497    mNativeCaps.maxShaderStorageBlockSize          = 0;
498    mNativeCaps.shaderStorageBufferOffsetAlignment = 0;
499
500    // NOTE(hqle): support UBO
501    for (gl::ShaderType shaderType : gl::kAllGraphicsShaderTypes)
502    {
503        mNativeCaps.maxCombinedShaderUniformComponents[shaderType] = maxUniformComponents;
504    }
505
506    mNativeCaps.maxCombinedShaderOutputResources = 0;
507
508    mNativeCaps.maxTransformFeedbackInterleavedComponents =
509        gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS;
510    mNativeCaps.maxTransformFeedbackSeparateAttributes =
511        gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS;
512    mNativeCaps.maxTransformFeedbackSeparateComponents =
513        gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS;
514
515    // NOTE(hqle): support MSAA.
516    mNativeCaps.maxSamples = 1;
517
518    // GL_APPLE_clip_distance
519    mNativeCaps.maxClipDistances = 8;
520}
521
522void DisplayMtl::initializeExtensions() const
523{
524    // Reset
525    mNativeExtensions = gl::Extensions();
526
527    // Enable this for simple buffer readback testing, but some functionality is missing.
528    // NOTE(hqle): Support full mapBufferRange extension.
529    mNativeExtensions.mapBufferOES           = true;
530    mNativeExtensions.mapBufferRange         = false;
531    mNativeExtensions.textureStorage         = true;
532    mNativeExtensions.drawBuffers            = false;
533    mNativeExtensions.fragDepth              = true;
534    mNativeExtensions.framebufferBlit        = false;
535    mNativeExtensions.framebufferMultisample = false;
536    mNativeExtensions.copyTexture            = false;
537    mNativeExtensions.copyCompressedTexture  = false;
538    mNativeExtensions.debugMarker            = false;
539    mNativeExtensions.robustness             = true;
540    mNativeExtensions.textureBorderClampOES  = false;  // not implemented yet
541    mNativeExtensions.translatedShaderSource = true;
542    mNativeExtensions.discardFramebuffer     = true;
543
544    // Enable EXT_blend_minmax
545    mNativeExtensions.blendMinMax = true;
546
547    mNativeExtensions.eglImageOES         = false;
548    mNativeExtensions.eglImageExternalOES = false;
549    // NOTE(hqle): Support GL_OES_EGL_image_external_essl3.
550    mNativeExtensions.eglImageExternalEssl3OES = false;
551
552    mNativeExtensions.memoryObject   = false;
553    mNativeExtensions.memoryObjectFd = false;
554
555    mNativeExtensions.semaphore   = false;
556    mNativeExtensions.semaphoreFd = false;
557
558    mNativeExtensions.instancedArraysANGLE = mFeatures.hasBaseVertexInstancedDraw.enabled;
559    mNativeExtensions.instancedArraysEXT   = mNativeExtensions.instancedArraysANGLE;
560
561    mNativeExtensions.robustBufferAccessBehavior = false;
562
563    mNativeExtensions.eglSyncOES = false;
564
565    // NOTE(hqle): support occlusion query
566    mNativeExtensions.occlusionQueryBoolean = false;
567
568    mNativeExtensions.disjointTimerQuery          = false;
569    mNativeExtensions.queryCounterBitsTimeElapsed = false;
570    mNativeExtensions.queryCounterBitsTimestamp   = false;
571
572    mNativeExtensions.textureFilterAnisotropic = true;
573    mNativeExtensions.maxTextureAnisotropy     = 16;
574
575    // NOTE(hqle): Support true NPOT textures.
576    mNativeExtensions.textureNPOTOES = false;
577
578    mNativeExtensions.texture3DOES = false;
579
580    mNativeExtensions.standardDerivativesOES = true;
581
582    mNativeExtensions.elementIndexUintOES = true;
583
584    // GL_APPLE_clip_distance
585    mNativeExtensions.clipDistanceAPPLE = true;
586}
587
588void DisplayMtl::initializeTextureCaps() const
589{
590    mNativeTextureCaps.clear();
591
592    mFormatTable.generateTextureCaps(this, &mNativeTextureCaps,
593                                     &mNativeCaps.compressedTextureFormats);
594
595    // Re-verify texture extensions.
596    mNativeExtensions.setTextureExtensionSupport(mNativeTextureCaps);
597
598    // Disable all depth buffer and stencil buffer readback extensions until we need them
599    mNativeExtensions.readDepthNV         = false;
600    mNativeExtensions.readStencilNV       = false;
601    mNativeExtensions.depthBufferFloat2NV = false;
602}
603
604void DisplayMtl::initializeFeatures()
605{
606    // default values:
607    mFeatures.hasBaseVertexInstancedDraw.enabled        = true;
608    mFeatures.hasDepthTextureFiltering.enabled          = false;
609    mFeatures.hasNonUniformDispatch.enabled             = true;
610    mFeatures.hasTextureSwizzle.enabled                 = false;
611    mFeatures.allowSeparatedDepthStencilBuffers.enabled = false;
612
613#if TARGET_OS_OSX || TARGET_OS_MACCATALYST
614    mFeatures.hasDepthTextureFiltering.enabled = true;
615
616    // Texture swizzle is only supported if macos sdk 10.15 is present
617#    if defined(__MAC_10_15)
618    if (ANGLE_APPLE_AVAILABLE_XC(10.15, 13.0))
619    {
620        // The runtime OS must be MacOS 10.15+ or Mac Catalyst for this to be supported:
621        ANGLE_FEATURE_CONDITION((&mFeatures), hasTextureSwizzle,
622                                [getMetalDevice() supportsFamily:MTLGPUFamilyMac2]);
623    }
624#    endif
625#elif TARGET_OS_IOS
626    // Base Vertex drawing is only supported since GPU family 3.
627    ANGLE_FEATURE_CONDITION((&mFeatures), hasBaseVertexInstancedDraw,
628                            [getMetalDevice() supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily3_v1]);
629
630    ANGLE_FEATURE_CONDITION((&mFeatures), hasNonUniformDispatch,
631                            [getMetalDevice() supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily4_v1]);
632
633#    if !TARGET_OS_SIMULATOR
634    mFeatures.allowSeparatedDepthStencilBuffers.enabled = true;
635#    endif
636#endif
637
638    angle::PlatformMethods *platform = ANGLEPlatformCurrent();
639    platform->overrideFeaturesMtl(platform, &mFeatures);
640}
641
642angle::Result DisplayMtl::initializeShaderLibrary()
643{
644    mtl::AutoObjCObj<NSError> err = nil;
645
646#if defined(ANGLE_MTL_DEBUG_INTERNAL_SHADERS)
647    mDefaultShaders = CreateShaderLibrary(getMetalDevice(), default_metallib_src,
648                                          sizeof(default_metallib_src), &err);
649#else
650    mDefaultShaders = CreateShaderLibraryFromBinary(getMetalDevice(), compiled_default_metallib,
651                                                    compiled_default_metallib_len, &err);
652#endif
653
654    if (err && !mDefaultShaders)
655    {
656        ANGLE_MTL_OBJC_SCOPE
657        {
658            ERR() << "Internal error: " << err.get().localizedDescription.UTF8String;
659        }
660        return angle::Result::Stop;
661    }
662
663    return angle::Result::Continue;
664}
665
666}  // namespace rx
667