Skip to content

enum SpirvTargetEnv containing all available targets #311

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

Open
wants to merge 7 commits into
base: main
Choose a base branch
from

Conversation

Firestar99
Copy link
Member

@Firestar99 Firestar99 commented Jul 1, 2025

cargo-gpu fixup: Rust-GPU/cargo-gpu#92

List all available targets in enum SpirvTargetEnv and centralize parsing, to_string and target spec references there. Changes SpirvBuilder.target from String to the new enum and makes SpirvBuilder::new accept both String and the new enum to reduce breakage as much as possible.

@Firestar99 Firestar99 marked this pull request as draft July 1, 2025 11:32
@Firestar99 Firestar99 force-pushed the target_env_enum branch 3 times, most recently from bbbcf8b to 61a51d6 Compare July 1, 2025 14:39
@@ -490,10 +490,10 @@ impl Default for SpirvBuilder {
}

impl SpirvBuilder {
pub fn new(path_to_crate: impl AsRef<Path>, target: impl Into<String>) -> Self {
pub fn new(path_to_crate: impl AsRef<Path>, target: SpirvTargetEnv) -> Self {
Copy link
Member Author

@Firestar99 Firestar99 Jul 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR introduces a significant breaking change right here that will affect everyone. I would like to change SpirvBuilder.target to the new enum, so new users don't have to deal with strings. But this moves parsing of the target string from build() to here, where we can't just return an error easily. The options:

  • breaking change: return a Result for failed parsing, may be annoying to handle for the user
  • My choice: breaking change: require everyone to use the new enum directly (SpirvTargetEnv::Vulkan_1_2) or explicitly call the parse function that may fail (SpirvTargetEnv::parse_triple("spirv-unknown-vulkan1.2")?)
  • a surprise panic if parsing fails

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not impl Into<SpirvTargetEnv> and support &'static str, breaking everyone who didn't specify a string?

I forget if you can mark an impl or its methods as deprecated (or rather, if that ever results in a warning).

But honestly, enumerating the target-env explicitly is a bit silly. It would be much cooler if you can come up with a foolproof way for spirv-builder itself to create and cache a target JSON (e.g. in the target dir, which currently we only detect based off of $OUT_DIR, but maybe we could cheaply get "what would be the target dir used for the shader crate" out of Cargo?).

And then we presumably wouldn't even need this part of the system to care about the values at all and it can remain a string (unless that interferes with other plans ofc).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I may have an even better idea how not to break anything: Just have SpirvBuilder.target be Result<SpirvTargetEnv, *ParseError> so we can forward the error to the build() call. Then make new(..., target: impl IntoSpirvTargetEnv) so it can accept a &str, String or SpirvTargetEnv. We would only break anyone doing builder.target = Some("spirv-unknown-vulkan1.2") which is a small minority since that only works since about 2 months or so.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

impl IntoSpirvTargetEnv ... so it can accept a &str, String or ...

I suppose one way to be 100% back-compat would be to implement IntoSpirvTargetEnv for all types that implement Into<String>, but that might feel wasteful, idk. Then again, some of this depends on whether we care about parsing SpirvTargetEnv at all.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like that IDEs can auto-complete enum names, since they're symbols, not magic strings

@Firestar99 Firestar99 marked this pull request as ready for review July 1, 2025 17:50
Comment on lines +7 to +62
match self {
SpirvTargetEnv::OpenGL_4_0 => {
include_str!("../target-specs/spirv-unknown-opengl4.0.json")
}
SpirvTargetEnv::OpenGL_4_1 => {
include_str!("../target-specs/spirv-unknown-opengl4.1.json")
}
SpirvTargetEnv::OpenGL_4_2 => {
include_str!("../target-specs/spirv-unknown-opengl4.2.json")
}
SpirvTargetEnv::OpenGL_4_3 => {
include_str!("../target-specs/spirv-unknown-opengl4.3.json")
}
SpirvTargetEnv::OpenGL_4_5 => {
include_str!("../target-specs/spirv-unknown-opengl4.5.json")
}
SpirvTargetEnv::Spv_1_0 => {
include_str!("../target-specs/spirv-unknown-spv1.0.json")
}
SpirvTargetEnv::Spv_1_1 => {
include_str!("../target-specs/spirv-unknown-spv1.1.json")
}
SpirvTargetEnv::Spv_1_2 => {
include_str!("../target-specs/spirv-unknown-spv1.2.json")
}
SpirvTargetEnv::Spv_1_3 => {
include_str!("../target-specs/spirv-unknown-spv1.3.json")
}
SpirvTargetEnv::Spv_1_4 => {
include_str!("../target-specs/spirv-unknown-spv1.4.json")
}
SpirvTargetEnv::Spv_1_5 => {
include_str!("../target-specs/spirv-unknown-spv1.5.json")
}
SpirvTargetEnv::Spv_1_6 => {
include_str!("../target-specs/spirv-unknown-spv1.6.json")
}
SpirvTargetEnv::Vulkan_1_0 => {
include_str!("../target-specs/spirv-unknown-vulkan1.0.json")
}
SpirvTargetEnv::Vulkan_1_1 => {
include_str!("../target-specs/spirv-unknown-vulkan1.1.json")
}
SpirvTargetEnv::Vulkan_1_1_Spv_1_4 => {
include_str!("../target-specs/spirv-unknown-vulkan1.1spv1.4.json")
}
SpirvTargetEnv::Vulkan_1_2 => {
include_str!("../target-specs/spirv-unknown-vulkan1.2.json")
}
SpirvTargetEnv::Vulkan_1_3 => {
include_str!("../target-specs/spirv-unknown-vulkan1.3.json")
}
SpirvTargetEnv::Vulkan_1_4 => {
include_str!("../target-specs/spirv-unknown-vulkan1.4.json")
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Quick question since we keep changing these things, since I went with JSON files to minimal deviation from previous behavior, and because they wouldn't cause spurious rebuilds (relative to the spirv-builder version being used, since I would expect shaders to be rebuilt most of the times spirv-builder itself is rebuilt):

Could cargo-gpu generate the JSON file on-demand (and maybe cache it)? Especially since there's include_str! going on here, I feel like that's already what's happening?

Because the only difference between these files is, for spirv-unknown-X:

  • env is set to X
  • llvm-target is set to spirv-unknown-X
$ echo crates/rustc_codegen_spirv-target-specs/target-specs/*.json | xargs -n1 diff -U0 crates/rustc_codegen_spirv-targe
t-specs/target-specs/spirv-unknown-spv1.0.json | rg '^[\-+] ' -r '' | sed 's/: .*/: .../' | sort -u
 "env": ...
 "llvm-target": ...

(run this without sed 's/: .*/: .../' to see the actual values)

They could even be generated by string interpolation, if not serde_json, since the target env name doesn't even need escaping!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cargo-gpu only needs them for the "legacy path" aka rustc_codegen_spirv versions which did not depend on *target-specs. And that "legacy" dependency is fixed to version 0.9 on crates, so technically these changes don't actually do anything. It just feels wrong not to adjust them as well.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I'm not 100% sure what's going on, are you saying that most of the time, the .json files in the source tree get used?

I would actually be happier if cargo-gpu/spirv-builder created these from one template - I don't mind rustc_codegen_spirv-target-specs existing (and we can release older versions of that crate, if we want, I guess?) - but its main job could be "take this target_env string and return a JSON blob", without having the result of that templating be baked in the way it is today.

Copy link
Member Author

@Firestar99 Firestar99 Jul 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow, I actually wrote some nice docs for what's going on: https://github.com/Rust-GPU/cargo-gpu/blob/main/crates/cargo-gpu/src/target_specs.rs

And I get that they actually don't change much, just something I didn't know / want to worry about back when I wrote this.

@Firestar99 Firestar99 marked this pull request as draft July 1, 2025 20:30
@Firestar99 Firestar99 self-assigned this Jul 1, 2025
@Firestar99 Firestar99 marked this pull request as ready for review July 1, 2025 20:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants