KhronosGroup / GLSL

GLSL Shading Language Specification and Extensions
Other
337 stars 98 forks source link

Template Programming #141

Open devshgraphicsprogramming opened 3 years ago

devshgraphicsprogramming commented 3 years ago

Metal SL has this.

its getting really tedious to write functions that only differ in variable types, see this library of GLSL code which I've made: https://github.com/buildaworldnet/IrrlichtBAW/tree/property_pool/include/irr/builtin/glsl

Especially the code for parallel data primitives: https://github.com/buildaworldnet/IrrlichtBAW/tree/property_pool/include/irr/builtin/glsl/subgroup https://github.com/buildaworldnet/IrrlichtBAW/tree/property_pool/include/irr/builtin/glsl/workgroup

I've had to use very ugly macros as crutches. in order not to have heaps of duplicate code.

Also there's no way for me to 100% ensure certain things get unrolled, template metaprogramming could help a lot with this.

I sense that using GLSL I will eventually come to a point where inventing or stripping down an existing language (CUDA or C++) and compiling it straight to SPIR-V will make economical sense for me.

devshgraphicsprogramming commented 3 years ago

on the topic of name mangling, you can see the sheer "prefix insanity" here https://github.com/buildaworldnet/IrrlichtBAW/tree/property_pool/include/irr/builtin/glsl/bxdf

Cazadorro commented 3 years ago

Template programming is a nightmare in terms of implementation and bugs. C++ compilers still couldn't agree on how to correctly compile certain types of template code in very common cases not too far back. What your use case seems to be however, is generics. Rust style generics may be a better suit for GLSL, which are much simpler than C++ generic programming through templates, unless Khronos group disagrees, since they are the ones maintaining GLSLang, which is the only implementation that will effectively be updated with this. Basically you don't get SFINAE with generics. It is still useful for const generics though, but as Rust is still having trouble with this, I would expect GLSL to also have issue implementing this, and should probably be a separate proposal.

devshgraphicsprogramming commented 3 years ago

Rust generics dont take non type parameters (e.g. integers) AFAIK, if I wanted to create a statically unrolled loop of then, metaprogramming via C++ templates makes it easy. I simply need to provide a general specialization for case when parmater > 0 and a NOOP specialization when parameter equals 0

But again, generics would still be better than nothing.

Cazadorro commented 3 years ago

Rust generics dont take non type parameters (e.g. integers) AFAIK

This was not a feature originally in the language, yes, but it has a feature getting into stable called const generics. I don't believe this is considered a separate feature in C++, but I'm not 100% sure. This is what I was talking about with const generics. I've used const generics in CUDA code, so this is 100% useful in GLSL code.

if I wanted to create a statically unrolled loop of then, metaprogramming via C++ templates makes it easy

I think this is the wrong attitude and way to think about metaprogramming in C++. Metaprogramming in C++ is more or less accidental, and eventually was supported by the language committee. Implementing this specific kind of feature requires const generics and SFINAE, and is not actually all that simple to implement. C++ style template meta programming is not the correct feature for this kind of thing IMO.

Right now, you shouldn't run into performance issues with most loops, if you've got a compile time known constant in GLSL, either SPIR-V opt, or lower level GPU ISA compilers should be able to unroll the loop.

But lets say you didn't have this functionality for whatever reason. Wouldn't you rather do this instead of using SFINAE?

#unroll
for(int i = 0; i < SOME_CONSTANT; ++i){
...
}

With modern rust macros, you can essentially do this in code. You can probably do this with normal GLSL macros as well, though it would take a lot more effort and probably not be able to use arbitrary constants.

Alternatively, if you didn't want to use rust/pascal sanitary macros, you could instead vouch for a macro like facility that uses GLSL code to produce GLSL code. For C++, they strayed away from this due to security concerns, but for GLSL, this isn't an issue because GLSL code does not access file io or network io.

You could then write something like (in strawman code)

constexpr for(int i = 0; i < SOME_CONSTANT; ++i){
paste ... /*your code you want to actually run here*/
}
seanbaxter commented 3 years ago

https://github.com/seanbaxter/shaders/blob/master/README.md

Templates! Compile-time loop unrolling! Everything here is addressed in the Circle C++ Shaders extension.

devshgraphicsprogramming commented 3 years ago

Can I use it as a standalone thing (no shaders mixed with my C++) and does it have feature parity with all the Vulkan GLSL dialect (all the extensions) ?

seanbaxter commented 3 years ago

Can I use it as a standalone thing (no shaders mixed with my C++) Yes. Described in the usage notes.

does it have feature parity with all the Vulkan GLSL dialect (all the extensions) ? No. Does core raster, ray_tracing, mesh_shader, subgroup ballot stuff. See the spirv.cxx link for the implicit declarations.

It's not a funded project. It's incomplete. It has some bugs dealing with control flow and ponitres. Hoping to secure funding to turn it into a proper GLSL replacement. But as a proof point it shows that templates are absolutely compatible with shader programming.

devshgraphicsprogramming commented 3 years ago

Ok, you're doing God's work... good luck with securing funding.

Btw, does it absolutely require the pointer extension?

Cazadorro commented 3 years ago

@seanbaxter This would be great! Unfortunately, as the projects we work on can't get this to work with windows with out WSL, and the compiler itself is closed source, it can't and won't be adopted by us. We can't afford to deal with closed source compiler infrastructure when it comes to graphics programming, too many bugs appear that we can't diagnose and fix. It would be economically easier for us to simply do the same thing you did from scratch than it would to rely on Circle's shader resources right now, which is unfortunate. We look forward to when the compiler becomes public and able to work on more systems.

