GLSL Shaders? (Has there been any work done before I start?)

I see where the question has been asked before. But is there the ability to write shaders in GLSL? Even if it means manually compiling the shaders? If not, is this still planned? If it is planned when might it be ready and what actually needs to be done/do you need help with it? I might be willing to help on select features that are missing/incomplete!

Thanks!

i asked this myself in the old forum, and even on SO, it is not supported but if i remember well monogame dev team was working on it, but well it will probably take time, not that i know anything about how hard the task is or how available developers are.

I’ve been busy for a few days but I am looking into adding this into MonoGame myself.

Before I start though I would love to know if anyone has actually done any work on this yet as well as if someone from the MonoGame team can spare a few minutes to give me a high level overview of how the effect pipeline currently works and how they would see adding support for GLSL. Would it be a separate processor that is selected or should it be added into the current effect processor with some way of telling it that a particular file is GLSL?

How would you see adding the technique/passes support? Should they be separate files for each or some way of adding them within one file and some form the the technique/pass setup be added to the file?

Thanks
-Koderz

So yes… this is a feature we’re working towards.

The current high level concept is simple:

  • Run HLSL .FX file thru 2MGFX command-line tool or MonoGame Effect pipeline processor.
  • A binary file with embedded shader code and metadata is generated for the appropriate platform.
  • Runtime loads binary file and creates Effect with techniques/passes/parameters/shaders/etc.

What needs to happen here is we need to support an FX file with GLSL code embedded in it instead of HLSL. There are a few complications with that:

  • We need to write a preprocessor to resolve #includes and ideally #defines to replace the DX preprocessor we currently use (as it won’t run on Mac).
  • Need to support extracting features the GLSL compiler doesn’t understand (techniques,passes,sampler state, etc).
  • Need a way to optimize the shader GLSL. Dead code removal, removing whitespace (it slows down mobile compile times), etc.
  • Need a way to generate uniform blocks/structures to allow us to set all shader constants with one GL call.

Currently this all is handled by the fact that all shaders are compiled to HLSL bytecode first.

There is currently a lot of work i’m doing for PS4 in this area which might help get these features moving, but I don’t have any ETA for it arriving in the develop branch yet.

The techniques and passes will be embedded along side the GLSL code… just like we do right now in HLSL.

I suggest you spend some time examining the 2MGFX tool…

https://github.com/mono/MonoGame/tree/develop/Tools/2MGFX

It is a fairly concise view of how the MonoGame Effect system works.

Thanks! I’m hoping to have the time to at least start the basic support as a project I’m currently working on would benefit greatly from it as well as I know people have been asking for it off and on.

I hadn’t seen that specific tool, I had been looking at the content processors built into the pipeline which from a 1 minute glance appear to be basically the same thing just one is in the pipeline and one is a standalone tool?

If I’m understanding what you just described correctly then there shouldn’t be much if any work that needs to be done to the runtime itself? Only to the ContentPipline/TwoMGFX tools so that they generate all the needed information in the correct (and I’m assuming the same) format as what is currently generated by converting HLSL to GLSL for OpenGL based platforms?

I’ve seen already built tools for things like this one. Is there anything against using a 3rd party tool for this stage?

If you don’t mind me asking, what all are you doing that might help with this? Before I go recreate the wheel!

Exactly correct.

Assuming we can do everything I outlined… yes.

I fully expect we will use an existing library to do this work. The issue is finding the one which will serve our needs best. It no only had to do its work well, but it also needs to support 64bit, run on Mac and Linux, be easier bindable to C#, and not have too many dependencies itself.

Mostly working on the preprocessor and the FX parser at the moment. These are areas that affect PS4 as well as support for GLSL.

Cool. Think I’m seeing where this needs to go now!

I know you said you didn’t have an ETA on your work being merged back into the develop branch but is there any way for me to see what you’re working on? If not then I may progress on my own with the understanding that if/when you merge that back in that it will need some work to join up with what you’re doing.

