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