1# 2# Copyright (C) 2015 Intel Corporation 3# 4# Permission is hereby granted, free of charge, to any person obtaining a 5# copy of this software and associated documentation files (the "Software"), 6# to deal in the Software without restriction, including without limitation 7# the rights to use, copy, modify, merge, publish, distribute, sublicense, 8# and/or sell copies of the Software, and to permit persons to whom the 9# Software is furnished to do so, subject to the following conditions: 10# 11# The above copyright notice and this permission notice (including the next 12# paragraph) shall be included in all copies or substantial portions of the 13# Software. 14# 15# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21# IN THE SOFTWARE. 22 23import mako.template 24import sys 25 26class type(object): 27 def __init__(self, c_type, union_field, glsl_type): 28 self.c_type = c_type 29 self.union_field = union_field 30 self.glsl_type = glsl_type 31 32 33class type_signature_iter(object): 34 """Basic iterator for a set of type signatures. Various kinds of sequences of 35 types come in, and an iteration of type_signature objects come out. 36 37 """ 38 39 def __init__(self, source_types, num_operands): 40 """Initialize an iterator from a sequence of input types and a number 41 operands. This is for signatures where all the operands have the same 42 type and the result type of the operation is the same as the input type. 43 44 """ 45 self.dest_type = None 46 self.source_types = source_types 47 self.num_operands = num_operands 48 self.i = 0 49 50 def __init__(self, dest_type, source_types, num_operands): 51 """Initialize an iterator from a result tpye, a sequence of input types and a 52 number operands. This is for signatures where all the operands have the 53 same type but the result type of the operation is different from the 54 input type. 55 56 """ 57 self.dest_type = dest_type 58 self.source_types = source_types 59 self.num_operands = num_operands 60 self.i = 0 61 62 def __iter__(self): 63 return self 64 65 def __next__(self): 66 if self.i < len(self.source_types): 67 i = self.i 68 self.i += 1 69 70 if self.dest_type is None: 71 dest_type = self.source_types[i] 72 else: 73 dest_type = self.dest_type 74 75 return (dest_type, self.num_operands * (self.source_types[i],)) 76 else: 77 raise StopIteration() 78 79 next = __next__ 80 81 82uint_type = type("unsigned", "u", "GLSL_TYPE_UINT") 83int_type = type("int", "i", "GLSL_TYPE_INT") 84uint64_type = type("uint64_t", "u64", "GLSL_TYPE_UINT64") 85int64_type = type("int64_t", "i64", "GLSL_TYPE_INT64") 86float_type = type("float", "f", "GLSL_TYPE_FLOAT") 87double_type = type("double", "d", "GLSL_TYPE_DOUBLE") 88bool_type = type("bool", "b", "GLSL_TYPE_BOOL") 89 90all_types = (uint_type, int_type, float_type, double_type, uint64_type, int64_type, bool_type) 91numeric_types = (uint_type, int_type, float_type, double_type, uint64_type, int64_type) 92signed_numeric_types = (int_type, float_type, double_type, int64_type) 93integer_types = (uint_type, int_type, uint64_type, int64_type) 94real_types = (float_type, double_type) 95 96# This template is for operations that can have operands of a several 97# different types, and each type may or may not has a different C expression. 98# This is used by most operations. 99constant_template_common = mako.template.Template("""\ 100 case ${op.get_enum_name()}: 101 for (unsigned c = 0; c < op[0]->type->components(); c++) { 102 switch (op[0]->type->base_type) { 103 % for dst_type, src_types in op.signatures(): 104 case ${src_types[0].glsl_type}: 105 data.${dst_type.union_field}[c] = ${op.get_c_expression(src_types)}; 106 break; 107 % endfor 108 default: 109 unreachable("invalid type"); 110 } 111 } 112 break;""") 113 114# This template is for binary operations that can operate on some combination 115# of scalar and vector operands. 116constant_template_vector_scalar = mako.template.Template("""\ 117 case ${op.get_enum_name()}: 118 % if "mixed" in op.flags: 119 % for i in range(op.num_operands): 120 assert(op[${i}]->type->base_type == ${op.source_types[0].glsl_type} || 121 % for src_type in op.source_types[1:-1]: 122 op[${i}]->type->base_type == ${src_type.glsl_type} || 123 % endfor 124 op[${i}]->type->base_type == ${op.source_types[-1].glsl_type}); 125 % endfor 126 % else: 127 assert(op[0]->type == op[1]->type || op0_scalar || op1_scalar); 128 % endif 129 for (unsigned c = 0, c0 = 0, c1 = 0; 130 c < components; 131 c0 += c0_inc, c1 += c1_inc, c++) { 132 133 switch (op[0]->type->base_type) { 134 % for dst_type, src_types in op.signatures(): 135 case ${src_types[0].glsl_type}: 136 data.${dst_type.union_field}[c] = ${op.get_c_expression(src_types, ("c0", "c1", "c2"))}; 137 break; 138 % endfor 139 default: 140 unreachable("invalid type"); 141 } 142 } 143 break;""") 144 145# This template is for multiplication. It is unique because it has to support 146# matrix * vector and matrix * matrix operations, and those are just different. 147constant_template_mul = mako.template.Template("""\ 148 case ${op.get_enum_name()}: 149 /* Check for equal types, or unequal types involving scalars */ 150 if ((op[0]->type == op[1]->type && !op[0]->type->is_matrix()) 151 || op0_scalar || op1_scalar) { 152 for (unsigned c = 0, c0 = 0, c1 = 0; 153 c < components; 154 c0 += c0_inc, c1 += c1_inc, c++) { 155 156 switch (op[0]->type->base_type) { 157 % for dst_type, src_types in op.signatures(): 158 case ${src_types[0].glsl_type}: 159 data.${dst_type.union_field}[c] = ${op.get_c_expression(src_types, ("c0", "c1", "c2"))}; 160 break; 161 % endfor 162 default: 163 unreachable("invalid type"); 164 } 165 } 166 } else { 167 assert(op[0]->type->is_matrix() || op[1]->type->is_matrix()); 168 169 /* Multiply an N-by-M matrix with an M-by-P matrix. Since either 170 * matrix can be a GLSL vector, either N or P can be 1. 171 * 172 * For vec*mat, the vector is treated as a row vector. This 173 * means the vector is a 1-row x M-column matrix. 174 * 175 * For mat*vec, the vector is treated as a column vector. Since 176 * matrix_columns is 1 for vectors, this just works. 177 */ 178 const unsigned n = op[0]->type->is_vector() 179 ? 1 : op[0]->type->vector_elements; 180 const unsigned m = op[1]->type->vector_elements; 181 const unsigned p = op[1]->type->matrix_columns; 182 for (unsigned j = 0; j < p; j++) { 183 for (unsigned i = 0; i < n; i++) { 184 for (unsigned k = 0; k < m; k++) { 185 if (op[0]->type->is_double()) 186 data.d[i+n*j] += op[0]->value.d[i+n*k]*op[1]->value.d[k+m*j]; 187 else 188 data.f[i+n*j] += op[0]->value.f[i+n*k]*op[1]->value.f[k+m*j]; 189 } 190 } 191 } 192 } 193 break;""") 194 195# This template is for operations that are horizontal and either have only a 196# single type or the implementation for all types is identical. That is, the 197# operation consumes a vector and produces a scalar. 198constant_template_horizontal_single_implementation = mako.template.Template("""\ 199 case ${op.get_enum_name()}: 200 data.${op.dest_type.union_field}[0] = ${op.c_expression['default']}; 201 break;""") 202 203# This template is for operations that are horizontal and do not assign the 204# result. The various unpack operations are examples. 205constant_template_horizontal_nonassignment = mako.template.Template("""\ 206 case ${op.get_enum_name()}: 207 ${op.c_expression['default']}; 208 break;""") 209 210# This template is for binary operations that are horizontal. That is, the 211# operation consumes a vector and produces a scalar. 212constant_template_horizontal = mako.template.Template("""\ 213 case ${op.get_enum_name()}: 214 switch (op[0]->type->base_type) { 215 % for dst_type, src_types in op.signatures(): 216 case ${src_types[0].glsl_type}: 217 data.${dst_type.union_field}[0] = ${op.get_c_expression(src_types)}; 218 break; 219 % endfor 220 default: 221 unreachable("invalid type"); 222 } 223 break;""") 224 225# This template is for ir_binop_vector_extract. 226constant_template_vector_extract = mako.template.Template("""\ 227 case ${op.get_enum_name()}: { 228 const int c = CLAMP(op[1]->value.i[0], 0, 229 (int) op[0]->type->vector_elements - 1); 230 231 switch (op[0]->type->base_type) { 232 % for dst_type, src_types in op.signatures(): 233 case ${src_types[0].glsl_type}: 234 data.${dst_type.union_field}[0] = op[0]->value.${src_types[0].union_field}[c]; 235 break; 236 % endfor 237 default: 238 unreachable("invalid type"); 239 } 240 break; 241 }""") 242 243# This template is for ir_triop_vector_insert. 244constant_template_vector_insert = mako.template.Template("""\ 245 case ${op.get_enum_name()}: { 246 const unsigned idx = op[2]->value.u[0]; 247 248 memcpy(&data, &op[0]->value, sizeof(data)); 249 250 switch (return_type->base_type) { 251 % for dst_type, src_types in op.signatures(): 252 case ${src_types[0].glsl_type}: 253 data.${dst_type.union_field}[idx] = op[1]->value.${src_types[0].union_field}[0]; 254 break; 255 % endfor 256 default: 257 unreachable("invalid type"); 258 } 259 break; 260 }""") 261 262# This template is for ir_quadop_vector. 263constant_template_vector = mako.template.Template("""\ 264 case ${op.get_enum_name()}: 265 for (unsigned c = 0; c < return_type->vector_elements; c++) { 266 switch (return_type->base_type) { 267 % for dst_type, src_types in op.signatures(): 268 case ${src_types[0].glsl_type}: 269 data.${dst_type.union_field}[c] = op[c]->value.${src_types[0].union_field}[0]; 270 break; 271 % endfor 272 default: 273 unreachable("invalid type"); 274 } 275 } 276 break;""") 277 278# This template is for ir_triop_lrp. 279constant_template_lrp = mako.template.Template("""\ 280 case ${op.get_enum_name()}: { 281 assert(op[0]->type->is_float() || op[0]->type->is_double()); 282 assert(op[1]->type->is_float() || op[1]->type->is_double()); 283 assert(op[2]->type->is_float() || op[2]->type->is_double()); 284 285 unsigned c2_inc = op[2]->type->is_scalar() ? 0 : 1; 286 for (unsigned c = 0, c2 = 0; c < components; c2 += c2_inc, c++) { 287 switch (return_type->base_type) { 288 % for dst_type, src_types in op.signatures(): 289 case ${src_types[0].glsl_type}: 290 data.${dst_type.union_field}[c] = ${op.get_c_expression(src_types, ("c", "c", "c2"))}; 291 break; 292 % endfor 293 default: 294 unreachable("invalid type"); 295 } 296 } 297 break; 298 }""") 299 300# This template is for ir_triop_csel. This expression is really unique 301# because not all of the operands are the same type, and the second operand 302# determines the type of the expression (instead of the first). 303constant_template_csel = mako.template.Template("""\ 304 case ${op.get_enum_name()}: 305 for (unsigned c = 0; c < components; c++) { 306 switch (return_type->base_type) { 307 % for dst_type, src_types in op.signatures(): 308 case ${src_types[1].glsl_type}: 309 data.${dst_type.union_field}[c] = ${op.get_c_expression(src_types)}; 310 break; 311 % endfor 312 default: 313 unreachable("invalid type"); 314 } 315 } 316 break;""") 317 318 319vector_scalar_operation = "vector-scalar" 320horizontal_operation = "horizontal" 321types_identical_operation = "identical" 322non_assign_operation = "nonassign" 323mixed_type_operation = "mixed" 324 325class operation(object): 326 def __init__(self, name, num_operands, printable_name = None, source_types = None, dest_type = None, c_expression = None, flags = None, all_signatures = None): 327 self.name = name 328 self.num_operands = num_operands 329 330 if printable_name is None: 331 self.printable_name = name 332 else: 333 self.printable_name = printable_name 334 335 self.all_signatures = all_signatures 336 337 if source_types is None: 338 self.source_types = tuple() 339 else: 340 self.source_types = source_types 341 342 self.dest_type = dest_type 343 344 if c_expression is None: 345 self.c_expression = None 346 elif isinstance(c_expression, str): 347 self.c_expression = {'default': c_expression} 348 else: 349 self.c_expression = c_expression 350 351 if flags is None: 352 self.flags = frozenset() 353 elif isinstance(flags, str): 354 self.flags = frozenset([flags]) 355 else: 356 self.flags = frozenset(flags) 357 358 359 def get_enum_name(self): 360 return "ir_{0}op_{1}".format(("un", "bin", "tri", "quad")[self.num_operands-1], self.name) 361 362 363 def get_template(self): 364 if self.c_expression is None: 365 return None 366 367 if horizontal_operation in self.flags: 368 if non_assign_operation in self.flags: 369 return constant_template_horizontal_nonassignment.render(op=self) 370 elif types_identical_operation in self.flags: 371 return constant_template_horizontal_single_implementation.render(op=self) 372 else: 373 return constant_template_horizontal.render(op=self) 374 375 if self.num_operands == 2: 376 if self.name == "mul": 377 return constant_template_mul.render(op=self) 378 elif self.name == "vector_extract": 379 return constant_template_vector_extract.render(op=self) 380 elif vector_scalar_operation in self.flags: 381 return constant_template_vector_scalar.render(op=self) 382 elif self.num_operands == 3: 383 if self.name == "vector_insert": 384 return constant_template_vector_insert.render(op=self) 385 elif self.name == "lrp": 386 return constant_template_lrp.render(op=self) 387 elif self.name == "csel": 388 return constant_template_csel.render(op=self) 389 elif self.num_operands == 4: 390 if self.name == "vector": 391 return constant_template_vector.render(op=self) 392 393 return constant_template_common.render(op=self) 394 395 396 def get_c_expression(self, types, indices=("c", "c", "c")): 397 src0 = "op[0]->value.{0}[{1}]".format(types[0].union_field, indices[0]) 398 src1 = "op[1]->value.{0}[{1}]".format(types[1].union_field, indices[1]) if len(types) >= 2 else "ERROR" 399 src2 = "op[2]->value.{0}[{1}]".format(types[2].union_field, indices[2]) if len(types) >= 3 else "ERROR" 400 src3 = "op[3]->value.{0}[c]".format(types[3].union_field) if len(types) >= 4 else "ERROR" 401 402 expr = self.c_expression[types[0].union_field] if types[0].union_field in self.c_expression else self.c_expression['default'] 403 404 return expr.format(src0=src0, 405 src1=src1, 406 src2=src2, 407 src3=src3) 408 409 410 def signatures(self): 411 if self.all_signatures is not None: 412 return self.all_signatures 413 else: 414 return type_signature_iter(self.dest_type, self.source_types, self.num_operands) 415 416 417ir_expression_operation = [ 418 operation("bit_not", 1, printable_name="~", source_types=integer_types, c_expression="~ {src0}"), 419 operation("logic_not", 1, printable_name="!", source_types=(bool_type,), c_expression="!{src0}"), 420 operation("neg", 1, source_types=numeric_types, c_expression={'u': "-((int) {src0})", 'u64': "-((int64_t) {src0})", 'default': "-{src0}"}), 421 operation("abs", 1, source_types=signed_numeric_types, c_expression={'i': "{src0} < 0 ? -{src0} : {src0}", 'f': "fabsf({src0})", 'd': "fabs({src0})", 'i64': "{src0} < 0 ? -{src0} : {src0}"}), 422 operation("sign", 1, source_types=signed_numeric_types, c_expression={'i': "({src0} > 0) - ({src0} < 0)", 'f': "float(({src0} > 0.0F) - ({src0} < 0.0F))", 'd': "double(({src0} > 0.0) - ({src0} < 0.0))", 'i64': "({src0} > 0) - ({src0} < 0)"}), 423 operation("rcp", 1, source_types=real_types, c_expression={'f': "1.0F / {src0}", 'd': "1.0 / {src0}"}), 424 operation("rsq", 1, source_types=real_types, c_expression={'f': "1.0F / sqrtf({src0})", 'd': "1.0 / sqrt({src0})"}), 425 operation("sqrt", 1, source_types=real_types, c_expression={'f': "sqrtf({src0})", 'd': "sqrt({src0})"}), 426 operation("exp", 1, source_types=(float_type,), c_expression="expf({src0})"), # Log base e on gentype 427 operation("log", 1, source_types=(float_type,), c_expression="logf({src0})"), # Natural log on gentype 428 operation("exp2", 1, source_types=(float_type,), c_expression="exp2f({src0})"), 429 operation("log2", 1, source_types=(float_type,), c_expression="log2f({src0})"), 430 431 # Float-to-integer conversion. 432 operation("f2i", 1, source_types=(float_type,), dest_type=int_type, c_expression="(int) {src0}"), 433 # Float-to-unsigned conversion. 434 operation("f2u", 1, source_types=(float_type,), dest_type=uint_type, c_expression="(unsigned) {src0}"), 435 # Integer-to-float conversion. 436 operation("i2f", 1, source_types=(int_type,), dest_type=float_type, c_expression="(float) {src0}"), 437 # Float-to-boolean conversion 438 operation("f2b", 1, source_types=(float_type,), dest_type=bool_type, c_expression="{src0} != 0.0F ? true : false"), 439 # Boolean-to-float conversion 440 operation("b2f", 1, source_types=(bool_type,), dest_type=float_type, c_expression="{src0} ? 1.0F : 0.0F"), 441 # Boolean-to-float16 conversion 442 operation("b2f16", 1, source_types=(bool_type,), dest_type=float_type, c_expression="{src0} ? 1.0F : 0.0F"), 443 # int-to-boolean conversion 444 operation("i2b", 1, source_types=(uint_type, int_type), dest_type=bool_type, c_expression="{src0} ? true : false"), 445 # Boolean-to-int conversion 446 operation("b2i", 1, source_types=(bool_type,), dest_type=int_type, c_expression="{src0} ? 1 : 0"), 447 # Unsigned-to-float conversion. 448 operation("u2f", 1, source_types=(uint_type,), dest_type=float_type, c_expression="(float) {src0}"), 449 # Integer-to-unsigned conversion. 450 operation("i2u", 1, source_types=(int_type,), dest_type=uint_type, c_expression="{src0}"), 451 # Unsigned-to-integer conversion. 452 operation("u2i", 1, source_types=(uint_type,), dest_type=int_type, c_expression="{src0}"), 453 # Double-to-float conversion. 454 operation("d2f", 1, source_types=(double_type,), dest_type=float_type, c_expression="{src0}"), 455 # Float-to-double conversion. 456 operation("f2d", 1, source_types=(float_type,), dest_type=double_type, c_expression="{src0}"), 457 # Half-float conversions. These all operate on and return float types, 458 # since the framework expands half to full float before calling in. We 459 # still have to handle them here so that we can constant propagate through 460 # them, but they are no-ops. 461 operation("f2f16", 1, source_types=(float_type,), dest_type=float_type, c_expression="{src0}"), 462 operation("f2fmp", 1, source_types=(float_type,), dest_type=float_type, c_expression="{src0}"), 463 operation("f162f", 1, source_types=(float_type,), dest_type=float_type, c_expression="{src0}"), 464 # int16<->int32 conversion. 465 operation("i2i", 1, source_types=(int_type,), dest_type=int_type, c_expression="{src0}"), 466 operation("i2imp", 1, source_types=(int_type,), dest_type=int_type, c_expression="{src0}"), 467 operation("u2u", 1, source_types=(uint_type,), dest_type=uint_type, c_expression="{src0}"), 468 operation("u2ump", 1, source_types=(uint_type,), dest_type=uint_type, c_expression="{src0}"), 469 # Double-to-integer conversion. 470 operation("d2i", 1, source_types=(double_type,), dest_type=int_type, c_expression="{src0}"), 471 # Integer-to-double conversion. 472 operation("i2d", 1, source_types=(int_type,), dest_type=double_type, c_expression="{src0}"), 473 # Double-to-unsigned conversion. 474 operation("d2u", 1, source_types=(double_type,), dest_type=uint_type, c_expression="{src0}"), 475 # Unsigned-to-double conversion. 476 operation("u2d", 1, source_types=(uint_type,), dest_type=double_type, c_expression="{src0}"), 477 # Double-to-boolean conversion. 478 operation("d2b", 1, source_types=(double_type,), dest_type=bool_type, c_expression="{src0} != 0.0"), 479 # Float16-to-boolean conversion. 480 operation("f162b", 1, source_types=(float_type,), dest_type=bool_type, c_expression="{src0} != 0.0"), 481 # 'Bit-identical int-to-float "conversion" 482 operation("bitcast_i2f", 1, source_types=(int_type,), dest_type=float_type, c_expression="bitcast_u2f({src0})"), 483 # 'Bit-identical float-to-int "conversion" 484 operation("bitcast_f2i", 1, source_types=(float_type,), dest_type=int_type, c_expression="bitcast_f2u({src0})"), 485 # 'Bit-identical uint-to-float "conversion" 486 operation("bitcast_u2f", 1, source_types=(uint_type,), dest_type=float_type, c_expression="bitcast_u2f({src0})"), 487 # 'Bit-identical float-to-uint "conversion" 488 operation("bitcast_f2u", 1, source_types=(float_type,), dest_type=uint_type, c_expression="bitcast_f2u({src0})"), 489 # Bit-identical u64-to-double "conversion" 490 operation("bitcast_u642d", 1, source_types=(uint64_type,), dest_type=double_type, c_expression="bitcast_u642d({src0})"), 491 # Bit-identical i64-to-double "conversion" 492 operation("bitcast_i642d", 1, source_types=(int64_type,), dest_type=double_type, c_expression="bitcast_i642d({src0})"), 493 # Bit-identical double-to_u64 "conversion" 494 operation("bitcast_d2u64", 1, source_types=(double_type,), dest_type=uint64_type, c_expression="bitcast_d2u64({src0})"), 495 # Bit-identical double-to-i64 "conversion" 496 operation("bitcast_d2i64", 1, source_types=(double_type,), dest_type=int64_type, c_expression="bitcast_d2i64({src0})"), 497 # i64-to-i32 conversion 498 operation("i642i", 1, source_types=(int64_type,), dest_type=int_type, c_expression="{src0}"), 499 # ui64-to-i32 conversion 500 operation("u642i", 1, source_types=(uint64_type,), dest_type=int_type, c_expression="{src0}"), 501 operation("i642u", 1, source_types=(int64_type,), dest_type=uint_type, c_expression="{src0}"), 502 operation("u642u", 1, source_types=(uint64_type,), dest_type=uint_type, c_expression="{src0}"), 503 operation("i642b", 1, source_types=(int64_type,), dest_type=bool_type, c_expression="{src0} != 0"), 504 operation("i642f", 1, source_types=(int64_type,), dest_type=float_type, c_expression="{src0}"), 505 operation("u642f", 1, source_types=(uint64_type,), dest_type=float_type, c_expression="{src0}"), 506 operation("i642d", 1, source_types=(int64_type,), dest_type=double_type, c_expression="{src0}"), 507 operation("u642d", 1, source_types=(uint64_type,), dest_type=double_type, c_expression="{src0}"), 508 operation("i2i64", 1, source_types=(int_type,), dest_type=int64_type, c_expression="{src0}"), 509 operation("u2i64", 1, source_types=(uint_type,), dest_type=int64_type, c_expression="{src0}"), 510 operation("b2i64", 1, source_types=(bool_type,), dest_type=int64_type, c_expression="{src0}"), 511 operation("f2i64", 1, source_types=(float_type,), dest_type=int64_type, c_expression="{src0}"), 512 operation("d2i64", 1, source_types=(double_type,), dest_type=int64_type, c_expression="{src0}"), 513 operation("i2u64", 1, source_types=(int_type,), dest_type=uint64_type, c_expression="{src0}"), 514 operation("u2u64", 1, source_types=(uint_type,), dest_type=uint64_type, c_expression="{src0}"), 515 operation("f2u64", 1, source_types=(float_type,), dest_type=uint64_type, c_expression="{src0}"), 516 operation("d2u64", 1, source_types=(double_type,), dest_type=uint64_type, c_expression="{src0}"), 517 operation("u642i64", 1, source_types=(uint64_type,), dest_type=int64_type, c_expression="{src0}"), 518 operation("i642u64", 1, source_types=(int64_type,), dest_type=uint64_type, c_expression="{src0}"), 519 520 521 # Unary floating-point rounding operations. 522 operation("trunc", 1, source_types=real_types, c_expression={'f': "truncf({src0})", 'd': "trunc({src0})"}), 523 operation("ceil", 1, source_types=real_types, c_expression={'f': "ceilf({src0})", 'd': "ceil({src0})"}), 524 operation("floor", 1, source_types=real_types, c_expression={'f': "floorf({src0})", 'd': "floor({src0})"}), 525 operation("fract", 1, source_types=real_types, c_expression={'f': "{src0} - floorf({src0})", 'd': "{src0} - floor({src0})"}), 526 operation("round_even", 1, source_types=real_types, c_expression={'f': "_mesa_roundevenf({src0})", 'd': "_mesa_roundeven({src0})"}), 527 528 # Trigonometric operations. 529 operation("sin", 1, source_types=(float_type,), c_expression="sinf({src0})"), 530 operation("cos", 1, source_types=(float_type,), c_expression="cosf({src0})"), 531 operation("atan", 1, source_types=(float_type,), c_expression="atan({src0})"), 532 533 # Partial derivatives. 534 operation("dFdx", 1, source_types=(float_type,), c_expression="0.0f"), 535 operation("dFdx_coarse", 1, printable_name="dFdxCoarse", source_types=(float_type,), c_expression="0.0f"), 536 operation("dFdx_fine", 1, printable_name="dFdxFine", source_types=(float_type,), c_expression="0.0f"), 537 operation("dFdy", 1, source_types=(float_type,), c_expression="0.0f"), 538 operation("dFdy_coarse", 1, printable_name="dFdyCoarse", source_types=(float_type,), c_expression="0.0f"), 539 operation("dFdy_fine", 1, printable_name="dFdyFine", source_types=(float_type,), c_expression="0.0f"), 540 541 # Floating point pack and unpack operations. 542 operation("pack_snorm_2x16", 1, printable_name="packSnorm2x16", source_types=(float_type,), dest_type=uint_type, c_expression="pack_2x16(pack_snorm_1x16, op[0]->value.f[0], op[0]->value.f[1])", flags=horizontal_operation), 543 operation("pack_snorm_4x8", 1, printable_name="packSnorm4x8", source_types=(float_type,), dest_type=uint_type, c_expression="pack_4x8(pack_snorm_1x8, op[0]->value.f[0], op[0]->value.f[1], op[0]->value.f[2], op[0]->value.f[3])", flags=horizontal_operation), 544 operation("pack_unorm_2x16", 1, printable_name="packUnorm2x16", source_types=(float_type,), dest_type=uint_type, c_expression="pack_2x16(pack_unorm_1x16, op[0]->value.f[0], op[0]->value.f[1])", flags=horizontal_operation), 545 operation("pack_unorm_4x8", 1, printable_name="packUnorm4x8", source_types=(float_type,), dest_type=uint_type, c_expression="pack_4x8(pack_unorm_1x8, op[0]->value.f[0], op[0]->value.f[1], op[0]->value.f[2], op[0]->value.f[3])", flags=horizontal_operation), 546 operation("pack_half_2x16", 1, printable_name="packHalf2x16", source_types=(float_type,), dest_type=uint_type, c_expression="pack_2x16(pack_half_1x16, op[0]->value.f[0], op[0]->value.f[1])", flags=horizontal_operation), 547 operation("unpack_snorm_2x16", 1, printable_name="unpackSnorm2x16", source_types=(uint_type,), dest_type=float_type, c_expression="unpack_2x16(unpack_snorm_1x16, op[0]->value.u[0], &data.f[0], &data.f[1])", flags=frozenset((horizontal_operation, non_assign_operation))), 548 operation("unpack_snorm_4x8", 1, printable_name="unpackSnorm4x8", source_types=(uint_type,), dest_type=float_type, c_expression="unpack_4x8(unpack_snorm_1x8, op[0]->value.u[0], &data.f[0], &data.f[1], &data.f[2], &data.f[3])", flags=frozenset((horizontal_operation, non_assign_operation))), 549 operation("unpack_unorm_2x16", 1, printable_name="unpackUnorm2x16", source_types=(uint_type,), dest_type=float_type, c_expression="unpack_2x16(unpack_unorm_1x16, op[0]->value.u[0], &data.f[0], &data.f[1])", flags=frozenset((horizontal_operation, non_assign_operation))), 550 operation("unpack_unorm_4x8", 1, printable_name="unpackUnorm4x8", source_types=(uint_type,), dest_type=float_type, c_expression="unpack_4x8(unpack_unorm_1x8, op[0]->value.u[0], &data.f[0], &data.f[1], &data.f[2], &data.f[3])", flags=frozenset((horizontal_operation, non_assign_operation))), 551 operation("unpack_half_2x16", 1, printable_name="unpackHalf2x16", source_types=(uint_type,), dest_type=float_type, c_expression="unpack_2x16(unpack_half_1x16, op[0]->value.u[0], &data.f[0], &data.f[1])", flags=frozenset((horizontal_operation, non_assign_operation))), 552 553 # Bit operations, part of ARB_gpu_shader5. 554 operation("bitfield_reverse", 1, source_types=(uint_type, int_type), c_expression="bitfield_reverse({src0})"), 555 operation("bit_count", 1, source_types=(uint_type, int_type), dest_type=int_type, c_expression="util_bitcount({src0})"), 556 operation("find_msb", 1, source_types=(uint_type, int_type), dest_type=int_type, c_expression={'u': "find_msb_uint({src0})", 'i': "find_msb_int({src0})"}), 557 operation("find_lsb", 1, source_types=(uint_type, int_type), dest_type=int_type, c_expression="find_msb_uint({src0} & -{src0})"), 558 operation("clz", 1, source_types=(uint_type,), dest_type=uint_type, c_expression="(unsigned)(31 - find_msb_uint({src0}))"), 559 560 operation("saturate", 1, printable_name="sat", source_types=(float_type,), c_expression="CLAMP({src0}, 0.0f, 1.0f)"), 561 562 # Double packing, part of ARB_gpu_shader_fp64. 563 operation("pack_double_2x32", 1, printable_name="packDouble2x32", source_types=(uint_type,), dest_type=double_type, c_expression="data.u64[0] = pack_2x32(op[0]->value.u[0], op[0]->value.u[1])", flags=frozenset((horizontal_operation, non_assign_operation))), 564 operation("unpack_double_2x32", 1, printable_name="unpackDouble2x32", source_types=(double_type,), dest_type=uint_type, c_expression="unpack_2x32(op[0]->value.u64[0], &data.u[0], &data.u[1])", flags=frozenset((horizontal_operation, non_assign_operation))), 565 566 # Sampler/Image packing, part of ARB_bindless_texture. 567 operation("pack_sampler_2x32", 1, printable_name="packSampler2x32", source_types=(uint_type,), dest_type=uint64_type, c_expression="data.u64[0] = pack_2x32(op[0]->value.u[0], op[0]->value.u[1])", flags=frozenset((horizontal_operation, non_assign_operation))), 568 operation("pack_image_2x32", 1, printable_name="packImage2x32", source_types=(uint_type,), dest_type=uint64_type, c_expression="data.u64[0] = pack_2x32(op[0]->value.u[0], op[0]->value.u[1])", flags=frozenset((horizontal_operation, non_assign_operation))), 569 operation("unpack_sampler_2x32", 1, printable_name="unpackSampler2x32", source_types=(uint64_type,), dest_type=uint_type, c_expression="unpack_2x32(op[0]->value.u64[0], &data.u[0], &data.u[1])", flags=frozenset((horizontal_operation, non_assign_operation))), 570 operation("unpack_image_2x32", 1, printable_name="unpackImage2x32", source_types=(uint64_type,), dest_type=uint_type, c_expression="unpack_2x32(op[0]->value.u64[0], &data.u[0], &data.u[1])", flags=frozenset((horizontal_operation, non_assign_operation))), 571 572 operation("frexp_sig", 1), 573 operation("frexp_exp", 1), 574 575 operation("subroutine_to_int", 1), 576 577 # Interpolate fs input at centroid 578 # 579 # operand0 is the fs input. 580 operation("interpolate_at_centroid", 1), 581 582 # Ask the driver for the total size of a buffer block. 583 # operand0 is the ir_constant buffer block index in the linked shader. 584 operation("get_buffer_size", 1), 585 586 # Calculate length of an unsized array inside a buffer block. 587 # This opcode is going to be replaced in a lowering pass inside 588 # the linker. 589 # 590 # operand0 is the unsized array's ir_value for the calculation 591 # of its length. 592 operation("ssbo_unsized_array_length", 1), 593 594 # Calculate length of an implicitly sized array. 595 # This opcode is going to be replaced with a constant expression at link 596 # time. 597 operation("implicitly_sized_array_length", 1), 598 599 # 64-bit integer packing ops. 600 operation("pack_int_2x32", 1, printable_name="packInt2x32", source_types=(int_type,), dest_type=int64_type, c_expression="data.u64[0] = pack_2x32(op[0]->value.u[0], op[0]->value.u[1])", flags=frozenset((horizontal_operation, non_assign_operation))), 601 operation("pack_uint_2x32", 1, printable_name="packUint2x32", source_types=(uint_type,), dest_type=uint64_type, c_expression="data.u64[0] = pack_2x32(op[0]->value.u[0], op[0]->value.u[1])", flags=frozenset((horizontal_operation, non_assign_operation))), 602 operation("unpack_int_2x32", 1, printable_name="unpackInt2x32", source_types=(int64_type,), dest_type=int_type, c_expression="unpack_2x32(op[0]->value.u64[0], &data.u[0], &data.u[1])", flags=frozenset((horizontal_operation, non_assign_operation))), 603 operation("unpack_uint_2x32", 1, printable_name="unpackUint2x32", source_types=(uint64_type,), dest_type=uint_type, c_expression="unpack_2x32(op[0]->value.u64[0], &data.u[0], &data.u[1])", flags=frozenset((horizontal_operation, non_assign_operation))), 604 605 operation("add", 2, printable_name="+", source_types=numeric_types, c_expression="{src0} + {src1}", flags=vector_scalar_operation), 606 operation("sub", 2, printable_name="-", source_types=numeric_types, c_expression="{src0} - {src1}", flags=vector_scalar_operation), 607 operation("add_sat", 2, printable_name="add_sat", source_types=integer_types, c_expression={ 608 'u': "({src0} + {src1}) < {src0} ? UINT32_MAX : ({src0} + {src1})", 609 'i': "iadd_saturate({src0}, {src1})", 610 'u64': "({src0} + {src1}) < {src0} ? UINT64_MAX : ({src0} + {src1})", 611 'i64': "iadd64_saturate({src0}, {src1})" 612 }), 613 operation("sub_sat", 2, printable_name="sub_sat", source_types=integer_types, c_expression={ 614 'u': "({src1} > {src0}) ? 0 : {src0} - {src1}", 615 'i': "isub_saturate({src0}, {src1})", 616 'u64': "({src1} > {src0}) ? 0 : {src0} - {src1}", 617 'i64': "isub64_saturate({src0}, {src1})" 618 }), 619 operation("abs_sub", 2, printable_name="abs_sub", source_types=integer_types, c_expression={ 620 'u': "({src1} > {src0}) ? {src1} - {src0} : {src0} - {src1}", 621 'i': "({src1} > {src0}) ? (unsigned){src1} - (unsigned){src0} : (unsigned){src0} - (unsigned){src1}", 622 'u64': "({src1} > {src0}) ? {src1} - {src0} : {src0} - {src1}", 623 'i64': "({src1} > {src0}) ? (uint64_t){src1} - (uint64_t){src0} : (uint64_t){src0} - (uint64_t){src1}", 624 }), 625 operation("avg", 2, printable_name="average", source_types=integer_types, c_expression="({src0} >> 1) + ({src1} >> 1) + (({src0} & {src1}) & 1)"), 626 operation("avg_round", 2, printable_name="average_rounded", source_types=integer_types, c_expression="({src0} >> 1) + ({src1} >> 1) + (({src0} | {src1}) & 1)"), 627 628 # "Floating-point or low 32-bit integer multiply." 629 operation("mul", 2, printable_name="*", source_types=numeric_types, c_expression="{src0} * {src1}"), 630 operation("mul_32x16", 2, printable_name="*", source_types=(uint_type, int_type), c_expression={ 631 'u': "{src0} * (uint16_t){src1}", 632 'i': "{src0} * (int16_t){src0}" 633 }), 634 operation("imul_high", 2), # Calculates the high 32-bits of a 64-bit multiply. 635 operation("div", 2, printable_name="/", source_types=numeric_types, c_expression={'u': "{src1} == 0 ? 0 : {src0} / {src1}", 'i': "{src1} == 0 ? 0 : {src0} / {src1}", 'u64': "{src1} == 0 ? 0 : {src0} / {src1}", 'i64': "{src1} == 0 ? 0 : {src0} / {src1}", 'default': "{src0} / {src1}"}, flags=vector_scalar_operation), 636 637 # Returns the carry resulting from the addition of the two arguments. 638 operation("carry", 2), 639 640 # Returns the borrow resulting from the subtraction of the second argument 641 # from the first argument. 642 operation("borrow", 2), 643 644 # Either (vector % vector) or (vector % scalar) 645 # 646 # We don't use fmod because it rounds toward zero; GLSL specifies the use 647 # of floor. 648 operation("mod", 2, printable_name="%", source_types=numeric_types, c_expression={'u': "{src1} == 0 ? 0 : {src0} % {src1}", 'i': "{src1} == 0 ? 0 : {src0} % {src1}", 'f': "{src0} - {src1} * floorf({src0} / {src1})", 'd': "{src0} - {src1} * floor({src0} / {src1})", 'u64': "{src1} == 0 ? 0 : {src0} % {src1}", 'i64': "{src1} == 0 ? 0 : {src0} % {src1}"}, flags=vector_scalar_operation), 649 650 # Binary comparison operators which return a boolean vector. 651 # The type of both operands must be equal. 652 operation("less", 2, printable_name="<", source_types=numeric_types, dest_type=bool_type, c_expression="{src0} < {src1}"), 653 operation("gequal", 2, printable_name=">=", source_types=numeric_types, dest_type=bool_type, c_expression="{src0} >= {src1}"), 654 operation("equal", 2, printable_name="==", source_types=all_types, dest_type=bool_type, c_expression="{src0} == {src1}"), 655 operation("nequal", 2, printable_name="!=", source_types=all_types, dest_type=bool_type, c_expression="{src0} != {src1}"), 656 657 # Returns single boolean for whether all components of operands[0] 658 # equal the components of operands[1]. 659 operation("all_equal", 2, source_types=all_types, dest_type=bool_type, c_expression="op[0]->has_value(op[1])", flags=frozenset((horizontal_operation, types_identical_operation))), 660 661 # Returns single boolean for whether any component of operands[0] 662 # is not equal to the corresponding component of operands[1]. 663 operation("any_nequal", 2, source_types=all_types, dest_type=bool_type, c_expression="!op[0]->has_value(op[1])", flags=frozenset((horizontal_operation, types_identical_operation))), 664 665 # Bit-wise binary operations. 666 operation("lshift", 2, printable_name="<<", source_types=integer_types, c_expression="{src0} << {src1}", flags=frozenset((vector_scalar_operation, mixed_type_operation))), 667 operation("rshift", 2, printable_name=">>", source_types=integer_types, c_expression="{src0} >> {src1}", flags=frozenset((vector_scalar_operation, mixed_type_operation))), 668 operation("bit_and", 2, printable_name="&", source_types=integer_types, c_expression="{src0} & {src1}", flags=vector_scalar_operation), 669 operation("bit_xor", 2, printable_name="^", source_types=integer_types, c_expression="{src0} ^ {src1}", flags=vector_scalar_operation), 670 operation("bit_or", 2, printable_name="|", source_types=integer_types, c_expression="{src0} | {src1}", flags=vector_scalar_operation), 671 672 operation("logic_and", 2, printable_name="&&", source_types=(bool_type,), c_expression="{src0} && {src1}"), 673 operation("logic_xor", 2, printable_name="^^", source_types=(bool_type,), c_expression="{src0} != {src1}"), 674 operation("logic_or", 2, printable_name="||", source_types=(bool_type,), c_expression="{src0} || {src1}"), 675 676 operation("dot", 2, source_types=real_types, c_expression={'f': "dot_f(op[0], op[1])", 'd': "dot_d(op[0], op[1])"}, flags=horizontal_operation), 677 operation("min", 2, source_types=numeric_types, c_expression="MIN2({src0}, {src1})", flags=vector_scalar_operation), 678 operation("max", 2, source_types=numeric_types, c_expression="MAX2({src0}, {src1})", flags=vector_scalar_operation), 679 680 operation("pow", 2, source_types=(float_type,), c_expression="powf({src0}, {src1})"), 681 682 # Load a value the size of a given GLSL type from a uniform block. 683 # 684 # operand0 is the ir_constant uniform block index in the linked shader. 685 # operand1 is a byte offset within the uniform block. 686 operation("ubo_load", 2), 687 688 # Multiplies a number by two to a power, part of ARB_gpu_shader5. 689 operation("ldexp", 2, 690 all_signatures=((float_type, (float_type, int_type)), 691 (double_type, (double_type, int_type))), 692 c_expression={'f': "ldexpf_flush_subnormal({src0}, {src1})", 693 'd': "ldexp_flush_subnormal({src0}, {src1})"}), 694 695 # Extract a scalar from a vector 696 # 697 # operand0 is the vector 698 # operand1 is the index of the field to read from operand0 699 operation("vector_extract", 2, source_types=all_types, c_expression="anything-except-None"), 700 701 # Interpolate fs input at offset 702 # 703 # operand0 is the fs input 704 # operand1 is the offset from the pixel center 705 operation("interpolate_at_offset", 2), 706 707 # Interpolate fs input at sample position 708 # 709 # operand0 is the fs input 710 # operand1 is the sample ID 711 operation("interpolate_at_sample", 2), 712 713 operation("atan2", 2, source_types=(float_type,), c_expression="atan2({src0}, {src1})"), 714 715 # Fused floating-point multiply-add, part of ARB_gpu_shader5. 716 operation("fma", 3, source_types=real_types, c_expression="{src0} * {src1} + {src2}"), 717 718 operation("lrp", 3, source_types=real_types, c_expression={'f': "{src0} * (1.0f - {src2}) + ({src1} * {src2})", 'd': "{src0} * (1.0 - {src2}) + ({src1} * {src2})"}), 719 720 # Conditional Select 721 # 722 # A vector conditional select instruction (like ?:, but operating per- 723 # component on vectors). 724 # 725 # See also lower_instructions_visitor::ldexp_to_arith 726 operation("csel", 3, 727 all_signatures=zip(all_types, zip(len(all_types) * (bool_type,), all_types, all_types)), 728 c_expression="{src0} ? {src1} : {src2}"), 729 730 operation("bitfield_extract", 3, 731 all_signatures=((int_type, (uint_type, int_type, int_type)), 732 (int_type, (int_type, int_type, int_type))), 733 c_expression={'u': "bitfield_extract_uint({src0}, {src1}, {src2})", 734 'i': "bitfield_extract_int({src0}, {src1}, {src2})"}), 735 736 # Generate a value with one field of a vector changed 737 # 738 # operand0 is the vector 739 # operand1 is the value to write into the vector result 740 # operand2 is the index in operand0 to be modified 741 operation("vector_insert", 3, source_types=all_types, c_expression="anything-except-None"), 742 743 operation("bitfield_insert", 4, 744 all_signatures=((uint_type, (uint_type, uint_type, int_type, int_type)), 745 (int_type, (int_type, int_type, int_type, int_type))), 746 c_expression="bitfield_insert({src0}, {src1}, {src2}, {src3})"), 747 748 operation("vector", 4, source_types=all_types, c_expression="anything-except-None"), 749] 750 751 752if __name__ == "__main__": 753 copyright = """/* 754 * Copyright (C) 2010 Intel Corporation 755 * 756 * Permission is hereby granted, free of charge, to any person obtaining a 757 * copy of this software and associated documentation files (the "Software"), 758 * to deal in the Software without restriction, including without limitation 759 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 760 * and/or sell copies of the Software, and to permit persons to whom the 761 * Software is furnished to do so, subject to the following conditions: 762 * 763 * The above copyright notice and this permission notice (including the next 764 * paragraph) shall be included in all copies or substantial portions of the 765 * Software. 766 * 767 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 768 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 769 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 770 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 771 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 772 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 773 * DEALINGS IN THE SOFTWARE. 774 */ 775""" 776 enum_template = mako.template.Template(copyright + """ 777enum ir_expression_operation { 778% for item in values: 779 ${item.get_enum_name()}, 780% endfor 781 782 /* Sentinels marking the last of each kind of operation. */ 783% for item in lasts: 784 ir_last_${("un", "bin", "tri", "quad")[item.num_operands - 1]}op = ${item.get_enum_name()}, 785% endfor 786 ir_last_opcode = ir_quadop_${lasts[3].name} 787};""") 788 789 strings_template = mako.template.Template(copyright + """ 790const char *const ir_expression_operation_strings[] = { 791% for item in values: 792 "${item.printable_name}", 793% endfor 794}; 795 796const char *const ir_expression_operation_enum_strings[] = { 797% for item in values: 798 "${item.name}", 799% endfor 800};""") 801 802 constant_template = mako.template.Template("""\ 803 switch (this->operation) { 804% for op in values: 805 % if op.c_expression is not None: 806${op.get_template()} 807 808 % endif 809% endfor 810 default: 811 /* FINISHME: Should handle all expression types. */ 812 return NULL; 813 } 814""") 815 816 if sys.argv[1] == "enum": 817 lasts = [None, None, None, None] 818 for item in reversed(ir_expression_operation): 819 i = item.num_operands - 1 820 if lasts[i] is None: 821 lasts[i] = item 822 823 print(enum_template.render(values=ir_expression_operation, 824 lasts=lasts)) 825 elif sys.argv[1] == "strings": 826 print(strings_template.render(values=ir_expression_operation)) 827 elif sys.argv[1] == "constant": 828 print(constant_template.render(values=ir_expression_operation)) 829