MoltenGL 0.16.1 User Guide

Copyright (c) 2014-2017 The Brenwill Workshop Ltd. All rights reserved.

Table of Contents

Molten License Agreement

CAREFULLY READ THE Molten LICENSE AGREEMENT, FOUND IN THIS Molten DISTRIBUTION PACKAGE. BY INSTALLING OR OTHERWISE USING THIS Molten DISTRIBUTION PACKAGE, YOU ACCEPT AND AGREE TO BE BOUND BY THE TERMS AND CONDITIONS OF THE Molten LICENSE AGREEMENT. IF YOU DO NOT ACCEPT THE TERMS AND CONDITIONS OF THE Molten LICENSE AGREEMENT, DO NOT INSTALL OR USE THIS Molten DISTRIBUTION PACKAGE.

About MoltenGL

MoltenGL is an implementation of the OpenGL ES 2.0 API, that runs on Apple's Metal graphics framework on both iOS and macOS.

MoltenGL provides the performance benefits and added debugging and tracing capabilities of the Metal framework, while maintaining compliance with the proven OpenGL ES 2.0 API. Applications built on OpenGL ES 2.0, can use MoltenGL to provide additional graphic performance and development capabilities, without having to abandon the familiar OpenGL ES 2.0 API, or rewrite rendering logic and shaders for different platforms.

MoltenGL runs on either iOS or macOS, and provides a fast implementation of OpenGL ES 2.0 on both platforms. In addition to improving performance on each platform, MoltenGL allows you to easily transfer your OpenGL ES 2.0 application from iOS to macOS without having to rewrite your application in desktop OpenGL for use on macOS. On both platforms, your OpenGL ES 2.0 application will benefit from the speed and additional debugging and tracing capabilities of Metal.

MoltenGL automatically detects whether the device your application is running on supports Metal, and will use the Metal framework where available. When running on a device that does not support Metal, MoltenGL will automatically downshift, and transparently make use of the native OpenGL ES 2.0 rendering engine (see the Adding Support for Native OpenGL ES 2.0 in macOS section below for how to arrange this on the macOS platform).

Metal uses a different shading language, the Metal Shading Language (MSL), than OpenGL ES 2.0, which uses the OpenGL Shading Language (GLSL). However, fear not, as MoltenGL will automatically convert your GLSL shaders to their MSL equivalents. This can be performed transparently at run time, using the Runtime Shader Conversion feature of MoltenGL, or at development time using the MoltenGLShaderConverter tool provided with MoltenGL.

Running the MoltenGL Demo Applications

You can explore the range of performance improvements and additional debugging and tracing capabilities that MoltenGL can bring to your OpenGL ES applications by reviewing and running the demo applications that come with MoltenGL.

The MoltenGL sample apps are located in the MoltenGL/Demos folder within the Molten distribution package. Each demo app is available as an Xcode project. To allow you to compare performance, each app project can be built to render using either MoltenGL, or the native OpenGL ES engine.

To review and run all of the available demo apps, open the MoltenGL/Demos/Demos.xcworkspace workspace in Xcode.

Please read the Demos/README_MoltenGL_Demos.md document for a description of each demo app, and instructions on running the demo apps. In particular, run the DrawLoad sample app, to explore the conditions under which Metal performs better than OpenGL

Installing MoltenGL in Your OpenGL ES 2.0 Application

Installation of MoltenGL is straightforward and easy! To add MoltenGL to your OpenGL ES 2.0 application, follow the steps in this section. If you're new to MoltenGL, it is recommended that you start with a smaller project to help you understand the transition, and to reduce the possibility of needing to make modifications to your shaders to ensure their compatibility with the Metal environment.

  1. Open your application in Xcode and select your application's project in the Project Navigator panel.

  2. MoltenGL intercepts and redirects your application's OpenGL API calls to functionality within MoltenGL. To enable this, you need to make a few changes to the Build Settings in your Xcode project, as follows:

    1. In the Project Navigator panel, select your application's project, and open the Build Settings tab.
    2. Set the Always Search User Paths (aka ALWAYS_SEARCH_USER_PATHS) setting to YES.
    3. In the User Header Search Paths (aka USER_HEADER_SEARCH_PATHS) setting, add an entry that points to the MoltenGL/RedirectHeaders/include folder, found in the Molten distribution package, and mark it as recursive. Be sure that you have not included the MoltenGL/RedirectHeaders/orig folder.
    4. Set the Enable Modules (C and Objective-C) (aka CLANG_ENABLE_MODULES) setting to NO. Modules interfere with the ability to redirect the OpenGL API references.

    (Alternately, you can make the above changes to the Xcode project targets that reference OpenGL API or EAGL header files).

  3. Repeat the previous step for any Xcode sub-projects that also reference OpenGL API or EAGL header files.

  4. Within Xcode, add the MoltenGL framework to your application as follows:

    1. In the Project Navigator panel, select your application's project, select the Build Phases tab, and open the Link Binary With Libraries list.
    2. Click the + button, and in the dialog window that opens, click the Add Other... button. Locate MoltenGL/iOS/MoltenGL.framework in the Molten distribution package (or locate MoltenGL/macOS/MoltenGL.framework if building an macOS app), and click the Open button.
    3. In the Link Binary With Libraries list, click the + button again, and (selecting from the list of system frameworks) add Metal.framework and libc++.tbd (or libc++.dylib in Xcode 6 and earlier).
    4. In the Build Settings tab, ensure the Framework Search Paths (aka FRAMEWORK_SEARCH_PATHS) build setting includes a reference to the MoltenGL/iOS folder in the Molten distribution package (or the MoltenGL/macOS folder if building an macOS app). In some circumstances, Xcode 7 and later versions may not automatically populate this setting when the MoltenGL.framework is added to your project.
    5. Because of the need to set the Enable Modules (C and Objective-C) (aka CLANG_ENABLE_MODULES) build setting to NO (see above), the Link Frameworks Automatically (aka CLANG_MODULES_AUTOLINK) build setting will no longer have any effect. If you have not already done so, in the Link Binary With Libraries list, ensure that you have added any other system frameworks that your application uses (e.g. OpenGLES, UIKit, GLKit, QuartzCore, etc.).
  5. If you are just starting out, and want to make use of Runtime Shader Conversion to transparently convert your OpenGL shaders to Metal shaders at runtime, you can add the MoltenGL Shader Converter framework to your application as follows. If you already have Metal versions of your shaders, you can skip this step.

    1. In the Project Navigator panel, select your application's project, select the Build Phases tab, and open the Link Binary With Libraries list.
    2. Click the + button, and in the dialog window that opens, click the Add Other... button. Locate MoltenGLShaderConverter/iOS/MoltenGLShaderConverter.framework in the Molten distribution package (or locate MoltenGLShaderConverter/macOS/MoltenGLShaderConverter.framework if building an macOS app), and click the Open button.
    3. In the Build Settings tab, ensure the Framework Search Paths (aka FRAMEWORK_SEARCH_PATHS) build setting includes a reference to the MoltenGLShaderConverter/iOS folder in the Molten distribution package (or the MoltenGLShaderConverter/macOS folder if building an macOS app). In some circumstances, Xcode 7 and later versions may not automatically populate this setting when the MoltenGLShaderConverter.framework is added to your project.
    4. In the Build Settings tab, ensure that the Other Linker Flags (aka OTHER_LDFLAGS) setting includes an entry for -ObjC. Since the shader converter framework is optional and weakly-linked, this entry ensures Xcode will add the MoltenGLShaderConverter.framework to the application during the link phase.
  6. If you are building an iOS application, skip this step. If you are building an macOS application, drag the four files: gl.m, glext.m, egl.m, and EAGL.m from the MoltenGL/macOS folder in the Molten distribution package to your application project in the Xcode Project Navigator panel. In the dialog that opens, add the files to your application's macOS target.

    These files provide a non-functional "native" OpenGL ES 2.0 stub API for macOS, to satisfy the linker. If you will only be running your macOS application on devices that support Metal, this is sufficient. If you will be running your macOS application on legacy devices and versions of macOS that don't support Metal, you can add a full "native" implementation of OpenGL ES 2.0 for macOS by following the steps in the Adding Support for Native OpenGL ES 2.0 in macOS section below.

  7. When a Metal app is running from Xcode, the default Scheme settings reduce performance. To improve performance and gain the benefits of Metal, perform the following in Xcode:

    1. Open the Scheme Editor for building your main application. You can do this by selecting Edit Scheme... from the Scheme drop-down menu, or select Product -> Scheme -> Edit Scheme... from the main menu.
    2. On the Info tab, set the Build Configuration to Release, and disable the Debug executable check-box.
    3. On the Options tab, disable both the Metal API Validation and GPU Frame Capture options. For optimal performance, you may also consider disabling the other simulation and debugging options on this tab. For further information, see the Xcode Scheme Settings and Performance section of Apple's Metal Programming Guide documentation.
  8. Build and run your application.

