1#[cfg(not(any(windows, webgl)))]
86mod egl;
87#[cfg(Emscripten)]
88mod emscripten;
89#[cfg(webgl)]
90mod web;
91#[cfg(windows)]
92mod wgl;
93
94mod adapter;
95mod command;
96mod conv;
97mod device;
98mod queue;
99
100use crate::{CopyExtent, TextureDescriptor};
101
102#[cfg(not(any(windows, webgl)))]
103pub use self::egl::{AdapterContext, AdapterContextLock};
104#[cfg(not(any(windows, webgl)))]
105use self::egl::{Instance, Surface};
106
107#[cfg(webgl)]
108pub use self::web::AdapterContext;
109#[cfg(webgl)]
110use self::web::{Instance, Surface};
111
112#[cfg(windows)]
113use self::wgl::AdapterContext;
114#[cfg(windows)]
115use self::wgl::{Instance, Surface};
116
117use arrayvec::ArrayVec;
118
119use glow::HasContext;
120
121use naga::FastHashMap;
122use parking_lot::Mutex;
123use std::sync::atomic::{AtomicU32, AtomicU8, Ordering};
124use std::{fmt, ops::Range, sync::Arc};
125
126#[derive(Clone, Debug)]
127pub struct Api;
128
129const MAX_TEXTURE_SLOTS: usize = 16;
132const MAX_SAMPLERS: usize = 16;
133const MAX_VERTEX_ATTRIBUTES: usize = 16;
134const ZERO_BUFFER_SIZE: usize = 256 << 10;
135const MAX_PUSH_CONSTANTS: usize = 64;
136const MAX_PUSH_CONSTANT_COMMANDS: usize = MAX_PUSH_CONSTANTS * crate::MAX_CONCURRENT_SHADER_STAGES;
138
139impl crate::Api for Api {
140 type Instance = Instance;
141 type Surface = Surface;
142 type Adapter = Adapter;
143 type Device = Device;
144
145 type Queue = Queue;
146 type CommandEncoder = CommandEncoder;
147 type CommandBuffer = CommandBuffer;
148
149 type Buffer = Buffer;
150 type Texture = Texture;
151 type SurfaceTexture = Texture;
152 type TextureView = TextureView;
153 type Sampler = Sampler;
154 type QuerySet = QuerySet;
155 type Fence = Fence;
156 type AccelerationStructure = AccelerationStructure;
157 type PipelineCache = PipelineCache;
158
159 type BindGroupLayout = BindGroupLayout;
160 type BindGroup = BindGroup;
161 type PipelineLayout = PipelineLayout;
162 type ShaderModule = ShaderModule;
163 type RenderPipeline = RenderPipeline;
164 type ComputePipeline = ComputePipeline;
165}
166
167crate::impl_dyn_resource!(
168 Adapter,
169 AccelerationStructure,
170 BindGroup,
171 BindGroupLayout,
172 Buffer,
173 CommandBuffer,
174 CommandEncoder,
175 ComputePipeline,
176 Device,
177 Fence,
178 Instance,
179 PipelineCache,
180 PipelineLayout,
181 QuerySet,
182 Queue,
183 RenderPipeline,
184 Sampler,
185 ShaderModule,
186 Surface,
187 Texture,
188 TextureView
189);
190
191bitflags::bitflags! {
192 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
195 struct PrivateCapabilities: u32 {
196 const BUFFER_ALLOCATION = 1 << 0;
198 const SHADER_BINDING_LAYOUT = 1 << 1;
200 const SHADER_TEXTURE_SHADOW_LOD = 1 << 2;
202 const MEMORY_BARRIERS = 1 << 3;
204 const VERTEX_BUFFER_LAYOUT = 1 << 4;
206 const INDEX_BUFFER_ROLE_CHANGE = 1 << 5;
209 const GET_BUFFER_SUB_DATA = 1 << 7;
211 const COLOR_BUFFER_HALF_FLOAT = 1 << 8;
213 const COLOR_BUFFER_FLOAT = 1 << 9;
215 const QUERY_BUFFERS = 1 << 11;
217 const QUERY_64BIT = 1 << 12;
219 const TEXTURE_STORAGE = 1 << 13;
221 const DEBUG_FNS = 1 << 14;
223 const INVALIDATE_FRAMEBUFFER = 1 << 15;
225 const FULLY_FEATURED_INSTANCING = 1 << 16;
229 }
230}
231
232bitflags::bitflags! {
233 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
235 struct Workarounds: u32 {
236 const MESA_I915_SRGB_SHADER_CLEAR = 1 << 0;
243 const EMULATE_BUFFER_MAP = 1 << 1;
245 }
246}
247
248type BindTarget = u32;
249
250#[derive(Debug, Clone, Copy)]
251enum VertexAttribKind {
252 Float, Integer, }
256
257impl Default for VertexAttribKind {
258 fn default() -> Self {
259 Self::Float
260 }
261}
262
263#[derive(Clone, Debug)]
264pub struct TextureFormatDesc {
265 pub internal: u32,
266 pub external: u32,
267 pub data_type: u32,
268}
269
270struct AdapterShared {
271 context: AdapterContext,
272 private_caps: PrivateCapabilities,
273 features: wgt::Features,
274 workarounds: Workarounds,
275 shading_language_version: naga::back::glsl::Version,
276 next_shader_id: AtomicU32,
277 program_cache: Mutex<ProgramCache>,
278 es: bool,
279
280 max_msaa_samples: i32,
284}
285
286pub struct Adapter {
287 shared: Arc<AdapterShared>,
288}
289
290pub struct Device {
291 shared: Arc<AdapterShared>,
292 main_vao: glow::VertexArray,
293 #[cfg(all(native, feature = "renderdoc"))]
294 render_doc: crate::auxil::renderdoc::RenderDoc,
295 counters: wgt::HalCounters,
296}
297
298pub struct ShaderClearProgram {
299 pub program: glow::Program,
300 pub color_uniform_location: glow::UniformLocation,
301}
302
303pub struct Queue {
304 shared: Arc<AdapterShared>,
305 features: wgt::Features,
306 draw_fbo: glow::Framebuffer,
307 copy_fbo: glow::Framebuffer,
308 shader_clear_program: Option<ShaderClearProgram>,
311 zero_buffer: glow::Buffer,
314 temp_query_results: Mutex<Vec<u64>>,
315 draw_buffer_count: AtomicU8,
316 current_index_buffer: Mutex<Option<glow::Buffer>>,
317}
318
319#[derive(Clone, Debug)]
320pub struct Buffer {
321 raw: Option<glow::Buffer>,
322 target: BindTarget,
323 size: wgt::BufferAddress,
324 map_flags: u32,
325 data: Option<Arc<std::sync::Mutex<Vec<u8>>>>,
326 offset_of_current_mapping: Arc<std::sync::Mutex<wgt::BufferAddress>>,
327}
328
329#[cfg(send_sync)]
330unsafe impl Sync for Buffer {}
331#[cfg(send_sync)]
332unsafe impl Send for Buffer {}
333
334impl crate::DynBuffer for Buffer {}
335
336#[derive(Clone, Debug)]
337pub enum TextureInner {
338 Renderbuffer {
339 raw: glow::Renderbuffer,
340 },
341 DefaultRenderbuffer,
342 Texture {
343 raw: glow::Texture,
344 target: BindTarget,
345 },
346 #[cfg(webgl)]
347 ExternalFramebuffer {
348 inner: web_sys::WebGlFramebuffer,
349 },
350}
351
352#[cfg(send_sync)]
353unsafe impl Sync for TextureInner {}
354#[cfg(send_sync)]
355unsafe impl Send for TextureInner {}
356
357impl TextureInner {
358 fn as_native(&self) -> (glow::Texture, BindTarget) {
359 match *self {
360 Self::Renderbuffer { .. } | Self::DefaultRenderbuffer => {
361 panic!("Unexpected renderbuffer");
362 }
363 Self::Texture { raw, target } => (raw, target),
364 #[cfg(webgl)]
365 Self::ExternalFramebuffer { .. } => panic!("Unexpected external framebuffer"),
366 }
367 }
368}
369
370#[derive(Debug)]
371pub struct Texture {
372 pub inner: TextureInner,
373 pub drop_guard: Option<crate::DropGuard>,
374 pub mip_level_count: u32,
375 pub array_layer_count: u32,
376 pub format: wgt::TextureFormat,
377 #[allow(unused)]
378 pub format_desc: TextureFormatDesc,
379 pub copy_size: CopyExtent,
380}
381
382impl crate::DynTexture for Texture {}
383impl crate::DynSurfaceTexture for Texture {}
384
385impl std::borrow::Borrow<dyn crate::DynTexture> for Texture {
386 fn borrow(&self) -> &dyn crate::DynTexture {
387 self
388 }
389}
390
391impl Texture {
392 pub fn default_framebuffer(format: wgt::TextureFormat) -> Self {
393 Self {
394 inner: TextureInner::DefaultRenderbuffer,
395 drop_guard: None,
396 mip_level_count: 1,
397 array_layer_count: 1,
398 format,
399 format_desc: TextureFormatDesc {
400 internal: 0,
401 external: 0,
402 data_type: 0,
403 },
404 copy_size: CopyExtent {
405 width: 0,
406 height: 0,
407 depth: 0,
408 },
409 }
410 }
411
412 fn get_info_from_desc(desc: &TextureDescriptor) -> u32 {
414 match desc.dimension {
415 wgt::TextureDimension::D1 => glow::TEXTURE_2D,
418 wgt::TextureDimension::D2 => {
419 match (desc.is_cube_compatible(), desc.size.depth_or_array_layers) {
421 (false, 1) => glow::TEXTURE_2D,
422 (false, _) => glow::TEXTURE_2D_ARRAY,
423 (true, 6) => glow::TEXTURE_CUBE_MAP,
424 (true, _) => glow::TEXTURE_CUBE_MAP_ARRAY,
425 }
426 }
427 wgt::TextureDimension::D3 => glow::TEXTURE_3D,
428 }
429 }
430
431 fn log_failing_target_heuristics(view_dimension: wgt::TextureViewDimension, target: u32) {
433 let expected_target = match view_dimension {
434 wgt::TextureViewDimension::D1 => glow::TEXTURE_2D,
435 wgt::TextureViewDimension::D2 => glow::TEXTURE_2D,
436 wgt::TextureViewDimension::D2Array => glow::TEXTURE_2D_ARRAY,
437 wgt::TextureViewDimension::Cube => glow::TEXTURE_CUBE_MAP,
438 wgt::TextureViewDimension::CubeArray => glow::TEXTURE_CUBE_MAP_ARRAY,
439 wgt::TextureViewDimension::D3 => glow::TEXTURE_3D,
440 };
441
442 if expected_target == target {
443 return;
444 }
445
446 let buffer;
447 let got = match target {
448 glow::TEXTURE_2D => "D2",
449 glow::TEXTURE_2D_ARRAY => "D2Array",
450 glow::TEXTURE_CUBE_MAP => "Cube",
451 glow::TEXTURE_CUBE_MAP_ARRAY => "CubeArray",
452 glow::TEXTURE_3D => "D3",
453 target => {
454 buffer = target.to_string();
455 &buffer
456 }
457 };
458
459 log::error!(
460 concat!(
461 "wgpu-hal heuristics assumed that ",
462 "the view dimension will be equal to `{}` rather than `{:?}`.\n",
463 "`D2` textures with ",
464 "`depth_or_array_layers == 1` ",
465 "are assumed to have view dimension `D2`\n",
466 "`D2` textures with ",
467 "`depth_or_array_layers > 1` ",
468 "are assumed to have view dimension `D2Array`\n",
469 "`D2` textures with ",
470 "`depth_or_array_layers == 6` ",
471 "are assumed to have view dimension `Cube`\n",
472 "`D2` textures with ",
473 "`depth_or_array_layers > 6 && depth_or_array_layers % 6 == 0` ",
474 "are assumed to have view dimension `CubeArray`\n",
475 ),
476 got,
477 view_dimension,
478 );
479 }
480}
481
482#[derive(Clone, Debug)]
483pub struct TextureView {
484 inner: TextureInner,
485 aspects: crate::FormatAspects,
486 mip_levels: Range<u32>,
487 array_layers: Range<u32>,
488 format: wgt::TextureFormat,
489}
490
491impl crate::DynTextureView for TextureView {}
492
493#[derive(Debug)]
494pub struct Sampler {
495 raw: glow::Sampler,
496}
497
498impl crate::DynSampler for Sampler {}
499
500#[derive(Debug)]
501pub struct BindGroupLayout {
502 entries: Arc<[wgt::BindGroupLayoutEntry]>,
503}
504
505impl crate::DynBindGroupLayout for BindGroupLayout {}
506
507#[derive(Debug)]
508struct BindGroupLayoutInfo {
509 entries: Arc<[wgt::BindGroupLayoutEntry]>,
510 binding_to_slot: Box<[u8]>,
516}
517
518#[derive(Debug)]
519pub struct PipelineLayout {
520 group_infos: Box<[BindGroupLayoutInfo]>,
521 naga_options: naga::back::glsl::Options,
522}
523
524impl crate::DynPipelineLayout for PipelineLayout {}
525
526impl PipelineLayout {
527 fn get_slot(&self, br: &naga::ResourceBinding) -> u8 {
528 let group_info = &self.group_infos[br.group as usize];
529 group_info.binding_to_slot[br.binding as usize]
530 }
531}
532
533#[derive(Debug)]
534enum BindingRegister {
535 UniformBuffers,
536 StorageBuffers,
537 Textures,
538 Images,
539}
540
541#[derive(Debug)]
542enum RawBinding {
543 Buffer {
544 raw: glow::Buffer,
545 offset: i32,
546 size: i32,
547 },
548 Texture {
549 raw: glow::Texture,
550 target: BindTarget,
551 aspects: crate::FormatAspects,
552 mip_levels: Range<u32>,
553 },
555 Image(ImageBinding),
556 Sampler(glow::Sampler),
557}
558
559#[derive(Debug)]
560pub struct BindGroup {
561 contents: Box<[RawBinding]>,
562}
563
564impl crate::DynBindGroup for BindGroup {}
565
566type ShaderId = u32;
567
568#[derive(Debug)]
569pub struct ShaderModule {
570 naga: crate::NagaShader,
571 label: Option<String>,
572 id: ShaderId,
573}
574
575impl crate::DynShaderModule for ShaderModule {}
576
577#[derive(Clone, Debug, Default)]
578struct VertexFormatDesc {
579 element_count: i32,
580 element_format: u32,
581 attrib_kind: VertexAttribKind,
582}
583
584#[derive(Clone, Debug, Default)]
585struct AttributeDesc {
586 location: u32,
587 offset: u32,
588 buffer_index: u32,
589 format_desc: VertexFormatDesc,
590}
591
592#[derive(Clone, Debug)]
593struct BufferBinding {
594 raw: glow::Buffer,
595 offset: wgt::BufferAddress,
596}
597
598#[derive(Clone, Debug)]
599struct ImageBinding {
600 raw: glow::Texture,
601 mip_level: u32,
602 array_layer: Option<u32>,
603 access: u32,
604 format: u32,
605}
606
607#[derive(Clone, Debug, Default, PartialEq)]
608struct VertexBufferDesc {
609 step: wgt::VertexStepMode,
610 stride: u32,
611}
612
613#[derive(Clone, Debug)]
614struct PushConstantDesc {
615 location: glow::UniformLocation,
616 ty: naga::TypeInner,
617 offset: u32,
618 size_bytes: u32,
619}
620
621#[cfg(send_sync)]
622unsafe impl Sync for PushConstantDesc {}
623#[cfg(send_sync)]
624unsafe impl Send for PushConstantDesc {}
625
626type SamplerBindMap = [Option<u8>; MAX_TEXTURE_SLOTS];
629
630#[derive(Debug)]
631struct PipelineInner {
632 program: glow::Program,
633 sampler_map: SamplerBindMap,
634 first_instance_location: Option<glow::UniformLocation>,
635 push_constant_descs: ArrayVec<PushConstantDesc, MAX_PUSH_CONSTANT_COMMANDS>,
636}
637
638#[derive(Clone, Debug)]
639struct DepthState {
640 function: u32,
641 mask: bool,
642}
643
644#[derive(Clone, Debug, PartialEq)]
645struct BlendComponent {
646 src: u32,
647 dst: u32,
648 equation: u32,
649}
650
651#[derive(Clone, Debug, PartialEq)]
652struct BlendDesc {
653 alpha: BlendComponent,
654 color: BlendComponent,
655}
656
657#[derive(Clone, Debug, Default, PartialEq)]
658struct ColorTargetDesc {
659 mask: wgt::ColorWrites,
660 blend: Option<BlendDesc>,
661}
662
663#[derive(PartialEq, Eq, Hash)]
664struct ProgramStage {
665 naga_stage: naga::ShaderStage,
666 shader_id: ShaderId,
667 entry_point: String,
668 zero_initialize_workgroup_memory: bool,
669}
670
671#[derive(PartialEq, Eq, Hash)]
672struct ProgramCacheKey {
673 stages: ArrayVec<ProgramStage, 3>,
674 group_to_binding_to_slot: Box<[Box<[u8]>]>,
675}
676
677type ProgramCache = FastHashMap<ProgramCacheKey, Result<Arc<PipelineInner>, crate::PipelineError>>;
678
679#[derive(Debug)]
680pub struct RenderPipeline {
681 inner: Arc<PipelineInner>,
682 primitive: wgt::PrimitiveState,
683 vertex_buffers: Box<[VertexBufferDesc]>,
684 vertex_attributes: Box<[AttributeDesc]>,
685 color_targets: Box<[ColorTargetDesc]>,
686 depth: Option<DepthState>,
687 depth_bias: wgt::DepthBiasState,
688 stencil: Option<StencilState>,
689 alpha_to_coverage_enabled: bool,
690}
691
692impl crate::DynRenderPipeline for RenderPipeline {}
693
694#[cfg(send_sync)]
695unsafe impl Sync for RenderPipeline {}
696#[cfg(send_sync)]
697unsafe impl Send for RenderPipeline {}
698
699#[derive(Debug)]
700pub struct ComputePipeline {
701 inner: Arc<PipelineInner>,
702}
703
704impl crate::DynComputePipeline for ComputePipeline {}
705
706#[cfg(send_sync)]
707unsafe impl Sync for ComputePipeline {}
708#[cfg(send_sync)]
709unsafe impl Send for ComputePipeline {}
710
711#[derive(Debug)]
712pub struct QuerySet {
713 queries: Box<[glow::Query]>,
714 target: BindTarget,
715}
716
717impl crate::DynQuerySet for QuerySet {}
718
719#[derive(Debug)]
720pub struct Fence {
721 last_completed: crate::AtomicFenceValue,
722 pending: Vec<(crate::FenceValue, glow::Fence)>,
723}
724
725impl crate::DynFence for Fence {}
726
727#[cfg(any(
728 not(target_arch = "wasm32"),
729 all(
730 feature = "fragile-send-sync-non-atomic-wasm",
731 not(target_feature = "atomics")
732 )
733))]
734unsafe impl Send for Fence {}
735#[cfg(any(
736 not(target_arch = "wasm32"),
737 all(
738 feature = "fragile-send-sync-non-atomic-wasm",
739 not(target_feature = "atomics")
740 )
741))]
742unsafe impl Sync for Fence {}
743
744impl Fence {
745 fn get_latest(&self, gl: &glow::Context) -> crate::FenceValue {
746 let mut max_value = self.last_completed.load(Ordering::Relaxed);
747 for &(value, sync) in self.pending.iter() {
748 if value <= max_value {
749 continue;
751 }
752 let status = unsafe { gl.get_sync_status(sync) };
753 if status == glow::SIGNALED {
754 max_value = value;
755 } else {
756 break;
758 }
759 }
760
761 self.last_completed.fetch_max(max_value, Ordering::Relaxed);
763
764 max_value
765 }
766
767 fn maintain(&mut self, gl: &glow::Context) {
768 let latest = self.get_latest(gl);
769 for &(value, sync) in self.pending.iter() {
770 if value <= latest {
771 unsafe {
772 gl.delete_sync(sync);
773 }
774 }
775 }
776 self.pending.retain(|&(value, _)| value > latest);
777 }
778}
779
780#[derive(Debug)]
781pub struct AccelerationStructure;
782
783impl crate::DynAccelerationStructure for AccelerationStructure {}
784
785#[derive(Debug)]
786pub struct PipelineCache;
787
788impl crate::DynPipelineCache for PipelineCache {}
789
790#[derive(Clone, Debug, PartialEq)]
791struct StencilOps {
792 pass: u32,
793 fail: u32,
794 depth_fail: u32,
795}
796
797impl Default for StencilOps {
798 fn default() -> Self {
799 Self {
800 pass: glow::KEEP,
801 fail: glow::KEEP,
802 depth_fail: glow::KEEP,
803 }
804 }
805}
806
807#[derive(Clone, Debug, PartialEq)]
808struct StencilSide {
809 function: u32,
810 mask_read: u32,
811 mask_write: u32,
812 reference: u32,
813 ops: StencilOps,
814}
815
816impl Default for StencilSide {
817 fn default() -> Self {
818 Self {
819 function: glow::ALWAYS,
820 mask_read: 0xFF,
821 mask_write: 0xFF,
822 reference: 0,
823 ops: StencilOps::default(),
824 }
825 }
826}
827
828#[derive(Debug, Clone, Default)]
829struct StencilState {
830 front: StencilSide,
831 back: StencilSide,
832}
833
834#[derive(Clone, Debug, Default, PartialEq)]
835struct PrimitiveState {
836 front_face: u32,
837 cull_face: u32,
838 unclipped_depth: bool,
839 polygon_mode: u32,
840}
841
842type InvalidatedAttachments = ArrayVec<u32, { crate::MAX_COLOR_ATTACHMENTS + 2 }>;
843
844#[derive(Debug)]
845enum Command {
846 Draw {
847 topology: u32,
848 first_vertex: u32,
849 vertex_count: u32,
850 first_instance: u32,
851 instance_count: u32,
852 first_instance_location: Option<glow::UniformLocation>,
853 },
854 DrawIndexed {
855 topology: u32,
856 index_type: u32,
857 index_count: u32,
858 index_offset: wgt::BufferAddress,
859 base_vertex: i32,
860 first_instance: u32,
861 instance_count: u32,
862 first_instance_location: Option<glow::UniformLocation>,
863 },
864 DrawIndirect {
865 topology: u32,
866 indirect_buf: glow::Buffer,
867 indirect_offset: wgt::BufferAddress,
868 first_instance_location: Option<glow::UniformLocation>,
869 },
870 DrawIndexedIndirect {
871 topology: u32,
872 index_type: u32,
873 indirect_buf: glow::Buffer,
874 indirect_offset: wgt::BufferAddress,
875 first_instance_location: Option<glow::UniformLocation>,
876 },
877 Dispatch([u32; 3]),
878 DispatchIndirect {
879 indirect_buf: glow::Buffer,
880 indirect_offset: wgt::BufferAddress,
881 },
882 ClearBuffer {
883 dst: Buffer,
884 dst_target: BindTarget,
885 range: crate::MemoryRange,
886 },
887 CopyBufferToBuffer {
888 src: Buffer,
889 src_target: BindTarget,
890 dst: Buffer,
891 dst_target: BindTarget,
892 copy: crate::BufferCopy,
893 },
894 #[cfg(webgl)]
895 CopyExternalImageToTexture {
896 src: wgt::ImageCopyExternalImage,
897 dst: glow::Texture,
898 dst_target: BindTarget,
899 dst_format: wgt::TextureFormat,
900 dst_premultiplication: bool,
901 copy: crate::TextureCopy,
902 },
903 CopyTextureToTexture {
904 src: glow::Texture,
905 src_target: BindTarget,
906 dst: glow::Texture,
907 dst_target: BindTarget,
908 copy: crate::TextureCopy,
909 },
910 CopyBufferToTexture {
911 src: Buffer,
912 #[allow(unused)]
913 src_target: BindTarget,
914 dst: glow::Texture,
915 dst_target: BindTarget,
916 dst_format: wgt::TextureFormat,
917 copy: crate::BufferTextureCopy,
918 },
919 CopyTextureToBuffer {
920 src: glow::Texture,
921 src_target: BindTarget,
922 src_format: wgt::TextureFormat,
923 dst: Buffer,
924 #[allow(unused)]
925 dst_target: BindTarget,
926 copy: crate::BufferTextureCopy,
927 },
928 SetIndexBuffer(glow::Buffer),
929 BeginQuery(glow::Query, BindTarget),
930 EndQuery(BindTarget),
931 TimestampQuery(glow::Query),
932 CopyQueryResults {
933 query_range: Range<u32>,
934 dst: Buffer,
935 dst_target: BindTarget,
936 dst_offset: wgt::BufferAddress,
937 },
938 ResetFramebuffer {
939 is_default: bool,
940 },
941 BindAttachment {
942 attachment: u32,
943 view: TextureView,
944 },
945 ResolveAttachment {
946 attachment: u32,
947 dst: TextureView,
948 size: wgt::Extent3d,
949 },
950 InvalidateAttachments(InvalidatedAttachments),
951 SetDrawColorBuffers(u8),
952 ClearColorF {
953 draw_buffer: u32,
954 color: [f32; 4],
955 is_srgb: bool,
956 },
957 ClearColorU(u32, [u32; 4]),
958 ClearColorI(u32, [i32; 4]),
959 ClearDepth(f32),
960 ClearStencil(u32),
961 ClearDepthAndStencil(f32, u32),
966 BufferBarrier(glow::Buffer, crate::BufferUses),
967 TextureBarrier(crate::TextureUses),
968 SetViewport {
969 rect: crate::Rect<i32>,
970 depth: Range<f32>,
971 },
972 SetScissor(crate::Rect<i32>),
973 SetStencilFunc {
974 face: u32,
975 function: u32,
976 reference: u32,
977 read_mask: u32,
978 },
979 SetStencilOps {
980 face: u32,
981 write_mask: u32,
982 ops: StencilOps,
983 },
984 SetDepth(DepthState),
985 SetDepthBias(wgt::DepthBiasState),
986 ConfigureDepthStencil(crate::FormatAspects),
987 SetAlphaToCoverage(bool),
988 SetVertexAttribute {
989 buffer: Option<glow::Buffer>,
990 buffer_desc: VertexBufferDesc,
991 attribute_desc: AttributeDesc,
992 },
993 UnsetVertexAttribute(u32),
994 SetVertexBuffer {
995 index: u32,
996 buffer: BufferBinding,
997 buffer_desc: VertexBufferDesc,
998 },
999 SetProgram(glow::Program),
1000 SetPrimitive(PrimitiveState),
1001 SetBlendConstant([f32; 4]),
1002 SetColorTarget {
1003 draw_buffer_index: Option<u32>,
1004 desc: ColorTargetDesc,
1005 },
1006 BindBuffer {
1007 target: BindTarget,
1008 slot: u32,
1009 buffer: glow::Buffer,
1010 offset: i32,
1011 size: i32,
1012 },
1013 BindSampler(u32, Option<glow::Sampler>),
1014 BindTexture {
1015 slot: u32,
1016 texture: glow::Texture,
1017 target: BindTarget,
1018 aspects: crate::FormatAspects,
1019 mip_levels: Range<u32>,
1020 },
1021 BindImage {
1022 slot: u32,
1023 binding: ImageBinding,
1024 },
1025 InsertDebugMarker(Range<u32>),
1026 PushDebugGroup(Range<u32>),
1027 PopDebugGroup,
1028 SetPushConstants {
1029 uniform: PushConstantDesc,
1030 offset: u32,
1032 },
1033}
1034
1035#[derive(Default)]
1036pub struct CommandBuffer {
1037 label: Option<String>,
1038 commands: Vec<Command>,
1039 data_bytes: Vec<u8>,
1040 queries: Vec<glow::Query>,
1041}
1042
1043impl crate::DynCommandBuffer for CommandBuffer {}
1044
1045impl fmt::Debug for CommandBuffer {
1046 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1047 let mut builder = f.debug_struct("CommandBuffer");
1048 if let Some(ref label) = self.label {
1049 builder.field("label", label);
1050 }
1051 builder.finish()
1052 }
1053}
1054
1055#[cfg(send_sync)]
1056unsafe impl Sync for CommandBuffer {}
1057#[cfg(send_sync)]
1058unsafe impl Send for CommandBuffer {}
1059
1060pub struct CommandEncoder {
1065 cmd_buffer: CommandBuffer,
1066 state: command::State,
1067 private_caps: PrivateCapabilities,
1068}
1069
1070impl fmt::Debug for CommandEncoder {
1071 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1072 f.debug_struct("CommandEncoder")
1073 .field("cmd_buffer", &self.cmd_buffer)
1074 .finish()
1075 }
1076}
1077
1078#[cfg(send_sync)]
1079unsafe impl Sync for CommandEncoder {}
1080#[cfg(send_sync)]
1081unsafe impl Send for CommandEncoder {}
1082
1083#[cfg(not(webgl))]
1084fn gl_debug_message_callback(source: u32, gltype: u32, id: u32, severity: u32, message: &str) {
1085 let source_str = match source {
1086 glow::DEBUG_SOURCE_API => "API",
1087 glow::DEBUG_SOURCE_WINDOW_SYSTEM => "Window System",
1088 glow::DEBUG_SOURCE_SHADER_COMPILER => "ShaderCompiler",
1089 glow::DEBUG_SOURCE_THIRD_PARTY => "Third Party",
1090 glow::DEBUG_SOURCE_APPLICATION => "Application",
1091 glow::DEBUG_SOURCE_OTHER => "Other",
1092 _ => unreachable!(),
1093 };
1094
1095 let log_severity = match severity {
1096 glow::DEBUG_SEVERITY_HIGH => log::Level::Error,
1097 glow::DEBUG_SEVERITY_MEDIUM => log::Level::Warn,
1098 glow::DEBUG_SEVERITY_LOW => log::Level::Info,
1099 glow::DEBUG_SEVERITY_NOTIFICATION => log::Level::Trace,
1100 _ => unreachable!(),
1101 };
1102
1103 let type_str = match gltype {
1104 glow::DEBUG_TYPE_DEPRECATED_BEHAVIOR => "Deprecated Behavior",
1105 glow::DEBUG_TYPE_ERROR => "Error",
1106 glow::DEBUG_TYPE_MARKER => "Marker",
1107 glow::DEBUG_TYPE_OTHER => "Other",
1108 glow::DEBUG_TYPE_PERFORMANCE => "Performance",
1109 glow::DEBUG_TYPE_POP_GROUP => "Pop Group",
1110 glow::DEBUG_TYPE_PORTABILITY => "Portability",
1111 glow::DEBUG_TYPE_PUSH_GROUP => "Push Group",
1112 glow::DEBUG_TYPE_UNDEFINED_BEHAVIOR => "Undefined Behavior",
1113 _ => unreachable!(),
1114 };
1115
1116 let _ = std::panic::catch_unwind(|| {
1117 log::log!(
1118 log_severity,
1119 "GLES: [{}/{}] ID {} : {}",
1120 source_str,
1121 type_str,
1122 id,
1123 message
1124 );
1125 });
1126
1127 if cfg!(debug_assertions) && log_severity == log::Level::Error {
1128 crate::VALIDATION_CANARY.add(message.to_string());
1130 }
1131}