Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Examples not working on macOS with Ogre2.2 #422

Closed
srmainwaring opened this issue Sep 23, 2021 · 19 comments
Closed

Examples not working on macOS with Ogre2.2 #422

srmainwaring opened this issue Sep 23, 2021 · 19 comments
Labels
bug Something isn't working help wanted Extra attention is needed macOS macOS support ogre2.x

Comments

@srmainwaring
Copy link
Contributor

This issue is a placeholder to report that an upstream issue with Ogre2.2 is preventing examples that work for Edifice using Ogre2.1 from running in Fortress.

The examples tested include:

  • simple_demo
  • simple_demo_qml
  • ogre2_demo

The problem is essentially the same in all cases: the application segmentation faults.

The issue is arising in the macOS OpenGL3Plus windows code in Ogre2.2 located in ogre-next/RenderSystems/GL3Plus/src/windowing/OSX. It appears that ignition-rendering uses this code in a way that is not tested by running the Ogre2 samples, which do run on the environment described below.

Environment

  • OS Version:

    • macOS Big Sur 11.4
  • Source or binary build?

    • source build
    • branch: main
    • commit: d2ff058
  • Rendering issue

    • Rendering plugin: [ogre2].
      • [ x] GUI rendering error
      • [ x] running on real hardware
    • Rendering system info:
      $ system_profiler SPDisplaysDataType
      2021-09-23 14:48:58.715 system_profiler[91265:26022571] Device PreExisted [00000001000009d5] AMD Radeon Pro W5700X
      Graphics/Displays:
      
          AMD Radeon Pro W5700X:
      
            Chipset Model: AMD Radeon Pro W5700X
            Type: GPU
            Bus: PCIe
            Slot: Slot-1
            PCIe Lane Width: x16
            VRAM (Total): 16 GB
            Vendor: AMD (0x1002)
            Device ID: 0x7310
            Revision ID: 0x0000
            ROM Revision: 113-D1860W-213
            VBIOS Version: 113-D186A2XT-019
            Option ROM Version: 113-D186A2XT-019
            EFI Driver Version: 01.01.200
            Metal Family: Supported, Metal GPUFamily macOS 2
            Displays:
              Cinema HD:
                Display Type: LCD
                Resolution: 2560 x 1600
                UI Looks like: 2560 x 1600
                Framebuffer Depth: 30-Bit Color (ARGB2101010)
                Display Serial Number: CY628129UG1
                Main Display: Yes
                Mirror: Off
                Online: Yes
                Rotation: Supported
                Automatically Adjust Brightness: Yes
                Connection Type: DVI or HDMI
                Adapter Firmware Version: 2.21
    • [ x] ogre2.log

Description

  • Expected behaviour:
    • Run simple_demo ogre2
    • A new GUI window is created and the scene is rendered.
  • Actual behaviour:
    • The application segmentation faults.

Steps to reproduce

  1. Build ignition-rendering from source on macOS
  2. Build the simple_demo example
  3. Run the example

Output