You can tell whether your application is now using Metal by checking the logs for an entry similar to the following:

[mgl-info] OpenGL functionality using Metal provided by MoltenGL 0.16.1 (build X). 

You can also verify that your application is now using Metal by Using Xcode to capture a GPU frame.

If you find that your application is not running Metal, the first thing you should do is verify that the device supports Metal. Metal requires iOS 8 running on a device with at least a 64-bit A7 processor, or a Mac running macOS 10.11. Then check that the path to the MoltenGL/RedirectHeaders/include folder that you configured in the User Header Search Paths (aka USER_HEADER_SEARCH_PATHS) build setting is correct, and has been marked recursive. If it is not accurate, redirection of the OpenGL API calls into MoltenGL functionality will not occur, and your application will continue to use the native OpenGL ES libraries.

Adding Support for Native OpenGL ES 2.0 in macOS

When using MoltenGL on macOS, on a device or version of macOS that does not support Metal, your OpenGL ES 2.0 app needs to be able to access a "native" OpenGL ES 2.0 implementation. macOS supports desktop OpenGL by default, and so an OpenGL ES 2.0 implementation must be provided for use on macOS if Metal is not available.

You do not need to install a native OpenGL ES 2.0 implementation if your app will only run on an macOS device that supports Metal, or when running your app on iOS, as iOS already provides a native OpenGL ES 2.0 implementation.

You can use any "native" OpenGL ES implementation for macOS you prefer. If you do not already have a preference, you can download a free implementation here. This implementation contains both OpenGL ES 2.0 and EGL libraries, and converts OpenGL ES 2.0 calls to the desktop OpenGL calls available on macOS.

Follow these steps to add a native OpenGL ES 2.0 implementation for macOS to your application (or follow similar steps if you already have a preferred implementation of OpenGL ES for macOS):

  1. Download the OpenGL ES 2.0 for macOS implementation and unzip the contents.

  2. Open your application in Xcode.

  3. In the Project Navigator panel, remove the gl.m and egl.m files that you added during the installation steps above, from your project. Leave the glext.m and EAGL.m files in your project.

  4. Drag the libGLESv2.dylib and libEGL.dylib files to the Frameworks group in the Xcode Project Navigator panel. In the dialog that opens, add the files to your application's macOS target.

  5. Select your application's project in the Project Navigator panel, select the macOS target, and select the Build Phases tab. Drag the libGLESv2.dylib and libEGL.dylib files from the Frameworks group in the Xcode Project Navigator panel to the Copy Files list in the Build Phases tab. If a Copy Files list does not exist, you can add it as a new phase by clicking the + button in the Build Phases tab.

    Hint: If you find it difficult to select both files in the Frameworks group without switching away from the Build Phases tab of the project target, use the Command key on your keyboard when selecting each of the files, or try dragging the files one by one from the Frameworks group to the Copy Files list in the Build Phases tab.

