#[cfg(feature = "trace")] mod record; #[cfg(feature = "replay")] mod replay; use core::{convert::Infallible, ops::Range}; use alloc::{string::String, vec::Vec}; use macro_rules_attribute::apply; use crate::{ command::{serde_object_reference_struct, BasePass, Command, ReferenceType, RenderCommand}, id::{markers, PointerId}, pipeline::GeneralRenderPipelineDescriptor, }; #[cfg(feature = "trace")] pub use record::*; #[cfg(feature = "replay")] pub use replay::*; type FileName = String; pub const FILE_NAME: &str = "trace.ron"; #[derive(Debug)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum Data { File(FileName), String(DataKind, String), Binary(DataKind, Vec), } #[derive(Clone, Copy, Debug, Eq, PartialEq)] #[cfg_attr( feature = "serde", derive(serde::Serialize, serde::Deserialize), serde(rename_all = "lowercase") )] pub enum DataKind { Bin, Wgsl, /// IR of Naga module, serialized in RON format Ron, Spv, Dxil, Hlsl, Msl, Glsl, } impl core::fmt::Display for DataKind { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { let s = match self { DataKind::Bin => "bin", DataKind::Wgsl => "wgsl", DataKind::Ron => "ron", DataKind::Spv => "spv", DataKind::Dxil => "dxil", DataKind::Hlsl => "hlsl", DataKind::Msl => "metal", DataKind::Glsl => "glsl", }; write!(f, "{s}") } } impl DataKind { #[cfg(feature = "replay")] fn is_string(&self) -> bool { match *self { DataKind::Wgsl | DataKind::Ron | DataKind::Hlsl | DataKind::Msl | DataKind::Glsl => { true } DataKind::Bin | DataKind::Spv | DataKind::Dxil => false, } } } impl Data { pub fn kind(&self) -> DataKind { match self { Data::File(file) => { if file.ends_with(".bin") { DataKind::Bin } else if file.ends_with(".wgsl") { DataKind::Wgsl } else if file.ends_with(".ron") { DataKind::Ron } else if file.ends_with(".spv") { DataKind::Spv } else if file.ends_with(".dxil") { DataKind::Dxil } else if file.ends_with(".hlsl") { DataKind::Hlsl } else if file.ends_with(".metal") { DataKind::Msl } else if file.ends_with(".glsl") { DataKind::Glsl } else { panic!("unknown data file extension: {file}"); } } Data::String(kind, _) => *kind, Data::Binary(kind, _) => *kind, } } } #[allow(clippy::large_enum_variant)] #[derive(Debug)] #[apply(serde_object_reference_struct)] pub enum Action<'a, R: ReferenceType> { Init { desc: crate::device::DeviceDescriptor<'a>, backend: wgt::Backend, }, ConfigureSurface( R::Surface, wgt::SurfaceConfiguration>, ), CreateBuffer(R::Buffer, crate::resource::BufferDescriptor<'a>), FreeBuffer(R::Buffer), DestroyBuffer(R::Buffer), CreateTexture(R::Texture, crate::resource::TextureDescriptor<'a>), FreeTexture(R::Texture), DestroyTexture(R::Texture), CreateTextureView { id: R::TextureView, parent: R::Texture, desc: crate::resource::TextureViewDescriptor<'a>, }, DestroyTextureView(R::TextureView), CreateExternalTexture { id: R::ExternalTexture, desc: crate::resource::ExternalTextureDescriptor<'a>, planes: alloc::boxed::Box<[R::TextureView]>, }, FreeExternalTexture(R::ExternalTexture), DestroyExternalTexture(R::ExternalTexture), CreateSampler( PointerId, crate::resource::SamplerDescriptor<'a>, ), DestroySampler(PointerId), GetSurfaceTexture { id: R::Texture, parent: R::Surface, }, Present(R::Surface), DiscardSurfaceTexture(R::Surface), CreateBindGroupLayout( PointerId, crate::binding_model::BindGroupLayoutDescriptor<'a>, ), GetRenderPipelineBindGroupLayout { id: PointerId, pipeline: PointerId, index: u32, }, GetComputePipelineBindGroupLayout { id: PointerId, pipeline: PointerId, index: u32, }, DestroyBindGroupLayout(PointerId), CreatePipelineLayout( PointerId, crate::binding_model::ResolvedPipelineLayoutDescriptor< 'a, PointerId, >, ), DestroyPipelineLayout(PointerId), CreateBindGroup(PointerId, TraceBindGroupDescriptor<'a>), DestroyBindGroup(PointerId), CreateShaderModule { id: PointerId, desc: crate::pipeline::ShaderModuleDescriptor<'a>, data: Data, }, CreateShaderModulePassthrough { id: PointerId, data: Vec, entry_point: String, label: crate::Label<'a>, num_workgroups: (u32, u32, u32), runtime_checks: wgt::ShaderRuntimeChecks, }, DestroyShaderModule(PointerId), CreateComputePipeline { id: PointerId, desc: TraceComputePipelineDescriptor<'a>, }, DestroyComputePipeline(PointerId), CreateGeneralRenderPipeline { id: PointerId, desc: TraceGeneralRenderPipelineDescriptor<'a>, }, DestroyRenderPipeline(PointerId), CreatePipelineCache { id: PointerId, desc: crate::pipeline::PipelineCacheDescriptor<'a>, }, DestroyPipelineCache(PointerId), CreateRenderBundle { id: R::RenderBundle, desc: crate::command::RenderBundleEncoderDescriptor<'a>, base: BasePass, Infallible>, }, DestroyRenderBundle(PointerId), CreateQuerySet { id: PointerId, desc: crate::resource::QuerySetDescriptor<'a>, }, DestroyQuerySet(PointerId), WriteBuffer { id: R::Buffer, data: Data, range: Range, queued: bool, }, WriteTexture { to: wgt::TexelCopyTextureInfo, data: Data, layout: wgt::TexelCopyBufferLayout, size: wgt::Extent3d, }, Submit(crate::SubmissionIndex, Vec>), FailedCommands { commands: Option>>, /// If `None`, then encoding failed due to a validation error (returned /// from `CommandEncoder::finish`). If `Some`, submission failed due to /// a resource having been destroyed. failed_at_submit: Option, error: String, }, CreateBlas { id: R::Blas, desc: crate::resource::BlasDescriptor<'a>, sizes: wgt::BlasGeometrySizeDescriptors, }, DestroyBlas(R::Blas), CreateTlas { id: R::Tlas, desc: crate::resource::TlasDescriptor<'a>, }, DestroyTlas(R::Tlas), } /// cbindgen:ignore pub type TraceBindGroupDescriptor<'a> = crate::binding_model::BindGroupDescriptor< 'a, PointerId, PointerId, PointerId, PointerId, PointerId, PointerId, >; /// Not a public API. For use by `player` only. /// /// cbindgen:ignore #[doc(hidden)] pub type TraceGeneralRenderPipelineDescriptor<'a> = GeneralRenderPipelineDescriptor< 'a, PointerId, PointerId, PointerId, >; /// Not a public API. For use by `player` only. /// /// cbindgen:ignore #[doc(hidden)] pub type TraceComputePipelineDescriptor<'a> = crate::pipeline::ComputePipelineDescriptor< 'a, PointerId, PointerId, PointerId, >;