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
21pub struct Context {
22 options: Arc<wgt::NoopBackendOptions>,
23}
24#[derive(Debug)]
25pub struct Encoder;
26#[derive(Debug)]
27pub struct Resource;
28
29#[derive(Debug)]
30pub struct Fence {
31 value: AtomicU64,
32}
33
34type DeviceResult<T> = Result<T, crate::DeviceError>;
35
36impl crate::Api for Api {
37 const VARIANT: wgt::Backend = wgt::Backend::Noop;
38
39 type Instance = Context;
40 type Surface = Context;
41 type Adapter = Context;
42 type Device = Context;
43
44 type Queue = Context;
45 type CommandEncoder = CommandBuffer;
46 type CommandBuffer = CommandBuffer;
47
48 type Buffer = Buffer;
49 type Texture = Resource;
50 type SurfaceTexture = Resource;
51 type TextureView = Resource;
52 type Sampler = Resource;
53 type QuerySet = Resource;
54 type Fence = Fence;
55 type AccelerationStructure = Resource;
56 type PipelineCache = Resource;
57
58 type BindGroupLayout = Resource;
59 type BindGroup = Resource;
60 type PipelineLayout = Resource;
61 type ShaderModule = Resource;
62 type RenderPipeline = Resource;
63 type ComputePipeline = Resource;
64}
65
66crate::impl_dyn_resource!(Buffer, CommandBuffer, Context, Fence, Resource);
67
68impl crate::DynAccelerationStructure for Resource {}
69impl crate::DynBindGroup for Resource {}
70impl crate::DynBindGroupLayout for Resource {}
71impl crate::DynBuffer for Buffer {}
72impl crate::DynCommandBuffer for CommandBuffer {}
73impl crate::DynComputePipeline for Resource {}
74impl crate::DynFence for Fence {}
75impl crate::DynPipelineCache for Resource {}
76impl crate::DynPipelineLayout for Resource {}
77impl crate::DynQuerySet for Resource {}
78impl crate::DynRenderPipeline 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 },
182 downlevel: wgt::DownlevelCapabilities {
183 flags: wgt::DownlevelFlags::all(),
184 limits: wgt::DownlevelLimits {},
185 shader_model: wgt::ShaderModel::Sm5,
186 },
187 cooperative_matrix_properties: Vec::new(),
188 }
189};
190
191impl crate::Surface for Context {
192 type A = Api;
193
194 unsafe fn configure(
195 &self,
196 device: &Context,
197 config: &crate::SurfaceConfiguration,
198 ) -> Result<(), crate::SurfaceError> {
199 Ok(())
200 }
201
202 unsafe fn unconfigure(&self, device: &Context) {}
203
204 unsafe fn acquire_texture(
205 &self,
206 _timeout: Option<Duration>,
207 _fence: &Fence,
208 ) -> Result<crate::AcquiredSurfaceTexture<Api>, crate::SurfaceError> {
209 Err(crate::SurfaceError::Timeout)
210 }
211 unsafe fn discard_texture(&self, texture: Resource) {}
212}
213
214impl crate::Adapter for Context {
215 type A = Api;
216
217 unsafe fn open(
218 &self,
219 features: wgt::Features,
220 _limits: &wgt::Limits,
221 _memory_hints: &wgt::MemoryHints,
222 ) -> DeviceResult<crate::OpenDevice<Api>> {
223 Ok(crate::OpenDevice {
224 device: Context {
225 options: Arc::clone(&self.options),
226 },
227 queue: Context {
228 options: Arc::clone(&self.options),
229 },
230 })
231 }
232 unsafe fn texture_format_capabilities(
233 &self,
234 format: wgt::TextureFormat,
235 ) -> crate::TextureFormatCapabilities {
236 crate::TextureFormatCapabilities::empty()
237 }
238
239 unsafe fn surface_capabilities(&self, surface: &Context) -> Option<crate::SurfaceCapabilities> {
240 None
241 }
242
243 unsafe fn get_presentation_timestamp(&self) -> wgt::PresentationTimestamp {
244 wgt::PresentationTimestamp::INVALID_TIMESTAMP
245 }
246
247 fn get_ordered_buffer_usages(&self) -> wgt::BufferUses {
248 wgt::BufferUses::INCLUSIVE | wgt::BufferUses::MAP_WRITE
249 }
250
251 fn get_ordered_texture_usages(&self) -> wgt::TextureUses {
252 wgt::TextureUses::INCLUSIVE
253 | wgt::TextureUses::COLOR_TARGET
254 | wgt::TextureUses::DEPTH_STENCIL_WRITE
255 }
256}
257
258impl crate::Queue for Context {
259 type A = Api;
260
261 unsafe fn submit(
262 &self,
263 command_buffers: &[&CommandBuffer],
264 surface_textures: &[&Resource],
265 (fence, fence_value): (&mut Fence, crate::FenceValue),
266 ) -> DeviceResult<()> {
267 for cb in command_buffers {
269 unsafe {
272 cb.execute();
273 }
274 }
275 fence.value.store(fence_value, Ordering::Release);
276 Ok(())
277 }
278 unsafe fn present(
279 &self,
280 surface: &Context,
281 texture: Resource,
282 ) -> Result<(), crate::SurfaceError> {
283 Ok(())
284 }
285
286 unsafe fn get_timestamp_period(&self) -> f32 {
287 1.0
288 }
289}
290
291impl crate::Device for Context {
292 type A = Api;
293
294 unsafe fn create_buffer(&self, desc: &crate::BufferDescriptor) -> DeviceResult<Buffer> {
295 Buffer::new(desc)
296 }
297
298 unsafe fn destroy_buffer(&self, buffer: Buffer) {}
299 unsafe fn add_raw_buffer(&self, _buffer: &Buffer) {}
300
301 unsafe fn map_buffer(
302 &self,
303 buffer: &Buffer,
304 range: crate::MemoryRange,
305 ) -> DeviceResult<crate::BufferMapping> {
306 Ok(crate::BufferMapping {
310 ptr: ptr::NonNull::new(buffer.get_slice_ptr(range).cast::<u8>()).unwrap(),
311 is_coherent: true,
312 })
313 }
314 unsafe fn unmap_buffer(&self, buffer: &Buffer) {}
315 unsafe fn flush_mapped_ranges<I>(&self, buffer: &Buffer, ranges: I) {}
316 unsafe fn invalidate_mapped_ranges<I>(&self, buffer: &Buffer, ranges: I) {}
317
318 unsafe fn create_texture(&self, desc: &crate::TextureDescriptor) -> DeviceResult<Resource> {
319 Ok(Resource)
320 }
321 unsafe fn destroy_texture(&self, texture: Resource) {}
322 unsafe fn add_raw_texture(&self, _texture: &Resource) {}
323
324 unsafe fn create_texture_view(
325 &self,
326 texture: &Resource,
327 desc: &crate::TextureViewDescriptor,
328 ) -> DeviceResult<Resource> {
329 Ok(Resource)
330 }
331 unsafe fn destroy_texture_view(&self, view: Resource) {}
332 unsafe fn create_sampler(&self, desc: &crate::SamplerDescriptor) -> DeviceResult<Resource> {
333 Ok(Resource)
334 }
335 unsafe fn destroy_sampler(&self, sampler: Resource) {}
336
337 unsafe fn create_command_encoder(
338 &self,
339 desc: &crate::CommandEncoderDescriptor<Context>,
340 ) -> DeviceResult<CommandBuffer> {
341 Ok(CommandBuffer::new())
342 }
343
344 unsafe fn create_bind_group_layout(
345 &self,
346 desc: &crate::BindGroupLayoutDescriptor,
347 ) -> DeviceResult<Resource> {
348 Ok(Resource)
349 }
350 unsafe fn destroy_bind_group_layout(&self, bg_layout: Resource) {}
351 unsafe fn create_pipeline_layout(
352 &self,
353 desc: &crate::PipelineLayoutDescriptor<Resource>,
354 ) -> DeviceResult<Resource> {
355 Ok(Resource)
356 }
357 unsafe fn destroy_pipeline_layout(&self, pipeline_layout: Resource) {}
358 unsafe fn create_bind_group(
359 &self,
360 desc: &crate::BindGroupDescriptor<Resource, Buffer, Resource, Resource, Resource>,
361 ) -> DeviceResult<Resource> {
362 Ok(Resource)
363 }
364 unsafe fn destroy_bind_group(&self, group: Resource) {}
365
366 unsafe fn create_shader_module(
367 &self,
368 desc: &crate::ShaderModuleDescriptor,
369 shader: crate::ShaderInput,
370 ) -> Result<Resource, crate::ShaderError> {
371 Ok(Resource)
372 }
373 unsafe fn destroy_shader_module(&self, module: Resource) {}
374 unsafe fn create_render_pipeline(
375 &self,
376 desc: &crate::RenderPipelineDescriptor<Resource, Resource, Resource>,
377 ) -> Result<Resource, crate::PipelineError> {
378 Ok(Resource)
379 }
380 unsafe fn destroy_render_pipeline(&self, pipeline: Resource) {}
381 unsafe fn create_compute_pipeline(
382 &self,
383 desc: &crate::ComputePipelineDescriptor<Resource, Resource, Resource>,
384 ) -> Result<Resource, crate::PipelineError> {
385 Ok(Resource)
386 }
387 unsafe fn destroy_compute_pipeline(&self, pipeline: Resource) {}
388 unsafe fn create_pipeline_cache(
389 &self,
390 desc: &crate::PipelineCacheDescriptor<'_>,
391 ) -> Result<Resource, crate::PipelineCacheError> {
392 Ok(Resource)
393 }
394 unsafe fn destroy_pipeline_cache(&self, cache: Resource) {}
395
396 unsafe fn create_query_set(
397 &self,
398 desc: &wgt::QuerySetDescriptor<crate::Label>,
399 ) -> DeviceResult<Resource> {
400 Ok(Resource)
401 }
402 unsafe fn destroy_query_set(&self, set: Resource) {}
403 unsafe fn create_fence(&self) -> DeviceResult<Fence> {
404 Ok(Fence {
405 value: AtomicU64::new(0),
406 })
407 }
408 unsafe fn destroy_fence(&self, fence: Fence) {}
409 unsafe fn get_fence_value(&self, fence: &Fence) -> DeviceResult<crate::FenceValue> {
410 Ok(fence.value.load(Ordering::Acquire))
411 }
412 unsafe fn wait(
413 &self,
414 fence: &Fence,
415 value: crate::FenceValue,
416 timeout: Option<Duration>,
417 ) -> DeviceResult<bool> {
418 assert!(
422 fence.value.load(Ordering::Acquire) >= value,
423 "submission must have already been done"
424 );
425 Ok(true)
426 }
427
428 unsafe fn start_graphics_debugger_capture(&self) -> bool {
429 false
430 }
431 unsafe fn stop_graphics_debugger_capture(&self) {}
432 unsafe fn create_acceleration_structure(
433 &self,
434 desc: &crate::AccelerationStructureDescriptor,
435 ) -> DeviceResult<Resource> {
436 Ok(Resource)
437 }
438 unsafe fn get_acceleration_structure_build_sizes<'a>(
439 &self,
440 _desc: &crate::GetAccelerationStructureBuildSizesDescriptor<'a, Buffer>,
441 ) -> crate::AccelerationStructureBuildSizes {
442 Default::default()
443 }
444 unsafe fn get_acceleration_structure_device_address(
445 &self,
446 _acceleration_structure: &Resource,
447 ) -> wgt::BufferAddress {
448 Default::default()
449 }
450 unsafe fn destroy_acceleration_structure(&self, _acceleration_structure: Resource) {}
451
452 fn tlas_instance_to_bytes(&self, instance: TlasInstance) -> Vec<u8> {
453 vec![]
454 }
455
456 fn get_internal_counters(&self) -> wgt::HalCounters {
457 Default::default()
458 }
459
460 fn check_if_oom(&self) -> DeviceResult<()> {
461 Ok(())
462 }
463}