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 size: wgt::BufferAddress,
388 map_flags: u32,
390 map_state: Arc<Mutex<BufferMapState>>,
394 drop_guard: Option<Arc<crate::DropGuard>>,
400}
401
402#[derive(Clone, Debug)]
403struct BufferMapState {
404 mapped: bool,
407 data: Option<Vec<u8>>,
408 offset_of_current_mapping: wgt::BufferAddress,
409}
410
411#[cfg(send_sync)]
412static_assertions::assert_impl_all!(Buffer: Send, Sync);
413
414impl crate::DynBuffer for Buffer {}
415
416#[derive(Clone, Debug)]
417pub enum TextureInner {
418 Renderbuffer {
419 raw: glow::Renderbuffer,
420 },
421 DefaultRenderbuffer,
422 Texture {
423 raw: glow::Texture,
424 target: BindTarget,
425 },
426 #[cfg(webgl)]
427 ExternalFramebuffer {
431 inner: web_sys::WebGlFramebuffer,
432 },
433 #[cfg(native)]
434 ExternalNativeFramebuffer {
440 inner: glow::NativeFramebuffer,
441 },
442}
443
444#[cfg(send_sync)]
445unsafe impl Sync for TextureInner {}
446#[cfg(send_sync)]
447unsafe impl Send for TextureInner {}
448
449impl TextureInner {
450 fn as_native(&self) -> (glow::Texture, BindTarget) {
451 match *self {
452 Self::Renderbuffer { .. } | Self::DefaultRenderbuffer => {
453 panic!("Unexpected renderbuffer");
454 }
455 Self::Texture { raw, target } => (raw, target),
456 #[cfg(webgl)]
457 Self::ExternalFramebuffer { .. } => panic!("Unexpected external framebuffer"),
458 #[cfg(native)]
459 Self::ExternalNativeFramebuffer { .. } => panic!("unexpected external framebuffer"),
460 }
461 }
462}
463
464#[derive(Debug)]
465pub struct Texture {
466 pub inner: TextureInner,
467 pub mip_level_count: u32,
468 pub array_layer_count: u32,
469 pub format: wgt::TextureFormat,
470 pub format_desc: TextureFormatDesc,
471 pub copy_size: CopyExtent,
472
473 pub drop_guard: Option<crate::DropGuard>,
483}
484
485impl crate::DynTexture for Texture {}
486impl crate::DynSurfaceTexture for Texture {}
487
488impl core::borrow::Borrow<dyn crate::DynTexture> for Texture {
489 fn borrow(&self) -> &dyn crate::DynTexture {
490 self
491 }
492}
493
494impl Texture {
495 pub fn default_framebuffer(format: wgt::TextureFormat) -> Self {
496 Self {
497 inner: TextureInner::DefaultRenderbuffer,
498 drop_guard: None,
499 mip_level_count: 1,
500 array_layer_count: 1,
501 format,
502 format_desc: TextureFormatDesc {
503 internal: 0,
504 external: 0,
505 data_type: 0,
506 },
507 copy_size: CopyExtent {
508 width: 0,
509 height: 0,
510 depth: 0,
511 },
512 }
513 }
514
515 fn get_info_from_desc(desc: &TextureDescriptor) -> u32 {
517 match desc.dimension {
518 wgt::TextureDimension::D1 => glow::TEXTURE_2D,
521 wgt::TextureDimension::D2 => {
522 match (desc.is_cube_compatible(), desc.size.depth_or_array_layers) {
524 (false, 1) => glow::TEXTURE_2D,
525 (false, _) => glow::TEXTURE_2D_ARRAY,
526 (true, 6) => glow::TEXTURE_CUBE_MAP,
527 (true, _) => glow::TEXTURE_CUBE_MAP_ARRAY,
528 }
529 }
530 wgt::TextureDimension::D3 => glow::TEXTURE_3D,
531 }
532 }
533
534 fn target_for_view_dimension(view_dimension: wgt::TextureViewDimension) -> BindTarget {
539 match view_dimension {
540 wgt::TextureViewDimension::D1 | wgt::TextureViewDimension::D2 => glow::TEXTURE_2D,
541 wgt::TextureViewDimension::D2Array => glow::TEXTURE_2D_ARRAY,
542 wgt::TextureViewDimension::Cube => glow::TEXTURE_CUBE_MAP,
543 wgt::TextureViewDimension::CubeArray => glow::TEXTURE_CUBE_MAP_ARRAY,
544 wgt::TextureViewDimension::D3 => glow::TEXTURE_3D,
545 }
546 }
547
548 fn log_failing_target_heuristics(view_dimension: wgt::TextureViewDimension, target: u32) {
550 let expected_target = Self::target_for_view_dimension(view_dimension);
551
552 if expected_target == target {
553 return;
554 }
555
556 let buffer;
557 let got = match target {
558 glow::TEXTURE_2D => "D2",
559 glow::TEXTURE_2D_ARRAY => "D2Array",
560 glow::TEXTURE_CUBE_MAP => "Cube",
561 glow::TEXTURE_CUBE_MAP_ARRAY => "CubeArray",
562 glow::TEXTURE_3D => "D3",
563 target => {
564 buffer = target.to_string();
565 &buffer
566 }
567 };
568
569 log::error!(
570 concat!(
571 "wgpu-hal heuristics assumed that ",
572 "the view dimension will be equal to `{}` rather than `{:?}`.\n",
573 "`D2` textures with ",
574 "`depth_or_array_layers == 1` ",
575 "are assumed to have view dimension `D2`\n",
576 "`D2` textures with ",
577 "`depth_or_array_layers > 1` ",
578 "are assumed to have view dimension `D2Array`\n",
579 "`D2` textures with ",
580 "`depth_or_array_layers == 6` ",
581 "are assumed to have view dimension `Cube`\n",
582 "`D2` textures with ",
583 "`depth_or_array_layers > 6 && depth_or_array_layers % 6 == 0` ",
584 "are assumed to have view dimension `CubeArray`\n",
585 ),
586 got,
587 view_dimension,
588 );
589 }
590}
591
592#[derive(Clone, Debug)]
593pub struct TextureView {
594 inner: TextureInner,
595 aspects: crate::FormatAspects,
596 mip_levels: Range<u32>,
597 array_layers: Range<u32>,
598 format: wgt::TextureFormat,
599}
600
601impl crate::DynTextureView for TextureView {}
602
603#[derive(Debug)]
604pub struct Sampler {
605 raw: glow::Sampler,
606}
607
608impl crate::DynSampler for Sampler {}
609
610#[derive(Debug)]
611pub struct BindGroupLayout {
612 entries: Arc<[wgt::BindGroupLayoutEntry]>,
613}
614
615impl crate::DynBindGroupLayout for BindGroupLayout {}
616
617#[derive(Debug)]
618struct BindGroupLayoutInfo {
619 entries: Arc<[wgt::BindGroupLayoutEntry]>,
620 binding_to_slot: Box<[u8]>,
626}
627
628#[derive(Debug)]
629pub struct PipelineLayout {
630 group_infos: Box<[Option<BindGroupLayoutInfo>]>,
631 naga_options: naga::back::glsl::Options,
632}
633
634impl crate::DynPipelineLayout for PipelineLayout {}
635
636impl PipelineLayout {
637 fn get_slot(&self, br: &naga::ResourceBinding) -> u8 {
641 let group_info = self.group_infos[br.group as usize].as_ref().unwrap();
642 group_info.binding_to_slot[br.binding as usize]
643 }
644}
645
646#[derive(Debug)]
647enum BindingRegister {
648 UniformBuffers,
649 StorageBuffers,
650 Textures,
651 Images,
652}
653
654#[derive(Debug)]
655enum RawBinding {
656 Buffer {
657 raw: glow::Buffer,
658 offset: i32,
659 size: i32,
660 },
661 Texture {
662 raw: glow::Texture,
663 target: BindTarget,
664 aspects: crate::FormatAspects,
665 mip_levels: Range<u32>,
666 },
668 Image(ImageBinding),
669 Sampler(glow::Sampler),
670}
671
672#[derive(Debug)]
673pub struct BindGroup {
674 contents: Box<[RawBinding]>,
675}
676
677impl crate::DynBindGroup for BindGroup {}
678
679type ShaderId = u32;
680
681#[derive(Debug)]
682pub enum ShaderModuleSource {
683 Naga(crate::NagaShader),
684 Passthrough { source: String },
685}
686
687#[derive(Debug)]
688pub struct ShaderModule {
689 source: ShaderModuleSource,
690 label: Option<String>,
691 id: ShaderId,
692}
693
694impl crate::DynShaderModule for ShaderModule {}
695
696#[derive(Clone, Debug, Default)]
697struct VertexFormatDesc {
698 element_count: i32,
699 element_format: u32,
700 attrib_kind: VertexAttribKind,
701}
702
703#[derive(Clone, Debug, Default)]
704struct AttributeDesc {
705 location: u32,
706 offset: u32,
707 buffer_index: u32,
708 format_desc: VertexFormatDesc,
709}
710
711#[derive(Clone, Debug)]
712struct BufferBinding {
713 raw: glow::Buffer,
714 offset: wgt::BufferAddress,
715}
716
717#[derive(Clone, Debug)]
718struct ImageBinding {
719 raw: glow::Texture,
720 mip_level: u32,
721 array_layer: Option<u32>,
722 access: u32,
723 format: u32,
724}
725
726#[derive(Clone, Debug, Default, PartialEq)]
727struct VertexBufferDesc {
728 step: wgt::VertexStepMode,
729 stride: u32,
730}
731
732#[derive(Clone, Debug)]
733struct ImmediateDesc {
734 location: glow::UniformLocation,
735 ty: nt::glsl::GlslUniformType,
736 offset: u32,
737 size_bytes: u32,
738}
739
740#[cfg(send_sync)]
741unsafe impl Sync for ImmediateDesc {}
742#[cfg(send_sync)]
743unsafe impl Send for ImmediateDesc {}
744
745type SamplerBindMap = [Option<u8>; MAX_TEXTURE_SLOTS];
748
749#[derive(Debug)]
750struct PipelineInner {
751 program: glow::Program,
752 sampler_map: SamplerBindMap,
753 first_instance_location: Option<glow::UniformLocation>,
754 immediates_descs: ArrayVec<ImmediateDesc, MAX_IMMEDIATES_COMMANDS>,
755 clip_distance_count: u32,
756}
757
758#[cfg(send_sync)]
759unsafe impl Sync for PipelineInner {}
760#[cfg(send_sync)]
761unsafe impl Send for PipelineInner {}
762
763#[derive(Clone, Debug)]
764struct DepthState {
765 function: u32,
766 mask: bool,
767}
768
769#[derive(Clone, Debug, PartialEq)]
770struct BlendComponent {
771 src: u32,
772 dst: u32,
773 equation: u32,
774}
775
776#[derive(Clone, Debug, PartialEq)]
777struct BlendDesc {
778 alpha: BlendComponent,
779 color: BlendComponent,
780}
781
782#[derive(Clone, Debug, Default, PartialEq)]
783struct ColorTargetDesc {
784 mask: wgt::ColorWrites,
785 blend: Option<BlendDesc>,
786}
787
788#[derive(Debug, PartialEq, Eq, Hash)]
789struct ProgramStage {
790 naga_stage: naga::ShaderStage,
791 shader_id: ShaderId,
792 entry_point: String,
793 zero_initialize_workgroup_memory: bool,
794 constant_hash: Vec<u8>,
795}
796
797#[derive(Debug, PartialEq, Eq, Hash)]
798struct ProgramCacheKey {
799 stages: ArrayVec<ProgramStage, 3>,
800 group_to_binding_to_slot: Box<[Option<Box<[u8]>>]>,
801}
802
803type ProgramCache = FastHashMap<ProgramCacheKey, Result<Arc<PipelineInner>, crate::PipelineError>>;
804
805#[derive(Debug)]
806pub struct RenderPipeline {
807 inner: Arc<PipelineInner>,
808 primitive: wgt::PrimitiveState,
809 vertex_buffers: Box<[Option<VertexBufferDesc>]>,
810 vertex_attributes: Box<[AttributeDesc]>,
811 color_targets: Box<[ColorTargetDesc]>,
812 depth: Option<DepthState>,
813 depth_bias: wgt::DepthBiasState,
814 stencil: Option<StencilState>,
815 alpha_to_coverage_enabled: bool,
816}
817
818impl crate::DynRenderPipeline for RenderPipeline {}
819
820#[cfg(send_sync)]
821static_assertions::assert_impl_all!(RenderPipeline: Send, Sync);
822
823#[derive(Debug)]
824pub struct ComputePipeline {
825 inner: Arc<PipelineInner>,
826}
827
828impl crate::DynComputePipeline for ComputePipeline {}
829
830#[derive(Debug)]
831pub struct RayTracingPipeline {}
832
833impl crate::DynRayTracingPipeline for RayTracingPipeline {}
834
835#[cfg(send_sync)]
836static_assertions::assert_impl_all!(ComputePipeline: Send, Sync);
837
838#[derive(Debug)]
839pub struct QuerySet {
840 queries: Box<[glow::Query]>,
841 target: BindTarget,
842}
843
844impl crate::DynQuerySet for QuerySet {}
845
846#[derive(Debug)]
847pub struct AccelerationStructure;
848
849impl crate::DynAccelerationStructure for AccelerationStructure {}
850
851#[derive(Debug)]
852pub struct PipelineCache;
853
854impl crate::DynPipelineCache for PipelineCache {}
855
856#[derive(Clone, Debug, PartialEq)]
857struct StencilOps {
858 pass: u32,
859 fail: u32,
860 depth_fail: u32,
861}
862
863impl Default for StencilOps {
864 fn default() -> Self {
865 Self {
866 pass: glow::KEEP,
867 fail: glow::KEEP,
868 depth_fail: glow::KEEP,
869 }
870 }
871}
872
873#[derive(Clone, Debug, PartialEq)]
874struct StencilSide {
875 function: u32,
876 mask_read: u32,
877 mask_write: u32,
878 reference: u32,
879 ops: StencilOps,
880}
881
882impl Default for StencilSide {
883 fn default() -> Self {
884 Self {
885 function: glow::ALWAYS,
886 mask_read: 0xFF,
887 mask_write: 0xFF,
888 reference: 0,
889 ops: StencilOps::default(),
890 }
891 }
892}
893
894#[derive(Debug, Clone, Default)]
895struct StencilState {
896 front: StencilSide,
897 back: StencilSide,
898}
899
900#[derive(Clone, Debug, Default, PartialEq)]
901struct PrimitiveState {
902 front_face: u32,
903 cull_face: u32,
904 unclipped_depth: bool,
905 polygon_mode: u32,
906}
907
908type InvalidatedAttachments = ArrayVec<u32, { crate::MAX_COLOR_ATTACHMENTS + 2 }>;
909
910#[derive(Debug)]
911enum Command {
912 Draw {
913 topology: u32,
914 first_vertex: u32,
915 vertex_count: u32,
916 first_instance: u32,
917 instance_count: u32,
918 first_instance_location: Option<glow::UniformLocation>,
919 },
920 DrawIndexed {
921 topology: u32,
922 index_type: u32,
923 index_count: u32,
924 index_offset: wgt::BufferAddress,
925 base_vertex: i32,
926 first_instance: u32,
927 instance_count: u32,
928 first_instance_location: Option<glow::UniformLocation>,
929 },
930 DrawIndirect {
931 topology: u32,
932 indirect_buf: glow::Buffer,
933 indirect_offset: wgt::BufferAddress,
934 first_instance_location: Option<glow::UniformLocation>,
935 },
936 DrawIndexedIndirect {
937 topology: u32,
938 index_type: u32,
939 indirect_buf: glow::Buffer,
940 indirect_offset: wgt::BufferAddress,
941 first_instance_location: Option<glow::UniformLocation>,
942 },
943 Dispatch([u32; 3]),
944 DispatchIndirect {
945 indirect_buf: glow::Buffer,
946 indirect_offset: wgt::BufferAddress,
947 },
948 ClearBuffer {
949 dst: Buffer,
950 dst_target: BindTarget,
951 range: crate::MemoryRange,
952 },
953 CopyBufferToBuffer {
954 src: Buffer,
955 src_target: BindTarget,
956 dst: Buffer,
957 dst_target: BindTarget,
958 copy: crate::BufferCopy,
959 },
960 #[cfg(webgl)]
961 CopyExternalImageToTexture {
962 src: wgt::CopyExternalImageSourceInfo,
963 dst: glow::Texture,
964 dst_target: BindTarget,
965 dst_format: wgt::TextureFormat,
966 dst_premultiplication: bool,
967 copy: crate::TextureCopy,
968 },
969 CopyTextureToTexture {
970 src: glow::Texture,
971 src_target: BindTarget,
972 dst: glow::Texture,
973 dst_target: BindTarget,
974 copy: crate::TextureCopy,
975 },
976 CopyBufferToTexture {
977 src: Buffer,
978 #[allow(unused)]
979 src_target: BindTarget,
980 dst: glow::Texture,
981 dst_target: BindTarget,
982 dst_format: wgt::TextureFormat,
983 copy: crate::BufferTextureCopy,
984 },
985 CopyTextureToBuffer {
986 src: glow::Texture,
987 src_target: BindTarget,
988 src_format: wgt::TextureFormat,
989 dst: Buffer,
990 #[allow(unused)]
991 dst_target: BindTarget,
992 copy: crate::BufferTextureCopy,
993 },
994 SetIndexBuffer(glow::Buffer),
995 BeginQuery(glow::Query, BindTarget),
996 EndQuery(BindTarget),
997 TimestampQuery(glow::Query),
998 CopyQueryResults {
999 query_range: Range<u32>,
1000 dst: Buffer,
1001 dst_target: BindTarget,
1002 dst_offset: wgt::BufferAddress,
1003 },
1004 ResetFramebuffer {
1005 is_default: bool,
1006 },
1007 BindAttachment {
1008 attachment: u32,
1009 view: TextureView,
1010 depth_slice: Option<u32>,
1011 sample_count: u32,
1012 },
1013 ResolveAttachment {
1014 attachment: u32,
1015 dst: TextureView,
1016 size: wgt::Extent3d,
1017 },
1018 InvalidateAttachments(InvalidatedAttachments),
1019 SetDrawColorBuffers(u8),
1020 ClearColorF {
1021 draw_buffer: u32,
1022 color: [f32; 4],
1023 is_srgb: bool,
1024 },
1025 ClearColorU(u32, [u32; 4]),
1026 ClearColorI(u32, [i32; 4]),
1027 ClearDepth(f32),
1028 ClearStencil(u32),
1029 ClearDepthAndStencil(f32, u32),
1034 BufferBarrier(glow::Buffer, wgt::BufferUses),
1035 TextureBarrier(wgt::TextureUses),
1036 SetViewport {
1037 rect: crate::Rect<i32>,
1038 depth: Range<f32>,
1039 },
1040 SetScissor(crate::Rect<i32>),
1041 SetStencilFunc {
1042 face: u32,
1043 function: u32,
1044 reference: u32,
1045 read_mask: u32,
1046 },
1047 SetStencilOps {
1048 face: u32,
1049 write_mask: u32,
1050 ops: StencilOps,
1051 },
1052 SetDepth(DepthState),
1053 SetDepthBias(wgt::DepthBiasState),
1054 ConfigureDepthStencil(crate::FormatAspects),
1055 SetAlphaToCoverage(bool),
1056 SetVertexAttribute {
1057 buffer: Option<glow::Buffer>,
1058 buffer_desc: VertexBufferDesc,
1059 attribute_desc: AttributeDesc,
1060 },
1061 UnsetVertexAttribute(u32),
1062 SetVertexBuffer {
1063 index: u32,
1064 buffer: BufferBinding,
1065 buffer_desc: VertexBufferDesc,
1066 },
1067 SetProgram(glow::Program),
1068 SetPrimitive(PrimitiveState),
1069 SetBlendConstant([f32; 4]),
1070 SetColorTarget {
1071 draw_buffer_index: Option<u32>,
1072 desc: ColorTargetDesc,
1073 },
1074 BindBuffer {
1075 target: BindTarget,
1076 slot: u32,
1077 buffer: glow::Buffer,
1078 offset: i32,
1079 size: i32,
1080 },
1081 BindSampler(u32, Option<glow::Sampler>),
1082 BindTexture {
1083 slot: u32,
1084 texture: glow::Texture,
1085 target: BindTarget,
1086 aspects: crate::FormatAspects,
1087 mip_levels: Range<u32>,
1088 },
1089 BindImage {
1090 slot: u32,
1091 binding: ImageBinding,
1092 },
1093 InsertDebugMarker(Range<u32>),
1094 PushDebugGroup(Range<u32>),
1095 PopDebugGroup,
1096 SetImmediates {
1097 uniform: ImmediateDesc,
1098 offset: u32,
1100 },
1101 SetClipDistances {
1102 old_count: u32,
1103 new_count: u32,
1104 },
1105}
1106
1107#[derive(Default)]
1108pub struct CommandBuffer {
1109 label: Option<String>,
1110 commands: Vec<Command>,
1111 data_bytes: Vec<u8>,
1112 queries: Vec<glow::Query>,
1113}
1114
1115impl crate::DynCommandBuffer for CommandBuffer {}
1116
1117impl fmt::Debug for CommandBuffer {
1118 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1119 let mut builder = f.debug_struct("CommandBuffer");
1120 if let Some(ref label) = self.label {
1121 builder.field("label", label);
1122 }
1123 builder.finish()
1124 }
1125}
1126
1127#[cfg(send_sync)]
1128unsafe impl Sync for CommandBuffer {}
1129#[cfg(send_sync)]
1130unsafe impl Send for CommandBuffer {}
1131
1132pub struct CommandEncoder {
1137 cmd_buffer: CommandBuffer,
1138 state: command::State,
1139 private_caps: PrivateCapabilities,
1140 counters: Arc<wgt::HalCounters>,
1141}
1142
1143impl fmt::Debug for CommandEncoder {
1144 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1145 f.debug_struct("CommandEncoder")
1146 .field("cmd_buffer", &self.cmd_buffer)
1147 .finish()
1148 }
1149}
1150
1151#[cfg(send_sync)]
1152unsafe impl Sync for CommandEncoder {}
1153#[cfg(send_sync)]
1154unsafe impl Send for CommandEncoder {}
1155
1156#[cfg(not(webgl))]
1157fn gl_debug_message_callback(source: u32, gltype: u32, id: u32, severity: u32, message: &str) {
1158 let source_str = match source {
1159 glow::DEBUG_SOURCE_API => "API",
1160 glow::DEBUG_SOURCE_WINDOW_SYSTEM => "Window System",
1161 glow::DEBUG_SOURCE_SHADER_COMPILER => "ShaderCompiler",
1162 glow::DEBUG_SOURCE_THIRD_PARTY => "Third Party",
1163 glow::DEBUG_SOURCE_APPLICATION => "Application",
1164 glow::DEBUG_SOURCE_OTHER => "Other",
1165 _ => unreachable!(),
1166 };
1167
1168 let log_severity = match severity {
1169 glow::DEBUG_SEVERITY_HIGH => log::Level::Error,
1170 glow::DEBUG_SEVERITY_MEDIUM => log::Level::Warn,
1171 glow::DEBUG_SEVERITY_LOW => log::Level::Debug,
1172 glow::DEBUG_SEVERITY_NOTIFICATION => log::Level::Trace,
1173 _ => unreachable!(),
1174 };
1175
1176 let type_str = match gltype {
1177 glow::DEBUG_TYPE_DEPRECATED_BEHAVIOR => "Deprecated Behavior",
1178 glow::DEBUG_TYPE_ERROR => "Error",
1179 glow::DEBUG_TYPE_MARKER => "Marker",
1180 glow::DEBUG_TYPE_OTHER => "Other",
1181 glow::DEBUG_TYPE_PERFORMANCE => "Performance",
1182 glow::DEBUG_TYPE_POP_GROUP => "Pop Group",
1183 glow::DEBUG_TYPE_PORTABILITY => "Portability",
1184 glow::DEBUG_TYPE_PUSH_GROUP => "Push Group",
1185 glow::DEBUG_TYPE_UNDEFINED_BEHAVIOR => "Undefined Behavior",
1186 _ => unreachable!(),
1187 };
1188
1189 let _ = std::panic::catch_unwind(|| {
1190 log::log!(
1191 log_severity,
1192 "GLES: [{source_str}/{type_str}] ID {id} : {message}"
1193 );
1194 });
1195
1196 #[cfg(feature = "validation_canary")]
1197 if cfg!(debug_assertions) && log_severity == log::Level::Error {
1198 crate::VALIDATION_CANARY.add(message.to_string());
1200 }
1201}