From 0943cfddc26fac7177e53f415ae67ec2479f4670 Mon Sep 17 00:00:00 2001 From: Connor Fitzgerald Date: Tue, 19 Apr 2022 19:25:29 -0400 Subject: [PATCH 01/10] Move texture-array example over to wgsl --- Cargo.lock | 1 - Cargo.toml | 2 +- wgpu-core/Cargo.toml | 2 +- wgpu-core/src/device/mod.rs | 19 +++++ wgpu-core/src/validation.rs | 9 +- wgpu-hal/Cargo.toml | 4 +- wgpu-hal/src/dx12/adapter.rs | 3 +- wgpu-hal/src/dx12/device.rs | 9 -- wgpu-hal/src/dx12/mod.rs | 1 - wgpu-hal/src/metal/device.rs | 2 + wgpu-hal/src/vulkan/adapter.rs | 26 +++--- wgpu-hal/src/vulkan/device.rs | 80 +++++++++++++++--- wgpu-hal/src/vulkan/mod.rs | 10 ++- wgpu-types/src/lib.rs | 50 +++++------ wgpu/Cargo.toml | 7 +- wgpu/examples/texture-arrays/constant.frag | 19 ----- .../examples/texture-arrays/constant.frag.spv | Bin 1708 -> 0 bytes wgpu/examples/texture-arrays/indexing.wgsl | 60 +++++++++++++ wgpu/examples/texture-arrays/main.rs | 46 +++++----- wgpu/examples/texture-arrays/non-uniform.frag | 14 --- .../texture-arrays/non-uniform.frag.spv | Bin 1328 -> 0 bytes wgpu/examples/texture-arrays/shader.vert | 13 --- wgpu/examples/texture-arrays/shader.vert.spv | Bin 892 -> 0 bytes wgpu/examples/texture-arrays/uniform.frag | 15 ---- wgpu/examples/texture-arrays/uniform.frag.spv | Bin 1376 -> 0 bytes .../texture-arrays/unsized-non-uniform.frag | 14 --- .../unsized-non-uniform.frag.spv | Bin 1296 -> 0 bytes wgpu/src/backend/direct.rs | 4 +- 28 files changed, 235 insertions(+), 175 deletions(-) delete mode 100644 wgpu/examples/texture-arrays/constant.frag delete mode 100644 wgpu/examples/texture-arrays/constant.frag.spv create mode 100644 wgpu/examples/texture-arrays/indexing.wgsl delete mode 100644 wgpu/examples/texture-arrays/non-uniform.frag delete mode 100644 wgpu/examples/texture-arrays/non-uniform.frag.spv delete mode 100644 wgpu/examples/texture-arrays/shader.vert delete mode 100644 wgpu/examples/texture-arrays/shader.vert.spv delete mode 100644 wgpu/examples/texture-arrays/uniform.frag delete mode 100644 wgpu/examples/texture-arrays/uniform.frag.spv delete mode 100644 wgpu/examples/texture-arrays/unsized-non-uniform.frag delete mode 100644 wgpu/examples/texture-arrays/unsized-non-uniform.frag.spv diff --git a/Cargo.lock b/Cargo.lock index bda80b068e..575c1c228c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1032,7 +1032,6 @@ dependencies = [ [[package]] name = "naga" version = "0.8.0" -source = "git+https://github.com/gfx-rs/naga?rev=85056524#850565243d1d0d03215f13246c94d63e1d4c51cd" dependencies = [ "bit-set", "bitflags", diff --git a/Cargo.toml b/Cargo.toml index 7d3044ae3d..8bf2f6d65d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,7 @@ exclude = [ default-members = ["wgpu", "wgpu-hal", "wgpu-info"] [patch."https://github.com/gfx-rs/naga"] -#naga = { path = "../naga" } +naga = { path = "../naga" } [patch."https://github.com/zakarumych/gpu-descriptor"] #gpu-descriptor = { path = "../gpu-descriptor/gpu-descriptor" } diff --git a/wgpu-core/Cargo.toml b/wgpu-core/Cargo.toml index 3711818264..e33cd7c45b 100644 --- a/wgpu-core/Cargo.toml +++ b/wgpu-core/Cargo.toml @@ -40,7 +40,7 @@ thiserror = "1" [dependencies.naga] git = "https://github.com/gfx-rs/naga" -rev = "85056524" +rev = "ad283968" #version = "0.8" features = ["span", "validate", "wgsl-in"] diff --git a/wgpu-core/src/device/mod.rs b/wgpu-core/src/device/mod.rs index b951c318bd..7a8bdc89e5 100644 --- a/wgpu-core/src/device/mod.rs +++ b/wgpu-core/src/device/mod.rs @@ -1142,6 +1142,25 @@ impl Device { self.features .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) .validate(&module) .map_err(|inner| { diff --git a/wgpu-core/src/validation.rs b/wgpu-core/src/validation.rs index 921ec49275..5596de8369 100644 --- a/wgpu-core/src/validation.rs +++ b/wgpu-core/src/validation.rs @@ -867,7 +867,14 @@ impl Interface { Some(ref br) => br.clone(), _ => 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 { dim, arrayed, diff --git a/wgpu-hal/Cargo.toml b/wgpu-hal/Cargo.toml index f5d6c52d73..3c317d0a32 100644 --- a/wgpu-hal/Cargo.toml +++ b/wgpu-hal/Cargo.toml @@ -91,14 +91,14 @@ js-sys = { version = "0.3" } [dependencies.naga] git = "https://github.com/gfx-rs/naga" -rev = "85056524" +rev = "ad283968" #version = "0.8" # DEV dependencies [dev-dependencies.naga] git = "https://github.com/gfx-rs/naga" -rev = "85056524" +rev = "ad283968" #version = "0.8" features = ["wgsl-in"] diff --git a/wgpu-hal/src/dx12/adapter.rs b/wgpu-hal/src/dx12/adapter.rs index 88959bdb47..f774cc8635 100644 --- a/wgpu-hal/src/dx12/adapter.rs +++ b/wgpu-hal/src/dx12/adapter.rs @@ -282,7 +282,7 @@ impl super::Adapter { impl crate::Adapter for super::Adapter { unsafe fn open( &self, - features: wgt::Features, + _features: wgt::Features, _limits: &wgt::Limits, ) -> Result, crate::DeviceError> { let queue = { @@ -300,7 +300,6 @@ impl crate::Adapter for super::Adapter { let device = super::Device::new( self.device, queue, - features, self.private_caps, &self.library, )?; diff --git a/wgpu-hal/src/dx12/device.rs b/wgpu-hal/src/dx12/device.rs index f87111f6bc..ab8a3f684f 100644 --- a/wgpu-hal/src/dx12/device.rs +++ b/wgpu-hal/src/dx12/device.rs @@ -21,7 +21,6 @@ impl super::Device { pub(super) fn new( raw: native::Device, present_queue: native::CommandQueue, - features: wgt::Features, private_caps: super::PrivateCapabilities, library: &Arc, ) -> Result { @@ -87,7 +86,6 @@ impl super::Device { let capacity_samplers = 2_048; let shared = super::DeviceShared { - features, zero_buffer, cmd_signatures: super::CommandSignatures { draw: raw @@ -222,13 +220,6 @@ impl super::Device { compile_flags |= 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 { Some(ref cstr) => cstr.as_c_str().as_ptr(), diff --git a/wgpu-hal/src/dx12/mod.rs b/wgpu-hal/src/dx12/mod.rs index ffef5a3ada..4b048ff009 100644 --- a/wgpu-hal/src/dx12/mod.rs +++ b/wgpu-hal/src/dx12/mod.rs @@ -199,7 +199,6 @@ impl CommandSignatures { } struct DeviceShared { - features: wgt::Features, zero_buffer: native::Resource, cmd_signatures: CommandSignatures, heap_views: descriptor::GeneralHeap, diff --git a/wgpu-hal/src/metal/device.rs b/wgpu-hal/src/metal/device.rs index b560bd0670..ac29074859 100644 --- a/wgpu-hal/src/metal/device.rs +++ b/wgpu-hal/src/metal/device.rs @@ -667,6 +667,8 @@ impl crate::Device for super::Device { index: naga::proc::BoundsCheckPolicy::ReadZeroSkipWrite, buffer: 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, diff --git a/wgpu-hal/src/vulkan/adapter.rs b/wgpu-hal/src/vulkan/adapter.rs index 20065e3a7f..8fb81c50cc 100644 --- a/wgpu-hal/src/vulkan/adapter.rs +++ b/wgpu-hal/src/vulkan/adapter.rs @@ -3,13 +3,12 @@ use super::conv; use ash::{extensions::khr, vk}; use parking_lot::Mutex; -use std::{ffi::CStr, sync::Arc}; +use std::{collections::BTreeMap, ffi::CStr, sync::Arc}; //TODO: const fn? fn indexing_features() -> wgt::Features { wgt::Features::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_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`. @@ -212,9 +211,6 @@ impl PhysicalDeviceFeatures { uab_types.contains(super::UpdateAfterBindTypes::STORAGE_BUFFER), ) .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)) .imageless_framebuffer(private_caps.imageless_framebuffers) .timeline_semaphore(private_caps.timeline_semaphores) @@ -253,9 +249,6 @@ impl PhysicalDeviceFeatures { uab_types.contains(super::UpdateAfterBindTypes::STORAGE_BUFFER), ) .descriptor_binding_partially_bound(needs_partially_bound) - .runtime_descriptor_array( - requested_features.contains(wgt::Features::UNSIZED_BINDING_ARRAY), - ) .build(), ) } else { @@ -471,9 +464,6 @@ impl PhysicalDeviceFeatures { ) { 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 { features |= F::PARTIALLY_BOUND_BINDING_ARRAY; } @@ -519,9 +509,6 @@ impl PhysicalDeviceFeatures { if descriptor_indexing.descriptor_binding_partially_bound != 0 && !intel_windows { 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 { @@ -1183,6 +1170,13 @@ impl super::Adapter { 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(); flags.set( spv::WriterFlags::DEBUG, @@ -1215,7 +1209,11 @@ impl super::Adapter { } else { 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(), } }; diff --git a/wgpu-hal/src/vulkan/device.rs b/wgpu-hal/src/vulkan/device.rs index 55dcd82f9d..d6a2e3bd21 100644 --- a/wgpu-hal/src/vulkan/device.rs +++ b/wgpu-hal/src/vulkan/device.rs @@ -6,7 +6,12 @@ use inplace_it::inplace_or_alloc_from_iter; use parking_lot::Mutex; 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 { @@ -628,6 +633,7 @@ impl super::Device { &self, stage: &crate::ProgrammableStage, naga_stage: naga::ShaderStage, + binding_map: &naga::back::spv::BindingMap, ) -> Result { let stage_flags = crate::auxil::map_naga_stage(naga_stage); let vk_module = match *stage.module { @@ -640,16 +646,21 @@ impl super::Device { entry_point: stage.entry_point.to_string(), shader_stage: naga_stage, }; - let temp_options; - let options = if !runtime_checks { - temp_options = naga::back::spv::Options { - bounds_check_policies: naga::proc::BoundsCheckPolicies { + let needs_temp_options = !runtime_checks || !binding_map.is_empty(); + let mut temp_options; + let options = if needs_temp_options { + temp_options = self.naga_options.clone(); + if !runtime_checks { + temp_options.bounds_check_policies = naga::proc::BoundsCheckPolicies { index: naga::proc::BoundsCheckPolicy::Unchecked, buffer: naga::proc::BoundsCheckPolicy::Unchecked, image: naga::proc::BoundsCheckPolicy::Unchecked, - }, - ..self.naga_options.clone() - }; + binding_array: naga::proc::BoundsCheckPolicy::Unchecked, + }; + } + if !binding_map.is_empty() { + temp_options.binding_map = binding_map.clone(); + } &temp_options } else { &self.naga_options @@ -1100,6 +1111,19 @@ impl crate::Device for super::Device { let vk_info = vk::DescriptorSetLayoutCreateInfo::builder().bindings(&vk_bindings); + let binding_arrays = desc + .entries + .iter() + .enumerate() + .filter_map(|(idx, entry)| { + if let Some(count) = entry.count { + Some((idx as u32, count)) + } else { + None + } + }) + .collect(); + let mut binding_flag_info; let binding_flag_vec; let mut requires_update_after_bind = false; @@ -1176,6 +1200,7 @@ impl crate::Device for super::Device { raw, desc_count, types: types.into_boxed_slice(), + binding_arrays, requires_update_after_bind, }) } @@ -1220,7 +1245,25 @@ impl crate::Device for super::Device { .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) { self.shared @@ -1344,6 +1387,7 @@ impl crate::Device for super::Device { index: naga::proc::BoundsCheckPolicy::Unchecked, buffer: naga::proc::BoundsCheckPolicy::Unchecked, image: naga::proc::BoundsCheckPolicy::Unchecked, + binding_array: naga::proc::BoundsCheckPolicy::Unchecked, }; } Cow::Owned( @@ -1425,11 +1469,19 @@ impl crate::Device for super::Device { .primitive_restart_enable(desc.primitive.strip_index_format.is_some()) .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); let compiled_fs = match desc.fragment_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); Some(compiled) } @@ -1604,7 +1656,11 @@ impl crate::Device for super::Device { &self, desc: &crate::ComputePipelineDescriptor, ) -> Result { - 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 = [{ vk::ComputePipelineCreateInfo::builder() diff --git a/wgpu-hal/src/vulkan/mod.rs b/wgpu-hal/src/vulkan/mod.rs index 41690095bc..caade3dc07 100644 --- a/wgpu-hal/src/vulkan/mod.rs +++ b/wgpu-hal/src/vulkan/mod.rs @@ -31,7 +31,12 @@ mod conv; mod device; mod instance; -use std::{borrow::Borrow, ffi::CStr, num::NonZeroU32, sync::Arc}; +use std::{ + borrow::Borrow, + ffi::CStr, + num::{NonZeroU32}, + sync::Arc, +}; use arrayvec::ArrayVec; use ash::{ @@ -398,12 +403,15 @@ pub struct BindGroupLayout { raw: vk::DescriptorSetLayout, desc_count: gpu_descriptor::DescriptorTotalCount, types: Box<[(vk::DescriptorType, u32)]>, + /// Map of binding index to size, + binding_arrays: Vec<(u32, NonZeroU32)>, requires_update_after_bind: bool, } #[derive(Debug)] pub struct PipelineLayout { raw: vk::PipelineLayout, + binding_arrays: naga::back::spv::BindingMap, } #[derive(Debug)] diff --git a/wgpu-types/src/lib.rs b/wgpu-types/src/lib.rs index 59b202059d..ec5a4b5b48 100644 --- a/wgpu-types/src/lib.rs +++ b/wgpu-types/src/lib.rs @@ -348,16 +348,6 @@ bitflags::bitflags! { /// /// This is a native only feature. 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 multiple indirect calls to be dispatched from a single buffer. @@ -367,7 +357,7 @@ bitflags::bitflags! { /// - Vulkan /// /// 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`]. /// /// 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) /// /// 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 /// inside a [`RenderPass`]. /// @@ -394,7 +384,7 @@ bitflags::bitflags! { /// - OpenGL (emulated with uniforms) /// /// 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 /// other than [`SamplerBorderColor::Zero`]. /// @@ -406,7 +396,7 @@ bitflags::bitflags! { /// - OpenGL /// /// 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`] /// /// This allows drawing polygons/triangles as lines (wireframe) instead of filled @@ -417,7 +407,7 @@ bitflags::bitflags! { /// - Metal /// /// 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`] /// /// This allows only drawing the vertices of polygons/triangles instead of filled @@ -427,7 +417,7 @@ bitflags::bitflags! { /// - Vulkan /// /// 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. /// 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) /// /// 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. /// Blocks are always 16 bytes. /// @@ -457,7 +447,7 @@ bitflags::bitflags! { /// - Mobile (some) /// /// 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. /// /// See `TextureFormatFeatures` for a listing of the features in question. @@ -469,7 +459,7 @@ bitflags::bitflags! { /// This extension does not enable additional formats. /// /// 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. /// /// Note: even when supported by GPU hardware, 64-bit floating point operations are @@ -479,7 +469,7 @@ bitflags::bitflags! { /// - Vulkan /// /// This is a native-only feature. - const SHADER_FLOAT64 = 1 << 33; + const SHADER_FLOAT64 = 1 << 32; /// Enables using 64-bit types for vertex attributes. /// /// Requires SHADER_FLOAT64. @@ -487,7 +477,7 @@ bitflags::bitflags! { /// Supported Platforms: N/A /// /// 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`] /// /// Processing of degenerate triangles/lines is hardware specific. @@ -497,7 +487,7 @@ bitflags::bitflags! { /// - Vulkan /// /// 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. /// /// Note: some (tiled-based) platforms do not support vertex shaders with any side-effects. @@ -506,14 +496,14 @@ bitflags::bitflags! { /// - All /// /// This is a native-only feature. - const VERTEX_WRITABLE_STORAGE = 1 << 36; + const VERTEX_WRITABLE_STORAGE = 1 << 35; /// Enables clear to zero for textures. /// /// Supported platforms: /// - All /// /// 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). /// /// SPIR-V data is not parsed or interpreted in any way; you can use @@ -525,7 +515,7 @@ bitflags::bitflags! { /// Vulkan implementation. /// /// 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. /// /// Note: enables geometry processing for pipelines using the builtin. @@ -536,14 +526,14 @@ bitflags::bitflags! { /// - Vulkan /// /// 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. /// /// Supported platforms: /// - Vulkan /// /// This is a native only feature. - const MULTIVIEW = 1 << 40; + const MULTIVIEW = 1 << 39; /// Enables normalized `16-bit` texture formats. /// /// Supported platforms: @@ -552,7 +542,7 @@ bitflags::bitflags! { /// - Metal /// /// 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 /// of [`SamplerBorderColor::Zero`]. /// @@ -564,12 +554,12 @@ bitflags::bitflags! { /// - OpenGL /// /// This is a native only feature. - const ADDRESS_MODE_CLAMP_TO_ZERO = 1 << 42; + const ADDRESS_MODE_CLAMP_TO_ZERO = 1 << 41; /// Supported Platforms: /// - Metal /// /// This is a native-only feature. - const TEXTURE_COMPRESSION_ASTC_HDR = 1 << 43; + const TEXTURE_COMPRESSION_ASTC_HDR = 1 << 42; } } diff --git a/wgpu/Cargo.toml b/wgpu/Cargo.toml index 63f0dbb338..4cb3f00f8f 100644 --- a/wgpu/Cargo.toml +++ b/wgpu/Cargo.toml @@ -69,7 +69,6 @@ test = true [[example]] name="texture-arrays" -required-features = ["spirv"] test = true [[example]] @@ -139,20 +138,20 @@ env_logger = "0.9" [dependencies.naga] git = "https://github.com/gfx-rs/naga" -rev = "85056524" +rev = "ad283968" #version = "0.8" optional = true # used to test all the example shaders [dev-dependencies.naga] git = "https://github.com/gfx-rs/naga" -rev = "85056524" +rev = "ad283968" #version = "0.8" features = ["wgsl-in"] [target.'cfg(target_arch = "wasm32")'.dependencies.naga] git = "https://github.com/gfx-rs/naga" -rev = "85056524" +rev = "ad283968" #version = "0.8" features = ["wgsl-out"] diff --git a/wgpu/examples/texture-arrays/constant.frag b/wgpu/examples/texture-arrays/constant.frag deleted file mode 100644 index a622de3799..0000000000 --- a/wgpu/examples/texture-arrays/constant.frag +++ /dev/null @@ -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); - } -} diff --git a/wgpu/examples/texture-arrays/constant.frag.spv b/wgpu/examples/texture-arrays/constant.frag.spv deleted file mode 100644 index 2ac4287204008167e8d26ba232da075561e25a55..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1708 zcmZ9KSx-|@6oogm#R4+PB!hAb&R|6aM3KpgjY*SgF#32y+WXL?v`wero4?1O;h%Cy zOkCgPo^awxR`%X&Pv@?4Q-f>Q%m!@4#_XM4o+%p?V>W6-u`QNPOZiT>n%~;qq+;As zaUnGmmbJ7jI6td3NMwZ@!hK;qpdOy}DYXQtws$f{ZHs-NfwghwmHJ=)#D(OEWAq>&>>}jNMe+3qM5{ z-CjHDSj?@&-09hQs~)xGQ^)=L)D@b|cGaw?`!jo7C?jZ z+3Dwr$-8;%ck`yD9NOh#6)pB>wPQ$JAkY&iMrVBZy(H$&aO+9^h~QkEE9nK>oPi^DUMm~Vw!uwk2)rJf!BaWVItQ6fl^+=F;l;G32e&&e_ej-B(e z9C&sTqbG;_!lfJcENaTKV&>e6?bRHoA3Sr2(V4@XAol1rThbS;$#M^LxGT$daYt(J z$qoqc%p&HE;HZBjOFg>qjrbda*|$Td{c}asyZl?yIvaX9^gR*a0KM29{fpcoEpV9s zOH4*~Uo3AuEbz|X#qy@t6OOn3sSf^G&L7p28xx)i%)viaADS)-=u988(PBw}rzVii z325kQ&~7#1KdS}}?+En4GY8Ec23pryD6W3>dB+;fwbXYCih#L&c(}yPu=Re+S;, + @location(1) tex_coord: vec2, + @location(2) index: i32, +} + +struct VertexOutput { + @builtin(position) position: vec4, + @location(0) tex_coord: vec2, + @location(1) index: i32, +} + +@vertex +fn vert_main(vertex: VertexInput) -> VertexOutput { + var outval: VertexOutput; + outval.position = vec4(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, + @location(1) index: i32, +} + +@group(0) @binding(0) +var texture_array: binding_array>; +@group(0) @binding(1) +var sampler_array: binding_array; + +struct Uniforms { + index: u32, +} + +var uniforms: Uniforms; + +@fragment +fn uniform_main(fragment: FragmentInput) -> @location(0) vec4 { + var outval = textureSampleLevel( + texture_array[uniforms.index], + sampler_array[uniforms.index], + fragment.tex_coord, + 0.0 + ).rgb; + + return vec4(outval.x, outval.y, outval.z, 1.0); +} + +@fragment +fn non_uniform_main(fragment: FragmentInput) -> @location(0) vec4 { + var outval = textureSampleLevel( + texture_array[fragment.index], + sampler_array[fragment.index], + fragment.tex_coord, + 0.0 + ).rgb; + + return vec4(outval.x, outval.y, outval.z, 1.0); +} diff --git a/wgpu/examples/texture-arrays/main.rs b/wgpu/examples/texture-arrays/main.rs index af074e21d9..f43ed7f806 100644 --- a/wgpu/examples/texture-arrays/main.rs +++ b/wgpu/examples/texture-arrays/main.rs @@ -71,12 +71,11 @@ struct Example { impl framework::Example for Example { 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 { - wgpu::Features::TEXTURE_BINDING_ARRAY | wgpu::Features::SPIRV_SHADER_PASSTHROUGH + wgpu::Features::TEXTURE_BINDING_ARRAY } fn required_limits() -> wgpu::Limits { wgpu::Limits { @@ -91,24 +90,33 @@ impl framework::Example for Example { queue: &wgpu::Queue, ) -> Self { let mut uniform_workaround = false; - let vs_module = device.create_shader_module(&wgpu::include_spirv!("shader.vert.spv")); - let fs_source = match device.features() { - f if f.contains(wgpu::Features::UNSIZED_BINDING_ARRAY) => { - wgpu::include_spirv_raw!("unsized-non-uniform.frag.spv") + let shader_module = device.create_shader_module(&wgpu::include_wgsl!("indexing.wgsl")); + let env_override = match std::env::var("WGPU_TEXTURE_ARRAY_STYLE") { + Ok(value) => match &*value.to_lowercase() { + "nonuniform" | "non_uniform" => Some(true), + "uniform" => Some(false), + _ => None, + }, + Err(_) => None, + }; + let fragment_entry_point = match (device.features(), env_override) { + (_, Some(false)) => { + uniform_workaround = true; + "uniform_main" } - f if f.contains( - wgpu::Features::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING, - ) => + (_, Some(true)) => "non_uniform_main", + (f, _) + if f.contains( + wgpu::Features::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING, + ) => { - wgpu::include_spirv_raw!("non-uniform.frag.spv") + "non_uniform_main" } - f if f.contains(wgpu::Features::TEXTURE_BINDING_ARRAY) => { + _ => { uniform_workaround = true; - wgpu::include_spirv_raw!("uniform.frag.spv") + "uniform_main" } - _ => unreachable!(), }; - let fs_module = unsafe { device.create_shader_module_spirv(&fs_source) }; let vertex_size = std::mem::size_of::(); let vertex_data = create_vertices(); @@ -231,8 +239,8 @@ impl framework::Example for Example { label: None, layout: Some(&pipeline_layout), vertex: wgpu::VertexState { - module: &vs_module, - entry_point: "main", + module: &shader_module, + entry_point: "vert_main", buffers: &[wgpu::VertexBufferLayout { array_stride: vertex_size as wgpu::BufferAddress, step_mode: wgpu::VertexStepMode::Vertex, @@ -240,8 +248,8 @@ impl framework::Example for Example { }], }, fragment: Some(wgpu::FragmentState { - module: &fs_module, - entry_point: "main", + module: &shader_module, + entry_point: fragment_entry_point, targets: &[config.format.into()], }), primitive: wgpu::PrimitiveState { diff --git a/wgpu/examples/texture-arrays/non-uniform.frag b/wgpu/examples/texture-arrays/non-uniform.frag deleted file mode 100644 index 990d0dd366..0000000000 --- a/wgpu/examples/texture-arrays/non-uniform.frag +++ /dev/null @@ -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); -} diff --git a/wgpu/examples/texture-arrays/non-uniform.frag.spv b/wgpu/examples/texture-arrays/non-uniform.frag.spv deleted file mode 100644 index 1d0844771d74cc0fce548722eab4d53b0c28a6fd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1328 zcmYk5TWb?x5QfJlsWr7HYg>CzH`a5tc%dSQij)$BKq@KKyCr0|vas2Wn*;UEAEj5` z`K!DUe4j77ai>gY=KbcplgixwWwT3Gw=qNEp(gR(tDGO3{6&u4nQz5zmUQY&b64FQMbGQ{LVTl!`&#DoP3iN( zJn@!h;#*>~S5N;JB)JIi*SXD(!M3&Sx+MPeRHnk-P|Ttpy!`PXx39{kmp$1_lH>uS zCOd<`sfo?5A@Z$CdSYtezn1IZ_+zv0;$3TYM2#I)-IAp44N3H(?zVIYoIKd<9HP$N zRCO`C+Q4nu|{O9#WZzz%YZ*b`Nw-V-tL`18)* P-fBzSC2xO~;g$Fw`a@|t diff --git a/wgpu/examples/texture-arrays/shader.vert b/wgpu/examples/texture-arrays/shader.vert deleted file mode 100644 index cd7d2c7694..0000000000 --- a/wgpu/examples/texture-arrays/shader.vert +++ /dev/null @@ -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); -} diff --git a/wgpu/examples/texture-arrays/shader.vert.spv b/wgpu/examples/texture-arrays/shader.vert.spv deleted file mode 100644 index c1ca86d7fb38ac98d74b971414720342a777686a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 892 zcmYL`%T5A85Jk)3AwB>R0Urp1xHBOx)R-7Gu5iIZ;}@8?aiJUi06*J}iRaAFp^}@b zx>a3$ySkE1*CW=V5zRP_(mIjBL~KR9@bksXV)pg@HoLeyx1$x6qS2l>O**@<@)LSIW85dI<8v^epCuN#wVb?xw^#mVnfrD*>zjCWrnuvNmFDdbdp6b0-MyUpx_I^aR_E{GbD*6q^B%GNL-Ib}ez_5m zyGb*w33ct`)nHv+=Ki;wbJcSQH0!?8-FlC8?>Gip%FDg~+&ljS-dWy##h<%h-=N9= z!qo7$uHT V{ecbE3+9Gpbwqj44u&0#CTPW$oq zH0ud5-Lz_8$T;}a52JG-o~`DP%h`3YpIU0^Q9ZA#k=9NV_*L@SzaIfb>XvbuuW}#P8L4(r=|4Qlryh@Uj+9H|Ehdu*^$2> zOC2zJGCKlJPkeTWP;Xh*m(pWbld!)WtJpQ2nGcLyeBKm{-tewV5qho35-am>5Rfp> zmL}YmWyT#@&gG0ZbwKIGnodo|HZLQtGguh7|m(IPB?;bV~{jhrK+IvXgJ( z@GU-+!UON7+6b@2iPjm)@TVe+VM($^Iqu*00`S6Le|F_yE M-wv@qs_;ts7qV+tY5)KL diff --git a/wgpu/examples/texture-arrays/unsized-non-uniform.frag b/wgpu/examples/texture-arrays/unsized-non-uniform.frag deleted file mode 100644 index e49a83103e..0000000000 --- a/wgpu/examples/texture-arrays/unsized-non-uniform.frag +++ /dev/null @@ -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); -} diff --git a/wgpu/examples/texture-arrays/unsized-non-uniform.frag.spv b/wgpu/examples/texture-arrays/unsized-non-uniform.frag.spv deleted file mode 100644 index 1c98e9421156df924fdf8473b5f492bb906eef89..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1296 zcmYk4T~8BH5QYcZA{GG=0Rhn#{3an@s4+2W3?UnnCdHJXcblfWm`%33b^8&#^GB&S z-ubJ%G4Xv)ck50wotbyunR90LROSz^n9W(;mhI4{vS#x_%&nI9!Vco`+1ZOIl~z1Qlrj)tS)=-Kn9bY8KFJAmG+>QR+N``suZ zaaDR<+H|(!a=M(VD!Pf;ZxvQm=e69?Nt%q4=pxPf{+Dq#jxM4wQ@&2#Yq!1DiQgLx z{NdPDnER#vaT=$Y)%06dJoeAR%h5Os zhbE-z?mzM0vkJ$#p#{jTqXzh3eM<#^S&SGhki{fi#kGj7FpOaASdUv>QA&g=R@e50n$$Tv7ra{jTLCF!~X*M`S}W z`)Ww3hrgQp;P8prYmvVpAEEz_CfbnY%uQK*dThxeVDunnmk9Ztsq6T=s@+peKlX7~ zmigEf+=lF&6r5hfO(_`sd$RD^&!J-c2U4?dZ(rzL(TCk4aQ+CX$-WlKjJylxdnc6H zcpK~o91i#5jer+5yn~{KS$GS~2M&il@Fu{|)tC8r6Z8Rx!#w*^X89-%-}^uc54^3H zz-;%W;3&e}%=AGu%=%CY2Pv>e^1#cq#n{ DD0XPM diff --git a/wgpu/src/backend/direct.rs b/wgpu/src/backend/direct.rs index d6478044b1..8c3ff54a34 100644 --- a/wgpu/src/backend/direct.rs +++ b/wgpu/src/backend/direct.rs @@ -1325,8 +1325,8 @@ impl crate::Context for Context { )); if let Some(cause) = error { if let wgc::pipeline::CreateRenderPipelineError::Internal { stage, ref error } = cause { - log::warn!("Shader translation error for stage {:?}: {}", stage, error); - log::warn!("Please report it to https://github.com/gfx-rs/naga"); + log::error!("Shader translation error for stage {:?}: {}", stage, error); + log::error!("Please report it to https://github.com/gfx-rs/naga"); } self.handle_error( &device.error_sink, From 6db64be32f5ba2eb1dadfa30d79332446184606f Mon Sep 17 00:00:00 2001 From: Connor Fitzgerald Date: Tue, 19 Apr 2022 19:53:14 -0400 Subject: [PATCH 02/10] [hal/vk] Properly write sampler descriptor arrays --- wgpu-hal/src/vulkan/device.rs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/wgpu-hal/src/vulkan/device.rs b/wgpu-hal/src/vulkan/device.rs index d6a2e3bd21..7b52e20b33 100644 --- a/wgpu-hal/src/vulkan/device.rs +++ b/wgpu-hal/src/vulkan/device.rs @@ -1309,11 +1309,15 @@ impl crate::Device for super::Device { write = match ty { vk::DescriptorType::SAMPLER => { let index = sampler_infos.len(); - let binding = desc.samplers[entry.resource_index as usize]; - let vk_info = vk::DescriptorImageInfo::builder() - .sampler(binding.raw) - .build(); - sampler_infos.push(vk_info); + let start = entry.resource_index; + let end = start + entry.count; + sampler_infos.extend(desc.samplers[start as usize..end as usize].iter().map( + |binding| { + vk::DescriptorImageInfo::builder() + .sampler(binding.raw) + .build() + }, + )); write.image_info(&sampler_infos[index..]) } vk::DescriptorType::SAMPLED_IMAGE | vk::DescriptorType::STORAGE_IMAGE => { From 799c09c0e9ce5f35a761c7444270176ec8a25ade Mon Sep 17 00:00:00 2001 From: Connor Fitzgerald Date: Wed, 20 Apr 2022 00:20:48 -0400 Subject: [PATCH 03/10] Implement binding arrays on dx12 --- wgpu-hal/src/dx12/adapter.rs | 31 ++-- wgpu-hal/src/dx12/device.rs | 175 ++++++++++++--------- wgpu/examples/texture-arrays/indexing.wgsl | 51 ++++-- wgpu/examples/texture-arrays/main.rs | 109 ++++++++++--- 4 files changed, 245 insertions(+), 121 deletions(-) diff --git a/wgpu-hal/src/dx12/adapter.rs b/wgpu-hal/src/dx12/adapter.rs index f774cc8635..3be86494d8 100644 --- a/wgpu-hal/src/dx12/adapter.rs +++ b/wgpu-hal/src/dx12/adapter.rs @@ -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::() as _, + ) + }); + let mut workarounds = super::Workarounds::default(); let info = wgt::AdapterInfo { @@ -175,11 +187,6 @@ impl super::Adapter { | wgt::Features::DEPTH_CLIP_CONTROL | wgt::Features::INDIRECT_FIRST_INSTANCE | 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_COUNT | wgt::Features::ADDRESS_MODE_CLAMP_TO_BORDER @@ -204,6 +211,13 @@ impl super::Adapter { != 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(); Some(crate::ExposedAdapter { @@ -297,12 +311,7 @@ impl crate::Adapter for super::Adapter { .into_device_result("Queue creation")? }; - let device = super::Device::new( - self.device, - queue, - self.private_caps, - &self.library, - )?; + let device = super::Device::new(self.device, queue, self.private_caps, &self.library)?; Ok(crate::OpenDevice { device, queue: super::Queue { diff --git a/wgpu-hal/src/dx12/device.rs b/wgpu-hal/src/dx12/device.rs index ab8a3f684f..ca86a56843 100644 --- a/wgpu-hal/src/dx12/device.rs +++ b/wgpu-hal/src/dx12/device.rs @@ -682,16 +682,17 @@ impl crate::Device for super::Device { ) -> Result { let (mut num_buffer_views, mut num_samplers, mut num_texture_views) = (0, 0, 0); for entry in desc.entries.iter() { + let count = entry.count.map_or(1, NonZeroU32::get); match entry.ty { wgt::BindingType::Buffer { has_dynamic_offset: true, .. } => {} - wgt::BindingType::Buffer { .. } => num_buffer_views += 1, + wgt::BindingType::Buffer { .. } => num_buffer_views += count, 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, } } @@ -849,7 +850,10 @@ impl crate::Device for super::Device { group: index as u32, binding: entry.binding, }, - bt.clone(), + hlsl::BindTarget { + binding_array_size: entry.count.map(NonZeroU32::get), + ..bt.clone() + }, ); ranges.push(native::DescriptorRange::new( range_ty, @@ -857,7 +861,7 @@ impl crate::Device for super::Device { native_binding(bt), d3d12::D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND, )); - bt.register += 1; + bt.register += entry.count.map(NonZeroU32::get).unwrap_or(1); } if ranges.len() > range_base { log::debug!( @@ -885,7 +889,10 @@ impl crate::Device for super::Device { group: index as u32, binding: entry.binding, }, - bind_sampler.clone(), + hlsl::BindTarget { + binding_array_size: entry.count.map(NonZeroU32::get), + ..bind_sampler.clone() + }, ); ranges.push(native::DescriptorRange::new( range_ty, @@ -893,7 +900,7 @@ impl crate::Device for super::Device { native_binding(&bind_sampler), 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 { log::debug!( @@ -944,7 +951,10 @@ impl crate::Device for super::Device { group: index as u32, binding: entry.binding, }, - bt.clone(), + hlsl::BindTarget { + binding_array_size: entry.count.map(NonZeroU32::get), + ..bt.clone() + }, ); info.dynamic_buffers.push(kind); @@ -960,7 +970,7 @@ impl crate::Device for super::Device { native_binding(bt), )); - bt.register += 1; + bt.register += entry.count.map(NonZeroU32::get).unwrap_or(1); } bind_group_infos.push(info); @@ -1073,82 +1083,97 @@ impl crate::Device for super::Device { has_dynamic_offset: true, .. } => { - let data = &desc.buffers[entry.resource_index as usize]; - dynamic_buffers.push(data.resolve_address()); + let start = entry.resource_index as usize; + let end = start + entry.count as usize; + for data in &desc.buffers[start..end] { + dynamic_buffers.push(data.resolve_address()); + } } wgt::BindingType::Buffer { ty, .. } => { - let data = &desc.buffers[entry.resource_index as usize]; - let gpu_address = data.resolve_address(); - let size = data.resolve_size() as u32; - let inner = cpu_views.as_mut().unwrap(); - let cpu_index = inner.stage.len() as u32; - let handle = desc.layout.cpu_heap_views.as_ref().unwrap().at(cpu_index); - match ty { - wgt::BufferBindingType::Uniform => { - let size_mask = - d3d12::D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT - 1; - let raw_desc = d3d12::D3D12_CONSTANT_BUFFER_VIEW_DESC { - BufferLocation: gpu_address, - SizeInBytes: ((size - 1) | size_mask) + 1, - }; - self.raw.CreateConstantBufferView(&raw_desc, handle); - } - wgt::BufferBindingType::Storage { read_only: true } => { - let mut raw_desc = d3d12::D3D12_SHADER_RESOURCE_VIEW_DESC { - Format: dxgiformat::DXGI_FORMAT_R32_TYPELESS, - Shader4ComponentMapping: - view::D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING, - ViewDimension: d3d12::D3D12_SRV_DIMENSION_BUFFER, - u: mem::zeroed(), - }; - *raw_desc.u.Buffer_mut() = d3d12::D3D12_BUFFER_SRV { - FirstElement: data.offset / 4, - NumElements: size / 4, - StructureByteStride: 0, - Flags: d3d12::D3D12_BUFFER_SRV_FLAG_RAW, - }; - self.raw.CreateShaderResourceView( - 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, - ViewDimension: d3d12::D3D12_UAV_DIMENSION_BUFFER, - u: mem::zeroed(), - }; - *raw_desc.u.Buffer_mut() = d3d12::D3D12_BUFFER_UAV { - FirstElement: data.offset / 4, - NumElements: size / 4, - StructureByteStride: 0, - CounterOffsetInBytes: 0, - Flags: d3d12::D3D12_BUFFER_UAV_FLAG_RAW, - }; - self.raw.CreateUnorderedAccessView( - data.buffer.resource.as_mut_ptr(), - ptr::null_mut(), - &raw_desc, - handle, - ); + let start = entry.resource_index as usize; + let end = start + entry.count as usize; + for data in &desc.buffers[start..end] { + let gpu_address = data.resolve_address(); + let size = data.resolve_size() as u32; + let inner = cpu_views.as_mut().unwrap(); + let cpu_index = inner.stage.len() as u32; + let handle = desc.layout.cpu_heap_views.as_ref().unwrap().at(cpu_index); + match ty { + wgt::BufferBindingType::Uniform => { + let size_mask = + d3d12::D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT - 1; + let raw_desc = d3d12::D3D12_CONSTANT_BUFFER_VIEW_DESC { + BufferLocation: gpu_address, + SizeInBytes: ((size - 1) | size_mask) + 1, + }; + self.raw.CreateConstantBufferView(&raw_desc, handle); + } + wgt::BufferBindingType::Storage { read_only: true } => { + let mut raw_desc = d3d12::D3D12_SHADER_RESOURCE_VIEW_DESC { + Format: dxgiformat::DXGI_FORMAT_R32_TYPELESS, + Shader4ComponentMapping: + view::D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING, + ViewDimension: d3d12::D3D12_SRV_DIMENSION_BUFFER, + u: mem::zeroed(), + }; + *raw_desc.u.Buffer_mut() = d3d12::D3D12_BUFFER_SRV { + FirstElement: data.offset / 4, + NumElements: size / 4, + StructureByteStride: 0, + Flags: d3d12::D3D12_BUFFER_SRV_FLAG_RAW, + }; + self.raw.CreateShaderResourceView( + 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, + ViewDimension: d3d12::D3D12_UAV_DIMENSION_BUFFER, + u: mem::zeroed(), + }; + *raw_desc.u.Buffer_mut() = d3d12::D3D12_BUFFER_UAV { + FirstElement: data.offset / 4, + NumElements: size / 4, + StructureByteStride: 0, + CounterOffsetInBytes: 0, + Flags: d3d12::D3D12_BUFFER_UAV_FLAG_RAW, + }; + self.raw.CreateUnorderedAccessView( + data.buffer.resource.as_mut_ptr(), + ptr::null_mut(), + &raw_desc, + handle, + ); + } } + inner.stage.push(handle); } - inner.stage.push(handle); } wgt::BindingType::Texture { .. } => { - let data = &desc.textures[entry.resource_index as usize]; - let handle = data.view.handle_srv.unwrap(); - cpu_views.as_mut().unwrap().stage.push(handle.raw); + let start = entry.resource_index as usize; + let end = start + entry.count as usize; + 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 { .. } => { - let data = &desc.textures[entry.resource_index as usize]; - let handle = data.view.handle_uav.unwrap(); - cpu_views.as_mut().unwrap().stage.push(handle.raw); + let start = entry.resource_index as usize; + let end = start + entry.count as usize; + 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 { .. } => { - let data = &desc.samplers[entry.resource_index as usize]; - cpu_samplers.as_mut().unwrap().stage.push(data.handle.raw); + let start = entry.resource_index as usize; + let end = start + entry.count as usize; + for data in &desc.samplers[start..end] { + cpu_samplers.as_mut().unwrap().stage.push(data.handle.raw); + } } } } diff --git a/wgpu/examples/texture-arrays/indexing.wgsl b/wgpu/examples/texture-arrays/indexing.wgsl index da972ba18b..1694374b97 100644 --- a/wgpu/examples/texture-arrays/indexing.wgsl +++ b/wgpu/examples/texture-arrays/indexing.wgsl @@ -25,36 +25,59 @@ struct FragmentInput { } @group(0) @binding(0) -var texture_array: binding_array>; +var texture_array_top: binding_array>; @group(0) @binding(1) +var texture_array_bottom: binding_array>; +@group(0) @binding(2) var sampler_array: binding_array; struct Uniforms { index: u32, } -var uniforms: Uniforms; +@group(0) @binding(3) +var uniforms: Uniforms; @fragment fn uniform_main(fragment: FragmentInput) -> @location(0) vec4 { - var outval = textureSampleLevel( - texture_array[uniforms.index], - sampler_array[uniforms.index], - fragment.tex_coord, - 0.0 - ).rgb; + var outval: vec3; + 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(outval.x, outval.y, outval.z, 1.0); } @fragment fn non_uniform_main(fragment: FragmentInput) -> @location(0) vec4 { - var outval = textureSampleLevel( - texture_array[fragment.index], - sampler_array[fragment.index], - fragment.tex_coord, - 0.0 - ).rgb; + var outval: vec3; + 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(outval.x, outval.y, outval.z, 1.0); } diff --git a/wgpu/examples/texture-arrays/main.rs b/wgpu/examples/texture-arrays/main.rs index f43ed7f806..cf90115f8a 100644 --- a/wgpu/examples/texture-arrays/main.rs +++ b/wgpu/examples/texture-arrays/main.rs @@ -2,7 +2,7 @@ mod framework; use bytemuck::{Pod, Zeroable}; -use std::num::NonZeroU32; +use std::num::{NonZeroU32, NonZeroU64}; use wgpu::util::DeviceExt; #[repr(C)] @@ -51,12 +51,16 @@ fn create_indices() -> Vec { enum Color { Red, Green, + Blue, + White, } fn create_texture_data(color: Color) -> [u8; 4] { match color { Color::Red => [255, 0, 0, 255], Color::Green => [0, 255, 0, 255], + Color::Blue => [0, 0, 255, 255], + Color::White => [255, 255, 255, 255], } } @@ -72,17 +76,10 @@ struct Example { impl framework::Example for Example { fn optional_features() -> wgpu::Features { wgpu::Features::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING - | wgpu::Features::PUSH_CONSTANTS } fn required_features() -> wgpu::Features { wgpu::Features::TEXTURE_BINDING_ARRAY } - fn required_limits() -> wgpu::Limits { - wgpu::Limits { - max_push_constant_size: 4, - ..wgpu::Limits::default() - } - } fn init( config: &wgpu::SurfaceConfiguration, _adapter: &wgpu::Adapter, @@ -118,6 +115,8 @@ impl framework::Example for Example { } }; + println!("Using fragment entry point '{}'", fragment_entry_point); + let vertex_size = std::mem::size_of::(); let vertex_data = create_vertices(); let vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { @@ -133,8 +132,19 @@ impl framework::Example for Example { 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 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 { size: wgpu::Extent3d::default(), @@ -153,9 +163,19 @@ impl framework::Example for Example { label: Some("green"), ..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 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( red_texture.as_image_copy(), @@ -177,6 +197,26 @@ impl framework::Example for Example { }, 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()); @@ -196,9 +236,29 @@ impl framework::Example for Example { wgpu::BindGroupLayoutEntry { binding: 1, 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), 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, + }, ], }); @@ -213,8 +273,23 @@ impl framework::Example for Example { }, wgpu::BindGroupEntry { binding: 1, + resource: wgpu::BindingResource::TextureViewArray(&[ + &blue_texture_view, + &white_texture_view, + ]), + }, + wgpu::BindGroupEntry { + binding: 2, 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, label: Some("bind group"), @@ -223,14 +298,7 @@ impl framework::Example for Example { let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("main"), bind_group_layouts: &[&bind_group_layout], - push_constant_ranges: if uniform_workaround { - &[wgpu::PushConstantRange { - stages: wgpu::ShaderStages::FRAGMENT, - range: 0..4, - }] - } else { - &[] - }, + push_constant_ranges: &[], }); let index_format = wgpu::IndexFormat::Uint16; @@ -306,15 +374,15 @@ impl framework::Example for Example { }); rpass.set_pipeline(&self.pipeline); - rpass.set_bind_group(0, &self.bind_group, &[]); rpass.set_vertex_buffer(0, self.vertex_buffer.slice(..)); rpass.set_index_buffer(self.index_buffer.slice(..), self.index_format); 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.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); } else { + rpass.set_bind_group(0, &self.bind_group, &[0]); rpass.draw_indexed(0..12, 0, 0..1); } @@ -379,8 +447,7 @@ fn texture_arrays_unsized_non_uniform() { 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, + | wgpu::Features::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING, base_test_parameters: framework::test_common::TestParameters::default().failure(), tolerance: 0, max_outliers: 0, From 33466283cf51c578d28a6823d12f7113feb6d21e Mon Sep 17 00:00:00 2001 From: Connor Fitzgerald Date: Wed, 20 Apr 2022 01:09:19 -0400 Subject: [PATCH 04/10] Support sampler arrays on metal --- wgpu-hal/src/metal/device.rs | 74 ++++++++++++++++++++---------------- 1 file changed, 42 insertions(+), 32 deletions(-) diff --git a/wgpu-hal/src/metal/device.rs b/wgpu-hal/src/metal/device.rs index ac29074859..5aef9eb332 100644 --- a/wgpu-hal/src/metal/device.rs +++ b/wgpu-hal/src/metal/device.rs @@ -1,5 +1,6 @@ use parking_lot::Mutex; use std::{ + num::NonZeroU32, ptr, sync::{atomic, Arc}, thread, time, @@ -73,6 +74,8 @@ impl super::Device { ) .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(); options.set_language_version(self.shared.private_caps.msl_version); @@ -558,10 +561,12 @@ impl crate::Device for super::Device { } 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 { wgt::BindingType::Buffer { ty, .. } => { target.buffer = Some(info.counters.buffers as _); - info.counters.buffers += 1; + info.counters.buffers += count; if let wgt::BufferBindingType::Storage { read_only } = ty { target.mutable = !read_only; } @@ -570,15 +575,15 @@ impl crate::Device for super::Device { target.sampler = Some(naga::back::msl::BindSamplerTarget::Resource( info.counters.samplers as _, )); - info.counters.samplers += 1; + info.counters.samplers += count; } wgt::BindingType::Texture { .. } => { target.texture = Some(info.counters.textures as _); - info.counters.textures += 1; + info.counters.textures += count; } wgt::BindingType::StorageTexture { access, .. } => { target.texture = Some(info.counters.textures as _); - info.counters.textures += 1; + info.counters.textures += count; target.mutable = match access { wgt::StorageTextureAccess::ReadOnly => false, wgt::StorageTextureAccess::WriteOnly => true, @@ -691,7 +696,7 @@ impl crate::Device for super::Device { .. } = layout.ty { - dynamic_offsets_count += 1; + dynamic_offsets_count += size; } if !layout.visibility.contains(stage_bit) { continue; @@ -702,39 +707,44 @@ impl crate::Device for super::Device { has_dynamic_offset, .. } => { - debug_assert_eq!(size, 1); - let source = &desc.buffers[entry.resource_index as usize]; - let remaining_size = - wgt::BufferSize::new(source.buffer.size - source.offset); - let binding_size = match ty { - wgt::BufferBindingType::Storage { .. } => { - source.size.or(remaining_size) - } - _ => None, - }; - bg.buffers.push(super::BufferResource { - ptr: source.buffer.as_raw(), - offset: source.offset, - dynamic_index: if has_dynamic_offset { - Some(dynamic_offsets_count - 1) - } else { - None - }, - binding_size, - binding_location: layout.binding, - }); + let start = entry.resource_index as usize; + let end = start + size as usize; + bg.buffers + .extend(desc.buffers[start..end].iter().map(|source| { + let remaining_size = + wgt::BufferSize::new(source.buffer.size - source.offset); + let binding_size = match ty { + wgt::BufferBindingType::Storage { .. } => { + source.size.or(remaining_size) + } + _ => None, + }; + super::BufferResource { + ptr: source.buffer.as_raw(), + offset: source.offset, + dynamic_index: if has_dynamic_offset { + Some(dynamic_offsets_count - 1) + } else { + None + }, + binding_size, + binding_location: layout.binding, + } + })); counter.buffers += 1; } wgt::BindingType::Sampler { .. } => { - let res = desc.samplers[entry.resource_index as usize].as_raw(); - bg.samplers.push(res); - counter.samplers += 1; + let start = entry.resource_index as usize; + let end = start + size as usize; + bg.samplers + .extend(desc.samplers[start..end].iter().map(|samp| samp.as_raw())); + counter.samplers += size; } wgt::BindingType::Texture { .. } | wgt::BindingType::StorageTexture { .. } => { - let start = entry.resource_index; - let end = start + size; + let start = entry.resource_index as usize; + let end = start + size as usize; bg.textures.extend( - desc.textures[start as usize..end as usize] + desc.textures[start..end] .iter() .map(|tex| tex.view.as_raw()), ); From 03f5c3f331a221d4462df263917b175206559b67 Mon Sep 17 00:00:00 2001 From: Connor Fitzgerald Date: Wed, 20 Apr 2022 02:06:48 -0400 Subject: [PATCH 05/10] Fix texture array tests --- wgpu/examples/texture-arrays/indexing.wgsl | 22 ------- wgpu/examples/texture-arrays/main.rs | 54 ++++++------------ .../texture-arrays/non_uniform_indexing.wgsl | 33 +++++++++++ wgpu/examples/texture-arrays/screenshot.png | Bin 0 -> 6568 bytes 4 files changed, 49 insertions(+), 60 deletions(-) create mode 100644 wgpu/examples/texture-arrays/non_uniform_indexing.wgsl create mode 100644 wgpu/examples/texture-arrays/screenshot.png diff --git a/wgpu/examples/texture-arrays/indexing.wgsl b/wgpu/examples/texture-arrays/indexing.wgsl index 1694374b97..0f952264c4 100644 --- a/wgpu/examples/texture-arrays/indexing.wgsl +++ b/wgpu/examples/texture-arrays/indexing.wgsl @@ -59,25 +59,3 @@ fn uniform_main(fragment: FragmentInput) -> @location(0) vec4 { return vec4(outval.x, outval.y, outval.z, 1.0); } - -@fragment -fn non_uniform_main(fragment: FragmentInput) -> @location(0) vec4 { - var outval: vec3; - 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(outval.x, outval.y, outval.z, 1.0); -} diff --git a/wgpu/examples/texture-arrays/main.rs b/wgpu/examples/texture-arrays/main.rs index cf90115f8a..87e89cc48f 100644 --- a/wgpu/examples/texture-arrays/main.rs +++ b/wgpu/examples/texture-arrays/main.rs @@ -87,7 +87,7 @@ impl framework::Example for Example { queue: &wgpu::Queue, ) -> Self { let mut uniform_workaround = false; - let shader_module = device.create_shader_module(&wgpu::include_wgsl!("indexing.wgsl")); + let base_shader_module = device.create_shader_module(&wgpu::include_wgsl!("indexing.wgsl")); let env_override = match std::env::var("WGPU_TEXTURE_ARRAY_STYLE") { Ok(value) => match &*value.to_lowercase() { "nonuniform" | "non_uniform" => Some(true), @@ -114,6 +114,15 @@ impl framework::Example for Example { "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); @@ -307,7 +316,7 @@ impl framework::Example for Example { label: None, layout: Some(&pipeline_layout), vertex: wgpu::VertexState { - module: &shader_module, + module: &base_shader_module, entry_point: "vert_main", buffers: &[wgpu::VertexBufferLayout { array_stride: vertex_size as wgpu::BufferAddress, @@ -316,7 +325,7 @@ impl framework::Example for Example { }], }, fragment: Some(wgpu::FragmentState { - module: &shader_module, + module: &fragment_shader_module, entry_point: fragment_entry_point, targets: &[config.format.into()], }), @@ -396,60 +405,29 @@ fn main() { framework::run::("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::(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] fn texture_arrays_uniform() { framework::test::(framework::FrameworkRefTest { image_path: "/examples/texture-arrays/screenshot.png", width: 1024, height: 768, - optional_features: wgpu::Features::TEXTURE_BINDING_ARRAY | wgpu::Features::PUSH_CONSTANTS, - base_test_parameters: framework::test_common::TestParameters::default().failure(), + optional_features: wgpu::Features::empty(), + 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_non_uniform() { framework::test::(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, - base_test_parameters: framework::test_common::TestParameters::default().failure(), + optional_features: wgpu::Features::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING, + 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::(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, - base_test_parameters: framework::test_common::TestParameters::default().failure(), - tolerance: 0, - max_outliers: 0, - }); -} diff --git a/wgpu/examples/texture-arrays/non_uniform_indexing.wgsl b/wgpu/examples/texture-arrays/non_uniform_indexing.wgsl new file mode 100644 index 0000000000..7fb30e7929 --- /dev/null +++ b/wgpu/examples/texture-arrays/non_uniform_indexing.wgsl @@ -0,0 +1,33 @@ +struct FragmentInput { + @location(0) tex_coord: vec2, + @location(1) index: i32, +} + +@group(0) @binding(0) +var texture_array_top: binding_array>; +@group(0) @binding(1) +var texture_array_bottom: binding_array>; +@group(0) @binding(2) +var sampler_array: binding_array; + +@fragment +fn non_uniform_main(fragment: FragmentInput) -> @location(0) vec4 { + var outval: vec3; + 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(outval.x, outval.y, outval.z, 1.0); +} diff --git a/wgpu/examples/texture-arrays/screenshot.png b/wgpu/examples/texture-arrays/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..3bafceb552cc478977e4a643af652fd0344b296e GIT binary patch literal 6568 zcmeAS@N?(olHy`uVBq!ia0y~yU;#3j893O0)UI8kybKJI`JOJ0Ar*7p-e44DP~bVT z;q3m58U1SQ?df;Ti}@KeB46_}STX@MaxySnP-b9om;lsjJ1Q_59;3-&G&hVE2BT%+ zXx%VcHIB9nMjJ+>?ZVM!@!;wvY%c%*n~A}p=PP@I93ulm(;9n*FB}XE0x5qP7q~Mp zG$;W3HsCmmtY>&3$iSd*;uo_+KQJ9TUXy320(O-+HvNOPaz~9A4U5rqF`7q4%Zt&n ybF>}-Hg-oV#L)_Iv_c%M5JxLSk}AZ{j5hnLrvG`rbq=tb!QkoY=d#Wzp$PyB`32?x literal 0 HcmV?d00001 From 567d06c08ec0b29805acfb3b9f158661689671fe Mon Sep 17 00:00:00 2001 From: Connor Fitzgerald Date: Mon, 25 Apr 2022 01:07:42 -0400 Subject: [PATCH 06/10] Update naga to 1aa91549 --- Cargo.lock | 1 + Cargo.toml | 2 +- wgpu-core/Cargo.toml | 2 +- wgpu-hal/Cargo.toml | 4 ++-- wgpu-hal/src/dx12/device.rs | 2 +- wgpu-hal/src/vulkan/device.rs | 8 +------- wgpu/Cargo.toml | 6 +++--- 7 files changed, 10 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 575c1c228c..962fcb1de5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1032,6 +1032,7 @@ dependencies = [ [[package]] name = "naga" version = "0.8.0" +source = "git+https://github.com/gfx-rs/naga?rev=1aa91549#1aa9154964238af8c692cf521ff90e1f2395e147" dependencies = [ "bit-set", "bitflags", diff --git a/Cargo.toml b/Cargo.toml index 8bf2f6d65d..7d3044ae3d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,7 @@ exclude = [ default-members = ["wgpu", "wgpu-hal", "wgpu-info"] [patch."https://github.com/gfx-rs/naga"] -naga = { path = "../naga" } +#naga = { path = "../naga" } [patch."https://github.com/zakarumych/gpu-descriptor"] #gpu-descriptor = { path = "../gpu-descriptor/gpu-descriptor" } diff --git a/wgpu-core/Cargo.toml b/wgpu-core/Cargo.toml index e33cd7c45b..cafa3d5436 100644 --- a/wgpu-core/Cargo.toml +++ b/wgpu-core/Cargo.toml @@ -40,7 +40,7 @@ thiserror = "1" [dependencies.naga] git = "https://github.com/gfx-rs/naga" -rev = "ad283968" +rev = "1aa91549" #version = "0.8" features = ["span", "validate", "wgsl-in"] diff --git a/wgpu-hal/Cargo.toml b/wgpu-hal/Cargo.toml index 3c317d0a32..529fc4f174 100644 --- a/wgpu-hal/Cargo.toml +++ b/wgpu-hal/Cargo.toml @@ -91,14 +91,14 @@ js-sys = { version = "0.3" } [dependencies.naga] git = "https://github.com/gfx-rs/naga" -rev = "ad283968" +rev = "1aa91549" #version = "0.8" # DEV dependencies [dev-dependencies.naga] git = "https://github.com/gfx-rs/naga" -rev = "ad283968" +rev = "1aa91549" #version = "0.8" features = ["wgsl-in"] diff --git a/wgpu-hal/src/dx12/device.rs b/wgpu-hal/src/dx12/device.rs index ca86a56843..2f92cab44c 100644 --- a/wgpu-hal/src/dx12/device.rs +++ b/wgpu-hal/src/dx12/device.rs @@ -970,7 +970,7 @@ impl crate::Device for super::Device { native_binding(bt), )); - bt.register += entry.count.map(NonZeroU32::get).unwrap_or(1); + bt.register += entry.count.map_or(1, NonZeroU32::get); } bind_group_infos.push(info); diff --git a/wgpu-hal/src/vulkan/device.rs b/wgpu-hal/src/vulkan/device.rs index 7b52e20b33..79127eb178 100644 --- a/wgpu-hal/src/vulkan/device.rs +++ b/wgpu-hal/src/vulkan/device.rs @@ -1115,13 +1115,7 @@ impl crate::Device for super::Device { .entries .iter() .enumerate() - .filter_map(|(idx, entry)| { - if let Some(count) = entry.count { - Some((idx as u32, count)) - } else { - None - } - }) + .filter_map(|(idx, entry)| entry.count.map(|count| (idx as u32, count))) .collect(); let mut binding_flag_info; diff --git a/wgpu/Cargo.toml b/wgpu/Cargo.toml index 4cb3f00f8f..404c72a9d5 100644 --- a/wgpu/Cargo.toml +++ b/wgpu/Cargo.toml @@ -138,20 +138,20 @@ env_logger = "0.9" [dependencies.naga] git = "https://github.com/gfx-rs/naga" -rev = "ad283968" +rev = "1aa91549" #version = "0.8" optional = true # used to test all the example shaders [dev-dependencies.naga] git = "https://github.com/gfx-rs/naga" -rev = "ad283968" +rev = "1aa91549" #version = "0.8" features = ["wgsl-in"] [target.'cfg(target_arch = "wasm32")'.dependencies.naga] git = "https://github.com/gfx-rs/naga" -rev = "ad283968" +rev = "1aa91549" #version = "0.8" features = ["wgsl-out"] From 8a6c6094de0d580c87645a7fbc68b9a188fce16d Mon Sep 17 00:00:00 2001 From: Connor Fitzgerald Date: Mon, 25 Apr 2022 01:10:06 -0400 Subject: [PATCH 07/10] README updates --- wgpu/examples/README.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/wgpu/examples/README.md b/wgpu/examples/README.md index 70b01aadda..efbf6fa776 100644 --- a/wgpu/examples/README.md +++ b/wgpu/examples/README.md @@ -21,7 +21,6 @@ All framework-based examples render to the window and are reftested against the | implicit layout | | | | :star: | | | | | | | | sampled color textures | :star: | :star: | :star: | :star: | | | :star: | :star: | :star: | :star: | | storage textures | :star: | | | | | | | | | | -| binding array | | | | | | | | :star: | | | | comparison samplers | | | | | | :star: | | | | | | subresource views | | | | :star: | | :star: | | | | | | cubemaps | | | | | | | :star: | | | | @@ -36,9 +35,9 @@ All framework-based examples render to the window and are reftested against the | compute passes | :star: | | | | | | | | | | | error scopes | | | :star: | | | | | | | | | *optional extensions* | | | | | | | | :star: | | | -| - SPIR-V shaders | | | | | | | | :star: | | | -| - binding indexing | | | | | | | | :star: | | | -| - push constants | | | | | | | | :star: | | | +| - SPIR-V shaders | | | | | | | | | | | +| - binding array | | | | | | | | :star: | | | +| - push constants | | | | | | | | | | | | - depth clamping | | | | | | :star: | | | | | | - compressed textures | | | | | | | :star: | | | | | - polygon mode | | | :star: | | | | | | | | From b4810ba9c7db793dbea46f9b23e8919bd8bba30e Mon Sep 17 00:00:00 2001 From: Connor Fitzgerald Date: Mon, 25 Apr 2022 01:15:10 -0400 Subject: [PATCH 08/10] Clippy --- wgpu/examples/texture-arrays/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wgpu/examples/texture-arrays/main.rs b/wgpu/examples/texture-arrays/main.rs index 87e89cc48f..34ffc44941 100644 --- a/wgpu/examples/texture-arrays/main.rs +++ b/wgpu/examples/texture-arrays/main.rs @@ -325,7 +325,7 @@ impl framework::Example for Example { }], }, fragment: Some(wgpu::FragmentState { - module: &fragment_shader_module, + module: fragment_shader_module, entry_point: fragment_entry_point, targets: &[config.format.into()], }), From 70056820810b06d99f46857eccae82ab78082dcd Mon Sep 17 00:00:00 2001 From: Connor Fitzgerald Date: Mon, 25 Apr 2022 01:21:31 -0400 Subject: [PATCH 09/10] CI fixes --- deno_webgpu/src/lib.rs | 7 ------- wgpu-hal/src/metal/device.rs | 7 ++++++- wgpu-hal/src/vulkan/mod.rs | 7 +------ wgpu/examples/texture-arrays/main.rs | 7 ++++--- 4 files changed, 11 insertions(+), 17 deletions(-) diff --git a/deno_webgpu/src/lib.rs b/deno_webgpu/src/lib.rs index 63bd720ebb..96cb351407 100644 --- a/deno_webgpu/src/lib.rs +++ b/deno_webgpu/src/lib.rs @@ -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"); } - 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) { return_features.push("address-mode-clamp-to-border"); } @@ -341,10 +338,6 @@ impl From for wgpu_types::Features { .0 .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( wgpu_types::Features::ADDRESS_MODE_CLAMP_TO_BORDER, required_features.0.contains("address-mode-clamp-to-border"), diff --git a/wgpu-hal/src/metal/device.rs b/wgpu-hal/src/metal/device.rs index 5aef9eb332..4b36e3d757 100644 --- a/wgpu-hal/src/metal/device.rs +++ b/wgpu-hal/src/metal/device.rs @@ -74,7 +74,12 @@ impl super::Device { ) .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); + log::debug!( + "Naga generated shader for entry point '{}' and stage {:?}\n{}", + stage.entry_point, + naga_stage, + &source + ); let options = mtl::CompileOptions::new(); options.set_language_version(self.shared.private_caps.msl_version); diff --git a/wgpu-hal/src/vulkan/mod.rs b/wgpu-hal/src/vulkan/mod.rs index caade3dc07..0b7e116437 100644 --- a/wgpu-hal/src/vulkan/mod.rs +++ b/wgpu-hal/src/vulkan/mod.rs @@ -31,12 +31,7 @@ mod conv; mod device; mod instance; -use std::{ - borrow::Borrow, - ffi::CStr, - num::{NonZeroU32}, - sync::Arc, -}; +use std::{borrow::Borrow, ffi::CStr, num::NonZeroU32, sync::Arc}; use arrayvec::ArrayVec; use ash::{ diff --git a/wgpu/examples/texture-arrays/main.rs b/wgpu/examples/texture-arrays/main.rs index 34ffc44941..8c68585cc4 100644 --- a/wgpu/examples/texture-arrays/main.rs +++ b/wgpu/examples/texture-arrays/main.rs @@ -118,7 +118,8 @@ impl framework::Example for Example { // 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 = + device.create_shader_module(&wgpu::include_wgsl!("non_uniform_indexing.wgsl")); &non_uniform_shader_module } else { &base_shader_module @@ -424,10 +425,10 @@ fn texture_arrays_non_uniform() { image_path: "/examples/texture-arrays/screenshot.png", width: 1024, height: 768, - optional_features: wgpu::Features::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING, + optional_features: + wgpu::Features::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING, base_test_parameters: framework::test_common::TestParameters::default(), tolerance: 0, max_outliers: 0, }); } - From 37b55a2c1bc1136f58a2e6898e93ac1f46dc5fef Mon Sep 17 00:00:00 2001 From: Connor Fitzgerald Date: Mon, 25 Apr 2022 14:20:24 -0400 Subject: [PATCH 10/10] CI --- player/tests/data/clear-buffer-texture.ron | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/player/tests/data/clear-buffer-texture.ron b/player/tests/data/clear-buffer-texture.ron index bd01fb61d7..a4e2485c3d 100644 --- a/player/tests/data/clear-buffer-texture.ron +++ b/player/tests/data/clear-buffer-texture.ron @@ -1,5 +1,5 @@ ( - features: 0x0000_0020_0000_0000, + features: 0x0000_0010_0000_0000, expectations: [ ( name: "Quad",