diff --git a/crates/bevy_render/src/diagnostic/internal.rs b/crates/bevy_render/src/diagnostic/internal.rs index 1f84ab4f568d8..ee9b502823e2e 100644 --- a/crates/bevy_render/src/diagnostic/internal.rs +++ b/crates/bevy_render/src/diagnostic/internal.rs @@ -34,7 +34,7 @@ struct DiagnosticsRecorderInternal { submitted_frames: Vec, finished_frames: Vec, #[cfg(feature = "tracing-tracy")] - tracy_gpu_context: tracy_client::GpuContext, + tracy_gpu_context: Option, } /// Records diagnostics into [`QuerySet`]'s keeping track of the mapping between @@ -229,14 +229,14 @@ struct FrameData { is_mapped: Arc, callback: Option>, #[cfg(feature = "tracing-tracy")] - tracy_gpu_context: tracy_client::GpuContext, + tracy_gpu_context: Option, } impl FrameData { fn new( device: &RenderDevice, features: Features, - #[cfg(feature = "tracing-tracy")] tracy_gpu_context: tracy_client::GpuContext, + #[cfg(feature = "tracing-tracy")] tracy_gpu_context: Option, ) -> FrameData { let wgpu_device = device.wgpu_device(); let mut buffer_size = 0; @@ -614,12 +614,14 @@ impl FrameData { // Calling span_alloc() and end_zone() here instead of in open_span() and close_span() means that tracy does not know where each GPU command was recorded on the CPU timeline. // Unfortunately we must do it this way, because tracy does not play nicely with multithreaded command recording. The start/end pairs would get all mixed up. // The GPU spans themselves are still accurate though, and it's probably safe to assume that each GPU span in frame N belongs to the corresponding CPU render node span from frame N-1. - let name = &self.path_components[span.path_range.clone()].join("/"); - let mut tracy_gpu_span = - self.tracy_gpu_context.span_alloc(name, "", "", 0).unwrap(); - tracy_gpu_span.end_zone(); - tracy_gpu_span.upload_timestamp_start(begin as i64); - tracy_gpu_span.upload_timestamp_end(end as i64); + if let Some(tracy_gpu_context) = &self.tracy_gpu_context { + let name = &self.path_components[span.path_range.clone()].join("/"); + let mut tracy_gpu_span = + tracy_gpu_context.span_alloc(name, "", "", 0).unwrap(); + tracy_gpu_span.end_zone(); + tracy_gpu_span.upload_timestamp_start(begin as i64); + tracy_gpu_span.upload_timestamp_end(end as i64); + } } diagnostics.push(RenderDiagnostic { diff --git a/crates/bevy_render/src/diagnostic/tracy_gpu.rs b/crates/bevy_render/src/diagnostic/tracy_gpu.rs index 488e41581190a..573975ea40038 100644 --- a/crates/bevy_render/src/diagnostic/tracy_gpu.rs +++ b/crates/bevy_render/src/diagnostic/tracy_gpu.rs @@ -9,12 +9,25 @@ pub fn new_tracy_gpu_context( adapter_info: &RenderAdapterInfo, device: &RenderDevice, queue: &RenderQueue, -) -> GpuContext { +) -> Option { let tracy_gpu_backend = match adapter_info.backend { Backend::Vulkan => GpuContextType::Vulkan, Backend::Dx12 => GpuContextType::Direct3D12, Backend::Gl => GpuContextType::OpenGL, - Backend::Metal | Backend::BrowserWebGpu | Backend::Noop => GpuContextType::Invalid, + Backend::Metal | Backend::BrowserWebGpu | Backend::Noop => { + // Previously this path would return a `GpuContextType::Invalid` and + // the whole function just returned a non-optional `GpuContext`. + // However calling the `initial_timestamp` function would freeze on + // macOS (at least 26.3) and therefore the whole Bevy app wouldn't + // start when trying to tracy with Tracy. + // + // An issue was filed on the wgpu-profiler repository that the function + // is copied from. https://github.com/Wumpf/wgpu-profiler/issues/107 + // + // Once the root cause of the issue is located and fixed this should + // probably be moved back to not returning an option? + return None; + } }; let tracy_client = Client::running().unwrap(); @@ -25,7 +38,7 @@ pub fn new_tracy_gpu_context( initial_timestamp(device, queue), queue.get_timestamp_period(), ) - .unwrap() + .ok() } // Code copied from https://github.com/Wumpf/wgpu-profiler/blob/f9de342a62cb75f50904a98d11dd2bbeb40ceab8/src/tracy.rs