Add sample_bias and gather functions (#704)

* Add sample_bias function

* Update line numbers

* Add gather function

* Update spirv-tools

CI was failing on "Capability SampledRect is not allowed by Vulkan 1.1
specification (or requires extension)", except locally it was fine, and
I have more up to date spirv-tools than CI, so try bumping the CI
version to see if it's just an out-of-date spirv-val

* Fix gather() in vulkan

* Convert compiler valication into marker traits
This commit is contained in:
Ashley Hauck 2021-08-06 15:26:30 +02:00 committed by GitHub
parent bca7656c8c
commit a93d6e0f2a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 762 additions and 210 deletions

View File

@ -22,7 +22,7 @@ jobs:
target: aarch64-linux-android
runs-on: ${{ matrix.os }}
env:
spirv_tools_version: "20200928"
spirv_tools_version: "20210805"
RUSTUP_UNPACK_RAM: "26214400"
RUSTUP_IO_THREADS: "1"
steps:
@ -34,7 +34,7 @@ jobs:
run: |
sudo apt install libwayland-cursor0 libxkbcommon-dev libwayland-dev
mkdir "${HOME}/spirv-tools"
curl -fL https://storage.googleapis.com/spirv-tools/artifacts/prod/graphics_shader_compiler/spirv-tools/linux-clang-release/continuous/1409/20210313-175801/install.tgz | tar -xz -C "${HOME}/spirv-tools"
curl -fL https://storage.googleapis.com/spirv-tools/artifacts/prod/graphics_shader_compiler/spirv-tools/linux-clang-release/continuous/1530/20210805-040049/install.tgz | tar -xz -C "${HOME}/spirv-tools"
echo "${HOME}/spirv-tools/install/bin" >> $GITHUB_PATH
- if: ${{ runner.os == 'macOS' }}
name: Mac - Install spirv-tools
@ -47,7 +47,7 @@ jobs:
run: |
tmparch=$(mktemp)
mkdir "${HOME}/spirv-tools"
curl -fL -o "$tmparch" https://storage.googleapis.com/spirv-tools/artifacts/prod/graphics_shader_compiler/spirv-tools/windows-msvc-2017-release/continuous/1391/20210313-183536/install.zip
curl -fL -o "$tmparch" https://storage.googleapis.com/spirv-tools/artifacts/prod/graphics_shader_compiler/spirv-tools/windows-msvc-2017-release/continuous/1517/20210805-040116/install.zip
unzip "$tmparch" -d "${HOME}/spirv-tools"
- if: ${{ runner.os == 'Windows' }}
# Runs separately to add spir-v tools to Powershell's Path.

View File

@ -5,7 +5,7 @@ use crate::spirv_type::SpirvType;
use rspirv::dr;
use rspirv::grammar::{LogicalOperand, OperandKind, OperandQuantifier};
use rspirv::spirv::{
Dim, FPFastMathMode, FragmentShadingRate, FunctionControl, ImageOperands, KernelProfilingInfo,
FPFastMathMode, FragmentShadingRate, FunctionControl, ImageOperands, KernelProfilingInfo,
LoopControl, MemoryAccess, MemorySemantics, Op, RayFlags, SelectionControl, StorageClass, Word,
};
use rustc_ast::ast::{InlineAsmOptions, InlineAsmTemplatePiece};
@ -333,7 +333,6 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> {
return;
}
_ => {
self.validate_instruction(&inst);
self.emit()
.insert_into_block(dr::InsertPoint::End, inst)
.unwrap();
@ -1314,131 +1313,6 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> {
}
true
}
pub fn validate_instruction(&mut self, inst: &dr::Instruction) {
fn find_image_ty<'cx, 'tcx>(
builder: &mut Builder<'cx, 'tcx>,
inst: &dr::Instruction,
) -> Option<SpirvType> {
// Assumes the image parameter is the first operand
let image_obj = inst.operands[0].unwrap_id_ref();
let emit = builder.emit();
// Assumes the image's value definition is in the current block
let block = &emit.module_ref().functions[emit.selected_function().unwrap()].blocks
[emit.selected_block().unwrap()];
// Loop through the block to find the defining instruction
let defining_inst = match block
.instructions
.iter()
.find(|inst| inst.result_id == Some(image_obj))
{
Some(defining_inst) => defining_inst,
None => {
// Something has gone wrong. All the asm! blocks using these instructions
// should produce the image value in their own basic blocks (usually with
// an OpLoad), so there's probably some typo somewhere with an error
// already emitted, so just skip validation. If there truly is something
// bad going on, spirv-val will catch it.
return None;
}
};
match builder.lookup_type(defining_inst.result_type.unwrap()) {
SpirvType::SampledImage { image_type } => Some(builder.lookup_type(image_type)),
ty => Some(ty),
}
}
fn is_valid_query_size(ty: &SpirvType) -> bool {
match *ty {
SpirvType::Image {
dim,
multisampled,
sampled,
..
} => match dim {
Dim::Dim1D | Dim::Dim2D | Dim::Dim3D | Dim::DimCube => {
multisampled == 1 || sampled == 0 || sampled == 2
}
Dim::DimBuffer | Dim::DimRect => true,
Dim::DimSubpassData => false,
},
_ => true,
}
}
fn is_valid_query_size_lod(ty: &SpirvType) -> bool {
match *ty {
SpirvType::Image {
dim, multisampled, ..
} => match dim {
Dim::Dim1D | Dim::Dim2D | Dim::Dim3D | Dim::DimCube => multisampled == 0,
_ => false,
},
_ => true,
}
}
match inst.class.opcode {
Op::ImageQueryLevels | Op::ImageQueryLod => {
let image_ty = match find_image_ty(self, inst) {
Some(ty) => ty,
None => return,
};
if let SpirvType::Image { dim, .. } = image_ty {
match dim {
Dim::Dim1D | Dim::Dim2D | Dim::Dim3D | Dim::DimCube => {}
bad => self
.struct_err(&format!(
"Op{}'s image has a dimension of {:?}",
inst.class.opname, bad
))
.note("Allowed dimensions are 1D, 2D, 3D, and Cube")
.emit(),
}
}
// If the type isn't an image, something has gone wrong. The functions in image.rs
// shouldn't allow it, so the user is doing something weird. Let spirv-val handle
// the error later on.
}
Op::ImageQuerySize => {
let image_ty = match find_image_ty(self, inst) {
Some(ty) => ty,
None => return,
};
if !is_valid_query_size(&image_ty) {
let mut err =
self.struct_err("OpImageQuerySize is invalid for this image type");
err.note(
"allowed dimensions are 1D, 2D, 3D, Buffer, Rect, or Cube. \
if dimension is 1D, 2D, 3D, or Cube, it must have either \
multisampled be true, *or* sampled of Unknown or No",
);
if is_valid_query_size_lod(&image_ty) {
err.note("query_size_lod is valid for this image, did you mean to use it instead?");
}
err.emit();
}
}
Op::ImageQuerySizeLod => {
let image_ty = match find_image_ty(self, inst) {
Some(ty) => ty,
None => return,
};
if !is_valid_query_size_lod(&image_ty) {
let mut err =
self.struct_err("OpImageQuerySizeLod is invalid for this image type");
err.note("The image's dimension must be 1D, 2D, 3D, or Cube. Multisampled must be false.");
if is_valid_query_size(&image_ty) {
err.note(
"query_size is valid for this image, did you mean to use it instead?",
);
}
err.emit();
}
}
_ => {}
}
}
}
pub const IMAGE_OPERANDS: &[(&str, ImageOperands)] = &[

View File

@ -136,6 +136,42 @@ impl<
ACCESS_QUALIFIER,
>
{
// Note: #[inline] is needed because in vulkan, the component must be a constant expression.
/// Gathers the requested component from four texels.
#[crate::macros::gpu_only]
#[doc(alias = "OpImageGather")]
#[inline]
pub fn gather<F, V>(
&self,
sampler: Sampler,
coordinate: impl ImageCoordinate<F, DIM, ARRAYED>,
component: u32,
) -> V
where
Self: HasGather,
F: Float,
V: Vector<SampledType, 4>,
{
let mut result = V::default();
unsafe {
asm! {
"%typeSampledImage = OpTypeSampledImage typeof*{this}",
"%image = OpLoad _ {this}",
"%sampler = OpLoad _ {sampler}",
"%coordinate = OpLoad _ {coordinate}",
"%sampledImage = OpSampledImage %typeSampledImage %image %sampler",
"%result = OpImageGather typeof*{result} %sampledImage %coordinate {component}",
"OpStore {result} %result",
result = in(reg) &mut result,
this = in(reg) self,
sampler = in(reg) &sampler,
coordinate = in(reg) &coordinate,
component = in(reg) component,
}
}
result
}
/// Sample texels at `coord` from the image using `sampler`.
#[crate::macros::gpu_only]
pub fn sample<F, V>(&self, sampler: Sampler, coord: impl ImageCoordinate<F, DIM, ARRAYED>) -> V
@ -162,6 +198,39 @@ impl<
}
}
/// Sample texels at `coord` from the image using `sampler`, after adding the input bias to the
/// implicit level of detail.
#[crate::macros::gpu_only]
pub fn sample_bias<F, V>(
&self,
sampler: Sampler,
coord: impl ImageCoordinate<F, DIM, ARRAYED>,
bias: f32,
) -> V
where
F: Float,
V: Vector<SampledType, 4>,
{
unsafe {
let mut result = Default::default();
asm!(
"%typeSampledImage = OpTypeSampledImage typeof*{1}",
"%image = OpLoad typeof*{1} {1}",
"%sampler = OpLoad typeof*{2} {2}",
"%coord = OpLoad typeof*{3} {3}",
"%sampledImage = OpSampledImage %typeSampledImage %image %sampler",
"%result = OpImageSampleImplicitLod typeof*{0} %sampledImage %coord Bias {4}",
"OpStore {0} %result",
in(reg) &mut result,
in(reg) self,
in(reg) &sampler,
in(reg) &coord,
in(reg) bias,
);
result
}
}
/// Fetch a single texel with a sampler set at compile time
#[crate::macros::gpu_only]
#[doc(alias = "OpImageSampleExplicitLod")]
@ -358,9 +427,9 @@ impl<
ACCESS_QUALIFIER,
>
{
/// Fetch a single texel with a sampler set at compile time
/// Sample the image with a project coordinate
#[crate::macros::gpu_only]
#[doc(alias = "OpImageFetch")]
#[doc(alias = "OpImageSampleProjImplicitLod")]
pub fn sample_with_project_coordinate<F, V>(
&self,
sampler: Sampler,
@ -750,14 +819,12 @@ impl<
> Image<SampledType, DIM, DEPTH, ARRAYED, MULTISAMPLED, SAMPLED, FORMAT, ACCESS_QUALIFIER>
{
/// Query the number of mipmap levels.
///
/// Note: Const generics aren't able to reason about the constraints on this function (yet),
/// and so are enforced by the compiler. The constraints are:
///
/// The image's dimension must be 1D, 2D, 3D, or Cube.
#[crate::macros::gpu_only]
#[doc(alias = "OpImageQueryLevels")]
pub fn query_levels(&self) -> u32 {
pub fn query_levels(&self) -> u32
where
Self: HasQueryLevels,
{
let result: u32;
unsafe {
asm! {
@ -774,18 +841,16 @@ impl<
/// Coordinate using an implicit level of detail. The first component of the result contains
/// the mipmap array layer. The second component of the result contains the implicit level of
/// detail relative to the base level.
///
/// Note: Const generics aren't able to reason about the constraints on this function (yet),
/// and so are enforced by the compiler. The constraints are:
///
/// The image's dimension must be 1D, 2D, 3D, or Cube.
#[crate::macros::gpu_only]
#[doc(alias = "OpImageQueryLod")]
pub fn query_lod<V: Vector<f32, 2>>(
&self,
sampler: Sampler,
coord: impl ImageCoordinate<f32, DIM, { Arrayed::False }>,
) -> V {
) -> V
where
Self: HasQueryLevels,
{
// Note: Arrayed::False isn't a typo in the ImageCoordinate, the spec states:
// Coordinate must be a scalar or vector of floating-point type or integer type. It
// contains (u[, v] ... ) as needed by the definition of Sampled Image, **not including any
@ -811,15 +876,12 @@ impl<
}
/// Query the dimensions of Image, with no level of detail.
///
/// Note: Const generics aren't able to reason about the constraints on this function (yet),
/// and so are enforced by the compiler. The constraints are:
///
/// The image's dimension must be 1D, 2D, 3D, Buffer, Rect, or Cube. If dimension is 1D, 2D,
/// 3D, or Cube, it must have *either* multisampled be true, *or* sampled of Unknown or No.
#[crate::macros::gpu_only]
#[doc(alias = "OpImageQuerySize")]
pub fn query_size<Size: ImageCoordinate<u32, DIM, ARRAYED> + Default>(&self) -> Size {
pub fn query_size<Size: ImageCoordinate<u32, DIM, ARRAYED> + Default>(&self) -> Size
where
Self: HasQuerySize,
{
let mut result: Size = Default::default();
unsafe {
asm! {
@ -855,17 +917,15 @@ impl<
>
{
/// Query the dimensions of Image, with no level of detail.
///
/// Note: Const generics aren't able to reason about the constraints on this function (yet),
/// and so are enforced by the compiler. The constraints are:
///
/// The image's dimension must be 1D, 2D, 3D, or Cube. Multisampled must be false.
#[crate::macros::gpu_only]
#[doc(alias = "OpImageQuerySizeLod")]
pub fn query_size_lod<Size: ImageCoordinate<u32, DIM, ARRAYED> + Default>(
&self,
lod: u32,
) -> Size {
) -> Size
where
Self: HasQuerySizeLod,
{
let mut result: Size = Default::default();
unsafe {
asm! {
@ -974,3 +1034,527 @@ impl<
result
}
}
/// This is a marker trait to represent the constraints on `OpImageGather` too complex to be
/// represented by const generics. Specifically:
///
/// "Its `OpTypeImage` must have a Dim of 2D, Cube, or Rect. The MS operand of the underlying
/// `OpTypeImage` must be 0."
pub trait HasGather {}
impl<
SampledType: SampleType<FORMAT>,
const DEPTH: ImageDepth,
const FORMAT: ImageFormat,
const ARRAYED: Arrayed,
const SAMPLED: Sampled,
const ACCESS_QUALIFIER: Option<AccessQualifier>,
> HasGather
for Image<
SampledType,
{ Dimensionality::TwoD },
DEPTH,
ARRAYED,
{ Multisampled::False },
SAMPLED,
FORMAT,
ACCESS_QUALIFIER,
>
{
}
impl<
SampledType: SampleType<FORMAT>,
const DEPTH: ImageDepth,
const FORMAT: ImageFormat,
const ARRAYED: Arrayed,
const SAMPLED: Sampled,
const ACCESS_QUALIFIER: Option<AccessQualifier>,
> HasGather
for Image<
SampledType,
{ Dimensionality::Rect },
DEPTH,
ARRAYED,
{ Multisampled::False },
SAMPLED,
FORMAT,
ACCESS_QUALIFIER,
>
{
}
impl<
SampledType: SampleType<FORMAT>,
const DEPTH: ImageDepth,
const FORMAT: ImageFormat,
const ARRAYED: Arrayed,
const SAMPLED: Sampled,
const ACCESS_QUALIFIER: Option<AccessQualifier>,
> HasGather
for Image<
SampledType,
{ Dimensionality::Cube },
DEPTH,
ARRAYED,
{ Multisampled::False },
SAMPLED,
FORMAT,
ACCESS_QUALIFIER,
>
{
}
/// This is a marker trait to represent the constraints on `OpImageQueryLevels` and
/// `OpImageQueryLod` too complex to be represented by const generics. Specifically:
///
/// "Its Dim operand must be one of 1D, 2D, 3D, or Cube."
pub trait HasQueryLevels {}
impl<
SampledType: SampleType<FORMAT>,
const DEPTH: ImageDepth,
const FORMAT: ImageFormat,
const ARRAYED: Arrayed,
const MULTISAMPLED: Multisampled,
const SAMPLED: Sampled,
const ACCESS_QUALIFIER: Option<AccessQualifier>,
> HasQueryLevels
for Image<
SampledType,
{ Dimensionality::OneD },
DEPTH,
ARRAYED,
MULTISAMPLED,
SAMPLED,
FORMAT,
ACCESS_QUALIFIER,
>
{
}
impl<
SampledType: SampleType<FORMAT>,
const DEPTH: ImageDepth,
const FORMAT: ImageFormat,
const ARRAYED: Arrayed,
const MULTISAMPLED: Multisampled,
const SAMPLED: Sampled,
const ACCESS_QUALIFIER: Option<AccessQualifier>,
> HasQueryLevels
for Image<
SampledType,
{ Dimensionality::TwoD },
DEPTH,
ARRAYED,
MULTISAMPLED,
SAMPLED,
FORMAT,
ACCESS_QUALIFIER,
>
{
}
impl<
SampledType: SampleType<FORMAT>,
const DEPTH: ImageDepth,
const FORMAT: ImageFormat,
const ARRAYED: Arrayed,
const MULTISAMPLED: Multisampled,
const SAMPLED: Sampled,
const ACCESS_QUALIFIER: Option<AccessQualifier>,
> HasQueryLevels
for Image<
SampledType,
{ Dimensionality::ThreeD },
DEPTH,
ARRAYED,
MULTISAMPLED,
SAMPLED,
FORMAT,
ACCESS_QUALIFIER,
>
{
}
impl<
SampledType: SampleType<FORMAT>,
const DEPTH: ImageDepth,
const FORMAT: ImageFormat,
const ARRAYED: Arrayed,
const MULTISAMPLED: Multisampled,
const SAMPLED: Sampled,
const ACCESS_QUALIFIER: Option<AccessQualifier>,
> HasQueryLevels
for Image<
SampledType,
{ Dimensionality::Cube },
DEPTH,
ARRAYED,
MULTISAMPLED,
SAMPLED,
FORMAT,
ACCESS_QUALIFIER,
>
{
}
/// This is a marker trait to represent the constraints on `OpImageQuerySize` too complex to be
/// represented by const generics. Specifically:
///
/// "Its Dim operand must be 1D, 2D, 3D, Cube, Rect, or Buffer. Additionally, if its Dim is 1D, 2D,
/// 3D, or Cube, it must also have either an MS of 1 or a Sampled of 0 or 2."
pub trait HasQuerySize {}
impl<
SampledType: SampleType<FORMAT>,
const DEPTH: ImageDepth,
const FORMAT: ImageFormat,
const ARRAYED: Arrayed,
const SAMPLED: Sampled,
const ACCESS_QUALIFIER: Option<AccessQualifier>,
> HasQuerySize
for Image<
SampledType,
{ Dimensionality::OneD },
DEPTH,
ARRAYED,
{ Multisampled::True },
SAMPLED,
FORMAT,
ACCESS_QUALIFIER,
>
{
}
impl<
SampledType: SampleType<FORMAT>,
const DEPTH: ImageDepth,
const FORMAT: ImageFormat,
const ARRAYED: Arrayed,
const ACCESS_QUALIFIER: Option<AccessQualifier>,
> HasQuerySize
for Image<
SampledType,
{ Dimensionality::OneD },
DEPTH,
ARRAYED,
{ Multisampled::False },
{ Sampled::Unknown },
FORMAT,
ACCESS_QUALIFIER,
>
{
}
impl<
SampledType: SampleType<FORMAT>,
const DEPTH: ImageDepth,
const FORMAT: ImageFormat,
const ARRAYED: Arrayed,
const ACCESS_QUALIFIER: Option<AccessQualifier>,
> HasQuerySize
for Image<
SampledType,
{ Dimensionality::OneD },
DEPTH,
ARRAYED,
{ Multisampled::False },
{ Sampled::No },
FORMAT,
ACCESS_QUALIFIER,
>
{
}
impl<
SampledType: SampleType<FORMAT>,
const DEPTH: ImageDepth,
const FORMAT: ImageFormat,
const ARRAYED: Arrayed,
const SAMPLED: Sampled,
const ACCESS_QUALIFIER: Option<AccessQualifier>,
> HasQuerySize
for Image<
SampledType,
{ Dimensionality::TwoD },
DEPTH,
ARRAYED,
{ Multisampled::True },
SAMPLED,
FORMAT,
ACCESS_QUALIFIER,
>
{
}
impl<
SampledType: SampleType<FORMAT>,
const DEPTH: ImageDepth,
const FORMAT: ImageFormat,
const ARRAYED: Arrayed,
const ACCESS_QUALIFIER: Option<AccessQualifier>,
> HasQuerySize
for Image<
SampledType,
{ Dimensionality::TwoD },
DEPTH,
ARRAYED,
{ Multisampled::False },
{ Sampled::Unknown },
FORMAT,
ACCESS_QUALIFIER,
>
{
}
impl<
SampledType: SampleType<FORMAT>,
const DEPTH: ImageDepth,
const FORMAT: ImageFormat,
const ARRAYED: Arrayed,
const ACCESS_QUALIFIER: Option<AccessQualifier>,
> HasQuerySize
for Image<
SampledType,
{ Dimensionality::TwoD },
DEPTH,
ARRAYED,
{ Multisampled::False },
{ Sampled::No },
FORMAT,
ACCESS_QUALIFIER,
>
{
}
impl<
SampledType: SampleType<FORMAT>,
const DEPTH: ImageDepth,
const FORMAT: ImageFormat,
const ARRAYED: Arrayed,
const SAMPLED: Sampled,
const ACCESS_QUALIFIER: Option<AccessQualifier>,
> HasQuerySize
for Image<
SampledType,
{ Dimensionality::ThreeD },
DEPTH,
ARRAYED,
{ Multisampled::True },
SAMPLED,
FORMAT,
ACCESS_QUALIFIER,
>
{
}
impl<
SampledType: SampleType<FORMAT>,
const DEPTH: ImageDepth,
const FORMAT: ImageFormat,
const ARRAYED: Arrayed,
const ACCESS_QUALIFIER: Option<AccessQualifier>,
> HasQuerySize
for Image<
SampledType,
{ Dimensionality::ThreeD },
DEPTH,
ARRAYED,
{ Multisampled::False },
{ Sampled::Unknown },
FORMAT,
ACCESS_QUALIFIER,
>
{
}
impl<
SampledType: SampleType<FORMAT>,
const DEPTH: ImageDepth,
const FORMAT: ImageFormat,
const ARRAYED: Arrayed,
const ACCESS_QUALIFIER: Option<AccessQualifier>,
> HasQuerySize
for Image<
SampledType,
{ Dimensionality::ThreeD },
DEPTH,
ARRAYED,
{ Multisampled::False },
{ Sampled::No },
FORMAT,
ACCESS_QUALIFIER,
>
{
}
impl<
SampledType: SampleType<FORMAT>,
const DEPTH: ImageDepth,
const FORMAT: ImageFormat,
const ARRAYED: Arrayed,
const SAMPLED: Sampled,
const ACCESS_QUALIFIER: Option<AccessQualifier>,
> HasQuerySize
for Image<
SampledType,
{ Dimensionality::Cube },
DEPTH,
ARRAYED,
{ Multisampled::True },
SAMPLED,
FORMAT,
ACCESS_QUALIFIER,
>
{
}
impl<
SampledType: SampleType<FORMAT>,
const DEPTH: ImageDepth,
const FORMAT: ImageFormat,
const ARRAYED: Arrayed,
const ACCESS_QUALIFIER: Option<AccessQualifier>,
> HasQuerySize
for Image<
SampledType,
{ Dimensionality::Cube },
DEPTH,
ARRAYED,
{ Multisampled::False },
{ Sampled::Unknown },
FORMAT,
ACCESS_QUALIFIER,
>
{
}
impl<
SampledType: SampleType<FORMAT>,
const DEPTH: ImageDepth,
const FORMAT: ImageFormat,
const ARRAYED: Arrayed,
const ACCESS_QUALIFIER: Option<AccessQualifier>,
> HasQuerySize
for Image<
SampledType,
{ Dimensionality::Cube },
DEPTH,
ARRAYED,
{ Multisampled::False },
{ Sampled::No },
FORMAT,
ACCESS_QUALIFIER,
>
{
}
impl<
SampledType: SampleType<FORMAT>,
const DEPTH: ImageDepth,
const FORMAT: ImageFormat,
const ARRAYED: Arrayed,
const MULTISAMPLED: Multisampled,
const SAMPLED: Sampled,
const ACCESS_QUALIFIER: Option<AccessQualifier>,
> HasQuerySize
for Image<
SampledType,
{ Dimensionality::Rect },
DEPTH,
ARRAYED,
MULTISAMPLED,
SAMPLED,
FORMAT,
ACCESS_QUALIFIER,
>
{
}
impl<
SampledType: SampleType<FORMAT>,
const DEPTH: ImageDepth,
const FORMAT: ImageFormat,
const ARRAYED: Arrayed,
const MULTISAMPLED: Multisampled,
const SAMPLED: Sampled,
const ACCESS_QUALIFIER: Option<AccessQualifier>,
> HasQuerySize
for Image<
SampledType,
{ Dimensionality::Buffer },
DEPTH,
ARRAYED,
MULTISAMPLED,
SAMPLED,
FORMAT,
ACCESS_QUALIFIER,
>
{
}
/// This is a marker trait to represent the constraints on `OpImageQuerySizeLod` too complex to be
/// represented by const generics. Specifically:
///
/// "Its Dim operand must be one of 1D, 2D, 3D, or Cube, and its MS must be 0."
pub trait HasQuerySizeLod {}
impl<
SampledType: SampleType<FORMAT>,
const DEPTH: ImageDepth,
const FORMAT: ImageFormat,
const ARRAYED: Arrayed,
const SAMPLED: Sampled,
const ACCESS_QUALIFIER: Option<AccessQualifier>,
> HasQuerySizeLod
for Image<
SampledType,
{ Dimensionality::OneD },
DEPTH,
ARRAYED,
{ Multisampled::False },
SAMPLED,
FORMAT,
ACCESS_QUALIFIER,
>
{
}
impl<
SampledType: SampleType<FORMAT>,
const DEPTH: ImageDepth,
const FORMAT: ImageFormat,
const ARRAYED: Arrayed,
const SAMPLED: Sampled,
const ACCESS_QUALIFIER: Option<AccessQualifier>,
> HasQuerySizeLod
for Image<
SampledType,
{ Dimensionality::TwoD },
DEPTH,
ARRAYED,
{ Multisampled::False },
SAMPLED,
FORMAT,
ACCESS_QUALIFIER,
>
{
}
impl<
SampledType: SampleType<FORMAT>,
const DEPTH: ImageDepth,
const FORMAT: ImageFormat,
const ARRAYED: Arrayed,
const SAMPLED: Sampled,
const ACCESS_QUALIFIER: Option<AccessQualifier>,
> HasQuerySizeLod
for Image<
SampledType,
{ Dimensionality::ThreeD },
DEPTH,
ARRAYED,
{ Multisampled::False },
SAMPLED,
FORMAT,
ACCESS_QUALIFIER,
>
{
}
impl<
SampledType: SampleType<FORMAT>,
const DEPTH: ImageDepth,
const FORMAT: ImageFormat,
const ARRAYED: Arrayed,
const SAMPLED: Sampled,
const ACCESS_QUALIFIER: Option<AccessQualifier>,
> HasQuerySizeLod
for Image<
SampledType,
{ Dimensionality::Cube },
DEPTH,
ARRAYED,
{ Multisampled::False },
SAMPLED,
FORMAT,
ACCESS_QUALIFIER,
>
{
}

35
tests/ui/image/gather.rs Normal file
View File

@ -0,0 +1,35 @@
// Test `OpImageGather`
// build-pass
use spirv_std::{arch, Image, Sampler};
#[spirv(fragment)]
pub fn main(
#[spirv(descriptor_set = 0, binding = 0)] image2d: &Image!(2D, type=f32, sampled),
#[spirv(descriptor_set = 2, binding = 2)] cubemap: &Image!(cube, type=f32, sampled),
#[spirv(descriptor_set = 3, binding = 3)] sampler: &Sampler,
output: &mut glam::Vec4,
) {
let v2 = glam::Vec2::new(0.0, 1.0);
let v3 = glam::Vec3::new(0.0, 1.0, 0.5);
let r1: glam::Vec4 = image2d.gather(*sampler, v2, 0);
let r2: glam::Vec4 = cubemap.gather(*sampler, v3, 0);
*output = r1 + r2;
}
#[cfg(not(any(
target_env = "vulkan1.0",
target_env = "vulkan1.1",
target_env = "vulkan1.2"
)))]
#[spirv(fragment)]
pub fn main_rect(
#[spirv(descriptor_set = 1, binding = 1)] rect: &Image!(rect, type=f32, sampled),
#[spirv(descriptor_set = 3, binding = 3)] sampler: &Sampler,
output: &mut glam::Vec4,
) {
// Must be asm! and not -Ctarget-feature=+SampledRect due to being in cfg
unsafe { asm!("OpCapability SampledRect") };
let v2 = glam::Vec2::new(0.0, 1.0);
*output = rect.gather(*sampler, v2, 0);
}

View File

@ -0,0 +1,18 @@
// build-fail
// normalize-stderr-test "\S*/crates/spirv-std/src/" -> "$$SPIRV_STD_SRC/"
// compile-flags: -Ctarget-feature=+Sampled1D
use spirv_std::{arch, Image, Sampler};
#[spirv(fragment)]
pub fn main(
#[spirv(descriptor_set = 0, binding = 0)] image1d: &Image!(1D, type=f32, sampled),
#[spirv(descriptor_set = 2, binding = 1)] image3d: &Image!(3D, type=f32, sampled),
#[spirv(descriptor_set = 3, binding = 3)] sampler: &Sampler,
output: &mut glam::Vec4,
) {
let v3 = glam::Vec3::new(0.0, 1.0, 0.5);
let r1: glam::Vec4 = image1d.gather(*sampler, 0.0, 0);
let r2: glam::Vec4 = image3d.gather(*sampler, v3, 0);
*output = r1 + r2;
}

View File

@ -0,0 +1,25 @@
error[E0277]: the trait bound `Image<f32, OneD, spirv_std::image::ImageDepth::Unknown, spirv_std::image::Arrayed::False, spirv_std::image::Multisampled::False, Yes, spirv_std::image::ImageFormat::Unknown, Option::<AccessQualifier>::None>: HasGather` is not satisfied
--> $DIR/gather_err.rs:15:34
|
15 | let r1: glam::Vec4 = image1d.gather(*sampler, 0.0, 0);
| ^^^^^^ the trait `HasGather` is not implemented for `Image<f32, OneD, spirv_std::image::ImageDepth::Unknown, spirv_std::image::Arrayed::False, spirv_std::image::Multisampled::False, Yes, spirv_std::image::ImageFormat::Unknown, Option::<AccessQualifier>::None>`
|
= help: the following implementations were found:
<Image<SampledType, Cube, DEPTH, ARRAYED, spirv_std::image::Multisampled::False, SAMPLED, FORMAT, ACCESS_QUALIFIER> as HasGather>
<Image<SampledType, Rect, DEPTH, ARRAYED, spirv_std::image::Multisampled::False, SAMPLED, FORMAT, ACCESS_QUALIFIER> as HasGather>
<Image<SampledType, TwoD, DEPTH, ARRAYED, spirv_std::image::Multisampled::False, SAMPLED, FORMAT, ACCESS_QUALIFIER> as HasGather>
error[E0277]: the trait bound `Image<f32, ThreeD, spirv_std::image::ImageDepth::Unknown, spirv_std::image::Arrayed::False, spirv_std::image::Multisampled::False, Yes, spirv_std::image::ImageFormat::Unknown, Option::<AccessQualifier>::None>: HasGather` is not satisfied
--> $DIR/gather_err.rs:16:34
|
16 | let r2: glam::Vec4 = image3d.gather(*sampler, v3, 0);
| ^^^^^^ the trait `HasGather` is not implemented for `Image<f32, ThreeD, spirv_std::image::ImageDepth::Unknown, spirv_std::image::Arrayed::False, spirv_std::image::Multisampled::False, Yes, spirv_std::image::ImageFormat::Unknown, Option::<AccessQualifier>::None>`
|
= help: the following implementations were found:
<Image<SampledType, Cube, DEPTH, ARRAYED, spirv_std::image::Multisampled::False, SAMPLED, FORMAT, ACCESS_QUALIFIER> as HasGather>
<Image<SampledType, Rect, DEPTH, ARRAYED, spirv_std::image::Multisampled::False, SAMPLED, FORMAT, ACCESS_QUALIFIER> as HasGather>
<Image<SampledType, TwoD, DEPTH, ARRAYED, spirv_std::image::Multisampled::False, SAMPLED, FORMAT, ACCESS_QUALIFIER> as HasGather>
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0277`.

View File

@ -1,15 +1,15 @@
error: OpImageQueryLevels's image has a dimension of DimRect
--> $SPIRV_STD_SRC/image.rs:763:13
error[E0277]: the trait bound `Image<f32, Rect, spirv_std::image::ImageDepth::Unknown, spirv_std::image::Arrayed::False, spirv_std::image::Multisampled::False, Yes, spirv_std::image::ImageFormat::Unknown, Option::<AccessQualifier>::None>: HasQueryLevels` is not satisfied
--> $DIR/query_levels_err.rs:12:21
|
763 | / asm! {
764 | | "%image = OpLoad _ {this}",
765 | | "{result} = OpImageQueryLevels typeof{result} %image",
766 | | this = in(reg) self,
767 | | result = out(reg) result,
768 | | }
| |_____________^
12 | *output = image.query_levels();
| ^^^^^^^^^^^^ the trait `HasQueryLevels` is not implemented for `Image<f32, Rect, spirv_std::image::ImageDepth::Unknown, spirv_std::image::Arrayed::False, spirv_std::image::Multisampled::False, Yes, spirv_std::image::ImageFormat::Unknown, Option::<AccessQualifier>::None>`
|
= note: Allowed dimensions are 1D, 2D, 3D, and Cube
= help: the following implementations were found:
<Image<SampledType, Cube, DEPTH, ARRAYED, MULTISAMPLED, SAMPLED, FORMAT, ACCESS_QUALIFIER> as HasQueryLevels>
<Image<SampledType, OneD, DEPTH, ARRAYED, MULTISAMPLED, SAMPLED, FORMAT, ACCESS_QUALIFIER> as HasQueryLevels>
<Image<SampledType, ThreeD, DEPTH, ARRAYED, MULTISAMPLED, SAMPLED, FORMAT, ACCESS_QUALIFIER> as HasQueryLevels>
<Image<SampledType, TwoD, DEPTH, ARRAYED, MULTISAMPLED, SAMPLED, FORMAT, ACCESS_QUALIFIER> as HasQueryLevels>
error: aborting due to previous error
For more information about this error, try `rustc --explain E0277`.

View File

@ -1,16 +1,15 @@
error: OpImageQueryLod's image has a dimension of DimRect
--> $SPIRV_STD_SRC/image.rs:796:13
error[E0277]: the trait bound `Image<f32, Rect, spirv_std::image::ImageDepth::Unknown, spirv_std::image::Arrayed::False, spirv_std::image::Multisampled::False, Yes, spirv_std::image::ImageFormat::Unknown, Option::<AccessQualifier>::None>: HasQueryLevels` is not satisfied
--> $DIR/query_lod_err.rs:13:21
|
796 | / asm! {
797 | | "%typeSampledImage = OpTypeSampledImage typeof*{this}",
798 | | "%image = OpLoad _ {this}",
799 | | "%sampler = OpLoad _ {sampler}",
... |
807 | | coord = in(reg) &coord
808 | | }
| |_____________^
13 | *output = image.query_lod(*sampler, glam::Vec2::new(0.0, 1.0));
| ^^^^^^^^^ the trait `HasQueryLevels` is not implemented for `Image<f32, Rect, spirv_std::image::ImageDepth::Unknown, spirv_std::image::Arrayed::False, spirv_std::image::Multisampled::False, Yes, spirv_std::image::ImageFormat::Unknown, Option::<AccessQualifier>::None>`
|
= note: Allowed dimensions are 1D, 2D, 3D, and Cube
= help: the following implementations were found:
<Image<SampledType, Cube, DEPTH, ARRAYED, MULTISAMPLED, SAMPLED, FORMAT, ACCESS_QUALIFIER> as HasQueryLevels>
<Image<SampledType, OneD, DEPTH, ARRAYED, MULTISAMPLED, SAMPLED, FORMAT, ACCESS_QUALIFIER> as HasQueryLevels>
<Image<SampledType, ThreeD, DEPTH, ARRAYED, MULTISAMPLED, SAMPLED, FORMAT, ACCESS_QUALIFIER> as HasQueryLevels>
<Image<SampledType, TwoD, DEPTH, ARRAYED, MULTISAMPLED, SAMPLED, FORMAT, ACCESS_QUALIFIER> as HasQueryLevels>
error: aborting due to previous error
For more information about this error, try `rustc --explain E0277`.

View File

@ -1,17 +1,16 @@
error: OpImageQuerySize is invalid for this image type
--> $SPIRV_STD_SRC/image.rs:825:13
error[E0277]: the trait bound `Image<f32, TwoD, spirv_std::image::ImageDepth::Unknown, spirv_std::image::Arrayed::False, spirv_std::image::Multisampled::False, Yes, spirv_std::image::ImageFormat::Unknown, Option::<AccessQualifier>::None>: HasQuerySize` is not satisfied
--> $DIR/query_size_err.rs:12:21
|
825 | / asm! {
826 | | "%image = OpLoad _ {this}",
827 | | "%result = OpImageQuerySize typeof*{result} %image",
828 | | "OpStore {result} %result",
829 | | this = in(reg) self,
830 | | result = in(reg) &mut result,
831 | | }
| |_____________^
12 | *output = image.query_size();
| ^^^^^^^^^^ the trait `HasQuerySize` is not implemented for `Image<f32, TwoD, spirv_std::image::ImageDepth::Unknown, spirv_std::image::Arrayed::False, spirv_std::image::Multisampled::False, Yes, spirv_std::image::ImageFormat::Unknown, Option::<AccessQualifier>::None>`
|
= note: allowed dimensions are 1D, 2D, 3D, Buffer, Rect, or Cube. if dimension is 1D, 2D, 3D, or Cube, it must have either multisampled be true, *or* sampled of Unknown or No
= note: query_size_lod is valid for this image, did you mean to use it instead?
= help: the following implementations were found:
<Image<SampledType, Cube, DEPTH, ARRAYED, spirv_std::image::Multisampled::False, No, FORMAT, ACCESS_QUALIFIER> as HasQuerySize>
<Image<SampledType, Cube, DEPTH, ARRAYED, spirv_std::image::Multisampled::False, spirv_std::image::Sampled::Unknown, FORMAT, ACCESS_QUALIFIER> as HasQuerySize>
<Image<SampledType, Cube, DEPTH, ARRAYED, spirv_std::image::Multisampled::True, SAMPLED, FORMAT, ACCESS_QUALIFIER> as HasQuerySize>
<Image<SampledType, OneD, DEPTH, ARRAYED, spirv_std::image::Multisampled::False, No, FORMAT, ACCESS_QUALIFIER> as HasQuerySize>
and 10 others
error: aborting due to previous error
For more information about this error, try `rustc --explain E0277`.

View File

@ -1,17 +1,15 @@
error: OpImageQuerySizeLod is invalid for this image type
--> $SPIRV_STD_SRC/image.rs:871:13
error[E0277]: the trait bound `Image<f32, Rect, spirv_std::image::ImageDepth::Unknown, spirv_std::image::Arrayed::False, spirv_std::image::Multisampled::False, Yes, spirv_std::image::ImageFormat::Unknown, Option::<AccessQualifier>::None>: HasQuerySizeLod` is not satisfied
--> $DIR/query_size_lod_err.rs:12:21
|
871 | / asm! {
872 | | "%image = OpLoad _ {this}",
873 | | "%result = OpImageQuerySizeLod typeof*{result} %image {lod}",
874 | | "OpStore {result} %result",
... |
877 | | result = in(reg) &mut result,
878 | | }
| |_____________^
12 | *output = image.query_size_lod(0);
| ^^^^^^^^^^^^^^ the trait `HasQuerySizeLod` is not implemented for `Image<f32, Rect, spirv_std::image::ImageDepth::Unknown, spirv_std::image::Arrayed::False, spirv_std::image::Multisampled::False, Yes, spirv_std::image::ImageFormat::Unknown, Option::<AccessQualifier>::None>`
|
= note: The image's dimension must be 1D, 2D, 3D, or Cube. Multisampled must be false.
= note: query_size is valid for this image, did you mean to use it instead?
= help: the following implementations were found:
<Image<SampledType, Cube, DEPTH, ARRAYED, spirv_std::image::Multisampled::False, SAMPLED, FORMAT, ACCESS_QUALIFIER> as HasQuerySizeLod>
<Image<SampledType, OneD, DEPTH, ARRAYED, spirv_std::image::Multisampled::False, SAMPLED, FORMAT, ACCESS_QUALIFIER> as HasQuerySizeLod>
<Image<SampledType, ThreeD, DEPTH, ARRAYED, spirv_std::image::Multisampled::False, SAMPLED, FORMAT, ACCESS_QUALIFIER> as HasQuerySizeLod>
<Image<SampledType, TwoD, DEPTH, ARRAYED, spirv_std::image::Multisampled::False, SAMPLED, FORMAT, ACCESS_QUALIFIER> as HasQuerySizeLod>
error: aborting due to previous error
For more information about this error, try `rustc --explain E0277`.

View File

@ -0,0 +1,20 @@
// Test `OpImageSampleImplicitLod` Bias
// build-pass
use spirv_std::{arch, Image, Sampler};
#[spirv(fragment)]
pub fn main(
#[spirv(descriptor_set = 0, binding = 0)] image2d: &Image!(2D, type=f32, sampled),
#[spirv(descriptor_set = 1, binding = 1)] image2d_array: &Image!(2D, type=f32, arrayed, sampled),
#[spirv(descriptor_set = 2, binding = 2)] cubemap: &Image!(3D, type=f32, sampled),
#[spirv(descriptor_set = 3, binding = 3)] sampler: &Sampler,
output: &mut glam::Vec4,
) {
let v2 = glam::Vec2::new(0.0, 1.0);
let v3 = glam::Vec3::new(0.0, 1.0, 0.5);
let r1: glam::Vec4 = image2d.sample_bias(*sampler, v2, 0.0);
let r2: glam::Vec4 = image2d_array.sample_bias(*sampler, v3, 0.0);
let r3: glam::Vec4 = cubemap.sample_bias(*sampler, v3, 0.0);
*output = r1 + r2 + r3;
}