mod conv; mod help; mod keywords; mod mesh_shader; mod ray; mod storage; mod writer;
use alloc::{string::String, vec::Vec}; use core::fmt::Error as FmtError;
use thiserror::Error;
usecrate::{
back::{self, TaskDispatchLimits},
ir, proc, Handle,
};
/// Direct3D 12 binding information for a global variable. /// /// This type provides the HLSL-specific information Naga needs to declare and /// access an HLSL global variable that cannot be derived from the `Module` /// itself. /// /// An HLSL global variable declaration includes details that the Direct3D API /// will use to refer to it. For example: /// /// RWByteAddressBuffer s_sasm : register(u0, space2); /// /// This defines a global `s_sasm` that a Direct3D root signature would refer to /// as register `0` in register space `2` in a `UAV` descriptor range. Naga can /// infer the register's descriptor range type from the variable's address class /// (writable [`Storage`] variables are implemented by Direct3D Unordered Access /// Views, the `u` register type), but the register number and register space /// must be supplied by the user. /// /// The [`back::hlsl::Options`] structure provides `BindTarget`s for various /// situations in which Naga may need to generate an HLSL global variable, like /// [`binding_map`] for Naga global variables, or [`immediates_target`] for /// a module's sole [`Immediate`] variable. See those fields' documentation /// for details. /// /// [`Storage`]: crate::ir::AddressSpace::Storage /// [`back::hlsl::Options`]: Options /// [`binding_map`]: Options::binding_map /// [`immediates_target`]: Options::immediates_target /// [`Immediate`]: crate::ir::AddressSpace::Immediate #[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Hash)] #[cfg_attr(feature = "serialize", derive(serde::Serialize))] #[cfg_attr(feature = "deserialize", derive(serde::Deserialize))] pubstruct BindTarget { pub space: u8, /// For regular bindings this is the register number. /// /// For sampler bindings, this is the index to use into the bind group's sampler index buffer. pub register: u32, /// If the binding is an unsized binding array, this overrides the size. pub binding_array_size: Option<u32>, /// This is the index in the buffer at [`Options::dynamic_storage_buffer_offsets_targets`]. pub dynamic_storage_buffer_offsets_index: Option<u32>, /// This is a hint that we need to restrict indexing of vectors, matrices and arrays. /// /// If [`Options::restrict_indexing`] is also `true`, we will restrict indexing. #[cfg_attr(any(feature = "serialize", feature = "deserialize"), serde(default))] pub restrict_indexing: bool,
}
#[cfg(feature = "deserialize")] fn deserialize_binding_map<'de, D>(deserializer: D) -> Result<BindingMap, D::Error> where
D: serde::Deserializer<'de>,
{ use serde::Deserialize;
let vec = Vec::<BindingMapSerialization>::deserialize(deserializer)?; letmut map = BindingMap::default(); for item in vec {
map.insert(item.resource_binding, item.bind_target);
}
Ok(map)
}
// Using `BTreeMap` instead of `HashMap` so that we can hash itself. pubtype BindingMap = alloc::collections::BTreeMap<crate::ResourceBinding, BindTarget>;
#[cfg(feature = "deserialize")] fn deserialize_sampler_index_buffer_bindings<'de, D>(
deserializer: D,
) -> Result<SamplerIndexBufferBindingMap, D::Error> where
D: serde::Deserializer<'de>,
{ use serde::Deserialize;
let vec = Vec::<SamplerIndexBufferBindingSerialization>::deserialize(deserializer)?; letmut map = SamplerIndexBufferBindingMap::default(); for item in vec {
map.insert(
SamplerIndexBufferKey { group: item.group },
item.bind_target,
);
}
Ok(map)
}
// We use a BTreeMap here so that we can hash it. pubtype SamplerIndexBufferBindingMap =
alloc::collections::BTreeMap<SamplerIndexBufferKey, BindTarget>;
/// HLSL binding information for a Naga [`External`] image global variable. /// /// See the module documentation's section on [External textures][mod] for details. /// /// [`External`]: crate::ir::ImageClass::External /// [mod]: #external-textures #[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Hash)] #[cfg_attr(feature = "serialize", derive(serde::Serialize))] #[cfg_attr(feature = "deserialize", derive(serde::Deserialize))] pubstruct ExternalTextureBindTarget { /// HLSL binding information for the individual plane textures. /// /// Each of these should refer to an HLSL `Texture2D<float4>` holding one /// plane of data for the external texture. The exact meaning of each plane /// varies at runtime depending on where the external texture's data /// originated. pub planes: [BindTarget; 3],
/// HLSL binding information for a buffer holding the sampling parameters. /// /// This should refer to a cbuffer of type `NagaExternalTextureParams`, that /// the code Naga generates for `textureSampleBaseClampToEdge` consults to /// decide how to combine the data in [`planes`] to get the result required /// by the spec. /// /// [`planes`]: Self::planes pub params: BindTarget,
}
/// Configuration used in the [`Writer`]. #[derive(Clone, Debug, Hash, PartialEq, Eq)] #[cfg_attr(feature = "serialize", derive(serde::Serialize))] #[cfg_attr(feature = "deserialize", derive(serde::Deserialize))] #[cfg_attr(feature = "deserialize", serde(default))] pubstruct Options { /// The hlsl shader model to be used pub shader_model: ShaderModel,
/// HLSL binding information for each Naga global variable. /// /// This maps Naga [`GlobalVariable`]'s [`ResourceBinding`]s to a /// [`BindTarget`] specifying its register number and space, along with /// other details necessary to generate a full HLSL declaration for it, /// or to access its value. /// /// This must provide a [`BindTarget`] for every [`GlobalVariable`] in the /// [`Module`] that has a [`binding`]. /// /// [`GlobalVariable`]: crate::ir::GlobalVariable /// [`ResourceBinding`]: crate::ir::ResourceBinding /// [`Module`]: crate::ir::Module /// [`binding`]: crate::ir::GlobalVariable::binding #[cfg_attr(
feature = "deserialize",
serde(deserialize_with = "deserialize_binding_map")
)] pub binding_map: BindingMap,
/// Don't panic on missing bindings, instead generate any HLSL. pub fake_missing_bindings: bool, /// Add special constants to `SV_VertexIndex` and `SV_InstanceIndex`, /// to make them work like in Vulkan/Metal, with help of the host. pub special_constants_binding: Option<BindTarget>,
/// HLSL binding information for the [`Immediate`] global, if present. /// /// If a module contains a global in the [`Immediate`] address space, the /// `dx12` backend stores its value directly in the root signature as a /// series of [`D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS`], whose binding /// information is given here. /// /// [`Immediate`]: crate::ir::AddressSpace::Immediate /// [`D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS`]: https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_root_parameter_type pub immediates_target: Option<BindTarget>,
/// HLSL binding information for the sampler heap and comparison sampler heap. pub sampler_heap_target: SamplerHeapBindTargets,
/// Mapping of each bind group's sampler index buffer to a bind target. #[cfg_attr(
feature = "deserialize",
serde(deserialize_with = "deserialize_sampler_index_buffer_bindings")
)] pub sampler_buffer_binding_map: SamplerIndexBufferBindingMap, /// Bind target for dynamic storage buffer offsets #[cfg_attr(
feature = "deserialize",
serde(deserialize_with = "deserialize_storage_buffer_offsets")
)] pub dynamic_storage_buffer_offsets_targets: DynamicStorageBufferOffsetsTargets, #[cfg_attr(
feature = "deserialize",
serde(deserialize_with = "deserialize_external_texture_binding_map")
)]
/// HLSL binding information for [`External`] image global variables. /// /// See [`ExternalTextureBindTarget`] for details. /// /// [`External`]: crate::ir::ImageClass::External pub external_texture_binding_map: ExternalTextureBindingMap,
/// Should workgroup variables be zero initialized (by polyfilling)? pub zero_initialize_workgroup_memory: bool, /// Should we restrict indexing of vectors, matrices and arrays? pub restrict_indexing: bool, /// If set, loops will have code injected into them, forcing the compiler /// to think the number of iterations is bounded. pub force_loop_bounding: bool,
/// Limits to the mesh shader dispatch group a task workgroup can dispatch. /// /// Metal for example limits to 1024 workgroups per task shader dispatch. Dispatching more is /// undefined behavior, so this would validate that to dispatch zero workgroups. pub task_dispatch_limits: Option<TaskDispatchLimits>,
/// If true, naga may generate checks that the primitive indices are valid in the output. /// /// Currently this validation is unimplemented. pub mesh_shader_primitive_indices_clamp: bool, /// if set, ray queries will get a variable to track their state to prevent /// misuse. pub ray_query_initialization_tracking: bool,
}
/// Reflection info for entry point names. #[derive(Default)] pubstruct ReflectionInfo { /// Mapping of the entry point names. /// /// Each item in the array corresponds to an entry point index. The real entry point name may be different if one of the /// reserved words are used. /// /// Note: Some entry points may fail translation because of missing bindings. pub entry_point_names: Vec<Result<String, EntryPointError>>,
}
/// A subset of options that are meant to be changed per pipeline. #[derive(Debug, Default, Clone)] #[cfg_attr(feature = "serialize", derive(serde::Serialize))] #[cfg_attr(feature = "deserialize", derive(serde::Deserialize))] #[cfg_attr(feature = "deserialize", serde(default))] pubstruct PipelineOptions { /// The entry point to write. /// /// Entry points are identified by a shader stage specification, /// and a name. /// /// If `None`, all entry points will be written. If `Some` and the entry /// point is not found, an error will be thrown while writing. pub entry_point: Option<(ir::ShaderStage, String)>,
}
#[derive(Error, Debug)] pubenum Error { #[error(transparent)]
IoError(#[from] FmtError), #[error("A scalar with an unsupported width was requested: {0:?}")]
UnsupportedScalar(crate::Scalar), #[error("{0}")]
Unimplemented(String), // TODO: Error used only during development #[error("{0}")]
Custom(String), #[error("overrides should not be present at this stage")] Override, #[error(transparent)]
ResolveArraySizeError(#[from] proc::ResolveArraySizeError), #[error("entry point with stage {0:?} and name '{1}' not found")]
EntryPointNotFound(ir::ShaderStage, String), #[error("requires shader model {1:?} for reason: {0}")]
ShaderModelTooLow(String, ShaderModel),
}
#[derive(Default)] struct Wrapped {
types: crate::FastHashSet<WrappedType>, /// If true, the sampler heaps have been written out.
sampler_heaps: bool, // Mapping from SamplerIndexBufferKey to the name the namer returned.
sampler_index_buffers: crate::FastHashMap<SamplerIndexBufferKey, String>,
}
/// A fragment entry point to be considered when generating HLSL for the output interface of vertex /// entry points. /// /// This is provided as an optional parameter to [`Writer::write`]. /// /// If this is provided, vertex outputs will be removed if they are not inputs of this fragment /// entry point. This is necessary for generating correct HLSL when some of the vertex shader /// outputs are not consumed by the fragment shader. pubstruct FragmentEntryPoint<'a> {
module: &'a crate::Module,
func: &'a crate::Function,
}
impl<'a> FragmentEntryPoint<'a> { /// Returns `None` if the entry point with the provided name can't be found or isn't a fragment /// entry point. pubfn new(module: &'a crate::Module, ep_name: &'a str) -> Option<Self> {
module
.entry_points
.iter()
.find(|ep| ep.name == ep_name)
.filter(|ep| ep.stage == crate::ShaderStage::Fragment)
.map(|ep| Self {
module,
func: &ep.function,
})
}
}
pubstruct Writer<'a, W> {
out: W,
names: crate::FastHashMap<proc::NameKey, String>,
namer: proc::Namer, /// HLSL backend options
options: &'a Options, /// Per-stage backend options
pipeline_options: &'a PipelineOptions, /// Information about entry point arguments and result types.
entry_point_io: crate::FastHashMap<usize, writer::EntryPointInterface>, /// Set of expressions that have associated temporary variables
named_expressions: crate::NamedExpressions,
wrapped: Wrapped,
written_committed_intersection: bool,
written_candidate_intersection: bool,
continue_ctx: back::continue_forward::ContinueCtx,
/// A reference to some part of a global variable, lowered to a series of /// byte offset calculations. /// /// See the [`storage`] module for background on why we need this. /// /// Each [`SubAccess`] in the vector is a lowering of some [`Access`] or /// [`AccessIndex`] expression to the level of byte strides and offsets. See /// [`SubAccess`] for details. /// /// This field is a member of [`Writer`] solely to allow re-use of /// the `Vec`'s dynamic allocation. The value is no longer needed /// once HLSL for the access has been generated. /// /// [`Storage`]: crate::AddressSpace::Storage /// [`SubAccess`]: storage::SubAccess /// [`Access`]: crate::Expression::Access /// [`AccessIndex`]: crate::Expression::AccessIndex
temp_access_chain: Vec<storage::SubAccess>,
need_bake_expressions: back::NeedBakeExpressions,
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.