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