use crate::{GpuProfiler, GpuProfilerQuery, ProfilerCommandRecorder};
pub struct Scope<'a, Recorder: ProfilerCommandRecorder> {
pub profiler: &'a GpuProfiler,
pub recorder: &'a mut Recorder,
pub scope: Option<GpuProfilerQuery>,
}
impl<R: ProfilerCommandRecorder> Drop for Scope<'_, R> {
#[inline]
fn drop(&mut self) {
if let Some(scope) = self.scope.take() {
self.profiler.end_query(self.recorder, scope);
}
}
}
pub struct OwningScope<'a, Recorder: ProfilerCommandRecorder> {
pub profiler: &'a GpuProfiler,
pub recorder: Recorder,
pub scope: Option<GpuProfilerQuery>,
}
impl<R: ProfilerCommandRecorder> Drop for OwningScope<'_, R> {
#[inline]
fn drop(&mut self) {
if let Some(scope) = self.scope.take() {
self.profiler.end_query(&mut self.recorder, scope);
}
}
}
pub struct ManualOwningScope<'a, Recorder: ProfilerCommandRecorder> {
pub profiler: &'a GpuProfiler,
pub recorder: Recorder,
pub scope: Option<GpuProfilerQuery>,
}
impl<R: ProfilerCommandRecorder> ManualOwningScope<'_, R> {
#[track_caller]
#[inline]
pub fn end_query(mut self) -> R {
self.profiler
.end_query(&mut self.recorder, self.scope.take().unwrap());
self.recorder
}
}
macro_rules! impl_scope_ext {
($scope:ident, $recorder_type:ty) => {
impl<'a, R: ProfilerCommandRecorder> $scope<'a, R> {
#[must_use]
#[track_caller]
#[inline]
pub fn scope(&mut self, label: impl Into<String>) -> Scope<'_, R> {
let recorder: &mut R = &mut self.recorder;
let scope = self
.profiler
.begin_query(label, recorder)
.with_parent(self.scope.as_ref());
Scope {
profiler: self.profiler,
recorder,
scope: Some(scope),
}
}
}
impl<'a> $scope<'a, wgpu::CommandEncoder> {
#[track_caller]
pub fn scoped_render_pass(
&mut self,
label: impl Into<String>,
pass_descriptor: wgpu::RenderPassDescriptor<'_>,
) -> OwningScope<'_, wgpu::RenderPass<'_>> {
let child_scope = self
.profiler
.begin_pass_query(label, &mut self.recorder)
.with_parent(self.scope.as_ref());
let render_pass = self
.recorder
.begin_render_pass(&wgpu::RenderPassDescriptor {
timestamp_writes: child_scope.render_pass_timestamp_writes(),
label: pass_descriptor.label.or(Some(&child_scope.label)),
..pass_descriptor
});
OwningScope {
profiler: self.profiler,
recorder: render_pass,
scope: Some(child_scope),
}
}
#[track_caller]
pub fn scoped_compute_pass(
&mut self,
label: impl Into<String>,
) -> OwningScope<'_, wgpu::ComputePass<'_>> {
let child_scope = self
.profiler
.begin_pass_query(label, &mut self.recorder)
.with_parent(self.scope.as_ref());
let render_pass = self
.recorder
.begin_compute_pass(&wgpu::ComputePassDescriptor {
label: Some(&child_scope.label),
timestamp_writes: child_scope.compute_pass_timestamp_writes(),
});
OwningScope {
profiler: self.profiler,
recorder: render_pass,
scope: Some(child_scope),
}
}
}
impl<'a, R: ProfilerCommandRecorder> std::ops::Deref for $scope<'a, R> {
type Target = R;
#[inline]
fn deref(&self) -> &Self::Target {
&self.recorder
}
}
impl<'a, R: ProfilerCommandRecorder> std::ops::DerefMut for $scope<'a, R> {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.recorder
}
}
};
}
impl_scope_ext!(Scope, &'a mut R);
impl_scope_ext!(OwningScope, R);
impl_scope_ext!(ManualOwningScope, R);