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