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