I’ll look around for solutions to the optimizer.

Not really yet. We’re taking weeks here anyway not months or years.

That is probably the best thing you can do as that is something that i’m not looking into at all right now.

I’d like to ask a question in this thread if I may, instead of starting a new one. I’d like to use GLSL on all platforms I intend to target (and they all suport it), without going through the whole fx parsing, preprocessing, compilation & conversion charade. From where I’m standing, this is not providing any benefit to me. Even though the XNA legacy is keeping this project back, there are numerous features which makes it golden, especially when talking about the OpenGL support across the board.

In more simpler terms, I have GLSL shaders which I’d like to use as they are. Is there currently a way to achieve that with the nightly builds, and if not where should I focus my attention in order to bypass the current code overhead and get the resource passed straight into the GL renderer.

Thanks.

I’m playing with setting up a basic implementation of a pass through system to get some GLSL working. I’m trying to do something similar but I honestly want to bring full GLSL support not just a pass through that leaves out most of the pipeline.

I “might” be able to run some simple GLSL through it within the next couple days but it will be very basic support. Not anywhere near what Tom and I have been talking about. Only reason I’m doing this basic setup right now is because a project we’re working on needs support for GLSL and I would like something to hold us over until the full pipeline can be built.

I’m playing with the content pipeline as I’m writing this getting acclimated to how it works so I can attempt to support it. I don’t think what we’re talking about doing really means much changes to how you’re wanting to do GLSL. Just that basically you take a GLSL shader (Vertex and Fragment) and combine it with the Technique/Pass setup from a standard FX file and the pipeline sets it up to run with MonoGame. MonoGame needs several pieces of information about the shader for the Effect system to work.

Damn forgot about MonoGame’s techinque/pass setup. You’re right, there’s more to it than meets the eye. I’m just at the beginning of my project, but since I’m going so deep, I’m beginning to wonder whether MonoGame would be beneficial for me or not. Might as well go OpenTk/Assimp… Also the XNA DNA in MonoGame makes me feel uneasy, but that’s subjective talk.

Basically right… but there is more than just a technique and pass:

  • Uniform names, offsets, types, sizes.
  • Sampler states like wrap, clamp, etc.
  • Render states for each pass.

Most of this is handled already by the core parser in there. We just need to get GLSL to pass thru it unscathed, optimize the GLSL a bit, and be able to gather the in-use uniform data for GLSL.

Only you can make the decision if MonoGame is right for you. I feel that if people that shy away from using something like this because of one or two small missing features (Yes I understand GLSL isn’t a “small” feature) would instead help out the project for both themselves and the community it would further the framework and hopefully get more people using/helping it! That is why that even with GLSL not currently being supported I decided to use MonoGame for my current project!

Yeah I saw parts of that, haven’t looked in depth with some of those parts yet, but I think I see how the pieces generally fit together now.

In regards to the optimizer, how far are you thinking it should go? Basic dead code removal, white space/comment removal, or that and getting into things like constant propagation, inlining, arithmetic optimizations etc? I see a couple optimizers with differing capabilities that could be useful here but it would depend how far it should go.

Also in regards to the techniques/passes… They work by referencing the name of the function directly… Would GLSL be setup the same way so that instead of having a “main” function or in GLSL’s case more than one, it would use a named function for the vertex/fragment shaders and TwoMGFX would get the information it needs based on that but then convert the function name back to “main” before it’s sent on to the file and therefor onto the compiler?

Other side question is I see that in TwoMGFX where you’re getting the ShaderInfo you use the DirectX compiler to pre-process the file for #includes and macros and in the comments it say’s “this even works for GLSL”? What would that do to GLSL specific pre-processor directives?

So basically what I’m seeing is basically parsing it once to deal with techniques/passes/samplers/render states etc… then hand it off to a GLSL optimizer and then run it back through another parser to pull the remaining uniform data etc. Unless there’s a better way that I haven’t seen yet!

