1use super::{conv::is_layered_target, Command as C, PrivateCapabilities};
2use arrayvec::ArrayVec;
3use glow::HasContext;
4use std::{mem, slice, sync::Arc};
5
6#[cfg(not(target_arch = "wasm32"))]
7const DEBUG_ID: u32 = 0;
8
9#[cfg(not(target_arch = "wasm32"))]
10fn extract_marker<'a>(data: &'a [u8], range: &std::ops::Range<u32>) -> &'a str {
11 std::str::from_utf8(&data[range.start as usize..range.end as usize]).unwrap()
12}
13
14fn get_2d_target(target: u32, array_layer: u32) -> u32 {
15 const CUBEMAP_FACES: [u32; 6] = [
16 glow::TEXTURE_CUBE_MAP_POSITIVE_X,
17 glow::TEXTURE_CUBE_MAP_NEGATIVE_X,
18 glow::TEXTURE_CUBE_MAP_POSITIVE_Y,
19 glow::TEXTURE_CUBE_MAP_NEGATIVE_Y,
20 glow::TEXTURE_CUBE_MAP_POSITIVE_Z,
21 glow::TEXTURE_CUBE_MAP_NEGATIVE_Z,
22 ];
23
24 match target {
25 glow::TEXTURE_2D => target,
26 glow::TEXTURE_CUBE_MAP => CUBEMAP_FACES[array_layer as usize],
27 _ => unreachable!(),
28 }
29}
30
31fn get_z_offset(target: u32, base: &crate::TextureCopyBase) -> u32 {
32 match target {
33 glow::TEXTURE_2D_ARRAY | glow::TEXTURE_CUBE_MAP_ARRAY => base.array_layer,
34 glow::TEXTURE_3D => base.origin.z,
35 _ => unreachable!(),
36 }
37}
38
39impl super::Queue {
40 unsafe fn perform_shader_clear(&self, gl: &glow::Context, draw_buffer: u32, color: [f32; 4]) {
42 unsafe { gl.use_program(Some(self.shader_clear_program)) };
43 unsafe {
44 gl.uniform_4_f32(
45 Some(&self.shader_clear_program_color_uniform_location),
46 color[0],
47 color[1],
48 color[2],
49 color[3],
50 )
51 };
52 unsafe { gl.disable(glow::DEPTH_TEST) };
53 unsafe { gl.disable(glow::STENCIL_TEST) };
54 unsafe { gl.disable(glow::SCISSOR_TEST) };
55 unsafe { gl.disable(glow::BLEND) };
56 unsafe { gl.disable(glow::CULL_FACE) };
57 unsafe { gl.draw_buffers(&[glow::COLOR_ATTACHMENT0 + draw_buffer]) };
58 unsafe { gl.draw_arrays(glow::TRIANGLES, 0, 3) };
59
60 if self.draw_buffer_count != 0 {
61 let indices = (0..self.draw_buffer_count as u32)
63 .map(|i| glow::COLOR_ATTACHMENT0 + i)
64 .collect::<ArrayVec<_, { crate::MAX_COLOR_ATTACHMENTS }>>();
65 unsafe { gl.draw_buffers(&indices) };
66 }
67 }
68
69 unsafe fn reset_state(&mut self, gl: &glow::Context) {
70 unsafe { gl.use_program(None) };
71 unsafe { gl.bind_framebuffer(glow::FRAMEBUFFER, None) };
72 unsafe { gl.disable(glow::DEPTH_TEST) };
73 unsafe { gl.disable(glow::STENCIL_TEST) };
74 unsafe { gl.disable(glow::SCISSOR_TEST) };
75 unsafe { gl.disable(glow::BLEND) };
76 unsafe { gl.disable(glow::CULL_FACE) };
77 unsafe { gl.disable(glow::POLYGON_OFFSET_FILL) };
78 unsafe { gl.disable(glow::SAMPLE_ALPHA_TO_COVERAGE) };
79 if self.features.contains(wgt::Features::DEPTH_CLIP_CONTROL) {
80 unsafe { gl.disable(glow::DEPTH_CLAMP) };
81 }
82
83 unsafe { gl.bind_buffer(glow::ELEMENT_ARRAY_BUFFER, None) };
84 self.current_index_buffer = None;
85 }
86
87 unsafe fn set_attachment(
88 &self,
89 gl: &glow::Context,
90 fbo_target: u32,
91 attachment: u32,
92 view: &super::TextureView,
93 ) {
94 match view.inner {
95 super::TextureInner::Renderbuffer { raw } => {
96 unsafe {
97 gl.framebuffer_renderbuffer(
98 fbo_target,
99 attachment,
100 glow::RENDERBUFFER,
101 Some(raw),
102 )
103 };
104 }
105 super::TextureInner::DefaultRenderbuffer => panic!("Unexpected default RBO"),
106 super::TextureInner::Texture { raw, target } => {
107 let num_layers = view.array_layers.end - view.array_layers.start;
108 if num_layers > 1 {
109 #[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
110 unsafe {
111 gl.framebuffer_texture_multiview_ovr(
112 fbo_target,
113 attachment,
114 Some(raw),
115 view.mip_levels.start as i32,
116 view.array_layers.start as i32,
117 num_layers as i32,
118 )
119 };
120 } else if is_layered_target(target) {
121 unsafe {
122 gl.framebuffer_texture_layer(
123 fbo_target,
124 attachment,
125 Some(raw),
126 view.mip_levels.start as i32,
127 view.array_layers.start as i32,
128 )
129 };
130 } else {
131 unsafe {
132 gl.framebuffer_texture_2d(
133 fbo_target,
134 attachment,
135 get_2d_target(target, view.array_layers.start),
136 Some(raw),
137 view.mip_levels.start as i32,
138 )
139 };
140 }
141 }
142 #[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))]
143 super::TextureInner::ExternalFramebuffer { ref inner } => unsafe {
144 gl.bind_external_framebuffer(glow::FRAMEBUFFER, inner);
145 },
146 }
147 }
148
149 unsafe fn process(
150 &mut self,
151 gl: &glow::Context,
152 command: &C,
153 #[cfg_attr(target_arch = "wasm32", allow(unused))] data_bytes: &[u8],
154 queries: &[glow::Query],
155 ) {
156 match *command {
157 C::Draw {
158 topology,
159 start_vertex,
160 vertex_count,
161 instance_count,
162 } => {
163 unsafe {
167 gl.draw_arrays_instanced(
168 topology,
169 start_vertex as i32,
170 vertex_count as i32,
171 instance_count as i32,
172 )
173 };
174 }
175 C::DrawIndexed {
176 topology,
177 index_type,
178 index_count,
179 index_offset,
180 base_vertex,
181 instance_count,
182 } => {
183 match base_vertex {
184 0 => unsafe {
188 gl.draw_elements_instanced(
189 topology,
190 index_count as i32,
191 index_type,
192 index_offset as i32,
193 instance_count as i32,
194 )
195 },
196 _ => unsafe {
197 gl.draw_elements_instanced_base_vertex(
198 topology,
199 index_count as _,
200 index_type,
201 index_offset as i32,
202 instance_count as i32,
203 base_vertex,
204 )
205 },
206 }
207 }
208 C::DrawIndirect {
209 topology,
210 indirect_buf,
211 indirect_offset,
212 } => {
213 unsafe { gl.bind_buffer(glow::DRAW_INDIRECT_BUFFER, Some(indirect_buf)) };
214 unsafe { gl.draw_arrays_indirect_offset(topology, indirect_offset as i32) };
215 }
216 C::DrawIndexedIndirect {
217 topology,
218 index_type,
219 indirect_buf,
220 indirect_offset,
221 } => {
222 unsafe { gl.bind_buffer(glow::DRAW_INDIRECT_BUFFER, Some(indirect_buf)) };
223 unsafe {
224 gl.draw_elements_indirect_offset(topology, index_type, indirect_offset as i32)
225 };
226 }
227 C::Dispatch(group_counts) => {
228 unsafe { gl.dispatch_compute(group_counts[0], group_counts[1], group_counts[2]) };
229 }
230 C::DispatchIndirect {
231 indirect_buf,
232 indirect_offset,
233 } => {
234 unsafe { gl.bind_buffer(glow::DISPATCH_INDIRECT_BUFFER, Some(indirect_buf)) };
235 unsafe { gl.dispatch_compute_indirect(indirect_offset as i32) };
236 }
237 C::ClearBuffer {
238 ref dst,
239 dst_target,
240 ref range,
241 } => match dst.raw {
242 Some(buffer) => {
243 let can_use_zero_buffer = self
252 .shared
253 .private_caps
254 .contains(super::PrivateCapabilities::INDEX_BUFFER_ROLE_CHANGE)
255 || dst_target != glow::ELEMENT_ARRAY_BUFFER;
256
257 if can_use_zero_buffer {
258 unsafe { gl.bind_buffer(glow::COPY_READ_BUFFER, Some(self.zero_buffer)) };
259 unsafe { gl.bind_buffer(dst_target, Some(buffer)) };
260 let mut dst_offset = range.start;
261 while dst_offset < range.end {
262 let size = (range.end - dst_offset).min(super::ZERO_BUFFER_SIZE as u64);
263 unsafe {
264 gl.copy_buffer_sub_data(
265 glow::COPY_READ_BUFFER,
266 dst_target,
267 0,
268 dst_offset as i32,
269 size as i32,
270 )
271 };
272 dst_offset += size;
273 }
274 } else {
275 unsafe { gl.bind_buffer(dst_target, Some(buffer)) };
276 let zeroes = vec![0u8; (range.end - range.start) as usize];
277 unsafe {
278 gl.buffer_sub_data_u8_slice(dst_target, range.start as i32, &zeroes)
279 };
280 }
281 }
282 None => {
283 dst.data.as_ref().unwrap().lock().unwrap().as_mut_slice()
284 [range.start as usize..range.end as usize]
285 .fill(0);
286 }
287 },
288 C::CopyBufferToBuffer {
289 ref src,
290 src_target,
291 ref dst,
292 dst_target,
293 copy,
294 } => {
295 let copy_src_target = glow::COPY_READ_BUFFER;
296 let is_index_buffer_only_element_dst = !self
297 .shared
298 .private_caps
299 .contains(super::PrivateCapabilities::INDEX_BUFFER_ROLE_CHANGE)
300 && dst_target == glow::ELEMENT_ARRAY_BUFFER
301 || src_target == glow::ELEMENT_ARRAY_BUFFER;
302
303 let copy_dst_target = if is_index_buffer_only_element_dst {
305 glow::ELEMENT_ARRAY_BUFFER
306 } else {
307 glow::COPY_WRITE_BUFFER
308 };
309 let size = copy.size.get() as usize;
310 match (src.raw, dst.raw) {
311 (Some(ref src), Some(ref dst)) => {
312 unsafe { gl.bind_buffer(copy_src_target, Some(*src)) };
313 unsafe { gl.bind_buffer(copy_dst_target, Some(*dst)) };
314 unsafe {
315 gl.copy_buffer_sub_data(
316 copy_src_target,
317 copy_dst_target,
318 copy.src_offset as _,
319 copy.dst_offset as _,
320 copy.size.get() as _,
321 )
322 };
323 }
324 (Some(src), None) => {
325 let mut data = dst.data.as_ref().unwrap().lock().unwrap();
326 let dst_data = &mut data.as_mut_slice()
327 [copy.dst_offset as usize..copy.dst_offset as usize + size];
328
329 unsafe { gl.bind_buffer(copy_src_target, Some(src)) };
330 unsafe {
331 self.shared.get_buffer_sub_data(
332 gl,
333 copy_src_target,
334 copy.src_offset as i32,
335 dst_data,
336 )
337 };
338 }
339 (None, Some(dst)) => {
340 let data = src.data.as_ref().unwrap().lock().unwrap();
341 let src_data = &data.as_slice()
342 [copy.src_offset as usize..copy.src_offset as usize + size];
343 unsafe { gl.bind_buffer(copy_dst_target, Some(dst)) };
344 unsafe {
345 gl.buffer_sub_data_u8_slice(
346 copy_dst_target,
347 copy.dst_offset as i32,
348 src_data,
349 )
350 };
351 }
352 (None, None) => {
353 todo!()
354 }
355 }
356 unsafe { gl.bind_buffer(copy_src_target, None) };
357 if is_index_buffer_only_element_dst {
358 unsafe {
359 gl.bind_buffer(glow::ELEMENT_ARRAY_BUFFER, self.current_index_buffer)
360 };
361 } else {
362 unsafe { gl.bind_buffer(copy_dst_target, None) };
363 }
364 }
365 #[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))]
366 C::CopyExternalImageToTexture {
367 ref src,
368 dst,
369 dst_target,
370 dst_format,
371 dst_premultiplication,
372 ref copy,
373 } => {
374 const UNPACK_FLIP_Y_WEBGL: u32 =
375 web_sys::WebGl2RenderingContext::UNPACK_FLIP_Y_WEBGL;
376 const UNPACK_PREMULTIPLY_ALPHA_WEBGL: u32 =
377 web_sys::WebGl2RenderingContext::UNPACK_PREMULTIPLY_ALPHA_WEBGL;
378
379 unsafe {
380 if src.flip_y {
381 gl.pixel_store_bool(UNPACK_FLIP_Y_WEBGL, true);
382 }
383 if dst_premultiplication {
384 gl.pixel_store_bool(UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
385 }
386 }
387
388 unsafe { gl.bind_texture(dst_target, Some(dst)) };
389 let format_desc = self.shared.describe_texture_format(dst_format);
390 if is_layered_target(dst_target) {
391 let z_offset = get_z_offset(dst_target, ©.dst_base);
392
393 match src.source {
394 wgt::ExternalImageSource::ImageBitmap(ref b) => unsafe {
395 gl.tex_sub_image_3d_with_image_bitmap(
396 dst_target,
397 copy.dst_base.mip_level as i32,
398 copy.dst_base.origin.x as i32,
399 copy.dst_base.origin.y as i32,
400 z_offset as i32,
401 copy.size.width as i32,
402 copy.size.height as i32,
403 copy.size.depth as i32,
404 format_desc.external,
405 format_desc.data_type,
406 b,
407 );
408 },
409 wgt::ExternalImageSource::HTMLVideoElement(ref v) => unsafe {
410 gl.tex_sub_image_3d_with_html_video_element(
411 dst_target,
412 copy.dst_base.mip_level as i32,
413 copy.dst_base.origin.x as i32,
414 copy.dst_base.origin.y as i32,
415 z_offset as i32,
416 copy.size.width as i32,
417 copy.size.height as i32,
418 copy.size.depth as i32,
419 format_desc.external,
420 format_desc.data_type,
421 v,
422 );
423 },
424 wgt::ExternalImageSource::HTMLCanvasElement(ref c) => unsafe {
425 gl.tex_sub_image_3d_with_html_canvas_element(
426 dst_target,
427 copy.dst_base.mip_level as i32,
428 copy.dst_base.origin.x as i32,
429 copy.dst_base.origin.y as i32,
430 z_offset as i32,
431 copy.size.width as i32,
432 copy.size.height as i32,
433 copy.size.depth as i32,
434 format_desc.external,
435 format_desc.data_type,
436 c,
437 );
438 },
439 wgt::ExternalImageSource::OffscreenCanvas(_) => unreachable!(),
440 }
441 } else {
442 let dst_target = get_2d_target(dst_target, copy.dst_base.array_layer);
443
444 match src.source {
445 wgt::ExternalImageSource::ImageBitmap(ref b) => unsafe {
446 gl.tex_sub_image_2d_with_image_bitmap_and_width_and_height(
447 dst_target,
448 copy.dst_base.mip_level as i32,
449 copy.dst_base.origin.x as i32,
450 copy.dst_base.origin.y as i32,
451 copy.size.width as i32,
452 copy.size.height as i32,
453 format_desc.external,
454 format_desc.data_type,
455 b,
456 );
457 },
458 wgt::ExternalImageSource::HTMLVideoElement(ref v) => unsafe {
459 gl.tex_sub_image_2d_with_html_video_and_width_and_height(
460 dst_target,
461 copy.dst_base.mip_level as i32,
462 copy.dst_base.origin.x as i32,
463 copy.dst_base.origin.y as i32,
464 copy.size.width as i32,
465 copy.size.height as i32,
466 format_desc.external,
467 format_desc.data_type,
468 v,
469 )
470 },
471 wgt::ExternalImageSource::HTMLCanvasElement(ref c) => unsafe {
472 gl.tex_sub_image_2d_with_html_canvas_and_width_and_height(
473 dst_target,
474 copy.dst_base.mip_level as i32,
475 copy.dst_base.origin.x as i32,
476 copy.dst_base.origin.y as i32,
477 copy.size.width as i32,
478 copy.size.height as i32,
479 format_desc.external,
480 format_desc.data_type,
481 c,
482 )
483 },
484 wgt::ExternalImageSource::OffscreenCanvas(_) => unreachable!(),
485 }
486 }
487
488 unsafe {
489 if src.flip_y {
490 gl.pixel_store_bool(UNPACK_FLIP_Y_WEBGL, false);
491 }
492 if dst_premultiplication {
493 gl.pixel_store_bool(UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
494 }
495 }
496 }
497 C::CopyTextureToTexture {
498 src,
499 src_target,
500 dst,
501 dst_target,
502 ref copy,
503 } => {
504 unsafe { gl.bind_framebuffer(glow::READ_FRAMEBUFFER, Some(self.copy_fbo)) };
506 if is_layered_target(src_target) {
507 unsafe {
509 gl.framebuffer_texture_layer(
510 glow::READ_FRAMEBUFFER,
511 glow::COLOR_ATTACHMENT0,
512 Some(src),
513 copy.src_base.mip_level as i32,
514 copy.src_base.array_layer as i32,
515 )
516 };
517 } else {
518 unsafe {
519 gl.framebuffer_texture_2d(
520 glow::READ_FRAMEBUFFER,
521 glow::COLOR_ATTACHMENT0,
522 src_target,
523 Some(src),
524 copy.src_base.mip_level as i32,
525 )
526 };
527 }
528
529 unsafe { gl.bind_texture(dst_target, Some(dst)) };
530 if is_layered_target(dst_target) {
531 unsafe {
532 gl.copy_tex_sub_image_3d(
533 dst_target,
534 copy.dst_base.mip_level as i32,
535 copy.dst_base.origin.x as i32,
536 copy.dst_base.origin.y as i32,
537 get_z_offset(dst_target, ©.dst_base) as i32,
538 copy.src_base.origin.x as i32,
539 copy.src_base.origin.y as i32,
540 copy.size.width as i32,
541 copy.size.height as i32,
542 )
543 };
544 } else {
545 unsafe {
546 gl.copy_tex_sub_image_2d(
547 get_2d_target(dst_target, copy.dst_base.array_layer),
548 copy.dst_base.mip_level as i32,
549 copy.dst_base.origin.x as i32,
550 copy.dst_base.origin.y as i32,
551 copy.src_base.origin.x as i32,
552 copy.src_base.origin.y as i32,
553 copy.size.width as i32,
554 copy.size.height as i32,
555 )
556 };
557 }
558 }
559 C::CopyBufferToTexture {
560 ref src,
561 src_target: _,
562 dst,
563 dst_target,
564 dst_format,
565 ref copy,
566 } => {
567 let (block_width, block_height) = dst_format.block_dimensions();
568 let block_size = dst_format.block_size(None).unwrap();
569 let format_desc = self.shared.describe_texture_format(dst_format);
570 let row_texels = copy
571 .buffer_layout
572 .bytes_per_row
573 .map_or(0, |bpr| block_width * bpr / block_size);
574 let column_texels = copy
575 .buffer_layout
576 .rows_per_image
577 .map_or(0, |rpi| block_height * rpi);
578
579 unsafe { gl.bind_texture(dst_target, Some(dst)) };
580 unsafe { gl.pixel_store_i32(glow::UNPACK_ROW_LENGTH, row_texels as i32) };
581 unsafe { gl.pixel_store_i32(glow::UNPACK_IMAGE_HEIGHT, column_texels as i32) };
582 let mut unbind_unpack_buffer = false;
583 if !dst_format.is_compressed() {
584 let buffer_data;
585 let unpack_data = match src.raw {
586 Some(buffer) => {
587 unsafe { gl.bind_buffer(glow::PIXEL_UNPACK_BUFFER, Some(buffer)) };
588 unbind_unpack_buffer = true;
589 glow::PixelUnpackData::BufferOffset(copy.buffer_layout.offset as u32)
590 }
591 None => {
592 buffer_data = src.data.as_ref().unwrap().lock().unwrap();
593 let src_data =
594 &buffer_data.as_slice()[copy.buffer_layout.offset as usize..];
595 glow::PixelUnpackData::Slice(src_data)
596 }
597 };
598 if is_layered_target(dst_target) {
599 unsafe {
600 gl.tex_sub_image_3d(
601 dst_target,
602 copy.texture_base.mip_level as i32,
603 copy.texture_base.origin.x as i32,
604 copy.texture_base.origin.y as i32,
605 get_z_offset(dst_target, ©.texture_base) as i32,
606 copy.size.width as i32,
607 copy.size.height as i32,
608 copy.size.depth as i32,
609 format_desc.external,
610 format_desc.data_type,
611 unpack_data,
612 )
613 };
614 } else {
615 unsafe {
616 gl.tex_sub_image_2d(
617 get_2d_target(dst_target, copy.texture_base.array_layer),
618 copy.texture_base.mip_level as i32,
619 copy.texture_base.origin.x as i32,
620 copy.texture_base.origin.y as i32,
621 copy.size.width as i32,
622 copy.size.height as i32,
623 format_desc.external,
624 format_desc.data_type,
625 unpack_data,
626 )
627 };
628 }
629 } else {
630 let bytes_per_row = copy
631 .buffer_layout
632 .bytes_per_row
633 .unwrap_or(copy.size.width * block_size);
634 let minimum_rows_per_image =
635 (copy.size.height + block_height - 1) / block_height;
636 let rows_per_image = copy
637 .buffer_layout
638 .rows_per_image
639 .unwrap_or(minimum_rows_per_image);
640
641 let bytes_per_image = bytes_per_row * rows_per_image;
642 let minimum_bytes_per_image = bytes_per_row * minimum_rows_per_image;
643 let bytes_in_upload =
644 (bytes_per_image * (copy.size.depth - 1)) + minimum_bytes_per_image;
645 let offset = copy.buffer_layout.offset as u32;
646
647 let buffer_data;
648 let unpack_data = match src.raw {
649 Some(buffer) => {
650 unsafe { gl.bind_buffer(glow::PIXEL_UNPACK_BUFFER, Some(buffer)) };
651 unbind_unpack_buffer = true;
652 glow::CompressedPixelUnpackData::BufferRange(
653 offset..offset + bytes_in_upload,
654 )
655 }
656 None => {
657 buffer_data = src.data.as_ref().unwrap().lock().unwrap();
658 let src_data = &buffer_data.as_slice()
659 [(offset as usize)..(offset + bytes_in_upload) as usize];
660 glow::CompressedPixelUnpackData::Slice(src_data)
661 }
662 };
663
664 if is_layered_target(dst_target) {
665 unsafe {
666 gl.compressed_tex_sub_image_3d(
667 dst_target,
668 copy.texture_base.mip_level as i32,
669 copy.texture_base.origin.x as i32,
670 copy.texture_base.origin.y as i32,
671 get_z_offset(dst_target, ©.texture_base) as i32,
672 copy.size.width as i32,
673 copy.size.height as i32,
674 copy.size.depth as i32,
675 format_desc.internal,
676 unpack_data,
677 )
678 };
679 } else {
680 unsafe {
681 gl.compressed_tex_sub_image_2d(
682 get_2d_target(dst_target, copy.texture_base.array_layer),
683 copy.texture_base.mip_level as i32,
684 copy.texture_base.origin.x as i32,
685 copy.texture_base.origin.y as i32,
686 copy.size.width as i32,
687 copy.size.height as i32,
688 format_desc.internal,
689 unpack_data,
690 )
691 };
692 }
693 }
694 if unbind_unpack_buffer {
695 unsafe { gl.bind_buffer(glow::PIXEL_UNPACK_BUFFER, None) };
696 }
697 }
698 C::CopyTextureToBuffer {
699 src,
700 src_target,
701 src_format,
702 ref dst,
703 dst_target: _,
704 ref copy,
705 } => {
706 let block_size = src_format.block_size(None).unwrap();
707 if src_format.is_compressed() {
708 log::error!("Not implemented yet: compressed texture copy to buffer");
709 return;
710 }
711 if src_target == glow::TEXTURE_CUBE_MAP
712 || src_target == glow::TEXTURE_CUBE_MAP_ARRAY
713 {
714 log::error!("Not implemented yet: cubemap texture copy to buffer");
715 return;
716 }
717 let format_desc = self.shared.describe_texture_format(src_format);
718 let row_texels = copy
719 .buffer_layout
720 .bytes_per_row
721 .map_or(copy.size.width, |bpr| bpr / block_size);
722 let column_texels = copy
723 .buffer_layout
724 .rows_per_image
725 .unwrap_or(copy.size.height);
726
727 unsafe { gl.bind_framebuffer(glow::READ_FRAMEBUFFER, Some(self.copy_fbo)) };
728
729 let read_pixels = |offset| {
730 let mut buffer_data;
731 let unpack_data = match dst.raw {
732 Some(buffer) => {
733 unsafe { gl.pixel_store_i32(glow::PACK_ROW_LENGTH, row_texels as i32) };
734 unsafe { gl.bind_buffer(glow::PIXEL_PACK_BUFFER, Some(buffer)) };
735 glow::PixelPackData::BufferOffset(offset as u32)
736 }
737 None => {
738 buffer_data = dst.data.as_ref().unwrap().lock().unwrap();
739 let dst_data = &mut buffer_data.as_mut_slice()[offset as usize..];
740 glow::PixelPackData::Slice(dst_data)
741 }
742 };
743 unsafe {
744 gl.read_pixels(
745 copy.texture_base.origin.x as i32,
746 copy.texture_base.origin.y as i32,
747 copy.size.width as i32,
748 copy.size.height as i32,
749 format_desc.external,
750 format_desc.data_type,
751 unpack_data,
752 )
753 };
754 };
755
756 match src_target {
757 glow::TEXTURE_2D => {
758 unsafe {
759 gl.framebuffer_texture_2d(
760 glow::READ_FRAMEBUFFER,
761 glow::COLOR_ATTACHMENT0,
762 src_target,
763 Some(src),
764 copy.texture_base.mip_level as i32,
765 )
766 };
767 read_pixels(copy.buffer_layout.offset);
768 }
769 glow::TEXTURE_2D_ARRAY => {
770 unsafe {
771 gl.framebuffer_texture_layer(
772 glow::READ_FRAMEBUFFER,
773 glow::COLOR_ATTACHMENT0,
774 Some(src),
775 copy.texture_base.mip_level as i32,
776 copy.texture_base.array_layer as i32,
777 )
778 };
779 read_pixels(copy.buffer_layout.offset);
780 }
781 glow::TEXTURE_3D => {
782 for z in copy.texture_base.origin.z..copy.size.depth {
783 unsafe {
784 gl.framebuffer_texture_layer(
785 glow::READ_FRAMEBUFFER,
786 glow::COLOR_ATTACHMENT0,
787 Some(src),
788 copy.texture_base.mip_level as i32,
789 z as i32,
790 )
791 };
792 let offset = copy.buffer_layout.offset
793 + (z * block_size * row_texels * column_texels) as u64;
794 read_pixels(offset);
795 }
796 }
797 glow::TEXTURE_CUBE_MAP | glow::TEXTURE_CUBE_MAP_ARRAY => unimplemented!(),
798 _ => unreachable!(),
799 }
800 }
801 C::SetIndexBuffer(buffer) => {
802 unsafe { gl.bind_buffer(glow::ELEMENT_ARRAY_BUFFER, Some(buffer)) };
803 self.current_index_buffer = Some(buffer);
804 }
805 C::BeginQuery(query, target) => {
806 unsafe { gl.begin_query(target, query) };
807 }
808 C::EndQuery(target) => {
809 unsafe { gl.end_query(target) };
810 }
811 C::TimestampQuery(query) => {
812 unsafe { gl.query_counter(query, glow::TIMESTAMP) };
813 }
814 C::CopyQueryResults {
815 ref query_range,
816 ref dst,
817 dst_target,
818 dst_offset,
819 } => {
820 if self
821 .shared
822 .private_caps
823 .contains(PrivateCapabilities::QUERY_BUFFERS)
824 && dst.raw.is_some()
825 {
826 unsafe {
827 let query_size = 8;
830
831 let query_range_size = query_size * query_range.len();
832
833 let buffer = gl.create_buffer().ok();
834 gl.bind_buffer(glow::QUERY_BUFFER, buffer);
835 gl.buffer_data_size(
836 glow::QUERY_BUFFER,
837 query_range_size as _,
838 glow::STREAM_COPY,
839 );
840
841 for (i, &query) in queries
842 [query_range.start as usize..query_range.end as usize]
843 .iter()
844 .enumerate()
845 {
846 gl.get_query_parameter_u64_with_offset(
847 query,
848 glow::QUERY_RESULT,
849 query_size * i,
850 )
851 }
852 gl.bind_buffer(dst_target, dst.raw);
853 gl.copy_buffer_sub_data(
854 glow::QUERY_BUFFER,
855 dst_target,
856 0,
857 dst_offset as _,
858 query_range_size as _,
859 );
860 if let Some(buffer) = buffer {
861 gl.delete_buffer(buffer)
862 }
863 }
864 } else {
865 self.temp_query_results.clear();
866 for &query in
867 queries[query_range.start as usize..query_range.end as usize].iter()
868 {
869 let mut result: u64 = 0;
870 unsafe {
871 let result: *mut u64 = &mut result;
872 gl.get_query_parameter_u64_with_offset(
873 query,
874 glow::QUERY_RESULT,
875 result as usize,
876 )
877 };
878 self.temp_query_results.push(result);
879 }
880 let query_data = unsafe {
881 slice::from_raw_parts(
882 self.temp_query_results.as_ptr() as *const u8,
883 self.temp_query_results.len() * mem::size_of::<u64>(),
884 )
885 };
886 match dst.raw {
887 Some(buffer) => {
888 unsafe { gl.bind_buffer(dst_target, Some(buffer)) };
889 unsafe {
890 gl.buffer_sub_data_u8_slice(
891 dst_target,
892 dst_offset as i32,
893 query_data,
894 )
895 };
896 }
897 None => {
898 let data = &mut dst.data.as_ref().unwrap().lock().unwrap();
899 let len = query_data.len().min(data.len());
900 data[..len].copy_from_slice(&query_data[..len]);
901 }
902 }
903 }
904 }
905 C::ResetFramebuffer { is_default } => {
906 if is_default {
907 unsafe { gl.bind_framebuffer(glow::DRAW_FRAMEBUFFER, None) };
908 } else {
909 unsafe { gl.bind_framebuffer(glow::DRAW_FRAMEBUFFER, Some(self.draw_fbo)) };
910 unsafe {
911 gl.framebuffer_texture_2d(
912 glow::DRAW_FRAMEBUFFER,
913 glow::DEPTH_STENCIL_ATTACHMENT,
914 glow::TEXTURE_2D,
915 None,
916 0,
917 )
918 };
919 for i in 0..crate::MAX_COLOR_ATTACHMENTS {
920 let target = glow::COLOR_ATTACHMENT0 + i as u32;
921 unsafe {
922 gl.framebuffer_texture_2d(
923 glow::DRAW_FRAMEBUFFER,
924 target,
925 glow::TEXTURE_2D,
926 None,
927 0,
928 )
929 };
930 }
931 }
932 unsafe { gl.color_mask(true, true, true, true) };
933 unsafe { gl.depth_mask(true) };
934 unsafe { gl.stencil_mask(!0) };
935 unsafe { gl.disable(glow::DEPTH_TEST) };
936 unsafe { gl.disable(glow::STENCIL_TEST) };
937 unsafe { gl.disable(glow::SCISSOR_TEST) };
938 }
939 C::BindAttachment {
940 attachment,
941 ref view,
942 } => {
943 unsafe { self.set_attachment(gl, glow::DRAW_FRAMEBUFFER, attachment, view) };
944 }
945 C::ResolveAttachment {
946 attachment,
947 ref dst,
948 ref size,
949 } => {
950 unsafe { gl.bind_framebuffer(glow::READ_FRAMEBUFFER, Some(self.draw_fbo)) };
951 unsafe { gl.read_buffer(attachment) };
952 unsafe { gl.bind_framebuffer(glow::DRAW_FRAMEBUFFER, Some(self.copy_fbo)) };
953 unsafe {
954 self.set_attachment(gl, glow::DRAW_FRAMEBUFFER, glow::COLOR_ATTACHMENT0, dst)
955 };
956 unsafe {
957 gl.blit_framebuffer(
958 0,
959 0,
960 size.width as i32,
961 size.height as i32,
962 0,
963 0,
964 size.width as i32,
965 size.height as i32,
966 glow::COLOR_BUFFER_BIT,
967 glow::NEAREST,
968 )
969 };
970 unsafe { gl.bind_framebuffer(glow::READ_FRAMEBUFFER, None) };
971 unsafe { gl.bind_framebuffer(glow::DRAW_FRAMEBUFFER, Some(self.draw_fbo)) };
972 }
973 C::InvalidateAttachments(ref list) => {
974 unsafe { gl.invalidate_framebuffer(glow::DRAW_FRAMEBUFFER, list) };
975 }
976 C::SetDrawColorBuffers(count) => {
977 self.draw_buffer_count = count;
978 let indices = (0..count as u32)
979 .map(|i| glow::COLOR_ATTACHMENT0 + i)
980 .collect::<ArrayVec<_, { crate::MAX_COLOR_ATTACHMENTS }>>();
981 unsafe { gl.draw_buffers(&indices) };
982 }
983 C::ClearColorF {
984 draw_buffer,
985 ref color,
986 is_srgb,
987 } => {
988 if self
989 .shared
990 .workarounds
991 .contains(super::Workarounds::MESA_I915_SRGB_SHADER_CLEAR)
992 && is_srgb
993 {
994 unsafe { self.perform_shader_clear(gl, draw_buffer, *color) };
995 } else {
996 unsafe { gl.clear_buffer_f32_slice(glow::COLOR, draw_buffer, color) };
997 }
998 }
999 C::ClearColorU(draw_buffer, ref color) => {
1000 unsafe { gl.clear_buffer_u32_slice(glow::COLOR, draw_buffer, color) };
1001 }
1002 C::ClearColorI(draw_buffer, ref color) => {
1003 unsafe { gl.clear_buffer_i32_slice(glow::COLOR, draw_buffer, color) };
1004 }
1005 C::ClearDepth(depth) => {
1006 unsafe { gl.clear_buffer_f32_slice(glow::DEPTH, 0, &[depth]) };
1007 }
1008 C::ClearStencil(value) => {
1009 unsafe { gl.clear_buffer_i32_slice(glow::STENCIL, 0, &[value as i32]) };
1010 }
1011 C::ClearDepthAndStencil(depth, stencil_value) => {
1012 unsafe {
1013 gl.clear_buffer_depth_stencil(
1014 glow::DEPTH_STENCIL,
1015 0,
1016 depth,
1017 stencil_value as i32,
1018 )
1019 };
1020 }
1021 C::BufferBarrier(raw, usage) => {
1022 let mut flags = 0;
1023 if usage.contains(crate::BufferUses::VERTEX) {
1024 flags |= glow::VERTEX_ATTRIB_ARRAY_BARRIER_BIT;
1025 unsafe { gl.bind_buffer(glow::ARRAY_BUFFER, Some(raw)) };
1026 unsafe { gl.vertex_attrib_pointer_f32(0, 1, glow::BYTE, true, 0, 0) };
1027 }
1028 if usage.contains(crate::BufferUses::INDEX) {
1029 flags |= glow::ELEMENT_ARRAY_BARRIER_BIT;
1030 unsafe { gl.bind_buffer(glow::ELEMENT_ARRAY_BUFFER, Some(raw)) };
1031 }
1032 if usage.contains(crate::BufferUses::UNIFORM) {
1033 flags |= glow::UNIFORM_BARRIER_BIT;
1034 }
1035 if usage.contains(crate::BufferUses::INDIRECT) {
1036 flags |= glow::COMMAND_BARRIER_BIT;
1037 unsafe { gl.bind_buffer(glow::DRAW_INDIRECT_BUFFER, Some(raw)) };
1038 }
1039 if usage.contains(crate::BufferUses::COPY_SRC) {
1040 flags |= glow::PIXEL_BUFFER_BARRIER_BIT;
1041 unsafe { gl.bind_buffer(glow::PIXEL_UNPACK_BUFFER, Some(raw)) };
1042 }
1043 if usage.contains(crate::BufferUses::COPY_DST) {
1044 flags |= glow::PIXEL_BUFFER_BARRIER_BIT;
1045 unsafe { gl.bind_buffer(glow::PIXEL_PACK_BUFFER, Some(raw)) };
1046 }
1047 if usage.intersects(crate::BufferUses::MAP_READ | crate::BufferUses::MAP_WRITE) {
1048 flags |= glow::BUFFER_UPDATE_BARRIER_BIT;
1049 }
1050 if usage.intersects(
1051 crate::BufferUses::STORAGE_READ | crate::BufferUses::STORAGE_READ_WRITE,
1052 ) {
1053 flags |= glow::SHADER_STORAGE_BARRIER_BIT;
1054 }
1055 unsafe { gl.memory_barrier(flags) };
1056 }
1057 C::TextureBarrier(usage) => {
1058 let mut flags = 0;
1059 if usage.contains(crate::TextureUses::RESOURCE) {
1060 flags |= glow::TEXTURE_FETCH_BARRIER_BIT;
1061 }
1062 if usage.intersects(
1063 crate::TextureUses::STORAGE_READ | crate::TextureUses::STORAGE_READ_WRITE,
1064 ) {
1065 flags |= glow::SHADER_IMAGE_ACCESS_BARRIER_BIT;
1066 }
1067 if usage.contains(crate::TextureUses::COPY_DST) {
1068 flags |= glow::TEXTURE_UPDATE_BARRIER_BIT;
1069 }
1070 if usage.intersects(
1071 crate::TextureUses::COLOR_TARGET
1072 | crate::TextureUses::DEPTH_STENCIL_READ
1073 | crate::TextureUses::DEPTH_STENCIL_WRITE,
1074 ) {
1075 flags |= glow::FRAMEBUFFER_BARRIER_BIT;
1076 }
1077 unsafe { gl.memory_barrier(flags) };
1078 }
1079 C::SetViewport {
1080 ref rect,
1081 ref depth,
1082 } => {
1083 unsafe { gl.viewport(rect.x, rect.y, rect.w, rect.h) };
1084 unsafe { gl.depth_range_f32(depth.start, depth.end) };
1085 }
1086 C::SetScissor(ref rect) => {
1087 unsafe { gl.scissor(rect.x, rect.y, rect.w, rect.h) };
1088 unsafe { gl.enable(glow::SCISSOR_TEST) };
1089 }
1090 C::SetStencilFunc {
1091 face,
1092 function,
1093 reference,
1094 read_mask,
1095 } => {
1096 unsafe { gl.stencil_func_separate(face, function, reference as i32, read_mask) };
1097 }
1098 C::SetStencilOps {
1099 face,
1100 write_mask,
1101 ref ops,
1102 } => {
1103 unsafe { gl.stencil_mask_separate(face, write_mask) };
1104 unsafe { gl.stencil_op_separate(face, ops.fail, ops.depth_fail, ops.pass) };
1105 }
1106 C::SetVertexAttribute {
1107 buffer,
1108 ref buffer_desc,
1109 attribute_desc: ref vat,
1110 } => {
1111 unsafe { gl.bind_buffer(glow::ARRAY_BUFFER, buffer) };
1112 unsafe { gl.enable_vertex_attrib_array(vat.location) };
1113
1114 if buffer.is_none() {
1115 match vat.format_desc.attrib_kind {
1116 super::VertexAttribKind::Float => unsafe {
1117 gl.vertex_attrib_format_f32(
1118 vat.location,
1119 vat.format_desc.element_count,
1120 vat.format_desc.element_format,
1121 true, vat.offset,
1123 )
1124 },
1125 super::VertexAttribKind::Integer => unsafe {
1126 gl.vertex_attrib_format_i32(
1127 vat.location,
1128 vat.format_desc.element_count,
1129 vat.format_desc.element_format,
1130 vat.offset,
1131 )
1132 },
1133 }
1134
1135 unsafe { gl.vertex_attrib_binding(vat.location, vat.buffer_index) };
1138 } else {
1139 match vat.format_desc.attrib_kind {
1140 super::VertexAttribKind::Float => unsafe {
1141 gl.vertex_attrib_pointer_f32(
1142 vat.location,
1143 vat.format_desc.element_count,
1144 vat.format_desc.element_format,
1145 true, buffer_desc.stride as i32,
1147 vat.offset as i32,
1148 )
1149 },
1150 super::VertexAttribKind::Integer => unsafe {
1151 gl.vertex_attrib_pointer_i32(
1152 vat.location,
1153 vat.format_desc.element_count,
1154 vat.format_desc.element_format,
1155 buffer_desc.stride as i32,
1156 vat.offset as i32,
1157 )
1158 },
1159 }
1160 unsafe { gl.vertex_attrib_divisor(vat.location, buffer_desc.step as u32) };
1161 }
1162 }
1163 C::UnsetVertexAttribute(location) => {
1164 unsafe { gl.disable_vertex_attrib_array(location) };
1165 }
1166 C::SetVertexBuffer {
1167 index,
1168 ref buffer,
1169 ref buffer_desc,
1170 } => {
1171 unsafe { gl.vertex_binding_divisor(index, buffer_desc.step as u32) };
1172 unsafe {
1173 gl.bind_vertex_buffer(
1174 index,
1175 Some(buffer.raw),
1176 buffer.offset as i32,
1177 buffer_desc.stride as i32,
1178 )
1179 };
1180 }
1181 C::SetDepth(ref depth) => {
1182 unsafe { gl.depth_func(depth.function) };
1183 unsafe { gl.depth_mask(depth.mask) };
1184 }
1185 C::SetDepthBias(bias) => {
1186 if bias.is_enabled() {
1187 unsafe { gl.enable(glow::POLYGON_OFFSET_FILL) };
1188 unsafe { gl.polygon_offset(bias.slope_scale, bias.constant as f32) };
1189 } else {
1190 unsafe { gl.disable(glow::POLYGON_OFFSET_FILL) };
1191 }
1192 }
1193 C::ConfigureDepthStencil(aspects) => {
1194 if aspects.contains(crate::FormatAspects::DEPTH) {
1195 unsafe { gl.enable(glow::DEPTH_TEST) };
1196 } else {
1197 unsafe { gl.disable(glow::DEPTH_TEST) };
1198 }
1199 if aspects.contains(crate::FormatAspects::STENCIL) {
1200 unsafe { gl.enable(glow::STENCIL_TEST) };
1201 } else {
1202 unsafe { gl.disable(glow::STENCIL_TEST) };
1203 }
1204 }
1205 C::SetAlphaToCoverage(enabled) => {
1206 if enabled {
1207 unsafe { gl.enable(glow::SAMPLE_ALPHA_TO_COVERAGE) };
1208 } else {
1209 unsafe { gl.disable(glow::SAMPLE_ALPHA_TO_COVERAGE) };
1210 }
1211 }
1212 C::SetProgram(program) => {
1213 unsafe { gl.use_program(Some(program)) };
1214 }
1215 C::SetPrimitive(ref state) => {
1216 unsafe { gl.front_face(state.front_face) };
1217 if state.cull_face != 0 {
1218 unsafe { gl.enable(glow::CULL_FACE) };
1219 unsafe { gl.cull_face(state.cull_face) };
1220 } else {
1221 unsafe { gl.disable(glow::CULL_FACE) };
1222 }
1223 if self.features.contains(wgt::Features::DEPTH_CLIP_CONTROL) {
1224 if state.unclipped_depth {
1226 unsafe { gl.enable(glow::DEPTH_CLAMP) };
1227 } else {
1228 unsafe { gl.disable(glow::DEPTH_CLAMP) };
1229 }
1230 }
1231 }
1232 C::SetBlendConstant(c) => {
1233 unsafe { gl.blend_color(c[0], c[1], c[2], c[3]) };
1234 }
1235 C::SetColorTarget {
1236 draw_buffer_index,
1237 desc: super::ColorTargetDesc { mask, ref blend },
1238 } => {
1239 use wgt::ColorWrites as Cw;
1240 if let Some(index) = draw_buffer_index {
1241 unsafe {
1242 gl.color_mask_draw_buffer(
1243 index,
1244 mask.contains(Cw::RED),
1245 mask.contains(Cw::GREEN),
1246 mask.contains(Cw::BLUE),
1247 mask.contains(Cw::ALPHA),
1248 )
1249 };
1250 if let Some(ref blend) = *blend {
1251 unsafe { gl.enable_draw_buffer(glow::BLEND, index) };
1252 if blend.color != blend.alpha {
1253 unsafe {
1254 gl.blend_equation_separate_draw_buffer(
1255 index,
1256 blend.color.equation,
1257 blend.alpha.equation,
1258 )
1259 };
1260 unsafe {
1261 gl.blend_func_separate_draw_buffer(
1262 index,
1263 blend.color.src,
1264 blend.color.dst,
1265 blend.alpha.src,
1266 blend.alpha.dst,
1267 )
1268 };
1269 } else {
1270 unsafe { gl.blend_equation_draw_buffer(index, blend.color.equation) };
1271 unsafe {
1272 gl.blend_func_draw_buffer(index, blend.color.src, blend.color.dst)
1273 };
1274 }
1275 } else {
1276 unsafe { gl.disable_draw_buffer(glow::BLEND, index) };
1277 }
1278 } else {
1279 unsafe {
1280 gl.color_mask(
1281 mask.contains(Cw::RED),
1282 mask.contains(Cw::GREEN),
1283 mask.contains(Cw::BLUE),
1284 mask.contains(Cw::ALPHA),
1285 )
1286 };
1287 if let Some(ref blend) = *blend {
1288 unsafe { gl.enable(glow::BLEND) };
1289 if blend.color != blend.alpha {
1290 unsafe {
1291 gl.blend_equation_separate(
1292 blend.color.equation,
1293 blend.alpha.equation,
1294 )
1295 };
1296 unsafe {
1297 gl.blend_func_separate(
1298 blend.color.src,
1299 blend.color.dst,
1300 blend.alpha.src,
1301 blend.alpha.dst,
1302 )
1303 };
1304 } else {
1305 unsafe { gl.blend_equation(blend.color.equation) };
1306 unsafe { gl.blend_func(blend.color.src, blend.color.dst) };
1307 }
1308 } else {
1309 unsafe { gl.disable(glow::BLEND) };
1310 }
1311 }
1312 }
1313 C::BindBuffer {
1314 target,
1315 slot,
1316 buffer,
1317 offset,
1318 size,
1319 } => {
1320 unsafe { gl.bind_buffer_range(target, slot, Some(buffer), offset, size) };
1321 }
1322 C::BindSampler(texture_index, sampler) => {
1323 unsafe { gl.bind_sampler(texture_index, sampler) };
1324 }
1325 C::BindTexture {
1326 slot,
1327 texture,
1328 target,
1329 aspects,
1330 } => {
1331 unsafe { gl.active_texture(glow::TEXTURE0 + slot) };
1332 unsafe { gl.bind_texture(target, Some(texture)) };
1333
1334 let version = gl.version();
1335 let is_min_es_3_1 = version.is_embedded && (version.major, version.minor) >= (3, 1);
1336 let is_min_4_3 = !version.is_embedded && (version.major, version.minor) >= (4, 3);
1337 if is_min_es_3_1 || is_min_4_3 {
1338 let mode = match aspects {
1339 crate::FormatAspects::DEPTH => Some(glow::DEPTH_COMPONENT),
1340 crate::FormatAspects::STENCIL => Some(glow::STENCIL_INDEX),
1341 _ => None,
1342 };
1343 if let Some(mode) = mode {
1344 unsafe {
1345 gl.tex_parameter_i32(
1346 target,
1347 glow::DEPTH_STENCIL_TEXTURE_MODE,
1348 mode as _,
1349 )
1350 };
1351 }
1352 }
1353 }
1354 C::BindImage { slot, ref binding } => {
1355 unsafe {
1356 gl.bind_image_texture(
1357 slot,
1358 binding.raw,
1359 binding.mip_level as i32,
1360 binding.array_layer.is_none(),
1361 binding.array_layer.unwrap_or_default() as i32,
1362 binding.access,
1363 binding.format,
1364 )
1365 };
1366 }
1367 #[cfg(not(target_arch = "wasm32"))]
1368 C::InsertDebugMarker(ref range) => {
1369 let marker = extract_marker(data_bytes, range);
1370 unsafe {
1371 gl.debug_message_insert(
1372 glow::DEBUG_SOURCE_APPLICATION,
1373 glow::DEBUG_TYPE_MARKER,
1374 DEBUG_ID,
1375 glow::DEBUG_SEVERITY_NOTIFICATION,
1376 marker,
1377 )
1378 };
1379 }
1380 #[cfg(target_arch = "wasm32")]
1381 C::InsertDebugMarker(_) => (),
1382 #[cfg_attr(target_arch = "wasm32", allow(unused))]
1383 C::PushDebugGroup(ref range) => {
1384 #[cfg(not(target_arch = "wasm32"))]
1385 let marker = extract_marker(data_bytes, range);
1386 #[cfg(not(target_arch = "wasm32"))]
1387 unsafe {
1388 gl.push_debug_group(glow::DEBUG_SOURCE_APPLICATION, DEBUG_ID, marker)
1389 };
1390 }
1391 C::PopDebugGroup => {
1392 #[cfg(not(target_arch = "wasm32"))]
1393 unsafe {
1394 gl.pop_debug_group()
1395 };
1396 }
1397 C::SetPushConstants {
1398 ref uniform,
1399 offset,
1400 } => {
1401 fn get_data<T>(data: &[u8], offset: u32) -> &[T] {
1402 let raw = &data[(offset as usize)..];
1403 unsafe {
1404 slice::from_raw_parts(
1405 raw.as_ptr() as *const _,
1406 raw.len() / mem::size_of::<T>(),
1407 )
1408 }
1409 }
1410
1411 let location = uniform.location.as_ref();
1412
1413 match uniform.utype {
1414 glow::FLOAT => {
1415 let data = get_data::<f32>(data_bytes, offset)[0];
1416 unsafe { gl.uniform_1_f32(location, data) };
1417 }
1418 glow::FLOAT_VEC2 => {
1419 let data = get_data::<[f32; 2]>(data_bytes, offset)[0];
1420 unsafe { gl.uniform_2_f32_slice(location, &data) };
1421 }
1422 glow::FLOAT_VEC3 => {
1423 let data = get_data::<[f32; 3]>(data_bytes, offset)[0];
1424 unsafe { gl.uniform_3_f32_slice(location, &data) };
1425 }
1426 glow::FLOAT_VEC4 => {
1427 let data = get_data::<[f32; 4]>(data_bytes, offset)[0];
1428 unsafe { gl.uniform_4_f32_slice(location, &data) };
1429 }
1430 glow::INT => {
1431 let data = get_data::<i32>(data_bytes, offset)[0];
1432 unsafe { gl.uniform_1_i32(location, data) };
1433 }
1434 glow::INT_VEC2 => {
1435 let data = get_data::<[i32; 2]>(data_bytes, offset)[0];
1436 unsafe { gl.uniform_2_i32_slice(location, &data) };
1437 }
1438 glow::INT_VEC3 => {
1439 let data = get_data::<[i32; 3]>(data_bytes, offset)[0];
1440 unsafe { gl.uniform_3_i32_slice(location, &data) };
1441 }
1442 glow::INT_VEC4 => {
1443 let data = get_data::<[i32; 4]>(data_bytes, offset)[0];
1444 unsafe { gl.uniform_4_i32_slice(location, &data) };
1445 }
1446 glow::FLOAT_MAT2 => {
1447 let data = get_data::<[f32; 4]>(data_bytes, offset)[0];
1448 unsafe { gl.uniform_matrix_2_f32_slice(location, false, &data) };
1449 }
1450 glow::FLOAT_MAT3 => {
1451 let data = get_data::<[f32; 9]>(data_bytes, offset)[0];
1452 unsafe { gl.uniform_matrix_3_f32_slice(location, false, &data) };
1453 }
1454 glow::FLOAT_MAT4 => {
1455 let data = get_data::<[f32; 16]>(data_bytes, offset)[0];
1456 unsafe { gl.uniform_matrix_4_f32_slice(location, false, &data) };
1457 }
1458 _ => panic!("Unsupported uniform datatype!"),
1459 }
1460 }
1461 }
1462 }
1463}
1464
1465impl crate::Queue<super::Api> for super::Queue {
1466 unsafe fn submit(
1467 &mut self,
1468 command_buffers: &[&super::CommandBuffer],
1469 signal_fence: Option<(&mut super::Fence, crate::FenceValue)>,
1470 ) -> Result<(), crate::DeviceError> {
1471 let shared = Arc::clone(&self.shared);
1472 let gl = &shared.context.lock();
1473 for cmd_buf in command_buffers.iter() {
1474 unsafe { self.reset_state(gl) };
1479 #[cfg(not(target_arch = "wasm32"))]
1480 if let Some(ref label) = cmd_buf.label {
1481 unsafe { gl.push_debug_group(glow::DEBUG_SOURCE_APPLICATION, DEBUG_ID, label) };
1482 }
1483
1484 for command in cmd_buf.commands.iter() {
1485 unsafe { self.process(gl, command, &cmd_buf.data_bytes, &cmd_buf.queries) };
1486 }
1487
1488 #[cfg(not(target_arch = "wasm32"))]
1489 if cmd_buf.label.is_some() {
1490 unsafe { gl.pop_debug_group() };
1491 }
1492 }
1493
1494 if let Some((fence, value)) = signal_fence {
1495 fence.maintain(gl);
1496 let sync = unsafe { gl.fence_sync(glow::SYNC_GPU_COMMANDS_COMPLETE, 0) }
1497 .map_err(|_| crate::DeviceError::OutOfMemory)?;
1498 fence.pending.push((value, sync));
1499 }
1500
1501 Ok(())
1502 }
1503
1504 unsafe fn present(
1505 &mut self,
1506 surface: &mut super::Surface,
1507 texture: super::Texture,
1508 ) -> Result<(), crate::SurfaceError> {
1509 unsafe { surface.present(texture, &self.shared.context) }
1510 }
1511
1512 unsafe fn get_timestamp_period(&self) -> f32 {
1513 1.0
1514 }
1515}
1516
1517#[cfg(all(
1518 target_arch = "wasm32",
1519 feature = "fragile-send-sync-non-atomic-wasm",
1520 not(target_feature = "atomics")
1521))]
1522unsafe impl Sync for super::Queue {}
1523#[cfg(all(
1524 target_arch = "wasm32",
1525 feature = "fragile-send-sync-non-atomic-wasm",
1526 not(target_feature = "atomics")
1527))]
1528unsafe impl Send for super::Queue {}