./simple_demo ogre2
[Msg] Loading plugin [ignition-rendering-ogre2]
Creating resource group General
Creating resource group Internal
Creating resource group Autodetect
SceneManagerFactory for type 'DefaultSceneManager' registered.
Registering ResourceManager for type Material
Registering ResourceManager for type Mesh
Registering ResourceManager for type Mesh2
Registering ResourceManager for type OldSkeleton
MovableObjectFactory for type 'ParticleSystem' registered.
ArchiveFactory for archive type FileSystem registered.
ArchiveFactory for archive type Zip registered.
ArchiveFactory for archive type EmbeddedZip registered.
DDS codec registering
FreeImage version: 3.18.0
This program uses FreeImage, a free, open source image library supporting all common bitmap formats. See http://freeimage.sourceforge.net for details
Supported formats: bmp,ico,jpg,jif,jpeg,jpe,jng,koa,iff,lbm,mng,pbm,pbm,pcd,pcx,pgm,pgm,png,ppm,ppm,ras,tga,targa,tif,tiff,wap,wbmp,wbm,psd,psb,cut,xbm,xpm,gif,hdr,g3,sgi,rgb,rgba,bw,exr,j2k,j2c,jp2,pfm,pct,pict,pic,3fr,arw,bay,bmq,cap,cine,cr2,crw,cs1,dc2,dcr,drf,dsc,dng,erf,fff,ia,iiq,k25,kc2,kdc,mdc,mef,mos,mrw,nef,nrw,orf,pef,ptx,pxn,qtk,raf,raw,rdc,rw2,rwl,rwz,sr2,srf,srw,sti,x3f,webp,jxr,wdp,hdp
ETC codec registering
OITD codec registering
Registering ResourceManager for type HighLevelGpuProgram
MovableObjectFactory for type 'Decal' registered.
MovableObjectFactory for type 'InternalCubemapProbe' registered.
MovableObjectFactory for type 'Entity' registered.
MovableObjectFactory for type 'Item' registered.
MovableObjectFactory for type 'Light' registered.
MovableObjectFactory for type 'Rectangle2Dv2' registered.
MovableObjectFactory for type 'BillboardSet' registered.
MovableObjectFactory for type 'ManualObject2' registered.
MovableObjectFactory for type 'BillboardChain' registered.
MovableObjectFactory for type 'RibbonTrail' registered.
MovableObjectFactory for type 'WireAabb' registered.
*-*-* OGRE Initialising
*-*-* Version 2.2.6 (Cerberus)
OverlayElementFactory for type Panel registered.
OverlayElementFactory for type BorderPanel registered.
OverlayElementFactory for type TextArea registered.
Registering ResourceManager for type Font
Loading library /usr/local/opt/ogre2.2/lib/OGRE-2.2/OGRE/RenderSystem_GL3Plus.dylib
Installing plugin: GL 3+ RenderSystem
OpenGL 3+ Rendering Subsystem created.
Plugin successfully installed
Loading library /usr/local/opt/ogre2.2/lib/OGRE-2.2/OGRE/Plugin_ParticleFX.dylib
Installing plugin: ParticleFX
Particle Emitter Type 'Point' registered
Particle Emitter Type 'Box' registered
Particle Emitter Type 'Ellipsoid' registered
Particle Emitter Type 'Cylinder' registered
Particle Emitter Type 'Ring' registered
Particle Emitter Type 'HollowEllipsoid' registered
Particle Affector Type 'LinearForce' registered
Particle Affector Type 'ColourFader' registered
Particle Affector Type 'ColourFader2' registered
Particle Affector Type 'ColourImage' registered
Particle Affector Type 'ColourInterpolator' registered
Particle Affector Type 'Scaler' registered
Particle Affector Type 'Rotator' registered
Particle Affector Type 'DirectionRandomiser' registered
Particle Affector Type 'DeflectorPlane' registered
Plugin successfully installed
CPU Identifier & Features
-------------------------
 *   CPU ID: GenuineIntel: Intel(R) Xeon(R) W-3245 CPU @ 3.20GHz
 *   Logical cores: 32
 *      SSE: yes
 *     SSE2: yes
 *     SSE3: yes
 *      MMX: yes
 *   MMXEXT: yes
 *    3DNOW: no
 * 3DNOWEXT: no
 *     CMOV: yes
 *      TSC: yes
 *      FPU: yes
 *      PRO: yes
 *       HT: no
-------------------------
***********************************************
***  Starting Mac OS X OpenGL 3+ Subsystem  ***
***********************************************
GL3PlusRenderSystem::_createRenderWindow "OgreWindow(0)_0", 1x1 windowed  miscParams: FSAA=0 border=none contentScalingFactor=1.000000 externalWindowHandle=0 gamma=Yes macAPI=cocoa macAPICocoaUseNSView=true stereoMode=Frame Sequential 
Creating a Cocoa Compatible Render System
zsh: segmentation fault  ./simple_demo ogre2
@srmainwaring srmainwaring added the bug Something isn't working label Sep 23, 2021
@iche033
Copy link
Contributor

iche033 commented Sep 23, 2021

the tests on our homebrew CI builds were all failing as well to so we had to switch back to running ogre 1.x tests on macOS in Fortress, #407.

@srmainwaring
Copy link
Contributor Author

The segmentation fault should be fixed by this PR: [OSX] Fix segmentation fault when creating a CocoaWindow #225.

