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 "ShSmBackend.hpp"
00028 #include <iostream>
00029 #include <sstream>
00030 #include "ShEnvironment.hpp"
00031 #include "ShContext.hpp"
00032 #include "ShDebug.hpp"
00033 #include "ShError.hpp"
00034 #include "ShOptimizations.hpp"
00035 #include "ShLinearAllocator.hpp"
00036 #include "ShCtrlGraph.hpp"
00037 #include "ShVariable.hpp"
00038 #include "ShStream.hpp"
00039
00040 namespace ShSm {
00041
00042 const int SmMaxTR = 256;
00043
00044 using namespace SH;
00045
00046 static SH::ShPointer<Backend> instance = new Backend();
00047 static std::string* opNames;
00048
00049 void initOps();
00050
00051 std::string SmRegister::print() const
00052 {
00053 std::ostringstream stream;
00054 switch(type) {
00055 case SHSM_REG_INPUT:
00056 stream << "iR";
00057 break;
00058 case SHSM_REG_OUTPUT:
00059 stream << "oR";
00060 break;
00061 case SHSM_REG_TEMP:
00062 stream << "tR";
00063 break;
00064 case SHSM_REG_CONST:
00065 stream << "cR";
00066 break;
00067 case SHSM_REG_TEXTURE:
00068 stream << index;
00069 return stream.str();
00070 }
00071 stream << "[" << index << "]";
00072
00073 return stream.str();
00074 }
00075
00076 BackendCode::BackendCode(ShPointer<Backend> backend, const ShProgram& shader,
00077 const std::string& target)
00078 : m_backend(backend), m_shader(shader), m_originalShader(shader),
00079 m_smShader(0), m_target(target),
00080 m_maxCR(0), m_maxTR(0), m_maxIR(0), m_maxOR(0), m_maxTex(0),
00081 m_cR(0), m_tR(0), m_iR(0), m_oR(0)
00082 {
00083 }
00084
00085 BackendCode::~BackendCode()
00086 {
00087 delete [] m_cR;
00088 delete [] m_tR;
00089 delete [] m_iR;
00090 delete [] m_oR;
00091
00092 for (TextureNodeMap::iterator I = m_textureMap.begin(); I != m_textureMap.end(); ++I) {
00093 smDeleteTexture(I->second);
00094 }
00095 }
00096
00097 bool BackendCode::allocateRegister(const SH::ShVariableNodePtr& var)
00098 {
00099 if (!var) return true;
00100 if (var->kind() != SH_TEMP) return true;
00101 if (var->uniform()) return true;
00102
00103 if (m_tempRegs.empty()) {
00104 SH_DEBUG_WARN("Oh no, out of registers!");
00105 return false;
00106 }
00107
00108 int idx = m_tempRegs.front();
00109 m_tempRegs.pop_front();
00110
00111 if (idx + 1 > m_maxTR) m_maxTR = idx + 1;
00112 m_registers[var] = SmRegister(SHSM_REG_TEMP, idx);
00113 return true;
00114 }
00115
00116 void BackendCode::freeRegister(const SH::ShVariableNodePtr& var)
00117 {
00118 if (!var) return;
00119 if (var->kind() != SH_TEMP) return;
00120 if (var->uniform()) return;
00121
00122 if (m_registers.find(var) == m_registers.end()) {
00123 shError( ShBackendException( "Cannot find register to free" ) );
00124 }
00125 m_tempRegs.push_front(m_registers[var].index);
00126 }
00127
00128 int shSmTarget(const std::string& target)
00129 {
00130 if (target == "gpu:vertex") return 0;
00131 if (target == "gpu:fragment") return 1;
00132 return -1;
00133 }
00134
00135 void BackendCode::upload()
00136 {
00137 SH_DEBUG_PRINT("Uploading shader");
00138 m_smShader = smDeclareShader(shSmTarget(m_target));
00139 smShaderBegin(m_smShader);
00140
00141 for (int i = 0; i < m_maxTR; i++) m_tR[i] = smReg();
00142 for (int i = 0; i < m_maxIR; i++) m_iR[i] = smInputReg(i);
00143 for (int i = 0; i < m_maxOR; i++) m_oR[i] = smOutputReg(i);
00144 for (int i = 0; i < m_maxCR; i++) m_cR[i] = smConstantReg(i);
00145
00146 int i = 0;
00147 for (SmInstList::const_iterator I = m_instructions.begin(); I != m_instructions.end();
00148 ++I) {
00149 if (I->op == OP_TEX) {
00150 SH_DEBUG_PRINT("Adding an OP_TEX");
00151 if (getReg(I->src2.node()).type != SHSM_REG_TEXTURE) {
00152 shError( ShBackendException( "src regster for OP_TEX is not a texture register" ) );
00153 }
00154 smInstr(OP_TEX, getSmReg(I->dest), getSmReg(I->src1), getReg(I->src2.node()).index);
00155 } else if (I->src1.null()) {
00156 smInstr(I->op, getSmReg(I->dest));
00157 } else if (I->src2.null()) {
00158 smInstr(I->op, getSmReg(I->dest), getSmReg(I->src1));
00159 } else if (I->src3.null()) {
00160 smInstr(I->op, getSmReg(I->dest), getSmReg(I->src1), getSmReg(I->src2));
00161 } else {
00162 smInstr(I->op, getSmReg(I->dest), getSmReg(I->src1), getSmReg(I->src2), getSmReg(I->src3));
00163 }
00164 i++;
00165 }
00166 SH_DEBUG_PRINT(i << " instructions uploaded.");
00167 smShaderEnd();
00168 }
00169
00170 void BackendCode::bind()
00171 {
00172 if (!m_smShader) upload();
00173
00174 SH_DEBUG_PRINT("Binding shader");
00175
00176 smBindShader(m_smShader);
00177 SH::ShEnvironment::boundShaders()[m_target] = m_originalShader;
00178
00179
00180 for (RegMap::const_iterator I = m_registers.begin(); I != m_registers.end(); ++I) {
00181 ShVariableNodePtr node = I->first;
00182 SmRegister reg = I->second;
00183 if (node->hasValues() && reg.type == SHSM_REG_CONST) {
00184 float values[4];
00185 int i;
00186 for (i = 0; i < node->size(); i++) {
00187 values[i] = node->getValue(i);
00188 }
00189 for (; i < 4; i++) {
00190 values[i] = 0.0;
00191 }
00192 smModLocalConstant(shSmTarget(m_target), reg.index, smTuple(values[0], values[1], values[2], values[3]));
00193 }
00194 }
00195
00196 SH_DEBUG_PRINT("Uploading textures...");
00197 for (ShProgramNode::VarList::const_iterator I = m_shader->textures.begin(); I != m_shader->textures.end();
00198 ++I) {
00199 ShDataTextureNodePtr texture = *I;
00200 if (!texture) {
00201 SH_DEBUG_WARN((*I)->name() << " is not a valid texture!");
00202 continue;
00203 }
00204 if (m_textureMap.find(texture) == m_textureMap.end()) {
00205 ShDataMemoryObjectPtr texmem = texture->mem();
00206 if( !texmem ) {
00207 SH_DEBUG_WARN((*I)->name() << " has invalid texture data!");
00208 continue;
00209 }
00210
00211
00212 m_textureMap[texture] = smNewTexture2DRect(texture->width(), texture->height(),
00213 texture->elements(), SM_FLOAT);
00214 SMtexture smTex = m_textureMap[texture];
00215 smTexImage2D(smTex, 0, const_cast<float*>(texmem->data()));
00216
00217
00218 smTexWrapS(smTex, SM_REPEAT);
00219 smTexWrapT(smTex, SM_REPEAT);
00220 } else {
00221 SH_DEBUG_PRINT("Texture already allocated");
00222 }
00223 SH_DEBUG_PRINT("Binding texture " << m_textureMap[texture] << " to texture unit " << getReg(texture).index);
00224 smBindTexture(shSmTarget(m_target), getReg(texture).index, m_textureMap[texture]);
00225 }
00226 }
00227
00228 std::string BackendCode::printVar(const ShVariable& var)
00229 {
00230 const char* swizChars = "xyzw";
00231
00232 std::string out;
00233
00234 if (var.neg()) out += "-";
00235
00236 out += getReg(var.node()).print();
00237
00238 if (var.node()->kind() == SH_TEXTURE) return out;
00239
00240 if (var.swizzle().size()) {
00241 out += "[\"";
00242 for (int i = 0; i < std::min(var.swizzle().size(), 4); i++) {
00243 out += swizChars[var.swizzle()[i]];
00244 }
00245 out += "\"]";
00246 } else {
00247 if (var.size() < 4) {
00248 out += "[\"";
00249 for (int i = 0; i < var.size(); i++) out += swizChars[i];
00250 out += "\"]";
00251 }
00252 }
00253 return out;
00254 }
00255
00256 void BackendCode::updateUniform(const ShVariableNodePtr& uniform)
00257 {
00258 if (!haveReg(uniform)) return;
00259
00260 SmRegister reg = getReg(uniform);
00261
00262 float values[4];
00263 int i;
00264 for (i = 0; i < uniform->size(); i++) {
00265 values[i] = uniform->getValue(i);
00266 }
00267 for (; i < 4; i++) {
00268 values[i] = 0.0;
00269 }
00270 smModLocalConstant(shSmTarget(m_target), reg.index, smTuple(values[0], values[1], values[2], values[3]));
00271 }
00272
00273 void BackendCode::generate() {
00274
00275 m_shader = cloneProgram(m_originalShader);
00276 ShEnvironment::shader = m_shader;
00277 ShTransformer transform(m_shader);
00278
00279 transform.convertInputOutput();
00280 transform.splitTuples(4, m_splits);
00281
00282 if(transform.changed()) {
00283 optimize(m_shader);
00284 m_shader->collectVariables();
00285 } else {
00286 m_shader = m_originalShader;
00287 ShEnvironment::shader = m_shader;
00288 }
00289
00290 shader->ctrlGraph->entry->clearMarked();
00291 generateNode(code, entry);
00292 shader->ctrlGraph->entry->clearMarked();
00293
00294 code->allocRegs();
00295 }
00296
00297 std::ostream& BackendCode::print(std::ostream& out)
00298 {
00299 out << "SMshader shader = smDeclareShader(" << shSmTarget(m_target) << ");" << std::endl;
00300 out << "{" << std::endl;
00301 out << "smShaderBegin(shader);" << std::endl;
00302 out << std::endl;
00303 out << "// Register declarations" << std::endl;
00304 out << "SMreg tR[" << m_maxTR << "];" << std::endl;
00305 out << "for (int i = 0; i < " << m_maxTR << "; i++) tR[i] = smReg();" << std::endl;
00306 out << "SMreg iR[" << m_maxIR << "];" << std::endl;
00307 for (int i = 0; i < m_maxIR; i++) out << "iR[" << i << "] = smInputReg(" << i << ");" << std::endl;
00308 out << "SMreg oR[" << m_maxOR << "];" << std::endl;
00309 for (int i = 0; i < m_maxOR; i++) out << "oR[" << i << "] = smOutputReg(" << i << ");" << std::endl;
00310 out << "SMreg cR[" << m_maxCR << "];" << std::endl;
00311 for (int i = 0; i < m_maxCR; i++) out << "cR[" << i << "] = smConstantReg(" << i << ");" << std::endl;
00312
00313 out << std::endl;
00314 out << "
00315 #ifdef SH_DEBUG
00316 int i = 0;
00317 #endif
00318 for (SmInstList::const_iterator I = m_instructions.begin(); I != m_instructions.end();
00319 ++I) {
00320 out << "sm" << opNames[I->op] << "(" << printVar(I->dest);
00321 if (!I->src1.null()) {
00322 out << ", " << printVar(I->src1);
00323 }
00324 if (!I->src2.null()) {
00325 out << ", " << printVar(I->src2);
00326 }
00327 if (!I->src3.null()) {
00328 out << ", " << printVar(I->src3);
00329 }
00330 out << ");";
00331 #ifdef SH_DEBUG
00332 out << " // PC = " << i++;
00333 #endif
00334 out << std::endl;
00335 }
00336 out << std::endl;
00337 out << "smShaderEnd();" << std::endl;
00338 out << "}" << std::endl;
00339
00340 out << std::endl;
00341 out << "// Initialize constant registers" << std::endl;
00342
00343
00344
00345
00346
00347
00348 for (RegMap::const_iterator I = m_registers.begin(); I != m_registers.end(); ++I) {
00349 ShVariableNodePtr node = I->first;
00350 SmRegister reg = I->second;
00351 if (node->hasValues() && reg.type == SHSM_REG_CONST) {
00352 out << "smModLocalConstant(" << shSmTarget(m_target) << ", " << reg.index << ", smTuple(";
00353 for (int i = 0; i < node->size(); i++) {
00354 if (i) out << ", ";
00355 out << node->getValue(i);
00356 }
00357 out << "));" << std::endl;
00358 }
00359 }
00360 return out;
00361 }
00362
00363 std::ostream& BackendCode::printInputOutputFormat(std::ostream& out) {
00364
00365 return out;
00366 }
00367
00368 void BackendCode::genScalarVectorInst( SH::ShVariable dest, SH::ShVariable op1,
00369 SH::ShVariable op2, Operation opcode ) {
00370 if (op1.size() != 1 || op2.size() != 1) {
00371 if (op1.size() == 1) {
00372 int* swizzle = new int[op2.size()];
00373 for (int i = 0; i < op2.size(); i++) swizzle[i] = 0;
00374 m_instructions.push_back(SmInstruction((Operation)opcode, dest,
00375 op1(op2.size(), swizzle), op2));
00376 delete [] swizzle;
00377 return;
00378 } else if (op2.size() == 1) {
00379 int* swizzle = new int[op1.size()];
00380 for (int i = 0; i < op1.size(); i++) swizzle[i] = 0;
00381 m_instructions.push_back(SmInstruction((Operation)opcode, dest, op1,
00382 op2(op1.size(), swizzle)));
00383 delete [] swizzle;
00384 return;
00385 }
00386 }
00387 m_instructions.push_back(SmInstruction((Operation)opcode, dest, op1, op2));
00388 }
00389
00390 void BackendCode::addBasicBlock(const ShBasicBlockPtr& block)
00391 {
00392 for (ShBasicBlock::ShStmtList::const_iterator I = block->begin();
00393 I != block->end(); ++I) {
00394 const ShStatement& stmt = *I;
00395 switch (stmt.op) {
00396
00397 case SH_OP_ASN:
00398 m_instructions.push_back(SmInstruction(OP_MOV, stmt.dest, stmt.src[0]));
00399 break;
00400 case SH_OP_ADD:
00401 m_instructions.push_back(SmInstruction(OP_ADD, stmt.dest, stmt.src[0], stmt.src[1]));
00402 break;
00403 case SH_OP_MUL:
00404 genScalarVectorInst(stmt.dest, stmt.src[0], stmt.src[1], OP_MUL);
00405 case SH_OP_DIV:
00406 {
00407 ShVariable rcp(new ShVariableNode(SH_TEMP, stmt.src[1].size()));
00408 m_instructions.push_back(SmInstruction(OP_RCP, rcp, stmt.src[1]));
00409
00410 if (rcp.size() == 1 && stmt.src[0].size() != 1) {
00411 int* swizzle = new int[stmt.src[0].size()];
00412 for (int i = 0; i < stmt.src[0].size(); i++) swizzle[i] = 0;
00413 m_instructions.push_back(SmInstruction(OP_MUL, stmt.dest, stmt.src[0],
00414 rcp(stmt.src[0].size(), swizzle)));
00415 delete [] swizzle;
00416 } else {
00417 m_instructions.push_back(SmInstruction(OP_MUL, stmt.dest, stmt.src[0], rcp));
00418 }
00419 break;
00420 }
00421 case SH_OP_SLT:
00422 genScalarVectorInst(stmt.dest, stmt.src[0], stmt.src[1], OP_SLT);
00423 break;
00424 case SH_OP_SLE:
00425 genScalarVectorInst(stmt.dest, stmt.src[0], stmt.src[1], OP_SLE);
00426 break;
00427 case SH_OP_SGT:
00428 genScalarVectorInst(stmt.dest, stmt.src[0], stmt.src[1], OP_SGT);
00429 break;
00430 case SH_OP_SGE:
00431 genScalarVectorInst(stmt.dest, stmt.src[0], stmt.src[1], OP_SGE);
00432 break;
00433 case SH_OP_SEQ:
00434 genScalarVectorInst(stmt.dest, stmt.src[0], stmt.src[1], OP_SEQ);
00435 break;
00436 case SH_OP_SNE:
00437 genScalarVectorInst(stmt.dest, stmt.src[0], stmt.src[1], OP_SNE);
00438 break;
00439 case SH_OP_ABS:
00440 m_instructions.push_back(SmInstruction(OP_ABS, stmt.dest, stmt.src[0]));
00441 break;
00442 case SH_OP_CEIL:
00443 m_instructions.push_back(SmInstruction(OP_CEIL, stmt.dest, stmt.src[0]));
00444 break;
00445 case SH_OP_COS:
00446 m_instructions.push_back(SmInstruction(OP_COS, stmt.dest, stmt.src[0]));
00447 break;
00448 case SH_OP_DOT:
00449 {
00450 ShVariable left = stmt.src[0];
00451 ShVariable right = stmt.src[1];
00452
00453
00454 if( left.size() < right.size() ) {
00455 int *swizzle = new int[ right.size() ];
00456 for( int i = 0; i < right.size(); ++i ) swizzle[i] = 0;
00457 left = left( right.size(), swizzle );
00458 delete swizzle;
00459 } else if( right.size() < left.size() ) {
00460 int *swizzle = new int[ left.size() ];
00461 for( int i = 0; i < left.size(); ++i ) swizzle[i] = 0;
00462 right = right( left.size(), swizzle );
00463 delete swizzle;
00464 }
00465
00466 if (left.size() == 3) {
00467 m_instructions.push_back(SmInstruction(OP_DP3, stmt.dest, left, right));
00468 } else if (left.size() == 4) {
00469 m_instructions.push_back(SmInstruction(OP_DP4, stmt.dest, left, right));
00470 } else if (left.size() == 1) {
00471 m_instructions.push_back(SmInstruction(OP_MUL, stmt.dest, left, right));
00472 } else {
00473 ShVariable mul(new ShVariableNode(SH_TEMP, left.size()));
00474 m_instructions.push_back(SmInstruction(OP_MUL, mul, left, right));
00475 m_instructions.push_back(SmInstruction(OP_ADD, stmt.dest, mul(0), mul(1)));
00476 for (int i = 2; i < left.size(); i++) {
00477 m_instructions.push_back(SmInstruction(OP_ADD, stmt.dest, stmt.dest, mul(i)));
00478 }
00479 }
00480 break;
00481 }
00482 case SH_OP_FLR:
00483 m_instructions.push_back(SmInstruction(OP_FLR, stmt.dest, stmt.src[0]));
00484 break;
00485 case SH_OP_FRAC:
00486 m_instructions.push_back(SmInstruction(OP_FRC, stmt.dest, stmt.src[0]));
00487 break;
00488 case SH_OP_LRP:
00489 {
00490 if (stmt.src[0].size() == 1 && stmt.src[1].size() != 1) {
00491 int* swizzle = new int[stmt.src[1].size()];
00492 for (int i = 0; i < stmt.src[1].size(); i++) swizzle[i] = 0;
00493 m_instructions.push_back(SmInstruction(OP_LRP, stmt.dest, stmt.src[0](stmt.src[1].size(),swizzle), stmt.src[1], stmt.src[2]));
00494 delete [] swizzle;
00495 } else {
00496 m_instructions.push_back(SmInstruction(OP_LRP, stmt.dest, stmt.src[0], stmt.src[1], stmt.src[2]));
00497 }
00498 }
00499 break;
00500 case SH_OP_MAD:
00501 {
00502 if (stmt.src[0].size() != 1 || stmt.src[1].size() != 1) {
00503 if (stmt.src[0].size() == 1) {
00504 int* swizzle = new int[stmt.src[1].size()];
00505 for (int i = 0; i < stmt.src[1].size(); i++) swizzle[i] = 0;
00506 m_instructions.push_back(SmInstruction(OP_MAD, stmt.dest,
00507 stmt.src[0](stmt.src[1].size(), swizzle), stmt.src[1], stmt.src[2]));
00508 delete [] swizzle;
00509 break;
00510 } else if (stmt.src[1].size() == 1) {
00511 int* swizzle = new int[stmt.src[0].size()];
00512 for (int i = 0; i < stmt.src[0].size(); i++) swizzle[i] = 0;
00513 m_instructions.push_back(SmInstruction(OP_MAD, stmt.dest, stmt.src[0],
00514 stmt.src[1](stmt.src[0].size(), swizzle), stmt.src[2]));
00515 delete [] swizzle;
00516 break;
00517 }
00518 }
00519
00520 m_instructions.push_back(SmInstruction(OP_MAD, stmt.dest, stmt.src[0], stmt.src[1], stmt.src[2]));
00521 break;
00522 }
00523
00524 case SH_OP_MAX:
00525 m_instructions.push_back(SmInstruction(OP_MAX, stmt.dest, stmt.src[0], stmt.src[1]));
00526 break;
00527 case SH_OP_MIN:
00528 m_instructions.push_back(SmInstruction(OP_MIN, stmt.dest, stmt.src[0], stmt.src[1]));
00529 break;
00530 case SH_OP_MOD:
00531 if (stmt.src[1].size() == 1 && stmt.src[0].size() != 1) {
00532 int* swizzle = new int[stmt.src[0].size()];
00533 for (int i = 0; i < stmt.src[0].size(); i++) swizzle[i] = 0;
00534 m_instructions.push_back(SmInstruction(OP_FMOD, stmt.dest, stmt.src[0],
00535 stmt.src[1](stmt.src[0].size(), swizzle)));
00536 delete [] swizzle;
00537 } else {
00538 m_instructions.push_back(SmInstruction(OP_FMOD, stmt.dest, stmt.src[0], stmt.src[1]));
00539 }
00540 break;
00541 case SH_OP_POW:
00542 for (int i = 0; i < stmt.src[0].size(); i++) {
00543 m_instructions.push_back(SmInstruction(OP_POW, stmt.dest(i), stmt.src[0](i), stmt.src[1](i)));
00544 }
00545 break;
00546 case SH_OP_SIN:
00547 m_instructions.push_back(SmInstruction(OP_SIN, stmt.dest, stmt.src[0]));
00548 break;
00549 case SH_OP_SQRT:
00550 {
00551 int rsize = stmt.src[0].size();
00552 ShVariable rsq(new ShVariableNode(SH_TEMP, rsize));
00553 m_instructions.push_back(SmInstruction(OP_RSQ, rsq, stmt.src[0]));
00554 m_instructions.push_back(SmInstruction(OP_RCP, stmt.dest, rsq));
00555 break;
00556 }
00557 case SH_OP_NORM:
00558 m_instructions.push_back(SmInstruction(OP_NORM, stmt.dest, stmt.src[0]));
00559 break;
00560 case SH_OP_TEX:
00561 {
00562 ShTextureNodePtr texture = stmt.src[0].node();
00563 if (!texture) break;
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576 m_instructions.push_back(SmInstruction(OP_TEX, stmt.dest, stmt.src[1], stmt.src[0]));
00577 break;
00578 }
00579 case SH_OP_XPD:
00580 m_instructions.push_back(SmInstruction(OP_XPD, stmt.dest, stmt.src[0], stmt.src[1]));
00581 break;
00582 case SH_OP_COND:
00583 if (stmt.src[0].size() == 1 && stmt.src[1].size() != 1) {
00584 int* swizzle = new int[stmt.src[1].size()];
00585 for (int i = 0; i < stmt.src[1].size(); i++) swizzle[i] = 0;
00586 m_instructions.push_back(SmInstruction(OP_CMP, stmt.dest, -stmt.src[0](stmt.src[1].size(), swizzle),
00587 stmt.src[1], stmt.src[2]));
00588 delete [] swizzle;
00589 } else {
00590 m_instructions.push_back(SmInstruction(OP_CMP, stmt.dest, -stmt.src[0], stmt.src[1], stmt.src[2]));
00591 }
00592 break;
00593 default:
00594
00595 SH_DEBUG_WARN(opInfo[stmt.op].name << " not implement in SM backend");
00596 break;
00597 }
00598 }
00599 }
00600
00601 void BackendCode::allocRegs()
00602 {
00603 for (ShProgramNode::VarList::const_iterator I = m_shader->inputs.begin();
00604 I != m_shader->inputs.end(); ++I) {
00605 getReg(*I);
00606 }
00607 for (ShProgramNode::VarList::const_iterator I = m_shader->outputs.begin();
00608 I != m_shader->outputs.end(); ++I) {
00609 getReg(*I);
00610 }
00611
00612 m_tempRegs.clear();
00613 m_maxTR = 0;
00614 for (int i = 0; i < SmMaxTR; i++) {
00615 m_tempRegs.push_back(i);
00616 }
00617
00618 ShLinearAllocator allocator(ShBackendCodePtr(this));
00619
00620 for (std::size_t i = 0; i < m_instructions.size(); i++) {
00621 SmInstruction instr = m_instructions[i];
00622 getReg(instr.dest.node());
00623 allocator.mark(instr.dest.node(), i);
00624 getReg(instr.src1.node());
00625 allocator.mark(instr.src1.node(), i);
00626 getReg(instr.src2.node());
00627 allocator.mark(instr.src2.node(), i);
00628 getReg(instr.src3.node());
00629 allocator.mark(instr.src3.node(), i);
00630 }
00631 allocator.allocate();
00632
00633 m_tempRegs.clear();
00634
00635 m_tR = new SMreg[m_maxTR];
00636 m_cR = new SMreg[m_maxCR];
00637 m_iR = new SMreg[m_maxIR];
00638 m_oR = new SMreg[m_maxOR];
00639 }
00640
00641 bool BackendCode::haveReg(const SH::ShVariableNodePtr& var)
00642 {
00643 return m_registers.find(var) != m_registers.end();
00644 }
00645
00646 SmRegister BackendCode::getReg(const SH::ShVariableNodePtr& var)
00647 {
00648 if (!var) return SmRegister(SHSM_REG_TEMP, -1);
00649 RegMap::const_iterator I = m_registers.find(var);
00650 if (I != m_registers.end()) return I->second;
00651
00652 if (var->uniform() && var->kind() != SH_TEXTURE) {
00653 m_registers[var] = SmRegister(SHSM_REG_CONST, m_maxCR++);
00654 return m_registers[var];
00655 }
00656
00657 if (var->kind() == SH_TEMP) return SmRegister(SHSM_REG_TEMP, -1);
00658
00659 switch (var->kind()) {
00660 case SH_INPUT:
00661 m_registers[var] = SmRegister(SHSM_REG_INPUT, m_maxIR++);
00662 break;
00663 case SH_OUTPUT:
00664 m_registers[var] = SmRegister(SHSM_REG_OUTPUT, m_maxOR++);
00665 break;
00666 case SH_TEMP:
00667 break;
00668 case SH_CONST:
00669 m_registers[var] = SmRegister(SHSM_REG_CONST, m_maxCR++);
00670 break;
00671 case SH_TEXTURE:
00672 SH_DEBUG_PRINT("Allocating texture unit " << m_maxTex);
00673 m_registers[var] = SmRegister(SHSM_REG_TEXTURE, m_maxTex++);
00674 break;
00675 }
00676 return m_registers[var];
00677 }
00678
00679 SMreg BackendCode::getSmReg(const SH::ShVariable& var)
00680 {
00681 SmRegister reg = getReg(var.node());
00682 if (reg.index < 0) {
00683 SH_DEBUG_WARN("Could not obtain register!");
00684 return SMreg();
00685 }
00686
00687 SMreg smReg;
00688
00689 switch (reg.type) {
00690 case SHSM_REG_INPUT:
00691 smReg = m_iR[reg.index];
00692 break;
00693 case SHSM_REG_OUTPUT:
00694 smReg = m_oR[reg.index];
00695 break;
00696 case SHSM_REG_TEMP:
00697 smReg = m_tR[reg.index];
00698 break;
00699 case SHSM_REG_CONST:
00700 smReg = m_cR[reg.index];
00701 break;
00702 case SHSM_REG_TEXTURE:
00703 return SMreg();
00704 break;
00705 default:
00706 SH_DEBUG_WARN("Unknown register type " << (int)reg.type);
00707 break;
00708 }
00709
00710
00711 const char* swizChars = "xyzw";
00712 std::string swizzle;
00713 if (var.swizzle().size()) {
00714 for (int i = 0; i < std::min(var.swizzle().size(), 4); i++) {
00715 swizzle += swizChars[var.swizzle()[i]];
00716 }
00717 } else {
00718 if (var.size() < 4) {
00719 for (int i = 0; i < var.size(); i++) swizzle += swizChars[i];
00720 }
00721 }
00722 if (!swizzle.empty()) smReg = smReg[swizzle.c_str()];
00723
00724
00725 if (var.neg()) smReg = -smReg;
00726
00727 return smReg;
00728 }
00729
00730 Backend::Backend()
00731 {
00732 SH_DEBUG_PRINT("SM Backend loaded.");
00733 initOps();
00734 }
00735
00736 Backend::~Backend()
00737 {
00738 delete opNames;
00739 SH_DEBUG_PRINT("SM Backend unloaded.");
00740 }
00741
00742 void Backend::generateNode(BackendCodePtr& code, const ShCtrlGraphNodePtr& node)
00743 {
00744 if (node->marked()) return;
00745 node->mark();
00746 if (node->block) code->addBasicBlock(node->block);
00747 for (std::vector<ShCtrlGraphBranch>::const_iterator I = node->successors.begin();
00748 I != node->successors.end(); ++I) {
00749
00750 }
00751 if (node->follower) {
00752
00753 generateNode(code, node->follower);
00754 }
00755 for (std::vector<ShCtrlGraphBranch>::const_iterator I = node->successors.begin();
00756 I != node->successors.end(); ++I) {
00757 generateNode(code, I->node);
00758 }
00759 }
00760
00761 ShBackendCodePtr Backend::generateCode(const std::string& target, const ShProgram& shader)
00762 {
00763
00764 BackendCodePtr code = new BackendCode(this, shader, target);
00765 code->generate();
00766
00767 return code;
00768 }
00769
00770 std::string Backend::name() const
00771 {
00772 return "sm";
00773 }
00774
00775 void initOps()
00776 {
00777 opNames = new std::string[256];
00778 opNames[OP_ABS] = "ABS";
00779 opNames[OP_ADD] = "ADD";
00780 opNames[OP_BRA] = "BRA";
00781 opNames[OP_CAL] = "CAL";
00782 opNames[OP_CEIL] = "CEIL";
00783 opNames[OP_CMP] = "CMP";
00784 opNames[OP_COS] = "COS";
00785 opNames[OP_DDX] = "DDX";
00786 opNames[OP_DDY] = "DDY";
00787 opNames[OP_DP3] = "DP3";
00788 opNames[OP_DP4] = "DP4";
00789 opNames[OP_DPH] = "DPH";
00790 opNames[OP_DST] = "DST";
00791 opNames[OP_EX2] = "EX2";
00792 opNames[OP_EXP] = "EXP";
00793 opNames[OP_FLR] = "FLR";
00794 opNames[OP_FMOD] = "FMOD";
00795 opNames[OP_FRC] = "FRC";
00796 opNames[OP_KIL] = "KIL";
00797 opNames[OP_LG2] = "LG2";
00798 opNames[OP_LIT] = "LIT";
00799 opNames[OP_LOG] = "LOG";
00800 opNames[OP_LRP] = "LRP";
00801 opNames[OP_MAD] = "MAD";
00802 opNames[OP_MAX] = "MAX";
00803 opNames[OP_MIN] = "MIN";
00804 opNames[OP_MOV] = "MOV";
00805 opNames[OP_MUL] = "MUL";
00806 opNames[OP_NORM] = "NORM";
00807 opNames[OP_OUT] = "OUT";
00808 opNames[OP_POW] = "POW";
00809 opNames[OP_RCC] = "RCC";
00810 opNames[OP_RCP] = "RCP";
00811 opNames[OP_RET] = "RET";
00812 opNames[OP_RFL] = "RFL";
00813 opNames[OP_RSQ] = "RSQ";
00814 opNames[OP_SEQ] = "SEQ";
00815 opNames[OP_SCS] = "SCS";
00816 opNames[OP_SFL] = "SFL";
00817 opNames[OP_SGE] = "SGE";
00818 opNames[OP_SGT] = "SGT";
00819 opNames[OP_SIN] = "SIN";
00820 opNames[OP_SLE] = "SLE";
00821 opNames[OP_SLT] = "SLT";
00822 opNames[OP_SNE] = "SNE";
00823 opNames[OP_SSG] = "SSG";
00824 opNames[OP_STR] = "STR";
00825 opNames[OP_SUB] = "SUB";
00826 opNames[OP_TEX] = "TEX";
00827 opNames[OP_TXB] = "TXB";
00828 opNames[OP_TXD] = "TXD";
00829 opNames[OP_TXP] = "TXP";
00830 opNames[OP_X2D] = "X2D";
00831 opNames[OP_XPD] = "XPD";
00832 opNames[OP_HLT] = "HLT";
00833 }
00834
00835 void Backend::execute(const ShProgram& program, ShStream& dest)
00836 {
00837
00838 }
00839
00840 }