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