switchbrew / switch-examples

Switch examples for devkitA64 and libnx.
https://devkitpro.org/viewforum.php?f=42
559 stars 99 forks source link

Shaders #71

Closed niko1point0 closed 4 years ago

niko1point0 commented 4 years ago

I tried using glGetProgramBinary so that I could use precompiled shaders without SPIR-V, but it failed; it gave me 0 for format, and nullptr for the shader data. Is this function supported in nouveau? Is there any way to use it on Switch with nouveau?

niko1point0 commented 4 years ago

Also, I got a length of zero when checking the size of the program glGetProgramiv(s_program, GL_PROGRAM_BINARY_LENGTH, &length);

Prior to linking the program, I used this function to make sure I could get the shader, but it still did not work on Switch. glProgramParameteri(s_program, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE);

fincs commented 4 years ago

"Precompiled" shaders are very fragile in OpenGL and I wouldn't really recommend their use. They have never been tested on Switch and I am not surprised at all that they don't work, with the amount of customization we did to mesa/nouveau to get it working on HOS. In the end, OpenGL is not really designed to allow you to bypass the GLSL shader compiler. Mind if I ask what are you trying to do that requires bypassing GLSL?

niko1point0 commented 4 years ago

I am building a very large homebrew game. In the end, it will have over 100 shaders, and it takes a while for them to compile while the game was loading. That is why I am looking for a way to precompile them. I understand that they are fragile in OpenGL, but every Switch will have the exact same GPU. The Windows version of the game uses SPIR-V, while also having the ability to recompile the GLSL code as a last-resort if anything in SPIR-V fails

niko1point0 commented 4 years ago

How difficult would it be to add support to this feature?

niko1point0 commented 4 years ago

I am willing to donate money if it helps the efforts of implementing this feature. I am also willing to donate to help the efforts of SPIRV and Vulkan, although I know those would be extremely difficult to implement without Nouveau support

fincs commented 4 years ago

I'm sorry, but it's not really a monetary/incentive problem. OpenGL is not designed to support precompiled shaders in a robust way, and SPIR-V support in OpenGL has always been a (post-Vulkan) afterthought that not many drivers support at all. I understand that your homebrew app will only ever run on the Switch GPU and in theory it makes no sense whatsoever to compile shaders at runtime. I wholeheartedly agree with this, and that's one of the major shortcomings that arise from trying to use a cross-platform GPU API such as OpenGL on a fixed hardware platform such as the Switch (or even Vulkan for that matter; SPIR-V is essentially still yet another non-native shader program representation that needs to be compiled down to native code).

However, the fragility doesn't stem only from changing the system on top of which you are running your code; it also stems from different versions of the GL driver (in our case mesa/nouveau, which we do update from time to time). Shader binaries are not required to be forwards or backwards compatible across drivers or versions of the same driver; and in fact GL requires you to be prepared to fall back on actual GLSL in case loading shader binaries fails. On top of that, mesa's "precompiled" shaders aren't actually precompiled, if I recall correctly they are just some pre-baked IR that then needs to get through the shader compilation system anyway, so that wouldn't really be an improvement either. To summarize, this is by no means a robust mechanism and it is unlikely that you would actually want to use it fully knowing what it is and what it entails.

On the other hand, I have been working on a new low level Switch homebrew specific GPU API from time to time, and it requires shaders to be compiled ahead-of-time (on PC). Eventually I will get to the point where it can be tested by the public, so you might want to stay tuned for a definitive solution.

niko1point0 commented 4 years ago

That sounds great! I’m excited to see that, I’ll stay tuned.

If you need any help testing beta versions of the API, I am willing to try it, even if it is buggy.

The game has several pipelines, ranging in complexity from drawing a 2D texture on the screen, to Deferred Rendering with compute shaders, and beyond.

Even if only some of my basic pipelines run in beta, it would really make me happy to drop my OpenGL backend. I also have a DirectX 12 backend, and Vulkan is in progress

fincs commented 4 years ago

Sounds like exactly the kind of graphics workload I am more than happy to have someone test, once I get my stuff complete enough for a public beta.

The new API will be similar to Vulkan, but with a lot less arbitrary restrictions and rigidity. Since you already have the infrastructure to support multiple graphics API backends, I don't expect you to have major problems adding a new backend for it.

niko1point0 commented 4 years ago

Is there any estimate of release? Would it be in the upcoming months? Will it be many years?

fincs commented 4 years ago

I can't give ETAs, but I would expect it to be significantly prior to the Switch's end of life.

niko1point0 commented 4 years ago

will the shaders use GLSL?

fincs commented 4 years ago

Yes, shaders will be written in GLSL, and compiled on PC down to native Maxwell SASS.

niko1point0 commented 4 years ago

Great, I’ll stay tuned for updates. Thanks for the info