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