1 use super::helpers;
2 use spirv::{Op, Word};
3 
4 pub(super) enum Signedness {
5     Unsigned = 0,
6     Signed = 1,
7 }
8 
9 pub(super) enum SampleLod {
10     Explicit,
11     Implicit,
12 }
13 
14 pub(super) struct Case {
15     pub value: Word,
16     pub label_id: Word,
17 }
18 
19 impl super::Instruction {
20     //
21     //  Debug Instructions
22     //
23 
source(source_language: spirv::SourceLanguage, version: u32) -> Self24     pub(super) fn source(source_language: spirv::SourceLanguage, version: u32) -> Self {
25         let mut instruction = Self::new(Op::Source);
26         instruction.add_operand(source_language as u32);
27         instruction.add_operands(helpers::bytes_to_words(&version.to_le_bytes()));
28         instruction
29     }
30 
name(target_id: Word, name: &str) -> Self31     pub(super) fn name(target_id: Word, name: &str) -> Self {
32         let mut instruction = Self::new(Op::Name);
33         instruction.add_operand(target_id);
34         instruction.add_operands(helpers::string_to_words(name));
35         instruction
36     }
37 
member_name(target_id: Word, member: Word, name: &str) -> Self38     pub(super) fn member_name(target_id: Word, member: Word, name: &str) -> Self {
39         let mut instruction = Self::new(Op::MemberName);
40         instruction.add_operand(target_id);
41         instruction.add_operand(member);
42         instruction.add_operands(helpers::string_to_words(name));
43         instruction
44     }
45 
46     //
47     //  Annotation Instructions
48     //
49 
decorate( target_id: Word, decoration: spirv::Decoration, operands: &[Word], ) -> Self50     pub(super) fn decorate(
51         target_id: Word,
52         decoration: spirv::Decoration,
53         operands: &[Word],
54     ) -> Self {
55         let mut instruction = Self::new(Op::Decorate);
56         instruction.add_operand(target_id);
57         instruction.add_operand(decoration as u32);
58         for operand in operands {
59             instruction.add_operand(*operand)
60         }
61         instruction
62     }
63 
member_decorate( target_id: Word, member_index: Word, decoration: spirv::Decoration, operands: &[Word], ) -> Self64     pub(super) fn member_decorate(
65         target_id: Word,
66         member_index: Word,
67         decoration: spirv::Decoration,
68         operands: &[Word],
69     ) -> Self {
70         let mut instruction = Self::new(Op::MemberDecorate);
71         instruction.add_operand(target_id);
72         instruction.add_operand(member_index);
73         instruction.add_operand(decoration as u32);
74         for operand in operands {
75             instruction.add_operand(*operand)
76         }
77         instruction
78     }
79 
80     //
81     //  Extension Instructions
82     //
83 
extension(name: &str) -> Self84     pub(super) fn extension(name: &str) -> Self {
85         let mut instruction = Self::new(Op::Extension);
86         instruction.add_operands(helpers::string_to_words(name));
87         instruction
88     }
89 
ext_inst_import(id: Word, name: &str) -> Self90     pub(super) fn ext_inst_import(id: Word, name: &str) -> Self {
91         let mut instruction = Self::new(Op::ExtInstImport);
92         instruction.set_result(id);
93         instruction.add_operands(helpers::string_to_words(name));
94         instruction
95     }
96 
ext_inst( set_id: Word, op: spirv::GLOp, result_type_id: Word, id: Word, operands: &[Word], ) -> Self97     pub(super) fn ext_inst(
98         set_id: Word,
99         op: spirv::GLOp,
100         result_type_id: Word,
101         id: Word,
102         operands: &[Word],
103     ) -> Self {
104         let mut instruction = Self::new(Op::ExtInst);
105         instruction.set_type(result_type_id);
106         instruction.set_result(id);
107         instruction.add_operand(set_id);
108         instruction.add_operand(op as u32);
109         for operand in operands {
110             instruction.add_operand(*operand)
111         }
112         instruction
113     }
114 
115     //
116     //  Mode-Setting Instructions
117     //
118 
memory_model( addressing_model: spirv::AddressingModel, memory_model: spirv::MemoryModel, ) -> Self119     pub(super) fn memory_model(
120         addressing_model: spirv::AddressingModel,
121         memory_model: spirv::MemoryModel,
122     ) -> Self {
123         let mut instruction = Self::new(Op::MemoryModel);
124         instruction.add_operand(addressing_model as u32);
125         instruction.add_operand(memory_model as u32);
126         instruction
127     }
128 
entry_point( execution_model: spirv::ExecutionModel, entry_point_id: Word, name: &str, interface_ids: &[Word], ) -> Self129     pub(super) fn entry_point(
130         execution_model: spirv::ExecutionModel,
131         entry_point_id: Word,
132         name: &str,
133         interface_ids: &[Word],
134     ) -> Self {
135         let mut instruction = Self::new(Op::EntryPoint);
136         instruction.add_operand(execution_model as u32);
137         instruction.add_operand(entry_point_id);
138         instruction.add_operands(helpers::string_to_words(name));
139 
140         for interface_id in interface_ids {
141             instruction.add_operand(*interface_id);
142         }
143 
144         instruction
145     }
146 
execution_mode( entry_point_id: Word, execution_mode: spirv::ExecutionMode, args: &[Word], ) -> Self147     pub(super) fn execution_mode(
148         entry_point_id: Word,
149         execution_mode: spirv::ExecutionMode,
150         args: &[Word],
151     ) -> Self {
152         let mut instruction = Self::new(Op::ExecutionMode);
153         instruction.add_operand(entry_point_id);
154         instruction.add_operand(execution_mode as u32);
155         for arg in args {
156             instruction.add_operand(*arg);
157         }
158         instruction
159     }
160 
capability(capability: spirv::Capability) -> Self161     pub(super) fn capability(capability: spirv::Capability) -> Self {
162         let mut instruction = Self::new(Op::Capability);
163         instruction.add_operand(capability as u32);
164         instruction
165     }
166 
167     //
168     //  Type-Declaration Instructions
169     //
170 
type_void(id: Word) -> Self171     pub(super) fn type_void(id: Word) -> Self {
172         let mut instruction = Self::new(Op::TypeVoid);
173         instruction.set_result(id);
174         instruction
175     }
176 
type_bool(id: Word) -> Self177     pub(super) fn type_bool(id: Word) -> Self {
178         let mut instruction = Self::new(Op::TypeBool);
179         instruction.set_result(id);
180         instruction
181     }
182 
type_int(id: Word, width: Word, signedness: Signedness) -> Self183     pub(super) fn type_int(id: Word, width: Word, signedness: Signedness) -> Self {
184         let mut instruction = Self::new(Op::TypeInt);
185         instruction.set_result(id);
186         instruction.add_operand(width);
187         instruction.add_operand(signedness as u32);
188         instruction
189     }
190 
type_float(id: Word, width: Word) -> Self191     pub(super) fn type_float(id: Word, width: Word) -> Self {
192         let mut instruction = Self::new(Op::TypeFloat);
193         instruction.set_result(id);
194         instruction.add_operand(width);
195         instruction
196     }
197 
type_vector( id: Word, component_type_id: Word, component_count: crate::VectorSize, ) -> Self198     pub(super) fn type_vector(
199         id: Word,
200         component_type_id: Word,
201         component_count: crate::VectorSize,
202     ) -> Self {
203         let mut instruction = Self::new(Op::TypeVector);
204         instruction.set_result(id);
205         instruction.add_operand(component_type_id);
206         instruction.add_operand(component_count as u32);
207         instruction
208     }
209 
type_matrix( id: Word, column_type_id: Word, column_count: crate::VectorSize, ) -> Self210     pub(super) fn type_matrix(
211         id: Word,
212         column_type_id: Word,
213         column_count: crate::VectorSize,
214     ) -> Self {
215         let mut instruction = Self::new(Op::TypeMatrix);
216         instruction.set_result(id);
217         instruction.add_operand(column_type_id);
218         instruction.add_operand(column_count as u32);
219         instruction
220     }
221 
222     #[allow(clippy::too_many_arguments)]
type_image( id: Word, sampled_type_id: Word, dim: spirv::Dim, flags: super::ImageTypeFlags, image_format: spirv::ImageFormat, ) -> Self223     pub(super) fn type_image(
224         id: Word,
225         sampled_type_id: Word,
226         dim: spirv::Dim,
227         flags: super::ImageTypeFlags,
228         image_format: spirv::ImageFormat,
229     ) -> Self {
230         let mut instruction = Self::new(Op::TypeImage);
231         instruction.set_result(id);
232         instruction.add_operand(sampled_type_id);
233         instruction.add_operand(dim as u32);
234         instruction.add_operand(flags.contains(super::ImageTypeFlags::DEPTH) as u32);
235         instruction.add_operand(flags.contains(super::ImageTypeFlags::ARRAYED) as u32);
236         instruction.add_operand(flags.contains(super::ImageTypeFlags::MULTISAMPLED) as u32);
237         instruction.add_operand(if flags.contains(super::ImageTypeFlags::SAMPLED) {
238             1
239         } else {
240             2
241         });
242         instruction.add_operand(image_format as u32);
243         instruction
244     }
245 
type_sampler(id: Word) -> Self246     pub(super) fn type_sampler(id: Word) -> Self {
247         let mut instruction = Self::new(Op::TypeSampler);
248         instruction.set_result(id);
249         instruction
250     }
251 
type_sampled_image(id: Word, image_type_id: Word) -> Self252     pub(super) fn type_sampled_image(id: Word, image_type_id: Word) -> Self {
253         let mut instruction = Self::new(Op::TypeSampledImage);
254         instruction.set_result(id);
255         instruction.add_operand(image_type_id);
256         instruction
257     }
258 
type_array(id: Word, element_type_id: Word, length_id: Word) -> Self259     pub(super) fn type_array(id: Word, element_type_id: Word, length_id: Word) -> Self {
260         let mut instruction = Self::new(Op::TypeArray);
261         instruction.set_result(id);
262         instruction.add_operand(element_type_id);
263         instruction.add_operand(length_id);
264         instruction
265     }
266 
type_runtime_array(id: Word, element_type_id: Word) -> Self267     pub(super) fn type_runtime_array(id: Word, element_type_id: Word) -> Self {
268         let mut instruction = Self::new(Op::TypeRuntimeArray);
269         instruction.set_result(id);
270         instruction.add_operand(element_type_id);
271         instruction
272     }
273 
type_struct(id: Word, member_ids: &[Word]) -> Self274     pub(super) fn type_struct(id: Word, member_ids: &[Word]) -> Self {
275         let mut instruction = Self::new(Op::TypeStruct);
276         instruction.set_result(id);
277 
278         for member_id in member_ids {
279             instruction.add_operand(*member_id)
280         }
281 
282         instruction
283     }
284 
type_pointer( id: Word, storage_class: spirv::StorageClass, type_id: Word, ) -> Self285     pub(super) fn type_pointer(
286         id: Word,
287         storage_class: spirv::StorageClass,
288         type_id: Word,
289     ) -> Self {
290         let mut instruction = Self::new(Op::TypePointer);
291         instruction.set_result(id);
292         instruction.add_operand(storage_class as u32);
293         instruction.add_operand(type_id);
294         instruction
295     }
296 
type_function(id: Word, return_type_id: Word, parameter_ids: &[Word]) -> Self297     pub(super) fn type_function(id: Word, return_type_id: Word, parameter_ids: &[Word]) -> Self {
298         let mut instruction = Self::new(Op::TypeFunction);
299         instruction.set_result(id);
300         instruction.add_operand(return_type_id);
301 
302         for parameter_id in parameter_ids {
303             instruction.add_operand(*parameter_id);
304         }
305 
306         instruction
307     }
308 
309     //
310     //  Constant-Creation Instructions
311     //
312 
constant_null(result_type_id: Word, id: Word) -> Self313     pub(super) fn constant_null(result_type_id: Word, id: Word) -> Self {
314         let mut instruction = Self::new(Op::ConstantNull);
315         instruction.set_type(result_type_id);
316         instruction.set_result(id);
317         instruction
318     }
319 
constant_true(result_type_id: Word, id: Word) -> Self320     pub(super) fn constant_true(result_type_id: Word, id: Word) -> Self {
321         let mut instruction = Self::new(Op::ConstantTrue);
322         instruction.set_type(result_type_id);
323         instruction.set_result(id);
324         instruction
325     }
326 
constant_false(result_type_id: Word, id: Word) -> Self327     pub(super) fn constant_false(result_type_id: Word, id: Word) -> Self {
328         let mut instruction = Self::new(Op::ConstantFalse);
329         instruction.set_type(result_type_id);
330         instruction.set_result(id);
331         instruction
332     }
333 
constant(result_type_id: Word, id: Word, values: &[Word]) -> Self334     pub(super) fn constant(result_type_id: Word, id: Word, values: &[Word]) -> Self {
335         let mut instruction = Self::new(Op::Constant);
336         instruction.set_type(result_type_id);
337         instruction.set_result(id);
338 
339         for value in values {
340             instruction.add_operand(*value);
341         }
342 
343         instruction
344     }
345 
constant_composite( result_type_id: Word, id: Word, constituent_ids: &[Word], ) -> Self346     pub(super) fn constant_composite(
347         result_type_id: Word,
348         id: Word,
349         constituent_ids: &[Word],
350     ) -> Self {
351         let mut instruction = Self::new(Op::ConstantComposite);
352         instruction.set_type(result_type_id);
353         instruction.set_result(id);
354 
355         for constituent_id in constituent_ids {
356             instruction.add_operand(*constituent_id);
357         }
358 
359         instruction
360     }
361 
362     //
363     //  Memory Instructions
364     //
365 
variable( result_type_id: Word, id: Word, storage_class: spirv::StorageClass, initializer_id: Option<Word>, ) -> Self366     pub(super) fn variable(
367         result_type_id: Word,
368         id: Word,
369         storage_class: spirv::StorageClass,
370         initializer_id: Option<Word>,
371     ) -> Self {
372         let mut instruction = Self::new(Op::Variable);
373         instruction.set_type(result_type_id);
374         instruction.set_result(id);
375         instruction.add_operand(storage_class as u32);
376 
377         if let Some(initializer_id) = initializer_id {
378             instruction.add_operand(initializer_id);
379         }
380 
381         instruction
382     }
383 
load( result_type_id: Word, id: Word, pointer_id: Word, memory_access: Option<spirv::MemoryAccess>, ) -> Self384     pub(super) fn load(
385         result_type_id: Word,
386         id: Word,
387         pointer_id: Word,
388         memory_access: Option<spirv::MemoryAccess>,
389     ) -> Self {
390         let mut instruction = Self::new(Op::Load);
391         instruction.set_type(result_type_id);
392         instruction.set_result(id);
393         instruction.add_operand(pointer_id);
394 
395         if let Some(memory_access) = memory_access {
396             instruction.add_operand(memory_access.bits());
397         }
398 
399         instruction
400     }
401 
atomic_load( result_type_id: Word, id: Word, pointer_id: Word, scope_id: Word, semantics_id: Word, ) -> Self402     pub(super) fn atomic_load(
403         result_type_id: Word,
404         id: Word,
405         pointer_id: Word,
406         scope_id: Word,
407         semantics_id: Word,
408     ) -> Self {
409         let mut instruction = Self::new(Op::AtomicLoad);
410         instruction.set_type(result_type_id);
411         instruction.set_result(id);
412         instruction.add_operand(pointer_id);
413         instruction.add_operand(scope_id);
414         instruction.add_operand(semantics_id);
415         instruction
416     }
417 
store( pointer_id: Word, value_id: Word, memory_access: Option<spirv::MemoryAccess>, ) -> Self418     pub(super) fn store(
419         pointer_id: Word,
420         value_id: Word,
421         memory_access: Option<spirv::MemoryAccess>,
422     ) -> Self {
423         let mut instruction = Self::new(Op::Store);
424         instruction.add_operand(pointer_id);
425         instruction.add_operand(value_id);
426 
427         if let Some(memory_access) = memory_access {
428             instruction.add_operand(memory_access.bits());
429         }
430 
431         instruction
432     }
433 
atomic_store( pointer_id: Word, scope_id: Word, semantics_id: Word, value_id: Word, ) -> Self434     pub(super) fn atomic_store(
435         pointer_id: Word,
436         scope_id: Word,
437         semantics_id: Word,
438         value_id: Word,
439     ) -> Self {
440         let mut instruction = Self::new(Op::AtomicStore);
441         instruction.add_operand(pointer_id);
442         instruction.add_operand(scope_id);
443         instruction.add_operand(semantics_id);
444         instruction.add_operand(value_id);
445         instruction
446     }
447 
access_chain( result_type_id: Word, id: Word, base_id: Word, index_ids: &[Word], ) -> Self448     pub(super) fn access_chain(
449         result_type_id: Word,
450         id: Word,
451         base_id: Word,
452         index_ids: &[Word],
453     ) -> Self {
454         let mut instruction = Self::new(Op::AccessChain);
455         instruction.set_type(result_type_id);
456         instruction.set_result(id);
457         instruction.add_operand(base_id);
458 
459         for index_id in index_ids {
460             instruction.add_operand(*index_id);
461         }
462 
463         instruction
464     }
465 
array_length( result_type_id: Word, id: Word, structure_id: Word, array_member: Word, ) -> Self466     pub(super) fn array_length(
467         result_type_id: Word,
468         id: Word,
469         structure_id: Word,
470         array_member: Word,
471     ) -> Self {
472         let mut instruction = Self::new(Op::ArrayLength);
473         instruction.set_type(result_type_id);
474         instruction.set_result(id);
475         instruction.add_operand(structure_id);
476         instruction.add_operand(array_member);
477         instruction
478     }
479 
480     //
481     //  Function Instructions
482     //
483 
function( return_type_id: Word, id: Word, function_control: spirv::FunctionControl, function_type_id: Word, ) -> Self484     pub(super) fn function(
485         return_type_id: Word,
486         id: Word,
487         function_control: spirv::FunctionControl,
488         function_type_id: Word,
489     ) -> Self {
490         let mut instruction = Self::new(Op::Function);
491         instruction.set_type(return_type_id);
492         instruction.set_result(id);
493         instruction.add_operand(function_control.bits());
494         instruction.add_operand(function_type_id);
495         instruction
496     }
497 
function_parameter(result_type_id: Word, id: Word) -> Self498     pub(super) fn function_parameter(result_type_id: Word, id: Word) -> Self {
499         let mut instruction = Self::new(Op::FunctionParameter);
500         instruction.set_type(result_type_id);
501         instruction.set_result(id);
502         instruction
503     }
504 
function_end() -> Self505     pub(super) fn function_end() -> Self {
506         Self::new(Op::FunctionEnd)
507     }
508 
function_call( result_type_id: Word, id: Word, function_id: Word, argument_ids: &[Word], ) -> Self509     pub(super) fn function_call(
510         result_type_id: Word,
511         id: Word,
512         function_id: Word,
513         argument_ids: &[Word],
514     ) -> Self {
515         let mut instruction = Self::new(Op::FunctionCall);
516         instruction.set_type(result_type_id);
517         instruction.set_result(id);
518         instruction.add_operand(function_id);
519 
520         for argument_id in argument_ids {
521             instruction.add_operand(*argument_id);
522         }
523 
524         instruction
525     }
526 
527     //
528     //  Image Instructions
529     //
530 
sampled_image( result_type_id: Word, id: Word, image: Word, sampler: Word, ) -> Self531     pub(super) fn sampled_image(
532         result_type_id: Word,
533         id: Word,
534         image: Word,
535         sampler: Word,
536     ) -> Self {
537         let mut instruction = Self::new(Op::SampledImage);
538         instruction.set_type(result_type_id);
539         instruction.set_result(id);
540         instruction.add_operand(image);
541         instruction.add_operand(sampler);
542         instruction
543     }
544 
image_sample( result_type_id: Word, id: Word, lod: SampleLod, sampled_image: Word, coordinates: Word, depth_ref: Option<Word>, ) -> Self545     pub(super) fn image_sample(
546         result_type_id: Word,
547         id: Word,
548         lod: SampleLod,
549         sampled_image: Word,
550         coordinates: Word,
551         depth_ref: Option<Word>,
552     ) -> Self {
553         let op = match (lod, depth_ref) {
554             (SampleLod::Explicit, None) => Op::ImageSampleExplicitLod,
555             (SampleLod::Implicit, None) => Op::ImageSampleImplicitLod,
556             (SampleLod::Explicit, Some(_)) => Op::ImageSampleDrefExplicitLod,
557             (SampleLod::Implicit, Some(_)) => Op::ImageSampleDrefImplicitLod,
558         };
559 
560         let mut instruction = Self::new(op);
561         instruction.set_type(result_type_id);
562         instruction.set_result(id);
563         instruction.add_operand(sampled_image);
564         instruction.add_operand(coordinates);
565         if let Some(dref) = depth_ref {
566             instruction.add_operand(dref);
567         }
568 
569         instruction
570     }
571 
image_gather( result_type_id: Word, id: Word, sampled_image: Word, coordinates: Word, component_id: Word, depth_ref: Option<Word>, ) -> Self572     pub(super) fn image_gather(
573         result_type_id: Word,
574         id: Word,
575         sampled_image: Word,
576         coordinates: Word,
577         component_id: Word,
578         depth_ref: Option<Word>,
579     ) -> Self {
580         let op = match depth_ref {
581             None => Op::ImageGather,
582             Some(_) => Op::ImageDrefGather,
583         };
584 
585         let mut instruction = Self::new(op);
586         instruction.set_type(result_type_id);
587         instruction.set_result(id);
588         instruction.add_operand(sampled_image);
589         instruction.add_operand(coordinates);
590         if let Some(dref) = depth_ref {
591             instruction.add_operand(dref);
592         } else {
593             instruction.add_operand(component_id);
594         }
595 
596         instruction
597     }
598 
image_fetch_or_read( op: Op, result_type_id: Word, id: Word, image: Word, coordinates: Word, ) -> Self599     pub(super) fn image_fetch_or_read(
600         op: Op,
601         result_type_id: Word,
602         id: Word,
603         image: Word,
604         coordinates: Word,
605     ) -> Self {
606         let mut instruction = Self::new(op);
607         instruction.set_type(result_type_id);
608         instruction.set_result(id);
609         instruction.add_operand(image);
610         instruction.add_operand(coordinates);
611         instruction
612     }
613 
image_write(image: Word, coordinates: Word, value: Word) -> Self614     pub(super) fn image_write(image: Word, coordinates: Word, value: Word) -> Self {
615         let mut instruction = Self::new(Op::ImageWrite);
616         instruction.add_operand(image);
617         instruction.add_operand(coordinates);
618         instruction.add_operand(value);
619         instruction
620     }
621 
image_query(op: Op, result_type_id: Word, id: Word, image: Word) -> Self622     pub(super) fn image_query(op: Op, result_type_id: Word, id: Word, image: Word) -> Self {
623         let mut instruction = Self::new(op);
624         instruction.set_type(result_type_id);
625         instruction.set_result(id);
626         instruction.add_operand(image);
627         instruction
628     }
629 
630     //
631     //  Conversion Instructions
632     //
unary(op: Op, result_type_id: Word, id: Word, value: Word) -> Self633     pub(super) fn unary(op: Op, result_type_id: Word, id: Word, value: Word) -> Self {
634         let mut instruction = Self::new(op);
635         instruction.set_type(result_type_id);
636         instruction.set_result(id);
637         instruction.add_operand(value);
638         instruction
639     }
640 
641     //
642     //  Composite Instructions
643     //
644 
composite_construct( result_type_id: Word, id: Word, constituent_ids: &[Word], ) -> Self645     pub(super) fn composite_construct(
646         result_type_id: Word,
647         id: Word,
648         constituent_ids: &[Word],
649     ) -> Self {
650         let mut instruction = Self::new(Op::CompositeConstruct);
651         instruction.set_type(result_type_id);
652         instruction.set_result(id);
653 
654         for constituent_id in constituent_ids {
655             instruction.add_operand(*constituent_id);
656         }
657 
658         instruction
659     }
660 
composite_extract( result_type_id: Word, id: Word, composite_id: Word, indices: &[Word], ) -> Self661     pub(super) fn composite_extract(
662         result_type_id: Word,
663         id: Word,
664         composite_id: Word,
665         indices: &[Word],
666     ) -> Self {
667         let mut instruction = Self::new(Op::CompositeExtract);
668         instruction.set_type(result_type_id);
669         instruction.set_result(id);
670 
671         instruction.add_operand(composite_id);
672         for index in indices {
673             instruction.add_operand(*index);
674         }
675 
676         instruction
677     }
678 
vector_extract_dynamic( result_type_id: Word, id: Word, vector_id: Word, index_id: Word, ) -> Self679     pub(super) fn vector_extract_dynamic(
680         result_type_id: Word,
681         id: Word,
682         vector_id: Word,
683         index_id: Word,
684     ) -> Self {
685         let mut instruction = Self::new(Op::VectorExtractDynamic);
686         instruction.set_type(result_type_id);
687         instruction.set_result(id);
688 
689         instruction.add_operand(vector_id);
690         instruction.add_operand(index_id);
691 
692         instruction
693     }
694 
vector_shuffle( result_type_id: Word, id: Word, v1_id: Word, v2_id: Word, components: &[Word], ) -> Self695     pub(super) fn vector_shuffle(
696         result_type_id: Word,
697         id: Word,
698         v1_id: Word,
699         v2_id: Word,
700         components: &[Word],
701     ) -> Self {
702         let mut instruction = Self::new(Op::VectorShuffle);
703         instruction.set_type(result_type_id);
704         instruction.set_result(id);
705         instruction.add_operand(v1_id);
706         instruction.add_operand(v2_id);
707 
708         for &component in components {
709             instruction.add_operand(component);
710         }
711 
712         instruction
713     }
714 
715     //
716     // Arithmetic Instructions
717     //
binary( op: Op, result_type_id: Word, id: Word, operand_1: Word, operand_2: Word, ) -> Self718     pub(super) fn binary(
719         op: Op,
720         result_type_id: Word,
721         id: Word,
722         operand_1: Word,
723         operand_2: Word,
724     ) -> Self {
725         let mut instruction = Self::new(op);
726         instruction.set_type(result_type_id);
727         instruction.set_result(id);
728         instruction.add_operand(operand_1);
729         instruction.add_operand(operand_2);
730         instruction
731     }
732 
ternary( op: Op, result_type_id: Word, id: Word, operand_1: Word, operand_2: Word, operand_3: Word, ) -> Self733     pub(super) fn ternary(
734         op: Op,
735         result_type_id: Word,
736         id: Word,
737         operand_1: Word,
738         operand_2: Word,
739         operand_3: Word,
740     ) -> Self {
741         let mut instruction = Self::new(op);
742         instruction.set_type(result_type_id);
743         instruction.set_result(id);
744         instruction.add_operand(operand_1);
745         instruction.add_operand(operand_2);
746         instruction.add_operand(operand_3);
747         instruction
748     }
749 
quaternary( op: Op, result_type_id: Word, id: Word, operand_1: Word, operand_2: Word, operand_3: Word, operand_4: Word, ) -> Self750     pub(super) fn quaternary(
751         op: Op,
752         result_type_id: Word,
753         id: Word,
754         operand_1: Word,
755         operand_2: Word,
756         operand_3: Word,
757         operand_4: Word,
758     ) -> Self {
759         let mut instruction = Self::new(op);
760         instruction.set_type(result_type_id);
761         instruction.set_result(id);
762         instruction.add_operand(operand_1);
763         instruction.add_operand(operand_2);
764         instruction.add_operand(operand_3);
765         instruction.add_operand(operand_4);
766         instruction
767     }
768 
relational(op: Op, result_type_id: Word, id: Word, expr_id: Word) -> Self769     pub(super) fn relational(op: Op, result_type_id: Word, id: Word, expr_id: Word) -> Self {
770         let mut instruction = Self::new(op);
771         instruction.set_type(result_type_id);
772         instruction.set_result(id);
773         instruction.add_operand(expr_id);
774         instruction
775     }
776 
atomic_binary( op: Op, result_type_id: Word, id: Word, pointer: Word, scope_id: Word, semantics_id: Word, value: Word, ) -> Self777     pub(super) fn atomic_binary(
778         op: Op,
779         result_type_id: Word,
780         id: Word,
781         pointer: Word,
782         scope_id: Word,
783         semantics_id: Word,
784         value: Word,
785     ) -> Self {
786         let mut instruction = Self::new(op);
787         instruction.set_type(result_type_id);
788         instruction.set_result(id);
789         instruction.add_operand(pointer);
790         instruction.add_operand(scope_id);
791         instruction.add_operand(semantics_id);
792         instruction.add_operand(value);
793         instruction
794     }
795 
796     //
797     // Bit Instructions
798     //
799 
800     //
801     // Relational and Logical Instructions
802     //
803 
804     //
805     // Derivative Instructions
806     //
807 
derivative(op: Op, result_type_id: Word, id: Word, expr_id: Word) -> Self808     pub(super) fn derivative(op: Op, result_type_id: Word, id: Word, expr_id: Word) -> Self {
809         let mut instruction = Self::new(op);
810         instruction.set_type(result_type_id);
811         instruction.set_result(id);
812         instruction.add_operand(expr_id);
813         instruction
814     }
815 
816     //
817     // Control-Flow Instructions
818     //
819 
phi( result_type_id: Word, result_id: Word, var_parent_pairs: &[(Word, Word)], ) -> Self820     pub(super) fn phi(
821         result_type_id: Word,
822         result_id: Word,
823         var_parent_pairs: &[(Word, Word)],
824     ) -> Self {
825         let mut instruction = Self::new(Op::Phi);
826         instruction.add_operand(result_type_id);
827         instruction.add_operand(result_id);
828         for &(variable, parent) in var_parent_pairs {
829             instruction.add_operand(variable);
830             instruction.add_operand(parent);
831         }
832         instruction
833     }
834 
selection_merge( merge_id: Word, selection_control: spirv::SelectionControl, ) -> Self835     pub(super) fn selection_merge(
836         merge_id: Word,
837         selection_control: spirv::SelectionControl,
838     ) -> Self {
839         let mut instruction = Self::new(Op::SelectionMerge);
840         instruction.add_operand(merge_id);
841         instruction.add_operand(selection_control.bits());
842         instruction
843     }
844 
loop_merge( merge_id: Word, continuing_id: Word, selection_control: spirv::SelectionControl, ) -> Self845     pub(super) fn loop_merge(
846         merge_id: Word,
847         continuing_id: Word,
848         selection_control: spirv::SelectionControl,
849     ) -> Self {
850         let mut instruction = Self::new(Op::LoopMerge);
851         instruction.add_operand(merge_id);
852         instruction.add_operand(continuing_id);
853         instruction.add_operand(selection_control.bits());
854         instruction
855     }
856 
label(id: Word) -> Self857     pub(super) fn label(id: Word) -> Self {
858         let mut instruction = Self::new(Op::Label);
859         instruction.set_result(id);
860         instruction
861     }
862 
branch(id: Word) -> Self863     pub(super) fn branch(id: Word) -> Self {
864         let mut instruction = Self::new(Op::Branch);
865         instruction.add_operand(id);
866         instruction
867     }
868 
869     // TODO Branch Weights not implemented.
branch_conditional( condition_id: Word, true_label: Word, false_label: Word, ) -> Self870     pub(super) fn branch_conditional(
871         condition_id: Word,
872         true_label: Word,
873         false_label: Word,
874     ) -> Self {
875         let mut instruction = Self::new(Op::BranchConditional);
876         instruction.add_operand(condition_id);
877         instruction.add_operand(true_label);
878         instruction.add_operand(false_label);
879         instruction
880     }
881 
switch(selector_id: Word, default_id: Word, cases: &[Case]) -> Self882     pub(super) fn switch(selector_id: Word, default_id: Word, cases: &[Case]) -> Self {
883         let mut instruction = Self::new(Op::Switch);
884         instruction.add_operand(selector_id);
885         instruction.add_operand(default_id);
886         for case in cases {
887             instruction.add_operand(case.value);
888             instruction.add_operand(case.label_id);
889         }
890         instruction
891     }
892 
select( result_type_id: Word, id: Word, condition_id: Word, accept_id: Word, reject_id: Word, ) -> Self893     pub(super) fn select(
894         result_type_id: Word,
895         id: Word,
896         condition_id: Word,
897         accept_id: Word,
898         reject_id: Word,
899     ) -> Self {
900         let mut instruction = Self::new(Op::Select);
901         instruction.add_operand(result_type_id);
902         instruction.add_operand(id);
903         instruction.add_operand(condition_id);
904         instruction.add_operand(accept_id);
905         instruction.add_operand(reject_id);
906         instruction
907     }
908 
kill() -> Self909     pub(super) fn kill() -> Self {
910         Self::new(Op::Kill)
911     }
912 
return_void() -> Self913     pub(super) fn return_void() -> Self {
914         Self::new(Op::Return)
915     }
916 
return_value(value_id: Word) -> Self917     pub(super) fn return_value(value_id: Word) -> Self {
918         let mut instruction = Self::new(Op::ReturnValue);
919         instruction.add_operand(value_id);
920         instruction
921     }
922 
923     //
924     //  Atomic Instructions
925     //
926 
927     //
928     //  Primitive Instructions
929     //
930 
931     // Barriers
932 
control_barrier( exec_scope_id: Word, mem_scope_id: Word, semantics_id: Word, ) -> Self933     pub(super) fn control_barrier(
934         exec_scope_id: Word,
935         mem_scope_id: Word,
936         semantics_id: Word,
937     ) -> Self {
938         let mut instruction = Self::new(Op::ControlBarrier);
939         instruction.add_operand(exec_scope_id);
940         instruction.add_operand(mem_scope_id);
941         instruction.add_operand(semantics_id);
942         instruction
943     }
944 }
945 
946 impl From<crate::StorageFormat> for spirv::ImageFormat {
from(format: crate::StorageFormat) -> Self947     fn from(format: crate::StorageFormat) -> Self {
948         use crate::StorageFormat as Sf;
949         match format {
950             Sf::R8Unorm => Self::R8,
951             Sf::R8Snorm => Self::R8Snorm,
952             Sf::R8Uint => Self::R8ui,
953             Sf::R8Sint => Self::R8i,
954             Sf::R16Uint => Self::R16ui,
955             Sf::R16Sint => Self::R16i,
956             Sf::R16Float => Self::R16f,
957             Sf::Rg8Unorm => Self::Rg8,
958             Sf::Rg8Snorm => Self::Rg8Snorm,
959             Sf::Rg8Uint => Self::Rg8ui,
960             Sf::Rg8Sint => Self::Rg8i,
961             Sf::R32Uint => Self::R32ui,
962             Sf::R32Sint => Self::R32i,
963             Sf::R32Float => Self::R32f,
964             Sf::Rg16Uint => Self::Rg16ui,
965             Sf::Rg16Sint => Self::Rg16i,
966             Sf::Rg16Float => Self::Rg16f,
967             Sf::Rgba8Unorm => Self::Rgba8,
968             Sf::Rgba8Snorm => Self::Rgba8Snorm,
969             Sf::Rgba8Uint => Self::Rgba8ui,
970             Sf::Rgba8Sint => Self::Rgba8i,
971             Sf::Rgb10a2Unorm => Self::Rgb10a2ui,
972             Sf::Rg11b10Float => Self::R11fG11fB10f,
973             Sf::Rg32Uint => Self::Rg32ui,
974             Sf::Rg32Sint => Self::Rg32i,
975             Sf::Rg32Float => Self::Rg32f,
976             Sf::Rgba16Uint => Self::Rgba16ui,
977             Sf::Rgba16Sint => Self::Rgba16i,
978             Sf::Rgba16Float => Self::Rgba16f,
979             Sf::Rgba32Uint => Self::Rgba32ui,
980             Sf::Rgba32Sint => Self::Rgba32i,
981             Sf::Rgba32Float => Self::Rgba32f,
982         }
983     }
984 }
985 
986 impl From<crate::ImageDimension> for spirv::Dim {
from(dim: crate::ImageDimension) -> Self987     fn from(dim: crate::ImageDimension) -> Self {
988         use crate::ImageDimension as Id;
989         match dim {
990             Id::D1 => Self::Dim1D,
991             Id::D2 => Self::Dim2D,
992             Id::D3 => Self::Dim3D,
993             Id::Cube => Self::DimCube,
994         }
995     }
996 }
997