1use super::{block::DebugInfoInner, helpers};
2use spirv::{Op, Word};
3
4pub(super) enum Signedness {
5 Unsigned = 0,
6 Signed = 1,
7}
8
9pub(super) enum SampleLod {
10 Explicit,
11 Implicit,
12}
13
14pub(super) struct Case {
15 pub value: Word,
16 pub label_id: Word,
17}
18
19impl super::Instruction {
20 pub(super) fn string(name: &str, id: Word) -> Self {
25 let mut instruction = Self::new(Op::String);
26 instruction.set_result(id);
27 instruction.add_operands(helpers::string_to_words(name));
28 instruction
29 }
30
31 pub(super) fn source(
32 source_language: spirv::SourceLanguage,
33 version: u32,
34 source: &Option<DebugInfoInner>,
35 ) -> Self {
36 let mut instruction = Self::new(Op::Source);
37 instruction.add_operand(source_language as u32);
38 instruction.add_operands(helpers::bytes_to_words(&version.to_le_bytes()));
39 if let Some(source) = source.as_ref() {
40 instruction.add_operand(source.source_file_id);
41 instruction.add_operands(helpers::string_to_words(source.source_code));
42 }
43 instruction
44 }
45
46 pub(super) fn source_continued(source: &[u8]) -> Self {
47 let mut instruction = Self::new(Op::SourceContinued);
48 instruction.add_operands(helpers::str_bytes_to_words(source));
49 instruction
50 }
51
52 pub(super) fn source_auto_continued(
53 source_language: spirv::SourceLanguage,
54 version: u32,
55 source: &Option<DebugInfoInner>,
56 ) -> Vec<Self> {
57 let mut instructions = vec![];
58
59 let with_continue = source.as_ref().and_then(|debug_info| {
60 (debug_info.source_code.len() > u16::MAX as usize).then_some(debug_info)
61 });
62 if let Some(debug_info) = with_continue {
63 let mut instruction = Self::new(Op::Source);
64 instruction.add_operand(source_language as u32);
65 instruction.add_operands(helpers::bytes_to_words(&version.to_le_bytes()));
66
67 let words = helpers::string_to_byte_chunks(debug_info.source_code, u16::MAX as usize);
68 instruction.add_operand(debug_info.source_file_id);
69 instruction.add_operands(helpers::str_bytes_to_words(words[0]));
70 instructions.push(instruction);
71 for word_bytes in words[1..].iter() {
72 let instruction_continue = Self::source_continued(word_bytes);
73 instructions.push(instruction_continue);
74 }
75 } else {
76 let instruction = Self::source(source_language, version, source);
77 instructions.push(instruction);
78 }
79 instructions
80 }
81
82 pub(super) fn name(target_id: Word, name: &str) -> Self {
83 let mut instruction = Self::new(Op::Name);
84 instruction.add_operand(target_id);
85 instruction.add_operands(helpers::string_to_words(name));
86 instruction
87 }
88
89 pub(super) fn member_name(target_id: Word, member: Word, name: &str) -> Self {
90 let mut instruction = Self::new(Op::MemberName);
91 instruction.add_operand(target_id);
92 instruction.add_operand(member);
93 instruction.add_operands(helpers::string_to_words(name));
94 instruction
95 }
96
97 pub(super) fn line(file: Word, line: Word, column: Word) -> Self {
98 let mut instruction = Self::new(Op::Line);
99 instruction.add_operand(file);
100 instruction.add_operand(line);
101 instruction.add_operand(column);
102 instruction
103 }
104
105 pub(super) const fn no_line() -> Self {
106 Self::new(Op::NoLine)
107 }
108
109 pub(super) fn decorate(
114 target_id: Word,
115 decoration: spirv::Decoration,
116 operands: &[Word],
117 ) -> Self {
118 let mut instruction = Self::new(Op::Decorate);
119 instruction.add_operand(target_id);
120 instruction.add_operand(decoration as u32);
121 for operand in operands {
122 instruction.add_operand(*operand)
123 }
124 instruction
125 }
126
127 pub(super) fn member_decorate(
128 target_id: Word,
129 member_index: Word,
130 decoration: spirv::Decoration,
131 operands: &[Word],
132 ) -> Self {
133 let mut instruction = Self::new(Op::MemberDecorate);
134 instruction.add_operand(target_id);
135 instruction.add_operand(member_index);
136 instruction.add_operand(decoration as u32);
137 for operand in operands {
138 instruction.add_operand(*operand)
139 }
140 instruction
141 }
142
143 pub(super) fn extension(name: &str) -> Self {
148 let mut instruction = Self::new(Op::Extension);
149 instruction.add_operands(helpers::string_to_words(name));
150 instruction
151 }
152
153 pub(super) fn ext_inst_import(id: Word, name: &str) -> Self {
154 let mut instruction = Self::new(Op::ExtInstImport);
155 instruction.set_result(id);
156 instruction.add_operands(helpers::string_to_words(name));
157 instruction
158 }
159
160 pub(super) fn ext_inst(
161 set_id: Word,
162 op: spirv::GLOp,
163 result_type_id: Word,
164 id: Word,
165 operands: &[Word],
166 ) -> Self {
167 let mut instruction = Self::new(Op::ExtInst);
168 instruction.set_type(result_type_id);
169 instruction.set_result(id);
170 instruction.add_operand(set_id);
171 instruction.add_operand(op as u32);
172 for operand in operands {
173 instruction.add_operand(*operand)
174 }
175 instruction
176 }
177
178 pub(super) fn memory_model(
183 addressing_model: spirv::AddressingModel,
184 memory_model: spirv::MemoryModel,
185 ) -> Self {
186 let mut instruction = Self::new(Op::MemoryModel);
187 instruction.add_operand(addressing_model as u32);
188 instruction.add_operand(memory_model as u32);
189 instruction
190 }
191
192 pub(super) fn entry_point(
193 execution_model: spirv::ExecutionModel,
194 entry_point_id: Word,
195 name: &str,
196 interface_ids: &[Word],
197 ) -> Self {
198 let mut instruction = Self::new(Op::EntryPoint);
199 instruction.add_operand(execution_model as u32);
200 instruction.add_operand(entry_point_id);
201 instruction.add_operands(helpers::string_to_words(name));
202
203 for interface_id in interface_ids {
204 instruction.add_operand(*interface_id);
205 }
206
207 instruction
208 }
209
210 pub(super) fn execution_mode(
211 entry_point_id: Word,
212 execution_mode: spirv::ExecutionMode,
213 args: &[Word],
214 ) -> Self {
215 let mut instruction = Self::new(Op::ExecutionMode);
216 instruction.add_operand(entry_point_id);
217 instruction.add_operand(execution_mode as u32);
218 for arg in args {
219 instruction.add_operand(*arg);
220 }
221 instruction
222 }
223
224 pub(super) fn capability(capability: spirv::Capability) -> Self {
225 let mut instruction = Self::new(Op::Capability);
226 instruction.add_operand(capability as u32);
227 instruction
228 }
229
230 pub(super) fn type_void(id: Word) -> Self {
235 let mut instruction = Self::new(Op::TypeVoid);
236 instruction.set_result(id);
237 instruction
238 }
239
240 pub(super) fn type_bool(id: Word) -> Self {
241 let mut instruction = Self::new(Op::TypeBool);
242 instruction.set_result(id);
243 instruction
244 }
245
246 pub(super) fn type_int(id: Word, width: Word, signedness: Signedness) -> Self {
247 let mut instruction = Self::new(Op::TypeInt);
248 instruction.set_result(id);
249 instruction.add_operand(width);
250 instruction.add_operand(signedness as u32);
251 instruction
252 }
253
254 pub(super) fn type_float(id: Word, width: Word) -> Self {
255 let mut instruction = Self::new(Op::TypeFloat);
256 instruction.set_result(id);
257 instruction.add_operand(width);
258 instruction
259 }
260
261 pub(super) fn type_vector(
262 id: Word,
263 component_type_id: Word,
264 component_count: crate::VectorSize,
265 ) -> Self {
266 let mut instruction = Self::new(Op::TypeVector);
267 instruction.set_result(id);
268 instruction.add_operand(component_type_id);
269 instruction.add_operand(component_count as u32);
270 instruction
271 }
272
273 pub(super) fn type_matrix(
274 id: Word,
275 column_type_id: Word,
276 column_count: crate::VectorSize,
277 ) -> Self {
278 let mut instruction = Self::new(Op::TypeMatrix);
279 instruction.set_result(id);
280 instruction.add_operand(column_type_id);
281 instruction.add_operand(column_count as u32);
282 instruction
283 }
284
285 #[allow(clippy::too_many_arguments)]
286 pub(super) fn type_image(
287 id: Word,
288 sampled_type_id: Word,
289 dim: spirv::Dim,
290 flags: super::ImageTypeFlags,
291 image_format: spirv::ImageFormat,
292 ) -> Self {
293 let mut instruction = Self::new(Op::TypeImage);
294 instruction.set_result(id);
295 instruction.add_operand(sampled_type_id);
296 instruction.add_operand(dim as u32);
297 instruction.add_operand(flags.contains(super::ImageTypeFlags::DEPTH) as u32);
298 instruction.add_operand(flags.contains(super::ImageTypeFlags::ARRAYED) as u32);
299 instruction.add_operand(flags.contains(super::ImageTypeFlags::MULTISAMPLED) as u32);
300 instruction.add_operand(if flags.contains(super::ImageTypeFlags::SAMPLED) {
301 1
302 } else {
303 2
304 });
305 instruction.add_operand(image_format as u32);
306 instruction
307 }
308
309 pub(super) fn type_sampler(id: Word) -> Self {
310 let mut instruction = Self::new(Op::TypeSampler);
311 instruction.set_result(id);
312 instruction
313 }
314
315 pub(super) fn type_acceleration_structure(id: Word) -> Self {
316 let mut instruction = Self::new(Op::TypeAccelerationStructureKHR);
317 instruction.set_result(id);
318 instruction
319 }
320
321 pub(super) fn type_ray_query(id: Word) -> Self {
322 let mut instruction = Self::new(Op::TypeRayQueryKHR);
323 instruction.set_result(id);
324 instruction
325 }
326
327 pub(super) fn type_sampled_image(id: Word, image_type_id: Word) -> Self {
328 let mut instruction = Self::new(Op::TypeSampledImage);
329 instruction.set_result(id);
330 instruction.add_operand(image_type_id);
331 instruction
332 }
333
334 pub(super) fn type_array(id: Word, element_type_id: Word, length_id: Word) -> Self {
335 let mut instruction = Self::new(Op::TypeArray);
336 instruction.set_result(id);
337 instruction.add_operand(element_type_id);
338 instruction.add_operand(length_id);
339 instruction
340 }
341
342 pub(super) fn type_runtime_array(id: Word, element_type_id: Word) -> Self {
343 let mut instruction = Self::new(Op::TypeRuntimeArray);
344 instruction.set_result(id);
345 instruction.add_operand(element_type_id);
346 instruction
347 }
348
349 pub(super) fn type_struct(id: Word, member_ids: &[Word]) -> Self {
350 let mut instruction = Self::new(Op::TypeStruct);
351 instruction.set_result(id);
352
353 for member_id in member_ids {
354 instruction.add_operand(*member_id)
355 }
356
357 instruction
358 }
359
360 pub(super) fn type_pointer(
361 id: Word,
362 storage_class: spirv::StorageClass,
363 type_id: Word,
364 ) -> Self {
365 let mut instruction = Self::new(Op::TypePointer);
366 instruction.set_result(id);
367 instruction.add_operand(storage_class as u32);
368 instruction.add_operand(type_id);
369 instruction
370 }
371
372 pub(super) fn type_function(id: Word, return_type_id: Word, parameter_ids: &[Word]) -> Self {
373 let mut instruction = Self::new(Op::TypeFunction);
374 instruction.set_result(id);
375 instruction.add_operand(return_type_id);
376
377 for parameter_id in parameter_ids {
378 instruction.add_operand(*parameter_id);
379 }
380
381 instruction
382 }
383
384 pub(super) fn constant_null(result_type_id: Word, id: Word) -> Self {
389 let mut instruction = Self::new(Op::ConstantNull);
390 instruction.set_type(result_type_id);
391 instruction.set_result(id);
392 instruction
393 }
394
395 pub(super) fn constant_true(result_type_id: Word, id: Word) -> Self {
396 let mut instruction = Self::new(Op::ConstantTrue);
397 instruction.set_type(result_type_id);
398 instruction.set_result(id);
399 instruction
400 }
401
402 pub(super) fn constant_false(result_type_id: Word, id: Word) -> Self {
403 let mut instruction = Self::new(Op::ConstantFalse);
404 instruction.set_type(result_type_id);
405 instruction.set_result(id);
406 instruction
407 }
408
409 pub(super) fn constant_32bit(result_type_id: Word, id: Word, value: Word) -> Self {
410 Self::constant(result_type_id, id, &[value])
411 }
412
413 pub(super) fn constant_64bit(result_type_id: Word, id: Word, low: Word, high: Word) -> Self {
414 Self::constant(result_type_id, id, &[low, high])
415 }
416
417 pub(super) fn constant(result_type_id: Word, id: Word, values: &[Word]) -> Self {
418 let mut instruction = Self::new(Op::Constant);
419 instruction.set_type(result_type_id);
420 instruction.set_result(id);
421
422 for value in values {
423 instruction.add_operand(*value);
424 }
425
426 instruction
427 }
428
429 pub(super) fn constant_composite(
430 result_type_id: Word,
431 id: Word,
432 constituent_ids: &[Word],
433 ) -> Self {
434 let mut instruction = Self::new(Op::ConstantComposite);
435 instruction.set_type(result_type_id);
436 instruction.set_result(id);
437
438 for constituent_id in constituent_ids {
439 instruction.add_operand(*constituent_id);
440 }
441
442 instruction
443 }
444
445 pub(super) fn variable(
450 result_type_id: Word,
451 id: Word,
452 storage_class: spirv::StorageClass,
453 initializer_id: Option<Word>,
454 ) -> Self {
455 let mut instruction = Self::new(Op::Variable);
456 instruction.set_type(result_type_id);
457 instruction.set_result(id);
458 instruction.add_operand(storage_class as u32);
459
460 if let Some(initializer_id) = initializer_id {
461 instruction.add_operand(initializer_id);
462 }
463
464 instruction
465 }
466
467 pub(super) fn load(
468 result_type_id: Word,
469 id: Word,
470 pointer_id: Word,
471 memory_access: Option<spirv::MemoryAccess>,
472 ) -> Self {
473 let mut instruction = Self::new(Op::Load);
474 instruction.set_type(result_type_id);
475 instruction.set_result(id);
476 instruction.add_operand(pointer_id);
477
478 if let Some(memory_access) = memory_access {
479 instruction.add_operand(memory_access.bits());
480 }
481
482 instruction
483 }
484
485 pub(super) fn atomic_load(
486 result_type_id: Word,
487 id: Word,
488 pointer_id: Word,
489 scope_id: Word,
490 semantics_id: Word,
491 ) -> Self {
492 let mut instruction = Self::new(Op::AtomicLoad);
493 instruction.set_type(result_type_id);
494 instruction.set_result(id);
495 instruction.add_operand(pointer_id);
496 instruction.add_operand(scope_id);
497 instruction.add_operand(semantics_id);
498 instruction
499 }
500
501 pub(super) fn store(
502 pointer_id: Word,
503 value_id: Word,
504 memory_access: Option<spirv::MemoryAccess>,
505 ) -> Self {
506 let mut instruction = Self::new(Op::Store);
507 instruction.add_operand(pointer_id);
508 instruction.add_operand(value_id);
509
510 if let Some(memory_access) = memory_access {
511 instruction.add_operand(memory_access.bits());
512 }
513
514 instruction
515 }
516
517 pub(super) fn atomic_store(
518 pointer_id: Word,
519 scope_id: Word,
520 semantics_id: Word,
521 value_id: Word,
522 ) -> Self {
523 let mut instruction = Self::new(Op::AtomicStore);
524 instruction.add_operand(pointer_id);
525 instruction.add_operand(scope_id);
526 instruction.add_operand(semantics_id);
527 instruction.add_operand(value_id);
528 instruction
529 }
530
531 pub(super) fn access_chain(
532 result_type_id: Word,
533 id: Word,
534 base_id: Word,
535 index_ids: &[Word],
536 ) -> Self {
537 let mut instruction = Self::new(Op::AccessChain);
538 instruction.set_type(result_type_id);
539 instruction.set_result(id);
540 instruction.add_operand(base_id);
541
542 for index_id in index_ids {
543 instruction.add_operand(*index_id);
544 }
545
546 instruction
547 }
548
549 pub(super) fn array_length(
550 result_type_id: Word,
551 id: Word,
552 structure_id: Word,
553 array_member: Word,
554 ) -> Self {
555 let mut instruction = Self::new(Op::ArrayLength);
556 instruction.set_type(result_type_id);
557 instruction.set_result(id);
558 instruction.add_operand(structure_id);
559 instruction.add_operand(array_member);
560 instruction
561 }
562
563 pub(super) fn function(
568 return_type_id: Word,
569 id: Word,
570 function_control: spirv::FunctionControl,
571 function_type_id: Word,
572 ) -> Self {
573 let mut instruction = Self::new(Op::Function);
574 instruction.set_type(return_type_id);
575 instruction.set_result(id);
576 instruction.add_operand(function_control.bits());
577 instruction.add_operand(function_type_id);
578 instruction
579 }
580
581 pub(super) fn function_parameter(result_type_id: Word, id: Word) -> Self {
582 let mut instruction = Self::new(Op::FunctionParameter);
583 instruction.set_type(result_type_id);
584 instruction.set_result(id);
585 instruction
586 }
587
588 pub(super) const fn function_end() -> Self {
589 Self::new(Op::FunctionEnd)
590 }
591
592 pub(super) fn function_call(
593 result_type_id: Word,
594 id: Word,
595 function_id: Word,
596 argument_ids: &[Word],
597 ) -> Self {
598 let mut instruction = Self::new(Op::FunctionCall);
599 instruction.set_type(result_type_id);
600 instruction.set_result(id);
601 instruction.add_operand(function_id);
602
603 for argument_id in argument_ids {
604 instruction.add_operand(*argument_id);
605 }
606
607 instruction
608 }
609
610 pub(super) fn sampled_image(
615 result_type_id: Word,
616 id: Word,
617 image: Word,
618 sampler: Word,
619 ) -> Self {
620 let mut instruction = Self::new(Op::SampledImage);
621 instruction.set_type(result_type_id);
622 instruction.set_result(id);
623 instruction.add_operand(image);
624 instruction.add_operand(sampler);
625 instruction
626 }
627
628 pub(super) fn image_sample(
629 result_type_id: Word,
630 id: Word,
631 lod: SampleLod,
632 sampled_image: Word,
633 coordinates: Word,
634 depth_ref: Option<Word>,
635 ) -> Self {
636 let op = match (lod, depth_ref) {
637 (SampleLod::Explicit, None) => Op::ImageSampleExplicitLod,
638 (SampleLod::Implicit, None) => Op::ImageSampleImplicitLod,
639 (SampleLod::Explicit, Some(_)) => Op::ImageSampleDrefExplicitLod,
640 (SampleLod::Implicit, Some(_)) => Op::ImageSampleDrefImplicitLod,
641 };
642
643 let mut instruction = Self::new(op);
644 instruction.set_type(result_type_id);
645 instruction.set_result(id);
646 instruction.add_operand(sampled_image);
647 instruction.add_operand(coordinates);
648 if let Some(dref) = depth_ref {
649 instruction.add_operand(dref);
650 }
651
652 instruction
653 }
654
655 pub(super) fn image_gather(
656 result_type_id: Word,
657 id: Word,
658 sampled_image: Word,
659 coordinates: Word,
660 component_id: Word,
661 depth_ref: Option<Word>,
662 ) -> Self {
663 let op = match depth_ref {
664 None => Op::ImageGather,
665 Some(_) => Op::ImageDrefGather,
666 };
667
668 let mut instruction = Self::new(op);
669 instruction.set_type(result_type_id);
670 instruction.set_result(id);
671 instruction.add_operand(sampled_image);
672 instruction.add_operand(coordinates);
673 if let Some(dref) = depth_ref {
674 instruction.add_operand(dref);
675 } else {
676 instruction.add_operand(component_id);
677 }
678
679 instruction
680 }
681
682 pub(super) fn image_fetch_or_read(
683 op: Op,
684 result_type_id: Word,
685 id: Word,
686 image: Word,
687 coordinates: Word,
688 ) -> Self {
689 let mut instruction = Self::new(op);
690 instruction.set_type(result_type_id);
691 instruction.set_result(id);
692 instruction.add_operand(image);
693 instruction.add_operand(coordinates);
694 instruction
695 }
696
697 pub(super) fn image_write(image: Word, coordinates: Word, value: Word) -> Self {
698 let mut instruction = Self::new(Op::ImageWrite);
699 instruction.add_operand(image);
700 instruction.add_operand(coordinates);
701 instruction.add_operand(value);
702 instruction
703 }
704
705 pub(super) fn image_texel_pointer(
706 result_type_id: Word,
707 id: Word,
708 image: Word,
709 coordinates: Word,
710 sample: Word,
711 ) -> Self {
712 let mut instruction = Self::new(Op::ImageTexelPointer);
713 instruction.set_type(result_type_id);
714 instruction.set_result(id);
715 instruction.add_operand(image);
716 instruction.add_operand(coordinates);
717 instruction.add_operand(sample);
718 instruction
719 }
720
721 pub(super) fn image_atomic(
722 op: Op,
723 result_type_id: Word,
724 id: Word,
725 pointer: Word,
726 scope_id: Word,
727 semantics_id: Word,
728 value: Word,
729 ) -> Self {
730 let mut instruction = Self::new(op);
731 instruction.set_type(result_type_id);
732 instruction.set_result(id);
733 instruction.add_operand(pointer);
734 instruction.add_operand(scope_id);
735 instruction.add_operand(semantics_id);
736 instruction.add_operand(value);
737 instruction
738 }
739
740 pub(super) fn image_query(op: Op, result_type_id: Word, id: Word, image: Word) -> Self {
741 let mut instruction = Self::new(op);
742 instruction.set_type(result_type_id);
743 instruction.set_result(id);
744 instruction.add_operand(image);
745 instruction
746 }
747
748 #[allow(clippy::too_many_arguments)]
752 pub(super) fn ray_query_initialize(
753 query: Word,
754 acceleration_structure: Word,
755 ray_flags: Word,
756 cull_mask: Word,
757 ray_origin: Word,
758 ray_tmin: Word,
759 ray_dir: Word,
760 ray_tmax: Word,
761 ) -> Self {
762 let mut instruction = Self::new(Op::RayQueryInitializeKHR);
763 instruction.add_operand(query);
764 instruction.add_operand(acceleration_structure);
765 instruction.add_operand(ray_flags);
766 instruction.add_operand(cull_mask);
767 instruction.add_operand(ray_origin);
768 instruction.add_operand(ray_tmin);
769 instruction.add_operand(ray_dir);
770 instruction.add_operand(ray_tmax);
771 instruction
772 }
773
774 pub(super) fn ray_query_proceed(result_type_id: Word, id: Word, query: Word) -> Self {
775 let mut instruction = Self::new(Op::RayQueryProceedKHR);
776 instruction.set_type(result_type_id);
777 instruction.set_result(id);
778 instruction.add_operand(query);
779 instruction
780 }
781
782 pub(super) fn ray_query_get_intersection(
783 op: Op,
784 result_type_id: Word,
785 id: Word,
786 query: Word,
787 intersection: Word,
788 ) -> Self {
789 let mut instruction = Self::new(op);
790 instruction.set_type(result_type_id);
791 instruction.set_result(id);
792 instruction.add_operand(query);
793 instruction.add_operand(intersection);
794 instruction
795 }
796
797 pub(super) fn unary(op: Op, result_type_id: Word, id: Word, value: Word) -> Self {
801 let mut instruction = Self::new(op);
802 instruction.set_type(result_type_id);
803 instruction.set_result(id);
804 instruction.add_operand(value);
805 instruction
806 }
807
808 pub(super) fn composite_construct(
813 result_type_id: Word,
814 id: Word,
815 constituent_ids: &[Word],
816 ) -> Self {
817 let mut instruction = Self::new(Op::CompositeConstruct);
818 instruction.set_type(result_type_id);
819 instruction.set_result(id);
820
821 for constituent_id in constituent_ids {
822 instruction.add_operand(*constituent_id);
823 }
824
825 instruction
826 }
827
828 pub(super) fn composite_extract(
829 result_type_id: Word,
830 id: Word,
831 composite_id: Word,
832 indices: &[Word],
833 ) -> Self {
834 let mut instruction = Self::new(Op::CompositeExtract);
835 instruction.set_type(result_type_id);
836 instruction.set_result(id);
837
838 instruction.add_operand(composite_id);
839 for index in indices {
840 instruction.add_operand(*index);
841 }
842
843 instruction
844 }
845
846 pub(super) fn vector_extract_dynamic(
847 result_type_id: Word,
848 id: Word,
849 vector_id: Word,
850 index_id: Word,
851 ) -> Self {
852 let mut instruction = Self::new(Op::VectorExtractDynamic);
853 instruction.set_type(result_type_id);
854 instruction.set_result(id);
855
856 instruction.add_operand(vector_id);
857 instruction.add_operand(index_id);
858
859 instruction
860 }
861
862 pub(super) fn vector_shuffle(
863 result_type_id: Word,
864 id: Word,
865 v1_id: Word,
866 v2_id: Word,
867 components: &[Word],
868 ) -> Self {
869 let mut instruction = Self::new(Op::VectorShuffle);
870 instruction.set_type(result_type_id);
871 instruction.set_result(id);
872 instruction.add_operand(v1_id);
873 instruction.add_operand(v2_id);
874
875 for &component in components {
876 instruction.add_operand(component);
877 }
878
879 instruction
880 }
881
882 pub(super) fn binary(
886 op: Op,
887 result_type_id: Word,
888 id: Word,
889 operand_1: Word,
890 operand_2: Word,
891 ) -> Self {
892 let mut instruction = Self::new(op);
893 instruction.set_type(result_type_id);
894 instruction.set_result(id);
895 instruction.add_operand(operand_1);
896 instruction.add_operand(operand_2);
897 instruction
898 }
899
900 pub(super) fn ternary(
901 op: Op,
902 result_type_id: Word,
903 id: Word,
904 operand_1: Word,
905 operand_2: Word,
906 operand_3: Word,
907 ) -> Self {
908 let mut instruction = Self::new(op);
909 instruction.set_type(result_type_id);
910 instruction.set_result(id);
911 instruction.add_operand(operand_1);
912 instruction.add_operand(operand_2);
913 instruction.add_operand(operand_3);
914 instruction
915 }
916
917 pub(super) fn quaternary(
918 op: Op,
919 result_type_id: Word,
920 id: Word,
921 operand_1: Word,
922 operand_2: Word,
923 operand_3: Word,
924 operand_4: Word,
925 ) -> Self {
926 let mut instruction = Self::new(op);
927 instruction.set_type(result_type_id);
928 instruction.set_result(id);
929 instruction.add_operand(operand_1);
930 instruction.add_operand(operand_2);
931 instruction.add_operand(operand_3);
932 instruction.add_operand(operand_4);
933 instruction
934 }
935
936 pub(super) fn relational(op: Op, result_type_id: Word, id: Word, expr_id: Word) -> Self {
937 let mut instruction = Self::new(op);
938 instruction.set_type(result_type_id);
939 instruction.set_result(id);
940 instruction.add_operand(expr_id);
941 instruction
942 }
943
944 pub(super) fn atomic_binary(
945 op: Op,
946 result_type_id: Word,
947 id: Word,
948 pointer: Word,
949 scope_id: Word,
950 semantics_id: Word,
951 value: Word,
952 ) -> Self {
953 let mut instruction = Self::new(op);
954 instruction.set_type(result_type_id);
955 instruction.set_result(id);
956 instruction.add_operand(pointer);
957 instruction.add_operand(scope_id);
958 instruction.add_operand(semantics_id);
959 instruction.add_operand(value);
960 instruction
961 }
962
963 pub(super) fn derivative(op: Op, result_type_id: Word, id: Word, expr_id: Word) -> Self {
976 let mut instruction = Self::new(op);
977 instruction.set_type(result_type_id);
978 instruction.set_result(id);
979 instruction.add_operand(expr_id);
980 instruction
981 }
982
983 pub(super) fn phi(
988 result_type_id: Word,
989 result_id: Word,
990 var_parent_pairs: &[(Word, Word)],
991 ) -> Self {
992 let mut instruction = Self::new(Op::Phi);
993 instruction.add_operand(result_type_id);
994 instruction.add_operand(result_id);
995 for &(variable, parent) in var_parent_pairs {
996 instruction.add_operand(variable);
997 instruction.add_operand(parent);
998 }
999 instruction
1000 }
1001
1002 pub(super) fn selection_merge(
1003 merge_id: Word,
1004 selection_control: spirv::SelectionControl,
1005 ) -> Self {
1006 let mut instruction = Self::new(Op::SelectionMerge);
1007 instruction.add_operand(merge_id);
1008 instruction.add_operand(selection_control.bits());
1009 instruction
1010 }
1011
1012 pub(super) fn loop_merge(
1013 merge_id: Word,
1014 continuing_id: Word,
1015 selection_control: spirv::SelectionControl,
1016 ) -> Self {
1017 let mut instruction = Self::new(Op::LoopMerge);
1018 instruction.add_operand(merge_id);
1019 instruction.add_operand(continuing_id);
1020 instruction.add_operand(selection_control.bits());
1021 instruction
1022 }
1023
1024 pub(super) fn label(id: Word) -> Self {
1025 let mut instruction = Self::new(Op::Label);
1026 instruction.set_result(id);
1027 instruction
1028 }
1029
1030 pub(super) fn branch(id: Word) -> Self {
1031 let mut instruction = Self::new(Op::Branch);
1032 instruction.add_operand(id);
1033 instruction
1034 }
1035
1036 pub(super) fn branch_conditional(
1038 condition_id: Word,
1039 true_label: Word,
1040 false_label: Word,
1041 ) -> Self {
1042 let mut instruction = Self::new(Op::BranchConditional);
1043 instruction.add_operand(condition_id);
1044 instruction.add_operand(true_label);
1045 instruction.add_operand(false_label);
1046 instruction
1047 }
1048
1049 pub(super) fn switch(selector_id: Word, default_id: Word, cases: &[Case]) -> Self {
1050 let mut instruction = Self::new(Op::Switch);
1051 instruction.add_operand(selector_id);
1052 instruction.add_operand(default_id);
1053 for case in cases {
1054 instruction.add_operand(case.value);
1055 instruction.add_operand(case.label_id);
1056 }
1057 instruction
1058 }
1059
1060 pub(super) fn select(
1061 result_type_id: Word,
1062 id: Word,
1063 condition_id: Word,
1064 accept_id: Word,
1065 reject_id: Word,
1066 ) -> Self {
1067 let mut instruction = Self::new(Op::Select);
1068 instruction.add_operand(result_type_id);
1069 instruction.add_operand(id);
1070 instruction.add_operand(condition_id);
1071 instruction.add_operand(accept_id);
1072 instruction.add_operand(reject_id);
1073 instruction
1074 }
1075
1076 pub(super) const fn kill() -> Self {
1077 Self::new(Op::Kill)
1078 }
1079
1080 pub(super) const fn return_void() -> Self {
1081 Self::new(Op::Return)
1082 }
1083
1084 pub(super) fn return_value(value_id: Word) -> Self {
1085 let mut instruction = Self::new(Op::ReturnValue);
1086 instruction.add_operand(value_id);
1087 instruction
1088 }
1089
1090 pub(super) fn control_barrier(
1101 exec_scope_id: Word,
1102 mem_scope_id: Word,
1103 semantics_id: Word,
1104 ) -> Self {
1105 let mut instruction = Self::new(Op::ControlBarrier);
1106 instruction.add_operand(exec_scope_id);
1107 instruction.add_operand(mem_scope_id);
1108 instruction.add_operand(semantics_id);
1109 instruction
1110 }
1111
1112 pub(super) fn group_non_uniform_ballot(
1115 result_type_id: Word,
1116 id: Word,
1117 exec_scope_id: Word,
1118 predicate: Word,
1119 ) -> Self {
1120 let mut instruction = Self::new(Op::GroupNonUniformBallot);
1121 instruction.set_type(result_type_id);
1122 instruction.set_result(id);
1123 instruction.add_operand(exec_scope_id);
1124 instruction.add_operand(predicate);
1125
1126 instruction
1127 }
1128 pub(super) fn group_non_uniform_broadcast_first(
1129 result_type_id: Word,
1130 id: Word,
1131 exec_scope_id: Word,
1132 value: Word,
1133 ) -> Self {
1134 let mut instruction = Self::new(Op::GroupNonUniformBroadcastFirst);
1135 instruction.set_type(result_type_id);
1136 instruction.set_result(id);
1137 instruction.add_operand(exec_scope_id);
1138 instruction.add_operand(value);
1139
1140 instruction
1141 }
1142 pub(super) fn group_non_uniform_gather(
1143 op: Op,
1144 result_type_id: Word,
1145 id: Word,
1146 exec_scope_id: Word,
1147 value: Word,
1148 index: Word,
1149 ) -> Self {
1150 let mut instruction = Self::new(op);
1151 instruction.set_type(result_type_id);
1152 instruction.set_result(id);
1153 instruction.add_operand(exec_scope_id);
1154 instruction.add_operand(value);
1155 instruction.add_operand(index);
1156
1157 instruction
1158 }
1159 pub(super) fn group_non_uniform_arithmetic(
1160 op: Op,
1161 result_type_id: Word,
1162 id: Word,
1163 exec_scope_id: Word,
1164 group_op: Option<spirv::GroupOperation>,
1165 value: Word,
1166 ) -> Self {
1167 let mut instruction = Self::new(op);
1168 instruction.set_type(result_type_id);
1169 instruction.set_result(id);
1170 instruction.add_operand(exec_scope_id);
1171 if let Some(group_op) = group_op {
1172 instruction.add_operand(group_op as u32);
1173 }
1174 instruction.add_operand(value);
1175
1176 instruction
1177 }
1178}
1179
1180impl From<crate::StorageFormat> for spirv::ImageFormat {
1181 fn from(format: crate::StorageFormat) -> Self {
1182 use crate::StorageFormat as Sf;
1183 match format {
1184 Sf::R8Unorm => Self::R8,
1185 Sf::R8Snorm => Self::R8Snorm,
1186 Sf::R8Uint => Self::R8ui,
1187 Sf::R8Sint => Self::R8i,
1188 Sf::R16Uint => Self::R16ui,
1189 Sf::R16Sint => Self::R16i,
1190 Sf::R16Float => Self::R16f,
1191 Sf::Rg8Unorm => Self::Rg8,
1192 Sf::Rg8Snorm => Self::Rg8Snorm,
1193 Sf::Rg8Uint => Self::Rg8ui,
1194 Sf::Rg8Sint => Self::Rg8i,
1195 Sf::R32Uint => Self::R32ui,
1196 Sf::R32Sint => Self::R32i,
1197 Sf::R32Float => Self::R32f,
1198 Sf::Rg16Uint => Self::Rg16ui,
1199 Sf::Rg16Sint => Self::Rg16i,
1200 Sf::Rg16Float => Self::Rg16f,
1201 Sf::Rgba8Unorm => Self::Rgba8,
1202 Sf::Rgba8Snorm => Self::Rgba8Snorm,
1203 Sf::Rgba8Uint => Self::Rgba8ui,
1204 Sf::Rgba8Sint => Self::Rgba8i,
1205 Sf::Bgra8Unorm => Self::Unknown,
1206 Sf::Rgb10a2Uint => Self::Rgb10a2ui,
1207 Sf::Rgb10a2Unorm => Self::Rgb10A2,
1208 Sf::Rg11b10Ufloat => Self::R11fG11fB10f,
1209 Sf::R64Uint => Self::R64ui,
1210 Sf::Rg32Uint => Self::Rg32ui,
1211 Sf::Rg32Sint => Self::Rg32i,
1212 Sf::Rg32Float => Self::Rg32f,
1213 Sf::Rgba16Uint => Self::Rgba16ui,
1214 Sf::Rgba16Sint => Self::Rgba16i,
1215 Sf::Rgba16Float => Self::Rgba16f,
1216 Sf::Rgba32Uint => Self::Rgba32ui,
1217 Sf::Rgba32Sint => Self::Rgba32i,
1218 Sf::Rgba32Float => Self::Rgba32f,
1219 Sf::R16Unorm => Self::R16,
1220 Sf::R16Snorm => Self::R16Snorm,
1221 Sf::Rg16Unorm => Self::Rg16,
1222 Sf::Rg16Snorm => Self::Rg16Snorm,
1223 Sf::Rgba16Unorm => Self::Rgba16,
1224 Sf::Rgba16Snorm => Self::Rgba16Snorm,
1225 }
1226 }
1227}
1228
1229impl From<crate::ImageDimension> for spirv::Dim {
1230 fn from(dim: crate::ImageDimension) -> Self {
1231 use crate::ImageDimension as Id;
1232 match dim {
1233 Id::D1 => Self::Dim1D,
1234 Id::D2 => Self::Dim2D,
1235 Id::D3 => Self::Dim3D,
1236 Id::Cube => Self::DimCube,
1237 }
1238 }
1239}