@@ -154,7 +154,7 @@ impl fmt::Display for SpirvBuilderError {
154
154
155
155
impl Error for SpirvBuilderError { }
156
156
157
- #[ derive( Debug , PartialEq , Eq , Clone , Copy ) ]
157
+ #[ derive( Debug , PartialEq , Eq , Clone , Copy , Default ) ]
158
158
pub enum MetadataPrintout {
159
159
/// Print no cargo metadata.
160
160
None ,
@@ -163,12 +163,14 @@ pub enum MetadataPrintout {
163
163
/// Print all cargo metadata.
164
164
///
165
165
/// Includes dependency information and spirv environment variable.
166
+ #[ default]
166
167
Full ,
167
168
}
168
169
169
- #[ derive( Debug , PartialEq , Eq , Clone , Copy ) ]
170
+ #[ derive( Debug , PartialEq , Eq , Clone , Copy , Default ) ]
170
171
pub enum SpirvMetadata {
171
172
/// Strip all names and other debug information from SPIR-V output.
173
+ #[ default]
172
174
None ,
173
175
/// Only include `OpName`s for public interface variables (uniforms and the like), to allow
174
176
/// shader reflection.
@@ -178,13 +180,14 @@ pub enum SpirvMetadata {
178
180
}
179
181
180
182
/// 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 ) ]
182
184
pub enum ShaderPanicStrategy {
183
185
/// Return from shader entry-point with no side-effects **(default)**.
184
186
///
185
187
/// While similar to the standard SPIR-V `OpTerminateInvocation`, this is
186
188
/// *not* limited to fragment shaders, and instead supports all shaders
187
189
/// (as it's handled via control-flow rewriting, instead of SPIR-V features).
190
+ #[ default]
188
191
SilentExit ,
189
192
190
193
/// Like `SilentExit`, but also using `debugPrintf` to report the panic in
@@ -258,76 +261,185 @@ pub enum ShaderPanicStrategy {
258
261
UNSOUND_DO_NOT_USE_UndefinedBehaviorViaUnreachable ,
259
262
}
260
263
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
+
261
349
/// Cargo features specification for building the shader crate.
262
350
#[ 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 > ,
266
356
}
267
357
358
+ #[ non_exhaustive]
268
359
pub 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 > ,
280
387
// 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 > ,
285
398
286
399
// `rustc_codegen_spirv::linker` codegen args
400
+ /// Change the shader `panic!` handling strategy (see [`ShaderPanicStrategy`]).
287
401
pub shader_panic_strategy : ShaderPanicStrategy ,
288
402
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 ,
296
405
297
- // spirv-opt flags
298
- pub preserve_bindings : bool ,
406
+ /// spirv-opt flags
407
+ pub optimizer : OptimizerOptions ,
299
408
}
300
409
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 {
303
412
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 ( ) ,
306
415
release : true ,
307
- target : target . into ( ) ,
416
+ target : None ,
308
417
deny_warnings : false ,
309
418
multimodule : false ,
310
- spirv_metadata : SpirvMetadata :: None ,
419
+ spirv_metadata : SpirvMetadata :: default ( ) ,
311
420
capabilities : Vec :: new ( ) ,
312
421
extensions : Vec :: new ( ) ,
313
422
extra_args : Vec :: new ( ) ,
314
423
rustc_codegen_spirv_location : None ,
315
424
path_to_target_spec : None ,
316
425
target_dir_path : None ,
317
426
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 ( ) ,
328
430
shader_crate_features : ShaderCrateFeatures :: default ( ) ,
329
431
}
330
432
}
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
+ }
331
443
332
444
/// Sets the path of the "target specification" file.
333
445
///
@@ -402,31 +514,31 @@ impl SpirvBuilder {
402
514
/// Allow store from one struct type to a different type with compatible layout and members.
403
515
#[ must_use]
404
516
pub fn relax_struct_store ( mut self , v : bool ) -> Self {
405
- self . relax_struct_store = v;
517
+ self . validator . relax_struct_store = v;
406
518
self
407
519
}
408
520
409
521
/// Allow allocating an object of a pointer type and returning a pointer value from a function
410
522
/// in logical addressing mode
411
523
#[ must_use]
412
524
pub fn relax_logical_pointer ( mut self , v : bool ) -> Self {
413
- self . relax_logical_pointer = v;
525
+ self . validator . relax_logical_pointer = v;
414
526
self
415
527
}
416
528
417
529
/// Enable `VK_KHR_relaxed_block_layout` when checking standard uniform, storage buffer, and
418
530
/// push constant layouts. This is the default when targeting Vulkan 1.1 or later.
419
531
#[ must_use]
420
532
pub fn relax_block_layout ( mut self , v : bool ) -> Self {
421
- self . relax_block_layout = v ;
533
+ self . validator . relax_block_layout = Some ( v ) ;
422
534
self
423
535
}
424
536
425
537
/// Enable `VK_KHR_uniform_buffer_standard_layout` when checking standard uniform buffer
426
538
/// layouts.
427
539
#[ must_use]
428
540
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;
430
542
self
431
543
}
432
544
@@ -435,22 +547,22 @@ impl SpirvBuilder {
435
547
/// in effect this will override the --relax-block-layout option.
436
548
#[ must_use]
437
549
pub fn scalar_block_layout ( mut self , v : bool ) -> Self {
438
- self . scalar_block_layout = v;
550
+ self . validator . scalar_block_layout = v;
439
551
self
440
552
}
441
553
442
554
/// Skip checking standard uniform/storage buffer layout. Overrides any --relax-block-layout or
443
555
/// --scalar-block-layout option.
444
556
#[ must_use]
445
557
pub fn skip_block_layout ( mut self , v : bool ) -> Self {
446
- self . skip_block_layout = v;
558
+ self . validator . skip_block_layout = v;
447
559
self
448
560
}
449
561
450
562
/// Preserve unused descriptor bindings. Useful for reflection.
451
563
#[ must_use]
452
564
pub fn preserve_bindings ( mut self , v : bool ) -> Self {
453
- self . preserve_bindings = v;
565
+ self . optimizer . preserve_bindings = v;
454
566
self
455
567
}
456
568
@@ -696,25 +808,25 @@ fn invoke_rustc(builder: &SpirvBuilder) -> Result<PathBuf, SpirvBuilderError> {
696
808
}
697
809
SpirvMetadata :: Full => llvm_args. push ( "--spirv-metadata=full" . to_string ( ) ) ,
698
810
}
699
- if builder. relax_struct_store {
811
+ if builder. validator . relax_struct_store {
700
812
llvm_args. push ( "--relax-struct-store" . to_string ( ) ) ;
701
813
}
702
- if builder. relax_logical_pointer {
814
+ if builder. validator . relax_logical_pointer {
703
815
llvm_args. push ( "--relax-logical-pointer" . to_string ( ) ) ;
704
816
}
705
- if builder. relax_block_layout {
817
+ if builder. validator . relax_block_layout {
706
818
llvm_args. push ( "--relax-block-layout" . to_string ( ) ) ;
707
819
}
708
- if builder. uniform_buffer_standard_layout {
820
+ if builder. validator . uniform_buffer_standard_layout {
709
821
llvm_args. push ( "--uniform-buffer-standard-layout" . to_string ( ) ) ;
710
822
}
711
- if builder. scalar_block_layout {
823
+ if builder. validator . scalar_block_layout {
712
824
llvm_args. push ( "--scalar-block-layout" . to_string ( ) ) ;
713
825
}
714
- if builder. skip_block_layout {
826
+ if builder. validator . skip_block_layout {
715
827
llvm_args. push ( "--skip-block-layout" . to_string ( ) ) ;
716
828
}
717
- if builder. preserve_bindings {
829
+ if builder. optimizer . preserve_bindings {
718
830
llvm_args. push ( "--preserve-bindings" . to_string ( ) ) ;
719
831
}
720
832
let mut target_features = vec ! [ ] ;
0 commit comments