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

ShProgramNode.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 "ShProgramNode.hpp" 00028 #include <cassert> 00029 #include <algorithm> 00030 #include <sstream> 00031 #include "ShBackend.hpp" 00032 #include "ShEnvironment.hpp" 00033 #include "ShContext.hpp" 00034 #include "ShDebug.hpp" 00035 #include "ShTextureNode.hpp" 00036 #include "ShCtrlGraph.hpp" 00037 #include "ShError.hpp" 00038 00039 namespace SH { 00040 00041 ShProgramNode::ShProgramNode(const std::string& target) 00042 : m_target(target), m_finished(false), 00043 m_assigned_var(0) 00044 { 00045 } 00046 00047 ShProgramNode::~ShProgramNode() 00048 { 00049 // TODO: maybe need some cleanup here, although refcounting ought to 00050 // take care of it. 00051 } 00052 00053 void ShProgramNode::compile(const ShPointer<ShBackend>& backend) 00054 { 00055 if (m_target.empty()) shError( ShException( "Invalid ShProgram target" ) ); 00056 compile(m_target, backend); 00057 } 00058 00059 void ShProgramNode::compile(const std::string& target, const ShPointer<ShBackend>& backend) 00060 { 00061 if (!backend) return; 00062 00063 ShContext::current()->enter(this); 00064 00065 collectVariables(); 00066 00067 ShBackendCodePtr code = backend->generateCode(target, this); 00068 #ifdef SH_DEBUG 00069 // code->print(std::cerr); 00070 #endif 00071 ShContext::current()->exit(); 00072 m_code[std::make_pair(target, backend)] = code; 00073 } 00074 00075 ShPointer<ShBackendCode> ShProgramNode::code() { 00076 return code(ShEnvironment::backend); 00077 } 00078 00079 ShPointer<ShBackendCode> ShProgramNode::code(const ShPointer<ShBackend>& backend) { 00080 if (m_target.empty()) shError( ShException( "Invalid ShProgram target" ) ); 00081 00082 return code(m_target, backend); 00083 } 00084 00085 ShPointer<ShBackendCode> ShProgramNode::code(const std::string& target, const ShPointer<ShBackend>& backend) { 00086 if (!backend) return 0; 00087 00088 if (m_code.find(std::make_pair(target, backend)) == m_code.end()) compile(target, backend); 00089 00090 return m_code[std::make_pair(target, backend)]; 00091 } 00092 00093 std::string ShProgramNode::describe_interface() const 00094 { 00095 std::ostringstream os; 00096 os << "Interface for "; 00097 if (has_name()) { 00098 os << name(); 00099 } else { 00100 os << "<anonymous program>"; 00101 } 00102 os << std::endl; 00103 os << std::endl; 00104 os << "Inputs:" << std::endl; 00105 for (VarList::const_iterator I = inputs.begin(); I != inputs.end(); ++I) { 00106 os << " " << (*I)->nameOfType() << " " << (*I)->name() << ";" << std::endl; 00107 } 00108 os << std::endl; 00109 os << "Outputs:" << std::endl; 00110 for (VarList::const_iterator I = outputs.begin(); I != outputs.end(); ++I) { 00111 os << " " << (*I)->nameOfType() << " " << (*I)->name() << ";" << std::endl; 00112 } 00113 os << std::endl; 00114 os << "Uniforms:" << std::endl; 00115 for (VarList::const_iterator I = uniforms.begin(); I != uniforms.end(); ++I) { 00116 os << " " << (*I)->nameOfType() << " " << (*I)->name() << ";" << std::endl; 00117 } 00118 00119 return os.str(); 00120 } 00121 00122 void ShProgramNode::updateUniform(const ShVariableNodePtr& uniform) 00123 { 00124 for (CodeMap::iterator I = m_code.begin(); I != m_code.end(); ++I) { 00125 I->second->updateUniform(uniform); 00126 } 00127 } 00128 00129 void ShProgramNode::collectVariables() 00130 { 00131 temps.clear(); 00132 uniforms.clear(); 00133 constants.clear(); 00134 textures.clear(); 00135 channels.clear(); 00136 if (ctrlGraph->entry()) { 00137 ctrlGraph->entry()->clearMarked(); 00138 collectNodeVars(ctrlGraph->entry()); 00139 ctrlGraph->entry()->clearMarked(); 00140 } 00141 } 00142 00143 void ShProgramNode::collectNodeVars(const ShCtrlGraphNodePtr& node) 00144 { 00145 if (node->marked()) return; 00146 node->mark(); 00147 00148 if (node->block) { 00149 for (ShBasicBlock::ShStmtList::const_iterator I = node->block->begin(); 00150 I != node->block->end(); ++I) { 00151 00152 collectVar(I->dest.node()); 00153 collectVar(I->src[0].node()); 00154 collectVar(I->src[1].node()); 00155 collectVar(I->src[2].node()); 00156 } 00157 } 00158 00159 for (std::vector<ShCtrlGraphBranch>::const_iterator J = node->successors.begin(); 00160 J != node->successors.end(); ++J) { 00161 collectNodeVars(J->node); 00162 } 00163 00164 if (node->follower) collectNodeVars(node->follower); 00165 } 00166 00167 void ShProgramNode::collectVar(const ShVariableNodePtr& var) 00168 { 00169 if (!var) return; 00170 if (var->uniform()) { 00171 if (std::find(uniforms.begin(), uniforms.end(), var) == uniforms.end()) { 00172 uniforms.push_back(var); 00173 } 00174 } else switch (var->kind()) { 00175 case SH_INPUT: 00176 case SH_OUTPUT: 00177 case SH_INOUT: 00178 // Taken care of by ShVariableNode constructor 00179 break; 00180 case SH_TEMP: 00181 if (std::find(temps.begin(), temps.end(), var) == temps.end()) { 00182 temps.push_back(var); 00183 } 00184 break; 00185 case SH_CONST: 00186 if (std::find(constants.begin(), constants.end(), var) == constants.end()) { 00187 constants.push_back(var); 00188 } 00189 break; 00190 case SH_TEXTURE: 00191 if (std::find(textures.begin(), textures.end(), 00192 shref_dynamic_cast<ShTextureNode>(var)) == textures.end()) { 00193 textures.push_back(shref_dynamic_cast<ShTextureNode>(var)); 00194 } 00195 break; 00196 case SH_STREAM: 00197 if (std::find(channels.begin(), channels.end(), 00198 shref_dynamic_cast<ShChannelNode>(var)) == channels.end()) { 00199 channels.push_back(shref_dynamic_cast<ShChannelNode>(var)); 00200 } 00201 break; 00202 } 00203 } 00204 00205 std::ostream& ShProgramNode::print(std::ostream& out, 00206 const ShProgramNode::VarList& varList) 00207 { 00208 out << "("; 00209 for(VarList::const_iterator it = varList.begin(); it != varList.end(); ++it) { 00210 if( it != varList.begin() ) out << ", "; 00211 out << (*it)->nameOfType() << " " << (*it)->name(); 00212 } 00213 out << ")"; 00214 return out; 00215 } 00216 00217 ShPointer<ShProgramNode> ShProgramNode::clone() const 00218 { 00219 ShCtrlGraphNodePtr head, tail; 00220 ctrlGraph->copy(head, tail); 00221 00222 ShProgramNodePtr result = new ShProgramNode(target()); 00223 result->ctrlGraph = new ShCtrlGraph(head, tail); 00224 result->inputs = inputs; 00225 result->outputs = outputs; 00226 result->collectVariables(); 00227 return result; 00228 } 00229 00230 ShProgramNode::VarList::const_iterator ShProgramNode::inputs_begin() const 00231 { 00232 return inputs.begin(); 00233 } 00234 00235 ShProgramNode::VarList::const_iterator ShProgramNode::inputs_end() const 00236 { 00237 return inputs.end(); 00238 } 00239 00240 ShProgramNode::VarList::const_iterator ShProgramNode::outputs_begin() const 00241 { 00242 return outputs.begin(); 00243 } 00244 00245 ShProgramNode::VarList::const_iterator ShProgramNode::outputs_end() const 00246 { 00247 return outputs.end(); 00248 } 00249 00250 ShProgramNode::VarList::const_iterator ShProgramNode::temps_begin() const 00251 { 00252 return temps.begin(); 00253 } 00254 00255 ShProgramNode::VarList::const_iterator ShProgramNode::temps_end() const 00256 { 00257 return temps.end(); 00258 } 00259 00260 ShProgramNode::VarList::const_iterator ShProgramNode::constants_begin() const 00261 { 00262 return constants.begin(); 00263 } 00264 00265 ShProgramNode::VarList::const_iterator ShProgramNode::constants_end() const 00266 { 00267 return constants.end(); 00268 } 00269 00270 ShProgramNode::VarList::const_iterator ShProgramNode::uniforms_begin() const 00271 { 00272 return uniforms.begin(); 00273 } 00274 00275 ShProgramNode::VarList::const_iterator ShProgramNode::uniforms_end() const 00276 { 00277 return uniforms.end(); 00278 } 00279 00280 ShProgramNode::TexList::const_iterator ShProgramNode::textures_begin() const 00281 { 00282 return textures.begin(); 00283 } 00284 00285 ShProgramNode::TexList::const_iterator ShProgramNode::textures_end() const 00286 { 00287 return textures.end(); 00288 } 00289 00290 ShProgramNode::ChannelList::const_iterator ShProgramNode::channels_begin() const 00291 { 00292 return channels.begin(); 00293 } 00294 00295 ShProgramNode::ChannelList::const_iterator ShProgramNode::channels_end() const 00296 { 00297 return channels.end(); 00298 } 00299 00300 bool ShProgramNode::finished() const 00301 { 00302 return m_finished; 00303 } 00304 00305 void ShProgramNode::finish() 00306 { 00307 m_finished = true; 00308 if (m_assigned_var) { 00309 m_assigned_var->attach(this); 00310 m_assigned_var = 0; 00311 } 00312 } 00313 00314 void ShProgramNode::assign(const ShVariableNodePtr& var) const 00315 { 00316 m_assigned_var = var; 00317 } 00318 00319 }

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