From 704e6fb920598f69cdf093c8ed9d10e352d76abb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Capucho?= Date: Sat, 15 Jan 2022 15:16:59 +0000 Subject: [PATCH] hal/gl: Allow push constants trough emulation Uses freestanding uniforms for push constants --- Cargo.lock | 2 +- Cargo.toml | 1 + wgpu-core/Cargo.toml | 2 +- wgpu-hal/Cargo.toml | 4 +- wgpu-hal/src/gles/adapter.rs | 5 ++- wgpu-hal/src/gles/command.rs | 44 +++++++++++++++++--- wgpu-hal/src/gles/device.rs | 43 +++++++++++++++++++- wgpu-hal/src/gles/mod.rs | 7 +++- wgpu-hal/src/gles/queue.rs | 78 ++++++++++++++++++++++++++++++++++++ wgpu-hal/src/metal/device.rs | 2 +- wgpu/Cargo.toml | 6 +-- 11 files changed, 176 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 74884819c5e..6f93884aa8d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1039,7 +1039,7 @@ dependencies = [ [[package]] name = "naga" version = "0.8.0" -source = "git+https://github.com/gfx-rs/naga?rev=c0b7ac7#c0b7ac7f542cc42ccac6f2ec3fc1fb01309cf4d7" +source = "git+https://github.com/JCapucho/naga?branch=glsl-out-push-constants-v2#c60d70eddf99d5858747d0a7823ab79c8cd0d019" dependencies = [ "bit-set", "bitflags", diff --git a/Cargo.toml b/Cargo.toml index 0c7770ed44c..53c15013a73 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,6 +18,7 @@ default-members = ["wgpu", "wgpu-hal", "wgpu-info"] [patch."https://github.com/gfx-rs/naga"] #naga = { path = "../naga" } +naga = { git = "https://github.com/JCapucho/naga", branch = "glsl-out-push-constants-v2" } [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 4460086e262..45977a517b5 100644 --- a/wgpu-core/Cargo.toml +++ b/wgpu-core/Cargo.toml @@ -38,7 +38,7 @@ thiserror = "1" [dependencies.naga] git = "https://github.com/gfx-rs/naga" -rev = "c0b7ac7" +rev = "a1840be" #version = "0.8" features = ["span", "validate", "wgsl-in"] diff --git a/wgpu-hal/Cargo.toml b/wgpu-hal/Cargo.toml index 045aded7873..9f69af5098e 100644 --- a/wgpu-hal/Cargo.toml +++ b/wgpu-hal/Cargo.toml @@ -82,14 +82,14 @@ js-sys = { version = "0.3" } [dependencies.naga] git = "https://github.com/gfx-rs/naga" -rev = "c0b7ac7" +rev = "a1840be" #version = "0.8" # DEV dependencies [dev-dependencies.naga] git = "https://github.com/gfx-rs/naga" -rev = "c0b7ac7" +rev = "a1840be" #version = "0.8" features = ["wgsl-in"] diff --git a/wgpu-hal/src/gles/adapter.rs b/wgpu-hal/src/gles/adapter.rs index e4bb5b60c94..d1438165d1b 100644 --- a/wgpu-hal/src/gles/adapter.rs +++ b/wgpu-hal/src/gles/adapter.rs @@ -286,7 +286,8 @@ impl super::Adapter { let mut features = wgt::Features::empty() | wgt::Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES - | wgt::Features::CLEAR_TEXTURE; + | wgt::Features::CLEAR_TEXTURE + | wgt::Features::PUSH_CONSTANTS; features.set( wgt::Features::ADDRESS_MODE_CLAMP_TO_BORDER, extensions.contains("GL_EXT_texture_border_clamp"), @@ -399,7 +400,7 @@ impl super::Adapter { } else { !0 }, - max_push_constant_size: 0, + max_push_constant_size: 64, min_uniform_buffer_offset_alignment, min_storage_buffer_offset_alignment, max_inter_stage_shader_components: gl.get_parameter_i32(glow::MAX_VARYING_COMPONENTS) diff --git a/wgpu-hal/src/gles/command.rs b/wgpu-hal/src/gles/command.rs index a2e80e0f6c8..3b9dd7cf7b2 100644 --- a/wgpu-hal/src/gles/command.rs +++ b/wgpu-hal/src/gles/command.rs @@ -28,6 +28,7 @@ pub(super) struct State { has_pass_label: bool, instance_vbuf_mask: usize, dirty_vbuf_mask: usize, + uniforms: Box<[super::UniformDesc]>, } impl super::CommandBuffer { @@ -43,6 +44,19 @@ impl super::CommandBuffer { self.data_bytes.extend(marker.as_bytes()); start..self.data_bytes.len() as u32 } + + fn add_push_constant_data(&mut self, data: &[u32]) -> Range { + let data_raw = unsafe { + std::slice::from_raw_parts( + data.as_ptr() as *const _, + data.len() * mem::size_of::(), + ) + }; + let start = self.data_bytes.len(); + self.data_bytes.extend_from_slice(data_raw); + let end = self.data_bytes.len(); + start..end + } } impl super::CommandEncoder { @@ -148,8 +162,7 @@ impl super::CommandEncoder { fn set_pipeline_inner(&mut self, inner: &super::PipelineInner) { self.cmd_buffer.commands.push(C::SetProgram(inner.program)); - //TODO: push constants - let _ = &inner.uniforms; + self.state.uniforms = inner.uniforms.clone(); // rebind textures, if needed let mut dirty_textures = 0u32; @@ -603,10 +616,31 @@ impl crate::CommandEncoder for super::CommandEncoder { &mut self, _layout: &super::PipelineLayout, _stages: wgt::ShaderStages, - _offset: u32, - _data: &[u32], + offset: u32, + data: &[u32], ) { - unimplemented!() + let range = self.cmd_buffer.add_push_constant_data(data); + + let uniforms = &self.state.uniforms; + if uniforms.is_empty() { + unimplemented!() + } + + let uniform = if offset == 0 { + // If offset is zero, we can just return the first item + // in our uniform list + uniforms.get(0).unwrap() + } else { + match uniforms.binary_search_by(|uniform| uniform.offset.cmp(&offset)) { + Ok(index) => uniforms.get(index).unwrap(), + Err(_) => panic!("No uniform found at offset: {}", offset), + } + } + .clone(); + + self.cmd_buffer + .commands + .push(C::SetPushConstants { uniform, range }); } unsafe fn insert_debug_marker(&mut self, label: &str) { diff --git a/wgpu-hal/src/gles/device.rs b/wgpu-hal/src/gles/device.rs index a85301fa2c0..3a13e27205c 100644 --- a/wgpu-hal/src/gles/device.rs +++ b/wgpu-hal/src/gles/device.rs @@ -281,9 +281,48 @@ impl super::Device { let glow::ActiveUniform { size, utype, name } = gl.get_active_uniform(program, uniform).unwrap(); + match utype { + glow::INT_SAMPLER_1D + | glow::INT_SAMPLER_1D_ARRAY + | glow::INT_SAMPLER_2D + | glow::INT_SAMPLER_2D_ARRAY + | glow::INT_SAMPLER_2D_MULTISAMPLE + | glow::INT_SAMPLER_2D_MULTISAMPLE_ARRAY + | glow::INT_SAMPLER_2D_RECT + | glow::INT_SAMPLER_3D + | glow::INT_SAMPLER_CUBE + | glow::INT_SAMPLER_CUBE_MAP_ARRAY + | glow::UNSIGNED_INT_SAMPLER_1D + | glow::UNSIGNED_INT_SAMPLER_1D_ARRAY + | glow::UNSIGNED_INT_SAMPLER_2D + | glow::UNSIGNED_INT_SAMPLER_2D_ARRAY + | glow::UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE + | glow::UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY + | glow::UNSIGNED_INT_SAMPLER_2D_RECT + | glow::UNSIGNED_INT_SAMPLER_3D + | glow::UNSIGNED_INT_SAMPLER_CUBE + | glow::UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY + | glow::SAMPLER_1D + | glow::SAMPLER_1D_SHADOW + | glow::SAMPLER_1D_ARRAY + | glow::SAMPLER_1D_ARRAY_SHADOW + | glow::SAMPLER_2D + | glow::SAMPLER_2D_SHADOW + | glow::SAMPLER_2D_ARRAY + | glow::SAMPLER_2D_ARRAY_SHADOW + | glow::SAMPLER_2D_MULTISAMPLE + | glow::SAMPLER_2D_MULTISAMPLE_ARRAY + | glow::SAMPLER_2D_RECT + | glow::SAMPLER_2D_RECT_SHADOW + | glow::SAMPLER_3D + | glow::SAMPLER_CUBE + | glow::SAMPLER_CUBE_MAP_ARRAY + | glow::SAMPLER_CUBE_MAP_ARRAY_SHADOW + | glow::SAMPLER_CUBE_SHADOW => continue, + _ => {} + } + if let Some(location) = gl.get_uniform_location(program, &name) { - // Sampler2D won't show up in UniformLocation and the only other uniforms - // should be push constants uniforms.push(super::UniformDesc { location, offset, diff --git a/wgpu-hal/src/gles/mod.rs b/wgpu-hal/src/gles/mod.rs index d5e1980b212..18150accaa4 100644 --- a/wgpu-hal/src/gles/mod.rs +++ b/wgpu-hal/src/gles/mod.rs @@ -393,7 +393,7 @@ struct VertexBufferDesc { } #[allow(unused)] -#[derive(Clone)] +#[derive(Clone, Debug)] struct UniformDesc { location: glow::UniformLocation, offset: u32, @@ -716,6 +716,11 @@ enum Command { InsertDebugMarker(Range), PushDebugGroup(Range), PopDebugGroup, + SetPushConstants { + uniform: UniformDesc, + /// Offset from the start of the `data_bytes` + range: Range, + }, } #[derive(Default)] diff --git a/wgpu-hal/src/gles/queue.rs b/wgpu-hal/src/gles/queue.rs index b3acddc9f85..b5370531c73 100644 --- a/wgpu-hal/src/gles/queue.rs +++ b/wgpu-hal/src/gles/queue.rs @@ -1067,6 +1067,84 @@ impl super::Queue { #[cfg(not(target_arch = "wasm32"))] gl.pop_debug_group(); } + C::SetPushConstants { + ref uniform, + ref range, + } => { + let range = range.clone(); + fn get_data(data: &[u8], range: std::ops::Range) -> &[T] { + let range_size = range.end - range.start; + assert_eq!(range_size % mem::size_of::(), 0); + assert!(data.len() >= range.start + range_size); + let raw = &data[range.start..range.end]; + unsafe { + slice::from_raw_parts( + raw.as_ptr() as *const _, + raw.len() / mem::size_of::(), + ) + } + } + + match uniform.utype { + glow::FLOAT => { + let data = get_data::(data_bytes, range)[0]; + gl.uniform_1_f32(Some(&uniform.location.clone()), data); + } + glow::FLOAT_VEC2 => { + let data = get_data::<[f32; 2]>(data_bytes, range)[0]; + gl.uniform_2_f32_slice(Some(&uniform.location.clone()), &data); + } + glow::FLOAT_VEC3 => { + let data = get_data::<[f32; 3]>(data_bytes, range)[0]; + gl.uniform_3_f32_slice(Some(&uniform.location.clone()), &data); + } + glow::FLOAT_VEC4 => { + let data = get_data::<[f32; 4]>(data_bytes, range)[0]; + gl.uniform_4_f32_slice(Some(&uniform.location.clone()), &data); + } + glow::INT => { + let data = get_data::(data_bytes, range)[0]; + gl.uniform_1_i32(Some(&uniform.location.clone()), data); + } + glow::INT_VEC2 => { + let data = get_data::<[i32; 2]>(data_bytes, range)[0]; + gl.uniform_2_i32_slice(Some(&uniform.location.clone()), &data); + } + glow::INT_VEC3 => { + let data = get_data::<[i32; 3]>(data_bytes, range)[0]; + gl.uniform_3_i32_slice(Some(&uniform.location.clone()), &data); + } + glow::INT_VEC4 => { + let data = get_data::<[i32; 4]>(data_bytes, range)[0]; + gl.uniform_4_i32_slice(Some(&uniform.location.clone()), &data); + } + glow::FLOAT_MAT2 => { + let data = get_data::<[f32; 4]>(data_bytes, range)[0]; + gl.uniform_matrix_2_f32_slice( + Some(&uniform.location.clone()), + false, + &data, + ); + } + glow::FLOAT_MAT3 => { + let data = get_data::<[f32; 9]>(data_bytes, range)[0]; + gl.uniform_matrix_3_f32_slice( + Some(&uniform.location.clone()), + false, + &data, + ); + } + glow::FLOAT_MAT4 => { + let data = get_data::<[f32; 16]>(data_bytes, range)[0]; + gl.uniform_matrix_4_f32_slice( + Some(&uniform.location.clone()), + false, + &data, + ); + } + _ => panic!("Unsupported uniform datatype!"), + } + } } } } diff --git a/wgpu-hal/src/metal/device.rs b/wgpu-hal/src/metal/device.rs index cc6dc6ab938..f2d09912757 100644 --- a/wgpu-hal/src/metal/device.rs +++ b/wgpu-hal/src/metal/device.rs @@ -117,7 +117,7 @@ impl super::Device { let mut immutable_buffer_mask = 0; for (var_handle, var) in module.global_variables.iter() { if var.class == naga::StorageClass::WorkGroup { - let size = module.types[var.ty].inner.span(&module.constants); + let size = module.types[var.ty].inner.size(&module.constants); wg_memory_sizes.push(size); } diff --git a/wgpu/Cargo.toml b/wgpu/Cargo.toml index 5110322b833..dc6f4eb455a 100644 --- a/wgpu/Cargo.toml +++ b/wgpu/Cargo.toml @@ -136,20 +136,20 @@ env_logger = "0.8" [dependencies.naga] git = "https://github.com/gfx-rs/naga" -rev = "c0b7ac7" +rev = "a1840be" #version = "0.8" optional = true # used to test all the example shaders [dev-dependencies.naga] git = "https://github.com/gfx-rs/naga" -rev = "c0b7ac7" +rev = "a1840be" #version = "0.8" features = ["wgsl-in"] [target.'cfg(target_arch = "wasm32")'.dependencies.naga] git = "https://github.com/gfx-rs/naga" -rev = "c0b7ac7" +rev = "a1840be" #version = "0.8" features = ["wgsl-out"]