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