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