mirror of
https://github.com/EmbarkStudios/rust-gpu.git
synced 2024-11-25 00:04:11 +00:00
Added read_subpass for SubpassData images, and necessary attrs for it. (#643)
* Added read_subpass for SubpassData images, and necessary attrs for it. * Fix CI; test bless + rustfmt * Rename attachment_index => input_attachment_index. * Rustfmt * Fix clippy warning. * Review: check for cap rather than adding cap, fix error messages.
This commit is contained in:
parent
7fc445eb10
commit
985cbed9e4
@ -96,6 +96,7 @@ pub enum SpirvAttribute {
|
||||
Binding(u32),
|
||||
Flat,
|
||||
Invariant,
|
||||
InputAttachmentIndex(u32),
|
||||
|
||||
// `fn`/closure attributes:
|
||||
UnrollLoops,
|
||||
@ -130,6 +131,7 @@ pub struct AggregatedSpirvAttributes {
|
||||
pub binding: Option<Spanned<u32>>,
|
||||
pub flat: Option<Spanned<()>>,
|
||||
pub invariant: Option<Spanned<()>>,
|
||||
pub input_attachment_index: Option<Spanned<u32>>,
|
||||
|
||||
// `fn`/closure attributes:
|
||||
pub unroll_loops: Option<Spanned<()>>,
|
||||
@ -215,6 +217,12 @@ impl AggregatedSpirvAttributes {
|
||||
Binding(value) => try_insert(&mut self.binding, value, span, "#[spirv(binding)]"),
|
||||
Flat => try_insert(&mut self.flat, (), span, "#[spirv(flat)]"),
|
||||
Invariant => try_insert(&mut self.invariant, (), span, "#[spirv(invariant)]"),
|
||||
InputAttachmentIndex(value) => try_insert(
|
||||
&mut self.input_attachment_index,
|
||||
value,
|
||||
span,
|
||||
"#[spirv(attachment_index)]",
|
||||
),
|
||||
UnrollLoops => try_insert(&mut self.unroll_loops, (), span, "#[spirv(unroll_loops)]"),
|
||||
InternalBufferLoad => try_insert(
|
||||
&mut self.internal_buffer_load,
|
||||
@ -308,7 +316,8 @@ impl CheckSpirvAttrVisitor<'_> {
|
||||
| SpirvAttribute::DescriptorSet(_)
|
||||
| SpirvAttribute::Binding(_)
|
||||
| SpirvAttribute::Flat
|
||||
| SpirvAttribute::Invariant => match target {
|
||||
| SpirvAttribute::Invariant
|
||||
| SpirvAttribute::InputAttachmentIndex(_) => match target {
|
||||
Target::Param => {
|
||||
let parent_hir_id = self.tcx.hir().get_parent_node(hir_id);
|
||||
let parent_is_entry_point =
|
||||
|
@ -6,7 +6,9 @@ use crate::builder_spirv::{SpirvValue, SpirvValueExt};
|
||||
use crate::codegen_cx::BindlessDescriptorSets;
|
||||
use crate::spirv_type::SpirvType;
|
||||
use rspirv::dr::Operand;
|
||||
use rspirv::spirv::{Capability, Decoration, ExecutionModel, FunctionControl, StorageClass, Word};
|
||||
use rspirv::spirv::{
|
||||
Capability, Decoration, Dim, ExecutionModel, FunctionControl, StorageClass, Word,
|
||||
};
|
||||
use rustc_codegen_ssa::traits::{BaseTypeMethods, BuilderMethods};
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_hir as hir;
|
||||
@ -663,6 +665,46 @@ impl<'tcx> CodegenCx<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
let is_subpass_input = match self.lookup_type(value_spirv_type) {
|
||||
SpirvType::Image {
|
||||
dim: Dim::DimSubpassData,
|
||||
..
|
||||
} => true,
|
||||
SpirvType::RuntimeArray { element: elt, .. }
|
||||
| SpirvType::Array { element: elt, .. } => matches!(
|
||||
self.lookup_type(elt),
|
||||
SpirvType::Image {
|
||||
dim: Dim::DimSubpassData,
|
||||
..
|
||||
}
|
||||
),
|
||||
_ => false,
|
||||
};
|
||||
if let Some(attachment_index) = attrs.input_attachment_index {
|
||||
if is_subpass_input && self.builder.has_capability(Capability::InputAttachment) {
|
||||
self.emit_global().decorate(
|
||||
var,
|
||||
Decoration::InputAttachmentIndex,
|
||||
std::iter::once(Operand::LiteralInt32(attachment_index.value)),
|
||||
)
|
||||
} else if is_subpass_input {
|
||||
self.tcx
|
||||
.sess
|
||||
.span_err(hir_param.ty_span, "Missing capability InputAttachment")
|
||||
} else {
|
||||
self.tcx.sess.span_err(
|
||||
attachment_index.span,
|
||||
"#[spirv(input_attachment_index)] is only valid on Image types with dim = SubpassData"
|
||||
);
|
||||
}
|
||||
decoration_supersedes_location = true;
|
||||
} else if is_subpass_input {
|
||||
self.tcx.sess.span_err(
|
||||
hir_param.ty_span,
|
||||
"Image types with dim = SubpassData require #[spirv(input_attachment_index)] decoration",
|
||||
)
|
||||
}
|
||||
|
||||
// Assign locations from left to right, incrementing each storage class
|
||||
// individually.
|
||||
// TODO: Is this right for UniformConstant? Do they share locations with
|
||||
|
@ -23,6 +23,7 @@ pub struct Symbols {
|
||||
pub entry_point_name: Symbol,
|
||||
descriptor_set: Symbol,
|
||||
binding: Symbol,
|
||||
input_attachment_index: Symbol,
|
||||
image_type: Symbol,
|
||||
dim: Symbol,
|
||||
depth: Symbol,
|
||||
@ -380,6 +381,7 @@ impl Symbols {
|
||||
num_traits: Symbol::intern("num_traits"),
|
||||
descriptor_set: Symbol::intern("descriptor_set"),
|
||||
binding: Symbol::intern("binding"),
|
||||
input_attachment_index: Symbol::intern("input_attachment_index"),
|
||||
image_type: Symbol::intern("image_type"),
|
||||
dim: Symbol::intern("dim"),
|
||||
depth: Symbol::intern("depth"),
|
||||
@ -452,6 +454,8 @@ pub(crate) fn parse_attrs_for_checking<'a>(
|
||||
SpirvAttribute::DescriptorSet(parse_attr_int_value(arg)?)
|
||||
} else if arg.has_name(sym.binding) {
|
||||
SpirvAttribute::Binding(parse_attr_int_value(arg)?)
|
||||
} else if arg.has_name(sym.input_attachment_index) {
|
||||
SpirvAttribute::InputAttachmentIndex(parse_attr_int_value(arg)?)
|
||||
} else {
|
||||
let name = match arg.ident() {
|
||||
Some(i) => i,
|
||||
|
@ -5,7 +5,7 @@
|
||||
#[rustfmt::skip]
|
||||
mod params;
|
||||
|
||||
pub use self::params::{ImageCoordinate, SampleType};
|
||||
pub use self::params::{ImageCoordinate, ImageCoordinateSubpassData, SampleType};
|
||||
pub use crate::macros::Image;
|
||||
pub use spirv_types::image_params::{
|
||||
AccessQualifier, Arrayed, Dimensionality, ImageDepth, ImageFormat, Multisampled, Sampled,
|
||||
@ -659,6 +659,55 @@ impl<
|
||||
}
|
||||
}
|
||||
|
||||
impl<
|
||||
SampledType: SampleType<FORMAT>,
|
||||
const DEPTH: ImageDepth,
|
||||
const ARRAYED: Arrayed,
|
||||
const MULTISAMPLED: Multisampled,
|
||||
const FORMAT: ImageFormat,
|
||||
const ACCESS_QUALIFIER: Option<AccessQualifier>,
|
||||
>
|
||||
Image<
|
||||
SampledType,
|
||||
{ Dimensionality::SubpassData },
|
||||
DEPTH,
|
||||
ARRAYED,
|
||||
MULTISAMPLED,
|
||||
{ Sampled::No },
|
||||
FORMAT,
|
||||
ACCESS_QUALIFIER,
|
||||
>
|
||||
{
|
||||
/// Read a texel from subpass input attachment.
|
||||
/// Note: Vulkan only allows the read if the first two components of the coordinate are zero.
|
||||
#[crate::macros::gpu_only]
|
||||
#[doc(alias = "OpImageRead")]
|
||||
pub fn read_subpass<I, V, const N: usize>(
|
||||
&self,
|
||||
coordinate: impl ImageCoordinateSubpassData<I, ARRAYED>,
|
||||
) -> V
|
||||
where
|
||||
I: Integer,
|
||||
V: Vector<SampledType, N>,
|
||||
{
|
||||
let mut result = V::default();
|
||||
|
||||
unsafe {
|
||||
asm! {
|
||||
"%image = OpLoad _ {this}",
|
||||
"%coordinate = OpLoad _ {coordinate}",
|
||||
"%result = OpImageRead typeof*{result} %image %coordinate",
|
||||
"OpStore {result} %result",
|
||||
this = in(reg) self,
|
||||
coordinate = in(reg) &coordinate,
|
||||
result = in(reg) &mut result,
|
||||
}
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
impl<
|
||||
SampledType: SampleType<FORMAT>,
|
||||
const DIM: Dimensionality,
|
||||
|
@ -1,5 +1,5 @@
|
||||
use super::{Arrayed, Dimensionality, ImageFormat};
|
||||
use crate::{scalar::Scalar, vector::Vector};
|
||||
use crate::{scalar::Scalar, vector::Vector, integer::Integer};
|
||||
|
||||
/// Marker trait for arguments that accept single scalar values or vectors
|
||||
/// of scalars.
|
||||
@ -72,3 +72,8 @@ impl<V: Vector<S, 3>, S: Scalar> ImageCoordinate<S, { Dimensionality::TwoD }, {
|
||||
impl<V: Vector<S, 3>, S: Scalar> ImageCoordinate<S, { Dimensionality::Rect }, { Arrayed::True }> for V {}
|
||||
impl<V: Vector<S, 4>, S: Scalar> ImageCoordinate<S, { Dimensionality::Cube }, { Arrayed::True }> for V {}
|
||||
impl<V: Vector<S, 4>, S: Scalar> ImageCoordinate<S, { Dimensionality::ThreeD }, { Arrayed::True }> for V {}
|
||||
|
||||
/// Marker trait for arguments that are valid for a [`crate::image::Dimensionality::SubpassData`] image query.
|
||||
pub trait ImageCoordinateSubpassData<T, const ARRAYED: Arrayed> {}
|
||||
impl<V: Vector<I, 2>, I: Integer> ImageCoordinateSubpassData<I, { Arrayed::False }> for V {}
|
||||
impl<V: Vector<I, 3>, I: Integer> ImageCoordinateSubpassData<I, { Arrayed::True }> for V {}
|
||||
|
@ -1,12 +1,12 @@
|
||||
error: OpImageQueryLevels's image has a dimension of DimRect
|
||||
--> $SPIRV_STD_SRC/image.rs:684:13
|
||||
--> $SPIRV_STD_SRC/image.rs:733:13
|
||||
|
|
||||
684 | / asm! {
|
||||
685 | | "%image = OpLoad _ {this}",
|
||||
686 | | "{result} = OpImageQueryLevels typeof{result} %image",
|
||||
687 | | this = in(reg) self,
|
||||
688 | | result = out(reg) result,
|
||||
689 | | }
|
||||
733 | / asm! {
|
||||
734 | | "%image = OpLoad _ {this}",
|
||||
735 | | "{result} = OpImageQueryLevels typeof{result} %image",
|
||||
736 | | this = in(reg) self,
|
||||
737 | | result = out(reg) result,
|
||||
738 | | }
|
||||
| |_____________^
|
||||
|
|
||||
= note: Allowed dimensions are 1D, 2D, 3D, and Cube
|
||||
|
@ -1,13 +1,13 @@
|
||||
error: OpImageQueryLod's image has a dimension of DimRect
|
||||
--> $SPIRV_STD_SRC/image.rs:717:13
|
||||
--> $SPIRV_STD_SRC/image.rs:766:13
|
||||
|
|
||||
717 | / asm! {
|
||||
718 | | "%typeSampledImage = OpTypeSampledImage typeof*{this}",
|
||||
719 | | "%image = OpLoad _ {this}",
|
||||
720 | | "%sampler = OpLoad _ {sampler}",
|
||||
766 | / asm! {
|
||||
767 | | "%typeSampledImage = OpTypeSampledImage typeof*{this}",
|
||||
768 | | "%image = OpLoad _ {this}",
|
||||
769 | | "%sampler = OpLoad _ {sampler}",
|
||||
... |
|
||||
728 | | coord = in(reg) &coord
|
||||
729 | | }
|
||||
777 | | coord = in(reg) &coord
|
||||
778 | | }
|
||||
| |_____________^
|
||||
|
|
||||
= note: Allowed dimensions are 1D, 2D, 3D, and Cube
|
||||
|
@ -1,13 +1,13 @@
|
||||
error: OpImageQuerySize is invalid for this image type
|
||||
--> $SPIRV_STD_SRC/image.rs:746:13
|
||||
--> $SPIRV_STD_SRC/image.rs:795:13
|
||||
|
|
||||
746 | / asm! {
|
||||
747 | | "%image = OpLoad _ {this}",
|
||||
748 | | "%result = OpImageQuerySize typeof*{result} %image",
|
||||
749 | | "OpStore {result} %result",
|
||||
750 | | this = in(reg) self,
|
||||
751 | | result = in(reg) &mut result,
|
||||
752 | | }
|
||||
795 | / asm! {
|
||||
796 | | "%image = OpLoad _ {this}",
|
||||
797 | | "%result = OpImageQuerySize typeof*{result} %image",
|
||||
798 | | "OpStore {result} %result",
|
||||
799 | | this = in(reg) self,
|
||||
800 | | result = in(reg) &mut result,
|
||||
801 | | }
|
||||
| |_____________^
|
||||
|
|
||||
= 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
|
||||
|
@ -1,13 +1,13 @@
|
||||
error: OpImageQuerySizeLod is invalid for this image type
|
||||
--> $SPIRV_STD_SRC/image.rs:792:13
|
||||
--> $SPIRV_STD_SRC/image.rs:841:13
|
||||
|
|
||||
792 | / asm! {
|
||||
793 | | "%image = OpLoad _ {this}",
|
||||
794 | | "%result = OpImageQuerySizeLod typeof*{result} %image {lod}",
|
||||
795 | | "OpStore {result} %result",
|
||||
841 | / asm! {
|
||||
842 | | "%image = OpLoad _ {this}",
|
||||
843 | | "%result = OpImageQuerySizeLod typeof*{result} %image {lod}",
|
||||
844 | | "OpStore {result} %result",
|
||||
... |
|
||||
798 | | result = in(reg) &mut result,
|
||||
799 | | }
|
||||
847 | | result = in(reg) &mut result,
|
||||
848 | | }
|
||||
| |_____________^
|
||||
|
|
||||
= note: The image's dimension must be 1D, 2D, 3D, or Cube. Multisampled must be false.
|
||||
|
13
tests/ui/image/read_subpass.rs
Normal file
13
tests/ui/image/read_subpass.rs
Normal file
@ -0,0 +1,13 @@
|
||||
// build-pass
|
||||
// compile-flags: -C target-feature=+InputAttachment
|
||||
|
||||
use spirv_std::{arch, Image};
|
||||
|
||||
#[spirv(fragment)]
|
||||
pub fn main(
|
||||
#[spirv(descriptor_set = 0, binding = 0, input_attachment_index = 0)] image: &Image!(subpass, type=f32, sampled=false),
|
||||
output: &mut glam::Vec4,
|
||||
) {
|
||||
let coords = image.read_subpass(glam::IVec2::new(0, 0));
|
||||
*output = coords;
|
||||
}
|
Loading…
Reference in New Issue
Block a user