00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00020 #include <algorithm>
00021 #include <map>
00022 #include <list>
00023 #include "ShSyntax.hpp"
00024 #include "ShError.hpp"
00025 #include "ShDebug.hpp"
00026 #include "ShTypeInfo.hpp"
00027 #include "ShVariableNode.hpp"
00028 #include "ShInternals.hpp"
00029 #include "ShInstructions.hpp"
00030 #include "ShEval.hpp"
00031 #include "ShTransformer.hpp"
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048 namespace SH {
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121 struct FloatConverter {
00122 FloatConverter(ShTransformer::ValueTypeMap &valueTypeMap, ShVarMap &converts)
00123 : m_valueTypeMap(valueTypeMap), m_converts(converts), m_eval(ShEval::instance())
00124 {
00125 }
00126
00127 void operator()(ShCtrlGraphNodePtr node) {
00128 if (!node) return;
00129 ShBasicBlockPtr block = node->block;
00130 if (!block) return;
00131
00132 ShBasicBlock::ShStmtList::iterator I;
00133 for(I = block->begin(); I != block->end(); ++I) {
00134 fixStatement(block->m_statements, I);
00135 }
00136 }
00137
00138
00139
00140 bool isFloat(ShValueType valueType) {
00141 return shIsFloat(valueType) && shIsRegularValueType(valueType);
00142 }
00143
00144 bool isInt(ShValueType valueType) {
00145 return shIsInteger(valueType) && shIsSigned(valueType);
00146 }
00147
00148
00149 bool isUint(ShValueType valueType) {
00150 return shIsInteger(valueType) && !shIsSigned(valueType);
00151 }
00152
00153
00154 bool isFrac(ShValueType valueType) {
00155 return shIsFraction(valueType) && shIsSigned(valueType);
00156 }
00157
00158 bool isUfrac(ShValueType valueType) {
00159 return shIsFraction(valueType) && !shIsSigned(valueType);
00160 }
00161
00162
00163 static const unsigned int APPLY_MAX_1 = 0x01;
00164 static const unsigned int APPLY_MAX0 = 0x02;
00165 static const unsigned int APPLY_MIN1 = 0x04;
00166 static const unsigned int APPLY_FLR = 0x08;
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178 void insertConversion(ShBasicBlock::ShStmtList &stmtList, const ShBasicBlock::ShStmtList::iterator &I,
00179 const ShVariable &var, ShValueType fromType, const ShVariable &result, ShValueType toType,
00180 unsigned int forced = 0)
00181 {
00182 unsigned int operations = forced;
00183 if(isFloat(toType)) {
00184 } else if(isInt(toType)) {
00185 if(!(isInt(fromType) || isUint(fromType))) {
00186 operations |= APPLY_FLR;
00187 }
00188 } else if(isUint(toType)) {
00189 if(isFloat(fromType) || isInt(fromType) || isFrac(fromType)) {
00190 operations |= APPLY_MAX0;
00191 }
00192 operations |= APPLY_FLR;
00193 } else if(isFrac(toType)) {
00194 if (isFloat(fromType) || isInt(fromType)) {
00195 operations |= APPLY_MAX_1;
00196 operations |= APPLY_MIN1;
00197 } else if (isUint(fromType)) {
00198 operations |= APPLY_MIN1;
00199 }
00200 } else if(isUfrac(toType)) {
00201 if (isFloat(fromType) || isInt(fromType)) {
00202 operations |= APPLY_MAX0;
00203 operations |= APPLY_MIN1;
00204 } else if (isUint(fromType)) {
00205 operations |= APPLY_MIN1;
00206 }
00207 }
00208
00209
00210 ShVariable temp(var.node()->clone(SH_TEMP, var.size(), SH_VALUETYPE_END, SH_SEMANTICTYPE_END, false, false));
00211
00212 stmtList.insert(I, ShStatement(temp, SH_OP_ASN, var));
00213
00214 if(operations & APPLY_MAX_1) {
00215 ShVariable one(var.node()->clone(SH_CONST, 1, SH_VALUETYPE_END, SH_SEMANTICTYPE_END, false, false));
00216 one.setVariant(shVariantFactory(var.valueType())->generateOne());
00217 stmtList.insert(I, ShStatement(temp, temp, SH_OP_MAX, one));
00218 }
00219
00220 if(operations & APPLY_MAX0) {
00221 ShVariable zero(var.node()->clone(SH_CONST, 1, SH_VALUETYPE_END, SH_SEMANTICTYPE_END, false, false));
00222 zero.setVariant(shVariantFactory(var.valueType())->generateZero());
00223 stmtList.insert(I, ShStatement(temp, temp, SH_OP_MAX, zero));
00224 }
00225
00226 if(operations & APPLY_MIN1) {
00227 ShVariable one(var.node()->clone(SH_CONST, 1, SH_VALUETYPE_END, SH_SEMANTICTYPE_END, false, false));
00228 one.setVariant(shVariantFactory(var.valueType())->generateOne());
00229 stmtList.insert(I, ShStatement(temp, temp, SH_OP_MIN, one));
00230 }
00231
00232 if(operations & APPLY_FLR) stmtList.insert(I, ShStatement(temp, SH_OP_FLR, temp));
00233
00234 stmtList.insert(I, ShStatement(result, SH_OP_ASN, temp));
00235
00236 if((operations & APPLY_FLR) && (operations - APPLY_FLR)) {
00237 #ifdef SH_DEBUG_TYPECONVERT
00238 SH_DEBUG_PRINT("Unhandled conversion operations");
00239 #endif
00240 }
00241 }
00242
00243
00244 void fixStatement(ShBasicBlock::ShStmtList &stmtList, const ShBasicBlock::ShStmtList::iterator &I) {
00245 ShStatement &stmt = *I;
00246 if(stmt.dest.null()) return;
00247 #ifdef SH_DEBUG_TYPECONVERT
00248 SH_DEBUG_PRINT("Checking a statement op=" << opInfo[stmt.op].name);
00249 #endif
00250
00251 const ShEvalOpInfo* evalOpInfo;
00252 ShEvalOpInfo* texInfo = 0;
00253 switch(stmt.op) {
00254 case SH_OP_TEX:
00255 case SH_OP_TEXI:
00256 case SH_OP_FETCH:
00257 case SH_OP_TEXD:
00258 case SH_OP_DX:
00259 case SH_OP_DY:
00260
00261
00262
00263
00264
00265
00266 evalOpInfo = texInfo = new ShEvalOpInfo(stmt.op, 0, stmt.dest.valueType(), stmt.src[0].valueType(), stmt.src[1].valueType(), stmt.src[2].valueType());
00267 break;
00268 default:
00269 evalOpInfo = m_eval->getEvalOpInfo(
00270 stmt.op,
00271 stmt.dest.valueType(),
00272 stmt.src[0].valueType(),
00273 stmt.src[1].valueType(),
00274 stmt.src[2].valueType());
00275 break;
00276 }
00277
00278 if(!evalOpInfo) {
00279 switch(stmt.op) {
00280 case SH_OP_TEX:
00281 case SH_OP_TEXI:
00282 case SH_OP_FETCH:
00283 case SH_OP_TEXD:
00284 case SH_OP_KIL:
00285
00286
00287
00288
00289
00290
00291 evalOpInfo = texInfo = new ShEvalOpInfo(stmt.op, 0, stmt.dest.valueType(), stmt.src[0].valueType(), stmt.src[1].valueType(), stmt.src[2].valueType());
00292 break;
00293
00294 default:
00295
00296 SH_DEBUG_PRINT("Possible problem finding evaluator for op = " << opInfo[stmt.op].name);
00297 return;
00298 }
00299 }
00300
00301
00302 for(int i = 0; i < 3; ++i) {
00303 ShValueType srcValueType = stmt.src[i].valueType();
00304 ShValueType opValueType = evalOpInfo->m_src[i];
00305 if(srcValueType == opValueType) continue;
00306 if((m_valueTypeMap.count(srcValueType) == 0) && (m_valueTypeMap.count(opValueType) == 0)) continue;
00307
00308 #ifdef SH_DEBUG_TYPECONVERT
00309 SH_DEBUG_PRINT(" Converting src[" << i << "] from " << shTypeInfo(srcValueType)->name()
00310 << " to " << shTypeInfo(opValueType)->name());
00311 #endif
00312
00313
00314
00315 ShValueType tempValueType = opValueType;
00316 if(m_valueTypeMap.count(tempValueType) > 0) tempValueType = m_valueTypeMap[tempValueType];
00317 ShVariable temp(stmt.src[i].node()->clone(SH_TEMP, stmt.src[i].size(), tempValueType, SH_SEMANTICTYPE_END, false, false));
00318
00319 ShVariableNodePtr varNode = stmt.src[i].node();
00320 if(m_converts.count(varNode) > 0) varNode = m_converts[varNode];
00321 ShVariable newsrc(varNode, stmt.src[i].swizzle(), stmt.src[i].neg());
00322
00323 insertConversion(stmtList, I, newsrc, srcValueType, temp, opValueType);
00324
00325 stmt.src[i] = temp;
00326 }
00327
00328
00329
00330
00331
00332
00333
00334 ShValueType destValueType = stmt.dest.valueType();
00335 ShValueType opDest = evalOpInfo->m_dest;
00336 if((destValueType != opDest) &&
00337 (m_valueTypeMap.count(destValueType) + m_valueTypeMap.count(opDest) > 0)) {
00338
00339 #ifdef SH_DEBUG_TYPECONVERT
00340 SH_DEBUG_PRINT(" Converting dest from " << shTypeInfo(opDest)->name() << " to " << shTypeInfo(destValueType)->name() );
00341 #endif
00342
00343 ShBasicBlock::ShStmtList::iterator afterI = I;
00344 ++afterI;
00345
00346 ShValueType tempValueType = opDest;
00347 if(m_valueTypeMap.count(tempValueType) > 0) tempValueType = m_valueTypeMap[tempValueType];
00348 ShVariable temp(stmt.dest.node()->clone(SH_TEMP, stmt.dest.size(), tempValueType, SH_SEMANTICTYPE_END, false, false));
00349
00350 ShVariableNodePtr varNode = stmt.dest.node();
00351 if(m_converts.count(varNode) > 0) varNode = m_converts[varNode];
00352 ShVariable newdest(varNode, stmt.dest.swizzle(), stmt.dest.neg());
00353
00354
00355 unsigned int forcedOps = 0;
00356 if((stmt.op == SH_OP_DIV || stmt.op == SH_OP_POW) &&
00357 (isInt(destValueType) || isUint(destValueType))) {
00358 forcedOps |= APPLY_FLR;
00359 }
00360
00361 insertConversion(stmtList, afterI, temp, opDest, newdest, destValueType, forcedOps);
00362
00363 stmt.dest = temp;
00364 }
00365
00366 if(texInfo) delete texInfo;
00367 }
00368
00369
00370 void operator()(const ShVariableNodePtr &p) {
00371
00372 if(m_converts.count(p) > 0) return;
00373 if(m_valueTypeMap.count(p->valueType()) == 0) return;
00374 ShVariableNodePtr &converted_p = m_converts[p]
00375 = p->clone(SH_BINDINGTYPE_END, 0, m_valueTypeMap[p->valueType()], SH_SEMANTICTYPE_END, false);
00376
00377 if(p->hasValues()) {
00378 converted_p->setVariant(p->getVariant());
00379
00380 #ifdef SH_DEBUG_TYPECONVERT
00381 SH_DEBUG_PRINT("Setting values on replacement = " << converted_p->getVariant()->encode() << " original = " << p->getVariant()->encode());
00382 #endif
00383 }
00384
00385 if(p->uniform()) {
00386 ShProgram prg = SH_BEGIN_PROGRAM("uniform") {
00387 ShVariable original(p);
00388 ShVariable converted(converted_p);
00389 shASN(converted, original);
00390 } SH_END;
00391 converted_p->attach(prg.node());
00392 }
00393
00394 #ifdef SH_DEBUG_TYPECONVERT
00395 SH_DEBUG_PRINT("Converting " << p->name() << " from " << shTypeInfo(p->valueType())->name()
00396 << " to " << shTypeInfo(m_valueTypeMap[p->valueType()])->name());
00397 #endif
00398 }
00399
00400
00401 ShTransformer::ValueTypeMap &m_valueTypeMap;
00402 ShVarMap &m_converts;
00403
00404 private:
00405 ShEval* m_eval;
00406 };
00407
00408 void ShTransformer::convertToFloat(ValueTypeMap &valueTypeMap)
00409 {
00410 ShVarMap converts;
00411 FloatConverter floatconv(valueTypeMap, converts);
00412
00413
00414 m_program->collectVariables();
00415 std::for_each(m_program->inputs.begin(), m_program->inputs.end(), floatconv);
00416 std::for_each(m_program->outputs.begin(), m_program->outputs.end(), floatconv);
00417 std::for_each(m_program->temps.begin(), m_program->temps.end(), floatconv);
00418 std::for_each(m_program->constants.begin(), m_program->constants.end(), floatconv);
00419 std::for_each(m_program->uniforms.begin(), m_program->uniforms.end(), floatconv);
00420
00421
00422 m_program->ctrlGraph->dfs(floatconv);
00423
00424
00425 ShVariableReplacer vr(converts);
00426 m_program->ctrlGraph->dfs(vr);
00427 vr(m_program->inputs);
00428 vr(m_program->outputs);
00429
00430 if(!converts.empty()) m_changed = true;
00431 }
00432
00433 }
00434