Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Various doc fixes #1726

Merged
merged 3 commits into from
Feb 16, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions src/back/msl/writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1856,8 +1856,12 @@ impl<W: Write> Writer<W> {
if min_ref_count <= expr_info.ref_count {
self.need_bake_expressions.insert(expr.0);
}
// if the expression is a Dot product with integer arguments,
// then the args needs baking as well

// WGSL's `dot` function works on any `vecN` type, but Metal's only
// works on floating-point vectors, so we emit inline code for
// integer vector `dot` calls. But that code uses each argument `N`
// times, once for each component (see `put_dot_product`), so to
// avoid duplicated evaluation, we must bake integer operands.
if let (
fun_handle,
&Expression::Math {
Expand Down
20 changes: 11 additions & 9 deletions src/back/spv/image.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,16 +35,18 @@ struct ImageCoordinates {

/// A trait for image access (load or store) code generators.
///
/// When generating code for `ImageLoad` and `ImageStore` expressions, the image
/// bounds checks policy can affect some operands of the image access
/// instruction (the coordinates, level of detail, and sample index), but other
/// aspects are unaffected: the image id, result type (if any), and the specific
/// SPIR-V instruction used.
/// Types implementing this trait hold information about an `ImageStore` or
/// `ImageLoad` operation that is not affected by the bounds check policy. The
/// `generate` method emits code for the access, given the results of bounds
/// checking.
///
/// This struct holds the latter category of information, saving us from passing
/// a half-dozen parameters along the various code paths. The parts that are
/// affected by bounds checks, are passed as parameters to the `generate`
/// method.
/// The [`image`] bounds checks policy affects access coordinates, level of
/// detail, and sample index, but never the image id, result type (if any), or
/// the specific SPIR-V instruction used. Types that implement this trait gather
/// together the latter category, so we don't have to plumb them through the
/// bounds-checking code.
///
/// [`image`]: crate::proc::BoundsCheckPolicies::index
trait Access {
/// The Rust type that represents SPIR-V values and types for this access.
///
Expand Down
70 changes: 56 additions & 14 deletions src/valid/analyzer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,17 +199,51 @@ pub struct FunctionInfo {
pub uniformity: Uniformity,
/// Function may kill the invocation.
pub may_kill: bool,
/// Set of image-sampler pais used with sampling.

/// All pairs of (texture, sampler) globals that may be used together in
/// sampling operations by this function and its callees. This includes
/// pairings that arise when this function passes textures and samplers as
/// arguments to its callees.
///
/// This table does not include uses of textures and samplers passed as
/// arguments to this function itself, since we do not know which globals
/// those will be. However, this table *is* exhaustive when computed for an
/// entry point function: entry points never receive textures or samplers as
/// arguments, so all an entry point's sampling can be reported in terms of
/// globals.
///
/// The GLSL back end uses this table to construct reflection info that
/// clients need to construct texture-combined sampler values.
pub sampling_set: crate::FastHashSet<SamplingKey>,
/// Vector of global variable usages.

/// How this function and its callees use this module's globals.
///
/// Each item corresponds to a global variable in the module.
/// This is indexed by `Handle<GlobalVariable>` indices. However,
/// `FunctionInfo` implements `std::ops::Index<Handle<Globalvariable>>`,
/// so you can simply index this struct with a global handle to retrieve
/// its usage information.
global_uses: Box<[GlobalUse]>,
/// Vector of expression infos.

/// Information about each expression in this function's body.
///
/// Each item corresponds to an expression in the function.
/// This is indexed by `Handle<Expression>` indices. However, `FunctionInfo`
/// implements `std::ops::Index<Handle<Expression>>`, so you can simply
/// index this struct with an expression handle to retrieve its
/// `ExpressionInfo`.
expressions: Box<[ExpressionInfo]>,
/// HashSet with information about sampling realized by the function

/// All (texture, sampler) pairs that may be used together in sampling
/// operations by this function and its callees, whether they are accessed
/// as globals or passed as arguments.
///
/// Participants are represented by [`GlobalVariable`] handles whenever
/// possible, and otherwise by indices of this function's arguments.
///
/// When analyzing a function call, we combine this data about the callee
/// with the actual arguments being passed to produce the callers' own
/// `sampling_set` and `sampling` tables.
///
/// [`GlobalVariable`]: crate::GlobalVariable
sampling: crate::FastHashSet<Sampling>,
}

Expand Down Expand Up @@ -309,14 +343,15 @@ impl FunctionInfo {
/// Inherit information from a called function.
fn process_call(
&mut self,
info: &Self,
callee: &Self,
jimblandy marked this conversation as resolved.
Show resolved Hide resolved
arguments: &[Handle<crate::Expression>],
expression_arena: &Arena<crate::Expression>,
) -> Result<FunctionUniformity, WithSpan<FunctionError>> {
for key in info.sampling_set.iter() {
self.sampling_set.insert(key.clone());
}
for sampling in info.sampling.iter() {
self.sampling_set
.extend(callee.sampling_set.iter().cloned());
for sampling in callee.sampling.iter() {
// If the callee was passed the texture or sampler as an argument,
// we may now be able to determine which globals those referred to.
let image_storage = match sampling.image {
GlobalOrArgument::Global(var) => GlobalOrArgument::Global(var),
GlobalOrArgument::Argument(i) => {
Expand All @@ -343,6 +378,10 @@ impl FunctionInfo {
}
};

// If we've managed to pin both the image and sampler down to
// specific globals, record that in our `sampling_set`. Otherwise,
// record as much as we do know in our own `sampling` table, for our
// callers to sort out.
match (image_storage, sampler_storage) {
(GlobalOrArgument::Global(image), GlobalOrArgument::Global(sampler)) => {
self.sampling_set.insert(SamplingKey { image, sampler });
Expand All @@ -352,12 +391,15 @@ impl FunctionInfo {
}
}
}
for (mine, other) in self.global_uses.iter_mut().zip(info.global_uses.iter()) {

// Inherit global use from our callees.
for (mine, other) in self.global_uses.iter_mut().zip(callee.global_uses.iter()) {
*mine |= *other;
}

Ok(FunctionUniformity {
result: info.uniformity.clone(),
exit: if info.may_kill {
result: callee.uniformity.clone(),
exit: if callee.may_kill {
ExitFlags::MAY_KILL
} else {
ExitFlags::empty()
Expand Down