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 name(target_id: Word, name: &str) -> Self {
47 let mut instruction = Self::new(Op::Name);
48 instruction.add_operand(target_id);
49 instruction.add_operands(helpers::string_to_words(name));
50 instruction
51 }
52
53 pub(super) fn member_name(target_id: Word, member: Word, name: &str) -> Self {
54 let mut instruction = Self::new(Op::MemberName);
55 instruction.add_operand(target_id);
56 instruction.add_operand(member);
57 instruction.add_operands(helpers::string_to_words(name));
58 instruction
59 }
60
61 pub(super) fn line(file: Word, line: Word, column: Word) -> Self {
62 let mut instruction = Self::new(Op::Line);
63 instruction.add_operand(file);
64 instruction.add_operand(line);
65 instruction.add_operand(column);
66 instruction
67 }
68
69 pub(super) const fn no_line() -> Self {
70 Self::new(Op::NoLine)
71 }
72
73 pub(super) fn decorate(
78 target_id: Word,
79 decoration: spirv::Decoration,
80 operands: &[Word],
81 ) -> Self {
82 let mut instruction = Self::new(Op::Decorate);
83 instruction.add_operand(target_id);
84 instruction.add_operand(decoration as u32);
85 for operand in operands {
86 instruction.add_operand(*operand)
87 }
88 instruction
89 }
90
91 pub(super) fn member_decorate(
92 target_id: Word,
93 member_index: Word,
94 decoration: spirv::Decoration,
95 operands: &[Word],
96 ) -> Self {
97 let mut instruction = Self::new(Op::MemberDecorate);
98 instruction.add_operand(target_id);
99 instruction.add_operand(member_index);
100 instruction.add_operand(decoration as u32);
101 for operand in operands {
102 instruction.add_operand(*operand)
103 }
104 instruction
105 }
106
107 pub(super) fn extension(name: &str) -> Self {
112 let mut instruction = Self::new(Op::Extension);
113 instruction.add_operands(helpers::string_to_words(name));
114 instruction
115 }
116
117 pub(super) fn ext_inst_import(id: Word, name: &str) -> Self {
118 let mut instruction = Self::new(Op::ExtInstImport);
119 instruction.set_result(id);
120 instruction.add_operands(helpers::string_to_words(name));
121 instruction
122 }
123
124 pub(super) fn ext_inst(
125 set_id: Word,
126 op: spirv::GLOp,
127 result_type_id: Word,
128 id: Word,
129 operands: &[Word],
130 ) -> Self {
131 let mut instruction = Self::new(Op::ExtInst);
132 instruction.set_type(result_type_id);
133 instruction.set_result(id);
134 instruction.add_operand(set_id);
135 instruction.add_operand(op as u32);
136 for operand in operands {
137 instruction.add_operand(*operand)
138 }
139 instruction
140 }
141
142 pub(super) fn memory_model(
147 addressing_model: spirv::AddressingModel,
148 memory_model: spirv::MemoryModel,
149 ) -> Self {
150 let mut instruction = Self::new(Op::MemoryModel);
151 instruction.add_operand(addressing_model as u32);
152 instruction.add_operand(memory_model as u32);
153 instruction
154 }
155
156 pub(super) fn entry_point(
157 execution_model: spirv::ExecutionModel,
158 entry_point_id: Word,
159 name: &str,
160 interface_ids: &[Word],
161 ) -> Self {
162 let mut instruction = Self::new(Op::EntryPoint);
163 instruction.add_operand(execution_model as u32);
164 instruction.add_operand(entry_point_id);
165 instruction.add_operands(helpers::string_to_words(name));
166
167 for interface_id in interface_ids {
168 instruction.add_operand(*interface_id);
169 }
170
171 instruction
172 }
173
174 pub(super) fn execution_mode(
175 entry_point_id: Word,
176 execution_mode: spirv::ExecutionMode,
177 args: &[Word],
178 ) -> Self {
179 let mut instruction = Self::new(Op::ExecutionMode);
180 instruction.add_operand(entry_point_id);
181 instruction.add_operand(execution_mode as u32);
182 for arg in args {
183 instruction.add_operand(*arg);
184 }
185 instruction
186 }
187
188 pub(super) fn capability(capability: spirv::Capability) -> Self {
189 let mut instruction = Self::new(Op::Capability);
190 instruction.add_operand(capability as u32);
191 instruction
192 }
193
194 pub(super) fn type_void(id: Word) -> Self {
199 let mut instruction = Self::new(Op::TypeVoid);
200 instruction.set_result(id);
201 instruction
202 }
203
204 pub(super) fn type_bool(id: Word) -> Self {
205 let mut instruction = Self::new(Op::TypeBool);
206 instruction.set_result(id);
207 instruction
208 }
209
210 pub(super) fn type_int(id: Word, width: Word, signedness: Signedness) -> Self {
211 let mut instruction = Self::new(Op::TypeInt);
212 instruction.set_result(id);
213 instruction.add_operand(width);
214 instruction.add_operand(signedness as u32);
215 instruction
216 }
217
218 pub(super) fn type_float(id: Word, width: Word) -> Self {
219 let mut instruction = Self::new(Op::TypeFloat);
220 instruction.set_result(id);
221 instruction.add_operand(width);
222 instruction
223 }
224
225 pub(super) fn type_vector(
226 id: Word,
227 component_type_id: Word,
228 component_count: crate::VectorSize,
229 ) -> Self {
230 let mut instruction = Self::new(Op::TypeVector);
231 instruction.set_result(id);
232 instruction.add_operand(component_type_id);
233 instruction.add_operand(component_count as u32);
234 instruction
235 }
236
237 pub(super) fn type_matrix(
238 id: Word,
239 column_type_id: Word,
240 column_count: crate::VectorSize,
241 ) -> Self {
242 let mut instruction = Self::new(Op::TypeMatrix);
243 instruction.set_result(id);
244 instruction.add_operand(column_type_id);
245 instruction.add_operand(column_count as u32);
246 instruction
247 }
248
249 #[allow(clippy::too_many_arguments)]
250 pub(super) fn type_image(
251 id: Word,
252 sampled_type_id: Word,
253 dim: spirv::Dim,
254 flags: super::ImageTypeFlags,
255 image_format: spirv::ImageFormat,
256 ) -> Self {
257 let mut instruction = Self::new(Op::TypeImage);
258 instruction.set_result(id);
259 instruction.add_operand(sampled_type_id);
260 instruction.add_operand(dim as u32);
261 instruction.add_operand(flags.contains(super::ImageTypeFlags::DEPTH) as u32);
262 instruction.add_operand(flags.contains(super::ImageTypeFlags::ARRAYED) as u32);
263 instruction.add_operand(flags.contains(super::ImageTypeFlags::MULTISAMPLED) as u32);
264 instruction.add_operand(if flags.contains(super::ImageTypeFlags::SAMPLED) {
265 1
266 } else {
267 2
268 });
269 instruction.add_operand(image_format as u32);
270 instruction
271 }
272
273 pub(super) fn type_sampler(id: Word) -> Self {
274 let mut instruction = Self::new(Op::TypeSampler);
275 instruction.set_result(id);
276 instruction
277 }
278
279 pub(super) fn type_acceleration_structure(id: Word) -> Self {
280 let mut instruction = Self::new(Op::TypeAccelerationStructureKHR);
281 instruction.set_result(id);
282 instruction
283 }
284
285 pub(super) fn type_ray_query(id: Word) -> Self {
286 let mut instruction = Self::new(Op::TypeRayQueryKHR);
287 instruction.set_result(id);
288 instruction
289 }
290
291 pub(super) fn type_sampled_image(id: Word, image_type_id: Word) -> Self {
292 let mut instruction = Self::new(Op::TypeSampledImage);
293 instruction.set_result(id);
294 instruction.add_operand(image_type_id);
295 instruction
296 }
297
298 pub(super) fn type_array(id: Word, element_type_id: Word, length_id: Word) -> Self {
299 let mut instruction = Self::new(Op::TypeArray);
300 instruction.set_result(id);
301 instruction.add_operand(element_type_id);
302 instruction.add_operand(length_id);
303 instruction
304 }
305
306 pub(super) fn type_runtime_array(id: Word, element_type_id: Word) -> Self {
307 let mut instruction = Self::new(Op::TypeRuntimeArray);
308 instruction.set_result(id);
309 instruction.add_operand(element_type_id);
310 instruction
311 }
312
313 pub(super) fn type_struct(id: Word, member_ids: &[Word]) -> Self {
314 let mut instruction = Self::new(Op::TypeStruct);
315 instruction.set_result(id);
316
317 for member_id in member_ids {
318 instruction.add_operand(*member_id)
319 }
320
321 instruction
322 }
323
324 pub(super) fn type_pointer(
325 id: Word,
326 storage_class: spirv::StorageClass,
327 type_id: Word,
328 ) -> Self {
329 let mut instruction = Self::new(Op::TypePointer);
330 instruction.set_result(id);
331 instruction.add_operand(storage_class as u32);
332 instruction.add_operand(type_id);
333 instruction
334 }
335
336 pub(super) fn type_function(id: Word, return_type_id: Word, parameter_ids: &[Word]) -> Self {
337 let mut instruction = Self::new(Op::TypeFunction);
338 instruction.set_result(id);
339 instruction.add_operand(return_type_id);
340
341 for parameter_id in parameter_ids {
342 instruction.add_operand(*parameter_id);
343 }
344
345 instruction
346 }
347
348 pub(super) fn constant_null(result_type_id: Word, id: Word) -> Self {
353 let mut instruction = Self::new(Op::ConstantNull);
354 instruction.set_type(result_type_id);
355 instruction.set_result(id);
356 instruction
357 }
358
359 pub(super) fn constant_true(result_type_id: Word, id: Word) -> Self {
360 let mut instruction = Self::new(Op::ConstantTrue);
361 instruction.set_type(result_type_id);
362 instruction.set_result(id);
363 instruction
364 }
365
366 pub(super) fn constant_false(result_type_id: Word, id: Word) -> Self {
367 let mut instruction = Self::new(Op::ConstantFalse);
368 instruction.set_type(result_type_id);
369 instruction.set_result(id);
370 instruction
371 }
372
373 pub(super) fn constant_32bit(result_type_id: Word, id: Word, value: Word) -> Self {
374 Self::constant(result_type_id, id, &[value])
375 }
376
377 pub(super) fn constant_64bit(result_type_id: Word, id: Word, low: Word, high: Word) -> Self {
378 Self::constant(result_type_id, id, &[low, high])
379 }
380
381 pub(super) fn constant(result_type_id: Word, id: Word, values: &[Word]) -> Self {
382 let mut instruction = Self::new(Op::Constant);
383 instruction.set_type(result_type_id);
384 instruction.set_result(id);
385
386 for value in values {
387 instruction.add_operand(*value);
388 }
389
390 instruction
391 }
392
393 pub(super) fn constant_composite(
394 result_type_id: Word,
395 id: Word,
396 constituent_ids: &[Word],
397 ) -> Self {
398 let mut instruction = Self::new(Op::ConstantComposite);
399 instruction.set_type(result_type_id);
400 instruction.set_result(id);
401
402 for constituent_id in constituent_ids {
403 instruction.add_operand(*constituent_id);
404 }
405
406 instruction
407 }
408
409 pub(super) fn variable(
414 result_type_id: Word,
415 id: Word,
416 storage_class: spirv::StorageClass,
417 initializer_id: Option<Word>,
418 ) -> Self {
419 let mut instruction = Self::new(Op::Variable);
420 instruction.set_type(result_type_id);
421 instruction.set_result(id);
422 instruction.add_operand(storage_class as u32);
423
424 if let Some(initializer_id) = initializer_id {
425 instruction.add_operand(initializer_id);
426 }
427
428 instruction
429 }
430
431 pub(super) fn load(
432 result_type_id: Word,
433 id: Word,
434 pointer_id: Word,
435 memory_access: Option<spirv::MemoryAccess>,
436 ) -> Self {
437 let mut instruction = Self::new(Op::Load);
438 instruction.set_type(result_type_id);
439 instruction.set_result(id);
440 instruction.add_operand(pointer_id);
441
442 if let Some(memory_access) = memory_access {
443 instruction.add_operand(memory_access.bits());
444 }
445
446 instruction
447 }
448
449 pub(super) fn atomic_load(
450 result_type_id: Word,
451 id: Word,
452 pointer_id: Word,
453 scope_id: Word,
454 semantics_id: Word,
455 ) -> Self {
456 let mut instruction = Self::new(Op::AtomicLoad);
457 instruction.set_type(result_type_id);
458 instruction.set_result(id);
459 instruction.add_operand(pointer_id);
460 instruction.add_operand(scope_id);
461 instruction.add_operand(semantics_id);
462 instruction
463 }
464
465 pub(super) fn store(
466 pointer_id: Word,
467 value_id: Word,
468 memory_access: Option<spirv::MemoryAccess>,
469 ) -> Self {
470 let mut instruction = Self::new(Op::Store);
471 instruction.add_operand(pointer_id);
472 instruction.add_operand(value_id);
473
474 if let Some(memory_access) = memory_access {
475 instruction.add_operand(memory_access.bits());
476 }
477
478 instruction
479 }
480
481 pub(super) fn atomic_store(
482 pointer_id: Word,
483 scope_id: Word,
484 semantics_id: Word,
485 value_id: Word,
486 ) -> Self {
487 let mut instruction = Self::new(Op::AtomicStore);
488 instruction.add_operand(pointer_id);
489 instruction.add_operand(scope_id);
490 instruction.add_operand(semantics_id);
491 instruction.add_operand(value_id);
492 instruction
493 }
494
495 pub(super) fn access_chain(
496 result_type_id: Word,
497 id: Word,
498 base_id: Word,
499 index_ids: &[Word],
500 ) -> Self {
501 let mut instruction = Self::new(Op::AccessChain);
502 instruction.set_type(result_type_id);
503 instruction.set_result(id);
504 instruction.add_operand(base_id);
505
506 for index_id in index_ids {
507 instruction.add_operand(*index_id);
508 }
509
510 instruction
511 }
512
513 pub(super) fn array_length(
514 result_type_id: Word,
515 id: Word,
516 structure_id: Word,
517 array_member: Word,
518 ) -> Self {
519 let mut instruction = Self::new(Op::ArrayLength);
520 instruction.set_type(result_type_id);
521 instruction.set_result(id);
522 instruction.add_operand(structure_id);
523 instruction.add_operand(array_member);
524 instruction
525 }
526
527 pub(super) fn function(
532 return_type_id: Word,
533 id: Word,
534 function_control: spirv::FunctionControl,
535 function_type_id: Word,
536 ) -> Self {
537 let mut instruction = Self::new(Op::Function);
538 instruction.set_type(return_type_id);
539 instruction.set_result(id);
540 instruction.add_operand(function_control.bits());
541 instruction.add_operand(function_type_id);
542 instruction
543 }
544
545 pub(super) fn function_parameter(result_type_id: Word, id: Word) -> Self {
546 let mut instruction = Self::new(Op::FunctionParameter);
547 instruction.set_type(result_type_id);
548 instruction.set_result(id);
549 instruction
550 }
551
552 pub(super) const fn function_end() -> Self {
553 Self::new(Op::FunctionEnd)
554 }
555
556 pub(super) fn function_call(
557 result_type_id: Word,
558 id: Word,
559 function_id: Word,
560 argument_ids: &[Word],
561 ) -> Self {
562 let mut instruction = Self::new(Op::FunctionCall);
563 instruction.set_type(result_type_id);
564 instruction.set_result(id);
565 instruction.add_operand(function_id);
566
567 for argument_id in argument_ids {
568 instruction.add_operand(*argument_id);
569 }
570
571 instruction
572 }
573
574 pub(super) fn sampled_image(
579 result_type_id: Word,
580 id: Word,
581 image: Word,
582 sampler: Word,
583 ) -> Self {
584 let mut instruction = Self::new(Op::SampledImage);
585 instruction.set_type(result_type_id);
586 instruction.set_result(id);
587 instruction.add_operand(image);
588 instruction.add_operand(sampler);
589 instruction
590 }
591
592 pub(super) fn image_sample(
593 result_type_id: Word,
594 id: Word,
595 lod: SampleLod,
596 sampled_image: Word,
597 coordinates: Word,
598 depth_ref: Option<Word>,
599 ) -> Self {
600 let op = match (lod, depth_ref) {
601 (SampleLod::Explicit, None) => Op::ImageSampleExplicitLod,
602 (SampleLod::Implicit, None) => Op::ImageSampleImplicitLod,
603 (SampleLod::Explicit, Some(_)) => Op::ImageSampleDrefExplicitLod,
604 (SampleLod::Implicit, Some(_)) => Op::ImageSampleDrefImplicitLod,
605 };
606
607 let mut instruction = Self::new(op);
608 instruction.set_type(result_type_id);
609 instruction.set_result(id);
610 instruction.add_operand(sampled_image);
611 instruction.add_operand(coordinates);
612 if let Some(dref) = depth_ref {
613 instruction.add_operand(dref);
614 }
615
616 instruction
617 }
618
619 pub(super) fn image_gather(
620 result_type_id: Word,
621 id: Word,
622 sampled_image: Word,
623 coordinates: Word,
624 component_id: Word,
625 depth_ref: Option<Word>,
626 ) -> Self {
627 let op = match depth_ref {
628 None => Op::ImageGather,
629 Some(_) => Op::ImageDrefGather,
630 };
631
632 let mut instruction = Self::new(op);
633 instruction.set_type(result_type_id);
634 instruction.set_result(id);
635 instruction.add_operand(sampled_image);
636 instruction.add_operand(coordinates);
637 if let Some(dref) = depth_ref {
638 instruction.add_operand(dref);
639 } else {
640 instruction.add_operand(component_id);
641 }
642
643 instruction
644 }
645
646 pub(super) fn image_fetch_or_read(
647 op: Op,
648 result_type_id: Word,
649 id: Word,
650 image: Word,
651 coordinates: Word,
652 ) -> Self {
653 let mut instruction = Self::new(op);
654 instruction.set_type(result_type_id);
655 instruction.set_result(id);
656 instruction.add_operand(image);
657 instruction.add_operand(coordinates);
658 instruction
659 }
660
661 pub(super) fn image_write(image: Word, coordinates: Word, value: Word) -> Self {
662 let mut instruction = Self::new(Op::ImageWrite);
663 instruction.add_operand(image);
664 instruction.add_operand(coordinates);
665 instruction.add_operand(value);
666 instruction
667 }
668
669 pub(super) fn image_query(op: Op, result_type_id: Word, id: Word, image: Word) -> Self {
670 let mut instruction = Self::new(op);
671 instruction.set_type(result_type_id);
672 instruction.set_result(id);
673 instruction.add_operand(image);
674 instruction
675 }
676
677 #[allow(clippy::too_many_arguments)]
681 pub(super) fn ray_query_initialize(
682 query: Word,
683 acceleration_structure: Word,
684 ray_flags: Word,
685 cull_mask: Word,
686 ray_origin: Word,
687 ray_tmin: Word,
688 ray_dir: Word,
689 ray_tmax: Word,
690 ) -> Self {
691 let mut instruction = Self::new(Op::RayQueryInitializeKHR);
692 instruction.add_operand(query);
693 instruction.add_operand(acceleration_structure);
694 instruction.add_operand(ray_flags);
695 instruction.add_operand(cull_mask);
696 instruction.add_operand(ray_origin);
697 instruction.add_operand(ray_tmin);
698 instruction.add_operand(ray_dir);
699 instruction.add_operand(ray_tmax);
700 instruction
701 }
702
703 pub(super) fn ray_query_proceed(result_type_id: Word, id: Word, query: Word) -> Self {
704 let mut instruction = Self::new(Op::RayQueryProceedKHR);
705 instruction.set_type(result_type_id);
706 instruction.set_result(id);
707 instruction.add_operand(query);
708 instruction
709 }
710
711 pub(super) fn ray_query_get_intersection(
712 op: Op,
713 result_type_id: Word,
714 id: Word,
715 query: Word,
716 intersection: Word,
717 ) -> Self {
718 let mut instruction = Self::new(op);
719 instruction.set_type(result_type_id);
720 instruction.set_result(id);
721 instruction.add_operand(query);
722 instruction.add_operand(intersection);
723 instruction
724 }
725
726 pub(super) fn unary(op: Op, result_type_id: Word, id: Word, value: Word) -> Self {
730 let mut instruction = Self::new(op);
731 instruction.set_type(result_type_id);
732 instruction.set_result(id);
733 instruction.add_operand(value);
734 instruction
735 }
736
737 pub(super) fn composite_construct(
742 result_type_id: Word,
743 id: Word,
744 constituent_ids: &[Word],
745 ) -> Self {
746 let mut instruction = Self::new(Op::CompositeConstruct);
747 instruction.set_type(result_type_id);
748 instruction.set_result(id);
749
750 for constituent_id in constituent_ids {
751 instruction.add_operand(*constituent_id);
752 }
753
754 instruction
755 }
756
757 pub(super) fn composite_extract(
758 result_type_id: Word,
759 id: Word,
760 composite_id: Word,
761 indices: &[Word],
762 ) -> Self {
763 let mut instruction = Self::new(Op::CompositeExtract);
764 instruction.set_type(result_type_id);
765 instruction.set_result(id);
766
767 instruction.add_operand(composite_id);
768 for index in indices {
769 instruction.add_operand(*index);
770 }
771
772 instruction
773 }
774
775 pub(super) fn vector_extract_dynamic(
776 result_type_id: Word,
777 id: Word,
778 vector_id: Word,
779 index_id: Word,
780 ) -> Self {
781 let mut instruction = Self::new(Op::VectorExtractDynamic);
782 instruction.set_type(result_type_id);
783 instruction.set_result(id);
784
785 instruction.add_operand(vector_id);
786 instruction.add_operand(index_id);
787
788 instruction
789 }
790
791 pub(super) fn vector_shuffle(
792 result_type_id: Word,
793 id: Word,
794 v1_id: Word,
795 v2_id: Word,
796 components: &[Word],
797 ) -> Self {
798 let mut instruction = Self::new(Op::VectorShuffle);
799 instruction.set_type(result_type_id);
800 instruction.set_result(id);
801 instruction.add_operand(v1_id);
802 instruction.add_operand(v2_id);
803
804 for &component in components {
805 instruction.add_operand(component);
806 }
807
808 instruction
809 }
810
811 pub(super) fn binary(
815 op: Op,
816 result_type_id: Word,
817 id: Word,
818 operand_1: Word,
819 operand_2: Word,
820 ) -> Self {
821 let mut instruction = Self::new(op);
822 instruction.set_type(result_type_id);
823 instruction.set_result(id);
824 instruction.add_operand(operand_1);
825 instruction.add_operand(operand_2);
826 instruction
827 }
828
829 pub(super) fn ternary(
830 op: Op,
831 result_type_id: Word,
832 id: Word,
833 operand_1: Word,
834 operand_2: Word,
835 operand_3: Word,
836 ) -> Self {
837 let mut instruction = Self::new(op);
838 instruction.set_type(result_type_id);
839 instruction.set_result(id);
840 instruction.add_operand(operand_1);
841 instruction.add_operand(operand_2);
842 instruction.add_operand(operand_3);
843 instruction
844 }
845
846 pub(super) fn quaternary(
847 op: Op,
848 result_type_id: Word,
849 id: Word,
850 operand_1: Word,
851 operand_2: Word,
852 operand_3: Word,
853 operand_4: Word,
854 ) -> Self {
855 let mut instruction = Self::new(op);
856 instruction.set_type(result_type_id);
857 instruction.set_result(id);
858 instruction.add_operand(operand_1);
859 instruction.add_operand(operand_2);
860 instruction.add_operand(operand_3);
861 instruction.add_operand(operand_4);
862 instruction
863 }
864
865 pub(super) fn relational(op: Op, result_type_id: Word, id: Word, expr_id: Word) -> Self {
866 let mut instruction = Self::new(op);
867 instruction.set_type(result_type_id);
868 instruction.set_result(id);
869 instruction.add_operand(expr_id);
870 instruction
871 }
872
873 pub(super) fn atomic_binary(
874 op: Op,
875 result_type_id: Word,
876 id: Word,
877 pointer: Word,
878 scope_id: Word,
879 semantics_id: Word,
880 value: Word,
881 ) -> Self {
882 let mut instruction = Self::new(op);
883 instruction.set_type(result_type_id);
884 instruction.set_result(id);
885 instruction.add_operand(pointer);
886 instruction.add_operand(scope_id);
887 instruction.add_operand(semantics_id);
888 instruction.add_operand(value);
889 instruction
890 }
891
892 pub(super) fn derivative(op: Op, result_type_id: Word, id: Word, expr_id: Word) -> Self {
905 let mut instruction = Self::new(op);
906 instruction.set_type(result_type_id);
907 instruction.set_result(id);
908 instruction.add_operand(expr_id);
909 instruction
910 }
911
912 pub(super) fn phi(
917 result_type_id: Word,
918 result_id: Word,
919 var_parent_pairs: &[(Word, Word)],
920 ) -> Self {
921 let mut instruction = Self::new(Op::Phi);
922 instruction.add_operand(result_type_id);
923 instruction.add_operand(result_id);
924 for &(variable, parent) in var_parent_pairs {
925 instruction.add_operand(variable);
926 instruction.add_operand(parent);
927 }
928 instruction
929 }
930
931 pub(super) fn selection_merge(
932 merge_id: Word,
933 selection_control: spirv::SelectionControl,
934 ) -> Self {
935 let mut instruction = Self::new(Op::SelectionMerge);
936 instruction.add_operand(merge_id);
937 instruction.add_operand(selection_control.bits());
938 instruction
939 }
940
941 pub(super) fn loop_merge(
942 merge_id: Word,
943 continuing_id: Word,
944 selection_control: spirv::SelectionControl,
945 ) -> Self {
946 let mut instruction = Self::new(Op::LoopMerge);
947 instruction.add_operand(merge_id);
948 instruction.add_operand(continuing_id);
949 instruction.add_operand(selection_control.bits());
950 instruction
951 }
952
953 pub(super) fn label(id: Word) -> Self {
954 let mut instruction = Self::new(Op::Label);
955 instruction.set_result(id);
956 instruction
957 }
958
959 pub(super) fn branch(id: Word) -> Self {
960 let mut instruction = Self::new(Op::Branch);
961 instruction.add_operand(id);
962 instruction
963 }
964
965 pub(super) fn branch_conditional(
967 condition_id: Word,
968 true_label: Word,
969 false_label: Word,
970 ) -> Self {
971 let mut instruction = Self::new(Op::BranchConditional);
972 instruction.add_operand(condition_id);
973 instruction.add_operand(true_label);
974 instruction.add_operand(false_label);
975 instruction
976 }
977
978 pub(super) fn switch(selector_id: Word, default_id: Word, cases: &[Case]) -> Self {
979 let mut instruction = Self::new(Op::Switch);
980 instruction.add_operand(selector_id);
981 instruction.add_operand(default_id);
982 for case in cases {
983 instruction.add_operand(case.value);
984 instruction.add_operand(case.label_id);
985 }
986 instruction
987 }
988
989 pub(super) fn select(
990 result_type_id: Word,
991 id: Word,
992 condition_id: Word,
993 accept_id: Word,
994 reject_id: Word,
995 ) -> Self {
996 let mut instruction = Self::new(Op::Select);
997 instruction.add_operand(result_type_id);
998 instruction.add_operand(id);
999 instruction.add_operand(condition_id);
1000 instruction.add_operand(accept_id);
1001 instruction.add_operand(reject_id);
1002 instruction
1003 }
1004
1005 pub(super) const fn kill() -> Self {
1006 Self::new(Op::Kill)
1007 }
1008
1009 pub(super) const fn return_void() -> Self {
1010 Self::new(Op::Return)
1011 }
1012
1013 pub(super) fn return_value(value_id: Word) -> Self {
1014 let mut instruction = Self::new(Op::ReturnValue);
1015 instruction.add_operand(value_id);
1016 instruction
1017 }
1018
1019 pub(super) fn control_barrier(
1030 exec_scope_id: Word,
1031 mem_scope_id: Word,
1032 semantics_id: Word,
1033 ) -> Self {
1034 let mut instruction = Self::new(Op::ControlBarrier);
1035 instruction.add_operand(exec_scope_id);
1036 instruction.add_operand(mem_scope_id);
1037 instruction.add_operand(semantics_id);
1038 instruction
1039 }
1040}
1041
1042impl From<crate::StorageFormat> for spirv::ImageFormat {
1043 fn from(format: crate::StorageFormat) -> Self {
1044 use crate::StorageFormat as Sf;
1045 match format {
1046 Sf::R8Unorm => Self::R8,
1047 Sf::R8Snorm => Self::R8Snorm,
1048 Sf::R8Uint => Self::R8ui,
1049 Sf::R8Sint => Self::R8i,
1050 Sf::R16Uint => Self::R16ui,
1051 Sf::R16Sint => Self::R16i,
1052 Sf::R16Float => Self::R16f,
1053 Sf::Rg8Unorm => Self::Rg8,
1054 Sf::Rg8Snorm => Self::Rg8Snorm,
1055 Sf::Rg8Uint => Self::Rg8ui,
1056 Sf::Rg8Sint => Self::Rg8i,
1057 Sf::R32Uint => Self::R32ui,
1058 Sf::R32Sint => Self::R32i,
1059 Sf::R32Float => Self::R32f,
1060 Sf::Rg16Uint => Self::Rg16ui,
1061 Sf::Rg16Sint => Self::Rg16i,
1062 Sf::Rg16Float => Self::Rg16f,
1063 Sf::Rgba8Unorm => Self::Rgba8,
1064 Sf::Rgba8Snorm => Self::Rgba8Snorm,
1065 Sf::Rgba8Uint => Self::Rgba8ui,
1066 Sf::Rgba8Sint => Self::Rgba8i,
1067 Sf::Rgb10a2Unorm => Self::Rgb10a2ui,
1068 Sf::Rg11b10Float => Self::R11fG11fB10f,
1069 Sf::Rg32Uint => Self::Rg32ui,
1070 Sf::Rg32Sint => Self::Rg32i,
1071 Sf::Rg32Float => Self::Rg32f,
1072 Sf::Rgba16Uint => Self::Rgba16ui,
1073 Sf::Rgba16Sint => Self::Rgba16i,
1074 Sf::Rgba16Float => Self::Rgba16f,
1075 Sf::Rgba32Uint => Self::Rgba32ui,
1076 Sf::Rgba32Sint => Self::Rgba32i,
1077 Sf::Rgba32Float => Self::Rgba32f,
1078 Sf::R16Unorm => Self::R16,
1079 Sf::R16Snorm => Self::R16Snorm,
1080 Sf::Rg16Unorm => Self::Rg16,
1081 Sf::Rg16Snorm => Self::Rg16Snorm,
1082 Sf::Rgba16Unorm => Self::Rgba16,
1083 Sf::Rgba16Snorm => Self::Rgba16Snorm,
1084 }
1085 }
1086}
1087
1088impl From<crate::ImageDimension> for spirv::Dim {
1089 fn from(dim: crate::ImageDimension) -> Self {
1090 use crate::ImageDimension as Id;
1091 match dim {
1092 Id::D1 => Self::Dim1D,
1093 Id::D2 => Self::Dim2D,
1094 Id::D3 => Self::Dim3D,
1095 Id::Cube => Self::DimCube,
1096 }
1097 }
1098}