Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: Timestamp queries #3636

Merged
merged 56 commits into from
Aug 2, 2023
Merged
Show file tree
Hide file tree
Changes from 28 commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
53ff5df
feat: timestamp query on metal
FL33TW00D Mar 28, 2023
15c21f4
chore: clippy
FL33TW00D Apr 2, 2023
31b5870
chore: CHANGELOG
FL33TW00D Apr 2, 2023
f86bff8
chore: initial render mock
FL33TW00D Apr 2, 2023
cd5d147
chore: more work
FL33TW00D Apr 2, 2023
326de79
chore: working render example
FL33TW00D Apr 2, 2023
92329a6
chore: update tests, one failing
FL33TW00D Apr 2, 2023
1ce3e4e
chore: testing
FL33TW00D Apr 3, 2023
c7669c1
remove unnecessary naga patch again
Wumpf Apr 30, 2023
dfd8a3b
incorporate webgpu spec changes
Wumpf May 1, 2023
6eba839
"fix" timestamp conversion on metal, comments to clarify the situatio…
Wumpf May 1, 2023
77bbe86
fix metal timequery feature detection
Wumpf May 1, 2023
8d445f1
warning fixes
Wumpf May 1, 2023
cc84ae1
better error handling for failing to create metal timestamp counter
Wumpf May 1, 2023
c8433d8
use public version of metal in patch
Wumpf May 6, 2023
0c26cd9
disable metal deprecation warnings (and comment why and what)
Wumpf May 6, 2023
d2f7e8b
better documentation for timestamp features
Wumpf May 6, 2023
9680a18
dedicated sample for timestamp queries
Wumpf May 7, 2023
76b55bd
add command encoder timestamps on example, notes on (missing) impleme…
Wumpf May 7, 2023
7f48055
finish rolling back changes to hello-triangle & hello-compute
Wumpf May 7, 2023
e3f71b7
reset timerqueries for being/end pass queries, implement begin/end pa…
Wumpf May 7, 2023
55627de
implement begin/end pass timer queries for DX12
Wumpf May 7, 2023
f9df588
minor cleanup in new timerstamp-query sample
Wumpf May 7, 2023
70414a3
compile & warning fixes
Wumpf May 7, 2023
ca9fbc2
Merge branch 'gfx-rs:trunk' into feature/metal-timestamp
FL33TW00D May 10, 2023
641b0db
fix remaining warnings & errors
Wumpf May 14, 2023
83d2402
remove timestamp feature requirement again from hello-compute/triangle
Wumpf May 14, 2023
788b219
chore: remove patch
FL33TW00D May 21, 2023
0c0c787
remove direct dependency to foreign-types
Wumpf May 29, 2023
9b462e7
Merge remote-tracking branch 'upstream/trunk' into feature/metal-time…
Wumpf May 29, 2023
4819fa5
Merge branch 'trunk' into feature/metal-timestamp
cwfitzgerald Jun 5, 2023
a111844
Format
cwfitzgerald Jun 5, 2023
73c58ed
Merge remote-tracking branch 'upstream/trunk' into feature/metal-time…
Wumpf Jul 23, 2023
bb5ad0e
dx12: reuse write_timestamp method more often
Wumpf Jul 23, 2023
43dcabd
longer expose for timestamp query example
Wumpf Jul 23, 2023
079754c
comment fixes/improvements
Wumpf Jul 23, 2023
1b1db9b
added timestamp query tests, fix test compilation
Wumpf Jul 23, 2023
d15dabf
warning fixes
Wumpf Jul 23, 2023
9b5423e
fix dx12 compilation
Wumpf Jul 23, 2023
98f20bf
Merge remote-tracking branch 'upstream/trunk' into feature/metal-time…
Wumpf Jul 23, 2023
280e50c
d3d12::QuerySet no longer implements Clone
Wumpf Jul 23, 2023
6a8dc8b
improve timestamp test assertions
Wumpf Jul 23, 2023
4aaf264
fix send/sync assertions on wasm builds
Wumpf Jul 23, 2023
27bcd25
disable timestamp test for molkenvk
Wumpf Jul 23, 2023
9a4cc4c
Merge branch 'trunk' into feature/metal-timestamp
FL33TW00D Jul 25, 2023
8585e16
Merge branch 'trunk' into feature/metal-timestamp
FL33TW00D Jul 25, 2023
1c5e6c8
Merge branch 'trunk' into feature/metal-timestamp
FL33TW00D Jul 27, 2023
de0807e
Merge branch 'trunk' into feature/metal-timestamp
FL33TW00D Jul 29, 2023
1c7c175
Workaround https://github.com/gfx-rs/wgpu/issues/3993
Wumpf Jul 30, 2023
f942813
enable test_timestamps_passes test for molten
Wumpf Jul 30, 2023
dec97f8
fix querying invalid queries in example
Wumpf Jul 30, 2023
00f0095
enable test_timestamps_encoder on molten
Wumpf Jul 30, 2023
422a1e6
Merge branch 'trunk' into feature/metal-timestamp
FL33TW00D Aug 2, 2023
f23322e
Apply suggestions from code review
cwfitzgerald Aug 2, 2023
2fc4cf2
Simplify feature logic
cwfitzgerald Aug 2, 2023
6144694
Merge branch 'trunk' into feature/metal-timestamp
cwfitzgerald Aug 2, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,15 @@ Some texture format names have changed to get back in line with the spec.

