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

Cc.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 
00028 #ifdef WIN32
00029 #include <math.h>
00030 #else
00031 #include <dlfcn.h>
00032 #include <unistd.h>
00033 #include <sys/wait.h>
00034 #endif /* WIN32 */
00035 
00036 #include <iostream>
00037 #include <fstream>
00038 
00039 #include "Cc.hpp" 
00040 #include "ShDebug.hpp" 
00041 #include "ShStream.hpp" 
00042 #include "ShVariant.hpp"
00043 #include "ShVariantFactory.hpp"
00044 #include "ShTypeInfo.hpp"
00045 #include "ShOptimizations.hpp"
00046 
00047 #ifdef HAVE_CONFIG_H
00048 #include "config.h"
00049 #endif
00050 
00051 #ifdef SH_CC_DEBUG
00052 #  define SH_CC_DEBUG_PRINT(x) SH_DEBUG_PRINT(x)
00053 #else
00054 #  define SH_CC_DEBUG_PRINT(x) do { } while(0)
00055 #endif
00056 
00057 
00058 namespace ShCc {
00059   using namespace SH;
00060 
00061 #include "CcTexturesString.hpp"
00062 
00063   std::string encode(const ShVariable& v) {
00064     std::stringstream ret;
00065     if (v.neg()) ret << "-";
00066     ret << v.name();
00067     ret << v.swizzle();
00068     return ret.str();
00069   }
00070 
00071   // internal use only 
00072   const char* makeVarname(const char* prefix, int suffix) {
00073     static char buffer[128];
00074     sprintf(buffer, "%s%d", prefix, suffix); 
00075     return buffer;
00076   }
00077 
00078   const char* InputPrefix = "var_i_";
00079   const char* OutputPrefix = "var_o_";
00080   const char* TempPrefix = "var_t_";
00081   const char* ConstPrefix = "var_c_";
00082   const char* TexturePrefix = "var_tex_";
00083   const char* StreamPrefix = "var_s_";
00084   const char* UniformPrefix= "var_u_";
00085 
00086   CcVariable::CcVariable(void) 
00087     : m_num(-1), 
00088       m_size(-1), 
00089       m_valueType(SH_VALUETYPE_END)
00090   {}
00091   
00092   CcVariable::CcVariable(int num, const std::string& name, int size, ShValueType valueType) 
00093     : m_num(num),
00094       m_name(name),
00095       m_size(size),
00096       m_valueType(valueType) 
00097   {}
00098 
00099   CcBackendCode::LabelFunctor::LabelFunctor(std::map<ShCtrlGraphNodePtr, int>& label_map) 
00100     : m_cur_label(0),
00101       m_label_map(label_map) 
00102   {}
00103 
00104   void CcBackendCode::LabelFunctor::operator()(ShCtrlGraphNode* node) 
00105   {
00106     m_label_map[node] = m_cur_label++;
00107   }
00108   
00109   CcBackendCode::EmitFunctor::EmitFunctor(CcBackendCode* bec) 
00110     : m_bec(bec) 
00111   {}
00112   
00113   void CcBackendCode::EmitFunctor::operator()(ShCtrlGraphNode* node) 
00114   {
00115     m_bec->emit(node);
00116   }
00117   
00118   CcBackendCode::CcBackendCode(const ShProgramNodeCPtr& program) 
00119     : m_original_program(program),
00120     m_program(0),
00121 #ifdef WIN32
00122     m_hmodule(NULL),
00123 #else
00124     m_handle(NULL),
00125 #endif
00126       m_shader_func(NULL),
00127       m_cur_temp(0),
00128       m_params(NULL) 
00129   {
00130     SH_CC_DEBUG_PRINT(__FUNCTION__);
00131 
00132     // convert half floats, fractionals to types we can use
00133     m_convertMap[SH_HALF] = SH_FLOAT;
00134     m_convertMap[SH_FINT] = SH_FLOAT;
00135     m_convertMap[SH_FSHORT] = SH_FLOAT;
00136     m_convertMap[SH_FBYTE] = SH_FLOAT;
00137     m_convertMap[SH_FUINT] = SH_FLOAT;
00138     m_convertMap[SH_FUSHORT] = SH_FLOAT;
00139     m_convertMap[SH_FUBYTE] = SH_FLOAT;
00140   }
00141 
00142   CcBackendCode::~CcBackendCode(void) 
00143   {
00144     SH_CC_DEBUG_PRINT(__FUNCTION__);
00145   }
00146 
00147   bool CcBackendCode::allocateRegister(const ShVariableNodePtr& var) 
00148   {
00149     SH_CC_DEBUG_PRINT(__FUNCTION__);
00150     return false;
00151   }
00152 
00153   void CcBackendCode::freeRegister(const ShVariableNodePtr& var) 
00154   {
00155     SH_CC_DEBUG_PRINT(__FUNCTION__);
00156   }
00157 
00158   void CcBackendCode::upload(void) 
00159   {
00160     SH_CC_DEBUG_PRINT(__FUNCTION__);
00161   }
00162 
00163   void CcBackendCode::bind(void) 
00164   {
00165     SH_CC_DEBUG_PRINT(__FUNCTION__);
00166   }
00167 
00168   void CcBackendCode::update(void) 
00169   {
00170     SH_CC_DEBUG_PRINT(__FUNCTION__);
00171   }
00172 
00173   void CcBackendCode::updateUniform(const ShVariableNodePtr& uniform) 
00174   {
00175     SH_CC_DEBUG_PRINT(__FUNCTION__);
00176   }
00177 
00178   std::ostream& CcBackendCode::print(std::ostream& out) 
00179   {
00180     SH_CC_DEBUG_PRINT(__FUNCTION__);
00181     return out;
00182   }
00183 
00184   std::ostream& CcBackendCode::describe_interface(std::ostream& out) 
00185   {
00186     SH_CC_DEBUG_PRINT(__FUNCTION__);
00187     return out;
00188   }
00189   
00190   template<typename T>
00191   void CcBackendCode::allocate_varlist(const std::list<T> &varList, const char* varPrefix, const char* arrayName, const char* typePrefix)
00192   {
00193     int num = 0;
00194 
00195     m_code << "  // Assigning locals for " << arrayName << std::endl;
00196     for(typename std::list<T>::const_iterator I = varList.begin()
00197         ; I != varList.end(); ++I, ++num) {
00198       ShVariableNodePtr node = *I; 
00199 
00200       const char* name = makeVarname(varPrefix, num);
00201       const char* type = ctype(node->valueType());
00202       m_code << "  " << typePrefix << " " << type << " *" << name 
00203         << " = ((" << type << "*) " << arrayName << "[" << num << "]); // " 
00204         << node->name() << std::endl; 
00205 
00206       m_varmap[node] = CcVariable(num, name, node->size(), node->valueType()); 
00207     }
00208     m_code << std::endl;
00209 
00210     SH_CC_DEBUG_PRINT("Found " << num << " " << arrayName << "...");
00211   }
00212 
00213   void CcBackendCode::allocate_consts(void) 
00214   {
00215     int num = 0;
00216     
00217     m_code << "  // Declaring constants" << std::endl; 
00218     for (ShProgramNode::VarList::const_iterator I = m_program->constants.begin()
00219         ; I != m_program->constants.end(); ++I, ++num) {
00220       ShVariableNodePtr node = (*I);
00221       const char* name = makeVarname(ConstPrefix, num);
00222       
00223       m_code << "const " << ctype(node->valueType()) << " " << name << "[" << node->size() << "] = {" 
00224         << node->getVariant()->encodeArray() << "}; // " << node->name() << std::endl;
00225 
00226       m_varmap[node] = CcVariable(num, name, node->size(), node->valueType()); 
00227     }
00228     m_code << std::endl;
00229 
00230     SH_CC_DEBUG_PRINT("Found " << num << " consts...");
00231   }
00232 
00233   void CcBackendCode::allocate_inputs(void) {
00234     allocate_varlist(m_program->inputs, InputPrefix, "inputs"); 
00235   }
00236 
00237   void CcBackendCode::allocate_outputs(void) {
00238     allocate_varlist(m_program->outputs, OutputPrefix, "outputs"); 
00239   }
00240 
00241   void CcBackendCode::allocate_channels(void) {
00242     allocate_varlist(m_program->channels, StreamPrefix, "channels", "const"); 
00243   }
00244 
00245   void CcBackendCode::allocate_textures(void) {
00246     allocate_varlist(m_program->textures, TexturePrefix, "textures", "const"); 
00247   }
00248 
00249   void CcBackendCode::allocate_uniforms(void) {
00250     allocate_varlist(m_program->uniforms, UniformPrefix, "params"/*, "const"*/);  // let uniforms be assigned to...
00251     
00252     ShProgramNode::VarList &uniforms = m_program->uniforms;
00253     m_params = new void*[uniforms.size()]; 
00254 
00255 
00256     // @todo type Trying to use the variants' data arrays directly. Hope this works. (<-- stupid comment)
00257     // @todo note that since ray assigns to uniforms, we're going to allow
00258     // this to be non-const...
00259     ShProgramNode::VarList::iterator I = uniforms.begin(); 
00260     for (int i = 0; I != m_program->uniforms.end(); ++I, ++i) {
00261       ShVariableNodePtr node = *I; 
00262       m_params[i] = node->getVariant()->array(); 
00263     }
00264   }
00265 
00266   void CcBackendCode::allocate_temps() 
00267   {
00268     ShProgramNode::VarList::const_iterator I = m_program->temps.begin();
00269     for (; I != m_program->temps.end(); ++I, ++m_cur_temp) {
00270       ShVariableNodePtr node = (*I);
00271       const char* name = makeVarname(TempPrefix, m_cur_temp);
00272       
00273       m_code << ctype(node->valueType()) << " " << name << "[" << node->size() << "]"
00274         << "; // " << node->name() << std::endl;
00275       m_varmap[node] = CcVariable(m_cur_temp, name, node->size(), node->valueType()); 
00276     }
00277 
00278     SH_CC_DEBUG_PRINT("Found " << m_cur_temp << " temps...");
00279   }
00280 
00281   std::string CcBackendCode::resolve(const ShVariable& v) {
00282     CcVariable &var = m_varmap[v.node()];
00283     SH_DEBUG_ASSERT(var.m_num != -1);
00284 
00285     std::stringstream buf;
00286     if (v.neg()) buf << "-";
00287     buf << var.m_name;
00288     return buf.str();
00289   }
00290 
00291   std::string CcBackendCode::resolve(const ShVariable& v, int idx) {
00292     CcVariable &var = m_varmap[v.node()];
00293     SH_DEBUG_ASSERT(var.m_num != -1);
00294 
00295     std::stringstream buf;
00296     if (v.neg()) buf << "-";
00297     buf << var.m_name << "[" << v.swizzle()[idx] << "]";
00298     return buf.str();
00299   }
00300 
00301   const char* CcBackendCode::ctype(ShValueType valueType)
00302   {
00303     switch(valueType) {
00304       case SH_HALF:
00305       case SH_FLOAT:
00306       case SH_FBYTE:
00307       case SH_FSHORT:
00308       case SH_FINT:
00309       case SH_FUBYTE:
00310       case SH_FUSHORT:
00311       case SH_FUINT:
00312         return "float";
00313 
00314       case SH_DOUBLE: return "double";
00315       case SH_BYTE:   return "char";
00316       case SH_SHORT:  return "short";
00317       case SH_INT:    return "int";
00318       case SH_UBYTE:  return "unsigned char";
00319       case SH_USHORT: return "unsigned short";
00320       case SH_UINT:   return "unsigned int";
00321       default:
00322         SH_DEBUG_ASSERT(0 && "Invalid value type");
00323     }
00324     return "unknown"; 
00325   }
00326 
00327   void CcBackendCode::emit(ShBasicBlockPtr block) {
00328     if (!block) {
00329       m_code << "  // empty basic block" << std::endl;
00330     }
00331     else {
00332       m_code << "  // start basic block" << std::endl;
00333       ShBasicBlock::ShStmtList::const_iterator I = block->begin();
00334       for(;I != block->end(); ++I) {
00335         emit((*I));
00336       }
00337       m_code << "  // end basic block" << std::endl;
00338     }
00339   }
00340 
00341   void CcBackendCode::emit(ShCtrlGraphNodePtr node) {
00342     m_code << "label_" << m_label_map[node] << ":" << std::endl
00343            << "  ;" << std::endl;
00344         
00345     if (node->block) {
00346       emit(node->block);
00347     }
00348 
00349     std::vector<ShCtrlGraphBranch>::iterator I = node->successors.begin();
00350     for(;I != node->successors.end(); ++I) {
00351 
00352       m_code << "  if (";
00353       for(int i = 0; i < (*I).cond.size(); i++) {
00354         if (i != 0) {
00355           m_code << " || ";
00356         }
00357 
00358         m_code << "(";
00359         m_code << resolve((*I).cond, i) << " > 0"; // @todo type fix this truth condition 
00360         m_code << ")";
00361       }
00362       m_code << ")";
00363 
00364       m_code << " goto label_" << m_label_map[(*I).node] << ";" << std::endl;
00365     }
00366 
00367     if (node->follower) {
00368       m_code << "  goto label_" << m_label_map[node->follower] << ";" << std::endl;
00369     }
00370 
00371     if (node->successors.empty() && !node->follower) {
00372       // Last block, need to return from the function
00373       m_code << "  return;" << std::endl;
00374     }
00375   }
00376 
00377   bool CcBackendCode::generate(void) {
00378     // Transform the code to remove types this backend cannot handle
00379     m_program = m_original_program->clone();
00380     ShContext::current()->enter(m_program);
00381     ShTransformer transform(m_program);
00382 
00383     transform.convertToFloat(m_convertMap);
00384     if(transform.changed()) {
00385       optimize(m_program);
00386       m_program->collectVariables();
00387     } else {
00388       m_program = shref_const_cast<ShProgramNode>(m_original_program);
00389     }
00390     ShContext::current()->exit();
00391 
00392     // @todo type add conversion code on 
00393     // transformer already fixes the ShProgram.  Now we just need to set up
00394     // some storages that hold a copy of texture and input stream data in 
00395     // our computation type, and make a temp buffer for output if it needs 
00396     // to be type converted.
00397     //
00398     // a) texture lookups
00399     // b) convert input data array to a useable computation type
00400     // c) convert output data array to the memory storage type
00401 
00402     SH_CC_DEBUG_PRINT("Creating label map...");
00403     LabelFunctor fl(m_label_map);
00404     m_program->ctrlGraph->dfs(fl);
00405 
00406     allocate_consts();
00407     allocate_inputs();
00408     allocate_outputs();
00409     allocate_channels();
00410     allocate_textures();
00411     allocate_uniforms();
00412     allocate_temps();
00413 
00414     // emit code
00415     SH_CC_DEBUG_PRINT("Emitting code...");
00416     EmitFunctor fe(this);
00417     m_program->ctrlGraph->dfs(fe);
00418 
00419     // prologue
00420     std::stringstream prologue;
00421     prologue << "#include <math.h>" << std::endl;
00422     for(int i = 0; cc_texture_string[i][0] != 0; ++i) {
00423       prologue << cc_texture_string[i]; 
00424     }
00425     // @todo output the CcTextures.hpp file here
00426     prologue << std::endl;
00427     prologue << std::endl;
00428     prologue << "extern \"C\" "
00429 #ifdef WIN32
00430              << " void __declspec(dllexport) cc_shader("
00431 #else
00432              << " void cc_shader("
00433 #endif /* WIN32 */
00434            << "void** inputs, "
00435            << "void** params, "
00436            << "void** channels, "
00437            << "void** textures, "
00438            << "void** outputs)" << std::endl;
00439     prologue << "{" << std::endl;
00440 
00441 
00442     // epilogue
00443     std::stringstream epilogue;
00444     epilogue << "}" << std::endl;
00445 
00446     // output code for debugging...
00447     //SH_CC_DEBUG_PRINT(prologue.str());
00448     //SH_CC_DEBUG_PRINT(m_code.str());
00449     //SH_CC_DEBUG_PRINT(epilogue.str());
00450 
00451 //#ifdef SH_CC_DEBUG
00452     SH_CC_DEBUG_PRINT("Outputting generated C++ code to ccstream.cpp");
00453     std::ofstream dbgout("ccstream.cpp");
00454     dbgout << prologue.str();
00455     dbgout << m_code.str();
00456     dbgout << epilogue.str();
00457     dbgout.flush();
00458     dbgout.close();
00459 //#endif
00460 
00461 #ifdef WIN32
00462     // generate temporary names for the
00463     // code and the dll
00464     char path[1024];
00465     GetTempPath(1024, path);
00466 
00467     char prefix[1024];
00468     GetTempFileName(path, "shcc", 0, prefix);
00469 
00470     char cppfile[1024];
00471     char dllfile[1024];
00472     sprintf(cppfile, "%s.cpp", prefix);
00473     sprintf(dllfile, "%s.dll", prefix);
00474 
00475     // write the code out to cppfile
00476     std::ofstream fout(cppfile);
00477     fout << prologue.str();
00478     fout << m_code.str();
00479     fout << epilogue.str();
00480     fout.flush();
00481     fout.close();
00482 
00483     // run cl on cppfile and generate dllfile
00484     char cmdline[1024];
00485     sprintf(cmdline, "cl /EHsc /LD /Fe\"%s\" \"%s\"", dllfile, cppfile);
00486 
00487     SH_CC_DEBUG_PRINT("cmdline: \"" << cmdline << "\"");
00488 
00489     STARTUPINFO si;
00490     PROCESS_INFORMATION pi;
00491     ZeroMemory(&si, sizeof(STARTUPINFO));   
00492     ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));   
00493     si.cb = sizeof(STARTUPINFO);
00494 
00495     if (!CreateProcess(NULL, cmdline, NULL, NULL,
00496                       TRUE, 0, NULL, NULL, &si, &pi)) {
00497       SH_CC_DEBUG_PRINT("CreateProcess failed!" << GetLastError());
00498       return false;
00499     }
00500 
00501     // TODO: do not use INFINITE
00502     WaitForSingleObject(pi.hProcess, INFINITE);
00503 
00504     // Attempt to load the dll and fetch our function
00505     m_hmodule = LoadLibrary(dllfile);
00506     if (m_hmodule == NULL) {
00507       SH_CC_DEBUG_PRINT("LoadLibrary failed: " << GetLastError());
00508       return false;
00509     } else {
00510       m_shader_func = (CcShaderFunc)GetProcAddress(m_hmodule, "cc_shader");
00511 
00512       if (m_shader_func == NULL) {
00513         SH_CC_DEBUG_PRINT("GetProcAddress failed: " << GetLastError());
00514         return false;
00515       }
00516     }
00517 
00518     return true;
00519 #else
00520     char name[32];
00521     tmpnam(name);
00522     char ccfile[32];
00523     char sofile[32];
00524     sprintf(ccfile, "%s.cc", name);
00525     sprintf(sofile, "%s.so", name);
00526 
00527     std::ofstream fout(ccfile);
00528     fout << prologue.str();
00529     fout << m_code.str();
00530     fout << epilogue.str();
00531     fout.flush();
00532     fout.close();
00533 
00534     pid_t pid = fork();
00535     if (pid == 0) {
00536       // child
00537       execlp("cc", "cc", "-O2", "-shared", "-o", sofile, ccfile, NULL);
00538       SH_CC_DEBUG_PRINT("exec failed (" << errno << ")");
00539       exit(-1);
00540     } else if (pid > 0) {
00541       int status;
00542       pid_t ret = waitpid(pid, &status, 0);
00543       if (ret == -1) {
00544         SH_CC_DEBUG_PRINT("wait failed...");
00545         return false;
00546       } else {
00547         SH_CC_DEBUG_PRINT("status = " << status);
00548       }
00549 
00550       m_handle = dlopen(sofile, RTLD_NOW);
00551       if (m_handle == NULL) {
00552         SH_CC_DEBUG_PRINT("dlopen failed: " << dlerror());
00553         return false;
00554       } else {
00555         m_shader_func = (CcShaderFunc)dlsym(m_handle, "cc_shader");
00556         if (m_shader_func == NULL) {
00557           SH_CC_DEBUG_PRINT("dlsym failed: " << dlerror());
00558           return false;
00559         }
00560       }
00561       return true;
00562     } else  {
00563       // fork failed
00564       SH_CC_DEBUG_PRINT("fork failed...");
00565       return false;
00566     }
00567 #endif /* WIN32 */
00568   }
00569 
00570   bool CcBackendCode::execute(ShStream& dest) 
00571   {
00572     if (!m_shader_func) {
00573       if (!generate()) {
00574         SH_CC_DEBUG_PRINT("failed to generate program..."); 
00575         return false;
00576       }
00577     }
00578 
00579     int num_outputs = dest.size();
00580     int num_streams = m_program->channels.size();
00581     int num_textures = m_program->textures.size();
00582     void** inputs = NULL;
00583     void** outputs = new void*[num_outputs]; 
00584     void** streams = new void*[num_streams];
00585     void** textures = new void*[num_textures];
00586     std::vector<int> output_sizes(num_outputs); // sizes of each output element in bytes 
00587     std::vector<int> output_types(num_outputs);
00588     std::vector<int> stream_sizes(num_streams); // sizes of each stream element in bytes 
00589     std::vector<int> stream_types(num_streams);
00590     
00591     int sidx = 0;
00592     
00593     SH_CC_DEBUG_PRINT("Assigning input channels to arrays");
00594     for(ShProgramNode::ChannelList::const_iterator I = m_program->channels_begin()
00595         ;I != m_program->channels_end(); ++I, ++sidx) {
00596       ShChannelNodePtr channel = (*I);
00597       ShHostStoragePtr storage = shref_dynamic_cast<ShHostStorage>(channel->memory()->findStorage("host"));
00598       
00599       int datasize = shTypeInfo(channel->valueType(), SH_MEM)->datasize();
00600       stream_sizes[sidx] = datasize * channel->size();
00601       stream_types[sidx] = channel->valueType();
00602 
00603       if (!storage) {
00604         storage = new ShHostStorage(channel->memory().object(),
00605            datasize * channel->size() * channel->count());
00606       }
00607       storage->dirty();
00608       streams[sidx] = storage->data();
00609     }
00610 
00611     int tidx = 0;
00612     for(ShProgramNode::TexList::const_iterator I = m_program->textures_begin()
00613         ;I != m_program->textures_end(); ++I, ++tidx) {
00614       ShTextureNodePtr texture = (*I);
00615 
00616       ShHostStoragePtr storage = shref_dynamic_cast<ShHostStorage>(
00617           texture->memory()->findStorage("host"));
00618 
00619       // @todo type this doesn't work with cube maps
00620       // but should be taken care of
00621       textures[tidx] = storage->data(); 
00622     }
00623 
00624     // @todo code below is *exactly* the same as the code above for streams...
00625     // factor this out
00626     int oidx = 0;
00627     int count = 0;
00628 
00629     
00630     SH_CC_DEBUG_PRINT("Assigning output channels to arrays");
00631     for(ShStream::NodeList::iterator I = dest.begin()
00632         ;I != dest.end(); ++I, ++oidx) {
00633       ShChannelNodePtr channel = (*I);
00634       ShHostStoragePtr storage = shref_dynamic_cast<ShHostStorage>(
00635           channel->memory()->findStorage("host"));
00636 
00637       int datasize = shTypeInfo(channel->valueType(), SH_MEM)->datasize();
00638       output_sizes[oidx] = datasize * channel->size();
00639       output_types[oidx] = channel->valueType();
00640 
00641       if (!storage) {
00642         SH_CC_DEBUG_PRINT("  Allocating new storage?");
00643         storage = new ShHostStorage(channel->memory().object(),
00644            datasize * channel->size() * channel->count());
00645       }
00646       storage->dirty();
00647       outputs[oidx] = storage->data();
00648       SH_CC_DEBUG_PRINT("  outputs[" << oidx << "] = " << outputs[oidx]);
00649 
00650       if (count == 0) {
00651         count = channel->count();
00652       } else if (count != channel->count()) {
00653         SH_CC_DEBUG_PRINT("channel count discrepancy...");
00654         return false;
00655       }
00656     }
00657 
00658       
00659     for(int i = 0; i < count; i++) {
00660       SH_CC_DEBUG_PRINT("execution " << i << " of " << count);
00661       m_shader_func(inputs, m_params, streams, textures, outputs);
00662 
00663       for(int j = 0; j < num_streams; j++) {
00664         SH_CC_DEBUG_PRINT("advancing input stream "
00665                        << j
00666                        << " by "
00667                        << stream_sizes[j] 
00668            << " bytes." );
00669         // @todo type - not sure if void pointers inc by 1 byte,
00670         // so cast
00671         streams[j] = reinterpret_cast<char*>(streams[j]) + stream_sizes[j]; 
00672       }
00673       for(int j = 0; j < num_outputs; j++) {
00674         SH_CC_DEBUG_PRINT("advancing output stream "
00675                        << j
00676                        << " by "
00677                        << output_sizes[j]
00678            << " bytes." );
00679         outputs[j] = reinterpret_cast<char*>(outputs[j]) + output_sizes[j]; 
00680       }
00681     }
00682 
00683     return true;
00684   }
00685 
00686 
00687   CcBackend::CcBackend(void) {
00688     SH_CC_DEBUG_PRINT(__FUNCTION__);
00689   }
00690 
00691   CcBackend::~CcBackend(void) {
00692     SH_CC_DEBUG_PRINT(__FUNCTION__);
00693   }
00694 
00695   std::string CcBackend::name(void) const {
00696     SH_CC_DEBUG_PRINT(__FUNCTION__);
00697     return "cc";
00698   }
00699 
00700   ShBackendCodePtr CcBackend::generateCode(const std::string& target,
00701                                                 const ShProgramNodeCPtr& program) {
00702     SH_CC_DEBUG_PRINT(__FUNCTION__);
00703     CcBackendCodePtr backendcode = new CcBackendCode(program);
00704     backendcode->generate();
00705     return backendcode;
00706   }
00707 
00708   void CcBackend::execute(const ShProgramNodeCPtr& program, ShStream& dest) {
00709     SH_CC_DEBUG_PRINT(__FUNCTION__);
00710 
00711     ShProgramNodePtr prg = shref_const_cast<ShProgramNode>(program);
00712     ShPointer<ShBackend> b(this);
00713     
00714     CcBackendCodePtr backendcode = shref_dynamic_cast<CcBackendCode>(prg->code(b)); // = new CcBackendCode(program);
00715     backendcode->execute(dest);
00716   }
00717 
00718   static CcBackend* backend = new CcBackend();
00719 
00720 }
00721 

Generated on Mon Jan 24 18:36:29 2005 for Sh by  doxygen 1.4.1