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 case SH_OP_RET:
00286
00287
00288
00289
00290
00291
00292 evalOpInfo = texInfo = new ShEvalOpInfo(stmt.op, 0, stmt.dest.valueType(), stmt.src[0].valueType(), stmt.src[1].valueType(), stmt.src[2].valueType());
00293 break;
00294
00295 default:
00296
00297 SH_DEBUG_PRINT("Possible problem finding evaluator for op = " << opInfo[stmt.op].name);
00298 return;
00299 }
00300 }
00301
00302
00303 for(int i = 0; i < 3; ++i) {
00304 ShValueType srcValueType = stmt.src[i].valueType();
00305 ShValueType opValueType = evalOpInfo->m_src[i];
00306 if(srcValueType == opValueType) continue;
00307 if((m_valueTypeMap.count(srcValueType) == 0) && (m_valueTypeMap.count(opValueType) == 0)) continue;
00308
00309 #ifdef SH_DEBUG_TYPECONVERT
00310 SH_DEBUG_PRINT(" Converting src[" << i << "] from " << shTypeInfo(srcValueType)->name()
00311 << " to " << shTypeInfo(opValueType)->name());
00312 #endif
00313
00314
00315
00316 ShValueType tempValueType = opValueType;
00317 if(m_valueTypeMap.count(tempValueType) > 0) tempValueType = m_valueTypeMap[tempValueType];
00318 ShVariable temp(stmt.src[i].node()->clone(SH_TEMP, stmt.src[i].size(), tempValueType, SH_SEMANTICTYPE_END, false, false));
00319
00320 ShVariableNodePtr varNode = stmt.src[i].node();
00321 if(m_converts.count(varNode) > 0) varNode = m_converts[varNode];
00322 ShVariable newsrc(varNode, stmt.src[i].swizzle(), stmt.src[i].neg());
00323
00324 insertConversion(stmtList, I, newsrc, srcValueType, temp, opValueType);
00325
00326 stmt.src[i] = temp;
00327 }
00328
00329
00330
00331
00332
00333
00334
00335 ShValueType destValueType = stmt.dest.valueType();
00336 ShValueType opDest = evalOpInfo->m_dest;
00337 if((destValueType != opDest) &&
00338 (m_valueTypeMap.count(destValueType) + m_valueTypeMap.count(opDest) > 0)) {
00339
00340 #ifdef SH_DEBUG_TYPECONVERT
00341 SH_DEBUG_PRINT(" Converting dest from " << shTypeInfo(opDest)->name() << " to " << shTypeInfo(destValueType)->name() );
00342 #endif
00343
00344 ShBasicBlock::ShStmtList::iterator afterI = I;
00345 ++afterI;
00346
00347 ShValueType tempValueType = opDest;
00348 if(m_valueTypeMap.count(tempValueType) > 0) tempValueType = m_valueTypeMap[tempValueType];
00349 ShVariable temp(stmt.dest.node()->clone(SH_TEMP, stmt.dest.size(), tempValueType, SH_SEMANTICTYPE_END, false, false));
00350
00351 ShVariableNodePtr varNode = stmt.dest.node();
00352 if(m_converts.count(varNode) > 0) varNode = m_converts[varNode];
00353 ShVariable newdest(varNode, stmt.dest.swizzle(), stmt.dest.neg());
00354
00355
00356 unsigned int forcedOps = 0;
00357 if((stmt.op == SH_OP_DIV || stmt.op == SH_OP_POW) &&
00358 (isInt(destValueType) || isUint(destValueType))) {
00359 forcedOps |= APPLY_FLR;
00360 }
00361
00362 insertConversion(stmtList, afterI, temp, opDest, newdest, destValueType, forcedOps);
00363
00364 stmt.dest = temp;
00365 }
00366
00367 if(texInfo) delete texInfo;
00368 }
00369
00370
00371 void operator()(const ShVariableNodePtr &p) {
00372
00373 if(m_converts.count(p) > 0) return;
00374 if(m_valueTypeMap.count(p->valueType()) == 0) return;
00375 ShVariableNodePtr &converted_p = m_converts[p]
00376 = p->clone(SH_BINDINGTYPE_END, 0, m_valueTypeMap[p->valueType()], SH_SEMANTICTYPE_END, false);
00377
00378 if(p->hasValues()) {
00379 converted_p->setVariant(p->getVariant());
00380
00381 #ifdef SH_DEBUG_TYPECONVERT
00382 SH_DEBUG_PRINT("Setting values on replacement = " << converted_p->getVariant()->encode() << " original = " << p->getVariant()->encode());
00383 #endif
00384 }
00385
00386 if(p->uniform()) {
00387 ShProgram prg = SH_BEGIN_PROGRAM("uniform") {
00388 ShVariable original(p);
00389 ShVariable converted(converted_p);
00390 shASN(converted, original);
00391 } SH_END;
00392 converted_p->attach(prg.node());
00393 }
00394
00395 #ifdef SH_DEBUG_TYPECONVERT
00396 SH_DEBUG_PRINT("Converting " << p->name() << " from " << shTypeInfo(p->valueType())->name()
00397 << " to " << shTypeInfo(m_valueTypeMap[p->valueType()])->name());
00398 #endif
00399 }
00400
00401
00402 ShTransformer::ValueTypeMap &m_valueTypeMap;
00403 ShVarMap &m_converts;
00404
00405 private:
00406 ShEval* m_eval;
00407 };
00408
00409 void ShTransformer::convertToFloat(ValueTypeMap &valueTypeMap)
00410 {
00411 ShVarMap converts;
00412 FloatConverter floatconv(valueTypeMap, converts);
00413
00414
00415 m_program->collectVariables();
00416 std::for_each(m_program->inputs.begin(), m_program->inputs.end(), floatconv);
00417 std::for_each(m_program->outputs.begin(), m_program->outputs.end(), floatconv);
00418 std::for_each(m_program->temps.begin(), m_program->temps.end(), floatconv);
00419 std::for_each(m_program->constants.begin(), m_program->constants.end(), floatconv);
00420 std::for_each(m_program->uniforms.begin(), m_program->uniforms.end(), floatconv);
00421
00422
00423 m_program->ctrlGraph->dfs(floatconv);
00424
00425
00426 ShVariableReplacer vr(converts);
00427 m_program->ctrlGraph->dfs(vr);
00428 vr(m_program->inputs);
00429 vr(m_program->outputs);
00430
00431 if(!converts.empty()) m_changed = true;
00432 }
00433
00434 }
00435