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 "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
00050
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
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
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 }