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