Activating Your MoltenGL License

MoltenGL is provided under a commercial paid license. You must purchase licenses covering the MoltenGL features you are using before releasing MoltenGL as part of a production game or application.

During evaluation, you can run MoltenGL without purchasing a license. The same Molten distribution package can be used for both evaluation and production games and applications, and the features and performance are identical in both modes. During evaluation, you will see the MoltenGL logo displayed as a watermark overlay on your OpenGL scene. Once valid licenses have been purchased and activated to cover the MoltenGL features you are using, this watermark will disappear.

Licenses can be purchased for one or more MoltenGL feature sets. Depending on whether you purchased a single license that covers all the features you are using, or purchased individual licenses for each features set, you will need to activate one or more licenses within MoltenGL.

Each license is composed of two parts, a license ID and a license key, both of which are provided to you when you purchase the license. There are two ways to activate a license within MoltenGL:

  1. The preferred method is to enter your license ID and key as compiler build settings in your development environment, and call the glActivateMoltenGLLicensesMGL() function to activate them. If you have multiple licenses, covering multiple MoltenGL feature sets, you can configure up to four licenses using the following pairs of build settings:

    MGL_LICENSE_ID   and MGL_LICENSE_KEY
    MGL_LICENSE_ID_1 and MGL_LICENSE_KEY_1
    MGL_LICENSE_ID_2 and MGL_LICENSE_KEY_2
    MGL_LICENSE_ID_3 and MGL_LICENSE_KEY_3

    Each element of each pair is a single string defined as a build setting, and should not include quote marks. For example, you might configure the following build settings:

    MGL_LICENSE_ID=john.doe@example.com
    MGL_LICENSE_KEY=NOVOT3NGHDZ6OQSCXX4VYNXGI3QLI6Z6

    and if you purchase an additional feature set on a separate license, you can add a second pair of build settings:

    MGL_LICENSE_ID_1=john.doe@example.com
    MGL_LICENSE_KEY_1=MZ4T1Y2LDKBJHAL73JPOEJBHELRHEQJF

    In addition to the license ID and key, for any license activation to take place, you must also set the following build setting to indicate that you accept the terms and conditions of the MoltenGL License Agreement:

    MGL_LICENSE_ACCEPT_TERMS_AND_CONDITIONS=1

    You can call the glActivateMoltenGLLicensesMGL() function at any time, but typically you will call it during application startup.

  2. If you are unable to use build settings to enter license information, you can call the glActivateMoltenGLLicenseMGL(licenseID, licenseKey, acceptLicenseTermsAndConditions) function from within your application, passing a license ID and key directly as a pair of null-terminated strings, as well as a boolean affirmation that you accept the terms and conditions of the MoltenGL License Agreement.

    You can call this function at any time, before or after the OpenGL context is created, but typically you will call this function during application startup. You can call this function multiple times to accommodate licenses purchased for multiple individual feature sets. Until a valid license is applied covering each feature set used by your application, MoltenGL will operate in evaluation mode.

    Using the glActivateMoltenGLLicenseMGL() function is not the preferred method for activating licenses because, in a team environment, it is more difficult to enter valid licenses for each developer from your application code. Instead, consider using the glActivateMoltenGLLicensesMGL() function (discussed above), which allows you to specify the license information through compiler build settings. Using compiler build settings allows you to more easily specify the license information for each developer.

If your MoltenGL license is part of a multi-user pack, you must verify the user count with your license purchaser or administrator.

Once you have activated one or more licenses to cover the MoltenGL features you are using, an information message will appear in the console logs for each activated feature set:

[mgl-info] Activated MoltenGL OpenGL ES 2.0 Core license for 'john.doe@example.com'.
[mgl-info] Activated MoltenGL OpenGL ES 2.0 Extensions license for 'john.doe@example.com'.

