Skip to content

Commit

Permalink
hal/gl: Allow push constants trough emulation
Browse files Browse the repository at this point in the history
Uses a uniform buffer to emulate push constants since openGL doesn't
support them natively.
  • Loading branch information
JCapucho committed Jan 17, 2022
1 parent 5b2b6f5 commit 41e18c1
Show file tree
Hide file tree
Showing 10 changed files with 69 additions and 16 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion wgpu-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"]

Expand Down
4 changes: 2 additions & 2 deletions wgpu-hal/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"]

Expand Down
30 changes: 25 additions & 5 deletions wgpu-hal/src/gles/adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"),
Expand Down Expand Up @@ -363,6 +364,9 @@ impl super::Adapter {
0
};

let max_uniform_buffer_binding_size =
gl.get_parameter_i32(glow::MAX_UNIFORM_BLOCK_SIZE) as u32;

let limits = wgt::Limits {
max_texture_dimension_1d: max_texture_size,
max_texture_dimension_2d: max_texture_size,
Expand All @@ -376,8 +380,7 @@ impl super::Adapter {
max_storage_buffers_per_shader_stage,
max_storage_textures_per_shader_stage,
max_uniform_buffers_per_shader_stage,
max_uniform_buffer_binding_size: gl.get_parameter_i32(glow::MAX_UNIFORM_BLOCK_SIZE)
as u32,
max_uniform_buffer_binding_size,
max_storage_buffer_binding_size: if ver >= (3, 1) {
gl.get_parameter_i32(glow::MAX_SHADER_STORAGE_BLOCK_SIZE)
} else {
Expand All @@ -399,7 +402,7 @@ impl super::Adapter {
} else {
!0
},
max_push_constant_size: 0,
max_push_constant_size: max_uniform_buffer_binding_size,
min_uniform_buffer_offset_alignment,
min_storage_buffer_offset_alignment,
max_inter_stage_shader_components: gl.get_parameter_i32(glow::MAX_VARYING_COMPONENTS)
Expand Down Expand Up @@ -522,7 +525,7 @@ impl crate::Adapter<super::Api> for super::Adapter {
unsafe fn open(
&self,
features: wgt::Features,
_limits: &wgt::Limits,
limits: &wgt::Limits,
) -> Result<crate::OpenDevice<super::Api>, crate::DeviceError> {
let gl = &self.shared.context.lock();
gl.pixel_store_i32(glow::UNPACK_ALIGNMENT, 1);
Expand All @@ -539,6 +542,22 @@ impl crate::Adapter<super::Api> for super::Adapter {
let zeroes = vec![0u8; super::ZERO_BUFFER_SIZE];
gl.buffer_data_u8_slice(glow::COPY_READ_BUFFER, &zeroes, glow::STATIC_DRAW);

let push_constants_buffer = if features.contains(wgt::Features::PUSH_CONSTANTS) {
let size = limits.max_push_constant_size.max(256) as i32;
let buffer = gl
.create_buffer()
.map_err(|_| crate::DeviceError::OutOfMemory)?;
gl.bind_buffer(glow::UNIFORM_BUFFER, Some(buffer));
gl.buffer_data_size(glow::UNIFORM_BUFFER, size, glow::DYNAMIC_READ);
let ptr = gl.map_buffer_range(glow::UNIFORM_BUFFER, 0, size, glow::MAP_WRITE_BIT);
// TODO: this should always be 4 byte aligned but maybe add some checks
let slice = std::slice::from_raw_parts_mut(ptr as *mut u32, size as usize);
gl.bind_buffer(glow::UNIFORM_BUFFER, None);
Some((buffer, slice))
} else {
None
};

// Compile the shader program we use for doing manual clears to work around Mesa fastclear
// bug.
let (shader_clear_program, shader_clear_program_color_uniform_location) =
Expand Down Expand Up @@ -566,6 +585,7 @@ impl crate::Adapter<super::Api> for super::Adapter {
temp_query_results: Vec::new(),
draw_buffer_count: 1,
current_index_buffer: None,
push_constants_buffer,
},
})
}
Expand Down
9 changes: 6 additions & 3 deletions wgpu-hal/src/gles/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -603,10 +603,13 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
&mut self,
_layout: &super::PipelineLayout,
_stages: wgt::ShaderStages,
_offset: u32,
_data: &[u32],
offset: u32,
data: &[u32],
) {
unimplemented!()
self.cmd_buffer.commands.push(C::SetPushConstants {
offset,
data: data.into(),
});
}

unsafe fn insert_debug_marker(&mut self, label: &str) {
Expand Down
12 changes: 12 additions & 0 deletions wgpu-hal/src/gles/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ impl CompilationContext<'_> {
ep_info: &naga::valid::FunctionInfo,
reflection_info: naga::back::glsl::ReflectionInfo,
) {
if let Some(name) = reflection_info.push_constant {
self.name_binding_map
.insert(name, (super::BindingRegister::UniformBuffers, 0));
}

for (handle, var) in module.global_variables.iter() {
if ep_info[handle].is_empty() {
continue;
Expand Down Expand Up @@ -809,6 +814,12 @@ impl crate::Device<super::Api> for super::Device {
);
let mut binding_map = glsl::BindingMap::default();

// If push constants are used by the pipeline, reserve the first slot
// for the uniform buffer used to emulate push constants.
if !desc.push_constant_ranges.is_empty() {
num_uniform_buffers += 1;
}

for (group_index, bg_layout) in desc.bind_group_layouts.iter().enumerate() {
// create a vector with the size enough to hold all the bindings, filled with `!0`
let mut binding_to_slot = vec![
Expand Down Expand Up @@ -856,6 +867,7 @@ impl crate::Device<super::Api> for super::Device {
version: self.shared.shading_language_version,
writer_flags,
binding_map,
push_constant_binding: 0,
},
})
}
Expand Down
5 changes: 5 additions & 0 deletions wgpu-hal/src/gles/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ pub struct Queue {
temp_query_results: Vec<u64>,
draw_buffer_count: u8,
current_index_buffer: Option<glow::Buffer>,
push_constants_buffer: Option<(glow::Buffer, &'static mut [u32])>,
}

#[derive(Clone, Debug)]
Expand Down Expand Up @@ -716,6 +717,10 @@ enum Command {
InsertDebugMarker(Range<u32>),
PushDebugGroup(Range<u32>),
PopDebugGroup,
SetPushConstants {
offset: u32,
data: Vec<u32>,
},
}

#[derive(Default)]
Expand Down
13 changes: 13 additions & 0 deletions wgpu-hal/src/gles/queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1067,6 +1067,19 @@ impl super::Queue {
#[cfg(not(target_arch = "wasm32"))]
gl.pop_debug_group();
}
C::SetPushConstants { offset, ref data } => {
let &mut (buffer, ref mut buffer_data) =
self.push_constants_buffer.as_mut().unwrap();
buffer_data[offset as usize..(offset as usize + data.len())]
.copy_from_slice(&data[..]);
gl.bind_buffer_range(
glow::UNIFORM_BUFFER,
0,
Some(buffer),
offset as i32,
data.len() as i32,
);
}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion wgpu-hal/src/metal/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down
6 changes: 3 additions & 3 deletions wgpu/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"]

Expand Down

0 comments on commit 41e18c1

Please sign in to comment.