diff --git a/.cargo/config.in b/.cargo/config.in index 95a92144399f5..7b640c68ad091 100644 --- a/.cargo/config.in +++ b/.cargo/config.in @@ -30,9 +30,9 @@ git = "https://github.com/gfx-rs/naga" rev = "bac2d82a430fbfcf100ee22b7c3bc12f3d593079" replace-with = "vendored-sources" -[source."git+https://github.com/gfx-rs/wgpu?rev=09b010b26af6876ce84991576a168a572172f08d"] +[source."git+https://github.com/gfx-rs/wgpu?rev=7c6b85756237f77bfe8d6231dfc7a1412ff662b6"] git = "https://github.com/gfx-rs/wgpu" -rev = "09b010b26af6876ce84991576a168a572172f08d" +rev = "7c6b85756237f77bfe8d6231dfc7a1412ff662b6" replace-with = "vendored-sources" [source."git+https://github.com/glandium/prost?rev=95964e9d33df3c2a9c3f14285e262867cab6f96b"] diff --git a/Cargo.lock b/Cargo.lock index f6f483db9e47b..9cee1f1a24fc8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6290,7 +6290,7 @@ dependencies = [ [[package]] name = "wgpu-core" version = "0.17.0" -source = "git+https://github.com/gfx-rs/wgpu?rev=09b010b26af6876ce84991576a168a572172f08d#09b010b26af6876ce84991576a168a572172f08d" +source = "git+https://github.com/gfx-rs/wgpu?rev=7c6b85756237f77bfe8d6231dfc7a1412ff662b6#7c6b85756237f77bfe8d6231dfc7a1412ff662b6" dependencies = [ "arrayvec", "bit-vec", @@ -6313,7 +6313,7 @@ dependencies = [ [[package]] name = "wgpu-hal" version = "0.17.0" -source = "git+https://github.com/gfx-rs/wgpu?rev=09b010b26af6876ce84991576a168a572172f08d#09b010b26af6876ce84991576a168a572172f08d" +source = "git+https://github.com/gfx-rs/wgpu?rev=7c6b85756237f77bfe8d6231dfc7a1412ff662b6#7c6b85756237f77bfe8d6231dfc7a1412ff662b6" dependencies = [ "android_system_properties", "arrayvec", @@ -6349,7 +6349,7 @@ dependencies = [ [[package]] name = "wgpu-types" version = "0.17.0" -source = "git+https://github.com/gfx-rs/wgpu?rev=09b010b26af6876ce84991576a168a572172f08d#09b010b26af6876ce84991576a168a572172f08d" +source = "git+https://github.com/gfx-rs/wgpu?rev=7c6b85756237f77bfe8d6231dfc7a1412ff662b6#7c6b85756237f77bfe8d6231dfc7a1412ff662b6" dependencies = [ "bitflags 2.999.999", "js-sys", diff --git a/gfx/wgpu_bindings/Cargo.toml b/gfx/wgpu_bindings/Cargo.toml index 73373b6a3525d..bad5f3ded6136 100644 --- a/gfx/wgpu_bindings/Cargo.toml +++ b/gfx/wgpu_bindings/Cargo.toml @@ -17,7 +17,7 @@ default = [] [dependencies.wgc] package = "wgpu-core" git = "https://github.com/gfx-rs/wgpu" -rev = "09b010b26af6876ce84991576a168a572172f08d" +rev = "7c6b85756237f77bfe8d6231dfc7a1412ff662b6" #Note: "replay" shouldn't ideally be needed, # but it allows us to serialize everything across IPC. features = ["replay", "trace", "serial-pass", "strict_asserts", "wgsl"] @@ -27,32 +27,32 @@ features = ["replay", "trace", "serial-pass", "strict_asserts", "wgsl"] [target.'cfg(any(target_os = "macos", target_os = "ios"))'.dependencies.wgc] package = "wgpu-core" git = "https://github.com/gfx-rs/wgpu" -rev = "09b010b26af6876ce84991576a168a572172f08d" +rev = "7c6b85756237f77bfe8d6231dfc7a1412ff662b6" features = ["metal"] # We want the wgpu-core Direct3D backends on Windows. [target.'cfg(windows)'.dependencies.wgc] package = "wgpu-core" git = "https://github.com/gfx-rs/wgpu" -rev = "09b010b26af6876ce84991576a168a572172f08d" +rev = "7c6b85756237f77bfe8d6231dfc7a1412ff662b6" features = ["dx11", "dx12"] # We want the wgpu-core Vulkan backend on Linux and Windows. [target.'cfg(any(windows, all(unix, not(any(target_os = "macos", target_os = "ios")))))'.dependencies.wgc] package = "wgpu-core" git = "https://github.com/gfx-rs/wgpu" -rev = "09b010b26af6876ce84991576a168a572172f08d" +rev = "7c6b85756237f77bfe8d6231dfc7a1412ff662b6" features = ["vulkan"] [dependencies.wgt] package = "wgpu-types" git = "https://github.com/gfx-rs/wgpu" -rev = "09b010b26af6876ce84991576a168a572172f08d" +rev = "7c6b85756237f77bfe8d6231dfc7a1412ff662b6" [dependencies.wgh] package = "wgpu-hal" git = "https://github.com/gfx-rs/wgpu" -rev = "09b010b26af6876ce84991576a168a572172f08d" +rev = "7c6b85756237f77bfe8d6231dfc7a1412ff662b6" [dependencies] bincode = "1" diff --git a/gfx/wgpu_bindings/cbindgen.toml b/gfx/wgpu_bindings/cbindgen.toml index cd6f4731e1a34..575ff332a7118 100644 --- a/gfx/wgpu_bindings/cbindgen.toml +++ b/gfx/wgpu_bindings/cbindgen.toml @@ -29,6 +29,7 @@ typedef uint64_t WGPUOption_BindGroupLayoutId; typedef uint64_t WGPUOption_SamplerId; typedef uint64_t WGPUOption_SurfaceId; typedef uint64_t WGPUOption_TextureViewId; +typedef uint64_t WGPUOption_QuerySetId; """ include_version = true braces = "SameLine" @@ -44,7 +45,7 @@ exclude = [ "Option_AdapterId", "Option_BufferId", "Option_PipelineLayoutId", "Option_BindGroupLayoutId", "Option_SamplerId", "Option_SurfaceId", "Option_TextureViewId", "Option_BufferSize", "Option_NonZeroU32", "Option_NonZeroU8", - "ANativeWindow_setBuffersGeometry", + "ANativeWindow_setBuffersGeometry", "Option_QuerySetId", ] include = ["BufferUsages"] diff --git a/gfx/wgpu_bindings/moz.yaml b/gfx/wgpu_bindings/moz.yaml index f92c5de11e0c5..d0df94b243212 100644 --- a/gfx/wgpu_bindings/moz.yaml +++ b/gfx/wgpu_bindings/moz.yaml @@ -20,11 +20,11 @@ origin: # Human-readable identifier for this version/release # Generally "version NNN", "tag SSS", "bookmark SSS" - release: commit 09b010b26af6876ce84991576a168a572172f08d + release: commit 7c6b85756237f77bfe8d6231dfc7a1412ff662b6 # Revision to pull in # Must be a long or short commit SHA (long preferred) - revision: 09b010b26af6876ce84991576a168a572172f08d + revision: 7c6b85756237f77bfe8d6231dfc7a1412ff662b6 license: ['MIT', 'Apache-2.0'] diff --git a/gfx/wgpu_bindings/src/client.rs b/gfx/wgpu_bindings/src/client.rs index 01ba4f6bf340c..bc9d2814c8bf9 100644 --- a/gfx/wgpu_bindings/src/client.rs +++ b/gfx/wgpu_bindings/src/client.rs @@ -545,7 +545,7 @@ pub extern "C" fn wgpu_client_create_texture_view( .alloc(backend); let wgpu_desc = wgc::resource::TextureViewDescriptor { - label: label, + label, format: desc.format.cloned(), dimension: desc.dimension.cloned(), range: wgt::ImageSubresourceRange { @@ -580,7 +580,7 @@ pub extern "C" fn wgpu_client_create_sampler( .alloc(backend); let wgpu_desc = wgc::resource::SamplerDescriptor { - label: label, + label, address_modes: desc.address_modes, mag_filter: desc.mag_filter, min_filter: desc.min_filter, @@ -645,7 +645,7 @@ pub extern "C" fn wgpu_device_create_render_bundle_encoder( .map(|format| Some(format.clone())) .collect(); let descriptor = wgc::command::RenderBundleEncoderDescriptor { - label: label, + label, color_formats: Cow::Owned(color_formats), depth_stencil: desc .depth_stencil_format @@ -729,6 +729,14 @@ pub unsafe extern "C" fn wgpu_client_create_render_bundle_error( #[repr(C)] pub struct ComputePassDescriptor<'a> { pub label: Option<&'a nsACString>, + pub timestamp_writes: Option<&'a ComputePassTimestampWrites<'a>>, +} + +#[repr(C)] +pub struct ComputePassTimestampWrites<'a> { + pub query_set: id::QuerySetId, + pub beginning_of_pass_write_index: Option<&'a u32>, + pub end_of_pass_write_index: Option<&'a u32>, } #[no_mangle] @@ -736,11 +744,35 @@ pub unsafe extern "C" fn wgpu_command_encoder_begin_compute_pass( encoder_id: id::CommandEncoderId, desc: &ComputePassDescriptor, ) -> *mut wgc::command::ComputePass { - let label = wgpu_string(desc.label); + let &ComputePassDescriptor { + label, + timestamp_writes, + } = desc; + + let label = wgpu_string(label); + + let timestamp_writes = timestamp_writes.map(|tsw| { + let &ComputePassTimestampWrites { + query_set, + beginning_of_pass_write_index, + end_of_pass_write_index, + } = tsw; + let beginning_of_pass_write_index = beginning_of_pass_write_index.cloned(); + let end_of_pass_write_index = end_of_pass_write_index.cloned(); + wgc::command::ComputePassTimestampWrites { + query_set, + beginning_of_pass_write_index, + end_of_pass_write_index, + } + }); + let timestamp_writes = timestamp_writes.as_ref(); let pass = wgc::command::ComputePass::new( encoder_id, - &wgc::command::ComputePassDescriptor { label: label }, + &wgc::command::ComputePassDescriptor { + label, + timestamp_writes, + }, ); Box::into_raw(Box::new(pass)) } @@ -765,6 +797,15 @@ pub struct RenderPassDescriptor<'a> { pub color_attachments: *const wgc::command::RenderPassColorAttachment, pub color_attachments_length: usize, pub depth_stencil_attachment: *const wgc::command::RenderPassDepthStencilAttachment, + pub timestamp_writes: Option<&'a RenderPassTimestampWrites<'a>>, + pub occlusion_query_set: Option, +} + +#[repr(C)] +pub struct RenderPassTimestampWrites<'a> { + pub query_set: wgc::id::QuerySetId, + pub beginning_of_pass_write_index: Option<&'a u32>, + pub end_of_pass_write_index: Option<&'a u32>, } #[no_mangle] @@ -772,19 +813,46 @@ pub unsafe extern "C" fn wgpu_command_encoder_begin_render_pass( encoder_id: id::CommandEncoderId, desc: &RenderPassDescriptor, ) -> *mut wgc::command::RenderPass { - let label = wgpu_string(desc.label); + let &RenderPassDescriptor { + label, + color_attachments, + color_attachments_length, + depth_stencil_attachment, + timestamp_writes, + occlusion_query_set, + } = desc; - let color_attachments: Vec<_> = - make_slice(desc.color_attachments, desc.color_attachments_length) - .iter() - .map(|format| Some(format.clone())) - .collect(); + let label = wgpu_string(label); + + let timestamp_writes = timestamp_writes.map(|tsw| { + let &RenderPassTimestampWrites { + query_set, + beginning_of_pass_write_index, + end_of_pass_write_index, + } = tsw; + let beginning_of_pass_write_index = beginning_of_pass_write_index.cloned(); + let end_of_pass_write_index = end_of_pass_write_index.cloned(); + wgc::command::RenderPassTimestampWrites { + query_set, + beginning_of_pass_write_index, + end_of_pass_write_index, + } + }); + + let timestamp_writes = timestamp_writes.as_ref(); + + let color_attachments: Vec<_> = make_slice(color_attachments, color_attachments_length) + .iter() + .map(|format| Some(format.clone())) + .collect(); let pass = wgc::command::RenderPass::new( encoder_id, &wgc::command::RenderPassDescriptor { - label: label, + label, color_attachments: Cow::Owned(color_attachments), - depth_stencil_attachment: desc.depth_stencil_attachment.as_ref(), + depth_stencil_attachment: depth_stencil_attachment.as_ref(), + timestamp_writes, + occlusion_query_set, }, ); Box::into_raw(Box::new(pass)) @@ -882,7 +950,7 @@ pub unsafe extern "C" fn wgpu_client_create_bind_group_layout( }); } let wgpu_desc = wgc::binding_model::BindGroupLayoutDescriptor { - label: label, + label, entries: Cow::Owned(entries), }; @@ -909,7 +977,7 @@ pub unsafe extern "C" fn wgpu_client_create_pipeline_layout( .alloc(backend); let wgpu_desc = wgc::binding_model::PipelineLayoutDescriptor { - label: label, + label, bind_group_layouts: Cow::Borrowed(make_slice( desc.bind_group_layouts, desc.bind_group_layouts_length, @@ -959,7 +1027,7 @@ pub unsafe extern "C" fn wgpu_client_create_bind_group( }); } let wgpu_desc = wgc::binding_model::BindGroupDescriptor { - label: label, + label, layout: desc.layout, entries: Cow::Owned(entries), }; diff --git a/gfx/wgpu_bindings/src/error.rs b/gfx/wgpu_bindings/src/error.rs index 828d66f6a9453..c826c2b1ba71f 100644 --- a/gfx/wgpu_bindings/src/error.rs +++ b/gfx/wgpu_bindings/src/error.rs @@ -439,6 +439,7 @@ mod foreign { DeviceError::Invalid => ErrorBufferType::Validation, DeviceError::Lost => ErrorBufferType::None, DeviceError::OutOfMemory => ErrorBufferType::OutOfMemory, + DeviceError::ResourceCreationFailed => ErrorBufferType::Internal, } } } diff --git a/gfx/wgpu_bindings/src/server.rs b/gfx/wgpu_bindings/src/server.rs index b2bbd78d5c07e..3c96cb546cc71 100644 --- a/gfx/wgpu_bindings/src/server.rs +++ b/gfx/wgpu_bindings/src/server.rs @@ -11,8 +11,8 @@ use crate::{ use nsstring::{nsACString, nsCString, nsString}; -use wgc::{pipeline::CreateShaderModuleError, resource::BufferAccessError}; use wgc::{gfx_select, id}; +use wgc::{pipeline::CreateShaderModuleError, resource::BufferAccessError}; use std::borrow::Cow; use std::slice; @@ -565,10 +565,15 @@ impl Global { error_buf.init(err); } } - CommandEncoderAction::RunComputePass { base } => { - if let Err(err) = - self.command_encoder_run_compute_pass_impl::(self_id, base.as_ref()) - { + CommandEncoderAction::RunComputePass { + base, + timestamp_writes, + } => { + if let Err(err) = self.command_encoder_run_compute_pass_impl::( + self_id, + base.as_ref(), + timestamp_writes.as_ref(), + ) { error_buf.init(err); } } @@ -604,12 +609,16 @@ impl Global { base, target_colors, target_depth_stencil, + timestamp_writes, + occlusion_query_set_id, } => { if let Err(err) = self.command_encoder_run_render_pass_impl::( self_id, base.as_ref(), &target_colors, target_depth_stencil.as_ref(), + timestamp_writes.as_ref(), + occlusion_query_set_id, ) { error_buf.init(err); } diff --git a/supply-chain/audits.toml b/supply-chain/audits.toml index d12a8acb01b76..d2a5bdf657e1a 100644 --- a/supply-chain/audits.toml +++ b/supply-chain/audits.toml @@ -3931,6 +3931,11 @@ who = "Teodor Tanasoaia " criteria = "safe-to-deploy" delta = "0.16.0@git:f71a1bc736fde37509262ca03e91d8f56a13aeb5 -> 0.16.0@git:dcad7dfba92dd85c3ca21bb553a61834e01b04f5" +[[audits.wgpu-core]] +who = "Erich Gubler " +criteria = "safe-to-deploy" +delta = "0.17.0@git:09b010b26af6876ce84991576a168a572172f08d -> 0.17.0@git:7c6b85756237f77bfe8d6231dfc7a1412ff662b6" + [[audits.wgpu-hal]] who = "Dzmitry Malyshau " criteria = "safe-to-deploy" @@ -4029,6 +4034,11 @@ who = "Teodor Tanasoaia " criteria = "safe-to-deploy" delta = "0.16.0@git:f71a1bc736fde37509262ca03e91d8f56a13aeb5 -> 0.16.0@git:dcad7dfba92dd85c3ca21bb553a61834e01b04f5" +[[audits.wgpu-hal]] +who = "Erich Gubler " +criteria = "safe-to-deploy" +delta = "0.17.0@git:09b010b26af6876ce84991576a168a572172f08d -> 0.17.0@git:7c6b85756237f77bfe8d6231dfc7a1412ff662b6" + [[audits.wgpu-types]] who = "Dzmitry Malyshau " criteria = "safe-to-deploy" @@ -4127,6 +4137,11 @@ who = "Teodor Tanasoaia " criteria = "safe-to-deploy" delta = "0.16.0@git:f71a1bc736fde37509262ca03e91d8f56a13aeb5 -> 0.16.0@git:dcad7dfba92dd85c3ca21bb553a61834e01b04f5" +[[audits.wgpu-types]] +who = "Erich Gubler " +criteria = "safe-to-deploy" +delta = "0.17.0@git:09b010b26af6876ce84991576a168a572172f08d -> 0.17.0@git:7c6b85756237f77bfe8d6231dfc7a1412ff662b6" + [[audits.whatsys]] who = "Bobby Holley " criteria = "safe-to-deploy" diff --git a/third_party/rust/wgpu-core/.cargo-checksum.json b/third_party/rust/wgpu-core/.cargo-checksum.json index dfc96b5a89f5a..d39f2a3042a7b 100644 --- a/third_party/rust/wgpu-core/.cargo-checksum.json +++ b/third_party/rust/wgpu-core/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"fc7c48cea2d58e3baa0f569d89f2680e92c509e268c8f565cce461d759643569","LICENSE.APACHE":"a6cba85bc92e0cff7a450b1d873c0eaa2e9fc96bf472df0247a26bec77bf3ff9","LICENSE.MIT":"c7fea58d1cfe49634cd92e54fc10a9d871f4b275321a4cd8c09e449122caaeb4","src/binding_model.rs":"d92a2c21642d0bece4ce1a9877d08567a86af4991cfe0bf6ecaaaf8f8b9c8d74","src/command/bind.rs":"aa778a7a125496f31220e8aa06a7eee5c5bc524a29e77cc5a314a178a0813a80","src/command/bundle.rs":"00ac15c8c70cf58437a0f66472e6c8b73200c6ec15e2062adabd151bebc9b2fc","src/command/clear.rs":"b61144473752e363dfe9c15951702865921b568c8ee5136af7aa4237f015c383","src/command/compute.rs":"96ca2d55d9ba5f1067c701df25eb5e655557b17a45f306e3d8d31bd196839868","src/command/draw.rs":"14a0319da47e4995c2ad97f1102998b0d4beb2f6d07df8a0cb6f08023185ce7a","src/command/memory_init.rs":"b50d3d20dbf659052f19da2e79469ba6435e06370f19d6ef45e1b1128d9900b7","src/command/mod.rs":"c7b7a4dd50636694a835e48f6a65dba8cf873168a02758fae73d6c04d48dfc45","src/command/query.rs":"e12108706de23a2925d180f96dcb870d167c1d4033903d306435395284b7a0d5","src/command/render.rs":"b72e27b8a615551bb3320ceaac3e285e082522cd0524e9960e8628aa3d4b10d6","src/command/transfer.rs":"c777c6e51afb459d2b5416e31071f24e4215c66f456fee3bd8f7395f9d1c5db1","src/conv.rs":"a21506ce183e7989df0e8db29d8cd6f9884b3531d004a0e5193e3aa0b73b10c8","src/device/global.rs":"a06a5b10cda63dd97f5cd59e2813fd189d2cf59fd4154950a878874d4221cc12","src/device/life.rs":"c935c15c4c7f929e378a5ea930d0d36b47616a49991c236aaa10d25ce5852d15","src/device/mod.rs":"f0f8da084e0959ea1ec19438eda1dcf80325ef117ab1dec777a776e5b45fcef2","src/device/queue.rs":"b1ef887b92574d2541ef6f572cd14067e2af3a514fa26d547f9c18e2cbd30b92","src/device/resource.rs":"cbb1bcd91c5e62a2a98288fa1cd9b5d8eb54cc78fa5ba042adaffe6b6770675a","src/device/trace.rs":"f69aa6af36a6defcf391ddb6cf12a56e37e00b4595e95c284cd7fd400394349c","src/error.rs":"ca37282283985e2b7d184b2ab7ca6f53f726432d920f8d8477bfff6fab9b34e2","src/global.rs":"cf551de97c3eb5acd0c2710da09ebd92cc863ad0bb0f53c0fd4911bf8cd3ad97","src/hal_api.rs":"92a2f0cb80f192693530ed61048919bbad446742c2370bf0944c44b1c5df8362","src/hub.rs":"49f479c3ebed842a4bc8ab2fee00bc02dceb57790fbac8ba33e1bfed795fa675","src/id.rs":"f6245d024586c7fe63ded13b3cb926b940c191bbee56aedc655e8cef74bdd66b","src/identity.rs":"c2e008e652723f7896465bfdafd5a10141cf5866e8c481a8efcf0bdaa9619a6a","src/init_tracker/buffer.rs":"a0ebf54a1e6d269c7b4aa0ac7bb8b04fd2cea3221a1d058ff33cb683b2aea3e9","src/init_tracker/mod.rs":"0867f79f83555390d0982d1dc6dcf0d4340e10cb89aa633d3c3ecc45deb3c78c","src/init_tracker/texture.rs":"37b6584aaca11c407d91f77002dcbb48d8a4876e27edd1b71b7929ef966f901d","src/instance.rs":"363484220e0936eabd79098631a1b646173632ed01126aaf56f65b300bf6df92","src/lib.rs":"27ff8dd787d41cf412e90d0c4674aa70db59e608f9eb3be485c0bd18e9f13369","src/pipeline.rs":"669219add15448fdf5fe8bc5e03fd6fd1ada2b45b07047fd8c0a9bbbcdecad8b","src/present.rs":"ebcbf2e3b35d13a8dad191126de5f5006233ba8a0fb186303eafe2aeb412dce3","src/registry.rs":"4098413de7f48e9ff15d0246793be47a0d54c95b4c8594baf9fafd222a90ba84","src/resource.rs":"a03329428f820b43810d82f990c72990a45a6bdf482d3ce4b096b0f99c6c6844","src/storage.rs":"bc70689ba299e9b4d9f4992c4d3f4dd36b1d8e71327595094981fdfd624f811a","src/track/buffer.rs":"dd6f632c6f31b15807148d705c516a8a1a8d72d02b137dd3b9d7c939447917cb","src/track/metadata.rs":"a80bd086ce825f7484ce6318a586c482d06fea0efc9c76bfa0124e480cc8b75e","src/track/mod.rs":"04cd09cf5f26262175e48cc3855b79fbd8988916c4367a55d39a4c95784d249b","src/track/range.rs":"5bbfed6e103b3234d9de8e42057022da6d628c2cc1db6bb51b88f87f2d8adf8b","src/track/stateless.rs":"1d786b5e9558672243ba7d913736561065ef2bd5c6105c935e982486d10841f0","src/track/texture.rs":"7d60dc81ba7f7e2c2819525b90e6e6c7760cb0920e36aeefe98e76cedd49d26e","src/validation.rs":"6be9229cc34ef293ae99cfa520c6ad22bab39b83a53880a4aca36c42c53d40c3"},"package":null} +{"files":{"Cargo.toml":"fc7c48cea2d58e3baa0f569d89f2680e92c509e268c8f565cce461d759643569","LICENSE.APACHE":"a6cba85bc92e0cff7a450b1d873c0eaa2e9fc96bf472df0247a26bec77bf3ff9","LICENSE.MIT":"c7fea58d1cfe49634cd92e54fc10a9d871f4b275321a4cd8c09e449122caaeb4","src/binding_model.rs":"d92a2c21642d0bece4ce1a9877d08567a86af4991cfe0bf6ecaaaf8f8b9c8d74","src/command/bind.rs":"aa778a7a125496f31220e8aa06a7eee5c5bc524a29e77cc5a314a178a0813a80","src/command/bundle.rs":"b26eb6cb877a19d203e9d2b8ac3b10e81f6a94b8b68617eac97a3b861cbe102b","src/command/clear.rs":"418ac36738d782ab72e8700aabef802638cdef1c873f4b036aa8a4c521cb9caf","src/command/compute.rs":"8f0ce8f80ad19454c7a0fdaf7a7fbb6d84f2cb0e374346f740a4ebe01beee53d","src/command/draw.rs":"1cbdeff80fa57663262f92141c5752530e911bad23c5379667b406cb8b57c4f7","src/command/memory_init.rs":"b50d3d20dbf659052f19da2e79469ba6435e06370f19d6ef45e1b1128d9900b7","src/command/mod.rs":"a63937a5b8a441b714329a5e1b0b4dd4b70ae2f39b52da633fd79edbe183edc6","src/command/query.rs":"d39e1b8cb6a054fd31333a916da5d79a6671a724212c90c490c13e55043a1685","src/command/render.rs":"c40036b5d3220ec621903473085ef8b9e0eb9dc51751ddab914d4f67b4852229","src/command/transfer.rs":"c777c6e51afb459d2b5416e31071f24e4215c66f456fee3bd8f7395f9d1c5db1","src/conv.rs":"da95b36b7680ae74ebf810ad8f1decf01bd3eeaff44b3c5af1d4b3c3f0e2059a","src/device/global.rs":"a06a5b10cda63dd97f5cd59e2813fd189d2cf59fd4154950a878874d4221cc12","src/device/life.rs":"c935c15c4c7f929e378a5ea930d0d36b47616a49991c236aaa10d25ce5852d15","src/device/mod.rs":"c150878d8b80b727ba1904725dafd747d6459106196b1cc67d9428dae75b0163","src/device/queue.rs":"b1ef887b92574d2541ef6f572cd14067e2af3a514fa26d547f9c18e2cbd30b92","src/device/resource.rs":"cbb1bcd91c5e62a2a98288fa1cd9b5d8eb54cc78fa5ba042adaffe6b6770675a","src/device/trace.rs":"21408dfd2c99e3ce36a77d08ba86cf52f32bb376ed82690bbbf74937bfd42cbe","src/error.rs":"ca37282283985e2b7d184b2ab7ca6f53f726432d920f8d8477bfff6fab9b34e2","src/global.rs":"cf551de97c3eb5acd0c2710da09ebd92cc863ad0bb0f53c0fd4911bf8cd3ad97","src/hal_api.rs":"92a2f0cb80f192693530ed61048919bbad446742c2370bf0944c44b1c5df8362","src/hub.rs":"49f479c3ebed842a4bc8ab2fee00bc02dceb57790fbac8ba33e1bfed795fa675","src/id.rs":"f6245d024586c7fe63ded13b3cb926b940c191bbee56aedc655e8cef74bdd66b","src/identity.rs":"c2e008e652723f7896465bfdafd5a10141cf5866e8c481a8efcf0bdaa9619a6a","src/init_tracker/buffer.rs":"a0ebf54a1e6d269c7b4aa0ac7bb8b04fd2cea3221a1d058ff33cb683b2aea3e9","src/init_tracker/mod.rs":"0867f79f83555390d0982d1dc6dcf0d4340e10cb89aa633d3c3ecc45deb3c78c","src/init_tracker/texture.rs":"37b6584aaca11c407d91f77002dcbb48d8a4876e27edd1b71b7929ef966f901d","src/instance.rs":"1a44acecaba0031be7b2450846f56ec741bafb2e4e9f0fc606e13788e5600083","src/lib.rs":"27ff8dd787d41cf412e90d0c4674aa70db59e608f9eb3be485c0bd18e9f13369","src/pipeline.rs":"669219add15448fdf5fe8bc5e03fd6fd1ada2b45b07047fd8c0a9bbbcdecad8b","src/present.rs":"ebcbf2e3b35d13a8dad191126de5f5006233ba8a0fb186303eafe2aeb412dce3","src/registry.rs":"4098413de7f48e9ff15d0246793be47a0d54c95b4c8594baf9fafd222a90ba84","src/resource.rs":"a03329428f820b43810d82f990c72990a45a6bdf482d3ce4b096b0f99c6c6844","src/storage.rs":"bc70689ba299e9b4d9f4992c4d3f4dd36b1d8e71327595094981fdfd624f811a","src/track/buffer.rs":"dd6f632c6f31b15807148d705c516a8a1a8d72d02b137dd3b9d7c939447917cb","src/track/metadata.rs":"a80bd086ce825f7484ce6318a586c482d06fea0efc9c76bfa0124e480cc8b75e","src/track/mod.rs":"04cd09cf5f26262175e48cc3855b79fbd8988916c4367a55d39a4c95784d249b","src/track/range.rs":"5bbfed6e103b3234d9de8e42057022da6d628c2cc1db6bb51b88f87f2d8adf8b","src/track/stateless.rs":"1d786b5e9558672243ba7d913736561065ef2bd5c6105c935e982486d10841f0","src/track/texture.rs":"7d60dc81ba7f7e2c2819525b90e6e6c7760cb0920e36aeefe98e76cedd49d26e","src/validation.rs":"6be9229cc34ef293ae99cfa520c6ad22bab39b83a53880a4aca36c42c53d40c3"},"package":null} \ No newline at end of file diff --git a/third_party/rust/wgpu-core/src/command/bundle.rs b/third_party/rust/wgpu-core/src/command/bundle.rs index 5c4ca122a849a..0a4660a7988c0 100644 --- a/third_party/rust/wgpu-core/src/command/bundle.rs +++ b/third_party/rust/wgpu-core/src/command/bundle.rs @@ -637,6 +637,8 @@ impl RenderBundleEncoder { RenderCommand::InsertDebugMarker { color: _, len: _ } => unimplemented!(), RenderCommand::PopDebugGroup => unimplemented!(), RenderCommand::WriteTimestamp { .. } // Must check the TIMESTAMP_QUERY_INSIDE_PASSES feature + | RenderCommand::BeginOcclusionQuery { .. } + | RenderCommand::EndOcclusionQuery | RenderCommand::BeginPipelineStatisticsQuery { .. } | RenderCommand::EndPipelineStatisticsQuery => unimplemented!(), RenderCommand::ExecuteBundle(_) @@ -950,6 +952,8 @@ impl RenderBundle { return Err(ExecutionError::Unimplemented("debug-markers")) } RenderCommand::WriteTimestamp { .. } + | RenderCommand::BeginOcclusionQuery { .. } + | RenderCommand::EndOcclusionQuery | RenderCommand::BeginPipelineStatisticsQuery { .. } | RenderCommand::EndPipelineStatisticsQuery => { return Err(ExecutionError::Unimplemented("queries")) diff --git a/third_party/rust/wgpu-core/src/command/clear.rs b/third_party/rust/wgpu-core/src/command/clear.rs index 9f677298b9261..ceceb2ba58da7 100644 --- a/third_party/rust/wgpu-core/src/command/clear.rs +++ b/third_party/rust/wgpu-core/src/command/clear.rs @@ -452,6 +452,8 @@ fn clear_texture_via_render_passes( color_attachments, depth_stencil_attachment, multiview: None, + timestamp_writes: None, + occlusion_query_set: None, }); encoder.end_render_pass(); } diff --git a/third_party/rust/wgpu-core/src/command/compute.rs b/third_party/rust/wgpu-core/src/command/compute.rs index 0a0b4e85e6b04..567ef4efa7457 100644 --- a/third_party/rust/wgpu-core/src/command/compute.rs +++ b/third_party/rust/wgpu-core/src/command/compute.rs @@ -26,6 +26,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}; @@ -94,6 +99,7 @@ pub enum ComputeCommand { pub struct ComputePass { base: BasePass, parent_id: id::CommandEncoderId, + timestamp_writes: Option, // Resource binding dedupe state. #[cfg_attr(feature = "serial-pass", serde(skip))] @@ -107,6 +113,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(), @@ -119,7 +126,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, + } } } @@ -135,9 +145,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 set at which a start timestamp of this pass is written, if any. + pub beginning_of_pass_write_index: Option, + /// The index of the query set at which an end timestamp of this pass is written, if any. + pub end_of_pass_write_index: Option, +} + #[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)] @@ -325,7 +351,11 @@ impl Global { encoder_id: id::CommandEncoderId, pass: &ComputePass, ) -> Result<(), ComputePassError> { - self.command_encoder_run_compute_pass_impl::(encoder_id, pass.base.as_ref()) + self.command_encoder_run_compute_pass_impl::( + encoder_id, + pass.base.as_ref(), + pass.timestamp_writes.as_ref(), + ) } #[doc(hidden)] @@ -333,6 +363,7 @@ impl Global { &self, encoder_id: id::CommandEncoderId, base: BasePassRef, + timestamp_writes: Option<&ComputePassTimestampWrites>, ) -> Result<(), ComputePassError> { profiling::scope!("CommandEncoder::run_compute_pass"); let init_scope = PassErrorScope::Pass(encoder_id); @@ -363,6 +394,7 @@ impl Global { 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(), }); } @@ -385,6 +417,42 @@ impl Global { let mut string_offset = 0; let mut active_query = None; + let timestamp_writes = if let Some(tw) = timestamp_writes { + let query_set: &resource::QuerySet = 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 error. + // 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), @@ -397,7 +465,11 @@ impl Global { 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); } diff --git a/third_party/rust/wgpu-core/src/command/draw.rs b/third_party/rust/wgpu-core/src/command/draw.rs index b629ffaba0e14..0b7b48cda9fb0 100644 --- a/third_party/rust/wgpu-core/src/command/draw.rs +++ b/third_party/rust/wgpu-core/src/command/draw.rs @@ -243,6 +243,10 @@ pub enum RenderCommand { query_set_id: id::QuerySetId, query_index: u32, }, + BeginOcclusionQuery { + query_index: u32, + }, + EndOcclusionQuery, BeginPipelineStatisticsQuery { query_set_id: id::QuerySetId, query_index: u32, diff --git a/third_party/rust/wgpu-core/src/command/mod.rs b/third_party/rust/wgpu-core/src/command/mod.rs index 311ade7f43267..d97d4b41e34ac 100644 --- a/third_party/rust/wgpu-core/src/command/mod.rs +++ b/third_party/rust/wgpu-core/src/command/mod.rs @@ -112,6 +112,7 @@ pub struct CommandBuffer { pub(crate) trackers: Tracker, buffer_memory_init_actions: Vec, texture_memory_actions: CommandBufferTextureMemoryActions, + pub(crate) pending_query_resets: QueryResetMap, limits: wgt::Limits, support_clear_texture: bool, #[cfg(feature = "trace")] @@ -140,6 +141,7 @@ impl CommandBuffer { 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")] @@ -592,6 +594,10 @@ pub enum PassErrorScope { QueryReset, #[error("In a write_timestamp command")] WriteTimestamp, + #[error("In a begin_occlusion_query command")] + BeginOcclusionQuery, + #[error("In a end_occlusion_query command")] + EndOcclusionQuery, #[error("In a begin_pipeline_statistics_query command")] BeginPipelineStatisticsQuery, #[error("In a end_pipeline_statistics_query command")] diff --git a/third_party/rust/wgpu-core/src/command/query.rs b/third_party/rust/wgpu-core/src/command/query.rs index c34aa48c9c428..14e91483e8d69 100644 --- a/third_party/rust/wgpu-core/src/command/query.rs +++ b/third_party/rust/wgpu-core/src/command/query.rs @@ -19,7 +19,7 @@ use thiserror::Error; use wgt::BufferAddress; #[derive(Debug)] -pub(super) struct QueryResetMap { +pub(crate) struct QueryResetMap { map: FastHashMap, Epoch)>, _phantom: PhantomData, } @@ -47,12 +47,12 @@ impl QueryResetMap { } pub fn reset_queries( - self, + &mut self, raw_encoder: &mut A::CommandEncoder, query_set_storage: &Storage, 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)?; @@ -240,6 +240,40 @@ impl QuerySet { Ok(()) } + pub(super) fn validate_and_begin_occlusion_query( + &self, + raw_encoder: &mut A::CommandEncoder, + query_set_id: id::QuerySetId, + query_index: u32, + reset_state: Option<&mut QueryResetMap>, + active_query: &mut Option<(id::QuerySetId, u32)>, + ) -> Result<(), QueryUseError> { + let needs_reset = reset_state.is_none(); + let query_set = self.validate_query( + query_set_id, + SimplifiedQueryType::Occlusion, + query_index, + reset_state, + )?; + + if let Some((_old_id, old_idx)) = active_query.replace((query_set_id, query_index)) { + return Err(QueryUseError::AlreadyStarted { + active_query_index: old_idx, + new_query_index: query_index, + }); + } + + unsafe { + // If we don't have a reset state tracker which can defer resets, we must reset now. + if needs_reset { + raw_encoder.reset_queries(&self.raw, query_index..(query_index + 1)); + } + raw_encoder.begin_query(query_set, query_index); + } + + Ok(()) + } + pub(super) fn validate_and_begin_pipeline_statistics_query( &self, raw_encoder: &mut A::CommandEncoder, @@ -275,6 +309,23 @@ impl QuerySet { } } +pub(super) fn end_occlusion_query( + raw_encoder: &mut A::CommandEncoder, + storage: &Storage, id::QuerySetId>, + active_query: &mut Option<(id::QuerySetId, u32)>, +) -> Result<(), QueryUseError> { + if let Some((query_set_id, query_index)) = active_query.take() { + // We can unwrap here as the validity was validated when the active query was set + let query_set = storage.get(query_set_id).unwrap(); + + unsafe { raw_encoder.end_query(&query_set.raw, query_index) }; + + Ok(()) + } else { + Err(QueryUseError::AlreadyStopped) + } +} + pub(super) fn end_pipeline_statistics_query( raw_encoder: &mut A::CommandEncoder, storage: &Storage, id::QuerySetId>, @@ -411,6 +462,7 @@ impl Global { .into()); } + // TODO(https://github.com/gfx-rs/wgpu/issues/3993): Need to track initialization state. cmd_buf .buffer_memory_init_actions .extend(dst_buffer.initialization_status.create_action( diff --git a/third_party/rust/wgpu-core/src/command/render.rs b/third_party/rust/wgpu-core/src/command/render.rs index e8080abba3243..4066bb3a0780a 100644 --- a/third_party/rust/wgpu-core/src/command/render.rs +++ b/third_party/rust/wgpu-core/src/command/render.rs @@ -3,11 +3,11 @@ use crate::{ command::{ self, bind::Binder, - end_pipeline_statistics_query, + end_occlusion_query, end_pipeline_statistics_query, memory_init::{fixup_discarded_surfaces, SurfacesInDiscardState}, BasePass, BasePassRef, BindGroupStateChange, CommandBuffer, CommandEncoderError, - CommandEncoderStatus, DrawError, ExecutionError, MapPassErr, PassErrorScope, QueryResetMap, - QueryUseError, RenderCommand, RenderCommandError, StateChange, + CommandEncoderStatus, DrawError, ExecutionError, MapPassErr, PassErrorScope, QueryUseError, + RenderCommand, RenderCommandError, StateChange, }, device::{ AttachmentData, Device, MissingDownlevelFlags, MissingFeatures, @@ -21,7 +21,7 @@ use crate::{ identity::GlobalIdentityHandlerFactory, init_tracker::{MemoryInitKind, TextureInitRange, TextureInitTrackerAction}, pipeline::{self, PipelineFlags}, - resource::{self, Buffer, Texture, TextureView, TextureViewNotRenderableReason}, + resource::{Buffer, QuerySet, Texture, TextureView, TextureViewNotRenderableReason}, storage::Storage, track::{TextureSelector, UsageConflict, UsageScope}, validation::{ @@ -179,6 +179,31 @@ impl RenderPassDepthStencilAttachment { } } +/// Location to write a timestamp to (beginning or end of the pass). +#[repr(C)] +#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] +#[cfg_attr(any(feature = "serial-pass", feature = "trace"), derive(Serialize))] +#[cfg_attr(any(feature = "serial-pass", feature = "replay"), derive(Deserialize))] +#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))] +pub enum RenderPassTimestampLocation { + Beginning = 0, + End = 1, +} + +/// Describes the writing of timestamp values in a render 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 RenderPassTimestampWrites { + /// The query set to write the timestamp to. + pub query_set: id::QuerySetId, + /// The index of the query set at which a start timestamp of this pass is written, if any. + pub beginning_of_pass_write_index: Option, + /// The index of the query set at which an end timestamp of this pass is written, if any. + pub end_of_pass_write_index: Option, +} + /// Describes the attachments of a render pass. #[derive(Clone, Debug, Default, PartialEq)] pub struct RenderPassDescriptor<'a> { @@ -187,6 +212,10 @@ pub struct RenderPassDescriptor<'a> { pub color_attachments: Cow<'a, [Option]>, /// The depth and stencil attachment of the render pass, if any. pub depth_stencil_attachment: Option<&'a RenderPassDepthStencilAttachment>, + /// Defines where and when timestamp values will be written for this pass. + pub timestamp_writes: Option<&'a RenderPassTimestampWrites>, + /// Defines where the occlusion query results will be stored for this pass. + pub occlusion_query_set: Option, } #[cfg_attr(feature = "serial-pass", derive(Deserialize, Serialize))] @@ -195,6 +224,8 @@ pub struct RenderPass { parent_id: id::CommandEncoderId, color_targets: ArrayVec, { hal::MAX_COLOR_ATTACHMENTS }>, depth_stencil_target: Option, + timestamp_writes: Option, + occlusion_query_set_id: Option, // Resource binding dedupe state. #[cfg_attr(feature = "serial-pass", serde(skip))] @@ -210,6 +241,8 @@ impl RenderPass { parent_id, color_targets: desc.color_attachments.iter().cloned().collect(), depth_stencil_target: desc.depth_stencil_attachment.cloned(), + timestamp_writes: desc.timestamp_writes.cloned(), + occlusion_query_set_id: desc.occlusion_query_set, current_bind_groups: BindGroupStateChange::new(), current_pipeline: StateChange::new(), @@ -226,6 +259,8 @@ impl RenderPass { base: self.base, target_colors: self.color_targets.into_iter().collect(), target_depth_stencil: self.depth_stencil_target, + timestamp_writes: self.timestamp_writes, + occlusion_query_set_id: self.occlusion_query_set_id, } } @@ -589,6 +624,10 @@ pub enum RenderPassErrorInner { "Multiview pass texture views with more than one array layer must have D2Array dimension" )] MultiViewDimensionMismatch, + #[error("QuerySet {0:?} is invalid")] + InvalidQuerySet(id::QuerySetId), + #[error("missing occlusion query set")] + MissingOcclusionQuerySet, } impl PrettyError for RenderPassErrorInner { @@ -718,10 +757,13 @@ impl<'a, A: HalApi> RenderPassInfo<'a, A> { label: Option<&str>, color_attachments: &[Option], depth_stencil_attachment: Option<&RenderPassDepthStencilAttachment>, + timestamp_writes: Option<&RenderPassTimestampWrites>, + occlusion_query_set: Option, cmd_buf: &mut CommandBuffer, view_guard: &'a Storage, id::TextureViewId>, buffer_guard: &'a Storage, id::BufferId>, texture_guard: &'a Storage, id::TextureId>, + query_set_guard: &'a Storage, id::QuerySetId>, ) -> Result { profiling::scope!("RenderPassInfo::start"); @@ -1083,6 +1125,45 @@ impl<'a, A: HalApi> RenderPassInfo<'a, A> { multiview, }; + let timestamp_writes = if let Some(tw) = timestamp_writes { + let query_set = cmd_buf + .trackers + .query_sets + .add_single(query_set_guard, tw.query_set) + .ok_or(RenderPassErrorInner::InvalidQuerySet(tw.query_set))?; + + if let Some(index) = tw.beginning_of_pass_write_index { + cmd_buf + .pending_query_resets + .use_query_set(tw.query_set, query_set, index); + } + if let Some(index) = tw.end_of_pass_write_index { + cmd_buf + .pending_query_resets + .use_query_set(tw.query_set, query_set, index); + } + + Some(hal::RenderPassTimestampWrites { + 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 + }; + + let occlusion_query_set = if let Some(occlusion_query_set) = occlusion_query_set { + let query_set = cmd_buf + .trackers + .query_sets + .add_single(query_set_guard, occlusion_query_set) + .ok_or(RenderPassErrorInner::InvalidQuerySet(occlusion_query_set))?; + + Some(&query_set.raw) + } else { + None + }; + let hal_desc = hal::RenderPassDescriptor { label, extent, @@ -1090,6 +1171,8 @@ impl<'a, A: HalApi> RenderPassInfo<'a, A> { color_attachments: &colors, depth_stencil_attachment: depth_stencil, multiview, + timestamp_writes, + occlusion_query_set, }; unsafe { cmd_buf.encoder.raw.begin_render_pass(&hal_desc); @@ -1177,6 +1260,8 @@ impl<'a, A: HalApi> RenderPassInfo<'a, A> { clear_value: (0.0, 0), }), multiview: self.multiview, + timestamp_writes: None, + occlusion_query_set: None, }; unsafe { raw.begin_render_pass(&desc); @@ -1201,6 +1286,8 @@ impl Global { pass.base.as_ref(), &pass.color_targets, pass.depth_stencil_target.as_ref(), + pass.timestamp_writes.as_ref(), + pass.occlusion_query_set_id, ) } @@ -1211,6 +1298,8 @@ impl Global { base: BasePassRef, color_attachments: &[Option], depth_stencil_attachment: Option<&RenderPassDepthStencilAttachment>, + timestamp_writes: Option<&RenderPassTimestampWrites>, + occlusion_query_set_id: Option, ) -> Result<(), RenderPassError> { profiling::scope!("CommandEncoder::run_render_pass"); let init_scope = PassErrorScope::Pass(encoder_id); @@ -1219,7 +1308,7 @@ impl Global { let mut token = Token::root(); let (device_guard, mut token) = hub.devices.read(&mut token); - let (scope, query_reset_state, pending_discard_init_fixups) = { + let (scope, pending_discard_init_fixups) = { let (mut cmb_guard, mut token) = hub.command_buffers.write(&mut token); // Spell out the type, to placate rust-analyzer. @@ -1241,6 +1330,8 @@ impl Global { base: BasePass::from_ref(base), target_colors: color_attachments.to_vec(), target_depth_stencil: depth_stencil_attachment.cloned(), + timestamp_writes: timestamp_writes.cloned(), + occlusion_query_set_id, }); } @@ -1266,10 +1357,13 @@ impl Global { base.label, color_attachments, depth_stencil_attachment, + timestamp_writes, + occlusion_query_set_id, cmd_buf, &*view_guard, &*buffer_guard, &*texture_guard, + &*query_set_guard, ) .map_pass_err(init_scope)?; @@ -1301,7 +1395,6 @@ impl Global { let mut dynamic_offset_count = 0; let mut string_offset = 0; let mut active_query = None; - let mut query_reset_state = QueryResetMap::new(); for command in base.commands { match *command { @@ -2011,7 +2104,7 @@ impl Global { .require_features(wgt::Features::TIMESTAMP_QUERY_INSIDE_PASSES) .map_pass_err(scope)?; - let query_set: &resource::QuerySet = cmd_buf + let query_set = cmd_buf .trackers .query_sets .add_single(&*query_set_guard, query_set_id) @@ -2023,17 +2116,47 @@ impl Global { raw, query_set_id, query_index, - Some(&mut query_reset_state), + Some(&mut cmd_buf.pending_query_resets), ) .map_pass_err(scope)?; } + RenderCommand::BeginOcclusionQuery { query_index } => { + let scope = PassErrorScope::BeginOcclusionQuery; + + let query_set_id = occlusion_query_set_id + .ok_or(RenderPassErrorInner::MissingOcclusionQuerySet) + .map_pass_err(scope)?; + + let query_set = cmd_buf + .trackers + .query_sets + .add_single(&*query_set_guard, query_set_id) + .ok_or(RenderCommandError::InvalidQuerySet(query_set_id)) + .map_pass_err(scope)?; + + query_set + .validate_and_begin_occlusion_query( + raw, + query_set_id, + query_index, + Some(&mut cmd_buf.pending_query_resets), + &mut active_query, + ) + .map_pass_err(scope)?; + } + RenderCommand::EndOcclusionQuery => { + let scope = PassErrorScope::EndOcclusionQuery; + + end_occlusion_query(raw, &*query_set_guard, &mut active_query) + .map_pass_err(scope)?; + } RenderCommand::BeginPipelineStatisticsQuery { query_set_id, query_index, } => { let scope = PassErrorScope::BeginPipelineStatisticsQuery; - let query_set: &resource::QuerySet = cmd_buf + let query_set = cmd_buf .trackers .query_sets .add_single(&*query_set_guard, query_set_id) @@ -2045,7 +2168,7 @@ impl Global { raw, query_set_id, query_index, - Some(&mut query_reset_state), + Some(&mut cmd_buf.pending_query_resets), &mut active_query, ) .map_pass_err(scope)?; @@ -2142,7 +2265,7 @@ impl Global { info.finish(raw, &*texture_guard).map_pass_err(init_scope)?; cmd_buf.encoder.close(); - (trackers, query_reset_state, pending_discard_init_fixups) + (trackers, pending_discard_init_fixups) }; let (mut cmb_guard, mut token) = hub.command_buffers.write(&mut token); @@ -2162,7 +2285,8 @@ impl Global { &device_guard[cmd_buf.device_id.value], ); - query_reset_state + cmd_buf + .pending_query_resets .reset_queries( transit, &query_set_guard, @@ -2544,6 +2668,21 @@ pub mod render_ffi { }); } + #[no_mangle] + pub extern "C" fn wgpu_render_pass_begin_occlusion_query( + pass: &mut RenderPass, + query_index: u32, + ) { + pass.base + .commands + .push(RenderCommand::BeginOcclusionQuery { query_index }); + } + + #[no_mangle] + pub extern "C" fn wgpu_render_pass_end_occlusion_query(pass: &mut RenderPass) { + pass.base.commands.push(RenderCommand::EndOcclusionQuery); + } + #[no_mangle] pub extern "C" fn wgpu_render_pass_begin_pipeline_statistics_query( pass: &mut RenderPass, diff --git a/third_party/rust/wgpu-core/src/conv.rs b/third_party/rust/wgpu-core/src/conv.rs index 75a97eb087ac4..90629f08d6359 100644 --- a/third_party/rust/wgpu-core/src/conv.rs +++ b/third_party/rust/wgpu-core/src/conv.rs @@ -95,6 +95,10 @@ pub fn map_buffer_usage(usage: wgt::BufferUsages) -> hal::BufferUses { hal::BufferUses::INDIRECT, usage.contains(wgt::BufferUsages::INDIRECT), ); + u.set( + hal::BufferUses::QUERY_RESOLVE, + usage.contains(wgt::BufferUsages::QUERY_RESOLVE), + ); u } diff --git a/third_party/rust/wgpu-core/src/device/mod.rs b/third_party/rust/wgpu-core/src/device/mod.rs index 2f749a4495521..5792791abe767 100644 --- a/third_party/rust/wgpu-core/src/device/mod.rs +++ b/third_party/rust/wgpu-core/src/device/mod.rs @@ -296,6 +296,8 @@ pub enum DeviceError { Lost, #[error("Not enough memory left")] OutOfMemory, + #[error("Creation of a resource failed for a reason other than running out of memory.")] + ResourceCreationFailed, } impl From for DeviceError { @@ -303,6 +305,7 @@ impl From for DeviceError { match error { hal::DeviceError::Lost => DeviceError::Lost, hal::DeviceError::OutOfMemory => DeviceError::OutOfMemory, + hal::DeviceError::ResourceCreationFailed => DeviceError::ResourceCreationFailed, } } } diff --git a/third_party/rust/wgpu-core/src/device/trace.rs b/third_party/rust/wgpu-core/src/device/trace.rs index 57f82c181eeb2..ab5806bb903fc 100644 --- a/third_party/rust/wgpu-core/src/device/trace.rs +++ b/third_party/rust/wgpu-core/src/device/trace.rs @@ -176,11 +176,14 @@ pub enum Command { InsertDebugMarker(String), RunComputePass { base: crate::command::BasePass, + timestamp_writes: Option, }, RunRenderPass { base: crate::command::BasePass, target_colors: Vec>, target_depth_stencil: Option, + timestamp_writes: Option, + occlusion_query_set_id: Option, }, } diff --git a/third_party/rust/wgpu-core/src/instance.rs b/third_party/rust/wgpu-core/src/instance.rs index 45f01824b76fc..cf28777dc6e4f 100644 --- a/third_party/rust/wgpu-core/src/instance.rs +++ b/third_party/rust/wgpu-core/src/instance.rs @@ -352,6 +352,7 @@ impl Adapter { |err| match err { hal::DeviceError::Lost => RequestDeviceError::DeviceLost, hal::DeviceError::OutOfMemory => RequestDeviceError::OutOfMemory, + hal::DeviceError::ResourceCreationFailed => RequestDeviceError::Internal, }, )?; diff --git a/third_party/rust/wgpu-hal/.cargo-checksum.json b/third_party/rust/wgpu-hal/.cargo-checksum.json index 0e568a662aafb..e7f14a61049a1 100644 --- a/third_party/rust/wgpu-hal/.cargo-checksum.json +++ b/third_party/rust/wgpu-hal/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"6a5260fb4176c4938192be4e33d9d3273ef23019961aa10298c0c0fe241f7017","LICENSE.APACHE":"a6cba85bc92e0cff7a450b1d873c0eaa2e9fc96bf472df0247a26bec77bf3ff9","LICENSE.MIT":"c7fea58d1cfe49634cd92e54fc10a9d871f4b275321a4cd8c09e449122caaeb4","README.md":"78377f5876fafd77963eff7e3c2ba3a7e3ad5cf9201b09ed5612e49c2288eb18","examples/halmark/main.rs":"246e117a481144bfe1c39676ecb5aaf9fc9a6a42df6a17af27ae894f9637e537","examples/halmark/shader.wgsl":"26c256ec36d6f0e9a1647431ca772766bee4382d64eaa718ba7b488dcfb6bcca","examples/raw-gles.em.html":"70fbe68394a1a4522192de1dcfaf7d399f60d7bdf5de70b708f9bb0417427546","examples/raw-gles.rs":"a98d82eadf0b0ade89de6d41402e03f6e1b177d27a9d93c9ae9c5c320f90796c","src/auxil/dxgi/conv.rs":"c1e8d584e408712097d075455375e04d1895a0ff9a494305c16d658277ce7b90","src/auxil/dxgi/exception.rs":"baad31f4529f1cf9d10519c4cceccbb21ed9bba7d7ea99e4789c1d5ddf3a450b","src/auxil/dxgi/factory.rs":"4d934b586dec17f49da0b63a57885107336e111f98556af95b45339a3898c23d","src/auxil/dxgi/mod.rs":"a202564d9ac97530b16a234b87d180cd345aae705e082a9b1177dcde813645f9","src/auxil/dxgi/result.rs":"20c8eb03d738062dff198feca6327addb9882ed0462be842c789eadf7dca0573","src/auxil/dxgi/time.rs":"b6f966b250e9424d5d7e4065f2108cba87197c1e30baae6d87083055d1bc5a4b","src/auxil/mod.rs":"c38f0d3b10804d1c1d7e3b8e4a975fcb87271f8b1904f2f4a3153cceddafb56b","src/auxil/renderdoc.rs":"c2f849f70f576b0c9b0d32dd155b6a6353f74dff59cbeeaa994a12789d047c0f","src/dx11/adapter.rs":"621c7d06ebac419f17f88c64b1a7cd2930499f2826f62a209cd93c42c47c316c","src/dx11/command.rs":"cdad8dcdb800acba56c931f1726ddada652af18db0f066465af643f82a034492","src/dx11/device.rs":"96ccd8d6645839f3daf832ddf569676643ac92d1b332ab9a0c8563b3b5026295","src/dx11/instance.rs":"451fbe179dfdad74fe9ea378ad38a5db525e7008ec492e40ce78cc7b530b53ae","src/dx11/library.rs":"4fb09475fb24bc45fb7a464a7c6a30b45e10fed0022aad2891a390b512c11ae1","src/dx11/mod.rs":"21bc698bc0ff8b36a4906ee8dfaf469b6ed35ad852b7c0a5f60c5e5007bba128","src/dx12/adapter.rs":"1ecf0277171ff09368daa62b31759aadee3044e8033699b306e359cf10f01bdc","src/dx12/command.rs":"708570d63707888f6dbcc84638531537b1048e4c6f9e53d65a689df21bbfbbcb","src/dx12/conv.rs":"4746ab2e46d8fbf4eac66c4dde11ca932f7ca9ba8177b5316eb12710a89700c2","src/dx12/descriptor.rs":"d9e295c48dc7d1759fd121c927c2218c1bde90e9f1b35f2ad01b610b184b614e","src/dx12/device.rs":"c25d970de578668166f812a139a6bd5cdf6852399552ef9a1d69b593c5c84225","src/dx12/instance.rs":"cb838a49a69f91aff364c8f76fe6c42307152aed56f456f74218b716a770ef99","src/dx12/mod.rs":"b703e9a049e87f46a6fe6e4d0e33b185719a447323b8637f8471656f7cf63018","src/dx12/shader_compilation.rs":"dcff4c2c37b4d8c971a1e940eb7a843a32a3016cc65ef26bad71372687a835dc","src/dx12/suballocation.rs":"f5eb7c11dfe9c8d319ec853fec2a1aec8abe6bc61a729faa60302b105265f677","src/dx12/types.rs":"29b11268d11c1b7437de3dac403af574ec8aa84fd9954a95a16d80f5808be44d","src/dx12/view.rs":"c09241520377e6a47ad8822c69075e6e16e6c558e18bb64398c8d7424fc57dcf","src/empty.rs":"78c5cc9a37e7401a2618dcabbe38f012de45e5a0b4793cfc70ef7a6874087b15","src/gles/adapter.rs":"4ee3f6b4604bed1beb08dcd8715700855b495dac0689f23119ba1d74440aaeff","src/gles/command.rs":"572a6ec50c4a11b1db807a485cf5104eced6b35c74ebebeeb79a8e792cbaad7b","src/gles/conv.rs":"84164c6b93afdbd07b037cdbee4c94dd40df0a21d42703481d0c293e92a13efd","src/gles/device.rs":"cd44f1648cef05789070decc8ebad8aba4a1da407f0409bae64dc3745391ef20","src/gles/egl.rs":"aeabffbd826df8c8512b7a2658da4e74b29e87db0012d053947c846d5a094bf7","src/gles/emscripten.rs":"19bb73a9d140645f3f32cd48b002151711a9b8456e213eab5f3a2be79239e147","src/gles/mod.rs":"65996152dff84f00d6d491bfe5edc5c343f2302a4aa01eef14aadb4bdab096ed","src/gles/queue.rs":"5a85e6c2ad9e97779b6fec81d2811c1e05d71f82f7c5bee87b31eade64c1501e","src/gles/shaders/clear.frag":"aac702eed9ece5482db5ba6783a678b119a5e7802b1ecf93f4975dee8acab0b3","src/gles/shaders/clear.vert":"8f636168e1da2cac48091c466a543c3b09fb4a0dd8c60c1c9bf34cc890766740","src/gles/shaders/srgb_present.frag":"dd9a43c339a2fa4ccf7f6a1854c6f400cabf271a7d5e9230768e9f39d47f3ff5","src/gles/shaders/srgb_present.vert":"6e85d489403d80b81cc94790730bb53b309dfc5eeede8f1ea3412a660f31d357","src/gles/web.rs":"0e39ca4011e0ceb8c8d1a615d3cf81feb722d6245f863090cab5f92d51488981","src/lib.rs":"b370471a4f5421edffffc5ff44ae1a50261712f8c9826f025056f8818bf88f32","src/metal/adapter.rs":"c751a69fb1975214d04bb6e5c215adeace8eb144f4e630df67b38ebe5a69fbd9","src/metal/command.rs":"05bfa64dad2ed988400299bf121db16a827d379cedb01bdca8c9c4b883849472","src/metal/conv.rs":"e4aeafcddc75b2f9b54245faedaf0566f1e63681807ae786ceb46ac35f0e13bf","src/metal/device.rs":"9ea59f6f7ff0b60198a654573b9cce9594f21dcf4f671b27c7ded6d21b6787a8","src/metal/mod.rs":"1665ed043146e199ac75fab3612f11bcfd117bd4d59245c05b0b75b2b15280e7","src/metal/surface.rs":"f4b3f8364ec32a7540f7a1da3b4b7e8c6c1cf336aa5535a4515b4efb5b11c443","src/metal/time.rs":"c32d69f30e846dfcc0e39e01097fb80df63b2bebb6586143bb62494999850246","src/vulkan/adapter.rs":"bdd26edf5dacd7e3c9ee7678e1e040624c5a27dd40128649bf30bc1836d6a5a0","src/vulkan/command.rs":"f3a84dc73f93297247882e3f253df8e4239ae40326a00844b4ea14caf176a4a9","src/vulkan/conv.rs":"284f002063260811ba3fcfe75d6dc1c4c2eb2bc8b6622eac781157b7683478cd","src/vulkan/device.rs":"235557b97de7356399190beac3b7ae215210151b4e7e20796b42dcebfb245dbf","src/vulkan/instance.rs":"515cec19fd438ea35a4a0804ebed90e3013f976763fd1c1023ae16f6543cb50b","src/vulkan/mod.rs":"fed3c7e3a8fd1a22db0ee23c41acf3c0439b6822c93986cd92bb97b10db301e9"},"package":null} +{"files":{"Cargo.toml":"3b84e07e7947faaa8195e08012891802ffeaa52ce3bcc18009ec4a4b9ebfac32","LICENSE.APACHE":"a6cba85bc92e0cff7a450b1d873c0eaa2e9fc96bf472df0247a26bec77bf3ff9","LICENSE.MIT":"c7fea58d1cfe49634cd92e54fc10a9d871f4b275321a4cd8c09e449122caaeb4","README.md":"78377f5876fafd77963eff7e3c2ba3a7e3ad5cf9201b09ed5612e49c2288eb18","examples/halmark/main.rs":"dcbe0d8309d0842d33a598137d2f2c8a23f510497f6cb5c3917857688db308d1","examples/halmark/shader.wgsl":"26c256ec36d6f0e9a1647431ca772766bee4382d64eaa718ba7b488dcfb6bcca","examples/raw-gles.em.html":"70fbe68394a1a4522192de1dcfaf7d399f60d7bdf5de70b708f9bb0417427546","examples/raw-gles.rs":"d7e0d311514555f41b633eef2fdf355737e22c0b01d045d6afa6ba1b95511b2b","src/auxil/dxgi/conv.rs":"c1e8d584e408712097d075455375e04d1895a0ff9a494305c16d658277ce7b90","src/auxil/dxgi/exception.rs":"baad31f4529f1cf9d10519c4cceccbb21ed9bba7d7ea99e4789c1d5ddf3a450b","src/auxil/dxgi/factory.rs":"4d934b586dec17f49da0b63a57885107336e111f98556af95b45339a3898c23d","src/auxil/dxgi/mod.rs":"a202564d9ac97530b16a234b87d180cd345aae705e082a9b1177dcde813645f9","src/auxil/dxgi/result.rs":"20c8eb03d738062dff198feca6327addb9882ed0462be842c789eadf7dca0573","src/auxil/dxgi/time.rs":"b6f966b250e9424d5d7e4065f2108cba87197c1e30baae6d87083055d1bc5a4b","src/auxil/mod.rs":"c38f0d3b10804d1c1d7e3b8e4a975fcb87271f8b1904f2f4a3153cceddafb56b","src/auxil/renderdoc.rs":"c2f849f70f576b0c9b0d32dd155b6a6353f74dff59cbeeaa994a12789d047c0f","src/dx11/adapter.rs":"621c7d06ebac419f17f88c64b1a7cd2930499f2826f62a209cd93c42c47c316c","src/dx11/command.rs":"32a759d36ebc6d92528a128b117a752dd7fb6f4f0b4d8eda3ed564e5b8d783c2","src/dx11/device.rs":"96ccd8d6645839f3daf832ddf569676643ac92d1b332ab9a0c8563b3b5026295","src/dx11/instance.rs":"451fbe179dfdad74fe9ea378ad38a5db525e7008ec492e40ce78cc7b530b53ae","src/dx11/library.rs":"4fb09475fb24bc45fb7a464a7c6a30b45e10fed0022aad2891a390b512c11ae1","src/dx11/mod.rs":"21bc698bc0ff8b36a4906ee8dfaf469b6ed35ad852b7c0a5f60c5e5007bba128","src/dx12/adapter.rs":"1ecf0277171ff09368daa62b31759aadee3044e8033699b306e359cf10f01bdc","src/dx12/command.rs":"9074f4b3f80d9a9168b12b59518ca613a81bb7799f8756f5221e46c16cbeae8e","src/dx12/conv.rs":"4746ab2e46d8fbf4eac66c4dde11ca932f7ca9ba8177b5316eb12710a89700c2","src/dx12/descriptor.rs":"d9e295c48dc7d1759fd121c927c2218c1bde90e9f1b35f2ad01b610b184b614e","src/dx12/device.rs":"1e622243cddd09a4c39a5abb516421e1aa9bea5b2291f049b9fe44024592bc5a","src/dx12/instance.rs":"cb838a49a69f91aff364c8f76fe6c42307152aed56f456f74218b716a770ef99","src/dx12/mod.rs":"d7a34fd7143f62db30d3909ea7b66cc129ba1d971c27ce4cb38cbe1028ea2785","src/dx12/shader_compilation.rs":"dcff4c2c37b4d8c971a1e940eb7a843a32a3016cc65ef26bad71372687a835dc","src/dx12/suballocation.rs":"f5eb7c11dfe9c8d319ec853fec2a1aec8abe6bc61a729faa60302b105265f677","src/dx12/types.rs":"29b11268d11c1b7437de3dac403af574ec8aa84fd9954a95a16d80f5808be44d","src/dx12/view.rs":"c09241520377e6a47ad8822c69075e6e16e6c558e18bb64398c8d7424fc57dcf","src/empty.rs":"98c4ad29fdf1bad55097d540393b9ef62cce23b9d5cfd2a131f790042e3bd8b8","src/gles/adapter.rs":"4ee3f6b4604bed1beb08dcd8715700855b495dac0689f23119ba1d74440aaeff","src/gles/command.rs":"c7d6ff845b597d85d2fd61be625cf43554944d93f9324c98c2123995946cfd6b","src/gles/conv.rs":"84164c6b93afdbd07b037cdbee4c94dd40df0a21d42703481d0c293e92a13efd","src/gles/device.rs":"11b99f2da55ee07db7549b4313ceb68e35a13f87041832643359e80e6f355034","src/gles/egl.rs":"aeabffbd826df8c8512b7a2658da4e74b29e87db0012d053947c846d5a094bf7","src/gles/emscripten.rs":"19bb73a9d140645f3f32cd48b002151711a9b8456e213eab5f3a2be79239e147","src/gles/mod.rs":"65996152dff84f00d6d491bfe5edc5c343f2302a4aa01eef14aadb4bdab096ed","src/gles/queue.rs":"5a85e6c2ad9e97779b6fec81d2811c1e05d71f82f7c5bee87b31eade64c1501e","src/gles/shaders/clear.frag":"aac702eed9ece5482db5ba6783a678b119a5e7802b1ecf93f4975dee8acab0b3","src/gles/shaders/clear.vert":"8f636168e1da2cac48091c466a543c3b09fb4a0dd8c60c1c9bf34cc890766740","src/gles/shaders/srgb_present.frag":"dd9a43c339a2fa4ccf7f6a1854c6f400cabf271a7d5e9230768e9f39d47f3ff5","src/gles/shaders/srgb_present.vert":"6e85d489403d80b81cc94790730bb53b309dfc5eeede8f1ea3412a660f31d357","src/gles/web.rs":"0e39ca4011e0ceb8c8d1a615d3cf81feb722d6245f863090cab5f92d51488981","src/lib.rs":"8953b775ad67e5cb0102bd78f70410c4fd9f8b30c170ab3f8a7558f78686b91a","src/metal/adapter.rs":"93f48f24ff4add6c54891d630018b668127a52471acbdfcb2f888209c1231ed4","src/metal/command.rs":"a43a399b6f65a15ddd943bf981506d51571da6af73eeb8932c62a36c202d786c","src/metal/conv.rs":"e4aeafcddc75b2f9b54245faedaf0566f1e63681807ae786ceb46ac35f0e13bf","src/metal/device.rs":"d2fb16e8d7cfc0c9e3141dcf1245a1f0ea8a891962c0cd83c0cd4450e7acaf36","src/metal/mod.rs":"2ace6e0ac37b09e98f5fb7c19d5fb8f23f7b14ac35137ba7a7ad99f0ba032d77","src/metal/surface.rs":"f4b3f8364ec32a7540f7a1da3b4b7e8c6c1cf336aa5535a4515b4efb5b11c443","src/metal/time.rs":"c32d69f30e846dfcc0e39e01097fb80df63b2bebb6586143bb62494999850246","src/vulkan/adapter.rs":"bdd26edf5dacd7e3c9ee7678e1e040624c5a27dd40128649bf30bc1836d6a5a0","src/vulkan/command.rs":"08d9a43bd43820f2681efe4207a1be678f1aab47d779390c4dbb929d1b5450fa","src/vulkan/conv.rs":"284f002063260811ba3fcfe75d6dc1c4c2eb2bc8b6622eac781157b7683478cd","src/vulkan/device.rs":"9f445c3fcaf5b162b283c9abf112948b2e5a1ee0799156288a08acfb8fc7daa2","src/vulkan/instance.rs":"e840e512a2efa025c84696bf7750cd4f75f8a3f6efe9cc526445c369f578848b","src/vulkan/mod.rs":"1bef6c8213bfccf6dd23fe07414db2893a0f85a755bcf26f461371956c960173"},"package":null} \ No newline at end of file diff --git a/third_party/rust/wgpu-hal/Cargo.toml b/third_party/rust/wgpu-hal/Cargo.toml index 8de94115e4032..43eca8286ae0f 100644 --- a/third_party/rust/wgpu-hal/Cargo.toml +++ b/third_party/rust/wgpu-hal/Cargo.toml @@ -158,16 +158,13 @@ features = [ [target."cfg(any(target_os=\"macos\", target_os=\"ios\"))".dependencies] core-graphics-types = "0.1" +metal = "0.26.0" objc = "0.2.5" [target."cfg(any(target_os=\"macos\", target_os=\"ios\"))".dependencies.block] version = "0.1" optional = true -[target."cfg(any(target_os=\"macos\", target_os=\"ios\"))".dependencies.metal] -version = "0.26.0" -default_features = false - [target."cfg(not(target_arch = \"wasm32\"))".dependencies.ash] version = "0.37.3" optional = true diff --git a/third_party/rust/wgpu-hal/examples/halmark/main.rs b/third_party/rust/wgpu-hal/examples/halmark/main.rs index 61c1584a2562a..21289b18e564e 100644 --- a/third_party/rust/wgpu-hal/examples/halmark/main.rs +++ b/third_party/rust/wgpu-hal/examples/halmark/main.rs @@ -679,6 +679,8 @@ impl Example { })], depth_stencil_attachment: None, multiview: None, + timestamp_writes: None, + occlusion_query_set: None, }; unsafe { ctx.encoder.begin_render_pass(&pass_desc); diff --git a/third_party/rust/wgpu-hal/examples/raw-gles.rs b/third_party/rust/wgpu-hal/examples/raw-gles.rs index 1bf2ead0f565d..0e89783aa1825 100644 --- a/third_party/rust/wgpu-hal/examples/raw-gles.rs +++ b/third_party/rust/wgpu-hal/examples/raw-gles.rs @@ -175,6 +175,8 @@ fn fill_screen(exposed: &hal::ExposedAdapter, width: u32, height })], depth_stencil_attachment: None, multiview: None, + timestamp_writes: None, + occlusion_query_set: None, }; unsafe { encoder.begin_encoding(None).unwrap(); diff --git a/third_party/rust/wgpu-hal/src/dx11/command.rs b/third_party/rust/wgpu-hal/src/dx11/command.rs index 1c73f3c325683..17cd5a22d2eb3 100644 --- a/third_party/rust/wgpu-hal/src/dx11/command.rs +++ b/third_party/rust/wgpu-hal/src/dx11/command.rs @@ -246,7 +246,10 @@ impl crate::CommandEncoder for super::CommandEncoder { todo!() } - unsafe fn begin_compute_pass(&mut self, desc: &crate::ComputePassDescriptor) { + unsafe fn begin_compute_pass<'a>( + &mut self, + desc: &crate::ComputePassDescriptor<'a, super::Api>, + ) { todo!() } diff --git a/third_party/rust/wgpu-hal/src/dx12/command.rs b/third_party/rust/wgpu-hal/src/dx12/command.rs index 86fb7e4fe13ce..719e63a36f095 100644 --- a/third_party/rust/wgpu-hal/src/dx12/command.rs +++ b/third_party/rust/wgpu-hal/src/dx12/command.rs @@ -228,6 +228,21 @@ impl super::CommandEncoder { self.pass.layout = layout.clone(); self.pass.dirty_root_elements = (1 << layout.total_root_elements) - 1; } + + fn write_pass_end_timestamp_if_requested(&mut self) { + if let Some((query_set_raw, index)) = self.end_of_pass_timer_query.take() { + use crate::CommandEncoder as _; + unsafe { + self.write_timestamp( + &crate::dx12::QuerySet { + raw: query_set_raw, + raw_ty: d3d12_ty::D3D12_QUERY_TYPE_TIMESTAMP, + }, + index, + ); + } + } + } } impl crate::CommandEncoder for super::CommandEncoder { @@ -656,6 +671,19 @@ impl crate::CommandEncoder for super::CommandEncoder { unsafe fn begin_render_pass(&mut self, desc: &crate::RenderPassDescriptor) { unsafe { self.begin_pass(super::PassKind::Render, desc.label) }; + + // Start timestamp if any (before all other commands but after debug marker) + if let Some(timestamp_writes) = desc.timestamp_writes.as_ref() { + if let Some(index) = timestamp_writes.beginning_of_pass_write_index { + unsafe { + self.write_timestamp(timestamp_writes.query_set, index); + } + } + self.end_of_pass_timer_query = timestamp_writes + .end_of_pass_write_index + .map(|index| (timestamp_writes.query_set.raw.clone(), index)); + } + let mut color_views = [d3d12::CpuDescriptor { ptr: 0 }; crate::MAX_COLOR_ATTACHMENTS]; for (rtv, cat) in color_views.iter_mut().zip(desc.color_attachments.iter()) { if let Some(cat) = cat.as_ref() { @@ -825,6 +853,8 @@ impl crate::CommandEncoder for super::CommandEncoder { } } + self.write_pass_end_timestamp_if_requested(); + unsafe { self.end_pass() }; } @@ -1109,10 +1139,25 @@ impl crate::CommandEncoder for super::CommandEncoder { // compute - unsafe fn begin_compute_pass(&mut self, desc: &crate::ComputePassDescriptor) { + unsafe fn begin_compute_pass<'a>( + &mut self, + desc: &crate::ComputePassDescriptor<'a, super::Api>, + ) { unsafe { self.begin_pass(super::PassKind::Compute, desc.label) }; + + if let Some(timestamp_writes) = desc.timestamp_writes.as_ref() { + if let Some(index) = timestamp_writes.beginning_of_pass_write_index { + unsafe { + self.write_timestamp(timestamp_writes.query_set, index); + } + } + self.end_of_pass_timer_query = timestamp_writes + .end_of_pass_write_index + .map(|index| (timestamp_writes.query_set.raw.clone(), index)); + } } unsafe fn end_compute_pass(&mut self) { + self.write_pass_end_timestamp_if_requested(); unsafe { self.end_pass() }; } diff --git a/third_party/rust/wgpu-hal/src/dx12/device.rs b/third_party/rust/wgpu-hal/src/dx12/device.rs index ad991d12276f5..1471db3b30b0d 100644 --- a/third_party/rust/wgpu-hal/src/dx12/device.rs +++ b/third_party/rust/wgpu-hal/src/dx12/device.rs @@ -644,6 +644,7 @@ impl crate::Device for super::Device { free_lists: Vec::new(), pass: super::PassState::new(), temp: super::Temp::default(), + end_of_pass_timer_query: None, }) } unsafe fn destroy_command_encoder(&self, encoder: super::CommandEncoder) { diff --git a/third_party/rust/wgpu-hal/src/dx12/mod.rs b/third_party/rust/wgpu-hal/src/dx12/mod.rs index 74e82085024a4..564bc349c6ba7 100644 --- a/third_party/rust/wgpu-hal/src/dx12/mod.rs +++ b/third_party/rust/wgpu-hal/src/dx12/mod.rs @@ -347,6 +347,10 @@ pub struct CommandEncoder { free_lists: Vec, pass: PassState, temp: Temp, + + /// If set, the end of the next render/compute pass will write a timestamp at + /// the given pool & location. + end_of_pass_timer_query: Option<(d3d12::QueryHeap, u32)>, } unsafe impl Send for CommandEncoder {} diff --git a/third_party/rust/wgpu-hal/src/empty.rs b/third_party/rust/wgpu-hal/src/empty.rs index 1497acad9184f..b72ea0aadee3a 100644 --- a/third_party/rust/wgpu-hal/src/empty.rs +++ b/third_party/rust/wgpu-hal/src/empty.rs @@ -403,7 +403,7 @@ impl crate::CommandEncoder for Encoder { // compute - unsafe fn begin_compute_pass(&mut self, desc: &crate::ComputePassDescriptor) {} + unsafe fn begin_compute_pass(&mut self, desc: &crate::ComputePassDescriptor) {} unsafe fn end_compute_pass(&mut self) {} unsafe fn set_compute_pipeline(&mut self, pipeline: &Resource) {} diff --git a/third_party/rust/wgpu-hal/src/gles/command.rs b/third_party/rust/wgpu-hal/src/gles/command.rs index c31b5770791d8..866211f442870 100644 --- a/third_party/rust/wgpu-hal/src/gles/command.rs +++ b/third_party/rust/wgpu-hal/src/gles/command.rs @@ -1030,7 +1030,7 @@ impl crate::CommandEncoder for super::CommandEncoder { // compute - unsafe fn begin_compute_pass(&mut self, desc: &crate::ComputePassDescriptor) { + unsafe fn begin_compute_pass(&mut self, desc: &crate::ComputePassDescriptor) { if let Some(label) = desc.label { let range = self.cmd_buffer.add_marker(label); self.cmd_buffer.commands.push(C::PushDebugGroup(range)); diff --git a/third_party/rust/wgpu-hal/src/gles/device.rs b/third_party/rust/wgpu-hal/src/gles/device.rs index cc21f14836535..47004724a7677 100644 --- a/third_party/rust/wgpu-hal/src/gles/device.rs +++ b/third_party/rust/wgpu-hal/src/gles/device.rs @@ -527,6 +527,10 @@ impl crate::Device for super::Device { map_flags |= glow::MAP_COHERENT_BIT; } } + // TODO: may also be required for other calls involving `buffer_sub_data_u8_slice` (e.g. copy buffer to buffer and clear buffer) + if desc.usage.intersects(crate::BufferUses::QUERY_RESOLVE) { + map_flags |= glow::DYNAMIC_STORAGE_BIT; + } unsafe { gl.buffer_storage(target, raw_size, None, map_flags) }; } else { assert!(!is_coherent); @@ -1238,7 +1242,7 @@ impl crate::Device for super::Device { Ok(super::QuerySet { queries: queries.into_boxed_slice(), target: match desc.ty { - wgt::QueryType::Occlusion => glow::ANY_SAMPLES_PASSED, + wgt::QueryType::Occlusion => glow::ANY_SAMPLES_PASSED_CONSERVATIVE, _ => unimplemented!(), }, }) diff --git a/third_party/rust/wgpu-hal/src/lib.rs b/third_party/rust/wgpu-hal/src/lib.rs index 436553b29e7c6..1248ee9030181 100644 --- a/third_party/rust/wgpu-hal/src/lib.rs +++ b/third_party/rust/wgpu-hal/src/lib.rs @@ -118,6 +118,8 @@ pub enum DeviceError { OutOfMemory, #[error("Device is lost")] Lost, + #[error("Creation of a resource failed for a reason other than running out of memory.")] + ResourceCreationFailed, } #[derive(Clone, Debug, Eq, PartialEq, Error)] @@ -463,7 +465,13 @@ pub trait CommandEncoder: WasmNotSend + WasmNotSync + fmt::Debug { // queries + /// # Safety: + /// + /// - If `set` is an occlusion query set, it must be the same one as used in the [`RenderPassDescriptor::occlusion_query_set`] parameter. unsafe fn begin_query(&mut self, set: &A::QuerySet, index: u32); + /// # Safety: + /// + /// - If `set` is an occlusion query set, it must be the same one as used in the [`RenderPassDescriptor::occlusion_query_set`] parameter. unsafe fn end_query(&mut self, set: &A::QuerySet, index: u32); unsafe fn write_timestamp(&mut self, set: &A::QuerySet, index: u32); unsafe fn reset_queries(&mut self, set: &A::QuerySet, range: Range); @@ -542,7 +550,7 @@ pub trait CommandEncoder: WasmNotSend + WasmNotSync + fmt::Debug { // compute passes // Begins a compute pass, clears all active bindings. - unsafe fn begin_compute_pass(&mut self, desc: &ComputePassDescriptor); + unsafe fn begin_compute_pass(&mut self, desc: &ComputePassDescriptor); unsafe fn end_compute_pass(&mut self); unsafe fn set_compute_pipeline(&mut self, pipeline: &A::ComputePipeline); @@ -718,6 +726,8 @@ bitflags::bitflags! { const STORAGE_READ_WRITE = 1 << 8; /// The indirect or count buffer in a indirect draw or dispatch. const INDIRECT = 1 << 9; + /// A buffer used to store query results. + const QUERY_RESOLVE = 1 << 10; /// The combination of states that a buffer may be in _at the same time_. const INCLUSIVE = Self::MAP_READ.bits() | Self::COPY_SRC.bits() | Self::INDEX.bits() | Self::VERTEX.bits() | Self::UNIFORM.bits() | @@ -1262,6 +1272,24 @@ pub struct DepthStencilAttachment<'a, A: Api> { pub clear_value: (f32, u32), } +#[derive(Debug)] +pub struct RenderPassTimestampWrites<'a, A: Api> { + pub query_set: &'a A::QuerySet, + pub beginning_of_pass_write_index: Option, + pub end_of_pass_write_index: Option, +} + +// Rust gets confused about the impl requirements for `A` +impl Clone for RenderPassTimestampWrites<'_, A> { + fn clone(&self) -> Self { + Self { + query_set: self.query_set, + beginning_of_pass_write_index: self.beginning_of_pass_write_index, + end_of_pass_write_index: self.end_of_pass_write_index, + } + } +} + #[derive(Clone, Debug)] pub struct RenderPassDescriptor<'a, A: Api> { pub label: Label<'a>, @@ -1270,11 +1298,32 @@ pub struct RenderPassDescriptor<'a, A: Api> { pub color_attachments: &'a [Option>], pub depth_stencil_attachment: Option>, pub multiview: Option, + pub timestamp_writes: Option>, + pub occlusion_query_set: Option<&'a A::QuerySet>, +} + +#[derive(Debug)] +pub struct ComputePassTimestampWrites<'a, A: Api> { + pub query_set: &'a A::QuerySet, + pub beginning_of_pass_write_index: Option, + pub end_of_pass_write_index: Option, +} + +// Rust gets confused about the impl requirements for `A` +impl Clone for ComputePassTimestampWrites<'_, A> { + fn clone(&self) -> Self { + Self { + query_set: self.query_set, + beginning_of_pass_write_index: self.beginning_of_pass_write_index, + end_of_pass_write_index: self.end_of_pass_write_index, + } + } } #[derive(Clone, Debug)] -pub struct ComputePassDescriptor<'a> { +pub struct ComputePassDescriptor<'a, A: Api> { pub label: Label<'a>, + pub timestamp_writes: Option>, } /// Stores if any API validation error has occurred in this process diff --git a/third_party/rust/wgpu-hal/src/metal/adapter.rs b/third_party/rust/wgpu-hal/src/metal/adapter.rs index c5e6316c19582..5e44a18164d87 100644 --- a/third_party/rust/wgpu-hal/src/metal/adapter.rs +++ b/third_party/rust/wgpu-hal/src/metal/adapter.rs @@ -27,6 +27,33 @@ impl crate::Adapter for super::Adapter { .device .lock() .new_command_queue_with_max_command_buffer_count(MAX_COMMAND_BUFFERS); + + // Acquiring the meaning of timestamp ticks is hard with Metal! + // The only thing there is is a method correlating cpu & gpu timestamps (`device.sample_timestamps`). + // Users are supposed to call this method twice and calculate the difference, + // see "Converting GPU Timestamps into CPU Time": + // https://developer.apple.com/documentation/metal/gpu_counters_and_counter_sample_buffers/converting_gpu_timestamps_into_cpu_time + // Not only does this mean we get an approximate value, this is as also *very slow*! + // Chromium opted to solve this using a linear regression that they stop at some point + // https://source.chromium.org/chromium/chromium/src/+/refs/heads/main:third_party/dawn/src/dawn/native/metal/DeviceMTL.mm;drc=76be2f9f117654f3fe4faa477b0445114fccedda;bpv=0;bpt=1;l=46 + // Generally, the assumption is that timestamp values aren't changing over time, after all all other APIs provide stable values. + // + // We should do as Chromium does for the general case, but this requires quite some state tracking + // and doesn't even provide perfectly accurate values, especially at the start of the application when + // we didn't have the chance to sample a lot of values just yet. + // + // So instead, we're doing the dangerous but easy thing and use our "knowledge" of timestamps + // conversions on different devices, after all Metal isn't supported on that many ;) + // Based on: + // * https://github.com/gfx-rs/wgpu/pull/2528 + // * https://github.com/gpuweb/gpuweb/issues/1325#issuecomment-761041326 + let timestamp_period = if self.shared.device.lock().name().starts_with("Intel") { + 83.333 + } else { + // Known for Apple Silicon (at least M1 & M2, iPad Pro 2018) and AMD GPUs. + 1.0 + }; + Ok(crate::OpenDevice { device: super::Device { shared: Arc::clone(&self.shared), @@ -34,6 +61,7 @@ impl crate::Adapter for super::Adapter { }, queue: super::Queue { raw: Arc::new(Mutex::new(queue)), + timestamp_period, }, }) } @@ -745,6 +773,13 @@ impl super::PrivateCapabilities { } else { None }, + support_timestamp_query: version.at_least((11, 0), (14, 0), os_is_mac) + && device + .supports_counter_sampling(metal::MTLCounterSamplingPoint::AtStageBoundary), + support_timestamp_query_in_passes: version.at_least((11, 0), (14, 0), os_is_mac) + && device.supports_counter_sampling(metal::MTLCounterSamplingPoint::AtDrawBoundary) + && device + .supports_counter_sampling(metal::MTLCounterSamplingPoint::AtDispatchBoundary), } } @@ -772,6 +807,12 @@ impl super::PrivateCapabilities { | F::DEPTH32FLOAT_STENCIL8 | F::MULTI_DRAW_INDIRECT; + features.set(F::TIMESTAMP_QUERY, self.support_timestamp_query); + // TODO: Not yet implemented. + // features.set( + // F::TIMESTAMP_QUERY_INSIDE_PASSES, + // self.support_timestamp_query_in_passes, + // ); features.set(F::TEXTURE_COMPRESSION_ASTC, self.format_astc); features.set(F::TEXTURE_COMPRESSION_ASTC_HDR, self.format_astc_hdr); features.set(F::TEXTURE_COMPRESSION_BC, self.format_bc); diff --git a/third_party/rust/wgpu-hal/src/metal/command.rs b/third_party/rust/wgpu-hal/src/metal/command.rs index 34712859ef7be..05af2805b8267 100644 --- a/third_party/rust/wgpu-hal/src/metal/command.rs +++ b/third_party/rust/wgpu-hal/src/metal/command.rs @@ -321,7 +321,18 @@ impl crate::CommandEncoder for super::CommandEncoder { _ => {} } } - unsafe fn write_timestamp(&mut self, _set: &super::QuerySet, _index: u32) {} + unsafe fn write_timestamp(&mut self, _set: &super::QuerySet, _index: u32) { + // TODO: If MTLCounterSamplingPoint::AtDrawBoundary/AtBlitBoundary/AtDispatchBoundary is supported, + // we don't need to insert a new encoder, but can instead use respective current one. + //let encoder = self.enter_any().unwrap_or_else(|| self.enter_blit()); + + // TODO: Otherwise, we need to create a new blit command encoder with a descriptor that inserts the timestamps. + // Note that as of writing creating a new encoder is not exposed by the metal crate. + // https://developer.apple.com/documentation/metal/mtlcommandbuffer/3564431-makeblitcommandencoder + + // TODO: Enable respective test in `examples/timestamp-queries/src/tests.rs`. + } + unsafe fn reset_queries(&mut self, set: &super::QuerySet, range: Range) { let encoder = self.enter_blit(); let raw_range = metal::NSRange { @@ -339,14 +350,27 @@ impl crate::CommandEncoder for super::CommandEncoder { _: wgt::BufferSize, // Metal doesn't support queries that are bigger than a single element are not supported ) { let encoder = self.enter_blit(); - let size = (range.end - range.start) as u64 * crate::QUERY_SIZE; - encoder.copy_from_buffer( - &set.raw_buffer, - range.start as u64 * crate::QUERY_SIZE, - &buffer.raw, - offset, - size, - ); + match set.ty { + wgt::QueryType::Occlusion => { + let size = (range.end - range.start) as u64 * crate::QUERY_SIZE; + encoder.copy_from_buffer( + &set.raw_buffer, + range.start as u64 * crate::QUERY_SIZE, + &buffer.raw, + offset, + size, + ); + } + wgt::QueryType::Timestamp => { + encoder.resolve_counters( + set.counter_sample_buffer.as_ref().unwrap(), + metal::NSRange::new(range.start as u64, range.end as u64), + &buffer.raw, + offset, + ); + } + wgt::QueryType::PipelineStatistics(_) => todo!(), + } } // render @@ -361,7 +385,6 @@ impl crate::CommandEncoder for super::CommandEncoder { objc::rc::autoreleasepool(|| { let descriptor = metal::RenderPassDescriptor::new(); - //TODO: set visibility results buffer for (i, at) in desc.color_attachments.iter().enumerate() { if let Some(at) = at.as_ref() { @@ -430,6 +453,29 @@ impl crate::CommandEncoder for super::CommandEncoder { } } + if let Some(ref timestamp_writes) = desc.timestamp_writes { + let sba_descriptor = descriptor.sample_buffer_attachments().object_at(0).unwrap(); + sba_descriptor.set_sample_buffer( + timestamp_writes + .query_set + .counter_sample_buffer + .as_ref() + .unwrap(), + ); + + if let Some(start_index) = timestamp_writes.beginning_of_pass_write_index { + sba_descriptor.set_start_of_vertex_sample_index(start_index as _); + } + if let Some(end_index) = timestamp_writes.end_of_pass_write_index { + sba_descriptor.set_end_of_fragment_sample_index(end_index as _); + } + } + + if let Some(occlusion_query_set) = desc.occlusion_query_set { + descriptor + .set_visibility_result_buffer(Some(occlusion_query_set.raw_buffer.as_ref())) + } + let raw = self.raw_cmd_buf.as_ref().unwrap(); let encoder = raw.new_render_command_encoder(descriptor); if let Some(label) = desc.label { @@ -910,18 +956,44 @@ impl crate::CommandEncoder for super::CommandEncoder { // compute - unsafe fn begin_compute_pass(&mut self, desc: &crate::ComputePassDescriptor) { + unsafe fn begin_compute_pass(&mut self, desc: &crate::ComputePassDescriptor) { self.begin_pass(); - let raw = self.raw_cmd_buf.as_ref().unwrap(); debug_assert!(self.state.blit.is_none()); debug_assert!(self.state.compute.is_none()); debug_assert!(self.state.render.is_none()); + + let raw = self.raw_cmd_buf.as_ref().unwrap(); + objc::rc::autoreleasepool(|| { - let encoder = raw.new_compute_command_encoder(); + let descriptor = metal::ComputePassDescriptor::new(); + + if let Some(timestamp_writes) = desc.timestamp_writes.as_ref() { + let sba_descriptor = descriptor + .sample_buffer_attachments() + .object_at(0 as _) + .unwrap(); + sba_descriptor.set_sample_buffer( + timestamp_writes + .query_set + .counter_sample_buffer + .as_ref() + .unwrap(), + ); + + if let Some(start_index) = timestamp_writes.beginning_of_pass_write_index { + sba_descriptor.set_start_of_encoder_sample_index(start_index as _); + } + if let Some(end_index) = timestamp_writes.end_of_pass_write_index { + sba_descriptor.set_end_of_encoder_sample_index(end_index as _); + } + } + + let encoder = raw.compute_command_encoder_with_descriptor(descriptor); if let Some(label) = desc.label { encoder.set_label(label); } + self.state.compute = Some(encoder.to_owned()); }); } diff --git a/third_party/rust/wgpu-hal/src/metal/device.rs b/third_party/rust/wgpu-hal/src/metal/device.rs index c3166d26ab2cf..475332b76d5e9 100644 --- a/third_party/rust/wgpu-hal/src/metal/device.rs +++ b/third_party/rust/wgpu-hal/src/metal/device.rs @@ -1098,11 +1098,51 @@ impl crate::Device for super::Device { } Ok(super::QuerySet { raw_buffer, + counter_sample_buffer: None, ty: desc.ty, }) } - wgt::QueryType::Timestamp | wgt::QueryType::PipelineStatistics(_) => { - Err(crate::DeviceError::OutOfMemory) + wgt::QueryType::Timestamp => { + let size = desc.count as u64 * crate::QUERY_SIZE; + let device = self.shared.device.lock(); + let destination_buffer = + device.new_buffer(size, metal::MTLResourceOptions::empty()); + + let csb_desc = metal::CounterSampleBufferDescriptor::new(); + csb_desc.set_storage_mode(metal::MTLStorageMode::Shared); + csb_desc.set_sample_count(desc.count as _); + if let Some(label) = desc.label { + csb_desc.set_label(label); + } + + let counter_sets = device.counter_sets(); + let timestamp_counter = + match counter_sets.iter().find(|cs| cs.name() == "timestamp") { + Some(counter) => counter, + None => { + log::error!("Failed to obtain timestamp counter set."); + return Err(crate::DeviceError::ResourceCreationFailed); + } + }; + csb_desc.set_counter_set(timestamp_counter); + + let counter_sample_buffer = + match device.new_counter_sample_buffer_with_descriptor(&csb_desc) { + Ok(buffer) => buffer, + Err(err) => { + log::error!("Failed to create counter sample buffer: {:?}", err); + return Err(crate::DeviceError::ResourceCreationFailed); + } + }; + + Ok(super::QuerySet { + raw_buffer: destination_buffer, + counter_sample_buffer: Some(counter_sample_buffer), + ty: desc.ty, + }) + } + _ => { + todo!() } } }) diff --git a/third_party/rust/wgpu-hal/src/metal/mod.rs b/third_party/rust/wgpu-hal/src/metal/mod.rs index 6611f29548a0b..3a8ebc5570a0b 100644 --- a/third_party/rust/wgpu-hal/src/metal/mod.rs +++ b/third_party/rust/wgpu-hal/src/metal/mod.rs @@ -237,6 +237,8 @@ struct PrivateCapabilities { supports_preserve_invariance: bool, supports_shader_primitive_index: bool, has_unified_memory: Option, + support_timestamp_query: bool, + support_timestamp_query_in_passes: bool, } #[derive(Clone, Debug)] @@ -285,18 +287,21 @@ pub struct Adapter { pub struct Queue { raw: Arc>, + timestamp_period: f32, } unsafe impl Send for Queue {} unsafe impl Sync for Queue {} impl Queue { - pub unsafe fn queue_from_raw(raw: metal::CommandQueue) -> Self { + pub unsafe fn queue_from_raw(raw: metal::CommandQueue, timestamp_period: f32) -> Self { Self { raw: Arc::new(Mutex::new(raw)), + timestamp_period, } } } + pub struct Device { shared: Arc, features: wgt::Features, @@ -406,8 +411,7 @@ impl crate::Queue for Queue { } unsafe fn get_timestamp_period(&self) -> f32 { - // TODO: This is hard, see https://github.com/gpuweb/gpuweb/issues/1325 - 1.0 + self.timestamp_period } } @@ -701,6 +705,8 @@ unsafe impl Sync for ComputePipeline {} #[derive(Debug)] pub struct QuerySet { raw_buffer: metal::Buffer, + //Metal has a custom buffer for counters. + counter_sample_buffer: Option, ty: wgt::QueryType, } diff --git a/third_party/rust/wgpu-hal/src/vulkan/command.rs b/third_party/rust/wgpu-hal/src/vulkan/command.rs index 417367689b6c5..c2e7afe3f1ef7 100644 --- a/third_party/rust/wgpu-hal/src/vulkan/command.rs +++ b/third_party/rust/wgpu-hal/src/vulkan/command.rs @@ -45,6 +45,21 @@ impl super::DeviceShared { } } +impl super::CommandEncoder { + fn write_pass_end_timestamp_if_requested(&mut self) { + if let Some((query_set, index)) = self.end_of_pass_timer_query.take() { + unsafe { + self.device.raw.cmd_write_timestamp( + self.active, + vk::PipelineStageFlags::BOTTOM_OF_PIPE, + query_set, + index, + ); + } + } + } +} + impl crate::CommandEncoder for super::CommandEncoder { unsafe fn begin_encoding(&mut self, label: crate::Label) -> Result<(), crate::DeviceError> { if self.free.is_empty() { @@ -489,6 +504,18 @@ impl crate::CommandEncoder for super::CommandEncoder { self.rpass_debug_marker_active = true; } + // Start timestamp if any (before all other commands but after debug marker) + if let Some(timestamp_writes) = desc.timestamp_writes.as_ref() { + if let Some(index) = timestamp_writes.beginning_of_pass_write_index { + unsafe { + self.write_timestamp(timestamp_writes.query_set, index); + } + } + self.end_of_pass_timer_query = timestamp_writes + .end_of_pass_write_index + .map(|index| (timestamp_writes.query_set.raw, index)); + } + unsafe { self.device .raw @@ -508,10 +535,16 @@ impl crate::CommandEncoder for super::CommandEncoder { unsafe fn end_render_pass(&mut self) { unsafe { self.device.raw.cmd_end_render_pass(self.active); - if self.rpass_debug_marker_active { + } + + // After all other commands but before debug marker, so this is still seen as part of this pass. + self.write_pass_end_timestamp_if_requested(); + + if self.rpass_debug_marker_active { + unsafe { self.end_debug_marker(); - self.rpass_debug_marker_active = false; } + self.rpass_debug_marker_active = false; } } @@ -781,14 +814,27 @@ impl crate::CommandEncoder for super::CommandEncoder { // compute - unsafe fn begin_compute_pass(&mut self, desc: &crate::ComputePassDescriptor) { + unsafe fn begin_compute_pass(&mut self, desc: &crate::ComputePassDescriptor<'_, super::Api>) { self.bind_point = vk::PipelineBindPoint::COMPUTE; if let Some(label) = desc.label { unsafe { self.begin_debug_marker(label) }; self.rpass_debug_marker_active = true; } + + if let Some(timestamp_writes) = desc.timestamp_writes.as_ref() { + if let Some(index) = timestamp_writes.beginning_of_pass_write_index { + unsafe { + self.write_timestamp(timestamp_writes.query_set, index); + } + } + self.end_of_pass_timer_query = timestamp_writes + .end_of_pass_write_index + .map(|index| (timestamp_writes.query_set.raw, index)); + } } unsafe fn end_compute_pass(&mut self) { + self.write_pass_end_timestamp_if_requested(); + if self.rpass_debug_marker_active { unsafe { self.end_debug_marker() }; self.rpass_debug_marker_active = false diff --git a/third_party/rust/wgpu-hal/src/vulkan/device.rs b/third_party/rust/wgpu-hal/src/vulkan/device.rs index 43410be885e42..a69897a32483c 100644 --- a/third_party/rust/wgpu-hal/src/vulkan/device.rs +++ b/third_party/rust/wgpu-hal/src/vulkan/device.rs @@ -1188,6 +1188,7 @@ impl crate::Device for super::Device { free: Vec::new(), discarded: Vec::new(), rpass_debug_marker_active: false, + end_of_pass_timer_query: None, }) } unsafe fn destroy_command_encoder(&self, cmd_encoder: super::CommandEncoder) { diff --git a/third_party/rust/wgpu-hal/src/vulkan/instance.rs b/third_party/rust/wgpu-hal/src/vulkan/instance.rs index 81ecbaf3e3b37..931d4a2819b86 100644 --- a/third_party/rust/wgpu-hal/src/vulkan/instance.rs +++ b/third_party/rust/wgpu-hal/src/vulkan/instance.rs @@ -47,6 +47,19 @@ unsafe extern "system" fn debug_utils_messenger_callback( return vk::FALSE; } + // Silence Vulkan Validation error "VUID-VkRenderPassBeginInfo-framebuffer-04627" + // if the OBS layer is enabled. This is a bug in the OBS layer. As the OBS layer + // does not have a version number they increment, there is no way to qualify the + // supression of the error to a specific version of the OBS layer. + // + // See https://github.com/obsproject/obs-studio/issues/9353 + const VUID_VKRENDERPASSBEGININFO_FRAMEBUFFER_04627: i32 = 0x45125641; + if cd.message_id_number == VUID_VKRENDERPASSBEGININFO_FRAMEBUFFER_04627 + && user_data.has_obs_layer + { + return vk::FALSE; + } + let level = match message_severity { vk::DebugUtilsMessageSeverityFlagsEXT::VERBOSE => log::Level::Debug, vk::DebugUtilsMessageSeverityFlagsEXT::INFO => log::Level::Info, @@ -593,6 +606,9 @@ impl crate::Instance for super::Instance { let nv_optimus_layer = CStr::from_bytes_with_nul(b"VK_LAYER_NV_optimus\0").unwrap(); let has_nv_optimus = find_layer(&instance_layers, nv_optimus_layer).is_some(); + let obs_layer = CStr::from_bytes_with_nul(b"VK_LAYER_OBS_HOOK\0").unwrap(); + let has_obs_layer = find_layer(&instance_layers, obs_layer).is_some(); + let mut layers: Vec<&'static CStr> = Vec::new(); // Request validation layer if asked. @@ -609,6 +625,7 @@ impl crate::Instance for super::Instance { .unwrap() .to_owned(), validation_layer_spec_version: layer_properties.spec_version, + has_obs_layer, }); } else { log::warn!( diff --git a/third_party/rust/wgpu-hal/src/vulkan/mod.rs b/third_party/rust/wgpu-hal/src/vulkan/mod.rs index 3a0bfd82b9977..c2165e1dd8323 100644 --- a/third_party/rust/wgpu-hal/src/vulkan/mod.rs +++ b/third_party/rust/wgpu-hal/src/vulkan/mod.rs @@ -96,6 +96,10 @@ pub struct DebugUtilsMessengerUserData { /// Validation layer specification version, from `vk::LayerProperties`. validation_layer_spec_version: u32, + + /// If the OBS layer is present. OBS never increments the version of their layer, + /// so there's no reason to have the version. + has_obs_layer: bool, } pub struct InstanceShared { @@ -400,6 +404,10 @@ pub struct CommandEncoder { /// If this is true, the active renderpass enabled a debug span, /// and needs to be disabled on renderpass close. rpass_debug_marker_active: bool, + + /// If set, the end of the next render/compute pass will write a timestamp at + /// the given pool & location. + end_of_pass_timer_query: Option<(vk::QueryPool, u32)>, } impl fmt::Debug for CommandEncoder { diff --git a/third_party/rust/wgpu-types/.cargo-checksum.json b/third_party/rust/wgpu-types/.cargo-checksum.json index 5bd169bc6ba29..38bb584a29414 100644 --- a/third_party/rust/wgpu-types/.cargo-checksum.json +++ b/third_party/rust/wgpu-types/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"3e6c7a81b7f5b26b82b7a8a423eda073864e457083fe884b5ba53bda62e68cc9","LICENSE.APACHE":"a6cba85bc92e0cff7a450b1d873c0eaa2e9fc96bf472df0247a26bec77bf3ff9","LICENSE.MIT":"c7fea58d1cfe49634cd92e54fc10a9d871f4b275321a4cd8c09e449122caaeb4","src/assertions.rs":"3fe98027aa73970c8ab7874a3e13dbfd6faa87df2081beb5c83aeec4c60f372f","src/lib.rs":"a37ed56b53ef8dcd8e3420b25186b3a7416b951b234290e37887770e32ad7e61","src/math.rs":"4d03039736dd6926feb139bc68734cb59df34ede310427bbf059e5c925e0af3b"},"package":null} +{"files":{"Cargo.toml":"3e6c7a81b7f5b26b82b7a8a423eda073864e457083fe884b5ba53bda62e68cc9","LICENSE.APACHE":"a6cba85bc92e0cff7a450b1d873c0eaa2e9fc96bf472df0247a26bec77bf3ff9","LICENSE.MIT":"c7fea58d1cfe49634cd92e54fc10a9d871f4b275321a4cd8c09e449122caaeb4","src/assertions.rs":"3fe98027aa73970c8ab7874a3e13dbfd6faa87df2081beb5c83aeec4c60f372f","src/lib.rs":"539e99813685991a2e57e84b503c9a144d1b9ae24b36f321114f15d5b2867fec","src/math.rs":"4d03039736dd6926feb139bc68734cb59df34ede310427bbf059e5c925e0af3b"},"package":null} \ No newline at end of file diff --git a/third_party/rust/wgpu-types/src/lib.rs b/third_party/rust/wgpu-types/src/lib.rs index 29619210e180c..a3dc1906c6279 100644 --- a/third_party/rust/wgpu-types/src/lib.rs +++ b/third_party/rust/wgpu-types/src/lib.rs @@ -253,9 +253,14 @@ bitflags::bitflags! { /// This is a web and native feature. const DEPTH_CLIP_CONTROL = 1 << 0; /// Enables use of Timestamp Queries. These queries tell the current gpu timestamp when - /// all work before the query is finished. Call [`CommandEncoder::write_timestamp`], - /// [`RenderPassEncoder::write_timestamp`], or [`ComputePassEncoder::write_timestamp`] to - /// write out a timestamp. + /// all work before the query is finished. + /// + /// This feature allows the use of + /// - [`CommandEncoder::write_timestamp`] + /// - [`RenderPassDescriptor::timestamp_writes`] + /// - [`ComputePassDescriptor::timestamp_writes`] + /// to write out timestamps. + /// For timestamps within passes refer to [`Features::TIMESTAMP_QUERY_INSIDE_PASSES`] /// /// They must be resolved using [`CommandEncoder::resolve_query_sets`] into a buffer, /// then the result must be multiplied by the timestamp period [`Queue::get_timestamp_period`] @@ -265,8 +270,7 @@ bitflags::bitflags! { /// Supported Platforms: /// - Vulkan /// - DX12 - /// - /// This is currently unimplemented on Metal. + /// - Metal - TODO: Not yet supported on command encoder. /// /// This is a web and native feature. const TIMESTAMP_QUERY = 1 << 1; @@ -447,12 +451,17 @@ bitflags::bitflags! { /// /// Implies [`Features::TIMESTAMP_QUERY`] is supported. /// + /// Additionally allows for timestamp queries to be used inside render & compute passes using: + /// - [`RenderPassEncoder::write_timestamp`] + /// - [`ComputePassEncoder::write_timestamp`] + /// /// Supported platforms: /// - Vulkan /// - DX12 /// /// This is currently unimplemented on Metal. /// When implemented, it will be supported on Metal on AMD and Intel GPUs, but not Apple GPUs. + /// (This is a common limitation of tile-based rasterization GPUs) /// /// This is a native only feature with a [proposal](https://github.com/gpuweb/gpuweb/blob/0008bd30da2366af88180b511a5d0d0c1dffbc36/proposals/timestamp-query-inside-passes.md) for the web. const TIMESTAMP_QUERY_INSIDE_PASSES = 1 << 33; @@ -847,7 +856,7 @@ pub struct Limits { pub max_texture_array_layers: u32, /// Amount of bind groups that can be attached to a pipeline at the same time. Defaults to 4. Higher is "better". pub max_bind_groups: u32, - /// Maximum binding index allowed in `create_bind_group_layout`. Defaults to 1000. + /// Maximum binding index allowed in `create_bind_group_layout`. Defaults to 1000. Higher is "better". pub max_bindings_per_bind_group: u32, /// Amount of uniform buffer bindings that can be dynamic in a single pipeline. Defaults to 8. Higher is "better". pub max_dynamic_uniform_buffers_per_pipeline_layout: u32, @@ -863,14 +872,15 @@ pub struct Limits { pub max_storage_textures_per_shader_stage: u32, /// Amount of uniform buffers visible in a single shader stage. Defaults to 12. Higher is "better". pub max_uniform_buffers_per_shader_stage: u32, - /// Maximum size in bytes of a binding to a uniform buffer. Defaults to 64 KB. Higher is "better". + /// Maximum size in bytes of a binding to a uniform buffer. Defaults to 64 KiB. Higher is "better". pub max_uniform_buffer_binding_size: u32, - /// Maximum size in bytes of a binding to a storage buffer. Defaults to 128 MB. Higher is "better". + /// Maximum size in bytes of a binding to a storage buffer. Defaults to 128 MiB. Higher is "better". pub max_storage_buffer_binding_size: u32, /// Maximum length of `VertexState::buffers` when creating a `RenderPipeline`. /// Defaults to 8. Higher is "better". pub max_vertex_buffers: u32, /// A limit above which buffer allocations are guaranteed to fail. + /// Defaults to 256 MiB. Higher is "better". /// /// Buffer allocations below the maximum buffer size may not succeed depending on available memory, /// fragmentation and other factors. @@ -892,24 +902,25 @@ pub struct Limits { pub min_storage_buffer_offset_alignment: u32, /// Maximum allowed number of components (scalars) of input or output locations for /// inter-stage communication (vertex outputs to fragment inputs). Defaults to 60. + /// Higher is "better". pub max_inter_stage_shader_components: u32, /// Maximum number of bytes used for workgroup memory in a compute entry point. Defaults to - /// 16352. + /// 16352. Higher is "better". pub max_compute_workgroup_storage_size: u32, /// Maximum value of the product of the `workgroup_size` dimensions for a compute entry-point. - /// Defaults to 256. + /// Defaults to 256. Higher is "better". pub max_compute_invocations_per_workgroup: u32, /// The maximum value of the workgroup_size X dimension for a compute stage `ShaderModule` entry-point. - /// Defaults to 256. + /// Defaults to 256. Higher is "better". pub max_compute_workgroup_size_x: u32, /// The maximum value of the workgroup_size Y dimension for a compute stage `ShaderModule` entry-point. - /// Defaults to 256. + /// Defaults to 256. Higher is "better". pub max_compute_workgroup_size_y: u32, /// The maximum value of the workgroup_size Z dimension for a compute stage `ShaderModule` entry-point. - /// Defaults to 64. + /// Defaults to 64. Higher is "better". pub max_compute_workgroup_size_z: u32, /// The maximum value for each dimension of a `ComputePass::dispatch(x, y, z)` operation. - /// Defaults to 65535. + /// Defaults to 65535. Higher is "better". pub max_compute_workgroups_per_dimension: u32, /// Amount of storage available for push constants in bytes. Defaults to 0. Higher is "better". /// Requesting more than 0 during device creation requires [`Features::PUSH_CONSTANTS`] to be enabled. @@ -942,7 +953,7 @@ impl Default for Limits { max_uniform_buffer_binding_size: 64 << 10, max_storage_buffer_binding_size: 128 << 20, max_vertex_buffers: 8, - max_buffer_size: 1 << 28, + max_buffer_size: 256 << 20, max_vertex_attributes: 16, max_vertex_buffer_array_stride: 2048, min_uniform_buffer_offset_alignment: 256, @@ -961,6 +972,42 @@ impl Default for Limits { impl Limits { /// These default limits are guaranteed to be compatible with GLES-3.1, and D3D11 + /// + /// Those limits are as follows (different from default are marked with *): + /// ```rust + /// # use wgpu_types::Limits; + /// assert_eq!(Limits::downlevel_defaults(), Limits { + /// max_texture_dimension_1d: 2048, // * + /// max_texture_dimension_2d: 2048, // * + /// max_texture_dimension_3d: 256, // * + /// max_texture_array_layers: 256, + /// max_bind_groups: 4, + /// max_bindings_per_bind_group: 1000, + /// max_dynamic_uniform_buffers_per_pipeline_layout: 8, + /// max_dynamic_storage_buffers_per_pipeline_layout: 4, + /// max_sampled_textures_per_shader_stage: 16, + /// max_samplers_per_shader_stage: 16, + /// max_storage_buffers_per_shader_stage: 4, // * + /// max_storage_textures_per_shader_stage: 4, + /// max_uniform_buffers_per_shader_stage: 12, + /// max_uniform_buffer_binding_size: 16 << 10, // * (16 KiB) + /// max_storage_buffer_binding_size: 128 << 20, // (128 MiB) + /// max_vertex_buffers: 8, + /// max_vertex_attributes: 16, + /// max_vertex_buffer_array_stride: 2048, + /// max_push_constant_size: 0, + /// min_uniform_buffer_offset_alignment: 256, + /// min_storage_buffer_offset_alignment: 256, + /// max_inter_stage_shader_components: 60, + /// max_compute_workgroup_storage_size: 16352, + /// max_compute_invocations_per_workgroup: 256, + /// max_compute_workgroup_size_x: 256, + /// max_compute_workgroup_size_y: 256, + /// max_compute_workgroup_size_z: 64, + /// max_compute_workgroups_per_dimension: 65535, + /// max_buffer_size: 256 << 20, // (256 MiB) + /// }); + /// ``` pub fn downlevel_defaults() -> Self { Self { max_texture_dimension_1d: 2048, @@ -991,11 +1038,48 @@ impl Limits { max_compute_workgroup_size_y: 256, max_compute_workgroup_size_z: 64, max_compute_workgroups_per_dimension: 65535, - max_buffer_size: 1 << 28, + max_buffer_size: 256 << 20, } } /// These default limits are guaranteed to be compatible with GLES-3.0, and D3D11, and WebGL2 + /// + /// Those limits are as follows (different from `downlevel_defaults` are marked with +, + /// *'s from `downlevel_defaults` shown as well.): + /// ```rust + /// # use wgpu_types::Limits; + /// assert_eq!(Limits::downlevel_webgl2_defaults(), Limits { + /// max_texture_dimension_1d: 2048, // * + /// max_texture_dimension_2d: 2048, // * + /// max_texture_dimension_3d: 256, // * + /// max_texture_array_layers: 256, + /// max_bind_groups: 4, + /// max_bindings_per_bind_group: 1000, + /// max_dynamic_uniform_buffers_per_pipeline_layout: 8, + /// max_dynamic_storage_buffers_per_pipeline_layout: 0, // + + /// max_sampled_textures_per_shader_stage: 16, + /// max_samplers_per_shader_stage: 16, + /// max_storage_buffers_per_shader_stage: 0, // * + + /// max_storage_textures_per_shader_stage: 0, // + + /// max_uniform_buffers_per_shader_stage: 11, // + + /// max_uniform_buffer_binding_size: 16 << 10, // * (16 KiB) + /// max_storage_buffer_binding_size: 0, // * + + /// max_vertex_buffers: 8, + /// max_vertex_attributes: 16, + /// max_vertex_buffer_array_stride: 255, // + + /// max_push_constant_size: 0, + /// min_uniform_buffer_offset_alignment: 256, + /// min_storage_buffer_offset_alignment: 256, + /// max_inter_stage_shader_components: 60, + /// max_compute_workgroup_storage_size: 0, // + + /// max_compute_invocations_per_workgroup: 0, // + + /// max_compute_workgroup_size_x: 0, // + + /// max_compute_workgroup_size_y: 0, // + + /// max_compute_workgroup_size_z: 0, // + + /// max_compute_workgroups_per_dimension: 0, // + + /// max_buffer_size: 256 << 20, // (256 MiB) + /// }); + /// ``` pub fn downlevel_webgl2_defaults() -> Self { Self { max_uniform_buffers_per_shader_stage: 11,