-
Notifications
You must be signed in to change notification settings - Fork 10
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
[Needed Crate] A pure rust SPIRV generator #23
Comments
One approach is to make static libs of Same thing with It's more productive to use existing tools and tweak them than to wait until pure Rust alternatives show up. Looking at Winit, it's still far behind SDL2 in terms of stability and features - so I am thinking the same issues will pop up when waiting for these crates. |
I would be interested in contributing to this project. It has a clear goal and it sounds fun!
With that mindset, a pure Rust alternative will never happen. Why wait? We can do it ourselves! I think a pure Rust solution will not only bring a lot of value to the Rust ecosystem itself, but also to other ecosystems as well (like the Web). |
Also interested in contributing. For what it's worth, I've been prototyping some ideas for a (W)HLSL parser a bit over the past few weeks (primary goal of compiling WHLSL to SPIR-V), but it's not ready for anything to be built on top of it yet. |
@Lokathor Thank you for writing this down! We've had quite a bit of discussion on gfx-rs/gfx-rs.github.io#30 , and I'm happy to see the steps you are making to solve this 👏 🏅
Also used by PS4, pretty much. HLSL overall is the dominant source language today, according to Google SPIR-V team data.
I wouldn't call them superficial. The binding model is different. The semantics of operations is different. Even things like the control flow analysis is different. There are a lot of subtleties. The biggest user of GLSL -> HLSL is probably Angle, but I don't know anyone doing the opposite translation in production. |
It's worth noting that most Vulkan documentation assumes GLSL, too. |
There are many things wrong with what @seivan said, but I'm just going to tackle one of them that's of the highest concern in case anyone gets the idea to try it: Simply shipping static libs for various platforms is, at least on Win32, fundamentally opening the door for an unsound compilation. MSVC allows itself the freedom to potentially change the C ABI of static libs the same as we allow the call ABI of "rust-call" functions to potentially change over time. At this time it's next to impossible to ensure, in an automatically checked way, that the version of the C runtime that was used to build the static lib shipped to you is the same as the version of the C runtime that will go with the |
I asked some clarifications on what the status of shader text There is a project that both of the arrows above require: rspirv. Following that I think there are some next steps in this particular project discussed here, as I see there is a lot of interest shown on this subject:
Between 1 and 2 it looks like features have to be added to |
Can I ask what the actual goal behind this library is? Is this to remove the dependency on spirv_cross (e.g. the C/C++ build dependency?). From what I can gather on this post, that is the stated goal here: can I assume this is correct? If the above is correct, I would like to preface everything by saying: I think if the only goal of this project is to remove a single C dependency, than this is poor choice to use the WG's time and energy, and the initiative itself is being approached naively. Currently, as written, in my mind, this post seems to say we as a community wish to:
I ask because this is a much more nuanced endeavour than it seems on the surface, and I believe even more complex than iterated here by @kvark and others. I think some consideration needs to go into existing frameworks, libraries and initiatives on this front as well. I see rspirv was mentioned, which is a good start. There also exists LLVM-SPIRV - which is an official, from KhronosGroup LLVM backend for SPIRV. This would be a much better approach to Spirv generation than baking a custom one into rust. The Rust ecosystem seems to constantly fall into traps of reinventing the wheel or reimplementing projects in rust, which many times leads to poor implementations to the overall detriment of the community as a whole. I believe this is a case where everyone should take a step back and consider what the goal is here. Although the concept of a Rust-compiled shader language is neat for an experiment, and in the future could be interesting, it currently would lock out the majority of current graphics engineers and shader designers from the rust gamedev core ecosystem. GLSL and HLSL are the current primary shader languages in the entire graphics industry. There is good reason for that - the problem space and execution space of shaders is drastically limited compared to general purpose computing and languages. So, taking that into consideration, that means GLSL/HLSL are the best routes to go - but again, each has their own specifics as mentioned here and the choice is actually not so clear cut. Although I understand the desire for a rusty specific solution, I don't necessarily think the community has the resources, time and financial backing currently to keep up with LunarG, KhronosGroup and Google in re-implementing rust reimplemented replacements. I fear the fragmentation of these solutions would overall do more harm than good, as our rust solutions would constantly be lacking and playing catch-up with the "Big" Solutions. Lastly, is the concept of mobile and web devices, and how much legacy wants to be supported. If that is the case, there are many - many quirks and iterations of previous versions of GLSL/HLSL that will need to be supported. This is, again, a huge overhead. I'd just like to ask, if the goal is because of build issues, is our time best spent re-implementing these production-ready, enterprise solutions, or perhaps determining the deficiencies in either the Rust or shaderc build pipelines, and perhaps solving those? |
Not all of this is contained in the initial post, some of this clarification comes from today's WG meeting:
|
@jaynus Javelin will happen anyway due to unrelated reasons and backed by gfx-rs. They have certain needs that spirv-cross does not satisfy or is unwilling to satisfy so there are other reasons for that work there discussed on the gfx-rs group. Now, Javelin happening means some other things around manipulating SPIRV data need to also happen or improve (in rspirv). Given this there's still a gap left in making actual spirv code from something (GLSL/HLSL), and given all the work that needs to happen for Javelin, the remaining work to fill that gap might or might not be a lot. People have responded quite positively to this initiative, however, my position right now is that there is not enough data explained on what this work actually is. That's the reason why why I asked for a sort of high-level design so we all understand what the space is and what's missing for this to happen. The proposal does match the charter, being a low-level library that enables engines to happen so at least that's a checkbox that got checked. However, I am yet to see enough data for us to lean towards a decision here, thus I asked for some high-level design + review on that. My bad if it sounded like it will happen anyway. The review's purpose is exactly what the name says, to review, then help us decide how far away this is from happening then either move to the next step or postpone, or something else. |
Another aspect, which might serve as additional motivation: if we tackle this issue, we should build a number of crates instead of "just" a As consequence, I would like to ask for a nice toolbox for compiling something to SPIRV. Including:
With this, creating a |
There's also a project for RLSL but that's apparently "totally unusable" at the moment. |
@AlexEne Do you have a link to this discussion? FWIW this seems like a very costly project to me, and at face value I don't really see how a rewrite of both shaderc and spirv-cross can be considered the highest priority for the ecosystem if the value to be gained is primarily a more streamlined build system. I believe they are both multi-man-year efforts before all the quirks are ironed out, especially considering various driver workarounds etc.
|
@kabergstrom this not the link you are asking about, but it might be helpful - https://gfx-rs.github.io/2019/07/13/javelin.html
It's an interesting philosophic question. Can we just write bindings to Unreal, Godot, etc, and call it a day? It's called an "ecosystem" because we have a number of connected things written in Rust. SPIRV-Cross and |
Thank you for the quick reply! Yes I had read this post but I guess I hadn't read the linked issues that closely.
Yes, we could write bindings to those if they were actually composable and under a FOSS license. But individual features in the engines are not re-usable by other engines, as so many parts of the engines are very strongly coupled. For me, it's all about the reusable capabilities of FOSS within gamedev. I don't participate in Rust gamedev projects because I need all game engine code to be written in Rust. It's easier to trust Rust code due to its safety guarantees, its standardized documentation tools and Rust's traits make it easy to loosely couple crates with traits at no runtime cost. But I use lots of C code every day and it works great, as I am sure all of us do. This means people can build their own engines for their games out of various independent crates, as is often necessary. That's where the value for gamedevs is. Apparently a majority of the most popular indie games use custom engines, for example. So what's an ecosystem anyway? I think it's about people using other people's code, and organically contributing into that pool of code that people use. Rust's most important features for enabling an ecosystem are its capabilities for instilling trust and making it easier to re-use other people's code with confidence. But we can still use C/C++ codebases as long as there is trust in it, as the interop provably works well. When it comes to Javelin's question of is it really worth it? Mozilla is free to pour its resources where it pleases, of course, and we are all better off for it, with graceful thanks. As for a |
Just poking my nose in to say I'm surprised that nobody has mentioned |
@kabergstrom thank you for an extensive reply!
I strongly believe that it's critical to gfx-rs long-time strategy. Javelin by itself is not something the WG needs to focus (or even care much), it's just that we need the very same things out of
This has very little to do with Mozilla. There is no "pouring of resources" happening.
Only if it turns out to be successful. If we didn't want to bring a better alternative to the status quo, we wouldn't have gfx-portability, wgpu-native, and... well... Rust.
The point is to have a clean Rust rewrite. I don't know what to say to SPIRV-Cross maintainers.
It's backed by Valve and sponsored by Valve. It's possible that Google started reworking some parts of it for the WebGPU implementation needs. But if we ever want to be faster and more robust than Chrome/MoltenVK/younameit, we can't use all the same tech. Angle, for example, has been both a blessing and a curse in the browsers world. It's the convenience that buys you in, and then you end up linked and dependent for the rest of the product life, periodically suffering from upstream issues. |
While the discussion here is interesting, we're slowly drifting into subjects further and further away from the initial proposal, like discussing what an ecosystem is or debating if Javelin (a project unrelated to this wg) is actually worth it. For the issue here, we haven't yet seen what this cost is and what the design on the specific proposed library here actually is. For this reason, I'd kindly ask you all to focus on the subject discussed here and what I consider a reasonable next step, that is a design of what this SPIRV generator with it's dependencies, missing parts and problems that still need to be solved. If we're such a high-level design for the SPIRV generator can't be produced, spending our time debating the cost of something that is still not well defined is not a proper use of anyone's time and I will vote us to park this issue until more data is produced that we can reason on. |
To recount, mainly for the sake of my own memory, the problem we are considering is essentially this:
This process can be divided two steps,
|
Just popped up in my feed: glsl-1.0 & glsl-quasiquote-1.0 released. It uses |
glsl author here. Yes, glsl can parse GLSL450 formatted shaders (adding support for 460 is just the matter of a single The current state of
That is completely solved by my crate, yes. However, the rest is not: obviously I hope it helps the discussion. |
@phaazon Duuuuuuude. 🥂 Good timing. |
Actually, for this specific issue, the problem we are considering is ONLY the |
Just so you know, GLSL460 is now supported and is part of glsl-1.0.2. If you need anything else, ping me! I’ll be happy to help and dig any further. |
Welp, I knew it was only a matter of time before I got distracted by shiny programming language things. So, apparently now I'm playing with a language to compile to SPIR-V: https://hg.sr.ht/~icefox/chrysanthemum Suggestions welcome, I have no idea what I'm doing. |
@icefoxen I love it! For what it's worth, I am also working on a functional shader front end: a visual material editor that will compile to (for now) GLSL. It will hopefully target SPIR-V as I learn more. On the subject:
Is SPIRV actually a good IR for targeting other shading languages? Since it seems there's a fair number of us writing shader frontends, it may be beneficial to create an API that takes something resembling an AST and produces the desired output. It wouldn't need to do optimization (but could) and would just take a program description. A higher level abstraction like this could better capture any metadata needed to produce things other than GLSL/SPIRV. The result would be an object that describes whether or not each shader stage you supplied was compatible with the target, or if you used any features that could not be emulated. It would contain the source you need for your target API. // either specify a platform/api or shading language version, depending on this project's scope
let target = Target::... ;
let r = generator(target, Stages {
vertex: VertexShader { main: Block(vec![Assignment {/* and so on */}]) },
pixel: // ...,
..Default::default()
});
let glsl_vertex_source = r.unwrap().glsl_source().vertex; // more or less Just the rough idea, it would need to be thought about (e.g. input definitions). 😄 From the charter:
This idea doesn't directly help anyone doing game development (get your own SPIRV; provide your own control flow graph/ast thing; both have high bars to entry). But, it would help everyone writing shader frontend libraries in Rust produce usable products faster, which in turn helps people new to game engines or new to Rust get going. This could be easier to complete than Javelin since it doesn't have to divine anything not included directly in the SPIR-V source. (Or this could just produce SPIR-V, and hand it to Javelin, which still fits the bill for "a pure rust spirv generator"). |
My gut response is "oh gods not ANOTHER layer in the shader translation pipeline!" 😋 My more measured response is that this is basically the job of, well, a compiler backend. I haven't gotten around to investigating Cranelift seriously though. From my (still very incomplete) knowledge of SPIR-V so far, it seems fine as an IR. It's basically a structured list of extended basic blocks, and the instruction set is a SSA form. I don't think there's any real difficulties translating it into a (slow) program in a higher level language. |
Following @jaynus and @seivan -- it seems like there's a gap in the ecosystem that would be fairly simple to fill and could help a lot of different projects: a crate that downloads a prebuilt binary from some url, verifies its hash, and installs it to the target directory for linking. This would make it easy to include shaderc as a binary dependency, while these other projects gestate (for however many years it will realistically take them to get to production-readiness). Ideally this crate would use a minimal-dependencies solution for downloading files, like alexcrichton's curl crate / raw winapi, to minimize download and compile times. To really polish it off, it could include instructions like trust on how to set up CI builds that publish to github releases / bintray. Plus instructions for setting up a cargo feature that switches from downloading a prebuilt crate to compiling from scratch, to support people who don't want to download binaries for whatever reason. I've contemplated writing a crate like this for my own purposes but haven't gotten around to it yet. Is anyone else interested in working on something like this? |
On windows there's an unfortunate soundness hole with using static libs because the MSVC compiler allows static lib ABI breaks between versions (just like If there's an ABI mismatch when you link two things together it's UB and you hopefully get a linking error, but you can also end up putting together a binary with silent runtime UB lurking in the program. I don't know if this is a thing that C compilers also do on other platforms, but it could be a concern on linux and mac and such as well. |
Thanks for clarifying @Lokathor @est31 @MaikKlein! In that case, from my understanding it seems like the remaining step to close the gap for a very basic, "working" |
That's the missing step. Then we put it together in an easy to use crate once the parts are ready. |
It's worth emphasis that good SPIR-V is not nearly so important as any (correct) SPIR-V at all. Demanding applications can use external optimizers and distribute optimized SPIR-V code directly if necessary, but just being able to produce something that works will make life much easier for most purposes, and optimization can be iterated on endlessly. |
Exactly, I do quite a few passes inside rlsl to make sure that I am producing "correct" spir-v. That is why I was considering to produce "Relaxed SPIR-V" (rspirv :p), which I would produce from rlsl and then have an external lib/tool make everything correct. I'll just go an mention a few things here: For example this detects the merge block bb7 correctly, but in SPIR-V every merge block as to be unique Or you can't really have pointers in SPIR-V. It somewhat got nicer with the variable pointer extension but in rlsl I just optimize them away if I know they are static. Also functions that return a pointer for example Obviously (as I have said above) restructuring the CFG so that you can actually recompute the control flow would be nice. Just look at this cfg, it is just not very fun to recompute structure control flow for this. I have mostly solved this in rlsl though, execpt I have a few violations with complex loops sometimes. I forgot the name for it but expanding structs to scalars would be nice to have. SPIR-V doesn't allow pointers in structs, but this should be legal if you know the pointer is statically known.
This doesn't work because a slice contains a ptr and a length, and it is illegal to have pointers in structs. but
works just fine. where
This is also the reason why iterators can't be easily expressed in SPIR-V by default. I could go on but I don't want to make this too long. Everyone has to solve a subset of these problems if they want to generate SPIR-V. I assume this is why we don't see many other SPIR-V backends. With a relaxed SPIR-V spec, even non compiler people could port their language of choice to SPIR-V in a relatively short amount of time. And I would love to see more GPU languages besides GLSL and HLSL. Sorry for the brain dump, hopefully not too offtopic. |
Yup I am doing that as we speak.
Correct - that being said, as usual I applaud the people here to taking this on and I too would love to see pure rust tools that can replace those.
Well I'm not planning supporting compiling from scratch, I do allow defining your own bindgen config, formatter, wrapper.h & header(s) and/or static lib as ENV variables - wish feature flags could take arguments!
I'm currently doing it for Sorry for detracting. I'm all for the work being done here, I just can't wait :). |
I update the documentation of glsl. It now contains an example to see how to parse and use it. I will make small patches releases from now on to add more documentation about transpiling, whenever needed. |
@seivan cool!
I think if you distribute glslang as an executable the ABI becomes a non-issue, is that an option? and just write a rust wrapper that runs the executable
hm, those options are good, but not including a build-from-source option will likely cause problems down the line -- projects like debian, some enterprise environments, and prickly security people often don't like downloading binaries. plus you don't want to irreparably break everybody's builds if your binary host goes down. i'd strongly recommend including a build-from-source feature flag. oh wait, you support a custom binary through an ENV variable; that's fine i suppose. i'd still suggest including a build-from-source feature flag just for ease of use purposes. you have to write those build files anyway for making the binaries, it's not much more work to just distribute them as well. good luck on the project! |
For those interested, I created an IRC channel dedicated to the Also, whoever decides to write the crate that will eat |
Welp, my toy shader language now can produce an actual functioning shader: I'm probably not going to make it actually useful ever, but if anyone ever wants to do something similar I highly recommend they give it a go. SPIR-V is a pretty nice compiler target, apart from entry point definitions at least; it seems a shame to waste it on junk like GLSL. |
@jrmuizel has been working on a high-level representation ("hir") of GLSL, based on @phaazon 's parser. They hooked it up with a basic SPIR-V module builder, using |
What is the status of shaders in WebGPU? Is it still possible we will get a binary SPIR-V-like format? (I really-really hope we'll do...) In that case it would be nice for pipeline to be flexible enough to also eventually include this hypothetical format. |
Shaders in WebGPU is a very difficult topic that causes most of the conflict within the working group. No decision has been made yet. Perhaps, in a month from now, at face-to-face meeting we'll see better. |
While I know It might not be useful for Rust puritans, especially how painful it was to fix for iOS as it required a lot of changes to all its submodules like All I really care about is the ability to do That being said it also takes around a fun year to compile so I do hope we can replace it with https://github.com/jrmuizel/glsl-to-spirv one day. |
Coming back to this conversation, mostly just a quick update of the state of things as I am aware. The Javelin project has been renamed to It's all very rough around the edges, still. Most of the WGSL spec is filled with placeholders, and I wasn't able to get |
@parasyte we are approaching a point where wgpu-rs examples are written in WGSL, see gfx-rs/wgpu-rs#679, so I believe it's going to be usable soon. |
@kvark @Lokathor naga seems to be getting more mature by the day, so I guess this issue can be closed? |
Actually, got ahead of myself here a bit. The issue talks about spirv-cross, but the subject is largely orthogonal to it. |
Also, for any browsing this issue that aren't already aware of it, in terms of "Rust things that generate SPIR-V", rust-gpu generates SPIR-V from (a subset of) pure Rust code (using Rust as a shader language) and is already quite usable, though still early :) |
Right now the modern graphics APIs are moving towards using the SPIRV binary format as the default way to upload a shader to the GPU.
In some cases, an alternative format is used and the
spirv_cross
crate (a C++ wrapper) will convert that SPIRV into the alternative format.As with all C/C++ wrapping crates, the biggest problem with using the crate is just getting the C part compiled in the first place. For as portable as C the language is, C the build process is one of the least portable things you can find around. When using these things as a crate, people need a pure Rust solution simply because that's the only way to ensure that
cargo build
will "just work" regardless of platform or local setup. The pure Rust version could provide the exact same abilities as the C version, and it would still be better simply because it would interact better with the rest ofcargo
's build process.Javelin is a new project by the
gfx-rs
team to replace thespirv_cross
functionality with a pure Rust version. Amazing, and I support them.What we need is another project that does the same thing for the first part of the pipeline.
-->
SPIRV-->
API ShaderJavelin replaces that second arrow in the pipeline with pure Rust. Right now that first arrow, converting some sort of textual shader language into SPIRV, doesn't have a pure Rust answer.
Now there's no single source language. SPIRV is just a format the same as LLVM IR is a format, and potentially anything can produce SPIRV if it wants. There are, however, two main shader languages that people are likely to be familiar with (or be able to find books about):
The differences between these two languages are very superficial overall. There's automatic converters between the two for simple shader programs, and a small 30 minute tutorial is all that a person who knows one of them would need to learn the other.
So, what we need is: a crate that lets you convert a
&str
holding a shader program into the correct binary SPIRV data (Vec<u32>
).The text was updated successfully, but these errors were encountered: