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