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_gl_op(
160 set_id: Word,
161 op: spirv::GLOp,
162 result_type_id: Word,
163 id: Word,
164 operands: &[Word],
165 ) -> Self {
166 Self::ext_inst(set_id, op as u32, result_type_id, id, operands)
167 }
168
169 pub(super) fn ext_inst(
170 set_id: Word,
171 op: u32,
172 result_type_id: Word,
173 id: Word,
174 operands: &[Word],
175 ) -> Self {
176 let mut instruction = Self::new(Op::ExtInst);
177 instruction.set_type(result_type_id);
178 instruction.set_result(id);
179 instruction.add_operand(set_id);
180 instruction.add_operand(op);
181 for operand in operands {
182 instruction.add_operand(*operand)
183 }
184 instruction
185 }
186
187 pub(super) fn memory_model(
192 addressing_model: spirv::AddressingModel,
193 memory_model: spirv::MemoryModel,
194 ) -> Self {
195 let mut instruction = Self::new(Op::MemoryModel);
196 instruction.add_operand(addressing_model as u32);
197 instruction.add_operand(memory_model as u32);
198 instruction
199 }
200
201 pub(super) fn entry_point(
202 execution_model: spirv::ExecutionModel,
203 entry_point_id: Word,
204 name: &str,
205 interface_ids: &[Word],
206 ) -> Self {
207 let mut instruction = Self::new(Op::EntryPoint);
208 instruction.add_operand(execution_model as u32);
209 instruction.add_operand(entry_point_id);
210 instruction.add_operands(helpers::string_to_words(name));
211
212 for interface_id in interface_ids {
213 instruction.add_operand(*interface_id);
214 }
215
216 instruction
217 }
218
219 pub(super) fn execution_mode(
220 entry_point_id: Word,
221 execution_mode: spirv::ExecutionMode,
222 args: &[Word],
223 ) -> Self {
224 let mut instruction = Self::new(Op::ExecutionMode);
225 instruction.add_operand(entry_point_id);
226 instruction.add_operand(execution_mode as u32);
227 for arg in args {
228 instruction.add_operand(*arg);
229 }
230 instruction
231 }
232
233 pub(super) fn capability(capability: spirv::Capability) -> Self {
234 let mut instruction = Self::new(Op::Capability);
235 instruction.add_operand(capability as u32);
236 instruction
237 }
238
239 pub(super) fn type_void(id: Word) -> Self {
244 let mut instruction = Self::new(Op::TypeVoid);
245 instruction.set_result(id);
246 instruction
247 }
248
249 pub(super) fn type_bool(id: Word) -> Self {
250 let mut instruction = Self::new(Op::TypeBool);
251 instruction.set_result(id);
252 instruction
253 }
254
255 pub(super) fn type_int(id: Word, width: Word, signedness: Signedness) -> Self {
256 let mut instruction = Self::new(Op::TypeInt);
257 instruction.set_result(id);
258 instruction.add_operand(width);
259 instruction.add_operand(signedness as u32);
260 instruction
261 }
262
263 pub(super) fn type_float(id: Word, width: Word) -> Self {
264 let mut instruction = Self::new(Op::TypeFloat);
265 instruction.set_result(id);
266 instruction.add_operand(width);
267 instruction
268 }
269
270 pub(super) fn type_vector(
271 id: Word,
272 component_type_id: Word,
273 component_count: crate::VectorSize,
274 ) -> Self {
275 let mut instruction = Self::new(Op::TypeVector);
276 instruction.set_result(id);
277 instruction.add_operand(component_type_id);
278 instruction.add_operand(component_count as u32);
279 instruction
280 }
281
282 pub(super) fn type_matrix(
283 id: Word,
284 column_type_id: Word,
285 column_count: crate::VectorSize,
286 ) -> Self {
287 let mut instruction = Self::new(Op::TypeMatrix);
288 instruction.set_result(id);
289 instruction.add_operand(column_type_id);
290 instruction.add_operand(column_count as u32);
291 instruction
292 }
293
294 pub(super) fn type_coop_matrix(
295 id: Word,
296 scalar_type_id: Word,
297 scope_id: Word,
298 row_count_id: Word,
299 column_count_id: Word,
300 matrix_use_id: Word,
301 ) -> Self {
302 let mut instruction = Self::new(Op::TypeCooperativeMatrixKHR);
303 instruction.set_result(id);
304 instruction.add_operand(scalar_type_id);
305 instruction.add_operand(scope_id);
306 instruction.add_operand(row_count_id);
307 instruction.add_operand(column_count_id);
308 instruction.add_operand(matrix_use_id);
309 instruction
310 }
311
312 #[allow(clippy::too_many_arguments)]
313 pub(super) fn type_image(
314 id: Word,
315 sampled_type_id: Word,
316 dim: spirv::Dim,
317 flags: super::ImageTypeFlags,
318 image_format: spirv::ImageFormat,
319 ) -> Self {
320 let mut instruction = Self::new(Op::TypeImage);
321 instruction.set_result(id);
322 instruction.add_operand(sampled_type_id);
323 instruction.add_operand(dim as u32);
324 instruction.add_operand(flags.contains(super::ImageTypeFlags::DEPTH) as u32);
325 instruction.add_operand(flags.contains(super::ImageTypeFlags::ARRAYED) as u32);
326 instruction.add_operand(flags.contains(super::ImageTypeFlags::MULTISAMPLED) as u32);
327 instruction.add_operand(if flags.contains(super::ImageTypeFlags::SAMPLED) {
328 1
329 } else {
330 2
331 });
332 instruction.add_operand(image_format as u32);
333 instruction
334 }
335
336 pub(super) fn type_sampler(id: Word) -> Self {
337 let mut instruction = Self::new(Op::TypeSampler);
338 instruction.set_result(id);
339 instruction
340 }
341
342 pub(super) fn type_acceleration_structure(id: Word) -> Self {
343 let mut instruction = Self::new(Op::TypeAccelerationStructureKHR);
344 instruction.set_result(id);
345 instruction
346 }
347
348 pub(super) fn type_ray_query(id: Word) -> Self {
349 let mut instruction = Self::new(Op::TypeRayQueryKHR);
350 instruction.set_result(id);
351 instruction
352 }
353
354 pub(super) fn type_sampled_image(id: Word, image_type_id: Word) -> Self {
355 let mut instruction = Self::new(Op::TypeSampledImage);
356 instruction.set_result(id);
357 instruction.add_operand(image_type_id);
358 instruction
359 }
360
361 pub(super) fn type_array(id: Word, element_type_id: Word, length_id: Word) -> Self {
362 let mut instruction = Self::new(Op::TypeArray);
363 instruction.set_result(id);
364 instruction.add_operand(element_type_id);
365 instruction.add_operand(length_id);
366 instruction
367 }
368
369 pub(super) fn type_runtime_array(id: Word, element_type_id: Word) -> Self {
370 let mut instruction = Self::new(Op::TypeRuntimeArray);
371 instruction.set_result(id);
372 instruction.add_operand(element_type_id);
373 instruction
374 }
375
376 pub(super) fn type_struct(id: Word, member_ids: &[Word]) -> Self {
377 let mut instruction = Self::new(Op::TypeStruct);
378 instruction.set_result(id);
379
380 for member_id in member_ids {
381 instruction.add_operand(*member_id)
382 }
383
384 instruction
385 }
386
387 pub(super) fn type_pointer(
388 id: Word,
389 storage_class: spirv::StorageClass,
390 type_id: Word,
391 ) -> Self {
392 let mut instruction = Self::new(Op::TypePointer);
393 instruction.set_result(id);
394 instruction.add_operand(storage_class as u32);
395 instruction.add_operand(type_id);
396 instruction
397 }
398
399 pub(super) fn type_function(id: Word, return_type_id: Word, parameter_ids: &[Word]) -> Self {
400 let mut instruction = Self::new(Op::TypeFunction);
401 instruction.set_result(id);
402 instruction.add_operand(return_type_id);
403
404 for parameter_id in parameter_ids {
405 instruction.add_operand(*parameter_id);
406 }
407
408 instruction
409 }
410
411 pub(super) fn constant_null(result_type_id: Word, id: Word) -> Self {
416 let mut instruction = Self::new(Op::ConstantNull);
417 instruction.set_type(result_type_id);
418 instruction.set_result(id);
419 instruction
420 }
421
422 pub(super) fn constant_true(result_type_id: Word, id: Word) -> Self {
423 let mut instruction = Self::new(Op::ConstantTrue);
424 instruction.set_type(result_type_id);
425 instruction.set_result(id);
426 instruction
427 }
428
429 pub(super) fn constant_false(result_type_id: Word, id: Word) -> Self {
430 let mut instruction = Self::new(Op::ConstantFalse);
431 instruction.set_type(result_type_id);
432 instruction.set_result(id);
433 instruction
434 }
435
436 pub(super) fn constant_16bit(result_type_id: Word, id: Word, low: Word) -> Self {
437 Self::constant(result_type_id, id, &[low])
438 }
439
440 pub(super) fn constant_32bit(result_type_id: Word, id: Word, value: Word) -> Self {
441 Self::constant(result_type_id, id, &[value])
442 }
443
444 pub(super) fn constant_64bit(result_type_id: Word, id: Word, low: Word, high: Word) -> Self {
445 Self::constant(result_type_id, id, &[low, high])
446 }
447
448 pub(super) fn constant(result_type_id: Word, id: Word, values: &[Word]) -> Self {
449 let mut instruction = Self::new(Op::Constant);
450 instruction.set_type(result_type_id);
451 instruction.set_result(id);
452
453 for value in values {
454 instruction.add_operand(*value);
455 }
456
457 instruction
458 }
459
460 pub(super) fn constant_composite(
461 result_type_id: Word,
462 id: Word,
463 constituent_ids: &[Word],
464 ) -> Self {
465 let mut instruction = Self::new(Op::ConstantComposite);
466 instruction.set_type(result_type_id);
467 instruction.set_result(id);
468
469 for constituent_id in constituent_ids {
470 instruction.add_operand(*constituent_id);
471 }
472
473 instruction
474 }
475
476 pub(super) fn variable(
481 result_type_id: Word,
482 id: Word,
483 storage_class: spirv::StorageClass,
484 initializer_id: Option<Word>,
485 ) -> Self {
486 let mut instruction = Self::new(Op::Variable);
487 instruction.set_type(result_type_id);
488 instruction.set_result(id);
489 instruction.add_operand(storage_class as u32);
490
491 if let Some(initializer_id) = initializer_id {
492 instruction.add_operand(initializer_id);
493 }
494
495 instruction
496 }
497
498 pub(super) fn load(
499 result_type_id: Word,
500 id: Word,
501 pointer_id: Word,
502 memory_access: Option<spirv::MemoryAccess>,
503 ) -> Self {
504 let mut instruction = Self::new(Op::Load);
505 instruction.set_type(result_type_id);
506 instruction.set_result(id);
507 instruction.add_operand(pointer_id);
508
509 if let Some(memory_access) = memory_access {
510 instruction.add_operand(memory_access.bits());
511 }
512
513 instruction
514 }
515
516 pub(super) fn atomic_load(
517 result_type_id: Word,
518 id: Word,
519 pointer_id: Word,
520 scope_id: Word,
521 semantics_id: Word,
522 ) -> Self {
523 let mut instruction = Self::new(Op::AtomicLoad);
524 instruction.set_type(result_type_id);
525 instruction.set_result(id);
526 instruction.add_operand(pointer_id);
527 instruction.add_operand(scope_id);
528 instruction.add_operand(semantics_id);
529 instruction
530 }
531
532 pub(super) fn store(
533 pointer_id: Word,
534 value_id: Word,
535 memory_access: Option<spirv::MemoryAccess>,
536 ) -> Self {
537 let mut instruction = Self::new(Op::Store);
538 instruction.add_operand(pointer_id);
539 instruction.add_operand(value_id);
540
541 if let Some(memory_access) = memory_access {
542 instruction.add_operand(memory_access.bits());
543 }
544
545 instruction
546 }
547
548 pub(super) fn atomic_store(
549 pointer_id: Word,
550 scope_id: Word,
551 semantics_id: Word,
552 value_id: Word,
553 ) -> Self {
554 let mut instruction = Self::new(Op::AtomicStore);
555 instruction.add_operand(pointer_id);
556 instruction.add_operand(scope_id);
557 instruction.add_operand(semantics_id);
558 instruction.add_operand(value_id);
559 instruction
560 }
561
562 pub(super) fn access_chain(
563 result_type_id: Word,
564 id: Word,
565 base_id: Word,
566 index_ids: &[Word],
567 ) -> Self {
568 let mut instruction = Self::new(Op::AccessChain);
569 instruction.set_type(result_type_id);
570 instruction.set_result(id);
571 instruction.add_operand(base_id);
572
573 for index_id in index_ids {
574 instruction.add_operand(*index_id);
575 }
576
577 instruction
578 }
579
580 pub(super) fn array_length(
581 result_type_id: Word,
582 id: Word,
583 structure_id: Word,
584 array_member: Word,
585 ) -> Self {
586 let mut instruction = Self::new(Op::ArrayLength);
587 instruction.set_type(result_type_id);
588 instruction.set_result(id);
589 instruction.add_operand(structure_id);
590 instruction.add_operand(array_member);
591 instruction
592 }
593
594 pub(super) fn function(
599 return_type_id: Word,
600 id: Word,
601 function_control: spirv::FunctionControl,
602 function_type_id: Word,
603 ) -> Self {
604 let mut instruction = Self::new(Op::Function);
605 instruction.set_type(return_type_id);
606 instruction.set_result(id);
607 instruction.add_operand(function_control.bits());
608 instruction.add_operand(function_type_id);
609 instruction
610 }
611
612 pub(super) fn function_parameter(result_type_id: Word, id: Word) -> Self {
613 let mut instruction = Self::new(Op::FunctionParameter);
614 instruction.set_type(result_type_id);
615 instruction.set_result(id);
616 instruction
617 }
618
619 pub(super) const fn function_end() -> Self {
620 Self::new(Op::FunctionEnd)
621 }
622
623 pub(super) fn function_call(
624 result_type_id: Word,
625 id: Word,
626 function_id: Word,
627 argument_ids: &[Word],
628 ) -> Self {
629 let mut instruction = Self::new(Op::FunctionCall);
630 instruction.set_type(result_type_id);
631 instruction.set_result(id);
632 instruction.add_operand(function_id);
633
634 for argument_id in argument_ids {
635 instruction.add_operand(*argument_id);
636 }
637
638 instruction
639 }
640
641 pub(super) fn sampled_image(
646 result_type_id: Word,
647 id: Word,
648 image: Word,
649 sampler: Word,
650 ) -> Self {
651 let mut instruction = Self::new(Op::SampledImage);
652 instruction.set_type(result_type_id);
653 instruction.set_result(id);
654 instruction.add_operand(image);
655 instruction.add_operand(sampler);
656 instruction
657 }
658
659 pub(super) fn image_sample(
660 result_type_id: Word,
661 id: Word,
662 lod: SampleLod,
663 sampled_image: Word,
664 coordinates: Word,
665 depth_ref: Option<Word>,
666 ) -> Self {
667 let op = match (lod, depth_ref) {
668 (SampleLod::Explicit, None) => Op::ImageSampleExplicitLod,
669 (SampleLod::Implicit, None) => Op::ImageSampleImplicitLod,
670 (SampleLod::Explicit, Some(_)) => Op::ImageSampleDrefExplicitLod,
671 (SampleLod::Implicit, Some(_)) => Op::ImageSampleDrefImplicitLod,
672 };
673
674 let mut instruction = Self::new(op);
675 instruction.set_type(result_type_id);
676 instruction.set_result(id);
677 instruction.add_operand(sampled_image);
678 instruction.add_operand(coordinates);
679 if let Some(dref) = depth_ref {
680 instruction.add_operand(dref);
681 }
682
683 instruction
684 }
685
686 pub(super) fn image_gather(
687 result_type_id: Word,
688 id: Word,
689 sampled_image: Word,
690 coordinates: Word,
691 component_id: Word,
692 depth_ref: Option<Word>,
693 ) -> Self {
694 let op = match depth_ref {
695 None => Op::ImageGather,
696 Some(_) => Op::ImageDrefGather,
697 };
698
699 let mut instruction = Self::new(op);
700 instruction.set_type(result_type_id);
701 instruction.set_result(id);
702 instruction.add_operand(sampled_image);
703 instruction.add_operand(coordinates);
704 if let Some(dref) = depth_ref {
705 instruction.add_operand(dref);
706 } else {
707 instruction.add_operand(component_id);
708 }
709
710 instruction
711 }
712
713 pub(super) fn image_fetch_or_read(
714 op: Op,
715 result_type_id: Word,
716 id: Word,
717 image: Word,
718 coordinates: Word,
719 ) -> Self {
720 let mut instruction = Self::new(op);
721 instruction.set_type(result_type_id);
722 instruction.set_result(id);
723 instruction.add_operand(image);
724 instruction.add_operand(coordinates);
725 instruction
726 }
727
728 pub(super) fn image_write(image: Word, coordinates: Word, value: Word) -> Self {
729 let mut instruction = Self::new(Op::ImageWrite);
730 instruction.add_operand(image);
731 instruction.add_operand(coordinates);
732 instruction.add_operand(value);
733 instruction
734 }
735
736 pub(super) fn image_texel_pointer(
737 result_type_id: Word,
738 id: Word,
739 image: Word,
740 coordinates: Word,
741 sample: Word,
742 ) -> Self {
743 let mut instruction = Self::new(Op::ImageTexelPointer);
744 instruction.set_type(result_type_id);
745 instruction.set_result(id);
746 instruction.add_operand(image);
747 instruction.add_operand(coordinates);
748 instruction.add_operand(sample);
749 instruction
750 }
751
752 pub(super) fn image_atomic(
753 op: Op,
754 result_type_id: Word,
755 id: Word,
756 pointer: Word,
757 scope_id: Word,
758 semantics_id: Word,
759 value: Word,
760 ) -> Self {
761 let mut instruction = Self::new(op);
762 instruction.set_type(result_type_id);
763 instruction.set_result(id);
764 instruction.add_operand(pointer);
765 instruction.add_operand(scope_id);
766 instruction.add_operand(semantics_id);
767 instruction.add_operand(value);
768 instruction
769 }
770
771 pub(super) fn image_query(op: Op, result_type_id: Word, id: Word, image: Word) -> Self {
772 let mut instruction = Self::new(op);
773 instruction.set_type(result_type_id);
774 instruction.set_result(id);
775 instruction.add_operand(image);
776 instruction
777 }
778
779 #[allow(clippy::too_many_arguments)]
783 pub(super) fn ray_query_initialize(
784 query: Word,
785 acceleration_structure: Word,
786 ray_flags: Word,
787 cull_mask: Word,
788 ray_origin: Word,
789 ray_tmin: Word,
790 ray_dir: Word,
791 ray_tmax: Word,
792 ) -> Self {
793 let mut instruction = Self::new(Op::RayQueryInitializeKHR);
794 instruction.add_operand(query);
795 instruction.add_operand(acceleration_structure);
796 instruction.add_operand(ray_flags);
797 instruction.add_operand(cull_mask);
798 instruction.add_operand(ray_origin);
799 instruction.add_operand(ray_tmin);
800 instruction.add_operand(ray_dir);
801 instruction.add_operand(ray_tmax);
802 instruction
803 }
804
805 pub(super) fn ray_query_proceed(result_type_id: Word, id: Word, query: Word) -> Self {
806 let mut instruction = Self::new(Op::RayQueryProceedKHR);
807 instruction.set_type(result_type_id);
808 instruction.set_result(id);
809 instruction.add_operand(query);
810 instruction
811 }
812
813 pub(super) fn ray_query_generate_intersection(query: Word, hit: Word) -> Self {
814 let mut instruction = Self::new(Op::RayQueryGenerateIntersectionKHR);
815 instruction.add_operand(query);
816 instruction.add_operand(hit);
817 instruction
818 }
819
820 pub(super) fn ray_query_confirm_intersection(query: Word) -> Self {
821 let mut instruction = Self::new(Op::RayQueryConfirmIntersectionKHR);
822 instruction.add_operand(query);
823 instruction
824 }
825
826 pub(super) fn ray_query_return_vertex_position(
827 result_type_id: Word,
828 id: Word,
829 query: Word,
830 intersection: Word,
831 ) -> Self {
832 let mut instruction = Self::new(Op::RayQueryGetIntersectionTriangleVertexPositionsKHR);
833 instruction.set_type(result_type_id);
834 instruction.set_result(id);
835 instruction.add_operand(query);
836 instruction.add_operand(intersection);
837 instruction
838 }
839
840 pub(super) fn ray_query_get_intersection(
841 op: Op,
842 result_type_id: Word,
843 id: Word,
844 query: Word,
845 intersection: Word,
846 ) -> Self {
847 let mut instruction = Self::new(op);
848 instruction.set_type(result_type_id);
849 instruction.set_result(id);
850 instruction.add_operand(query);
851 instruction.add_operand(intersection);
852 instruction
853 }
854
855 pub(super) fn ray_query_get_t_min(result_type_id: Word, id: Word, query: Word) -> Self {
856 let mut instruction = Self::new(Op::RayQueryGetRayTMinKHR);
857 instruction.set_type(result_type_id);
858 instruction.set_result(id);
859 instruction.add_operand(query);
860 instruction
861 }
862
863 pub(super) fn ray_query_terminate(query: Word) -> Self {
864 let mut instruction = Self::new(Op::RayQueryTerminateKHR);
865 instruction.add_operand(query);
866 instruction
867 }
868
869 pub(super) fn unary(op: Op, result_type_id: Word, id: Word, value: Word) -> Self {
873 let mut instruction = Self::new(op);
874 instruction.set_type(result_type_id);
875 instruction.set_result(id);
876 instruction.add_operand(value);
877 instruction
878 }
879
880 pub(super) fn composite_construct(
885 result_type_id: Word,
886 id: Word,
887 constituent_ids: &[Word],
888 ) -> Self {
889 let mut instruction = Self::new(Op::CompositeConstruct);
890 instruction.set_type(result_type_id);
891 instruction.set_result(id);
892
893 for constituent_id in constituent_ids {
894 instruction.add_operand(*constituent_id);
895 }
896
897 instruction
898 }
899
900 pub(super) fn composite_extract(
901 result_type_id: Word,
902 id: Word,
903 composite_id: Word,
904 indices: &[Word],
905 ) -> Self {
906 let mut instruction = Self::new(Op::CompositeExtract);
907 instruction.set_type(result_type_id);
908 instruction.set_result(id);
909
910 instruction.add_operand(composite_id);
911 for index in indices {
912 instruction.add_operand(*index);
913 }
914
915 instruction
916 }
917
918 pub(super) fn vector_extract_dynamic(
919 result_type_id: Word,
920 id: Word,
921 vector_id: Word,
922 index_id: Word,
923 ) -> Self {
924 let mut instruction = Self::new(Op::VectorExtractDynamic);
925 instruction.set_type(result_type_id);
926 instruction.set_result(id);
927
928 instruction.add_operand(vector_id);
929 instruction.add_operand(index_id);
930
931 instruction
932 }
933
934 pub(super) fn vector_shuffle(
935 result_type_id: Word,
936 id: Word,
937 v1_id: Word,
938 v2_id: Word,
939 components: &[Word],
940 ) -> Self {
941 let mut instruction = Self::new(Op::VectorShuffle);
942 instruction.set_type(result_type_id);
943 instruction.set_result(id);
944 instruction.add_operand(v1_id);
945 instruction.add_operand(v2_id);
946
947 for &component in components {
948 instruction.add_operand(component);
949 }
950
951 instruction
952 }
953
954 pub(super) fn binary(
958 op: Op,
959 result_type_id: Word,
960 id: Word,
961 operand_1: Word,
962 operand_2: Word,
963 ) -> Self {
964 let mut instruction = Self::new(op);
965 instruction.set_type(result_type_id);
966 instruction.set_result(id);
967 instruction.add_operand(operand_1);
968 instruction.add_operand(operand_2);
969 instruction
970 }
971
972 pub(super) fn ternary(
973 op: Op,
974 result_type_id: Word,
975 id: Word,
976 operand_1: Word,
977 operand_2: Word,
978 operand_3: Word,
979 ) -> Self {
980 let mut instruction = Self::new(op);
981 instruction.set_type(result_type_id);
982 instruction.set_result(id);
983 instruction.add_operand(operand_1);
984 instruction.add_operand(operand_2);
985 instruction.add_operand(operand_3);
986 instruction
987 }
988
989 pub(super) fn quaternary(
990 op: Op,
991 result_type_id: Word,
992 id: Word,
993 operand_1: Word,
994 operand_2: Word,
995 operand_3: Word,
996 operand_4: Word,
997 ) -> Self {
998 let mut instruction = Self::new(op);
999 instruction.set_type(result_type_id);
1000 instruction.set_result(id);
1001 instruction.add_operand(operand_1);
1002 instruction.add_operand(operand_2);
1003 instruction.add_operand(operand_3);
1004 instruction.add_operand(operand_4);
1005 instruction
1006 }
1007
1008 pub(super) fn relational(op: Op, result_type_id: Word, id: Word, expr_id: Word) -> Self {
1009 let mut instruction = Self::new(op);
1010 instruction.set_type(result_type_id);
1011 instruction.set_result(id);
1012 instruction.add_operand(expr_id);
1013 instruction
1014 }
1015
1016 pub(super) fn atomic_binary(
1017 op: Op,
1018 result_type_id: Word,
1019 id: Word,
1020 pointer: Word,
1021 scope_id: Word,
1022 semantics_id: Word,
1023 value: Word,
1024 ) -> Self {
1025 let mut instruction = Self::new(op);
1026 instruction.set_type(result_type_id);
1027 instruction.set_result(id);
1028 instruction.add_operand(pointer);
1029 instruction.add_operand(scope_id);
1030 instruction.add_operand(semantics_id);
1031 instruction.add_operand(value);
1032 instruction
1033 }
1034
1035 pub(super) fn derivative(op: Op, result_type_id: Word, id: Word, expr_id: Word) -> Self {
1048 let mut instruction = Self::new(op);
1049 instruction.set_type(result_type_id);
1050 instruction.set_result(id);
1051 instruction.add_operand(expr_id);
1052 instruction
1053 }
1054
1055 pub(super) fn phi(
1060 result_type_id: Word,
1061 result_id: Word,
1062 var_parent_pairs: &[(Word, Word)],
1063 ) -> Self {
1064 let mut instruction = Self::new(Op::Phi);
1065 instruction.add_operand(result_type_id);
1066 instruction.add_operand(result_id);
1067 for &(variable, parent) in var_parent_pairs {
1068 instruction.add_operand(variable);
1069 instruction.add_operand(parent);
1070 }
1071 instruction
1072 }
1073
1074 pub(super) fn selection_merge(
1075 merge_id: Word,
1076 selection_control: spirv::SelectionControl,
1077 ) -> Self {
1078 let mut instruction = Self::new(Op::SelectionMerge);
1079 instruction.add_operand(merge_id);
1080 instruction.add_operand(selection_control.bits());
1081 instruction
1082 }
1083
1084 pub(super) fn loop_merge(
1085 merge_id: Word,
1086 continuing_id: Word,
1087 selection_control: spirv::SelectionControl,
1088 ) -> Self {
1089 let mut instruction = Self::new(Op::LoopMerge);
1090 instruction.add_operand(merge_id);
1091 instruction.add_operand(continuing_id);
1092 instruction.add_operand(selection_control.bits());
1093 instruction
1094 }
1095
1096 pub(super) fn label(id: Word) -> Self {
1097 let mut instruction = Self::new(Op::Label);
1098 instruction.set_result(id);
1099 instruction
1100 }
1101
1102 pub(super) fn branch(id: Word) -> Self {
1103 let mut instruction = Self::new(Op::Branch);
1104 instruction.add_operand(id);
1105 instruction
1106 }
1107
1108 pub(super) fn branch_conditional(
1110 condition_id: Word,
1111 true_label: Word,
1112 false_label: Word,
1113 ) -> Self {
1114 let mut instruction = Self::new(Op::BranchConditional);
1115 instruction.add_operand(condition_id);
1116 instruction.add_operand(true_label);
1117 instruction.add_operand(false_label);
1118 instruction
1119 }
1120
1121 pub(super) fn switch(selector_id: Word, default_id: Word, cases: &[Case]) -> Self {
1122 let mut instruction = Self::new(Op::Switch);
1123 instruction.add_operand(selector_id);
1124 instruction.add_operand(default_id);
1125 for case in cases {
1126 instruction.add_operand(case.value);
1127 instruction.add_operand(case.label_id);
1128 }
1129 instruction
1130 }
1131
1132 pub(super) fn select(
1133 result_type_id: Word,
1134 id: Word,
1135 condition_id: Word,
1136 accept_id: Word,
1137 reject_id: Word,
1138 ) -> Self {
1139 let mut instruction = Self::new(Op::Select);
1140 instruction.add_operand(result_type_id);
1141 instruction.add_operand(id);
1142 instruction.add_operand(condition_id);
1143 instruction.add_operand(accept_id);
1144 instruction.add_operand(reject_id);
1145 instruction
1146 }
1147
1148 pub(super) const fn kill() -> Self {
1149 Self::new(Op::Kill)
1150 }
1151
1152 pub(super) const fn return_void() -> Self {
1153 Self::new(Op::Return)
1154 }
1155
1156 pub(super) fn return_value(value_id: Word) -> Self {
1157 let mut instruction = Self::new(Op::ReturnValue);
1158 instruction.add_operand(value_id);
1159 instruction
1160 }
1161
1162 pub(super) fn control_barrier(
1173 exec_scope_id: Word,
1174 mem_scope_id: Word,
1175 semantics_id: Word,
1176 ) -> Self {
1177 let mut instruction = Self::new(Op::ControlBarrier);
1178 instruction.add_operand(exec_scope_id);
1179 instruction.add_operand(mem_scope_id);
1180 instruction.add_operand(semantics_id);
1181 instruction
1182 }
1183 pub(super) fn memory_barrier(mem_scope_id: Word, semantics_id: Word) -> Self {
1184 let mut instruction = Self::new(Op::MemoryBarrier);
1185 instruction.add_operand(mem_scope_id);
1186 instruction.add_operand(semantics_id);
1187 instruction
1188 }
1189
1190 pub(super) fn group_non_uniform_ballot(
1193 result_type_id: Word,
1194 id: Word,
1195 exec_scope_id: Word,
1196 predicate: Word,
1197 ) -> Self {
1198 let mut instruction = Self::new(Op::GroupNonUniformBallot);
1199 instruction.set_type(result_type_id);
1200 instruction.set_result(id);
1201 instruction.add_operand(exec_scope_id);
1202 instruction.add_operand(predicate);
1203
1204 instruction
1205 }
1206 pub(super) fn group_non_uniform_broadcast_first(
1207 result_type_id: Word,
1208 id: Word,
1209 exec_scope_id: Word,
1210 value: Word,
1211 ) -> Self {
1212 let mut instruction = Self::new(Op::GroupNonUniformBroadcastFirst);
1213 instruction.set_type(result_type_id);
1214 instruction.set_result(id);
1215 instruction.add_operand(exec_scope_id);
1216 instruction.add_operand(value);
1217
1218 instruction
1219 }
1220 pub(super) fn group_non_uniform_gather(
1221 op: Op,
1222 result_type_id: Word,
1223 id: Word,
1224 exec_scope_id: Word,
1225 value: Word,
1226 index: Word,
1227 ) -> Self {
1228 let mut instruction = Self::new(op);
1229 instruction.set_type(result_type_id);
1230 instruction.set_result(id);
1231 instruction.add_operand(exec_scope_id);
1232 instruction.add_operand(value);
1233 instruction.add_operand(index);
1234
1235 instruction
1236 }
1237 pub(super) fn group_non_uniform_arithmetic(
1238 op: Op,
1239 result_type_id: Word,
1240 id: Word,
1241 exec_scope_id: Word,
1242 group_op: Option<spirv::GroupOperation>,
1243 value: Word,
1244 ) -> Self {
1245 let mut instruction = Self::new(op);
1246 instruction.set_type(result_type_id);
1247 instruction.set_result(id);
1248 instruction.add_operand(exec_scope_id);
1249 if let Some(group_op) = group_op {
1250 instruction.add_operand(group_op as u32);
1251 }
1252 instruction.add_operand(value);
1253
1254 instruction
1255 }
1256 pub(super) fn group_non_uniform_quad_swap(
1257 result_type_id: Word,
1258 id: Word,
1259 exec_scope_id: Word,
1260 value: Word,
1261 direction: Word,
1262 ) -> Self {
1263 let mut instruction = Self::new(Op::GroupNonUniformQuadSwap);
1264 instruction.set_type(result_type_id);
1265 instruction.set_result(id);
1266 instruction.add_operand(exec_scope_id);
1267 instruction.add_operand(value);
1268 instruction.add_operand(direction);
1269
1270 instruction
1271 }
1272
1273 pub(super) fn coop_load(
1275 result_type_id: Word,
1276 id: Word,
1277 pointer_id: Word,
1278 layout_id: Word,
1279 stride_id: Word,
1280 ) -> Self {
1281 let mut instruction = Self::new(Op::CooperativeMatrixLoadKHR);
1282 instruction.set_type(result_type_id);
1283 instruction.set_result(id);
1284 instruction.add_operand(pointer_id);
1285 instruction.add_operand(layout_id);
1286 instruction.add_operand(stride_id);
1287 instruction
1288 }
1289 pub(super) fn coop_store(id: Word, pointer_id: Word, layout_id: Word, stride_id: Word) -> Self {
1290 let mut instruction = Self::new(Op::CooperativeMatrixStoreKHR);
1291 instruction.add_operand(pointer_id);
1292 instruction.add_operand(id);
1293 instruction.add_operand(layout_id);
1294 instruction.add_operand(stride_id);
1295 instruction
1296 }
1297 pub(super) fn coop_mul_add(result_type_id: Word, id: Word, a: Word, b: Word, c: Word) -> Self {
1298 let mut instruction = Self::new(Op::CooperativeMatrixMulAddKHR);
1299 instruction.set_type(result_type_id);
1300 instruction.set_result(id);
1301 instruction.add_operand(a);
1302 instruction.add_operand(b);
1303 instruction.add_operand(c);
1304
1305 instruction
1306 }
1307}
1308
1309impl From<crate::StorageFormat> for spirv::ImageFormat {
1310 fn from(format: crate::StorageFormat) -> Self {
1311 use crate::StorageFormat as Sf;
1312 match format {
1313 Sf::R8Unorm => Self::R8,
1314 Sf::R8Snorm => Self::R8Snorm,
1315 Sf::R8Uint => Self::R8ui,
1316 Sf::R8Sint => Self::R8i,
1317 Sf::R16Uint => Self::R16ui,
1318 Sf::R16Sint => Self::R16i,
1319 Sf::R16Float => Self::R16f,
1320 Sf::Rg8Unorm => Self::Rg8,
1321 Sf::Rg8Snorm => Self::Rg8Snorm,
1322 Sf::Rg8Uint => Self::Rg8ui,
1323 Sf::Rg8Sint => Self::Rg8i,
1324 Sf::R32Uint => Self::R32ui,
1325 Sf::R32Sint => Self::R32i,
1326 Sf::R32Float => Self::R32f,
1327 Sf::Rg16Uint => Self::Rg16ui,
1328 Sf::Rg16Sint => Self::Rg16i,
1329 Sf::Rg16Float => Self::Rg16f,
1330 Sf::Rgba8Unorm => Self::Rgba8,
1331 Sf::Rgba8Snorm => Self::Rgba8Snorm,
1332 Sf::Rgba8Uint => Self::Rgba8ui,
1333 Sf::Rgba8Sint => Self::Rgba8i,
1334 Sf::Bgra8Unorm => Self::Unknown,
1335 Sf::Rgb10a2Uint => Self::Rgb10a2ui,
1336 Sf::Rgb10a2Unorm => Self::Rgb10A2,
1337 Sf::Rg11b10Ufloat => Self::R11fG11fB10f,
1338 Sf::R64Uint => Self::R64ui,
1339 Sf::Rg32Uint => Self::Rg32ui,
1340 Sf::Rg32Sint => Self::Rg32i,
1341 Sf::Rg32Float => Self::Rg32f,
1342 Sf::Rgba16Uint => Self::Rgba16ui,
1343 Sf::Rgba16Sint => Self::Rgba16i,
1344 Sf::Rgba16Float => Self::Rgba16f,
1345 Sf::Rgba32Uint => Self::Rgba32ui,
1346 Sf::Rgba32Sint => Self::Rgba32i,
1347 Sf::Rgba32Float => Self::Rgba32f,
1348 Sf::R16Unorm => Self::R16,
1349 Sf::R16Snorm => Self::R16Snorm,
1350 Sf::Rg16Unorm => Self::Rg16,
1351 Sf::Rg16Snorm => Self::Rg16Snorm,
1352 Sf::Rgba16Unorm => Self::Rgba16,
1353 Sf::Rgba16Snorm => Self::Rgba16Snorm,
1354 }
1355 }
1356}
1357
1358impl From<crate::ImageDimension> for spirv::Dim {
1359 fn from(dim: crate::ImageDimension) -> Self {
1360 use crate::ImageDimension as Id;
1361 match dim {
1362 Id::D1 => Self::Dim1D,
1363 Id::D2 => Self::Dim2D,
1364 Id::D3 => Self::Dim3D,
1365 Id::Cube => Self::DimCube,
1366 }
1367 }
1368}
1369
1370impl From<crate::CooperativeRole> for spirv::CooperativeMatrixUse {
1371 fn from(role: crate::CooperativeRole) -> Self {
1372 match role {
1373 crate::CooperativeRole::A => Self::MatrixAKHR,
1374 crate::CooperativeRole::B => Self::MatrixBKHR,
1375 crate::CooperativeRole::C => Self::MatrixAccumulatorKHR,
1376 }
1377 }
1378}