UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
VectorVM.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
5#include "CoreMinimal.h"
7
8#include <atomic>
9
10#include "VectorVM.generated.h"
11
12#if UE_BUILD_DEBUG
13#define VM_FORCEINLINE FORCENOINLINE
14#else
15#define VM_FORCEINLINE FORCEINLINE
16#endif
17
18struct FRandomStream;
19
20namespace VectorVM::Runtime
21{
22 struct FVectorVMExecContext;
23 struct FVectorVMRuntimeContext;
24 struct FVectorVMState;
25} // VectorVM::Runtime
26
27//TODO: move to a per platform header and have VM scale vectorization according to vector width.
28#define VECTOR_WIDTH (128)
29#define VECTOR_WIDTH_BYTES (16)
30#define VECTOR_WIDTH_FLOATS (4)
31
32UENUM()
34{
35 Float,
36 Int,
37 Bool,
39};
40
41UENUM()
48
49// OpCode Category #in #out dispatch, merge tbl offset, merge tbl count, int/float flags
50#define VVM_OP_XM_LIST \
51 VVM_OP_XM( done , Other , 0 , 0 , done , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 0 */ \
52 VVM_OP_XM( add , Op , 2 , 1 , f , 0 , 2 , VVM_INS_PARAM_FFFFFF) /* 1 */ \
53 VVM_OP_XM( sub , Op , 2 , 1 , f , 2 , 3 , VVM_INS_PARAM_FFFFFF) /* 2 */ \
54 VVM_OP_XM( mul , Op , 2 , 1 , f , 5 , 8 , VVM_INS_PARAM_FFFFFF) /* 3 */ \
55 VVM_OP_XM( div , Op , 2 , 1 , f , 13 , 3 , VVM_INS_PARAM_FFFFFF) /* 4 */ \
56 VVM_OP_XM( mad , Op , 3 , 1 , f , 16 , 7 , VVM_INS_PARAM_FFFFFF) /* 5 */ \
57 VVM_OP_XM( lerp , Op , 3 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 6 */ \
58 VVM_OP_XM( rcp , Op , 1 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 7 */ \
59 VVM_OP_XM( rsq , Op , 1 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 8 */ \
60 VVM_OP_XM( sqrt , Op , 1 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 9 */ \
61 VVM_OP_XM( neg , Op , 1 , 1 , f , 23 , 1 , VVM_INS_PARAM_FFFFFF) /* 10 */ \
62 VVM_OP_XM( abs , Op , 1 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 11 */ \
63 VVM_OP_XM( exp , Op , 1 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 12 */ \
64 VVM_OP_XM( exp2 , Op , 1 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 13 */ \
65 VVM_OP_XM( log , Op , 1 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 14 */ \
66 VVM_OP_XM( log2 , Op , 1 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 15 */ \
67 VVM_OP_XM( sin , Op , 1 , 1 , f , 24 , 1 , VVM_INS_PARAM_FFFFFF) /* 16 */ \
68 VVM_OP_XM( cos , Op , 1 , 1 , f , 25 , 1 , VVM_INS_PARAM_FFFFFF) /* 17 */ \
69 VVM_OP_XM( tan , Op , 1 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 18 */ \
70 VVM_OP_XM( asin , Op , 1 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 19 */ \
71 VVM_OP_XM( acos , Op , 1 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 20 */ \
72 VVM_OP_XM( atan , Op , 1 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 21 */ \
73 VVM_OP_XM( atan2 , Op , 2 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 22 */ \
74 VVM_OP_XM( ceil , Op , 1 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 23 */ \
75 VVM_OP_XM( floor , Op , 1 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 24 */ \
76 VVM_OP_XM( fmod , Op , 2 , 1 , f , 26 , 1 , VVM_INS_PARAM_FFFFFF) /* 25 */ \
77 VVM_OP_XM( frac , Op , 1 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 26 */ \
78 VVM_OP_XM( trunc , Op , 1 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 27 */ \
79 VVM_OP_XM( clamp , Op , 3 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 28 */ \
80 VVM_OP_XM( min , Op , 2 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 29 */ \
81 VVM_OP_XM( max , Op , 2 , 1 , f , 27 , 1 , VVM_INS_PARAM_FFFFFF) /* 30 */ \
82 VVM_OP_XM( pow , Op , 2 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 31 */ \
83 VVM_OP_XM( round , Op , 1 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 32 */ \
84 VVM_OP_XM( sign , Op , 1 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 33 */ \
85 VVM_OP_XM( step , Op , 2 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 34 */ \
86 VVM_OP_XM( random , Op , 1 , 1 , null , 28 , 2 , VVM_INS_PARAM_FFFFFF) /* 35 */ \
87 VVM_OP_XM( noise , Op , 0 , 0 , null , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 36 */ \
88 VVM_OP_XM( cmplt , Op , 2 , 1 , f , 30 , 3 , VVM_INS_PARAM_FFFIFF) /* 37 */ \
89 VVM_OP_XM( cmple , Op , 2 , 1 , f , 33 , 3 , VVM_INS_PARAM_FFFIFF) /* 38 */ \
90 VVM_OP_XM( cmpgt , Op , 2 , 1 , f , 36 , 2 , VVM_INS_PARAM_FFFIFF) /* 39 */ \
91 VVM_OP_XM( cmpge , Op , 2 , 1 , f , 38 , 2 , VVM_INS_PARAM_FFFIFF) /* 40 */ \
92 VVM_OP_XM( cmpeq , Op , 2 , 1 , f , 40 , 3 , VVM_INS_PARAM_FFFIFF) /* 41 */ \
93 VVM_OP_XM( cmpneq , Op , 2 , 1 , f , 43 , 2 , VVM_INS_PARAM_FFFIFF) /* 42 */ \
94 VVM_OP_XM( select , Op , 3 , 1 , f , 45 , 2 , VVM_INS_PARAM_FFFFFI) /* 43 */ \
95 VVM_OP_XM( addi , Op , 2 , 1 , i , 47 , 2 , VVM_INS_PARAM_FFIIII) /* 44 */ \
96 VVM_OP_XM( subi , Op , 2 , 1 , i , 0 , 0 , VVM_INS_PARAM_FFIIII) /* 45 */ \
97 VVM_OP_XM( muli , Op , 2 , 1 , i , 49 , 1 , VVM_INS_PARAM_FFIIII) /* 46 */ \
98 VVM_OP_XM( divi , Op , 2 , 1 , i , 0 , 0 , VVM_INS_PARAM_FFIIII) /* 47 */ \
99 VVM_OP_XM( clampi , Op , 3 , 1 , i , 0 , 0 , VVM_INS_PARAM_FFIIII) /* 48 */ \
100 VVM_OP_XM( mini , Op , 2 , 1 , i , 0 , 0 , VVM_INS_PARAM_FFIIII) /* 49 */ \
101 VVM_OP_XM( maxi , Op , 2 , 1 , i , 0 , 0 , VVM_INS_PARAM_FFIIII) /* 50 */ \
102 VVM_OP_XM( absi , Op , 1 , 1 , i , 0 , 0 , VVM_INS_PARAM_FFIIII) /* 51 */ \
103 VVM_OP_XM( negi , Op , 1 , 1 , i , 0 , 0 , VVM_INS_PARAM_FFIIII) /* 52 */ \
104 VVM_OP_XM( signi , Op , 1 , 1 , i , 0 , 0 , VVM_INS_PARAM_FFIIII) /* 53 */ \
105 VVM_OP_XM( randomi , Op , 1 , 1 , null , 0 , 0 , VVM_INS_PARAM_FFIIII) /* 54 */ \
106 VVM_OP_XM( cmplti , Op , 2 , 1 , i , 50 , 3 , VVM_INS_PARAM_FFIIII) /* 55 */ \
107 VVM_OP_XM( cmplei , Op , 2 , 1 , i , 53 , 3 , VVM_INS_PARAM_FFIIII) /* 56 */ \
108 VVM_OP_XM( cmpgti , Op , 2 , 1 , i , 59 , 2 , VVM_INS_PARAM_FFIIII) /* 57 */ \
109 VVM_OP_XM( cmpgei , Op , 2 , 1 , i , 61 , 2 , VVM_INS_PARAM_FFIIII) /* 58 */ \
110 VVM_OP_XM( cmpeqi , Op , 2 , 1 , i , 56 , 3 , VVM_INS_PARAM_FFIIII) /* 59 */ \
111 VVM_OP_XM( cmpneqi , Op , 2 , 1 , i , 63 , 2 , VVM_INS_PARAM_FFIIII) /* 60 */ \
112 VVM_OP_XM( bit_and , Op , 2 , 1 , i , 65 , 1 , VVM_INS_PARAM_FFIIII) /* 61 */ \
113 VVM_OP_XM( bit_or , Op , 2 , 1 , i , 66 , 1 , VVM_INS_PARAM_FFIIII) /* 62 */ \
114 VVM_OP_XM( bit_xor , Op , 2 , 1 , i , 0 , 0 , VVM_INS_PARAM_FFIIII) /* 63 */ \
115 VVM_OP_XM( bit_not , Op , 1 , 1 , i , 0 , 0 , VVM_INS_PARAM_FFIIII) /* 64 */ \
116 VVM_OP_XM( bit_lshift , Op , 2 , 1 , i , 67 , 1 , VVM_INS_PARAM_FFIIII) /* 65 */ \
117 VVM_OP_XM( bit_rshift , Op , 2 , 1 , i , 68 , 1 , VVM_INS_PARAM_FFIIII) /* 66 */ \
118 VVM_OP_XM( logic_and , Op , 2 , 1 , i , 0 , 0 , VVM_INS_PARAM_FFIIII) /* 67 */ \
119 VVM_OP_XM( logic_or , Op , 2 , 1 , i , 0 , 0 , VVM_INS_PARAM_FFIIII) /* 68 */ \
120 VVM_OP_XM( logic_xor , Op , 2 , 1 , i , 0 , 0 , VVM_INS_PARAM_FFIIII) /* 69 */ \
121 VVM_OP_XM( logic_not , Op , 1 , 1 , i , 0 , 0 , VVM_INS_PARAM_FFIIII) /* 70 */ \
122 VVM_OP_XM( f2i , Op , 1 , 1 , i , 74 , 3 , VVM_INS_PARAM_FFFFFI) /* 71 */ \
123 VVM_OP_XM( i2f , Op , 1 , 1 , f , 69 , 5 , VVM_INS_PARAM_FFFFIF) /* 72 */ \
124 VVM_OP_XM( f2b , Op , 1 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFFI) /* 73 */ \
125 VVM_OP_XM( b2f , Op , 1 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFIF) /* 74 */ \
126 VVM_OP_XM( i2b , Op , 1 , 1 , i , 0 , 0 , VVM_INS_PARAM_FFFFII) /* 75 */ \
127 VVM_OP_XM( b2i , Op , 1 , 1 , i , 77 , 1 , VVM_INS_PARAM_FFFFII) /* 76 */ \
128 VVM_OP_XM( inputdata_float , Input , 0 , 0 , null , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 77 */ \
129 VVM_OP_XM( inputdata_int32 , Input , 0 , 0 , null , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 78 */ \
130 VVM_OP_XM( inputdata_half , Input , 0 , 0 , null , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 79 */ \
131 VVM_OP_XM( inputdata_noadvance_float , Input , 0 , 0 , null , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 80 */ \
132 VVM_OP_XM( inputdata_noadvance_int32 , Input , 0 , 0 , null , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 81 */ \
133 VVM_OP_XM( inputdata_noadvance_half , Input , 0 , 0 , null , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 82 */ \
134 VVM_OP_XM( outputdata_float , Output , 0 , 0 , null , 0 , 0 , VVM_INS_PARAM_FFFFFI) /* 83 */ \
135 VVM_OP_XM( outputdata_int32 , Output , 0 , 0 , null , 0 , 0 , VVM_INS_PARAM_FFFIII) /* 84 */ \
136 VVM_OP_XM( outputdata_half , Output , 0 , 0 , null , 0 , 0 , VVM_INS_PARAM_FFFFFI) /* 85 */ \
137 VVM_OP_XM( acquireindex , IndexGen , 1 , 0 , null , 0 , 0 , VVM_INS_PARAM_FFFFII) /* 86 */ \
138 VVM_OP_XM( external_func_call , ExtFnCall , 0 , 0 , null , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 87 */ \
139 VVM_OP_XM( exec_index , Op , 1 , 1 , null , 78 , 2 , VVM_INS_PARAM_FFFFFI) /* 88 */ \
140 VVM_OP_XM( noise2D , Other , 0 , 0 , null , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 89 */ \
141 VVM_OP_XM( noise3D , Other , 0 , 0 , null , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 90 */ \
142 VVM_OP_XM( enter_stat_scope , Stat , 1 , 0 , null , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 91 */ \
143 VVM_OP_XM( exit_stat_scope , Stat , 0 , 0 , null , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 92 */ \
144 VVM_OP_XM( update_id , RWBuffer , 0 , 0 , null , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 93 */ \
145 VVM_OP_XM( acquire_id , RWBuffer , 1 , 0 , null , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 94 */ \
146 VVM_OP_XM( half_to_float , Op , 1 , 1 , null , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 95 */ \
147 VVM_OP_XM( fasi , Op , 1 , 1 , null , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 96 */ \
148 VVM_OP_XM( iasf , Op , 1 , 1 , null , 0 , 0 , VVM_INS_PARAM_FFFFFI) /* 97 */ \
149 /* Merged ops -- combined ops that show up frequently together in Fornite. There are three types: */ \
150 /* 1. exec_index that get immediately fed into an add or i2f */ \
151 /* 2. ops with identical inputs */ \
152 /* 3. ops where the output of one chain to the next.. ie a mul that feeds directly into a sub */ \
153 VVM_OP_XM( exec_indexf , Op , 1 , 1 , null , 0 , 0 , VVM_INS_PARAM_FFIIIF) /* 98 */ \
154 VVM_OP_XM( exec_index_addi , Op , 1 , 1 , null , 0 , 0 , VVM_INS_PARAM_FFIIII) /* 99 */ \
155 VVM_OP_XM( cmplt_select , Op , 4 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 100 */ \
156 VVM_OP_XM( cmple_select , Op , 4 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 101 */ \
157 VVM_OP_XM( cmpeq_select , Op , 4 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 102 */ \
158 VVM_OP_XM( cmplti_select , Op , 4 , 1 , f , 0 , 0 , VVM_INS_PARAM_FIIFFF) /* 103 */ \
159 VVM_OP_XM( cmplei_select , Op , 4 , 1 , f , 0 , 0 , VVM_INS_PARAM_FIIFFF) /* 104 */ \
160 VVM_OP_XM( cmpeqi_select , Op , 4 , 1 , f , 0 , 0 , VVM_INS_PARAM_FIIFFF) /* 105 */ \
161 VVM_OP_XM( cmplt_logic_and , Op , 3 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFII) /* 106 */ \
162 VVM_OP_XM( cmple_logic_and , Op , 3 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFII) /* 107 */ \
163 VVM_OP_XM( cmpgt_logic_and , Op , 3 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFII) /* 108 */ \
164 VVM_OP_XM( cmpge_logic_and , Op , 3 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFII) /* 109 */ \
165 VVM_OP_XM( cmpeq_logic_and , Op , 3 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFII) /* 110 */ \
166 VVM_OP_XM( cmpne_logic_and , Op , 3 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFII) /* 111 */ \
167 VVM_OP_XM( cmplti_logic_and , Op , 3 , 1 , i , 0 , 0 , VVM_INS_PARAM_FIIFII) /* 112 */ \
168 VVM_OP_XM( cmplei_logic_and , Op , 3 , 1 , i , 0 , 0 , VVM_INS_PARAM_FIIFII) /* 113 */ \
169 VVM_OP_XM( cmpgti_logic_and , Op , 3 , 1 , i , 0 , 0 , VVM_INS_PARAM_FIIFII) /* 114 */ \
170 VVM_OP_XM( cmpgei_logic_and , Op , 3 , 1 , i , 0 , 0 , VVM_INS_PARAM_FIIFIF) /* 115 */ \
171 VVM_OP_XM( cmpeqi_logic_and , Op , 3 , 1 , i , 0 , 0 , VVM_INS_PARAM_FIIFIF) /* 116 */ \
172 VVM_OP_XM( cmpnei_logic_and , Op , 3 , 1 , i , 0 , 0 , VVM_INS_PARAM_FIIFIF) /* 117 */ \
173 VVM_OP_XM( cmplt_logic_or , Op , 3 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 118 */ \
174 VVM_OP_XM( cmple_logic_or , Op , 3 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 119 */ \
175 VVM_OP_XM( cmpgt_logic_or , Op , 3 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 120 */ \
176 VVM_OP_XM( cmpge_logic_or , Op , 3 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 121 */ \
177 VVM_OP_XM( cmpeq_logic_or , Op , 3 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 122 */ \
178 VVM_OP_XM( cmpne_logic_or , Op , 3 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 123 */ \
179 VVM_OP_XM( cmplti_logic_or , Op , 3 , 1 , i , 0 , 0 , VVM_INS_PARAM_FIIFFF) /* 124 */ \
180 VVM_OP_XM( cmplei_logic_or , Op , 3 , 1 , i , 0 , 0 , VVM_INS_PARAM_FIIFFF) /* 125 */ \
181 VVM_OP_XM( cmpgti_logic_or , Op , 3 , 1 , i , 0 , 0 , VVM_INS_PARAM_FIIFFF) /* 126 */ \
182 VVM_OP_XM( cmpgei_logic_or , Op , 3 , 1 , i , 0 , 0 , VVM_INS_PARAM_FIIFFF) /* 127 */ \
183 VVM_OP_XM( cmpeqi_logic_or , Op , 3 , 1 , i , 0 , 0 , VVM_INS_PARAM_FIIFFF) /* 128 */ \
184 VVM_OP_XM( cmpnei_logic_or , Op , 3 , 1 , i , 0 , 0 , VVM_INS_PARAM_FIIFFF) /* 129 */ \
185 VVM_OP_XM( mad_add , Op , 4 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 130 */ \
186 VVM_OP_XM( mad_sub0 , Op , 4 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 131 */ \
187 VVM_OP_XM( mad_sub1 , Op , 4 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 132 */ \
188 VVM_OP_XM( mad_mul , Op , 4 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 133 */ \
189 VVM_OP_XM( mad_sqrt , Op , 3 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 134 */ \
190 VVM_OP_XM( mad_mad0 , Op , 5 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 135 */ \
191 VVM_OP_XM( mad_mad1 , Op , 5 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 136 */ \
192 VVM_OP_XM( mul_mad0 , Op , 4 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 137 */ \
193 VVM_OP_XM( mul_mad1 , Op , 4 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 138 */ \
194 VVM_OP_XM( mul_add , Op , 3 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 139 */ \
195 VVM_OP_XM( mul_sub0 , Op , 3 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 140 */ \
196 VVM_OP_XM( mul_sub1 , Op , 3 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 141 */ \
197 VVM_OP_XM( mul_mul , Op , 3 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 142 */ \
198 VVM_OP_XM( mul_max , Op , 3 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 143 */ \
199 VVM_OP_XM( mul_2x , Op , 2 , 2 , f , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 144 */ \
200 VVM_OP_XM( add_mad1 , Op , 4 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 145 */ \
201 VVM_OP_XM( add_add , Op , 3 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 146 */ \
202 VVM_OP_XM( sub_cmplt1 , Op , 3 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFIFFF) /* 147 */ \
203 VVM_OP_XM( sub_neg , Op , 2 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 148 */ \
204 VVM_OP_XM( sub_mul , Op , 3 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 149 */ \
205 VVM_OP_XM( div_mad0 , Op , 4 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 150 */ \
206 VVM_OP_XM( div_f2i , Op , 2 , 1 , i , 0 , 0 , VVM_INS_PARAM_FFFFFI) /* 151 */ \
207 VVM_OP_XM( div_mul , Op , 3 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 152 */ \
208 VVM_OP_XM( muli_addi , Op , 3 , 1 , i , 0 , 0 , VVM_INS_PARAM_IIIIII) /* 153 */ \
209 VVM_OP_XM( addi_bit_rshift , Op , 3 , 1 , i , 0 , 0 , VVM_INS_PARAM_IIIIII) /* 154 */ \
210 VVM_OP_XM( addi_muli , Op , 3 , 1 , i , 0 , 0 , VVM_INS_PARAM_IIIIII) /* 155 */ \
211 VVM_OP_XM( b2i_2x , Op , 1 , 2 , i , 0 , 0 , VVM_INS_PARAM_IIIIII) /* 156 */ \
212 VVM_OP_XM( i2f_div0 , Op , 2 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 157 */ \
213 VVM_OP_XM( i2f_div1 , Op , 2 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 158 */ \
214 VVM_OP_XM( i2f_mul , Op , 2 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 159 */ \
215 VVM_OP_XM( i2f_mad0 , Op , 3 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 160 */ \
216 VVM_OP_XM( i2f_mad1 , Op , 3 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 161 */ \
217 VVM_OP_XM( f2i_select1 , Op , 3 , 1 , i , 0 , 0 , VVM_INS_PARAM_IIFIII) /* 162 */ \
218 VVM_OP_XM( f2i_maxi , Op , 2 , 1 , i , 0 , 0 , VVM_INS_PARAM_IIIFII) /* 163 */ \
219 VVM_OP_XM( f2i_addi , Op , 2 , 1 , i , 0 , 0 , VVM_INS_PARAM_IIIFII) /* 164 */ \
220 VVM_OP_XM( fmod_add , Op , 3 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 165 */ \
221 VVM_OP_XM( bit_and_i2f , Op , 2 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 166 */ \
222 VVM_OP_XM( bit_rshift_bit_and , Op , 3 , 1 , i , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 167 */ \
223 VVM_OP_XM( neg_cmplt , Op , 2 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 168 */ \
224 VVM_OP_XM( bit_or_muli , Op , 3 , 1 , i , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 169 */ \
225 VVM_OP_XM( bit_lshift_bit_or , Op , 3 , 1 , i , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 170 */ \
226 VVM_OP_XM( random_add , Op , 2 , 1 , null , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 171 */ \
227 VVM_OP_XM( random_2x , Op , 1 , 2 , null , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 172 */ \
228 VVM_OP_XM( max_f2i , Op , 2 , 1 , i , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 173 */ \
229 VVM_OP_XM( select_mul , Op , 4 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 174 */ \
230 VVM_OP_XM( select_add , Op , 4 , 1 , f , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 175 */ \
231 VVM_OP_XM( sin_cos , Op , 1 , 2 , null , 0 , 0 , VVM_INS_PARAM_FFFFFF) /* 176 */ \
232 VVM_OP_XM( outputdata_float_from_half , Output , 0 , 0 , null , 0 , 0 , VVM_INS_PARAM_FFFFFI) /* 177 */ \
233 VVM_OP_XM( outputdata_half_from_half , Output , 0 , 0 , null , 0 , 0 , VVM_INS_PARAM_FFFFFI) /* 178 */
234
235#define VVM_OP_XM(n, ...) n,
236enum class EVectorVMOp : uint8
237{
240};
241#undef VVM_OP_XM
242
243//TODO:
244//All of this stuff can be handled by the VM compiler rather than dirtying the VM code.
245//Some require RWBuffer like support.
247{
250
253
256
257 int32 DataSetAccessIndex = INDEX_NONE; // index for individual elements of this set
258
259 int32 InstanceOffset = INDEX_NONE; // offset of the first instance processed
260
264
266 int32* NumFreeIDs = nullptr;
267
269 int32* MaxUsedID = nullptr;
270
272
274
275 FDataSetMeta() = default;
276
277 inline void Reset()
278 {
283 IDTable = nullptr;
284 FreeIDTable = nullptr;
285 SpawnedIDsTable = nullptr;
286 NumFreeIDs = nullptr;
287 MaxUsedID = nullptr;
289 }
290
306
307private:
308 // Non-copyable and non-movable
309 FDataSetMeta(FDataSetMeta&&) = delete;
310 FDataSetMeta(const FDataSetMeta&) = delete;
311 FDataSetMeta& operator=(FDataSetMeta&&) = delete;
312 FDataSetMeta& operator=(const FDataSetMeta&) = delete;
313};
314
316{
317public:
320
323
328
331
335
339 {
340 if (!*RandCounters)
341 {
342 *RandCounters = (int*)FMemory::MallocZeroed(sizeof(int32) * NumInstances);
343 }
344 return *RandCounters;
345 }
347 inline void* GetUserPtrTable(int32 UserPtrIdx) { check(UserPtrIdx < NumUserPtrs); return UserPtrTable[UserPtrIdx]; }
348 template<uint32 InstancesPerOp> inline int32 GetNumLoops() const { static_assert(InstancesPerOp == 4); return NumLoops; };
349
356};
357
359
366
367namespace VectorVM
368{
371
372#if WITH_EDITOR
375#endif
376
378
379#if STATS
380
381 struct FStatScopeData
382 {
383 TStatId StatId;
384 std::atomic<uint64> ExecutionCycleCount = { 0 };
385
387 : StatId(InStatId)
388 {
389 }
390
391 FStatScopeData(const FStatScopeData& InObj)
392 : StatId(InObj.StatId)
393 {
394 ExecutionCycleCount.store(InObj.ExecutionCycleCount.load());
395 }
396 };
397
398#endif // STATS
399
400 VECTORVM_API void Init();
401
402 #define VVM_EXT_FUNC_INPUT_LOC_BIT (unsigned short)(1<<15)
403 #define VVM_EXT_FUNC_INPUT_LOC_MASK (unsigned short)~VVM_EXT_FUNC_INPUT_LOC_BIT
404
405 template<typename T>
407 {
409 T* Ptr;
411 {
412 int32 AdvanceOffset;
413 int32* ConstPtr = (int32*)Context.GetNextRegister(&AdvanceOffset);
414 check(AdvanceOffset == 0); //must be constant
417 Ptr = (T*)Context.GetUserPtrTable(UserPtrIdx);
418 }
419
420 VM_FORCEINLINE T* Get() { return Ptr; }
422 VM_FORCEINLINE operator T*() { return Ptr; }
423
424 VM_FORCEINLINE const T* Get() const { return Ptr; }
425 VM_FORCEINLINE const T* operator->() const { return Ptr; }
426 VM_FORCEINLINE operator const T* () const { return Ptr; }
427 };
428
429 // A flexible handler that can deal with either constant or register inputs.
430 template<typename T>
432 {
433 private:
435 const T* RESTRICT InputPtr = nullptr;
436 const T* RESTRICT StartPtr = nullptr;
437 int32 AdvanceOffset = 0;
438
439 public:
441
446
448 {
449 InputPtr = (T*)Context.GetNextRegister(&AdvanceOffset);
450 InputPtr += Context.PerInstanceFnInstanceIdx * AdvanceOffset;
451
452 StartPtr = InputPtr;
453 }
454
455 inline bool IsConstant() const { return !IsRegister(); }
456 inline bool IsRegister() const { return AdvanceOffset > 0; }
457 inline void Reset(){ InputPtr = StartPtr; }
458
459 inline const T Get() { return *InputPtr; }
460 inline const T* GetDest() { return InputPtr; }
461 inline void Advance(int32 Count=1) { InputPtr += AdvanceOffset * Count; }
462 inline const T GetAndAdvance()
463 {
464 const T* Ret = InputPtr;
465 InputPtr += AdvanceOffset;
466 return *Ret;
467 }
468 inline const T* GetDestAndAdvance()
469 {
470 const T* Ret = InputPtr;
471 InputPtr += AdvanceOffset;
472 return Ret;
473 }
474 };
475
476 template<typename T>
478 {
479 private:
480 T* RESTRICT Register = nullptr;
481 int32 AdvanceOffset = 0;
482 public:
484 {
485 Register = (T*)Context.GetNextRegister(&AdvanceOffset);
486
487 //Hack: Offset into the buffer by the instance offset.
488 Register += Context.PerInstanceFnInstanceIdx * AdvanceOffset;
489 }
490
491 inline bool IsValid() const { return AdvanceOffset > 0; }
492 inline const T Get() { return *Register; }
493 inline T* GetDest() { return Register; }
494 inline void Advance() { Register += AdvanceOffset; }
495 inline void Advance(int32 Count) { Register += AdvanceOffset * Count; }
496 inline const T GetAndAdvance()
497 {
498 T* Ret = Register;
499 Register += AdvanceOffset;
500 return *Ret;
501 }
503 {
504 T* Ret = Register;
505 Register += AdvanceOffset;
506 return Ret;
507 }
508 };
509
510 template<typename T>
512 {
514
516 {
517 int32 AdvanceOffset;
518 const T* Register = (const T*)Context.GetNextRegister(&AdvanceOffset);
519 Register += Context.PerInstanceFnInstanceIdx * AdvanceOffset;
520
522 }
523
524 VM_FORCEINLINE const T& Get() { return Constant; }
525 VM_FORCEINLINE const T& GetAndAdvance() { return Constant; }
527 };
528
530 {
533 VVMFlag_LargeScript = 1 << 2, //if true register indices are 16 bit, otherwise they're 8 bit
536 };
537} // namespace VectorVM
538
#define GCC_ALIGN(n)
Definition AndroidPlatform.h:163
#define check(expr)
Definition AssertionMacros.h:314
@ INDEX_NONE
Definition CoreMiscDefines.h:150
FPlatformTypes::int32 int32
A 32-bit signed integer.
Definition Platform.h:1125
#define RESTRICT
Definition Platform.h:706
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
#define DECLARE_DELEGATE_OneParam(DelegateName, Param1Type)
Definition DelegateCombinations.h:48
FRDGImportedBuffer Register(FRDGBuilder &GraphBuilder, const FRDGExternalBuffer &In, ERDGImportedBufferFlags Flags, ERDGUnorderedAccessViewFlags UAVFlags)
Definition HairStrandsInterface.cpp:94
#define UENUM(...)
Definition ObjectMacros.h:749
EVectorVMBaseTypes
Definition VectorVM.h:34
#define VVM_OP_XM_LIST
Definition VectorVM.h:50
EVectorVMOperandLocation
Definition VectorVM.h:43
#define VM_FORCEINLINE
Definition VectorVM.h:15
EVectorVMOp
Definition VectorVM.h:237
uint8_t uint8
Definition binka_ue_file_header.h:8
uint32_t uint32
Definition binka_ue_file_header.h:6
Definition VectorVM.h:316
FRandomStream & GetRandStream()
Definition VectorVM.h:346
int NumUserPtrs
Definition VectorVM.h:330
int32 * GetRandCounters()
Definition VectorVM.h:338
int StartInstance
Definition VectorVM.h:324
int RegReadCount
Definition VectorVM.h:321
VM_FORCEINLINE int32 GetNumInstances() const
Definition VectorVM.h:337
int32 GetNumLoops() const
Definition VectorVM.h:348
VM_FORCEINLINE int32 GetStartInstance() const
Definition VectorVM.h:336
FRandomStream * RandStream
Definition VectorVM.h:332
float * GetNextRegister(int32 *OutAdvanceOffset)
Definition VectorVM.h:350
int NumInstances
Definition VectorVM.h:325
TArrayView< FDataSetMeta > DataSets
Definition VectorVM.h:334
int32 ** RandCounters
Definition VectorVM.h:333
int NumRegisters
Definition VectorVM.h:322
uint8 * RegInc
Definition VectorVM.h:319
int NumLoops
Definition VectorVM.h:326
void * GetUserPtrTable(int32 UserPtrIdx)
Definition VectorVM.h:347
void ** UserPtrTable
Definition VectorVM.h:329
int PerInstanceFnInstanceIdx
Definition VectorVM.h:327
MS_ALIGN(32) uint32 **RegisterData GCC_ALIGN(32)
Definition ArrayView.h:139
Definition Array.h:670
EVectorVMFlags
Definition VectorVM.h:530
@ VVMFlag_HasRandInstruction
Definition VectorVM.h:534
@ VVMFlag_OptSaveIntermediateState
Definition VectorVM.h:531
@ VVMFlag_LargeScript
Definition VectorVM.h:533
@ VVMFlag_OptOmitStats
Definition VectorVM.h:532
@ VVMFlag_DataMapCacheSetup
Definition VectorVM.h:535
Definition VectorVMRuntime.cpp:31
Definition VectorVM.cpp:19
uint8 GetNumOpCodes()
Definition VectorVM.cpp:21
void Init()
Definition VectorVM.cpp:71
uint8 CreateSrcOperandMask(EVectorVMOperandLocation Type0, EVectorVMOperandLocation Type1, EVectorVMOperandLocation Type2)
Definition VectorVM.cpp:58
Definition VectorVM.h:247
TArray< int32 > *RESTRICT IDTable
Definition VectorVM.h:261
uint32 OutputRegisterTypeOffsets[3]
Definition VectorVM.h:255
void Init(FInputRegisterView InInputRegisters, FOutputRegisterView InOutputRegisters, int32 InInstanceOffset, TArray< int32 > *InIDTable, TArray< int32 > *InFreeIDTable, int32 *InNumFreeIDs, int32 *InNumSpawnedIDs, int32 *InMaxUsedID, int32 InIDAcquireTag, TArray< int32 > *InSpawnedIDsTable)
Definition VectorVM.h:291
TArrayView< uint8 const *RESTRICT const > FInputRegisterView
Definition VectorVM.h:248
TArray< int32 > *RESTRICT SpawnedIDsTable
Definition VectorVM.h:263
TArrayView< uint8 *RESTRICT const > FOutputRegisterView
Definition VectorVM.h:249
FOutputRegisterView OutputRegisters
Definition VectorVM.h:252
int32 * NumFreeIDs
Definition VectorVM.h:266
int32 InstanceOffset
Definition VectorVM.h:259
int32 DataSetAccessIndex
Definition VectorVM.h:257
int32 IDAcquireTag
Definition VectorVM.h:273
int32 * MaxUsedID
Definition VectorVM.h:269
TArray< int32 > *RESTRICT FreeIDTable
Definition VectorVM.h:262
FDataSetMeta()=default
int32 * NumSpawnedIDs
Definition VectorVM.h:271
uint32 InputRegisterTypeOffsets[3]
Definition VectorVM.h:254
FInputRegisterView InputRegisters
Definition VectorVM.h:251
void Reset()
Definition VectorVM.h:277
Definition RandomStream.h:20
Definition VectorVM.h:361
int32 NumOutputs
Definition VectorVM.h:364
const FVMExternalFunction * Function
Definition VectorVM.h:362
int32 NumInputs
Definition VectorVM.h:363
Definition LightweightStats.h:416
Definition VectorVM.h:512
FExternalFuncConstHandler(FVectorVMExternalFunctionContext &Context)
Definition VectorVM.h:515
VM_FORCEINLINE const T & GetAndAdvance()
Definition VectorVM.h:525
VM_FORCEINLINE const T & Get()
Definition VectorVM.h:524
VM_FORCEINLINE void Advance()
Definition VectorVM.h:526
T Constant
Definition VectorVM.h:513
Definition VectorVM.h:432
void Advance(int32 Count=1)
Definition VectorVM.h:461
FExternalFuncInputHandler(FVectorVMExternalFunctionContext &Context)
Definition VectorVM.h:442
bool IsRegister() const
Definition VectorVM.h:456
const T * GetDest()
Definition VectorVM.h:460
void Reset()
Definition VectorVM.h:457
bool IsConstant() const
Definition VectorVM.h:455
const T Get()
Definition VectorVM.h:459
const T * GetDestAndAdvance()
Definition VectorVM.h:468
void Init(FVectorVMExternalFunctionContext &Context)
Definition VectorVM.h:447
const T GetAndAdvance()
Definition VectorVM.h:462
FExternalFuncRegisterHandler(FVectorVMExternalFunctionContext &Context)
Definition VectorVM.h:483
void Advance()
Definition VectorVM.h:494
bool IsValid() const
Definition VectorVM.h:491
const T GetAndAdvance()
Definition VectorVM.h:496
void Advance(int32 Count)
Definition VectorVM.h:495
const T Get()
Definition VectorVM.h:492
T * GetDestAndAdvance()
Definition VectorVM.h:502
T * GetDest()
Definition VectorVM.h:493
Definition VectorVM.h:407
VM_FORCEINLINE const T * operator->() const
Definition VectorVM.h:425
VM_FORCEINLINE T * operator->()
Definition VectorVM.h:421
VM_FORCEINLINE T * Get()
Definition VectorVM.h:420
int32 UserPtrIdx
Definition VectorVM.h:408
VM_FORCEINLINE const T * Get() const
Definition VectorVM.h:424
FUserPtrHandler(FVectorVMExternalFunctionContext &Context)
Definition VectorVM.h:410
T * Ptr
Definition VectorVM.h:409