By @cwfitzgerald in [#3671](https://github.com/gfx-rs/wgpu/pull/3671).

#### Pass timestamp queries

Addition of `TimestampWrites` to compute and render passes to allow profiling.
This brings us in line with the spec.

Added new example to demonstrate the various kinds of timestamps.

By @FL33TW00D & @wumpf in [#3636](https://github.com/gfx-rs/wgpu/pull/3636).

#### Misc Breaking Changes

- Change type of `mip_level_count` and `array_layer_count` (members of `TextureViewDescriptor` and `ImageSubresourceRange`) from `Option<NonZeroU32>` to `Option<u32>`. By @teoxoy in [#3445](https://github.com/gfx-rs/wgpu/pull/3445)
Expand Down
13 changes: 10 additions & 3 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 Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ winit = "0.27.1"
# Metal dependencies
block = "0.1"
foreign-types = "0.3"
metal = "0.24.0"
metal = "0.25.0"
objc = "0.2.5"
core-graphics-types = "0.1"

Expand Down
2 changes: 2 additions & 0 deletions deno_webgpu/command_encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ pub fn op_webgpu_command_encoder_begin_render_pass(
label: label.map(Cow::from),
color_attachments: Cow::from(color_attachments),
depth_stencil_attachment: processed_depth_stencil_attachment.as_ref(),
timestamp_writes: None,
};

let render_pass = wgpu_core::command::RenderPass::new(command_encoder_resource.1, &descriptor);
Expand All @@ -200,6 +201,7 @@ pub fn op_webgpu_command_encoder_begin_compute_pass(

let descriptor = wgpu_core::command::ComputePassDescriptor {
label: label.map(Cow::from),
timestamp_writes: None,
};

let compute_pass =
Expand Down
4 changes: 3 additions & 1 deletion deno_webgpu/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,9 @@ impl From<DeviceError> for WebGpuError {
match err {
DeviceError::Lost => WebGpuError::Lost,
DeviceError::OutOfMemory => WebGpuError::OutOfMemory,
DeviceError::Invalid => WebGpuError::Validation(fmt_err(&err)),
DeviceError::ResourceCreationFailed | DeviceError::Invalid => {
WebGpuError::Validation(fmt_err(&err))
}
}
}
}
Expand Down
15 changes: 12 additions & 3 deletions player/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,20 +119,29 @@ impl GlobalPlay for wgc::hub::Global<IdentityPassThroughFactory> {
trace::Command::InsertDebugMarker(marker) => self
.command_encoder_insert_debug_marker::<A>(encoder, &marker)
.unwrap(),
trace::Command::RunComputePass { base } => {
self.command_encoder_run_compute_pass_impl::<A>(encoder, base.as_ref())
.unwrap();
trace::Command::RunComputePass {
base,
timestamp_writes,
} => {
self.command_encoder_run_compute_pass_impl::<A>(
encoder,
base.as_ref(),
timestamp_writes.as_ref(),
)
.unwrap();
}
trace::Command::RunRenderPass {
base,
target_colors,
target_depth_stencil,
timestamp_writes,
} => {
self.command_encoder_run_render_pass_impl::<A>(
encoder,
base.as_ref(),
&target_colors,
target_depth_stencil.as_ref(),
timestamp_writes.as_ref(),
)
.unwrap();
}
Expand Down
1 change: 1 addition & 0 deletions wgpu-core/src/command/clear.rs
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,7 @@ fn clear_texture_via_render_passes<A: hal::Api>(
color_attachments,
depth_stencil_attachment,
multiview: None,
timestamp_writes: None,
});
encoder.end_render_pass();
}
Expand Down
78 changes: 75 additions & 3 deletions wgpu-core/src/command/compute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ use crate::{
};

use hal::CommandEncoder as _;
#[cfg(any(feature = "serial-pass", feature = "replay"))]
use serde::Deserialize;
#[cfg(any(feature = "serial-pass", feature = "trace"))]
use serde::Serialize;

use thiserror::Error;

use std::{fmt, mem, str};
Expand Down Expand Up @@ -90,6 +95,7 @@ pub enum ComputeCommand {
pub struct ComputePass {
base: BasePass<ComputeCommand>,
parent_id: id::CommandEncoderId,
timestamp_writes: Option<ComputePassTimestampWrites>,

// Resource binding dedupe state.
#[cfg_attr(feature = "serial-pass", serde(skip))]
Expand All @@ -103,6 +109,7 @@ impl ComputePass {
Self {
base: BasePass::new(&desc.label),
parent_id,
timestamp_writes: desc.timestamp_writes.cloned(),

current_bind_groups: BindGroupStateChange::new(),
current_pipeline: StateChange::new(),
Expand All @@ -115,7 +122,10 @@ impl ComputePass {

#[cfg(feature = "trace")]
pub fn into_command(self) -> crate::device::trace::Command {
crate::device::trace::Command::RunComputePass { base: self.base }
crate::device::trace::Command::RunComputePass {
base: self.base,
timestamp_writes: self.timestamp_writes,
}
}
}

Expand All @@ -131,9 +141,25 @@ impl fmt::Debug for ComputePass {
}
}

/// Describes the writing of timestamp values in a compute pass.
#[repr(C)]
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(any(feature = "serial-pass", feature = "trace"), derive(Serialize))]
#[cfg_attr(any(feature = "serial-pass", feature = "replay"), derive(Deserialize))]
pub struct ComputePassTimestampWrites {
/// The query set to write the timestamps to.
pub query_set: id::QuerySetId,
/// The index of the query at which the start timestamp of the pass is written if any.
pub beginning_of_pass_write_index: Option<u32>,
/// The index of the query at which the end timestamp of the pass is written if any.
pub end_of_pass_write_index: Option<u32>,
}

#[derive(Clone, Debug, Default)]
pub struct ComputePassDescriptor<'a> {
pub label: Label<'a>,
/// Defines where and when timestamp values will be written for this pass.
pub timestamp_writes: Option<&'a ComputePassTimestampWrites>,
}

#[derive(Clone, Debug, Error, Eq, PartialEq)]
Expand Down Expand Up @@ -321,14 +347,19 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
encoder_id: id::CommandEncoderId,
pass: &ComputePass,
) -> Result<(), ComputePassError> {
self.command_encoder_run_compute_pass_impl::<A>(encoder_id, pass.base.as_ref())
self.command_encoder_run_compute_pass_impl::<A>(
encoder_id,
pass.base.as_ref(),
pass.timestamp_writes.as_ref(),
)
}

#[doc(hidden)]
pub fn command_encoder_run_compute_pass_impl<A: HalApi>(
&self,
encoder_id: id::CommandEncoderId,
base: BasePassRef<ComputeCommand>,
timestamp_writes: Option<&ComputePassTimestampWrites>,
) -> Result<(), ComputePassError> {
profiling::scope!("CommandEncoder::run_compute_pass");
let init_scope = PassErrorScope::Pass(encoder_id);
Expand All @@ -354,6 +385,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
if let Some(ref mut list) = cmd_buf.commands {
list.push(crate::device::trace::Command::RunComputePass {
base: BasePass::from_ref(base),
timestamp_writes: timestamp_writes.cloned(),
});
}

Expand All @@ -376,6 +408,42 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
let mut string_offset = 0;
let mut active_query = None;

let timestamp_writes = if let Some(tw) = timestamp_writes {
let query_set: &resource::QuerySet<A> = cmd_buf
.trackers
.query_sets
.add_single(&*query_set_guard, tw.query_set)
.ok_or(ComputePassErrorInner::InvalidQuerySet(tw.query_set))
.map_pass_err(init_scope)?;

// Unlike in render passes we can't delay resetting the query sets since
// there is no auxillary pass.
let range = if let (Some(index_a), Some(index_b)) =
(tw.beginning_of_pass_write_index, tw.end_of_pass_write_index)
{
Some(index_a.min(index_b)..index_a.max(index_b) + 1)
} else {
tw.beginning_of_pass_write_index
.or(tw.end_of_pass_write_index)
.map(|i| i..i + 1)
};
// Range should always be Some, both values being None should lead to a validation err.r
cwfitzgerald marked this conversation as resolved.
Show resolved Hide resolved
// But no point in erroring over that nuance here!
if let Some(range) = range {
unsafe {
raw.reset_queries(&query_set.raw, range);
}
}

Some(hal::ComputePassTimestampWrites {
query_set: &query_set.raw,
beginning_of_pass_write_index: tw.beginning_of_pass_write_index,
end_of_pass_write_index: tw.end_of_pass_write_index,
})
} else {
None
};

cmd_buf.trackers.set_size(
Some(&*buffer_guard),
Some(&*texture_guard),
Expand All @@ -388,7 +456,11 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
Some(&*query_set_guard),
);

let hal_desc = hal::ComputePassDescriptor { label: base.label };
let hal_desc = hal::ComputePassDescriptor {
label: base.label,
timestamp_writes,
};

unsafe {
raw.begin_compute_pass(&hal_desc);
}
Expand Down
2 changes: 2 additions & 0 deletions wgpu-core/src/command/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ pub struct CommandBuffer<A: HalApi> {
pub(crate) trackers: Tracker<A>,
buffer_memory_init_actions: Vec<BufferInitTrackerAction>,
texture_memory_actions: CommandBufferTextureMemoryActions,
pub(crate) pending_query_resets: QueryResetMap<A>,
limits: wgt::Limits,
support_clear_texture: bool,
#[cfg(feature = "trace")]
Expand Down Expand Up @@ -127,6 +128,7 @@ impl<A: HalApi> CommandBuffer<A> {
trackers: Tracker::new(),
buffer_memory_init_actions: Default::default(),
texture_memory_actions: Default::default(),
pending_query_resets: QueryResetMap::new(),
limits,
support_clear_texture: features.contains(wgt::Features::CLEAR_TEXTURE),
#[cfg(feature = "trace")]
Expand Down
6 changes: 3 additions & 3 deletions wgpu-core/src/command/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use thiserror::Error;
use wgt::BufferAddress;

#[derive(Debug)]
pub(super) struct QueryResetMap<A: hal::Api> {
pub(crate) struct QueryResetMap<A: hal::Api> {
map: FastHashMap<Index, (Vec<bool>, Epoch)>,
_phantom: PhantomData<A>,
}
Expand Down Expand Up @@ -43,12 +43,12 @@ impl<A: hal::Api> QueryResetMap<A> {
}

pub fn reset_queries(
self,
&mut self,
raw_encoder: &mut A::CommandEncoder,
query_set_storage: &Storage<QuerySet<A>, id::QuerySetId>,
backend: wgt::Backend,
) -> Result<(), id::QuerySetId> {
for (query_set_id, (state, epoch)) in self.map.into_iter() {
for (query_set_id, (state, epoch)) in self.map.drain() {
let id = Id::zip(query_set_id, epoch, backend);
let query_set = query_set_storage.get(id).map_err(|_| id)?;

Expand Down
Loading