@@ -154,7 +154,7 @@ impl fmt::Display for SpirvBuilderError {
154154
155155impl Error for SpirvBuilderError { }
156156
157- #[ derive( Debug , PartialEq , Eq , Clone , Copy ) ]
157+ #[ derive( Debug , PartialEq , Eq , Clone , Copy , Default ) ]
158158pub enum MetadataPrintout {
159159 /// Print no cargo metadata.
160160 None ,
@@ -163,12 +163,14 @@ pub enum MetadataPrintout {
163163 /// Print all cargo metadata.
164164 ///
165165 /// Includes dependency information and spirv environment variable.
166+ #[ default]
166167 Full ,
167168}
168169
169- #[ derive( Debug , PartialEq , Eq , Clone , Copy ) ]
170+ #[ derive( Debug , PartialEq , Eq , Clone , Copy , Default ) ]
170171pub enum SpirvMetadata {
171172 /// Strip all names and other debug information from SPIR-V output.
173+ #[ default]
172174 None ,
173175 /// Only include `OpName`s for public interface variables (uniforms and the like), to allow
174176 /// shader reflection.
@@ -178,13 +180,14 @@ pub enum SpirvMetadata {
178180}
179181
180182/// Strategy used to handle Rust `panic!`s in shaders compiled to SPIR-V.
181- #[ derive( Debug , PartialEq , Eq , Clone , Copy ) ]
183+ #[ derive( Debug , PartialEq , Eq , Clone , Copy , Default ) ]
182184pub enum ShaderPanicStrategy {
183185 /// Return from shader entry-point with no side-effects **(default)**.
184186 ///
185187 /// While similar to the standard SPIR-V `OpTerminateInvocation`, this is
186188 /// *not* limited to fragment shaders, and instead supports all shaders
187189 /// (as it's handled via control-flow rewriting, instead of SPIR-V features).
190+ #[ default]
188191 SilentExit ,
189192
190193 /// Like `SilentExit`, but also using `debugPrintf` to report the panic in
@@ -258,76 +261,185 @@ pub enum ShaderPanicStrategy {
258261 UNSOUND_DO_NOT_USE_UndefinedBehaviorViaUnreachable ,
259262}
260263
264+ /// Options for specifying the behavior of the validator
265+ /// Copied from `spirv-tools/src/val.rs` struct `ValidatorOptions`, with some fields disabled.
266+ #[ derive( Default , Clone ) ]
267+ pub struct ValidatorOptions {
268+ /// Record whether or not the validator should relax the rules on types for
269+ /// stores to structs. When relaxed, it will allow a type mismatch as long as
270+ /// the types are structs with the same layout. Two structs have the same layout
271+ /// if
272+ ///
273+ /// 1) the members of the structs are either the same type or are structs with
274+ /// same layout, and
275+ ///
276+ /// 2) the decorations that affect the memory layout are identical for both
277+ /// types. Other decorations are not relevant.
278+ pub relax_struct_store : bool ,
279+ /// Records whether or not the validator should relax the rules on pointer usage
280+ /// in logical addressing mode.
281+ ///
282+ /// When relaxed, it will allow the following usage cases of pointers:
283+ /// 1) `OpVariable` allocating an object whose type is a pointer type
284+ /// 2) `OpReturnValue` returning a pointer value
285+ pub relax_logical_pointer : bool ,
286+ // /// Records whether or not the validator should relax the rules because it is
287+ // /// expected that the optimizations will make the code legal.
288+ // ///
289+ // /// When relaxed, it will allow the following:
290+ // /// 1) It will allow relaxed logical pointers. Setting this option will also
291+ // /// set that option.
292+ // /// 2) Pointers that are pass as parameters to function calls do not have to
293+ // /// match the storage class of the formal parameter.
294+ // /// 3) Pointers that are actaul parameters on function calls do not have to point
295+ // /// to the same type pointed as the formal parameter. The types just need to
296+ // /// logically match.
297+ // pub before_legalization: bool,
298+ /// Records whether the validator should use "relaxed" block layout rules.
299+ /// Relaxed layout rules are described by Vulkan extension
300+ /// `VK_KHR_relaxed_block_layout`, and they affect uniform blocks, storage blocks,
301+ /// and push constants.
302+ ///
303+ /// This is enabled by default when targeting Vulkan 1.1 or later.
304+ /// Relaxed layout is more permissive than the default rules in Vulkan 1.0.
305+ pub relax_block_layout : Option < bool > ,
306+ /// Records whether the validator should use standard block layout rules for
307+ /// uniform blocks.
308+ pub uniform_buffer_standard_layout : bool ,
309+ /// Records whether the validator should use "scalar" block layout rules.
310+ /// Scalar layout rules are more permissive than relaxed block layout.
311+ ///
312+ /// See Vulkan extnesion `VK_EXT_scalar_block_layout`. The scalar alignment is
313+ /// defined as follows:
314+ /// - scalar alignment of a scalar is the scalar size
315+ /// - scalar alignment of a vector is the scalar alignment of its component
316+ /// - scalar alignment of a matrix is the scalar alignment of its component
317+ /// - scalar alignment of an array is the scalar alignment of its element
318+ /// - scalar alignment of a struct is the max scalar alignment among its
319+ /// members
320+ ///
321+ /// For a struct in Uniform, `StorageClass`, or `PushConstant`:
322+ /// - a member Offset must be a multiple of the member's scalar alignment
323+ /// - `ArrayStride` or `MatrixStride` must be a multiple of the array or matrix
324+ /// scalar alignment
325+ pub scalar_block_layout : bool ,
326+ /// Records whether or not the validator should skip validating standard
327+ /// uniform/storage block layout.
328+ pub skip_block_layout : bool ,
329+ // /// Applies a maximum to one or more Universal limits
330+ // pub max_limits: Vec<(ValidatorLimits, u32)>,
331+ }
332+
333+ /// Options for specifying the behavior of the optimizer
334+ /// Copied from `spirv-tools/src/opt.rs` struct `Options`, with some fields disabled.
335+ #[ derive( Default , Clone ) ]
336+ pub struct OptimizerOptions {
337+ // /// Records the validator options that should be passed to the validator,
338+ // /// the validator will run with the options before optimizer.
339+ // pub validator_options: Option<crate::val::ValidatorOptions>,
340+ // /// Records the maximum possible value for the id bound.
341+ // pub max_id_bound: Option<u32>,
342+ /// Records whether all bindings within the module should be preserved.
343+ pub preserve_bindings : bool ,
344+ // /// Records whether all specialization constants within the module
345+ // /// should be preserved.
346+ // pub preserve_spec_constants: bool,
347+ }
348+
261349/// Cargo features specification for building the shader crate.
262350#[ derive( Default ) ]
263- struct ShaderCrateFeatures {
264- default_features : Option < bool > ,
265- features : Vec < String > ,
351+ pub struct ShaderCrateFeatures {
352+ /// Set --default-features for the target shader crate.
353+ pub default_features : Option < bool > ,
354+ /// Set --features for the target shader crate.
355+ pub features : Vec < String > ,
266356}
267357
358+ #[ non_exhaustive]
268359pub struct SpirvBuilder {
269- path_to_crate : PathBuf ,
270- print_metadata : MetadataPrintout ,
271- release : bool ,
272- target : String ,
273- shader_crate_features : ShaderCrateFeatures ,
274- deny_warnings : bool ,
275- multimodule : bool ,
276- spirv_metadata : SpirvMetadata ,
277- capabilities : Vec < Capability > ,
278- extensions : Vec < String > ,
279- extra_args : Vec < String > ,
360+ pub path_to_crate : Option < PathBuf > ,
361+ /// Whether to print build.rs cargo metadata (e.g. cargo:rustc-env=var=val). Defaults to [`MetadataPrintout::Full`].
362+ pub print_metadata : MetadataPrintout ,
363+ /// Build in release. Defaults to true.
364+ pub release : bool ,
365+ /// The target triple, eg. `spirv-unknown-vulkan1.2`
366+ pub target : Option < String > ,
367+ /// Cargo features specification for building the shader crate.
368+ pub shader_crate_features : ShaderCrateFeatures ,
369+ /// Deny any warnings, as they may never be printed when building within a build script. Defaults to false.
370+ pub deny_warnings : bool ,
371+ /// Splits the resulting SPIR-V file into one module per entry point. This is useful in cases
372+ /// where ecosystem tooling has bugs around multiple entry points per module - having all entry
373+ /// points bundled into a single file is the preferred system.
374+ pub multimodule : bool ,
375+ /// Sets the level of metadata (primarily `OpName` and `OpLine`) included in the SPIR-V binary.
376+ /// Including metadata significantly increases binary size.
377+ pub spirv_metadata : SpirvMetadata ,
378+ /// Adds a capability to the SPIR-V module. Checking if a capability is enabled in code can be
379+ /// done via `#[cfg(target_feature = "TheCapability")]`.
380+ pub capabilities : Vec < Capability > ,
381+ /// Adds an extension to the SPIR-V module. Checking if an extension is enabled in code can be
382+ /// done via `#[cfg(target_feature = "ext:the_extension")]`.
383+ pub extensions : Vec < String > ,
384+ /// Set additional "codegen arg". Note: the `RUSTGPU_CODEGEN_ARGS` environment variable
385+ /// takes precedence over any set arguments using this function.
386+ pub extra_args : Vec < String > ,
280387 // Optional location of a known `rustc_codegen_spirv` dylib
281- rustc_codegen_spirv_location : Option < std:: path:: PathBuf > ,
282- // Optional location of a known "target-spec" file
283- path_to_target_spec : Option < PathBuf > ,
284- target_dir_path : Option < String > ,
388+ pub rustc_codegen_spirv_location : Option < std:: path:: PathBuf > ,
389+
390+ /// The path of the "target specification" file.
391+ ///
392+ /// For more info on "target specification" see
393+ /// [this RFC](https://rust-lang.github.io/rfcs/0131-target-specification.html).
394+ pub path_to_target_spec : Option < PathBuf > ,
395+ /// Set the target dir path within `./target` to use for building shaders. Defaults to `spirv-builder`, resulting
396+ /// in the path `./target/spirv-builder`.
397+ pub target_dir_path : Option < String > ,
285398
286399 // `rustc_codegen_spirv::linker` codegen args
400+ /// Change the shader `panic!` handling strategy (see [`ShaderPanicStrategy`]).
287401 pub shader_panic_strategy : ShaderPanicStrategy ,
288402
289- // spirv-val flags
290- pub relax_struct_store : bool ,
291- pub relax_logical_pointer : bool ,
292- pub relax_block_layout : bool ,
293- pub uniform_buffer_standard_layout : bool ,
294- pub scalar_block_layout : bool ,
295- pub skip_block_layout : bool ,
403+ /// spirv-val flags
404+ pub validator : ValidatorOptions ,
296405
297- // spirv-opt flags
298- pub preserve_bindings : bool ,
406+ /// spirv-opt flags
407+ pub optimizer : OptimizerOptions ,
299408}
300409
301- impl SpirvBuilder {
302- pub fn new ( path_to_crate : impl AsRef < Path > , target : impl Into < String > ) -> Self {
410+ impl Default for SpirvBuilder {
411+ fn default ( ) -> Self {
303412 Self {
304- path_to_crate : path_to_crate . as_ref ( ) . to_owned ( ) ,
305- print_metadata : MetadataPrintout :: Full ,
413+ path_to_crate : None ,
414+ print_metadata : MetadataPrintout :: default ( ) ,
306415 release : true ,
307- target : target . into ( ) ,
416+ target : None ,
308417 deny_warnings : false ,
309418 multimodule : false ,
310- spirv_metadata : SpirvMetadata :: None ,
419+ spirv_metadata : SpirvMetadata :: default ( ) ,
311420 capabilities : Vec :: new ( ) ,
312421 extensions : Vec :: new ( ) ,
313422 extra_args : Vec :: new ( ) ,
314423 rustc_codegen_spirv_location : None ,
315424 path_to_target_spec : None ,
316425 target_dir_path : None ,
317426
318- shader_panic_strategy : ShaderPanicStrategy :: SilentExit ,
319-
320- relax_struct_store : false ,
321- relax_logical_pointer : false ,
322- relax_block_layout : false ,
323- uniform_buffer_standard_layout : false ,
324- scalar_block_layout : false ,
325- skip_block_layout : false ,
326-
327- preserve_bindings : false ,
427+ shader_panic_strategy : ShaderPanicStrategy :: default ( ) ,
428+ validator : ValidatorOptions :: default ( ) ,
429+ optimizer : OptimizerOptions :: default ( ) ,
328430 shader_crate_features : ShaderCrateFeatures :: default ( ) ,
329431 }
330432 }
433+ }
434+
435+ impl SpirvBuilder {
436+ pub fn new ( path_to_crate : impl AsRef < Path > , target : impl Into < String > ) -> Self {
437+ Self {
438+ path_to_crate : Some ( path_to_crate. as_ref ( ) . to_owned ( ) ) ,
439+ target : Some ( target. into ( ) ) ,
440+ ..SpirvBuilder :: default ( )
441+ }
442+ }
331443
332444 /// Sets the path of the "target specification" file.
333445 ///
@@ -402,31 +514,31 @@ impl SpirvBuilder {
402514 /// Allow store from one struct type to a different type with compatible layout and members.
403515 #[ must_use]
404516 pub fn relax_struct_store ( mut self , v : bool ) -> Self {
405- self . relax_struct_store = v;
517+ self . validator . relax_struct_store = v;
406518 self
407519 }
408520
409521 /// Allow allocating an object of a pointer type and returning a pointer value from a function
410522 /// in logical addressing mode
411523 #[ must_use]
412524 pub fn relax_logical_pointer ( mut self , v : bool ) -> Self {
413- self . relax_logical_pointer = v;
525+ self . validator . relax_logical_pointer = v;
414526 self
415527 }
416528
417529 /// Enable `VK_KHR_relaxed_block_layout` when checking standard uniform, storage buffer, and
418530 /// push constant layouts. This is the default when targeting Vulkan 1.1 or later.
419531 #[ must_use]
420532 pub fn relax_block_layout ( mut self , v : bool ) -> Self {
421- self . relax_block_layout = v ;
533+ self . validator . relax_block_layout = Some ( v ) ;
422534 self
423535 }
424536
425537 /// Enable `VK_KHR_uniform_buffer_standard_layout` when checking standard uniform buffer
426538 /// layouts.
427539 #[ must_use]
428540 pub fn uniform_buffer_standard_layout ( mut self , v : bool ) -> Self {
429- self . uniform_buffer_standard_layout = v;
541+ self . validator . uniform_buffer_standard_layout = v;
430542 self
431543 }
432544
@@ -435,22 +547,22 @@ impl SpirvBuilder {
435547 /// in effect this will override the --relax-block-layout option.
436548 #[ must_use]
437549 pub fn scalar_block_layout ( mut self , v : bool ) -> Self {
438- self . scalar_block_layout = v;
550+ self . validator . scalar_block_layout = v;
439551 self
440552 }
441553
442554 /// Skip checking standard uniform/storage buffer layout. Overrides any --relax-block-layout or
443555 /// --scalar-block-layout option.
444556 #[ must_use]
445557 pub fn skip_block_layout ( mut self , v : bool ) -> Self {
446- self . skip_block_layout = v;
558+ self . validator . skip_block_layout = v;
447559 self
448560 }
449561
450562 /// Preserve unused descriptor bindings. Useful for reflection.
451563 #[ must_use]
452564 pub fn preserve_bindings ( mut self , v : bool ) -> Self {
453- self . preserve_bindings = v;
565+ self . optimizer . preserve_bindings = v;
454566 self
455567 }
456568
@@ -696,25 +808,25 @@ fn invoke_rustc(builder: &SpirvBuilder) -> Result<PathBuf, SpirvBuilderError> {
696808 }
697809 SpirvMetadata :: Full => llvm_args. push ( "--spirv-metadata=full" . to_string ( ) ) ,
698810 }
699- if builder. relax_struct_store {
811+ if builder. validator . relax_struct_store {
700812 llvm_args. push ( "--relax-struct-store" . to_string ( ) ) ;
701813 }
702- if builder. relax_logical_pointer {
814+ if builder. validator . relax_logical_pointer {
703815 llvm_args. push ( "--relax-logical-pointer" . to_string ( ) ) ;
704816 }
705- if builder. relax_block_layout {
817+ if builder. validator . relax_block_layout {
706818 llvm_args. push ( "--relax-block-layout" . to_string ( ) ) ;
707819 }
708- if builder. uniform_buffer_standard_layout {
820+ if builder. validator . uniform_buffer_standard_layout {
709821 llvm_args. push ( "--uniform-buffer-standard-layout" . to_string ( ) ) ;
710822 }
711- if builder. scalar_block_layout {
823+ if builder. validator . scalar_block_layout {
712824 llvm_args. push ( "--scalar-block-layout" . to_string ( ) ) ;
713825 }
714- if builder. skip_block_layout {
826+ if builder. validator . skip_block_layout {
715827 llvm_args. push ( "--skip-block-layout" . to_string ( ) ) ;
716828 }
717- if builder. preserve_bindings {
829+ if builder. optimizer . preserve_bindings {
718830 llvm_args. push ( "--preserve-bindings" . to_string ( ) ) ;
719831 }
720832 let mut target_features = vec ! [ ] ;
0 commit comments