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 <<
"// Shader body" << std::endl;
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 }