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

ShVariableNode.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 <sstream> 00028 #include <cassert> 00029 #include <algorithm> 00030 #include "ShEnvironment.hpp" 00031 #include "ShVariableNode.hpp" 00032 #include "ShDebug.hpp" 00033 #include "ShContext.hpp" 00034 #include "ShProgramNode.hpp" 00035 #include "ShEvaluate.hpp" 00036 00037 namespace SH { 00038 00039 const char* ShBindingTypeName[] = { 00040 "Input", 00041 "Output", 00042 "InOut", 00043 "", 00044 "Constant", 00045 "Texture", 00046 "Stream" 00047 }; 00048 00049 const char* ShSemanticTypeName[] = { 00050 "Attrib", 00051 "Point", 00052 "Vector", 00053 "Normal", 00054 "Color", 00055 "TexCoord", 00056 "Position" 00057 }; 00058 00059 struct ShVariableNodeEval { 00060 ShPointer<ShProgramNode> value; 00061 00062 #ifdef SH_USE_MEMORY_POOL 00063 // Memory pool stuff. 00064 void* operator new(std::size_t size) 00065 { 00066 if (!m_pool) m_pool = new ShPool(sizeof(ShVariableNodeEval), 32768); 00067 return m_pool->alloc(); 00068 } 00069 void operator delete(void* ptr) 00070 { 00071 m_pool->free(ptr); 00072 } 00073 00074 static ShPool* m_pool; 00075 #endif 00076 }; 00077 00078 #ifdef SH_USE_MEMORY_POOL 00079 ShPool* ShVariableNodeEval::m_pool = 0; 00080 #endif 00081 00082 ShVariableNode::ShVariableNode(ShBindingType kind, int size, ShSemanticType type) 00083 : m_uniform(!ShContext::current()->parsing() && kind == SH_TEMP), 00084 m_kind(kind), m_specialType(type), 00085 m_size(size), m_id(m_maxID++), m_locked(0), 00086 m_values(0), 00087 m_eval(0) 00088 { 00089 if (m_uniform || m_kind == SH_CONST) addValues(); 00090 switch (m_kind) { 00091 case SH_INPUT: 00092 assert(ShContext::current()->parsing()); 00093 ShContext::current()->parsing()->inputs.push_back(this); 00094 break; 00095 case SH_OUTPUT: 00096 assert(ShContext::current()->parsing()); 00097 ShContext::current()->parsing()->outputs.push_back(this); 00098 break; 00099 case SH_INOUT: 00100 assert(ShContext::current()->parsing()); 00101 ShContext::current()->parsing()->outputs.push_back(this); 00102 ShContext::current()->parsing()->inputs.push_back(this); 00103 break; 00104 default: 00105 // Do nothing 00106 break; 00107 } 00108 00109 switch (type) { 00110 case SH_ATTRIB: 00111 range(0, 1.0); 00112 break; 00113 case SH_POINT: 00114 case SH_VECTOR: 00115 case SH_NORMAL: 00116 case SH_POSITION: 00117 range(-1.0, 1.0); 00118 break; 00119 case SH_TEXCOORD: 00120 case SH_COLOR: 00121 range(0, 1.0); 00122 break; 00123 default: 00124 range(0, 1.0); 00125 break; 00126 } 00127 } 00128 00129 ShVariableNode::~ShVariableNode() 00130 { 00131 detach_dependencies(); 00132 delete [] m_values; 00133 delete m_eval; 00134 m_values = 0; 00135 } 00136 00137 bool ShVariableNode::uniform() const 00138 { 00139 return m_uniform; 00140 } 00141 00142 bool ShVariableNode::hasValues() const 00143 { 00144 return (m_values != NULL); 00145 } 00146 00147 void ShVariableNode::lock() 00148 { 00149 m_locked++; 00150 } 00151 00152 void ShVariableNode::unlock() 00153 { 00154 m_locked--; 00155 if (m_locked == 0 && m_uniform) { 00156 00157 for (ShBoundIterator I = shBeginBound(); I != shEndBound(); ++I) { 00158 // TODO: Maybe pass in the backend unit to updateUniform 00159 if (I->second.node()) I->second.updateUniform(this); 00160 } 00161 00162 update_dependents(); 00163 } 00164 } 00165 00166 int ShVariableNode::size() const 00167 { 00168 return m_size; 00169 } 00170 00171 void ShVariableNode::size(int s) 00172 { 00173 SH_DEBUG_ASSERT(!m_values); 00174 m_size = s; 00175 } 00176 00177 void ShVariableNode::name(const std::string& n) 00178 { 00179 this->ShMeta::name(n); 00180 } 00181 00182 std::string ShVariableNode::name() const 00183 { 00184 00185 if (has_name()) return this->ShMeta::name(); 00186 00187 std::ostringstream stream; 00188 00189 // Special case for constants 00190 if (m_kind == SH_CONST) { 00191 if (m_size == 1) { 00192 stream << m_values[0]; 00193 } else { 00194 stream << "("; 00195 for (int i = 0; i < m_size; i++) { 00196 if (i > 0) stream << ", "; 00197 stream << m_values[i]; 00198 } 00199 stream << ")"; 00200 } 00201 return stream.str(); 00202 } 00203 00204 switch (m_kind) { 00205 case SH_INPUT: 00206 stream << "i"; 00207 break; 00208 case SH_OUTPUT: 00209 stream << "o"; 00210 break; 00211 case SH_INOUT: 00212 stream << "io"; 00213 break; 00214 case SH_TEMP: 00215 stream << "t"; 00216 break; 00217 case SH_CONST: 00218 stream << "c"; 00219 break; 00220 case SH_TEXTURE: 00221 stream << "tex"; 00222 break; 00223 case SH_STREAM: 00224 stream << "str"; 00225 break; 00226 } 00227 00228 stream << m_id; 00229 00230 return stream.str(); 00231 } 00232 00233 void ShVariableNode::range(ShVariableNode::ValueType low, ShVariableNode::ValueType high) 00234 { 00235 m_lowBound = low; 00236 m_highBound = high; 00237 } 00238 00239 ShVariableNode::ValueType ShVariableNode::lowBound() const 00240 { 00241 return m_lowBound; 00242 } 00243 00244 ShVariableNode::ValueType ShVariableNode::highBound() const 00245 { 00246 return m_highBound; 00247 } 00248 00249 ShBindingType ShVariableNode::kind() const 00250 { 00251 return m_kind; 00252 } 00253 00254 ShSemanticType ShVariableNode::specialType() const 00255 { 00256 return m_specialType; 00257 } 00258 00259 std::string ShVariableNode::nameOfType() const { 00260 std::ostringstream os; 00261 // TODO indicate ValueType properly 00262 os << "Sh" << ShBindingTypeName[ m_kind ] << ShSemanticTypeName[ m_specialType ] << m_size << "f"; 00263 return os.str(); 00264 } 00265 00266 void ShVariableNode::specialType(ShSemanticType type) 00267 { 00268 m_specialType = type; 00269 } 00270 00271 // TODO: also have an n-length set value, since updating the uniforms 00272 // will otherwise be horribly inefficient. 00273 void ShVariableNode::setValue(int i, ValueType value) 00274 { 00275 assert(m_values); 00276 if (i < 0 || i >= m_size) return; 00277 m_values[i] = value; 00278 00279 if (m_uniform && !m_locked) { 00280 for (ShBoundIterator I = shBeginBound(); I != shEndBound(); ++I) { 00281 // TODO: Maybe pass in the backend unit to updateUniform 00282 if (I->second.node()) I->second.updateUniform(this); 00283 } 00284 00285 update_dependents(); 00286 } 00287 } 00288 00289 ShVariableNode::ValueType ShVariableNode::getValue(int i) const 00290 { 00291 assert(m_values); 00292 assert(i >= 0 && i < m_size); 00293 return m_values[i]; 00294 } 00295 00296 void ShVariableNode::addValues() 00297 { 00298 if (m_values) return; 00299 m_values = new ValueType[m_size]; 00300 for (int i = 0; i < m_size; i++) m_values[i] = 0.0; 00301 } 00302 00303 void ShVariableNode::attach(const ShProgramNodePtr& evaluator) 00304 { 00305 SH_DEBUG_ASSERT(uniform()); 00306 if (!m_eval) m_eval = new ShVariableNodeEval; 00307 // TODO: Check that the program really evaluates this variable. 00308 00309 detach_dependencies(); 00310 00311 m_eval->value = evaluator; 00312 00313 if (m_eval->value) { 00314 for (ShProgramNode::VarList::const_iterator I = m_eval->value->uniforms_begin(); 00315 I != m_eval->value->uniforms_end(); ++I) { 00316 if ((*I).object() == this) continue; 00317 (*I)->add_dependent(this); 00318 } 00319 00320 update(); 00321 } 00322 } 00323 00324 void ShVariableNode::update() 00325 { 00326 if (!m_eval) m_eval = new ShVariableNodeEval; 00327 if (!m_eval->value) return; 00328 00329 evaluate(m_eval->value); 00330 } 00331 00332 const ShPointer<ShProgramNode>& ShVariableNode::evaluator() const 00333 { 00334 if (!m_eval) m_eval = new ShVariableNodeEval; 00335 return m_eval->value; 00336 } 00337 00338 #ifdef SH_USE_MEMORY_POOL 00339 void* ShVariableNode::operator new(std::size_t size) 00340 { 00341 if (size != sizeof(ShVariableNode)) return ::operator new(size); 00342 if (!m_pool) m_pool = new ShPool(sizeof(ShVariableNode), 32768); 00343 return m_pool->alloc(); 00344 } 00345 00346 void ShVariableNode::operator delete(void* ptr) 00347 { 00348 // Really, if we don't have a pool, we should throw an exception or something. 00349 return m_pool->free(ptr); 00350 } 00351 #endif 00352 00353 void ShVariableNode::add_dependent(ShVariableNode* dep) 00354 { 00355 if (std::find(m_dependents.begin(), m_dependents.end(), dep) != m_dependents.end()) return; 00356 m_dependents.push_back(dep); 00357 } 00358 00359 void ShVariableNode::remove_dependent(ShVariableNode* dep) 00360 { 00361 m_dependents.remove(dep); 00362 } 00363 00364 void ShVariableNode::update_dependents() 00365 { 00366 for (std::list<ShVariableNode*>::iterator I = m_dependents.begin(); 00367 I != m_dependents.end(); ++I) { 00368 (*I)->update(); 00369 } 00370 } 00371 00372 void ShVariableNode::detach_dependencies() 00373 { 00374 if (!m_eval) return; 00375 if (m_eval->value) { 00376 for (ShProgramNode::VarList::const_iterator I = m_eval->value->uniforms_begin(); 00377 I != m_eval->value->uniforms_end(); ++I) { 00378 if ((*I).object() == this) continue; 00379 (*I)->remove_dependent(this); 00380 } 00381 m_eval->value = 0; 00382 } 00383 } 00384 00385 int ShVariableNode::m_maxID = 0; 00386 #ifdef SH_USE_MEMORY_POOL 00387 ShPool* ShVariableNode::m_pool = 0; 00388 #endif 00389 }

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