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