There is an issue compiling one of shader pieces on macOS because texelFetch does not have a signature matching the type usampler2D (this in ogre2/src/media/Hlms/Common/GLSL/CrossPlatformSettings_piece_all.glsl. Commenting out the problem definition allows the samples to run but nothing is being rendered (just the clear screen).

I am trying to isolate the cause of the rendering issue - not sure if it's a shader problem or something in the way the ignition-rendering uses Ogre2-2 that is different from the Ogre Samples. The Ogre2 examples: Sample_Tutorial03_DeterministicLoop and Sample_PbsMaterials are both working with the GL3Plus render system, so it should be feasible to get Fortress running on macOS.

@chapulina chapulina added macOS macOS support ogre2.x help wanted Extra attention is needed labels Sep 27, 2021
@iche033
Copy link
Contributor

iche033 commented Sep 27, 2021

great, that sounds promising. We can update our ogre2.2 formula (and probably also the debs) to pull from a new commit upstream when it's ready. Thanks!

@srmainwaring
Copy link
Contributor Author

We can update our ogre2.2 formula (and probably also the debs) to pull from a new commit upstream when it's ready.

OGRECave/ogre-next#225 has been merged into ogre-next/v2-2 and ogre-next/main. I've checked that cherry-picking it into the commit used by osrf/simulation/ogre2.2.rb (OGRECave/ogre-next@ec3f70c) addresses the segmentation fault (i.e. no other commits are required).

The shader compilation error when running simple_demo ogre2 is this:

GLSL compile log: 100000002PixelShader_ps
ERROR: 0:1118: No matching function for call to texelFetch(usampler2D, int)
ERROR: 0:1125: No matching function for call to texelFetch(usampler2D, int)
ERROR: 0:1128: Use of undeclared identifier 'idx'
ERROR: 0:1131: Use of undeclared identifier 'idx'
ERROR: 0:1133: Use of undeclared identifier 'idx'
ERROR: 0:1134: Use of undeclared identifier 'idx'
ERROR: 0:1137: Use of undeclared identifier 'posAndType'
ERROR: 0:1140: Use of undeclared identifier 'attenuation'
ERROR: 0:1143: Use of undeclared identifier 'attenuation'
ERROR: 0:1143: Use of undeclared identifier 'attenuation'
ERROR: 0:1145: Use of undeclared identifier 'atten'
ERROR: 0:1145: Use of undeclared identifier 'attenuation'
ERROR: 0:1145: Use of undeclared identifier 'attenuation'
ERROR: 0:1151: Use of undeclared identifier 'lightDiffuse'
ERROR: 0:1151: Use of undeclared identifier 'lightSpecular'
ERROR: 0:1152: Use of undeclared identifier 'atten'
ERROR: 0:1157: No matching function for call to texelFetch(usampler2D, int)
ERROR: 0:1164: No matching function for call to texelFetch(usampler2D, int)
ERROR: 0:1167: Use of undeclared identifier 'idx'
ERROR: 0:1170: Use of undeclared identifier 'idx'
ERROR: 0:1172: Use of undeclared identifier 'idx'
ERROR: 0:1173: Use of undeclared identifier 'idx'
ERROR: 0:1175: Use of undeclared identifier 'idx'
ERROR: 0:1177: Use of undeclared identifier 'idx'
ERROR: 0:1179: Use of undeclared identifier 'posAndType'
ERROR: 0:1182: Use of undeclared identifier 'attenuation'
ERROR: 0:1185: Use of undeclared identifier 'attenuation'
ERROR: 0:1185: Use of undeclared identifier 'attenuation'
ERROR: 0:1187: Use of undeclared identifier 'atten'
ERROR: 0:1187: Use of undeclared identifier 'attenuation'
ERROR: 0:1187: Use of undeclared identifier 'attenuation'
ERROR: 0:1195: Use of undeclared identifier 'spotDirection'
ERROR: 0:1197: Use of undeclared identifier 'spotParams'
ERROR: 0:1197: Use of undeclared identifier 'spotParams'
ERROR: 0:1198: Use of undeclared identifier 'spotAtten'
ERROR: 0:1198: Use of undeclared identifier 'spotAtten'
ERROR: 0:1198: Use of undeclared identifier 'spotParams'
ERROR: 0:1199: Use of undeclared identifier 'atten'
ERROR: 0:1199: Use of undeclared identifier 'spotAtten'
ERROR: 0:1203: Use of undeclared identifier 'spotParams'
ERROR: 0:1205: Use of undeclared identifier 'lightDiffuse'
ERROR: 0:1205: Use of undeclared identifier 'lightSpecular'
ERROR: 0:1206: Use of undeclared identifier 'atten'
libc++abi: terminating with uncaught exception of type Ogre::RenderingAPIException: OGRE EXCEPTION(3:RenderingAPIException): Fragment Program 100000002PixelShader_ps failed to compile. See compile log above for details. in GLSLShader::compile at /Users/rhys/Code/ogre/ogre-next2.2/RenderSystems/GL3Plus/src/GLSL/OgreGLSLShader.cpp (line 314)
zsh: abort      ./simple_demo ogre2

It's a bit odd. I've created a standalone ogre2 sample based off the Sample_PbsMaterial that renders to GLUT (like simple_demo) rather than SDL, and added some custom Unlit and Pbs materials with scripting. It runs as expected using the patched homebrew version of ogre2.2 (see below):

ogre2 2_pbs_spheres_8x8_custom_materials

The ign-rendering6 render pass is more complicated than my simple test case, and now includes Hlms/Terra so it will take further analysis to try and isolate the change that is causing the error. Any insights welcomed.

It would be nice to be able to easily switch rendering features on and off to help track down the origins of this type of error - even to the extent of being able to swap out Pbs for a simpler shader.

@iche033
Copy link
Contributor

iche033 commented Oct 1, 2021

OGRECave/ogre-next#225 has been merged into ogre-next/v2-2 and ogre-next/main. I've checked that cherry-picking it into the commit used by osrf/simulation/ogre2.2.rb (OGRECave/ogre-next@ec3f70c) addresses the segmentation fault (i.e. no other commits are required).

cool, I also just want to make sure that we don't need any more changes upstream to fix the remaining ign-rendering shader compile issue. Just so that we don't roll out 2 different ogre 2.2 versions in a short time.

I've created a standalone ogre2 sample based off the Sample_PbsMaterial that renders to GLUT (like simple_demo) rather than SDL

thanks for testing that! Just brainstorming ideas:

  1. The ign-rendering6 compositor setup is based on the Postprocessing demo in ogre-next:
    https://github.com/OGRECave/ogre-next/tree/v2-2/Samples/2.0/Showcase/Postprocessing
    So maybe try and see if that ogre demo runs?

  2. the shader compile error look like they are related to lights and I noticed that the PbsMaterial demo in ogre samples only have directional and spot lights. So maybe try commenting out the directional and point lights (or the whole scene with just the camera left) in the ign-rendering simple_demo?

and now includes Hlms/Terra

I think the issue is less likely related to Terra as those Hlms are not used if heightmaps are not loaded in the scene. But I could be wrong

@srmainwaring
Copy link
Contributor Author

srmainwaring commented Oct 2, 2021

cool, I also just want to make sure that we don't need any more changes upstream to fix the remaining ign-rendering shader compile issue.

Agree completely - I'm hoping it's just shaders from here on in rather than the C++ code in Ogre, but it could be residual OpenGL < 4.2 compatibility issues.

2. the shader compile error look like they are related to lights and I noticed that the PbsMaterial demo in ogre samples only have directional and spot lights.

The Sample_Forward3D demo is not working correctly, so there is an issue with the lights shaders. I will probably need help from the Ogre team to track this down, but will keep this issue updated with progress.

Have checked the Sample_Postprocessing demo and it's not working at all (rendering clear colour only) - so it looks like there is still a bit of work required in Ogre to get macOS / GL3+ back up and running well enough to support ignition.

@iche033
Copy link
Contributor

iche033 commented Oct 4, 2021

The Sample_Forward3D demo is not working correctly, so there is an issue with the lights shaders. I will probably need help from the Ogre team to track this down, but will keep this issue updated with progress.

cc @darksylinc, do you have some insights on what could be the causing the Forward3D demo to generate the shader errors (see #422 (comment)) on macOS?

@darksylinc
Copy link
Contributor

darksylinc commented Oct 4, 2021

The shader errors were fixed by srmainwaring as he says:

There is an issue compiling one of shader pieces on macOS because texelFetch does not have a signature matching the type usampler2D (this in ogre2/src/media/Hlms/Common/GLSL/CrossPlatformSettings_piece_all.glsl. Commenting out the problem definition allows the samples to run but nothing is being rendered (just the clear screen).

Indeed, the problem is that texelFetching a TBO does not exist in macOS so a workaround is to use a regular texture 2D and use texelFetch on it (which is 2D instead of 1D).

Now as to why the screen is clear after the fix could either be a problem with the way srmainwaring fixed it; it could be a bug in how we workaround the problem (alignment issues for being a 2D texture, integer slot not being set since we rely on layout() on normal GLSL/OpenGL*), a driver bug; or a bug caused by missing functionality. It's hard to guess without trying it.

*There's a relatively high chance this is the problem. I see setTextureReg( PixelShader, "f3dLightList", texUnit++ ) (and "f3dGrid") are being called but we'd have to follow the paths to ensure the slots are properly set.

@darksylinc
Copy link
Contributor

Btw I strongly suggest to place efforts on Metal support instead. I don't see this being a hard endeavour; and getting OpenGL to work on macOS is an uphill battle.

@srmainwaring
Copy link
Contributor Author

@darksylinc to get rid of the shader compile error I modified CrossPlatformSettings_piece_all.glsl to use:

@property( GL_ARB_texture_buffer_range )
#define bufferFetch1( buffer, idx ) texelFetch( buffer, idx ).x
@else
#define bufferFetch1( buffer, idx ) bufferFetch( buffer, idx ).x
@end

where bufferFetch is defined in @piece( SetCompatibilityLayer ).

With this the Forward3D sample will run but the lights are not rendering correctly. I think there is something to your suggestion that it's an alignment issue as when the number of lights are increased there are overlapping and incorrectly positioned blocks of lights.

Sample_Postprocessing is running but not rendering anything, and I'm not really sure where to start there.

I appreciate OpenGL is legacy for macOS now, but if you'd be able to help I'd like to try get ignition fortress working as well as ignition edifice is on macOS (which is functional enough for day to day dev work). I can either open an issue on ogre-next or continue the ogre forum thread I started.

Looking to the next version of ignition, I'd very much be in favour of having Metal support as well. I'm hoping that this work on legacy OpenGL can tide things over until then.

@srmainwaring
Copy link
Contributor Author

The ign-rendering6 compositor setup is based on the Postprocessing demo in ogre-next:
https://github.com/OGRECave/ogre-next/tree/v2-2/Samples/2.0/Showcase/Postprocessing
So maybe try and see if that ogre demo runs?

@iche033 this may not be the whole story for what's preventing macOS from running fortress, but it explains why I'm not seeing anything rendered: Compositor local textures not working correctly in macOS with GL3+ #231.

@iche033
Copy link
Contributor

iche033 commented Oct 7, 2021

thanks for investigating the issue! I was thinking that we could work around the issue by disabling post processing in regular cameras (and just use the PbsMaterial compositor setup) but lots of sensors also use local textures unfortunately. If the local texture issue turns out that it may take some time to fix, we could try to just get a regular camera working for macOs by adding ifdefs in our code for macOS.

@srmainwaring
Copy link
Contributor Author

no prob. @darksylinc is being very helpful suggesting lines of investigation and I'm sure we'll eventually get to the bottom of it.

On a related note: have been thinking about looking into what would be required to add Metal support to the ogre2 render engine. I realise that the initial thought was the team would not support Metal shaders, but it may turn out to be less effort than trying to maintain OpenGL on macOS. Ogre2 already has mechanisms for creating universal materials. If I was to get the initial port to Metal running would the team support it?

@iche033
Copy link
Contributor

iche033 commented Oct 8, 2021

Metal support came up a few times. The main concern was the extra maintenance effort on the shaders down the road but looks like now it's hard to avoid.

A few ideas on the shader situation if we were to add Metal support:

  1. Support metal shaders alongside of glsl, and continue to support both shaders in the future
  • +: users are more familiar with the shader syntax
  • -: work needed to convert existing shaders, e.g. manually or through SPIR-V Cross. Higher maintenance effort
  1. Support OGRE Any shaders alongside of glsl, and use OGRE Any shaders in the future
  • +: works on all platforms. I think OGRE 2.3 is also moving in this direction
  • -: work needed to convert existing shaders, and forces users / contributors to learn new shader language
  1. Use macros (ifdefs) in shaders mask glsl / any / metal differences.
  • +: Shaders share common code
  • -: Effort required to combine the shaders. We may end up with lots of ifdefs and the shaders become hard to read

3 will probably take quite a bit of effort to do so I am leaning towards 1 and 2 for now. I don't have experience with SPIR-V Cross so I don't know how well it works. If we're able to go from glsl -> spirv -> metal using this conversion tool, it may be the faster way to get something working.

@srmainwaring
Copy link
Contributor Author

3 will probably take quite a bit of effort to do so I am leaning towards 1 and 2 for now. I don't have experience with SPIR-V Cross so I don't know how well it works. If we're able to go from glsl -> spirv -> metal using this conversion tool, it may be the faster way to get something working.

I'd favour option 1 as well, at least initially. There are only about 17 - 18 shaders specific to ignition-rendering that need to be ported to Metal as all the Ogre HlmsPbs and HlmsUnit versions are there already. That doesn't seem too bad. As it's a bit off topic for this issue I'll open a new feature request for Metal support as a place to gather ideas and outline the effort.

@srmainwaring
Copy link
Contributor Author

srmainwaring commented Oct 9, 2021

Progress update:

The problem in Ogre2 is related to setting up the FBOs for legacy OpenGL. With a partial workaround the ignition-rendering demos will render on macOS, although there are some artefacts. I believe this is arising in some cases because of the order in which the textures are created then attached to FBOs (it looks like a placeholder for a texture may be set in the FBO with the texture creation deferred - which is not supported on macOS) . The good news is that if this is addressed then it should be feasible to have ogre2 GL3+ rending on macOS working again.

simple_demo with incorrect rendering artefacts

simple_demo

thermal_camera

thermal_camera

transform_control

transform_control

ogre2_demo with rendering artefacts

ogre2_demo

@darksylinc
Copy link
Contributor

darksylinc commented Oct 9, 2021

Hi!

I'll chime in regarding Metal support:

Indeed adding Metal support should be easy, since it's mostly porting shaders and ignition uses few shaders.

As for how to port shaders (option 1, 2, 3):

Duplicating all shaders (i.e. rewriting them in metal)

Pros:

  • It's beginner friendly (low entry barrier). If you know Metal you can write Metal shaders. If you know GLSL, you can write GLSL shaders.

Cons:

  • Double the work. Each time a shader gets patched, it needs to be patched twice. Contributors often overlook this in their PRs and reviewers need to be constantly on the look for this. And another issue is ensuring latest patch version gets transplanted to the duplicate instead of an older version
  • Out of sync errors from above can sometimes take a long time to be discovered if they are subtle
  • Maintenance is somewhere between O( N ) and O( N² ) complexity. If you have 10 shaders with 2 bugs each and support GLSL + Metal, then you need to do 40 shader edits (10 * 2 * 2). If you find one bug that only applies to Metal per shader and retry, you end up with 50 shader edits (10 * 2 * 2 + 10). If you later find out there was a transplant bug, 10 more shader edits and you end up with 60. With a unified approach you would've made 20 shader edits for the original bug.

Any shaders.

Contrary to what ignition devs believe, "any" shader files are not an extension or special functionality. It's a convention.

90% of the shader syntax is the same. Thus we use macros to abstract some of the differences.

e.g.

// Raw GLSL
vec4 myColour = texture( myTexture, uv );

// Any (macros defined on GLSL)
#define float4 vec4
#define OGRE_Sample texture

float4 myColour = OGRE_Sample( myTexture, uv );

The main divergence is that metal provides uniform parameters through a struct that has only local scope while GLSL is via uniform variables with global scope. The convention we use at Ogre is the following:

// GLSL
uniform float myParam;
#define p_myParam myParam

void main()
{
 #include "MyShader.any" // uses p_myParam
}

// Metal
struct Params
{
   float myParam;
};
#define p_myParam p.myParam

fragment float main_metal( constant Param &p [[buffer(PARAMETER_SLOT)]] )
{
 #include "MyShader.any" // uses p_myParam
}

Pros:

  • Shader is unified
  • Still very raw
  • Once you understand it's only a convention trick, it becomes easy
  • D3D11/HLSL and Metal syntaxes are so similar that supporting one means supporting the other is a breeze. D3D11 driver support is much more robust on Windows than OpenGL's which makes it worth it.
  • Metal and HLSL have additional tools that drastically improve debugging:
    1. RenderDoc supports source level debugging of HLSL
    2. Visual Studio also supports source level debugging of HLSL
    3. XCode Graphics Debugger supports source level debugging of Metal shaders

Cons:

  • Higher entry barrier, as any files may sound intimidating as if it's a different tech
  • A bit cumbersome since you need to switch between two files (the GLSL/Metal one and the .any)
  • In OpenGL on errors during compilation Ogre will dump the shader to Ogre.log so that "error on line 123" you can actually find what line 123 is in the amalgamated shader. Metal doesn't have this issue as it supports error messages per header file i.e. it will say "error on line 33 in file MyShader.any"
  • Not guaranteed it always works cross platform (e.g. if you accidentally write vec4 myVal inside the any file, the OpenGL backend will accept it, but the Metal backend will reject it. This is easy to fix, but what I mean is that it's not guaranteed)

SPIRV-Cross.

I never tried this venue but did hear about it a lot. Epic and Roblox use it.

Pros:

  • Translation is automated. Write raw GLSL (or raw HLSL via dxc compiler) and you get shaders for all other APIs.
  • Once you get it working, it just works. Write once, target everywhere
  • Source level debugging is supported like in any files, but you'll be debugging machine-generated source code.

Cons

  • When debugging or if shaders fail, it can be tricky to diagnose the error since there are multiple intermediates
  • Certain advanced features (i.e. compute shaders) may be unsupported. Both Epic and Roblox are interested in getting their regular rendering shaders into mobile on ES 2.0/3.0 hardware, rather than doing complex stuff; so that's where SPIRV-Cross focus is
  • When there is a SPIRV-Cross bug, good luck

Possible issues:

  1. I know that SPIRV-Cross has an API to inform how the data has been remapped. SPIRV-Cross is wild: It supports porting a modern GLSL 4.5 shader into the much older GL ES 2.0; therefore the lib will tell you how UBO offsets map to uniform variables from GL ES 2.0
  2. I don't know if the same applies to modern GLSL -> Metal translation, i.e. if you feed a GLSL shader with uniform float myParam I don't know how it will appear in the Metal version and if it follows Ogre conventions (i.e. placing the constant buffer in the PARAMETER_SLOT which is a macro Ogre defines). If the mismatch is too large, rather than converting the shader and feeding metal code to the Metal backend, Ogre would need to have a SpirvCrossProgram class in the Metal backend that asks the lib how parameters (and other inputs) have been remapped so that it takes care of everything automatically. Depending on how much SPIRV-Cross modifies, this could be super easy, or super hard to support.

@srmainwaring
Copy link
Contributor Author

@darksylinc thanks for the detailed analysis on options for providing Metal support.

I've taken approach 1, at least to start with. This seemed like the least intrusive method with a minimal impact on existing GLSL shaders while getting things up and running. The main change to existing methods is a move to unified vertex and fragment program definitions in the material files.

So far it looks promising - all the ign-rendering shaders now have a Metal version and most of the examples that should run on Metal are now running. There's some odd behaviour where an example that runs in my environment won't complete the last render step on @ahcorde's machine, but we're working through that. The last hurdle is to get the QML demo working, which currently relies on a shared OpenGL context between QML and Ogre. IIRC there is a variant of the Qt declarative example that covers this case for Metal - so that's next, and solving that should provide a path to getting the Scene3d plugin working for ign-gui and ign-gazebo.

As a follow up it might help with maintenance to move to your second proposal, and consolidate into Any shaders. It could be worth converting one shader as an example so the Ignition team can compare approaches and decide what works best for them.

@srmainwaring
Copy link
Contributor Author

With the exception of the simple_demo_qml example, this is addressed by #463. The QML example can be followed up separately using a similar approach to that proposed in gazebosim/gz-gui#323.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working help wanted Extra attention is needed macOS macOS support ogre2.x
Projects
None yet
Development

No branches or pull requests

4 participants