pub enum ShaderPanicStrategy {
    SilentExit,
    DebugPrintfThenExit {
        print_inputs: bool,
        print_backtrace: bool,
    },
    UNSOUND_DO_NOT_USE_UndefinedBehaviorViaUnreachable,
}
Expand description

Strategy used to handle Rust panic!s in shaders compiled to SPIR-V.

Variants§

§

SilentExit

Return from shader entry-point with no side-effects (default).

While similar to the standard SPIR-V OpTerminateInvocation, this is not limited to fragment shaders, and instead supports all shaders (as it’s handled via control-flow rewriting, instead of SPIR-V features).

§

DebugPrintfThenExit

Fields

§print_inputs: bool

Whether to also print the entry-point inputs (excluding buffers/resources), which should uniquely identify the panicking shader invocation.

§print_backtrace: bool

Whether to also print a “backtrace” (i.e. the chain of function calls that led to the `panic!).

As there is no way to dynamically compute this information, the string containing the full backtrace of each panic! is statically generated, meaning this option could significantly increase binary size.

Like SilentExit, but also using debugPrintf to report the panic in a way that can reach the user, before returning from the entry-point.

Will automatically require the SPV_KHR_non_semantic_info extension, as debugPrintf uses a “non-semantic extended instruction set”.

If you have multiple entry-points, you may need to also enable the multimodule node (see https://github.com/KhronosGroup/SPIRV-Tools/issues/4892).

Note: actually obtaining the debugPrintf output requires:

  • Vulkan Validation Layers (from e.g. the Vulkan SDK)
    • (they contain the debugPrintf implementation, a SPIR-V -> SPIR-V translation)
    • set the VK_LOADER_LAYERS_ENABLE=VK_LAYER_KHRONOS_validation environment variable to easily enable them without any code changes
    • alternatively, "VK_LAYER_KHRONOS_validation" can be passed during instance creation, to enable them programmatically
  • Validation Layers’ debugPrintf support:
    • set the VK_LAYER_ENABLES=VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT environment variable to easily enable the debugPrintf support
    • alternatively, VkValidationFeaturesEXT during instance creation, or the khronos_validation.enables field in vk_layer_settings.txt, can be used to enable VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT (see also https://github.com/KhronosGroup/Vulkan-ValidationLayers/blob/main/docs/debug_printf.md)
  • for outputting the debugPrintf messages sent back from the GPU:
    • set the DEBUG_PRINTF_TO_STDOUT=1 environment variable if you don’t plan on customizing the reporting (see below for alternatives)
  • for wgpu:
    • required: wgpu::Features::SPIRV_SHADER_PASSTHROUGH (Naga lacks debugPrintf)
    • optional: building in debug mode (and/or with debug-assertions enabled), to enable wgpu logging/debug support
      • (the debug assertions requirement may be lifted in future wgpu versions)
      • this uses VK_EXT_debug_utils internally, and is a better-integrated alternative to just setting DEBUG_PRINTF_TO_STDOUT=1
      • RUST_LOG=wgpu_hal::vulkan=info (or equivalent) will enable said output (as debugPrintf messages have the “info” level)
      • RUST_LOG controls env_logger, which isn’t itself required, but some log/tracing subscriber is needed to get any output
  • for Vulkan (e.g. via ash):
    • required: enabling the VK_KHR_shader_non_semantic_info Vulkan Device extension
    • optional: as described above, enabling the Validation Layers and their debugPrintf support can be done during instance creation
    • optional: integrating VK_EXT_debug_utils allows more reporting flexibility than DEBUG_PRINTF_TO_STDOUT=1)
§

UNSOUND_DO_NOT_USE_UndefinedBehaviorViaUnreachable

Warning: this is unsound (i.e. adds Undefined Behavior to safe Rust code)

This option only exists for testing (hence the unfriendly name it has), and more specifically testing whether conditional panics are responsible for performance differences when upgrading from older Rust-GPU versions (which used infinite loops for panics, that spirv-opt/drivers could’ve sometimes treated as UB, and optimized as if they were impossible to reach).

Unlike those infinite loops, however, this uses OpUnreachable, so it forces the old worst-case (all panic!s become UB and are optimized out).

Trait Implementations§

source§

impl Clone for ShaderPanicStrategy

source§

fn clone(&self) -> ShaderPanicStrategy

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for ShaderPanicStrategy

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl PartialEq<ShaderPanicStrategy> for ShaderPanicStrategy

source§

fn eq(&self, other: &ShaderPanicStrategy) -> bool

This method tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
source§

impl Copy for ShaderPanicStrategy

source§

impl Eq for ShaderPanicStrategy

source§

impl StructuralEq for ShaderPanicStrategy

source§

impl StructuralPartialEq for ShaderPanicStrategy

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for Twhere T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for Twhere U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T> ToOwned for Twhere T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for Twhere U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.