00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00020 #include <map>
00021 #include <vector>
00022 #include <sstream>
00023 #include "Cc.hpp"
00024 #include "ShDebug.hpp"
00025 #include "ShStream.hpp"
00026 #include "ShVariant.hpp"
00027 #include "ShOperation.hpp"
00028
00029 #ifdef HAVE_CONFIG_H
00030 #include "config.h"
00031 #endif
00032
00033 #ifdef SH_CC_DEBUG
00034 # define SH_CC_DEBUG_PRINT(x) SH_DEBUG_PRINT(x)
00035 #else
00036 # define SH_CC_DEBUG_PRINT(x) do { } while(0)
00037 #endif
00038
00039 namespace ShCc {
00040
00041 using namespace SH;
00042
00048
00049
00050
00051
00052 struct CcOpCode
00053 {
00054 ShOperation op;
00055 char *code;
00056 };
00057
00058 struct CcOpCodeVecs
00059 {
00060 CcOpCodeVecs() {}
00061
00062
00063
00064
00065
00066
00067 CcOpCodeVecs(const CcOpCode &op);
00068
00069 bool operator<(const CcOpCodeVecs &other) {
00070 return op < other.op;
00071 }
00072
00073 std::string encode() const;
00074
00075 ShOperation op;
00076
00077 std::vector<int> index;
00078 std::vector<bool> scalar;
00079 std::vector<std::string> frag;
00080 };
00081
00082
00083 typedef std::map<SH::ShOperation, CcOpCodeVecs> CcOpCodeMap;
00084
00085 CcOpCodeVecs::CcOpCodeVecs(const CcOpCode &op) {
00086 std::string code = op.code;
00087
00088 unsigned i, j;
00089 i = j = 0;
00090 for(; (j = code.find_first_of("#$", i)) != std::string::npos;) {
00091 frag.push_back(code.substr(i, j - i));
00092 scalar.push_back(code[j] == '$');
00093 i = j + 1;
00094 j = code.find_first_not_of("012345689", i);
00095 index.push_back(atoi(code.substr(i, j - i).c_str()));
00096 i = j;
00097 }
00098 if(i == std::string::npos) {
00099 frag.push_back("");
00100 } else {
00101 frag.push_back(code.substr(i));
00102 }
00103
00104 }
00105
00106 std::string CcOpCodeVecs::encode() const
00107 {
00108 std::ostringstream out;
00109 for(unsigned int i = 0; i < index.size(); ++i) {
00110 out << frag[i];
00111 out << "src[" << index[i] << "]";
00112 if(scalar[i]) out << ".scalar";
00113 }
00114 out << frag.back();
00115 return out.str();
00116 }
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132 const CcOpCode opCodeTable[] = {
00133 {SH_OP_ASN, "#0" },
00134 {SH_OP_NEG, "-#0" },
00135 {SH_OP_ADD, "$0 + $1"},
00136 {SH_OP_MUL, "$0 * $1"},
00137 {SH_OP_DIV, "$0 / $1"},
00138
00139 {SH_OP_SLT, "($0 < $1 ? 1 : 0)"},
00140 {SH_OP_SLE, "($0 <= $1 ? 1 : 0)"},
00141 {SH_OP_SGT, "($0 > $1 ? 1 : 0)"},
00142 {SH_OP_SGE, "($0 >= $1 ? 1 : 0)"},
00143 {SH_OP_SEQ, "($0 == $1 ? 1 : 0)"},
00144 {SH_OP_SNE, "($0 != $1 ? 1 : 0)"},
00145
00146 {SH_OP_ABS, "fabs(#0)"},
00147 {SH_OP_ACOS, "acos(#0)"},
00148 {SH_OP_ASIN, "asin(#0)"},
00149 {SH_OP_ATAN, "atan(#0)"},
00150 {SH_OP_ATAN2, "atan2(#1, #0)"},
00151 #ifdef WIN32
00152 {SH_OP_ACOSH, "log(#0 + sqrt(#0 * #0 - 1.0))"},
00153 {SH_OP_ASINH, "log(#0 + sqrt(#0 * #0 + 1.0))"},
00154 {SH_OP_ATANH, "log((1.0 + #0)/(1.0 - #0)) / 2.0"},
00155 #else
00156 {SH_OP_ACOSH, "acosh(#0)"},
00157 {SH_OP_ASINH, "asinh(#0)"},
00158 {SH_OP_ATANH, "atanh(#0)"},
00159 #endif
00160 {SH_OP_CBRT, "pow(#0, 1 / 3.0)"},
00161 {SH_OP_CEIL, "ceil(#0)"},
00162 {SH_OP_COS, "cos(#0)"},
00163 {SH_OP_COSH, "cosh(#0)"},
00164 {SH_OP_EXP, "exp(#0)"},
00165 {SH_OP_EXP2, "exp2(#0)"},
00166 {SH_OP_EXP10, "exp10(#0)"},
00167 {SH_OP_FLR, "floor(#0)"},
00168 {SH_OP_FRAC, "#0 - floor(#0)"},
00169 {SH_OP_LOG, "log(#0)"},
00170 {SH_OP_LOG2, "log2(#0)"},
00171 {SH_OP_LOG10, "log10(#0)"},
00172 {SH_OP_LRP, "$0 * ($1 - $2) + $2"},
00173 {SH_OP_MAD, "$0 * $1 + $2"},
00174 {SH_OP_MAX, "($0 > $1 ? $0 : $1)"},
00175 {SH_OP_MIN, "($0 < $1 ? $0 : $1)"},
00176 {SH_OP_MOD, "($0 - $1 * floor((double)$0 / $1))"},
00177 {SH_OP_POW, "pow($0, $1)"},
00178 {SH_OP_RCP, "1 / #0"},
00179 {SH_OP_RND, "floor(#0 + 0.5)"},
00180 {SH_OP_RSQ, "1 / sqrt(#0)"},
00181 {SH_OP_SIN, "sin(#0)"},
00182 {SH_OP_SINH, "sinh(#0)"},
00183 {SH_OP_SGN, "(#0 < 0 ? -1 : (#0 > 0 ? 1 : 0))"},
00184 {SH_OP_SQRT, "sqrt(#0)"},
00185 {SH_OP_TAN, "tan(#0)"},
00186 {SH_OP_TANH, "tanh(#0)"},
00187 {SH_OP_COND, "($0 > 0 ? $1 : $2)"},
00188 {SH_OP_FETCH, "#0"},
00189
00190 {SH_OPERATION_END, 0}
00191
00192 };
00193
00194
00195
00196 #if 0
00197 {SH_OP_CMUL,
00198 {SH_OP_CSUM,
00199 {SH_OP_DOT,
00200 {SH_OP_NORM,
00201 {SH_OP_XPD,
00202 {SH_OP_TEX,
00203 {SH_OP_TEXI,
00204 {SH_OP_TEXD,
00205 {SH_OP_KIL,
00206 {SH_OP_OPTBRA,
00207 #endif
00208
00209
00210 void CcBackendCode::emit(const ShStatement& stmt) {
00211 static CcOpCodeMap opcodeMap;
00212
00213
00214
00215
00216
00217 if(opcodeMap.empty()) {
00218 SH_CC_DEBUG_PRINT("ShOperation -> C++ code mappings");
00219 for(int i = 0; opCodeTable[i].op != SH_OPERATION_END; ++i) {
00220
00221 opcodeMap[opCodeTable[i].op] = CcOpCodeVecs(opCodeTable[i]);
00222 SH_CC_DEBUG_PRINT(opInfo[opCodeTable[i].op].name << " -> "
00223 << opcodeMap[opCodeTable[i].op].encode());
00224 }
00225 }
00226
00227
00228 m_code << " // " << stmt << std::endl;
00229
00230
00231
00232
00233
00234
00235
00236 if(opcodeMap.find(stmt.op) != opcodeMap.end()) {
00237 CcOpCodeVecs codeVecs = opcodeMap[stmt.op];
00238 for(int i = 0; i < stmt.dest.size(); ++i) {
00239 m_code << " " << resolve(stmt.dest, i) << " = ("
00240 << ctype(stmt.dest.valueType()) << ")(";
00241 unsigned int j;
00242 for(j = 0; j < codeVecs.index.size(); ++j) {
00243 const ShVariable& src = stmt.src[codeVecs.index[j]];
00244 m_code << codeVecs.frag[j];
00245 if(codeVecs.scalar[j]) {
00246 m_code << resolve(src, src.size() > 1 ? i : 0);
00247 } else {
00248 m_code << resolve(src, i);
00249 }
00250 }
00251 m_code << codeVecs.frag[j] << ");" << std::endl;
00252 }
00253 return;
00254 }
00255
00256
00257
00258 switch(stmt.op) {
00259 case SH_OP_DOT:
00260 {
00261 SH_DEBUG_ASSERT(stmt.dest.size() == 1);
00262 m_code << " " << resolve(stmt.dest, 0) << " = "
00263 << resolve(stmt.src[0], 0)
00264 << " * "
00265 << resolve(stmt.src[1], 0)
00266 << ";" << std::endl;
00267
00268 int inc0 = stmt.src[0].size() == 1 ? 0 : 1;
00269 int inc1 = stmt.src[1].size() == 1 ? 0 : 1;
00270 int size = std::max(stmt.src[0].size(), stmt.src[1].size());
00271
00272 int i, s0, s1;
00273 for(i = s0 = s1 = 1; i < size; ++i, s0 += inc0, s1 += inc1) {
00274 m_code << " " << resolve(stmt.dest, 0) << " += "
00275 << resolve(stmt.src[0], s0)
00276 << " * "
00277 << resolve(stmt.src[1], s1)
00278 << ";" << std::endl;
00279 }
00280 break;
00281 }
00282
00283 case SH_OP_CSUM:
00284 {
00285 SH_DEBUG_ASSERT(stmt.dest.size() == 1);
00286 m_code << " " << resolve(stmt.dest, 0) << " = "
00287 << resolve(stmt.src[0], 0)
00288 << ";" << std::endl;
00289
00290 int size = stmt.src[0].size();
00291 for(int i = 1; i < size; ++i) {
00292 m_code << " " << resolve(stmt.dest, 0) << " += "
00293 << resolve(stmt.src[0], i)
00294 << ";" << std::endl;
00295 }
00296 break;
00297 }
00298
00299 case SH_OP_CMUL:
00300 {
00301 SH_DEBUG_ASSERT(stmt.dest.size() == 1);
00302 m_code << " " << resolve(stmt.dest, 0) << " = "
00303 << resolve(stmt.src[0], 0)
00304 << ";" << std::endl;
00305
00306 int size = stmt.src[0].size();
00307 for(int i = 1; i < size; ++i) {
00308 m_code << " " << resolve(stmt.dest, 0) << " *= "
00309 << resolve(stmt.src[0], i)
00310 << ";" << std::endl;
00311 }
00312 break;
00313 }
00314
00315 case SH_OP_LIT:
00316 {
00317 m_code << " {" << std::endl;
00318
00319
00320 m_code << " " << resolve(stmt.src[0], 0) << " = ("
00321 << resolve(stmt.src[0], 0) << " > 0) ? "
00322 << resolve(stmt.src[0], 0) << " : 0;" << std::endl;
00323 m_code << " " << resolve(stmt.src[0], 1) << " = ("
00324 << resolve(stmt.src[0], 1) << " > 0) ? "
00325 << resolve(stmt.src[0], 1) << " : 0;" << std::endl;
00326
00327
00328 m_code << " " << resolve(stmt.src[0], 2) << " = ("
00329 << resolve(stmt.src[0], 2) << " > -128.0) ? "
00330 << resolve(stmt.src[0], 2) << " : -128.0;" << std::endl;
00331 m_code << " " << resolve(stmt.src[0], 2) << " = ("
00332 << resolve(stmt.src[0], 2) << " < 128.0) ? "
00333 << resolve(stmt.src[0], 2) << " : 128.0;" << std::endl;
00334
00335
00336 m_code << " " << resolve(stmt.dest, 0) << " = 1;" << std::endl;
00337 m_code << " " << resolve(stmt.dest, 1) << " = "
00338 << resolve(stmt.src[0], 0) << ";" << std::endl;
00339 m_code << " " << resolve(stmt.dest, 2) << " = ("
00340 << resolve(stmt.src[0], 0) << " > 0)" << " * pow("
00341 << resolve(stmt.src[0], 1) << ", " << resolve(stmt.src[0], 2)
00342 << ");" << std::endl;
00343 m_code << " " << resolve(stmt.dest, 3) << " = 1;" << std::endl;
00344
00345 m_code << " }" << std::endl;
00346 break;
00347 }
00348
00349 case SH_OP_NORM:
00350 {
00351 m_code << " {" << std::endl;
00352 m_code << " float len = 1.0/sqrt(";
00353 for(int i = 0; i < stmt.dest.size(); i++)
00354 {
00355 if (i != 0) m_code << " + ";
00356 m_code << resolve(stmt.src[0], i)
00357 << " * "
00358 << resolve(stmt.src[0], i);
00359 }
00360 m_code << ");" << std::endl;
00361 for(int i = 0; i < stmt.dest.size(); i++)
00362 {
00363 m_code << " "
00364 << resolve(stmt.dest, i)
00365 << " = len*"
00366 << resolve(stmt.src[0], i)
00367 << ";" << std::endl;
00368 }
00369 m_code << " }" << std::endl;
00370
00371 break;
00372 }
00373 case SH_OP_XPD:
00374 {
00375 for(int i = 0; i < stmt.dest.size(); i++)
00376 {
00377 int i0 = (i+1)%3;
00378 int i1 = (i+2)%3;
00379 m_code << " "
00380 << resolve(stmt.dest, i)
00381 << " = "
00382 << resolve(stmt.src[0], i0)
00383 << " * "
00384 << resolve(stmt.src[1], i1)
00385 << " - "
00386 << resolve(stmt.src[1], i0)
00387 << " * "
00388 << resolve(stmt.src[0], i1)
00389 << ";" << std::endl;
00390 }
00391
00392 break;
00393 }
00394 case SH_OP_TEX:
00395 emitTexLookup(stmt, "sh_cc_backend_lookup");
00396 break;
00397
00398 case SH_OP_TEXI:
00399 emitTexLookup(stmt, "sh_cc_backend_lookupi");
00400 break;
00401
00402 case SH_OP_KIL:
00403 {
00404
00405 m_code << " if (";
00406 for(int i = 0; i < stmt.src[0].size(); i++)
00407 {
00408 if (i != 0) m_code << " || ";
00409 m_code << "("
00410 << resolve(stmt.src[0], i)
00411 << " > 0)";
00412 }
00413 m_code << ")" << std::endl;
00414 m_code << " return;" << std::endl;
00415 break;
00416 }
00417 case SH_OP_OPTBRA:
00418 {
00419 SH_DEBUG_ASSERT(false);
00420 break;
00421 }
00422 default:
00423 {
00424
00425
00426
00427
00428
00429
00430
00431
00432 m_code << " // *** unhandled operation " << opInfo[stmt.op].name
00433 << " ***" << std::endl;
00434 break;
00435 }
00436 }
00437 }
00438
00439 void CcBackendCode::emitTexLookup(const ShStatement& stmt, const char* texfunc) {
00440 ShTextureNodePtr node = shref_dynamic_cast<ShTextureNode>(stmt.src[0].node());
00441 int dims = 0;
00442 switch(node->dims()) {
00443 case SH_TEXTURE_1D: dims = 1; break;
00444 case SH_TEXTURE_2D: dims = 2; break;
00445 case SH_TEXTURE_RECT: dims = 2; break;
00446 case SH_TEXTURE_3D: dims = 3; break;
00447 case SH_TEXTURE_CUBE:
00448 SH_DEBUG_ERROR("Cube maps not handled");
00449 default:
00450 SH_DEBUG_ERROR("Unhandled texture dim");
00451 }
00452
00453
00454 std::string srcInterp, srcFilter, srcWrap;
00455
00456 if(node->traits().interpolation() != 0) {
00457
00458
00459 }
00460
00461 if (node->traits().filtering() != ShTextureTraits::SH_FILTER_NONE) {
00462
00463 SH_DEBUG_WARN("cc backend does not support texture filtering.");
00464 }
00465
00466 switch(node->traits().wrapping()) {
00467 case ShTextureTraits::SH_WRAP_CLAMP:
00468 case ShTextureTraits::SH_WRAP_CLAMP_TO_EDGE:
00469 srcWrap = "sh_gcc_backend_wrap_clamp";
00470 break;
00471 case ShTextureTraits::SH_WRAP_REPEAT:
00472 srcWrap = "sh_gcc_backend_wrap_repeat";
00473 break;
00474 default:
00475 shError(ShBackendException("cc backend does not support requested texture wrapping mode."));
00476 break;
00477 }
00478
00479 m_code << " {" << std::endl;
00480 std::string destvar;
00481 std::string srcvar;
00482 bool tempdest = !stmt.dest.swizzle().identity();
00483 bool tempsrc = (!stmt.src[1].swizzle().identity()) || stmt.src[1].neg();
00484
00485 if(tempdest) {
00486 m_code << " " << ctype(stmt.dest.valueType()) <<
00487 " result[" << stmt.dest.size() << "];" << std::endl;
00488 destvar = "result";
00489 } else destvar = resolve(stmt.dest);
00490
00491 if(tempsrc) {
00492 m_code << " " << ctype(stmt.src[1].valueType())
00493 << " input[" << stmt.src[1].size() << "];" << std::endl;
00494
00495 for(int i = 0; i < stmt.src[1].size(); i++) {
00496 m_code << " input[" << i << "] = "
00497 << resolve(stmt.src[1], i) << ";" << std::endl;
00498 }
00499
00500 srcvar = "input";
00501 } else srcvar = resolve(stmt.src[1]);
00502
00503 m_code << " " << texfunc << "<"
00504 << dims << ", "
00505 << node->size() << ", "
00506 << node->width() << ", "
00507 << node->height() << ", "
00508 << node->depth() << ", "
00509 << ctype(node->valueType()) << ","
00510 << srcWrap << ">("
00511 << resolve(stmt.src[0])
00512 << ", "
00513 << srcvar
00514 << ", "
00515 << destvar
00516 << ");" << std::endl;
00517
00518 if(tempdest) {
00519 for(int i = 0; i < stmt.dest.size(); i++) {
00520 m_code << " "
00521 << resolve(stmt.dest, i)
00522 << " = result[" << i << "];" << std::endl;
00523 }
00524 }
00525 m_code << " }" << std::endl;
00526 }
00527
00528 }
00529