The only thing that i think would be required would be dead code removal and whitespace optimization. These will absolutely reduce shader size on disk and in turn speed up shader compile times.

Constant propagation, arithmetic optimizations, and other stuff would be nice, but I think not absolutely required. GLSL optimization at runtime on mobile devices I know was pretty poor a 5 years ago… not so sure now. Still any offline optimization we can do helps.

We should also be able to disable optimizations in “debug” modes and inject #pragma file and line references to make things nice for shader debugging tools.

Yes… it would work just like HLSL. Each vertex/fragment shader would have a unique name and the technique/pass will gather them and pair them together. The “optimizer” then would run once per vertex or fragment shader. Optimizing for that particular entry point only then renaming it to “main” in the final block of GLSL.

I’m not aware of any standard GLSL specific pre-processor directives.

All I meant with that comment was that the DirectX compiler’s preprocessor function doesn’t care what the code within it looks like. It just looks for #includes, #ifs, #defines, etc. No matter if the code is HLSL, GLSL, C++, whatever… it still works.

The problem with the DirectX compiler preprocessor is that it is only available on Windows. To have a MGFX tool that runs on Mac or Linux desktops we need to replace it with our own stand alone preprocessor.

Yep… that is about it.

Yeah, I haven’t really played with mobile devices so I’m basing that off what you’re telling me but it makes sense! I’ve been playing with a tool that can actually do all of the optimizations mentioned but at the cost that it sometimes makes the code longer based on what it’s doing and what you gave it. It appears that it’s cross-platform but it may not actually help the situation when it comes to mobile devices. So it may be that you should be able to turn this off even on release builds for those cases where it does more harm than good, and we just attempt to remove comments/excess whitespace. Also you where wanting something that’s easier to bind to c# well with a small one file c .dll wrapper for the library it’s actually really easy, I already have the basic functionality of it bound to c# as I wanted to see how it went. I am still looking around to see if there’s any better alternatives

I understand and agree completely with the debug mode and line references!

The only one I can think of would be the “#version” directive but I guess that’s not really a pre-processor directive so much as something the compiler looks for to know what it should do. But I see what you mean with everything else. Yeah don’t know why I didn’t think about the fact that it would only be available on Windows.

I’m not so sure there’s going to be a readily usable tool to rebuild all the uniforms into blocks.

Other than that I think I have the picture of what needs to be done! Sounds like a fun project that I would like to help on!

What tool is this?

If your example is a small shader getting a little bigger… that doesn’t matter too much really. Look at BasicEffect.fx as an example of a big effect file:

https://github.com/mono/MonoGame/blob/develop/MonoGame.Framework/Graphics/Effect/Resources/BasicEffect.fx

If every vertex and pixel shader had a full copy of this one file (don’t forget macro expansion makes it bigger) it would take forever to compile GLSL shaders on iOS or Android. Dead code removal (like removing all the other shaders not currently being compiled) is very important for that reason.

Yea… I suspect we’re going to have to come up with our own solution here. We really need this feature as it is critical to reducing uniform setting calls.

The tool I’m currently playing with and have it bound to c# is:
https://github.com/aras-p/glsl-optimizer

Which appears to be partly supported by Unity Technologies and is MIT licensed.

There’s a couple others that I’m investigating as well.

I wouldn’t really say this is a small shader, but it’s definitely not the size of the basic effect shader you linked. I will try it with a few larger shaders and see what happens.

I agree… This sounds like what’s necessary is a little expansion to the parser to be able to process this type thing ourselves. Also that optimizer deals with the pre-processing step but it doesn’t appear that you can invoke just the pre-processor and I’m not sure what it does with #includes as I haven’t tried them yet. So this might be something to find/make some alternative that can be used for both hlsl and glsl that is cross platform.

Also should this be a separate content processor for glsl or have some way of telling the content processor that this file contains glsl?