Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

Gcc.cpp

00001 // Sh: A GPU metaprogramming language. 00002 // 00003 // Copyright (c) 2003 University of Waterloo Computer Graphics Laboratory 00004 // Project administrator: Michael D. McCool 00005 // Authors: Zheng Qin, Stefanus Du Toit, Kevin Moule, Tiberiu S. Popa, 00006 // Michael D. McCool 00007 // 00008 // This software is provided 'as-is', without any express or implied 00009 // warranty. In no event will the authors be held liable for any damages 00010 // arising from the use of this software. 00011 // 00012 // Permission is granted to anyone to use this software for any purpose, 00013 // including commercial applications, and to alter it and redistribute it 00014 // freely, subject to the following restrictions: 00015 // 00016 // 1. The origin of this software must not be misrepresented; you must 00017 // not claim that you wrote the original software. If you use this 00018 // software in a product, an acknowledgment in the product documentation 00019 // would be appreciated but is not required. 00020 // 00021 // 2. Altered source versions must be plainly marked as such, and must 00022 // not be misrepresented as being the original software. 00023 // 00024 // 3. This notice may not be removed or altered from any source 00025 // distribution. 00027 #include <dlfcn.h> 00028 #include <unistd.h> 00029 #include <sys/wait.h> 00030 00031 #include "Gcc.hpp" 00032 #include "ShDebug.hpp" 00033 #include "ShStream.hpp" 00034 00035 #ifdef HAVE_CONFIG_H 00036 #include "config.h" 00037 #endif 00038 00039 #ifdef SH_GCC_DEBUG 00040 # define SH_GCC_DEBUG_PRINT(x) SH_DEBUG_PRINT(x) 00041 #else 00042 # define SH_GCC_DEBUG_PRINT(x) do { } while(0) 00043 #endif 00044 00045 void sh_gcc_backend_lookup1D(SH::ShTextureNode* tex, float* src, float* dst) 00046 { 00047 if (tex->traits().filtering() == SH::ShTextureTraits::SH_FILTER_MIPMAP) 00048 { 00049 SH_GCC_DEBUG_PRINT("1D/SH_FILTER_MIPMAP textures unsupported..."); 00050 return; 00051 } 00052 00053 SH::ShHostStoragePtr storage = SH::shref_dynamic_cast<SH::ShHostStorage>(tex->memory()->findStorage("host")); 00054 if (!storage) 00055 { 00056 SH_GCC_DEBUG_PRINT("failed to find host storage..."); 00057 } 00058 float* data = (float*)storage->data(); 00059 00060 switch(tex->traits().interpolation()) 00061 { 00062 case 0: 00063 { 00064 // nearest neighbour 00065 float s = src[0]; 00066 switch(tex->traits().wrapping()) 00067 { 00068 case SH::ShTextureTraits::SH_WRAP_CLAMP: 00069 case SH::ShTextureTraits::SH_WRAP_CLAMP_TO_EDGE: 00070 s = std::max((float)0, std::min((float)1, s)); 00071 break; 00072 case SH::ShTextureTraits::SH_WRAP_REPEAT: 00073 s = s - floor(s); 00074 break; 00075 } 00076 00077 int u = (int)floor(tex->width()*s); 00078 u = std::max(0, std::min(tex->width()-1, u)); 00079 00080 switch(tex->traits().clamping()) 00081 { 00082 case SH::ShTextureTraits::SH_CLAMPED: 00083 for(int i = 0; i < tex->size(); i++) 00084 { 00085 dst[i] = std::max((float)0, std::min((float)1, data[tex->size()*u + i])); 00086 } 00087 break; 00088 case SH::ShTextureTraits::SH_UNCLAMPED: 00089 for(int i = 0; i < tex->size(); i++) 00090 { 00091 dst[i] = data[tex->size()*u + i]; 00092 } 00093 break; 00094 } 00095 break; 00096 } 00097 case 1: 00098 // linear interpolation 00099 SH_GCC_DEBUG_PRINT("1D/LINEAR textures unsupported..."); 00100 break; 00101 } 00102 } 00103 00104 void sh_gcc_backend_lookup2D(SH::ShTextureNode* tex, float* src, float* dst) 00105 { 00106 if (tex->traits().filtering() == SH::ShTextureTraits::SH_FILTER_MIPMAP) 00107 { 00108 SH_GCC_DEBUG_PRINT("2D/SH_FILTER_MIPMAP textures unsupported..."); 00109 return; 00110 } 00111 00112 SH::ShHostStoragePtr storage = SH::shref_dynamic_cast<SH::ShHostStorage>(tex->memory()->findStorage("host")); 00113 if (!storage) 00114 { 00115 SH_GCC_DEBUG_PRINT("failed to find host storage..."); 00116 } 00117 float* data = (float*)storage->data(); 00118 00119 switch(tex->traits().interpolation()) 00120 { 00121 case 0: 00122 { 00123 // nearest neighbour 00124 float s = src[0]; 00125 switch(tex->traits().wrapping()) 00126 { 00127 case SH::ShTextureTraits::SH_WRAP_CLAMP: 00128 case SH::ShTextureTraits::SH_WRAP_CLAMP_TO_EDGE: 00129 s = std::max((float)0, std::min((float)1, s)); 00130 break; 00131 case SH::ShTextureTraits::SH_WRAP_REPEAT: 00132 s = s - floor(s); 00133 break; 00134 } 00135 00136 float t = src[1]; 00137 switch(tex->traits().wrapping()) 00138 { 00139 case SH::ShTextureTraits::SH_WRAP_CLAMP: 00140 case SH::ShTextureTraits::SH_WRAP_CLAMP_TO_EDGE: 00141 t = std::max((float)0, std::min((float)1, t)); 00142 break; 00143 case SH::ShTextureTraits::SH_WRAP_REPEAT: 00144 t = t - floor(t); 00145 break; 00146 } 00147 00148 int u = (int)floor(tex->width()*s); 00149 u = std::max(0, std::min(tex->width()-1, u)); 00150 00151 int v = (int)floor(tex->width()*t); 00152 v = std::max(0, std::min(tex->height()-1, v)); 00153 00154 int offset = v*tex->width()+u; 00155 00156 switch(tex->traits().clamping()) 00157 { 00158 case SH::ShTextureTraits::SH_CLAMPED: 00159 for(int i = 0; i < tex->size(); i++) 00160 { 00161 dst[i] = std::max((float)0, std::min((float)1, data[tex->size()*offset + i])); 00162 } 00163 break; 00164 case SH::ShTextureTraits::SH_UNCLAMPED: 00165 for(int i = 0; i < tex->size(); i++) 00166 { 00167 dst[i] = data[tex->size()*offset + i]; 00168 } 00169 break; 00170 } 00171 break; 00172 } 00173 case 1: 00174 // linear interpolation 00175 SH_GCC_DEBUG_PRINT("2D/LINEAR textures unsupported..."); 00176 break; 00177 } 00178 } 00179 00180 void sh_gcc_backend_lookupRECT(SH::ShTextureNode* tex, float* src, float* dst) 00181 { 00182 if (tex->traits().filtering() == SH::ShTextureTraits::SH_FILTER_MIPMAP) 00183 { 00184 SH_GCC_DEBUG_PRINT("RECT/SH_FILTER_MIPMAP textures unsupported..."); 00185 return; 00186 } 00187 00188 SH::ShHostStoragePtr storage = SH::shref_dynamic_cast<SH::ShHostStorage>(tex->memory()->findStorage("host")); 00189 if (!storage) 00190 { 00191 SH_GCC_DEBUG_PRINT("failed to find host storage..."); 00192 } 00193 float* data = (float*)storage->data(); 00194 00195 switch(tex->traits().interpolation()) 00196 { 00197 case 0: 00198 { 00199 // nearest neighbour 00200 float s = src[0]; 00201 switch(tex->traits().wrapping()) 00202 { 00203 case SH::ShTextureTraits::SH_WRAP_CLAMP: 00204 case SH::ShTextureTraits::SH_WRAP_CLAMP_TO_EDGE: 00205 s = std::max((float)0, std::min((float)1, s)); 00206 break; 00207 case SH::ShTextureTraits::SH_WRAP_REPEAT: 00208 s = s - floor(s); 00209 break; 00210 } 00211 00212 float t = src[1]; 00213 switch(tex->traits().wrapping()) 00214 { 00215 case SH::ShTextureTraits::SH_WRAP_CLAMP: 00216 case SH::ShTextureTraits::SH_WRAP_CLAMP_TO_EDGE: 00217 t = std::max((float)0, std::min((float)1, t)); 00218 break; 00219 case SH::ShTextureTraits::SH_WRAP_REPEAT: 00220 t = t - floor(t); 00221 break; 00222 } 00223 00224 int u = (int)floor(tex->width()*s); 00225 u = std::max(0, std::min(tex->width()-1, u)); 00226 00227 int v = (int)floor(tex->width()*t); 00228 v = std::max(0, std::min(tex->height()-1, v)); 00229 00230 int offset = v*tex->width()+u; 00231 00232 switch(tex->traits().clamping()) 00233 { 00234 case SH::ShTextureTraits::SH_CLAMPED: 00235 for(int i = 0; i < tex->size(); i++) 00236 { 00237 dst[i] = std::max((float)0, std::min((float)1, data[tex->size()*offset + i])); 00238 } 00239 break; 00240 case SH::ShTextureTraits::SH_UNCLAMPED: 00241 for(int i = 0; i < tex->size(); i++) 00242 { 00243 dst[i] = data[tex->size()*offset + i]; 00244 } 00245 break; 00246 } 00247 break; 00248 } 00249 case 1: 00250 // linear interpolation 00251 SH_GCC_DEBUG_PRINT("RECT/LINEAR textures unsupported..."); 00252 break; 00253 } 00254 } 00255 00256 void sh_gcc_backend_lookup3D(SH::ShTextureNode* tex, float* src, float* dst) 00257 { 00258 SH_GCC_DEBUG_PRINT("3D textures unsupported..."); 00259 } 00260 00261 void sh_gcc_backend_lookupCUBE(SH::ShTextureNode* tex, float* src, float* dst) 00262 { 00263 SH_GCC_DEBUG_PRINT("CUBE textures unsupported..."); 00264 } 00265 00266 extern "C" void sh_gcc_backend_lookup(void *t, float* src, float* dst) 00267 { 00268 // [0, 1) float based texture lookup 00269 SH::ShTextureNode* tex = (SH::ShTextureNode*)t; 00270 00271 switch(tex->dims()) 00272 { 00273 case SH::SH_TEXTURE_1D: 00274 sh_gcc_backend_lookup1D(tex, src, dst); 00275 break; 00276 case SH::SH_TEXTURE_2D: 00277 sh_gcc_backend_lookup2D(tex, src, dst); 00278 break; 00279 case SH::SH_TEXTURE_RECT: 00280 sh_gcc_backend_lookupRECT(tex, src, dst); 00281 break; 00282 case SH::SH_TEXTURE_3D: 00283 sh_gcc_backend_lookup3D(tex, src, dst); 00284 break; 00285 case SH::SH_TEXTURE_CUBE: 00286 sh_gcc_backend_lookupCUBE(tex, src, dst); 00287 break; 00288 default: 00289 SH_GCC_DEBUG_PRINT("unknown texture dimension (" << tex->dims() << ")"); 00290 break; 00291 } 00292 } 00293 00294 void sh_gcc_backend_lookupi1D(SH::ShTextureNode* tex, float* src, float* dst) 00295 { 00296 if (tex->traits().filtering() == SH::ShTextureTraits::SH_FILTER_MIPMAP) 00297 { 00298 SH_GCC_DEBUG_PRINT("1D/SH_FILTER_MIPMAP textures unsupported..."); 00299 return; 00300 } 00301 00302 SH::ShHostStoragePtr storage = SH::shref_dynamic_cast<SH::ShHostStorage>(tex->memory()->findStorage("host")); 00303 if (!storage) 00304 { 00305 SH_GCC_DEBUG_PRINT("failed to find host storage..."); 00306 } 00307 float* data = (float*)storage->data(); 00308 00309 switch(tex->traits().interpolation()) 00310 { 00311 case 0: 00312 { 00313 // nearest neighbour 00314 float s = src[0]; 00315 switch(tex->traits().wrapping()) 00316 { 00317 case SH::ShTextureTraits::SH_WRAP_CLAMP: 00318 case SH::ShTextureTraits::SH_WRAP_CLAMP_TO_EDGE: 00319 s = std::max((float)0, std::min((float)tex->width(), s)); 00320 break; 00321 case SH::ShTextureTraits::SH_WRAP_REPEAT: 00322 s = tex->width()*(s/tex->width() - floor(s/tex->width())); 00323 break; 00324 } 00325 00326 int u = (int)floor(s); 00327 u = std::max(0, std::min(tex->width()-1, u)); 00328 00329 switch(tex->traits().clamping()) 00330 { 00331 case SH::ShTextureTraits::SH_CLAMPED: 00332 for(int i = 0; i < tex->size(); i++) 00333 { 00334 dst[i] = std::max((float)0, std::min((float)1, data[tex->size()*u + i])); 00335 } 00336 break; 00337 case SH::ShTextureTraits::SH_UNCLAMPED: 00338 for(int i = 0; i < tex->size(); i++) 00339 { 00340 dst[i] = data[tex->size()*u + i]; 00341 } 00342 break; 00343 } 00344 break; 00345 } 00346 case 1: 00347 // linear interpolation 00348 SH_GCC_DEBUG_PRINT("1D/LINEAR textures unsupported..."); 00349 break; 00350 } 00351 } 00352 00353 void sh_gcc_backend_lookupi2D(SH::ShTextureNode* tex, float* src, float* dst) 00354 { 00355 if (tex->traits().filtering() == SH::ShTextureTraits::SH_FILTER_MIPMAP) 00356 { 00357 SH_GCC_DEBUG_PRINT("2D/SH_FILTER_MIPMAP textures unsupported..."); 00358 return; 00359 } 00360 00361 SH::ShHostStoragePtr storage = SH::shref_dynamic_cast<SH::ShHostStorage>(tex->memory()->findStorage("host")); 00362 if (!storage) 00363 { 00364 SH_GCC_DEBUG_PRINT("failed to find host storage..."); 00365 } 00366 float* data = (float*)storage->data(); 00367 00368 switch(tex->traits().interpolation()) 00369 { 00370 case 0: 00371 { 00372 // nearest neighbour 00373 float s = src[0]; 00374 switch(tex->traits().wrapping()) 00375 { 00376 case SH::ShTextureTraits::SH_WRAP_CLAMP: 00377 case SH::ShTextureTraits::SH_WRAP_CLAMP_TO_EDGE: 00378 s = std::max((float)0, std::min((float)tex->width(), s)); 00379 break; 00380 case SH::ShTextureTraits::SH_WRAP_REPEAT: 00381 s = tex->width()*(s/tex->width() - floor(s/tex->width())); 00382 break; 00383 } 00384 00385 float t = src[1]; 00386 switch(tex->traits().wrapping()) 00387 { 00388 case SH::ShTextureTraits::SH_WRAP_CLAMP: 00389 case SH::ShTextureTraits::SH_WRAP_CLAMP_TO_EDGE: 00390 t = std::max((float)0, std::min((float)tex->height(), t)); 00391 break; 00392 case SH::ShTextureTraits::SH_WRAP_REPEAT: 00393 t = tex->height()*(t/tex->height() - floor(t/tex->height())); 00394 break; 00395 } 00396 00397 int u = (int)floor(s); 00398 u = std::max(0, std::min(tex->width()-1, u)); 00399 00400 int v = (int)floor(t); 00401 v = std::max(0, std::min(tex->height()-1, v)); 00402 00403 int offset = v*tex->width()+u; 00404 00405 switch(tex->traits().clamping()) 00406 { 00407 case SH::ShTextureTraits::SH_CLAMPED: 00408 for(int i = 0; i < tex->size(); i++) 00409 { 00410 dst[i] = std::max((float)0, std::min((float)1, data[tex->size()*offset + i])); 00411 } 00412 break; 00413 case SH::ShTextureTraits::SH_UNCLAMPED: 00414 for(int i = 0; i < tex->size(); i++) 00415 { 00416 dst[i] = data[tex->size()*offset + i]; 00417 } 00418 break; 00419 } 00420 break; 00421 } 00422 case 1: 00423 // linear interpolation 00424 SH_GCC_DEBUG_PRINT("2D/LINEAR textures unsupported..."); 00425 break; 00426 } 00427 } 00428 00429 void sh_gcc_backend_lookupiRECT(SH::ShTextureNode* tex, float* src, float* dst) 00430 { 00431 if (tex->traits().filtering() == SH::ShTextureTraits::SH_FILTER_MIPMAP) 00432 { 00433 SH_GCC_DEBUG_PRINT("RECT/SH_FILTER_MIPMAP textures unsupported..."); 00434 return; 00435 } 00436 00437 SH::ShHostStoragePtr storage = SH::shref_dynamic_cast<SH::ShHostStorage>(tex->memory()->findStorage("host")); 00438 if (!storage) 00439 { 00440 SH_GCC_DEBUG_PRINT("failed to find host storage..."); 00441 } 00442 float* data = (float*)storage->data(); 00443 00444 switch(tex->traits().interpolation()) 00445 { 00446 case 0: 00447 { 00448 // nearest neighbour 00449 float s = src[0]; 00450 switch(tex->traits().wrapping()) 00451 { 00452 case SH::ShTextureTraits::SH_WRAP_CLAMP: 00453 case SH::ShTextureTraits::SH_WRAP_CLAMP_TO_EDGE: 00454 s = std::max((float)0, std::min((float)tex->width(), s)); 00455 break; 00456 case SH::ShTextureTraits::SH_WRAP_REPEAT: 00457 s = tex->width()*(s/tex->width() - floor(s/tex->width())); 00458 break; 00459 } 00460 00461 float t = src[1]; 00462 switch(tex->traits().wrapping()) 00463 { 00464 case SH::ShTextureTraits::SH_WRAP_CLAMP: 00465 case SH::ShTextureTraits::SH_WRAP_CLAMP_TO_EDGE: 00466 t = std::max((float)0, std::min((float)tex->height(), t)); 00467 break; 00468 case SH::ShTextureTraits::SH_WRAP_REPEAT: 00469 t = tex->height()*(t/tex->height() - floor(t/tex->height())); 00470 break; 00471 } 00472 00473 int u = (int)floor(s); 00474 u = std::max(0, std::min(tex->width()-1, u)); 00475 00476 int v = (int)floor(t); 00477 v = std::max(0, std::min(tex->height()-1, v)); 00478 00479 int offset = v*tex->width()+u; 00480 00481 switch(tex->traits().clamping()) 00482 { 00483 case SH::ShTextureTraits::SH_CLAMPED: 00484 for(int i = 0; i < tex->size(); i++) 00485 { 00486 dst[i] = std::max((float)0, std::min((float)1, data[tex->size()*offset + i])); 00487 } 00488 break; 00489 case SH::ShTextureTraits::SH_UNCLAMPED: 00490 for(int i = 0; i < tex->size(); i++) 00491 { 00492 dst[i] = data[tex->size()*offset + i]; 00493 } 00494 break; 00495 } 00496 break; 00497 } 00498 case 1: 00499 // linear interpolation 00500 SH_GCC_DEBUG_PRINT("RECT/LINEAR textures unsupported..."); 00501 break; 00502 } 00503 } 00504 00505 void sh_gcc_backend_lookupi3D(SH::ShTextureNode* tex, float* src, float* dst) 00506 { 00507 SH_GCC_DEBUG_PRINT("3D textures unsupported..."); 00508 } 00509 00510 void sh_gcc_backend_lookupiCUBE(SH::ShTextureNode* tex, float* src, float* dst) 00511 { 00512 SH_GCC_DEBUG_PRINT("CUBE textures unsupported..."); 00513 } 00514 00515 extern "C" void sh_gcc_backend_lookupi(void* t, float* src, float* dst) 00516 { 00517 // [0, size] integer based texture lookup 00518 SH::ShTextureNode* tex = (SH::ShTextureNode*)t; 00519 00520 switch(tex->dims()) 00521 { 00522 case SH::SH_TEXTURE_1D: 00523 sh_gcc_backend_lookupi1D(tex, src, dst); 00524 break; 00525 case SH::SH_TEXTURE_2D: 00526 sh_gcc_backend_lookupi2D(tex, src, dst); 00527 break; 00528 case SH::SH_TEXTURE_RECT: 00529 sh_gcc_backend_lookupiRECT(tex, src, dst); 00530 break; 00531 case SH::SH_TEXTURE_3D: 00532 sh_gcc_backend_lookupi3D(tex, src, dst); 00533 break; 00534 case SH::SH_TEXTURE_CUBE: 00535 sh_gcc_backend_lookupiCUBE(tex, src, dst); 00536 break; 00537 default: 00538 SH_GCC_DEBUG_PRINT("unknown texture dimension (" << tex->dims() << ")"); 00539 break; 00540 } 00541 } 00542 00543 std::string encode(const SH::ShVariable& v) 00544 { 00545 std::stringstream ret; 00546 if (v.neg()) ret << "-"; 00547 ret << v.name(); 00548 ret << v.swizzle(); 00549 return ret.str(); 00550 } 00551 00552 namespace ShGcc { 00553 00554 GccVariable::GccVariable(void) : 00555 m_num(-1), 00556 m_size(-1) 00557 { 00558 } 00559 00560 GccVariable::GccVariable(int num, const std::string& name) : 00561 m_num(num), 00562 m_name(name), 00563 m_size(-1) 00564 { 00565 } 00566 00567 GccVariable::GccVariable(int num, const std::string& name, int size) : 00568 m_num(num), 00569 m_name(name), 00570 m_size(size) 00571 { 00572 } 00573 00574 GccBackendCode::LabelFunctor::LabelFunctor(std::map<SH::ShCtrlGraphNodePtr, int>& label_map) : 00575 m_cur_label(0), 00576 m_label_map(label_map) 00577 { 00578 } 00579 00580 void GccBackendCode::LabelFunctor::operator()(SH::ShCtrlGraphNode* node) 00581 { 00582 m_label_map[node] = m_cur_label++; 00583 } 00584 00585 GccBackendCode::EmitFunctor::EmitFunctor(GccBackendCode* bec) : 00586 m_bec(bec) 00587 { 00588 } 00589 00590 void GccBackendCode::EmitFunctor::operator()(SH::ShCtrlGraphNode* node) 00591 { 00592 m_bec->emit(node); 00593 } 00594 00595 GccBackendCode::GccBackendCode(const SH::ShProgramNodeCPtr& program) : 00596 m_program(program), 00597 m_handle(NULL), 00598 m_func(NULL), 00599 m_cur_temp(0), 00600 m_params(NULL) 00601 { 00602 SH_GCC_DEBUG_PRINT(__FUNCTION__); 00603 } 00604 00605 GccBackendCode::~GccBackendCode(void) 00606 { 00607 SH_GCC_DEBUG_PRINT(__FUNCTION__); 00608 } 00609 00610 bool GccBackendCode::allocateRegister(const SH::ShVariableNodePtr& var) 00611 { 00612 SH_GCC_DEBUG_PRINT(__FUNCTION__); 00613 return false; 00614 } 00615 00616 void GccBackendCode::freeRegister(const SH::ShVariableNodePtr& var) 00617 { 00618 SH_GCC_DEBUG_PRINT(__FUNCTION__); 00619 } 00620 00621 void GccBackendCode::upload(void) 00622 { 00623 SH_GCC_DEBUG_PRINT(__FUNCTION__); 00624 } 00625 00626 void GccBackendCode::bind(void) 00627 { 00628 SH_GCC_DEBUG_PRINT(__FUNCTION__); 00629 } 00630 00631 void GccBackendCode::updateUniform(const SH::ShVariableNodePtr& uniform) 00632 { 00633 SH_GCC_DEBUG_PRINT(__FUNCTION__); 00634 } 00635 00636 std::ostream& GccBackendCode::print(std::ostream& out) 00637 { 00638 SH_GCC_DEBUG_PRINT(__FUNCTION__); 00639 return out; 00640 } 00641 00642 std::ostream& GccBackendCode::printInputOutputFormat(std::ostream& out) 00643 { 00644 SH_GCC_DEBUG_PRINT(__FUNCTION__); 00645 return out; 00646 } 00647 00648 void GccBackendCode::allocate_consts(void) 00649 { 00650 int cur_const = 0; 00651 for (SH::ShProgramNode::VarList::const_iterator itr = m_program->constants.begin(); 00652 itr != m_program->constants.end(); 00653 itr++) 00654 { 00655 SH::ShVariableNodePtr node = (*itr); 00656 00657 // allocate internal variable as constant 00658 char name[128]; 00659 sprintf(name, "var_c_%d", cur_const); 00660 m_varmap[node] = GccVariable(cur_const++, name); 00661 00662 // output constant definition 00663 m_code << "float " << name << "[" << node->size() << "] = {"; 00664 for (int i = 0; i < node->size(); i++) 00665 { 00666 if (i == 0) 00667 m_code << node->getValue(i); 00668 else 00669 m_code << ", " << node->getValue(i); 00670 } 00671 m_code << "};" << std::endl; 00672 } 00673 00674 SH_GCC_DEBUG_PRINT("Found " << cur_const << " consts..."); 00675 } 00676 00677 void GccBackendCode::allocate_inputs(void) 00678 { 00679 int cur_input = 0; 00680 for (SH::ShProgramNode::VarList::const_iterator itr = m_program->inputs.begin(); 00681 itr != m_program->inputs.end(); 00682 itr++) 00683 { 00684 SH::ShVariableNodePtr node = (*itr); 00685 00686 // allocate internal variable as attribute 00687 char name[128]; 00688 sprintf(name, "inputs[%d]", cur_input); 00689 m_varmap[node] = GccVariable(cur_input++, name); 00690 } 00691 00692 SH_GCC_DEBUG_PRINT("Found " << cur_input << " inputs..."); 00693 } 00694 00695 void GccBackendCode::allocate_outputs(void) 00696 { 00697 int cur_output = 0; 00698 for (SH::ShProgramNode::VarList::const_iterator itr = m_program->outputs.begin(); 00699 itr != m_program->outputs.end(); 00700 itr++) 00701 { 00702 SH::ShVariableNodePtr node = (*itr); 00703 00704 // allocate internal variable as attribute 00705 char name[128]; 00706 sprintf(name, "outputs[%d]", cur_output); 00707 m_varmap[node] = GccVariable(cur_output++, name); 00708 } 00709 00710 SH_GCC_DEBUG_PRINT("Found " << cur_output << " outputs..."); 00711 } 00712 00713 void GccBackendCode::allocate_streams(void) 00714 { 00715 int cur_stream = 0; 00716 for (SH::ShProgramNode::ChannelList::const_iterator itr = m_program->channels.begin(); 00717 itr != m_program->channels.end(); 00718 itr++) 00719 { 00720 SH::ShChannelNodePtr node = (*itr); 00721 00722 // allocate internal variable as stream 00723 char name[128]; 00724 sprintf(name, "streams[%d]", cur_stream); 00725 m_varmap[node] = GccVariable(cur_stream++, name); 00726 m_streams.push_back(node); 00727 } 00728 00729 SH_GCC_DEBUG_PRINT("Found " << cur_stream << " streams..."); 00730 } 00731 00732 void GccBackendCode::allocate_textures(void) 00733 { 00734 int cur_texture = 0; 00735 for (SH::ShProgramNode::TexList::const_iterator itr = m_program->textures.begin(); 00736 itr != m_program->textures.end(); 00737 itr++) 00738 { 00739 SH::ShTextureNodePtr node = (*itr); 00740 00741 // allocate internal variable as texture 00742 char name[128]; 00743 sprintf(name, "textures[%d]", cur_texture); 00744 m_varmap[node] = GccVariable(cur_texture++, name); 00745 m_textures.push_back(node); 00746 } 00747 00748 SH_GCC_DEBUG_PRINT("Found " << cur_texture << " textures..."); 00749 } 00750 00751 void GccBackendCode::allocate_uniforms(void) 00752 { 00753 int cur_uniform = 0; 00754 std::vector<SH::ShVariableNodePtr> uniforms; 00755 00756 for (SH::ShProgramNode::VarList::const_iterator itr = m_program->uniforms.begin(); 00757 itr != m_program->uniforms.end(); 00758 itr++) 00759 { 00760 SH::ShVariableNodePtr node = (*itr); 00761 00762 // allocate internal variable as parameter 00763 char name[128]; 00764 sprintf(name, "params[%d]", cur_uniform); 00765 m_varmap[node] = GccVariable(cur_uniform++, name); 00766 uniforms.push_back(node); 00767 } 00768 00769 m_params = new float*[uniforms.size()]; 00770 for(unsigned int i = 0; i < uniforms.size(); i++) 00771 { 00772 SH::ShVariableNodePtr node = uniforms[i]; 00773 m_params[i] = new float[node->size()]; 00774 00775 if (node->hasValues()) 00776 { 00777 for(int j = 0; j < node->size(); j++) 00778 { 00779 m_params[i][j] = node->getValue(j); 00780 } 00781 } 00782 else 00783 { 00784 for(int j = 0; j < node->size(); j++) 00785 { 00786 m_params[i][j] = 0; 00787 } 00788 } 00789 } 00790 00791 SH_GCC_DEBUG_PRINT("Found " << cur_uniform << " uniforms..."); 00792 } 00793 00794 std::string GccBackendCode::resolve(const SH::ShVariable& v) 00795 { 00796 GccVariable v2; 00797 std::map<SH::ShVariableNodePtr, GccVariable>::iterator itr = m_varmap.find(v.node()); 00798 00799 if (itr == m_varmap.end()) 00800 { 00801 // not defined yet, it had better be a temp... 00802 SH_DEBUG_ASSERT(v.node()->kind() == SH::SH_TEMP); 00803 00804 // allocate internal variable as temp 00805 char name[128]; 00806 sprintf(name, "var_t_%d", m_cur_temp); 00807 v2 = GccVariable(m_cur_temp++, name, v.node()->size()); 00808 m_varmap[v.node()] = v2; 00809 m_temps.push_back(v2); 00810 } 00811 else 00812 { 00813 v2 = (*itr).second; 00814 } 00815 00816 std::stringstream buf; 00817 if (v.neg()) buf << "-"; 00818 buf << v2.m_name; 00819 return buf.str(); 00820 } 00821 00822 std::string GccBackendCode::resolve(const SH::ShVariable& v, int idx) 00823 { 00824 GccVariable v2; 00825 std::map<SH::ShVariableNodePtr, GccVariable>::iterator itr = m_varmap.find(v.node()); 00826 00827 if (itr == m_varmap.end()) 00828 { 00829 // not defined yet, it had better be a temp... 00830 SH_DEBUG_ASSERT(v.node()->kind() == SH::SH_TEMP); 00831 00832 // allocate internal variable as temp 00833 char name[128]; 00834 sprintf(name, "var_t_%d", m_cur_temp); 00835 v2 = GccVariable(m_cur_temp++, name, v.node()->size()); 00836 m_varmap[v.node()] = v2; 00837 m_temps.push_back(v2); 00838 } 00839 else 00840 { 00841 v2 = (*itr).second; 00842 } 00843 00844 std::stringstream buf; 00845 if (v.neg()) buf << "-"; 00846 buf << v2.m_name; 00847 buf << "[" << v.swizzle()[idx] << "]"; 00848 return buf.str(); 00849 } 00850 00851 void GccBackendCode::emit(const SH::ShStatement& stmt) 00852 { 00853 // output SH intermediate m_code for reference 00854 switch(SH::opInfo[stmt.op].arity) 00855 { 00856 case 0: 00857 m_code << " // " 00858 << SH::opInfo[stmt.op].name << " " 00859 << encode(stmt.dest) 00860 << std::endl; 00861 break; 00862 case 1: 00863 m_code << " // " 00864 << SH::opInfo[stmt.op].name << " " 00865 << encode(stmt.dest) << ", " 00866 << encode(stmt.src[0]) 00867 << std::endl; 00868 break; 00869 case 2: 00870 m_code << " // " 00871 << SH::opInfo[stmt.op].name << " " 00872 << encode(stmt.dest) << ", " 00873 << encode(stmt.src[0]) << ", " 00874 << encode(stmt.src[1]) 00875 << std::endl; 00876 break; 00877 case 3: 00878 m_code << " // " 00879 << SH::opInfo[stmt.op].name << " " 00880 << encode(stmt.dest) << ", " 00881 << encode(stmt.src[0]) << ", " 00882 << encode(stmt.src[1]) << ", " 00883 << encode(stmt.src[2]) 00884 << std::endl; 00885 break; 00886 default: 00887 m_code << " // " 00888 << SH::opInfo[stmt.op].name << " " 00889 << "<unknown format>" 00890 << std::endl; 00891 break; 00892 } 00893 00894 // generate C m_code from statement 00895 switch(stmt.op) 00896 { 00897 case SH::SH_OP_ASN: 00898 { 00899 for(int i = 0; i < stmt.dest.size(); i++) 00900 { 00901 m_code << " " 00902 << resolve(stmt.dest, i) 00903 << " = " 00904 << resolve(stmt.src[0], i) 00905 << ";" << std::endl; 00906 } 00907 00908 break; 00909 } 00910 case SH::SH_OP_NEG: 00911 { 00912 for(int i = 0; i < stmt.dest.size(); i++) 00913 { 00914 m_code << " " 00915 << resolve(stmt.dest, i) 00916 << " = -" 00917 << resolve(stmt.src[0], i) 00918 << ";" << std::endl; 00919 } 00920 00921 break; 00922 } 00923 case SH::SH_OP_ADD: 00924 { 00925 for(int i = 0; i < stmt.dest.size(); i++) 00926 { 00927 m_code << " " 00928 << resolve(stmt.dest, i) 00929 << " = " 00930 << resolve(stmt.src[0], (stmt.src[0].size() > 1 ? i : 0)) 00931 << " + " 00932 << resolve(stmt.src[1], (stmt.src[1].size() > 1 ? i : 0)) 00933 << ";" << std::endl; 00934 } 00935 break; 00936 } 00937 case SH::SH_OP_MUL: 00938 { 00939 for(int i = 0; i < stmt.dest.size(); i++) 00940 { 00941 m_code << " " 00942 << resolve(stmt.dest, i) 00943 << " = " 00944 << resolve(stmt.src[0], (stmt.src[0].size() > 1 ? i : 0)) 00945 << " * " 00946 << resolve(stmt.src[1], (stmt.src[1].size() > 1 ? i : 0)) 00947 << ";" << std::endl; 00948 } 00949 break; 00950 } 00951 case SH::SH_OP_DIV: 00952 { 00953 for(int i = 0; i < stmt.dest.size(); i++) 00954 { 00955 m_code << " " 00956 << resolve(stmt.dest, i) 00957 << " = " 00958 << resolve(stmt.src[0], (stmt.src[0].size() > 1 ? i : 0)) 00959 << " / " 00960 << resolve(stmt.src[1], (stmt.src[1].size() > 1 ? i : 0)) 00961 << ";" << std::endl; 00962 } 00963 break; 00964 } 00965 case SH::SH_OP_SLT: 00966 { 00967 bool scalar0 = (stmt.src[0].size() == 1); 00968 bool scalar1 = (stmt.src[1].size() == 1); 00969 for(int i = 0; i < stmt.dest.size(); i++) 00970 { 00971 m_code << " " 00972 << resolve(stmt.dest, i) 00973 << " = (" 00974 << resolve(stmt.src[0], (scalar0 ? 0 : i)) 00975 << " < " 00976 << resolve(stmt.src[1], (scalar1 ? 0 : i)) 00977 << " ? 1.0f : 0.0f)" 00978 << ";" 00979 << std::endl; 00980 } 00981 break; 00982 } 00983 case SH::SH_OP_SLE: 00984 { 00985 bool scalar0 = (stmt.src[0].size() == 1); 00986 bool scalar1 = (stmt.src[1].size() == 1); 00987 for(int i = 0; i < stmt.dest.size(); i++) 00988 { 00989 m_code << " " 00990 << resolve(stmt.dest, i) 00991 << " = (" 00992 << resolve(stmt.src[0], (scalar0 ? 0 : i)) 00993 << " <= " 00994 << resolve(stmt.src[1], (scalar1 ? 0 : i)) 00995 << " ? 1.0f : 0.0f)" 00996 << ";" 00997 << std::endl; 00998 } 00999 break; 01000 } 01001 case SH::SH_OP_SGT: 01002 { 01003 bool scalar0 = (stmt.src[0].size() == 1); 01004 bool scalar1 = (stmt.src[1].size() == 1); 01005 for(int i = 0; i < stmt.dest.size(); i++) 01006 { 01007 m_code << " " 01008 << resolve(stmt.dest, i) 01009 << " = (" 01010 << resolve(stmt.src[0], (scalar0 ? 0 : i)) 01011 << " > " 01012 << resolve(stmt.src[1], (scalar1 ? 0 : i)) 01013 << " ? 1.0f : 0.0f)" 01014 << ";" 01015 << std::endl; 01016 } 01017 break; 01018 } 01019 case SH::SH_OP_SGE: 01020 { 01021 bool scalar0 = (stmt.src[0].size() == 1); 01022 bool scalar1 = (stmt.src[1].size() == 1); 01023 for(int i = 0; i < stmt.dest.size(); i++) 01024 { 01025 m_code << " " 01026 << resolve(stmt.dest, i) 01027 << " = (" 01028 << resolve(stmt.src[0], (scalar0 ? 0 : i)) 01029 << " >= " 01030 << resolve(stmt.src[1], (scalar1 ? 0 : i)) 01031 << " ? 1.0f : 0.0f)" 01032 << ";" 01033 << std::endl; 01034 } 01035 break; 01036 } 01037 case SH::SH_OP_SEQ: 01038 { 01039 bool scalar0 = (stmt.src[0].size() == 1); 01040 bool scalar1 = (stmt.src[1].size() == 1); 01041 for(int i = 0; i < stmt.dest.size(); i++) 01042 { 01043 m_code << " " 01044 << resolve(stmt.dest, i) 01045 << " = (" 01046 << resolve(stmt.src[0], (scalar0 ? 0 : i)) 01047 << " == " 01048 << resolve(stmt.src[1], (scalar1 ? 0 : i)) 01049 << " ? 1.0f : 0.0f)" 01050 << ";" 01051 << std::endl; 01052 } 01053 break; 01054 } 01055 case SH::SH_OP_SNE: 01056 { 01057 bool scalar0 = (stmt.src[0].size() == 1); 01058 bool scalar1 = (stmt.src[1].size() == 1); 01059 for(int i = 0; i < stmt.dest.size(); i++) 01060 { 01061 m_code << " " 01062 << resolve(stmt.dest, i) 01063 << " = (" 01064 << resolve(stmt.src[0], (scalar0 ? 0 : i)) 01065 << " != " 01066 << resolve(stmt.src[1], (scalar1 ? 0 : i)) 01067 << " ? 1.0f : 0.0f)" 01068 << ";" 01069 << std::endl; 01070 } 01071 break; 01072 } 01073 case SH::SH_OP_ABS: 01074 { 01075 for(int i = 0; i < stmt.dest.size(); i++) 01076 { 01077 m_code << " " 01078 << resolve(stmt.dest, i) 01079 << " = fabs(" 01080 << resolve(stmt.src[0], i) 01081 << ");" << std::endl; 01082 } 01083 01084 break; 01085 } 01086 case SH::SH_OP_ACOS: 01087 { 01088 for(int i = 0; i < stmt.dest.size(); i++) 01089 { 01090 m_code << " " 01091 << resolve(stmt.dest, i) 01092 << " = acos(" 01093 << resolve(stmt.src[0], i) 01094 << ");" << std::endl; 01095 } 01096 01097 break; 01098 } 01099 case SH::SH_OP_ASIN: 01100 { 01101 for(int i = 0; i < stmt.dest.size(); i++) 01102 { 01103 m_code << " " 01104 << resolve(stmt.dest, i) 01105 << " = asin(" 01106 << resolve(stmt.src[0], i) 01107 << ");" << std::endl; 01108 } 01109 01110 break; 01111 } 01112 case SH::SH_OP_ATAN: 01113 { 01114 for(int i = 0; i < stmt.dest.size(); i++) 01115 { 01116 m_code << " " 01117 << resolve(stmt.dest, i) 01118 << " = atan(" 01119 << resolve(stmt.src[0], i) 01120 << ");" << std::endl; 01121 } 01122 01123 break; 01124 } 01125 case SH::SH_OP_ATAN2: 01126 { 01127 for(int i = 0; i < stmt.dest.size(); i++) 01128 { 01129 m_code << " " 01130 << resolve(stmt.dest, i) 01131 << " = atan2(" 01132 << resolve(stmt.src[0], i) 01133 << ", " 01134 << resolve(stmt.src[1], i) 01135 << ");" << std::endl; 01136 } 01137 01138 break; 01139 } 01140 case SH::SH_OP_CEIL: 01141 { 01142 for(int i = 0; i < stmt.dest.size(); i++) 01143 { 01144 m_code << " " 01145 << resolve(stmt.dest, i) 01146 << " = ceil(" 01147 << resolve(stmt.src[0], i) 01148 << ");" << std::endl; 01149 } 01150 01151 break; 01152 } 01153 case SH::SH_OP_COS: 01154 { 01155 for(int i = 0; i < stmt.dest.size(); i++) 01156 { 01157 m_code << " " 01158 << resolve(stmt.dest, i) 01159 << " = cos(" 01160 << resolve(stmt.src[0], i) 01161 << ");" << std::endl; 01162 } 01163 01164 break; 01165 } 01166 case SH::SH_OP_DOT: 01167 { 01168 SH_DEBUG_ASSERT(stmt.dest.size() == 1); 01169 01170 if (stmt.src[0].swizzle().size() == 1) 01171 { 01172 m_code << " " 01173 << resolve(stmt.dest, 0) 01174 << " = "; 01175 for(int i = 0; i < stmt.src[1].size(); i++) 01176 { 01177 if (i != 0) 01178 m_code << " + "; 01179 01180 m_code << "(" 01181 << resolve(stmt.src[0], 0) 01182 << "*" 01183 << resolve(stmt.src[1], i) 01184 << ")"; 01185 } 01186 m_code << ";" << std::endl; 01187 } 01188 else if (stmt.src[1].swizzle().size() == 1) 01189 { 01190 m_code << " " 01191 << resolve(stmt.dest, 0) 01192 << " = "; 01193 for(int i = 0; i < stmt.src[0].size(); i++) 01194 { 01195 if (i != 0) 01196 m_code << " + "; 01197 01198 m_code << "(" 01199 << resolve(stmt.src[0], i) 01200 << "*" 01201 << resolve(stmt.src[1], 0) 01202 << ")"; 01203 } 01204 m_code << ";" << std::endl; 01205 } 01206 else 01207 { 01208 m_code << " " 01209 << resolve(stmt.dest, 0) 01210 << " = "; 01211 for(int i = 0; i < stmt.src[0].size(); i++) 01212 { 01213 if (i != 0) 01214 m_code << " + "; 01215 01216 m_code << "(" 01217 << resolve(stmt.src[0], i) 01218 << "*" 01219 << resolve(stmt.src[1], i) 01220 << ")"; 01221 } 01222 m_code << ";" << std::endl; 01223 } 01224 01225 break; 01226 } 01227 case SH::SH_OP_EXP: 01228 { 01229 for(int i = 0; i < stmt.dest.size(); i++) 01230 { 01231 m_code << " " 01232 << resolve(stmt.dest, i) 01233 << " = exp(" 01234 << resolve(stmt.src[0], i) 01235 << ");" << std::endl; 01236 } 01237 01238 break; 01239 } 01240 case SH::SH_OP_EXP2: 01241 { 01242 for(int i = 0; i < stmt.dest.size(); i++) 01243 { 01244 m_code << " " 01245 << resolve(stmt.dest, i) 01246 << " = exp2(" 01247 << resolve(stmt.src[0], i) 01248 << ");" << std::endl; 01249 } 01250 01251 break; 01252 } 01253 case SH::SH_OP_EXP10: 01254 { 01255 for(int i = 0; i < stmt.dest.size(); i++) 01256 { 01257 m_code << " " 01258 << resolve(stmt.dest, i) 01259 << " = exp10(" 01260 << resolve(stmt.src[0], i) 01261 << ");" << std::endl; 01262 } 01263 01264 break; 01265 } 01266 case SH::SH_OP_FLR: 01267 { 01268 for(int i = 0; i < stmt.dest.size(); i++) 01269 { 01270 m_code << " " 01271 << resolve(stmt.dest, i) 01272 << " = floor(" 01273 << resolve(stmt.src[0], i) 01274 << ");" << std::endl; 01275 } 01276 01277 break; 01278 } 01279 case SH::SH_OP_FRAC: 01280 { 01281 for(int i = 0; i < stmt.dest.size(); i++) 01282 { 01283 m_code << " " 01284 << resolve(stmt.dest, i) 01285 << " = " 01286 << resolve(stmt.src[0], i) 01287 << " - floor(" 01288 << resolve(stmt.src[0], i) 01289 << ");" << std::endl; 01290 } 01291 01292 break; 01293 } 01294 case SH::SH_OP_LOG: 01295 { 01296 for(int i = 0; i < stmt.dest.size(); i++) 01297 { 01298 m_code << " " 01299 << resolve(stmt.dest, i) 01300 << " = log(" 01301 << resolve(stmt.src[0], i) 01302 << ");" << std::endl; 01303 } 01304 01305 break; 01306 } 01307 case SH::SH_OP_LOG2: 01308 { 01309 for(int i = 0; i < stmt.dest.size(); i++) 01310 { 01311 m_code << " " 01312 << resolve(stmt.dest, i) 01313 << " = log2(" 01314 << resolve(stmt.src[0], i) 01315 << ");" << std::endl; 01316 } 01317 01318 break; 01319 } 01320 case SH::SH_OP_LOG10: 01321 { 01322 for(int i = 0; i < stmt.dest.size(); i++) 01323 { 01324 m_code << " " 01325 << resolve(stmt.dest, i) 01326 << " = log10(" 01327 << resolve(stmt.src[0], i) 01328 << ");" << std::endl; 01329 } 01330 01331 break; 01332 } 01333 case SH::SH_OP_LRP: 01334 { 01335 if (stmt.src[0].swizzle().size() == 1) 01336 { 01337 for(int i = 0; i < stmt.dest.size(); i++) 01338 { 01339 m_code << " " 01340 << resolve(stmt.dest, i) 01341 << " = " 01342 << resolve(stmt.src[0], 0) 01343 << " * (" 01344 << resolve(stmt.src[1], i) 01345 << " - " 01346 << resolve(stmt.src[2], i) 01347 << ") + " 01348 << resolve(stmt.src[2], i) 01349 << ");" << std::endl; 01350 } 01351 } 01352 else 01353 { 01354 for(int i = 0; i < stmt.dest.size(); i++) 01355 { 01356 m_code << " " 01357 << resolve(stmt.dest, i) 01358 << " = " 01359 << resolve(stmt.src[0], i) 01360 << " * (" 01361 << resolve(stmt.src[1], i) 01362 << " - " 01363 << resolve(stmt.src[2], i) 01364 << ") + " 01365 << resolve(stmt.src[2], i) 01366 << ");" << std::endl; 01367 } 01368 } 01369 01370 break; 01371 } 01372 case SH::SH_OP_MAD: 01373 { 01374 if (stmt.src[0].swizzle().size() == 1) 01375 { 01376 for(int i = 0; i < stmt.dest.size(); i++) 01377 { 01378 m_code << " " 01379 << resolve(stmt.dest, i) 01380 << " = " 01381 << resolve(stmt.src[0], 0) 01382 << " * " 01383 << resolve(stmt.src[1], i) 01384 << " + " 01385 << resolve(stmt.src[2], i) 01386 << ";" << std::endl; 01387 } 01388 } 01389 else if (stmt.src[1].swizzle().size() == 1) 01390 { 01391 for(int i = 0; i < stmt.dest.size(); i++) 01392 { 01393 m_code << " " 01394 << resolve(stmt.dest, i) 01395 << " = " 01396 << resolve(stmt.src[0], i) 01397 << " * " 01398 << resolve(stmt.src[1], 0) 01399 << " + " 01400 << resolve(stmt.src[2], i) 01401 << ";" << std::endl; 01402 } 01403 } 01404 else 01405 { 01406 for(int i = 0; i < stmt.dest.size(); i++) 01407 { 01408 m_code << " " 01409 << resolve(stmt.dest, i) 01410 << " = " 01411 << resolve(stmt.src[0], i) 01412 << " * " 01413 << resolve(stmt.src[1], i) 01414 << " + " 01415 << resolve(stmt.src[2], i) 01416 << ";" << std::endl; 01417 } 01418 } 01419 01420 break; 01421 } 01422 case SH::SH_OP_MAX: 01423 { 01424 for(int i = 0; i < stmt.dest.size(); i++) 01425 { 01426 m_code << " " 01427 << resolve(stmt.dest, i) 01428 << " = (" 01429 << resolve(stmt.src[0], i) 01430 << " > " 01431 << resolve(stmt.src[1], i) 01432 << " ? " 01433 << resolve(stmt.src[0], i) 01434 << " : " 01435 << resolve(stmt.src[1], i) 01436 << ");" << std::endl; 01437 } 01438 01439 break; 01440 } 01441 case SH::SH_OP_MIN: 01442 { 01443 for(int i = 0; i < stmt.dest.size(); i++) 01444 { 01445 m_code << " " 01446 << resolve(stmt.dest, i) 01447 << " = (" 01448 << resolve(stmt.src[0], i) 01449 << " < " 01450 << resolve(stmt.src[1], i) 01451 << " ? " 01452 << resolve(stmt.src[0], i) 01453 << " : " 01454 << resolve(stmt.src[1], i) 01455 << ");" << std::endl; 01456 } 01457 01458 break; 01459 } 01460 case SH::SH_OP_MOD: 01461 { 01462 for(int i = 0; i < stmt.dest.size(); i++) 01463 { 01464 m_code << " " 01465 << resolve(stmt.dest, i) 01466 << " = fmod(" 01467 << resolve(stmt.src[0], i) 01468 << ", " 01469 << resolve(stmt.src[1], i) 01470 << ");" << std::endl; 01471 } 01472 01473 break; 01474 } 01475 case SH::SH_OP_POW: 01476 { 01477 for(int i = 0; i < stmt.dest.size(); i++) 01478 { 01479 m_code << " " 01480 << resolve(stmt.dest, i) 01481 << " = pow(" 01482 << resolve(stmt.src[0], i) 01483 << ", " 01484 << resolve(stmt.src[1], (stmt.src[1].size() > 1 ? i : 0)) 01485 << ");" << std::endl; 01486 } 01487 01488 break; 01489 } 01490 case SH::SH_OP_RCP: 01491 { 01492 for(int i = 0; i < stmt.dest.size(); i++) 01493 { 01494 m_code << " " 01495 << resolve(stmt.dest, i) 01496 << " = 1.0/(" 01497 << resolve(stmt.src[0], i) 01498 << ");" << std::endl; 01499 } 01500 01501 break; 01502 } 01503 case SH::SH_OP_RSQ: 01504 { 01505 for(int i = 0; i < stmt.dest.size(); i++) 01506 { 01507 m_code << " " 01508 << resolve(stmt.dest, i) 01509 << " = 1.0/sqrt(" 01510 << resolve(stmt.src[0], i) 01511 << ");" << std::endl; 01512 } 01513 01514 break; 01515 } 01516 case SH::SH_OP_SIN: 01517 { 01518 for(int i = 0; i < stmt.dest.size(); i++) 01519 { 01520 m_code << " " 01521 << resolve(stmt.dest, i) 01522 << " = sin(" 01523 << resolve(stmt.src[0], i) 01524 << ");" << std::endl; 01525 } 01526 01527 break; 01528 } 01529 case SH::SH_OP_SGN: 01530 { 01531 for(int i = 0; i < stmt.dest.size(); i++) 01532 { 01533 m_code << " " 01534 << resolve(stmt.dest, i) 01535 << " = (" 01536 << resolve(stmt.src[0], i) 01537 << " < 0.0f ? -1.0f : (" 01538 << resolve(stmt.src[0], i) 01539 << " > 0.0f ? 1.0f : 0.0)" 01540 << ");" << std::endl; 01541 } 01542 01543 break; 01544 } 01545 case SH::SH_OP_SQRT: 01546 { 01547 for(int i = 0; i < stmt.dest.size(); i++) 01548 { 01549 m_code << " " 01550 << resolve(stmt.dest, i) 01551 << " = sqrt(" 01552 << resolve(stmt.src[0], i) 01553 << ");" << std::endl; 01554 } 01555 01556 break; 01557 } 01558 case SH::SH_OP_NORM: 01559 { 01560 m_code << " {" << std::endl; 01561 m_code << " float len = 1.0/sqrt("; 01562 for(int i = 0; i < stmt.dest.size(); i++) 01563 { 01564 if (i != 0) m_code << " + "; 01565 m_code << resolve(stmt.src[0], i) 01566 << " * " 01567 << resolve(stmt.src[0], i); 01568 } 01569 m_code << ");" << std::endl; 01570 for(int i = 0; i < stmt.dest.size(); i++) 01571 { 01572 m_code << " " 01573 << resolve(stmt.dest, i) 01574 << " = len*" 01575 << resolve(stmt.src[0], i) 01576 << ";" << std::endl; 01577 } 01578 m_code << " }" << std::endl; 01579 01580 break; 01581 } 01582 case SH::SH_OP_XPD: 01583 { 01584 for(int i = 0; i < stmt.dest.size(); i++) 01585 { 01586 int i0 = (i+1)%3; 01587 int i1 = (i+2)%3; 01588 m_code << " " 01589 << resolve(stmt.dest, i) 01590 << " = " 01591 << resolve(stmt.src[0], i0) 01592 << " * " 01593 << resolve(stmt.src[1], i1) 01594 << " - " 01595 << resolve(stmt.src[1], i0) 01596 << " * " 01597 << resolve(stmt.src[0], i1) 01598 << ";" << std::endl; 01599 } 01600 01601 break; 01602 } 01603 case SH::SH_OP_TEX: 01604 { 01605 // TODO: negation flags? 01606 if (stmt.dest.swizzle().identity()) 01607 { 01608 if (stmt.src[1].swizzle().identity()) 01609 { 01610 m_code << " sh_gcc_backend_lookup(" 01611 << resolve(stmt.src[0]) 01612 << ", " 01613 << resolve(stmt.src[1]) 01614 << ", " 01615 << resolve(stmt.dest) 01616 << ");" << std::endl; 01617 } 01618 else 01619 { 01620 m_code << " {" << std::endl; 01621 m_code << " float input[" << stmt.src[1].size() << "];" << std::endl; 01622 for(int i = 0; i < stmt.src[1].size(); i++) 01623 { 01624 m_code << " " 01625 << "input[" 01626 << i 01627 << "] = " 01628 << resolve(stmt.src[1], i) 01629 << ";" << std::endl; 01630 } 01631 m_code << " sh_gcc_backend_lookup(" 01632 << resolve(stmt.src[0]) 01633 << ", " 01634 << "input" 01635 << ", " 01636 << resolve(stmt.dest) 01637 << ");" << std::endl; 01638 m_code << " }" << std::endl; 01639 } 01640 } 01641 else 01642 { 01643 if (stmt.src[1].swizzle().identity()) 01644 { 01645 m_code << " {" << std::endl; 01646 m_code << " float result[" << stmt.dest.size() << "];" << std::endl; 01647 m_code << " sh_gcc_backend_lookup(" 01648 << resolve(stmt.src[0]) 01649 << ", " 01650 << resolve(stmt.src[1]) 01651 << ", " 01652 << "result" 01653 << ");" << std::endl; 01654 for(int i = 0; i < stmt.dest.size(); i++) 01655 { 01656 m_code << " " 01657 << resolve(stmt.dest, i) 01658 << " = result[" 01659 << i 01660 << "];" << std::endl; 01661 } 01662 m_code << " }" << std::endl; 01663 } 01664 else 01665 { 01666 m_code << " {" << std::endl; 01667 m_code << " float result[" << stmt.dest.size() << "];" << std::endl; 01668 m_code << " float input[" << stmt.src[1].size() << "];" << std::endl; 01669 for(int i = 0; i < stmt.src[1].size(); i++) 01670 { 01671 m_code << " " 01672 << "input[" 01673 << i 01674 << "] = " 01675 << resolve(stmt.src[1], i) 01676 << ";" << std::endl; 01677 } 01678 m_code << " sh_gcc_backend_lookup(" 01679 << resolve(stmt.src[0]) 01680 << ", " 01681 << "input" 01682 << ", " 01683 << "result" 01684 << ");" << std::endl; 01685 for(int i = 0; i < stmt.dest.size(); i++) 01686 { 01687 m_code << " " 01688 << resolve(stmt.dest, i) 01689 << " = result[" 01690 << i 01691 << "];" << std::endl; 01692 } 01693 m_code << " }" << std::endl; 01694 } 01695 } 01696 break; 01697 } 01698 case SH::SH_OP_TEXI: 01699 { 01700 // TODO: negation flags? 01701 if (stmt.dest.swizzle().identity()) 01702 { 01703 if (stmt.src[1].swizzle().identity()) 01704 { 01705 m_code << " sh_gcc_backend_lookupi(" 01706 << resolve(stmt.src[0]) 01707 << ", " 01708 << resolve(stmt.src[1]) 01709 << ", " 01710 << resolve(stmt.dest) 01711 << ");" << std::endl; 01712 } 01713 else 01714 { 01715 m_code << " {" << std::endl; 01716 m_code << " float input[" << stmt.src[1].size() << "];" << std::endl; 01717 for(int i = 0; i < stmt.src[1].size(); i++) 01718 { 01719 m_code << " " 01720 << "input[" 01721 << i 01722 << "] = " 01723 << resolve(stmt.src[1], i) 01724 << ";" << std::endl; 01725 } 01726 m_code << " sh_gcc_backend_lookupi(" 01727 << resolve(stmt.src[0]) 01728 << ", " 01729 << "input" 01730 << ", " 01731 << resolve(stmt.dest) 01732 << ");" << std::endl; 01733 m_code << " }" << std::endl; 01734 } 01735 } 01736 else 01737 { 01738 if (stmt.src[1].swizzle().identity()) 01739 { 01740 m_code << " {" << std::endl; 01741 m_code << " float result[" << stmt.dest.size() << "];" << std::endl; 01742 m_code << " sh_gcc_backend_lookupi(" 01743 << resolve(stmt.src[0]) 01744 << ", " 01745 << resolve(stmt.src[1]) 01746 << ", " 01747 << "result" 01748 << ");" << std::endl; 01749 for(int i = 0; i < stmt.dest.size(); i++) 01750 { 01751 m_code << " " 01752 << resolve(stmt.dest, i) 01753 << " = result[" 01754 << i 01755 << "];" << std::endl; 01756 } 01757 m_code << " }" << std::endl; 01758 } 01759 else 01760 { 01761 m_code << " {" << std::endl; 01762 m_code << " float result[" << stmt.dest.size() << "];" << std::endl; 01763 m_code << " float input[" << stmt.src[1].size() << "];" << std::endl; 01764 for(int i = 0; i < stmt.src[1].size(); i++) 01765 { 01766 m_code << " " 01767 << "input[" 01768 << i 01769 << "] = " 01770 << resolve(stmt.src[1], i) 01771 << ";" << std::endl; 01772 } 01773 m_code << " sh_gcc_backend_lookupi(" 01774 << resolve(stmt.src[0]) 01775 << ", " 01776 << "input" 01777 << ", " 01778 << "result" 01779 << ");" << std::endl; 01780 for(int i = 0; i < stmt.dest.size(); i++) 01781 { 01782 m_code << " " 01783 << resolve(stmt.dest, i) 01784 << " = result[" 01785 << i 01786 << "];" << std::endl; 01787 } 01788 m_code << " }" << std::endl; 01789 } 01790 } 01791 break; 01792 } 01793 case SH::SH_OP_COND: 01794 { 01795 if (stmt.src[0].swizzle().size() == 1) 01796 { 01797 for(int i = 0; i < stmt.dest.size(); i++) 01798 { 01799 m_code << " " 01800 << resolve(stmt.dest, i) 01801 << " = (" 01802 << resolve(stmt.src[0], 0) 01803 << " > 0 ? " 01804 << resolve(stmt.src[1], i) 01805 << " : " 01806 << resolve(stmt.src[2], i) 01807 << ");" << std::endl; 01808 } 01809 } 01810 else 01811 { 01812 for(int i = 0; i < stmt.dest.size(); i++) 01813 { 01814 m_code << " " 01815 << resolve(stmt.dest, i) 01816 << " = (" 01817 << resolve(stmt.src[0], i) 01818 << " > 0 ? " 01819 << resolve(stmt.src[1], i) 01820 << " : " 01821 << resolve(stmt.src[2], i) 01822 << ");" << std::endl; 01823 } 01824 } 01825 break; 01826 } 01827 case SH::SH_OP_KIL: 01828 { 01829 // TODO: maintain prior output values 01830 m_code << " if ("; 01831 for(int i = 0; i < stmt.src[0].size(); i++) 01832 { 01833 if (i != 0) m_code << " || "; 01834 m_code << "(" 01835 << resolve(stmt.src[0], i) 01836 << " > 0)"; 01837 } 01838 m_code << ")" << std::endl; 01839 m_code << " return;" << std::endl; 01840 break; 01841 } 01842 case SH::SH_OP_OPTBRA: 01843 { 01844 SH_DEBUG_ASSERT(false); 01845 break; 01846 } 01847 case SH::SH_OP_FETCH: 01848 { 01849 for(int i = 0; i < stmt.dest.size(); i++) 01850 { 01851 m_code << " " 01852 << resolve(stmt.dest, i) 01853 << " = " 01854 << resolve(stmt.src[0], i) 01855 << ";" << std::endl; 01856 } 01857 01858 break; 01859 } 01860 default: 01861 { 01862 m_code << " // *** unhandled operation " 01863 << SH::opInfo[stmt.op].name 01864 << " ***" << std::endl; 01865 break; 01866 } 01867 } 01868 } 01869 01870 void GccBackendCode::emit(SH::ShBasicBlockPtr block) 01871 { 01872 if (!block) 01873 { 01874 m_code << " // empty basic block" << std::endl; 01875 } 01876 else 01877 { 01878 m_code << " // start basic block" << std::endl; 01879 for(SH::ShBasicBlock::ShStmtList::const_iterator itr = block->begin(); 01880 itr != block->end(); 01881 itr++) 01882 { 01883 emit((*itr)); 01884 } 01885 m_code << " // end basic block" << std::endl; 01886 } 01887 } 01888 01889 void GccBackendCode::emit(SH::ShCtrlGraphNodePtr node) 01890 { 01891 m_code << "label_" << m_label_map[node] << ":" << std::endl 01892 << " ;" << std::endl; 01893 01894 if (node->block) 01895 { 01896 emit(node->block); 01897 } 01898 01899 for(std::vector<SH::ShCtrlGraphBranch>::iterator itr = node->successors.begin(); 01900 itr != node->successors.end(); 01901 itr++) 01902 { 01903 m_code << " if ("; 01904 for(int i = 0; i < (*itr).cond.size(); i++) 01905 { 01906 if (i != 0) 01907 m_code << " || "; 01908 01909 m_code << "("; 01910 m_code << resolve((*itr).cond, i) << " > 0.0f"; 01911 m_code << ")"; 01912 } 01913 m_code << ")"; 01914 01915 m_code << " goto label_" 01916 << m_label_map[(*itr).node] 01917 << ";" << std::endl; 01918 } 01919 01920 if (node->follower) 01921 { 01922 m_code << " goto label_" << m_label_map[node->follower] << ";" << std::endl; 01923 } 01924 01925 if (node->successors.empty() && !node->follower) 01926 { 01927 // Last block, need to return from the function 01928 m_code << " return;" << std::endl; 01929 } 01930 } 01931 01932 bool GccBackendCode::generate(void) 01933 { 01934 SH_GCC_DEBUG_PRINT("Creating label map..."); 01935 LabelFunctor fl(m_label_map); 01936 m_program->ctrlGraph->dfs(fl); 01937 01938 allocate_consts(); 01939 allocate_inputs(); 01940 allocate_outputs(); 01941 allocate_streams(); 01942 allocate_textures(); 01943 allocate_uniforms(); 01944 01945 // emit code 01946 SH_GCC_DEBUG_PRINT("Emitting code..."); 01947 EmitFunctor fe(this); 01948 m_program->ctrlGraph->dfs(fe); 01949 01950 // prologue 01951 std::stringstream prologue; 01952 prologue << "#include <math.h>" << std::endl; 01953 prologue << std::endl; 01954 prologue << "extern \"C\" void sh_gcc_backend_lookup(void*, float*, float*);" << std::endl; 01955 prologue << "extern \"C\" void sh_gcc_backend_lookupi(void*, float*, float*);" << std::endl; 01956 prologue << std::endl; 01957 prologue << "extern \"C\" " 01958 << " void func(" 01959 << "float** inputs, " 01960 << "float** params, " 01961 << "float** streams, " 01962 << "void** textures, " 01963 << "float** outputs)" << std::endl; 01964 prologue << " {" << std::endl; 01965 01966 // output temp declarations 01967 for(std::vector<GccVariable>::iterator itr = m_temps.begin(); 01968 itr != m_temps.end(); 01969 itr++) 01970 { 01971 // output temp declaration 01972 prologue << " float " 01973 << (*itr).m_name << "[" << (*itr).m_size << "]" 01974 << ";" << std::endl; 01975 } 01976 01977 // epilogue 01978 std::stringstream epilogue; 01979 epilogue << " }" << std::endl; 01980 01981 // output code for debugging... 01982 SH_GCC_DEBUG_PRINT(prologue.str()); 01983 SH_GCC_DEBUG_PRINT(m_code.str()); 01984 SH_GCC_DEBUG_PRINT(epilogue.str()); 01985 01986 char name[32]; 01987 tmpnam(name); 01988 char ccfile[32]; 01989 char sofile[32]; 01990 sprintf(ccfile, "%s.cc", name); 01991 sprintf(sofile, "%s.so", name); 01992 FILE* f = fopen(ccfile, "w"); 01993 fprintf(f, "%s", prologue.str().c_str()); 01994 fprintf(f, "%s", m_code.str().c_str()); 01995 fprintf(f, "%s", epilogue.str().c_str()); 01996 fflush(f); 01997 01998 pid_t pid = fork(); 01999 if (pid == 0) 02000 { 02001 // child 02002 execlp("gcc", "gcc", "-O2", "-shared", "-o", sofile, ccfile, 02003 "-L", SH_INSTALL_PREFIX "/lib/sh", "-lshgcc", NULL); 02004 SH_GCC_DEBUG_PRINT("exec failed (" << errno << ")"); 02005 exit(-1); 02006 } 02007 else if (pid > 0) 02008 { 02009 int status; 02010 pid_t ret = waitpid(pid, &status, 0); 02011 if (ret == -1) 02012 { 02013 SH_GCC_DEBUG_PRINT("wait failed..."); 02014 return false; 02015 } 02016 else 02017 { 02018 SH_GCC_DEBUG_PRINT("status = " << status); 02019 } 02020 02021 m_handle = dlopen(sofile, RTLD_NOW); 02022 if (m_handle == NULL) 02023 { 02024 SH_GCC_DEBUG_PRINT("dlopen failed: " << dlerror()); 02025 return false; 02026 } 02027 else 02028 { 02029 m_func = (GccFunc)dlsym(m_handle, "func"); 02030 02031 if (m_func == NULL) 02032 { 02033 SH_GCC_DEBUG_PRINT("dlsym failed: " << dlerror()); 02034 return false; 02035 } 02036 } 02037 02038 return true; 02039 } 02040 else 02041 { 02042 // fork failed 02043 SH_GCC_DEBUG_PRINT("fork failed..."); 02044 return false; 02045 } 02046 } 02047 02048 bool GccBackendCode::execute(SH::ShStream& dest) 02049 { 02050 if (!m_func) 02051 { 02052 if (!generate()) 02053 { 02054 SH_GCC_DEBUG_PRINT("failed to generate program..."); 02055 return false; 02056 } 02057 } 02058 02059 int num_outputs = dest.size(); 02060 int num_streams = m_streams.size(); 02061 float** inputs = NULL; 02062 float** params = m_params; 02063 float** streams = new float*[m_streams.size()]; 02064 void** textures = new void*[m_textures.size()]; 02065 float** outputs = new float*[dest.size()]; 02066 std::vector<int> output_sizes(num_outputs); 02067 std::vector<int> stream_sizes(num_streams); 02068 02069 int sidx = 0; 02070 for(std::vector<SH::ShChannelNodePtr>::iterator itr = m_streams.begin(); 02071 itr != m_streams.end(); 02072 itr++, sidx++) 02073 { 02074 SH::ShChannelNodePtr channel = (*itr); 02075 SH::ShHostStoragePtr storage = SH::shref_dynamic_cast<SH::ShHostStorage>(channel->memory()->findStorage("host")); 02076 if (!storage) 02077 { 02078 storage = new SH::ShHostStorage(channel->memory().object(), 02079 sizeof(float)*channel->size()*channel->count()); 02080 } 02081 storage->dirty(); 02082 streams[sidx] = (float*)storage->data(); 02083 stream_sizes[sidx] = channel->size(); 02084 } 02085 02086 int tidx = 0; 02087 for(std::vector<SH::ShTextureNodePtr>::iterator itr = m_textures.begin(); 02088 itr != m_textures.end(); 02089 itr++, tidx++) 02090 { 02091 SH::ShTextureNodePtr texture = (*itr); 02092 textures[tidx] = (void*)(texture.object()); 02093 } 02094 02095 int oidx = 0; 02096 int count = 0; 02097 for(SH::ShStream::NodeList::iterator itr = dest.begin(); 02098 itr != dest.end(); 02099 itr++, oidx++) 02100 { 02101 SH::ShChannelNodePtr channel = (*itr); 02102 SH::ShHostStoragePtr storage = SH::shref_dynamic_cast<SH::ShHostStorage>(channel->memory()->findStorage("host")); 02103 if (!storage) 02104 { 02105 storage = new SH::ShHostStorage(channel->memory().object(), 02106 sizeof(float)*channel->size()*channel->count()); 02107 } 02108 storage->dirty(); 02109 outputs[oidx] = (float*)storage->data(); 02110 output_sizes[oidx] = channel->size(); 02111 02112 if (count == 0) count = channel->count(); 02113 else 02114 { 02115 if (count != channel->count()) 02116 { 02117 SH_GCC_DEBUG_PRINT("channel count discrepancy..."); 02118 return false; 02119 } 02120 } 02121 } 02122 02123 02124 for(int i = 0; i < count; i++) 02125 { 02126 SH_GCC_DEBUG_PRINT("execution " << i << " of " << count); 02127 m_func(inputs, params, streams, textures, outputs); 02128 02129 for(int j = 0; j < num_streams; j++) 02130 { 02131 SH_GCC_DEBUG_PRINT("advancing input stream " 02132 << j 02133 << " by " 02134 << stream_sizes[j]); 02135 streams[j] += stream_sizes[j]; 02136 } 02137 for(int j = 0; j < num_outputs; j++) 02138 { 02139 SH_GCC_DEBUG_PRINT("advancing output stream " 02140 << j 02141 << " by " 02142 << output_sizes[j]); 02143 outputs[j] += output_sizes[j]; 02144 } 02145 } 02146 02147 return true; 02148 } 02149 02150 02151 GccBackend::GccBackend(void) 02152 { 02153 SH_GCC_DEBUG_PRINT(__FUNCTION__); 02154 } 02155 02156 GccBackend::~GccBackend(void) 02157 { 02158 SH_GCC_DEBUG_PRINT(__FUNCTION__); 02159 } 02160 02161 std::string GccBackend::name(void) const 02162 { 02163 SH_GCC_DEBUG_PRINT(__FUNCTION__); 02164 return "gcc"; 02165 } 02166 02167 SH::ShBackendCodePtr GccBackend::generateCode(const std::string& target, 02168 const SH::ShProgramNodeCPtr& program) 02169 { 02170 SH_GCC_DEBUG_PRINT(__FUNCTION__); 02171 GccBackendCodePtr backendcode = new GccBackendCode(program); 02172 backendcode->generate(); 02173 return backendcode; 02174 } 02175 02176 void GccBackend::execute(const SH::ShProgramNodeCPtr& program, SH::ShStream& dest) 02177 { 02178 SH_GCC_DEBUG_PRINT(__FUNCTION__); 02179 02180 GccBackendCodePtr backendcode = new GccBackendCode(program); 02181 backendcode->execute(dest); 02182 } 02183 02184 static GccBackend* backend = new GccBackend(); 02185 02186 } 02187

Generated on Mon Oct 18 14:17:38 2004 for Sh by doxygen 1.3.7