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 }
238}
239
240bitflags::bitflags! {
241 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
243 struct Workarounds: u32 {
244 const MESA_I915_SRGB_SHADER_CLEAR = 1 << 0;
251 const EMULATE_BUFFER_MAP = 1 << 1;
253 }
254}
255
256type BindTarget = u32;
257
258#[derive(Debug, Default, Clone, Copy)]
259enum VertexAttribKind {
260 #[default]
261 Float, Integer, }
265
266#[derive(Clone, Debug)]
267pub struct TextureFormatDesc {
268 pub internal: u32,
269 pub external: u32,
270 pub data_type: u32,
271}
272
273struct AdapterShared {
274 context: AdapterContext,
275 private_caps: PrivateCapabilities,
276 features: wgt::Features,
277 limits: wgt::Limits,
278 workarounds: Workarounds,
279 options: wgt::GlBackendOptions,
280 shading_language_version: naga::back::glsl::Version,
281 next_shader_id: AtomicU32,
282 program_cache: Mutex<ProgramCache>,
283 es: bool,
284
285 max_msaa_samples: i32,
289}
290
291pub struct Adapter {
292 shared: Arc<AdapterShared>,
293}
294
295pub struct Device {
296 shared: Arc<AdapterShared>,
297 main_vao: glow::VertexArray,
298 #[cfg(all(native, feature = "renderdoc"))]
299 render_doc: crate::auxil::renderdoc::RenderDoc,
300 counters: Arc<wgt::HalCounters>,
301}
302
303impl Drop for Device {
304 fn drop(&mut self) {
305 let gl = &self.shared.context.lock();
306 unsafe { gl.delete_vertex_array(self.main_vao) };
307 }
308}
309
310pub struct ShaderClearProgram {
311 pub program: glow::Program,
312 pub color_uniform_location: glow::UniformLocation,
313}
314
315pub struct Queue {
316 shared: Arc<AdapterShared>,
317 features: wgt::Features,
318 draw_fbo: glow::Framebuffer,
319 copy_fbo: glow::Framebuffer,
320 shader_clear_program: Option<ShaderClearProgram>,
323 zero_buffer: glow::Buffer,
326 temp_query_results: Mutex<Vec<u64>>,
327 draw_buffer_count: AtomicU8,
328 current_index_buffer: Mutex<Option<glow::Buffer>>,
329}
330
331impl Drop for Queue {
332 fn drop(&mut self) {
333 let gl = &self.shared.context.lock();
334 unsafe { gl.delete_framebuffer(self.draw_fbo) };
335 unsafe { gl.delete_framebuffer(self.copy_fbo) };
336 unsafe { gl.delete_buffer(self.zero_buffer) };
337 }
338}
339
340#[derive(Clone, Debug)]
341pub struct Buffer {
342 raw: Option<glow::Buffer>,
343 target: BindTarget,
344 size: wgt::BufferAddress,
345 map_flags: u32,
347 data: Option<Arc<MaybeMutex<Vec<u8>>>>,
348 offset_of_current_mapping: Arc<MaybeMutex<wgt::BufferAddress>>,
349}
350
351#[cfg(send_sync)]
352unsafe impl Sync for Buffer {}
353#[cfg(send_sync)]
354unsafe impl Send for Buffer {}
355
356impl crate::DynBuffer for Buffer {}
357
358#[derive(Clone, Debug)]
359pub enum TextureInner {
360 Renderbuffer {
361 raw: glow::Renderbuffer,
362 },
363 DefaultRenderbuffer,
364 Texture {
365 raw: glow::Texture,
366 target: BindTarget,
367 },
368 #[cfg(webgl)]
369 ExternalFramebuffer {
373 inner: web_sys::WebGlFramebuffer,
374 },
375 #[cfg(native)]
376 ExternalNativeFramebuffer {
382 inner: glow::NativeFramebuffer,
383 },
384}
385
386#[cfg(send_sync)]
387unsafe impl Sync for TextureInner {}
388#[cfg(send_sync)]
389unsafe impl Send for TextureInner {}
390
391impl TextureInner {
392 fn as_native(&self) -> (glow::Texture, BindTarget) {
393 match *self {
394 Self::Renderbuffer { .. } | Self::DefaultRenderbuffer => {
395 panic!("Unexpected renderbuffer");
396 }
397 Self::Texture { raw, target } => (raw, target),
398 #[cfg(webgl)]
399 Self::ExternalFramebuffer { .. } => panic!("Unexpected external framebuffer"),
400 #[cfg(native)]
401 Self::ExternalNativeFramebuffer { .. } => panic!("unexpected external framebuffer"),
402 }
403 }
404}
405
406#[derive(Debug)]
407pub struct Texture {
408 pub inner: TextureInner,
409 pub mip_level_count: u32,
410 pub array_layer_count: u32,
411 pub format: wgt::TextureFormat,
412 pub format_desc: TextureFormatDesc,
413 pub copy_size: CopyExtent,
414
415 pub drop_guard: Option<crate::DropGuard>,
418}
419
420impl crate::DynTexture for Texture {}
421impl crate::DynSurfaceTexture for Texture {}
422
423impl core::borrow::Borrow<dyn crate::DynTexture> for Texture {
424 fn borrow(&self) -> &dyn crate::DynTexture {
425 self
426 }
427}
428
429impl Texture {
430 pub fn default_framebuffer(format: wgt::TextureFormat) -> Self {
431 Self {
432 inner: TextureInner::DefaultRenderbuffer,
433 drop_guard: None,
434 mip_level_count: 1,
435 array_layer_count: 1,
436 format,
437 format_desc: TextureFormatDesc {
438 internal: 0,
439 external: 0,
440 data_type: 0,
441 },
442 copy_size: CopyExtent {
443 width: 0,
444 height: 0,
445 depth: 0,
446 },
447 }
448 }
449
450 fn get_info_from_desc(desc: &TextureDescriptor) -> u32 {
452 match desc.dimension {
453 wgt::TextureDimension::D1 => glow::TEXTURE_2D,
456 wgt::TextureDimension::D2 => {
457 match (desc.is_cube_compatible(), desc.size.depth_or_array_layers) {
459 (false, 1) => glow::TEXTURE_2D,
460 (false, _) => glow::TEXTURE_2D_ARRAY,
461 (true, 6) => glow::TEXTURE_CUBE_MAP,
462 (true, _) => glow::TEXTURE_CUBE_MAP_ARRAY,
463 }
464 }
465 wgt::TextureDimension::D3 => glow::TEXTURE_3D,
466 }
467 }
468
469 fn log_failing_target_heuristics(view_dimension: wgt::TextureViewDimension, target: u32) {
471 let expected_target = match view_dimension {
472 wgt::TextureViewDimension::D1 => glow::TEXTURE_2D,
473 wgt::TextureViewDimension::D2 => glow::TEXTURE_2D,
474 wgt::TextureViewDimension::D2Array => glow::TEXTURE_2D_ARRAY,
475 wgt::TextureViewDimension::Cube => glow::TEXTURE_CUBE_MAP,
476 wgt::TextureViewDimension::CubeArray => glow::TEXTURE_CUBE_MAP_ARRAY,
477 wgt::TextureViewDimension::D3 => glow::TEXTURE_3D,
478 };
479
480 if expected_target == target {
481 return;
482 }
483
484 let buffer;
485 let got = match target {
486 glow::TEXTURE_2D => "D2",
487 glow::TEXTURE_2D_ARRAY => "D2Array",
488 glow::TEXTURE_CUBE_MAP => "Cube",
489 glow::TEXTURE_CUBE_MAP_ARRAY => "CubeArray",
490 glow::TEXTURE_3D => "D3",
491 target => {
492 buffer = target.to_string();
493 &buffer
494 }
495 };
496
497 log::error!(
498 concat!(
499 "wgpu-hal heuristics assumed that ",
500 "the view dimension will be equal to `{}` rather than `{:?}`.\n",
501 "`D2` textures with ",
502 "`depth_or_array_layers == 1` ",
503 "are assumed to have view dimension `D2`\n",
504 "`D2` textures with ",
505 "`depth_or_array_layers > 1` ",
506 "are assumed to have view dimension `D2Array`\n",
507 "`D2` textures with ",
508 "`depth_or_array_layers == 6` ",
509 "are assumed to have view dimension `Cube`\n",
510 "`D2` textures with ",
511 "`depth_or_array_layers > 6 && depth_or_array_layers % 6 == 0` ",
512 "are assumed to have view dimension `CubeArray`\n",
513 ),
514 got,
515 view_dimension,
516 );
517 }
518}
519
520#[derive(Clone, Debug)]
521pub struct TextureView {
522 inner: TextureInner,
523 aspects: crate::FormatAspects,
524 mip_levels: Range<u32>,
525 array_layers: Range<u32>,
526 format: wgt::TextureFormat,
527}
528
529impl crate::DynTextureView for TextureView {}
530
531#[derive(Debug)]
532pub struct Sampler {
533 raw: glow::Sampler,
534}
535
536impl crate::DynSampler for Sampler {}
537
538#[derive(Debug)]
539pub struct BindGroupLayout {
540 entries: Arc<[wgt::BindGroupLayoutEntry]>,
541}
542
543impl crate::DynBindGroupLayout for BindGroupLayout {}
544
545#[derive(Debug)]
546struct BindGroupLayoutInfo {
547 entries: Arc<[wgt::BindGroupLayoutEntry]>,
548 binding_to_slot: Box<[u8]>,
554}
555
556#[derive(Debug)]
557pub struct PipelineLayout {
558 group_infos: Box<[Option<BindGroupLayoutInfo>]>,
559 naga_options: naga::back::glsl::Options,
560}
561
562impl crate::DynPipelineLayout for PipelineLayout {}
563
564impl PipelineLayout {
565 fn get_slot(&self, br: &naga::ResourceBinding) -> u8 {
569 let group_info = self.group_infos[br.group as usize].as_ref().unwrap();
570 group_info.binding_to_slot[br.binding as usize]
571 }
572}
573
574#[derive(Debug)]
575enum BindingRegister {
576 UniformBuffers,
577 StorageBuffers,
578 Textures,
579 Images,
580}
581
582#[derive(Debug)]
583enum RawBinding {
584 Buffer {
585 raw: glow::Buffer,
586 offset: i32,
587 size: i32,
588 },
589 Texture {
590 raw: glow::Texture,
591 target: BindTarget,
592 aspects: crate::FormatAspects,
593 mip_levels: Range<u32>,
594 },
596 Image(ImageBinding),
597 Sampler(glow::Sampler),
598}
599
600#[derive(Debug)]
601pub struct BindGroup {
602 contents: Box<[RawBinding]>,
603}
604
605impl crate::DynBindGroup for BindGroup {}
606
607type ShaderId = u32;
608
609#[derive(Debug)]
610pub struct ShaderModule {
611 source: crate::NagaShader,
612 label: Option<String>,
613 id: ShaderId,
614}
615
616impl crate::DynShaderModule for ShaderModule {}
617
618#[derive(Clone, Debug, Default)]
619struct VertexFormatDesc {
620 element_count: i32,
621 element_format: u32,
622 attrib_kind: VertexAttribKind,
623}
624
625#[derive(Clone, Debug, Default)]
626struct AttributeDesc {
627 location: u32,
628 offset: u32,
629 buffer_index: u32,
630 format_desc: VertexFormatDesc,
631}
632
633#[derive(Clone, Debug)]
634struct BufferBinding {
635 raw: glow::Buffer,
636 offset: wgt::BufferAddress,
637}
638
639#[derive(Clone, Debug)]
640struct ImageBinding {
641 raw: glow::Texture,
642 mip_level: u32,
643 array_layer: Option<u32>,
644 access: u32,
645 format: u32,
646}
647
648#[derive(Clone, Debug, Default, PartialEq)]
649struct VertexBufferDesc {
650 step: wgt::VertexStepMode,
651 stride: u32,
652}
653
654#[derive(Clone, Debug)]
655struct ImmediateDesc {
656 location: glow::UniformLocation,
657 ty: naga::TypeInner,
658 offset: u32,
659 size_bytes: u32,
660}
661
662#[cfg(send_sync)]
663unsafe impl Sync for ImmediateDesc {}
664#[cfg(send_sync)]
665unsafe impl Send for ImmediateDesc {}
666
667type SamplerBindMap = [Option<u8>; MAX_TEXTURE_SLOTS];
670
671#[derive(Debug)]
672struct PipelineInner {
673 program: glow::Program,
674 sampler_map: SamplerBindMap,
675 first_instance_location: Option<glow::UniformLocation>,
676 immediates_descs: ArrayVec<ImmediateDesc, MAX_IMMEDIATES_COMMANDS>,
677 clip_distance_count: u32,
678}
679
680#[derive(Clone, Debug)]
681struct DepthState {
682 function: u32,
683 mask: bool,
684}
685
686#[derive(Clone, Debug, PartialEq)]
687struct BlendComponent {
688 src: u32,
689 dst: u32,
690 equation: u32,
691}
692
693#[derive(Clone, Debug, PartialEq)]
694struct BlendDesc {
695 alpha: BlendComponent,
696 color: BlendComponent,
697}
698
699#[derive(Clone, Debug, Default, PartialEq)]
700struct ColorTargetDesc {
701 mask: wgt::ColorWrites,
702 blend: Option<BlendDesc>,
703}
704
705#[derive(PartialEq, Eq, Hash)]
706struct ProgramStage {
707 naga_stage: naga::ShaderStage,
708 shader_id: ShaderId,
709 entry_point: String,
710 zero_initialize_workgroup_memory: bool,
711 constant_hash: Vec<u8>,
712}
713
714#[derive(PartialEq, Eq, Hash)]
715struct ProgramCacheKey {
716 stages: ArrayVec<ProgramStage, 3>,
717 group_to_binding_to_slot: Box<[Option<Box<[u8]>>]>,
718}
719
720type ProgramCache = FastHashMap<ProgramCacheKey, Result<Arc<PipelineInner>, crate::PipelineError>>;
721
722#[derive(Debug)]
723pub struct RenderPipeline {
724 inner: Arc<PipelineInner>,
725 primitive: wgt::PrimitiveState,
726 vertex_buffers: Box<[VertexBufferDesc]>,
727 vertex_attributes: Box<[AttributeDesc]>,
728 color_targets: Box<[ColorTargetDesc]>,
729 depth: Option<DepthState>,
730 depth_bias: wgt::DepthBiasState,
731 stencil: Option<StencilState>,
732 alpha_to_coverage_enabled: bool,
733}
734
735impl crate::DynRenderPipeline for RenderPipeline {}
736
737#[cfg(send_sync)]
738unsafe impl Sync for RenderPipeline {}
739#[cfg(send_sync)]
740unsafe impl Send for RenderPipeline {}
741
742#[derive(Debug)]
743pub struct ComputePipeline {
744 inner: Arc<PipelineInner>,
745}
746
747impl crate::DynComputePipeline for ComputePipeline {}
748
749#[cfg(send_sync)]
750unsafe impl Sync for ComputePipeline {}
751#[cfg(send_sync)]
752unsafe impl Send for ComputePipeline {}
753
754#[derive(Debug)]
755pub struct QuerySet {
756 queries: Box<[glow::Query]>,
757 target: BindTarget,
758}
759
760impl crate::DynQuerySet for QuerySet {}
761
762#[derive(Debug)]
763pub struct AccelerationStructure;
764
765impl crate::DynAccelerationStructure for AccelerationStructure {}
766
767#[derive(Debug)]
768pub struct PipelineCache;
769
770impl crate::DynPipelineCache for PipelineCache {}
771
772#[derive(Clone, Debug, PartialEq)]
773struct StencilOps {
774 pass: u32,
775 fail: u32,
776 depth_fail: u32,
777}
778
779impl Default for StencilOps {
780 fn default() -> Self {
781 Self {
782 pass: glow::KEEP,
783 fail: glow::KEEP,
784 depth_fail: glow::KEEP,
785 }
786 }
787}
788
789#[derive(Clone, Debug, PartialEq)]
790struct StencilSide {
791 function: u32,
792 mask_read: u32,
793 mask_write: u32,
794 reference: u32,
795 ops: StencilOps,
796}
797
798impl Default for StencilSide {
799 fn default() -> Self {
800 Self {
801 function: glow::ALWAYS,
802 mask_read: 0xFF,
803 mask_write: 0xFF,
804 reference: 0,
805 ops: StencilOps::default(),
806 }
807 }
808}
809
810#[derive(Debug, Clone, Default)]
811struct StencilState {
812 front: StencilSide,
813 back: StencilSide,
814}
815
816#[derive(Clone, Debug, Default, PartialEq)]
817struct PrimitiveState {
818 front_face: u32,
819 cull_face: u32,
820 unclipped_depth: bool,
821 polygon_mode: u32,
822}
823
824type InvalidatedAttachments = ArrayVec<u32, { crate::MAX_COLOR_ATTACHMENTS + 2 }>;
825
826#[derive(Debug)]
827enum Command {
828 Draw {
829 topology: u32,
830 first_vertex: u32,
831 vertex_count: u32,
832 first_instance: u32,
833 instance_count: u32,
834 first_instance_location: Option<glow::UniformLocation>,
835 },
836 DrawIndexed {
837 topology: u32,
838 index_type: u32,
839 index_count: u32,
840 index_offset: wgt::BufferAddress,
841 base_vertex: i32,
842 first_instance: u32,
843 instance_count: u32,
844 first_instance_location: Option<glow::UniformLocation>,
845 },
846 DrawIndirect {
847 topology: u32,
848 indirect_buf: glow::Buffer,
849 indirect_offset: wgt::BufferAddress,
850 first_instance_location: Option<glow::UniformLocation>,
851 },
852 DrawIndexedIndirect {
853 topology: u32,
854 index_type: u32,
855 indirect_buf: glow::Buffer,
856 indirect_offset: wgt::BufferAddress,
857 first_instance_location: Option<glow::UniformLocation>,
858 },
859 Dispatch([u32; 3]),
860 DispatchIndirect {
861 indirect_buf: glow::Buffer,
862 indirect_offset: wgt::BufferAddress,
863 },
864 ClearBuffer {
865 dst: Buffer,
866 dst_target: BindTarget,
867 range: crate::MemoryRange,
868 },
869 CopyBufferToBuffer {
870 src: Buffer,
871 src_target: BindTarget,
872 dst: Buffer,
873 dst_target: BindTarget,
874 copy: crate::BufferCopy,
875 },
876 #[cfg(webgl)]
877 CopyExternalImageToTexture {
878 src: wgt::CopyExternalImageSourceInfo,
879 dst: glow::Texture,
880 dst_target: BindTarget,
881 dst_format: wgt::TextureFormat,
882 dst_premultiplication: bool,
883 copy: crate::TextureCopy,
884 },
885 CopyTextureToTexture {
886 src: glow::Texture,
887 src_target: BindTarget,
888 dst: glow::Texture,
889 dst_target: BindTarget,
890 copy: crate::TextureCopy,
891 },
892 CopyBufferToTexture {
893 src: Buffer,
894 #[allow(unused)]
895 src_target: BindTarget,
896 dst: glow::Texture,
897 dst_target: BindTarget,
898 dst_format: wgt::TextureFormat,
899 copy: crate::BufferTextureCopy,
900 },
901 CopyTextureToBuffer {
902 src: glow::Texture,
903 src_target: BindTarget,
904 src_format: wgt::TextureFormat,
905 dst: Buffer,
906 #[allow(unused)]
907 dst_target: BindTarget,
908 copy: crate::BufferTextureCopy,
909 },
910 SetIndexBuffer(glow::Buffer),
911 BeginQuery(glow::Query, BindTarget),
912 EndQuery(BindTarget),
913 TimestampQuery(glow::Query),
914 CopyQueryResults {
915 query_range: Range<u32>,
916 dst: Buffer,
917 dst_target: BindTarget,
918 dst_offset: wgt::BufferAddress,
919 },
920 ResetFramebuffer {
921 is_default: bool,
922 },
923 BindAttachment {
924 attachment: u32,
925 view: TextureView,
926 depth_slice: Option<u32>,
927 sample_count: u32,
928 },
929 ResolveAttachment {
930 attachment: u32,
931 dst: TextureView,
932 size: wgt::Extent3d,
933 },
934 InvalidateAttachments(InvalidatedAttachments),
935 SetDrawColorBuffers(u8),
936 ClearColorF {
937 draw_buffer: u32,
938 color: [f32; 4],
939 is_srgb: bool,
940 },
941 ClearColorU(u32, [u32; 4]),
942 ClearColorI(u32, [i32; 4]),
943 ClearDepth(f32),
944 ClearStencil(u32),
945 ClearDepthAndStencil(f32, u32),
950 BufferBarrier(glow::Buffer, wgt::BufferUses),
951 TextureBarrier(wgt::TextureUses),
952 SetViewport {
953 rect: crate::Rect<i32>,
954 depth: Range<f32>,
955 },
956 SetScissor(crate::Rect<i32>),
957 SetStencilFunc {
958 face: u32,
959 function: u32,
960 reference: u32,
961 read_mask: u32,
962 },
963 SetStencilOps {
964 face: u32,
965 write_mask: u32,
966 ops: StencilOps,
967 },
968 SetDepth(DepthState),
969 SetDepthBias(wgt::DepthBiasState),
970 ConfigureDepthStencil(crate::FormatAspects),
971 SetAlphaToCoverage(bool),
972 SetVertexAttribute {
973 buffer: Option<glow::Buffer>,
974 buffer_desc: VertexBufferDesc,
975 attribute_desc: AttributeDesc,
976 },
977 UnsetVertexAttribute(u32),
978 SetVertexBuffer {
979 index: u32,
980 buffer: BufferBinding,
981 buffer_desc: VertexBufferDesc,
982 },
983 SetProgram(glow::Program),
984 SetPrimitive(PrimitiveState),
985 SetBlendConstant([f32; 4]),
986 SetColorTarget {
987 draw_buffer_index: Option<u32>,
988 desc: ColorTargetDesc,
989 },
990 BindBuffer {
991 target: BindTarget,
992 slot: u32,
993 buffer: glow::Buffer,
994 offset: i32,
995 size: i32,
996 },
997 BindSampler(u32, Option<glow::Sampler>),
998 BindTexture {
999 slot: u32,
1000 texture: glow::Texture,
1001 target: BindTarget,
1002 aspects: crate::FormatAspects,
1003 mip_levels: Range<u32>,
1004 },
1005 BindImage {
1006 slot: u32,
1007 binding: ImageBinding,
1008 },
1009 InsertDebugMarker(Range<u32>),
1010 PushDebugGroup(Range<u32>),
1011 PopDebugGroup,
1012 SetImmediates {
1013 uniform: ImmediateDesc,
1014 offset: u32,
1016 },
1017 SetClipDistances {
1018 old_count: u32,
1019 new_count: u32,
1020 },
1021}
1022
1023#[derive(Default)]
1024pub struct CommandBuffer {
1025 label: Option<String>,
1026 commands: Vec<Command>,
1027 data_bytes: Vec<u8>,
1028 queries: Vec<glow::Query>,
1029}
1030
1031impl crate::DynCommandBuffer for CommandBuffer {}
1032
1033impl fmt::Debug for CommandBuffer {
1034 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1035 let mut builder = f.debug_struct("CommandBuffer");
1036 if let Some(ref label) = self.label {
1037 builder.field("label", label);
1038 }
1039 builder.finish()
1040 }
1041}
1042
1043#[cfg(send_sync)]
1044unsafe impl Sync for CommandBuffer {}
1045#[cfg(send_sync)]
1046unsafe impl Send for CommandBuffer {}
1047
1048pub struct CommandEncoder {
1053 cmd_buffer: CommandBuffer,
1054 state: command::State,
1055 private_caps: PrivateCapabilities,
1056 counters: Arc<wgt::HalCounters>,
1057}
1058
1059impl fmt::Debug for CommandEncoder {
1060 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1061 f.debug_struct("CommandEncoder")
1062 .field("cmd_buffer", &self.cmd_buffer)
1063 .finish()
1064 }
1065}
1066
1067#[cfg(send_sync)]
1068unsafe impl Sync for CommandEncoder {}
1069#[cfg(send_sync)]
1070unsafe impl Send for CommandEncoder {}
1071
1072#[cfg(not(webgl))]
1073fn gl_debug_message_callback(source: u32, gltype: u32, id: u32, severity: u32, message: &str) {
1074 let source_str = match source {
1075 glow::DEBUG_SOURCE_API => "API",
1076 glow::DEBUG_SOURCE_WINDOW_SYSTEM => "Window System",
1077 glow::DEBUG_SOURCE_SHADER_COMPILER => "ShaderCompiler",
1078 glow::DEBUG_SOURCE_THIRD_PARTY => "Third Party",
1079 glow::DEBUG_SOURCE_APPLICATION => "Application",
1080 glow::DEBUG_SOURCE_OTHER => "Other",
1081 _ => unreachable!(),
1082 };
1083
1084 let log_severity = match severity {
1085 glow::DEBUG_SEVERITY_HIGH => log::Level::Error,
1086 glow::DEBUG_SEVERITY_MEDIUM => log::Level::Warn,
1087 glow::DEBUG_SEVERITY_LOW => log::Level::Debug,
1088 glow::DEBUG_SEVERITY_NOTIFICATION => log::Level::Trace,
1089 _ => unreachable!(),
1090 };
1091
1092 let type_str = match gltype {
1093 glow::DEBUG_TYPE_DEPRECATED_BEHAVIOR => "Deprecated Behavior",
1094 glow::DEBUG_TYPE_ERROR => "Error",
1095 glow::DEBUG_TYPE_MARKER => "Marker",
1096 glow::DEBUG_TYPE_OTHER => "Other",
1097 glow::DEBUG_TYPE_PERFORMANCE => "Performance",
1098 glow::DEBUG_TYPE_POP_GROUP => "Pop Group",
1099 glow::DEBUG_TYPE_PORTABILITY => "Portability",
1100 glow::DEBUG_TYPE_PUSH_GROUP => "Push Group",
1101 glow::DEBUG_TYPE_UNDEFINED_BEHAVIOR => "Undefined Behavior",
1102 _ => unreachable!(),
1103 };
1104
1105 let _ = std::panic::catch_unwind(|| {
1106 log::log!(
1107 log_severity,
1108 "GLES: [{source_str}/{type_str}] ID {id} : {message}"
1109 );
1110 });
1111
1112 #[cfg(feature = "validation_canary")]
1113 if cfg!(debug_assertions) && log_severity == log::Level::Error {
1114 crate::VALIDATION_CANARY.add(message.to_string());
1116 }
1117}
1118
1119cfg_if::cfg_if! {
1121 if #[cfg(gles_with_std)] {
1122 type MaybeMutex<T> = std::sync::Mutex<T>;
1123
1124 fn lock<T>(mutex: &MaybeMutex<T>) -> std::sync::MutexGuard<'_, T> {
1125 mutex.lock().unwrap()
1126 }
1127 } else {
1128 #[cfg(all(send_sync, not(feature = "fragile-send-sync-non-atomic-wasm")))]
1132 compile_error!("cannot provide non-fragile Send+Sync without std");
1133
1134 type MaybeMutex<T> = core::cell::RefCell<T>;
1135
1136 fn lock<T>(mutex: &MaybeMutex<T>) -> core::cell::RefMut<'_, T> {
1137 mutex.borrow_mut()
1138 }
1139 }
1140}