For personal projects I would be willing to at least try this out, but it would need Mingw64 support first. Looking at your twitter thread on the 3rd of November, you mention you need access to the MSVC ABI for windows, but this doesn't apply to mingw AFAIK.

seanbaxter commented 3 years ago

@Cazadorro I'm not asking you to use it yet. Just spreading the word that template programming is good for shader programming. If one of the vendors stepped in and supported this, I could get Windows support and the rest of the stuff you need.

Cazadorro commented 3 years ago

@seanbaxter I think what you've working on is incredibly valuable. I think the way this is being done is ideal, especially for C++ developers. Is the only reason you haven't gotten support yet from a company because you've only just released this a couple of weeks ago? Have you gone to all the typical subreddits like /r/Vulkan, /r/GraphicsProgramming, /r/cpp, /r/programming? I'm surprised Khronos, Valve, and others haven't already endorsed this otherwise.

Also are you holding off on publicly releasing this because of sponsors? That would make sense, though I'm not sure if that's what other projects like imgui did before they got sponsored. A lot of them rely on actual company adoption before a company will start sponsoring them.

Also I think a lot of us from CUDA and OpenCL already knew TMP or similar facilities were useful in a GPU context, but what is surprising to me is that you were able to sanely integrate SPIR-V and GLSL constructs inline with C++. A lot of people, my self included, thought you had to go to higher level abstractions, maybe even separate abstractions per shader stage for it to integrate that well, that you had to mimic CUDA to get something like this.

devshgraphicsprogramming commented 3 years ago

@seanbaxter the only thing I'm "queasy" about is a requirement for hardware pointer extension... I'd like to see something like "ranged pointers" implemented in the language, i.e. pointer that can only be used to point to a specific SSBO (descriptor binding and set), UBO, shared memory or local memory array and cannot be casted to another one.

Seems like a really weird concept but trust me I could explain why it makes sense.

devshgraphicsprogramming commented 3 years ago

Have you gone to all the typical subreddits like /r/Vulkan, /r/GraphicsProgramming, /r/cpp, /r/programming? I'm surprised Khronos, Valve, and others haven't already endorsed this otherwise.

I think that's all the wrong avenues of looking for money @Cazadorro, @seanbaxter 's best bet would be getting someone on the inside of an IHV who is already working on compilers (like @themaister ), or higher ups in developer relations to push his case forward. Or a big ISV in the business of creating tools who appreciates the gains in developer productivity such as Autodesk, Unreal, Unity, etc.

seanbaxter commented 3 years ago

@seanbaxter the only thing I'm "queasy" about is a requirement for hardware pointer extension... I'd like to see something like "ranged pointers" implemented in the language, i.e. pointer that can only be used to point to a specific SSBO (descriptor binding and set), UBO, shared memory or local memory array and cannot be casted to another one.

I'm not talking about pointer extensions. I have control flow graph passes that de-pointerize C++ code by splitting OpPtrAccessChain instructions apart by pointer offset and index. This has to ripple through OpPhi and all that back to the source. The end effect is that most statically-analyzable code that initializes pointers from the same OpVariable can be transformed to direct indexing. It's basically an optimization pass, but it has to be moved up into the compiler middle-end rather than back-end, because SPIR-V disallows OpPtrAccessChain in Logical addressing mode. I had a telecon with Khronos folk today and they are aware of this challenge. In the binary on my website I don't even have these passes enabled because of a bug in the mem2reg pass. It's a big wad of optimizations just to get a correct module.

seanbaxter commented 3 years ago

A lot of people, my self included, thought you had to go to higher level abstractions, maybe even separate abstractions per shader stage for it to integrate that well, that you had to mimic CUDA to get something like this.

What higher-level abstractions do you have in mind? I basically just dragged in GLSL constructs and embedded them into C++. All the layout attributes are now C++ attributes and so on. That's a kind of low-level treatment, and I use C++ features to add higher-level abstractions. But that doesn't rule out additional language-provided abstractions if add value. Is there something you wish that GLSL or HLSL had beyond the stuff I already addressed?

Cazadorro commented 3 years ago

@seanbaxter Sorry if I didn't make myself clear, That statement wasn't skepticism or criticism of you or your work, but amazement of what you've already done. Basically the idea was that SPIR-V and GLSL-vulkan constructs were wholly incompatible with languages like C++ in terms of development, and that you had to apply some sort of "CUDA" but for each shader type rather than using raw SPIR-V binding concepts and stage concepts.

It wasn't an expression of a desire for a higher level language interface, but a fear that it was a requirement, and a sigh of relief that what you have presented shows that it isn't. This means that SPIR-V can be expanded and the changes can be implemented hypothetically into circle with out having to re-think how its going to fit in from a conceptual level, and not for separate compute/geometry/vertex/fragment passes.

seanbaxter commented 3 years ago

No no, I wasn't taking it as skepticism. I'm actually looking for new ideas. :+1:

devshgraphicsprogramming commented 3 years ago

Let's not lag behind HLSL people https://github.com/microsoft/DirectXShaderCompiler/blob/hlsl-2021/tools/clang/test/HLSLFileCheck/hlsl/template/RandomGenerators.hlsl