Skip to content

Commit

Permalink
Add timestamp support to OpenGL
Browse files Browse the repository at this point in the history
  • Loading branch information
Zoxc committed Oct 19, 2023
1 parent 7598919 commit c0ba6bb
Show file tree
Hide file tree
Showing 8 changed files with 132 additions and 26 deletions.
3 changes: 1 addition & 2 deletions 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-hal/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ rustc-hash = "1.1"
log = "0.4"

# backend: Gles
glow = { version = "0.12.3", optional = true }
glow = { git = "https://github.com/grovesNL/glow.git", commit = "f4fa72ed67c9c1edc2e92cce0fe79ab93ff8e032", optional = true }

[dependencies.wgt]
package = "wgpu-types"
Expand Down
12 changes: 11 additions & 1 deletion wgpu-hal/src/gles/adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,13 @@ impl super::Adapter {
supported((3, 1), (4, 2)) || extensions.contains("GL_ARB_shader_image_load_store"),
);
features.set(wgt::Features::SHADER_UNUSED_VERTEX_OUTPUT, true);
if extensions.contains("GL_ARB_timer_query")
&& (extensions.contains("GL_ARB_query_buffer_object")
|| extensions.contains("GL_AMD_query_buffer_object"))
{
features.set(wgt::Features::TIMESTAMP_QUERY, true);
features.set(wgt::Features::TIMESTAMP_QUERY_INSIDE_PASSES, true);
}
let gles_bcn_exts = [
"GL_EXT_texture_compression_s3tc_srgb",
"GL_EXT_texture_compression_rgtc",
Expand Down Expand Up @@ -538,7 +545,10 @@ impl super::Adapter {
);
private_caps.set(
super::PrivateCapabilities::GET_BUFFER_SUB_DATA,
cfg!(target_arch = "wasm32"),
cfg!(target_arch = "wasm32")
|| full_ver
.map(|full_ver| full_ver >= (2, 0))
.unwrap_or_default(),
);
let color_buffer_float = extensions.contains("GL_EXT_color_buffer_float")
|| extensions.contains("EXT_color_buffer_float");
Expand Down
32 changes: 30 additions & 2 deletions wgpu-hal/src/gles/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ pub(super) struct State {
dirty_vbuf_mask: usize,
active_first_instance: u32,
push_offset_to_uniform: ArrayVec<super::UniformDesc, { super::MAX_PUSH_CONSTANTS }>,
end_of_pass_timestamp: Option<glow::Query>,
}

impl super::CommandBuffer {
Expand Down Expand Up @@ -409,8 +410,9 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
unsafe fn end_query(&mut self, set: &super::QuerySet, _index: u32) {
self.cmd_buffer.commands.push(C::EndQuery(set.target));
}
unsafe fn write_timestamp(&mut self, _set: &super::QuerySet, _index: u32) {
unimplemented!()
unsafe fn write_timestamp(&mut self, set: &super::QuerySet, index: u32) {
let query = set.queries[index as usize];
self.cmd_buffer.commands.push(C::TimestampQuery(query));
}
unsafe fn reset_queries(&mut self, _set: &super::QuerySet, _range: Range<u32>) {
//TODO: what do we do here?
Expand Down Expand Up @@ -439,6 +441,15 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
// render

unsafe fn begin_render_pass(&mut self, desc: &crate::RenderPassDescriptor<super::Api>) {
debug_assert!(self.state.end_of_pass_timestamp.is_none());
desc.timestamp_writes.as_ref().map(|t| {
t.beginning_of_pass_write_index
.map(|index| unsafe { self.write_timestamp(t.query_set, index) });
self.state.end_of_pass_timestamp = t
.end_of_pass_write_index
.map(|index| t.query_set.queries[index as usize]);
});

self.state.render_size = desc.extent;
self.state.resolve_attachments.clear();
self.state.invalidate_attachments.clear();
Expand Down Expand Up @@ -623,6 +634,10 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
}
self.state.vertex_attributes.clear();
self.state.primitive = super::PrimitiveState::default();

if let Some(query) = self.state.end_of_pass_timestamp.take() {
self.cmd_buffer.commands.push(C::TimestampQuery(query));
}
}

unsafe fn set_bind_group(
Expand Down Expand Up @@ -1030,6 +1045,15 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
// compute

unsafe fn begin_compute_pass(&mut self, desc: &crate::ComputePassDescriptor<super::Api>) {
debug_assert!(self.state.end_of_pass_timestamp.is_none());
desc.timestamp_writes.as_ref().map(|t| {
t.beginning_of_pass_write_index
.map(|index| unsafe { self.write_timestamp(t.query_set, index) });
self.state.end_of_pass_timestamp = t
.end_of_pass_write_index
.map(|index| t.query_set.queries[index as usize]);
});

if let Some(label) = desc.label {
let range = self.cmd_buffer.add_marker(label);
self.cmd_buffer.commands.push(C::PushDebugGroup(range));
Expand All @@ -1041,6 +1065,10 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
self.cmd_buffer.commands.push(C::PopDebugGroup);
self.state.has_pass_label = false;
}

if let Some(query) = self.state.end_of_pass_timestamp.take() {
self.cmd_buffer.commands.push(C::TimestampQuery(query));
}
}

unsafe fn set_compute_pipeline(&mut self, pipeline: &super::ComputePipeline) {
Expand Down
9 changes: 9 additions & 0 deletions wgpu-hal/src/gles/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1224,6 +1224,14 @@ impl crate::Device<super::Api> for super::Device {
if gl.supports_debug() {
use std::fmt::Write;

// Initialize the query so we can label it
match desc.ty {
wgt::QueryType::Timestamp => unsafe {
gl.query_counter(query, glow::TIMESTAMP)
},
_ => (),
}

if let Some(label) = desc.label {
temp_string.clear();
let _ = write!(temp_string, "{label}[{i}]");
Expand All @@ -1238,6 +1246,7 @@ impl crate::Device<super::Api> for super::Device {
queries: queries.into_boxed_slice(),
target: match desc.ty {
wgt::QueryType::Occlusion => glow::ANY_SAMPLES_PASSED_CONSERVATIVE,
wgt::QueryType::Timestamp => glow::TIMESTAMP,
_ => unimplemented!(),
},
})
Expand Down
1 change: 1 addition & 0 deletions wgpu-hal/src/gles/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -775,6 +775,7 @@ enum Command {
SetIndexBuffer(glow::Buffer),
BeginQuery(glow::Query, BindTarget),
EndQuery(BindTarget),
TimestampQuery(glow::Query),
CopyQueryResults {
query_range: Range<u32>,
dst: Buffer,
Expand Down
97 changes: 78 additions & 19 deletions wgpu-hal/src/gles/queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -808,34 +808,93 @@ impl super::Queue {
C::EndQuery(target) => {
unsafe { gl.end_query(target) };
}
C::TimestampQuery(query) => {
unsafe { gl.query_counter(query, glow::TIMESTAMP) };
}
C::CopyQueryResults {
ref query_range,
ref dst,
dst_target,
dst_offset,
} => {
self.temp_query_results.clear();
for &query in queries[query_range.start as usize..query_range.end as usize].iter() {
let result = unsafe { gl.get_query_parameter_u32(query, glow::QUERY_RESULT) };
self.temp_query_results.push(result as u64);
}
let query_data = unsafe {
slice::from_raw_parts(
self.temp_query_results.as_ptr() as *const u8,
self.temp_query_results.len() * mem::size_of::<u64>(),
)
};
match dst.raw {
Some(buffer) => {
unsafe { gl.bind_buffer(dst_target, Some(buffer)) };
if self
.features
.contains(wgt::Features::TIMESTAMP_QUERY_INSIDE_PASSES)
&& dst.raw.is_some()
{
unsafe {
// We're assuming that the only relevant queries are 8 byte timestamps.
let query_size = 8;

let query_range_size = query_size * query_range.len();

let buffer = gl.create_buffer().ok();
gl.bind_buffer(glow::QUERY_BUFFER, buffer);
gl.buffer_data_size(
glow::QUERY_BUFFER,
query_range_size as _,
glow::STREAM_COPY,
);

for (i, &query) in queries
[query_range.start as usize..query_range.end as usize]
.iter()
.enumerate()
{
gl.get_query_parameter_u64_with_offset(
query,
glow::QUERY_RESULT,
query_size * i,
)
}
gl.bind_buffer(dst_target, dst.raw);
gl.copy_buffer_sub_data(
glow::QUERY_BUFFER,
dst_target,
0,
dst_offset as _,
query_range_size as _,
);
buffer.map(|buffer| gl.delete_buffer(buffer));
}
} else {
self.temp_query_results.clear();
for &query in
queries[query_range.start as usize..query_range.end as usize].iter()
{
let mut result: u64 = 0;
unsafe {
gl.buffer_sub_data_u8_slice(dst_target, dst_offset as i32, query_data)
let result: *mut u64 = &mut result;
gl.get_query_parameter_u64_with_offset(
query,
glow::QUERY_RESULT,
result as usize,
)
};
self.temp_query_results.push(result);
}
None => {
let data = &mut dst.data.as_ref().unwrap().lock().unwrap();
let len = query_data.len().min(data.len());
data[..len].copy_from_slice(&query_data[..len]);
let query_data = unsafe {
slice::from_raw_parts(
self.temp_query_results.as_ptr() as *const u8,
self.temp_query_results.len() * mem::size_of::<u64>(),
)
};
match dst.raw {
Some(buffer) => {
unsafe { gl.bind_buffer(dst_target, Some(buffer)) };
unsafe {
gl.buffer_sub_data_u8_slice(
dst_target,
dst_offset as i32,
query_data,
)
};
}
None => {
let data = &mut dst.data.as_ref().unwrap().lock().unwrap();
let len = query_data.len().min(data.len());
data[..len].copy_from_slice(&query_data[..len]);
}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion wgpu-hal/src/gles/wgl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,7 @@ impl crate::Instance<super::Api> for Instance {
)
})?;

let gl = unsafe {
let mut gl = unsafe {
glow::Context::from_loader_function(|name| load_gl_func(name, Some(opengl_module)))
};

Expand Down

0 comments on commit c0ba6bb

Please sign in to comment.