and the MoltenGL logo watermark will no longer be displayed on top of your OpenGL scene. If the watermark remains, ensure that you have indicated acceptance of the terms and conditions of the MoltenGL License Agreement, as described above, and check the console logs to ensure that your license covers all of the MoltenGL features that you are using, as described in the following sub-section.

Determining Which MoltenGL Feature Sets You Are Using

Before acquiring a MoltenGL license, you can tell which MoltenGL features sets are being used by your application by searching the console logs for entries such as the following:

[mgl-info] You require a MoltenGL license for the OpenGL ES 2.0 Core feature set.
[mgl-info] You require a MoltenGL license for the OpenGL ES 2.0 Extensions feature set...

In the case of the Extensions feature set, the logged message will also include an indication of the name of the first OpenGL extension that was used by your application, and the first function that was called in using that extension. This will help you understand which MoltenGL features you will need to acquire a license for. A list of the OpenGL extensions supported by MoltenGL is provided in the next section.

Once you have entered one or more valid MoltenGL licenses, as described above, these log messages will no longer appear for the feature sets covered by the license(s).

MoltenGL Product Support

Support for MoltenGL is readily available through the MoltenGL Support Forum. This forum is actively and professionally managed by the staff at MoltenGL, as well as the community of MoltenGL users like you. For more advanced support requirements, you can contact us to learn more about professional services available to help you integrate MoltenGL into your application.

Supported OpenGL ES 2.0 Extensions

This version of MoltenGL provides support for the following OpenGL ES 2.0 extensions:

APPLE_color_buffer_packed_float
APPLE_rgb_422
APPLE_texture_format_BGRA8888
APPLE_texture_packed_float
EXT_color_buffer_half_float
EXT_debug_label
EXT_debug_marker
EXT_discard_framebuffer
EXT_pvrtc_sRGB
EXT_read_format_bgra
EXT_shadow_samplers
EXT_sRGB
EXT_texture_filter_anisotropic
EXT_texture_rg
IMG_read_format
IMG_texture_compression_pvrtc
NV_generate_mipmap_sRGB
OES_depth24
OES_depth_texture
OES_element_index_uint
OES_mapbuffer
OES_packed_depth_stencil
OES_rgb8_rgba8
OES_texture_float
OES_texture_half_float
OES_texture_half_float_linear
OES_vertex_array_object

This list can also be retrieved at runtime via the standard glGetString(GL_EXTENSIONS) function call.

Device Platforms and OpenGL System Classes

There are several typical platform configuration scenarios under which your application might be running MoltenGL:

  1. iOS 8 (or above) on a device with an A7 processor (or above), or macOS 10.11 (or above) on a Mac:

    These devices use a CPU and GPU that support Metal. Under this scenario, Metal is available. MoltenGL will automatically intercept all OpenGL ES 2.0 calls and redirect them to the MoltenGL libraries, where all OpenGL ES 2.0 functionality will be implemented using Metal.

  2. iOS 7 (or earlier) on a device with an A7 processor (or above), or macOS 10.10 (or earlier) on a Mac:

    Although these devices use a CPU and GPU that support Metal, the Metal framework is only available with iOS 8 and macOS 10.11, or above. Under this scenario, Metal is currently unavailable, but it will be available in the future when the user upgrades to the OS. MoltenGL will automatically intercept all OpenGL ES 2.0 calls and direct them to the native OpenGL ES 2.0 implementation. When the user upgrades to a compatible version of iOS or macOS, MoltenGL will then follow Scenario 1 above and redirect all OpenGL ES 2.0 calls to the MoltenGL libraries, where all OpenGL ES 2.0 functionality will be implemented using Metal.

    When running under this scenario under macOS, your OpenGL ES 2.0 app needs to be able to access a "native" OpenGL ES 2.0 implementation. macOS supports OpenGL by default, and so an OpenGL ES 2.0 implementation must be provided for use on macOS if Metal is not available. Follow this instructions in the Adding Support for Native OpenGL ES 2.0 in macOS section above to add this capability.

  3. Any iOS version on a device with an A6 processor (or earlier):

    These devices use the arm7 processor, and have a GPU that cannot support Metal. Under this scenario, Metal will never be available. When building for an arm7 architecture, all OpenGL ES 2.0 calls will be directed to the native OpenGL implementation directly, without first passing through the MoltenGL framework. In this scenario, your OpenGL application runs exactly as it does without MoltenGL.

