mirror of
https://github.com/gfx-rs/wgpu.git
synced 2024-11-22 14:55:05 +00:00
Merge #1047
1047: Update bind group layout API to match upstream r=cwfitzgerald a=kvark **Connections** Follows https://github.com/gpuweb/gpuweb/pull/1076, https://github.com/gpuweb/gpuweb/pull/1223 (https://github.com/gpuweb/gpuweb/issues/1164), https://github.com/gpuweb/gpuweb/pull/1255, and https://github.com/gpuweb/gpuweb/pull/1256 **Description** Aligns our API closer to the latest changes in WebGPU upstream. We technically don't have to do this, but I believe in the end it would be best if our API gets close to upstream. Note: this is a sensitive change for the users, everybody will get their code broken. So please take a look at the API and see if something is missing or needs improvement, so that we don't have to go through the changes again afterwards. **Testing** Doesn't really need testing. Partially covered by the existing playtest. Co-authored-by: Dzmitry Malyshau <kvarkus@gmail.com>
This commit is contained in:
commit
67e652f471
@ -34,11 +34,9 @@
|
||||
(
|
||||
binding: 0,
|
||||
visibility: (bits: 0x3),
|
||||
ty: UniformBuffer(
|
||||
dynamic: false,
|
||||
min_binding_size: None,
|
||||
ty: Buffer(
|
||||
ty: Uniform,
|
||||
),
|
||||
count: None,
|
||||
),
|
||||
],
|
||||
)),
|
||||
|
@ -193,22 +193,30 @@ impl BindingTypeMaxCountValidator {
|
||||
pub(crate) fn add_binding(&mut self, binding: &wgt::BindGroupLayoutEntry) {
|
||||
let count = binding.count.map_or(1, |count| count.get());
|
||||
match binding.ty {
|
||||
wgt::BindingType::UniformBuffer { dynamic, .. } => {
|
||||
wgt::BindingType::Buffer {
|
||||
ty: wgt::BufferBindingType::Uniform,
|
||||
has_dynamic_offset,
|
||||
..
|
||||
} => {
|
||||
self.uniform_buffers.add(binding.visibility, count);
|
||||
if dynamic {
|
||||
if has_dynamic_offset {
|
||||
self.dynamic_uniform_buffers += count;
|
||||
}
|
||||
}
|
||||
wgt::BindingType::StorageBuffer { dynamic, .. } => {
|
||||
wgt::BindingType::Buffer {
|
||||
ty: wgt::BufferBindingType::Storage { .. },
|
||||
has_dynamic_offset,
|
||||
..
|
||||
} => {
|
||||
self.storage_buffers.add(binding.visibility, count);
|
||||
if dynamic {
|
||||
if has_dynamic_offset {
|
||||
self.dynamic_storage_buffers += count;
|
||||
}
|
||||
}
|
||||
wgt::BindingType::Sampler { .. } => {
|
||||
self.samplers.add(binding.visibility, count);
|
||||
}
|
||||
wgt::BindingType::SampledTexture { .. } => {
|
||||
wgt::BindingType::Texture { .. } => {
|
||||
self.sampled_textures.add(binding.visibility, count);
|
||||
}
|
||||
wgt::BindingType::StorageTexture { .. } => {
|
||||
|
@ -84,36 +84,33 @@ pub fn map_binding_type(binding: &wgt::BindGroupLayoutEntry) -> hal::pso::Descri
|
||||
use hal::pso;
|
||||
use wgt::BindingType as Bt;
|
||||
match binding.ty {
|
||||
Bt::UniformBuffer {
|
||||
dynamic,
|
||||
Bt::Buffer {
|
||||
ty,
|
||||
has_dynamic_offset,
|
||||
min_binding_size: _,
|
||||
} => pso::DescriptorType::Buffer {
|
||||
ty: pso::BufferDescriptorType::Uniform,
|
||||
format: pso::BufferDescriptorFormat::Structured {
|
||||
dynamic_offset: dynamic,
|
||||
},
|
||||
},
|
||||
Bt::StorageBuffer {
|
||||
readonly,
|
||||
dynamic,
|
||||
min_binding_size: _,
|
||||
} => pso::DescriptorType::Buffer {
|
||||
ty: pso::BufferDescriptorType::Storage {
|
||||
read_only: readonly,
|
||||
ty: match ty {
|
||||
wgt::BufferBindingType::Uniform => pso::BufferDescriptorType::Uniform,
|
||||
wgt::BufferBindingType::Storage { read_only } => {
|
||||
pso::BufferDescriptorType::Storage { read_only }
|
||||
}
|
||||
},
|
||||
format: pso::BufferDescriptorFormat::Structured {
|
||||
dynamic_offset: dynamic,
|
||||
dynamic_offset: has_dynamic_offset,
|
||||
},
|
||||
},
|
||||
Bt::Sampler { comparison: _ } => pso::DescriptorType::Sampler,
|
||||
Bt::SampledTexture { .. } => pso::DescriptorType::Image {
|
||||
Bt::Sampler { .. } => pso::DescriptorType::Sampler,
|
||||
Bt::Texture { .. } => pso::DescriptorType::Image {
|
||||
ty: pso::ImageDescriptorType::Sampled {
|
||||
with_sampler: false,
|
||||
},
|
||||
},
|
||||
Bt::StorageTexture { readonly, .. } => pso::DescriptorType::Image {
|
||||
Bt::StorageTexture { access, .. } => pso::DescriptorType::Image {
|
||||
ty: pso::ImageDescriptorType::Storage {
|
||||
read_only: readonly,
|
||||
read_only: match access {
|
||||
wgt::StorageTextureAccess::ReadOnly => true,
|
||||
_ => false,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -989,7 +989,7 @@ impl<B: GfxBackend> Device<B> {
|
||||
for binding in entry_map.values() {
|
||||
if binding.count.is_some() {
|
||||
match binding.ty {
|
||||
wgt::BindingType::SampledTexture { .. } => {
|
||||
wgt::BindingType::Texture { .. } => {
|
||||
if !self
|
||||
.features
|
||||
.contains(wgt::Features::SAMPLED_TEXTURE_BINDING_ARRAY)
|
||||
@ -1100,30 +1100,12 @@ impl<B: GfxBackend> Device<B> {
|
||||
.ok_or(Error::MissingBindingDeclaration(binding))?;
|
||||
let descriptors: SmallVec<[_; 1]> = match entry.resource {
|
||||
Br::Buffer(ref bb) => {
|
||||
let (pub_usage, internal_use, min_size, dynamic) = match decl.ty {
|
||||
wgt::BindingType::UniformBuffer {
|
||||
dynamic,
|
||||
let (binding_ty, dynamic, min_size) = match decl.ty {
|
||||
wgt::BindingType::Buffer {
|
||||
ty,
|
||||
has_dynamic_offset,
|
||||
min_binding_size,
|
||||
} => (
|
||||
wgt::BufferUsage::UNIFORM,
|
||||
resource::BufferUse::UNIFORM,
|
||||
min_binding_size,
|
||||
dynamic,
|
||||
),
|
||||
wgt::BindingType::StorageBuffer {
|
||||
dynamic,
|
||||
min_binding_size,
|
||||
readonly,
|
||||
} => (
|
||||
wgt::BufferUsage::STORAGE,
|
||||
if readonly {
|
||||
resource::BufferUse::STORAGE_LOAD
|
||||
} else {
|
||||
resource::BufferUse::STORAGE_STORE
|
||||
},
|
||||
min_binding_size,
|
||||
dynamic,
|
||||
),
|
||||
} => (ty, has_dynamic_offset, min_binding_size),
|
||||
_ => {
|
||||
return Err(Error::WrongBindingType {
|
||||
binding,
|
||||
@ -1132,6 +1114,19 @@ impl<B: GfxBackend> Device<B> {
|
||||
})
|
||||
}
|
||||
};
|
||||
let (pub_usage, internal_use) = match binding_ty {
|
||||
wgt::BufferBindingType::Uniform => {
|
||||
(wgt::BufferUsage::UNIFORM, resource::BufferUse::UNIFORM)
|
||||
}
|
||||
wgt::BufferBindingType::Storage { read_only } => (
|
||||
wgt::BufferUsage::STORAGE,
|
||||
if read_only {
|
||||
resource::BufferUse::STORAGE_LOAD
|
||||
} else {
|
||||
resource::BufferUse::STORAGE_STORE
|
||||
},
|
||||
),
|
||||
};
|
||||
|
||||
if bb.offset % wgt::BIND_BUFFER_ALIGNMENT != 0 {
|
||||
return Err(Error::UnalignedBufferOffset(bb.offset));
|
||||
@ -1161,7 +1156,7 @@ impl<B: GfxBackend> Device<B> {
|
||||
None => (buffer.size - bb.offset, buffer.size),
|
||||
};
|
||||
|
||||
if pub_usage == wgt::BufferUsage::UNIFORM
|
||||
if binding_ty == wgt::BufferBindingType::Uniform
|
||||
&& (self.limits.max_uniform_buffer_binding_size as u64) < bind_size
|
||||
{
|
||||
return Err(Error::UniformBufferRangeTooLarge);
|
||||
@ -1192,7 +1187,10 @@ impl<B: GfxBackend> Device<B> {
|
||||
}
|
||||
Br::Sampler(id) => {
|
||||
match decl.ty {
|
||||
wgt::BindingType::Sampler { comparison } => {
|
||||
wgt::BindingType::Sampler {
|
||||
filtering: _,
|
||||
comparison,
|
||||
} => {
|
||||
let sampler = used
|
||||
.samplers
|
||||
.use_extend(&*sampler_guard, id, (), ())
|
||||
@ -1220,15 +1218,18 @@ impl<B: GfxBackend> Device<B> {
|
||||
.use_extend(&*texture_view_guard, id, (), ())
|
||||
.map_err(|_| Error::InvalidTextureView(id))?;
|
||||
let (pub_usage, internal_use) = match decl.ty {
|
||||
wgt::BindingType::SampledTexture { .. } => {
|
||||
wgt::BindingType::Texture { .. } => {
|
||||
(wgt::TextureUsage::SAMPLED, resource::TextureUse::SAMPLED)
|
||||
}
|
||||
wgt::BindingType::StorageTexture { readonly, .. } => (
|
||||
wgt::BindingType::StorageTexture { access, .. } => (
|
||||
wgt::TextureUsage::STORAGE,
|
||||
if readonly {
|
||||
resource::TextureUse::STORAGE_LOAD
|
||||
} else {
|
||||
resource::TextureUse::STORAGE_STORE
|
||||
match access {
|
||||
wgt::StorageTextureAccess::ReadOnly => {
|
||||
resource::TextureUse::STORAGE_LOAD
|
||||
}
|
||||
wgt::StorageTextureAccess::WriteOnly => {
|
||||
resource::TextureUse::STORAGE_STORE
|
||||
}
|
||||
},
|
||||
),
|
||||
_ => return Err(Error::WrongBindingType {
|
||||
@ -1290,7 +1291,7 @@ impl<B: GfxBackend> Device<B> {
|
||||
}
|
||||
|
||||
let (pub_usage, internal_use) = match decl.ty {
|
||||
wgt::BindingType::SampledTexture { .. } => {
|
||||
wgt::BindingType::Texture { .. } => {
|
||||
(wgt::TextureUsage::SAMPLED, resource::TextureUse::SAMPLED)
|
||||
}
|
||||
_ => {
|
||||
|
@ -240,19 +240,17 @@ fn check_binding_use(
|
||||
match module.types[var.ty].inner {
|
||||
naga::TypeInner::Struct { ref members } => {
|
||||
let (allowed_usage, min_size) = match entry.ty {
|
||||
BindingType::UniformBuffer {
|
||||
dynamic: _,
|
||||
BindingType::Buffer {
|
||||
ty,
|
||||
has_dynamic_offset: _,
|
||||
min_binding_size,
|
||||
} => (naga::GlobalUse::LOAD, min_binding_size),
|
||||
BindingType::StorageBuffer {
|
||||
dynamic: _,
|
||||
min_binding_size,
|
||||
readonly,
|
||||
} => {
|
||||
let global_use = if readonly {
|
||||
naga::GlobalUse::LOAD
|
||||
} else {
|
||||
naga::GlobalUse::all()
|
||||
let global_use = match ty {
|
||||
wgt::BufferBindingType::Uniform
|
||||
| wgt::BufferBindingType::Storage { read_only: true } => {
|
||||
naga::GlobalUse::LOAD
|
||||
}
|
||||
wgt::BufferBindingType::Storage { read_only: _ } => naga::GlobalUse::all(),
|
||||
};
|
||||
(global_use, min_binding_size)
|
||||
}
|
||||
@ -271,7 +269,10 @@ fn check_binding_use(
|
||||
Ok(allowed_usage)
|
||||
}
|
||||
naga::TypeInner::Sampler { comparison } => match entry.ty {
|
||||
BindingType::Sampler { comparison: cmp } => {
|
||||
BindingType::Sampler {
|
||||
filtering: _,
|
||||
comparison: cmp,
|
||||
} => {
|
||||
if cmp == comparison {
|
||||
Ok(naga::GlobalUse::LOAD)
|
||||
} else {
|
||||
@ -286,8 +287,8 @@ fn check_binding_use(
|
||||
class,
|
||||
} => {
|
||||
let view_dimension = match entry.ty {
|
||||
BindingType::SampledTexture { dimension, .. }
|
||||
| BindingType::StorageTexture { dimension, .. } => dimension,
|
||||
BindingType::Texture { view_dimension, .. }
|
||||
| BindingType::StorageTexture { view_dimension, .. } => view_dimension,
|
||||
_ => {
|
||||
return Err(BindingError::WrongTextureViewDimension {
|
||||
dim,
|
||||
@ -321,40 +322,38 @@ fn check_binding_use(
|
||||
}
|
||||
}
|
||||
let (expected_class, usage) = match entry.ty {
|
||||
BindingType::SampledTexture {
|
||||
dimension: _,
|
||||
component_type,
|
||||
multisampled,
|
||||
BindingType::Texture {
|
||||
sample_type,
|
||||
view_dimension: _,
|
||||
multisampled: multi,
|
||||
} => {
|
||||
let (kind, comparison) = match component_type {
|
||||
wgt::TextureComponentType::Float => (naga::ScalarKind::Float, false),
|
||||
wgt::TextureComponentType::Sint => (naga::ScalarKind::Sint, false),
|
||||
wgt::TextureComponentType::Uint => (naga::ScalarKind::Uint, false),
|
||||
wgt::TextureComponentType::DepthComparison => {
|
||||
(naga::ScalarKind::Float, true)
|
||||
}
|
||||
};
|
||||
let class = if comparison {
|
||||
naga::ImageClass::Depth
|
||||
} else {
|
||||
naga::ImageClass::Sampled {
|
||||
kind,
|
||||
multi: multisampled,
|
||||
}
|
||||
let class = match sample_type {
|
||||
wgt::TextureSampleType::Float { .. } => naga::ImageClass::Sampled {
|
||||
kind: naga::ScalarKind::Float,
|
||||
multi,
|
||||
},
|
||||
wgt::TextureSampleType::Sint => naga::ImageClass::Sampled {
|
||||
kind: naga::ScalarKind::Sint,
|
||||
multi,
|
||||
},
|
||||
wgt::TextureSampleType::Uint => naga::ImageClass::Sampled {
|
||||
kind: naga::ScalarKind::Uint,
|
||||
multi,
|
||||
},
|
||||
wgt::TextureSampleType::Depth => naga::ImageClass::Depth,
|
||||
};
|
||||
(class, naga::GlobalUse::LOAD)
|
||||
}
|
||||
BindingType::StorageTexture {
|
||||
readonly,
|
||||
access,
|
||||
format,
|
||||
dimension: _,
|
||||
view_dimension: _,
|
||||
} => {
|
||||
let naga_format = map_storage_format_to_naga(format)
|
||||
.ok_or(BindingError::BadStorageFormat(format))?;
|
||||
let usage = if readonly {
|
||||
naga::GlobalUse::LOAD
|
||||
} else {
|
||||
naga::GlobalUse::STORE
|
||||
let usage = match access {
|
||||
wgt::StorageTextureAccess::ReadOnly => naga::GlobalUse::LOAD,
|
||||
wgt::StorageTextureAccess::WriteOnly => naga::GlobalUse::STORE,
|
||||
};
|
||||
(naga::ImageClass::Storage(naga_format), usage)
|
||||
}
|
||||
@ -780,31 +779,37 @@ fn derive_binding_type(
|
||||
let ty = &module.types[var.ty];
|
||||
Ok(match ty.inner {
|
||||
naga::TypeInner::Struct { ref members } => {
|
||||
let dynamic = false;
|
||||
let has_dynamic_offset = false;
|
||||
let mut actual_size = 0;
|
||||
for (i, member) in members.iter().enumerate() {
|
||||
actual_size += get_aligned_type_size(module, member.ty, i + 1 == members.len());
|
||||
}
|
||||
match var.class {
|
||||
naga::StorageClass::Uniform => BindingType::UniformBuffer {
|
||||
dynamic,
|
||||
naga::StorageClass::Uniform => BindingType::Buffer {
|
||||
ty: wgt::BufferBindingType::Uniform,
|
||||
has_dynamic_offset,
|
||||
min_binding_size: wgt::BufferSize::new(actual_size),
|
||||
},
|
||||
naga::StorageClass::Storage => BindingType::StorageBuffer {
|
||||
dynamic,
|
||||
naga::StorageClass::Storage => BindingType::Buffer {
|
||||
ty: wgt::BufferBindingType::Storage {
|
||||
read_only: !usage.contains(naga::GlobalUse::STORE),
|
||||
},
|
||||
has_dynamic_offset,
|
||||
min_binding_size: wgt::BufferSize::new(actual_size),
|
||||
readonly: !usage.contains(naga::GlobalUse::STORE),
|
||||
},
|
||||
_ => return Err(BindingError::WrongType),
|
||||
}
|
||||
}
|
||||
naga::TypeInner::Sampler { comparison } => BindingType::Sampler { comparison },
|
||||
naga::TypeInner::Sampler { comparison } => BindingType::Sampler {
|
||||
filtering: true,
|
||||
comparison,
|
||||
},
|
||||
naga::TypeInner::Image {
|
||||
dim,
|
||||
arrayed,
|
||||
class,
|
||||
} => {
|
||||
let dimension = match dim {
|
||||
let view_dimension = match dim {
|
||||
naga::ImageDimension::D1 => wgt::TextureViewDimension::D1,
|
||||
naga::ImageDimension::D2 if arrayed => wgt::TextureViewDimension::D2Array,
|
||||
naga::ImageDimension::D2 => wgt::TextureViewDimension::D2,
|
||||
@ -813,23 +818,30 @@ fn derive_binding_type(
|
||||
naga::ImageDimension::Cube => wgt::TextureViewDimension::Cube,
|
||||
};
|
||||
match class {
|
||||
naga::ImageClass::Sampled { multi, kind } => BindingType::SampledTexture {
|
||||
dimension,
|
||||
component_type: match kind {
|
||||
naga::ScalarKind::Float => wgt::TextureComponentType::Float,
|
||||
naga::ScalarKind::Sint => wgt::TextureComponentType::Sint,
|
||||
naga::ScalarKind::Uint => wgt::TextureComponentType::Uint,
|
||||
naga::ImageClass::Sampled { multi, kind } => BindingType::Texture {
|
||||
sample_type: match kind {
|
||||
naga::ScalarKind::Float => {
|
||||
wgt::TextureSampleType::Float { filterable: true }
|
||||
}
|
||||
naga::ScalarKind::Sint => wgt::TextureSampleType::Sint,
|
||||
naga::ScalarKind::Uint => wgt::TextureSampleType::Uint,
|
||||
naga::ScalarKind::Bool => unreachable!(),
|
||||
},
|
||||
view_dimension,
|
||||
multisampled: multi,
|
||||
},
|
||||
naga::ImageClass::Depth => BindingType::SampledTexture {
|
||||
dimension,
|
||||
component_type: wgt::TextureComponentType::DepthComparison,
|
||||
naga::ImageClass::Depth => BindingType::Texture {
|
||||
sample_type: wgt::TextureSampleType::Depth,
|
||||
view_dimension,
|
||||
multisampled: false,
|
||||
},
|
||||
naga::ImageClass::Storage(format) => BindingType::StorageTexture {
|
||||
dimension,
|
||||
access: if usage.contains(naga::GlobalUse::STORE) {
|
||||
wgt::StorageTextureAccess::WriteOnly
|
||||
} else {
|
||||
wgt::StorageTextureAccess::ReadOnly
|
||||
},
|
||||
view_dimension,
|
||||
format: {
|
||||
let f = map_storage_format_from_naga(format);
|
||||
let original = map_storage_format_to_naga(f)
|
||||
@ -837,7 +849,6 @@ fn derive_binding_type(
|
||||
debug_assert_eq!(format, original);
|
||||
f
|
||||
},
|
||||
readonly: !usage.contains(naga::GlobalUse::STORE),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -447,6 +447,12 @@ pub enum TextureViewDimension {
|
||||
D3,
|
||||
}
|
||||
|
||||
impl Default for TextureViewDimension {
|
||||
fn default() -> Self {
|
||||
Self::D2
|
||||
}
|
||||
}
|
||||
|
||||
impl TextureViewDimension {
|
||||
/// Get the texture dimension required fo this texture view dimension.
|
||||
pub fn compatible_texture_dimension(self) -> TextureDimension {
|
||||
@ -1225,9 +1231,9 @@ bitflags::bitflags! {
|
||||
const INDEX = 16;
|
||||
/// Allow a buffer to be the vertex buffer in a draw operation.
|
||||
const VERTEX = 32;
|
||||
/// Allow a buffer to be a [`BindingType::UniformBuffer`] inside a bind group.
|
||||
/// Allow a buffer to be a [`BufferBindingType::Uniform`] inside a bind group.
|
||||
const UNIFORM = 64;
|
||||
/// Allow a buffer to be a [`BindingType::StorageBuffer`] inside a bind group.
|
||||
/// Allow a buffer to be a [`BufferBindingType::Storage`] inside a bind group.
|
||||
const STORAGE = 128;
|
||||
/// Allow a buffer to be the indirect buffer in an indirect draw call.
|
||||
const INDIRECT = 256;
|
||||
@ -1324,7 +1330,7 @@ bitflags::bitflags! {
|
||||
/// Allows a texture to be the destination in a [`CommandEncoder::copy_texture_to_buffer`],
|
||||
/// [`CommandEncoder::copy_texture_to_texture`], or [`Queue::write_texture`] operation.
|
||||
const COPY_DST = 2;
|
||||
/// Allows a texture to be a [`BindingType::SampledTexture`] in a bind group.
|
||||
/// Allows a texture to be a [`BindingType::Texture`] in a bind group.
|
||||
const SAMPLED = 4;
|
||||
/// Allows a texture to be a [`BindingType::StorageTexture`] in a bind group.
|
||||
const STORAGE = 8;
|
||||
@ -1485,7 +1491,7 @@ pub struct TextureDescriptor<L> {
|
||||
pub size: Extent3d,
|
||||
/// Mip count of texture. For a texture with no extra mips, this must be 1.
|
||||
pub mip_level_count: u32,
|
||||
/// Sample count of texture. If this is not 1, texture must have [`BindingType::SampledTexture::multisampled`] set to true.
|
||||
/// Sample count of texture. If this is not 1, texture must have [`BindingType::Texture::multisampled`] set to true.
|
||||
pub sample_count: u32,
|
||||
/// Dimensions of the texture.
|
||||
pub dimension: TextureDimension,
|
||||
@ -1640,85 +1646,6 @@ impl<T> Default for RenderBundleDescriptor<Option<T>> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Type of data shaders will read from a texture.
|
||||
///
|
||||
/// Only relevant for [`BindingType::SampledTexture`] bindings. See [`TextureFormat`] for more information.
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
||||
#[cfg_attr(feature = "trace", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
pub enum TextureComponentType {
|
||||
/// They see it as a floating point number `texture1D`, `texture2D` etc
|
||||
Float,
|
||||
/// They see it as a signed integer `itexture1D`, `itexture2D` etc
|
||||
Sint,
|
||||
/// They see it as a unsigned integer `utexture1D`, `utexture2D` etc
|
||||
Uint,
|
||||
/// They see it as a floating point 0-1 result of comparison, i.e. `shadowTexture2D`
|
||||
DepthComparison,
|
||||
}
|
||||
|
||||
impl From<TextureFormat> for TextureComponentType {
|
||||
fn from(format: TextureFormat) -> Self {
|
||||
match format {
|
||||
TextureFormat::R8Uint
|
||||
| TextureFormat::R16Uint
|
||||
| TextureFormat::Rg8Uint
|
||||
| TextureFormat::R32Uint
|
||||
| TextureFormat::Rg16Uint
|
||||
| TextureFormat::Rgba8Uint
|
||||
| TextureFormat::Rg32Uint
|
||||
| TextureFormat::Rgba16Uint
|
||||
| TextureFormat::Rgba32Uint => Self::Uint,
|
||||
|
||||
TextureFormat::R8Sint
|
||||
| TextureFormat::R16Sint
|
||||
| TextureFormat::Rg8Sint
|
||||
| TextureFormat::R32Sint
|
||||
| TextureFormat::Rg16Sint
|
||||
| TextureFormat::Rgba8Sint
|
||||
| TextureFormat::Rg32Sint
|
||||
| TextureFormat::Rgba16Sint
|
||||
| TextureFormat::Rgba32Sint => Self::Sint,
|
||||
|
||||
TextureFormat::R8Unorm
|
||||
| TextureFormat::R8Snorm
|
||||
| TextureFormat::R16Float
|
||||
| TextureFormat::R32Float
|
||||
| TextureFormat::Rg8Unorm
|
||||
| TextureFormat::Rg8Snorm
|
||||
| TextureFormat::Rg16Float
|
||||
| TextureFormat::Rg11b10Float
|
||||
| TextureFormat::Rg32Float
|
||||
| TextureFormat::Rgba8Snorm
|
||||
| TextureFormat::Rgba16Float
|
||||
| TextureFormat::Rgba32Float
|
||||
| TextureFormat::Rgba8Unorm
|
||||
| TextureFormat::Rgba8UnormSrgb
|
||||
| TextureFormat::Bgra8Unorm
|
||||
| TextureFormat::Bgra8UnormSrgb
|
||||
| TextureFormat::Rgb10a2Unorm
|
||||
| TextureFormat::Depth32Float
|
||||
| TextureFormat::Depth24Plus
|
||||
| TextureFormat::Depth24PlusStencil8
|
||||
| TextureFormat::Bc1RgbaUnorm
|
||||
| TextureFormat::Bc1RgbaUnormSrgb
|
||||
| TextureFormat::Bc2RgbaUnorm
|
||||
| TextureFormat::Bc2RgbaUnormSrgb
|
||||
| TextureFormat::Bc3RgbaUnorm
|
||||
| TextureFormat::Bc3RgbaUnormSrgb
|
||||
| TextureFormat::Bc4RUnorm
|
||||
| TextureFormat::Bc4RSnorm
|
||||
| TextureFormat::Bc5RgUnorm
|
||||
| TextureFormat::Bc5RgSnorm
|
||||
| TextureFormat::Bc6hRgbSfloat
|
||||
| TextureFormat::Bc6hRgbUfloat
|
||||
| TextureFormat::Bc7RgbaUnorm
|
||||
| TextureFormat::Bc7RgbaUnormSrgb => Self::Float,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Layout of a texture in a buffer's memory.
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Debug, Default)]
|
||||
@ -1743,13 +1670,13 @@ pub struct TextureDataLayout {
|
||||
pub rows_per_image: u32,
|
||||
}
|
||||
|
||||
/// Specific type of a binding.
|
||||
/// Specific type of a buffer binding.
|
||||
///
|
||||
/// WebGPU spec: https://gpuweb.github.io/gpuweb/#dictdef-gpubindgrouplayoutentry
|
||||
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
|
||||
/// WebGPU spec: https://gpuweb.github.io/gpuweb/#enumdef-gpubufferbindingtype
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
|
||||
#[cfg_attr(feature = "trace", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
pub enum BindingType {
|
||||
pub enum BufferBindingType {
|
||||
/// A buffer for uniform values.
|
||||
///
|
||||
/// Example GLSL syntax:
|
||||
@ -1760,16 +1687,7 @@ pub enum BindingType {
|
||||
/// vec2 anotherUniform;
|
||||
/// };
|
||||
/// ```
|
||||
UniformBuffer {
|
||||
/// Indicates that the binding has a dynamic offset.
|
||||
/// One offset must be passed to [`RenderPass::set_bind_group`] for each dynamic binding in increasing order of binding number.
|
||||
dynamic: bool,
|
||||
/// Minimum size of the corresponding `BufferBinding` required to match this entry.
|
||||
/// When pipeline is created, the size has to cover at least the corresponding structure in the shader
|
||||
/// plus one element of the unbound array, which can only be last in the structure.
|
||||
/// If `None`, the check is performed at draw call time instead of pipeline and bind group creation.
|
||||
min_binding_size: Option<BufferSize>,
|
||||
},
|
||||
Uniform,
|
||||
/// A storage buffer.
|
||||
///
|
||||
/// Example GLSL syntax:
|
||||
@ -1778,16 +1696,9 @@ pub enum BindingType {
|
||||
/// vec4 myElement[];
|
||||
/// };
|
||||
/// ```
|
||||
StorageBuffer {
|
||||
/// Indicates that the binding has a dynamic offset.
|
||||
/// One offset must be passed to [`RenderPass::set_bind_group`] for each dynamic binding in increasing order of binding number.
|
||||
dynamic: bool,
|
||||
/// Minimum size of the corresponding `BufferBinding` required to match this entry.
|
||||
/// When pipeline is created, the size has to cover at least the corresponding structure in the shader
|
||||
/// plus one element of the unbound array, which can only be last in the structure.
|
||||
/// If `None`, the check is performed at draw call time instead of pipeline and bind group creation.
|
||||
min_binding_size: Option<BufferSize>,
|
||||
/// The buffer can only be read in the shader and it must be annotated with `readonly`.
|
||||
Storage {
|
||||
/// If `true`, the buffer can only be read in the shader,
|
||||
/// and it must be annotated with `readonly`.
|
||||
///
|
||||
/// Example GLSL syntax:
|
||||
/// ```cpp,ignore
|
||||
@ -1795,7 +1706,176 @@ pub enum BindingType {
|
||||
/// vec4 myElement[];
|
||||
/// };
|
||||
/// ```
|
||||
readonly: bool,
|
||||
read_only: bool,
|
||||
},
|
||||
}
|
||||
|
||||
impl Default for BufferBindingType {
|
||||
fn default() -> Self {
|
||||
Self::Uniform
|
||||
}
|
||||
}
|
||||
|
||||
/// Specific type of a sample in a texture binding.
|
||||
///
|
||||
/// WebGPU spec: https://gpuweb.github.io/gpuweb/#enumdef-gputexturesampletype
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
|
||||
#[cfg_attr(feature = "trace", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
pub enum TextureSampleType {
|
||||
/// Sampling returns floats.
|
||||
///
|
||||
/// If `filterable` is false, the texture can't be sampled with
|
||||
/// a filtering sampler.
|
||||
///
|
||||
/// Example GLSL syntax:
|
||||
/// ```cpp,ignore
|
||||
/// layout(binding = 0)
|
||||
/// uniform texture2D t;
|
||||
/// ```
|
||||
Float { filterable: bool },
|
||||
/// Sampling does the depth reference comparison.
|
||||
///
|
||||
/// Example GLSL syntax:
|
||||
/// ```cpp,ignore
|
||||
/// layout(binding = 0)
|
||||
/// uniform texture2DShadow t;
|
||||
/// ```
|
||||
Depth,
|
||||
/// Sampling returns signed integers.
|
||||
///
|
||||
/// Example GLSL syntax:
|
||||
/// ```cpp,ignore
|
||||
/// layout(binding = 0)
|
||||
/// uniform itexture2D t;
|
||||
/// ```
|
||||
Sint,
|
||||
/// Sampling returns unsigned integers.
|
||||
///
|
||||
/// Example GLSL syntax:
|
||||
/// ```cpp,ignore
|
||||
/// layout(binding = 0)
|
||||
/// uniform utexture2D t;
|
||||
/// ```
|
||||
Uint,
|
||||
}
|
||||
|
||||
impl Default for TextureSampleType {
|
||||
fn default() -> Self {
|
||||
Self::Float { filterable: true }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TextureFormat> for TextureSampleType {
|
||||
fn from(format: TextureFormat) -> Self {
|
||||
match format {
|
||||
TextureFormat::R8Uint
|
||||
| TextureFormat::R16Uint
|
||||
| TextureFormat::Rg8Uint
|
||||
| TextureFormat::R32Uint
|
||||
| TextureFormat::Rg16Uint
|
||||
| TextureFormat::Rgba8Uint
|
||||
| TextureFormat::Rg32Uint
|
||||
| TextureFormat::Rgba16Uint
|
||||
| TextureFormat::Rgba32Uint => Self::Uint,
|
||||
|
||||
TextureFormat::R8Sint
|
||||
| TextureFormat::R16Sint
|
||||
| TextureFormat::Rg8Sint
|
||||
| TextureFormat::R32Sint
|
||||
| TextureFormat::Rg16Sint
|
||||
| TextureFormat::Rgba8Sint
|
||||
| TextureFormat::Rg32Sint
|
||||
| TextureFormat::Rgba16Sint
|
||||
| TextureFormat::Rgba32Sint => Self::Sint,
|
||||
|
||||
TextureFormat::R32Float | TextureFormat::Rg32Float | TextureFormat::Rgba32Float => {
|
||||
Self::Float { filterable: false }
|
||||
}
|
||||
|
||||
TextureFormat::R8Unorm
|
||||
| TextureFormat::R8Snorm
|
||||
| TextureFormat::R16Float
|
||||
| TextureFormat::Rg8Unorm
|
||||
| TextureFormat::Rg8Snorm
|
||||
| TextureFormat::Rg16Float
|
||||
| TextureFormat::Rg11b10Float
|
||||
| TextureFormat::Rgba8Snorm
|
||||
| TextureFormat::Rgba16Float
|
||||
| TextureFormat::Rgba8Unorm
|
||||
| TextureFormat::Rgba8UnormSrgb
|
||||
| TextureFormat::Bgra8Unorm
|
||||
| TextureFormat::Bgra8UnormSrgb
|
||||
| TextureFormat::Rgb10a2Unorm
|
||||
| TextureFormat::Bc1RgbaUnorm
|
||||
| TextureFormat::Bc1RgbaUnormSrgb
|
||||
| TextureFormat::Bc2RgbaUnorm
|
||||
| TextureFormat::Bc2RgbaUnormSrgb
|
||||
| TextureFormat::Bc3RgbaUnorm
|
||||
| TextureFormat::Bc3RgbaUnormSrgb
|
||||
| TextureFormat::Bc4RUnorm
|
||||
| TextureFormat::Bc4RSnorm
|
||||
| TextureFormat::Bc5RgUnorm
|
||||
| TextureFormat::Bc5RgSnorm
|
||||
| TextureFormat::Bc6hRgbSfloat
|
||||
| TextureFormat::Bc6hRgbUfloat
|
||||
| TextureFormat::Bc7RgbaUnorm
|
||||
| TextureFormat::Bc7RgbaUnormSrgb => Self::Float { filterable: true },
|
||||
|
||||
TextureFormat::Depth32Float
|
||||
| TextureFormat::Depth24Plus
|
||||
| TextureFormat::Depth24PlusStencil8 => Self::Depth,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Specific type of a sample in a texture binding.
|
||||
///
|
||||
/// WebGPU spec: https://gpuweb.github.io/gpuweb/#enumdef-gpustoragetextureaccess
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
|
||||
#[cfg_attr(feature = "trace", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
pub enum StorageTextureAccess {
|
||||
/// The texture can only be read in the shader and it must be annotated with `readonly`.
|
||||
///
|
||||
/// Example GLSL syntax:
|
||||
/// ```cpp,ignore
|
||||
/// layout(set=0, binding=0, r32f) readonly uniform image2D myStorageImage;
|
||||
/// ```
|
||||
ReadOnly,
|
||||
/// The texture can only be read in the shader and it must be annotated with `writeonly`.
|
||||
///
|
||||
/// Example GLSL syntax:
|
||||
/// ```cpp,ignore
|
||||
/// layout(set=0, binding=0, r32f) writeonly uniform image2D myStorageImage;
|
||||
/// ```
|
||||
WriteOnly,
|
||||
}
|
||||
|
||||
/// Specific type of a binding.
|
||||
///
|
||||
/// WebGPU spec: the enum of
|
||||
/// - https://gpuweb.github.io/gpuweb/#dictdef-gpubufferbindinglayout
|
||||
/// - https://gpuweb.github.io/gpuweb/#dictdef-gpusamplerbindinglayout
|
||||
/// - https://gpuweb.github.io/gpuweb/#dictdef-gputexturebindinglayout
|
||||
/// - https://gpuweb.github.io/gpuweb/#dictdef-gpustoragetexturebindinglayout
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
|
||||
#[cfg_attr(feature = "trace", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
pub enum BindingType {
|
||||
/// A buffer binding.
|
||||
Buffer {
|
||||
ty: BufferBindingType,
|
||||
/// Indicates that the binding has a dynamic offset.
|
||||
/// One offset must be passed to [`RenderPass::set_bind_group`] for each dynamic binding in increasing order of binding number.
|
||||
#[cfg_attr(any(feature = "replay", feature = "trace"), serde(default))]
|
||||
has_dynamic_offset: bool,
|
||||
/// Minimum size of the corresponding `BufferBinding` required to match this entry.
|
||||
/// When pipeline is created, the size has to cover at least the corresponding structure in the shader
|
||||
/// plus one element of the unbound array, which can only be last in the structure.
|
||||
/// If `None`, the check is performed at draw call time instead of pipeline and bind group creation.
|
||||
#[cfg_attr(any(feature = "replay", feature = "trace"), serde(default))]
|
||||
min_binding_size: Option<BufferSize>,
|
||||
},
|
||||
/// A sampler that can be used to sample a texture.
|
||||
///
|
||||
@ -1805,23 +1885,27 @@ pub enum BindingType {
|
||||
/// uniform sampler s;
|
||||
/// ```
|
||||
Sampler {
|
||||
/// The sampling result is produced based on more than a single color sample from a texture,
|
||||
/// e.g. when bilinear interpolation is enabled.
|
||||
///
|
||||
/// A filtering sampler can only be used with a filterable texture.
|
||||
filtering: bool,
|
||||
/// Use as a comparison sampler instead of a normal sampler.
|
||||
/// For more info take a look at the analogous functionality in OpenGL: https://www.khronos.org/opengl/wiki/Sampler_Object#Comparison_mode.
|
||||
comparison: bool,
|
||||
},
|
||||
/// A texture.
|
||||
/// A texture binding.
|
||||
///
|
||||
/// Example GLSL syntax:
|
||||
/// ```cpp,ignore
|
||||
/// layout(binding = 0)
|
||||
/// uniform texture2D t;
|
||||
/// ```
|
||||
SampledTexture {
|
||||
Texture {
|
||||
/// Sample type of the texture binding.
|
||||
sample_type: TextureSampleType,
|
||||
/// Dimension of the texture view that is going to be sampled.
|
||||
dimension: TextureViewDimension,
|
||||
/// Component type of the texture.
|
||||
/// This must be compatible with the format of the texture.
|
||||
component_type: TextureComponentType,
|
||||
view_dimension: TextureViewDimension,
|
||||
/// True if the texture has a sample count greater than 1. If this is true,
|
||||
/// the texture must be read from shaders with `texture1DMS`, `texture2DMS`, or `texture3DMS`,
|
||||
/// depending on `dimension`.
|
||||
@ -1836,24 +1920,21 @@ pub enum BindingType {
|
||||
/// Note that the texture format must be specified in the shader as well.
|
||||
/// A list of valid formats can be found in the specification here: https://www.khronos.org/registry/OpenGL/specs/gl/GLSLangSpec.4.60.html#layout-qualifiers
|
||||
StorageTexture {
|
||||
/// Dimension of the texture view that is going to be sampled.
|
||||
dimension: TextureViewDimension,
|
||||
/// Allowed access to this texture.
|
||||
access: StorageTextureAccess,
|
||||
/// Format of the texture.
|
||||
format: TextureFormat,
|
||||
/// The texture can only be read in the shader and it must be annotated with `readonly`.
|
||||
///
|
||||
/// Example GLSL syntax:
|
||||
/// ```cpp,ignore
|
||||
/// layout(set=0, binding=0, r32f) readonly uniform image2D myStorageImage;
|
||||
/// ```
|
||||
readonly: bool,
|
||||
/// Dimension of the texture view that is going to be sampled.
|
||||
view_dimension: TextureViewDimension,
|
||||
},
|
||||
}
|
||||
|
||||
impl BindingType {
|
||||
pub fn has_dynamic_offset(&self) -> bool {
|
||||
match *self {
|
||||
Self::UniformBuffer { dynamic, .. } | Self::StorageBuffer { dynamic, .. } => dynamic,
|
||||
Self::Buffer {
|
||||
has_dynamic_offset, ..
|
||||
} => has_dynamic_offset,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
@ -1873,9 +1954,10 @@ pub struct BindGroupLayoutEntry {
|
||||
pub ty: BindingType,
|
||||
/// If this value is Some, indicates this entry is an array. Array size must be 1 or greater.
|
||||
///
|
||||
/// If this value is Some and `ty` is `BindingType::SampledTexture`, [`Capabilities::SAMPLED_TEXTURE_BINDING_ARRAY`] must be supported.
|
||||
/// If this value is Some and `ty` is `BindingType::Texture`, [`Features::SAMPLED_TEXTURE_BINDING_ARRAY`] must be supported.
|
||||
///
|
||||
/// If this value is Some and `ty` is any other variant, bind group creation will fail.
|
||||
#[cfg_attr(any(feature = "replay", feature = "trace"), serde(default))]
|
||||
pub count: Option<NonZeroU32>,
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user