00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00027
#include <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
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
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
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
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
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
00272
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
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
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
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
}