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