@@ -466,38 +466,75 @@ enum CachedConstant {
466
466
ZeroValue ( Word ) ,
467
467
}
468
468
469
+ /// How a Naga global variable is represented in SPIR-V.
470
+ ///
471
+ /// In the Vulkan spec 1.3.296, the section [Descriptor Set Interface][dsi] says:
472
+ ///
473
+ /// > Variables identified with the `Uniform` storage class are used to access
474
+ /// > transparent buffer backed resources. Such variables *must* be:
475
+ /// >
476
+ /// > - typed as `OpTypeStruct`, or an array of this type,
477
+ /// >
478
+ /// > - identified with a `Block` or `BufferBlock` decoration, and
479
+ /// >
480
+ /// > - laid out explicitly using the `Offset`, `ArrayStride`, and `MatrixStride`
481
+ /// > decorations as specified in "Offset and Stride Assignment".
482
+ ///
483
+ /// This is followed by identical language for the `StorageBuffer`,
484
+ /// except that a `BufferBlock` decoration is not allowed.
485
+ ///
486
+ /// When we encounter a global variable in the [`Storage`] or [`Uniform`]
487
+ /// address spaces whose type is not already [`Struct`], this backend implicitly
488
+ /// wraps the global variable in a struct: we generate a SPIR-V global variable
489
+ /// holding an `OpTypeStruct` with a single member, whose type is what the Naga
490
+ /// global's type would suggest, decorated as required above.
491
+ ///
492
+ /// The [`helpers::global_needs_wrapper`] function determines whether a given
493
+ /// [`crate::GlobalVariable`] needs to be wrapped.
494
+ ///
495
+ /// [dsi]: https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#interfaces-resources-descset
496
+ /// [`Storage`]: crate::AddressSpace::Storage
497
+ /// [`Uniform`]: crate::AddressSpace::Uniform
498
+ /// [`Struct`]: crate::TypeInner::Struct
469
499
#[ derive( Clone ) ]
470
500
struct GlobalVariable {
471
- /// ID of the OpVariable that declares the global.
501
+ /// The SPIR-V id of the `OpVariable` that declares the global.
502
+ ///
503
+ /// If this global has been implicitly wrapped in an `OpTypeStruct`, this id
504
+ /// refers to the wrapper, not the original Naga value it contains. If you
505
+ /// need the Naga value, use [`access_id`] instead of this field.
472
506
///
473
- /// If you need the variable's value, use [`access_id`] instead of this
474
- /// field. If we wrapped the Naga IR `GlobalVariable`'s type in a struct to
475
- /// comply with Vulkan's requirements, then this points to the `OpVariable`
476
- /// with the synthesized struct type, whereas `access_id` points to the
477
- /// field of said struct that holds the variable's actual value.
507
+ /// If this global is not implicitly wrapped, this is the same as
508
+ /// [`access_id`].
478
509
///
479
510
/// This is used to compute the `access_id` pointer in function prologues,
480
- /// and used for `ArrayLength` expressions, which do need the struct.
511
+ /// and used for `ArrayLength` expressions, which need to pass the wrapper
512
+ /// struct.
481
513
///
482
514
/// [`access_id`]: GlobalVariable::access_id
483
515
var_id : Word ,
484
516
485
- /// For `AddressSpace::Handle` variables, this ID is recorded in the function
486
- /// prelude block (and reset before every function) as `OpLoad` of the variable.
487
- /// It is then used for all the global ops, such as `OpImageSample`.
517
+ /// The loaded value of a `AddressSpace::Handle` global variable.
518
+ ///
519
+ /// If the current function uses this global variable, this is the id of an
520
+ /// `OpLoad` instruction in the function's prologue that loads its value.
521
+ /// (This value is assigned as we write the prologue code of each function.)
522
+ /// It is then used for all operations on the global, such as `OpImageSample`.
488
523
handle_id : Word ,
489
524
490
- /// Actual ID used to access this variable.
491
- /// For wrapped buffer variables, this ID is `OpAccessChain` into the
492
- /// wrapper. Otherwise, the same as `var_id`.
525
+ /// The SPIR-V id of a pointer to this variable's Naga IR value.
526
+ ///
527
+ /// If the current function uses this global variable, and it has been
528
+ /// implicitly wrapped in an `OpTypeStruct`, this is the id of an
529
+ /// `OpAccessChain` instruction in the function's prologue that refers to
530
+ /// the wrapped value inside the struct. (This value is assigned as we write
531
+ /// the prologue code of each function.) If you need the wrapper struct
532
+ /// itself, use [`var_id`] instead of this field.
533
+ ///
534
+ /// If this global is not implicitly wrapped, this is the same as
535
+ /// [`var_id`].
493
536
///
494
- /// Vulkan requires that globals in the `StorageBuffer` and `Uniform` storage
495
- /// classes must be structs with the `Block` decoration, but WGSL and Naga IR
496
- /// make no such requirement. So for such variables, we generate a wrapper struct
497
- /// type with a single element of the type given by Naga, generate an
498
- /// `OpAccessChain` for that member in the function prelude, and use that pointer
499
- /// to refer to the global in the function body. This is the id of that access,
500
- /// updated for each function in `write_function`.
537
+ /// [`var_id`]: GlobalVariable::var_id
501
538
access_id : Word ,
502
539
}
503
540
0 commit comments