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
00128 FloatConverter& operator=(FloatConverter const&);
00129
00130 void operator()(const ShCtrlGraphNodePtr& node) {
00131 if (!node) return;
00132 ShBasicBlockPtr block = node->block;
00133 if (!block) return;
00134
00135 ShBasicBlock::ShStmtList::iterator I;
00136 for(I = block->begin(); I != block->end(); ++I) {
00137 fixStatement(block->m_statements, I);
00138 }
00139 }
00140
00141
00142
00143 bool isFloat(ShValueType valueType) {
00144 return shIsFloat(valueType) && shIsRegularValueType(valueType);
00145 }
00146
00147 bool isInt(ShValueType valueType) {
00148 return shIsInteger(valueType) && shIsSigned(valueType);
00149 }
00150
00151
00152 bool isUint(ShValueType valueType) {
00153 return shIsInteger(valueType) && !shIsSigned(valueType);
00154 }
00155
00156
00157 bool isFrac(ShValueType valueType) {
00158 return shIsFraction(valueType) && shIsSigned(valueType);
00159 }
00160
00161 bool isUfrac(ShValueType valueType) {
00162 return shIsFraction(valueType) && !shIsSigned(valueType);
00163 }
00164
00165
00166 static const unsigned int APPLY_MAX_1 = 0x01;
00167 static const unsigned int APPLY_MAX0 = 0x02;
00168 static const unsigned int APPLY_MIN1 = 0x04;
00169 static const unsigned int APPLY_FLR = 0x08;
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181 void insertConversion(ShBasicBlock::ShStmtList &stmtList, const ShBasicBlock::ShStmtList::iterator &I,
00182 const ShVariable &var, ShValueType fromType, const ShVariable &result, ShValueType toType,
00183 unsigned int forced = 0)
00184 {
00185 unsigned int operations = forced;
00186 if(isFloat(toType)) {
00187 } else if(isInt(toType)) {
00188 if(!(isInt(fromType) || isUint(fromType))) {
00189 operations |= APPLY_FLR;
00190 }
00191 } else if(isUint(toType)) {
00192 if(isFloat(fromType) || isInt(fromType) || isFrac(fromType)) {
00193 operations |= APPLY_MAX0;
00194 }
00195 operations |= APPLY_FLR;
00196 } else if(isFrac(toType)) {
00197 if (isFloat(fromType) || isInt(fromType)) {
00198 operations |= APPLY_MAX_1;
00199 operations |= APPLY_MIN1;
00200 } else if (isUint(fromType)) {
00201 operations |= APPLY_MIN1;
00202 }
00203 } else if(isUfrac(toType)) {
00204 if (isFloat(fromType) || isInt(fromType)) {
00205 operations |= APPLY_MAX0;
00206 operations |= APPLY_MIN1;
00207 } else if (isUint(fromType)) {
00208 operations |= APPLY_MIN1;
00209 }
00210 }
00211
00212
00213 ShVariable temp(var.node()->clone(SH_TEMP, var.size(), SH_VALUETYPE_END, SH_SEMANTICTYPE_END, false, false));
00214
00215 stmtList.insert(I, ShStatement(temp, SH_OP_ASN, var));
00216
00217 if(operations & APPLY_MAX_1) {
00218 ShVariable one(var.node()->clone(SH_CONST, 1, SH_VALUETYPE_END, SH_SEMANTICTYPE_END, false, false));
00219 one.setVariant(shVariantFactory(var.valueType())->generateOne());
00220 stmtList.insert(I, ShStatement(temp, temp, SH_OP_MAX, one));
00221 }
00222
00223 if(operations & APPLY_MAX0) {
00224 ShVariable zero(var.node()->clone(SH_CONST, 1, SH_VALUETYPE_END, SH_SEMANTICTYPE_END, false, false));
00225 zero.setVariant(shVariantFactory(var.valueType())->generateZero());
00226 stmtList.insert(I, ShStatement(temp, temp, SH_OP_MAX, zero));
00227 }
00228
00229 if(operations & APPLY_MIN1) {
00230 ShVariable one(var.node()->clone(SH_CONST, 1, SH_VALUETYPE_END, SH_SEMANTICTYPE_END, false, false));
00231 one.setVariant(shVariantFactory(var.valueType())->generateOne());
00232 stmtList.insert(I, ShStatement(temp, temp, SH_OP_MIN, one));
00233 }
00234
00235 if(operations & APPLY_FLR) stmtList.insert(I, ShStatement(temp, SH_OP_FLR, temp));
00236
00237 stmtList.insert(I, ShStatement(result, SH_OP_ASN, temp));
00238
00239 if((operations & APPLY_FLR) && (operations - APPLY_FLR)) {
00240 #ifdef SH_DEBUG_TYPECONVERT
00241 SH_DEBUG_PRINT("Unhandled conversion operations");
00242 #endif
00243 }
00244 }
00245
00246
00247 void fixStatement(ShBasicBlock::ShStmtList &stmtList, const ShBasicBlock::ShStmtList::iterator &I) {
00248 ShStatement &stmt = *I;
00249 if(stmt.dest.null()) return;
00250 #ifdef SH_DEBUG_TYPECONVERT
00251 SH_DEBUG_PRINT("Checking a statement op=" << opInfo[stmt.op].name);
00252 #endif
00253
00254 const ShEvalOpInfo* evalOpInfo;
00255 ShEvalOpInfo* texInfo = 0;
00256 switch(stmt.op) {
00257 case SH_OP_TEX:
00258 case SH_OP_TEXI:
00259 case SH_OP_FETCH:
00260 case SH_OP_TEXD:
00261 case SH_OP_DX:
00262 case SH_OP_DY:
00263
00264
00265
00266
00267
00268
00269 evalOpInfo = texInfo = new ShEvalOpInfo(stmt.op, 0, stmt.dest.valueType(), stmt.src[0].valueType(), stmt.src[1].valueType(), stmt.src[2].valueType());
00270 break;
00271 default:
00272 evalOpInfo = m_eval->getEvalOpInfo(
00273 stmt.op,
00274 stmt.dest.valueType(),
00275 stmt.src[0].valueType(),
00276 stmt.src[1].valueType(),
00277 stmt.src[2].valueType());
00278 break;
00279 }
00280
00281 if(!evalOpInfo) {
00282 switch(stmt.op) {
00283 case SH_OP_TEX:
00284 case SH_OP_TEXI:
00285 case SH_OP_FETCH:
00286 case SH_OP_TEXD:
00287 case SH_OP_KIL:
00288 case SH_OP_RET:
00289
00290
00291
00292
00293
00294
00295 evalOpInfo = texInfo = new ShEvalOpInfo(stmt.op, 0, stmt.dest.valueType(), stmt.src[0].valueType(), stmt.src[1].valueType(), stmt.src[2].valueType());
00296 break;
00297
00298 default:
00299
00300 SH_DEBUG_PRINT("Possible problem finding evaluator for op = " << opInfo[stmt.op].name);
00301 return;
00302 }
00303 }
00304
00305
00306 for(int i = 0; i < 3; ++i) {
00307 ShValueType srcValueType = stmt.src[i].valueType();
00308 ShValueType opValueType = evalOpInfo->m_src[i];
00309 if(srcValueType == opValueType) continue;
00310 if((m_valueTypeMap.count(srcValueType) == 0) && (m_valueTypeMap.count(opValueType) == 0)) continue;
00311
00312 #ifdef SH_DEBUG_TYPECONVERT
00313 SH_DEBUG_PRINT(" Converting src[" << i << "] from " << shTypeInfo(srcValueType)->name()
00314 << " to " << shTypeInfo(opValueType)->name());
00315 #endif
00316
00317
00318
00319 ShValueType tempValueType = opValueType;
00320 if(m_valueTypeMap.count(tempValueType) > 0) tempValueType = m_valueTypeMap[tempValueType];
00321 ShVariable temp(stmt.src[i].node()->clone(SH_TEMP, stmt.src[i].size(), tempValueType, SH_SEMANTICTYPE_END, false, false));
00322
00323 ShVariableNodePtr varNode = stmt.src[i].node();
00324 if(m_converts.count(varNode) > 0) varNode = m_converts[varNode];
00325 ShVariable newsrc(varNode, stmt.src[i].swizzle(), stmt.src[i].neg());
00326
00327 insertConversion(stmtList, I, newsrc, srcValueType, temp, opValueType);
00328
00329 stmt.src[i] = temp;
00330 }
00331
00332
00333
00334
00335
00336
00337
00338 ShValueType destValueType = stmt.dest.valueType();
00339 ShValueType opDest = evalOpInfo->m_dest;
00340 if((destValueType != opDest) &&
00341 (m_valueTypeMap.count(destValueType) + m_valueTypeMap.count(opDest) > 0)) {
00342
00343 #ifdef SH_DEBUG_TYPECONVERT
00344 SH_DEBUG_PRINT(" Converting dest from " << shTypeInfo(opDest)->name() << " to " << shTypeInfo(destValueType)->name() );
00345 #endif
00346
00347 ShBasicBlock::ShStmtList::iterator afterI = I;
00348 ++afterI;
00349
00350 ShValueType tempValueType = opDest;
00351 if(m_valueTypeMap.count(tempValueType) > 0) tempValueType = m_valueTypeMap[tempValueType];
00352 ShVariable temp(stmt.dest.node()->clone(SH_TEMP, stmt.dest.size(), tempValueType, SH_SEMANTICTYPE_END, false, false));
00353
00354 ShVariableNodePtr varNode = stmt.dest.node();
00355 if(m_converts.count(varNode) > 0) varNode = m_converts[varNode];
00356 ShVariable newdest(varNode, stmt.dest.swizzle(), stmt.dest.neg());
00357
00358
00359 unsigned int forcedOps = 0;
00360 if((stmt.op == SH_OP_DIV || stmt.op == SH_OP_POW) &&
00361 (isInt(destValueType) || isUint(destValueType))) {
00362 forcedOps |= APPLY_FLR;
00363 }
00364
00365 insertConversion(stmtList, afterI, temp, opDest, newdest, destValueType, forcedOps);
00366
00367 stmt.dest = temp;
00368 }
00369
00370 if(texInfo) delete texInfo;
00371 }
00372
00373
00374 void operator()(const ShVariableNodePtr &p) {
00375
00376 if(m_converts.count(p) > 0) return;
00377 if(m_valueTypeMap.count(p->valueType()) == 0) return;
00378 ShVariableNodePtr &converted_p = m_converts[p]
00379 = p->clone(SH_BINDINGTYPE_END, 0, m_valueTypeMap[p->valueType()], SH_SEMANTICTYPE_END, false);
00380
00381 if(p->hasValues()) {
00382 converted_p->setVariant(p->getVariant());
00383
00384 #ifdef SH_DEBUG_TYPECONVERT
00385 SH_DEBUG_PRINT("Setting values on replacement = " << converted_p->getVariant()->encode() << " original = " << p->getVariant()->encode());
00386 #endif
00387 }
00388
00389 if(p->uniform()) {
00390 ShProgram prg = SH_BEGIN_PROGRAM("uniform") {
00391 ShVariable original(p);
00392 ShVariable converted(converted_p);
00393 shASN(converted, original);
00394 } SH_END;
00395 converted_p->attach(prg.node());
00396 }
00397
00398 #ifdef SH_DEBUG_TYPECONVERT
00399 SH_DEBUG_PRINT("Converting " << p->name() << " from " << shTypeInfo(p->valueType())->name()
00400 << " to " << shTypeInfo(m_valueTypeMap[p->valueType()])->name());
00401 #endif
00402 }
00403
00404
00405 ShTransformer::ValueTypeMap &m_valueTypeMap;
00406 ShVarMap &m_converts;
00407
00408 private:
00409 ShEval* m_eval;
00410 };
00411
00412 void ShTransformer::convertToFloat(ValueTypeMap &valueTypeMap)
00413 {
00414 ShVarMap converts;
00415 FloatConverter floatconv(valueTypeMap, converts);
00416
00417
00418 m_program->collectVariables();
00419 std::for_each(m_program->inputs.begin(), m_program->inputs.end(), floatconv);
00420 std::for_each(m_program->outputs.begin(), m_program->outputs.end(), floatconv);
00421 std::for_each(m_program->temps.begin(), m_program->temps.end(), floatconv);
00422 std::for_each(m_program->constants.begin(), m_program->constants.end(), floatconv);
00423 std::for_each(m_program->uniforms.begin(), m_program->uniforms.end(), floatconv);
00424
00425
00426 m_program->ctrlGraph->dfs(floatconv);
00427
00428
00429 ShVariableReplacer vr(converts);
00430 m_program->ctrlGraph->dfs(vr);
00431 vr(m_program->inputs);
00432 vr(m_program->outputs);
00433
00434 if(!converts.empty()) m_changed = true;
00435 }
00436
00437 }
00438