Moving to wgpu 30
pfx moved from wgpu 27.0.1 to wgpu 30.0.1, naga 30 and egui 0.36.2. An app that pins pfx and also uses wgpu or egui directly moves its own pins to the same versions and makes the changes below; an app that only calls pfx’s crates sees the pfx changes at the end. The counts are the sites pfx itself had to change.
Hardware ray queries
Section titled “Hardware ray queries”pfx_gpuasks forwgpu::Features::EXPERIMENTAL_RAY_QUERYwhenever the adapter offers it (Vulkan withVK_KHR_ray_query, DX12 with raytracing tier 1.1, Metal where the device supports ray tracing, which Apple Silicon does even without ray-tracing hardware) and opens the device withwgpu::ExperimentalFeatures::enabled()in that case only.pfx-tracetraces with ray queries over a hardware TLAS when the device has the feature, and with its own BVH otherwise;Trace::hardware_rays()says which.PFX_TRACE_RT=0forces the software path. Both paths draw the same random numbers, so the same seed gives the same picture within float differences at triangle edges.- Analytic shapes (rounded boxes, cones, ellipsoids, capsules, smooth unions) are tested by the shader’s exact loop on both paths. An AABB BLAS for them is behind
PFX_TRACE_RT_BOXES=1and is not yet exact on RADV, which leaves some box candidates unreported. naga 30.0.1’srayQueryGenerateIntersectionvalidity check reads the candidate’s t instead of the committed one, so the trace never generates intersections; it keeps the nearest shape hit itself. - The ray-query trace shader takes the driver several seconds to compile the first time (about 8 s on RADV); the driver’s shader cache keeps it after that.
wgpu 27 -> 30
Section titled “wgpu 27 -> 30”PipelineLayoutDescriptor.bind_group_layoutsis&[Option<&BindGroupLayout>]: wrap every entry inSome(..)(an array of layouts:&layouts.map(Some)). 67 sites (live, physics, post).PipelineLayoutDescriptor.push_constant_rangesis gone, replaced byimmediate_size: u32:push_constant_ranges: &[]->immediate_size: 0. 67 sites (live, physics, post); no crate uses push constants.RenderPipelineDescriptor.multiview->multiview_mask: Option<NonZeroU32>(multiview: None->multiview_mask: None). 33 sites.RenderPassDescriptorgainedmultiview_mask: Option<NonZeroU32>: addmultiview_mask: None. 82 sites.Buffer(Slice)::get_mapped_range()/get_mapped_range_mut()returnResult<_, MapRangeError>:.expect("a mapped range"). 49 sites.BufferViewMutis write-only (no Deref/Index to[u8]):view[a..b].copy_from_slice(x)->view.slice(a..b).copy_from_slice(x); whole bufferview.copy_from_slice(x);.fill(0)->.slice(..).fill(0);bytemuck::cast_slice_mut(&mut view)-> build the bytes first, then copy. Seen in physics (fluid.rs fill x2) and the sites the scripted pass and the first fixes covered.DepthStencilState.depth_write_enabledisOption<bool>anddepth_compareisOption<CompareFunction>: wrap inSome(..). 14 literals (live, post).VertexState.buffersis&[Option<VertexBufferLayout>]: wrap each layout inSome(..); helpers taking&[VertexBufferLayout]take&[Option<VertexBufferLayout>]. 14 literals, 3 helper signatures (live).SamplerDescriptor.mipmap_filteris the newwgpu::MipmapFilterMode(Nearest/Linear), notFilterMode. 13 sites (live); a returned descriptor’s.mipmap_filtercompares againstMipmapFilterModetoo.Instance::newtakesInstanceDescriptorby value andInstanceDescriptorhas noDefault:wgpu::Instance::new(wgpu::InstanceDescriptor { backends, ..wgpu::InstanceDescriptor::new_without_display_handle() }). 8 sites (gpu, live, physics, trace).Instance::enumerate_adaptersis async:pollster::block_on(instance.enumerate_adapters(backends))or.await. 3 sites (gpu, live).RequestAdapterOptionsgainedapply_limit_buckets: bool: setfalsein literals that do not end in..Default::default(). 5 sites (gpu, live, physics).SurfaceConfigurationgainedcolor_space: wgpu::SurfaceColorSpace(Auto). 1 site (gpu).AdapterInfoliterals:..wgpu::AdapterInfo::new(device_type, backend)(the struct is non-exhaustive). gpu tests.Limits.max_storage_buffer_binding_sizeandmax_uniform_buffer_binding_sizeareu64(clippy flagsu64::from(..)around them, remove it). 4 sites (denoise, post, trace).Limits.max_inter_stage_shader_componentsis gone;max_inter_stage_shader_variablescounts vec4 locations, son * 4 <= componentsbecomesn <= variables. 1 site (live test).Surface::get_current_texture()returnswgpu::CurrentSurfaceTexture(notResult<SurfaceTexture, SurfaceError>):Success(frame) | Suboptimal(frame)is the frame,Lost | Outdatedreconfigure,Timeout | Occludedskip the frame,Validationis the error case.wgpu::SurfaceErroris no longer matched here. 2 sites (editor-shell, game).SurfaceTexture::present()moved:queue.present(frame). 2 sites (editor-shell, game).Device::push_error_scope(filter)returns anErrorScopeGuard;device.pop_error_scope()is gone:let scope = device.push_error_scope(..); ... pollster::block_on(scope.pop()). 1 site (live test).
egui / egui-wgpu / epaint 0.33 -> 0.36
Section titled “egui / egui-wgpu / epaint 0.33 -> 0.36”Context::runis gone; useContext::run_ui(input, |ui: &mut Ui| ..). The rootUicovers the viewport with no margin or background; reach the context withui.ctx(). 5 sites (live hud, editor-shell window and offscreen, tests).SidePanelandTopBottomPanelare replaced byegui::Panel::{left,right,top,bottom}(id);Panel::show(ui, ..)andCentralPanel::show(ui, ..)take a&mut Ui, not a&Context.exact_height->exact_size,default_height/default_width->default_size.Panelis resizable by default on every side (the old top/bottom panels were not): add.resizable(false)to keep a fixed bar.Area::show(ctx, ..)is unchanged. About 25 sites (editor, editor-viewport, tests).- pfx-editor-shell
App::uitakes&mut Uiinstead of&Context(so panels can show inside it), anddrive(ctx, size, script, |ui| ..);Editor::uiandSession::uifollow. Apps that implementAppchangefn ui(&mut self, ctx: &Context)tofn ui(&mut self, ui: &mut Ui)and callui.ctx()for the context. RawInput.modifiersis gone: sendEvent::ModifiersChanged(modifiers)as the first event of the frame. 1 site (editor-shell offscreen).Event::MouseWheelgainedphase: TouchPhase(TouchPhase::Movewhen unknown). 2 literals (editor-shell offscreen, editor input test).InputState::raw_scroll_deltais gone (only the smoothedsmooth_scroll_deltaremains): the unsmoothed per-frame sum is rebuilt frominput.events(pfx_editor_viewport::scrolled, withContext::options(|o| o.input_options)forline_scroll_speedand the scroll modifiers). 2 sites (editor, editor-viewport).Context::wants_keyboard_input->egui_wants_keyboard_input. 1 site (editor).Context::style()->global_style()(style_of(theme)unchanged). 4 sites (editor-style, editor-shell test).TexturesDelta.setmaps eachTextureIdto aSmallVec<[ImageDelta; 1]>: loop the deltas and callupdate_texturefor each. 2 sites (live hud, editor-shell paint).Id::new(source)needsHash + Debug: functions takingimpl Hashfor a salt takeimpl Hash + Debug. 2 sites (editor-toml Source::new, editor-viewport Viewport::open).TextEdit::frame(bool)takes aFrame:.frame(false)->.frame(egui::Frame::NONE). 1 site (editor-toml).TextEditOutput.responseis anAtomLayoutResponse(derefs toResponse, does not clone as one): useoutput.response.response.clone()to move aResponse. 1 site (editor-toml).TextEditStatecursorCCursor.indexis aCharIndex(usize)newtype: read.0. 1 site (editor-toml panel).LayoutSection.byte_rangeisRange<ByteIndex>(epaint::text::ByteIndex(usize)): wrap withByteIndex(..). 7 sites (editor-toml job.rs and its tests).Row.ends_with_newlinemoved toPlacedRow.ends_with_newline: set it where thePlacedRowis built, and a cachedArc<Row>is no longer mutated. 3 sites (editor-toml job.rs).ui.data_mut(|d| d.insert_temp(..))andd.remove::<T>(..)now return values of different types, so amatchusing one in each arm needs both closures to end in;. 1 site (editor-style number widget).- A
TexturesDeltathat drops with deltas still in it trips a debug assertion: after painting aFullOutput(or when a test ignores one, such aspfx_editor_shell::drive’s), calloutput.textures_delta.clear().pfx_editor_shell::drivereturns its output with the deltas already cleared (its shot path paints them itself). 4 sites (editor-shell, live hud). - A text field takes focus one pass after the click that focuses it, so a
pfx_editor_shellscript that clicks a field and types needs aframebetween the click and thetext. 1 site (editor-shell shot test). - Collapsing headers and their rows sit about 2 px tighter, so stored editor shots move a little; re-bless them after looking. 1 shot (pfx-editor project-scene-camera).
- egui-wgpu
Renderer::update_textureis perImageDelta(see TexturesDelta).RendererOptions/ScreenDescriptorliterals needed no change.
pfx’s own API
Section titled “pfx’s own API”pfx_editor_shell::App::uitakes&mut egui::Ui(listed with the egui changes above).pfx_trace::gpu::SceneBuffershas anrtfield (the ray-query geometry) andpfx_trace::gpu::shader_rt(lit)returns the ray-query variant of the trace shader.