effect_symbol_table_intrinsics.inl (159812B)
1 /* 2 * Copyright (C) 2014 Patrick Mours 3 * SPDX-License-Identifier: BSD-3-Clause 4 */ 5 6 #if defined(__INTELLISENSE__) || !defined(DEFINE_INTRINSIC) 7 #define DEFINE_INTRINSIC(name, i, ret_type, ...) 8 #endif 9 #if defined(__INTELLISENSE__) || !defined(IMPLEMENT_INTRINSIC_GLSL) 10 #define IMPLEMENT_INTRINSIC_GLSL(name, i, code) 11 #endif 12 #if defined(__INTELLISENSE__) || !defined(IMPLEMENT_INTRINSIC_HLSL) 13 #define IMPLEMENT_INTRINSIC_HLSL(name, i, code) 14 #endif 15 #if defined(__INTELLISENSE__) || !defined(IMPLEMENT_INTRINSIC_SPIRV) 16 #define IMPLEMENT_INTRINSIC_SPIRV(name, i, code) 17 #endif 18 19 // ret abs(x) 20 DEFINE_INTRINSIC(abs, 0, int, int) 21 DEFINE_INTRINSIC(abs, 0, int2, int2) 22 DEFINE_INTRINSIC(abs, 0, int3, int3) 23 DEFINE_INTRINSIC(abs, 0, int4, int4) 24 DEFINE_INTRINSIC(abs, 1, float, float) 25 DEFINE_INTRINSIC(abs, 1, float2, float2) 26 DEFINE_INTRINSIC(abs, 1, float3, float3) 27 DEFINE_INTRINSIC(abs, 1, float4, float4) 28 IMPLEMENT_INTRINSIC_GLSL(abs, 0, { 29 code += "abs(" + id_to_name(args[0].base) + ')'; 30 }) 31 IMPLEMENT_INTRINSIC_GLSL(abs, 1, { 32 code += "abs(" + id_to_name(args[0].base) + ')'; 33 }) 34 IMPLEMENT_INTRINSIC_HLSL(abs, 0, { 35 code += "abs(" + id_to_name(args[0].base) + ')'; 36 }) 37 IMPLEMENT_INTRINSIC_HLSL(abs, 1, { 38 code += "abs(" + id_to_name(args[0].base) + ')'; 39 }) 40 IMPLEMENT_INTRINSIC_SPIRV(abs, 0, { 41 return 42 add_instruction(spv::OpExtInst, convert_type(res_type)) 43 .add(_glsl_ext) 44 .add(spv::GLSLstd450SAbs) 45 .add(args[0].base) 46 .result; 47 }) 48 IMPLEMENT_INTRINSIC_SPIRV(abs, 1, { 49 return 50 add_instruction(spv::OpExtInst, convert_type(res_type)) 51 .add(_glsl_ext) 52 .add(spv::GLSLstd450FAbs) 53 .add(args[0].base) 54 .result; 55 }) 56 57 // ret all(x) 58 DEFINE_INTRINSIC(all, 0, bool, bool) 59 DEFINE_INTRINSIC(all, 1, bool, bool2) 60 DEFINE_INTRINSIC(all, 1, bool, bool3) 61 DEFINE_INTRINSIC(all, 1, bool, bool4) 62 IMPLEMENT_INTRINSIC_GLSL(all, 0, { 63 code += id_to_name(args[0].base); 64 }) 65 IMPLEMENT_INTRINSIC_GLSL(all, 1, { 66 code += "all(" + id_to_name(args[0].base) + ')'; 67 }) 68 IMPLEMENT_INTRINSIC_HLSL(all, 0, { 69 code += id_to_name(args[0].base); 70 }) 71 IMPLEMENT_INTRINSIC_HLSL(all, 1, { 72 code += "all(" + id_to_name(args[0].base) + ')'; 73 }) 74 IMPLEMENT_INTRINSIC_SPIRV(all, 0, { 75 return args[0].base; 76 }) 77 IMPLEMENT_INTRINSIC_SPIRV(all, 1, { 78 return 79 add_instruction(spv::OpAll, convert_type(res_type)) 80 .add(args[0].base) 81 .result; 82 }) 83 84 // ret any(x) 85 DEFINE_INTRINSIC(any, 0, bool, bool) 86 DEFINE_INTRINSIC(any, 1, bool, bool2) 87 DEFINE_INTRINSIC(any, 1, bool, bool3) 88 DEFINE_INTRINSIC(any, 1, bool, bool4) 89 IMPLEMENT_INTRINSIC_GLSL(any, 0, { 90 code += id_to_name(args[0].base); 91 }) 92 IMPLEMENT_INTRINSIC_GLSL(any, 1, { 93 code += "any(" + id_to_name(args[0].base) + ')'; 94 }) 95 IMPLEMENT_INTRINSIC_HLSL(any, 0, { 96 code += id_to_name(args[0].base); 97 }) 98 IMPLEMENT_INTRINSIC_HLSL(any, 1, { 99 code += "any(" + id_to_name(args[0].base) + ')'; 100 }) 101 IMPLEMENT_INTRINSIC_SPIRV(any, 0, { 102 return args[0].base; 103 }) 104 IMPLEMENT_INTRINSIC_SPIRV(any, 1, { 105 return 106 add_instruction(spv::OpAny, convert_type(res_type)) 107 .add(args[0].base) 108 .result; 109 }) 110 111 // ret asin(x) 112 DEFINE_INTRINSIC(asin, 0, float, float) 113 DEFINE_INTRINSIC(asin, 0, float2, float2) 114 DEFINE_INTRINSIC(asin, 0, float3, float3) 115 DEFINE_INTRINSIC(asin, 0, float4, float4) 116 IMPLEMENT_INTRINSIC_GLSL(asin, 0, { 117 code += "asin(" + id_to_name(args[0].base) + ')'; 118 }) 119 IMPLEMENT_INTRINSIC_HLSL(asin, 0, { 120 code += "asin(" + id_to_name(args[0].base) + ')'; 121 }) 122 IMPLEMENT_INTRINSIC_SPIRV(asin, 0, { 123 return 124 add_instruction(spv::OpExtInst, convert_type(res_type)) 125 .add(_glsl_ext) 126 .add(spv::GLSLstd450Asin) 127 .add(args[0].base) 128 .result; 129 }) 130 131 // ret acos(x) 132 DEFINE_INTRINSIC(acos, 0, float, float) 133 DEFINE_INTRINSIC(acos, 0, float2, float2) 134 DEFINE_INTRINSIC(acos, 0, float3, float3) 135 DEFINE_INTRINSIC(acos, 0, float4, float4) 136 IMPLEMENT_INTRINSIC_GLSL(acos, 0, { 137 code += "acos(" + id_to_name(args[0].base) + ')'; 138 }) 139 IMPLEMENT_INTRINSIC_HLSL(acos, 0, { 140 code += "acos(" + id_to_name(args[0].base) + ')'; 141 }) 142 IMPLEMENT_INTRINSIC_SPIRV(acos, 0, { 143 return 144 add_instruction(spv::OpExtInst, convert_type(res_type)) 145 .add(_glsl_ext) 146 .add(spv::GLSLstd450Acos) 147 .add(args[0].base) 148 .result; 149 }) 150 151 // ret atan(x) 152 DEFINE_INTRINSIC(atan, 0, float, float) 153 DEFINE_INTRINSIC(atan, 0, float2, float2) 154 DEFINE_INTRINSIC(atan, 0, float3, float3) 155 DEFINE_INTRINSIC(atan, 0, float4, float4) 156 IMPLEMENT_INTRINSIC_GLSL(atan, 0, { 157 code += "atan(" + id_to_name(args[0].base) + ')'; 158 }) 159 IMPLEMENT_INTRINSIC_HLSL(atan, 0, { 160 code += "atan(" + id_to_name(args[0].base) + ')'; 161 }) 162 IMPLEMENT_INTRINSIC_SPIRV(atan, 0, { 163 return 164 add_instruction(spv::OpExtInst, convert_type(res_type)) 165 .add(_glsl_ext) 166 .add(spv::GLSLstd450Atan) 167 .add(args[0].base) 168 .result; 169 }) 170 171 // ret atan2(x, y) 172 DEFINE_INTRINSIC(atan2, 0, float, float, float) 173 DEFINE_INTRINSIC(atan2, 0, float2, float2, float2) 174 DEFINE_INTRINSIC(atan2, 0, float3, float3, float3) 175 DEFINE_INTRINSIC(atan2, 0, float4, float4, float4) 176 IMPLEMENT_INTRINSIC_GLSL(atan2, 0, { 177 code += "atan(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ')'; 178 }) 179 IMPLEMENT_INTRINSIC_HLSL(atan2, 0, { 180 code += "atan2(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ')'; 181 }) 182 IMPLEMENT_INTRINSIC_SPIRV(atan2, 0, { 183 return 184 add_instruction(spv::OpExtInst, convert_type(res_type)) 185 .add(_glsl_ext) 186 .add(spv::GLSLstd450Atan2) 187 .add(args[0].base) 188 .add(args[1].base) 189 .result; 190 }) 191 192 // ret sin(x) 193 DEFINE_INTRINSIC(sin, 0, float, float) 194 DEFINE_INTRINSIC(sin, 0, float2, float2) 195 DEFINE_INTRINSIC(sin, 0, float3, float3) 196 DEFINE_INTRINSIC(sin, 0, float4, float4) 197 IMPLEMENT_INTRINSIC_GLSL(sin, 0, { 198 code += "sin(" + id_to_name(args[0].base) + ')'; 199 }) 200 IMPLEMENT_INTRINSIC_HLSL(sin, 0, { 201 code += "sin(" + id_to_name(args[0].base) + ')'; 202 }) 203 IMPLEMENT_INTRINSIC_SPIRV(sin, 0, { 204 return 205 add_instruction(spv::OpExtInst, convert_type(res_type)) 206 .add(_glsl_ext) 207 .add(spv::GLSLstd450Sin) 208 .add(args[0].base) 209 .result; 210 }) 211 212 // ret sinh(x) 213 DEFINE_INTRINSIC(sinh, 0, float, float) 214 DEFINE_INTRINSIC(sinh, 0, float2, float2) 215 DEFINE_INTRINSIC(sinh, 0, float3, float3) 216 DEFINE_INTRINSIC(sinh, 0, float4, float4) 217 IMPLEMENT_INTRINSIC_GLSL(sinh, 0, { 218 code += "sinh(" + id_to_name(args[0].base) + ')'; 219 }) 220 IMPLEMENT_INTRINSIC_HLSL(sinh, 0, { 221 code += "sinh(" + id_to_name(args[0].base) + ')'; 222 }) 223 IMPLEMENT_INTRINSIC_SPIRV(sinh, 0, { 224 return 225 add_instruction(spv::OpExtInst, convert_type(res_type)) 226 .add(_glsl_ext) 227 .add(spv::GLSLstd450Sinh) 228 .add(args[0].base) 229 .result; 230 }) 231 232 // ret cos(x) 233 DEFINE_INTRINSIC(cos, 0, float, float) 234 DEFINE_INTRINSIC(cos, 0, float2, float2) 235 DEFINE_INTRINSIC(cos, 0, float3, float3) 236 DEFINE_INTRINSIC(cos, 0, float4, float4) 237 IMPLEMENT_INTRINSIC_GLSL(cos, 0, { 238 code += "cos(" + id_to_name(args[0].base) + ')'; 239 }) 240 IMPLEMENT_INTRINSIC_HLSL(cos, 0, { 241 code += "cos(" + id_to_name(args[0].base) + ')'; 242 }) 243 IMPLEMENT_INTRINSIC_SPIRV(cos, 0, { 244 return 245 add_instruction(spv::OpExtInst, convert_type(res_type)) 246 .add(_glsl_ext) 247 .add(spv::GLSLstd450Cos) 248 .add(args[0].base) 249 .result; 250 }) 251 252 // ret cosh(x) 253 DEFINE_INTRINSIC(cosh, 0, float, float) 254 DEFINE_INTRINSIC(cosh, 0, float2, float2) 255 DEFINE_INTRINSIC(cosh, 0, float3, float3) 256 DEFINE_INTRINSIC(cosh, 0, float4, float4) 257 IMPLEMENT_INTRINSIC_GLSL(cosh, 0, { 258 code += "cosh(" + id_to_name(args[0].base) + ')'; 259 }) 260 IMPLEMENT_INTRINSIC_HLSL(cosh, 0, { 261 code += "cosh(" + id_to_name(args[0].base) + ')'; 262 }) 263 IMPLEMENT_INTRINSIC_SPIRV(cosh, 0, { 264 return 265 add_instruction(spv::OpExtInst, convert_type(res_type)) 266 .add(_glsl_ext) 267 .add(spv::GLSLstd450Cosh) 268 .add(args[0].base) 269 .result; 270 }) 271 272 // ret tan(x) 273 DEFINE_INTRINSIC(tan, 0, float, float) 274 DEFINE_INTRINSIC(tan, 0, float2, float2) 275 DEFINE_INTRINSIC(tan, 0, float3, float3) 276 DEFINE_INTRINSIC(tan, 0, float4, float4) 277 IMPLEMENT_INTRINSIC_GLSL(tan, 0, { 278 code += "tan(" + id_to_name(args[0].base) + ')'; 279 }) 280 IMPLEMENT_INTRINSIC_HLSL(tan, 0, { 281 code += "tan(" + id_to_name(args[0].base) + ')'; 282 }) 283 IMPLEMENT_INTRINSIC_SPIRV(tan, 0, { 284 return 285 add_instruction(spv::OpExtInst, convert_type(res_type)) 286 .add(_glsl_ext) 287 .add(spv::GLSLstd450Tan) 288 .add(args[0].base) 289 .result; 290 }) 291 292 // ret tanh(x) 293 DEFINE_INTRINSIC(tanh, 0, float, float) 294 DEFINE_INTRINSIC(tanh, 0, float2, float2) 295 DEFINE_INTRINSIC(tanh, 0, float3, float3) 296 DEFINE_INTRINSIC(tanh, 0, float4, float4) 297 IMPLEMENT_INTRINSIC_GLSL(tanh, 0, { 298 code += "tanh(" + id_to_name(args[0].base) + ')'; 299 }) 300 IMPLEMENT_INTRINSIC_HLSL(tanh, 0, { 301 code += "tanh(" + id_to_name(args[0].base) + ')'; 302 }) 303 IMPLEMENT_INTRINSIC_SPIRV(tanh, 0, { 304 return 305 add_instruction(spv::OpExtInst, convert_type(res_type)) 306 .add(_glsl_ext) 307 .add(spv::GLSLstd450Tanh) 308 .add(args[0].base) 309 .result; 310 }) 311 312 // sincos(x, out s, out c) 313 DEFINE_INTRINSIC(sincos, 0, void, float, out_float, out_float) 314 DEFINE_INTRINSIC(sincos, 0, void, float2, out_float2, out_float2) 315 DEFINE_INTRINSIC(sincos, 0, void, float3, out_float3, out_float3) 316 DEFINE_INTRINSIC(sincos, 0, void, float4, out_float4, out_float4) 317 IMPLEMENT_INTRINSIC_GLSL(sincos, 0, { 318 code += id_to_name(args[1].base) + " = sin(" + id_to_name(args[0].base) + "), " + id_to_name(args[2].base) + " = cos(" + id_to_name(args[0].base) + ')'; 319 }) 320 IMPLEMENT_INTRINSIC_HLSL(sincos, 0, { 321 code += "sincos(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ", " + id_to_name(args[2].base) + ')'; 322 }) 323 IMPLEMENT_INTRINSIC_SPIRV(sincos, 0, { 324 const spv::Id sin_result = add_instruction(spv::OpExtInst, convert_type(args[0].type)) 325 .add(_glsl_ext) 326 .add(spv::GLSLstd450Sin) 327 .add(args[0].base) 328 .result; 329 const spv::Id cos_result = add_instruction(spv::OpExtInst, convert_type(args[0].type)) 330 .add(_glsl_ext) 331 .add(spv::GLSLstd450Cos) 332 .add(args[0].base) 333 .result; 334 335 add_instruction_without_result(spv::OpStore) 336 .add(args[1].base) 337 .add(sin_result); 338 add_instruction_without_result(spv::OpStore) 339 .add(args[2].base) 340 .add(cos_result); 341 342 return 0; 343 }) 344 345 // ret asint(x) 346 DEFINE_INTRINSIC(asint, 0, int, float) 347 DEFINE_INTRINSIC(asint, 0, int2, float2) 348 DEFINE_INTRINSIC(asint, 0, int3, float3) 349 DEFINE_INTRINSIC(asint, 0, int4, float4) 350 IMPLEMENT_INTRINSIC_GLSL(asint, 0, { 351 code += "floatBitsToInt(" + id_to_name(args[0].base) + ')'; 352 }) 353 IMPLEMENT_INTRINSIC_HLSL(asint, 0, { 354 _uses_bitwise_cast = true; 355 if (_shader_model < 40) 356 code += "__"; 357 code += "asint(" + id_to_name(args[0].base) + ')'; 358 }) 359 IMPLEMENT_INTRINSIC_SPIRV(asint, 0, { 360 return 361 add_instruction(spv::OpBitcast, convert_type(res_type)) 362 .add(args[0].base) 363 .result; 364 }) 365 366 // ret asuint(x) 367 DEFINE_INTRINSIC(asuint, 0, uint, float) 368 DEFINE_INTRINSIC(asuint, 0, uint2, float2) 369 DEFINE_INTRINSIC(asuint, 0, uint3, float3) 370 DEFINE_INTRINSIC(asuint, 0, uint4, float4) 371 IMPLEMENT_INTRINSIC_GLSL(asuint, 0, { 372 code += "floatBitsToUint(" + id_to_name(args[0].base) + ')'; 373 }) 374 IMPLEMENT_INTRINSIC_HLSL(asuint, 0, { 375 _uses_bitwise_cast = true; 376 if (_shader_model < 40) 377 code += "__"; 378 code += "asuint(" + id_to_name(args[0].base) + ')'; 379 }) 380 IMPLEMENT_INTRINSIC_SPIRV(asuint, 0, { 381 return 382 add_instruction(spv::OpBitcast, convert_type(res_type)) 383 .add(args[0].base) 384 .result; 385 }) 386 387 // ret asfloat(x) 388 DEFINE_INTRINSIC(asfloat, 0, float, int) 389 DEFINE_INTRINSIC(asfloat, 0, float2, int2) 390 DEFINE_INTRINSIC(asfloat, 0, float3, int3) 391 DEFINE_INTRINSIC(asfloat, 0, float4, int4) 392 DEFINE_INTRINSIC(asfloat, 1, float, uint) 393 DEFINE_INTRINSIC(asfloat, 1, float2, uint2) 394 DEFINE_INTRINSIC(asfloat, 1, float3, uint3) 395 DEFINE_INTRINSIC(asfloat, 1, float4, uint4) 396 IMPLEMENT_INTRINSIC_GLSL(asfloat, 0, { 397 code += "intBitsToFloat(" + id_to_name(args[0].base) + ')'; 398 }) 399 IMPLEMENT_INTRINSIC_GLSL(asfloat, 1, { 400 code += "uintBitsToFloat(" + id_to_name(args[0].base) + ')'; 401 }) 402 IMPLEMENT_INTRINSIC_HLSL(asfloat, 0, { 403 _uses_bitwise_cast = true; 404 if (_shader_model < 40) 405 code += "__"; 406 code += "asfloat(" + id_to_name(args[0].base) + ')'; 407 }) 408 IMPLEMENT_INTRINSIC_HLSL(asfloat, 1, { 409 _uses_bitwise_cast = true; 410 if (_shader_model < 40) 411 code += "__"; 412 code += "asfloat(" + id_to_name(args[0].base) + ')'; 413 }) 414 IMPLEMENT_INTRINSIC_SPIRV(asfloat, 0, { 415 return 416 add_instruction(spv::OpBitcast, convert_type(res_type)) 417 .add(args[0].base) 418 .result; 419 }) 420 IMPLEMENT_INTRINSIC_SPIRV(asfloat, 1, { 421 return 422 add_instruction(spv::OpBitcast, convert_type(res_type)) 423 .add(args[0].base) 424 .result; 425 }) 426 427 // ret firstbitlow 428 DEFINE_INTRINSIC(firstbitlow, 0, uint, uint) 429 DEFINE_INTRINSIC(firstbitlow, 0, uint2, uint2) 430 DEFINE_INTRINSIC(firstbitlow, 0, uint3, uint3) 431 DEFINE_INTRINSIC(firstbitlow, 0, uint4, uint4) 432 IMPLEMENT_INTRINSIC_GLSL(firstbitlow, 0, { 433 code += "findLSB(" + id_to_name(args[0].base) + ')'; 434 }) 435 IMPLEMENT_INTRINSIC_HLSL(firstbitlow, 0, { 436 if (_shader_model < 50) 437 code += "__"; 438 code += "firstbitlow(" + id_to_name(args[0].base) + ')'; 439 }) 440 IMPLEMENT_INTRINSIC_SPIRV(firstbitlow, 0, { 441 return 442 add_instruction(spv::OpExtInst, convert_type(res_type)) 443 .add(_glsl_ext) 444 .add(spv::GLSLstd450FindILsb) 445 .add(args[0].base) 446 .result; 447 }) 448 449 // ret firstbithigh 450 DEFINE_INTRINSIC(firstbithigh, 0, int, int) 451 DEFINE_INTRINSIC(firstbithigh, 0, int2, int2) 452 DEFINE_INTRINSIC(firstbithigh, 0, int3, int3) 453 DEFINE_INTRINSIC(firstbithigh, 0, int4, int4) 454 DEFINE_INTRINSIC(firstbithigh, 1, uint, uint) 455 DEFINE_INTRINSIC(firstbithigh, 1, uint2, uint2) 456 DEFINE_INTRINSIC(firstbithigh, 1, uint3, uint3) 457 DEFINE_INTRINSIC(firstbithigh, 1, uint4, uint4) 458 IMPLEMENT_INTRINSIC_GLSL(firstbithigh, 0, { 459 code += "findMSB(" + id_to_name(args[0].base) + ')'; 460 }) 461 IMPLEMENT_INTRINSIC_GLSL(firstbithigh, 1, { 462 code += "findMSB(" + id_to_name(args[0].base) + ')'; 463 }) 464 IMPLEMENT_INTRINSIC_HLSL(firstbithigh, 0, { 465 if (_shader_model < 50) 466 code += "__"; 467 code += "firstbithigh(" + id_to_name(args[0].base) + ')'; 468 }) 469 IMPLEMENT_INTRINSIC_HLSL(firstbithigh, 1, { 470 if (_shader_model < 50) 471 code += "__"; 472 code += "firstbithigh(" + id_to_name(args[0].base) + ')'; 473 }) 474 IMPLEMENT_INTRINSIC_SPIRV(firstbithigh, 0, { 475 return 476 add_instruction(spv::OpExtInst, convert_type(res_type)) 477 .add(_glsl_ext) 478 .add(spv::GLSLstd450FindSMsb) 479 .add(args[0].base) 480 .result; 481 }) 482 IMPLEMENT_INTRINSIC_SPIRV(firstbithigh, 1, { 483 return 484 add_instruction(spv::OpExtInst, convert_type(res_type)) 485 .add(_glsl_ext) 486 .add(spv::GLSLstd450FindUMsb) 487 .add(args[0].base) 488 .result; 489 }) 490 491 // ret countbits 492 DEFINE_INTRINSIC(countbits, 0, uint, uint) 493 DEFINE_INTRINSIC(countbits, 0, uint2, uint2) 494 DEFINE_INTRINSIC(countbits, 0, uint3, uint3) 495 DEFINE_INTRINSIC(countbits, 0, uint4, uint4) 496 IMPLEMENT_INTRINSIC_GLSL(countbits, 0, { 497 code += "bitCount(" + id_to_name(args[0].base) + ')'; 498 }) 499 IMPLEMENT_INTRINSIC_HLSL(countbits, 0, { 500 if (_shader_model < 50) 501 code += "__"; 502 code += "countbits(" + id_to_name(args[0].base) + ')'; 503 }) 504 IMPLEMENT_INTRINSIC_SPIRV(countbits, 0, { 505 return 506 add_instruction(spv::OpBitCount, convert_type(res_type)) 507 .add(args[0].base) 508 .result; 509 }) 510 511 // ret reversebits 512 DEFINE_INTRINSIC(reversebits, 0, uint, uint) 513 DEFINE_INTRINSIC(reversebits, 0, uint2, uint2) 514 DEFINE_INTRINSIC(reversebits, 0, uint3, uint3) 515 DEFINE_INTRINSIC(reversebits, 0, uint4, uint4) 516 IMPLEMENT_INTRINSIC_GLSL(reversebits, 0, { 517 code += "bitfieldReverse(" + id_to_name(args[0].base) + ')'; 518 }) 519 IMPLEMENT_INTRINSIC_HLSL(reversebits, 0, { 520 if (_shader_model < 50) 521 code += "__"; 522 code += "reversebits(" + id_to_name(args[0].base) + ')'; 523 }) 524 IMPLEMENT_INTRINSIC_SPIRV(reversebits, 0, { 525 return 526 add_instruction(spv::OpBitReverse, convert_type(res_type)) 527 .add(args[0].base) 528 .result; 529 }) 530 531 // ret ceil(x) 532 DEFINE_INTRINSIC(ceil, 0, float, float) 533 DEFINE_INTRINSIC(ceil, 0, float2, float2) 534 DEFINE_INTRINSIC(ceil, 0, float3, float3) 535 DEFINE_INTRINSIC(ceil, 0, float4, float4) 536 IMPLEMENT_INTRINSIC_GLSL(ceil, 0, { 537 code += "ceil(" + id_to_name(args[0].base) + ')'; 538 }) 539 IMPLEMENT_INTRINSIC_HLSL(ceil, 0, { 540 code += "ceil(" + id_to_name(args[0].base) + ')'; 541 }) 542 IMPLEMENT_INTRINSIC_SPIRV(ceil, 0, { 543 return 544 add_instruction(spv::OpExtInst, convert_type(res_type)) 545 .add(_glsl_ext) 546 .add(spv::GLSLstd450Ceil) 547 .add(args[0].base) 548 .result; 549 }) 550 551 // ret floor(x) 552 DEFINE_INTRINSIC(floor, 0, float, float) 553 DEFINE_INTRINSIC(floor, 0, float2, float2) 554 DEFINE_INTRINSIC(floor, 0, float3, float3) 555 DEFINE_INTRINSIC(floor, 0, float4, float4) 556 IMPLEMENT_INTRINSIC_GLSL(floor, 0, { 557 code += "floor(" + id_to_name(args[0].base) + ')'; 558 }) 559 IMPLEMENT_INTRINSIC_HLSL(floor, 0, { 560 if (_shader_model >= 40) 561 code += "floor(" + id_to_name(args[0].base) + ')'; 562 else // Using the floor intrinsic sometimes causes the SM3 D3DCompiler to generate wrong code, so replace it with a custom implementation 563 code += id_to_name(args[0].base) + " - frac(" + id_to_name(args[0].base) + ')'; 564 }) 565 IMPLEMENT_INTRINSIC_SPIRV(floor, 0, { 566 return 567 add_instruction(spv::OpExtInst, convert_type(res_type)) 568 .add(_glsl_ext) 569 .add(spv::GLSLstd450Floor) 570 .add(args[0].base) 571 .result; 572 }) 573 574 // ret clamp(x, min, max) 575 DEFINE_INTRINSIC(clamp, 0, int, int, int, int) 576 DEFINE_INTRINSIC(clamp, 0, int2, int2, int2, int2) 577 DEFINE_INTRINSIC(clamp, 0, int3, int3, int3, int3) 578 DEFINE_INTRINSIC(clamp, 0, int4, int4, int4, int4) 579 DEFINE_INTRINSIC(clamp, 1, uint, uint, uint, uint) 580 DEFINE_INTRINSIC(clamp, 1, uint2, uint2, uint2, uint2) 581 DEFINE_INTRINSIC(clamp, 1, uint3, uint3, uint3, uint3) 582 DEFINE_INTRINSIC(clamp, 1, uint4, uint4, uint4, uint4) 583 DEFINE_INTRINSIC(clamp, 2, float, float, float, float) 584 DEFINE_INTRINSIC(clamp, 2, float2, float2, float2, float2) 585 DEFINE_INTRINSIC(clamp, 2, float3, float3, float3, float3) 586 DEFINE_INTRINSIC(clamp, 2, float4, float4, float4, float4) 587 IMPLEMENT_INTRINSIC_GLSL(clamp, 0, { 588 code += "clamp(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ", " + id_to_name(args[2].base) + ')'; 589 }) 590 IMPLEMENT_INTRINSIC_GLSL(clamp, 1, { 591 code += "clamp(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ", " + id_to_name(args[2].base) + ')'; 592 }) 593 IMPLEMENT_INTRINSIC_GLSL(clamp, 2, { 594 code += "clamp(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ", " + id_to_name(args[2].base) + ')'; 595 }) 596 IMPLEMENT_INTRINSIC_HLSL(clamp, 0, { 597 code += "clamp(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ", " + id_to_name(args[2].base) + ')'; 598 }) 599 IMPLEMENT_INTRINSIC_HLSL(clamp, 1, { 600 code += "clamp(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ", " + id_to_name(args[2].base) + ')'; 601 }) 602 IMPLEMENT_INTRINSIC_HLSL(clamp, 2, { 603 code += "clamp(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ", " + id_to_name(args[2].base) + ')'; 604 }) 605 IMPLEMENT_INTRINSIC_SPIRV(clamp, 0, { 606 return 607 add_instruction(spv::OpExtInst, convert_type(res_type)) 608 .add(_glsl_ext) 609 .add(spv::GLSLstd450SClamp) 610 .add(args[0].base) 611 .add(args[1].base) 612 .add(args[2].base) 613 .result; 614 }) 615 IMPLEMENT_INTRINSIC_SPIRV(clamp, 1, { 616 return 617 add_instruction(spv::OpExtInst, convert_type(res_type)) 618 .add(_glsl_ext) 619 .add(spv::GLSLstd450UClamp) 620 .add(args[0].base) 621 .add(args[1].base) 622 .add(args[2].base) 623 .result; 624 }) 625 IMPLEMENT_INTRINSIC_SPIRV(clamp, 2, { 626 return 627 add_instruction(spv::OpExtInst, convert_type(res_type)) 628 .add(_glsl_ext) 629 .add(spv::GLSLstd450FClamp) 630 .add(args[0].base) 631 .add(args[1].base) 632 .add(args[2].base) 633 .result; 634 }) 635 636 // ret saturate(x) 637 DEFINE_INTRINSIC(saturate, 0, float, float) 638 DEFINE_INTRINSIC(saturate, 0, float2, float2) 639 DEFINE_INTRINSIC(saturate, 0, float3, float3) 640 DEFINE_INTRINSIC(saturate, 0, float4, float4) 641 IMPLEMENT_INTRINSIC_GLSL(saturate, 0, { 642 code += "clamp(" + id_to_name(args[0].base) + ", 0.0, 1.0)"; 643 }) 644 IMPLEMENT_INTRINSIC_HLSL(saturate, 0, { 645 code += "saturate(" + id_to_name(args[0].base) + ')'; 646 }) 647 IMPLEMENT_INTRINSIC_SPIRV(saturate, 0, { 648 const spv::Id constant_one = emit_constant(args[0].type, 1u); 649 const spv::Id constant_zero = emit_constant(args[0].type, 0u); 650 651 return 652 add_instruction(spv::OpExtInst, convert_type(res_type)) 653 .add(_glsl_ext) 654 .add(spv::GLSLstd450FClamp) 655 .add(args[0].base) 656 .add(constant_zero) 657 .add(constant_one) 658 .result; 659 }) 660 661 // ret mad(mvalue, avalue, bvalue) 662 DEFINE_INTRINSIC(mad, 0, float, float, float, float) 663 DEFINE_INTRINSIC(mad, 0, float2, float2, float2, float2) 664 DEFINE_INTRINSIC(mad, 0, float3, float3, float3, float3) 665 DEFINE_INTRINSIC(mad, 0, float4, float4, float4, float4) 666 IMPLEMENT_INTRINSIC_GLSL(mad, 0, { 667 code += "fma(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ", " + id_to_name(args[2].base) + ')'; 668 }) 669 IMPLEMENT_INTRINSIC_HLSL(mad, 0, { 670 if (_shader_model >= 50) 671 code += "mad(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ", " + id_to_name(args[2].base) + ')'; 672 else 673 code += id_to_name(args[0].base) + " * " + id_to_name(args[1].base) + " + " + id_to_name(args[2].base); 674 }) 675 IMPLEMENT_INTRINSIC_SPIRV(mad, 0, { 676 return 677 add_instruction(spv::OpExtInst, convert_type(res_type)) 678 .add(_glsl_ext) 679 .add(spv::GLSLstd450Fma) 680 .add(args[0].base) 681 .add(args[1].base) 682 .add(args[2].base) 683 .result; 684 }) 685 686 // ret rcp(x) 687 DEFINE_INTRINSIC(rcp, 0, float, float) 688 DEFINE_INTRINSIC(rcp, 0, float2, float2) 689 DEFINE_INTRINSIC(rcp, 0, float3, float3) 690 DEFINE_INTRINSIC(rcp, 0, float4, float4) 691 IMPLEMENT_INTRINSIC_GLSL(rcp, 0, { 692 code += "1.0 / " + id_to_name(args[0].base); 693 }) 694 IMPLEMENT_INTRINSIC_HLSL(rcp, 0, { 695 if (_shader_model >= 50) 696 code += "rcp(" + id_to_name(args[0].base) + ')'; 697 else 698 code += "1.0 / " + id_to_name(args[0].base); 699 }) 700 IMPLEMENT_INTRINSIC_SPIRV(rcp, 0, { 701 const spv::Id constant_one = emit_constant(args[0].type, 1u); 702 703 return 704 add_instruction(spv::OpFDiv, convert_type(res_type)) 705 .add(constant_one) 706 .add(args[0].base) 707 .result; 708 }) 709 710 // ret pow(x, y) 711 DEFINE_INTRINSIC(pow, 0, float, float, float) 712 DEFINE_INTRINSIC(pow, 0, float2, float2, float2) 713 DEFINE_INTRINSIC(pow, 0, float3, float3, float3) 714 DEFINE_INTRINSIC(pow, 0, float4, float4, float4) 715 IMPLEMENT_INTRINSIC_GLSL(pow, 0, { 716 code += "pow(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ')'; 717 }) 718 IMPLEMENT_INTRINSIC_HLSL(pow, 0, { 719 code += "pow(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ')'; 720 }) 721 IMPLEMENT_INTRINSIC_SPIRV(pow, 0, { 722 return 723 add_instruction(spv::OpExtInst, convert_type(res_type)) 724 .add(_glsl_ext) 725 .add(spv::GLSLstd450Pow) 726 .add(args[0].base) 727 .add(args[1].base) 728 .result; 729 }) 730 731 // ret exp(x) 732 DEFINE_INTRINSIC(exp, 0, float, float) 733 DEFINE_INTRINSIC(exp, 0, float2, float2) 734 DEFINE_INTRINSIC(exp, 0, float3, float3) 735 DEFINE_INTRINSIC(exp, 0, float4, float4) 736 IMPLEMENT_INTRINSIC_GLSL(exp, 0, { 737 code += "exp(" + id_to_name(args[0].base) + ')'; 738 }) 739 IMPLEMENT_INTRINSIC_HLSL(exp, 0, { 740 code += "exp(" + id_to_name(args[0].base) + ')'; 741 }) 742 IMPLEMENT_INTRINSIC_SPIRV(exp, 0, { 743 return 744 add_instruction(spv::OpExtInst, convert_type(res_type)) 745 .add(_glsl_ext) 746 .add(spv::GLSLstd450Exp) 747 .add(args[0].base) 748 .result; 749 }) 750 751 // ret exp2(x) 752 DEFINE_INTRINSIC(exp2, 0, float, float) 753 DEFINE_INTRINSIC(exp2, 0, float2, float2) 754 DEFINE_INTRINSIC(exp2, 0, float3, float3) 755 DEFINE_INTRINSIC(exp2, 0, float4, float4) 756 IMPLEMENT_INTRINSIC_GLSL(exp2, 0, { 757 code += "exp2(" + id_to_name(args[0].base) + ')'; 758 }) 759 IMPLEMENT_INTRINSIC_HLSL(exp2, 0, { 760 code += "exp2(" + id_to_name(args[0].base) + ')'; 761 }) 762 IMPLEMENT_INTRINSIC_SPIRV(exp2, 0, { 763 return 764 add_instruction(spv::OpExtInst, convert_type(res_type)) 765 .add(_glsl_ext) 766 .add(spv::GLSLstd450Exp2) 767 .add(args[0].base) 768 .result; 769 }) 770 771 // ret log(x) 772 DEFINE_INTRINSIC(log, 0, float, float) 773 DEFINE_INTRINSIC(log, 0, float2, float2) 774 DEFINE_INTRINSIC(log, 0, float3, float3) 775 DEFINE_INTRINSIC(log, 0, float4, float4) 776 IMPLEMENT_INTRINSIC_GLSL(log, 0, { 777 code += "log(" + id_to_name(args[0].base) + ')'; 778 }) 779 IMPLEMENT_INTRINSIC_HLSL(log, 0, { 780 code += "log(" + id_to_name(args[0].base) + ')'; 781 }) 782 IMPLEMENT_INTRINSIC_SPIRV(log, 0, { 783 return 784 add_instruction(spv::OpExtInst, convert_type(res_type)) 785 .add(_glsl_ext) 786 .add(spv::GLSLstd450Log) 787 .add(args[0].base) 788 .result; 789 }) 790 791 // ret log2(x) 792 DEFINE_INTRINSIC(log2, 0, float, float) 793 DEFINE_INTRINSIC(log2, 0, float2, float2) 794 DEFINE_INTRINSIC(log2, 0, float3, float3) 795 DEFINE_INTRINSIC(log2, 0, float4, float4) 796 IMPLEMENT_INTRINSIC_GLSL(log2, 0, { 797 code += "log2(" + id_to_name(args[0].base) + ')'; 798 }) 799 IMPLEMENT_INTRINSIC_HLSL(log2, 0, { 800 code += "log2(" + id_to_name(args[0].base) + ')'; 801 }) 802 IMPLEMENT_INTRINSIC_SPIRV(log2, 0, { 803 return 804 add_instruction(spv::OpExtInst, convert_type(res_type)) 805 .add(_glsl_ext) 806 .add(spv::GLSLstd450Log2) 807 .add(args[0].base) 808 .result; 809 }) 810 811 // ret log10(x) 812 DEFINE_INTRINSIC(log10, 0, float, float) 813 DEFINE_INTRINSIC(log10, 0, float2, float2) 814 DEFINE_INTRINSIC(log10, 0, float3, float3) 815 DEFINE_INTRINSIC(log10, 0, float4, float4) 816 IMPLEMENT_INTRINSIC_GLSL(log10, 0, { 817 code += "(log2(" + id_to_name(args[0].base) + ") / log2(10.0))"; 818 }) 819 IMPLEMENT_INTRINSIC_HLSL(log10, 0, { 820 code += "(log2(" + id_to_name(args[0].base) + ") / log2(10.0))"; 821 }) 822 IMPLEMENT_INTRINSIC_SPIRV(log10, 0, { 823 const spv::Id log2 = add_instruction(spv::OpExtInst, convert_type(res_type)) 824 .add(_glsl_ext) 825 .add(spv::GLSLstd450Log2) 826 .add(args[0].base) 827 .result; 828 829 const spv::Id log10 = emit_constant(args[0].type, /* log2(10) */ 830 constant { { 3.321928f, 3.321928f, 3.321928f, 3.321928f } }); 831 832 return 833 add_instruction(spv::OpFDiv, convert_type(res_type)) 834 .add(log2) 835 .add(log10) 836 .result; }) 837 838 // ret sign(x) 839 DEFINE_INTRINSIC(sign, 0, int, int) 840 DEFINE_INTRINSIC(sign, 0, int2, int2) 841 DEFINE_INTRINSIC(sign, 0, int3, int3) 842 DEFINE_INTRINSIC(sign, 0, int4, int4) 843 DEFINE_INTRINSIC(sign, 1, float, float) 844 DEFINE_INTRINSIC(sign, 1, float2, float2) 845 DEFINE_INTRINSIC(sign, 1, float3, float3) 846 DEFINE_INTRINSIC(sign, 1, float4, float4) 847 IMPLEMENT_INTRINSIC_GLSL(sign, 0, { 848 code += "sign(" + id_to_name(args[0].base) + ')'; 849 }) 850 IMPLEMENT_INTRINSIC_GLSL(sign, 1, { 851 code += "sign(" + id_to_name(args[0].base) + ')'; 852 }) 853 IMPLEMENT_INTRINSIC_HLSL(sign, 0, { 854 code += "sign(" + id_to_name(args[0].base) + ')'; 855 }) 856 IMPLEMENT_INTRINSIC_HLSL(sign, 1, { 857 code += "sign(" + id_to_name(args[0].base) + ')'; 858 }) 859 IMPLEMENT_INTRINSIC_SPIRV(sign, 0, { 860 return 861 add_instruction(spv::OpExtInst, convert_type(res_type)) 862 .add(_glsl_ext) 863 .add(spv::GLSLstd450SSign) 864 .add(args[0].base) 865 .result; 866 }) 867 IMPLEMENT_INTRINSIC_SPIRV(sign, 1, { 868 return 869 add_instruction(spv::OpExtInst, convert_type(res_type)) 870 .add(_glsl_ext) 871 .add(spv::GLSLstd450FSign) 872 .add(args[0].base) 873 .result; 874 }) 875 876 // ret sqrt(x) 877 DEFINE_INTRINSIC(sqrt, 0, float, float) 878 DEFINE_INTRINSIC(sqrt, 0, float2, float2) 879 DEFINE_INTRINSIC(sqrt, 0, float3, float3) 880 DEFINE_INTRINSIC(sqrt, 0, float4, float4) 881 IMPLEMENT_INTRINSIC_GLSL(sqrt, 0, { 882 code += "sqrt(" + id_to_name(args[0].base) + ')'; 883 }) 884 IMPLEMENT_INTRINSIC_HLSL(sqrt, 0, { 885 code += "sqrt(" + id_to_name(args[0].base) + ')'; 886 }) 887 IMPLEMENT_INTRINSIC_SPIRV(sqrt, 0, { 888 return 889 add_instruction(spv::OpExtInst, convert_type(res_type)) 890 .add(_glsl_ext) 891 .add(spv::GLSLstd450Sqrt) 892 .add(args[0].base) 893 .result; 894 }) 895 896 // ret rsqrt(x) 897 DEFINE_INTRINSIC(rsqrt, 0, float, float) 898 DEFINE_INTRINSIC(rsqrt, 0, float2, float2) 899 DEFINE_INTRINSIC(rsqrt, 0, float3, float3) 900 DEFINE_INTRINSIC(rsqrt, 0, float4, float4) 901 IMPLEMENT_INTRINSIC_GLSL(rsqrt, 0, { 902 code += "inversesqrt(" + id_to_name(args[0].base) + ')'; 903 }) 904 IMPLEMENT_INTRINSIC_HLSL(rsqrt, 0, { 905 code += "rsqrt(" + id_to_name(args[0].base) + ')'; 906 }) 907 IMPLEMENT_INTRINSIC_SPIRV(rsqrt, 0, { 908 return 909 add_instruction(spv::OpExtInst, convert_type(res_type)) 910 .add(_glsl_ext) 911 .add(spv::GLSLstd450InverseSqrt) 912 .add(args[0].base) 913 .result; 914 }) 915 916 // ret lerp(x, y, s) 917 DEFINE_INTRINSIC(lerp, 0, float, float, float, float) 918 DEFINE_INTRINSIC(lerp, 0, float2, float2, float2, float2) 919 DEFINE_INTRINSIC(lerp, 0, float3, float3, float3, float3) 920 DEFINE_INTRINSIC(lerp, 0, float4, float4, float4, float4) 921 IMPLEMENT_INTRINSIC_GLSL(lerp, 0, { 922 code += "mix(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ", " + id_to_name(args[2].base) + ')'; 923 }) 924 IMPLEMENT_INTRINSIC_HLSL(lerp, 0, { 925 code += "lerp(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ", " + id_to_name(args[2].base) + ')'; 926 }) 927 IMPLEMENT_INTRINSIC_SPIRV(lerp, 0, { 928 return 929 add_instruction(spv::OpExtInst, convert_type(res_type)) 930 .add(_glsl_ext) 931 .add(spv::GLSLstd450FMix) 932 .add(args[0].base) 933 .add(args[1].base) 934 .add(args[2].base) 935 .result; 936 }) 937 938 // ret step(y, x) 939 DEFINE_INTRINSIC(step, 0, float, float, float) 940 DEFINE_INTRINSIC(step, 0, float2, float2, float2) 941 DEFINE_INTRINSIC(step, 0, float3, float3, float3) 942 DEFINE_INTRINSIC(step, 0, float4, float4, float4) 943 IMPLEMENT_INTRINSIC_GLSL(step, 0, { 944 code += "step(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ')'; 945 }) 946 IMPLEMENT_INTRINSIC_HLSL(step, 0, { 947 code += "step(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ')'; 948 }) 949 IMPLEMENT_INTRINSIC_SPIRV(step, 0, { 950 return 951 add_instruction(spv::OpExtInst, convert_type(res_type)) 952 .add(_glsl_ext) 953 .add(spv::GLSLstd450Step) 954 .add(args[0].base) 955 .add(args[1].base) 956 .result; 957 }) 958 959 // ret smoothstep(min, max, x) 960 DEFINE_INTRINSIC(smoothstep, 0, float, float, float, float) 961 DEFINE_INTRINSIC(smoothstep, 0, float2, float2, float2, float2) 962 DEFINE_INTRINSIC(smoothstep, 0, float3, float3, float3, float3) 963 DEFINE_INTRINSIC(smoothstep, 0, float4, float4, float4, float4) 964 IMPLEMENT_INTRINSIC_GLSL(smoothstep, 0, { 965 code += "smoothstep(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ", " + id_to_name(args[2].base) + ')'; 966 }) 967 IMPLEMENT_INTRINSIC_HLSL(smoothstep, 0, { 968 code += "smoothstep(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ", " + id_to_name(args[2].base) + ')'; 969 }) 970 IMPLEMENT_INTRINSIC_SPIRV(smoothstep, 0, { 971 return 972 add_instruction(spv::OpExtInst, convert_type(args[2].type)) 973 .add(_glsl_ext) 974 .add(spv::GLSLstd450SmoothStep) 975 .add(args[0].base) 976 .add(args[1].base) 977 .add(args[2].base) 978 .result; 979 }) 980 981 // ret frac(x) 982 DEFINE_INTRINSIC(frac, 0, float, float) 983 DEFINE_INTRINSIC(frac, 0, float2, float2) 984 DEFINE_INTRINSIC(frac, 0, float3, float3) 985 DEFINE_INTRINSIC(frac, 0, float4, float4) 986 IMPLEMENT_INTRINSIC_GLSL(frac, 0, { 987 code += "fract(" + id_to_name(args[0].base) + ')'; 988 }) 989 IMPLEMENT_INTRINSIC_HLSL(frac, 0, { 990 code += "frac(" + id_to_name(args[0].base) + ')'; 991 }) 992 IMPLEMENT_INTRINSIC_SPIRV(frac, 0, { 993 return 994 add_instruction(spv::OpExtInst, convert_type(res_type)) 995 .add(_glsl_ext) 996 .add(spv::GLSLstd450Fract) 997 .add(args[0].base) 998 .result; 999 }) 1000 1001 // ret ldexp(x, exp) 1002 DEFINE_INTRINSIC(ldexp, 0, float, float, int) 1003 DEFINE_INTRINSIC(ldexp, 0, float2, float2, int2) 1004 DEFINE_INTRINSIC(ldexp, 0, float3, float3, int3) 1005 DEFINE_INTRINSIC(ldexp, 0, float4, float4, int4) 1006 IMPLEMENT_INTRINSIC_GLSL(ldexp, 0, { 1007 code += "ldexp(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ')'; 1008 }) 1009 IMPLEMENT_INTRINSIC_HLSL(ldexp, 0, { 1010 code += "ldexp(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ')'; 1011 }) 1012 IMPLEMENT_INTRINSIC_SPIRV(ldexp, 0, { 1013 return 1014 add_instruction(spv::OpExtInst, convert_type(res_type)) 1015 .add(_glsl_ext) 1016 .add(spv::GLSLstd450Ldexp) 1017 .add(args[0].base) 1018 .add(args[1].base) 1019 .result; 1020 }) 1021 1022 // ret modf(x, out ip) 1023 DEFINE_INTRINSIC(modf, 0, float, float, out_float) 1024 DEFINE_INTRINSIC(modf, 0, float2, float2, out_float2) 1025 DEFINE_INTRINSIC(modf, 0, float3, float3, out_float3) 1026 DEFINE_INTRINSIC(modf, 0, float4, float4, out_float4) 1027 IMPLEMENT_INTRINSIC_GLSL(modf, 0, { 1028 code += "modf(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ')'; 1029 }) 1030 IMPLEMENT_INTRINSIC_HLSL(modf, 0, { 1031 code += "modf(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ')'; 1032 }) 1033 IMPLEMENT_INTRINSIC_SPIRV(modf, 0, { 1034 return 1035 add_instruction(spv::OpExtInst, convert_type(res_type)) 1036 .add(_glsl_ext) 1037 .add(spv::GLSLstd450Modf) 1038 .add(args[0].base) 1039 .add(args[1].base) 1040 .result; 1041 }) 1042 1043 // ret frexp(x, out exp) 1044 DEFINE_INTRINSIC(frexp, 0, float, float, out_int) 1045 DEFINE_INTRINSIC(frexp, 0, float2, float2, out_int2) 1046 DEFINE_INTRINSIC(frexp, 0, float3, float3, out_int3) 1047 DEFINE_INTRINSIC(frexp, 0, float4, float4, out_int4) 1048 IMPLEMENT_INTRINSIC_GLSL(frexp, 0, { 1049 code += "frexp(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ')'; 1050 }) 1051 IMPLEMENT_INTRINSIC_HLSL(frexp, 0, { 1052 code += "frexp(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ')'; 1053 }) 1054 IMPLEMENT_INTRINSIC_SPIRV(frexp, 0, { 1055 return 1056 add_instruction(spv::OpExtInst, convert_type(res_type)) 1057 .add(_glsl_ext) 1058 .add(spv::GLSLstd450Frexp) 1059 .add(args[0].base) 1060 .add(args[1].base) 1061 .result; 1062 }) 1063 1064 // ret trunc(x) 1065 DEFINE_INTRINSIC(trunc, 0, float, float) 1066 DEFINE_INTRINSIC(trunc, 0, float2, float2) 1067 DEFINE_INTRINSIC(trunc, 0, float3, float3) 1068 DEFINE_INTRINSIC(trunc, 0, float4, float4) 1069 IMPLEMENT_INTRINSIC_GLSL(trunc, 0, { 1070 code += "trunc(" + id_to_name(args[0].base) + ')'; 1071 }) 1072 IMPLEMENT_INTRINSIC_HLSL(trunc, 0, { 1073 code += "trunc(" + id_to_name(args[0].base) + ')'; 1074 }) 1075 IMPLEMENT_INTRINSIC_SPIRV(trunc, 0, { 1076 return 1077 add_instruction(spv::OpExtInst, convert_type(res_type)) 1078 .add(_glsl_ext) 1079 .add(spv::GLSLstd450Trunc) 1080 .add(args[0].base) 1081 .result; 1082 }) 1083 1084 // ret round(x) 1085 DEFINE_INTRINSIC(round, 0, float, float) 1086 DEFINE_INTRINSIC(round, 0, float2, float2) 1087 DEFINE_INTRINSIC(round, 0, float3, float3) 1088 DEFINE_INTRINSIC(round, 0, float4, float4) 1089 IMPLEMENT_INTRINSIC_GLSL(round, 0, { 1090 code += "round(" + id_to_name(args[0].base) + ')'; 1091 }) 1092 IMPLEMENT_INTRINSIC_HLSL(round, 0, { 1093 code += "round(" + id_to_name(args[0].base) + ')'; 1094 }) 1095 IMPLEMENT_INTRINSIC_SPIRV(round, 0, { 1096 return 1097 add_instruction(spv::OpExtInst, convert_type(res_type)) 1098 .add(_glsl_ext) 1099 .add(spv::GLSLstd450Round) 1100 .add(args[0].base) 1101 .result; 1102 }) 1103 1104 // ret min(x, y) 1105 DEFINE_INTRINSIC(min, 0, int, int, int) 1106 DEFINE_INTRINSIC(min, 0, int2, int2, int2) 1107 DEFINE_INTRINSIC(min, 0, int3, int3, int3) 1108 DEFINE_INTRINSIC(min, 0, int4, int4, int4) 1109 DEFINE_INTRINSIC(min, 1, float, float, float) 1110 DEFINE_INTRINSIC(min, 1, float2, float2, float2) 1111 DEFINE_INTRINSIC(min, 1, float3, float3, float3) 1112 DEFINE_INTRINSIC(min, 1, float4, float4, float4) 1113 IMPLEMENT_INTRINSIC_GLSL(min, 0, { 1114 code += "min(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ')'; 1115 }) 1116 IMPLEMENT_INTRINSIC_GLSL(min, 1, { 1117 code += "min(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ')'; 1118 }) 1119 IMPLEMENT_INTRINSIC_HLSL(min, 0, { 1120 code += "min(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ')'; 1121 }) 1122 IMPLEMENT_INTRINSIC_HLSL(min, 1, { 1123 code += "min(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ')'; 1124 }) 1125 IMPLEMENT_INTRINSIC_SPIRV(min, 0, { 1126 return 1127 add_instruction(spv::OpExtInst, convert_type(res_type)) 1128 .add(_glsl_ext) 1129 .add(spv::GLSLstd450SMin) 1130 .add(args[0].base) 1131 .add(args[1].base) 1132 .result; 1133 }) 1134 IMPLEMENT_INTRINSIC_SPIRV(min, 1, { 1135 return 1136 add_instruction(spv::OpExtInst, convert_type(res_type)) 1137 .add(_glsl_ext) 1138 .add(spv::GLSLstd450FMin) 1139 .add(args[0].base) 1140 .add(args[1].base) 1141 .result; 1142 }) 1143 1144 // ret max(x, y) 1145 DEFINE_INTRINSIC(max, 0, int, int, int) 1146 DEFINE_INTRINSIC(max, 0, int2, int2, int2) 1147 DEFINE_INTRINSIC(max, 0, int3, int3, int3) 1148 DEFINE_INTRINSIC(max, 0, int4, int4, int4) 1149 DEFINE_INTRINSIC(max, 1, float, float, float) 1150 DEFINE_INTRINSIC(max, 1, float2, float2, float2) 1151 DEFINE_INTRINSIC(max, 1, float3, float3, float3) 1152 DEFINE_INTRINSIC(max, 1, float4, float4, float4) 1153 IMPLEMENT_INTRINSIC_GLSL(max, 0, { 1154 code += "max(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ')'; 1155 }) 1156 IMPLEMENT_INTRINSIC_GLSL(max, 1, { 1157 code += "max(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ')'; 1158 }) 1159 IMPLEMENT_INTRINSIC_HLSL(max, 0, { 1160 code += "max(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ')'; 1161 }) 1162 IMPLEMENT_INTRINSIC_HLSL(max, 1, { 1163 code += "max(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ')'; 1164 }) 1165 IMPLEMENT_INTRINSIC_SPIRV(max, 0, { 1166 return 1167 add_instruction(spv::OpExtInst, convert_type(res_type)) 1168 .add(_glsl_ext) 1169 .add(spv::GLSLstd450SMax) 1170 .add(args[0].base) 1171 .add(args[1].base) 1172 .result; 1173 }) 1174 IMPLEMENT_INTRINSIC_SPIRV(max, 1, { 1175 return 1176 add_instruction(spv::OpExtInst, convert_type(res_type)) 1177 .add(_glsl_ext) 1178 .add(spv::GLSLstd450FMax) 1179 .add(args[0].base) 1180 .add(args[1].base) 1181 .result; 1182 }) 1183 1184 // ret degree(x) 1185 DEFINE_INTRINSIC(degrees, 0, float, float) 1186 DEFINE_INTRINSIC(degrees, 0, float2, float2) 1187 DEFINE_INTRINSIC(degrees, 0, float3, float3) 1188 DEFINE_INTRINSIC(degrees, 0, float4, float4) 1189 IMPLEMENT_INTRINSIC_GLSL(degrees, 0, { 1190 code += "degrees(" + id_to_name(args[0].base) + ')'; 1191 }) 1192 IMPLEMENT_INTRINSIC_HLSL(degrees, 0, { 1193 code += "degrees(" + id_to_name(args[0].base) + ')'; 1194 }) 1195 IMPLEMENT_INTRINSIC_SPIRV(degrees, 0, { 1196 return 1197 add_instruction(spv::OpExtInst, convert_type(res_type)) 1198 .add(_glsl_ext) 1199 .add(spv::GLSLstd450Degrees) 1200 .add(args[0].base) 1201 .result; 1202 }) 1203 1204 // ret radians(x) 1205 DEFINE_INTRINSIC(radians, 0, float, float) 1206 DEFINE_INTRINSIC(radians, 0, float2, float2) 1207 DEFINE_INTRINSIC(radians, 0, float3, float3) 1208 DEFINE_INTRINSIC(radians, 0, float4, float4) 1209 IMPLEMENT_INTRINSIC_GLSL(radians, 0, { 1210 code += "radians(" + id_to_name(args[0].base) + ')'; 1211 }) 1212 IMPLEMENT_INTRINSIC_HLSL(radians, 0, { 1213 code += "radians(" + id_to_name(args[0].base) + ')'; 1214 }) 1215 IMPLEMENT_INTRINSIC_SPIRV(radians, 0, { 1216 return 1217 add_instruction(spv::OpExtInst, convert_type(res_type)) 1218 .add(_glsl_ext) 1219 .add(spv::GLSLstd450Radians) 1220 .add(args[0].base) 1221 .result; 1222 }) 1223 1224 // ret ddx(x) 1225 DEFINE_INTRINSIC(ddx, 0, float, float) 1226 DEFINE_INTRINSIC(ddx, 0, float2, float2) 1227 DEFINE_INTRINSIC(ddx, 0, float3, float3) 1228 DEFINE_INTRINSIC(ddx, 0, float4, float4) 1229 IMPLEMENT_INTRINSIC_GLSL(ddx, 0, { 1230 code += "dFdx(" + id_to_name(args[0].base) + ')'; 1231 }) 1232 IMPLEMENT_INTRINSIC_HLSL(ddx, 0, { 1233 code += "ddx(" + id_to_name(args[0].base) + ')'; 1234 }) 1235 IMPLEMENT_INTRINSIC_SPIRV(ddx, 0, { 1236 return 1237 add_instruction(spv::OpDPdx, convert_type(res_type)) 1238 .add(args[0].base) 1239 .result; 1240 }) 1241 1242 // ret ddy(x) 1243 DEFINE_INTRINSIC(ddy, 0, float, float) 1244 DEFINE_INTRINSIC(ddy, 0, float2, float2) 1245 DEFINE_INTRINSIC(ddy, 0, float3, float3) 1246 DEFINE_INTRINSIC(ddy, 0, float4, float4) 1247 IMPLEMENT_INTRINSIC_GLSL(ddy, 0, { 1248 code += "dFdy(" + id_to_name(args[0].base) + ')'; 1249 }) 1250 IMPLEMENT_INTRINSIC_HLSL(ddy, 0, { 1251 code += "ddy(" + id_to_name(args[0].base) + ')'; 1252 }) 1253 IMPLEMENT_INTRINSIC_SPIRV(ddy, 0, { 1254 return 1255 add_instruction(spv::OpDPdy, convert_type(res_type)) 1256 .add(args[0].base) 1257 .result; 1258 }) 1259 1260 // ret fwidth(x) 1261 DEFINE_INTRINSIC(fwidth, 0, float, float) 1262 DEFINE_INTRINSIC(fwidth, 0, float2, float2) 1263 DEFINE_INTRINSIC(fwidth, 0, float3, float3) 1264 DEFINE_INTRINSIC(fwidth, 0, float4, float4) 1265 IMPLEMENT_INTRINSIC_GLSL(fwidth, 0, { 1266 code += "fwidth(" + id_to_name(args[0].base) + ')'; 1267 }) 1268 IMPLEMENT_INTRINSIC_HLSL(fwidth, 0, { 1269 code += "fwidth(" + id_to_name(args[0].base) + ')'; 1270 }) 1271 IMPLEMENT_INTRINSIC_SPIRV(fwidth, 0, { 1272 return 1273 add_instruction(spv::OpFwidth, convert_type(res_type)) 1274 .add(args[0].base) 1275 .result; 1276 }) 1277 1278 // ret dot(x, y) 1279 DEFINE_INTRINSIC(dot, 0, float, float, float) 1280 DEFINE_INTRINSIC(dot, 1, float, float2, float2) 1281 DEFINE_INTRINSIC(dot, 1, float, float3, float3) 1282 DEFINE_INTRINSIC(dot, 1, float, float4, float4) 1283 IMPLEMENT_INTRINSIC_GLSL(dot, 0, { 1284 code += '(' + id_to_name(args[0].base) + " * " + id_to_name(args[1].base) + ')'; 1285 }) 1286 IMPLEMENT_INTRINSIC_GLSL(dot, 1, { 1287 code += "dot(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ')'; 1288 }) 1289 IMPLEMENT_INTRINSIC_HLSL(dot, 0, { 1290 code += '(' + id_to_name(args[0].base) + " * " + id_to_name(args[1].base) + ')'; 1291 }) 1292 IMPLEMENT_INTRINSIC_HLSL(dot, 1, { 1293 code += "dot(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ')'; 1294 }) 1295 IMPLEMENT_INTRINSIC_SPIRV(dot, 0, { 1296 return 1297 add_instruction(spv::OpFMul, convert_type(res_type)) 1298 .add(args[0].base) 1299 .add(args[1].base) 1300 .result; 1301 }) 1302 IMPLEMENT_INTRINSIC_SPIRV(dot, 1, { 1303 return 1304 add_instruction(spv::OpDot, convert_type(res_type)) 1305 .add(args[0].base) 1306 .add(args[1].base) 1307 .result; 1308 }) 1309 1310 // ret cross(x, y) 1311 DEFINE_INTRINSIC(cross, 0, float3, float3, float3) 1312 IMPLEMENT_INTRINSIC_GLSL(cross, 0, { 1313 code += "cross(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ')'; 1314 }) 1315 IMPLEMENT_INTRINSIC_HLSL(cross, 0, { 1316 code += "cross(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ')'; 1317 }) 1318 IMPLEMENT_INTRINSIC_SPIRV(cross, 0, { 1319 return 1320 add_instruction(spv::OpExtInst, convert_type(res_type)) 1321 .add(_glsl_ext) 1322 .add(spv::GLSLstd450Cross) 1323 .add(args[0].base) 1324 .add(args[1].base) 1325 .result; 1326 }) 1327 1328 // ret length(x) 1329 DEFINE_INTRINSIC(length, 0, float, float) 1330 DEFINE_INTRINSIC(length, 0, float, float2) 1331 DEFINE_INTRINSIC(length, 0, float, float3) 1332 DEFINE_INTRINSIC(length, 0, float, float4) 1333 IMPLEMENT_INTRINSIC_GLSL(length, 0, { 1334 code += "length(" + id_to_name(args[0].base) + ')'; 1335 }) 1336 IMPLEMENT_INTRINSIC_HLSL(length, 0, { 1337 code += "length(" + id_to_name(args[0].base) + ')'; 1338 }) 1339 IMPLEMENT_INTRINSIC_SPIRV(length, 0, { 1340 return 1341 add_instruction(spv::OpExtInst, convert_type(res_type)) 1342 .add(_glsl_ext) 1343 .add(spv::GLSLstd450Length) 1344 .add(args[0].base) 1345 .result; 1346 }) 1347 1348 // ret distance(x, y) 1349 DEFINE_INTRINSIC(distance, 0, float, float, float) 1350 DEFINE_INTRINSIC(distance, 0, float, float2, float2) 1351 DEFINE_INTRINSIC(distance, 0, float, float3, float3) 1352 DEFINE_INTRINSIC(distance, 0, float, float4, float4) 1353 IMPLEMENT_INTRINSIC_GLSL(distance, 0, { 1354 code += "distance(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ')'; 1355 }) 1356 IMPLEMENT_INTRINSIC_HLSL(distance, 0, { 1357 code += "distance(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ')'; 1358 }) 1359 IMPLEMENT_INTRINSIC_SPIRV(distance, 0, { 1360 return 1361 add_instruction(spv::OpExtInst, convert_type(res_type)) 1362 .add(_glsl_ext) 1363 .add(spv::GLSLstd450Distance) 1364 .add(args[0].base) 1365 .add(args[1].base) 1366 .result; 1367 }) 1368 1369 // ret normalize(x) 1370 DEFINE_INTRINSIC(normalize, 0, float2, float2) 1371 DEFINE_INTRINSIC(normalize, 0, float3, float3) 1372 DEFINE_INTRINSIC(normalize, 0, float4, float4) 1373 IMPLEMENT_INTRINSIC_GLSL(normalize, 0, { 1374 code += "normalize(" + id_to_name(args[0].base) + ')'; 1375 }) 1376 IMPLEMENT_INTRINSIC_HLSL(normalize, 0, { 1377 code += "normalize(" + id_to_name(args[0].base) + ')'; 1378 }) 1379 IMPLEMENT_INTRINSIC_SPIRV(normalize, 0, { 1380 return 1381 add_instruction(spv::OpExtInst, convert_type(res_type)) 1382 .add(_glsl_ext) 1383 .add(spv::GLSLstd450Normalize) 1384 .add(args[0].base) 1385 .result; 1386 }) 1387 1388 // ret transpose(x) 1389 DEFINE_INTRINSIC(transpose, 0, float2x2, float2x2) 1390 DEFINE_INTRINSIC(transpose, 0, float2x3, float3x2) 1391 DEFINE_INTRINSIC(transpose, 0, float2x4, float4x2) 1392 DEFINE_INTRINSIC(transpose, 0, float3x2, float2x3) 1393 DEFINE_INTRINSIC(transpose, 0, float3x3, float3x3) 1394 DEFINE_INTRINSIC(transpose, 0, float3x4, float4x3) 1395 DEFINE_INTRINSIC(transpose, 0, float4x2, float2x4) 1396 DEFINE_INTRINSIC(transpose, 0, float4x3, float3x4) 1397 DEFINE_INTRINSIC(transpose, 0, float4x4, float4x4) 1398 IMPLEMENT_INTRINSIC_GLSL(transpose, 0, { 1399 code += "transpose(" + id_to_name(args[0].base) + ')'; 1400 }) 1401 IMPLEMENT_INTRINSIC_HLSL(transpose, 0, { 1402 code += "transpose(" + id_to_name(args[0].base) + ')'; 1403 }) 1404 IMPLEMENT_INTRINSIC_SPIRV(transpose, 0, { 1405 return 1406 add_instruction(spv::OpTranspose, convert_type(res_type)) 1407 .add(args[0].base) 1408 .result; 1409 }) 1410 1411 // ret determinant(m) 1412 DEFINE_INTRINSIC(determinant, 0, float, float2x2) 1413 DEFINE_INTRINSIC(determinant, 0, float, float3x3) 1414 DEFINE_INTRINSIC(determinant, 0, float, float4x4) 1415 IMPLEMENT_INTRINSIC_GLSL(determinant, 0, { 1416 code += "determinant(" + id_to_name(args[0].base) + ')'; 1417 }) 1418 IMPLEMENT_INTRINSIC_HLSL(determinant, 0, { 1419 code += "determinant(" + id_to_name(args[0].base) + ')'; 1420 }) 1421 IMPLEMENT_INTRINSIC_SPIRV(determinant, 0, { 1422 return 1423 add_instruction(spv::OpExtInst, convert_type(res_type)) 1424 .add(_glsl_ext) 1425 .add(spv::GLSLstd450Determinant) 1426 .add(args[0].base) 1427 .result; 1428 }) 1429 1430 // ret reflect(i, n) 1431 DEFINE_INTRINSIC(reflect, 0, float2, float2, float2) 1432 DEFINE_INTRINSIC(reflect, 0, float3, float3, float3) 1433 DEFINE_INTRINSIC(reflect, 0, float4, float4, float4) 1434 IMPLEMENT_INTRINSIC_GLSL(reflect, 0, { 1435 code += "reflect(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ')'; 1436 }) 1437 IMPLEMENT_INTRINSIC_HLSL(reflect, 0, { 1438 code += "reflect(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ')'; 1439 }) 1440 IMPLEMENT_INTRINSIC_SPIRV(reflect, 0, { 1441 return 1442 add_instruction(spv::OpExtInst, convert_type(res_type)) 1443 .add(_glsl_ext) 1444 .add(spv::GLSLstd450Reflect) 1445 .add(args[0].base) 1446 .add(args[1].base) 1447 .result; 1448 }) 1449 1450 // ret refract(i, n, eta) 1451 DEFINE_INTRINSIC(refract, 0, float2, float2, float2, float) 1452 DEFINE_INTRINSIC(refract, 0, float3, float3, float3, float) 1453 DEFINE_INTRINSIC(refract, 0, float4, float4, float4, float) 1454 IMPLEMENT_INTRINSIC_GLSL(refract, 0, { 1455 code += "refract(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ", " + id_to_name(args[1].base) + ')'; 1456 }) 1457 IMPLEMENT_INTRINSIC_HLSL(refract, 0, { 1458 code += "refract(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ", " + id_to_name(args[1].base) + ')'; 1459 }) 1460 IMPLEMENT_INTRINSIC_SPIRV(refract, 0, { 1461 return 1462 add_instruction(spv::OpExtInst, convert_type(res_type)) 1463 .add(_glsl_ext) 1464 .add(spv::GLSLstd450Refract) 1465 .add(args[0].base) 1466 .add(args[1].base) 1467 .add(args[2].base) 1468 .result; 1469 }) 1470 1471 // ret faceforward(n, i, ng) 1472 DEFINE_INTRINSIC(faceforward, 0, float, float, float, float) 1473 DEFINE_INTRINSIC(faceforward, 0, float2, float2, float2, float2) 1474 DEFINE_INTRINSIC(faceforward, 0, float3, float3, float3, float3) 1475 DEFINE_INTRINSIC(faceforward, 0, float4, float4, float4, float4) 1476 IMPLEMENT_INTRINSIC_GLSL(faceforward, 0, { 1477 code += "faceforward(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ", " + id_to_name(args[1].base) + ')'; 1478 }) 1479 IMPLEMENT_INTRINSIC_HLSL(faceforward, 0, { 1480 code += "faceforward(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ", " + id_to_name(args[1].base) + ')'; 1481 }) 1482 IMPLEMENT_INTRINSIC_SPIRV(faceforward, 0, { 1483 return 1484 add_instruction(spv::OpExtInst, convert_type(res_type)) 1485 .add(_glsl_ext) 1486 .add(spv::GLSLstd450FaceForward) 1487 .add(args[0].base) 1488 .add(args[1].base) 1489 .add(args[2].base) 1490 .result; 1491 }) 1492 1493 // ret mul(x, y) 1494 DEFINE_INTRINSIC(mul, 0, int2, int, int2) 1495 DEFINE_INTRINSIC(mul, 0, int3, int, int3) 1496 DEFINE_INTRINSIC(mul, 0, int4, int, int4) 1497 DEFINE_INTRINSIC(mul, 0, float2, float, float2) 1498 DEFINE_INTRINSIC(mul, 0, float3, float, float3) 1499 DEFINE_INTRINSIC(mul, 0, float4, float, float4) 1500 IMPLEMENT_INTRINSIC_GLSL(mul, 0, { 1501 code += '(' + id_to_name(args[0].base) + " * " + id_to_name(args[1].base) + ')'; 1502 }) 1503 IMPLEMENT_INTRINSIC_HLSL(mul, 0, { 1504 code += '(' + id_to_name(args[0].base) + " * " + id_to_name(args[1].base) + ')'; 1505 }) 1506 IMPLEMENT_INTRINSIC_SPIRV(mul, 0, { 1507 return 1508 add_instruction(spv::OpVectorTimesScalar, convert_type(res_type)) 1509 .add(args[1].base) 1510 .add(args[0].base) 1511 .result; 1512 }) 1513 DEFINE_INTRINSIC(mul, 1, int2, int2, int) 1514 DEFINE_INTRINSIC(mul, 1, int3, int3, int) 1515 DEFINE_INTRINSIC(mul, 1, int4, int4, int) 1516 DEFINE_INTRINSIC(mul, 1, float2, float2, float) 1517 DEFINE_INTRINSIC(mul, 1, float3, float3, float) 1518 DEFINE_INTRINSIC(mul, 1, float4, float4, float) 1519 IMPLEMENT_INTRINSIC_GLSL(mul, 1, { 1520 code += '(' + id_to_name(args[0].base) + " * " + id_to_name(args[1].base) + ')'; 1521 }) 1522 IMPLEMENT_INTRINSIC_HLSL(mul, 1, { 1523 code += '(' + id_to_name(args[0].base) + " * " + id_to_name(args[1].base) + ')'; 1524 }) 1525 IMPLEMENT_INTRINSIC_SPIRV(mul, 1, { 1526 return 1527 add_instruction(spv::OpVectorTimesScalar, convert_type(res_type)) 1528 .add(args[0].base) 1529 .add(args[1].base) 1530 .result; 1531 }) 1532 1533 DEFINE_INTRINSIC(mul, 2, int2x2, int, int2x2) 1534 DEFINE_INTRINSIC(mul, 2, int2x3, int, int2x3) 1535 DEFINE_INTRINSIC(mul, 2, int2x4, int, int2x4) 1536 DEFINE_INTRINSIC(mul, 2, int3x2, int, int3x2) 1537 DEFINE_INTRINSIC(mul, 2, int3x3, int, int3x3) 1538 DEFINE_INTRINSIC(mul, 2, int3x4, int, int3x4) 1539 DEFINE_INTRINSIC(mul, 2, int4x2, int, int4x2) 1540 DEFINE_INTRINSIC(mul, 2, int4x3, int, int4x3) 1541 DEFINE_INTRINSIC(mul, 2, int4x4, int, int4x4) 1542 DEFINE_INTRINSIC(mul, 2, float2x2, float, float2x2) 1543 DEFINE_INTRINSIC(mul, 2, float2x3, float, float2x3) 1544 DEFINE_INTRINSIC(mul, 2, float2x4, float, float2x4) 1545 DEFINE_INTRINSIC(mul, 2, float3x2, float, float3x2) 1546 DEFINE_INTRINSIC(mul, 2, float3x3, float, float3x3) 1547 DEFINE_INTRINSIC(mul, 2, float3x4, float, float3x4) 1548 DEFINE_INTRINSIC(mul, 2, float4x2, float, float4x2) 1549 DEFINE_INTRINSIC(mul, 2, float4x3, float, float4x3) 1550 DEFINE_INTRINSIC(mul, 2, float4x4, float, float4x4) 1551 IMPLEMENT_INTRINSIC_GLSL(mul, 2, { 1552 code += '(' + id_to_name(args[0].base) + " * " + id_to_name(args[1].base) + ')'; 1553 }) 1554 IMPLEMENT_INTRINSIC_HLSL(mul, 2, { 1555 code += '(' + id_to_name(args[0].base) + " * " + id_to_name(args[1].base) + ')'; 1556 }) 1557 IMPLEMENT_INTRINSIC_SPIRV(mul, 2, { 1558 return 1559 add_instruction(spv::OpMatrixTimesScalar, convert_type(res_type)) 1560 .add(args[1].base) 1561 .add(args[0].base) 1562 .result; 1563 }) 1564 DEFINE_INTRINSIC(mul, 3, int2x2, int2x2, int) 1565 DEFINE_INTRINSIC(mul, 3, int2x3, int2x3, int) 1566 DEFINE_INTRINSIC(mul, 3, int2x4, int2x4, int) 1567 DEFINE_INTRINSIC(mul, 3, int3x2, int3x2, int) 1568 DEFINE_INTRINSIC(mul, 3, int3x3, int3x3, int) 1569 DEFINE_INTRINSIC(mul, 3, int3x4, int3x4, int) 1570 DEFINE_INTRINSIC(mul, 3, int4x2, int4x2, int) 1571 DEFINE_INTRINSIC(mul, 3, int4x3, int4x3, int) 1572 DEFINE_INTRINSIC(mul, 3, int4x4, int4x4, int) 1573 DEFINE_INTRINSIC(mul, 3, float2x2, float2x2, float) 1574 DEFINE_INTRINSIC(mul, 3, float2x3, float2x3, float) 1575 DEFINE_INTRINSIC(mul, 3, float2x4, float2x4, float) 1576 DEFINE_INTRINSIC(mul, 3, float3x2, float3x2, float) 1577 DEFINE_INTRINSIC(mul, 3, float3x3, float3x3, float) 1578 DEFINE_INTRINSIC(mul, 3, float3x4, float3x4, float) 1579 DEFINE_INTRINSIC(mul, 3, float4x2, float4x2, float) 1580 DEFINE_INTRINSIC(mul, 3, float4x3, float4x3, float) 1581 DEFINE_INTRINSIC(mul, 3, float4x4, float4x4, float) 1582 IMPLEMENT_INTRINSIC_GLSL(mul, 3, { 1583 code += '(' + id_to_name(args[0].base) + " * " + id_to_name(args[1].base) + ')'; 1584 }) 1585 IMPLEMENT_INTRINSIC_HLSL(mul, 3, { 1586 code += '(' + id_to_name(args[0].base) + " * " + id_to_name(args[1].base) + ')'; 1587 }) 1588 IMPLEMENT_INTRINSIC_SPIRV(mul, 3, { 1589 return 1590 add_instruction(spv::OpMatrixTimesScalar, convert_type(res_type)) 1591 .add(args[0].base) 1592 .add(args[1].base) 1593 .result; 1594 }) 1595 1596 DEFINE_INTRINSIC(mul, 4, int2, int2, int2x2) 1597 DEFINE_INTRINSIC(mul, 4, int3, int2, int2x3) 1598 DEFINE_INTRINSIC(mul, 4, int4, int2, int2x4) 1599 DEFINE_INTRINSIC(mul, 4, int2, int3, int3x2) 1600 DEFINE_INTRINSIC(mul, 4, int3, int3, int3x3) 1601 DEFINE_INTRINSIC(mul, 4, int4, int3, int3x4) 1602 DEFINE_INTRINSIC(mul, 4, int2, int4, int4x2) 1603 DEFINE_INTRINSIC(mul, 4, int3, int4, int4x3) 1604 DEFINE_INTRINSIC(mul, 4, int4, int4, int4x4) 1605 DEFINE_INTRINSIC(mul, 4, float2, float2, float2x2) 1606 DEFINE_INTRINSIC(mul, 4, float3, float2, float2x3) 1607 DEFINE_INTRINSIC(mul, 4, float4, float2, float2x4) 1608 DEFINE_INTRINSIC(mul, 4, float2, float3, float3x2) 1609 DEFINE_INTRINSIC(mul, 4, float3, float3, float3x3) 1610 DEFINE_INTRINSIC(mul, 4, float4, float3, float3x4) 1611 DEFINE_INTRINSIC(mul, 4, float2, float4, float4x2) 1612 DEFINE_INTRINSIC(mul, 4, float3, float4, float4x3) 1613 DEFINE_INTRINSIC(mul, 4, float4, float4, float4x4) 1614 IMPLEMENT_INTRINSIC_GLSL(mul, 4, { 1615 // Flip inputs because matrices are column-wise 1616 code += '(' + id_to_name(args[1].base) + " * " + id_to_name(args[0].base) + ')'; 1617 }) 1618 IMPLEMENT_INTRINSIC_HLSL(mul, 4, { 1619 code += "mul(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ')'; 1620 }) 1621 IMPLEMENT_INTRINSIC_SPIRV(mul, 4, { 1622 return 1623 add_instruction(spv::OpMatrixTimesVector, convert_type(res_type)) 1624 .add(args[1].base) // Flip inputs because matrices are column-wise 1625 .add(args[0].base) 1626 .result; 1627 }) 1628 DEFINE_INTRINSIC(mul, 5, int2, int2x2, int2) 1629 DEFINE_INTRINSIC(mul, 5, int2, int2x3, int3) 1630 DEFINE_INTRINSIC(mul, 5, int2, int2x4, int4) 1631 DEFINE_INTRINSIC(mul, 5, int3, int3x2, int2) 1632 DEFINE_INTRINSIC(mul, 5, int3, int3x3, int3) 1633 DEFINE_INTRINSIC(mul, 5, int3, int3x4, int4) 1634 DEFINE_INTRINSIC(mul, 5, int4, int4x2, int2) 1635 DEFINE_INTRINSIC(mul, 5, int4, int4x3, int3) 1636 DEFINE_INTRINSIC(mul, 5, int4, int4x4, int4) 1637 DEFINE_INTRINSIC(mul, 5, float2, float2x2, float2) 1638 DEFINE_INTRINSIC(mul, 5, float2, float2x3, float3) 1639 DEFINE_INTRINSIC(mul, 5, float2, float2x4, float4) 1640 DEFINE_INTRINSIC(mul, 5, float3, float3x2, float2) 1641 DEFINE_INTRINSIC(mul, 5, float3, float3x3, float3) 1642 DEFINE_INTRINSIC(mul, 5, float3, float3x4, float4) 1643 DEFINE_INTRINSIC(mul, 5, float4, float4x2, float2) 1644 DEFINE_INTRINSIC(mul, 5, float4, float4x3, float3) 1645 DEFINE_INTRINSIC(mul, 5, float4, float4x4, float4) 1646 IMPLEMENT_INTRINSIC_GLSL(mul, 5, { 1647 // Flip inputs because matrices are column-wise 1648 code += '(' + id_to_name(args[1].base) + " * " + id_to_name(args[0].base) + ')'; 1649 }) 1650 IMPLEMENT_INTRINSIC_HLSL(mul, 5, { 1651 code += "mul(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ')'; 1652 }) 1653 IMPLEMENT_INTRINSIC_SPIRV(mul, 5, { 1654 return 1655 add_instruction(spv::OpVectorTimesMatrix, convert_type(res_type)) 1656 .add(args[1].base) // Flip inputs because matrices are column-wise 1657 .add(args[0].base) 1658 .result; 1659 }) 1660 1661 DEFINE_INTRINSIC(mul, 6, int2x2, int2x2, int2x2) 1662 DEFINE_INTRINSIC(mul, 6, int2x3, int2x2, int2x3) 1663 DEFINE_INTRINSIC(mul, 6, int2x4, int2x2, int2x4) 1664 DEFINE_INTRINSIC(mul, 6, int2x2, int2x3, int3x2) 1665 DEFINE_INTRINSIC(mul, 6, int2x3, int2x3, int3x3) 1666 DEFINE_INTRINSIC(mul, 6, int2x4, int2x3, int3x4) 1667 DEFINE_INTRINSIC(mul, 6, int2x2, int2x4, int4x2) 1668 DEFINE_INTRINSIC(mul, 6, int2x3, int2x4, int4x3) 1669 DEFINE_INTRINSIC(mul, 6, int2x4, int2x4, int4x4) 1670 DEFINE_INTRINSIC(mul, 6, int3x2, int3x2, int2x2) 1671 DEFINE_INTRINSIC(mul, 6, int3x3, int3x2, int2x3) 1672 DEFINE_INTRINSIC(mul, 6, int3x4, int3x2, int2x4) 1673 DEFINE_INTRINSIC(mul, 6, int3x2, int3x3, int3x2) 1674 DEFINE_INTRINSIC(mul, 6, int3x3, int3x3, int3x3) 1675 DEFINE_INTRINSIC(mul, 6, int3x4, int3x3, int3x4) 1676 DEFINE_INTRINSIC(mul, 6, int3x2, int3x4, int4x2) 1677 DEFINE_INTRINSIC(mul, 6, int3x3, int3x4, int4x3) 1678 DEFINE_INTRINSIC(mul, 6, int3x4, int3x4, int4x4) 1679 DEFINE_INTRINSIC(mul, 6, int4x2, int4x2, int2x2) 1680 DEFINE_INTRINSIC(mul, 6, int4x3, int4x2, int2x3) 1681 DEFINE_INTRINSIC(mul, 6, int4x4, int4x2, int2x4) 1682 DEFINE_INTRINSIC(mul, 6, int4x2, int4x3, int3x2) 1683 DEFINE_INTRINSIC(mul, 6, int4x3, int4x3, int3x3) 1684 DEFINE_INTRINSIC(mul, 6, int4x4, int4x3, int3x4) 1685 DEFINE_INTRINSIC(mul, 6, int4x2, int4x4, int4x2) 1686 DEFINE_INTRINSIC(mul, 6, int4x3, int4x4, int4x3) 1687 DEFINE_INTRINSIC(mul, 6, int4x4, int4x4, int4x4) 1688 DEFINE_INTRINSIC(mul, 6, float2x2, float2x2, float2x2) 1689 DEFINE_INTRINSIC(mul, 6, float2x3, float2x2, float2x3) 1690 DEFINE_INTRINSIC(mul, 6, float2x4, float2x2, float2x4) 1691 DEFINE_INTRINSIC(mul, 6, float2x2, float2x3, float3x2) 1692 DEFINE_INTRINSIC(mul, 6, float2x3, float2x3, float3x3) 1693 DEFINE_INTRINSIC(mul, 6, float2x4, float2x3, float3x4) 1694 DEFINE_INTRINSIC(mul, 6, float2x2, float2x4, float4x2) 1695 DEFINE_INTRINSIC(mul, 6, float2x3, float2x4, float4x3) 1696 DEFINE_INTRINSIC(mul, 6, float2x4, float2x4, float4x4) 1697 DEFINE_INTRINSIC(mul, 6, float3x2, float3x2, float2x2) 1698 DEFINE_INTRINSIC(mul, 6, float3x3, float3x2, float2x3) 1699 DEFINE_INTRINSIC(mul, 6, float3x4, float3x2, float2x4) 1700 DEFINE_INTRINSIC(mul, 6, float3x2, float3x3, float3x2) 1701 DEFINE_INTRINSIC(mul, 6, float3x3, float3x3, float3x3) 1702 DEFINE_INTRINSIC(mul, 6, float3x4, float3x3, float3x4) 1703 DEFINE_INTRINSIC(mul, 6, float3x2, float3x4, float4x2) 1704 DEFINE_INTRINSIC(mul, 6, float3x3, float3x4, float4x3) 1705 DEFINE_INTRINSIC(mul, 6, float3x4, float3x4, float4x4) 1706 DEFINE_INTRINSIC(mul, 6, float4x2, float4x2, float2x2) 1707 DEFINE_INTRINSIC(mul, 6, float4x3, float4x2, float2x3) 1708 DEFINE_INTRINSIC(mul, 6, float4x4, float4x2, float2x4) 1709 DEFINE_INTRINSIC(mul, 6, float4x2, float4x3, float3x2) 1710 DEFINE_INTRINSIC(mul, 6, float4x3, float4x3, float3x3) 1711 DEFINE_INTRINSIC(mul, 6, float4x4, float4x3, float3x4) 1712 DEFINE_INTRINSIC(mul, 6, float4x2, float4x4, float4x2) 1713 DEFINE_INTRINSIC(mul, 6, float4x3, float4x4, float4x3) 1714 DEFINE_INTRINSIC(mul, 6, float4x4, float4x4, float4x4) 1715 IMPLEMENT_INTRINSIC_GLSL(mul, 6, { 1716 // Flip inputs because matrices are column-wise 1717 code += '(' + id_to_name(args[1].base) + " * " + id_to_name(args[0].base) + ')'; 1718 }) 1719 IMPLEMENT_INTRINSIC_HLSL(mul, 6, { 1720 code += "mul(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ')'; 1721 }) 1722 IMPLEMENT_INTRINSIC_SPIRV(mul, 6, { 1723 return 1724 add_instruction(spv::OpMatrixTimesMatrix, convert_type(res_type)) 1725 .add(args[1].base) // Flip inputs because matrices are column-wise 1726 .add(args[0].base) 1727 .result; 1728 }) 1729 1730 // ret isinf(x) 1731 DEFINE_INTRINSIC(isinf, 0, bool, float) 1732 DEFINE_INTRINSIC(isinf, 0, bool2, float2) 1733 DEFINE_INTRINSIC(isinf, 0, bool3, float3) 1734 DEFINE_INTRINSIC(isinf, 0, bool4, float4) 1735 IMPLEMENT_INTRINSIC_GLSL(isinf, 0, { 1736 code += "isinf(" + id_to_name(args[0].base) + ')'; 1737 }) 1738 IMPLEMENT_INTRINSIC_HLSL(isinf, 0, { 1739 code += "isinf(" + id_to_name(args[0].base) + ')'; 1740 }) 1741 IMPLEMENT_INTRINSIC_SPIRV(isinf, 0, { 1742 return 1743 add_instruction(spv::OpIsInf, convert_type(res_type)) 1744 .add(args[0].base) 1745 .result; 1746 }) 1747 1748 // ret isnan(x) 1749 DEFINE_INTRINSIC(isnan, 0, bool, float) 1750 DEFINE_INTRINSIC(isnan, 0, bool2, float2) 1751 DEFINE_INTRINSIC(isnan, 0, bool3, float3) 1752 DEFINE_INTRINSIC(isnan, 0, bool4, float4) 1753 IMPLEMENT_INTRINSIC_GLSL(isnan, 0, { 1754 code += "isnan(" + id_to_name(args[0].base) + ')'; 1755 }) 1756 IMPLEMENT_INTRINSIC_HLSL(isnan, 0, { 1757 code += "isnan(" + id_to_name(args[0].base) + ')'; 1758 }) 1759 IMPLEMENT_INTRINSIC_SPIRV(isnan, 0, { 1760 return 1761 add_instruction(spv::OpIsNan, convert_type(res_type)) 1762 .add(args[0].base) 1763 .result; 1764 }) 1765 1766 // ret tex1D(s, coords) 1767 // ret tex1D(s, coords, offset) 1768 DEFINE_INTRINSIC(tex1D, 0, int, sampler1d_int, float) 1769 DEFINE_INTRINSIC(tex1D, 0, uint, sampler1d_uint, float) 1770 DEFINE_INTRINSIC(tex1D, 0, float, sampler1d_float, float) 1771 DEFINE_INTRINSIC(tex1D, 0, float4, sampler1d_float4, float) 1772 DEFINE_INTRINSIC(tex1D, 1, int, sampler1d_int, float, int) 1773 DEFINE_INTRINSIC(tex1D, 1, uint, sampler1d_uint, float, int) 1774 DEFINE_INTRINSIC(tex1D, 1, float, sampler1d_float, float, int) 1775 DEFINE_INTRINSIC(tex1D, 1, float4, sampler1d_float4, float, int) 1776 IMPLEMENT_INTRINSIC_GLSL(tex1D, 0, { 1777 code += "texture(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ')'; 1778 if (res_type.rows == 1) 1779 code += ".x"; // Collapse last argument from a 4-component vector 1780 }) 1781 IMPLEMENT_INTRINSIC_GLSL(tex1D, 1, { 1782 code += "textureOffset(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ", " + id_to_name(args[2].base) + ')'; 1783 if (res_type.rows == 1) 1784 code += ".x"; 1785 }) 1786 IMPLEMENT_INTRINSIC_HLSL(tex1D, 0, { 1787 if (_shader_model >= 40) { // SM4 and higher use a more object-oriented programming model for textures 1788 if (res_type.is_floating_point() || _shader_model >= 67) 1789 code += id_to_name(args[0].base) + ".t.Sample(" + id_to_name(args[0].base) + ".s, " + id_to_name(args[1].base) + ')'; 1790 else // Integer sampling is not supported until SM6.7, so emulate with a texture fetch 1791 code += "uint temp" + std::to_string(res) + "; " + id_to_name(args[0].base) + ".t.GetDimensions(temp" + std::to_string(res) + "); " + 1792 id_to_name(res) + " = " + id_to_name(args[0].base) + ".t.Load(int2(" + id_to_name(args[1].base) + " * temp" + std::to_string(res) + ", 0))"; 1793 } 1794 else { 1795 code += "tex1D(" + id_to_name(args[0].base) + ".s, " + id_to_name(args[1].base) + ')'; 1796 if (res_type.rows == 1) 1797 code += ".x"; 1798 } 1799 }) 1800 IMPLEMENT_INTRINSIC_HLSL(tex1D, 1, { 1801 if (_shader_model >= 40) { 1802 if (res_type.is_floating_point() || _shader_model >= 67) 1803 code += id_to_name(args[0].base) + ".t.Sample(" + id_to_name(args[0].base) + ".s, " + id_to_name(args[1].base) + ", " + id_to_name(args[2].base) + ')'; 1804 else 1805 code += "uint temp" + std::to_string(res) + "; " + id_to_name(args[0].base) + ".t.GetDimensions(temp" + std::to_string(res) + "); " + 1806 id_to_name(res) + " = " + id_to_name(args[0].base) + ".t.Load(int2(" + id_to_name(args[1].base) + " * temp" + std::to_string(res) + ", 0), " + id_to_name(args[2].base) + ')'; 1807 } 1808 else { 1809 code += "tex1D(" + id_to_name(args[0].base) + ".s, " + id_to_name(args[1].base) + " + " + id_to_name(args[2].base) + " * " + id_to_name(args[0].base) + ".pixelsize)"; 1810 if (res_type.rows == 1) 1811 code += ".x"; 1812 } 1813 }) 1814 IMPLEMENT_INTRINSIC_SPIRV(tex1D, 0, { 1815 type res_vector_type = res_type; 1816 res_vector_type.rows = 4; 1817 1818 const spv::Id res = add_instruction(spv::OpImageSampleImplicitLod, convert_type(res_vector_type)) 1819 .add(args[0].base) 1820 .add(args[1].base) 1821 .add(spv::ImageOperandsMaskNone) 1822 .result; 1823 if (res_type.rows == 1) 1824 // Collapse last argument from a 4-component vector 1825 return 1826 add_instruction(spv::OpCompositeExtract, convert_type(res_type)) 1827 .add(res) 1828 .add(0u) 1829 .result; 1830 else 1831 return res; 1832 }) 1833 IMPLEMENT_INTRINSIC_SPIRV(tex1D, 1, { 1834 // Non-constant offset operand needs extended capability 1835 if (!args[2].is_constant) 1836 add_capability(spv::CapabilityImageGatherExtended); 1837 1838 type res_vector_type = res_type; 1839 res_vector_type.rows = 4; 1840 1841 const spv::Id res = add_instruction(spv::OpImageSampleImplicitLod, convert_type(res_vector_type)) 1842 .add(args[0].base) 1843 .add(args[1].base) 1844 .add(args[2].is_constant ? spv::ImageOperandsConstOffsetMask : spv::ImageOperandsOffsetMask) 1845 .add(args[2].base) 1846 .result; 1847 if (res_type.rows == 1) 1848 return 1849 add_instruction(spv::OpCompositeExtract, convert_type(res_type)) 1850 .add(res) 1851 .add(0u) 1852 .result; 1853 else 1854 return res; 1855 }) 1856 1857 // ret tex2D(s, coords) 1858 // ret tex2D(s, coords, offset) 1859 DEFINE_INTRINSIC(tex2D, 0, int, sampler2d_int, float2) 1860 DEFINE_INTRINSIC(tex2D, 0, uint, sampler2d_uint, float2) 1861 DEFINE_INTRINSIC(tex2D, 0, float, sampler2d_float, float2) 1862 DEFINE_INTRINSIC(tex2D, 0, float4, sampler2d_float4, float2) 1863 DEFINE_INTRINSIC(tex2D, 1, int, sampler2d_int, float2, int2) 1864 DEFINE_INTRINSIC(tex2D, 1, uint, sampler2d_uint, float2, int2) 1865 DEFINE_INTRINSIC(tex2D, 1, float, sampler2d_float, float2, int2) 1866 DEFINE_INTRINSIC(tex2D, 1, float4, sampler2d_float4, float2, int2) 1867 IMPLEMENT_INTRINSIC_GLSL(tex2D, 0, { 1868 code += "texture(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ')'; 1869 if (res_type.rows == 1) 1870 code += ".x"; // Collapse last argument from a 4-component vector 1871 }) 1872 IMPLEMENT_INTRINSIC_GLSL(tex2D, 1, { 1873 code += "textureOffset(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ", " + id_to_name(args[2].base) + ')'; 1874 if (res_type.rows == 1) 1875 code += ".x"; 1876 }) 1877 IMPLEMENT_INTRINSIC_HLSL(tex2D, 0, { 1878 if (_shader_model >= 40) { // SM4 and higher use a more object-oriented programming model for textures 1879 if (res_type.is_floating_point() || _shader_model >= 67) 1880 code += id_to_name(args[0].base) + ".t.Sample(" + id_to_name(args[0].base) + ".s, " + id_to_name(args[1].base) + ')'; 1881 else // Integer sampling is not supported until SM6.7, so emulate with a texture fetch 1882 code += "uint2 temp" + std::to_string(res) + "; " + id_to_name(args[0].base) + ".t.GetDimensions(temp" + std::to_string(res) + ".x, temp" + std::to_string(res) + ".y); " + 1883 id_to_name(res) + " = " + id_to_name(args[0].base) + ".t.Load(int3(" + id_to_name(args[1].base) + " * temp" + std::to_string(res) + ", 0))"; 1884 } 1885 else { 1886 code += "tex2D(" + id_to_name(args[0].base) + ".s, " + id_to_name(args[1].base) + ')'; 1887 if (res_type.rows == 1) 1888 code += ".x"; 1889 } 1890 }) 1891 IMPLEMENT_INTRINSIC_HLSL(tex2D, 1, { 1892 if (_shader_model >= 40) { 1893 if (res_type.is_floating_point() || _shader_model >= 67) 1894 code += id_to_name(args[0].base) + ".t.Sample(" + id_to_name(args[0].base) + ".s, " + id_to_name(args[1].base) + ", " + id_to_name(args[2].base) + ')'; 1895 else 1896 code += "uint2 temp" + std::to_string(res) + "; " + id_to_name(args[0].base) + ".t.GetDimensions(temp" + std::to_string(res) + ".x, temp" + std::to_string(res) + ".y); " + 1897 id_to_name(res) + " = " + id_to_name(args[0].base) + ".t.Load(int3(" + id_to_name(args[1].base) + " * temp" + std::to_string(res) + ", 0), " + id_to_name(args[2].base) + ')'; 1898 } 1899 else { 1900 code += "tex2D(" + id_to_name(args[0].base) + ".s, " + id_to_name(args[1].base) + " + " + id_to_name(args[2].base) + " * " + id_to_name(args[0].base) + ".pixelsize)"; 1901 if (res_type.rows == 1) 1902 code += ".x"; 1903 } 1904 }) 1905 IMPLEMENT_INTRINSIC_SPIRV(tex2D, 0, { 1906 type res_vector_type = res_type; 1907 res_vector_type.rows = 4; 1908 1909 const spv::Id res = add_instruction(spv::OpImageSampleImplicitLod, convert_type(res_vector_type)) 1910 .add(args[0].base) 1911 .add(args[1].base) 1912 .add(spv::ImageOperandsMaskNone) 1913 .result; 1914 if (res_type.rows == 1) 1915 // Collapse last argument from a 4-component vector 1916 return 1917 add_instruction(spv::OpCompositeExtract, convert_type(res_type)) 1918 .add(res) 1919 .add(0u) 1920 .result; 1921 else 1922 return res; 1923 }) 1924 IMPLEMENT_INTRINSIC_SPIRV(tex2D, 1, { 1925 // Non-constant offset operand needs extended capability 1926 if (!args[2].is_constant) 1927 add_capability(spv::CapabilityImageGatherExtended); 1928 1929 type res_vector_type = res_type; 1930 res_vector_type.rows = 4; 1931 1932 const spv::Id res = add_instruction(spv::OpImageSampleImplicitLod, convert_type(res_vector_type)) 1933 .add(args[0].base) 1934 .add(args[1].base) 1935 .add(args[2].is_constant ? spv::ImageOperandsConstOffsetMask : spv::ImageOperandsOffsetMask) 1936 .add(args[2].base) 1937 .result; 1938 if (res_type.rows == 1) 1939 return 1940 add_instruction(spv::OpCompositeExtract, convert_type(res_type)) 1941 .add(res) 1942 .add(0u) 1943 .result; 1944 else 1945 return res; 1946 }) 1947 1948 // ret tex3D(s, coords) 1949 // ret tex3D(s, coords, offset) 1950 DEFINE_INTRINSIC(tex3D, 0, int, sampler3d_int, float3) 1951 DEFINE_INTRINSIC(tex3D, 0, uint, sampler3d_uint, float3) 1952 DEFINE_INTRINSIC(tex3D, 0, float, sampler3d_float, float3) 1953 DEFINE_INTRINSIC(tex3D, 0, float4, sampler3d_float4, float3) 1954 DEFINE_INTRINSIC(tex3D, 1, int, sampler3d_int, float3, int3) 1955 DEFINE_INTRINSIC(tex3D, 1, uint, sampler3d_uint, float3, int3) 1956 DEFINE_INTRINSIC(tex3D, 1, float, sampler3d_float, float3, int3) 1957 DEFINE_INTRINSIC(tex3D, 1, float4, sampler3d_float4, float3, int3) 1958 IMPLEMENT_INTRINSIC_GLSL(tex3D, 0, { 1959 code += "texture(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ')'; 1960 if (res_type.rows == 1) 1961 code += ".x"; // Collapse last argument from a 4-component vector 1962 }) 1963 IMPLEMENT_INTRINSIC_GLSL(tex3D, 1, { 1964 code += "textureOffset(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ", " + id_to_name(args[2].base) + ')'; 1965 if (res_type.rows == 1) 1966 code += ".x"; 1967 }) 1968 IMPLEMENT_INTRINSIC_HLSL(tex3D, 0, { 1969 if (_shader_model >= 40) { // SM4 and higher use a more object-oriented programming model for textures 1970 if (res_type.is_floating_point() || _shader_model >= 67) 1971 code += id_to_name(args[0].base) + ".t.Sample(" + id_to_name(args[0].base) + ".s, " + id_to_name(args[1].base) + ')'; 1972 else // Integer sampling is not supported until SM6.7, so emulate with a texture fetch 1973 code += "uint3 temp" + std::to_string(res) + "; " + id_to_name(args[0].base) + ".t.GetDimensions(temp" + std::to_string(res) + ".x, temp" + std::to_string(res) + ".y, temp" + std::to_string(res) + ".z); " + 1974 id_to_name(res) + " = " + id_to_name(args[0].base) + ".t.Load(int4(" + id_to_name(args[1].base) + " * temp" + std::to_string(res) + ", 0))"; 1975 } 1976 else { 1977 code += "tex3D(" + id_to_name(args[0].base) + ".s, " + id_to_name(args[1].base) + ')'; 1978 if (res_type.rows == 1) 1979 code += ".x"; 1980 } 1981 }) 1982 IMPLEMENT_INTRINSIC_HLSL(tex3D, 1, { 1983 if (_shader_model >= 40) { 1984 if (res_type.is_floating_point() || _shader_model >= 67) 1985 code += id_to_name(args[0].base) + ".t.Sample(" + id_to_name(args[0].base) + ".s, " + id_to_name(args[1].base) + ", " + id_to_name(args[2].base) + ')'; 1986 else 1987 code += "uint3 temp" + std::to_string(res) + "; " + id_to_name(args[0].base) + ".t.GetDimensions(temp" + std::to_string(res) + ".x, temp" + std::to_string(res) + ".y, temp" + std::to_string(res) + ".z); " + 1988 id_to_name(res) + " = " + id_to_name(args[0].base) + ".t.Load(int4(" + id_to_name(args[1].base) + " * temp" + std::to_string(res) + ", 0), " + id_to_name(args[2].base) + ')'; 1989 } 1990 else { 1991 code += "tex3D(" + id_to_name(args[0].base) + ".s, " + id_to_name(args[1].base) + " + " + id_to_name(args[2].base) + " * " + id_to_name(args[0].base) + ".pixelsize)"; 1992 if (res_type.rows == 1) 1993 code += ".x"; 1994 } 1995 }) 1996 IMPLEMENT_INTRINSIC_SPIRV(tex3D, 0, { 1997 type res_vector_type = res_type; 1998 res_vector_type.rows = 4; 1999 2000 const spv::Id res = add_instruction(spv::OpImageSampleImplicitLod, convert_type(res_vector_type)) 2001 .add(args[0].base) 2002 .add(args[1].base) 2003 .add(spv::ImageOperandsMaskNone) 2004 .result; 2005 if (res_type.rows == 1) 2006 // Collapse last argument from a 4-component vector 2007 return 2008 add_instruction(spv::OpCompositeExtract, convert_type(res_type)) 2009 .add(res) 2010 .add(0u) 2011 .result; 2012 else 2013 return res; 2014 }) 2015 IMPLEMENT_INTRINSIC_SPIRV(tex3D, 1, { 2016 // Non-constant offset operand needs extended capability 2017 if (!args[2].is_constant) 2018 add_capability(spv::CapabilityImageGatherExtended); 2019 2020 type res_vector_type = res_type; 2021 res_vector_type.rows = 4; 2022 2023 const spv::Id res = add_instruction(spv::OpImageSampleImplicitLod, convert_type(res_vector_type)) 2024 .add(args[0].base) 2025 .add(args[1].base) 2026 .add(args[2].is_constant ? spv::ImageOperandsConstOffsetMask : spv::ImageOperandsOffsetMask) 2027 .add(args[2].base) 2028 .result; 2029 if (res_type.rows == 1) 2030 return 2031 add_instruction(spv::OpCompositeExtract, convert_type(res_type)) 2032 .add(res) 2033 .add(0u) 2034 .result; 2035 else 2036 return res; 2037 }) 2038 2039 // ret tex1Dlod(s, coords) 2040 // ret tex1Dlod(s, coords, offset) 2041 DEFINE_INTRINSIC(tex1Dlod, 0, int, sampler1d_int, float4) 2042 DEFINE_INTRINSIC(tex1Dlod, 0, uint, sampler1d_uint, float4) 2043 DEFINE_INTRINSIC(tex1Dlod, 0, float, sampler1d_float, float4) 2044 DEFINE_INTRINSIC(tex1Dlod, 0, float4, sampler1d_float4, float4) 2045 DEFINE_INTRINSIC(tex1Dlod, 1, int, sampler1d_int, float4, int) 2046 DEFINE_INTRINSIC(tex1Dlod, 1, uint, sampler1d_uint, float4, int) 2047 DEFINE_INTRINSIC(tex1Dlod, 1, float, sampler1d_float, float4, int) 2048 DEFINE_INTRINSIC(tex1Dlod, 1, float4, sampler1d_float4, float4, int) 2049 IMPLEMENT_INTRINSIC_GLSL(tex1Dlod, 0, { 2050 code += "textureLod(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ".x, " + id_to_name(args[1].base) + ".w)"; 2051 if (res_type.rows == 1) 2052 code += ".x"; // Collapse last argument from a 4-component vector 2053 }) 2054 IMPLEMENT_INTRINSIC_GLSL(tex1Dlod, 1, { 2055 code += "textureLodOffset(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ".x, " + id_to_name(args[1].base) + ".w, " + id_to_name(args[2].base) + ')'; 2056 if (res_type.rows == 1) 2057 code += ".x"; 2058 }) 2059 IMPLEMENT_INTRINSIC_HLSL(tex1Dlod, 0, { 2060 if (_shader_model >= 40) { 2061 if (res_type.is_floating_point() || _shader_model >= 67) 2062 code += id_to_name(args[0].base) + ".t.SampleLevel(" + id_to_name(args[0].base) + ".s, " + id_to_name(args[1].base) + ".x, " + id_to_name(args[1].base) + ".w)"; 2063 else // Integer sampling is not supported until SM6.7, so emulate with a texture fetch 2064 code += "uint2 temp" + std::to_string(res) + "; " + id_to_name(args[0].base) + ".t.GetDimensions((int)" + id_to_name(args[1].base) + ".w, temp" + std::to_string(res) + ".x, temp" + std::to_string(res) + ".y); " + 2065 id_to_name(res) + " = " + id_to_name(args[0].base) + ".t.Load(int2(" + id_to_name(args[1].base) + ".x * temp" + std::to_string(res) + ".x, (int)" + id_to_name(args[1].base) + ".w))"; 2066 } 2067 else { 2068 code += "tex1Dlod(" + id_to_name(args[0].base) + ".s, " + id_to_name(args[1].base) + ')'; 2069 if (res_type.rows == 1) 2070 code += ".x"; 2071 } 2072 }) 2073 IMPLEMENT_INTRINSIC_HLSL(tex1Dlod, 1, { 2074 if (_shader_model >= 40) { 2075 if (res_type.is_floating_point() || _shader_model >= 67) 2076 code += id_to_name(args[0].base) + ".t.SampleLevel(" + id_to_name(args[0].base) + ".s, " + id_to_name(args[1].base) + ".x, " + id_to_name(args[1].base) + ".w, " + id_to_name(args[2].base) + ')'; 2077 else 2078 code += "uint2 temp" + std::to_string(res) + "; " + id_to_name(args[0].base) + ".t.GetDimensions((int)" + id_to_name(args[1].base) + ".w, temp" + std::to_string(res) + ".x, temp" + std::to_string(res) + ".y); " + 2079 id_to_name(res) + " = " + id_to_name(args[0].base) + ".t.Load(int2(" + id_to_name(args[1].base) + ".x * temp" + std::to_string(res) + ".x, (int)" + id_to_name(args[1].base) + ".w))" + id_to_name(args[2].base) + ')'; 2080 } 2081 else { 2082 code += "tex1Dlod(" + id_to_name(args[0].base) + ".s, " + id_to_name(args[1].base) + " + float4(" + id_to_name(args[2].base) + " * " + id_to_name(args[0].base) + ".pixelsize, 0, 0, 0))"; 2083 if (res_type.rows == 1) 2084 code += ".x"; 2085 } 2086 }) 2087 IMPLEMENT_INTRINSIC_SPIRV(tex1Dlod, 0, { 2088 const spv::Id x = add_instruction(spv::OpCompositeExtract, convert_type({ type::t_float, 1, 1 })) 2089 .add(args[1].base) 2090 .add(0) // .x 2091 .result; 2092 const spv::Id lod = add_instruction(spv::OpCompositeExtract, convert_type({ type::t_float, 1, 1 })) 2093 .add(args[1].base) 2094 .add(3) // .w 2095 .result; 2096 2097 type res_vector_type = res_type; 2098 res_vector_type.rows = 4; 2099 2100 const spv::Id res = add_instruction(spv::OpImageSampleExplicitLod, convert_type(res_vector_type)) 2101 .add(args[0].base) 2102 .add(x) 2103 .add(spv::ImageOperandsLodMask) 2104 .add(lod) 2105 .result; 2106 if (res_type.rows == 1) 2107 // Collapse last argument from a 4-component vector 2108 return 2109 add_instruction(spv::OpCompositeExtract, convert_type(res_type)) 2110 .add(res) 2111 .add(0u) 2112 .result; 2113 else 2114 return res; 2115 }) 2116 IMPLEMENT_INTRINSIC_SPIRV(tex1Dlod, 1, { 2117 if (!args[2].is_constant) 2118 add_capability(spv::CapabilityImageGatherExtended); 2119 2120 const spv::Id x = add_instruction(spv::OpCompositeExtract, convert_type({ type::t_float, 1, 1 })) 2121 .add(args[1].base) 2122 .add(0) // .x 2123 .result; 2124 const spv::Id lod = add_instruction(spv::OpCompositeExtract, convert_type({ type::t_float, 1, 1 })) 2125 .add(args[1].base) 2126 .add(3) // .w 2127 .result; 2128 2129 type res_vector_type = res_type; 2130 res_vector_type.rows = 4; 2131 2132 const spv::Id res = add_instruction(spv::OpImageSampleExplicitLod, convert_type(res_vector_type)) 2133 .add(args[0].base) 2134 .add(x) 2135 .add(spv::ImageOperandsLodMask | (args[2].is_constant ? spv::ImageOperandsConstOffsetMask : spv::ImageOperandsOffsetMask)) 2136 .add(lod) 2137 .add(args[2].base) 2138 .result; 2139 if (res_type.rows == 1) 2140 return 2141 add_instruction(spv::OpCompositeExtract, convert_type(res_type)) 2142 .add(res) 2143 .add(0u) 2144 .result; 2145 else 2146 return res; 2147 }) 2148 2149 // ret tex2Dlod(s, coords) 2150 // ret tex2Dlod(s, coords, offset) 2151 DEFINE_INTRINSIC(tex2Dlod, 0, int, sampler2d_int, float4) 2152 DEFINE_INTRINSIC(tex2Dlod, 0, uint, sampler2d_uint, float4) 2153 DEFINE_INTRINSIC(tex2Dlod, 0, float, sampler2d_float, float4) 2154 DEFINE_INTRINSIC(tex2Dlod, 0, float4, sampler2d_float4, float4) 2155 DEFINE_INTRINSIC(tex2Dlod, 1, int, sampler2d_int, float4, int2) 2156 DEFINE_INTRINSIC(tex2Dlod, 1, uint, sampler2d_uint, float4, int2) 2157 DEFINE_INTRINSIC(tex2Dlod, 1, float, sampler2d_float, float4, int2) 2158 DEFINE_INTRINSIC(tex2Dlod, 1, float4, sampler2d_float4, float4, int2) 2159 IMPLEMENT_INTRINSIC_GLSL(tex2Dlod, 0, { 2160 code += "textureLod(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ".xy, " + id_to_name(args[1].base) + ".w)"; 2161 if (res_type.rows == 1) 2162 code += ".x"; // Collapse last argument from a 4-component vector 2163 }) 2164 IMPLEMENT_INTRINSIC_GLSL(tex2Dlod, 1, { 2165 code += "textureLodOffset(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ".xy, " + id_to_name(args[1].base) + ".w, " + id_to_name(args[2].base) + ')'; 2166 if (res_type.rows == 1) 2167 code += ".x"; 2168 }) 2169 IMPLEMENT_INTRINSIC_HLSL(tex2Dlod, 0, { 2170 if (_shader_model >= 40) { 2171 if (res_type.is_floating_point() || _shader_model >= 67) 2172 code += id_to_name(args[0].base) + ".t.SampleLevel(" + id_to_name(args[0].base) + ".s, " + id_to_name(args[1].base) + ".xy, " + id_to_name(args[1].base) + ".w)"; 2173 else // Integer sampling is not supported until SM6.7, so emulate with a texture fetch 2174 code += "uint3 temp" + std::to_string(res) + "; " + id_to_name(args[0].base) + ".t.GetDimensions((int)" + id_to_name(args[1].base) + ".w, temp" + std::to_string(res) + ".x, temp" + std::to_string(res) + ".y, temp" + std::to_string(res) + ".z); " + 2175 id_to_name(res) + " = " + id_to_name(args[0].base) + ".t.Load(int3(" + id_to_name(args[1].base) + ".xy * temp" + std::to_string(res) + ".xy, (int)" + id_to_name(args[1].base) + ".w))"; 2176 } 2177 else { 2178 code += "tex2Dlod(" + id_to_name(args[0].base) + ".s, " + id_to_name(args[1].base) + ')'; 2179 if (res_type.rows == 1) 2180 code += ".x"; 2181 } 2182 }) 2183 IMPLEMENT_INTRINSIC_HLSL(tex2Dlod, 1, { 2184 if (_shader_model >= 40) { 2185 if (res_type.is_floating_point() || _shader_model >= 67) 2186 code += id_to_name(args[0].base) + ".t.SampleLevel(" + id_to_name(args[0].base) + ".s, " + id_to_name(args[1].base) + ".xy, " + id_to_name(args[1].base) + ".w, " + id_to_name(args[2].base) + ')'; 2187 else 2188 code += "uint3 temp" + std::to_string(res) + "; " + id_to_name(args[0].base) + ".t.GetDimensions((int)" + id_to_name(args[1].base) + ".w, temp" + std::to_string(res) + ".x, temp" + std::to_string(res) + ".y, temp" + std::to_string(res) + ".z); " + 2189 id_to_name(res) + " = " + id_to_name(args[0].base) + ".t.Load(int3(" + id_to_name(args[1].base) + ".xy * temp" + std::to_string(res) + ".xy, (int)" + id_to_name(args[1].base) + ".w))" + id_to_name(args[2].base) + ')'; 2190 } 2191 else { 2192 code += "tex2Dlod(" + id_to_name(args[0].base) + ".s, " + id_to_name(args[1].base) + " + float4(" + id_to_name(args[2].base) + " * " + id_to_name(args[0].base) + ".pixelsize, 0, 0))"; 2193 if (res_type.rows == 1) 2194 code += ".x"; 2195 } 2196 }) 2197 IMPLEMENT_INTRINSIC_SPIRV(tex2Dlod, 0, { 2198 const spv::Id xy = add_instruction(spv::OpVectorShuffle, convert_type({ type::t_float, 2, 1 })) 2199 .add(args[1].base) 2200 .add(args[1].base) 2201 .add(0) // .x 2202 .add(1) // .y 2203 .result; 2204 const spv::Id lod = add_instruction(spv::OpCompositeExtract, convert_type({ type::t_float, 1, 1 })) 2205 .add(args[1].base) 2206 .add(3) // .w 2207 .result; 2208 2209 type res_vector_type = res_type; 2210 res_vector_type.rows = 4; 2211 2212 const spv::Id res = add_instruction(spv::OpImageSampleExplicitLod, convert_type(res_vector_type)) 2213 .add(args[0].base) 2214 .add(xy) 2215 .add(spv::ImageOperandsLodMask) 2216 .add(lod) 2217 .result; 2218 if (res_type.rows == 1) 2219 // Collapse last argument from a 4-component vector 2220 return 2221 add_instruction(spv::OpCompositeExtract, convert_type(res_type)) 2222 .add(res) 2223 .add(0u) 2224 .result; 2225 else 2226 return res; 2227 }) 2228 IMPLEMENT_INTRINSIC_SPIRV(tex2Dlod, 1, { 2229 if (!args[2].is_constant) 2230 add_capability(spv::CapabilityImageGatherExtended); 2231 2232 const spv::Id xy = add_instruction(spv::OpVectorShuffle, convert_type({ type::t_float, 2, 1 })) 2233 .add(args[1].base) 2234 .add(args[1].base) 2235 .add(0) // .x 2236 .add(1) // .y 2237 .result; 2238 const spv::Id lod = add_instruction(spv::OpCompositeExtract, convert_type({ type::t_float, 1, 1 })) 2239 .add(args[1].base) 2240 .add(3) // .w 2241 .result; 2242 2243 type res_vector_type = res_type; 2244 res_vector_type.rows = 4; 2245 2246 const spv::Id res = add_instruction(spv::OpImageSampleExplicitLod, convert_type(res_vector_type)) 2247 .add(args[0].base) 2248 .add(xy) 2249 .add(spv::ImageOperandsLodMask | (args[2].is_constant ? spv::ImageOperandsConstOffsetMask : spv::ImageOperandsOffsetMask)) 2250 .add(lod) 2251 .add(args[2].base) 2252 .result; 2253 if (res_type.rows == 1) 2254 return 2255 add_instruction(spv::OpCompositeExtract, convert_type(res_type)) 2256 .add(res) 2257 .add(0u) 2258 .result; 2259 else 2260 return res; 2261 }) 2262 2263 // ret tex3Dlod(s, coords) 2264 // ret tex3Dlod(s, coords, offset) 2265 DEFINE_INTRINSIC(tex3Dlod, 0, int, sampler3d_int, float4) 2266 DEFINE_INTRINSIC(tex3Dlod, 0, uint, sampler3d_uint, float4) 2267 DEFINE_INTRINSIC(tex3Dlod, 0, float, sampler3d_float, float4) 2268 DEFINE_INTRINSIC(tex3Dlod, 0, float4, sampler3d_float4, float4) 2269 DEFINE_INTRINSIC(tex3Dlod, 1, int, sampler3d_int, float4, int2) 2270 DEFINE_INTRINSIC(tex3Dlod, 1, uint, sampler3d_uint, float4, int2) 2271 DEFINE_INTRINSIC(tex3Dlod, 1, float, sampler3d_float, float4, int2) 2272 DEFINE_INTRINSIC(tex3Dlod, 1, float4, sampler3d_float4, float4, int2) 2273 IMPLEMENT_INTRINSIC_GLSL(tex3Dlod, 0, { 2274 code += "textureLod(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ".xyz, " + id_to_name(args[1].base) + ".w)"; 2275 if (res_type.rows == 1) 2276 code += ".x"; // Collapse last argument from a 4-component vector 2277 }) 2278 IMPLEMENT_INTRINSIC_GLSL(tex3Dlod, 1, { 2279 code += "textureLodOffset(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ".xyz, " + id_to_name(args[1].base) + ".w, " + id_to_name(args[2].base) + ')'; 2280 if (res_type.rows == 1) 2281 code += ".x"; 2282 }) 2283 IMPLEMENT_INTRINSIC_HLSL(tex3Dlod, 0, { 2284 if (_shader_model >= 40) { 2285 if (res_type.is_floating_point() || _shader_model >= 67) 2286 code += id_to_name(args[0].base) + ".t.SampleLevel(" + id_to_name(args[0].base) + ".s, " + id_to_name(args[1].base) + ".xyz, " + id_to_name(args[1].base) + ".w)"; 2287 else // Integer sampling is not supported until SM6.7, so emulate with a texture fetch 2288 code += "uint4 temp" + std::to_string(res) + "; " + id_to_name(args[0].base) + ".t.GetDimensions((int)" + id_to_name(args[1].base) + ".w, temp" + std::to_string(res) + ".x, temp" + std::to_string(res) + ".y, temp" + std::to_string(res) + ".z, temp" + std::to_string(res) + ".w); " + 2289 id_to_name(res) + " = " + id_to_name(args[0].base) + ".t.Load(int4(" + id_to_name(args[1].base) + ".xyz * temp" + std::to_string(res) + ".xyz, (int)" + id_to_name(args[1].base) + ".w))"; 2290 } 2291 else { 2292 code += "tex3Dlod(" + id_to_name(args[0].base) + ".s, " + id_to_name(args[1].base) + ')'; 2293 if (res_type.rows == 1) 2294 code += ".x"; 2295 } 2296 }) 2297 IMPLEMENT_INTRINSIC_HLSL(tex3Dlod, 1, { 2298 if (_shader_model >= 40) { 2299 if (res_type.is_floating_point() || _shader_model >= 67) 2300 code += id_to_name(args[0].base) + ".t.SampleLevel(" + id_to_name(args[0].base) + ".s, " + id_to_name(args[1].base) + ".xyz, " + id_to_name(args[1].base) + ".w, " + id_to_name(args[2].base) + ')'; 2301 else 2302 code += "uint4 temp" + std::to_string(res) + "; " + id_to_name(args[0].base) + ".t.GetDimensions((int)" + id_to_name(args[1].base) + ".w, temp" + std::to_string(res) + ".x, temp" + std::to_string(res) + ".y, temp" + std::to_string(res) + ".z, temp" + std::to_string(res) + ".w); " + 2303 id_to_name(res) + " = " + id_to_name(args[0].base) + ".t.Load(int4(" + id_to_name(args[1].base) + ".xyz * temp" + std::to_string(res) + ".xyz, (int)" + id_to_name(args[1].base) + ".w))" + id_to_name(args[2].base) + ')'; 2304 } 2305 else { 2306 code += "tex3Dlod(" + id_to_name(args[0].base) + ".s, " + id_to_name(args[1].base) + " + float4(" + id_to_name(args[2].base) + " * " + id_to_name(args[0].base) + ".pixelsize, 0))"; 2307 if (res_type.rows == 1) 2308 code += ".x"; 2309 } 2310 }) 2311 IMPLEMENT_INTRINSIC_SPIRV(tex3Dlod, 0, { 2312 const spv::Id xyz = add_instruction(spv::OpVectorShuffle, convert_type({ type::t_float, 3, 1 })) 2313 .add(args[1].base) 2314 .add(args[1].base) 2315 .add(0) // .x 2316 .add(1) // .y 2317 .add(2) // .z 2318 .result; 2319 const spv::Id lod = add_instruction(spv::OpCompositeExtract, convert_type({ type::t_float, 1, 1 })) 2320 .add(args[1].base) 2321 .add(3) // .w 2322 .result; 2323 2324 type res_vector_type = res_type; 2325 res_vector_type.rows = 4; 2326 2327 const spv::Id res = add_instruction(spv::OpImageSampleExplicitLod, convert_type(res_vector_type)) 2328 .add(args[0].base) 2329 .add(xyz) 2330 .add(spv::ImageOperandsLodMask) 2331 .add(lod) 2332 .result; 2333 if (res_type.rows == 1) 2334 // Collapse last argument from a 4-component vector 2335 return 2336 add_instruction(spv::OpCompositeExtract, convert_type(res_type)) 2337 .add(res) 2338 .add(0u) 2339 .result; 2340 else 2341 return res; 2342 }) 2343 IMPLEMENT_INTRINSIC_SPIRV(tex3Dlod, 1, { 2344 if (!args[2].is_constant) 2345 add_capability(spv::CapabilityImageGatherExtended); 2346 2347 const spv::Id xyz = add_instruction(spv::OpVectorShuffle, convert_type({ type::t_float, 3, 1 })) 2348 .add(args[1].base) 2349 .add(args[1].base) 2350 .add(0) // .x 2351 .add(1) // .y 2352 .add(2) // .z 2353 .result; 2354 const spv::Id lod = add_instruction(spv::OpCompositeExtract, convert_type({ type::t_float, 1, 1 })) 2355 .add(args[1].base) 2356 .add(3) // .w 2357 .result; 2358 2359 type res_vector_type = res_type; 2360 res_vector_type.rows = 4; 2361 2362 const spv::Id res = add_instruction(spv::OpImageSampleExplicitLod, convert_type(res_vector_type)) 2363 .add(args[0].base) 2364 .add(xyz) 2365 .add(spv::ImageOperandsLodMask | (args[2].is_constant ? spv::ImageOperandsConstOffsetMask : spv::ImageOperandsOffsetMask)) 2366 .add(lod) 2367 .add(args[2].base) 2368 .result; 2369 if (res_type.rows == 1) 2370 return 2371 add_instruction(spv::OpCompositeExtract, convert_type(res_type)) 2372 .add(res) 2373 .add(0u) 2374 .result; 2375 else 2376 return res; 2377 }) 2378 2379 // ret tex1Dfetch(s, coords) 2380 // ret tex1Dfetch(s, coords, lod) 2381 DEFINE_INTRINSIC(tex1Dfetch, 0, int, sampler1d_int, int) 2382 DEFINE_INTRINSIC(tex1Dfetch, 0, uint, sampler1d_uint, int) 2383 DEFINE_INTRINSIC(tex1Dfetch, 0, float, sampler1d_float, int) 2384 DEFINE_INTRINSIC(tex1Dfetch, 0, float4, sampler1d_float4, int) 2385 DEFINE_INTRINSIC(tex1Dfetch, 1, int, sampler1d_int, int, int) 2386 DEFINE_INTRINSIC(tex1Dfetch, 1, uint, sampler1d_uint, int, int) 2387 DEFINE_INTRINSIC(tex1Dfetch, 1, float, sampler1d_float, int, int) 2388 DEFINE_INTRINSIC(tex1Dfetch, 1, float4, sampler1d_float4, int, int) 2389 DEFINE_INTRINSIC(tex1Dfetch, 2, int, storage1d_int, int) 2390 DEFINE_INTRINSIC(tex1Dfetch, 2, uint, storage1d_uint, int) 2391 DEFINE_INTRINSIC(tex1Dfetch, 2, float, storage1d_float, int) 2392 DEFINE_INTRINSIC(tex1Dfetch, 2, float4, storage1d_float4, int) 2393 IMPLEMENT_INTRINSIC_GLSL(tex1Dfetch, 0, { 2394 code += "texelFetch(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ", 0)"; 2395 if (res_type.rows == 1) 2396 code += ".x"; // Collapse last argument from a 4-component vector 2397 }) 2398 IMPLEMENT_INTRINSIC_GLSL(tex1Dfetch, 1, { 2399 code += "texelFetch(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ", " + id_to_name(args[2].base) + ')'; 2400 if (res_type.rows == 1) 2401 code += ".x"; 2402 }) 2403 IMPLEMENT_INTRINSIC_GLSL(tex1Dfetch, 2, { 2404 code += "imageLoad(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ")"; 2405 if (res_type.rows == 1) 2406 code += ".x"; 2407 }) 2408 IMPLEMENT_INTRINSIC_HLSL(tex1Dfetch, 0, { 2409 if (_shader_model >= 40) 2410 code += id_to_name(args[0].base) + ".t.Load(int2(" + id_to_name(args[1].base) + ", 0))"; 2411 else { 2412 // SM3 does not have a fetch intrinsic, so emulate it by transforming coordinates into texture space ones 2413 // Also add a half-pixel offset to align texels with pixels 2414 // (coords + 0.5) / size 2415 code += "tex1Dlod(" + id_to_name(args[0].base) + ".s, float4((" + 2416 id_to_name(args[1].base) + " + 0.5) * " + id_to_name(args[0].base) + ".pixelsize, 0, 0, 0))"; 2417 if (res_type.rows == 1) 2418 code += ".x"; 2419 } 2420 }) 2421 IMPLEMENT_INTRINSIC_HLSL(tex1Dfetch, 1, { 2422 if (_shader_model >= 40) 2423 code += id_to_name(args[0].base) + ".t.Load(int2(" + id_to_name(args[1].base) + ", " + id_to_name(args[2].base) + "))"; 2424 else { 2425 code += "tex2Dlod(" + id_to_name(args[0].base) + ".s, float4((" + 2426 id_to_name(args[1].base) + " + 0.5) * " + id_to_name(args[0].base) + ".pixelsize * exp2(" + id_to_name(args[2].base) + "), 0, 0, " + 2427 id_to_name(args[2].base) + "))"; 2428 if (res_type.rows == 1) 2429 code += ".x"; 2430 } 2431 }) 2432 IMPLEMENT_INTRINSIC_HLSL(tex1Dfetch, 2, { 2433 code += id_to_name(args[0].base) + '[' + id_to_name(args[1].base) + ']'; 2434 }) 2435 IMPLEMENT_INTRINSIC_SPIRV(tex1Dfetch, 0, { 2436 const spv::Id image = add_instruction(spv::OpImage, convert_image_type(args[0].type)) 2437 .add(args[0].base) 2438 .result; 2439 2440 type res_vector_type = res_type; 2441 res_vector_type.rows = 4; 2442 2443 const spv::Id res = add_instruction(spv::OpImageFetch, convert_type(res_vector_type)) 2444 .add(image) 2445 .add(args[1].base) 2446 .result; 2447 if (res_type.rows == 1) 2448 // Collapse last argument from a 4-component vector 2449 return 2450 add_instruction(spv::OpCompositeExtract, convert_type(res_type)) 2451 .add(res) 2452 .add(0u) 2453 .result; 2454 else 2455 return res; 2456 }) 2457 IMPLEMENT_INTRINSIC_SPIRV(tex1Dfetch, 1, { 2458 const spv::Id image = add_instruction(spv::OpImage, convert_image_type(args[0].type)) 2459 .add(args[0].base) 2460 .result; 2461 2462 type res_vector_type = res_type; 2463 res_vector_type.rows = 4; 2464 2465 const spv::Id res = add_instruction(spv::OpImageFetch, convert_type(res_vector_type)) 2466 .add(image) 2467 .add(args[1].base) 2468 .add(spv::ImageOperandsLodMask) 2469 .add(args[2].base) 2470 .result; 2471 if (res_type.rows == 1) 2472 return 2473 add_instruction(spv::OpCompositeExtract, convert_type(res_type)) 2474 .add(res) 2475 .add(0u) 2476 .result; 2477 else 2478 return res; 2479 }) 2480 IMPLEMENT_INTRINSIC_SPIRV(tex1Dfetch, 2, { 2481 type res_vector_type = res_type; 2482 res_vector_type.rows = 4; 2483 2484 const spv::Id res = add_instruction(spv::OpImageRead, convert_type(res_vector_type)) 2485 .add(args[0].base) 2486 .add(args[1].base) 2487 .result; 2488 if (res_type.rows == 1) 2489 return 2490 add_instruction(spv::OpCompositeExtract, convert_type(res_type)) 2491 .add(res) 2492 .add(0u) 2493 .result; 2494 else 2495 return res; 2496 }) 2497 2498 // ret tex2Dfetch(s, coords) 2499 // ret tex2Dfetch(s, coords, lod) 2500 DEFINE_INTRINSIC(tex2Dfetch, 0, int, sampler2d_int, int2) 2501 DEFINE_INTRINSIC(tex2Dfetch, 0, uint, sampler2d_uint, int2) 2502 DEFINE_INTRINSIC(tex2Dfetch, 0, float, sampler2d_float, int2) 2503 DEFINE_INTRINSIC(tex2Dfetch, 0, float4, sampler2d_float4, int2) 2504 DEFINE_INTRINSIC(tex2Dfetch, 1, int, sampler2d_int, int2, int) 2505 DEFINE_INTRINSIC(tex2Dfetch, 1, uint, sampler2d_uint, int2, int) 2506 DEFINE_INTRINSIC(tex2Dfetch, 1, float, sampler2d_float, int2, int) 2507 DEFINE_INTRINSIC(tex2Dfetch, 1, float4, sampler2d_float4, int2, int) 2508 DEFINE_INTRINSIC(tex2Dfetch, 2, int, storage2d_int, int2) 2509 DEFINE_INTRINSIC(tex2Dfetch, 2, uint, storage2d_uint, int2) 2510 DEFINE_INTRINSIC(tex2Dfetch, 2, float, storage2d_float, int2) 2511 DEFINE_INTRINSIC(tex2Dfetch, 2, float4, storage2d_float4, int2) 2512 IMPLEMENT_INTRINSIC_GLSL(tex2Dfetch, 0, { 2513 code += "texelFetch(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ", 0)"; 2514 if (res_type.rows == 1) 2515 code += ".x"; // Collapse last argument from a 4-component vector 2516 }) 2517 IMPLEMENT_INTRINSIC_GLSL(tex2Dfetch, 1, { 2518 code += "texelFetch(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ", " + id_to_name(args[2].base) + ')'; 2519 if (res_type.rows == 1) 2520 code += ".x"; 2521 }) 2522 IMPLEMENT_INTRINSIC_GLSL(tex2Dfetch, 2, { 2523 code += "imageLoad(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ')'; 2524 if (res_type.rows == 1) 2525 code += ".x"; 2526 }) 2527 IMPLEMENT_INTRINSIC_HLSL(tex2Dfetch, 0, { 2528 if (_shader_model >= 40) 2529 code += id_to_name(args[0].base) + ".t.Load(int3(" + id_to_name(args[1].base) + ", 0))"; 2530 else { 2531 // SM3 does not have a fetch intrinsic, so emulate it by transforming coordinates into texture space ones 2532 // Also add a half-pixel offset to align texels with pixels 2533 // (coords + 0.5) / size 2534 code += "tex2Dlod(" + id_to_name(args[0].base) + ".s, float4((" + 2535 id_to_name(args[1].base) + " + 0.5) * " + id_to_name(args[0].base) + ".pixelsize, 0, 0))"; 2536 if (res_type.rows == 1) 2537 code += ".x"; 2538 } 2539 }) 2540 IMPLEMENT_INTRINSIC_HLSL(tex2Dfetch, 1, { 2541 if (_shader_model >= 40) 2542 code += id_to_name(args[0].base) + ".t.Load(int3(" + id_to_name(args[1].base) + ", " + id_to_name(args[2].base) + "))"; 2543 else { 2544 code += "tex2Dlod(" + id_to_name(args[0].base) + ".s, float4((" + 2545 id_to_name(args[1].base) + " + 0.5) * " + id_to_name(args[0].base) + ".pixelsize * exp2(" + id_to_name(args[2].base) + "), 0, " + 2546 id_to_name(args[2].base) + "))"; 2547 if (res_type.rows == 1) 2548 code += ".x"; 2549 } 2550 }) 2551 IMPLEMENT_INTRINSIC_HLSL(tex2Dfetch, 2, { 2552 if (_shader_model >= 50) 2553 code += id_to_name(args[0].base) + '[' + id_to_name(args[1].base) + ']'; 2554 else 2555 code += "{}"; 2556 }) 2557 IMPLEMENT_INTRINSIC_SPIRV(tex2Dfetch, 0, { 2558 const spv::Id image = add_instruction(spv::OpImage, convert_image_type(args[0].type)) 2559 .add(args[0].base) 2560 .result; 2561 2562 type res_vector_type = res_type; 2563 res_vector_type.rows = 4; 2564 2565 const spv::Id res = add_instruction(spv::OpImageFetch, convert_type(res_vector_type)) 2566 .add(image) 2567 .add(args[1].base) 2568 .result; 2569 if (res_type.rows == 1) 2570 // Collapse last argument from a 4-component vector 2571 return 2572 add_instruction(spv::OpCompositeExtract, convert_type(res_type)) 2573 .add(res) 2574 .add(0u) 2575 .result; 2576 else 2577 return res; 2578 }) 2579 IMPLEMENT_INTRINSIC_SPIRV(tex2Dfetch, 1, { 2580 const spv::Id image = add_instruction(spv::OpImage, convert_image_type(args[0].type)) 2581 .add(args[0].base) 2582 .result; 2583 2584 type res_vector_type = res_type; 2585 res_vector_type.rows = 4; 2586 2587 const spv::Id res = add_instruction(spv::OpImageFetch, convert_type(res_vector_type)) 2588 .add(image) 2589 .add(args[1].base) 2590 .add(spv::ImageOperandsLodMask) 2591 .add(args[2].base) 2592 .result; 2593 if (res_type.rows == 1) 2594 return 2595 add_instruction(spv::OpCompositeExtract, convert_type(res_type)) 2596 .add(res) 2597 .add(0u) 2598 .result; 2599 else 2600 return res; 2601 }) 2602 IMPLEMENT_INTRINSIC_SPIRV(tex2Dfetch, 2, { 2603 type res_vector_type = res_type; 2604 res_vector_type.rows = 4; 2605 2606 const spv::Id res = add_instruction(spv::OpImageRead, convert_type(res_vector_type)) 2607 .add(args[0].base) 2608 .add(args[1].base) 2609 .result; 2610 if (res_type.rows == 1) 2611 return 2612 add_instruction(spv::OpCompositeExtract, convert_type(res_type)) 2613 .add(res) 2614 .add(0u) 2615 .result; 2616 else 2617 return res; 2618 }) 2619 2620 // ret tex3Dfetch(s, coords) 2621 // ret tex3Dfetch(s, coords, lod) 2622 DEFINE_INTRINSIC(tex3Dfetch, 0, int, sampler3d_int, int3) 2623 DEFINE_INTRINSIC(tex3Dfetch, 0, uint, sampler3d_uint, int3) 2624 DEFINE_INTRINSIC(tex3Dfetch, 0, float, sampler3d_float, int3) 2625 DEFINE_INTRINSIC(tex3Dfetch, 0, float4, sampler3d_float4, int3) 2626 DEFINE_INTRINSIC(tex3Dfetch, 1, int, sampler3d_int, int3, int) 2627 DEFINE_INTRINSIC(tex3Dfetch, 1, uint, sampler3d_uint, int3, int) 2628 DEFINE_INTRINSIC(tex3Dfetch, 1, float, sampler3d_float, int3, int) 2629 DEFINE_INTRINSIC(tex3Dfetch, 1, float4, sampler3d_float4, int3, int) 2630 DEFINE_INTRINSIC(tex3Dfetch, 2, int, storage3d_int, int3) 2631 DEFINE_INTRINSIC(tex3Dfetch, 2, uint, storage3d_uint, int3) 2632 DEFINE_INTRINSIC(tex3Dfetch, 2, float, storage3d_float, int3) 2633 DEFINE_INTRINSIC(tex3Dfetch, 2, float4, storage3d_float4, int3) 2634 IMPLEMENT_INTRINSIC_GLSL(tex3Dfetch, 0, { 2635 code += "texelFetch(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ", 0)"; 2636 if (res_type.rows == 1) 2637 code += ".x"; // Collapse last argument from a 4-component vector 2638 }) 2639 IMPLEMENT_INTRINSIC_GLSL(tex3Dfetch, 1, { 2640 code += "texelFetch(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ", " + id_to_name(args[2].base) + ')'; 2641 if (res_type.rows == 1) 2642 code += ".x"; 2643 }) 2644 IMPLEMENT_INTRINSIC_GLSL(tex3Dfetch, 2, { 2645 code += "imageLoad(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ")"; 2646 if (res_type.rows == 1) 2647 code += ".x"; 2648 }) 2649 IMPLEMENT_INTRINSIC_HLSL(tex3Dfetch, 0, { 2650 if (_shader_model >= 40) 2651 code += id_to_name(args[0].base) + ".t.Load(int4(" + id_to_name(args[1].base) + ", 0))"; 2652 else { 2653 // SM3 does not have a fetch intrinsic, so emulate it by transforming coordinates into texture space ones 2654 // Also add a half-pixel offset to align texels with pixels 2655 // (coords + 0.5) / size 2656 code += "tex3Dlod(" + id_to_name(args[0].base) + ".s, float4((" + 2657 id_to_name(args[1].base) + " + 0.5) * " + id_to_name(args[0].base) + ".pixelsize, 0))"; 2658 if (res_type.rows == 1) 2659 code += ".x"; 2660 } 2661 }) 2662 IMPLEMENT_INTRINSIC_HLSL(tex3Dfetch, 1, { 2663 if (_shader_model >= 40) 2664 code += id_to_name(args[0].base) + ".t.Load(int4(" + id_to_name(args[1].base) + ", " + id_to_name(args[2].base) + "))"; 2665 else { 2666 code += "tex3Dlod(" + id_to_name(args[0].base) + ".s, float4((" + 2667 id_to_name(args[1].base) + " + 0.5) * " + id_to_name(args[0].base) + ".pixelsize * exp2(" + id_to_name(args[2].base) + "), " + 2668 id_to_name(args[2].base) + "))"; 2669 if (res_type.rows == 1) 2670 code += ".x"; 2671 } 2672 }) 2673 IMPLEMENT_INTRINSIC_HLSL(tex3Dfetch, 2, { 2674 code += id_to_name(args[0].base) + '[' + id_to_name(args[1].base) + ']'; 2675 }) 2676 IMPLEMENT_INTRINSIC_SPIRV(tex3Dfetch, 0, { 2677 const spv::Id image = add_instruction(spv::OpImage, convert_image_type(args[0].type)) 2678 .add(args[0].base) 2679 .result; 2680 2681 type res_vector_type = res_type; 2682 res_vector_type.rows = 4; 2683 2684 const spv::Id res = add_instruction(spv::OpImageFetch, convert_type(res_vector_type)) 2685 .add(image) 2686 .add(args[1].base) 2687 .result; 2688 if (res_type.rows == 1) 2689 // Collapse last argument from a 4-component vector 2690 return 2691 add_instruction(spv::OpCompositeExtract, convert_type(res_type)) 2692 .add(res) 2693 .add(0u) 2694 .result; 2695 else 2696 return res; 2697 }) 2698 IMPLEMENT_INTRINSIC_SPIRV(tex3Dfetch, 1, { 2699 const spv::Id image = add_instruction(spv::OpImage, convert_image_type(args[0].type)) 2700 .add(args[0].base) 2701 .result; 2702 2703 type res_vector_type = res_type; 2704 res_vector_type.rows = 4; 2705 2706 const spv::Id res = add_instruction(spv::OpImageFetch, convert_type(res_vector_type)) 2707 .add(image) 2708 .add(args[1].base) 2709 .add(spv::ImageOperandsLodMask) 2710 .add(args[2].base) 2711 .result; 2712 if (res_type.rows == 1) 2713 return 2714 add_instruction(spv::OpCompositeExtract, convert_type(res_type)) 2715 .add(res) 2716 .add(0u) 2717 .result; 2718 else 2719 return res; 2720 }) 2721 IMPLEMENT_INTRINSIC_SPIRV(tex3Dfetch, 2, { 2722 type res_vector_type = res_type; 2723 res_vector_type.rows = 4; 2724 2725 const spv::Id res = add_instruction(spv::OpImageRead, convert_type(res_vector_type)) 2726 .add(args[0].base) 2727 .add(args[1].base) 2728 .result; 2729 if (res_type.rows == 1) 2730 return 2731 add_instruction(spv::OpCompositeExtract, convert_type(res_type)) 2732 .add(res) 2733 .add(0u) 2734 .result; 2735 else 2736 return res; 2737 }) 2738 2739 // ret tex2DgatherR(s, coords) 2740 // ret tex2DgatherR(s, coords, offset) 2741 // ret tex2DgatherR(s, coords, offset0, offset1, offset2, offset3) 2742 DEFINE_INTRINSIC(tex2DgatherR, 0, float4, sampler2d_float4, float2) 2743 DEFINE_INTRINSIC(tex2DgatherR, 1, float4, sampler2d_float4, float2, int2) 2744 DEFINE_INTRINSIC(tex2DgatherR, 2, float4, sampler2d_float4, float2, int2, int2, int2, int2) 2745 IMPLEMENT_INTRINSIC_GLSL(tex2DgatherR, 0, { 2746 code += "textureGather(" + id_to_name(args[0].base) + ", " + 2747 id_to_name(args[1].base) + ", 0)"; 2748 }) 2749 IMPLEMENT_INTRINSIC_GLSL(tex2DgatherR, 1, { 2750 code += "textureGatherOffset(" + id_to_name(args[0].base) + ", " + 2751 id_to_name(args[1].base) + ", " + 2752 id_to_name(args[2].base) + ", 0)"; 2753 }) 2754 IMPLEMENT_INTRINSIC_GLSL(tex2DgatherR, 2, { 2755 code += "textureGatherOffsets(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ", " + 2756 "ivec2[]( " + id_to_name(args[2].base) + ", " + id_to_name(args[3].base) + ", " + id_to_name(args[4].base) + ", " + id_to_name(args[5].base) + "), 0)"; 2757 }) 2758 IMPLEMENT_INTRINSIC_HLSL(tex2DgatherR, 0, { 2759 const std::string s = id_to_name(args[0].base); 2760 if (_shader_model >= 50) 2761 code += s + ".t.GatherRed(" + s + ".s, " + id_to_name(args[1].base) + ')'; 2762 else if (_shader_model >= 40) // Emulate texture gather intrinsic by sampling each location separately (SM41 has 'Gather', but that only works on single component texture formats) 2763 code += "float4(" + 2764 s + ".t.SampleLevel(" + s + ".s, " + id_to_name(args[1].base) + ", 0, int2(0, 1))." + 'r' + ", " + 2765 s + ".t.SampleLevel(" + s + ".s, " + id_to_name(args[1].base) + ", 0, int2(1, 1))." + 'r' + ", " + 2766 s + ".t.SampleLevel(" + s + ".s, " + id_to_name(args[1].base) + ", 0, int2(1, 0))." + 'r' + ", " + 2767 s + ".t.SampleLevel(" + s + ".s, " + id_to_name(args[1].base) + ", 0, int2(0, 0))." + 'r' + ')'; 2768 else 2769 code += "float4(" 2770 "tex2Dlod(" + s + ".s, float4(" + id_to_name(args[1].base) + " + float2(0, 1) * " + s + ".pixelsize, 0, 0))." + 'r' + ", " 2771 "tex2Dlod(" + s + ".s, float4(" + id_to_name(args[1].base) + " + float2(1, 1) * " + s + ".pixelsize, 0, 0))." + 'r' + ", " 2772 "tex2Dlod(" + s + ".s, float4(" + id_to_name(args[1].base) + " + float2(1, 0) * " + s + ".pixelsize, 0, 0))." + 'r' + ", " 2773 "tex2Dlod(" + s + ".s, float4(" + id_to_name(args[1].base) + " + float2(0, 0) * " + s + ".pixelsize, 0, 0))." + 'r' + ')'; 2774 }) 2775 IMPLEMENT_INTRINSIC_HLSL(tex2DgatherR, 1, { 2776 const std::string s = id_to_name(args[0].base); 2777 if (_shader_model >= 50) 2778 code += s + ".t.GatherRed(" + s + ".s, " + id_to_name(args[1].base) + ", " + id_to_name(args[2].base) + ')'; 2779 else if (_shader_model >= 40) 2780 code += "float4(" + 2781 s + ".t.SampleLevel(" + s + ".s, " + id_to_name(args[1].base) + ", 0, " + id_to_name(args[2].base) + " + int2(0, 1))." + 'r' + ", " + 2782 s + ".t.SampleLevel(" + s + ".s, " + id_to_name(args[1].base) + ", 0, " + id_to_name(args[2].base) + " + int2(1, 1))." + 'r' + ", " + 2783 s + ".t.SampleLevel(" + s + ".s, " + id_to_name(args[1].base) + ", 0, " + id_to_name(args[2].base) + " + int2(1, 0))." + 'r' + ", " + 2784 s + ".t.SampleLevel(" + s + ".s, " + id_to_name(args[1].base) + ", 0, " + id_to_name(args[2].base) + " + int2(0, 0))." + 'r' + ')'; 2785 else 2786 code += "float4(" 2787 "tex2Dlod(" + s + ".s, float4(" + id_to_name(args[1].base) + " + (" + id_to_name(args[2].base) + " + float2(0, 1)) * " + s + ".pixelsize, 0, 0))." + 'r' + ", " 2788 "tex2Dlod(" + s + ".s, float4(" + id_to_name(args[1].base) + " + (" + id_to_name(args[2].base) + " + float2(1, 1)) * " + s + ".pixelsize, 0, 0))." + 'r' + ", " 2789 "tex2Dlod(" + s + ".s, float4(" + id_to_name(args[1].base) + " + (" + id_to_name(args[2].base) + " + float2(1, 0)) * " + s + ".pixelsize, 0, 0))." + 'r' + ", " 2790 "tex2Dlod(" + s + ".s, float4(" + id_to_name(args[1].base) + " + (" + id_to_name(args[2].base) + " + float2(0, 0)) * " + s + ".pixelsize, 0, 0))." + 'r' + ')'; 2791 }) 2792 IMPLEMENT_INTRINSIC_HLSL(tex2DgatherR, 2, { 2793 const std::string s = id_to_name(args[0].base); 2794 if (_shader_model >= 50) 2795 code += s + ".t.GatherRed(" + s + ".s, " + id_to_name(args[1].base) + ", " + 2796 id_to_name(args[2].base) + " - int2(0, 1), " + 2797 id_to_name(args[3].base) + " - int2(1, 1), " + 2798 id_to_name(args[4].base) + " - int2(1, 0), " + 2799 id_to_name(args[5].base) + ')'; 2800 else if (_shader_model >= 40) 2801 code += "float4(" + 2802 s + ".t.SampleLevel(" + s + ".s, " + id_to_name(args[1].base) + ", 0, " + id_to_name(args[2].base) + ")." + 'r' + ", " + 2803 s + ".t.SampleLevel(" + s + ".s, " + id_to_name(args[1].base) + ", 0, " + id_to_name(args[3].base) + ")." + 'r' + ", " + 2804 s + ".t.SampleLevel(" + s + ".s, " + id_to_name(args[1].base) + ", 0, " + id_to_name(args[4].base) + ")." + 'r' + ", " + 2805 s + ".t.SampleLevel(" + s + ".s, " + id_to_name(args[1].base) + ", 0, " + id_to_name(args[5].base) + ")." + 'r' + ')'; 2806 else 2807 code += "float4(" 2808 "tex2Dlod(" + s + ".s, float4(" + id_to_name(args[1].base) + " + (" + id_to_name(args[2].base) + ") * " + s + ".pixelsize, 0, 0))." + 'r' + ", " 2809 "tex2Dlod(" + s + ".s, float4(" + id_to_name(args[1].base) + " + (" + id_to_name(args[3].base) + ") * " + s + ".pixelsize, 0, 0))." + 'r' + ", " 2810 "tex2Dlod(" + s + ".s, float4(" + id_to_name(args[1].base) + " + (" + id_to_name(args[4].base) + ") * " + s + ".pixelsize, 0, 0))." + 'r' + ", " 2811 "tex2Dlod(" + s + ".s, float4(" + id_to_name(args[1].base) + " + (" + id_to_name(args[5].base) + ") * " + s + ".pixelsize, 0, 0))." + 'r' + ')'; 2812 }) 2813 IMPLEMENT_INTRINSIC_SPIRV(tex2DgatherR, 0, { 2814 const spv::Id comp = emit_constant(0u); 2815 2816 return 2817 add_instruction(spv::OpImageGather, convert_type(res_type)) 2818 .add(args[0].base) 2819 .add(args[1].base) 2820 .add(comp) 2821 .add(spv::ImageOperandsMaskNone) 2822 .result; 2823 }) 2824 IMPLEMENT_INTRINSIC_SPIRV(tex2DgatherR, 1, { 2825 if (!args[2].is_constant) 2826 add_capability(spv::CapabilityImageGatherExtended); 2827 2828 const spv::Id comp = emit_constant(0u); 2829 2830 return 2831 add_instruction(spv::OpImageGather, convert_type(res_type)) 2832 .add(args[0].base) 2833 .add(args[1].base) 2834 .add(comp) 2835 .add(args[2].is_constant ? spv::ImageOperandsConstOffsetMask : spv::ImageOperandsOffsetMask) 2836 .add(args[2].base) 2837 .result; 2838 }) 2839 IMPLEMENT_INTRINSIC_SPIRV(tex2DgatherR, 2, { 2840 add_capability(spv::CapabilityImageGatherExtended); 2841 2842 const spv::Id comp = emit_constant(0u); 2843 const spv::Id offsets = add_instruction(spv::OpConstantComposite, convert_type({ reshadefx::type::t_int, 2, 1, 0, 4 }), _types_and_constants) 2844 .add(args[2].base) 2845 .add(args[3].base) 2846 .add(args[4].base) 2847 .add(args[5].base) 2848 .result; 2849 2850 return 2851 add_instruction(spv::OpImageGather, convert_type(res_type)) 2852 .add(args[0].base) 2853 .add(args[1].base) 2854 .add(comp) 2855 .add(spv::ImageOperandsConstOffsetsMask) 2856 .add(offsets) 2857 .result; 2858 }) 2859 // ret tex2DgatherG(s, coords) 2860 // ret tex2DgatherG(s, coords, offset) 2861 // ret tex2DgatherG(s, coords, offset0, offset1, offset2, offset3) 2862 DEFINE_INTRINSIC(tex2DgatherG, 0, float4, sampler2d_float4, float2) 2863 DEFINE_INTRINSIC(tex2DgatherG, 1, float4, sampler2d_float4, float2, int2) 2864 DEFINE_INTRINSIC(tex2DgatherG, 2, float4, sampler2d_float4, float2, int2, int2, int2, int2) 2865 IMPLEMENT_INTRINSIC_GLSL(tex2DgatherG, 0, { 2866 code += "textureGather(" + id_to_name(args[0].base) + ", " + 2867 id_to_name(args[1].base) + ", 1)"; 2868 }) 2869 IMPLEMENT_INTRINSIC_GLSL(tex2DgatherG, 1, { 2870 code += "textureGatherOffset(" + id_to_name(args[0].base) + ", " + 2871 id_to_name(args[1].base) + ", " + 2872 id_to_name(args[2].base) + ", 1)"; 2873 }) 2874 IMPLEMENT_INTRINSIC_GLSL(tex2DgatherG, 2, { 2875 code += "textureGatherOffsets(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ", " + 2876 "ivec2[]( " + id_to_name(args[2].base) + ", " + id_to_name(args[3].base) + ", " + id_to_name(args[4].base) + ", " + id_to_name(args[5].base) + "), 1)"; 2877 }) 2878 IMPLEMENT_INTRINSIC_HLSL(tex2DgatherG, 0, { 2879 const std::string s = id_to_name(args[0].base); 2880 if (_shader_model >= 50) 2881 code += s + ".t.GatherGreen(" + id_to_name(args[0].base) + ".s, " + id_to_name(args[1].base) + ')'; 2882 else if (_shader_model >= 40) 2883 code += "float4(" + 2884 s + ".t.SampleLevel(" + s + ".s, " + id_to_name(args[1].base) + ", 0, int2(0, 1))." + 'g' + ", " + 2885 s + ".t.SampleLevel(" + s + ".s, " + id_to_name(args[1].base) + ", 0, int2(1, 1))." + 'g' + ", " + 2886 s + ".t.SampleLevel(" + s + ".s, " + id_to_name(args[1].base) + ", 0, int2(1, 0))." + 'g' + ", " + 2887 s + ".t.SampleLevel(" + s + ".s, " + id_to_name(args[1].base) + ", 0, int2(0, 0))." + 'g' + ')'; 2888 else 2889 code += "float4(" 2890 "tex2Dlod(" + s + ".s, float4(" + id_to_name(args[1].base) + " + float2(0, 1) * " + s + ".pixelsize, 0, 0))." + 'g' + ", " 2891 "tex2Dlod(" + s + ".s, float4(" + id_to_name(args[1].base) + " + float2(1, 1) * " + s + ".pixelsize, 0, 0))." + 'g' + ", " 2892 "tex2Dlod(" + s + ".s, float4(" + id_to_name(args[1].base) + " + float2(1, 0) * " + s + ".pixelsize, 0, 0))." + 'g' + ", " 2893 "tex2Dlod(" + s + ".s, float4(" + id_to_name(args[1].base) + " + float2(0, 0) * " + s + ".pixelsize, 0, 0))." + 'g' + ')'; 2894 }) 2895 IMPLEMENT_INTRINSIC_HLSL(tex2DgatherG, 1, { 2896 const std::string s = id_to_name(args[0].base); 2897 if (_shader_model >= 50) 2898 code += s + ".t.GatherGreen(" + s + ".s, " + id_to_name(args[1].base) + ", " + id_to_name(args[2].base) + ')'; 2899 else if (_shader_model >= 40) 2900 code += "float4(" + 2901 s + ".t.SampleLevel(" + s + ".s, " + id_to_name(args[1].base) + ", 0, " + id_to_name(args[2].base) + " + int2(0, 1))." + 'g' + ", " + 2902 s + ".t.SampleLevel(" + s + ".s, " + id_to_name(args[1].base) + ", 0, " + id_to_name(args[2].base) + " + int2(1, 1))." + 'g' + ", " + 2903 s + ".t.SampleLevel(" + s + ".s, " + id_to_name(args[1].base) + ", 0, " + id_to_name(args[2].base) + " + int2(1, 0))." + 'g' + ", " + 2904 s + ".t.SampleLevel(" + s + ".s, " + id_to_name(args[1].base) + ", 0, " + id_to_name(args[2].base) + " + int2(0, 0))." + 'g' + ')'; 2905 else 2906 code += "float4(" 2907 "tex2Dlod(" + s + ".s, float4(" + id_to_name(args[1].base) + " + (" + id_to_name(args[2].base) + " + float2(0, 1)) * " + s + ".pixelsize, 0, 0))." + 'g' + ", " 2908 "tex2Dlod(" + s + ".s, float4(" + id_to_name(args[1].base) + " + (" + id_to_name(args[2].base) + " + float2(1, 1)) * " + s + ".pixelsize, 0, 0))." + 'g' + ", " 2909 "tex2Dlod(" + s + ".s, float4(" + id_to_name(args[1].base) + " + (" + id_to_name(args[2].base) + " + float2(1, 0)) * " + s + ".pixelsize, 0, 0))." + 'g' + ", " 2910 "tex2Dlod(" + s + ".s, float4(" + id_to_name(args[1].base) + " + (" + id_to_name(args[2].base) + " + float2(0, 0)) * " + s + ".pixelsize, 0, 0))." + 'g' + ')'; 2911 }) 2912 IMPLEMENT_INTRINSIC_HLSL(tex2DgatherG, 2, { 2913 const std::string s = id_to_name(args[0].base); 2914 if (_shader_model >= 50) 2915 code += s + ".t.GatherGreen(" + s + ".s, " + id_to_name(args[1].base) + ", " + 2916 id_to_name(args[2].base) + " - int2(0, 1), " + 2917 id_to_name(args[3].base) + " - int2(1, 1), " + 2918 id_to_name(args[4].base) + " - int2(1, 0), " + 2919 id_to_name(args[5].base) + ')'; 2920 else if (_shader_model >= 40) 2921 code += "float4(" + 2922 s + ".t.SampleLevel(" + s + ".s, " + id_to_name(args[1].base) + ", 0, " + id_to_name(args[2].base) + ")." + 'g' + ", " + 2923 s + ".t.SampleLevel(" + s + ".s, " + id_to_name(args[1].base) + ", 0, " + id_to_name(args[3].base) + ")." + 'g' + ", " + 2924 s + ".t.SampleLevel(" + s + ".s, " + id_to_name(args[1].base) + ", 0, " + id_to_name(args[4].base) + ")." + 'g' + ", " + 2925 s + ".t.SampleLevel(" + s + ".s, " + id_to_name(args[1].base) + ", 0, " + id_to_name(args[5].base) + ")." + 'g' + ')'; 2926 else 2927 code += "float4(" 2928 "tex2Dlod(" + s + ".s, float4(" + id_to_name(args[1].base) + " + (" + id_to_name(args[2].base) + ") * " + s + ".pixelsize, 0, 0))." + 'g' + ", " 2929 "tex2Dlod(" + s + ".s, float4(" + id_to_name(args[1].base) + " + (" + id_to_name(args[3].base) + ") * " + s + ".pixelsize, 0, 0))." + 'g' + ", " 2930 "tex2Dlod(" + s + ".s, float4(" + id_to_name(args[1].base) + " + (" + id_to_name(args[4].base) + ") * " + s + ".pixelsize, 0, 0))." + 'g' + ", " 2931 "tex2Dlod(" + s + ".s, float4(" + id_to_name(args[1].base) + " + (" + id_to_name(args[5].base) + ") * " + s + ".pixelsize, 0, 0))." + 'g' + ')'; 2932 }) 2933 IMPLEMENT_INTRINSIC_SPIRV(tex2DgatherG, 0, { 2934 const spv::Id comp = emit_constant(1u); 2935 2936 return 2937 add_instruction(spv::OpImageGather, convert_type(res_type)) 2938 .add(args[0].base) 2939 .add(args[1].base) 2940 .add(comp) 2941 .add(spv::ImageOperandsMaskNone) 2942 .result; 2943 }) 2944 IMPLEMENT_INTRINSIC_SPIRV(tex2DgatherG, 1, { 2945 if (!args[2].is_constant) 2946 add_capability(spv::CapabilityImageGatherExtended); 2947 2948 const spv::Id comp = emit_constant(1u); 2949 2950 return 2951 add_instruction(spv::OpImageGather, convert_type(res_type)) 2952 .add(args[0].base) 2953 .add(args[1].base) 2954 .add(comp) 2955 .add(args[2].is_constant ? spv::ImageOperandsConstOffsetMask : spv::ImageOperandsOffsetMask) 2956 .add(args[2].base) 2957 .result; 2958 }) 2959 IMPLEMENT_INTRINSIC_SPIRV(tex2DgatherG, 2, { 2960 add_capability(spv::CapabilityImageGatherExtended); 2961 2962 const spv::Id comp = emit_constant(1u); 2963 const spv::Id offsets = add_instruction(spv::OpConstantComposite, convert_type({ reshadefx::type::t_int, 2, 1, 0, 4 }), _types_and_constants) 2964 .add(args[2].base) 2965 .add(args[3].base) 2966 .add(args[4].base) 2967 .add(args[5].base) 2968 .result; 2969 2970 return 2971 add_instruction(spv::OpImageGather, convert_type(res_type)) 2972 .add(args[0].base) 2973 .add(args[1].base) 2974 .add(comp) 2975 .add(spv::ImageOperandsConstOffsetsMask) 2976 .add(offsets) 2977 .result; 2978 }) 2979 // ret tex2DgatherB(s, coords) 2980 // ret tex2DgatherB(s, coords, offset) 2981 // ret tex2DgatherB(s, coords, offset0, offset1, offset2, offset3) 2982 DEFINE_INTRINSIC(tex2DgatherB, 0, float4, sampler2d_float4, float2) 2983 DEFINE_INTRINSIC(tex2DgatherB, 1, float4, sampler2d_float4, float2, int2) 2984 DEFINE_INTRINSIC(tex2DgatherB, 2, float4, sampler2d_float4, float2, int2, int2, int2, int2) 2985 IMPLEMENT_INTRINSIC_GLSL(tex2DgatherB, 0, { 2986 code += "textureGather(" + id_to_name(args[0].base) + ", " + 2987 id_to_name(args[1].base) + ", 2)"; 2988 }) 2989 IMPLEMENT_INTRINSIC_GLSL(tex2DgatherB, 1, { 2990 code += "textureGatherOffset(" + id_to_name(args[0].base) + ", " + 2991 id_to_name(args[1].base) + ", " + 2992 id_to_name(args[2].base) + ", 2)"; 2993 }) 2994 IMPLEMENT_INTRINSIC_GLSL(tex2DgatherB, 2, { 2995 code += "textureGatherOffsets(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ", " + 2996 "ivec2[]( " + id_to_name(args[2].base) + ", " + id_to_name(args[3].base) + ", " + id_to_name(args[4].base) + ", " + id_to_name(args[5].base) + "), 2)"; 2997 }) 2998 IMPLEMENT_INTRINSIC_HLSL(tex2DgatherB, 0, { 2999 const std::string s = id_to_name(args[0].base); 3000 if (_shader_model >= 50) 3001 code += s + ".t.GatherBlue(" + s + ".s, " + id_to_name(args[1].base) + ')'; 3002 else if (_shader_model >= 40) 3003 code += "float4(" + 3004 s + ".t.SampleLevel(" + s + ".s, " + id_to_name(args[1].base) + ", 0, int2(0, 1))." + 'b' + ", " + 3005 s + ".t.SampleLevel(" + s + ".s, " + id_to_name(args[1].base) + ", 0, int2(1, 1))." + 'b' + ", " + 3006 s + ".t.SampleLevel(" + s + ".s, " + id_to_name(args[1].base) + ", 0, int2(1, 0))." + 'b' + ", " + 3007 s + ".t.SampleLevel(" + s + ".s, " + id_to_name(args[1].base) + ", 0, int2(0, 0))." + 'b' + ')'; 3008 else 3009 code += "float4(" 3010 "tex2Dlod(" + s + ".s, float4(" + id_to_name(args[1].base) + " + float2(0, 1) * " + s + ".pixelsize, 0, 0))." + 'b' + ", " 3011 "tex2Dlod(" + s + ".s, float4(" + id_to_name(args[1].base) + " + float2(1, 1) * " + s + ".pixelsize, 0, 0))." + 'b' + ", " 3012 "tex2Dlod(" + s + ".s, float4(" + id_to_name(args[1].base) + " + float2(1, 0) * " + s + ".pixelsize, 0, 0))." + 'b' + ", " 3013 "tex2Dlod(" + s + ".s, float4(" + id_to_name(args[1].base) + " + float2(0, 0) * " + s + ".pixelsize, 0, 0))." + 'b' + ')'; 3014 }) 3015 IMPLEMENT_INTRINSIC_HLSL(tex2DgatherB, 1, { 3016 const std::string s = id_to_name(args[0].base); 3017 if (_shader_model >= 50) 3018 code += s + ".t.GatherBlue(" + s + ".s, " + id_to_name(args[1].base) + ", " + id_to_name(args[2].base) + ')'; 3019 else if (_shader_model >= 40) 3020 code += "float4(" + 3021 s + ".t.SampleLevel(" + s + ".s, " + id_to_name(args[1].base) + ", 0, " + id_to_name(args[2].base) + " + int2(0, 1))." + 'b' + ", " + 3022 s + ".t.SampleLevel(" + s + ".s, " + id_to_name(args[1].base) + ", 0, " + id_to_name(args[2].base) + " + int2(1, 1))." + 'b' + ", " + 3023 s + ".t.SampleLevel(" + s + ".s, " + id_to_name(args[1].base) + ", 0, " + id_to_name(args[2].base) + " + int2(1, 0))." + 'b' + ", " + 3024 s + ".t.SampleLevel(" + s + ".s, " + id_to_name(args[1].base) + ", 0, " + id_to_name(args[2].base) + " + int2(0, 0))." + 'b' + ')'; 3025 else 3026 code += "float4(" 3027 "tex2Dlod(" + s + ".s, float4(" + id_to_name(args[1].base) + " + (" + id_to_name(args[2].base) + " + float2(0, 1)) * " + s + ".pixelsize, 0, 0))." + 'b' + ", " 3028 "tex2Dlod(" + s + ".s, float4(" + id_to_name(args[1].base) + " + (" + id_to_name(args[2].base) + " + float2(1, 1)) * " + s + ".pixelsize, 0, 0))." + 'b' + ", " 3029 "tex2Dlod(" + s + ".s, float4(" + id_to_name(args[1].base) + " + (" + id_to_name(args[2].base) + " + float2(1, 0)) * " + s + ".pixelsize, 0, 0))." + 'b' + ", " 3030 "tex2Dlod(" + s + ".s, float4(" + id_to_name(args[1].base) + " + (" + id_to_name(args[2].base) + " + float2(0, 0)) * " + s + ".pixelsize, 0, 0))." + 'b' + ')'; 3031 }) 3032 IMPLEMENT_INTRINSIC_HLSL(tex2DgatherB, 2, { 3033 const std::string s = id_to_name(args[0].base); 3034 if (_shader_model >= 50) 3035 code += s + ".t.GatherBlue(" + s + ".s, " + id_to_name(args[1].base) + ", " + 3036 id_to_name(args[2].base) + " - int2(0, 1), " + 3037 id_to_name(args[3].base) + " - int2(1, 1), " + 3038 id_to_name(args[4].base) + " - int2(1, 0), " + 3039 id_to_name(args[5].base) + ')'; 3040 else if (_shader_model >= 40) 3041 code += "float4(" + 3042 s + ".t.SampleLevel(" + s + ".s, " + id_to_name(args[1].base) + ", 0, " + id_to_name(args[2].base) + ")." + 'b' + ", " + 3043 s + ".t.SampleLevel(" + s + ".s, " + id_to_name(args[1].base) + ", 0, " + id_to_name(args[3].base) + ")." + 'b' + ", " + 3044 s + ".t.SampleLevel(" + s + ".s, " + id_to_name(args[1].base) + ", 0, " + id_to_name(args[4].base) + ")." + 'b' + ", " + 3045 s + ".t.SampleLevel(" + s + ".s, " + id_to_name(args[1].base) + ", 0, " + id_to_name(args[5].base) + ")." + 'b' + ')'; 3046 else 3047 code += "float4(" 3048 "tex2Dlod(" + s + ".s, float4(" + id_to_name(args[1].base) + " + (" + id_to_name(args[2].base) + ") * " + s + ".pixelsize, 0, 0))." + 'b' + ", " 3049 "tex2Dlod(" + s + ".s, float4(" + id_to_name(args[1].base) + " + (" + id_to_name(args[3].base) + ") * " + s + ".pixelsize, 0, 0))." + 'b' + ", " 3050 "tex2Dlod(" + s + ".s, float4(" + id_to_name(args[1].base) + " + (" + id_to_name(args[4].base) + ") * " + s + ".pixelsize, 0, 0))." + 'b' + ", " 3051 "tex2Dlod(" + s + ".s, float4(" + id_to_name(args[1].base) + " + (" + id_to_name(args[5].base) + ") * " + s + ".pixelsize, 0, 0))." + 'b' + ')'; 3052 }) 3053 IMPLEMENT_INTRINSIC_SPIRV(tex2DgatherB, 0, { 3054 const spv::Id comp = emit_constant(2u); 3055 3056 return 3057 add_instruction(spv::OpImageGather, convert_type(res_type)) 3058 .add(args[0].base) 3059 .add(args[1].base) 3060 .add(comp) 3061 .add(spv::ImageOperandsMaskNone) 3062 .result; 3063 }) 3064 IMPLEMENT_INTRINSIC_SPIRV(tex2DgatherB, 1, { 3065 if (!args[2].is_constant) 3066 add_capability(spv::CapabilityImageGatherExtended); 3067 3068 const spv::Id comp = emit_constant(2u); 3069 3070 return 3071 add_instruction(spv::OpImageGather, convert_type(res_type)) 3072 .add(args[0].base) 3073 .add(args[1].base) 3074 .add(comp) 3075 .add(args[2].is_constant ? spv::ImageOperandsConstOffsetMask : spv::ImageOperandsOffsetMask) 3076 .add(args[2].base) 3077 .result; 3078 }) 3079 IMPLEMENT_INTRINSIC_SPIRV(tex2DgatherB, 2, { 3080 add_capability(spv::CapabilityImageGatherExtended); 3081 3082 const spv::Id comp = emit_constant(2u); 3083 const spv::Id offsets = add_instruction(spv::OpConstantComposite, convert_type({ reshadefx::type::t_int, 2, 1, 0, 4 }), _types_and_constants) 3084 .add(args[2].base) 3085 .add(args[3].base) 3086 .add(args[4].base) 3087 .add(args[5].base) 3088 .result; 3089 3090 return 3091 add_instruction(spv::OpImageGather, convert_type(res_type)) 3092 .add(args[0].base) 3093 .add(args[1].base) 3094 .add(comp) 3095 .add(spv::ImageOperandsConstOffsetsMask) 3096 .add(offsets) 3097 .result; 3098 }) 3099 // ret tex2DgatherA(s, coords) 3100 // ret tex2DgatherA(s, coords, offset) 3101 // ret tex2DgatherA(s, coords, offset0, offset1, offset2, offset3) 3102 DEFINE_INTRINSIC(tex2DgatherA, 0, float4, sampler2d_float4, float2) 3103 DEFINE_INTRINSIC(tex2DgatherA, 1, float4, sampler2d_float4, float2, int2) 3104 DEFINE_INTRINSIC(tex2DgatherA, 2, float4, sampler2d_float4, float2, int2, int2, int2, int2) 3105 IMPLEMENT_INTRINSIC_GLSL(tex2DgatherA, 0, { 3106 code += "textureGather(" + id_to_name(args[0].base) + ", " + 3107 id_to_name(args[1].base) + ", 3)"; 3108 }) 3109 IMPLEMENT_INTRINSIC_GLSL(tex2DgatherA, 1, { 3110 code += "textureGatherOffset(" + id_to_name(args[0].base) + ", " + 3111 id_to_name(args[1].base) + ", " + 3112 id_to_name(args[2].base) + ", 3)"; 3113 }) 3114 IMPLEMENT_INTRINSIC_GLSL(tex2DgatherA, 2, { 3115 code += "textureGatherOffsets(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ", " + 3116 "ivec2[]( " + id_to_name(args[2].base) + ", " + id_to_name(args[3].base) + ", " + id_to_name(args[4].base) + ", " + id_to_name(args[5].base) + "), 3)"; 3117 }) 3118 IMPLEMENT_INTRINSIC_HLSL(tex2DgatherA, 0, { 3119 const std::string s = id_to_name(args[0].base); 3120 if (_shader_model >= 50) 3121 code += s + ".t.GatherAlpha(" + s + ".s, " + id_to_name(args[1].base) + ')'; 3122 else if (_shader_model >= 40) 3123 code += "float4(" + 3124 s + ".t.SampleLevel(" + s + ".s, " + id_to_name(args[1].base) + ", 0, int2(0, 1))." + 'a' + ", " + 3125 s + ".t.SampleLevel(" + s + ".s, " + id_to_name(args[1].base) + ", 0, int2(1, 1))." + 'a' + ", " + 3126 s + ".t.SampleLevel(" + s + ".s, " + id_to_name(args[1].base) + ", 0, int2(1, 0))." + 'a' + ", " + 3127 s + ".t.SampleLevel(" + s + ".s, " + id_to_name(args[1].base) + ", 0, int2(0, 0))." + 'a' + ')'; 3128 else 3129 code += "float4(" 3130 "tex2Dlod(" + s + ".s, float4(" + id_to_name(args[1].base) + " + float2(0, 1) * " + s + ".pixelsize, 0, 0))." + 'a' + ", " 3131 "tex2Dlod(" + s + ".s, float4(" + id_to_name(args[1].base) + " + float2(1, 1) * " + s + ".pixelsize, 0, 0))." + 'a' + ", " 3132 "tex2Dlod(" + s + ".s, float4(" + id_to_name(args[1].base) + " + float2(1, 0) * " + s + ".pixelsize, 0, 0))." + 'a' + ", " 3133 "tex2Dlod(" + s + ".s, float4(" + id_to_name(args[1].base) + " + float2(0, 0) * " + s + ".pixelsize, 0, 0))." + 'a' + ')'; 3134 }) 3135 IMPLEMENT_INTRINSIC_HLSL(tex2DgatherA, 1, { 3136 const std::string s = id_to_name(args[0].base); 3137 if (_shader_model >= 50) 3138 code += s + ".t.GatherAlpha(" + s + ".s, " + id_to_name(args[1].base) + ", " + id_to_name(args[2].base) + ')'; 3139 else if (_shader_model >= 40) 3140 code += "float4(" + 3141 s + ".t.SampleLevel(" + s + ".s, " + id_to_name(args[1].base) + ", 0, " + id_to_name(args[2].base) + " + int2(0, 1))." + 'a' + ", " + 3142 s + ".t.SampleLevel(" + s + ".s, " + id_to_name(args[1].base) + ", 0, " + id_to_name(args[2].base) + " + int2(1, 1))." + 'a' + ", " + 3143 s + ".t.SampleLevel(" + s + ".s, " + id_to_name(args[1].base) + ", 0, " + id_to_name(args[2].base) + " + int2(1, 0))." + 'a' + ", " + 3144 s + ".t.SampleLevel(" + s + ".s, " + id_to_name(args[1].base) + ", 0, " + id_to_name(args[2].base) + " + int2(0, 0))." + 'a' + ')'; 3145 else 3146 code += "float4(" 3147 "tex2Dlod(" + s + ".s, float4(" + id_to_name(args[1].base) + " + (" + id_to_name(args[2].base) + " + float2(0, 1)) * " + s + ".pixelsize, 0, 0))." + 'a' + ", " 3148 "tex2Dlod(" + s + ".s, float4(" + id_to_name(args[1].base) + " + (" + id_to_name(args[2].base) + " + float2(1, 1)) * " + s + ".pixelsize, 0, 0))." + 'a' + ", " 3149 "tex2Dlod(" + s + ".s, float4(" + id_to_name(args[1].base) + " + (" + id_to_name(args[2].base) + " + float2(1, 0)) * " + s + ".pixelsize, 0, 0))." + 'a' + ", " 3150 "tex2Dlod(" + s + ".s, float4(" + id_to_name(args[1].base) + " + (" + id_to_name(args[2].base) + " + float2(0, 0)) * " + s + ".pixelsize, 0, 0))." + 'a' + ')'; 3151 }) 3152 IMPLEMENT_INTRINSIC_HLSL(tex2DgatherA, 2, { 3153 const std::string s = id_to_name(args[0].base); 3154 if (_shader_model >= 50) 3155 code += s + ".t.GatherAlpha(" + s + ".s, " + id_to_name(args[1].base) + ", " + 3156 id_to_name(args[2].base) + " - int2(0, 1), " + 3157 id_to_name(args[3].base) + " - int2(1, 1), " + 3158 id_to_name(args[4].base) + " - int2(1, 0), " + 3159 id_to_name(args[5].base) + ')'; 3160 else if (_shader_model >= 40) 3161 code += "float4(" + 3162 s + ".t.SampleLevel(" + s + ".s, " + id_to_name(args[1].base) + ", 0, " + id_to_name(args[2].base) + ")." + 'a' + ", " + 3163 s + ".t.SampleLevel(" + s + ".s, " + id_to_name(args[1].base) + ", 0, " + id_to_name(args[3].base) + ")." + 'a' + ", " + 3164 s + ".t.SampleLevel(" + s + ".s, " + id_to_name(args[1].base) + ", 0, " + id_to_name(args[4].base) + ")." + 'a' + ", " + 3165 s + ".t.SampleLevel(" + s + ".s, " + id_to_name(args[1].base) + ", 0, " + id_to_name(args[5].base) + ")." + 'a' + ')'; 3166 else 3167 code += "float4(" 3168 "tex2Dlod(" + s + ".s, float4(" + id_to_name(args[1].base) + " + (" + id_to_name(args[2].base) + ") * " + s + ".pixelsize, 0, 0))." + 'a' + ", " 3169 "tex2Dlod(" + s + ".s, float4(" + id_to_name(args[1].base) + " + (" + id_to_name(args[3].base) + ") * " + s + ".pixelsize, 0, 0))." + 'a' + ", " 3170 "tex2Dlod(" + s + ".s, float4(" + id_to_name(args[1].base) + " + (" + id_to_name(args[4].base) + ") * " + s + ".pixelsize, 0, 0))." + 'a' + ", " 3171 "tex2Dlod(" + s + ".s, float4(" + id_to_name(args[1].base) + " + (" + id_to_name(args[5].base) + ") * " + s + ".pixelsize, 0, 0))." + 'a' + ')'; 3172 }) 3173 IMPLEMENT_INTRINSIC_SPIRV(tex2DgatherA, 0, { 3174 const spv::Id comp = emit_constant(3u); 3175 3176 return 3177 add_instruction(spv::OpImageGather, convert_type(res_type)) 3178 .add(args[0].base) 3179 .add(args[1].base) 3180 .add(comp) 3181 .add(spv::ImageOperandsMaskNone) 3182 .result; 3183 }) 3184 IMPLEMENT_INTRINSIC_SPIRV(tex2DgatherA, 1, { 3185 if (!args[2].is_constant) 3186 add_capability(spv::CapabilityImageGatherExtended); 3187 3188 const spv::Id comp = emit_constant(3u); 3189 3190 return 3191 add_instruction(spv::OpImageGather, convert_type(res_type)) 3192 .add(args[0].base) 3193 .add(args[1].base) 3194 .add(comp) 3195 .add(args[2].is_constant ? spv::ImageOperandsConstOffsetMask : spv::ImageOperandsOffsetMask) 3196 .add(args[2].base) 3197 .result; 3198 }) 3199 IMPLEMENT_INTRINSIC_SPIRV(tex2DgatherA, 2, { 3200 add_capability(spv::CapabilityImageGatherExtended); 3201 3202 const spv::Id comp = emit_constant(3u); 3203 const spv::Id offsets = add_instruction(spv::OpConstantComposite, convert_type({ reshadefx::type::t_int, 2, 1, 0, 4 }), _types_and_constants) 3204 .add(args[2].base) 3205 .add(args[3].base) 3206 .add(args[4].base) 3207 .add(args[5].base) 3208 .result; 3209 3210 return 3211 add_instruction(spv::OpImageGather, convert_type(res_type)) 3212 .add(args[0].base) 3213 .add(args[1].base) 3214 .add(comp) 3215 .add(spv::ImageOperandsConstOffsetsMask) 3216 .add(offsets) 3217 .result; 3218 }) 3219 3220 // tex1Dstore(s, coords, value) 3221 DEFINE_INTRINSIC(tex1Dstore, 0, void, storage1d_int, int, int) 3222 DEFINE_INTRINSIC(tex1Dstore, 0, void, storage1d_uint, int, uint) 3223 DEFINE_INTRINSIC(tex1Dstore, 0, void, storage1d_float, int, float) 3224 DEFINE_INTRINSIC(tex1Dstore, 0, void, storage1d_float4, int, float4) 3225 IMPLEMENT_INTRINSIC_GLSL(tex1Dstore, 0, { 3226 code += "imageStore(" + id_to_name(args[0].base) + ", " + 3227 id_to_name(args[1].base) + ", " + 3228 id_to_name(args[2].base); 3229 if (args[2].type.rows == 1) 3230 code += ".xxxx"; // Expand last argument to a 4-component vector 3231 code += ')'; 3232 }) 3233 IMPLEMENT_INTRINSIC_HLSL(tex1Dstore, 0, { 3234 if (_shader_model >= 50) { 3235 code += id_to_name(args[0].base) + '[' + id_to_name(args[1].base) + "] = " + id_to_name(args[2].base); 3236 } 3237 }) 3238 IMPLEMENT_INTRINSIC_SPIRV(tex1Dstore, 0, { 3239 spv::Id data = args[2].base; 3240 if (args[2].type.rows == 1) 3241 { 3242 // Expand last argument to a 4-component vector 3243 auto comp_type = args[2].type; 3244 comp_type.rows = 4; 3245 3246 data = add_instruction(spv::OpCompositeConstruct, convert_type(comp_type)) 3247 .add(data) 3248 .add(data) 3249 .add(data) 3250 .add(data) 3251 .result; 3252 } 3253 3254 add_instruction_without_result(spv::OpImageWrite) 3255 .add(args[0].base) 3256 .add(args[1].base) 3257 .add(data); 3258 return 0; 3259 }) 3260 3261 // tex2Dstore(s, coords, value) 3262 DEFINE_INTRINSIC(tex2Dstore, 0, void, storage2d_int, int2, int) 3263 DEFINE_INTRINSIC(tex2Dstore, 0, void, storage2d_uint, int2, uint) 3264 DEFINE_INTRINSIC(tex2Dstore, 0, void, storage2d_float, int2, float) 3265 DEFINE_INTRINSIC(tex2Dstore, 0, void, storage2d_float4, int2, float4) 3266 IMPLEMENT_INTRINSIC_GLSL(tex2Dstore, 0, { 3267 code += "imageStore(" + id_to_name(args[0].base) + ", " + 3268 id_to_name(args[1].base) + ", " + 3269 id_to_name(args[2].base); 3270 if (args[2].type.rows == 1) 3271 code += ".xxxx"; // Expand last argument to a 4-component vector 3272 code += ')'; 3273 }) 3274 IMPLEMENT_INTRINSIC_HLSL(tex2Dstore, 0, { 3275 if (_shader_model >= 50) 3276 code += id_to_name(args[0].base) + '[' + id_to_name(args[1].base) + "] = " + id_to_name(args[2].base); 3277 }) 3278 IMPLEMENT_INTRINSIC_SPIRV(tex2Dstore, 0, { 3279 spv::Id data = args[2].base; 3280 if (args[2].type.rows == 1) 3281 { 3282 // Expand last argument to a 4-component vector 3283 auto comp_type = args[2].type; 3284 comp_type.rows = 4; 3285 3286 data = add_instruction(spv::OpCompositeConstruct, convert_type(comp_type)) 3287 .add(data) 3288 .add(data) 3289 .add(data) 3290 .add(data) 3291 .result; 3292 } 3293 3294 add_instruction_without_result(spv::OpImageWrite) 3295 .add(args[0].base) 3296 .add(args[1].base) 3297 .add(data); 3298 return 0; 3299 }) 3300 3301 // tex3Dstore(s, coords, value) 3302 DEFINE_INTRINSIC(tex3Dstore, 0, void, storage3d_int, int3, int) 3303 DEFINE_INTRINSIC(tex3Dstore, 0, void, storage3d_uint, int3, uint) 3304 DEFINE_INTRINSIC(tex3Dstore, 0, void, storage3d_float, int3, float) 3305 DEFINE_INTRINSIC(tex3Dstore, 0, void, storage3d_float4, int3, float4) 3306 IMPLEMENT_INTRINSIC_GLSL(tex3Dstore, 0, { 3307 code += "imageStore(" + id_to_name(args[0].base) + ", " + 3308 id_to_name(args[1].base) + ", " + 3309 id_to_name(args[2].base); 3310 if (args[2].type.rows == 1) 3311 code += ".xxxx"; // Expand last argument to a 4-component vector 3312 code += ')'; 3313 }) 3314 IMPLEMENT_INTRINSIC_HLSL(tex3Dstore, 0, { 3315 code += id_to_name(args[0].base) + '[' + id_to_name(args[1].base) + "] = " + id_to_name(args[2].base); 3316 }) 3317 IMPLEMENT_INTRINSIC_SPIRV(tex3Dstore, 0, { 3318 spv::Id data = args[2].base; 3319 if (args[2].type.rows == 1) 3320 { 3321 // Expand last argument to a 4-component vector 3322 auto comp_type = args[2].type; 3323 comp_type.rows = 4; 3324 3325 data = add_instruction(spv::OpCompositeConstruct, convert_type(comp_type)) 3326 .add(data) 3327 .add(data) 3328 .add(data) 3329 .add(data) 3330 .result; 3331 } 3332 3333 add_instruction_without_result(spv::OpImageWrite) 3334 .add(args[0].base) 3335 .add(args[1].base) 3336 .add(data); 3337 return 0; 3338 }) 3339 3340 // ret tex1Dsize(s) 3341 // ret tex1Dsize(s, lod) 3342 DEFINE_INTRINSIC(tex1Dsize, 0, int, sampler1d_int) 3343 DEFINE_INTRINSIC(tex1Dsize, 0, int, sampler1d_uint) 3344 DEFINE_INTRINSIC(tex1Dsize, 0, int, sampler1d_float) 3345 DEFINE_INTRINSIC(tex1Dsize, 0, int, sampler1d_float4) 3346 DEFINE_INTRINSIC(tex1Dsize, 1, int, sampler1d_int, int) 3347 DEFINE_INTRINSIC(tex1Dsize, 1, int, sampler1d_uint, int) 3348 DEFINE_INTRINSIC(tex1Dsize, 1, int, sampler1d_float, int) 3349 DEFINE_INTRINSIC(tex1Dsize, 1, int, sampler1d_float4, int) 3350 DEFINE_INTRINSIC(tex1Dsize, 2, int, storage1d_int) 3351 DEFINE_INTRINSIC(tex1Dsize, 2, int, storage1d_uint) 3352 DEFINE_INTRINSIC(tex1Dsize, 2, int, storage1d_float) 3353 DEFINE_INTRINSIC(tex1Dsize, 2, int, storage1d_float4) 3354 IMPLEMENT_INTRINSIC_GLSL(tex1Dsize, 0, { 3355 code += "textureSize(" + id_to_name(args[0].base) + ", 0)"; 3356 }) 3357 IMPLEMENT_INTRINSIC_GLSL(tex1Dsize, 1, { 3358 code += "textureSize(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ')'; 3359 }) 3360 IMPLEMENT_INTRINSIC_GLSL(tex1Dsize, 2, { 3361 code += "imageSize(" + id_to_name(args[0].base) + ')'; 3362 }) 3363 IMPLEMENT_INTRINSIC_HLSL(tex1Dsize, 0, { 3364 if (_shader_model >= 40) 3365 code += id_to_name(args[0].base) + ".t.GetDimensions(" + id_to_name(res) + ')'; 3366 else 3367 code += "int(1.0 / " + id_to_name(args[0].base) + ".pixelsize)"; 3368 }) 3369 IMPLEMENT_INTRINSIC_HLSL(tex1Dsize, 1, { 3370 if (_shader_model >= 40) 3371 code += "uint temp" + std::to_string(res) + "; " + // Don't need the number of levels out value, so route that to a dummy variable 3372 id_to_name(args[0].base) + ".t.GetDimensions(" + id_to_name(args[1].base) + ", " + id_to_name(res) + ", temp" + std::to_string(res) + ')'; 3373 else 3374 code += "int(1.0 / " + id_to_name(args[0].base) + ".pixelsize) / exp2(" + id_to_name(args[1].base) + ')'; 3375 }) 3376 IMPLEMENT_INTRINSIC_HLSL(tex1Dsize, 2, { 3377 if (_shader_model >= 50) 3378 code += id_to_name(args[0].base) + ".GetDimensions(" + id_to_name(res) + ')'; 3379 else 3380 code += "0"; // Only supported on SM5+ 3381 }) 3382 IMPLEMENT_INTRINSIC_SPIRV(tex1Dsize, 0, { 3383 add_capability(spv::CapabilityImageQuery); 3384 3385 const spv::Id image = add_instruction(spv::OpImage, convert_image_type(args[0].type)) 3386 .add(args[0].base) 3387 .result; 3388 const spv::Id level = emit_constant(0u); 3389 3390 return 3391 add_instruction(spv::OpImageQuerySizeLod, convert_type(res_type)) 3392 .add(image) 3393 .add(level) 3394 .result; 3395 }) 3396 IMPLEMENT_INTRINSIC_SPIRV(tex1Dsize, 1, { 3397 add_capability(spv::CapabilityImageQuery); 3398 3399 const spv::Id image = add_instruction(spv::OpImage, convert_image_type(args[0].type)) 3400 .add(args[0].base) 3401 .result; 3402 3403 return 3404 add_instruction(spv::OpImageQuerySizeLod, convert_type(res_type)) 3405 .add(image) 3406 .add(args[1].base) 3407 .result; 3408 }) 3409 IMPLEMENT_INTRINSIC_SPIRV(tex1Dsize, 2, { 3410 add_capability(spv::CapabilityImageQuery); 3411 3412 return 3413 add_instruction(spv::OpImageQuerySize, convert_type(res_type)) 3414 .add(args[0].base) 3415 .result; 3416 }) 3417 3418 // ret tex2Dsize(s) 3419 // ret tex2Dsize(s, lod) 3420 DEFINE_INTRINSIC(tex2Dsize, 0, int2, sampler2d_int) 3421 DEFINE_INTRINSIC(tex2Dsize, 0, int2, sampler2d_uint) 3422 DEFINE_INTRINSIC(tex2Dsize, 0, int2, sampler2d_float) 3423 DEFINE_INTRINSIC(tex2Dsize, 0, int2, sampler2d_float4) 3424 DEFINE_INTRINSIC(tex2Dsize, 1, int2, sampler2d_int, int) 3425 DEFINE_INTRINSIC(tex2Dsize, 1, int2, sampler2d_uint, int) 3426 DEFINE_INTRINSIC(tex2Dsize, 1, int2, sampler2d_float, int) 3427 DEFINE_INTRINSIC(tex2Dsize, 1, int2, sampler2d_float4, int) 3428 DEFINE_INTRINSIC(tex2Dsize, 2, int2, storage2d_int) 3429 DEFINE_INTRINSIC(tex2Dsize, 2, int2, storage2d_uint) 3430 DEFINE_INTRINSIC(tex2Dsize, 2, int2, storage2d_float) 3431 DEFINE_INTRINSIC(tex2Dsize, 2, int2, storage2d_float4) 3432 IMPLEMENT_INTRINSIC_GLSL(tex2Dsize, 0, { 3433 code += "textureSize(" + id_to_name(args[0].base) + ", 0)"; 3434 }) 3435 IMPLEMENT_INTRINSIC_GLSL(tex2Dsize, 1, { 3436 code += "textureSize(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ')'; 3437 }) 3438 IMPLEMENT_INTRINSIC_GLSL(tex2Dsize, 2, { 3439 code += "imageSize(" + id_to_name(args[0].base) + ')'; 3440 }) 3441 IMPLEMENT_INTRINSIC_HLSL(tex2Dsize, 0, { 3442 if (_shader_model >= 40) 3443 code += id_to_name(args[0].base) + ".t.GetDimensions(" + id_to_name(res) + ".x, " + id_to_name(res) + ".y)"; 3444 else 3445 code += "int2(1.0 / " + id_to_name(args[0].base) + ".pixelsize)"; 3446 }) 3447 IMPLEMENT_INTRINSIC_HLSL(tex2Dsize, 1, { 3448 if (_shader_model >= 40) 3449 code += "uint temp" + std::to_string(res) + "; " + // Don't need the number of levels out value, so route that to a dummy variable 3450 id_to_name(args[0].base) + ".t.GetDimensions(" + id_to_name(args[1].base) + ", " + id_to_name(res) + ".x, " + id_to_name(res) + ".y, temp" + std::to_string(res) + ')'; 3451 else 3452 code += "int2(1.0 / " + id_to_name(args[0].base) + ".pixelsize) / exp2(" + id_to_name(args[1].base) + ')'; 3453 }) 3454 IMPLEMENT_INTRINSIC_HLSL(tex2Dsize, 2, { 3455 if (_shader_model >= 50) 3456 code += id_to_name(args[0].base) + ".GetDimensions(" + id_to_name(res) + ".x, " + id_to_name(res) + ".y)"; 3457 else 3458 code += "int2(0, 0)"; // Only supported on SM5+ 3459 }) 3460 IMPLEMENT_INTRINSIC_SPIRV(tex2Dsize, 0, { 3461 add_capability(spv::CapabilityImageQuery); 3462 3463 const spv::Id image = add_instruction(spv::OpImage, convert_image_type(args[0].type)) 3464 .add(args[0].base) 3465 .result; 3466 const spv::Id level = emit_constant(0u); 3467 3468 return 3469 add_instruction(spv::OpImageQuerySizeLod, convert_type(res_type)) 3470 .add(image) 3471 .add(level) 3472 .result; 3473 }) 3474 IMPLEMENT_INTRINSIC_SPIRV(tex2Dsize, 1, { 3475 add_capability(spv::CapabilityImageQuery); 3476 3477 const spv::Id image = add_instruction(spv::OpImage, convert_image_type(args[0].type)) 3478 .add(args[0].base) 3479 .result; 3480 3481 return 3482 add_instruction(spv::OpImageQuerySizeLod, convert_type(res_type)) 3483 .add(image) 3484 .add(args[1].base) 3485 .result; 3486 }) 3487 IMPLEMENT_INTRINSIC_SPIRV(tex2Dsize, 2, { 3488 add_capability(spv::CapabilityImageQuery); 3489 3490 return 3491 add_instruction(spv::OpImageQuerySize, convert_type(res_type)) 3492 .add(args[0].base) 3493 .result; 3494 }) 3495 3496 // ret tex3Dsize(s) 3497 // ret tex3Dsize(s, lod) 3498 DEFINE_INTRINSIC(tex3Dsize, 0, int3, sampler3d_int) 3499 DEFINE_INTRINSIC(tex3Dsize, 0, int3, sampler3d_uint) 3500 DEFINE_INTRINSIC(tex3Dsize, 0, int3, sampler3d_float) 3501 DEFINE_INTRINSIC(tex3Dsize, 0, int3, sampler3d_float4) 3502 DEFINE_INTRINSIC(tex3Dsize, 1, int3, sampler3d_int, int) 3503 DEFINE_INTRINSIC(tex3Dsize, 1, int3, sampler3d_uint, int) 3504 DEFINE_INTRINSIC(tex3Dsize, 1, int3, sampler3d_float, int) 3505 DEFINE_INTRINSIC(tex3Dsize, 1, int3, sampler3d_float4, int) 3506 DEFINE_INTRINSIC(tex3Dsize, 2, int3, storage3d_int) 3507 DEFINE_INTRINSIC(tex3Dsize, 2, int3, storage3d_uint) 3508 DEFINE_INTRINSIC(tex3Dsize, 2, int3, storage3d_float) 3509 DEFINE_INTRINSIC(tex3Dsize, 2, int3, storage3d_float4) 3510 IMPLEMENT_INTRINSIC_GLSL(tex3Dsize, 0, { 3511 code += "textureSize(" + id_to_name(args[0].base) + ", 0)"; 3512 }) 3513 IMPLEMENT_INTRINSIC_GLSL(tex3Dsize, 1, { 3514 code += "textureSize(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ')'; 3515 }) 3516 IMPLEMENT_INTRINSIC_GLSL(tex3Dsize, 2, { 3517 code += "imageSize(" + id_to_name(args[0].base) + ')'; 3518 }) 3519 IMPLEMENT_INTRINSIC_HLSL(tex3Dsize, 0, { 3520 if (_shader_model >= 40) 3521 code += id_to_name(args[0].base) + ".t.GetDimensions(" + id_to_name(res) + ".x, " + id_to_name(res) + ".y, " + id_to_name(res) + ".z)"; 3522 else 3523 code += "int3(1.0 / " + id_to_name(args[0].base) + ".pixelsize)"; 3524 }) 3525 IMPLEMENT_INTRINSIC_HLSL(tex3Dsize, 1, { 3526 if (_shader_model >= 40) 3527 code += "uint temp" + std::to_string(res) + "; " + // Don't need the number of levels out value, so route that to a dummy variable 3528 id_to_name(args[0].base) + ".t.GetDimensions(" + id_to_name(args[1].base) + ", " + id_to_name(res) + ".x, " + id_to_name(res) + ".y, " + id_to_name(res) + ".z, temp" + std::to_string(res) + ')'; 3529 else 3530 code += "int3(1.0 / " + id_to_name(args[0].base) + ".pixelsize) / exp2(" + id_to_name(args[1].base) + ')'; 3531 }) 3532 IMPLEMENT_INTRINSIC_HLSL(tex3Dsize, 2, { 3533 if (_shader_model >= 50) 3534 code += id_to_name(args[0].base) + ".GetDimensions(" + id_to_name(res) + ".x, " + id_to_name(res) + ".y, " + id_to_name(res) + ".z)"; 3535 else 3536 code += "int3(0, 0, 0)"; // Only supported on SM5+ 3537 }) 3538 IMPLEMENT_INTRINSIC_SPIRV(tex3Dsize, 0, { 3539 add_capability(spv::CapabilityImageQuery); 3540 3541 const spv::Id image = add_instruction(spv::OpImage, convert_image_type(args[0].type)) 3542 .add(args[0].base) 3543 .result; 3544 const spv::Id level = emit_constant(0u); 3545 3546 return 3547 add_instruction(spv::OpImageQuerySizeLod, convert_type(res_type)) 3548 .add(image) 3549 .add(level) 3550 .result; 3551 }) 3552 IMPLEMENT_INTRINSIC_SPIRV(tex3Dsize, 1, { 3553 add_capability(spv::CapabilityImageQuery); 3554 3555 const spv::Id image = add_instruction(spv::OpImage, convert_image_type(args[0].type)) 3556 .add(args[0].base) 3557 .result; 3558 3559 return 3560 add_instruction(spv::OpImageQuerySizeLod, convert_type(res_type)) 3561 .add(image) 3562 .add(args[1].base) 3563 .result; 3564 }) 3565 IMPLEMENT_INTRINSIC_SPIRV(tex3Dsize, 2, { 3566 add_capability(spv::CapabilityImageQuery); 3567 3568 return 3569 add_instruction(spv::OpImageQuerySize, convert_type(res_type)) 3570 .add(args[0].base) 3571 .result; 3572 }) 3573 3574 // barrier() 3575 DEFINE_INTRINSIC(barrier, 0, void) 3576 IMPLEMENT_INTRINSIC_GLSL(barrier, 0, { 3577 code += "barrier()"; 3578 }) 3579 IMPLEMENT_INTRINSIC_HLSL(barrier, 0, { 3580 if (_shader_model >= 50) 3581 code += "GroupMemoryBarrierWithGroupSync()"; 3582 }) 3583 IMPLEMENT_INTRINSIC_SPIRV(barrier, 0, { 3584 const spv::Id mem_scope = emit_constant(spv::ScopeWorkgroup); 3585 const spv::Id mem_semantics = emit_constant(spv::MemorySemanticsWorkgroupMemoryMask | spv::MemorySemanticsAcquireReleaseMask); 3586 3587 add_instruction_without_result(spv::OpControlBarrier) 3588 .add(mem_scope) // Execution scope 3589 .add(mem_scope) 3590 .add(mem_semantics); 3591 return 0; 3592 }) 3593 3594 // memoryBarrier() 3595 DEFINE_INTRINSIC(memoryBarrier, 0, void) 3596 IMPLEMENT_INTRINSIC_GLSL(memoryBarrier, 0, { 3597 code += "memoryBarrier()"; 3598 }) 3599 IMPLEMENT_INTRINSIC_HLSL(memoryBarrier, 0, { 3600 if (_shader_model >= 50) 3601 code += "AllMemoryBarrier()"; 3602 }) 3603 IMPLEMENT_INTRINSIC_SPIRV(memoryBarrier, 0, { 3604 const spv::Id mem_scope = emit_constant(spv::ScopeDevice); 3605 const spv::Id mem_semantics = emit_constant(spv::MemorySemanticsImageMemoryMask | spv::MemorySemanticsUniformMemoryMask | spv::MemorySemanticsWorkgroupMemoryMask | spv::MemorySemanticsAcquireReleaseMask); 3606 3607 add_instruction_without_result(spv::OpMemoryBarrier) 3608 .add(mem_scope) 3609 .add(mem_semantics); 3610 return 0; 3611 }) 3612 // groupMemoryBarrier() 3613 DEFINE_INTRINSIC(groupMemoryBarrier, 0, void) 3614 IMPLEMENT_INTRINSIC_GLSL(groupMemoryBarrier, 0, { 3615 code += "groupMemoryBarrier()"; 3616 }) 3617 IMPLEMENT_INTRINSIC_HLSL(groupMemoryBarrier, 0, { 3618 if (_shader_model >= 50) 3619 code += "GroupMemoryBarrier()"; 3620 }) 3621 IMPLEMENT_INTRINSIC_SPIRV(groupMemoryBarrier, 0, { 3622 const spv::Id mem_scope = emit_constant(spv::ScopeWorkgroup); 3623 const spv::Id mem_semantics = emit_constant(spv::MemorySemanticsWorkgroupMemoryMask | spv::MemorySemanticsAcquireReleaseMask); 3624 3625 add_instruction_without_result(spv::OpMemoryBarrier) 3626 .add(mem_scope) 3627 .add(mem_semantics); 3628 return 0; 3629 }) 3630 3631 // ret atomicAdd(inout mem, data) 3632 DEFINE_INTRINSIC(atomicAdd, 0, int, inout_int, int) 3633 DEFINE_INTRINSIC(atomicAdd, 0, uint, inout_uint, uint) 3634 IMPLEMENT_INTRINSIC_GLSL(atomicAdd, 0, { 3635 code += "atomicAdd(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ')'; 3636 }) 3637 IMPLEMENT_INTRINSIC_HLSL(atomicAdd, 0, { 3638 if (_shader_model >= 50) 3639 code += "InterlockedAdd(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ", " + id_to_name(res) + ')'; 3640 else 3641 code += id_to_name(res) + " = " + id_to_name(args[0].base) + "; " + id_to_name(args[0].base) + " += " + id_to_name(args[1].base); 3642 }) 3643 IMPLEMENT_INTRINSIC_SPIRV(atomicAdd, 0, { 3644 const spv::Id mem_scope = emit_constant(spv::ScopeDevice); 3645 const spv::Id mem_semantics = emit_constant(spv::MemorySemanticsMaskNone); 3646 3647 return 3648 add_instruction(spv::OpAtomicIAdd, convert_type(res_type)) 3649 .add(args[0].base) 3650 .add(mem_scope) 3651 .add(mem_semantics) 3652 .add(args[1].base) 3653 .result; 3654 }) 3655 // ret atomicAdd(s, coords, data) 3656 DEFINE_INTRINSIC(atomicAdd, 1, int, inout_storage1d_int, int, int) 3657 DEFINE_INTRINSIC(atomicAdd, 1, int, inout_storage2d_int, int2, int) 3658 DEFINE_INTRINSIC(atomicAdd, 1, int, inout_storage3d_int, int3, int) 3659 DEFINE_INTRINSIC(atomicAdd, 1, uint, inout_storage1d_uint, int, uint) 3660 DEFINE_INTRINSIC(atomicAdd, 1, uint, inout_storage2d_uint, int2, uint) 3661 DEFINE_INTRINSIC(atomicAdd, 1, uint, inout_storage3d_uint, int3, uint) 3662 IMPLEMENT_INTRINSIC_GLSL(atomicAdd, 1, { 3663 code += "imageAtomicAdd(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ", " + id_to_name(args[2].base) + ')'; 3664 }) 3665 IMPLEMENT_INTRINSIC_HLSL(atomicAdd, 1, { 3666 if (_shader_model >= 50) 3667 code += "InterlockedAdd(" + id_to_name(args[0].base) + '[' + id_to_name(args[1].base) + ']' + ", " + id_to_name(args[2].base) + ", " + id_to_name(res) + ')'; 3668 }) 3669 IMPLEMENT_INTRINSIC_SPIRV(atomicAdd, 1, { 3670 const spv::Id ms_sample = emit_constant(0u); 3671 3672 const spv::Id texel = add_instruction(spv::OpImageTexelPointer, convert_type(res_type, true, spv::StorageClassImage)) 3673 .add(args[0].base) 3674 .add(args[1].base) 3675 .add(ms_sample) 3676 .result; 3677 const spv::Id mem_scope = emit_constant(spv::ScopeDevice); 3678 const spv::Id mem_semantics = emit_constant(spv::MemorySemanticsMaskNone); 3679 3680 return 3681 add_instruction(spv::OpAtomicIAdd, convert_type(res_type)) 3682 .add(texel) 3683 .add(mem_scope) 3684 .add(mem_semantics) 3685 .add(args[2].base) 3686 .result; 3687 }) 3688 3689 // ret atomicAnd(inout mem, data) 3690 DEFINE_INTRINSIC(atomicAnd, 0, int, inout_int, int) 3691 DEFINE_INTRINSIC(atomicAnd, 0, uint, inout_uint, uint) 3692 IMPLEMENT_INTRINSIC_GLSL(atomicAnd, 0, { 3693 code += "atomicAnd(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ')'; 3694 }) 3695 IMPLEMENT_INTRINSIC_HLSL(atomicAnd, 0, { 3696 if (_shader_model >= 50) 3697 code += "InterlockedAnd(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ", " + id_to_name(res) + ')'; 3698 else 3699 code += id_to_name(res) + " = " + id_to_name(args[0].base) + "; " + id_to_name(args[0].base) + " &= " + id_to_name(args[1].base); 3700 }) 3701 IMPLEMENT_INTRINSIC_SPIRV(atomicAnd, 0, { 3702 const spv::Id mem_scope = emit_constant(spv::ScopeDevice); 3703 const spv::Id mem_semantics = emit_constant(spv::MemorySemanticsMaskNone); 3704 3705 return 3706 add_instruction(spv::OpAtomicAnd, convert_type(res_type)) 3707 .add(args[0].base) 3708 .add(mem_scope) 3709 .add(mem_semantics) 3710 .add(args[1].base) 3711 .result; 3712 }) 3713 // ret atomicAnd(s, coords, data) 3714 DEFINE_INTRINSIC(atomicAnd, 1, int, inout_storage1d_int, int, int) 3715 DEFINE_INTRINSIC(atomicAnd, 1, int, inout_storage2d_int, int2, int) 3716 DEFINE_INTRINSIC(atomicAnd, 1, int, inout_storage3d_int, int3, int) 3717 DEFINE_INTRINSIC(atomicAnd, 1, uint, inout_storage1d_uint, int, uint) 3718 DEFINE_INTRINSIC(atomicAnd, 1, uint, inout_storage2d_uint, int2, uint) 3719 DEFINE_INTRINSIC(atomicAnd, 1, uint, inout_storage3d_uint, int3, uint) 3720 IMPLEMENT_INTRINSIC_GLSL(atomicAnd, 1, { 3721 code += "imageAtomicAnd(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ", " + id_to_name(args[2].base) + ')'; 3722 }) 3723 IMPLEMENT_INTRINSIC_HLSL(atomicAnd, 1, { 3724 if (_shader_model >= 50) 3725 code += "InterlockedAnd(" + id_to_name(args[0].base) + '[' + id_to_name(args[1].base) + ']' + ", " + id_to_name(args[2].base) + ", " + id_to_name(res) + ')'; 3726 }) 3727 IMPLEMENT_INTRINSIC_SPIRV(atomicAnd, 1, { 3728 const spv::Id ms_sample = emit_constant(0u); 3729 3730 const spv::Id texel = add_instruction(spv::OpImageTexelPointer, convert_type(res_type, true, spv::StorageClassImage)) 3731 .add(args[0].base) 3732 .add(args[1].base) 3733 .add(ms_sample) 3734 .result; 3735 const spv::Id mem_scope = emit_constant(spv::ScopeDevice); 3736 const spv::Id mem_semantics = emit_constant(spv::MemorySemanticsMaskNone); 3737 3738 return 3739 add_instruction(spv::OpAtomicAnd, convert_type(res_type)) 3740 .add(texel) 3741 .add(mem_scope) 3742 .add(mem_semantics) 3743 .add(args[2].base) 3744 .result; 3745 }) 3746 3747 // ret atomicOr(inout mem, data) 3748 DEFINE_INTRINSIC(atomicOr, 0, int, inout_int, int) 3749 DEFINE_INTRINSIC(atomicOr, 0, uint, inout_uint, uint) 3750 IMPLEMENT_INTRINSIC_GLSL(atomicOr, 0, { 3751 code += "atomicOr(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ')'; 3752 }) 3753 IMPLEMENT_INTRINSIC_HLSL(atomicOr, 0, { 3754 if (_shader_model >= 50) 3755 code += "InterlockedOr(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ", " + id_to_name(res) + ')'; 3756 else 3757 code += id_to_name(res) + " = " + id_to_name(args[0].base) + "; " + id_to_name(args[0].base) + " |= " + id_to_name(args[1].base); 3758 }) 3759 IMPLEMENT_INTRINSIC_SPIRV(atomicOr, 0, { 3760 const spv::Id mem_scope = emit_constant(spv::ScopeDevice); 3761 const spv::Id mem_semantics = emit_constant(spv::MemorySemanticsMaskNone); 3762 3763 return 3764 add_instruction(spv::OpAtomicOr, convert_type(res_type)) 3765 .add(args[0].base) 3766 .add(mem_scope) 3767 .add(mem_semantics) 3768 .add(args[1].base) 3769 .result; 3770 }) 3771 // ret atomicOr(s, coords, data) 3772 DEFINE_INTRINSIC(atomicOr, 1, int, inout_storage1d_int, int, int) 3773 DEFINE_INTRINSIC(atomicOr, 1, int, inout_storage2d_int, int2, int) 3774 DEFINE_INTRINSIC(atomicOr, 1, int, inout_storage3d_int, int3, int) 3775 DEFINE_INTRINSIC(atomicOr, 1, uint, inout_storage1d_uint, int, uint) 3776 DEFINE_INTRINSIC(atomicOr, 1, uint, inout_storage2d_uint, int2, uint) 3777 DEFINE_INTRINSIC(atomicOr, 1, uint, inout_storage3d_uint, int3, uint) 3778 IMPLEMENT_INTRINSIC_GLSL(atomicOr, 1, { 3779 code += "imageAtomicOr(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ", " + id_to_name(args[2].base) + ')'; 3780 }) 3781 IMPLEMENT_INTRINSIC_HLSL(atomicOr, 1, { 3782 if (_shader_model >= 50) 3783 code += "InterlockedOr(" + id_to_name(args[0].base) + '[' + id_to_name(args[1].base) + ']' + ", " + id_to_name(args[2].base) + ", " + id_to_name(res) + ')'; 3784 }) 3785 IMPLEMENT_INTRINSIC_SPIRV(atomicOr, 1, { 3786 const spv::Id ms_sample = emit_constant(0u); 3787 3788 const spv::Id texel = add_instruction(spv::OpImageTexelPointer, convert_type(res_type, true, spv::StorageClassImage)) 3789 .add(args[0].base) 3790 .add(args[1].base) 3791 .add(ms_sample) 3792 .result; 3793 const spv::Id mem_scope = emit_constant(spv::ScopeDevice); 3794 const spv::Id mem_semantics = emit_constant(spv::MemorySemanticsMaskNone); 3795 3796 return 3797 add_instruction(spv::OpAtomicOr, convert_type(res_type)) 3798 .add(texel) 3799 .add(mem_scope) 3800 .add(mem_semantics) 3801 .add(args[2].base) 3802 .result; 3803 }) 3804 3805 // ret atomicXor(inout mem, data) 3806 DEFINE_INTRINSIC(atomicXor, 0, int, inout_int, int) 3807 DEFINE_INTRINSIC(atomicXor, 0, uint, inout_uint, uint) 3808 IMPLEMENT_INTRINSIC_GLSL(atomicXor, 0, { 3809 code += "atomicXor(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ')'; 3810 }) 3811 IMPLEMENT_INTRINSIC_HLSL(atomicXor, 0, { 3812 if (_shader_model >= 50) 3813 code += "InterlockedXor(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ", " + id_to_name(res) + ')'; 3814 else 3815 code += id_to_name(res) + " = " + id_to_name(args[0].base) + "; " + id_to_name(args[0].base) + " ^= " + id_to_name(args[1].base); 3816 }) 3817 IMPLEMENT_INTRINSIC_SPIRV(atomicXor, 0, { 3818 const spv::Id mem_scope = emit_constant(spv::ScopeDevice); 3819 const spv::Id mem_semantics = emit_constant(spv::MemorySemanticsMaskNone); 3820 3821 return 3822 add_instruction(spv::OpAtomicXor, convert_type(res_type)) 3823 .add(args[0].base) 3824 .add(mem_scope) 3825 .add(mem_semantics) 3826 .add(args[1].base) 3827 .result; 3828 }) 3829 // ret atomicXor(s, coords, data) 3830 DEFINE_INTRINSIC(atomicXor, 1, int, inout_storage1d_int, int, int) 3831 DEFINE_INTRINSIC(atomicXor, 1, int, inout_storage2d_int, int2, int) 3832 DEFINE_INTRINSIC(atomicXor, 1, int, inout_storage3d_int, int3, int) 3833 DEFINE_INTRINSIC(atomicXor, 1, uint, inout_storage1d_uint, int, uint) 3834 DEFINE_INTRINSIC(atomicXor, 1, uint, inout_storage2d_uint, int2, uint) 3835 DEFINE_INTRINSIC(atomicXor, 1, uint, inout_storage3d_uint, int3, uint) 3836 IMPLEMENT_INTRINSIC_GLSL(atomicXor, 1, { 3837 code += "imageAtomicXor(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ", " + id_to_name(args[2].base) + ')'; 3838 }) 3839 IMPLEMENT_INTRINSIC_HLSL(atomicXor, 1, { 3840 if (_shader_model >= 50) 3841 code += "InterlockedXor(" + id_to_name(args[0].base) + '[' + id_to_name(args[1].base) + ']' + ", " + id_to_name(args[2].base) + ", " + id_to_name(res) + ')'; 3842 }) 3843 IMPLEMENT_INTRINSIC_SPIRV(atomicXor, 1, { 3844 const spv::Id ms_sample = emit_constant(0u); 3845 3846 const spv::Id texel = add_instruction(spv::OpImageTexelPointer, convert_type(res_type, true, spv::StorageClassImage)) 3847 .add(args[0].base) 3848 .add(args[1].base) 3849 .add(ms_sample) 3850 .result; 3851 const spv::Id mem_scope = emit_constant(spv::ScopeDevice); 3852 const spv::Id mem_semantics = emit_constant(spv::MemorySemanticsMaskNone); 3853 3854 return 3855 add_instruction(spv::OpAtomicXor, convert_type(res_type)) 3856 .add(texel) 3857 .add(mem_scope) 3858 .add(mem_semantics) 3859 .add(args[2].base) 3860 .result; 3861 }) 3862 3863 // ret atomicMin(inout mem, data) 3864 DEFINE_INTRINSIC(atomicMin, 0, int, inout_int, int) 3865 DEFINE_INTRINSIC(atomicMin, 1, uint, inout_uint, uint) 3866 IMPLEMENT_INTRINSIC_GLSL(atomicMin, 0, { 3867 code += "atomicMin(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ')'; 3868 }) 3869 IMPLEMENT_INTRINSIC_GLSL(atomicMin, 1, { 3870 code += "atomicMin(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ')'; 3871 }) 3872 IMPLEMENT_INTRINSIC_HLSL(atomicMin, 0, { 3873 if (_shader_model >= 50) 3874 code += "InterlockedMin(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ", " + id_to_name(res) + ')'; 3875 else 3876 code += id_to_name(res) + " = " + id_to_name(args[0].base) + "; " + id_to_name(args[0].base) + " = min(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ')'; 3877 }) 3878 IMPLEMENT_INTRINSIC_HLSL(atomicMin, 1, { 3879 if (_shader_model >= 50) 3880 code += "InterlockedMin(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ", " + id_to_name(res) + ')'; 3881 else 3882 code += id_to_name(res) + " = " + id_to_name(args[0].base) + "; " + id_to_name(args[0].base) + " = min(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ')'; 3883 }) 3884 IMPLEMENT_INTRINSIC_SPIRV(atomicMin, 0, { 3885 const spv::Id mem_scope = emit_constant(spv::ScopeDevice); 3886 const spv::Id mem_semantics = emit_constant(spv::MemorySemanticsMaskNone); 3887 3888 return 3889 add_instruction(spv::OpAtomicSMin, convert_type(res_type)) 3890 .add(args[0].base) 3891 .add(mem_scope) 3892 .add(mem_semantics) 3893 .add(args[1].base) 3894 .result; 3895 }) 3896 IMPLEMENT_INTRINSIC_SPIRV(atomicMin, 1, { 3897 const spv::Id mem_scope = emit_constant(spv::ScopeDevice); 3898 const spv::Id mem_semantics = emit_constant(spv::MemorySemanticsMaskNone); 3899 3900 return 3901 add_instruction(spv::OpAtomicUMin, convert_type(res_type)) 3902 .add(args[0].base) 3903 .add(mem_scope) 3904 .add(mem_semantics) 3905 .add(args[1].base) 3906 .result; 3907 }) 3908 // ret atomicMin(s, coords, data) 3909 DEFINE_INTRINSIC(atomicMin, 2, int, inout_storage1d_int, int, int) 3910 DEFINE_INTRINSIC(atomicMin, 2, int, inout_storage2d_int, int2, int) 3911 DEFINE_INTRINSIC(atomicMin, 2, int, inout_storage3d_int, int3, int) 3912 DEFINE_INTRINSIC(atomicMin, 3, uint, inout_storage1d_uint, int, uint) 3913 DEFINE_INTRINSIC(atomicMin, 3, uint, inout_storage2d_uint, int2, uint) 3914 DEFINE_INTRINSIC(atomicMin, 3, uint, inout_storage3d_uint, int3, uint) 3915 IMPLEMENT_INTRINSIC_GLSL(atomicMin, 2, { 3916 code += "imageAtomicMin(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ", " + id_to_name(args[2].base) + ')'; 3917 }) 3918 IMPLEMENT_INTRINSIC_GLSL(atomicMin, 3, { 3919 code += "imageAtomicMin(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ", " + id_to_name(args[2].base) + ')'; 3920 }) 3921 IMPLEMENT_INTRINSIC_HLSL(atomicMin, 2, { 3922 if (_shader_model >= 50) 3923 code += "InterlockedMin(" + id_to_name(args[0].base) + '[' + id_to_name(args[1].base) + ']' + ", " + id_to_name(args[2].base) + ", " + id_to_name(res) + ')'; 3924 }) 3925 IMPLEMENT_INTRINSIC_HLSL(atomicMin, 3, { 3926 if (_shader_model >= 50) 3927 code += "InterlockedMin(" + id_to_name(args[0].base) + '[' + id_to_name(args[1].base) + ']' + ", " + id_to_name(args[2].base) + ", " + id_to_name(res) + ')'; 3928 }) 3929 IMPLEMENT_INTRINSIC_SPIRV(atomicMin, 2, { 3930 const spv::Id ms_sample = emit_constant(0u); 3931 3932 const spv::Id texel = add_instruction(spv::OpImageTexelPointer, convert_type(res_type, true, spv::StorageClassImage)) 3933 .add(args[0].base) 3934 .add(args[1].base) 3935 .add(ms_sample) 3936 .result; 3937 const spv::Id mem_scope = emit_constant(spv::ScopeDevice); 3938 const spv::Id mem_semantics = emit_constant(spv::MemorySemanticsMaskNone); 3939 3940 return 3941 add_instruction(spv::OpAtomicSMin, convert_type(res_type)) 3942 .add(texel) 3943 .add(mem_scope) 3944 .add(mem_semantics) 3945 .add(args[2].base) 3946 .result; 3947 }) 3948 IMPLEMENT_INTRINSIC_SPIRV(atomicMin, 3, { 3949 const spv::Id ms_sample = emit_constant(0u); 3950 3951 const spv::Id texel = add_instruction(spv::OpImageTexelPointer, convert_type(res_type, true, spv::StorageClassImage)) 3952 .add(args[0].base) 3953 .add(args[1].base) 3954 .add(ms_sample) 3955 .result; 3956 const spv::Id mem_scope = emit_constant(spv::ScopeDevice); 3957 const spv::Id mem_semantics = emit_constant(spv::MemorySemanticsMaskNone); 3958 3959 return 3960 add_instruction(spv::OpAtomicUMin, convert_type(res_type)) 3961 .add(texel) 3962 .add(mem_scope) 3963 .add(mem_semantics) 3964 .add(args[2].base) 3965 .result; 3966 }) 3967 3968 // ret atomicMax(inout mem, data) 3969 DEFINE_INTRINSIC(atomicMax, 0, int, inout_int, int) 3970 DEFINE_INTRINSIC(atomicMax, 1, uint, inout_uint, uint) 3971 IMPLEMENT_INTRINSIC_GLSL(atomicMax, 0, { 3972 code += "atomicMax(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ')'; 3973 }) 3974 IMPLEMENT_INTRINSIC_GLSL(atomicMax, 1, { 3975 code += "atomicMax(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ')'; 3976 }) 3977 IMPLEMENT_INTRINSIC_HLSL(atomicMax, 0, { 3978 if (_shader_model >= 50) 3979 code += "InterlockedMax(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ", " + id_to_name(res) + ')'; 3980 else 3981 code += id_to_name(res) + " = " + id_to_name(args[0].base) + "; " + id_to_name(args[0].base) + " = max(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ')'; 3982 }) 3983 IMPLEMENT_INTRINSIC_HLSL(atomicMax, 1, { 3984 if (_shader_model >= 50) 3985 code += "InterlockedMax(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ", " + id_to_name(res) + ')'; 3986 else 3987 code += id_to_name(res) + " = " + id_to_name(args[0].base) + "; " + id_to_name(args[0].base) + " = max(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ')'; 3988 }) 3989 IMPLEMENT_INTRINSIC_SPIRV(atomicMax, 0, { 3990 const spv::Id mem_scope = emit_constant(spv::ScopeDevice); 3991 const spv::Id mem_semantics = emit_constant(spv::MemorySemanticsMaskNone); 3992 3993 return 3994 add_instruction(spv::OpAtomicSMax, convert_type(res_type)) 3995 .add(args[0].base) 3996 .add(mem_scope) 3997 .add(mem_semantics) 3998 .add(args[1].base) 3999 .result; 4000 }) 4001 IMPLEMENT_INTRINSIC_SPIRV(atomicMax, 1, { 4002 const spv::Id mem_scope = emit_constant(spv::ScopeDevice); 4003 const spv::Id mem_semantics = emit_constant(spv::MemorySemanticsMaskNone); 4004 4005 return 4006 add_instruction(spv::OpAtomicUMax, convert_type(res_type)) 4007 .add(args[0].base) 4008 .add(mem_scope) 4009 .add(mem_semantics) 4010 .add(args[1].base) 4011 .result; 4012 }) 4013 // ret atomicMax(s, coords, data) 4014 DEFINE_INTRINSIC(atomicMax, 2, int, inout_storage1d_int, int, int) 4015 DEFINE_INTRINSIC(atomicMax, 2, int, inout_storage2d_int, int2, int) 4016 DEFINE_INTRINSIC(atomicMax, 2, int, inout_storage3d_int, int3, int) 4017 DEFINE_INTRINSIC(atomicMax, 3, uint, inout_storage1d_uint, int, uint) 4018 DEFINE_INTRINSIC(atomicMax, 3, uint, inout_storage2d_uint, int2, uint) 4019 DEFINE_INTRINSIC(atomicMax, 3, uint, inout_storage3d_uint, int3, uint) 4020 IMPLEMENT_INTRINSIC_GLSL(atomicMax, 2, { 4021 code += "imageAtomicMax(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ", " + id_to_name(args[2].base) + ')'; 4022 }) 4023 IMPLEMENT_INTRINSIC_GLSL(atomicMax, 3, { 4024 code += "imageAtomicMax(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ", " + id_to_name(args[2].base) + ')'; 4025 }) 4026 IMPLEMENT_INTRINSIC_HLSL(atomicMax, 2, { 4027 if (_shader_model >= 50) 4028 code += "InterlockedMax(" + id_to_name(args[0].base) + '[' + id_to_name(args[1].base) + ']' + ", " + id_to_name(args[2].base) + ", " + id_to_name(res) + ')'; 4029 }) 4030 IMPLEMENT_INTRINSIC_HLSL(atomicMax, 3, { 4031 if (_shader_model >= 50) 4032 code += "InterlockedMax(" + id_to_name(args[0].base) + '[' + id_to_name(args[1].base) + ']' + ", " + id_to_name(args[2].base) + ", " + id_to_name(res) + ')'; 4033 }) 4034 IMPLEMENT_INTRINSIC_SPIRV(atomicMax, 2, { 4035 const spv::Id ms_sample = emit_constant(0u); 4036 4037 const spv::Id texel = add_instruction(spv::OpImageTexelPointer, convert_type(res_type, true, spv::StorageClassImage)) 4038 .add(args[0].base) 4039 .add(args[1].base) 4040 .add(ms_sample) 4041 .result; 4042 const spv::Id mem_scope = emit_constant(spv::ScopeDevice); 4043 const spv::Id mem_semantics = emit_constant(spv::MemorySemanticsMaskNone); 4044 4045 return 4046 add_instruction(spv::OpAtomicSMax, convert_type(res_type)) 4047 .add(texel) 4048 .add(mem_scope) 4049 .add(mem_semantics) 4050 .add(args[2].base) 4051 .result; 4052 }) 4053 IMPLEMENT_INTRINSIC_SPIRV(atomicMax, 3, { 4054 const spv::Id ms_sample = emit_constant(0u); 4055 4056 const spv::Id texel = add_instruction(spv::OpImageTexelPointer, convert_type(res_type, true, spv::StorageClassImage)) 4057 .add(args[0].base) 4058 .add(args[1].base) 4059 .add(ms_sample) 4060 .result; 4061 const spv::Id mem_scope = emit_constant(spv::ScopeDevice); 4062 const spv::Id mem_semantics = emit_constant(spv::MemorySemanticsMaskNone); 4063 4064 return 4065 add_instruction(spv::OpAtomicUMax, convert_type(res_type)) 4066 .add(texel) 4067 .add(mem_scope) 4068 .add(mem_semantics) 4069 .add(args[2].base) 4070 .result; 4071 }) 4072 4073 // ret atomicExchange(inout mem, data) 4074 DEFINE_INTRINSIC(atomicExchange, 0, int, inout_int, int) 4075 DEFINE_INTRINSIC(atomicExchange, 0, uint, inout_uint, uint) 4076 IMPLEMENT_INTRINSIC_GLSL(atomicExchange, 0, { 4077 code += "atomicExchange(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ')'; 4078 }) 4079 IMPLEMENT_INTRINSIC_HLSL(atomicExchange, 0, { 4080 if (_shader_model >= 50) 4081 code += "InterlockedExchange(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ", " + id_to_name(res) + ')'; 4082 else 4083 code += id_to_name(res) + " = " + id_to_name(args[0].base) + "; " + id_to_name(args[0].base) + " = " + id_to_name(args[1].base); 4084 }) 4085 IMPLEMENT_INTRINSIC_SPIRV(atomicExchange, 0, { 4086 const spv::Id mem_scope = emit_constant(spv::ScopeDevice); 4087 const spv::Id mem_semantics = emit_constant(spv::MemorySemanticsMaskNone); 4088 4089 return 4090 add_instruction(spv::OpAtomicExchange, convert_type(res_type)) 4091 .add(args[0].base) 4092 .add(mem_scope) 4093 .add(mem_semantics) 4094 .add(args[1].base) 4095 .result; 4096 }) 4097 // ret atomicExchange(s, coords, data) 4098 DEFINE_INTRINSIC(atomicExchange, 1, int, inout_storage1d_int, int, int) 4099 DEFINE_INTRINSIC(atomicExchange, 1, int, inout_storage2d_int, int2, int) 4100 DEFINE_INTRINSIC(atomicExchange, 1, int, inout_storage3d_int, int3, int) 4101 DEFINE_INTRINSIC(atomicExchange, 1, uint, inout_storage1d_uint, int, uint) 4102 DEFINE_INTRINSIC(atomicExchange, 1, uint, inout_storage2d_uint, int2, uint) 4103 DEFINE_INTRINSIC(atomicExchange, 1, uint, inout_storage3d_uint, int3, uint) 4104 IMPLEMENT_INTRINSIC_GLSL(atomicExchange, 1, { 4105 code += "imageAtomicExchange(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ", " + id_to_name(args[2].base) + ')'; 4106 }) 4107 IMPLEMENT_INTRINSIC_HLSL(atomicExchange, 1, { 4108 if (_shader_model >= 50) 4109 code += "InterlockedExchange(" + id_to_name(args[0].base) + '[' + id_to_name(args[1].base) + ']' + ", " + id_to_name(args[2].base) + ", " + id_to_name(res) + ')'; 4110 }) 4111 IMPLEMENT_INTRINSIC_SPIRV(atomicExchange, 1, { 4112 const spv::Id ms_sample = emit_constant(0u); 4113 4114 const spv::Id texel = add_instruction(spv::OpImageTexelPointer, convert_type(res_type, true, spv::StorageClassImage)) 4115 .add(args[0].base) 4116 .add(args[1].base) 4117 .add(ms_sample) 4118 .result; 4119 const spv::Id mem_scope = emit_constant(spv::ScopeDevice); 4120 const spv::Id mem_semantics = emit_constant(spv::MemorySemanticsMaskNone); 4121 4122 return 4123 add_instruction(spv::OpAtomicExchange, convert_type(res_type)) 4124 .add(texel) 4125 .add(mem_scope) 4126 .add(mem_semantics) 4127 .add(args[2].base) 4128 .result; 4129 }) 4130 4131 // ret atomicCompareExchange(inout mem, compare, data) 4132 DEFINE_INTRINSIC(atomicCompareExchange, 0, int, inout_int, int, int) 4133 DEFINE_INTRINSIC(atomicCompareExchange, 0, uint, inout_uint, uint, uint) 4134 IMPLEMENT_INTRINSIC_GLSL(atomicCompareExchange, 0, { 4135 code += "atomicCompSwap(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ", " + id_to_name(args[2].base) + ')'; 4136 }) 4137 IMPLEMENT_INTRINSIC_HLSL(atomicCompareExchange, 0, { 4138 if (_shader_model >= 50) 4139 code += "InterlockedCompareExchange(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ", " + id_to_name(args[2].base) + ", " + id_to_name(res) + ')'; 4140 else 4141 code += id_to_name(res) + " = " + id_to_name(args[0].base) + "; if (" + id_to_name(args[0].base) + " == " + id_to_name(args[1].base) + ") " + id_to_name(args[0].base) + " = " + id_to_name(args[2].base); 4142 }) 4143 IMPLEMENT_INTRINSIC_SPIRV(atomicCompareExchange, 0, { 4144 const spv::Id mem_scope = emit_constant(spv::ScopeDevice); 4145 const spv::Id mem_semantics = emit_constant(spv::MemorySemanticsMaskNone); 4146 4147 return 4148 add_instruction(spv::OpAtomicCompareExchange, convert_type(res_type)) 4149 .add(args[0].base) 4150 .add(mem_scope) 4151 .add(mem_semantics) 4152 .add(mem_semantics) 4153 .add(args[2].base) 4154 .add(args[1].base) 4155 .result; 4156 }) 4157 // ret atomicCompareExchange(s, coords, compare, data) 4158 DEFINE_INTRINSIC(atomicCompareExchange, 1, int, inout_storage1d_int, int, int, int) 4159 DEFINE_INTRINSIC(atomicCompareExchange, 1, int, inout_storage2d_int, int2, int, int) 4160 DEFINE_INTRINSIC(atomicCompareExchange, 1, int, inout_storage3d_int, int3, int, int) 4161 DEFINE_INTRINSIC(atomicCompareExchange, 1, uint, inout_storage1d_uint, int, uint, uint) 4162 DEFINE_INTRINSIC(atomicCompareExchange, 1, uint, inout_storage2d_uint, int2, uint, uint) 4163 DEFINE_INTRINSIC(atomicCompareExchange, 1, uint, inout_storage3d_uint, int3, uint, uint) 4164 IMPLEMENT_INTRINSIC_GLSL(atomicCompareExchange, 1, { 4165 code += "imageAtomicCompSwap(" + id_to_name(args[0].base) + ", " + id_to_name(args[1].base) + ", " + id_to_name(args[2].base) + ", " + id_to_name(args[3].base) + ')'; 4166 }) 4167 IMPLEMENT_INTRINSIC_HLSL(atomicCompareExchange, 1, { 4168 if (_shader_model >= 50) 4169 code += "InterlockedCompareExchange(" + id_to_name(args[0].base) + '[' + id_to_name(args[1].base) + ']' + ", " + id_to_name(args[2].base) + ", " + id_to_name(args[3].base) + ", " + id_to_name(res) + ')'; 4170 }) 4171 IMPLEMENT_INTRINSIC_SPIRV(atomicCompareExchange, 1, { 4172 const spv::Id ms_sample = emit_constant(0u); 4173 4174 const spv::Id texel = add_instruction(spv::OpImageTexelPointer, convert_type(res_type, true, spv::StorageClassImage)) 4175 .add(args[0].base) 4176 .add(args[1].base) 4177 .add(ms_sample) 4178 .result; 4179 const spv::Id mem_scope = emit_constant(spv::ScopeDevice); 4180 const spv::Id mem_semantics = emit_constant(spv::MemorySemanticsMaskNone); 4181 4182 return 4183 add_instruction(spv::OpAtomicCompareExchange, convert_type(res_type)) 4184 .add(texel) 4185 .add(mem_scope) 4186 .add(mem_semantics) 4187 .add(mem_semantics) 4188 .add(args[3].base) 4189 .add(args[2].base) 4190 .result; 4191 }) 4192 4193 #undef DEFINE_INTRINSIC 4194 #undef IMPLEMENT_INTRINSIC_GLSL 4195 #undef IMPLEMENT_INTRINSIC_HLSL 4196 #undef IMPLEMENT_INTRINSIC_SPIRV