Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 1 | // Copyright 2016 The SwiftShader Authors. All Rights Reserved. |
| 2 | // |
| 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // you may not use this file except in compliance with the License. |
| 5 | // You may obtain a copy of the License at |
| 6 | // |
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | // |
| 9 | // Unless required by applicable law or agreed to in writing, software |
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | // See the License for the specific language governing permissions and |
| 13 | // limitations under the License. |
| 14 | |
| 15 | #ifndef sw_Shader_hpp |
| 16 | #define sw_Shader_hpp |
| 17 | |
| 18 | #include "Common/Types.hpp" |
| 19 | |
| 20 | #include <string> |
| 21 | #include <vector> |
| 22 | |
| 23 | namespace sw |
| 24 | { |
| 25 | class Shader |
| 26 | { |
| 27 | public: |
| 28 | enum ShaderType |
| 29 | { |
| 30 | SHADER_PIXEL = 0xFFFF, |
| 31 | SHADER_VERTEX = 0xFFFE, |
| 32 | SHADER_GEOMETRY = 0xFFFD |
| 33 | }; |
| 34 | |
| 35 | enum Opcode |
| 36 | { |
| 37 | // Matches order in d3d9types.h |
Ben Clayton | d951f19 | 2019-02-11 20:59:19 +0000 | [diff] [blame] | 38 | // See https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/d3d9types/ne-d3d9types-_d3dshader_instruction_opcode_type |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 39 | OPCODE_NOP = 0, |
| 40 | OPCODE_MOV, |
| 41 | OPCODE_ADD, |
| 42 | OPCODE_SUB, |
| 43 | OPCODE_MAD, |
| 44 | OPCODE_MUL, |
| 45 | OPCODE_RCPX, |
| 46 | OPCODE_RSQX, |
| 47 | OPCODE_DP3, |
| 48 | OPCODE_DP4, |
| 49 | OPCODE_MIN, |
| 50 | OPCODE_MAX, |
| 51 | OPCODE_SLT, |
| 52 | OPCODE_SGE, |
| 53 | OPCODE_EXP2X, // D3DSIO_EXP |
| 54 | OPCODE_LOG2X, // D3DSIO_LOG |
| 55 | OPCODE_LIT, |
| 56 | OPCODE_ATT, // D3DSIO_DST |
| 57 | OPCODE_LRP, |
| 58 | OPCODE_FRC, |
| 59 | OPCODE_M4X4, |
| 60 | OPCODE_M4X3, |
| 61 | OPCODE_M3X4, |
| 62 | OPCODE_M3X3, |
| 63 | OPCODE_M3X2, |
| 64 | OPCODE_CALL, |
| 65 | OPCODE_CALLNZ, |
| 66 | OPCODE_LOOP, |
| 67 | OPCODE_RET, |
| 68 | OPCODE_ENDLOOP, |
| 69 | OPCODE_LABEL, |
| 70 | OPCODE_DCL, |
| 71 | OPCODE_POWX, |
| 72 | OPCODE_CRS, |
| 73 | OPCODE_SGN, |
| 74 | OPCODE_ABS, |
| 75 | OPCODE_NRM3, // D3DSIO_NRM |
| 76 | OPCODE_SINCOS, |
| 77 | OPCODE_REP, |
| 78 | OPCODE_ENDREP, |
| 79 | OPCODE_IF, |
| 80 | OPCODE_IFC, |
| 81 | OPCODE_ELSE, |
| 82 | OPCODE_ENDIF, |
| 83 | OPCODE_BREAK, |
| 84 | OPCODE_BREAKC, |
| 85 | OPCODE_MOVA, |
| 86 | OPCODE_DEFB, |
| 87 | OPCODE_DEFI, |
| 88 | |
| 89 | OPCODE_TEXCOORD = 64, |
| 90 | OPCODE_TEXKILL, |
| 91 | OPCODE_TEX, |
| 92 | OPCODE_TEXBEM, |
| 93 | OPCODE_TEXBEML, |
| 94 | OPCODE_TEXREG2AR, |
| 95 | OPCODE_TEXREG2GB, |
| 96 | OPCODE_TEXM3X2PAD, |
| 97 | OPCODE_TEXM3X2TEX, |
| 98 | OPCODE_TEXM3X3PAD, |
| 99 | OPCODE_TEXM3X3TEX, |
| 100 | OPCODE_RESERVED0, |
| 101 | OPCODE_TEXM3X3SPEC, |
| 102 | OPCODE_TEXM3X3VSPEC, |
| 103 | OPCODE_EXPP, |
| 104 | OPCODE_LOGP, |
| 105 | OPCODE_CND, |
| 106 | OPCODE_DEF, |
| 107 | OPCODE_TEXREG2RGB, |
| 108 | OPCODE_TEXDP3TEX, |
| 109 | OPCODE_TEXM3X2DEPTH, |
| 110 | OPCODE_TEXDP3, |
| 111 | OPCODE_TEXM3X3, |
| 112 | OPCODE_TEXDEPTH, |
| 113 | OPCODE_CMP0, // D3DSIO_CMP |
| 114 | OPCODE_BEM, |
| 115 | OPCODE_DP2ADD, |
| 116 | OPCODE_DFDX, // D3DSIO_DSX |
| 117 | OPCODE_DFDY, // D3DSIO_DSY |
| 118 | OPCODE_TEXLDD, |
| 119 | OPCODE_CMP, // D3DSIO_SETP |
| 120 | OPCODE_TEXLDL, |
| 121 | OPCODE_BREAKP, |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 122 | |
| 123 | OPCODE_PHASE = 0xFFFD, |
| 124 | OPCODE_COMMENT = 0xFFFE, |
| 125 | OPCODE_END = 0xFFFF, |
| 126 | |
| 127 | OPCODE_PS_1_0 = 0xFFFF0100, |
| 128 | OPCODE_PS_1_1 = 0xFFFF0101, |
| 129 | OPCODE_PS_1_2 = 0xFFFF0102, |
| 130 | OPCODE_PS_1_3 = 0xFFFF0103, |
| 131 | OPCODE_PS_1_4 = 0xFFFF0104, |
| 132 | OPCODE_PS_2_0 = 0xFFFF0200, |
| 133 | OPCODE_PS_2_x = 0xFFFF0201, |
| 134 | OPCODE_PS_3_0 = 0xFFFF0300, |
| 135 | |
| 136 | OPCODE_VS_1_0 = 0xFFFE0100, |
| 137 | OPCODE_VS_1_1 = 0xFFFE0101, |
| 138 | OPCODE_VS_2_0 = 0xFFFE0200, |
| 139 | OPCODE_VS_2_x = 0xFFFE0201, |
| 140 | OPCODE_VS_2_sw = 0xFFFE02FF, |
| 141 | OPCODE_VS_3_0 = 0xFFFE0300, |
| 142 | OPCODE_VS_3_sw = 0xFFFE03FF, |
| 143 | |
| 144 | OPCODE_NULL = 0x10000000, // Dead instruction, to be eliminated |
| 145 | OPCODE_WHILE, |
| 146 | OPCODE_ENDWHILE, |
| 147 | OPCODE_COS, |
| 148 | OPCODE_SIN, |
| 149 | OPCODE_TAN, |
| 150 | OPCODE_ACOS, |
| 151 | OPCODE_ASIN, |
| 152 | OPCODE_ATAN, |
| 153 | OPCODE_ATAN2, |
| 154 | OPCODE_COSH, |
| 155 | OPCODE_SINH, |
| 156 | OPCODE_TANH, |
| 157 | OPCODE_ACOSH, |
| 158 | OPCODE_ASINH, |
| 159 | OPCODE_ATANH, |
| 160 | OPCODE_DP1, |
| 161 | OPCODE_DP2, |
| 162 | OPCODE_TRUNC, |
| 163 | OPCODE_FLOOR, |
| 164 | OPCODE_ROUND, |
| 165 | OPCODE_ROUNDEVEN, |
| 166 | OPCODE_CEIL, |
| 167 | OPCODE_SQRT, |
| 168 | OPCODE_RSQ, |
| 169 | OPCODE_LEN2, |
| 170 | OPCODE_LEN3, |
| 171 | OPCODE_LEN4, |
| 172 | OPCODE_DIST1, |
| 173 | OPCODE_DIST2, |
| 174 | OPCODE_DIST3, |
| 175 | OPCODE_DIST4, |
| 176 | OPCODE_NRM2, |
| 177 | OPCODE_NRM4, |
| 178 | OPCODE_DIV, |
| 179 | OPCODE_MOD, |
| 180 | OPCODE_EXP2, |
| 181 | OPCODE_LOG2, |
| 182 | OPCODE_EXP, |
| 183 | OPCODE_LOG, |
| 184 | OPCODE_POW, |
| 185 | OPCODE_F2B, // Float to bool |
| 186 | OPCODE_B2F, // Bool to float |
| 187 | OPCODE_F2I, // Float to int |
| 188 | OPCODE_I2F, // Int to float |
| 189 | OPCODE_F2U, // Float to uint |
| 190 | OPCODE_U2F, // Uint to float |
| 191 | OPCODE_I2B, // Int to bool |
| 192 | OPCODE_B2I, // Bool to int |
| 193 | OPCODE_DET2, |
| 194 | OPCODE_DET3, |
| 195 | OPCODE_DET4, |
| 196 | OPCODE_ALL, |
| 197 | OPCODE_ANY, |
| 198 | OPCODE_NEG, |
| 199 | OPCODE_NOT, |
| 200 | OPCODE_OR, |
| 201 | OPCODE_XOR, |
| 202 | OPCODE_AND, |
| 203 | OPCODE_EQ, |
| 204 | OPCODE_NE, |
| 205 | OPCODE_STEP, |
| 206 | OPCODE_SMOOTH, |
| 207 | OPCODE_ISNAN, |
| 208 | OPCODE_ISINF, |
| 209 | OPCODE_TEXOFFSET, |
Nicolas Capens | a0b5783 | 2017-11-07 13:07:53 -0500 | [diff] [blame] | 210 | OPCODE_TEXLODOFFSET, |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 211 | OPCODE_TEXELFETCH, |
| 212 | OPCODE_TEXELFETCHOFFSET, |
| 213 | OPCODE_TEXGRAD, |
| 214 | OPCODE_TEXGRADOFFSET, |
Nicolas Capens | a0b5783 | 2017-11-07 13:07:53 -0500 | [diff] [blame] | 215 | OPCODE_TEXBIAS, |
| 216 | OPCODE_TEXLOD, |
| 217 | OPCODE_TEXOFFSETBIAS, |
| 218 | OPCODE_TEXSIZE, |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 219 | OPCODE_FLOATBITSTOINT, |
| 220 | OPCODE_FLOATBITSTOUINT, |
| 221 | OPCODE_INTBITSTOFLOAT, |
| 222 | OPCODE_UINTBITSTOFLOAT, |
| 223 | OPCODE_PACKSNORM2x16, |
| 224 | OPCODE_PACKUNORM2x16, |
| 225 | OPCODE_PACKHALF2x16, |
| 226 | OPCODE_UNPACKSNORM2x16, |
| 227 | OPCODE_UNPACKUNORM2x16, |
| 228 | OPCODE_UNPACKHALF2x16, |
| 229 | OPCODE_FORWARD1, |
| 230 | OPCODE_FORWARD2, |
| 231 | OPCODE_FORWARD3, |
| 232 | OPCODE_FORWARD4, |
| 233 | OPCODE_REFLECT1, |
| 234 | OPCODE_REFLECT2, |
| 235 | OPCODE_REFLECT3, |
| 236 | OPCODE_REFLECT4, |
| 237 | OPCODE_REFRACT1, |
| 238 | OPCODE_REFRACT2, |
| 239 | OPCODE_REFRACT3, |
| 240 | OPCODE_REFRACT4, |
| 241 | OPCODE_ICMP, |
| 242 | OPCODE_UCMP, |
| 243 | OPCODE_SELECT, |
| 244 | OPCODE_EXTRACT, |
| 245 | OPCODE_INSERT, |
| 246 | OPCODE_DISCARD, |
| 247 | OPCODE_FWIDTH, |
Nicolas Capens | 6e8ec33 | 2018-11-06 11:56:21 -0500 | [diff] [blame] | 248 | OPCODE_LEAVE, // Return before the end of the function |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 249 | OPCODE_CONTINUE, |
Nicolas Capens | 6e8ec33 | 2018-11-06 11:56:21 -0500 | [diff] [blame] | 250 | OPCODE_TEST, // Marks the end of the code that can be skipped by 'continue' |
| 251 | OPCODE_SCALAR, // Marks the start of code not subject to SIMD lane masking. Ends at WHILE and ENDWHILE. |
Alexis Hetu | 9aa83a9 | 2016-05-02 17:34:46 -0400 | [diff] [blame] | 252 | OPCODE_SWITCH, |
| 253 | OPCODE_ENDSWITCH, |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 254 | |
| 255 | // Integer opcodes |
| 256 | OPCODE_INEG, |
| 257 | OPCODE_IABS, |
| 258 | OPCODE_ISGN, |
| 259 | OPCODE_IADD, |
| 260 | OPCODE_ISUB, |
| 261 | OPCODE_IMUL, |
| 262 | OPCODE_IDIV, |
| 263 | OPCODE_IMAD, |
| 264 | OPCODE_IMOD, |
| 265 | OPCODE_SHL, |
| 266 | OPCODE_ISHR, |
| 267 | OPCODE_IMIN, |
| 268 | OPCODE_IMAX, |
| 269 | |
| 270 | // Unsigned integer opcodes |
| 271 | OPCODE_UDIV, |
| 272 | OPCODE_UMOD, |
| 273 | OPCODE_USHR, |
| 274 | OPCODE_UMIN, |
| 275 | OPCODE_UMAX, |
| 276 | }; |
| 277 | |
| 278 | static Opcode OPCODE_DP(int); |
| 279 | static Opcode OPCODE_LEN(int); |
| 280 | static Opcode OPCODE_DIST(int); |
| 281 | static Opcode OPCODE_NRM(int); |
| 282 | static Opcode OPCODE_FORWARD(int); |
| 283 | static Opcode OPCODE_REFLECT(int); |
| 284 | static Opcode OPCODE_REFRACT(int); |
| 285 | |
| 286 | enum Control |
| 287 | { |
| 288 | CONTROL_RESERVED0, |
| 289 | CONTROL_GT, |
| 290 | CONTROL_EQ, |
| 291 | CONTROL_GE, |
| 292 | CONTROL_LT, |
| 293 | CONTROL_NE, |
| 294 | CONTROL_LE, |
| 295 | CONTROL_RESERVED1 |
| 296 | }; |
| 297 | |
| 298 | enum SamplerType |
| 299 | { |
| 300 | SAMPLER_UNKNOWN, |
| 301 | SAMPLER_1D, |
| 302 | SAMPLER_2D, |
| 303 | SAMPLER_CUBE, |
| 304 | SAMPLER_VOLUME |
| 305 | }; |
| 306 | |
| 307 | enum Usage // For vertex input/output declarations |
| 308 | { |
| 309 | USAGE_POSITION = 0, |
| 310 | USAGE_BLENDWEIGHT = 1, |
| 311 | USAGE_BLENDINDICES = 2, |
| 312 | USAGE_NORMAL = 3, |
| 313 | USAGE_PSIZE = 4, |
| 314 | USAGE_TEXCOORD = 5, |
| 315 | USAGE_TANGENT = 6, |
| 316 | USAGE_BINORMAL = 7, |
| 317 | USAGE_TESSFACTOR = 8, |
| 318 | USAGE_POSITIONT = 9, |
| 319 | USAGE_COLOR = 10, |
| 320 | USAGE_FOG = 11, |
| 321 | USAGE_DEPTH = 12, |
| 322 | USAGE_SAMPLE = 13 |
| 323 | }; |
| 324 | |
| 325 | enum ParameterType |
| 326 | { |
| 327 | PARAMETER_TEMP = 0, |
| 328 | PARAMETER_INPUT = 1, |
| 329 | PARAMETER_CONST = 2, |
| 330 | PARAMETER_TEXTURE = 3, |
| 331 | PARAMETER_ADDR = 3, |
| 332 | PARAMETER_RASTOUT = 4, |
| 333 | PARAMETER_ATTROUT = 5, |
| 334 | PARAMETER_TEXCRDOUT = 6, |
| 335 | PARAMETER_OUTPUT = 6, |
| 336 | PARAMETER_CONSTINT = 7, |
| 337 | PARAMETER_COLOROUT = 8, |
| 338 | PARAMETER_DEPTHOUT = 9, |
| 339 | PARAMETER_SAMPLER = 10, |
| 340 | PARAMETER_CONST2 = 11, |
| 341 | PARAMETER_CONST3 = 12, |
| 342 | PARAMETER_CONST4 = 13, |
| 343 | PARAMETER_CONSTBOOL = 14, |
| 344 | PARAMETER_LOOP = 15, |
| 345 | PARAMETER_TEMPFLOAT16 = 16, |
| 346 | PARAMETER_MISCTYPE = 17, |
| 347 | PARAMETER_LABEL = 18, |
| 348 | PARAMETER_PREDICATE = 19, |
| 349 | |
| 350 | // PARAMETER_FLOAT1LITERAL, |
| 351 | // PARAMETER_FLOAT2LITERAL, |
| 352 | // PARAMETER_FLOAT3LITERAL, |
| 353 | PARAMETER_FLOAT4LITERAL, |
| 354 | PARAMETER_BOOL1LITERAL, |
| 355 | // PARAMETER_BOOL2LITERAL, |
| 356 | // PARAMETER_BOOL3LITERAL, |
| 357 | // PARAMETER_BOOL4LITERAL, |
| 358 | // PARAMETER_INT1LITERAL, |
| 359 | // PARAMETER_INT2LITERAL, |
| 360 | // PARAMETER_INT3LITERAL, |
| 361 | PARAMETER_INT4LITERAL, |
| 362 | |
| 363 | PARAMETER_VOID |
| 364 | }; |
| 365 | |
Alexis Hetu | 877ddfc | 2017-07-25 17:48:00 -0400 | [diff] [blame] | 366 | enum MiscParameterIndex |
| 367 | { |
| 368 | VPosIndex = 0, |
| 369 | VFaceIndex = 1, |
| 370 | InstanceIDIndex = 2, |
| 371 | VertexIDIndex = 3, |
| 372 | }; |
| 373 | |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 374 | enum Modifier |
| 375 | { |
| 376 | MODIFIER_NONE, |
| 377 | MODIFIER_NEGATE, |
| 378 | MODIFIER_BIAS, |
| 379 | MODIFIER_BIAS_NEGATE, |
| 380 | MODIFIER_SIGN, |
| 381 | MODIFIER_SIGN_NEGATE, |
| 382 | MODIFIER_COMPLEMENT, |
| 383 | MODIFIER_X2, |
| 384 | MODIFIER_X2_NEGATE, |
| 385 | MODIFIER_DZ, |
| 386 | MODIFIER_DW, |
| 387 | MODIFIER_ABS, |
| 388 | MODIFIER_ABS_NEGATE, |
| 389 | MODIFIER_NOT |
| 390 | }; |
| 391 | |
| 392 | enum Analysis |
| 393 | { |
| 394 | // Flags indicating whether an instruction is affected by an execution enable mask |
| 395 | ANALYSIS_BRANCH = 0x00000001, |
| 396 | ANALYSIS_BREAK = 0x00000002, |
| 397 | ANALYSIS_CONTINUE = 0x00000004, |
| 398 | ANALYSIS_LEAVE = 0x00000008, |
| 399 | }; |
| 400 | |
Nicolas Capens | 0530b45 | 2017-11-15 16:39:47 -0500 | [diff] [blame] | 401 | struct Relative |
| 402 | { |
| 403 | ParameterType type : 8; |
| 404 | unsigned int index; |
| 405 | unsigned int swizzle : 8; |
| 406 | unsigned int scale; |
Nicolas Capens | 4b74373 | 2018-05-28 13:22:07 -0400 | [diff] [blame] | 407 | bool dynamic; // Varies between concurrent shader instances |
Nicolas Capens | 0530b45 | 2017-11-15 16:39:47 -0500 | [diff] [blame] | 408 | }; |
| 409 | |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 410 | struct Parameter |
| 411 | { |
| 412 | union |
| 413 | { |
| 414 | struct |
| 415 | { |
| 416 | unsigned int index; // For registers types |
| 417 | |
Nicolas Capens | 0530b45 | 2017-11-15 16:39:47 -0500 | [diff] [blame] | 418 | Relative rel; |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 419 | }; |
| 420 | |
| 421 | float value[4]; // For float constants |
| 422 | int integer[4]; // For integer constants |
| 423 | int boolean[4]; // For boolean constants |
| 424 | |
| 425 | struct |
| 426 | { |
| 427 | unsigned int label; // Label index |
| 428 | unsigned int callSite; // Call index (per label) |
| 429 | }; |
| 430 | }; |
| 431 | |
| 432 | Parameter() : index(0), type(PARAMETER_VOID) |
| 433 | { |
| 434 | rel.type = PARAMETER_VOID; |
| 435 | rel.index = 0; |
| 436 | rel.swizzle = 0; |
| 437 | rel.scale = 1; |
Nicolas Capens | 4b74373 | 2018-05-28 13:22:07 -0400 | [diff] [blame] | 438 | rel.dynamic = true; |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 439 | } |
| 440 | |
| 441 | std::string string(ShaderType shaderType, unsigned short version) const; |
| 442 | std::string typeString(ShaderType shaderType, unsigned short version) const; |
| 443 | std::string relativeString() const; |
| 444 | |
| 445 | ParameterType type : 8; |
| 446 | }; |
| 447 | |
| 448 | struct DestinationParameter : Parameter |
| 449 | { |
| 450 | union |
| 451 | { |
| 452 | unsigned char mask; |
| 453 | |
| 454 | struct |
| 455 | { |
| 456 | bool x : 1; |
| 457 | bool y : 1; |
| 458 | bool z : 1; |
| 459 | bool w : 1; |
| 460 | }; |
| 461 | }; |
| 462 | |
Nicolas Capens | 360a774 | 2017-11-15 13:35:47 -0500 | [diff] [blame] | 463 | DestinationParameter() : mask(0xF), saturate(false), partialPrecision(false), centroid(false), shift(0) |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 464 | { |
| 465 | } |
| 466 | |
| 467 | std::string modifierString() const; |
| 468 | std::string shiftString() const; |
| 469 | std::string maskString() const; |
| 470 | |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 471 | bool saturate : 1; |
| 472 | bool partialPrecision : 1; |
| 473 | bool centroid : 1; |
| 474 | signed char shift : 4; |
| 475 | }; |
| 476 | |
| 477 | struct SourceParameter : Parameter |
| 478 | { |
| 479 | SourceParameter() : swizzle(0xE4), modifier(MODIFIER_NONE), bufferIndex(-1) |
| 480 | { |
| 481 | } |
| 482 | |
Nicolas Capens | a4f0c89 | 2017-11-15 14:34:44 -0500 | [diff] [blame] | 483 | std::string string(ShaderType shaderType, unsigned short version) const; |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 484 | std::string swizzleString() const; |
| 485 | std::string preModifierString() const; |
| 486 | std::string postModifierString() const; |
| 487 | |
| 488 | unsigned int swizzle : 8; |
| 489 | Modifier modifier : 8; |
| 490 | int bufferIndex : 8; |
| 491 | }; |
| 492 | |
| 493 | struct Instruction |
| 494 | { |
| 495 | explicit Instruction(Opcode opcode); |
| 496 | Instruction(const unsigned long *token, int size, unsigned char majorVersion); |
| 497 | |
| 498 | virtual ~Instruction(); |
| 499 | |
| 500 | void parseOperationToken(unsigned long token, unsigned char majorVersion); |
| 501 | void parseDeclarationToken(unsigned long token); |
| 502 | void parseDestinationToken(const unsigned long *token, unsigned char majorVersion); |
| 503 | void parseSourceToken(int i, const unsigned long *token, unsigned char majorVersion); |
| 504 | |
| 505 | std::string string(ShaderType shaderType, unsigned short version) const; |
| 506 | static std::string swizzleString(ParameterType type, unsigned char swizzle); |
| 507 | std::string operationString(unsigned short version) const; |
| 508 | std::string controlString() const; |
| 509 | |
| 510 | bool isBranch() const; |
| 511 | bool isCall() const; |
| 512 | bool isBreak() const; |
Nicolas Capens | cd74a5a | 2016-04-22 14:58:52 -0400 | [diff] [blame] | 513 | bool isLoop() const; |
| 514 | bool isEndLoop() const; |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 515 | |
| 516 | bool isPredicated() const; |
| 517 | |
| 518 | Opcode opcode; |
| 519 | |
| 520 | union |
| 521 | { |
| 522 | Control control; |
| 523 | |
| 524 | struct |
| 525 | { |
Nicolas Capens | 6b91e70 | 2016-08-04 11:03:40 -0400 | [diff] [blame] | 526 | unsigned char project : 1; // D3DSI_TEXLD_PROJECT |
| 527 | unsigned char bias : 1; // D3DSI_TEXLD_BIAS |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 528 | }; |
| 529 | }; |
| 530 | |
| 531 | bool predicate; |
| 532 | bool predicateNot; // Negative predicate |
| 533 | unsigned char predicateSwizzle; |
| 534 | |
| 535 | bool coissue; |
| 536 | SamplerType samplerType; |
| 537 | Usage usage; |
| 538 | unsigned char usageIndex; |
| 539 | |
| 540 | DestinationParameter dst; |
| 541 | SourceParameter src[5]; |
| 542 | |
| 543 | union |
| 544 | { |
| 545 | unsigned int analysis; |
| 546 | |
| 547 | struct |
| 548 | { |
| 549 | // Keep in sync with Shader::Analysis flags |
| 550 | unsigned int analysisBranch : 1; |
| 551 | unsigned int analysisBreak : 1; |
| 552 | unsigned int analysisContinue : 1; |
| 553 | unsigned int analysisLeave : 1; |
| 554 | }; |
| 555 | }; |
| 556 | }; |
| 557 | |
Ben Clayton | d951f19 | 2019-02-11 20:59:19 +0000 | [diff] [blame] | 558 | // Limits holds the maximum nested counts for the shader. |
| 559 | struct Limits |
| 560 | { |
| 561 | uint32_t loops = 0; // maximum nested loop and reps. |
| 562 | uint32_t ifs = 0; // maximum nested if statements. |
| 563 | uint32_t stack = 0; // maximum call depth. |
Ben Clayton | 3f48ecb | 2019-02-21 11:05:27 +0000 | [diff] [blame] | 564 | uint32_t maxLabel = 0; // highest label in use. |
Ben Clayton | d951f19 | 2019-02-11 20:59:19 +0000 | [diff] [blame] | 565 | }; |
| 566 | |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 567 | Shader(); |
| 568 | |
| 569 | virtual ~Shader(); |
| 570 | |
| 571 | int getSerialID() const; |
| 572 | size_t getLength() const; |
| 573 | ShaderType getShaderType() const; |
Alexis Hetu | 53ad4af | 2017-12-06 14:49:07 -0500 | [diff] [blame] | 574 | unsigned short getShaderModel() const; |
Ben Clayton | d951f19 | 2019-02-11 20:59:19 +0000 | [diff] [blame] | 575 | inline const Limits& getLimits() const { return limits; } |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 576 | |
| 577 | void append(Instruction *instruction); |
| 578 | void declareSampler(int i); |
| 579 | |
Alexis Hetu | 1d67244 | 2016-06-23 11:24:00 -0400 | [diff] [blame] | 580 | const Instruction *getInstruction(size_t i) const; |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 581 | int size(unsigned long opcode) const; |
Alexis Hetu | 53ad4af | 2017-12-06 14:49:07 -0500 | [diff] [blame] | 582 | static int size(unsigned long opcode, unsigned short shaderModel); |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 583 | |
| 584 | void print(const char *fileName, ...) const; |
| 585 | void printInstruction(int index, const char *fileName) const; |
| 586 | |
| 587 | static bool maskContainsComponent(int mask, int component); |
| 588 | static bool swizzleContainsComponent(int swizzle, int component); |
| 589 | static bool swizzleContainsComponentMasked(int swizzle, int component, int mask); |
| 590 | |
| 591 | bool containsDynamicBranching() const; |
| 592 | bool containsBreakInstruction() const; |
| 593 | bool containsContinueInstruction() const; |
| 594 | bool containsLeaveInstruction() const; |
| 595 | bool containsDefineInstruction() const; |
| 596 | bool usesSampler(int i) const; |
| 597 | |
| 598 | struct Semantic |
| 599 | { |
Alexis Hetu | 12b0050 | 2016-05-20 13:01:11 -0400 | [diff] [blame] | 600 | Semantic(unsigned char usage = 0xFF, unsigned char index = 0xFF, bool flat = false) : usage(usage), index(index), centroid(false), flat(flat) |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 601 | { |
| 602 | } |
| 603 | |
| 604 | bool operator==(const Semantic &semantic) const |
| 605 | { |
| 606 | return usage == semantic.usage && index == semantic.index; |
| 607 | } |
| 608 | |
| 609 | bool active() const |
| 610 | { |
| 611 | return usage != 0xFF; |
| 612 | } |
| 613 | |
| 614 | unsigned char usage; |
| 615 | unsigned char index; |
| 616 | bool centroid; |
Alexis Hetu | 12b0050 | 2016-05-20 13:01:11 -0400 | [diff] [blame] | 617 | bool flat; |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 618 | }; |
| 619 | |
| 620 | void optimize(); |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 621 | |
| 622 | // FIXME: Private |
| 623 | unsigned int dirtyConstantsF; |
| 624 | unsigned int dirtyConstantsI; |
| 625 | unsigned int dirtyConstantsB; |
| 626 | |
Nicolas Capens | 5bff405 | 2018-05-28 13:18:59 -0400 | [diff] [blame] | 627 | bool indirectAddressableTemporaries; |
| 628 | bool indirectAddressableInput; |
| 629 | bool indirectAddressableOutput; |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 630 | |
| 631 | protected: |
| 632 | void parse(const unsigned long *token); |
| 633 | |
| 634 | void optimizeLeave(); |
| 635 | void optimizeCall(); |
| 636 | void removeNull(); |
| 637 | |
| 638 | void analyzeDirtyConstants(); |
| 639 | void analyzeDynamicBranching(); |
| 640 | void analyzeSamplers(); |
| 641 | void analyzeCallSites(); |
Nicolas Capens | 5bff405 | 2018-05-28 13:18:59 -0400 | [diff] [blame] | 642 | void analyzeIndirectAddressing(); |
Ben Clayton | d951f19 | 2019-02-11 20:59:19 +0000 | [diff] [blame] | 643 | void analyzeLimits(); |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 644 | void markFunctionAnalysis(unsigned int functionLabel, Analysis flag); |
| 645 | |
Ben Clayton | d951f19 | 2019-02-11 20:59:19 +0000 | [diff] [blame] | 646 | Limits limits; // Calculated in analyzeLimits(). |
| 647 | |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 648 | ShaderType shaderType; |
| 649 | |
| 650 | union |
| 651 | { |
Alexis Hetu | 53ad4af | 2017-12-06 14:49:07 -0500 | [diff] [blame] | 652 | unsigned short shaderModel; |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 653 | |
| 654 | struct |
| 655 | { |
| 656 | unsigned char minorVersion; |
| 657 | unsigned char majorVersion; |
| 658 | }; |
| 659 | }; |
| 660 | |
| 661 | std::vector<Instruction*> instruction; |
| 662 | |
| 663 | unsigned short usedSamplers; // Bit flags |
| 664 | |
| 665 | private: |
| 666 | const int serialID; |
| 667 | static volatile int serialCounter; |
| 668 | |
| 669 | bool dynamicBranching; |
| 670 | bool containsBreak; |
| 671 | bool containsContinue; |
| 672 | bool containsLeave; |
| 673 | bool containsDefine; |
| 674 | }; |
| 675 | } |
| 676 | |
| 677 | #endif // sw_Shader_hpp |