You do not need to do anything to support these various scenarios. MoltenGL handles them all automatically.

Modifying the Scenarios

If needed, you can programmatically modify the scenario configurations above. For example, because Scenario 3 completely bypasses MoltenGL, it does not support the combined GLSL+MSL shaders described in the Metal Shaders section below, so you may want to run a device that would normally operate in Scenario 3 as if it was operating in Scenario 2 instead. Or during development, you may want to test your application under both Scenario 2 or Scenario 3 on a device that normally supports Scenario 1.

EAGL and GLKit System Classes

In order to correctly intercept OpenGL behaviour, under Scenario 1 (iOS & macOS) and Scenario 2 (iOS) above, MoltenGL automatically replaces the OpenGL system classes EAGLContext, EAGLSharegroup, CAEAGLLayer and GLKView with classes that operate the same way, but implement their behaviour using Metal instead of OpenGL.

Under Scenario 1, (running Metal) these classes are available in macOS as well.

In most cases, this replacement is completely transparent to your application under all three scenarios above. However, in order for your application to operate as expected in Scenario 2 on iOS, you should avoid adding custom categories to either of the classes GLKView or CAEAGLLayer. Any custom categories you add to GLKView or CAEAGLLayerwill be ignored in Scenario 2. If you want to add custom functionality to GLKView, you should do so be creating and using a custom subclass, instead of adding a custom category to GLKView itself. Your custom subclass will operate correctly in all three of the scenarios above.

On iOS, you can use GLKView and GLKViewController in an Xcode Storyboard, by declaring a subclass of GLKView (e.g. MyGLKitView) and using it in your Storyboard. You must declare and use a subclass of GLKit so that MoltenGL can automatically replace the GLKView superclass with a version that is compatible with Metal, when the class is dynamically loaded as part of the Storyboard.

On macOS under Scenario 1, you can do the same with GLKView, but you must subclass your view controller from NSViewController instead of GLKViewController.

On macOS under Scenario 2, GLKView is not available.

Support for GLKView is provided as a convenience for OpenGL applications that use GLKView in Storyboards, or simply as an easy way to create a view that is compatible with OpenGL rendering. Be aware that MoltenGL does not yet support other GLKit features and components, such as effects or the texture loader.

Interacting with the MoltenGL Runtime

You programmatically configure and interact with the MoltenGL runtime through function calls, enumeration values, and capabilities, in exactly the same way you do with OpenGL. The MoltenGL/RedirectHeaders/include/MoltenGL folder contains several header files that define access to MoltenGL configuration, capabilities, behaviour, and components:

Metal Shaders

Metal uses a different shader language than OpenGL. OpenGL uses the well-known OpenGL Shading Language (GLSL), whereas Metal uses the new Metal Shading Language (MSL).

MoltenGL provides several options for creating and running MSL versions of your existing GLSL shaders. The following options are presented in order of increasing sophistication and difficulty:

You can mix and match these options in your application. For example, a simple approach is to use Runtime Shader Conversion for most GLSL shaders, and provide combined GLSL+MSL shader source code for the odd GLSL shader that prove problematic for runtime conversion.

Metal Shader Texture Coordinates

One key difference between MSL and GLSL is the orientation of the texture coordinate system. In OpenGL (and GLSL), texture coordinates start at the lower-left corner of the texture and increase towards the upper-right corner. In Metal (and MSL), texture coordinates start at the upper-left corner of the texture and increase towards the lower-right corner.

