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