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 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 pub(super) fn unary(op: Op, result_type_id: Word, id: Word, value: Word) -> Self {
872 let mut instruction = Self::new(op);
873 instruction.set_type(result_type_id);
874 instruction.set_result(id);
875 instruction.add_operand(value);
876 instruction
877 }
878
879 pub(super) fn composite_construct(
884 result_type_id: Word,
885 id: Word,
886 constituent_ids: &[Word],
887 ) -> Self {
888 let mut instruction = Self::new(Op::CompositeConstruct);
889 instruction.set_type(result_type_id);
890 instruction.set_result(id);
891
892 for constituent_id in constituent_ids {
893 instruction.add_operand(*constituent_id);
894 }
895
896 instruction
897 }
898
899 pub(super) fn composite_extract(
900 result_type_id: Word,
901 id: Word,
902 composite_id: Word,
903 indices: &[Word],
904 ) -> Self {
905 let mut instruction = Self::new(Op::CompositeExtract);
906 instruction.set_type(result_type_id);
907 instruction.set_result(id);
908
909 instruction.add_operand(composite_id);
910 for index in indices {
911 instruction.add_operand(*index);
912 }
913
914 instruction
915 }
916
917 pub(super) fn vector_extract_dynamic(
918 result_type_id: Word,
919 id: Word,
920 vector_id: Word,
921 index_id: Word,
922 ) -> Self {
923 let mut instruction = Self::new(Op::VectorExtractDynamic);
924 instruction.set_type(result_type_id);
925 instruction.set_result(id);
926
927 instruction.add_operand(vector_id);
928 instruction.add_operand(index_id);
929
930 instruction
931 }
932
933 pub(super) fn vector_shuffle(
934 result_type_id: Word,
935 id: Word,
936 v1_id: Word,
937 v2_id: Word,
938 components: &[Word],
939 ) -> Self {
940 let mut instruction = Self::new(Op::VectorShuffle);
941 instruction.set_type(result_type_id);
942 instruction.set_result(id);
943 instruction.add_operand(v1_id);
944 instruction.add_operand(v2_id);
945
946 for &component in components {
947 instruction.add_operand(component);
948 }
949
950 instruction
951 }
952
953 pub(super) fn binary(
957 op: Op,
958 result_type_id: Word,
959 id: Word,
960 operand_1: Word,
961 operand_2: Word,
962 ) -> Self {
963 let mut instruction = Self::new(op);
964 instruction.set_type(result_type_id);
965 instruction.set_result(id);
966 instruction.add_operand(operand_1);
967 instruction.add_operand(operand_2);
968 instruction
969 }
970
971 pub(super) fn ternary(
972 op: Op,
973 result_type_id: Word,
974 id: Word,
975 operand_1: Word,
976 operand_2: Word,
977 operand_3: Word,
978 ) -> Self {
979 let mut instruction = Self::new(op);
980 instruction.set_type(result_type_id);
981 instruction.set_result(id);
982 instruction.add_operand(operand_1);
983 instruction.add_operand(operand_2);
984 instruction.add_operand(operand_3);
985 instruction
986 }
987
988 pub(super) fn quaternary(
989 op: Op,
990 result_type_id: Word,
991 id: Word,
992 operand_1: Word,
993 operand_2: Word,
994 operand_3: Word,
995 operand_4: Word,
996 ) -> Self {
997 let mut instruction = Self::new(op);
998 instruction.set_type(result_type_id);
999 instruction.set_result(id);
1000 instruction.add_operand(operand_1);
1001 instruction.add_operand(operand_2);
1002 instruction.add_operand(operand_3);
1003 instruction.add_operand(operand_4);
1004 instruction
1005 }
1006
1007 pub(super) fn relational(op: Op, result_type_id: Word, id: Word, expr_id: Word) -> Self {
1008 let mut instruction = Self::new(op);
1009 instruction.set_type(result_type_id);
1010 instruction.set_result(id);
1011 instruction.add_operand(expr_id);
1012 instruction
1013 }
1014
1015 pub(super) fn atomic_binary(
1016 op: Op,
1017 result_type_id: Word,
1018 id: Word,
1019 pointer: Word,
1020 scope_id: Word,
1021 semantics_id: Word,
1022 value: Word,
1023 ) -> Self {
1024 let mut instruction = Self::new(op);
1025 instruction.set_type(result_type_id);
1026 instruction.set_result(id);
1027 instruction.add_operand(pointer);
1028 instruction.add_operand(scope_id);
1029 instruction.add_operand(semantics_id);
1030 instruction.add_operand(value);
1031 instruction
1032 }
1033
1034 pub(super) fn derivative(op: Op, result_type_id: Word, id: Word, expr_id: Word) -> Self {
1047 let mut instruction = Self::new(op);
1048 instruction.set_type(result_type_id);
1049 instruction.set_result(id);
1050 instruction.add_operand(expr_id);
1051 instruction
1052 }
1053
1054 pub(super) fn phi(
1059 result_type_id: Word,
1060 result_id: Word,
1061 var_parent_pairs: &[(Word, Word)],
1062 ) -> Self {
1063 let mut instruction = Self::new(Op::Phi);
1064 instruction.add_operand(result_type_id);
1065 instruction.add_operand(result_id);
1066 for &(variable, parent) in var_parent_pairs {
1067 instruction.add_operand(variable);
1068 instruction.add_operand(parent);
1069 }
1070 instruction
1071 }
1072
1073 pub(super) fn selection_merge(
1074 merge_id: Word,
1075 selection_control: spirv::SelectionControl,
1076 ) -> Self {
1077 let mut instruction = Self::new(Op::SelectionMerge);
1078 instruction.add_operand(merge_id);
1079 instruction.add_operand(selection_control.bits());
1080 instruction
1081 }
1082
1083 pub(super) fn loop_merge(
1084 merge_id: Word,
1085 continuing_id: Word,
1086 selection_control: spirv::SelectionControl,
1087 ) -> Self {
1088 let mut instruction = Self::new(Op::LoopMerge);
1089 instruction.add_operand(merge_id);
1090 instruction.add_operand(continuing_id);
1091 instruction.add_operand(selection_control.bits());
1092 instruction
1093 }
1094
1095 pub(super) fn label(id: Word) -> Self {
1096 let mut instruction = Self::new(Op::Label);
1097 instruction.set_result(id);
1098 instruction
1099 }
1100
1101 pub(super) fn branch(id: Word) -> Self {
1102 let mut instruction = Self::new(Op::Branch);
1103 instruction.add_operand(id);
1104 instruction
1105 }
1106
1107 pub(super) fn branch_conditional(
1109 condition_id: Word,
1110 true_label: Word,
1111 false_label: Word,
1112 ) -> Self {
1113 let mut instruction = Self::new(Op::BranchConditional);
1114 instruction.add_operand(condition_id);
1115 instruction.add_operand(true_label);
1116 instruction.add_operand(false_label);
1117 instruction
1118 }
1119
1120 pub(super) fn switch(selector_id: Word, default_id: Word, cases: &[Case]) -> Self {
1121 let mut instruction = Self::new(Op::Switch);
1122 instruction.add_operand(selector_id);
1123 instruction.add_operand(default_id);
1124 for case in cases {
1125 instruction.add_operand(case.value);
1126 instruction.add_operand(case.label_id);
1127 }
1128 instruction
1129 }
1130
1131 pub(super) fn select(
1132 result_type_id: Word,
1133 id: Word,
1134 condition_id: Word,
1135 accept_id: Word,
1136 reject_id: Word,
1137 ) -> Self {
1138 let mut instruction = Self::new(Op::Select);
1139 instruction.add_operand(result_type_id);
1140 instruction.add_operand(id);
1141 instruction.add_operand(condition_id);
1142 instruction.add_operand(accept_id);
1143 instruction.add_operand(reject_id);
1144 instruction
1145 }
1146
1147 pub(super) const fn kill() -> Self {
1148 Self::new(Op::Kill)
1149 }
1150
1151 pub(super) const fn return_void() -> Self {
1152 Self::new(Op::Return)
1153 }
1154
1155 pub(super) fn return_value(value_id: Word) -> Self {
1156 let mut instruction = Self::new(Op::ReturnValue);
1157 instruction.add_operand(value_id);
1158 instruction
1159 }
1160
1161 pub(super) fn control_barrier(
1172 exec_scope_id: Word,
1173 mem_scope_id: Word,
1174 semantics_id: Word,
1175 ) -> Self {
1176 let mut instruction = Self::new(Op::ControlBarrier);
1177 instruction.add_operand(exec_scope_id);
1178 instruction.add_operand(mem_scope_id);
1179 instruction.add_operand(semantics_id);
1180 instruction
1181 }
1182 pub(super) fn memory_barrier(mem_scope_id: Word, semantics_id: Word) -> Self {
1183 let mut instruction = Self::new(Op::MemoryBarrier);
1184 instruction.add_operand(mem_scope_id);
1185 instruction.add_operand(semantics_id);
1186 instruction
1187 }
1188
1189 pub(super) fn group_non_uniform_ballot(
1192 result_type_id: Word,
1193 id: Word,
1194 exec_scope_id: Word,
1195 predicate: Word,
1196 ) -> Self {
1197 let mut instruction = Self::new(Op::GroupNonUniformBallot);
1198 instruction.set_type(result_type_id);
1199 instruction.set_result(id);
1200 instruction.add_operand(exec_scope_id);
1201 instruction.add_operand(predicate);
1202
1203 instruction
1204 }
1205 pub(super) fn group_non_uniform_broadcast_first(
1206 result_type_id: Word,
1207 id: Word,
1208 exec_scope_id: Word,
1209 value: Word,
1210 ) -> Self {
1211 let mut instruction = Self::new(Op::GroupNonUniformBroadcastFirst);
1212 instruction.set_type(result_type_id);
1213 instruction.set_result(id);
1214 instruction.add_operand(exec_scope_id);
1215 instruction.add_operand(value);
1216
1217 instruction
1218 }
1219 pub(super) fn group_non_uniform_gather(
1220 op: Op,
1221 result_type_id: Word,
1222 id: Word,
1223 exec_scope_id: Word,
1224 value: Word,
1225 index: Word,
1226 ) -> Self {
1227 let mut instruction = Self::new(op);
1228 instruction.set_type(result_type_id);
1229 instruction.set_result(id);
1230 instruction.add_operand(exec_scope_id);
1231 instruction.add_operand(value);
1232 instruction.add_operand(index);
1233
1234 instruction
1235 }
1236 pub(super) fn group_non_uniform_arithmetic(
1237 op: Op,
1238 result_type_id: Word,
1239 id: Word,
1240 exec_scope_id: Word,
1241 group_op: Option<spirv::GroupOperation>,
1242 value: Word,
1243 ) -> Self {
1244 let mut instruction = Self::new(op);
1245 instruction.set_type(result_type_id);
1246 instruction.set_result(id);
1247 instruction.add_operand(exec_scope_id);
1248 if let Some(group_op) = group_op {
1249 instruction.add_operand(group_op as u32);
1250 }
1251 instruction.add_operand(value);
1252
1253 instruction
1254 }
1255 pub(super) fn group_non_uniform_quad_swap(
1256 result_type_id: Word,
1257 id: Word,
1258 exec_scope_id: Word,
1259 value: Word,
1260 direction: Word,
1261 ) -> Self {
1262 let mut instruction = Self::new(Op::GroupNonUniformQuadSwap);
1263 instruction.set_type(result_type_id);
1264 instruction.set_result(id);
1265 instruction.add_operand(exec_scope_id);
1266 instruction.add_operand(value);
1267 instruction.add_operand(direction);
1268
1269 instruction
1270 }
1271
1272 pub(super) fn coop_load(
1274 result_type_id: Word,
1275 id: Word,
1276 pointer_id: Word,
1277 layout_id: Word,
1278 stride_id: Word,
1279 ) -> Self {
1280 let mut instruction = Self::new(Op::CooperativeMatrixLoadKHR);
1281 instruction.set_type(result_type_id);
1282 instruction.set_result(id);
1283 instruction.add_operand(pointer_id);
1284 instruction.add_operand(layout_id);
1285 instruction.add_operand(stride_id);
1286 instruction
1287 }
1288 pub(super) fn coop_store(id: Word, pointer_id: Word, layout_id: Word, stride_id: Word) -> Self {
1289 let mut instruction = Self::new(Op::CooperativeMatrixStoreKHR);
1290 instruction.add_operand(pointer_id);
1291 instruction.add_operand(id);
1292 instruction.add_operand(layout_id);
1293 instruction.add_operand(stride_id);
1294 instruction
1295 }
1296 pub(super) fn coop_mul_add(result_type_id: Word, id: Word, a: Word, b: Word, c: Word) -> Self {
1297 let mut instruction = Self::new(Op::CooperativeMatrixMulAddKHR);
1298 instruction.set_type(result_type_id);
1299 instruction.set_result(id);
1300 instruction.add_operand(a);
1301 instruction.add_operand(b);
1302 instruction.add_operand(c);
1303
1304 instruction
1305 }
1306}
1307
1308impl From<crate::StorageFormat> for spirv::ImageFormat {
1309 fn from(format: crate::StorageFormat) -> Self {
1310 use crate::StorageFormat as Sf;
1311 match format {
1312 Sf::R8Unorm => Self::R8,
1313 Sf::R8Snorm => Self::R8Snorm,
1314 Sf::R8Uint => Self::R8ui,
1315 Sf::R8Sint => Self::R8i,
1316 Sf::R16Uint => Self::R16ui,
1317 Sf::R16Sint => Self::R16i,
1318 Sf::R16Float => Self::R16f,
1319 Sf::Rg8Unorm => Self::Rg8,
1320 Sf::Rg8Snorm => Self::Rg8Snorm,
1321 Sf::Rg8Uint => Self::Rg8ui,
1322 Sf::Rg8Sint => Self::Rg8i,
1323 Sf::R32Uint => Self::R32ui,
1324 Sf::R32Sint => Self::R32i,
1325 Sf::R32Float => Self::R32f,
1326 Sf::Rg16Uint => Self::Rg16ui,
1327 Sf::Rg16Sint => Self::Rg16i,
1328 Sf::Rg16Float => Self::Rg16f,
1329 Sf::Rgba8Unorm => Self::Rgba8,
1330 Sf::Rgba8Snorm => Self::Rgba8Snorm,
1331 Sf::Rgba8Uint => Self::Rgba8ui,
1332 Sf::Rgba8Sint => Self::Rgba8i,
1333 Sf::Bgra8Unorm => Self::Unknown,
1334 Sf::Rgb10a2Uint => Self::Rgb10a2ui,
1335 Sf::Rgb10a2Unorm => Self::Rgb10A2,
1336 Sf::Rg11b10Ufloat => Self::R11fG11fB10f,
1337 Sf::R64Uint => Self::R64ui,
1338 Sf::Rg32Uint => Self::Rg32ui,
1339 Sf::Rg32Sint => Self::Rg32i,
1340 Sf::Rg32Float => Self::Rg32f,
1341 Sf::Rgba16Uint => Self::Rgba16ui,
1342 Sf::Rgba16Sint => Self::Rgba16i,
1343 Sf::Rgba16Float => Self::Rgba16f,
1344 Sf::Rgba32Uint => Self::Rgba32ui,
1345 Sf::Rgba32Sint => Self::Rgba32i,
1346 Sf::Rgba32Float => Self::Rgba32f,
1347 Sf::R16Unorm => Self::R16,
1348 Sf::R16Snorm => Self::R16Snorm,
1349 Sf::Rg16Unorm => Self::Rg16,
1350 Sf::Rg16Snorm => Self::Rg16Snorm,
1351 Sf::Rgba16Unorm => Self::Rgba16,
1352 Sf::Rgba16Snorm => Self::Rgba16Snorm,
1353 }
1354 }
1355}
1356
1357impl From<crate::ImageDimension> for spirv::Dim {
1358 fn from(dim: crate::ImageDimension) -> Self {
1359 use crate::ImageDimension as Id;
1360 match dim {
1361 Id::D1 => Self::Dim1D,
1362 Id::D2 => Self::Dim2D,
1363 Id::D3 => Self::Dim3D,
1364 Id::Cube => Self::DimCube,
1365 }
1366 }
1367}
1368
1369impl From<crate::CooperativeRole> for spirv::CooperativeMatrixUse {
1370 fn from(role: crate::CooperativeRole) -> Self {
1371 match role {
1372 crate::CooperativeRole::A => Self::MatrixAKHR,
1373 crate::CooperativeRole::B => Self::MatrixBKHR,
1374 crate::CooperativeRole::C => Self::MatrixAccumulatorKHR,
1375 }
1376 }
1377}