In effect, you can think of the Y-axis of the texture coordinates of Metal as being "flipped", or "inverted", relative to the Y-axis of OpenGL. To compensate for this, when writing an MSL shader, you should use (1.0 - y) wherever you need to specify the Y-value of a texture coordinate. As an example, in an MSL shader, you should sample a texture as follows:

half4 texColor = myTex.sample(mySampler, (float2)(v_texCoord.x, (1.0 - v_texCoord.y)));

When using Runtime Shader Conversion or the MoltenGLShaderConverter Shader Converter Tool, this is handled for you automatically. However, if you need to write your own MSL shaders (or hand-tweak the automatically converted GLSL shaders), be sure to invert the Y-value when using texture coordinates in MSL.

Further considerations regarding differences between MSL and GLSL are discussed in the Troubleshooting Shader Conversion section below.

MoltenGLShaderConverter Shader Converter Tool

The Molten distribution package includes the MoltenGLShaderConverter command line tool, located in the MoltenGLShaderConverter/Tools folder within the Molten distribution package. This tool allows you to convert your GLSL shader source code to MSL at development time, and then supply the MSL code to MoltenGL using one of the methods describe in the Metal Shaders section above.

The MoltenGLShaderConverter tool uses the same conversion technology as the Runtime Shader Conversion feature of MoltenGL.

The MoltenGLShaderConverter tool has a number of options available from the command line:

To see a complete list of options, run the MoltenGLShaderConverter tool from the command line with no arguments.

Troubleshooting Shader Conversion

The shader converter technology in MoltenGL is quite robust, and most GLSL shaders can be converted to MSL without any problems. In the case where a conversion issue arises, you can address the issue as follows:

The following sub-sections describe a few rare situations where the design features of the respective shading languages make automatic shader conversion difficult, and describe what you can do to correct it.

GLSL Preprocessor Directives

