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_query(op: Op, result_type_id: Word, id: Word, image: Word) -> Self {
706 let mut instruction = Self::new(op);
707 instruction.set_type(result_type_id);
708 instruction.set_result(id);
709 instruction.add_operand(image);
710 instruction
711 }
712
713 #[allow(clippy::too_many_arguments)]
717 pub(super) fn ray_query_initialize(
718 query: Word,
719 acceleration_structure: Word,
720 ray_flags: Word,
721 cull_mask: Word,
722 ray_origin: Word,
723 ray_tmin: Word,
724 ray_dir: Word,
725 ray_tmax: Word,
726 ) -> Self {
727 let mut instruction = Self::new(Op::RayQueryInitializeKHR);
728 instruction.add_operand(query);
729 instruction.add_operand(acceleration_structure);
730 instruction.add_operand(ray_flags);
731 instruction.add_operand(cull_mask);
732 instruction.add_operand(ray_origin);
733 instruction.add_operand(ray_tmin);
734 instruction.add_operand(ray_dir);
735 instruction.add_operand(ray_tmax);
736 instruction
737 }
738
739 pub(super) fn ray_query_proceed(result_type_id: Word, id: Word, query: Word) -> Self {
740 let mut instruction = Self::new(Op::RayQueryProceedKHR);
741 instruction.set_type(result_type_id);
742 instruction.set_result(id);
743 instruction.add_operand(query);
744 instruction
745 }
746
747 pub(super) fn ray_query_get_intersection(
748 op: Op,
749 result_type_id: Word,
750 id: Word,
751 query: Word,
752 intersection: Word,
753 ) -> Self {
754 let mut instruction = Self::new(op);
755 instruction.set_type(result_type_id);
756 instruction.set_result(id);
757 instruction.add_operand(query);
758 instruction.add_operand(intersection);
759 instruction
760 }
761
762 pub(super) fn unary(op: Op, result_type_id: Word, id: Word, value: Word) -> Self {
766 let mut instruction = Self::new(op);
767 instruction.set_type(result_type_id);
768 instruction.set_result(id);
769 instruction.add_operand(value);
770 instruction
771 }
772
773 pub(super) fn composite_construct(
778 result_type_id: Word,
779 id: Word,
780 constituent_ids: &[Word],
781 ) -> Self {
782 let mut instruction = Self::new(Op::CompositeConstruct);
783 instruction.set_type(result_type_id);
784 instruction.set_result(id);
785
786 for constituent_id in constituent_ids {
787 instruction.add_operand(*constituent_id);
788 }
789
790 instruction
791 }
792
793 pub(super) fn composite_extract(
794 result_type_id: Word,
795 id: Word,
796 composite_id: Word,
797 indices: &[Word],
798 ) -> Self {
799 let mut instruction = Self::new(Op::CompositeExtract);
800 instruction.set_type(result_type_id);
801 instruction.set_result(id);
802
803 instruction.add_operand(composite_id);
804 for index in indices {
805 instruction.add_operand(*index);
806 }
807
808 instruction
809 }
810
811 pub(super) fn vector_extract_dynamic(
812 result_type_id: Word,
813 id: Word,
814 vector_id: Word,
815 index_id: Word,
816 ) -> Self {
817 let mut instruction = Self::new(Op::VectorExtractDynamic);
818 instruction.set_type(result_type_id);
819 instruction.set_result(id);
820
821 instruction.add_operand(vector_id);
822 instruction.add_operand(index_id);
823
824 instruction
825 }
826
827 pub(super) fn vector_shuffle(
828 result_type_id: Word,
829 id: Word,
830 v1_id: Word,
831 v2_id: Word,
832 components: &[Word],
833 ) -> Self {
834 let mut instruction = Self::new(Op::VectorShuffle);
835 instruction.set_type(result_type_id);
836 instruction.set_result(id);
837 instruction.add_operand(v1_id);
838 instruction.add_operand(v2_id);
839
840 for &component in components {
841 instruction.add_operand(component);
842 }
843
844 instruction
845 }
846
847 pub(super) fn binary(
851 op: Op,
852 result_type_id: Word,
853 id: Word,
854 operand_1: Word,
855 operand_2: Word,
856 ) -> Self {
857 let mut instruction = Self::new(op);
858 instruction.set_type(result_type_id);
859 instruction.set_result(id);
860 instruction.add_operand(operand_1);
861 instruction.add_operand(operand_2);
862 instruction
863 }
864
865 pub(super) fn ternary(
866 op: Op,
867 result_type_id: Word,
868 id: Word,
869 operand_1: Word,
870 operand_2: Word,
871 operand_3: Word,
872 ) -> Self {
873 let mut instruction = Self::new(op);
874 instruction.set_type(result_type_id);
875 instruction.set_result(id);
876 instruction.add_operand(operand_1);
877 instruction.add_operand(operand_2);
878 instruction.add_operand(operand_3);
879 instruction
880 }
881
882 pub(super) fn quaternary(
883 op: Op,
884 result_type_id: Word,
885 id: Word,
886 operand_1: Word,
887 operand_2: Word,
888 operand_3: Word,
889 operand_4: Word,
890 ) -> Self {
891 let mut instruction = Self::new(op);
892 instruction.set_type(result_type_id);
893 instruction.set_result(id);
894 instruction.add_operand(operand_1);
895 instruction.add_operand(operand_2);
896 instruction.add_operand(operand_3);
897 instruction.add_operand(operand_4);
898 instruction
899 }
900
901 pub(super) fn relational(op: Op, result_type_id: Word, id: Word, expr_id: Word) -> Self {
902 let mut instruction = Self::new(op);
903 instruction.set_type(result_type_id);
904 instruction.set_result(id);
905 instruction.add_operand(expr_id);
906 instruction
907 }
908
909 pub(super) fn atomic_binary(
910 op: Op,
911 result_type_id: Word,
912 id: Word,
913 pointer: Word,
914 scope_id: Word,
915 semantics_id: Word,
916 value: Word,
917 ) -> Self {
918 let mut instruction = Self::new(op);
919 instruction.set_type(result_type_id);
920 instruction.set_result(id);
921 instruction.add_operand(pointer);
922 instruction.add_operand(scope_id);
923 instruction.add_operand(semantics_id);
924 instruction.add_operand(value);
925 instruction
926 }
927
928 pub(super) fn derivative(op: Op, result_type_id: Word, id: Word, expr_id: Word) -> Self {
941 let mut instruction = Self::new(op);
942 instruction.set_type(result_type_id);
943 instruction.set_result(id);
944 instruction.add_operand(expr_id);
945 instruction
946 }
947
948 pub(super) fn phi(
953 result_type_id: Word,
954 result_id: Word,
955 var_parent_pairs: &[(Word, Word)],
956 ) -> Self {
957 let mut instruction = Self::new(Op::Phi);
958 instruction.add_operand(result_type_id);
959 instruction.add_operand(result_id);
960 for &(variable, parent) in var_parent_pairs {
961 instruction.add_operand(variable);
962 instruction.add_operand(parent);
963 }
964 instruction
965 }
966
967 pub(super) fn selection_merge(
968 merge_id: Word,
969 selection_control: spirv::SelectionControl,
970 ) -> Self {
971 let mut instruction = Self::new(Op::SelectionMerge);
972 instruction.add_operand(merge_id);
973 instruction.add_operand(selection_control.bits());
974 instruction
975 }
976
977 pub(super) fn loop_merge(
978 merge_id: Word,
979 continuing_id: Word,
980 selection_control: spirv::SelectionControl,
981 ) -> Self {
982 let mut instruction = Self::new(Op::LoopMerge);
983 instruction.add_operand(merge_id);
984 instruction.add_operand(continuing_id);
985 instruction.add_operand(selection_control.bits());
986 instruction
987 }
988
989 pub(super) fn label(id: Word) -> Self {
990 let mut instruction = Self::new(Op::Label);
991 instruction.set_result(id);
992 instruction
993 }
994
995 pub(super) fn branch(id: Word) -> Self {
996 let mut instruction = Self::new(Op::Branch);
997 instruction.add_operand(id);
998 instruction
999 }
1000
1001 pub(super) fn branch_conditional(
1003 condition_id: Word,
1004 true_label: Word,
1005 false_label: Word,
1006 ) -> Self {
1007 let mut instruction = Self::new(Op::BranchConditional);
1008 instruction.add_operand(condition_id);
1009 instruction.add_operand(true_label);
1010 instruction.add_operand(false_label);
1011 instruction
1012 }
1013
1014 pub(super) fn switch(selector_id: Word, default_id: Word, cases: &[Case]) -> Self {
1015 let mut instruction = Self::new(Op::Switch);
1016 instruction.add_operand(selector_id);
1017 instruction.add_operand(default_id);
1018 for case in cases {
1019 instruction.add_operand(case.value);
1020 instruction.add_operand(case.label_id);
1021 }
1022 instruction
1023 }
1024
1025 pub(super) fn select(
1026 result_type_id: Word,
1027 id: Word,
1028 condition_id: Word,
1029 accept_id: Word,
1030 reject_id: Word,
1031 ) -> Self {
1032 let mut instruction = Self::new(Op::Select);
1033 instruction.add_operand(result_type_id);
1034 instruction.add_operand(id);
1035 instruction.add_operand(condition_id);
1036 instruction.add_operand(accept_id);
1037 instruction.add_operand(reject_id);
1038 instruction
1039 }
1040
1041 pub(super) const fn kill() -> Self {
1042 Self::new(Op::Kill)
1043 }
1044
1045 pub(super) const fn return_void() -> Self {
1046 Self::new(Op::Return)
1047 }
1048
1049 pub(super) fn return_value(value_id: Word) -> Self {
1050 let mut instruction = Self::new(Op::ReturnValue);
1051 instruction.add_operand(value_id);
1052 instruction
1053 }
1054
1055 pub(super) fn control_barrier(
1066 exec_scope_id: Word,
1067 mem_scope_id: Word,
1068 semantics_id: Word,
1069 ) -> Self {
1070 let mut instruction = Self::new(Op::ControlBarrier);
1071 instruction.add_operand(exec_scope_id);
1072 instruction.add_operand(mem_scope_id);
1073 instruction.add_operand(semantics_id);
1074 instruction
1075 }
1076
1077 pub(super) fn group_non_uniform_ballot(
1080 result_type_id: Word,
1081 id: Word,
1082 exec_scope_id: Word,
1083 predicate: Word,
1084 ) -> Self {
1085 let mut instruction = Self::new(Op::GroupNonUniformBallot);
1086 instruction.set_type(result_type_id);
1087 instruction.set_result(id);
1088 instruction.add_operand(exec_scope_id);
1089 instruction.add_operand(predicate);
1090
1091 instruction
1092 }
1093 pub(super) fn group_non_uniform_broadcast_first(
1094 result_type_id: Word,
1095 id: Word,
1096 exec_scope_id: Word,
1097 value: Word,
1098 ) -> Self {
1099 let mut instruction = Self::new(Op::GroupNonUniformBroadcastFirst);
1100 instruction.set_type(result_type_id);
1101 instruction.set_result(id);
1102 instruction.add_operand(exec_scope_id);
1103 instruction.add_operand(value);
1104
1105 instruction
1106 }
1107 pub(super) fn group_non_uniform_gather(
1108 op: Op,
1109 result_type_id: Word,
1110 id: Word,
1111 exec_scope_id: Word,
1112 value: Word,
1113 index: Word,
1114 ) -> Self {
1115 let mut instruction = Self::new(op);
1116 instruction.set_type(result_type_id);
1117 instruction.set_result(id);
1118 instruction.add_operand(exec_scope_id);
1119 instruction.add_operand(value);
1120 instruction.add_operand(index);
1121
1122 instruction
1123 }
1124 pub(super) fn group_non_uniform_arithmetic(
1125 op: Op,
1126 result_type_id: Word,
1127 id: Word,
1128 exec_scope_id: Word,
1129 group_op: Option<spirv::GroupOperation>,
1130 value: Word,
1131 ) -> Self {
1132 let mut instruction = Self::new(op);
1133 instruction.set_type(result_type_id);
1134 instruction.set_result(id);
1135 instruction.add_operand(exec_scope_id);
1136 if let Some(group_op) = group_op {
1137 instruction.add_operand(group_op as u32);
1138 }
1139 instruction.add_operand(value);
1140
1141 instruction
1142 }
1143}
1144
1145impl From<crate::StorageFormat> for spirv::ImageFormat {
1146 fn from(format: crate::StorageFormat) -> Self {
1147 use crate::StorageFormat as Sf;
1148 match format {
1149 Sf::R8Unorm => Self::R8,
1150 Sf::R8Snorm => Self::R8Snorm,
1151 Sf::R8Uint => Self::R8ui,
1152 Sf::R8Sint => Self::R8i,
1153 Sf::R16Uint => Self::R16ui,
1154 Sf::R16Sint => Self::R16i,
1155 Sf::R16Float => Self::R16f,
1156 Sf::Rg8Unorm => Self::Rg8,
1157 Sf::Rg8Snorm => Self::Rg8Snorm,
1158 Sf::Rg8Uint => Self::Rg8ui,
1159 Sf::Rg8Sint => Self::Rg8i,
1160 Sf::R32Uint => Self::R32ui,
1161 Sf::R32Sint => Self::R32i,
1162 Sf::R32Float => Self::R32f,
1163 Sf::Rg16Uint => Self::Rg16ui,
1164 Sf::Rg16Sint => Self::Rg16i,
1165 Sf::Rg16Float => Self::Rg16f,
1166 Sf::Rgba8Unorm => Self::Rgba8,
1167 Sf::Rgba8Snorm => Self::Rgba8Snorm,
1168 Sf::Rgba8Uint => Self::Rgba8ui,
1169 Sf::Rgba8Sint => Self::Rgba8i,
1170 Sf::Bgra8Unorm => Self::Unknown,
1171 Sf::Rgb10a2Uint => Self::Rgb10a2ui,
1172 Sf::Rgb10a2Unorm => Self::Rgb10A2,
1173 Sf::Rg11b10Ufloat => Self::R11fG11fB10f,
1174 Sf::Rg32Uint => Self::Rg32ui,
1175 Sf::Rg32Sint => Self::Rg32i,
1176 Sf::Rg32Float => Self::Rg32f,
1177 Sf::Rgba16Uint => Self::Rgba16ui,
1178 Sf::Rgba16Sint => Self::Rgba16i,
1179 Sf::Rgba16Float => Self::Rgba16f,
1180 Sf::Rgba32Uint => Self::Rgba32ui,
1181 Sf::Rgba32Sint => Self::Rgba32i,
1182 Sf::Rgba32Float => Self::Rgba32f,
1183 Sf::R16Unorm => Self::R16,
1184 Sf::R16Snorm => Self::R16Snorm,
1185 Sf::Rg16Unorm => Self::Rg16,
1186 Sf::Rg16Snorm => Self::Rg16Snorm,
1187 Sf::Rgba16Unorm => Self::Rgba16,
1188 Sf::Rgba16Snorm => Self::Rgba16Snorm,
1189 }
1190 }
1191}
1192
1193impl From<crate::ImageDimension> for spirv::Dim {
1194 fn from(dim: crate::ImageDimension) -> Self {
1195 use crate::ImageDimension as Id;
1196 match dim {
1197 Id::D1 => Self::Dim1D,
1198 Id::D2 => Self::Dim2D,
1199 Id::D3 => Self::Dim3D,
1200 Id::Cube => Self::DimCube,
1201 }
1202 }
1203}