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_EXP, "exp(#0)"},
00159 {SH_OP_EXP2, "exp2(#0)"},
00160 {SH_OP_EXP10, "exp10(#0)"},
00161 {SH_OP_FLR, "floor(#0)"},
00162 {SH_OP_FRAC, "#0 - floor(#0)"},
00163 {SH_OP_LOG, "log(#0)"},
00164 {SH_OP_LOG2, "log2(#0)"},
00165 {SH_OP_LOG10, "log10(#0)"},
00166 {SH_OP_LRP, "$0 * ($1 - $2) + $2"},
00167 {SH_OP_MAD, "$0 * $1 + $2"},
00168 {SH_OP_MAX, "($0 > $1 ? $0 : $1)"},
00169 {SH_OP_MIN, "($0 < $1 ? $0 : $1)"},
00170 {SH_OP_MOD, "($0 - $1 * floor((double)$0 / $1))"},
00171 {SH_OP_POW, "pow($0, $1)"},
00172 {SH_OP_RCP, "1 / #0"},
00173 {SH_OP_RND, "floor(#0 + 0.5)"},
00174 {SH_OP_RSQ, "1 / sqrt(#0)"},
00175 {SH_OP_SIN, "sin(#0)"},
00176 {SH_OP_SGN, "(#0 < 0 ? -1 : (#0 > 0 ? 1 : 0))"},
00177 {SH_OP_SQRT, "sqrt(#0)"},
00178 {SH_OP_TAN, "tan(#0)"},
00179 {SH_OP_COND, "($0 > 0 ? $1 : $2)"},
00180 {SH_OP_FETCH, "#0"},
00181
00182 {SH_OPERATION_END, 0}
00183
00184 };
00185
00186
00187
00188 #if 0
00189 {SH_OP_CMUL,
00190 {SH_OP_CSUM,
00191 {SH_OP_DOT,
00192 {SH_OP_NORM,
00193 {SH_OP_XPD,
00194 {SH_OP_TEX,
00195 {SH_OP_TEXI,
00196 {SH_OP_TEXD,
00197 {SH_OP_KIL,
00198 {SH_OP_OPTBRA,
00199 #endif
00200
00201
00202 void CcBackendCode::emit(const ShStatement& stmt) {
00203 static CcOpCodeMap opcodeMap;
00204
00205
00206
00207
00208
00209 if(opcodeMap.empty()) {
00210 SH_CC_DEBUG_PRINT("ShOperation -> C++ code mappings");
00211 for(int i = 0; opCodeTable[i].op != SH_OPERATION_END; ++i) {
00212
00213 opcodeMap[opCodeTable[i].op] = CcOpCodeVecs(opCodeTable[i]);
00214 SH_CC_DEBUG_PRINT(opInfo[opCodeTable[i].op].name << " -> "
00215 << opcodeMap[opCodeTable[i].op].encode());
00216 }
00217 }
00218
00219
00220 m_code << " // " << stmt << std::endl;
00221
00222
00223
00224
00225
00226
00227
00228 if(opcodeMap.find(stmt.op) != opcodeMap.end()) {
00229 CcOpCodeVecs codeVecs = opcodeMap[stmt.op];
00230 for(int i = 0; i < stmt.dest.size(); ++i) {
00231 m_code << " " << resolve(stmt.dest, i) << " = ("
00232 << ctype(stmt.dest.valueType()) << ")(";
00233 unsigned int j;
00234 for(j = 0; j < codeVecs.index.size(); ++j) {
00235 const ShVariable& src = stmt.src[codeVecs.index[j]];
00236 m_code << codeVecs.frag[j];
00237 if(codeVecs.scalar[j]) {
00238 m_code << resolve(src, src.size() > 1 ? i : 0);
00239 } else {
00240 m_code << resolve(src, i);
00241 }
00242 }
00243 m_code << codeVecs.frag[j] << ");" << std::endl;
00244 }
00245 return;
00246 }
00247
00248
00249
00250 switch(stmt.op) {
00251 case SH_OP_DOT:
00252 {
00253 SH_DEBUG_ASSERT(stmt.dest.size() == 1);
00254 m_code << " " << resolve(stmt.dest, 0) << " = "
00255 << resolve(stmt.src[0], 0)
00256 << " * "
00257 << resolve(stmt.src[1], 0)
00258 << ";" << std::endl;
00259
00260 int inc0 = stmt.src[0].size() == 1 ? 0 : 1;
00261 int inc1 = stmt.src[1].size() == 1 ? 0 : 1;
00262 int size = std::max(stmt.src[0].size(), stmt.src[1].size());
00263
00264 int i, s0, s1;
00265 for(i = s0 = s1 = 1; i < size; ++i, s0 += inc0, s1 += inc1) {
00266 m_code << " " << resolve(stmt.dest, 0) << " += "
00267 << resolve(stmt.src[0], s0)
00268 << " * "
00269 << resolve(stmt.src[1], s1)
00270 << ";" << std::endl;
00271 }
00272 break;
00273 }
00274
00275 case SH_OP_CSUM:
00276 {
00277 SH_DEBUG_ASSERT(stmt.dest.size() == 1);
00278 m_code << " " << resolve(stmt.dest, 0) << " = "
00279 << resolve(stmt.src[0], 0)
00280 << ";" << std::endl;
00281
00282 int size = stmt.src[0].size();
00283 for(int i = 1; i < size; ++i) {
00284 m_code << " " << resolve(stmt.dest, 0) << " += "
00285 << resolve(stmt.src[0], i)
00286 << ";" << std::endl;
00287 }
00288 break;
00289 }
00290
00291 case SH_OP_CMUL:
00292 {
00293 SH_DEBUG_ASSERT(stmt.dest.size() == 1);
00294 m_code << " " << resolve(stmt.dest, 0) << " = "
00295 << resolve(stmt.src[0], 0)
00296 << ";" << std::endl;
00297
00298 int size = stmt.src[0].size();
00299 for(int i = 1; i < size; ++i) {
00300 m_code << " " << resolve(stmt.dest, 0) << " *= "
00301 << resolve(stmt.src[0], i)
00302 << ";" << std::endl;
00303 }
00304 break;
00305 }
00306
00307 case SH_OP_LIT:
00308 {
00309 m_code << " {" << std::endl;
00310
00311
00312 m_code << " " << resolve(stmt.src[0], 0) << " = ("
00313 << resolve(stmt.src[0], 0) << " > 0) ? "
00314 << resolve(stmt.src[0], 0) << " : 0;" << std::endl;
00315 m_code << " " << resolve(stmt.src[0], 1) << " = ("
00316 << resolve(stmt.src[0], 1) << " > 0) ? "
00317 << resolve(stmt.src[0], 1) << " : 0;" << std::endl;
00318
00319
00320 m_code << " " << resolve(stmt.src[0], 2) << " = ("
00321 << resolve(stmt.src[0], 2) << " > -128.0) ? "
00322 << resolve(stmt.src[0], 2) << " : -128.0;" << std::endl;
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
00327
00328 m_code << " " << resolve(stmt.dest, 0) << " = 1;" << std::endl;
00329 m_code << " " << resolve(stmt.dest, 1) << " = "
00330 << resolve(stmt.src[0], 0) << ";" << std::endl;
00331 m_code << " " << resolve(stmt.dest, 2) << " = ("
00332 << resolve(stmt.src[0], 0) << " > 0)" << " * pow("
00333 << resolve(stmt.src[0], 1) << ", " << resolve(stmt.src[0], 2)
00334 << ");" << std::endl;
00335 m_code << " " << resolve(stmt.dest, 3) << " = 1;" << std::endl;
00336
00337 m_code << " }" << std::endl;
00338 break;
00339 }
00340
00341 case SH_OP_NORM:
00342 {
00343 m_code << " {" << std::endl;
00344 m_code << " float len = 1.0/sqrt(";
00345 for(int i = 0; i < stmt.dest.size(); i++)
00346 {
00347 if (i != 0) m_code << " + ";
00348 m_code << resolve(stmt.src[0], i)
00349 << " * "
00350 << resolve(stmt.src[0], i);
00351 }
00352 m_code << ");" << std::endl;
00353 for(int i = 0; i < stmt.dest.size(); i++)
00354 {
00355 m_code << " "
00356 << resolve(stmt.dest, i)
00357 << " = len*"
00358 << resolve(stmt.src[0], i)
00359 << ";" << std::endl;
00360 }
00361 m_code << " }" << std::endl;
00362
00363 break;
00364 }
00365 case SH_OP_XPD:
00366 {
00367 for(int i = 0; i < stmt.dest.size(); i++)
00368 {
00369 int i0 = (i+1)%3;
00370 int i1 = (i+2)%3;
00371 m_code << " "
00372 << resolve(stmt.dest, i)
00373 << " = "
00374 << resolve(stmt.src[0], i0)
00375 << " * "
00376 << resolve(stmt.src[1], i1)
00377 << " - "
00378 << resolve(stmt.src[1], i0)
00379 << " * "
00380 << resolve(stmt.src[0], i1)
00381 << ";" << std::endl;
00382 }
00383
00384 break;
00385 }
00386 case SH_OP_TEX:
00387 emitTexLookup(stmt, "sh_cc_backend_lookup");
00388 break;
00389
00390 case SH_OP_TEXI:
00391 emitTexLookup(stmt, "sh_cc_backend_lookupi");
00392 break;
00393
00394 case SH_OP_KIL:
00395 {
00396
00397 m_code << " if (";
00398 for(int i = 0; i < stmt.src[0].size(); i++)
00399 {
00400 if (i != 0) m_code << " || ";
00401 m_code << "("
00402 << resolve(stmt.src[0], i)
00403 << " > 0)";
00404 }
00405 m_code << ")" << std::endl;
00406 m_code << " return;" << std::endl;
00407 break;
00408 }
00409 case SH_OP_OPTBRA:
00410 {
00411 SH_DEBUG_ASSERT(false);
00412 break;
00413 }
00414 default:
00415 {
00416 m_code << " // *** unhandled operation "
00417 << opInfo[stmt.op].name
00418 << " ***" << std::endl;
00419 break;
00420 }
00421 }
00422 }
00423
00424 void CcBackendCode::emitTexLookup(const ShStatement& stmt, const char* texfunc) {
00425 ShTextureNodePtr node = shref_dynamic_cast<ShTextureNode>(stmt.src[0].node());
00426 int dims = 0;
00427 switch(node->dims()) {
00428 case SH_TEXTURE_1D: dims = 1; break;
00429 case SH_TEXTURE_2D: dims = 2; break;
00430 case SH_TEXTURE_RECT: dims = 2; break;
00431 case SH_TEXTURE_3D: dims = 3; break;
00432 case SH_TEXTURE_CUBE:
00433 SH_DEBUG_ERROR("Cube maps not handled");
00434 default:
00435 SH_DEBUG_ERROR("Unhandled texture dim");
00436 }
00437
00438
00439 std::string srcInterp, srcFilter, srcWrap, destClamp;
00440
00441 if(node->traits().interpolation() != 0) {
00442
00443
00444 }
00445
00446 if (node->traits().filtering() != ShTextureTraits::SH_FILTER_NONE) {
00447
00448 SH_DEBUG_WARN("cc backend does not support texture filtering.");
00449 }
00450
00451 switch(node->traits().wrapping()) {
00452 case ShTextureTraits::SH_WRAP_CLAMP:
00453 case ShTextureTraits::SH_WRAP_CLAMP_TO_EDGE:
00454 srcWrap = "sh_gcc_backend_wrap_clamp";
00455 break;
00456 case ShTextureTraits::SH_WRAP_REPEAT:
00457 srcWrap = "sh_gcc_backend_wrap_repeat";
00458 break;
00459 default:
00460 shError(ShBackendException("cc backend does not support requested texture wrapping mode."));
00461 break;
00462 }
00463
00464 switch(node->traits().clamping()) {
00465 case ShTextureTraits::SH_CLAMPED:
00466 destClamp = "sh_gcc_backend_clamped";
00467 break;
00468 default:
00469 destClamp = "sh_gcc_backend_unclamped";
00470 }
00471
00472 m_code << " {" << std::endl;
00473 std::string destvar;
00474 std::string srcvar;
00475 bool tempdest = !stmt.dest.swizzle().identity();
00476 bool tempsrc = (!stmt.src[1].swizzle().identity()) || stmt.src[1].neg();
00477
00478 if(tempdest) {
00479 m_code << " " << ctype(stmt.dest.valueType()) <<
00480 " result[" << stmt.dest.size() << "];" << std::endl;
00481 destvar = "result";
00482 } else destvar = resolve(stmt.dest);
00483
00484 if(tempsrc) {
00485 m_code << " " << ctype(stmt.src[1].valueType())
00486 << " input[" << stmt.src[1].size() << "];" << std::endl;
00487
00488 for(int i = 0; i < stmt.src[1].size(); i++) {
00489 m_code << " input[" << i << "] = "
00490 << resolve(stmt.src[1], i) << ";" << std::endl;
00491 }
00492
00493 srcvar = "input";
00494 } else srcvar = resolve(stmt.src[1]);
00495
00496 m_code << " " << texfunc << "<"
00497 << dims << ", "
00498 << node->size() << ", "
00499 << node->width() << ", "
00500 << node->height() << ", "
00501 << node->depth() << ", "
00502 << ctype(node->valueType()) << ","
00503 << srcWrap << ", "
00504 << destClamp << ">("
00505 << resolve(stmt.src[0])
00506 << ", "
00507 << srcvar
00508 << ", "
00509 << destvar
00510 << ");" << std::endl;
00511
00512 if(tempdest) {
00513 for(int i = 0; i < stmt.dest.size(); i++) {
00514 m_code << " "
00515 << resolve(stmt.dest, i)
00516 << " = result[" << i << "];" << std::endl;
00517 }
00518 }
00519 m_code << " }" << std::endl;
00520 }
00521
00522 }
00523