Shader conversion (via either Runtime Shader Conversion or the MoltenGLShaderConverter tool) resolves all GLSL preprocessor directives (eg- #define and #ifdef...#endif) prior to conversion to MSL. This can sometimes be problematic, particularly for offline shader conversion, if you depend on the directives being dynamically set prior to compilation.

Using Texture Arrays in Shaders

GLSL permits uniforms of type sampler2D and samplerCube to be declared and used as arrays. For example, the following could be used to declare a two-element array of texture samplers in GLSL:

uniform sampler2D myTextures[2];

On the other hand, MSL requires that all textures (and their associated samplers) be declared individually, as part of the Metal shader function argument list. For example, the following could be used to declare the same two texture samplers in MSL:

fragment FragOutStruct myFragmentShader(FragInStruct fragIn [[stage_in]],
    texture2d<half> myTextureA [[texture(1)]], sampler mySampler0 [[sampler(1)]]
    texture2d<half> myTextureB [[texture(2)]], sampler mySampler1 [[sampler(2)]])

A potential problem arises therefore, if the OpenGL application using the shaders expects to set the value of the texture sampler uniform as an array using a single call to the OpenGL function glUniform1iv.

With MoltenGL, if your OpenGL application uses an array of texture samplers, you have a couple of ways around this issue:

Sampling Depth Textures in Shaders

Most of the time, your textures contain visible content. However, there are certain multi-pass situations, such as shadow-mapping, where you will want to sample from a texture that contains depth information. Whereas GLSL does not always distinguish between sampling visible or depth texture content, MSL requires you to declare a different type of texture when using depth content.

If you are explicitly using a shadow sampler in your GLSL code to compare depth content held in a texture:

#extension GL_EXT_shadow_samplers : require
varying vec3            v_shadowCoords;
uniform sampler2DShadow s_ShadowTex;
...
float luma = shadow2DEXT(s_ShadowTex, v_shadowCoords);
...

MoltenGL will automatically convert this GLSL shadow sampler and texture to the cooresponding MSL representations. Note that you must explicitly require the EXT_shadow_samplers extension in your GLSL shader code.

However, if your GLSL code is simply treating the depth texture as a regular texture, you must treat the texture differently in the corresponding MSL code. For example, during normal shader conversion, a GLSL texture sampler declared as follows:

uniform sampler2D myTexture;

will typically be automatically converted to this texture2d MSL shader declaration:

fragment FragOutStruct myFragmentShader(FragInStruct fragIn [[stage_in]],
    texture2d<half> myTexture [[texture(1)]], sampler mySampler [[sampler(1)]])

However, under MSL, when sampling a depth texture, the equivalent texture declaration must be depth2d:

fragment FragOutStruct myFragmentShader(FragInStruct fragIn [[stage_in]],
    depth2d<float> myTexture [[texture(1)]], sampler mySampler [[sampler(1)]])

Unless you are explicitly using shader samplers (as described above), automatic shader conversion has no way of knowing that you intend to put depth content into the texture, and you will need to manually edit the resulting MSL shader source code to change the texture declaration to indicate depth content. Because you must modify your MSL code, you cannot make use of Runtime Shader Conversion, but you can use one of the other techniques listed above, to load the MSL code into your application when it is running Metal.

Performance Considerations

This section discusses how MoltenGL helps improve your game or application performance, and what results you should expect to see.

Call Latency

Metal has a much thinner API layer than OpenGL, providing lower latency for each draw call. In addition, Metal enforces a strict organization to how you construct the graphics context state used by each draw call, effectively forcing you to pre-configure your graphics context states. This is in contrast to the wildly free-form state construction available in OpenGL, which offers flexibility but, like any dynamic system, is less efficient than a fixed alternative.

Taken together, when compared with OpenGL, the CPU load for each draw call is much less with Metal, meaning that you can make many more draw calls within a given frame time. The result is the ability to render much more content per frame.

MoltenGL provides a comprehensive, lightweight, and highly-optimized bridge between the free-form state construction of OpenGL and the strict state management of Metal, while retaining much of the call latency improvements available through Metal. With MoltenGL you can perform over three times the number of OpenGL draw calls, compared with native OpenGL ES 2.0, effectively tripling the amount of content you can draw in each frame.

Keep in mind that MoltenGL can only help you reduce the time spent making OpenGL calls. It cannot help you reduce the time your app spends outside the OpenGL calls. An effective performance improvement strategy should involve an effort to streamline your application logic so that OpenGL calls are the blocking factor to further improvements, at which point MoltenGL will help you take your OpenGL game or application performance to the next level.

Shader Loading Time

Metal supports pre-compiled shaders, which can improve shader loading and set-up performance, allowing you to reduce your scene loading time. See the Metal Shaders and MoltenGLShaderConverter Shader Converter Tool sections above for more information about how to use the MoltenGLShaderConverter Shader Converter Tool to create and load pre-compiled Metal shaders into MoltenGL.

Xcode Configuration

When a Metal app is running from Xcode, the default Scheme settings reduce performance. Be sure to follow the instructions for configuring your application's Scheme within Xcode, found in the in the installation section above.

Metal System Trace Tool

To help you get the best performance from your graphics app, in addition to the GPU Driver template, starting with Xcode 7 and iOS 9, the Instruments profiling tool includes the Metal System Trace template. This template can be used to provide detailed tracing of the CPU and GPU behaviour of your application, allowing you unprecedented performance measurement and tuning capabilities for apps using Metal.

This enhanced performance tuning functionality is not available for native OpenGL ES applications, but is available for OpenGL ES applications running through MoltenGL.

Known MoltenGL Limitations

The following is a list of known limitations in this version of MoltenGL:


MoltenGL uses technology from the open-source GLSL optimizer and Mesa projects to perform GLSL to MSL shader conversion during Runtime Shader Conversion and in the MoltenGLShaderConverter tool.

MoltenGL uses technology from the open-source PVRTCCompressor project to help manage compressed PVRTC textures.