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