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 
type_image( id: Word, sampled_type_id: Word, dim: spirv::Dim, arrayed: bool, image_class: crate::ImageClass, ) -> Self222     pub(super) fn type_image(
223         id: Word,
224         sampled_type_id: Word,
225         dim: spirv::Dim,
226         arrayed: bool,
227         image_class: crate::ImageClass,
228     ) -> Self {
229         let mut instruction = Self::new(Op::TypeImage);
230         instruction.set_result(id);
231         instruction.add_operand(sampled_type_id);
232         instruction.add_operand(dim as u32);
233 
234         let (depth, multi, sampled) = match image_class {
235             crate::ImageClass::Sampled { kind: _, multi } => (false, multi, true),
236             crate::ImageClass::Depth => (true, false, true),
237             crate::ImageClass::Storage(_) => (false, false, false),
238         };
239         instruction.add_operand(depth as u32);
240         instruction.add_operand(arrayed as u32);
241         instruction.add_operand(multi as u32);
242         instruction.add_operand(if sampled { 1 } else { 2 });
243 
244         let format = match image_class {
245             crate::ImageClass::Storage(format) => match format {
246                 crate::StorageFormat::R8Unorm => spirv::ImageFormat::R8,
247                 crate::StorageFormat::R8Snorm => spirv::ImageFormat::R8Snorm,
248                 crate::StorageFormat::R8Uint => spirv::ImageFormat::R8ui,
249                 crate::StorageFormat::R8Sint => spirv::ImageFormat::R8i,
250                 crate::StorageFormat::R16Uint => spirv::ImageFormat::R16ui,
251                 crate::StorageFormat::R16Sint => spirv::ImageFormat::R16i,
252                 crate::StorageFormat::R16Float => spirv::ImageFormat::R16f,
253                 crate::StorageFormat::Rg8Unorm => spirv::ImageFormat::Rg8,
254                 crate::StorageFormat::Rg8Snorm => spirv::ImageFormat::Rg8Snorm,
255                 crate::StorageFormat::Rg8Uint => spirv::ImageFormat::Rg8ui,
256                 crate::StorageFormat::Rg8Sint => spirv::ImageFormat::Rg8i,
257                 crate::StorageFormat::R32Uint => spirv::ImageFormat::R32ui,
258                 crate::StorageFormat::R32Sint => spirv::ImageFormat::R32i,
259                 crate::StorageFormat::R32Float => spirv::ImageFormat::R32f,
260                 crate::StorageFormat::Rg16Uint => spirv::ImageFormat::Rg16ui,
261                 crate::StorageFormat::Rg16Sint => spirv::ImageFormat::Rg16i,
262                 crate::StorageFormat::Rg16Float => spirv::ImageFormat::Rg16f,
263                 crate::StorageFormat::Rgba8Unorm => spirv::ImageFormat::Rgba8,
264                 crate::StorageFormat::Rgba8Snorm => spirv::ImageFormat::Rgba8Snorm,
265                 crate::StorageFormat::Rgba8Uint => spirv::ImageFormat::Rgba8ui,
266                 crate::StorageFormat::Rgba8Sint => spirv::ImageFormat::Rgba8i,
267                 crate::StorageFormat::Rgb10a2Unorm => spirv::ImageFormat::Rgb10a2ui,
268                 crate::StorageFormat::Rg11b10Float => spirv::ImageFormat::R11fG11fB10f,
269                 crate::StorageFormat::Rg32Uint => spirv::ImageFormat::Rg32ui,
270                 crate::StorageFormat::Rg32Sint => spirv::ImageFormat::Rg32i,
271                 crate::StorageFormat::Rg32Float => spirv::ImageFormat::Rg32f,
272                 crate::StorageFormat::Rgba16Uint => spirv::ImageFormat::Rgba16ui,
273                 crate::StorageFormat::Rgba16Sint => spirv::ImageFormat::Rgba16i,
274                 crate::StorageFormat::Rgba16Float => spirv::ImageFormat::Rgba16f,
275                 crate::StorageFormat::Rgba32Uint => spirv::ImageFormat::Rgba32ui,
276                 crate::StorageFormat::Rgba32Sint => spirv::ImageFormat::Rgba32i,
277                 crate::StorageFormat::Rgba32Float => spirv::ImageFormat::Rgba32f,
278             },
279             _ => spirv::ImageFormat::Unknown,
280         };
281 
282         instruction.add_operand(format as u32);
283         instruction
284     }
285 
type_sampler(id: Word) -> Self286     pub(super) fn type_sampler(id: Word) -> Self {
287         let mut instruction = Self::new(Op::TypeSampler);
288         instruction.set_result(id);
289         instruction
290     }
291 
type_sampled_image(id: Word, image_type_id: Word) -> Self292     pub(super) fn type_sampled_image(id: Word, image_type_id: Word) -> Self {
293         let mut instruction = Self::new(Op::TypeSampledImage);
294         instruction.set_result(id);
295         instruction.add_operand(image_type_id);
296         instruction
297     }
298 
type_array(id: Word, element_type_id: Word, length_id: Word) -> Self299     pub(super) fn type_array(id: Word, element_type_id: Word, length_id: Word) -> Self {
300         let mut instruction = Self::new(Op::TypeArray);
301         instruction.set_result(id);
302         instruction.add_operand(element_type_id);
303         instruction.add_operand(length_id);
304         instruction
305     }
306 
type_runtime_array(id: Word, element_type_id: Word) -> Self307     pub(super) fn type_runtime_array(id: Word, element_type_id: Word) -> Self {
308         let mut instruction = Self::new(Op::TypeRuntimeArray);
309         instruction.set_result(id);
310         instruction.add_operand(element_type_id);
311         instruction
312     }
313 
type_struct(id: Word, member_ids: &[Word]) -> Self314     pub(super) fn type_struct(id: Word, member_ids: &[Word]) -> Self {
315         let mut instruction = Self::new(Op::TypeStruct);
316         instruction.set_result(id);
317 
318         for member_id in member_ids {
319             instruction.add_operand(*member_id)
320         }
321 
322         instruction
323     }
324 
type_pointer( id: Word, storage_class: spirv::StorageClass, type_id: Word, ) -> Self325     pub(super) fn type_pointer(
326         id: Word,
327         storage_class: spirv::StorageClass,
328         type_id: Word,
329     ) -> Self {
330         let mut instruction = Self::new(Op::TypePointer);
331         instruction.set_result(id);
332         instruction.add_operand(storage_class as u32);
333         instruction.add_operand(type_id);
334         instruction
335     }
336 
type_function(id: Word, return_type_id: Word, parameter_ids: &[Word]) -> Self337     pub(super) fn type_function(id: Word, return_type_id: Word, parameter_ids: &[Word]) -> Self {
338         let mut instruction = Self::new(Op::TypeFunction);
339         instruction.set_result(id);
340         instruction.add_operand(return_type_id);
341 
342         for parameter_id in parameter_ids {
343             instruction.add_operand(*parameter_id);
344         }
345 
346         instruction
347     }
348 
349     //
350     //  Constant-Creation Instructions
351     //
352 
constant_null(result_type_id: Word, id: Word) -> Self353     pub(super) fn constant_null(result_type_id: Word, id: Word) -> Self {
354         let mut instruction = Self::new(Op::ConstantNull);
355         instruction.set_type(result_type_id);
356         instruction.set_result(id);
357         instruction
358     }
359 
constant_true(result_type_id: Word, id: Word) -> Self360     pub(super) fn constant_true(result_type_id: Word, id: Word) -> Self {
361         let mut instruction = Self::new(Op::ConstantTrue);
362         instruction.set_type(result_type_id);
363         instruction.set_result(id);
364         instruction
365     }
366 
constant_false(result_type_id: Word, id: Word) -> Self367     pub(super) fn constant_false(result_type_id: Word, id: Word) -> Self {
368         let mut instruction = Self::new(Op::ConstantFalse);
369         instruction.set_type(result_type_id);
370         instruction.set_result(id);
371         instruction
372     }
373 
constant(result_type_id: Word, id: Word, values: &[Word]) -> Self374     pub(super) fn constant(result_type_id: Word, id: Word, values: &[Word]) -> Self {
375         let mut instruction = Self::new(Op::Constant);
376         instruction.set_type(result_type_id);
377         instruction.set_result(id);
378 
379         for value in values {
380             instruction.add_operand(*value);
381         }
382 
383         instruction
384     }
385 
constant_composite( result_type_id: Word, id: Word, constituent_ids: &[Word], ) -> Self386     pub(super) fn constant_composite(
387         result_type_id: Word,
388         id: Word,
389         constituent_ids: &[Word],
390     ) -> Self {
391         let mut instruction = Self::new(Op::ConstantComposite);
392         instruction.set_type(result_type_id);
393         instruction.set_result(id);
394 
395         for constituent_id in constituent_ids {
396             instruction.add_operand(*constituent_id);
397         }
398 
399         instruction
400     }
401 
402     //
403     //  Memory Instructions
404     //
405 
variable( result_type_id: Word, id: Word, storage_class: spirv::StorageClass, initializer_id: Option<Word>, ) -> Self406     pub(super) fn variable(
407         result_type_id: Word,
408         id: Word,
409         storage_class: spirv::StorageClass,
410         initializer_id: Option<Word>,
411     ) -> Self {
412         let mut instruction = Self::new(Op::Variable);
413         instruction.set_type(result_type_id);
414         instruction.set_result(id);
415         instruction.add_operand(storage_class as u32);
416 
417         if let Some(initializer_id) = initializer_id {
418             instruction.add_operand(initializer_id);
419         }
420 
421         instruction
422     }
423 
load( result_type_id: Word, id: Word, pointer_id: Word, memory_access: Option<spirv::MemoryAccess>, ) -> Self424     pub(super) fn load(
425         result_type_id: Word,
426         id: Word,
427         pointer_id: Word,
428         memory_access: Option<spirv::MemoryAccess>,
429     ) -> Self {
430         let mut instruction = Self::new(Op::Load);
431         instruction.set_type(result_type_id);
432         instruction.set_result(id);
433         instruction.add_operand(pointer_id);
434 
435         if let Some(memory_access) = memory_access {
436             instruction.add_operand(memory_access.bits());
437         }
438 
439         instruction
440     }
441 
store( pointer_id: Word, object_id: Word, memory_access: Option<spirv::MemoryAccess>, ) -> Self442     pub(super) fn store(
443         pointer_id: Word,
444         object_id: Word,
445         memory_access: Option<spirv::MemoryAccess>,
446     ) -> Self {
447         let mut instruction = Self::new(Op::Store);
448         instruction.add_operand(pointer_id);
449         instruction.add_operand(object_id);
450 
451         if let Some(memory_access) = memory_access {
452             instruction.add_operand(memory_access.bits());
453         }
454 
455         instruction
456     }
457 
access_chain( result_type_id: Word, id: Word, base_id: Word, index_ids: &[Word], ) -> Self458     pub(super) fn access_chain(
459         result_type_id: Word,
460         id: Word,
461         base_id: Word,
462         index_ids: &[Word],
463     ) -> Self {
464         let mut instruction = Self::new(Op::AccessChain);
465         instruction.set_type(result_type_id);
466         instruction.set_result(id);
467         instruction.add_operand(base_id);
468 
469         for index_id in index_ids {
470             instruction.add_operand(*index_id);
471         }
472 
473         instruction
474     }
475 
array_length( result_type_id: Word, id: Word, structure_id: Word, array_member: Word, ) -> Self476     pub(super) fn array_length(
477         result_type_id: Word,
478         id: Word,
479         structure_id: Word,
480         array_member: Word,
481     ) -> Self {
482         let mut instruction = Self::new(Op::ArrayLength);
483         instruction.set_type(result_type_id);
484         instruction.set_result(id);
485         instruction.add_operand(structure_id);
486         instruction.add_operand(array_member);
487         instruction
488     }
489 
490     //
491     //  Function Instructions
492     //
493 
function( return_type_id: Word, id: Word, function_control: spirv::FunctionControl, function_type_id: Word, ) -> Self494     pub(super) fn function(
495         return_type_id: Word,
496         id: Word,
497         function_control: spirv::FunctionControl,
498         function_type_id: Word,
499     ) -> Self {
500         let mut instruction = Self::new(Op::Function);
501         instruction.set_type(return_type_id);
502         instruction.set_result(id);
503         instruction.add_operand(function_control.bits());
504         instruction.add_operand(function_type_id);
505         instruction
506     }
507 
function_parameter(result_type_id: Word, id: Word) -> Self508     pub(super) fn function_parameter(result_type_id: Word, id: Word) -> Self {
509         let mut instruction = Self::new(Op::FunctionParameter);
510         instruction.set_type(result_type_id);
511         instruction.set_result(id);
512         instruction
513     }
514 
function_end() -> Self515     pub(super) fn function_end() -> Self {
516         Self::new(Op::FunctionEnd)
517     }
518 
function_call( result_type_id: Word, id: Word, function_id: Word, argument_ids: &[Word], ) -> Self519     pub(super) fn function_call(
520         result_type_id: Word,
521         id: Word,
522         function_id: Word,
523         argument_ids: &[Word],
524     ) -> Self {
525         let mut instruction = Self::new(Op::FunctionCall);
526         instruction.set_type(result_type_id);
527         instruction.set_result(id);
528         instruction.add_operand(function_id);
529 
530         for argument_id in argument_ids {
531             instruction.add_operand(*argument_id);
532         }
533 
534         instruction
535     }
536 
537     //
538     //  Image Instructions
539     //
540 
sampled_image( result_type_id: Word, id: Word, image: Word, sampler: Word, ) -> Self541     pub(super) fn sampled_image(
542         result_type_id: Word,
543         id: Word,
544         image: Word,
545         sampler: Word,
546     ) -> Self {
547         let mut instruction = Self::new(Op::SampledImage);
548         instruction.set_type(result_type_id);
549         instruction.set_result(id);
550         instruction.add_operand(image);
551         instruction.add_operand(sampler);
552         instruction
553     }
554 
image_sample( result_type_id: Word, id: Word, lod: SampleLod, sampled_image: Word, coordinates: Word, depth_ref: Option<Word>, ) -> Self555     pub(super) fn image_sample(
556         result_type_id: Word,
557         id: Word,
558         lod: SampleLod,
559         sampled_image: Word,
560         coordinates: Word,
561         depth_ref: Option<Word>,
562     ) -> Self {
563         let op = match (lod, depth_ref) {
564             (SampleLod::Explicit, None) => Op::ImageSampleExplicitLod,
565             (SampleLod::Implicit, None) => Op::ImageSampleImplicitLod,
566             (SampleLod::Explicit, Some(_)) => Op::ImageSampleDrefExplicitLod,
567             (SampleLod::Implicit, Some(_)) => Op::ImageSampleDrefImplicitLod,
568         };
569 
570         let mut instruction = Self::new(op);
571         instruction.set_type(result_type_id);
572         instruction.set_result(id);
573         instruction.add_operand(sampled_image);
574         instruction.add_operand(coordinates);
575         if let Some(dref) = depth_ref {
576             instruction.add_operand(dref);
577         }
578 
579         instruction
580     }
581 
image_fetch( result_type_id: Word, id: Word, image: Word, coordinates: Word, ) -> Self582     pub(super) fn image_fetch(
583         result_type_id: Word,
584         id: Word,
585         image: Word,
586         coordinates: Word,
587     ) -> Self {
588         let mut instruction = Self::new(Op::ImageFetch);
589         instruction.set_type(result_type_id);
590         instruction.set_result(id);
591         instruction.add_operand(image);
592         instruction.add_operand(coordinates);
593         instruction
594     }
595 
image_read( result_type_id: Word, id: Word, image: Word, coordinates: Word, ) -> Self596     pub(super) fn image_read(
597         result_type_id: Word,
598         id: Word,
599         image: Word,
600         coordinates: Word,
601     ) -> Self {
602         let mut instruction = Self::new(Op::ImageRead);
603         instruction.set_type(result_type_id);
604         instruction.set_result(id);
605         instruction.add_operand(image);
606         instruction.add_operand(coordinates);
607         instruction
608     }
609 
image_write(image: Word, coordinates: Word, value: Word) -> Self610     pub(super) fn image_write(image: Word, coordinates: Word, value: Word) -> Self {
611         let mut instruction = Self::new(Op::ImageWrite);
612         instruction.add_operand(image);
613         instruction.add_operand(coordinates);
614         instruction.add_operand(value);
615         instruction
616     }
617 
image_query(op: Op, result_type_id: Word, id: Word, image: Word) -> Self618     pub(super) fn image_query(op: Op, result_type_id: Word, id: Word, image: Word) -> Self {
619         let mut instruction = Self::new(op);
620         instruction.set_type(result_type_id);
621         instruction.set_result(id);
622         instruction.add_operand(image);
623         instruction
624     }
625 
626     //
627     //  Conversion Instructions
628     //
unary(op: Op, result_type_id: Word, id: Word, value: Word) -> Self629     pub(super) fn unary(op: Op, result_type_id: Word, id: Word, value: Word) -> Self {
630         let mut instruction = Self::new(op);
631         instruction.set_type(result_type_id);
632         instruction.set_result(id);
633         instruction.add_operand(value);
634         instruction
635     }
636 
637     //
638     //  Composite Instructions
639     //
640 
composite_construct( result_type_id: Word, id: Word, constituent_ids: &[Word], ) -> Self641     pub(super) fn composite_construct(
642         result_type_id: Word,
643         id: Word,
644         constituent_ids: &[Word],
645     ) -> Self {
646         let mut instruction = Self::new(Op::CompositeConstruct);
647         instruction.set_type(result_type_id);
648         instruction.set_result(id);
649 
650         for constituent_id in constituent_ids {
651             instruction.add_operand(*constituent_id);
652         }
653 
654         instruction
655     }
656 
composite_extract( result_type_id: Word, id: Word, composite_id: Word, indices: &[Word], ) -> Self657     pub(super) fn composite_extract(
658         result_type_id: Word,
659         id: Word,
660         composite_id: Word,
661         indices: &[Word],
662     ) -> Self {
663         let mut instruction = Self::new(Op::CompositeExtract);
664         instruction.set_type(result_type_id);
665         instruction.set_result(id);
666 
667         instruction.add_operand(composite_id);
668         for index in indices {
669             instruction.add_operand(*index);
670         }
671 
672         instruction
673     }
674 
vector_extract_dynamic( result_type_id: Word, id: Word, vector_id: Word, index_id: Word, ) -> Self675     pub(super) fn vector_extract_dynamic(
676         result_type_id: Word,
677         id: Word,
678         vector_id: Word,
679         index_id: Word,
680     ) -> Self {
681         let mut instruction = Self::new(Op::VectorExtractDynamic);
682         instruction.set_type(result_type_id);
683         instruction.set_result(id);
684 
685         instruction.add_operand(vector_id);
686         instruction.add_operand(index_id);
687 
688         instruction
689     }
690 
vector_shuffle( result_type_id: Word, id: Word, v1_id: Word, v2_id: Word, components: &[Word], ) -> Self691     pub(super) fn vector_shuffle(
692         result_type_id: Word,
693         id: Word,
694         v1_id: Word,
695         v2_id: Word,
696         components: &[Word],
697     ) -> Self {
698         let mut instruction = Self::new(Op::VectorShuffle);
699         instruction.set_type(result_type_id);
700         instruction.set_result(id);
701         instruction.add_operand(v1_id);
702         instruction.add_operand(v2_id);
703 
704         for &component in components {
705             instruction.add_operand(component);
706         }
707 
708         instruction
709     }
710 
711     //
712     // Arithmetic Instructions
713     //
binary( op: Op, result_type_id: Word, id: Word, operand_1: Word, operand_2: Word, ) -> Self714     pub(super) fn binary(
715         op: Op,
716         result_type_id: Word,
717         id: Word,
718         operand_1: Word,
719         operand_2: Word,
720     ) -> Self {
721         let mut instruction = Self::new(op);
722         instruction.set_type(result_type_id);
723         instruction.set_result(id);
724         instruction.add_operand(operand_1);
725         instruction.add_operand(operand_2);
726         instruction
727     }
728 
relational(op: Op, result_type_id: Word, id: Word, expr_id: Word) -> Self729     pub(super) fn relational(op: Op, result_type_id: Word, id: Word, expr_id: Word) -> Self {
730         let mut instruction = Self::new(op);
731         instruction.set_type(result_type_id);
732         instruction.set_result(id);
733         instruction.add_operand(expr_id);
734         instruction
735     }
736 
737     //
738     // Bit Instructions
739     //
740 
741     //
742     // Relational and Logical Instructions
743     //
744 
745     //
746     // Derivative Instructions
747     //
748 
derivative(op: Op, result_type_id: Word, id: Word, expr_id: Word) -> Self749     pub(super) fn derivative(op: Op, result_type_id: Word, id: Word, expr_id: Word) -> Self {
750         let mut instruction = Self::new(op);
751         instruction.set_type(result_type_id);
752         instruction.set_result(id);
753         instruction.add_operand(expr_id);
754         instruction
755     }
756 
757     //
758     // Control-Flow Instructions
759     //
760 
selection_merge( merge_id: Word, selection_control: spirv::SelectionControl, ) -> Self761     pub(super) fn selection_merge(
762         merge_id: Word,
763         selection_control: spirv::SelectionControl,
764     ) -> Self {
765         let mut instruction = Self::new(Op::SelectionMerge);
766         instruction.add_operand(merge_id);
767         instruction.add_operand(selection_control.bits());
768         instruction
769     }
770 
loop_merge( merge_id: Word, continuing_id: Word, selection_control: spirv::SelectionControl, ) -> Self771     pub(super) fn loop_merge(
772         merge_id: Word,
773         continuing_id: Word,
774         selection_control: spirv::SelectionControl,
775     ) -> Self {
776         let mut instruction = Self::new(Op::LoopMerge);
777         instruction.add_operand(merge_id);
778         instruction.add_operand(continuing_id);
779         instruction.add_operand(selection_control.bits());
780         instruction
781     }
782 
label(id: Word) -> Self783     pub(super) fn label(id: Word) -> Self {
784         let mut instruction = Self::new(Op::Label);
785         instruction.set_result(id);
786         instruction
787     }
788 
branch(id: Word) -> Self789     pub(super) fn branch(id: Word) -> Self {
790         let mut instruction = Self::new(Op::Branch);
791         instruction.add_operand(id);
792         instruction
793     }
794 
795     // TODO Branch Weights not implemented.
branch_conditional( condition_id: Word, true_label: Word, false_label: Word, ) -> Self796     pub(super) fn branch_conditional(
797         condition_id: Word,
798         true_label: Word,
799         false_label: Word,
800     ) -> Self {
801         let mut instruction = Self::new(Op::BranchConditional);
802         instruction.add_operand(condition_id);
803         instruction.add_operand(true_label);
804         instruction.add_operand(false_label);
805         instruction
806     }
807 
switch(selector_id: Word, default_id: Word, cases: &[Case]) -> Self808     pub(super) fn switch(selector_id: Word, default_id: Word, cases: &[Case]) -> Self {
809         let mut instruction = Self::new(Op::Switch);
810         instruction.add_operand(selector_id);
811         instruction.add_operand(default_id);
812         for case in cases {
813             instruction.add_operand(case.value);
814             instruction.add_operand(case.label_id);
815         }
816         instruction
817     }
818 
select( result_type_id: Word, id: Word, condition_id: Word, accept_id: Word, reject_id: Word, ) -> Self819     pub(super) fn select(
820         result_type_id: Word,
821         id: Word,
822         condition_id: Word,
823         accept_id: Word,
824         reject_id: Word,
825     ) -> Self {
826         let mut instruction = Self::new(Op::Select);
827         instruction.add_operand(result_type_id);
828         instruction.add_operand(id);
829         instruction.add_operand(condition_id);
830         instruction.add_operand(accept_id);
831         instruction.add_operand(reject_id);
832         instruction
833     }
834 
kill() -> Self835     pub(super) fn kill() -> Self {
836         Self::new(Op::Kill)
837     }
838 
return_void() -> Self839     pub(super) fn return_void() -> Self {
840         Self::new(Op::Return)
841     }
842 
return_value(value_id: Word) -> Self843     pub(super) fn return_value(value_id: Word) -> Self {
844         let mut instruction = Self::new(Op::ReturnValue);
845         instruction.add_operand(value_id);
846         instruction
847     }
848 
849     //
850     //  Atomic Instructions
851     //
852 
853     //
854     //  Primitive Instructions
855     //
856 
857     // Barriers
858 
control_barrier( exec_scope_id: Word, mem_scope_id: Word, semantics_id: Word, ) -> Self859     pub(super) fn control_barrier(
860         exec_scope_id: Word,
861         mem_scope_id: Word,
862         semantics_id: Word,
863     ) -> Self {
864         let mut instruction = Self::new(Op::ControlBarrier);
865         instruction.add_operand(exec_scope_id);
866         instruction.add_operand(mem_scope_id);
867         instruction.add_operand(semantics_id);
868         instruction
869     }
870 }
871