/// Options of a sampling operation. #[derive(Debug)] pubstruct SamplingOptions { /// Projection sampling: the division by W is expected to happen /// in the texture unit. pub project: bool, /// Depth comparison sampling with a reference value. pub compare: bool,
}
/// Return the texture coordinates separated from the array layer, /// and/or divided by the projection term. /// /// The Proj sampling ops expect an extra coordinate for the W. /// The arrayed (can't be Proj!) images expect an extra coordinate for the layer. fn extract_image_coordinates(
image_dim: crate::ImageDimension,
extra_coordinate: ExtraCoordinate,
base: Handle<crate::Expression>,
coordinate_ty: Handle<crate::Type>,
ctx: &mutsuper::BlockContext,
) -> (Handle<crate::Expression>, Option<Handle<crate::Expression>>) { let (given_size, kind) = match ctx.module.types[coordinate_ty].inner { crate::TypeInner::Scalar(Scalar { kind, .. }) => (None, kind), crate::TypeInner::Vector {
size,
scalar: Scalar { kind, .. },
} => (Some(size), kind), ref other => unreachable!("Unexpected texture coordinate {:?}", other),
};
let required_size = image_dim.required_coordinate_size(); let required_ty = required_size.map(|size| {
ctx.module
.types
.get(&crate::Type {
name: None,
inner: crate::TypeInner::Vector {
size,
scalar: Scalar { kind, width: 4 },
},
})
.expect("Required coordinate type should have been set up by `parse_type_image`!")
}); let extra_expr = crate::Expression::AccessIndex {
base,
index: required_size.map_or(1, |size| size as u32),
};
let base_span = ctx.expressions.get_span(base);
match extra_coordinate {
ExtraCoordinate::ArrayLayer => { let extracted = match required_size {
None => ctx
.expressions
.append(crate::Expression::AccessIndex { base, index: 0 }, base_span),
Some(size) => { letmut components = Vec::with_capacity(size as usize); for index in0..size as u32 { let comp = ctx
.expressions
.append(crate::Expression::AccessIndex { base, index }, base_span);
components.push(comp);
}
ctx.expressions.append( crate::Expression::Compose {
ty: required_ty.unwrap(),
components,
},
base_span,
)
}
}; let array_index_f32 = ctx.expressions.append(extra_expr, base_span); let array_index = ctx.expressions.append( crate::Expression::As {
kind: crate::ScalarKind::Sint,
expr: array_index_f32,
convert: Some(4),
},
base_span,
);
(extracted, Some(array_index))
}
ExtraCoordinate::Projection => { let projection = ctx.expressions.append(extra_expr, base_span); let divided = match required_size {
None => { let temp = ctx
.expressions
.append(crate::Expression::AccessIndex { base, index: 0 }, base_span);
ctx.expressions.append( crate::Expression::Binary {
op: crate::BinaryOperator::Divide,
left: temp,
right: projection,
},
base_span,
)
}
Some(size) => { letmut components = Vec::with_capacity(size as usize); for index in0..size as u32 { let temp = ctx
.expressions
.append(crate::Expression::AccessIndex { base, index }, base_span); let comp = ctx.expressions.append( crate::Expression::Binary {
op: crate::BinaryOperator::Divide,
left: temp,
right: projection,
},
base_span,
);
components.push(comp);
}
ctx.expressions.append( crate::Expression::Compose {
ty: required_ty.unwrap(),
components,
},
base_span,
)
}
};
(divided, None)
}
ExtraCoordinate::Garbage if given_size == required_size => (base, None),
ExtraCoordinate::Garbage => { usecrate::SwizzleComponent as Sc; let cut_expr = match required_size {
None => crate::Expression::AccessIndex { base, index: 0 },
Some(size) => crate::Expression::Swizzle {
size,
vector: base,
pattern: [Sc::X, Sc::Y, Sc::Z, Sc::W],
},
};
(ctx.expressions.append(cut_expr, base_span), None)
}
}
}
letmut sample = None; letmut level = None; while image_ops != 0 { let bit = 1 << image_ops.trailing_zeros(); match spirv::ImageOperands::from_bits_truncate(bit) {
spirv::ImageOperands::LOD => { let lod_expr = self.next()?; let lod_lexp = self.lookup_expression.lookup(lod_expr)?; let lod_handle = self.get_expr_handle(lod_expr, lod_lexp, ctx, emitter, block, body_idx);
level = Some(lod_handle);
words_left -= 1;
}
spirv::ImageOperands::SAMPLE => { let sample_expr = self.next()?; let sample_handle = self.lookup_expression.lookup(sample_expr)?.handle;
sample = Some(sample_handle);
words_left -= 1;
}
other => {
log::warn!("Unknown image load op {:?}", other); for _ in0..words_left { self.next()?;
} break;
}
}
image_ops ^= bit;
}
// No need to call get_expr_handle here since only globals/arguments are // allowed as images and they are always in the root scope let image_lexp = self.lookup_expression.lookup(image_id)?; let image_ty = ctx.get_image_expr_ty(image_lexp.handle)?;
let coord_lexp = self.lookup_expression.lookup(coordinate_id)?; let coord_handle = self.get_expr_handle(coordinate_id, coord_lexp, ctx, emitter, block, body_idx); let coord_type_handle = self.lookup_type.lookup(coord_lexp.type_id)?.handle; let (coordinate, array_index, is_depth) = match ctx.module.types[image_ty].inner { crate::TypeInner::Image {
dim,
arrayed,
class,
} => { let (coord, array_index) = extract_image_coordinates(
dim, if arrayed {
ExtraCoordinate::ArrayLayer
} else {
ExtraCoordinate::Garbage
},
coord_handle,
coord_type_handle,
ctx,
);
(coord, array_index, class.is_depth())
}
_ => return Err(Error::InvalidImage(image_ty)),
};
let image_load_expr = crate::Expression::ImageLoad {
image: image_lexp.handle,
coordinate,
array_index,
sample,
level,
}; let image_load_handle = ctx
.expressions
.append(image_load_expr, self.span_from_with_op(start));
let handle = if is_depth { let result_ty = self.lookup_type.lookup(result_type_id)?; // The return type of `OpImageRead` can be a scalar or vector. match ctx.module.types[result_ty.handle].inner { crate::TypeInner::Vector { size, .. } => { let splat_expr = crate::Expression::Splat {
size,
value: image_load_handle,
};
ctx.expressions
.append(splat_expr, self.span_from_with_op(start))
}
_ => image_load_handle,
}
} else {
image_load_handle
};
pub(super) fn parse_image_query_size(
&mutself,
at_level: bool,
ctx: &mutsuper::BlockContext,
emitter: &mutcrate::proc::Emitter,
block: &mutcrate::Block,
block_id: spirv::Word,
body_idx: usize,
) -> Result<(), Error> { let start = self.data_offset; let result_type_id = self.next()?; let result_id = self.next()?; let image_id = self.next()?; let level = if at_level { let level_id = self.next()?; let level_lexp = self.lookup_expression.lookup(level_id)?;
Some(self.get_expr_handle(level_id, level_lexp, ctx, emitter, block, body_idx))
} else {
None
};
// No need to call get_expr_handle here since only globals/arguments are // allowed as images and they are always in the root scope //TODO: handle arrays and cubes let image_lexp = self.lookup_expression.lookup(image_id)?;
let result_type_handle = self.lookup_type.lookup(result_type_id)?.handle; let maybe_scalar_kind = ctx.module.types[result_type_handle].inner.scalar_kind();
pub(super) fn parse_image_query_other(
&mutself,
query: crate::ImageQuery,
ctx: &mutsuper::BlockContext,
block_id: spirv::Word,
) -> Result<(), Error> { let start = self.data_offset; let result_type_id = self.next()?; let result_id = self.next()?; let image_id = self.next()?;
// No need to call get_expr_handle here since only globals/arguments are // allowed as images and they are always in the root scope let image_lexp = self.lookup_expression.lookup(image_id)?.clone();
let expr = crate::Expression::ImageQuery {
image: image_lexp.handle,
query,
};
let result_type_handle = self.lookup_type.lookup(result_type_id)?.handle; let maybe_scalar_kind = ctx.module.types[result_type_handle].inner.scalar_kind();
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.