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