1#![allow(unused_variables)]
2
3use alloc::{string::String, vec, vec::Vec};
4use core::{ptr, sync::atomic::Ordering, time::Duration};
5
6#[cfg(supports_64bit_atomics)]
7use core::sync::atomic::AtomicU64;
8#[cfg(not(supports_64bit_atomics))]
9use portable_atomic::AtomicU64;
10
11use crate::TlasInstance;
12
13mod buffer;
14pub use buffer::Buffer;
15mod command;
16pub use command::CommandBuffer;
17
18#[derive(Clone, Debug)]
19pub struct Api;
20pub struct Context;
21#[derive(Debug)]
22pub struct Encoder;
23#[derive(Debug)]
24pub struct Resource;
25
26#[derive(Debug)]
27pub struct Fence {
28 value: AtomicU64,
29}
30
31type DeviceResult<T> = Result<T, crate::DeviceError>;
32
33impl crate::Api for Api {
34 const VARIANT: wgt::Backend = wgt::Backend::Noop;
35
36 type Instance = Context;
37 type Surface = Context;
38 type Adapter = Context;
39 type Device = Context;
40
41 type Queue = Context;
42 type CommandEncoder = CommandBuffer;
43 type CommandBuffer = CommandBuffer;
44
45 type Buffer = Buffer;
46 type Texture = Resource;
47 type SurfaceTexture = Resource;
48 type TextureView = Resource;
49 type Sampler = Resource;
50 type QuerySet = Resource;
51 type Fence = Fence;
52 type AccelerationStructure = Resource;
53 type PipelineCache = Resource;
54
55 type BindGroupLayout = Resource;
56 type BindGroup = Resource;
57 type PipelineLayout = Resource;
58 type ShaderModule = Resource;
59 type RenderPipeline = Resource;
60 type ComputePipeline = Resource;
61}
62
63crate::impl_dyn_resource!(Buffer, CommandBuffer, Context, Fence, Resource);
64
65impl crate::DynAccelerationStructure for Resource {}
66impl crate::DynBindGroup for Resource {}
67impl crate::DynBindGroupLayout for Resource {}
68impl crate::DynBuffer for Buffer {}
69impl crate::DynCommandBuffer for CommandBuffer {}
70impl crate::DynComputePipeline for Resource {}
71impl crate::DynFence for Fence {}
72impl crate::DynPipelineCache for Resource {}
73impl crate::DynPipelineLayout for Resource {}
74impl crate::DynQuerySet for Resource {}
75impl crate::DynRenderPipeline for Resource {}
76impl crate::DynSampler for Resource {}
77impl crate::DynShaderModule for Resource {}
78impl crate::DynSurfaceTexture for Resource {}
79impl crate::DynTexture for Resource {}
80impl crate::DynTextureView for Resource {}
81
82impl core::borrow::Borrow<dyn crate::DynTexture> for Resource {
83 fn borrow(&self) -> &dyn crate::DynTexture {
84 self
85 }
86}
87
88impl crate::Instance for Context {
89 type A = Api;
90
91 unsafe fn init(desc: &crate::InstanceDescriptor<'_>) -> Result<Self, crate::InstanceError> {
92 let crate::InstanceDescriptor {
93 backend_options:
94 wgt::BackendOptions {
95 noop: wgt::NoopBackendOptions { enable },
96 ..
97 },
98 name: _,
99 flags: _,
100 memory_budget_thresholds: _,
101 telemetry: _,
102 display: _,
103 } = *desc;
104 if enable {
105 Ok(Context)
106 } else {
107 Err(crate::InstanceError::new(String::from(
108 "noop backend disabled because NoopBackendOptions::enable is false",
109 )))
110 }
111 }
112 unsafe fn create_surface(
113 &self,
114 _display_handle: raw_window_handle::RawDisplayHandle,
115 _window_handle: raw_window_handle::RawWindowHandle,
116 ) -> Result<Context, crate::InstanceError> {
117 Ok(Context)
118 }
119 unsafe fn enumerate_adapters(
120 &self,
121 _surface_hint: Option<&Context>,
122 ) -> Vec<crate::ExposedAdapter<Api>> {
123 vec![crate::ExposedAdapter {
124 adapter: Context,
125 info: adapter_info(),
126 features: wgt::Features::all(),
127 capabilities: CAPABILITIES,
128 }]
129 }
130}
131
132pub fn adapter_info() -> wgt::AdapterInfo {
137 wgt::AdapterInfo {
138 name: String::from("noop wgpu backend"),
139 vendor: 0,
140 device: 0,
141 device_type: wgt::DeviceType::Cpu,
142 device_pci_bus_id: String::new(),
143 driver: String::from("wgpu"),
144 driver_info: String::new(),
145 backend: wgt::Backend::Noop,
146 subgroup_min_size: wgt::MINIMUM_SUBGROUP_MIN_SIZE,
147 subgroup_max_size: wgt::MAXIMUM_SUBGROUP_MAX_SIZE,
148 transient_saves_memory: false,
149 }
150}
151
152pub const CAPABILITIES: crate::Capabilities = {
157 const ALLOC_MAX_U32: u32 = i32::MAX as u32;
160 const ALLOC_MAX_U64: u64 = i32::MAX as u64;
163
164 crate::Capabilities {
165 limits: wgt::Limits {
166 max_texture_dimension_1d: ALLOC_MAX_U32,
168 max_texture_dimension_2d: ALLOC_MAX_U32,
169 max_texture_dimension_3d: ALLOC_MAX_U32,
170 max_texture_array_layers: ALLOC_MAX_U32,
171 max_bind_groups: ALLOC_MAX_U32,
172 max_bindings_per_bind_group: ALLOC_MAX_U32,
173 max_dynamic_uniform_buffers_per_pipeline_layout: ALLOC_MAX_U32,
174 max_dynamic_storage_buffers_per_pipeline_layout: ALLOC_MAX_U32,
175 max_sampled_textures_per_shader_stage: ALLOC_MAX_U32,
176 max_samplers_per_shader_stage: ALLOC_MAX_U32,
177 max_storage_buffers_per_shader_stage: ALLOC_MAX_U32,
178 max_storage_textures_per_shader_stage: ALLOC_MAX_U32,
179 max_uniform_buffers_per_shader_stage: ALLOC_MAX_U32,
180 max_binding_array_elements_per_shader_stage: ALLOC_MAX_U32,
181 max_binding_array_sampler_elements_per_shader_stage: ALLOC_MAX_U32,
182 max_binding_array_acceleration_structure_elements_per_shader_stage: ALLOC_MAX_U32,
183 max_uniform_buffer_binding_size: ALLOC_MAX_U64,
184 max_storage_buffer_binding_size: ALLOC_MAX_U64,
185 max_vertex_buffers: ALLOC_MAX_U32,
186 max_buffer_size: ALLOC_MAX_U64,
187 max_vertex_attributes: ALLOC_MAX_U32,
188 max_vertex_buffer_array_stride: ALLOC_MAX_U32,
189 max_inter_stage_shader_variables: ALLOC_MAX_U32,
190 min_uniform_buffer_offset_alignment: 1,
191 min_storage_buffer_offset_alignment: 1,
192 max_color_attachments: ALLOC_MAX_U32,
193 max_color_attachment_bytes_per_sample: ALLOC_MAX_U32,
194 max_compute_workgroup_storage_size: ALLOC_MAX_U32,
195 max_compute_invocations_per_workgroup: ALLOC_MAX_U32,
196 max_compute_workgroup_size_x: ALLOC_MAX_U32,
197 max_compute_workgroup_size_y: ALLOC_MAX_U32,
198 max_compute_workgroup_size_z: ALLOC_MAX_U32,
199 max_compute_workgroups_per_dimension: ALLOC_MAX_U32,
200 max_immediate_size: ALLOC_MAX_U32,
201 max_non_sampler_bindings: ALLOC_MAX_U32,
202
203 max_task_mesh_workgroup_total_count: ALLOC_MAX_U32,
204 max_task_mesh_workgroups_per_dimension: ALLOC_MAX_U32,
205 max_task_invocations_per_workgroup: ALLOC_MAX_U32,
206 max_task_invocations_per_dimension: ALLOC_MAX_U32,
207 max_mesh_invocations_per_workgroup: ALLOC_MAX_U32,
208 max_mesh_invocations_per_dimension: ALLOC_MAX_U32,
209 max_task_payload_size: ALLOC_MAX_U32,
210 max_mesh_output_vertices: ALLOC_MAX_U32,
211 max_mesh_output_primitives: ALLOC_MAX_U32,
212 max_mesh_output_layers: ALLOC_MAX_U32,
213 max_mesh_multiview_view_count: ALLOC_MAX_U32,
214
215 max_blas_primitive_count: ALLOC_MAX_U32,
216 max_blas_geometry_count: ALLOC_MAX_U32,
217 max_tlas_instance_count: ALLOC_MAX_U32,
218 max_acceleration_structures_per_shader_stage: ALLOC_MAX_U32,
219
220 max_multiview_view_count: ALLOC_MAX_U32,
221 },
222 alignments: crate::Alignments {
223 buffer_copy_offset: wgt::BufferSize::MIN,
225 buffer_copy_pitch: wgt::BufferSize::MIN,
226 uniform_bounds_check_alignment: wgt::BufferSize::MIN,
227 raw_tlas_instance_size: 0,
228 ray_tracing_scratch_buffer_alignment: 1,
229 },
230 downlevel: wgt::DownlevelCapabilities {
231 flags: wgt::DownlevelFlags::all(),
232 limits: wgt::DownlevelLimits {},
233 shader_model: wgt::ShaderModel::Sm5,
234 },
235 cooperative_matrix_properties: Vec::new(),
236 }
237};
238
239impl crate::Surface for Context {
240 type A = Api;
241
242 unsafe fn configure(
243 &self,
244 device: &Context,
245 config: &crate::SurfaceConfiguration,
246 ) -> Result<(), crate::SurfaceError> {
247 Ok(())
248 }
249
250 unsafe fn unconfigure(&self, device: &Context) {}
251
252 unsafe fn acquire_texture(
253 &self,
254 _timeout: Option<Duration>,
255 _fence: &Fence,
256 ) -> Result<crate::AcquiredSurfaceTexture<Api>, crate::SurfaceError> {
257 Err(crate::SurfaceError::Timeout)
258 }
259 unsafe fn discard_texture(&self, texture: Resource) {}
260}
261
262impl crate::Adapter for Context {
263 type A = Api;
264
265 unsafe fn open(
266 &self,
267 features: wgt::Features,
268 _limits: &wgt::Limits,
269 _memory_hints: &wgt::MemoryHints,
270 ) -> DeviceResult<crate::OpenDevice<Api>> {
271 Ok(crate::OpenDevice {
272 device: Context,
273 queue: Context,
274 })
275 }
276 unsafe fn texture_format_capabilities(
277 &self,
278 format: wgt::TextureFormat,
279 ) -> crate::TextureFormatCapabilities {
280 crate::TextureFormatCapabilities::empty()
281 }
282
283 unsafe fn surface_capabilities(&self, surface: &Context) -> Option<crate::SurfaceCapabilities> {
284 None
285 }
286
287 unsafe fn get_presentation_timestamp(&self) -> wgt::PresentationTimestamp {
288 wgt::PresentationTimestamp::INVALID_TIMESTAMP
289 }
290
291 fn get_ordered_buffer_usages(&self) -> wgt::BufferUses {
292 wgt::BufferUses::INCLUSIVE | wgt::BufferUses::MAP_WRITE
293 }
294
295 fn get_ordered_texture_usages(&self) -> wgt::TextureUses {
296 wgt::TextureUses::INCLUSIVE
297 | wgt::TextureUses::COLOR_TARGET
298 | wgt::TextureUses::DEPTH_STENCIL_WRITE
299 }
300}
301
302impl crate::Queue for Context {
303 type A = Api;
304
305 unsafe fn submit(
306 &self,
307 command_buffers: &[&CommandBuffer],
308 surface_textures: &[&Resource],
309 (fence, fence_value): (&mut Fence, crate::FenceValue),
310 ) -> DeviceResult<()> {
311 for cb in command_buffers {
313 unsafe {
316 cb.execute();
317 }
318 }
319 fence.value.store(fence_value, Ordering::Release);
320 Ok(())
321 }
322 unsafe fn present(
323 &self,
324 surface: &Context,
325 texture: Resource,
326 ) -> Result<(), crate::SurfaceError> {
327 Ok(())
328 }
329
330 unsafe fn get_timestamp_period(&self) -> f32 {
331 1.0
332 }
333}
334
335impl crate::Device for Context {
336 type A = Api;
337
338 unsafe fn create_buffer(&self, desc: &crate::BufferDescriptor) -> DeviceResult<Buffer> {
339 Buffer::new(desc)
340 }
341
342 unsafe fn destroy_buffer(&self, buffer: Buffer) {}
343 unsafe fn add_raw_buffer(&self, _buffer: &Buffer) {}
344
345 unsafe fn map_buffer(
346 &self,
347 buffer: &Buffer,
348 range: crate::MemoryRange,
349 ) -> DeviceResult<crate::BufferMapping> {
350 Ok(crate::BufferMapping {
354 ptr: ptr::NonNull::new(buffer.get_slice_ptr(range).cast::<u8>()).unwrap(),
355 is_coherent: true,
356 })
357 }
358 unsafe fn unmap_buffer(&self, buffer: &Buffer) {}
359 unsafe fn flush_mapped_ranges<I>(&self, buffer: &Buffer, ranges: I) {}
360 unsafe fn invalidate_mapped_ranges<I>(&self, buffer: &Buffer, ranges: I) {}
361
362 unsafe fn create_texture(&self, desc: &crate::TextureDescriptor) -> DeviceResult<Resource> {
363 Ok(Resource)
364 }
365 unsafe fn destroy_texture(&self, texture: Resource) {}
366 unsafe fn add_raw_texture(&self, _texture: &Resource) {}
367
368 unsafe fn create_texture_view(
369 &self,
370 texture: &Resource,
371 desc: &crate::TextureViewDescriptor,
372 ) -> DeviceResult<Resource> {
373 Ok(Resource)
374 }
375 unsafe fn destroy_texture_view(&self, view: Resource) {}
376 unsafe fn create_sampler(&self, desc: &crate::SamplerDescriptor) -> DeviceResult<Resource> {
377 Ok(Resource)
378 }
379 unsafe fn destroy_sampler(&self, sampler: Resource) {}
380
381 unsafe fn create_command_encoder(
382 &self,
383 desc: &crate::CommandEncoderDescriptor<Context>,
384 ) -> DeviceResult<CommandBuffer> {
385 Ok(CommandBuffer::new())
386 }
387
388 unsafe fn create_bind_group_layout(
389 &self,
390 desc: &crate::BindGroupLayoutDescriptor,
391 ) -> DeviceResult<Resource> {
392 Ok(Resource)
393 }
394 unsafe fn destroy_bind_group_layout(&self, bg_layout: Resource) {}
395 unsafe fn create_pipeline_layout(
396 &self,
397 desc: &crate::PipelineLayoutDescriptor<Resource>,
398 ) -> DeviceResult<Resource> {
399 Ok(Resource)
400 }
401 unsafe fn destroy_pipeline_layout(&self, pipeline_layout: Resource) {}
402 unsafe fn create_bind_group(
403 &self,
404 desc: &crate::BindGroupDescriptor<Resource, Buffer, Resource, Resource, Resource>,
405 ) -> DeviceResult<Resource> {
406 Ok(Resource)
407 }
408 unsafe fn destroy_bind_group(&self, group: Resource) {}
409
410 unsafe fn create_shader_module(
411 &self,
412 desc: &crate::ShaderModuleDescriptor,
413 shader: crate::ShaderInput,
414 ) -> Result<Resource, crate::ShaderError> {
415 Ok(Resource)
416 }
417 unsafe fn destroy_shader_module(&self, module: Resource) {}
418 unsafe fn create_render_pipeline(
419 &self,
420 desc: &crate::RenderPipelineDescriptor<Resource, Resource, Resource>,
421 ) -> Result<Resource, crate::PipelineError> {
422 Ok(Resource)
423 }
424 unsafe fn destroy_render_pipeline(&self, pipeline: Resource) {}
425 unsafe fn create_compute_pipeline(
426 &self,
427 desc: &crate::ComputePipelineDescriptor<Resource, Resource, Resource>,
428 ) -> Result<Resource, crate::PipelineError> {
429 Ok(Resource)
430 }
431 unsafe fn destroy_compute_pipeline(&self, pipeline: Resource) {}
432 unsafe fn create_pipeline_cache(
433 &self,
434 desc: &crate::PipelineCacheDescriptor<'_>,
435 ) -> Result<Resource, crate::PipelineCacheError> {
436 Ok(Resource)
437 }
438 unsafe fn destroy_pipeline_cache(&self, cache: Resource) {}
439
440 unsafe fn create_query_set(
441 &self,
442 desc: &wgt::QuerySetDescriptor<crate::Label>,
443 ) -> DeviceResult<Resource> {
444 Ok(Resource)
445 }
446 unsafe fn destroy_query_set(&self, set: Resource) {}
447 unsafe fn create_fence(&self) -> DeviceResult<Fence> {
448 Ok(Fence {
449 value: AtomicU64::new(0),
450 })
451 }
452 unsafe fn destroy_fence(&self, fence: Fence) {}
453 unsafe fn get_fence_value(&self, fence: &Fence) -> DeviceResult<crate::FenceValue> {
454 Ok(fence.value.load(Ordering::Acquire))
455 }
456 unsafe fn wait(
457 &self,
458 fence: &Fence,
459 value: crate::FenceValue,
460 timeout: Option<Duration>,
461 ) -> DeviceResult<bool> {
462 assert!(
466 fence.value.load(Ordering::Acquire) >= value,
467 "submission must have already been done"
468 );
469 Ok(true)
470 }
471
472 unsafe fn start_graphics_debugger_capture(&self) -> bool {
473 false
474 }
475 unsafe fn stop_graphics_debugger_capture(&self) {}
476 unsafe fn create_acceleration_structure(
477 &self,
478 desc: &crate::AccelerationStructureDescriptor,
479 ) -> DeviceResult<Resource> {
480 Ok(Resource)
481 }
482 unsafe fn get_acceleration_structure_build_sizes<'a>(
483 &self,
484 _desc: &crate::GetAccelerationStructureBuildSizesDescriptor<'a, Buffer>,
485 ) -> crate::AccelerationStructureBuildSizes {
486 Default::default()
487 }
488 unsafe fn get_acceleration_structure_device_address(
489 &self,
490 _acceleration_structure: &Resource,
491 ) -> wgt::BufferAddress {
492 Default::default()
493 }
494 unsafe fn destroy_acceleration_structure(&self, _acceleration_structure: Resource) {}
495
496 fn tlas_instance_to_bytes(&self, instance: TlasInstance) -> Vec<u8> {
497 vec![]
498 }
499
500 fn get_internal_counters(&self) -> wgt::HalCounters {
501 Default::default()
502 }
503
504 fn check_if_oom(&self) -> DeviceResult<()> {
505 Ok(())
506 }
507}