00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00027 #include <map>
00028 #include <vector>
00029 #include <sstream>
00030 #include "Cc.hpp"
00031 #include "ShDebug.hpp"
00032 #include "ShStream.hpp"
00033 #include "ShVariant.hpp"
00034 #include "ShOperation.hpp"
00035
00036 #ifdef HAVE_CONFIG_H
00037 #include "config.h"
00038 #endif
00039
00040 #ifdef SH_CC_DEBUG
00041 # define SH_CC_DEBUG_PRINT(x) SH_DEBUG_PRINT(x)
00042 #else
00043 # define SH_CC_DEBUG_PRINT(x) do { } while(0)
00044 #endif
00045
00046 namespace ShCc {
00047
00048 using namespace SH;
00049
00055
00056
00057
00058
00059 struct CcOpCode
00060 {
00061 ShOperation op;
00062 char *code;
00063 };
00064
00065 struct CcOpCodeVecs
00066 {
00067 CcOpCodeVecs() {}
00068
00069
00070
00071
00072
00073
00074 CcOpCodeVecs(const CcOpCode &op);
00075
00076 bool operator<(const CcOpCodeVecs &other) {
00077 return op < other.op;
00078 }
00079
00080 std::string encode() const;
00081
00082 ShOperation op;
00083
00084 std::vector<int> index;
00085 std::vector<bool> scalar;
00086 std::vector<std::string> frag;
00087 };
00088
00089
00090 typedef std::map<SH::ShOperation, CcOpCodeVecs> CcOpCodeMap;
00091
00092 CcOpCodeVecs::CcOpCodeVecs(const CcOpCode &op) {
00093 std::string code = op.code;
00094
00095 unsigned i, j;
00096 i = j = 0;
00097 for(; (j = code.find_first_of("#$", i)) != std::string::npos;) {
00098 frag.push_back(code.substr(i, j - i));
00099 scalar.push_back(code[j] == '$');
00100 i = j + 1;
00101 j = code.find_first_not_of("012345689", i);
00102 index.push_back(atoi(code.substr(i, j - i).c_str()));
00103 i = j;
00104 }
00105 if(i == std::string::npos) {
00106 frag.push_back("");
00107 } else {
00108 frag.push_back(code.substr(i));
00109 }
00110
00111 }
00112
00113 std::string CcOpCodeVecs::encode() const
00114 {
00115 std::ostringstream out;
00116 for(unsigned int i = 0; i < index.size(); ++i) {
00117 out << frag[i];
00118 out << "src[" << index[i] << "]";
00119 if(scalar[i]) out << ".scalar";
00120 }
00121 out << frag.back();
00122 return out.str();
00123 }
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139 const CcOpCode opCodeTable[] = {
00140 {SH_OP_ASN, "#0" },
00141 {SH_OP_NEG, "-#0" },
00142 {SH_OP_ADD, "$0 + $1"},
00143 {SH_OP_MUL, "$0 * $1"},
00144 {SH_OP_DIV, "$0 / $1"},
00145
00146 {SH_OP_SLT, "($0 < $1 ? 1 : 0)"},
00147 {SH_OP_SLE, "($0 <= $1 ? 1 : 0)"},
00148 {SH_OP_SGT, "($0 > $1 ? 1 : 0)"},
00149 {SH_OP_SGE, "($0 >= $1 ? 1 : 0)"},
00150 {SH_OP_SEQ, "($0 == $1 ? 1 : 0)"},
00151 {SH_OP_SNE, "($0 != $1 ? 1 : 0)"},
00152
00153 {SH_OP_ABS, "fabs(#0)"},
00154 {SH_OP_ACOS, "acos(#0)"},
00155 {SH_OP_ASIN, "asin(#0)"},
00156 {SH_OP_ATAN, "atan(#0)"},
00157 {SH_OP_ATAN2, "atan2(#0, #1)"},
00158 {SH_OP_CBRT, "pow(#0, 1 / 3.0)"},
00159 {SH_OP_CEIL, "ceil(#0)"},
00160 {SH_OP_COS, "cos(#0)"},
00161 {SH_OP_EXP, "exp(#0)"},
00162 {SH_OP_EXP2, "exp2(#0)"},
00163 {SH_OP_EXP10, "exp10(#0)"},
00164 {SH_OP_FLR, "floor(#0)"},
00165 {SH_OP_FRAC, "#0 - floor(#0)"},
00166 {SH_OP_LOG, "log(#0)"},
00167 {SH_OP_LOG2, "log2(#0)"},
00168 {SH_OP_LOG10, "log10(#0)"},
00169 {SH_OP_LRP, "$0 * ($1 - $2) + $2"},
00170 {SH_OP_MAD, "$0 * $1 + $2"},
00171 {SH_OP_MAX, "($0 > $1 ? $0 : $1)"},
00172 {SH_OP_MIN, "($0 < $1 ? $0 : $1)"},
00173 {SH_OP_MOD, "fmod($0, $1)"},
00174 {SH_OP_POW, "pow($0, $1)"},
00175 {SH_OP_RCP, "1 / #0"},
00176 {SH_OP_RND, "floor(#0 + 0.5)"},
00177 {SH_OP_RSQ, "1 / sqrt(#0)"},
00178 {SH_OP_SIN, "sin(#0)"},
00179 {SH_OP_SGN, "(#0 < 0 ? -1 : (#0 > 0 ? 1 : 0))"},
00180 {SH_OP_SQRT, "sqrt(#0)"},
00181 {SH_OP_TAN, "tan(#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_NORM:
00311 {
00312 m_code << " {" << std::endl;
00313 m_code << " float len = 1.0/sqrt(";
00314 for(int i = 0; i < stmt.dest.size(); i++)
00315 {
00316 if (i != 0) m_code << " + ";
00317 m_code << resolve(stmt.src[0], i)
00318 << " * "
00319 << resolve(stmt.src[0], i);
00320 }
00321 m_code << ");" << std::endl;
00322 for(int i = 0; i < stmt.dest.size(); i++)
00323 {
00324 m_code << " "
00325 << resolve(stmt.dest, i)
00326 << " = len*"
00327 << resolve(stmt.src[0], i)
00328 << ";" << std::endl;
00329 }
00330 m_code << " }" << std::endl;
00331
00332 break;
00333 }
00334 case SH_OP_XPD:
00335 {
00336 for(int i = 0; i < stmt.dest.size(); i++)
00337 {
00338 int i0 = (i+1)%3;
00339 int i1 = (i+2)%3;
00340 m_code << " "
00341 << resolve(stmt.dest, i)
00342 << " = "
00343 << resolve(stmt.src[0], i0)
00344 << " * "
00345 << resolve(stmt.src[1], i1)
00346 << " - "
00347 << resolve(stmt.src[1], i0)
00348 << " * "
00349 << resolve(stmt.src[0], i1)
00350 << ";" << std::endl;
00351 }
00352
00353 break;
00354 }
00355 case SH_OP_TEX:
00356 emitTexLookup(stmt, "sh_cc_backend_lookup");
00357 break;
00358
00359 case SH_OP_TEXI:
00360 emitTexLookup(stmt, "sh_cc_backend_lookupi");
00361 break;
00362
00363 case SH_OP_KIL:
00364 {
00365
00366 m_code << " if (";
00367 for(int i = 0; i < stmt.src[0].size(); i++)
00368 {
00369 if (i != 0) m_code << " || ";
00370 m_code << "("
00371 << resolve(stmt.src[0], i)
00372 << " > 0)";
00373 }
00374 m_code << ")" << std::endl;
00375 m_code << " return;" << std::endl;
00376 break;
00377 }
00378 case SH_OP_OPTBRA:
00379 {
00380 SH_DEBUG_ASSERT(false);
00381 break;
00382 }
00383 default:
00384 {
00385 m_code << " // *** unhandled operation "
00386 << opInfo[stmt.op].name
00387 << " ***" << std::endl;
00388 break;
00389 }
00390 }
00391 }
00392
00393 void CcBackendCode::emitTexLookup(const ShStatement& stmt, const char* texfunc) {
00394 ShTextureNodePtr node = shref_dynamic_cast<ShTextureNode>(stmt.src[0].node());
00395 int dims = 0;
00396 switch(node->dims()) {
00397 case SH_TEXTURE_1D: dims = 1; break;
00398 case SH_TEXTURE_2D: dims = 2; break;
00399 case SH_TEXTURE_RECT: dims = 2; break;
00400 case SH_TEXTURE_3D: dims = 3; break;
00401 case SH_TEXTURE_CUBE:
00402 SH_DEBUG_ERROR("Cube maps not handled");
00403 default:
00404 SH_DEBUG_ERROR("Unhandled texture dim");
00405 }
00406
00407
00408 std::string srcInterp, srcFilter, srcWrap, destClamp;
00409
00410 if(node->traits().interpolation() != 0) {
00411
00412
00413 }
00414
00415 if (node->traits().filtering() != ShTextureTraits::SH_FILTER_NONE) {
00416
00417 SH_DEBUG_WARN("cc backend does not support texture filtering.");
00418 }
00419
00420 switch(node->traits().wrapping()) {
00421 case ShTextureTraits::SH_WRAP_CLAMP:
00422 case ShTextureTraits::SH_WRAP_CLAMP_TO_EDGE:
00423 srcWrap = "sh_gcc_backend_wrap_clamp";
00424 break;
00425 case ShTextureTraits::SH_WRAP_REPEAT:
00426 srcWrap = "sh_gcc_backend_wrap_repeat";
00427 break;
00428 default:
00429 shError(ShBackendException("cc backend does not support requested texture wrapping mode."));
00430 break;
00431 }
00432
00433 switch(node->traits().clamping()) {
00434 case ShTextureTraits::SH_CLAMPED:
00435 destClamp = "sh_gcc_backend_clamped";
00436 break;
00437 default:
00438 destClamp = "sh_gcc_backend_unclamped";
00439 }
00440
00441 m_code << " {" << std::endl;
00442 std::string destvar;
00443 std::string srcvar;
00444 bool tempdest = !stmt.dest.swizzle().identity();
00445 bool tempsrc = (!stmt.src[1].swizzle().identity()) || stmt.src[1].neg();
00446
00447 if(tempdest) {
00448 m_code << " " << ctype(stmt.dest.valueType()) <<
00449 " result[" << stmt.dest.size() << "];" << std::endl;
00450 destvar = "result";
00451 } else destvar = resolve(stmt.dest);
00452
00453 if(tempsrc) {
00454 m_code << " " << ctype(stmt.src[1].valueType())
00455 << " input[" << stmt.src[1].size() << "];" << std::endl;
00456
00457 for(int i = 0; i < stmt.src[1].size(); i++) {
00458 m_code << " input[" << i << "] = "
00459 << resolve(stmt.src[1], i) << ";" << std::endl;
00460 }
00461
00462 srcvar = "input";
00463 } else srcvar = resolve(stmt.src[1]);
00464
00465 m_code << " " << texfunc << "<"
00466 << dims << ", "
00467 << node->size() << ", "
00468 << node->width() << ", "
00469 << node->height() << ", "
00470 << node->depth() << ", "
00471 << ctype(node->valueType()) << ","
00472 << srcWrap << ", "
00473 << destClamp << ">("
00474 << resolve(stmt.src[0])
00475 << ", "
00476 << srcvar
00477 << ", "
00478 << destvar
00479 << ");" << std::endl;
00480
00481 if(tempdest) {
00482 for(int i = 0; i < stmt.dest.size(); i++) {
00483 m_code << " "
00484 << resolve(stmt.dest, i)
00485 << " = result[" << i << "];" << std::endl;
00486 }
00487 }
00488 m_code << " }" << std::endl;
00489 }
00490
00491 }
00492