mirror of
https://github.com/gfx-rs/wgpu.git
synced 2024-11-22 14:55:05 +00:00
Move texture-array example over to wgsl (#2618)
This commit is contained in:
parent
bc850d2a0e
commit
e54a36ee78
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -1032,7 +1032,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "naga"
|
name = "naga"
|
||||||
version = "0.8.0"
|
version = "0.8.0"
|
||||||
source = "git+https://github.com/gfx-rs/naga?rev=85056524#850565243d1d0d03215f13246c94d63e1d4c51cd"
|
source = "git+https://github.com/gfx-rs/naga?rev=1aa91549#1aa9154964238af8c692cf521ff90e1f2395e147"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bit-set",
|
"bit-set",
|
||||||
"bitflags",
|
"bitflags",
|
||||||
|
@ -170,9 +170,6 @@ fn deserialize_features(features: &wgpu_types::Features) -> Vec<&'static str> {
|
|||||||
) {
|
) {
|
||||||
return_features.push("uniform-buffer-and-storage-buffer-texture-non-uniform-indexing");
|
return_features.push("uniform-buffer-and-storage-buffer-texture-non-uniform-indexing");
|
||||||
}
|
}
|
||||||
if features.contains(wgpu_types::Features::UNSIZED_BINDING_ARRAY) {
|
|
||||||
return_features.push("unsized-binding-array");
|
|
||||||
}
|
|
||||||
if features.contains(wgpu_types::Features::ADDRESS_MODE_CLAMP_TO_BORDER) {
|
if features.contains(wgpu_types::Features::ADDRESS_MODE_CLAMP_TO_BORDER) {
|
||||||
return_features.push("address-mode-clamp-to-border");
|
return_features.push("address-mode-clamp-to-border");
|
||||||
}
|
}
|
||||||
@ -341,10 +338,6 @@ impl From<GpuRequiredFeatures> for wgpu_types::Features {
|
|||||||
.0
|
.0
|
||||||
.contains("uniform-buffer-and-storage-buffer-texture-non-uniform-indexing"),
|
.contains("uniform-buffer-and-storage-buffer-texture-non-uniform-indexing"),
|
||||||
);
|
);
|
||||||
features.set(
|
|
||||||
wgpu_types::Features::UNSIZED_BINDING_ARRAY,
|
|
||||||
required_features.0.contains("unsized-binding-array"),
|
|
||||||
);
|
|
||||||
features.set(
|
features.set(
|
||||||
wgpu_types::Features::ADDRESS_MODE_CLAMP_TO_BORDER,
|
wgpu_types::Features::ADDRESS_MODE_CLAMP_TO_BORDER,
|
||||||
required_features.0.contains("address-mode-clamp-to-border"),
|
required_features.0.contains("address-mode-clamp-to-border"),
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
(
|
(
|
||||||
features: 0x0000_0020_0000_0000,
|
features: 0x0000_0010_0000_0000,
|
||||||
expectations: [
|
expectations: [
|
||||||
(
|
(
|
||||||
name: "Quad",
|
name: "Quad",
|
||||||
|
@ -40,7 +40,7 @@ thiserror = "1"
|
|||||||
|
|
||||||
[dependencies.naga]
|
[dependencies.naga]
|
||||||
git = "https://github.com/gfx-rs/naga"
|
git = "https://github.com/gfx-rs/naga"
|
||||||
rev = "85056524"
|
rev = "1aa91549"
|
||||||
#version = "0.8"
|
#version = "0.8"
|
||||||
features = ["span", "validate", "wgsl-in"]
|
features = ["span", "validate", "wgsl-in"]
|
||||||
|
|
||||||
|
@ -1145,6 +1145,25 @@ impl<A: HalApi> Device<A> {
|
|||||||
self.features
|
self.features
|
||||||
.contains(wgt::Features::SHADER_PRIMITIVE_INDEX),
|
.contains(wgt::Features::SHADER_PRIMITIVE_INDEX),
|
||||||
);
|
);
|
||||||
|
caps.set(
|
||||||
|
Caps::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING,
|
||||||
|
self.features.contains(
|
||||||
|
wgt::Features::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
caps.set(
|
||||||
|
Caps::UNIFORM_BUFFER_AND_STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING,
|
||||||
|
self.features.contains(
|
||||||
|
wgt::Features::UNIFORM_BUFFER_AND_STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
// TODO: This needs a proper wgpu feature
|
||||||
|
caps.set(
|
||||||
|
Caps::SAMPLER_NON_UNIFORM_INDEXING,
|
||||||
|
self.features.contains(
|
||||||
|
wgt::Features::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING,
|
||||||
|
),
|
||||||
|
);
|
||||||
let info = naga::valid::Validator::new(naga::valid::ValidationFlags::all(), caps)
|
let info = naga::valid::Validator::new(naga::valid::ValidationFlags::all(), caps)
|
||||||
.validate(&module)
|
.validate(&module)
|
||||||
.map_err(|inner| {
|
.map_err(|inner| {
|
||||||
|
@ -867,7 +867,14 @@ impl Interface {
|
|||||||
Some(ref br) => br.clone(),
|
Some(ref br) => br.clone(),
|
||||||
_ => continue,
|
_ => continue,
|
||||||
};
|
};
|
||||||
let ty = match module.types[var.ty].inner {
|
let naga_ty = &module.types[var.ty].inner;
|
||||||
|
|
||||||
|
let inner_ty = match *naga_ty {
|
||||||
|
naga::TypeInner::BindingArray { base, .. } => &module.types[base].inner,
|
||||||
|
ref ty => ty,
|
||||||
|
};
|
||||||
|
|
||||||
|
let ty = match *inner_ty {
|
||||||
naga::TypeInner::Image {
|
naga::TypeInner::Image {
|
||||||
dim,
|
dim,
|
||||||
arrayed,
|
arrayed,
|
||||||
|
@ -91,14 +91,14 @@ js-sys = { version = "0.3" }
|
|||||||
|
|
||||||
[dependencies.naga]
|
[dependencies.naga]
|
||||||
git = "https://github.com/gfx-rs/naga"
|
git = "https://github.com/gfx-rs/naga"
|
||||||
rev = "85056524"
|
rev = "1aa91549"
|
||||||
#version = "0.8"
|
#version = "0.8"
|
||||||
|
|
||||||
# DEV dependencies
|
# DEV dependencies
|
||||||
|
|
||||||
[dev-dependencies.naga]
|
[dev-dependencies.naga]
|
||||||
git = "https://github.com/gfx-rs/naga"
|
git = "https://github.com/gfx-rs/naga"
|
||||||
rev = "85056524"
|
rev = "1aa91549"
|
||||||
#version = "0.8"
|
#version = "0.8"
|
||||||
features = ["wgsl-in"]
|
features = ["wgsl-in"]
|
||||||
|
|
||||||
|
@ -91,6 +91,18 @@ impl super::Adapter {
|
|||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let mut shader_model_support: d3d12::D3D12_FEATURE_DATA_SHADER_MODEL =
|
||||||
|
d3d12::D3D12_FEATURE_DATA_SHADER_MODEL {
|
||||||
|
HighestShaderModel: d3d12::D3D_SHADER_MODEL_6_0,
|
||||||
|
};
|
||||||
|
assert_eq!(0, unsafe {
|
||||||
|
device.CheckFeatureSupport(
|
||||||
|
d3d12::D3D12_FEATURE_SHADER_MODEL,
|
||||||
|
&mut shader_model_support as *mut _ as *mut _,
|
||||||
|
mem::size_of::<d3d12::D3D12_FEATURE_DATA_SHADER_MODEL>() as _,
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
let mut workarounds = super::Workarounds::default();
|
let mut workarounds = super::Workarounds::default();
|
||||||
|
|
||||||
let info = wgt::AdapterInfo {
|
let info = wgt::AdapterInfo {
|
||||||
@ -175,11 +187,6 @@ impl super::Adapter {
|
|||||||
| wgt::Features::DEPTH_CLIP_CONTROL
|
| wgt::Features::DEPTH_CLIP_CONTROL
|
||||||
| wgt::Features::INDIRECT_FIRST_INSTANCE
|
| wgt::Features::INDIRECT_FIRST_INSTANCE
|
||||||
| wgt::Features::MAPPABLE_PRIMARY_BUFFERS
|
| wgt::Features::MAPPABLE_PRIMARY_BUFFERS
|
||||||
//TODO: Naga part
|
|
||||||
//| wgt::Features::TEXTURE_BINDING_ARRAY
|
|
||||||
//| wgt::Features::BUFFER_BINDING_ARRAY
|
|
||||||
//| wgt::Features::STORAGE_RESOURCE_BINDING_ARRAY
|
|
||||||
//| wgt::Features::UNSIZED_BINDING_ARRAY
|
|
||||||
| wgt::Features::MULTI_DRAW_INDIRECT
|
| wgt::Features::MULTI_DRAW_INDIRECT
|
||||||
| wgt::Features::MULTI_DRAW_INDIRECT_COUNT
|
| wgt::Features::MULTI_DRAW_INDIRECT_COUNT
|
||||||
| wgt::Features::ADDRESS_MODE_CLAMP_TO_BORDER
|
| wgt::Features::ADDRESS_MODE_CLAMP_TO_BORDER
|
||||||
@ -204,6 +211,13 @@ impl super::Adapter {
|
|||||||
!= d3d12::D3D12_CONSERVATIVE_RASTERIZATION_TIER_NOT_SUPPORTED,
|
!= d3d12::D3D12_CONSERVATIVE_RASTERIZATION_TIER_NOT_SUPPORTED,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
features.set(
|
||||||
|
wgt::Features::TEXTURE_BINDING_ARRAY
|
||||||
|
| wgt::Features::UNIFORM_BUFFER_AND_STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING
|
||||||
|
| wgt::Features::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING,
|
||||||
|
shader_model_support.HighestShaderModel >= d3d12::D3D_SHADER_MODEL_5_1,
|
||||||
|
);
|
||||||
|
|
||||||
let base = wgt::Limits::default();
|
let base = wgt::Limits::default();
|
||||||
|
|
||||||
Some(crate::ExposedAdapter {
|
Some(crate::ExposedAdapter {
|
||||||
@ -282,7 +296,7 @@ impl super::Adapter {
|
|||||||
impl crate::Adapter<super::Api> for super::Adapter {
|
impl crate::Adapter<super::Api> for super::Adapter {
|
||||||
unsafe fn open(
|
unsafe fn open(
|
||||||
&self,
|
&self,
|
||||||
features: wgt::Features,
|
_features: wgt::Features,
|
||||||
_limits: &wgt::Limits,
|
_limits: &wgt::Limits,
|
||||||
) -> Result<crate::OpenDevice<super::Api>, crate::DeviceError> {
|
) -> Result<crate::OpenDevice<super::Api>, crate::DeviceError> {
|
||||||
let queue = {
|
let queue = {
|
||||||
@ -297,13 +311,7 @@ impl crate::Adapter<super::Api> for super::Adapter {
|
|||||||
.into_device_result("Queue creation")?
|
.into_device_result("Queue creation")?
|
||||||
};
|
};
|
||||||
|
|
||||||
let device = super::Device::new(
|
let device = super::Device::new(self.device, queue, self.private_caps, &self.library)?;
|
||||||
self.device,
|
|
||||||
queue,
|
|
||||||
features,
|
|
||||||
self.private_caps,
|
|
||||||
&self.library,
|
|
||||||
)?;
|
|
||||||
Ok(crate::OpenDevice {
|
Ok(crate::OpenDevice {
|
||||||
device,
|
device,
|
||||||
queue: super::Queue {
|
queue: super::Queue {
|
||||||
|
@ -21,7 +21,6 @@ impl super::Device {
|
|||||||
pub(super) fn new(
|
pub(super) fn new(
|
||||||
raw: native::Device,
|
raw: native::Device,
|
||||||
present_queue: native::CommandQueue,
|
present_queue: native::CommandQueue,
|
||||||
features: wgt::Features,
|
|
||||||
private_caps: super::PrivateCapabilities,
|
private_caps: super::PrivateCapabilities,
|
||||||
library: &Arc<native::D3D12Lib>,
|
library: &Arc<native::D3D12Lib>,
|
||||||
) -> Result<Self, crate::DeviceError> {
|
) -> Result<Self, crate::DeviceError> {
|
||||||
@ -87,7 +86,6 @@ impl super::Device {
|
|||||||
let capacity_samplers = 2_048;
|
let capacity_samplers = 2_048;
|
||||||
|
|
||||||
let shared = super::DeviceShared {
|
let shared = super::DeviceShared {
|
||||||
features,
|
|
||||||
zero_buffer,
|
zero_buffer,
|
||||||
cmd_signatures: super::CommandSignatures {
|
cmd_signatures: super::CommandSignatures {
|
||||||
draw: raw
|
draw: raw
|
||||||
@ -222,13 +220,6 @@ impl super::Device {
|
|||||||
compile_flags |=
|
compile_flags |=
|
||||||
d3dcompiler::D3DCOMPILE_DEBUG | d3dcompiler::D3DCOMPILE_SKIP_OPTIMIZATION;
|
d3dcompiler::D3DCOMPILE_DEBUG | d3dcompiler::D3DCOMPILE_SKIP_OPTIMIZATION;
|
||||||
}
|
}
|
||||||
if self
|
|
||||||
.shared
|
|
||||||
.features
|
|
||||||
.contains(wgt::Features::UNSIZED_BINDING_ARRAY)
|
|
||||||
{
|
|
||||||
compile_flags |= d3dcompiler::D3DCOMPILE_ENABLE_UNBOUNDED_DESCRIPTOR_TABLES;
|
|
||||||
}
|
|
||||||
|
|
||||||
let source_name = match stage.module.raw_name {
|
let source_name = match stage.module.raw_name {
|
||||||
Some(ref cstr) => cstr.as_c_str().as_ptr(),
|
Some(ref cstr) => cstr.as_c_str().as_ptr(),
|
||||||
@ -691,16 +682,17 @@ impl crate::Device<super::Api> for super::Device {
|
|||||||
) -> Result<super::BindGroupLayout, crate::DeviceError> {
|
) -> Result<super::BindGroupLayout, crate::DeviceError> {
|
||||||
let (mut num_buffer_views, mut num_samplers, mut num_texture_views) = (0, 0, 0);
|
let (mut num_buffer_views, mut num_samplers, mut num_texture_views) = (0, 0, 0);
|
||||||
for entry in desc.entries.iter() {
|
for entry in desc.entries.iter() {
|
||||||
|
let count = entry.count.map_or(1, NonZeroU32::get);
|
||||||
match entry.ty {
|
match entry.ty {
|
||||||
wgt::BindingType::Buffer {
|
wgt::BindingType::Buffer {
|
||||||
has_dynamic_offset: true,
|
has_dynamic_offset: true,
|
||||||
..
|
..
|
||||||
} => {}
|
} => {}
|
||||||
wgt::BindingType::Buffer { .. } => num_buffer_views += 1,
|
wgt::BindingType::Buffer { .. } => num_buffer_views += count,
|
||||||
wgt::BindingType::Texture { .. } | wgt::BindingType::StorageTexture { .. } => {
|
wgt::BindingType::Texture { .. } | wgt::BindingType::StorageTexture { .. } => {
|
||||||
num_texture_views += 1
|
num_texture_views += count
|
||||||
}
|
}
|
||||||
wgt::BindingType::Sampler { .. } => num_samplers += 1,
|
wgt::BindingType::Sampler { .. } => num_samplers += count,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -858,7 +850,10 @@ impl crate::Device<super::Api> for super::Device {
|
|||||||
group: index as u32,
|
group: index as u32,
|
||||||
binding: entry.binding,
|
binding: entry.binding,
|
||||||
},
|
},
|
||||||
bt.clone(),
|
hlsl::BindTarget {
|
||||||
|
binding_array_size: entry.count.map(NonZeroU32::get),
|
||||||
|
..bt.clone()
|
||||||
|
},
|
||||||
);
|
);
|
||||||
ranges.push(native::DescriptorRange::new(
|
ranges.push(native::DescriptorRange::new(
|
||||||
range_ty,
|
range_ty,
|
||||||
@ -866,7 +861,7 @@ impl crate::Device<super::Api> for super::Device {
|
|||||||
native_binding(bt),
|
native_binding(bt),
|
||||||
d3d12::D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND,
|
d3d12::D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND,
|
||||||
));
|
));
|
||||||
bt.register += 1;
|
bt.register += entry.count.map(NonZeroU32::get).unwrap_or(1);
|
||||||
}
|
}
|
||||||
if ranges.len() > range_base {
|
if ranges.len() > range_base {
|
||||||
log::debug!(
|
log::debug!(
|
||||||
@ -894,7 +889,10 @@ impl crate::Device<super::Api> for super::Device {
|
|||||||
group: index as u32,
|
group: index as u32,
|
||||||
binding: entry.binding,
|
binding: entry.binding,
|
||||||
},
|
},
|
||||||
bind_sampler.clone(),
|
hlsl::BindTarget {
|
||||||
|
binding_array_size: entry.count.map(NonZeroU32::get),
|
||||||
|
..bind_sampler.clone()
|
||||||
|
},
|
||||||
);
|
);
|
||||||
ranges.push(native::DescriptorRange::new(
|
ranges.push(native::DescriptorRange::new(
|
||||||
range_ty,
|
range_ty,
|
||||||
@ -902,7 +900,7 @@ impl crate::Device<super::Api> for super::Device {
|
|||||||
native_binding(&bind_sampler),
|
native_binding(&bind_sampler),
|
||||||
d3d12::D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND,
|
d3d12::D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND,
|
||||||
));
|
));
|
||||||
bind_sampler.register += 1;
|
bind_sampler.register += entry.count.map(NonZeroU32::get).unwrap_or(1);
|
||||||
}
|
}
|
||||||
if ranges.len() > range_base {
|
if ranges.len() > range_base {
|
||||||
log::debug!(
|
log::debug!(
|
||||||
@ -953,7 +951,10 @@ impl crate::Device<super::Api> for super::Device {
|
|||||||
group: index as u32,
|
group: index as u32,
|
||||||
binding: entry.binding,
|
binding: entry.binding,
|
||||||
},
|
},
|
||||||
bt.clone(),
|
hlsl::BindTarget {
|
||||||
|
binding_array_size: entry.count.map(NonZeroU32::get),
|
||||||
|
..bt.clone()
|
||||||
|
},
|
||||||
);
|
);
|
||||||
info.dynamic_buffers.push(kind);
|
info.dynamic_buffers.push(kind);
|
||||||
|
|
||||||
@ -969,7 +970,7 @@ impl crate::Device<super::Api> for super::Device {
|
|||||||
native_binding(bt),
|
native_binding(bt),
|
||||||
));
|
));
|
||||||
|
|
||||||
bt.register += 1;
|
bt.register += entry.count.map_or(1, NonZeroU32::get);
|
||||||
}
|
}
|
||||||
|
|
||||||
bind_group_infos.push(info);
|
bind_group_infos.push(info);
|
||||||
@ -1082,82 +1083,97 @@ impl crate::Device<super::Api> for super::Device {
|
|||||||
has_dynamic_offset: true,
|
has_dynamic_offset: true,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
let data = &desc.buffers[entry.resource_index as usize];
|
let start = entry.resource_index as usize;
|
||||||
dynamic_buffers.push(data.resolve_address());
|
let end = start + entry.count as usize;
|
||||||
|
for data in &desc.buffers[start..end] {
|
||||||
|
dynamic_buffers.push(data.resolve_address());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
wgt::BindingType::Buffer { ty, .. } => {
|
wgt::BindingType::Buffer { ty, .. } => {
|
||||||
let data = &desc.buffers[entry.resource_index as usize];
|
let start = entry.resource_index as usize;
|
||||||
let gpu_address = data.resolve_address();
|
let end = start + entry.count as usize;
|
||||||
let size = data.resolve_size() as u32;
|
for data in &desc.buffers[start..end] {
|
||||||
let inner = cpu_views.as_mut().unwrap();
|
let gpu_address = data.resolve_address();
|
||||||
let cpu_index = inner.stage.len() as u32;
|
let size = data.resolve_size() as u32;
|
||||||
let handle = desc.layout.cpu_heap_views.as_ref().unwrap().at(cpu_index);
|
let inner = cpu_views.as_mut().unwrap();
|
||||||
match ty {
|
let cpu_index = inner.stage.len() as u32;
|
||||||
wgt::BufferBindingType::Uniform => {
|
let handle = desc.layout.cpu_heap_views.as_ref().unwrap().at(cpu_index);
|
||||||
let size_mask =
|
match ty {
|
||||||
d3d12::D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT - 1;
|
wgt::BufferBindingType::Uniform => {
|
||||||
let raw_desc = d3d12::D3D12_CONSTANT_BUFFER_VIEW_DESC {
|
let size_mask =
|
||||||
BufferLocation: gpu_address,
|
d3d12::D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT - 1;
|
||||||
SizeInBytes: ((size - 1) | size_mask) + 1,
|
let raw_desc = d3d12::D3D12_CONSTANT_BUFFER_VIEW_DESC {
|
||||||
};
|
BufferLocation: gpu_address,
|
||||||
self.raw.CreateConstantBufferView(&raw_desc, handle);
|
SizeInBytes: ((size - 1) | size_mask) + 1,
|
||||||
}
|
};
|
||||||
wgt::BufferBindingType::Storage { read_only: true } => {
|
self.raw.CreateConstantBufferView(&raw_desc, handle);
|
||||||
let mut raw_desc = d3d12::D3D12_SHADER_RESOURCE_VIEW_DESC {
|
}
|
||||||
Format: dxgiformat::DXGI_FORMAT_R32_TYPELESS,
|
wgt::BufferBindingType::Storage { read_only: true } => {
|
||||||
Shader4ComponentMapping:
|
let mut raw_desc = d3d12::D3D12_SHADER_RESOURCE_VIEW_DESC {
|
||||||
view::D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING,
|
Format: dxgiformat::DXGI_FORMAT_R32_TYPELESS,
|
||||||
ViewDimension: d3d12::D3D12_SRV_DIMENSION_BUFFER,
|
Shader4ComponentMapping:
|
||||||
u: mem::zeroed(),
|
view::D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING,
|
||||||
};
|
ViewDimension: d3d12::D3D12_SRV_DIMENSION_BUFFER,
|
||||||
*raw_desc.u.Buffer_mut() = d3d12::D3D12_BUFFER_SRV {
|
u: mem::zeroed(),
|
||||||
FirstElement: data.offset / 4,
|
};
|
||||||
NumElements: size / 4,
|
*raw_desc.u.Buffer_mut() = d3d12::D3D12_BUFFER_SRV {
|
||||||
StructureByteStride: 0,
|
FirstElement: data.offset / 4,
|
||||||
Flags: d3d12::D3D12_BUFFER_SRV_FLAG_RAW,
|
NumElements: size / 4,
|
||||||
};
|
StructureByteStride: 0,
|
||||||
self.raw.CreateShaderResourceView(
|
Flags: d3d12::D3D12_BUFFER_SRV_FLAG_RAW,
|
||||||
data.buffer.resource.as_mut_ptr(),
|
};
|
||||||
&raw_desc,
|
self.raw.CreateShaderResourceView(
|
||||||
handle,
|
data.buffer.resource.as_mut_ptr(),
|
||||||
);
|
&raw_desc,
|
||||||
}
|
handle,
|
||||||
wgt::BufferBindingType::Storage { read_only: false } => {
|
);
|
||||||
let mut raw_desc = d3d12::D3D12_UNORDERED_ACCESS_VIEW_DESC {
|
}
|
||||||
Format: dxgiformat::DXGI_FORMAT_R32_TYPELESS,
|
wgt::BufferBindingType::Storage { read_only: false } => {
|
||||||
ViewDimension: d3d12::D3D12_UAV_DIMENSION_BUFFER,
|
let mut raw_desc = d3d12::D3D12_UNORDERED_ACCESS_VIEW_DESC {
|
||||||
u: mem::zeroed(),
|
Format: dxgiformat::DXGI_FORMAT_R32_TYPELESS,
|
||||||
};
|
ViewDimension: d3d12::D3D12_UAV_DIMENSION_BUFFER,
|
||||||
*raw_desc.u.Buffer_mut() = d3d12::D3D12_BUFFER_UAV {
|
u: mem::zeroed(),
|
||||||
FirstElement: data.offset / 4,
|
};
|
||||||
NumElements: size / 4,
|
*raw_desc.u.Buffer_mut() = d3d12::D3D12_BUFFER_UAV {
|
||||||
StructureByteStride: 0,
|
FirstElement: data.offset / 4,
|
||||||
CounterOffsetInBytes: 0,
|
NumElements: size / 4,
|
||||||
Flags: d3d12::D3D12_BUFFER_UAV_FLAG_RAW,
|
StructureByteStride: 0,
|
||||||
};
|
CounterOffsetInBytes: 0,
|
||||||
self.raw.CreateUnorderedAccessView(
|
Flags: d3d12::D3D12_BUFFER_UAV_FLAG_RAW,
|
||||||
data.buffer.resource.as_mut_ptr(),
|
};
|
||||||
ptr::null_mut(),
|
self.raw.CreateUnorderedAccessView(
|
||||||
&raw_desc,
|
data.buffer.resource.as_mut_ptr(),
|
||||||
handle,
|
ptr::null_mut(),
|
||||||
);
|
&raw_desc,
|
||||||
|
handle,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
inner.stage.push(handle);
|
||||||
}
|
}
|
||||||
inner.stage.push(handle);
|
|
||||||
}
|
}
|
||||||
wgt::BindingType::Texture { .. } => {
|
wgt::BindingType::Texture { .. } => {
|
||||||
let data = &desc.textures[entry.resource_index as usize];
|
let start = entry.resource_index as usize;
|
||||||
let handle = data.view.handle_srv.unwrap();
|
let end = start + entry.count as usize;
|
||||||
cpu_views.as_mut().unwrap().stage.push(handle.raw);
|
for data in &desc.textures[start..end] {
|
||||||
|
let handle = data.view.handle_srv.unwrap();
|
||||||
|
cpu_views.as_mut().unwrap().stage.push(handle.raw);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
wgt::BindingType::StorageTexture { .. } => {
|
wgt::BindingType::StorageTexture { .. } => {
|
||||||
let data = &desc.textures[entry.resource_index as usize];
|
let start = entry.resource_index as usize;
|
||||||
let handle = data.view.handle_uav.unwrap();
|
let end = start + entry.count as usize;
|
||||||
cpu_views.as_mut().unwrap().stage.push(handle.raw);
|
for data in &desc.textures[start..end] {
|
||||||
|
let handle = data.view.handle_uav.unwrap();
|
||||||
|
cpu_views.as_mut().unwrap().stage.push(handle.raw);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
wgt::BindingType::Sampler { .. } => {
|
wgt::BindingType::Sampler { .. } => {
|
||||||
let data = &desc.samplers[entry.resource_index as usize];
|
let start = entry.resource_index as usize;
|
||||||
cpu_samplers.as_mut().unwrap().stage.push(data.handle.raw);
|
let end = start + entry.count as usize;
|
||||||
|
for data in &desc.samplers[start..end] {
|
||||||
|
cpu_samplers.as_mut().unwrap().stage.push(data.handle.raw);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -199,7 +199,6 @@ impl CommandSignatures {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct DeviceShared {
|
struct DeviceShared {
|
||||||
features: wgt::Features,
|
|
||||||
zero_buffer: native::Resource,
|
zero_buffer: native::Resource,
|
||||||
cmd_signatures: CommandSignatures,
|
cmd_signatures: CommandSignatures,
|
||||||
heap_views: descriptor::GeneralHeap,
|
heap_views: descriptor::GeneralHeap,
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use std::{
|
use std::{
|
||||||
|
num::NonZeroU32,
|
||||||
ptr,
|
ptr,
|
||||||
sync::{atomic, Arc},
|
sync::{atomic, Arc},
|
||||||
thread, time,
|
thread, time,
|
||||||
@ -73,6 +74,13 @@ impl super::Device {
|
|||||||
)
|
)
|
||||||
.map_err(|e| crate::PipelineError::Linkage(stage_bit, format!("MSL: {:?}", e)))?;
|
.map_err(|e| crate::PipelineError::Linkage(stage_bit, format!("MSL: {:?}", e)))?;
|
||||||
|
|
||||||
|
log::debug!(
|
||||||
|
"Naga generated shader for entry point '{}' and stage {:?}\n{}",
|
||||||
|
stage.entry_point,
|
||||||
|
naga_stage,
|
||||||
|
&source
|
||||||
|
);
|
||||||
|
|
||||||
let options = mtl::CompileOptions::new();
|
let options = mtl::CompileOptions::new();
|
||||||
options.set_language_version(self.shared.private_caps.msl_version);
|
options.set_language_version(self.shared.private_caps.msl_version);
|
||||||
|
|
||||||
@ -558,10 +566,12 @@ impl crate::Device<super::Api> for super::Device {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut target = naga::back::msl::BindTarget::default();
|
let mut target = naga::back::msl::BindTarget::default();
|
||||||
|
let count = entry.count.map_or(1, NonZeroU32::get);
|
||||||
|
target.binding_array_size = entry.count.map(NonZeroU32::get);
|
||||||
match entry.ty {
|
match entry.ty {
|
||||||
wgt::BindingType::Buffer { ty, .. } => {
|
wgt::BindingType::Buffer { ty, .. } => {
|
||||||
target.buffer = Some(info.counters.buffers as _);
|
target.buffer = Some(info.counters.buffers as _);
|
||||||
info.counters.buffers += 1;
|
info.counters.buffers += count;
|
||||||
if let wgt::BufferBindingType::Storage { read_only } = ty {
|
if let wgt::BufferBindingType::Storage { read_only } = ty {
|
||||||
target.mutable = !read_only;
|
target.mutable = !read_only;
|
||||||
}
|
}
|
||||||
@ -570,15 +580,15 @@ impl crate::Device<super::Api> for super::Device {
|
|||||||
target.sampler = Some(naga::back::msl::BindSamplerTarget::Resource(
|
target.sampler = Some(naga::back::msl::BindSamplerTarget::Resource(
|
||||||
info.counters.samplers as _,
|
info.counters.samplers as _,
|
||||||
));
|
));
|
||||||
info.counters.samplers += 1;
|
info.counters.samplers += count;
|
||||||
}
|
}
|
||||||
wgt::BindingType::Texture { .. } => {
|
wgt::BindingType::Texture { .. } => {
|
||||||
target.texture = Some(info.counters.textures as _);
|
target.texture = Some(info.counters.textures as _);
|
||||||
info.counters.textures += 1;
|
info.counters.textures += count;
|
||||||
}
|
}
|
||||||
wgt::BindingType::StorageTexture { access, .. } => {
|
wgt::BindingType::StorageTexture { access, .. } => {
|
||||||
target.texture = Some(info.counters.textures as _);
|
target.texture = Some(info.counters.textures as _);
|
||||||
info.counters.textures += 1;
|
info.counters.textures += count;
|
||||||
target.mutable = match access {
|
target.mutable = match access {
|
||||||
wgt::StorageTextureAccess::ReadOnly => false,
|
wgt::StorageTextureAccess::ReadOnly => false,
|
||||||
wgt::StorageTextureAccess::WriteOnly => true,
|
wgt::StorageTextureAccess::WriteOnly => true,
|
||||||
@ -667,6 +677,8 @@ impl crate::Device<super::Api> for super::Device {
|
|||||||
index: naga::proc::BoundsCheckPolicy::ReadZeroSkipWrite,
|
index: naga::proc::BoundsCheckPolicy::ReadZeroSkipWrite,
|
||||||
buffer: naga::proc::BoundsCheckPolicy::ReadZeroSkipWrite,
|
buffer: naga::proc::BoundsCheckPolicy::ReadZeroSkipWrite,
|
||||||
image: naga::proc::BoundsCheckPolicy::ReadZeroSkipWrite,
|
image: naga::proc::BoundsCheckPolicy::ReadZeroSkipWrite,
|
||||||
|
// TODO: support bounds checks on binding arrays
|
||||||
|
binding_array: naga::proc::BoundsCheckPolicy::Unchecked,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
total_push_constants,
|
total_push_constants,
|
||||||
@ -689,7 +701,7 @@ impl crate::Device<super::Api> for super::Device {
|
|||||||
..
|
..
|
||||||
} = layout.ty
|
} = layout.ty
|
||||||
{
|
{
|
||||||
dynamic_offsets_count += 1;
|
dynamic_offsets_count += size;
|
||||||
}
|
}
|
||||||
if !layout.visibility.contains(stage_bit) {
|
if !layout.visibility.contains(stage_bit) {
|
||||||
continue;
|
continue;
|
||||||
@ -700,39 +712,44 @@ impl crate::Device<super::Api> for super::Device {
|
|||||||
has_dynamic_offset,
|
has_dynamic_offset,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
debug_assert_eq!(size, 1);
|
let start = entry.resource_index as usize;
|
||||||
let source = &desc.buffers[entry.resource_index as usize];
|
let end = start + size as usize;
|
||||||
let remaining_size =
|
bg.buffers
|
||||||
wgt::BufferSize::new(source.buffer.size - source.offset);
|
.extend(desc.buffers[start..end].iter().map(|source| {
|
||||||
let binding_size = match ty {
|
let remaining_size =
|
||||||
wgt::BufferBindingType::Storage { .. } => {
|
wgt::BufferSize::new(source.buffer.size - source.offset);
|
||||||
source.size.or(remaining_size)
|
let binding_size = match ty {
|
||||||
}
|
wgt::BufferBindingType::Storage { .. } => {
|
||||||
_ => None,
|
source.size.or(remaining_size)
|
||||||
};
|
}
|
||||||
bg.buffers.push(super::BufferResource {
|
_ => None,
|
||||||
ptr: source.buffer.as_raw(),
|
};
|
||||||
offset: source.offset,
|
super::BufferResource {
|
||||||
dynamic_index: if has_dynamic_offset {
|
ptr: source.buffer.as_raw(),
|
||||||
Some(dynamic_offsets_count - 1)
|
offset: source.offset,
|
||||||
} else {
|
dynamic_index: if has_dynamic_offset {
|
||||||
None
|
Some(dynamic_offsets_count - 1)
|
||||||
},
|
} else {
|
||||||
binding_size,
|
None
|
||||||
binding_location: layout.binding,
|
},
|
||||||
});
|
binding_size,
|
||||||
|
binding_location: layout.binding,
|
||||||
|
}
|
||||||
|
}));
|
||||||
counter.buffers += 1;
|
counter.buffers += 1;
|
||||||
}
|
}
|
||||||
wgt::BindingType::Sampler { .. } => {
|
wgt::BindingType::Sampler { .. } => {
|
||||||
let res = desc.samplers[entry.resource_index as usize].as_raw();
|
let start = entry.resource_index as usize;
|
||||||
bg.samplers.push(res);
|
let end = start + size as usize;
|
||||||
counter.samplers += 1;
|
bg.samplers
|
||||||
|
.extend(desc.samplers[start..end].iter().map(|samp| samp.as_raw()));
|
||||||
|
counter.samplers += size;
|
||||||
}
|
}
|
||||||
wgt::BindingType::Texture { .. } | wgt::BindingType::StorageTexture { .. } => {
|
wgt::BindingType::Texture { .. } | wgt::BindingType::StorageTexture { .. } => {
|
||||||
let start = entry.resource_index;
|
let start = entry.resource_index as usize;
|
||||||
let end = start + size;
|
let end = start + size as usize;
|
||||||
bg.textures.extend(
|
bg.textures.extend(
|
||||||
desc.textures[start as usize..end as usize]
|
desc.textures[start..end]
|
||||||
.iter()
|
.iter()
|
||||||
.map(|tex| tex.view.as_raw()),
|
.map(|tex| tex.view.as_raw()),
|
||||||
);
|
);
|
||||||
|
@ -3,13 +3,12 @@ use super::conv;
|
|||||||
use ash::{extensions::khr, vk};
|
use ash::{extensions::khr, vk};
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
|
|
||||||
use std::{ffi::CStr, sync::Arc};
|
use std::{collections::BTreeMap, ffi::CStr, sync::Arc};
|
||||||
|
|
||||||
//TODO: const fn?
|
//TODO: const fn?
|
||||||
fn indexing_features() -> wgt::Features {
|
fn indexing_features() -> wgt::Features {
|
||||||
wgt::Features::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING
|
wgt::Features::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING
|
||||||
| wgt::Features::UNIFORM_BUFFER_AND_STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING
|
| wgt::Features::UNIFORM_BUFFER_AND_STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING
|
||||||
| wgt::Features::UNSIZED_BINDING_ARRAY
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Aggregate of the `vk::PhysicalDevice*Features` structs used by `gfx`.
|
/// Aggregate of the `vk::PhysicalDevice*Features` structs used by `gfx`.
|
||||||
@ -212,9 +211,6 @@ impl PhysicalDeviceFeatures {
|
|||||||
uab_types.contains(super::UpdateAfterBindTypes::STORAGE_BUFFER),
|
uab_types.contains(super::UpdateAfterBindTypes::STORAGE_BUFFER),
|
||||||
)
|
)
|
||||||
.descriptor_binding_partially_bound(needs_partially_bound)
|
.descriptor_binding_partially_bound(needs_partially_bound)
|
||||||
.runtime_descriptor_array(
|
|
||||||
requested_features.contains(wgt::Features::UNSIZED_BINDING_ARRAY),
|
|
||||||
)
|
|
||||||
//.sampler_filter_minmax(requested_features.contains(wgt::Features::SAMPLER_REDUCTION))
|
//.sampler_filter_minmax(requested_features.contains(wgt::Features::SAMPLER_REDUCTION))
|
||||||
.imageless_framebuffer(private_caps.imageless_framebuffers)
|
.imageless_framebuffer(private_caps.imageless_framebuffers)
|
||||||
.timeline_semaphore(private_caps.timeline_semaphores)
|
.timeline_semaphore(private_caps.timeline_semaphores)
|
||||||
@ -253,9 +249,6 @@ impl PhysicalDeviceFeatures {
|
|||||||
uab_types.contains(super::UpdateAfterBindTypes::STORAGE_BUFFER),
|
uab_types.contains(super::UpdateAfterBindTypes::STORAGE_BUFFER),
|
||||||
)
|
)
|
||||||
.descriptor_binding_partially_bound(needs_partially_bound)
|
.descriptor_binding_partially_bound(needs_partially_bound)
|
||||||
.runtime_descriptor_array(
|
|
||||||
requested_features.contains(wgt::Features::UNSIZED_BINDING_ARRAY),
|
|
||||||
)
|
|
||||||
.build(),
|
.build(),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
@ -471,9 +464,6 @@ impl PhysicalDeviceFeatures {
|
|||||||
) {
|
) {
|
||||||
features.insert(F::UNIFORM_BUFFER_AND_STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING);
|
features.insert(F::UNIFORM_BUFFER_AND_STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING);
|
||||||
}
|
}
|
||||||
if vulkan_1_2.runtime_descriptor_array != 0 {
|
|
||||||
features |= F::UNSIZED_BINDING_ARRAY;
|
|
||||||
}
|
|
||||||
if vulkan_1_2.descriptor_binding_partially_bound != 0 && !intel_windows {
|
if vulkan_1_2.descriptor_binding_partially_bound != 0 && !intel_windows {
|
||||||
features |= F::PARTIALLY_BOUND_BINDING_ARRAY;
|
features |= F::PARTIALLY_BOUND_BINDING_ARRAY;
|
||||||
}
|
}
|
||||||
@ -519,9 +509,6 @@ impl PhysicalDeviceFeatures {
|
|||||||
if descriptor_indexing.descriptor_binding_partially_bound != 0 && !intel_windows {
|
if descriptor_indexing.descriptor_binding_partially_bound != 0 && !intel_windows {
|
||||||
features |= F::PARTIALLY_BOUND_BINDING_ARRAY;
|
features |= F::PARTIALLY_BOUND_BINDING_ARRAY;
|
||||||
}
|
}
|
||||||
if descriptor_indexing.runtime_descriptor_array != 0 {
|
|
||||||
features |= F::UNSIZED_BINDING_ARRAY;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(ref feature) = self.depth_clip_enable {
|
if let Some(ref feature) = self.depth_clip_enable {
|
||||||
@ -1183,6 +1170,13 @@ impl super::Adapter {
|
|||||||
capabilities.push(spv::Capability::MultiView);
|
capabilities.push(spv::Capability::MultiView);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if features.intersects(
|
||||||
|
wgt::Features::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING
|
||||||
|
| wgt::Features::UNIFORM_BUFFER_AND_STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING,
|
||||||
|
) {
|
||||||
|
capabilities.push(spv::Capability::ShaderNonUniform);
|
||||||
|
}
|
||||||
|
|
||||||
let mut flags = spv::WriterFlags::empty();
|
let mut flags = spv::WriterFlags::empty();
|
||||||
flags.set(
|
flags.set(
|
||||||
spv::WriterFlags::DEBUG,
|
spv::WriterFlags::DEBUG,
|
||||||
@ -1215,7 +1209,11 @@ impl super::Adapter {
|
|||||||
} else {
|
} else {
|
||||||
naga::proc::BoundsCheckPolicy::Restrict
|
naga::proc::BoundsCheckPolicy::Restrict
|
||||||
},
|
},
|
||||||
|
// TODO: support bounds checks on binding arrays
|
||||||
|
binding_array: naga::proc::BoundsCheckPolicy::Unchecked,
|
||||||
},
|
},
|
||||||
|
// We need to build this separately for each invocation, so just default it out here
|
||||||
|
binding_map: BTreeMap::default(),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -6,7 +6,12 @@ use inplace_it::inplace_or_alloc_from_iter;
|
|||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
borrow::Cow, collections::hash_map::Entry, ffi::CString, num::NonZeroU32, ptr, sync::Arc,
|
borrow::Cow,
|
||||||
|
collections::{hash_map::Entry, BTreeMap},
|
||||||
|
ffi::CString,
|
||||||
|
num::NonZeroU32,
|
||||||
|
ptr,
|
||||||
|
sync::Arc,
|
||||||
};
|
};
|
||||||
|
|
||||||
impl super::DeviceShared {
|
impl super::DeviceShared {
|
||||||
@ -628,6 +633,7 @@ impl super::Device {
|
|||||||
&self,
|
&self,
|
||||||
stage: &crate::ProgrammableStage<super::Api>,
|
stage: &crate::ProgrammableStage<super::Api>,
|
||||||
naga_stage: naga::ShaderStage,
|
naga_stage: naga::ShaderStage,
|
||||||
|
binding_map: &naga::back::spv::BindingMap,
|
||||||
) -> Result<CompiledStage, crate::PipelineError> {
|
) -> Result<CompiledStage, crate::PipelineError> {
|
||||||
let stage_flags = crate::auxil::map_naga_stage(naga_stage);
|
let stage_flags = crate::auxil::map_naga_stage(naga_stage);
|
||||||
let vk_module = match *stage.module {
|
let vk_module = match *stage.module {
|
||||||
@ -640,16 +646,21 @@ impl super::Device {
|
|||||||
entry_point: stage.entry_point.to_string(),
|
entry_point: stage.entry_point.to_string(),
|
||||||
shader_stage: naga_stage,
|
shader_stage: naga_stage,
|
||||||
};
|
};
|
||||||
let temp_options;
|
let needs_temp_options = !runtime_checks || !binding_map.is_empty();
|
||||||
let options = if !runtime_checks {
|
let mut temp_options;
|
||||||
temp_options = naga::back::spv::Options {
|
let options = if needs_temp_options {
|
||||||
bounds_check_policies: naga::proc::BoundsCheckPolicies {
|
temp_options = self.naga_options.clone();
|
||||||
|
if !runtime_checks {
|
||||||
|
temp_options.bounds_check_policies = naga::proc::BoundsCheckPolicies {
|
||||||
index: naga::proc::BoundsCheckPolicy::Unchecked,
|
index: naga::proc::BoundsCheckPolicy::Unchecked,
|
||||||
buffer: naga::proc::BoundsCheckPolicy::Unchecked,
|
buffer: naga::proc::BoundsCheckPolicy::Unchecked,
|
||||||
image: naga::proc::BoundsCheckPolicy::Unchecked,
|
image: naga::proc::BoundsCheckPolicy::Unchecked,
|
||||||
},
|
binding_array: naga::proc::BoundsCheckPolicy::Unchecked,
|
||||||
..self.naga_options.clone()
|
};
|
||||||
};
|
}
|
||||||
|
if !binding_map.is_empty() {
|
||||||
|
temp_options.binding_map = binding_map.clone();
|
||||||
|
}
|
||||||
&temp_options
|
&temp_options
|
||||||
} else {
|
} else {
|
||||||
&self.naga_options
|
&self.naga_options
|
||||||
@ -1100,6 +1111,13 @@ impl crate::Device<super::Api> for super::Device {
|
|||||||
|
|
||||||
let vk_info = vk::DescriptorSetLayoutCreateInfo::builder().bindings(&vk_bindings);
|
let vk_info = vk::DescriptorSetLayoutCreateInfo::builder().bindings(&vk_bindings);
|
||||||
|
|
||||||
|
let binding_arrays = desc
|
||||||
|
.entries
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.filter_map(|(idx, entry)| entry.count.map(|count| (idx as u32, count)))
|
||||||
|
.collect();
|
||||||
|
|
||||||
let mut binding_flag_info;
|
let mut binding_flag_info;
|
||||||
let binding_flag_vec;
|
let binding_flag_vec;
|
||||||
let mut requires_update_after_bind = false;
|
let mut requires_update_after_bind = false;
|
||||||
@ -1176,6 +1194,7 @@ impl crate::Device<super::Api> for super::Device {
|
|||||||
raw,
|
raw,
|
||||||
desc_count,
|
desc_count,
|
||||||
types: types.into_boxed_slice(),
|
types: types.into_boxed_slice(),
|
||||||
|
binding_arrays,
|
||||||
requires_update_after_bind,
|
requires_update_after_bind,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -1220,7 +1239,25 @@ impl crate::Device<super::Api> for super::Device {
|
|||||||
.set_object_name(vk::ObjectType::PIPELINE_LAYOUT, raw, label);
|
.set_object_name(vk::ObjectType::PIPELINE_LAYOUT, raw, label);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(super::PipelineLayout { raw })
|
let mut binding_arrays = BTreeMap::new();
|
||||||
|
for (group, &layout) in desc.bind_group_layouts.iter().enumerate() {
|
||||||
|
for &(binding, binding_array_size) in &layout.binding_arrays {
|
||||||
|
binding_arrays.insert(
|
||||||
|
naga::ResourceBinding {
|
||||||
|
group: group as u32,
|
||||||
|
binding,
|
||||||
|
},
|
||||||
|
naga::back::spv::BindingInfo {
|
||||||
|
binding_array_size: Some(binding_array_size.get()),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(super::PipelineLayout {
|
||||||
|
raw,
|
||||||
|
binding_arrays,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
unsafe fn destroy_pipeline_layout(&self, pipeline_layout: super::PipelineLayout) {
|
unsafe fn destroy_pipeline_layout(&self, pipeline_layout: super::PipelineLayout) {
|
||||||
self.shared
|
self.shared
|
||||||
@ -1266,11 +1303,15 @@ impl crate::Device<super::Api> for super::Device {
|
|||||||
write = match ty {
|
write = match ty {
|
||||||
vk::DescriptorType::SAMPLER => {
|
vk::DescriptorType::SAMPLER => {
|
||||||
let index = sampler_infos.len();
|
let index = sampler_infos.len();
|
||||||
let binding = desc.samplers[entry.resource_index as usize];
|
let start = entry.resource_index;
|
||||||
let vk_info = vk::DescriptorImageInfo::builder()
|
let end = start + entry.count;
|
||||||
.sampler(binding.raw)
|
sampler_infos.extend(desc.samplers[start as usize..end as usize].iter().map(
|
||||||
.build();
|
|binding| {
|
||||||
sampler_infos.push(vk_info);
|
vk::DescriptorImageInfo::builder()
|
||||||
|
.sampler(binding.raw)
|
||||||
|
.build()
|
||||||
|
},
|
||||||
|
));
|
||||||
write.image_info(&sampler_infos[index..])
|
write.image_info(&sampler_infos[index..])
|
||||||
}
|
}
|
||||||
vk::DescriptorType::SAMPLED_IMAGE | vk::DescriptorType::STORAGE_IMAGE => {
|
vk::DescriptorType::SAMPLED_IMAGE | vk::DescriptorType::STORAGE_IMAGE => {
|
||||||
@ -1344,6 +1385,7 @@ impl crate::Device<super::Api> for super::Device {
|
|||||||
index: naga::proc::BoundsCheckPolicy::Unchecked,
|
index: naga::proc::BoundsCheckPolicy::Unchecked,
|
||||||
buffer: naga::proc::BoundsCheckPolicy::Unchecked,
|
buffer: naga::proc::BoundsCheckPolicy::Unchecked,
|
||||||
image: naga::proc::BoundsCheckPolicy::Unchecked,
|
image: naga::proc::BoundsCheckPolicy::Unchecked,
|
||||||
|
binding_array: naga::proc::BoundsCheckPolicy::Unchecked,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
Cow::Owned(
|
Cow::Owned(
|
||||||
@ -1425,11 +1467,19 @@ impl crate::Device<super::Api> for super::Device {
|
|||||||
.primitive_restart_enable(desc.primitive.strip_index_format.is_some())
|
.primitive_restart_enable(desc.primitive.strip_index_format.is_some())
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let compiled_vs = self.compile_stage(&desc.vertex_stage, naga::ShaderStage::Vertex)?;
|
let compiled_vs = self.compile_stage(
|
||||||
|
&desc.vertex_stage,
|
||||||
|
naga::ShaderStage::Vertex,
|
||||||
|
&desc.layout.binding_arrays,
|
||||||
|
)?;
|
||||||
stages.push(compiled_vs.create_info);
|
stages.push(compiled_vs.create_info);
|
||||||
let compiled_fs = match desc.fragment_stage {
|
let compiled_fs = match desc.fragment_stage {
|
||||||
Some(ref stage) => {
|
Some(ref stage) => {
|
||||||
let compiled = self.compile_stage(stage, naga::ShaderStage::Fragment)?;
|
let compiled = self.compile_stage(
|
||||||
|
stage,
|
||||||
|
naga::ShaderStage::Fragment,
|
||||||
|
&desc.layout.binding_arrays,
|
||||||
|
)?;
|
||||||
stages.push(compiled.create_info);
|
stages.push(compiled.create_info);
|
||||||
Some(compiled)
|
Some(compiled)
|
||||||
}
|
}
|
||||||
@ -1604,7 +1654,11 @@ impl crate::Device<super::Api> for super::Device {
|
|||||||
&self,
|
&self,
|
||||||
desc: &crate::ComputePipelineDescriptor<super::Api>,
|
desc: &crate::ComputePipelineDescriptor<super::Api>,
|
||||||
) -> Result<super::ComputePipeline, crate::PipelineError> {
|
) -> Result<super::ComputePipeline, crate::PipelineError> {
|
||||||
let compiled = self.compile_stage(&desc.stage, naga::ShaderStage::Compute)?;
|
let compiled = self.compile_stage(
|
||||||
|
&desc.stage,
|
||||||
|
naga::ShaderStage::Compute,
|
||||||
|
&desc.layout.binding_arrays,
|
||||||
|
)?;
|
||||||
|
|
||||||
let vk_infos = [{
|
let vk_infos = [{
|
||||||
vk::ComputePipelineCreateInfo::builder()
|
vk::ComputePipelineCreateInfo::builder()
|
||||||
|
@ -398,12 +398,15 @@ pub struct BindGroupLayout {
|
|||||||
raw: vk::DescriptorSetLayout,
|
raw: vk::DescriptorSetLayout,
|
||||||
desc_count: gpu_descriptor::DescriptorTotalCount,
|
desc_count: gpu_descriptor::DescriptorTotalCount,
|
||||||
types: Box<[(vk::DescriptorType, u32)]>,
|
types: Box<[(vk::DescriptorType, u32)]>,
|
||||||
|
/// Map of binding index to size,
|
||||||
|
binding_arrays: Vec<(u32, NonZeroU32)>,
|
||||||
requires_update_after_bind: bool,
|
requires_update_after_bind: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct PipelineLayout {
|
pub struct PipelineLayout {
|
||||||
raw: vk::PipelineLayout,
|
raw: vk::PipelineLayout,
|
||||||
|
binding_arrays: naga::back::spv::BindingMap,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -348,16 +348,6 @@ bitflags::bitflags! {
|
|||||||
///
|
///
|
||||||
/// This is a native only feature.
|
/// This is a native only feature.
|
||||||
const PARTIALLY_BOUND_BINDING_ARRAY = 1 << 22;
|
const PARTIALLY_BOUND_BINDING_ARRAY = 1 << 22;
|
||||||
/// Allows the user to create unsized uniform arrays of bindings:
|
|
||||||
///
|
|
||||||
/// eg. `uniform texture2D textures[]`.
|
|
||||||
///
|
|
||||||
/// Supported platforms:
|
|
||||||
/// - DX12
|
|
||||||
/// - Vulkan 1.2+ (or VK_EXT_descriptor_indexing)'s runtimeDescriptorArray feature
|
|
||||||
///
|
|
||||||
/// This is a native only feature.
|
|
||||||
const UNSIZED_BINDING_ARRAY = 1 << 23;
|
|
||||||
/// Allows the user to call [`RenderPass::multi_draw_indirect`] and [`RenderPass::multi_draw_indexed_indirect`].
|
/// Allows the user to call [`RenderPass::multi_draw_indirect`] and [`RenderPass::multi_draw_indexed_indirect`].
|
||||||
///
|
///
|
||||||
/// Allows multiple indirect calls to be dispatched from a single buffer.
|
/// Allows multiple indirect calls to be dispatched from a single buffer.
|
||||||
@ -367,7 +357,7 @@ bitflags::bitflags! {
|
|||||||
/// - Vulkan
|
/// - Vulkan
|
||||||
///
|
///
|
||||||
/// This is a native only feature.
|
/// This is a native only feature.
|
||||||
const MULTI_DRAW_INDIRECT = 1 << 24;
|
const MULTI_DRAW_INDIRECT = 1 << 23;
|
||||||
/// Allows the user to call [`RenderPass::multi_draw_indirect_count`] and [`RenderPass::multi_draw_indexed_indirect_count`].
|
/// Allows the user to call [`RenderPass::multi_draw_indirect_count`] and [`RenderPass::multi_draw_indexed_indirect_count`].
|
||||||
///
|
///
|
||||||
/// This allows the use of a buffer containing the actual number of draw calls.
|
/// This allows the use of a buffer containing the actual number of draw calls.
|
||||||
@ -377,7 +367,7 @@ bitflags::bitflags! {
|
|||||||
/// - Vulkan 1.2+ (or VK_KHR_draw_indirect_count)
|
/// - Vulkan 1.2+ (or VK_KHR_draw_indirect_count)
|
||||||
///
|
///
|
||||||
/// This is a native only feature.
|
/// This is a native only feature.
|
||||||
const MULTI_DRAW_INDIRECT_COUNT = 1 << 25;
|
const MULTI_DRAW_INDIRECT_COUNT = 1 << 24;
|
||||||
/// Allows the use of push constants: small, fast bits of memory that can be updated
|
/// Allows the use of push constants: small, fast bits of memory that can be updated
|
||||||
/// inside a [`RenderPass`].
|
/// inside a [`RenderPass`].
|
||||||
///
|
///
|
||||||
@ -394,7 +384,7 @@ bitflags::bitflags! {
|
|||||||
/// - OpenGL (emulated with uniforms)
|
/// - OpenGL (emulated with uniforms)
|
||||||
///
|
///
|
||||||
/// This is a native only feature.
|
/// This is a native only feature.
|
||||||
const PUSH_CONSTANTS = 1 << 26;
|
const PUSH_CONSTANTS = 1 << 25;
|
||||||
/// Allows the use of [`AddressMode::ClampToBorder`] with a border color
|
/// Allows the use of [`AddressMode::ClampToBorder`] with a border color
|
||||||
/// other than [`SamplerBorderColor::Zero`].
|
/// other than [`SamplerBorderColor::Zero`].
|
||||||
///
|
///
|
||||||
@ -406,7 +396,7 @@ bitflags::bitflags! {
|
|||||||
/// - OpenGL
|
/// - OpenGL
|
||||||
///
|
///
|
||||||
/// This is a web and native feature.
|
/// This is a web and native feature.
|
||||||
const ADDRESS_MODE_CLAMP_TO_BORDER = 1 << 27;
|
const ADDRESS_MODE_CLAMP_TO_BORDER = 1 << 26;
|
||||||
/// Allows the user to set [`PolygonMode::Line`] in [`PrimitiveState::polygon_mode`]
|
/// Allows the user to set [`PolygonMode::Line`] in [`PrimitiveState::polygon_mode`]
|
||||||
///
|
///
|
||||||
/// This allows drawing polygons/triangles as lines (wireframe) instead of filled
|
/// This allows drawing polygons/triangles as lines (wireframe) instead of filled
|
||||||
@ -417,7 +407,7 @@ bitflags::bitflags! {
|
|||||||
/// - Metal
|
/// - Metal
|
||||||
///
|
///
|
||||||
/// This is a native only feature.
|
/// This is a native only feature.
|
||||||
const POLYGON_MODE_LINE = 1 << 28;
|
const POLYGON_MODE_LINE = 1 << 27;
|
||||||
/// Allows the user to set [`PolygonMode::Point`] in [`PrimitiveState::polygon_mode`]
|
/// Allows the user to set [`PolygonMode::Point`] in [`PrimitiveState::polygon_mode`]
|
||||||
///
|
///
|
||||||
/// This allows only drawing the vertices of polygons/triangles instead of filled
|
/// This allows only drawing the vertices of polygons/triangles instead of filled
|
||||||
@ -427,7 +417,7 @@ bitflags::bitflags! {
|
|||||||
/// - Vulkan
|
/// - Vulkan
|
||||||
///
|
///
|
||||||
/// This is a native only feature.
|
/// This is a native only feature.
|
||||||
const POLYGON_MODE_POINT = 1 << 29;
|
const POLYGON_MODE_POINT = 1 << 28;
|
||||||
/// Enables ETC family of compressed textures. All ETC textures use 4x4 pixel blocks.
|
/// Enables ETC family of compressed textures. All ETC textures use 4x4 pixel blocks.
|
||||||
/// ETC2 RGB and RGBA1 are 8 bytes per block. RTC2 RGBA8 and EAC are 16 bytes per block.
|
/// ETC2 RGB and RGBA1 are 8 bytes per block. RTC2 RGBA8 and EAC are 16 bytes per block.
|
||||||
///
|
///
|
||||||
@ -442,7 +432,7 @@ bitflags::bitflags! {
|
|||||||
/// - Mobile (some)
|
/// - Mobile (some)
|
||||||
///
|
///
|
||||||
/// This is a native-only feature.
|
/// This is a native-only feature.
|
||||||
const TEXTURE_COMPRESSION_ETC2 = 1 << 30;
|
const TEXTURE_COMPRESSION_ETC2 = 1 << 29;
|
||||||
/// Enables ASTC family of compressed textures. ASTC textures use pixel blocks varying from 4x4 to 12x12.
|
/// Enables ASTC family of compressed textures. ASTC textures use pixel blocks varying from 4x4 to 12x12.
|
||||||
/// Blocks are always 16 bytes.
|
/// Blocks are always 16 bytes.
|
||||||
///
|
///
|
||||||
@ -457,7 +447,7 @@ bitflags::bitflags! {
|
|||||||
/// - Mobile (some)
|
/// - Mobile (some)
|
||||||
///
|
///
|
||||||
/// This is a native-only feature.
|
/// This is a native-only feature.
|
||||||
const TEXTURE_COMPRESSION_ASTC_LDR = 1 << 31;
|
const TEXTURE_COMPRESSION_ASTC_LDR = 1 << 30;
|
||||||
/// Enables device specific texture format features.
|
/// Enables device specific texture format features.
|
||||||
///
|
///
|
||||||
/// See `TextureFormatFeatures` for a listing of the features in question.
|
/// See `TextureFormatFeatures` for a listing of the features in question.
|
||||||
@ -469,7 +459,7 @@ bitflags::bitflags! {
|
|||||||
/// This extension does not enable additional formats.
|
/// This extension does not enable additional formats.
|
||||||
///
|
///
|
||||||
/// This is a native-only feature.
|
/// This is a native-only feature.
|
||||||
const TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES = 1 << 32;
|
const TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES = 1 << 31;
|
||||||
/// Enables 64-bit floating point types in SPIR-V shaders.
|
/// Enables 64-bit floating point types in SPIR-V shaders.
|
||||||
///
|
///
|
||||||
/// Note: even when supported by GPU hardware, 64-bit floating point operations are
|
/// Note: even when supported by GPU hardware, 64-bit floating point operations are
|
||||||
@ -479,7 +469,7 @@ bitflags::bitflags! {
|
|||||||
/// - Vulkan
|
/// - Vulkan
|
||||||
///
|
///
|
||||||
/// This is a native-only feature.
|
/// This is a native-only feature.
|
||||||
const SHADER_FLOAT64 = 1 << 33;
|
const SHADER_FLOAT64 = 1 << 32;
|
||||||
/// Enables using 64-bit types for vertex attributes.
|
/// Enables using 64-bit types for vertex attributes.
|
||||||
///
|
///
|
||||||
/// Requires SHADER_FLOAT64.
|
/// Requires SHADER_FLOAT64.
|
||||||
@ -487,7 +477,7 @@ bitflags::bitflags! {
|
|||||||
/// Supported Platforms: N/A
|
/// Supported Platforms: N/A
|
||||||
///
|
///
|
||||||
/// This is a native-only feature.
|
/// This is a native-only feature.
|
||||||
const VERTEX_ATTRIBUTE_64BIT = 1 << 34;
|
const VERTEX_ATTRIBUTE_64BIT = 1 << 33;
|
||||||
/// Allows the user to set a overestimation-conservative-rasterization in [`PrimitiveState::conservative`]
|
/// Allows the user to set a overestimation-conservative-rasterization in [`PrimitiveState::conservative`]
|
||||||
///
|
///
|
||||||
/// Processing of degenerate triangles/lines is hardware specific.
|
/// Processing of degenerate triangles/lines is hardware specific.
|
||||||
@ -497,7 +487,7 @@ bitflags::bitflags! {
|
|||||||
/// - Vulkan
|
/// - Vulkan
|
||||||
///
|
///
|
||||||
/// This is a native only feature.
|
/// This is a native only feature.
|
||||||
const CONSERVATIVE_RASTERIZATION = 1 << 35;
|
const CONSERVATIVE_RASTERIZATION = 1 << 34;
|
||||||
/// Enables bindings of writable storage buffers and textures visible to vertex shaders.
|
/// Enables bindings of writable storage buffers and textures visible to vertex shaders.
|
||||||
///
|
///
|
||||||
/// Note: some (tiled-based) platforms do not support vertex shaders with any side-effects.
|
/// Note: some (tiled-based) platforms do not support vertex shaders with any side-effects.
|
||||||
@ -506,14 +496,14 @@ bitflags::bitflags! {
|
|||||||
/// - All
|
/// - All
|
||||||
///
|
///
|
||||||
/// This is a native-only feature.
|
/// This is a native-only feature.
|
||||||
const VERTEX_WRITABLE_STORAGE = 1 << 36;
|
const VERTEX_WRITABLE_STORAGE = 1 << 35;
|
||||||
/// Enables clear to zero for textures.
|
/// Enables clear to zero for textures.
|
||||||
///
|
///
|
||||||
/// Supported platforms:
|
/// Supported platforms:
|
||||||
/// - All
|
/// - All
|
||||||
///
|
///
|
||||||
/// This is a native only feature.
|
/// This is a native only feature.
|
||||||
const CLEAR_TEXTURE = 1 << 37;
|
const CLEAR_TEXTURE = 1 << 36;
|
||||||
/// Enables creating shader modules from SPIR-V binary data (unsafe).
|
/// Enables creating shader modules from SPIR-V binary data (unsafe).
|
||||||
///
|
///
|
||||||
/// SPIR-V data is not parsed or interpreted in any way; you can use
|
/// SPIR-V data is not parsed or interpreted in any way; you can use
|
||||||
@ -525,7 +515,7 @@ bitflags::bitflags! {
|
|||||||
/// Vulkan implementation.
|
/// Vulkan implementation.
|
||||||
///
|
///
|
||||||
/// This is a native only feature.
|
/// This is a native only feature.
|
||||||
const SPIRV_SHADER_PASSTHROUGH = 1 << 38;
|
const SPIRV_SHADER_PASSTHROUGH = 1 << 37;
|
||||||
/// Enables `builtin(primitive_index)` in fragment shaders.
|
/// Enables `builtin(primitive_index)` in fragment shaders.
|
||||||
///
|
///
|
||||||
/// Note: enables geometry processing for pipelines using the builtin.
|
/// Note: enables geometry processing for pipelines using the builtin.
|
||||||
@ -536,14 +526,14 @@ bitflags::bitflags! {
|
|||||||
/// - Vulkan
|
/// - Vulkan
|
||||||
///
|
///
|
||||||
/// This is a native only feature.
|
/// This is a native only feature.
|
||||||
const SHADER_PRIMITIVE_INDEX = 1 << 39;
|
const SHADER_PRIMITIVE_INDEX = 1 << 38;
|
||||||
/// Enables multiview render passes and `builtin(view_index)` in vertex shaders.
|
/// Enables multiview render passes and `builtin(view_index)` in vertex shaders.
|
||||||
///
|
///
|
||||||
/// Supported platforms:
|
/// Supported platforms:
|
||||||
/// - Vulkan
|
/// - Vulkan
|
||||||
///
|
///
|
||||||
/// This is a native only feature.
|
/// This is a native only feature.
|
||||||
const MULTIVIEW = 1 << 40;
|
const MULTIVIEW = 1 << 39;
|
||||||
/// Enables normalized `16-bit` texture formats.
|
/// Enables normalized `16-bit` texture formats.
|
||||||
///
|
///
|
||||||
/// Supported platforms:
|
/// Supported platforms:
|
||||||
@ -552,7 +542,7 @@ bitflags::bitflags! {
|
|||||||
/// - Metal
|
/// - Metal
|
||||||
///
|
///
|
||||||
/// This is a native only feature.
|
/// This is a native only feature.
|
||||||
const TEXTURE_FORMAT_16BIT_NORM = 1 << 41;
|
const TEXTURE_FORMAT_16BIT_NORM = 1 << 40;
|
||||||
/// Allows the use of [`AddressMode::ClampToBorder`] with a border color
|
/// Allows the use of [`AddressMode::ClampToBorder`] with a border color
|
||||||
/// of [`SamplerBorderColor::Zero`].
|
/// of [`SamplerBorderColor::Zero`].
|
||||||
///
|
///
|
||||||
@ -564,12 +554,12 @@ bitflags::bitflags! {
|
|||||||
/// - OpenGL
|
/// - OpenGL
|
||||||
///
|
///
|
||||||
/// This is a native only feature.
|
/// This is a native only feature.
|
||||||
const ADDRESS_MODE_CLAMP_TO_ZERO = 1 << 42;
|
const ADDRESS_MODE_CLAMP_TO_ZERO = 1 << 41;
|
||||||
/// Supported Platforms:
|
/// Supported Platforms:
|
||||||
/// - Metal
|
/// - Metal
|
||||||
///
|
///
|
||||||
/// This is a native-only feature.
|
/// This is a native-only feature.
|
||||||
const TEXTURE_COMPRESSION_ASTC_HDR = 1 << 43;
|
const TEXTURE_COMPRESSION_ASTC_HDR = 1 << 42;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,7 +69,6 @@ test = true
|
|||||||
|
|
||||||
[[example]]
|
[[example]]
|
||||||
name="texture-arrays"
|
name="texture-arrays"
|
||||||
required-features = ["spirv"]
|
|
||||||
test = true
|
test = true
|
||||||
|
|
||||||
[[example]]
|
[[example]]
|
||||||
@ -139,20 +138,20 @@ env_logger = "0.9"
|
|||||||
|
|
||||||
[dependencies.naga]
|
[dependencies.naga]
|
||||||
git = "https://github.com/gfx-rs/naga"
|
git = "https://github.com/gfx-rs/naga"
|
||||||
rev = "85056524"
|
rev = "1aa91549"
|
||||||
#version = "0.8"
|
#version = "0.8"
|
||||||
optional = true
|
optional = true
|
||||||
|
|
||||||
# used to test all the example shaders
|
# used to test all the example shaders
|
||||||
[dev-dependencies.naga]
|
[dev-dependencies.naga]
|
||||||
git = "https://github.com/gfx-rs/naga"
|
git = "https://github.com/gfx-rs/naga"
|
||||||
rev = "85056524"
|
rev = "1aa91549"
|
||||||
#version = "0.8"
|
#version = "0.8"
|
||||||
features = ["wgsl-in"]
|
features = ["wgsl-in"]
|
||||||
|
|
||||||
[target.'cfg(target_arch = "wasm32")'.dependencies.naga]
|
[target.'cfg(target_arch = "wasm32")'.dependencies.naga]
|
||||||
git = "https://github.com/gfx-rs/naga"
|
git = "https://github.com/gfx-rs/naga"
|
||||||
rev = "85056524"
|
rev = "1aa91549"
|
||||||
#version = "0.8"
|
#version = "0.8"
|
||||||
features = ["wgsl-out"]
|
features = ["wgsl-out"]
|
||||||
|
|
||||||
|
@ -21,7 +21,6 @@ All framework-based examples render to the window and are reftested against the
|
|||||||
| implicit layout | | | | :star: | | | | | | |
|
| implicit layout | | | | :star: | | | | | | |
|
||||||
| sampled color textures | :star: | :star: | :star: | :star: | | | :star: | :star: | :star: | :star: |
|
| sampled color textures | :star: | :star: | :star: | :star: | | | :star: | :star: | :star: | :star: |
|
||||||
| storage textures | :star: | | | | | | | | | |
|
| storage textures | :star: | | | | | | | | | |
|
||||||
| binding array | | | | | | | | :star: | | |
|
|
||||||
| comparison samplers | | | | | | :star: | | | | |
|
| comparison samplers | | | | | | :star: | | | | |
|
||||||
| subresource views | | | | :star: | | :star: | | | | |
|
| subresource views | | | | :star: | | :star: | | | | |
|
||||||
| cubemaps | | | | | | | :star: | | | |
|
| cubemaps | | | | | | | :star: | | | |
|
||||||
@ -36,9 +35,9 @@ All framework-based examples render to the window and are reftested against the
|
|||||||
| compute passes | :star: | | | | | | | | | |
|
| compute passes | :star: | | | | | | | | | |
|
||||||
| error scopes | | | :star: | | | | | | | |
|
| error scopes | | | :star: | | | | | | | |
|
||||||
| *optional extensions* | | | | | | | | :star: | | |
|
| *optional extensions* | | | | | | | | :star: | | |
|
||||||
| - SPIR-V shaders | | | | | | | | :star: | | |
|
| - SPIR-V shaders | | | | | | | | | | |
|
||||||
| - binding indexing | | | | | | | | :star: | | |
|
| - binding array | | | | | | | | :star: | | |
|
||||||
| - push constants | | | | | | | | :star: | | |
|
| - push constants | | | | | | | | | | |
|
||||||
| - depth clamping | | | | | | :star: | | | | |
|
| - depth clamping | | | | | | :star: | | | | |
|
||||||
| - compressed textures | | | | | | | :star: | | | |
|
| - compressed textures | | | | | | | :star: | | | |
|
||||||
| - polygon mode | | | :star: | | | | | | | |
|
| - polygon mode | | | :star: | | | | | | | |
|
||||||
|
@ -1,19 +0,0 @@
|
|||||||
#version 450
|
|
||||||
|
|
||||||
layout(location = 0) in vec2 v_TexCoord;
|
|
||||||
layout(location = 1) flat in int v_Index; // dynamically non-uniform
|
|
||||||
layout(location = 0) out vec4 o_Color;
|
|
||||||
|
|
||||||
layout(set = 0, binding = 0) uniform texture2D u_Textures[2];
|
|
||||||
layout(set = 0, binding = 1) uniform sampler u_Sampler[2];
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
if (v_Index == 0) {
|
|
||||||
o_Color = vec4(texture(sampler2D(u_Textures[0], u_Sampler[0]), v_TexCoord).rgb, 1.0);
|
|
||||||
} else if (v_Index == 1) {
|
|
||||||
o_Color = vec4(texture(sampler2D(u_Textures[1], u_Sampler[1]), v_TexCoord).rgb, 1.0);
|
|
||||||
} else {
|
|
||||||
// We need to write something to output color
|
|
||||||
o_Color = vec4(0.0, 0.0, 1.0, 0.0);
|
|
||||||
}
|
|
||||||
}
|
|
Binary file not shown.
61
wgpu/examples/texture-arrays/indexing.wgsl
Normal file
61
wgpu/examples/texture-arrays/indexing.wgsl
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
struct VertexInput {
|
||||||
|
@location(0) position: vec2<f32>,
|
||||||
|
@location(1) tex_coord: vec2<f32>,
|
||||||
|
@location(2) index: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct VertexOutput {
|
||||||
|
@builtin(position) position: vec4<f32>,
|
||||||
|
@location(0) tex_coord: vec2<f32>,
|
||||||
|
@location(1) index: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
@vertex
|
||||||
|
fn vert_main(vertex: VertexInput) -> VertexOutput {
|
||||||
|
var outval: VertexOutput;
|
||||||
|
outval.position = vec4<f32>(vertex.position.x, vertex.position.y, 0.0, 1.0);
|
||||||
|
outval.tex_coord = vertex.tex_coord;
|
||||||
|
outval.index = vertex.index;
|
||||||
|
return outval;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct FragmentInput {
|
||||||
|
@location(0) tex_coord: vec2<f32>,
|
||||||
|
@location(1) index: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
@group(0) @binding(0)
|
||||||
|
var texture_array_top: binding_array<texture_2d<f32>>;
|
||||||
|
@group(0) @binding(1)
|
||||||
|
var texture_array_bottom: binding_array<texture_2d<f32>>;
|
||||||
|
@group(0) @binding(2)
|
||||||
|
var sampler_array: binding_array<sampler>;
|
||||||
|
|
||||||
|
struct Uniforms {
|
||||||
|
index: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
@group(0) @binding(3)
|
||||||
|
var<uniform> uniforms: Uniforms;
|
||||||
|
|
||||||
|
@fragment
|
||||||
|
fn uniform_main(fragment: FragmentInput) -> @location(0) vec4<f32> {
|
||||||
|
var outval: vec3<f32>;
|
||||||
|
if fragment.tex_coord.y <= 0.5 {
|
||||||
|
outval = textureSampleLevel(
|
||||||
|
texture_array_top[uniforms.index],
|
||||||
|
sampler_array[uniforms.index],
|
||||||
|
fragment.tex_coord,
|
||||||
|
0.0
|
||||||
|
).rgb;
|
||||||
|
} else {
|
||||||
|
outval = textureSampleLevel(
|
||||||
|
texture_array_bottom[uniforms.index],
|
||||||
|
sampler_array[uniforms.index],
|
||||||
|
fragment.tex_coord,
|
||||||
|
0.0
|
||||||
|
).rgb;
|
||||||
|
}
|
||||||
|
|
||||||
|
return vec4<f32>(outval.x, outval.y, outval.z, 1.0);
|
||||||
|
}
|
@ -2,7 +2,7 @@
|
|||||||
mod framework;
|
mod framework;
|
||||||
|
|
||||||
use bytemuck::{Pod, Zeroable};
|
use bytemuck::{Pod, Zeroable};
|
||||||
use std::num::NonZeroU32;
|
use std::num::{NonZeroU32, NonZeroU64};
|
||||||
use wgpu::util::DeviceExt;
|
use wgpu::util::DeviceExt;
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
@ -51,12 +51,16 @@ fn create_indices() -> Vec<u16> {
|
|||||||
enum Color {
|
enum Color {
|
||||||
Red,
|
Red,
|
||||||
Green,
|
Green,
|
||||||
|
Blue,
|
||||||
|
White,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_texture_data(color: Color) -> [u8; 4] {
|
fn create_texture_data(color: Color) -> [u8; 4] {
|
||||||
match color {
|
match color {
|
||||||
Color::Red => [255, 0, 0, 255],
|
Color::Red => [255, 0, 0, 255],
|
||||||
Color::Green => [0, 255, 0, 255],
|
Color::Green => [0, 255, 0, 255],
|
||||||
|
Color::Blue => [0, 0, 255, 255],
|
||||||
|
Color::White => [255, 255, 255, 255],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,18 +75,10 @@ struct Example {
|
|||||||
|
|
||||||
impl framework::Example for Example {
|
impl framework::Example for Example {
|
||||||
fn optional_features() -> wgpu::Features {
|
fn optional_features() -> wgpu::Features {
|
||||||
wgpu::Features::UNSIZED_BINDING_ARRAY
|
wgpu::Features::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING
|
||||||
| wgpu::Features::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING
|
|
||||||
| wgpu::Features::PUSH_CONSTANTS
|
|
||||||
}
|
}
|
||||||
fn required_features() -> wgpu::Features {
|
fn required_features() -> wgpu::Features {
|
||||||
wgpu::Features::TEXTURE_BINDING_ARRAY | wgpu::Features::SPIRV_SHADER_PASSTHROUGH
|
wgpu::Features::TEXTURE_BINDING_ARRAY
|
||||||
}
|
|
||||||
fn required_limits() -> wgpu::Limits {
|
|
||||||
wgpu::Limits {
|
|
||||||
max_push_constant_size: 4,
|
|
||||||
..wgpu::Limits::default()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
fn init(
|
fn init(
|
||||||
config: &wgpu::SurfaceConfiguration,
|
config: &wgpu::SurfaceConfiguration,
|
||||||
@ -91,24 +87,45 @@ impl framework::Example for Example {
|
|||||||
queue: &wgpu::Queue,
|
queue: &wgpu::Queue,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let mut uniform_workaround = false;
|
let mut uniform_workaround = false;
|
||||||
let vs_module = device.create_shader_module(&wgpu::include_spirv!("shader.vert.spv"));
|
let base_shader_module = device.create_shader_module(&wgpu::include_wgsl!("indexing.wgsl"));
|
||||||
let fs_source = match device.features() {
|
let env_override = match std::env::var("WGPU_TEXTURE_ARRAY_STYLE") {
|
||||||
f if f.contains(wgpu::Features::UNSIZED_BINDING_ARRAY) => {
|
Ok(value) => match &*value.to_lowercase() {
|
||||||
wgpu::include_spirv_raw!("unsized-non-uniform.frag.spv")
|
"nonuniform" | "non_uniform" => Some(true),
|
||||||
}
|
"uniform" => Some(false),
|
||||||
f if f.contains(
|
_ => None,
|
||||||
wgpu::Features::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING,
|
},
|
||||||
) =>
|
Err(_) => None,
|
||||||
{
|
|
||||||
wgpu::include_spirv_raw!("non-uniform.frag.spv")
|
|
||||||
}
|
|
||||||
f if f.contains(wgpu::Features::TEXTURE_BINDING_ARRAY) => {
|
|
||||||
uniform_workaround = true;
|
|
||||||
wgpu::include_spirv_raw!("uniform.frag.spv")
|
|
||||||
}
|
|
||||||
_ => unreachable!(),
|
|
||||||
};
|
};
|
||||||
let fs_module = unsafe { device.create_shader_module_spirv(&fs_source) };
|
let fragment_entry_point = match (device.features(), env_override) {
|
||||||
|
(_, Some(false)) => {
|
||||||
|
uniform_workaround = true;
|
||||||
|
"uniform_main"
|
||||||
|
}
|
||||||
|
(_, Some(true)) => "non_uniform_main",
|
||||||
|
(f, _)
|
||||||
|
if f.contains(
|
||||||
|
wgpu::Features::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING,
|
||||||
|
) =>
|
||||||
|
{
|
||||||
|
"non_uniform_main"
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
uniform_workaround = true;
|
||||||
|
"uniform_main"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let non_uniform_shader_module;
|
||||||
|
// TODO: Because naga's capibilities are evaluated on validate, not on write, we cannot make a shader module with unsupported
|
||||||
|
// capabilities even if we don't use it. So for now put it in a separate module.
|
||||||
|
let fragment_shader_module = if !uniform_workaround {
|
||||||
|
non_uniform_shader_module =
|
||||||
|
device.create_shader_module(&wgpu::include_wgsl!("non_uniform_indexing.wgsl"));
|
||||||
|
&non_uniform_shader_module
|
||||||
|
} else {
|
||||||
|
&base_shader_module
|
||||||
|
};
|
||||||
|
|
||||||
|
println!("Using fragment entry point '{}'", fragment_entry_point);
|
||||||
|
|
||||||
let vertex_size = std::mem::size_of::<Vertex>();
|
let vertex_size = std::mem::size_of::<Vertex>();
|
||||||
let vertex_data = create_vertices();
|
let vertex_data = create_vertices();
|
||||||
@ -125,8 +142,19 @@ impl framework::Example for Example {
|
|||||||
usage: wgpu::BufferUsages::INDEX,
|
usage: wgpu::BufferUsages::INDEX,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let mut texture_index_buffer_contents = vec![0u32; 128];
|
||||||
|
texture_index_buffer_contents[0] = 0;
|
||||||
|
texture_index_buffer_contents[64] = 1;
|
||||||
|
let texture_index_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||||
|
label: Some("Index Buffer"),
|
||||||
|
contents: bytemuck::cast_slice(&texture_index_buffer_contents),
|
||||||
|
usage: wgpu::BufferUsages::UNIFORM,
|
||||||
|
});
|
||||||
|
|
||||||
let red_texture_data = create_texture_data(Color::Red);
|
let red_texture_data = create_texture_data(Color::Red);
|
||||||
let green_texture_data = create_texture_data(Color::Green);
|
let green_texture_data = create_texture_data(Color::Green);
|
||||||
|
let blue_texture_data = create_texture_data(Color::Blue);
|
||||||
|
let white_texture_data = create_texture_data(Color::White);
|
||||||
|
|
||||||
let texture_descriptor = wgpu::TextureDescriptor {
|
let texture_descriptor = wgpu::TextureDescriptor {
|
||||||
size: wgpu::Extent3d::default(),
|
size: wgpu::Extent3d::default(),
|
||||||
@ -145,9 +173,19 @@ impl framework::Example for Example {
|
|||||||
label: Some("green"),
|
label: Some("green"),
|
||||||
..texture_descriptor
|
..texture_descriptor
|
||||||
});
|
});
|
||||||
|
let blue_texture = device.create_texture(&wgpu::TextureDescriptor {
|
||||||
|
label: Some("blue"),
|
||||||
|
..texture_descriptor
|
||||||
|
});
|
||||||
|
let white_texture = device.create_texture(&wgpu::TextureDescriptor {
|
||||||
|
label: Some("white"),
|
||||||
|
..texture_descriptor
|
||||||
|
});
|
||||||
|
|
||||||
let red_texture_view = red_texture.create_view(&wgpu::TextureViewDescriptor::default());
|
let red_texture_view = red_texture.create_view(&wgpu::TextureViewDescriptor::default());
|
||||||
let green_texture_view = green_texture.create_view(&wgpu::TextureViewDescriptor::default());
|
let green_texture_view = green_texture.create_view(&wgpu::TextureViewDescriptor::default());
|
||||||
|
let blue_texture_view = blue_texture.create_view(&wgpu::TextureViewDescriptor::default());
|
||||||
|
let white_texture_view = white_texture.create_view(&wgpu::TextureViewDescriptor::default());
|
||||||
|
|
||||||
queue.write_texture(
|
queue.write_texture(
|
||||||
red_texture.as_image_copy(),
|
red_texture.as_image_copy(),
|
||||||
@ -169,6 +207,26 @@ impl framework::Example for Example {
|
|||||||
},
|
},
|
||||||
wgpu::Extent3d::default(),
|
wgpu::Extent3d::default(),
|
||||||
);
|
);
|
||||||
|
queue.write_texture(
|
||||||
|
blue_texture.as_image_copy(),
|
||||||
|
&blue_texture_data,
|
||||||
|
wgpu::ImageDataLayout {
|
||||||
|
offset: 0,
|
||||||
|
bytes_per_row: Some(NonZeroU32::new(4).unwrap()),
|
||||||
|
rows_per_image: None,
|
||||||
|
},
|
||||||
|
wgpu::Extent3d::default(),
|
||||||
|
);
|
||||||
|
queue.write_texture(
|
||||||
|
white_texture.as_image_copy(),
|
||||||
|
&white_texture_data,
|
||||||
|
wgpu::ImageDataLayout {
|
||||||
|
offset: 0,
|
||||||
|
bytes_per_row: Some(NonZeroU32::new(4).unwrap()),
|
||||||
|
rows_per_image: None,
|
||||||
|
},
|
||||||
|
wgpu::Extent3d::default(),
|
||||||
|
);
|
||||||
|
|
||||||
let sampler = device.create_sampler(&wgpu::SamplerDescriptor::default());
|
let sampler = device.create_sampler(&wgpu::SamplerDescriptor::default());
|
||||||
|
|
||||||
@ -188,9 +246,29 @@ impl framework::Example for Example {
|
|||||||
wgpu::BindGroupLayoutEntry {
|
wgpu::BindGroupLayoutEntry {
|
||||||
binding: 1,
|
binding: 1,
|
||||||
visibility: wgpu::ShaderStages::FRAGMENT,
|
visibility: wgpu::ShaderStages::FRAGMENT,
|
||||||
|
ty: wgpu::BindingType::Texture {
|
||||||
|
sample_type: wgpu::TextureSampleType::Float { filterable: true },
|
||||||
|
view_dimension: wgpu::TextureViewDimension::D2,
|
||||||
|
multisampled: false,
|
||||||
|
},
|
||||||
|
count: NonZeroU32::new(2),
|
||||||
|
},
|
||||||
|
wgpu::BindGroupLayoutEntry {
|
||||||
|
binding: 2,
|
||||||
|
visibility: wgpu::ShaderStages::FRAGMENT,
|
||||||
ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering),
|
ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering),
|
||||||
count: NonZeroU32::new(2),
|
count: NonZeroU32::new(2),
|
||||||
},
|
},
|
||||||
|
wgpu::BindGroupLayoutEntry {
|
||||||
|
binding: 3,
|
||||||
|
visibility: wgpu::ShaderStages::FRAGMENT,
|
||||||
|
ty: wgpu::BindingType::Buffer {
|
||||||
|
ty: wgpu::BufferBindingType::Uniform,
|
||||||
|
has_dynamic_offset: true,
|
||||||
|
min_binding_size: Some(NonZeroU64::new(4).unwrap()),
|
||||||
|
},
|
||||||
|
count: None,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -205,8 +283,23 @@ impl framework::Example for Example {
|
|||||||
},
|
},
|
||||||
wgpu::BindGroupEntry {
|
wgpu::BindGroupEntry {
|
||||||
binding: 1,
|
binding: 1,
|
||||||
|
resource: wgpu::BindingResource::TextureViewArray(&[
|
||||||
|
&blue_texture_view,
|
||||||
|
&white_texture_view,
|
||||||
|
]),
|
||||||
|
},
|
||||||
|
wgpu::BindGroupEntry {
|
||||||
|
binding: 2,
|
||||||
resource: wgpu::BindingResource::SamplerArray(&[&sampler, &sampler]),
|
resource: wgpu::BindingResource::SamplerArray(&[&sampler, &sampler]),
|
||||||
},
|
},
|
||||||
|
wgpu::BindGroupEntry {
|
||||||
|
binding: 3,
|
||||||
|
resource: wgpu::BindingResource::Buffer(wgpu::BufferBinding {
|
||||||
|
buffer: &texture_index_buffer,
|
||||||
|
offset: 0,
|
||||||
|
size: Some(NonZeroU64::new(4).unwrap()),
|
||||||
|
}),
|
||||||
|
},
|
||||||
],
|
],
|
||||||
layout: &bind_group_layout,
|
layout: &bind_group_layout,
|
||||||
label: Some("bind group"),
|
label: Some("bind group"),
|
||||||
@ -215,14 +308,7 @@ impl framework::Example for Example {
|
|||||||
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||||
label: Some("main"),
|
label: Some("main"),
|
||||||
bind_group_layouts: &[&bind_group_layout],
|
bind_group_layouts: &[&bind_group_layout],
|
||||||
push_constant_ranges: if uniform_workaround {
|
push_constant_ranges: &[],
|
||||||
&[wgpu::PushConstantRange {
|
|
||||||
stages: wgpu::ShaderStages::FRAGMENT,
|
|
||||||
range: 0..4,
|
|
||||||
}]
|
|
||||||
} else {
|
|
||||||
&[]
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
let index_format = wgpu::IndexFormat::Uint16;
|
let index_format = wgpu::IndexFormat::Uint16;
|
||||||
@ -231,8 +317,8 @@ impl framework::Example for Example {
|
|||||||
label: None,
|
label: None,
|
||||||
layout: Some(&pipeline_layout),
|
layout: Some(&pipeline_layout),
|
||||||
vertex: wgpu::VertexState {
|
vertex: wgpu::VertexState {
|
||||||
module: &vs_module,
|
module: &base_shader_module,
|
||||||
entry_point: "main",
|
entry_point: "vert_main",
|
||||||
buffers: &[wgpu::VertexBufferLayout {
|
buffers: &[wgpu::VertexBufferLayout {
|
||||||
array_stride: vertex_size as wgpu::BufferAddress,
|
array_stride: vertex_size as wgpu::BufferAddress,
|
||||||
step_mode: wgpu::VertexStepMode::Vertex,
|
step_mode: wgpu::VertexStepMode::Vertex,
|
||||||
@ -240,8 +326,8 @@ impl framework::Example for Example {
|
|||||||
}],
|
}],
|
||||||
},
|
},
|
||||||
fragment: Some(wgpu::FragmentState {
|
fragment: Some(wgpu::FragmentState {
|
||||||
module: &fs_module,
|
module: fragment_shader_module,
|
||||||
entry_point: "main",
|
entry_point: fragment_entry_point,
|
||||||
targets: &[config.format.into()],
|
targets: &[config.format.into()],
|
||||||
}),
|
}),
|
||||||
primitive: wgpu::PrimitiveState {
|
primitive: wgpu::PrimitiveState {
|
||||||
@ -298,15 +384,15 @@ impl framework::Example for Example {
|
|||||||
});
|
});
|
||||||
|
|
||||||
rpass.set_pipeline(&self.pipeline);
|
rpass.set_pipeline(&self.pipeline);
|
||||||
rpass.set_bind_group(0, &self.bind_group, &[]);
|
|
||||||
rpass.set_vertex_buffer(0, self.vertex_buffer.slice(..));
|
rpass.set_vertex_buffer(0, self.vertex_buffer.slice(..));
|
||||||
rpass.set_index_buffer(self.index_buffer.slice(..), self.index_format);
|
rpass.set_index_buffer(self.index_buffer.slice(..), self.index_format);
|
||||||
if self.uniform_workaround {
|
if self.uniform_workaround {
|
||||||
rpass.set_push_constants(wgpu::ShaderStages::FRAGMENT, 0, bytemuck::cast_slice(&[0]));
|
rpass.set_bind_group(0, &self.bind_group, &[0]);
|
||||||
rpass.draw_indexed(0..6, 0, 0..1);
|
rpass.draw_indexed(0..6, 0, 0..1);
|
||||||
rpass.set_push_constants(wgpu::ShaderStages::FRAGMENT, 0, bytemuck::cast_slice(&[1]));
|
rpass.set_bind_group(0, &self.bind_group, &[256]);
|
||||||
rpass.draw_indexed(6..12, 0, 0..1);
|
rpass.draw_indexed(6..12, 0, 0..1);
|
||||||
} else {
|
} else {
|
||||||
|
rpass.set_bind_group(0, &self.bind_group, &[0]);
|
||||||
rpass.draw_indexed(0..12, 0, 0..1);
|
rpass.draw_indexed(0..12, 0, 0..1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -320,60 +406,28 @@ fn main() {
|
|||||||
framework::run::<Example>("texture-arrays");
|
framework::run::<Example>("texture-arrays");
|
||||||
}
|
}
|
||||||
|
|
||||||
// This fails due to an issue with naga https://github.com/gfx-rs/wgpu/issues/1532
|
|
||||||
#[test]
|
|
||||||
fn texture_arrays_constant() {
|
|
||||||
framework::test::<Example>(framework::FrameworkRefTest {
|
|
||||||
image_path: "/examples/texture-arrays/screenshot.png",
|
|
||||||
width: 1024,
|
|
||||||
height: 768,
|
|
||||||
optional_features: wgpu::Features::default(),
|
|
||||||
base_test_parameters: framework::test_common::TestParameters::default().failure(),
|
|
||||||
tolerance: 0,
|
|
||||||
max_outliers: 0,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// This fails due to an issue with naga https://github.com/gfx-rs/wgpu/issues/1532
|
|
||||||
#[test]
|
#[test]
|
||||||
fn texture_arrays_uniform() {
|
fn texture_arrays_uniform() {
|
||||||
framework::test::<Example>(framework::FrameworkRefTest {
|
framework::test::<Example>(framework::FrameworkRefTest {
|
||||||
image_path: "/examples/texture-arrays/screenshot.png",
|
image_path: "/examples/texture-arrays/screenshot.png",
|
||||||
width: 1024,
|
width: 1024,
|
||||||
height: 768,
|
height: 768,
|
||||||
optional_features: wgpu::Features::TEXTURE_BINDING_ARRAY | wgpu::Features::PUSH_CONSTANTS,
|
optional_features: wgpu::Features::empty(),
|
||||||
base_test_parameters: framework::test_common::TestParameters::default().failure(),
|
base_test_parameters: framework::test_common::TestParameters::default(),
|
||||||
tolerance: 0,
|
tolerance: 0,
|
||||||
max_outliers: 0,
|
max_outliers: 0,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// This fails due to an issue with naga https://github.com/gfx-rs/wgpu/issues/1532
|
|
||||||
#[test]
|
#[test]
|
||||||
fn texture_arrays_non_uniform() {
|
fn texture_arrays_non_uniform() {
|
||||||
framework::test::<Example>(framework::FrameworkRefTest {
|
framework::test::<Example>(framework::FrameworkRefTest {
|
||||||
image_path: "/examples/texture-arrays/screenshot.png",
|
image_path: "/examples/texture-arrays/screenshot.png",
|
||||||
width: 1024,
|
width: 1024,
|
||||||
height: 768,
|
height: 768,
|
||||||
optional_features: wgpu::Features::TEXTURE_BINDING_ARRAY
|
optional_features:
|
||||||
| wgpu::Features::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING,
|
wgpu::Features::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING,
|
||||||
base_test_parameters: framework::test_common::TestParameters::default().failure(),
|
base_test_parameters: framework::test_common::TestParameters::default(),
|
||||||
tolerance: 0,
|
|
||||||
max_outliers: 0,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// This fails due to an issue with naga https://github.com/gfx-rs/wgpu/issues/1532
|
|
||||||
#[test]
|
|
||||||
fn texture_arrays_unsized_non_uniform() {
|
|
||||||
framework::test::<Example>(framework::FrameworkRefTest {
|
|
||||||
image_path: "/examples/texture-arrays/screenshot.png",
|
|
||||||
width: 1024,
|
|
||||||
height: 768,
|
|
||||||
optional_features: wgpu::Features::TEXTURE_BINDING_ARRAY
|
|
||||||
| wgpu::Features::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING
|
|
||||||
| wgpu::Features::UNSIZED_BINDING_ARRAY,
|
|
||||||
base_test_parameters: framework::test_common::TestParameters::default().failure(),
|
|
||||||
tolerance: 0,
|
tolerance: 0,
|
||||||
max_outliers: 0,
|
max_outliers: 0,
|
||||||
});
|
});
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
#version 450
|
|
||||||
|
|
||||||
#extension GL_EXT_nonuniform_qualifier : require
|
|
||||||
|
|
||||||
layout(location = 0) in vec2 v_TexCoord;
|
|
||||||
layout(location = 1) nonuniformEXT flat in int v_Index; // dynamically non-uniform
|
|
||||||
layout(location = 0) out vec4 o_Color;
|
|
||||||
|
|
||||||
layout(set = 0, binding = 0) uniform texture2D u_Textures[2];
|
|
||||||
layout(set = 0, binding = 1) uniform sampler u_Sampler[2];
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
o_Color = vec4(texture(sampler2D(u_Textures[v_Index], u_Sampler[v_Index]), v_TexCoord).rgb, 1.0);
|
|
||||||
}
|
|
Binary file not shown.
33
wgpu/examples/texture-arrays/non_uniform_indexing.wgsl
Normal file
33
wgpu/examples/texture-arrays/non_uniform_indexing.wgsl
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
struct FragmentInput {
|
||||||
|
@location(0) tex_coord: vec2<f32>,
|
||||||
|
@location(1) index: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
@group(0) @binding(0)
|
||||||
|
var texture_array_top: binding_array<texture_2d<f32>>;
|
||||||
|
@group(0) @binding(1)
|
||||||
|
var texture_array_bottom: binding_array<texture_2d<f32>>;
|
||||||
|
@group(0) @binding(2)
|
||||||
|
var sampler_array: binding_array<sampler>;
|
||||||
|
|
||||||
|
@fragment
|
||||||
|
fn non_uniform_main(fragment: FragmentInput) -> @location(0) vec4<f32> {
|
||||||
|
var outval: vec3<f32>;
|
||||||
|
if fragment.tex_coord.y <= 0.5 {
|
||||||
|
outval = textureSampleLevel(
|
||||||
|
texture_array_top[fragment.index],
|
||||||
|
sampler_array[fragment.index],
|
||||||
|
fragment.tex_coord,
|
||||||
|
0.0
|
||||||
|
).rgb;
|
||||||
|
} else {
|
||||||
|
outval = textureSampleLevel(
|
||||||
|
texture_array_bottom[fragment.index],
|
||||||
|
sampler_array[fragment.index],
|
||||||
|
fragment.tex_coord,
|
||||||
|
0.0
|
||||||
|
).rgb;
|
||||||
|
}
|
||||||
|
|
||||||
|
return vec4<f32>(outval.x, outval.y, outval.z, 1.0);
|
||||||
|
}
|
BIN
wgpu/examples/texture-arrays/screenshot.png
Normal file
BIN
wgpu/examples/texture-arrays/screenshot.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.4 KiB |
@ -1,13 +0,0 @@
|
|||||||
#version 450
|
|
||||||
|
|
||||||
layout(location = 0) in vec2 a_Pos;
|
|
||||||
layout(location = 1) in vec2 a_TexCoord;
|
|
||||||
layout(location = 2) in int a_Index;
|
|
||||||
layout(location = 0) out vec2 v_TexCoord;
|
|
||||||
layout(location = 1) flat out int v_Index;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
v_TexCoord = a_TexCoord;
|
|
||||||
v_Index = a_Index;
|
|
||||||
gl_Position = vec4(a_Pos, 0.0, 1.0);
|
|
||||||
}
|
|
Binary file not shown.
@ -1,15 +0,0 @@
|
|||||||
#version 450
|
|
||||||
|
|
||||||
layout(location = 0) in vec2 v_TexCoord;
|
|
||||||
layout(location = 1) flat in int v_Index; // dynamically non-uniform
|
|
||||||
layout(location = 0) out vec4 o_Color;
|
|
||||||
|
|
||||||
layout(set = 0, binding = 0) uniform texture2D u_Textures[2];
|
|
||||||
layout(set = 0, binding = 1) uniform sampler u_Sampler[2];
|
|
||||||
layout(push_constant) uniform Uniforms {
|
|
||||||
int u_Index; // dynamically uniform
|
|
||||||
};
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
o_Color = vec4(texture(sampler2D(u_Textures[u_Index], u_Sampler[u_Index]), v_TexCoord).rgb, 1.0);
|
|
||||||
}
|
|
Binary file not shown.
@ -1,14 +0,0 @@
|
|||||||
#version 450
|
|
||||||
|
|
||||||
#extension GL_EXT_nonuniform_qualifier : require
|
|
||||||
|
|
||||||
layout(location = 0) in vec2 v_TexCoord;
|
|
||||||
layout(location = 1) nonuniformEXT flat in int v_Index; // dynamically non-uniform
|
|
||||||
layout(location = 0) out vec4 o_Color;
|
|
||||||
|
|
||||||
layout(set = 0, binding = 0) uniform texture2D u_Textures[];
|
|
||||||
layout(set = 0, binding = 1) uniform sampler u_Sampler[];
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
o_Color = vec4(texture(sampler2D(u_Textures[v_Index], u_Sampler[v_Index]), v_TexCoord).rgb, 1.0);
|
|
||||||
}
|
|
Binary file not shown.
@ -1329,8 +1329,8 @@ impl crate::Context for Context {
|
|||||||
));
|
));
|
||||||
if let Some(cause) = error {
|
if let Some(cause) = error {
|
||||||
if let wgc::pipeline::CreateRenderPipelineError::Internal { stage, ref error } = cause {
|
if let wgc::pipeline::CreateRenderPipelineError::Internal { stage, ref error } = cause {
|
||||||
log::warn!("Shader translation error for stage {:?}: {}", stage, error);
|
log::error!("Shader translation error for stage {:?}: {}", stage, error);
|
||||||
log::warn!("Please report it to https://github.com/gfx-rs/naga");
|
log::error!("Please report it to https://github.com/gfx-rs/naga");
|
||||||
}
|
}
|
||||||
self.handle_error(
|
self.handle_error(
|
||||||
&device.error_sink,
|
&device.error_sink,
|
||||||
|
Loading…
Reference in New Issue
Block a user