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 <dlfcn.h>
00028
#include <unistd.h>
00029
#include <sys/wait.h>
00030
00031
#include "Gcc.hpp"
00032
#include "ShDebug.hpp"
00033
#include "ShStream.hpp"
00034
00035
#ifdef HAVE_CONFIG_H
00036
#include "config.h"
00037
#endif
00038
00039
#ifdef SH_GCC_DEBUG
00040
# define SH_GCC_DEBUG_PRINT(x) SH_DEBUG_PRINT(x)
00041
#else
00042
# define SH_GCC_DEBUG_PRINT(x) do { } while(0)
00043
#endif
00044
00045
void sh_gcc_backend_lookup1D(SH::ShTextureNode* tex,
float* src,
float* dst)
00046 {
00047
if (tex->traits().filtering() == SH::ShTextureTraits::SH_FILTER_MIPMAP)
00048 {
00049 SH_GCC_DEBUG_PRINT(
"1D/SH_FILTER_MIPMAP textures unsupported...");
00050
return;
00051 }
00052
00053
SH::ShHostStoragePtr storage = SH::shref_dynamic_cast<SH::ShHostStorage>(tex->memory()->findStorage(
"host"));
00054
if (!storage)
00055 {
00056 SH_GCC_DEBUG_PRINT(
"failed to find host storage...");
00057 }
00058
float* data = (
float*)storage->data();
00059
00060
switch(tex->traits().interpolation())
00061 {
00062
case 0:
00063 {
00064
00065
float s = src[0];
00066
switch(tex->traits().wrapping())
00067 {
00068
case SH::ShTextureTraits::SH_WRAP_CLAMP:
00069
case SH::ShTextureTraits::SH_WRAP_CLAMP_TO_EDGE:
00070 s = std::max((
float)0, std::min((
float)1, s));
00071
break;
00072
case SH::ShTextureTraits::SH_WRAP_REPEAT:
00073 s = s -
floor(s);
00074
break;
00075 }
00076
00077
int u = (
int)
floor(tex->width()*s);
00078 u = std::max(0, std::min(tex->width()-1, u));
00079
00080
switch(tex->traits().clamping())
00081 {
00082
case SH::ShTextureTraits::SH_CLAMPED:
00083
for(
int i = 0; i < tex->size(); i++)
00084 {
00085 dst[i] = std::max((
float)0, std::min((
float)1, data[tex->size()*u + i]));
00086 }
00087
break;
00088
case SH::ShTextureTraits::SH_UNCLAMPED:
00089
for(
int i = 0; i < tex->size(); i++)
00090 {
00091 dst[i] = data[tex->size()*u + i];
00092 }
00093
break;
00094 }
00095
break;
00096 }
00097
case 1:
00098
00099 SH_GCC_DEBUG_PRINT(
"1D/LINEAR textures unsupported...");
00100
break;
00101 }
00102 }
00103
00104
void sh_gcc_backend_lookup2D(SH::ShTextureNode* tex,
float* src,
float* dst)
00105 {
00106
if (tex->traits().filtering() == SH::ShTextureTraits::SH_FILTER_MIPMAP)
00107 {
00108 SH_GCC_DEBUG_PRINT(
"2D/SH_FILTER_MIPMAP textures unsupported...");
00109
return;
00110 }
00111
00112
SH::ShHostStoragePtr storage = SH::shref_dynamic_cast<SH::ShHostStorage>(tex->memory()->findStorage(
"host"));
00113
if (!storage)
00114 {
00115 SH_GCC_DEBUG_PRINT(
"failed to find host storage...");
00116 }
00117
float* data = (
float*)storage->data();
00118
00119
switch(tex->traits().interpolation())
00120 {
00121
case 0:
00122 {
00123
00124
float s = src[0];
00125
switch(tex->traits().wrapping())
00126 {
00127
case SH::ShTextureTraits::SH_WRAP_CLAMP:
00128
case SH::ShTextureTraits::SH_WRAP_CLAMP_TO_EDGE:
00129 s = std::max((
float)0, std::min((
float)1, s));
00130
break;
00131
case SH::ShTextureTraits::SH_WRAP_REPEAT:
00132 s = s -
floor(s);
00133
break;
00134 }
00135
00136
float t = src[1];
00137
switch(tex->traits().wrapping())
00138 {
00139
case SH::ShTextureTraits::SH_WRAP_CLAMP:
00140
case SH::ShTextureTraits::SH_WRAP_CLAMP_TO_EDGE:
00141 t = std::max((
float)0, std::min((
float)1, t));
00142
break;
00143
case SH::ShTextureTraits::SH_WRAP_REPEAT:
00144 t = t -
floor(t);
00145
break;
00146 }
00147
00148
int u = (
int)
floor(tex->width()*s);
00149 u = std::max(0, std::min(tex->width()-1, u));
00150
00151
int v = (
int)
floor(tex->width()*t);
00152 v = std::max(0, std::min(tex->height()-1, v));
00153
00154
int offset = v*tex->width()+u;
00155
00156
switch(tex->traits().clamping())
00157 {
00158
case SH::ShTextureTraits::SH_CLAMPED:
00159
for(
int i = 0; i < tex->size(); i++)
00160 {
00161 dst[i] = std::max((
float)0, std::min((
float)1, data[tex->size()*offset + i]));
00162 }
00163
break;
00164
case SH::ShTextureTraits::SH_UNCLAMPED:
00165
for(
int i = 0; i < tex->size(); i++)
00166 {
00167 dst[i] = data[tex->size()*offset + i];
00168 }
00169
break;
00170 }
00171
break;
00172 }
00173
case 1:
00174
00175 SH_GCC_DEBUG_PRINT(
"2D/LINEAR textures unsupported...");
00176
break;
00177 }
00178 }
00179
00180
void sh_gcc_backend_lookupRECT(SH::ShTextureNode* tex,
float* src,
float* dst)
00181 {
00182
if (tex->traits().filtering() == SH::ShTextureTraits::SH_FILTER_MIPMAP)
00183 {
00184 SH_GCC_DEBUG_PRINT(
"RECT/SH_FILTER_MIPMAP textures unsupported...");
00185
return;
00186 }
00187
00188
SH::ShHostStoragePtr storage = SH::shref_dynamic_cast<SH::ShHostStorage>(tex->memory()->findStorage(
"host"));
00189
if (!storage)
00190 {
00191 SH_GCC_DEBUG_PRINT(
"failed to find host storage...");
00192 }
00193
float* data = (
float*)storage->data();
00194
00195
switch(tex->traits().interpolation())
00196 {
00197
case 0:
00198 {
00199
00200
float s = src[0];
00201
switch(tex->traits().wrapping())
00202 {
00203
case SH::ShTextureTraits::SH_WRAP_CLAMP:
00204
case SH::ShTextureTraits::SH_WRAP_CLAMP_TO_EDGE:
00205 s = std::max((
float)0, std::min((
float)1, s));
00206
break;
00207
case SH::ShTextureTraits::SH_WRAP_REPEAT:
00208 s = s -
floor(s);
00209
break;
00210 }
00211
00212
float t = src[1];
00213
switch(tex->traits().wrapping())
00214 {
00215
case SH::ShTextureTraits::SH_WRAP_CLAMP:
00216
case SH::ShTextureTraits::SH_WRAP_CLAMP_TO_EDGE:
00217 t = std::max((
float)0, std::min((
float)1, t));
00218
break;
00219
case SH::ShTextureTraits::SH_WRAP_REPEAT:
00220 t = t -
floor(t);
00221
break;
00222 }
00223
00224
int u = (
int)
floor(tex->width()*s);
00225 u = std::max(0, std::min(tex->width()-1, u));
00226
00227
int v = (
int)
floor(tex->width()*t);
00228 v = std::max(0, std::min(tex->height()-1, v));
00229
00230
int offset = v*tex->width()+u;
00231
00232
switch(tex->traits().clamping())
00233 {
00234
case SH::ShTextureTraits::SH_CLAMPED:
00235
for(
int i = 0; i < tex->size(); i++)
00236 {
00237 dst[i] = std::max((
float)0, std::min((
float)1, data[tex->size()*offset + i]));
00238 }
00239
break;
00240
case SH::ShTextureTraits::SH_UNCLAMPED:
00241
for(
int i = 0; i < tex->size(); i++)
00242 {
00243 dst[i] = data[tex->size()*offset + i];
00244 }
00245
break;
00246 }
00247
break;
00248 }
00249
case 1:
00250
00251 SH_GCC_DEBUG_PRINT(
"RECT/LINEAR textures unsupported...");
00252
break;
00253 }
00254 }
00255
00256
void sh_gcc_backend_lookup3D(SH::ShTextureNode* tex,
float* src,
float* dst)
00257 {
00258 SH_GCC_DEBUG_PRINT(
"3D textures unsupported...");
00259 }
00260
00261
void sh_gcc_backend_lookupCUBE(SH::ShTextureNode* tex,
float* src,
float* dst)
00262 {
00263 SH_GCC_DEBUG_PRINT(
"CUBE textures unsupported...");
00264 }
00265
00266
extern "C" void sh_gcc_backend_lookup(
void *t,
float* src,
float* dst)
00267 {
00268
00269 SH::ShTextureNode* tex = (SH::ShTextureNode*)t;
00270
00271
switch(tex->dims())
00272 {
00273
case SH::SH_TEXTURE_1D:
00274 sh_gcc_backend_lookup1D(tex, src, dst);
00275
break;
00276
case SH::SH_TEXTURE_2D:
00277 sh_gcc_backend_lookup2D(tex, src, dst);
00278
break;
00279
case SH::SH_TEXTURE_RECT:
00280 sh_gcc_backend_lookupRECT(tex, src, dst);
00281
break;
00282
case SH::SH_TEXTURE_3D:
00283 sh_gcc_backend_lookup3D(tex, src, dst);
00284
break;
00285
case SH::SH_TEXTURE_CUBE:
00286 sh_gcc_backend_lookupCUBE(tex, src, dst);
00287
break;
00288
default:
00289 SH_GCC_DEBUG_PRINT(
"unknown texture dimension (" << tex->dims() <<
")");
00290
break;
00291 }
00292 }
00293
00294
void sh_gcc_backend_lookupi1D(SH::ShTextureNode* tex,
float* src,
float* dst)
00295 {
00296
if (tex->traits().filtering() == SH::ShTextureTraits::SH_FILTER_MIPMAP)
00297 {
00298 SH_GCC_DEBUG_PRINT(
"1D/SH_FILTER_MIPMAP textures unsupported...");
00299
return;
00300 }
00301
00302
SH::ShHostStoragePtr storage = SH::shref_dynamic_cast<SH::ShHostStorage>(tex->memory()->findStorage(
"host"));
00303
if (!storage)
00304 {
00305 SH_GCC_DEBUG_PRINT(
"failed to find host storage...");
00306 }
00307
float* data = (
float*)storage->data();
00308
00309
switch(tex->traits().interpolation())
00310 {
00311
case 0:
00312 {
00313
00314
float s = src[0];
00315
switch(tex->traits().wrapping())
00316 {
00317
case SH::ShTextureTraits::SH_WRAP_CLAMP:
00318
case SH::ShTextureTraits::SH_WRAP_CLAMP_TO_EDGE:
00319 s = std::max((
float)0, std::min((
float)tex->width(), s));
00320
break;
00321
case SH::ShTextureTraits::SH_WRAP_REPEAT:
00322 s = tex->width()*(s/tex->width() -
floor(s/tex->width()));
00323
break;
00324 }
00325
00326
int u = (
int)
floor(s);
00327 u = std::max(0, std::min(tex->width()-1, u));
00328
00329
switch(tex->traits().clamping())
00330 {
00331
case SH::ShTextureTraits::SH_CLAMPED:
00332
for(
int i = 0; i < tex->size(); i++)
00333 {
00334 dst[i] = std::max((
float)0, std::min((
float)1, data[tex->size()*u + i]));
00335 }
00336
break;
00337
case SH::ShTextureTraits::SH_UNCLAMPED:
00338
for(
int i = 0; i < tex->size(); i++)
00339 {
00340 dst[i] = data[tex->size()*u + i];
00341 }
00342
break;
00343 }
00344
break;
00345 }
00346
case 1:
00347
00348 SH_GCC_DEBUG_PRINT(
"1D/LINEAR textures unsupported...");
00349
break;
00350 }
00351 }
00352
00353
void sh_gcc_backend_lookupi2D(SH::ShTextureNode* tex,
float* src,
float* dst)
00354 {
00355
if (tex->traits().filtering() == SH::ShTextureTraits::SH_FILTER_MIPMAP)
00356 {
00357 SH_GCC_DEBUG_PRINT(
"2D/SH_FILTER_MIPMAP textures unsupported...");
00358
return;
00359 }
00360
00361
SH::ShHostStoragePtr storage = SH::shref_dynamic_cast<SH::ShHostStorage>(tex->memory()->findStorage(
"host"));
00362
if (!storage)
00363 {
00364 SH_GCC_DEBUG_PRINT(
"failed to find host storage...");
00365 }
00366
float* data = (
float*)storage->data();
00367
00368
switch(tex->traits().interpolation())
00369 {
00370
case 0:
00371 {
00372
00373
float s = src[0];
00374
switch(tex->traits().wrapping())
00375 {
00376
case SH::ShTextureTraits::SH_WRAP_CLAMP:
00377
case SH::ShTextureTraits::SH_WRAP_CLAMP_TO_EDGE:
00378 s = std::max((
float)0, std::min((
float)tex->width(), s));
00379
break;
00380
case SH::ShTextureTraits::SH_WRAP_REPEAT:
00381 s = tex->width()*(s/tex->width() -
floor(s/tex->width()));
00382
break;
00383 }
00384
00385
float t = src[1];
00386
switch(tex->traits().wrapping())
00387 {
00388
case SH::ShTextureTraits::SH_WRAP_CLAMP:
00389
case SH::ShTextureTraits::SH_WRAP_CLAMP_TO_EDGE:
00390 t = std::max((
float)0, std::min((
float)tex->height(), t));
00391
break;
00392
case SH::ShTextureTraits::SH_WRAP_REPEAT:
00393 t = tex->height()*(t/tex->height() -
floor(t/tex->height()));
00394
break;
00395 }
00396
00397
int u = (
int)
floor(s);
00398 u = std::max(0, std::min(tex->width()-1, u));
00399
00400
int v = (
int)
floor(t);
00401 v = std::max(0, std::min(tex->height()-1, v));
00402
00403
int offset = v*tex->width()+u;
00404
00405
switch(tex->traits().clamping())
00406 {
00407
case SH::ShTextureTraits::SH_CLAMPED:
00408
for(
int i = 0; i < tex->size(); i++)
00409 {
00410 dst[i] = std::max((
float)0, std::min((
float)1, data[tex->size()*offset + i]));
00411 }
00412
break;
00413
case SH::ShTextureTraits::SH_UNCLAMPED:
00414
for(
int i = 0; i < tex->size(); i++)
00415 {
00416 dst[i] = data[tex->size()*offset + i];
00417 }
00418
break;
00419 }
00420
break;
00421 }
00422
case 1:
00423
00424 SH_GCC_DEBUG_PRINT(
"2D/LINEAR textures unsupported...");
00425
break;
00426 }
00427 }
00428
00429
void sh_gcc_backend_lookupiRECT(SH::ShTextureNode* tex,
float* src,
float* dst)
00430 {
00431
if (tex->traits().filtering() == SH::ShTextureTraits::SH_FILTER_MIPMAP)
00432 {
00433 SH_GCC_DEBUG_PRINT(
"RECT/SH_FILTER_MIPMAP textures unsupported...");
00434
return;
00435 }
00436
00437
SH::ShHostStoragePtr storage = SH::shref_dynamic_cast<SH::ShHostStorage>(tex->memory()->findStorage(
"host"));
00438
if (!storage)
00439 {
00440 SH_GCC_DEBUG_PRINT(
"failed to find host storage...");
00441 }
00442
float* data = (
float*)storage->data();
00443
00444
switch(tex->traits().interpolation())
00445 {
00446
case 0:
00447 {
00448
00449
float s = src[0];
00450
switch(tex->traits().wrapping())
00451 {
00452
case SH::ShTextureTraits::SH_WRAP_CLAMP:
00453
case SH::ShTextureTraits::SH_WRAP_CLAMP_TO_EDGE:
00454 s = std::max((
float)0, std::min((
float)tex->width(), s));
00455
break;
00456
case SH::ShTextureTraits::SH_WRAP_REPEAT:
00457 s = tex->width()*(s/tex->width() -
floor(s/tex->width()));
00458
break;
00459 }
00460
00461
float t = src[1];
00462
switch(tex->traits().wrapping())
00463 {
00464
case SH::ShTextureTraits::SH_WRAP_CLAMP:
00465
case SH::ShTextureTraits::SH_WRAP_CLAMP_TO_EDGE:
00466 t = std::max((
float)0, std::min((
float)tex->height(), t));
00467
break;
00468
case SH::ShTextureTraits::SH_WRAP_REPEAT:
00469 t = tex->height()*(t/tex->height() -
floor(t/tex->height()));
00470
break;
00471 }
00472
00473
int u = (
int)
floor(s);
00474 u = std::max(0, std::min(tex->width()-1, u));
00475
00476
int v = (
int)
floor(t);
00477 v = std::max(0, std::min(tex->height()-1, v));
00478
00479
int offset = v*tex->width()+u;
00480
00481
switch(tex->traits().clamping())
00482 {
00483
case SH::ShTextureTraits::SH_CLAMPED:
00484
for(
int i = 0; i < tex->size(); i++)
00485 {
00486 dst[i] = std::max((
float)0, std::min((
float)1, data[tex->size()*offset + i]));
00487 }
00488
break;
00489
case SH::ShTextureTraits::SH_UNCLAMPED:
00490
for(
int i = 0; i < tex->size(); i++)
00491 {
00492 dst[i] = data[tex->size()*offset + i];
00493 }
00494
break;
00495 }
00496
break;
00497 }
00498
case 1:
00499
00500 SH_GCC_DEBUG_PRINT(
"RECT/LINEAR textures unsupported...");
00501
break;
00502 }
00503 }
00504
00505
void sh_gcc_backend_lookupi3D(SH::ShTextureNode* tex,
float* src,
float* dst)
00506 {
00507 SH_GCC_DEBUG_PRINT(
"3D textures unsupported...");
00508 }
00509
00510
void sh_gcc_backend_lookupiCUBE(SH::ShTextureNode* tex,
float* src,
float* dst)
00511 {
00512 SH_GCC_DEBUG_PRINT(
"CUBE textures unsupported...");
00513 }
00514
00515
extern "C" void sh_gcc_backend_lookupi(
void* t,
float* src,
float* dst)
00516 {
00517
00518 SH::ShTextureNode* tex = (SH::ShTextureNode*)t;
00519
00520
switch(tex->dims())
00521 {
00522
case SH::SH_TEXTURE_1D:
00523 sh_gcc_backend_lookupi1D(tex, src, dst);
00524
break;
00525
case SH::SH_TEXTURE_2D:
00526 sh_gcc_backend_lookupi2D(tex, src, dst);
00527
break;
00528
case SH::SH_TEXTURE_RECT:
00529 sh_gcc_backend_lookupiRECT(tex, src, dst);
00530
break;
00531
case SH::SH_TEXTURE_3D:
00532 sh_gcc_backend_lookupi3D(tex, src, dst);
00533
break;
00534
case SH::SH_TEXTURE_CUBE:
00535 sh_gcc_backend_lookupiCUBE(tex, src, dst);
00536
break;
00537
default:
00538 SH_GCC_DEBUG_PRINT(
"unknown texture dimension (" << tex->dims() <<
")");
00539
break;
00540 }
00541 }
00542
00543 std::string encode(
const SH::ShVariable& v)
00544 {
00545 std::stringstream ret;
00546
if (v.
neg()) ret <<
"-";
00547 ret << v.name();
00548 ret << v.
swizzle();
00549
return ret.str();
00550 }
00551
00552
namespace ShGcc {
00553
00554 GccVariable::GccVariable(
void) :
00555 m_num(-1),
00556 m_size(-1)
00557 {
00558 }
00559
00560 GccVariable::GccVariable(
int num,
const std::string& name) :
00561 m_num(num),
00562 m_name(name),
00563 m_size(-1)
00564 {
00565 }
00566
00567 GccVariable::GccVariable(
int num,
const std::string& name,
int size) :
00568 m_num(num),
00569 m_name(name),
00570 m_size(size)
00571 {
00572 }
00573
00574 GccBackendCode::LabelFunctor::LabelFunctor(std::map<SH::ShCtrlGraphNodePtr, int>& label_map) :
00575 m_cur_label(0),
00576 m_label_map(label_map)
00577 {
00578 }
00579
00580
void GccBackendCode::LabelFunctor::operator()(
SH::ShCtrlGraphNode* node)
00581 {
00582 m_label_map[node] = m_cur_label++;
00583 }
00584
00585 GccBackendCode::EmitFunctor::EmitFunctor(GccBackendCode* bec) :
00586 m_bec(bec)
00587 {
00588 }
00589
00590
void GccBackendCode::EmitFunctor::operator()(
SH::ShCtrlGraphNode* node)
00591 {
00592 m_bec->emit(node);
00593 }
00594
00595 GccBackendCode::GccBackendCode(
const SH::ShProgramNodeCPtr& program) :
00596 m_program(program),
00597 m_handle(NULL),
00598 m_func(NULL),
00599 m_cur_temp(0),
00600 m_params(NULL)
00601 {
00602 SH_GCC_DEBUG_PRINT(__FUNCTION__);
00603 }
00604
00605 GccBackendCode::~GccBackendCode(
void)
00606 {
00607 SH_GCC_DEBUG_PRINT(__FUNCTION__);
00608 }
00609
00610
bool GccBackendCode::allocateRegister(
const SH::ShVariableNodePtr& var)
00611 {
00612 SH_GCC_DEBUG_PRINT(__FUNCTION__);
00613
return false;
00614 }
00615
00616
void GccBackendCode::freeRegister(
const SH::ShVariableNodePtr& var)
00617 {
00618 SH_GCC_DEBUG_PRINT(__FUNCTION__);
00619 }
00620
00621
void GccBackendCode::upload(
void)
00622 {
00623 SH_GCC_DEBUG_PRINT(__FUNCTION__);
00624 }
00625
00626
void GccBackendCode::bind(
void)
00627 {
00628 SH_GCC_DEBUG_PRINT(__FUNCTION__);
00629 }
00630
00631
void GccBackendCode::updateUniform(
const SH::ShVariableNodePtr& uniform)
00632 {
00633 SH_GCC_DEBUG_PRINT(__FUNCTION__);
00634 }
00635
00636 std::ostream& GccBackendCode::print(std::ostream& out)
00637 {
00638 SH_GCC_DEBUG_PRINT(__FUNCTION__);
00639
return out;
00640 }
00641
00642 std::ostream& GccBackendCode::printInputOutputFormat(std::ostream& out)
00643 {
00644 SH_GCC_DEBUG_PRINT(__FUNCTION__);
00645
return out;
00646 }
00647
00648
void GccBackendCode::allocate_consts(
void)
00649 {
00650
int cur_const = 0;
00651
for (SH::ShProgramNode::VarList::const_iterator itr = m_program->constants.begin();
00652 itr != m_program->constants.end();
00653 itr++)
00654 {
00655
SH::ShVariableNodePtr node = (*itr);
00656
00657
00658
char name[128];
00659 sprintf(name,
"var_c_%d", cur_const);
00660 m_varmap[node] = GccVariable(cur_const++, name);
00661
00662
00663 m_code <<
"float " << name <<
"[" << node->size() <<
"] = {";
00664
for (
int i = 0; i < node->size(); i++)
00665 {
00666
if (i == 0)
00667 m_code << node->getValue(i);
00668
else
00669 m_code <<
", " << node->getValue(i);
00670 }
00671 m_code <<
"};" << std::endl;
00672 }
00673
00674 SH_GCC_DEBUG_PRINT(
"Found " << cur_const <<
" consts...");
00675 }
00676
00677
void GccBackendCode::allocate_inputs(
void)
00678 {
00679
int cur_input = 0;
00680
for (SH::ShProgramNode::VarList::const_iterator itr = m_program->inputs.begin();
00681 itr != m_program->inputs.end();
00682 itr++)
00683 {
00684
SH::ShVariableNodePtr node = (*itr);
00685
00686
00687
char name[128];
00688 sprintf(name,
"inputs[%d]", cur_input);
00689 m_varmap[node] = GccVariable(cur_input++, name);
00690 }
00691
00692 SH_GCC_DEBUG_PRINT(
"Found " << cur_input <<
" inputs...");
00693 }
00694
00695
void GccBackendCode::allocate_outputs(
void)
00696 {
00697
int cur_output = 0;
00698
for (SH::ShProgramNode::VarList::const_iterator itr = m_program->outputs.begin();
00699 itr != m_program->outputs.end();
00700 itr++)
00701 {
00702
SH::ShVariableNodePtr node = (*itr);
00703
00704
00705
char name[128];
00706 sprintf(name,
"outputs[%d]", cur_output);
00707 m_varmap[node] = GccVariable(cur_output++, name);
00708 }
00709
00710 SH_GCC_DEBUG_PRINT(
"Found " << cur_output <<
" outputs...");
00711 }
00712
00713
void GccBackendCode::allocate_streams(
void)
00714 {
00715
int cur_stream = 0;
00716
for (SH::ShProgramNode::ChannelList::const_iterator itr = m_program->channels.begin();
00717 itr != m_program->channels.end();
00718 itr++)
00719 {
00720
SH::ShChannelNodePtr node = (*itr);
00721
00722
00723
char name[128];
00724 sprintf(name,
"streams[%d]", cur_stream);
00725 m_varmap[node] = GccVariable(cur_stream++, name);
00726 m_streams.push_back(node);
00727 }
00728
00729 SH_GCC_DEBUG_PRINT(
"Found " << cur_stream <<
" streams...");
00730 }
00731
00732
void GccBackendCode::allocate_textures(
void)
00733 {
00734
int cur_texture = 0;
00735
for (SH::ShProgramNode::TexList::const_iterator itr = m_program->textures.begin();
00736 itr != m_program->textures.end();
00737 itr++)
00738 {
00739
SH::ShTextureNodePtr node = (*itr);
00740
00741
00742
char name[128];
00743 sprintf(name,
"textures[%d]", cur_texture);
00744 m_varmap[node] = GccVariable(cur_texture++, name);
00745 m_textures.push_back(node);
00746 }
00747
00748 SH_GCC_DEBUG_PRINT(
"Found " << cur_texture <<
" textures...");
00749 }
00750
00751
void GccBackendCode::allocate_uniforms(
void)
00752 {
00753
int cur_uniform = 0;
00754 std::vector<SH::ShVariableNodePtr> uniforms;
00755
00756
for (SH::ShProgramNode::VarList::const_iterator itr = m_program->uniforms.begin();
00757 itr != m_program->uniforms.end();
00758 itr++)
00759 {
00760
SH::ShVariableNodePtr node = (*itr);
00761
00762
00763
char name[128];
00764 sprintf(name,
"params[%d]", cur_uniform);
00765 m_varmap[node] = GccVariable(cur_uniform++, name);
00766 uniforms.push_back(node);
00767 }
00768
00769 m_params =
new float*[uniforms.size()];
00770
for(
unsigned int i = 0; i < uniforms.size(); i++)
00771 {
00772
SH::ShVariableNodePtr node = uniforms[i];
00773 m_params[i] =
new float[node->size()];
00774
00775
if (node->hasValues())
00776 {
00777
for(
int j = 0; j < node->size(); j++)
00778 {
00779 m_params[i][j] = node->getValue(j);
00780 }
00781 }
00782
else
00783 {
00784
for(
int j = 0; j < node->size(); j++)
00785 {
00786 m_params[i][j] = 0;
00787 }
00788 }
00789 }
00790
00791 SH_GCC_DEBUG_PRINT(
"Found " << cur_uniform <<
" uniforms...");
00792 }
00793
00794 std::string GccBackendCode::resolve(
const SH::ShVariable& v)
00795 {
00796 GccVariable v2;
00797 std::map<SH::ShVariableNodePtr, GccVariable>::iterator itr = m_varmap.find(v.
node());
00798
00799
if (itr == m_varmap.end())
00800 {
00801
00802 SH_DEBUG_ASSERT(v.
node()->kind() == SH::SH_TEMP);
00803
00804
00805
char name[128];
00806 sprintf(name,
"var_t_%d", m_cur_temp);
00807 v2 = GccVariable(m_cur_temp++, name, v.
node()->size());
00808 m_varmap[v.
node()] = v2;
00809 m_temps.push_back(v2);
00810 }
00811
else
00812 {
00813 v2 = (*itr).second;
00814 }
00815
00816 std::stringstream buf;
00817
if (v.
neg()) buf <<
"-";
00818 buf << v2.m_name;
00819
return buf.str();
00820 }
00821
00822 std::string GccBackendCode::resolve(
const SH::ShVariable& v,
int idx)
00823 {
00824 GccVariable v2;
00825 std::map<SH::ShVariableNodePtr, GccVariable>::iterator itr = m_varmap.find(v.
node());
00826
00827
if (itr == m_varmap.end())
00828 {
00829
00830 SH_DEBUG_ASSERT(v.
node()->kind() == SH::SH_TEMP);
00831
00832
00833
char name[128];
00834 sprintf(name,
"var_t_%d", m_cur_temp);
00835 v2 = GccVariable(m_cur_temp++, name, v.
node()->size());
00836 m_varmap[v.
node()] = v2;
00837 m_temps.push_back(v2);
00838 }
00839
else
00840 {
00841 v2 = (*itr).second;
00842 }
00843
00844 std::stringstream buf;
00845
if (v.
neg()) buf <<
"-";
00846 buf << v2.m_name;
00847 buf <<
"[" << v.
swizzle()[idx] <<
"]";
00848
return buf.str();
00849 }
00850
00851
void GccBackendCode::emit(
const SH::ShStatement& stmt)
00852 {
00853
00854
switch(SH::opInfo[stmt.
op].arity)
00855 {
00856
case 0:
00857 m_code <<
" // "
00858 << SH::opInfo[stmt.
op].name <<
" "
00859 << encode(stmt.
dest)
00860 << std::endl;
00861
break;
00862
case 1:
00863 m_code <<
" // "
00864 << SH::opInfo[stmt.
op].name <<
" "
00865 << encode(stmt.
dest) <<
", "
00866 << encode(stmt.
src[0])
00867 << std::endl;
00868
break;
00869
case 2:
00870 m_code <<
" // "
00871 << SH::opInfo[stmt.
op].name <<
" "
00872 << encode(stmt.
dest) <<
", "
00873 << encode(stmt.
src[0]) <<
", "
00874 << encode(stmt.
src[1])
00875 << std::endl;
00876
break;
00877
case 3:
00878 m_code <<
" // "
00879 << SH::opInfo[stmt.
op].name <<
" "
00880 << encode(stmt.
dest) <<
", "
00881 << encode(stmt.
src[0]) <<
", "
00882 << encode(stmt.
src[1]) <<
", "
00883 << encode(stmt.
src[2])
00884 << std::endl;
00885
break;
00886
default:
00887 m_code <<
" // "
00888 << SH::opInfo[stmt.
op].name <<
" "
00889 <<
"<unknown format>"
00890 << std::endl;
00891
break;
00892 }
00893
00894
00895
switch(stmt.
op)
00896 {
00897
case SH::SH_OP_ASN:
00898 {
00899
for(
int i = 0; i < stmt.
dest.size(); i++)
00900 {
00901 m_code <<
" "
00902 << resolve(stmt.
dest, i)
00903 <<
" = "
00904 << resolve(stmt.
src[0], i)
00905 <<
";" << std::endl;
00906 }
00907
00908
break;
00909 }
00910
case SH::SH_OP_NEG:
00911 {
00912
for(
int i = 0; i < stmt.
dest.size(); i++)
00913 {
00914 m_code <<
" "
00915 << resolve(stmt.
dest, i)
00916 <<
" = -"
00917 << resolve(stmt.
src[0], i)
00918 <<
";" << std::endl;
00919 }
00920
00921
break;
00922 }
00923
case SH::SH_OP_ADD:
00924 {
00925
for(
int i = 0; i < stmt.
dest.size(); i++)
00926 {
00927 m_code <<
" "
00928 << resolve(stmt.
dest, i)
00929 <<
" = "
00930 << resolve(stmt.
src[0], (stmt.
src[0].size() > 1 ? i : 0))
00931 <<
" + "
00932 << resolve(stmt.
src[1], (stmt.
src[1].size() > 1 ? i : 0))
00933 <<
";" << std::endl;
00934 }
00935
break;
00936 }
00937
case SH::SH_OP_MUL:
00938 {
00939
for(
int i = 0; i < stmt.
dest.size(); i++)
00940 {
00941 m_code <<
" "
00942 << resolve(stmt.
dest, i)
00943 <<
" = "
00944 << resolve(stmt.
src[0], (stmt.
src[0].size() > 1 ? i : 0))
00945 <<
" * "
00946 << resolve(stmt.
src[1], (stmt.
src[1].size() > 1 ? i : 0))
00947 <<
";" << std::endl;
00948 }
00949
break;
00950 }
00951
case SH::SH_OP_DIV:
00952 {
00953
for(
int i = 0; i < stmt.
dest.size(); i++)
00954 {
00955 m_code <<
" "
00956 << resolve(stmt.
dest, i)
00957 <<
" = "
00958 << resolve(stmt.
src[0], (stmt.
src[0].size() > 1 ? i : 0))
00959 <<
" / "
00960 << resolve(stmt.
src[1], (stmt.
src[1].size() > 1 ? i : 0))
00961 <<
";" << std::endl;
00962 }
00963
break;
00964 }
00965
case SH::SH_OP_SLT:
00966 {
00967
bool scalar0 = (stmt.
src[0].size() == 1);
00968
bool scalar1 = (stmt.
src[1].size() == 1);
00969
for(
int i = 0; i < stmt.
dest.size(); i++)
00970 {
00971 m_code <<
" "
00972 << resolve(stmt.
dest, i)
00973 <<
" = ("
00974 << resolve(stmt.
src[0], (scalar0 ? 0 : i))
00975 <<
" < "
00976 << resolve(stmt.
src[1], (scalar1 ? 0 : i))
00977 <<
" ? 1.0f : 0.0f)"
00978 <<
";"
00979 << std::endl;
00980 }
00981
break;
00982 }
00983
case SH::SH_OP_SLE:
00984 {
00985
bool scalar0 = (stmt.
src[0].size() == 1);
00986
bool scalar1 = (stmt.
src[1].size() == 1);
00987
for(
int i = 0; i < stmt.
dest.size(); i++)
00988 {
00989 m_code <<
" "
00990 << resolve(stmt.
dest, i)
00991 <<
" = ("
00992 << resolve(stmt.
src[0], (scalar0 ? 0 : i))
00993 <<
" <= "
00994 << resolve(stmt.
src[1], (scalar1 ? 0 : i))
00995 <<
" ? 1.0f : 0.0f)"
00996 <<
";"
00997 << std::endl;
00998 }
00999
break;
01000 }
01001
case SH::SH_OP_SGT:
01002 {
01003
bool scalar0 = (stmt.
src[0].size() == 1);
01004
bool scalar1 = (stmt.
src[1].size() == 1);
01005
for(
int i = 0; i < stmt.
dest.size(); i++)
01006 {
01007 m_code <<
" "
01008 << resolve(stmt.
dest, i)
01009 <<
" = ("
01010 << resolve(stmt.
src[0], (scalar0 ? 0 : i))
01011 <<
" > "
01012 << resolve(stmt.
src[1], (scalar1 ? 0 : i))
01013 <<
" ? 1.0f : 0.0f)"
01014 <<
";"
01015 << std::endl;
01016 }
01017
break;
01018 }
01019
case SH::SH_OP_SGE:
01020 {
01021
bool scalar0 = (stmt.
src[0].size() == 1);
01022
bool scalar1 = (stmt.
src[1].size() == 1);
01023
for(
int i = 0; i < stmt.
dest.size(); i++)
01024 {
01025 m_code <<
" "
01026 << resolve(stmt.
dest, i)
01027 <<
" = ("
01028 << resolve(stmt.
src[0], (scalar0 ? 0 : i))
01029 <<
" >= "
01030 << resolve(stmt.
src[1], (scalar1 ? 0 : i))
01031 <<
" ? 1.0f : 0.0f)"
01032 <<
";"
01033 << std::endl;
01034 }
01035
break;
01036 }
01037
case SH::SH_OP_SEQ:
01038 {
01039
bool scalar0 = (stmt.
src[0].size() == 1);
01040
bool scalar1 = (stmt.
src[1].size() == 1);
01041
for(
int i = 0; i < stmt.
dest.size(); i++)
01042 {
01043 m_code <<
" "
01044 << resolve(stmt.
dest, i)
01045 <<
" = ("
01046 << resolve(stmt.
src[0], (scalar0 ? 0 : i))
01047 <<
" == "
01048 << resolve(stmt.
src[1], (scalar1 ? 0 : i))
01049 <<
" ? 1.0f : 0.0f)"
01050 <<
";"
01051 << std::endl;
01052 }
01053
break;
01054 }
01055
case SH::SH_OP_SNE:
01056 {
01057
bool scalar0 = (stmt.
src[0].size() == 1);
01058
bool scalar1 = (stmt.
src[1].size() == 1);
01059
for(
int i = 0; i < stmt.
dest.size(); i++)
01060 {
01061 m_code <<
" "
01062 << resolve(stmt.
dest, i)
01063 <<
" = ("
01064 << resolve(stmt.
src[0], (scalar0 ? 0 : i))
01065 <<
" != "
01066 << resolve(stmt.
src[1], (scalar1 ? 0 : i))
01067 <<
" ? 1.0f : 0.0f)"
01068 <<
";"
01069 << std::endl;
01070 }
01071
break;
01072 }
01073
case SH::SH_OP_ABS:
01074 {
01075
for(
int i = 0; i < stmt.
dest.size(); i++)
01076 {
01077 m_code <<
" "
01078 << resolve(stmt.
dest, i)
01079 <<
" = fabs("
01080 << resolve(stmt.
src[0], i)
01081 <<
");" << std::endl;
01082 }
01083
01084
break;
01085 }
01086
case SH::SH_OP_ACOS:
01087 {
01088
for(
int i = 0; i < stmt.
dest.size(); i++)
01089 {
01090 m_code <<
" "
01091 << resolve(stmt.
dest, i)
01092 <<
" = acos("
01093 << resolve(stmt.
src[0], i)
01094 <<
");" << std::endl;
01095 }
01096
01097
break;
01098 }
01099
case SH::SH_OP_ASIN:
01100 {
01101
for(
int i = 0; i < stmt.
dest.size(); i++)
01102 {
01103 m_code <<
" "
01104 << resolve(stmt.
dest, i)
01105 <<
" = asin("
01106 << resolve(stmt.
src[0], i)
01107 <<
");" << std::endl;
01108 }
01109
01110
break;
01111 }
01112
case SH::SH_OP_ATAN:
01113 {
01114
for(
int i = 0; i < stmt.
dest.size(); i++)
01115 {
01116 m_code <<
" "
01117 << resolve(stmt.
dest, i)
01118 <<
" = atan("
01119 << resolve(stmt.
src[0], i)
01120 <<
");" << std::endl;
01121 }
01122
01123
break;
01124 }
01125
case SH::SH_OP_ATAN2:
01126 {
01127
for(
int i = 0; i < stmt.
dest.size(); i++)
01128 {
01129 m_code <<
" "
01130 << resolve(stmt.
dest, i)
01131 <<
" = atan2("
01132 << resolve(stmt.
src[0], i)
01133 <<
", "
01134 << resolve(stmt.
src[1], i)
01135 <<
");" << std::endl;
01136 }
01137
01138
break;
01139 }
01140
case SH::SH_OP_CEIL:
01141 {
01142
for(
int i = 0; i < stmt.
dest.size(); i++)
01143 {
01144 m_code <<
" "
01145 << resolve(stmt.
dest, i)
01146 <<
" = ceil("
01147 << resolve(stmt.
src[0], i)
01148 <<
");" << std::endl;
01149 }
01150
01151
break;
01152 }
01153
case SH::SH_OP_COS:
01154 {
01155
for(
int i = 0; i < stmt.
dest.size(); i++)
01156 {
01157 m_code <<
" "
01158 << resolve(stmt.
dest, i)
01159 <<
" = cos("
01160 << resolve(stmt.
src[0], i)
01161 <<
");" << std::endl;
01162 }
01163
01164
break;
01165 }
01166
case SH::SH_OP_DOT:
01167 {
01168 SH_DEBUG_ASSERT(stmt.
dest.size() == 1);
01169
01170
if (stmt.
src[0].swizzle().size() == 1)
01171 {
01172 m_code <<
" "
01173 << resolve(stmt.
dest, 0)
01174 <<
" = ";
01175
for(
int i = 0; i < stmt.
src[1].size(); i++)
01176 {
01177
if (i != 0)
01178 m_code <<
" + ";
01179
01180 m_code <<
"("
01181 << resolve(stmt.
src[0], 0)
01182 <<
"*"
01183 << resolve(stmt.
src[1], i)
01184 <<
")";
01185 }
01186 m_code <<
";" << std::endl;
01187 }
01188
else if (stmt.
src[1].swizzle().size() == 1)
01189 {
01190 m_code <<
" "
01191 << resolve(stmt.
dest, 0)
01192 <<
" = ";
01193
for(
int i = 0; i < stmt.
src[0].size(); i++)
01194 {
01195
if (i != 0)
01196 m_code <<
" + ";
01197
01198 m_code <<
"("
01199 << resolve(stmt.
src[0], i)
01200 <<
"*"
01201 << resolve(stmt.
src[1], 0)
01202 <<
")";
01203 }
01204 m_code <<
";" << std::endl;
01205 }
01206
else
01207 {
01208 m_code <<
" "
01209 << resolve(stmt.
dest, 0)
01210 <<
" = ";
01211
for(
int i = 0; i < stmt.
src[0].size(); i++)
01212 {
01213
if (i != 0)
01214 m_code <<
" + ";
01215
01216 m_code <<
"("
01217 << resolve(stmt.
src[0], i)
01218 <<
"*"
01219 << resolve(stmt.
src[1], i)
01220 <<
")";
01221 }
01222 m_code <<
";" << std::endl;
01223 }
01224
01225
break;
01226 }
01227
case SH::SH_OP_EXP:
01228 {
01229
for(
int i = 0; i < stmt.
dest.size(); i++)
01230 {
01231 m_code <<
" "
01232 << resolve(stmt.
dest, i)
01233 <<
" = exp("
01234 << resolve(stmt.
src[0], i)
01235 <<
");" << std::endl;
01236 }
01237
01238
break;
01239 }
01240
case SH::SH_OP_EXP2:
01241 {
01242
for(
int i = 0; i < stmt.
dest.size(); i++)
01243 {
01244 m_code <<
" "
01245 << resolve(stmt.
dest, i)
01246 <<
" = exp2("
01247 << resolve(stmt.
src[0], i)
01248 <<
");" << std::endl;
01249 }
01250
01251
break;
01252 }
01253
case SH::SH_OP_EXP10:
01254 {
01255
for(
int i = 0; i < stmt.
dest.size(); i++)
01256 {
01257 m_code <<
" "
01258 << resolve(stmt.
dest, i)
01259 <<
" = exp10("
01260 << resolve(stmt.
src[0], i)
01261 <<
");" << std::endl;
01262 }
01263
01264
break;
01265 }
01266
case SH::SH_OP_FLR:
01267 {
01268
for(
int i = 0; i < stmt.
dest.size(); i++)
01269 {
01270 m_code <<
" "
01271 << resolve(stmt.
dest, i)
01272 <<
" = floor("
01273 << resolve(stmt.
src[0], i)
01274 <<
");" << std::endl;
01275 }
01276
01277
break;
01278 }
01279
case SH::SH_OP_FRAC:
01280 {
01281
for(
int i = 0; i < stmt.
dest.size(); i++)
01282 {
01283 m_code <<
" "
01284 << resolve(stmt.
dest, i)
01285 <<
" = "
01286 << resolve(stmt.
src[0], i)
01287 <<
" - floor("
01288 << resolve(stmt.
src[0], i)
01289 <<
");" << std::endl;
01290 }
01291
01292
break;
01293 }
01294
case SH::SH_OP_LOG:
01295 {
01296
for(
int i = 0; i < stmt.
dest.size(); i++)
01297 {
01298 m_code <<
" "
01299 << resolve(stmt.
dest, i)
01300 <<
" = log("
01301 << resolve(stmt.
src[0], i)
01302 <<
");" << std::endl;
01303 }
01304
01305
break;
01306 }
01307
case SH::SH_OP_LOG2:
01308 {
01309
for(
int i = 0; i < stmt.
dest.size(); i++)
01310 {
01311 m_code <<
" "
01312 << resolve(stmt.
dest, i)
01313 <<
" = log2("
01314 << resolve(stmt.
src[0], i)
01315 <<
");" << std::endl;
01316 }
01317
01318
break;
01319 }
01320
case SH::SH_OP_LOG10:
01321 {
01322
for(
int i = 0; i < stmt.
dest.size(); i++)
01323 {
01324 m_code <<
" "
01325 << resolve(stmt.
dest, i)
01326 <<
" = log10("
01327 << resolve(stmt.
src[0], i)
01328 <<
");" << std::endl;
01329 }
01330
01331
break;
01332 }
01333
case SH::SH_OP_LRP:
01334 {
01335
if (stmt.
src[0].swizzle().size() == 1)
01336 {
01337
for(
int i = 0; i < stmt.
dest.size(); i++)
01338 {
01339 m_code <<
" "
01340 << resolve(stmt.
dest, i)
01341 <<
" = "
01342 << resolve(stmt.
src[0], 0)
01343 <<
" * ("
01344 << resolve(stmt.
src[1], i)
01345 <<
" - "
01346 << resolve(stmt.
src[2], i)
01347 <<
") + "
01348 << resolve(stmt.
src[2], i)
01349 <<
");" << std::endl;
01350 }
01351 }
01352
else
01353 {
01354
for(
int i = 0; i < stmt.
dest.size(); i++)
01355 {
01356 m_code <<
" "
01357 << resolve(stmt.
dest, i)
01358 <<
" = "
01359 << resolve(stmt.
src[0], i)
01360 <<
" * ("
01361 << resolve(stmt.
src[1], i)
01362 <<
" - "
01363 << resolve(stmt.
src[2], i)
01364 <<
") + "
01365 << resolve(stmt.
src[2], i)
01366 <<
");" << std::endl;
01367 }
01368 }
01369
01370
break;
01371 }
01372
case SH::SH_OP_MAD:
01373 {
01374
if (stmt.
src[0].swizzle().size() == 1)
01375 {
01376
for(
int i = 0; i < stmt.
dest.size(); i++)
01377 {
01378 m_code <<
" "
01379 << resolve(stmt.
dest, i)
01380 <<
" = "
01381 << resolve(stmt.
src[0], 0)
01382 <<
" * "
01383 << resolve(stmt.
src[1], i)
01384 <<
" + "
01385 << resolve(stmt.
src[2], i)
01386 <<
";" << std::endl;
01387 }
01388 }
01389
else if (stmt.
src[1].swizzle().size() == 1)
01390 {
01391
for(
int i = 0; i < stmt.
dest.size(); i++)
01392 {
01393 m_code <<
" "
01394 << resolve(stmt.
dest, i)
01395 <<
" = "
01396 << resolve(stmt.
src[0], i)
01397 <<
" * "
01398 << resolve(stmt.
src[1], 0)
01399 <<
" + "
01400 << resolve(stmt.
src[2], i)
01401 <<
";" << std::endl;
01402 }
01403 }
01404
else
01405 {
01406
for(
int i = 0; i < stmt.
dest.size(); i++)
01407 {
01408 m_code <<
" "
01409 << resolve(stmt.
dest, i)
01410 <<
" = "
01411 << resolve(stmt.
src[0], i)
01412 <<
" * "
01413 << resolve(stmt.
src[1], i)
01414 <<
" + "
01415 << resolve(stmt.
src[2], i)
01416 <<
";" << std::endl;
01417 }
01418 }
01419
01420
break;
01421 }
01422
case SH::SH_OP_MAX:
01423 {
01424
for(
int i = 0; i < stmt.
dest.size(); i++)
01425 {
01426 m_code <<
" "
01427 << resolve(stmt.
dest, i)
01428 <<
" = ("
01429 << resolve(stmt.
src[0], i)
01430 <<
" > "
01431 << resolve(stmt.
src[1], i)
01432 <<
" ? "
01433 << resolve(stmt.
src[0], i)
01434 <<
" : "
01435 << resolve(stmt.
src[1], i)
01436 <<
");" << std::endl;
01437 }
01438
01439
break;
01440 }
01441
case SH::SH_OP_MIN:
01442 {
01443
for(
int i = 0; i < stmt.
dest.size(); i++)
01444 {
01445 m_code <<
" "
01446 << resolve(stmt.
dest, i)
01447 <<
" = ("
01448 << resolve(stmt.
src[0], i)
01449 <<
" < "
01450 << resolve(stmt.
src[1], i)
01451 <<
" ? "
01452 << resolve(stmt.
src[0], i)
01453 <<
" : "
01454 << resolve(stmt.
src[1], i)
01455 <<
");" << std::endl;
01456 }
01457
01458
break;
01459 }
01460
case SH::SH_OP_MOD:
01461 {
01462
for(
int i = 0; i < stmt.
dest.size(); i++)
01463 {
01464 m_code <<
" "
01465 << resolve(stmt.
dest, i)
01466 <<
" = fmod("
01467 << resolve(stmt.
src[0], i)
01468 <<
", "
01469 << resolve(stmt.
src[1], i)
01470 <<
");" << std::endl;
01471 }
01472
01473
break;
01474 }
01475
case SH::SH_OP_POW:
01476 {
01477
for(
int i = 0; i < stmt.
dest.size(); i++)
01478 {
01479 m_code <<
" "
01480 << resolve(stmt.
dest, i)
01481 <<
" = pow("
01482 << resolve(stmt.
src[0], i)
01483 <<
", "
01484 << resolve(stmt.
src[1], (stmt.
src[1].size() > 1 ? i : 0))
01485 <<
");" << std::endl;
01486 }
01487
01488
break;
01489 }
01490
case SH::SH_OP_RCP:
01491 {
01492
for(
int i = 0; i < stmt.
dest.size(); i++)
01493 {
01494 m_code <<
" "
01495 << resolve(stmt.
dest, i)
01496 <<
" = 1.0/("
01497 << resolve(stmt.
src[0], i)
01498 <<
");" << std::endl;
01499 }
01500
01501
break;
01502 }
01503
case SH::SH_OP_RSQ:
01504 {
01505
for(
int i = 0; i < stmt.
dest.size(); i++)
01506 {
01507 m_code <<
" "
01508 << resolve(stmt.
dest, i)
01509 <<
" = 1.0/sqrt("
01510 << resolve(stmt.
src[0], i)
01511 <<
");" << std::endl;
01512 }
01513
01514
break;
01515 }
01516
case SH::SH_OP_SIN:
01517 {
01518
for(
int i = 0; i < stmt.
dest.size(); i++)
01519 {
01520 m_code <<
" "
01521 << resolve(stmt.
dest, i)
01522 <<
" = sin("
01523 << resolve(stmt.
src[0], i)
01524 <<
");" << std::endl;
01525 }
01526
01527
break;
01528 }
01529
case SH::SH_OP_SGN:
01530 {
01531
for(
int i = 0; i < stmt.
dest.size(); i++)
01532 {
01533 m_code <<
" "
01534 << resolve(stmt.
dest, i)
01535 <<
" = ("
01536 << resolve(stmt.
src[0], i)
01537 <<
" < 0.0f ? -1.0f : ("
01538 << resolve(stmt.
src[0], i)
01539 <<
" > 0.0f ? 1.0f : 0.0)"
01540 <<
");" << std::endl;
01541 }
01542
01543
break;
01544 }
01545
case SH::SH_OP_SQRT:
01546 {
01547
for(
int i = 0; i < stmt.
dest.size(); i++)
01548 {
01549 m_code <<
" "
01550 << resolve(stmt.
dest, i)
01551 <<
" = sqrt("
01552 << resolve(stmt.
src[0], i)
01553 <<
");" << std::endl;
01554 }
01555
01556
break;
01557 }
01558
case SH::SH_OP_NORM:
01559 {
01560 m_code <<
" {" << std::endl;
01561 m_code <<
" float len = 1.0/sqrt(";
01562
for(
int i = 0; i < stmt.
dest.size(); i++)
01563 {
01564
if (i != 0) m_code <<
" + ";
01565 m_code << resolve(stmt.
src[0], i)
01566 <<
" * "
01567 << resolve(stmt.
src[0], i);
01568 }
01569 m_code <<
");" << std::endl;
01570
for(
int i = 0; i < stmt.
dest.size(); i++)
01571 {
01572 m_code <<
" "
01573 << resolve(stmt.
dest, i)
01574 <<
" = len*"
01575 << resolve(stmt.
src[0], i)
01576 <<
";" << std::endl;
01577 }
01578 m_code <<
" }" << std::endl;
01579
01580
break;
01581 }
01582
case SH::SH_OP_XPD:
01583 {
01584
for(
int i = 0; i < stmt.
dest.size(); i++)
01585 {
01586
int i0 = (i+1)%3;
01587
int i1 = (i+2)%3;
01588 m_code <<
" "
01589 << resolve(stmt.
dest, i)
01590 <<
" = "
01591 << resolve(stmt.
src[0], i0)
01592 <<
" * "
01593 << resolve(stmt.
src[1], i1)
01594 <<
" - "
01595 << resolve(stmt.
src[1], i0)
01596 <<
" * "
01597 << resolve(stmt.
src[0], i1)
01598 <<
";" << std::endl;
01599 }
01600
01601
break;
01602 }
01603
case SH::SH_OP_TEX:
01604 {
01605
01606
if (stmt.
dest.swizzle().identity())
01607 {
01608
if (stmt.
src[1].swizzle().identity())
01609 {
01610 m_code <<
" sh_gcc_backend_lookup("
01611 << resolve(stmt.
src[0])
01612 <<
", "
01613 << resolve(stmt.
src[1])
01614 <<
", "
01615 << resolve(stmt.
dest)
01616 <<
");" << std::endl;
01617 }
01618
else
01619 {
01620 m_code <<
" {" << std::endl;
01621 m_code <<
" float input[" << stmt.
src[1].size() <<
"];" << std::endl;
01622
for(
int i = 0; i < stmt.
src[1].size(); i++)
01623 {
01624 m_code <<
" "
01625 <<
"input["
01626 << i
01627 <<
"] = "
01628 << resolve(stmt.
src[1], i)
01629 <<
";" << std::endl;
01630 }
01631 m_code <<
" sh_gcc_backend_lookup("
01632 << resolve(stmt.
src[0])
01633 <<
", "
01634 <<
"input"
01635 <<
", "
01636 << resolve(stmt.
dest)
01637 <<
");" << std::endl;
01638 m_code <<
" }" << std::endl;
01639 }
01640 }
01641
else
01642 {
01643
if (stmt.
src[1].swizzle().identity())
01644 {
01645 m_code <<
" {" << std::endl;
01646 m_code <<
" float result[" << stmt.
dest.size() <<
"];" << std::endl;
01647 m_code <<
" sh_gcc_backend_lookup("
01648 << resolve(stmt.
src[0])
01649 <<
", "
01650 << resolve(stmt.
src[1])
01651 <<
", "
01652 <<
"result"
01653 <<
");" << std::endl;
01654
for(
int i = 0; i < stmt.
dest.size(); i++)
01655 {
01656 m_code <<
" "
01657 << resolve(stmt.
dest, i)
01658 <<
" = result["
01659 << i
01660 <<
"];" << std::endl;
01661 }
01662 m_code <<
" }" << std::endl;
01663 }
01664
else
01665 {
01666 m_code <<
" {" << std::endl;
01667 m_code <<
" float result[" << stmt.
dest.size() <<
"];" << std::endl;
01668 m_code <<
" float input[" << stmt.
src[1].size() <<
"];" << std::endl;
01669
for(
int i = 0; i < stmt.
src[1].size(); i++)
01670 {
01671 m_code <<
" "
01672 <<
"input["
01673 << i
01674 <<
"] = "
01675 << resolve(stmt.
src[1], i)
01676 <<
";" << std::endl;
01677 }
01678 m_code <<
" sh_gcc_backend_lookup("
01679 << resolve(stmt.
src[0])
01680 <<
", "
01681 <<
"input"
01682 <<
", "
01683 <<
"result"
01684 <<
");" << std::endl;
01685
for(
int i = 0; i < stmt.
dest.size(); i++)
01686 {
01687 m_code <<
" "
01688 << resolve(stmt.
dest, i)
01689 <<
" = result["
01690 << i
01691 <<
"];" << std::endl;
01692 }
01693 m_code <<
" }" << std::endl;
01694 }
01695 }
01696
break;
01697 }
01698
case SH::SH_OP_TEXI:
01699 {
01700
01701
if (stmt.
dest.swizzle().identity())
01702 {
01703
if (stmt.
src[1].swizzle().identity())
01704 {
01705 m_code <<
" sh_gcc_backend_lookupi("
01706 << resolve(stmt.
src[0])
01707 <<
", "
01708 << resolve(stmt.
src[1])
01709 <<
", "
01710 << resolve(stmt.
dest)
01711 <<
");" << std::endl;
01712 }
01713
else
01714 {
01715 m_code <<
" {" << std::endl;
01716 m_code <<
" float input[" << stmt.
src[1].size() <<
"];" << std::endl;
01717
for(
int i = 0; i < stmt.
src[1].size(); i++)
01718 {
01719 m_code <<
" "
01720 <<
"input["
01721 << i
01722 <<
"] = "
01723 << resolve(stmt.
src[1], i)
01724 <<
";" << std::endl;
01725 }
01726 m_code <<
" sh_gcc_backend_lookupi("
01727 << resolve(stmt.
src[0])
01728 <<
", "
01729 <<
"input"
01730 <<
", "
01731 << resolve(stmt.
dest)
01732 <<
");" << std::endl;
01733 m_code <<
" }" << std::endl;
01734 }
01735 }
01736
else
01737 {
01738
if (stmt.
src[1].swizzle().identity())
01739 {
01740 m_code <<
" {" << std::endl;
01741 m_code <<
" float result[" << stmt.
dest.size() <<
"];" << std::endl;
01742 m_code <<
" sh_gcc_backend_lookupi("
01743 << resolve(stmt.
src[0])
01744 <<
", "
01745 << resolve(stmt.
src[1])
01746 <<
", "
01747 <<
"result"
01748 <<
");" << std::endl;
01749
for(
int i = 0; i < stmt.
dest.size(); i++)
01750 {
01751 m_code <<
" "
01752 << resolve(stmt.
dest, i)
01753 <<
" = result["
01754 << i
01755 <<
"];" << std::endl;
01756 }
01757 m_code <<
" }" << std::endl;
01758 }
01759
else
01760 {
01761 m_code <<
" {" << std::endl;
01762 m_code <<
" float result[" << stmt.
dest.size() <<
"];" << std::endl;
01763 m_code <<
" float input[" << stmt.
src[1].size() <<
"];" << std::endl;
01764
for(
int i = 0; i < stmt.
src[1].size(); i++)
01765 {
01766 m_code <<
" "
01767 <<
"input["
01768 << i
01769 <<
"] = "
01770 << resolve(stmt.
src[1], i)
01771 <<
";" << std::endl;
01772 }
01773 m_code <<
" sh_gcc_backend_lookupi("
01774 << resolve(stmt.
src[0])
01775 <<
", "
01776 <<
"input"
01777 <<
", "
01778 <<
"result"
01779 <<
");" << std::endl;
01780
for(
int i = 0; i < stmt.
dest.size(); i++)
01781 {
01782 m_code <<
" "
01783 << resolve(stmt.
dest, i)
01784 <<
" = result["
01785 << i
01786 <<
"];" << std::endl;
01787 }
01788 m_code <<
" }" << std::endl;
01789 }
01790 }
01791
break;
01792 }
01793
case SH::SH_OP_COND:
01794 {
01795
if (stmt.
src[0].swizzle().size() == 1)
01796 {
01797
for(
int i = 0; i < stmt.
dest.size(); i++)
01798 {
01799 m_code <<
" "
01800 << resolve(stmt.
dest, i)
01801 <<
" = ("
01802 << resolve(stmt.
src[0], 0)
01803 <<
" > 0 ? "
01804 << resolve(stmt.
src[1], i)
01805 <<
" : "
01806 << resolve(stmt.
src[2], i)
01807 <<
");" << std::endl;
01808 }
01809 }
01810
else
01811 {
01812
for(
int i = 0; i < stmt.
dest.size(); i++)
01813 {
01814 m_code <<
" "
01815 << resolve(stmt.
dest, i)
01816 <<
" = ("
01817 << resolve(stmt.
src[0], i)
01818 <<
" > 0 ? "
01819 << resolve(stmt.
src[1], i)
01820 <<
" : "
01821 << resolve(stmt.
src[2], i)
01822 <<
");" << std::endl;
01823 }
01824 }
01825
break;
01826 }
01827
case SH::SH_OP_KIL:
01828 {
01829
01830 m_code <<
" if (";
01831
for(
int i = 0; i < stmt.
src[0].size(); i++)
01832 {
01833
if (i != 0) m_code <<
" || ";
01834 m_code <<
"("
01835 << resolve(stmt.
src[0], i)
01836 <<
" > 0)";
01837 }
01838 m_code <<
")" << std::endl;
01839 m_code <<
" return;" << std::endl;
01840
break;
01841 }
01842
case SH::SH_OP_OPTBRA:
01843 {
01844 SH_DEBUG_ASSERT(
false);
01845
break;
01846 }
01847
case SH::SH_OP_FETCH:
01848 {
01849
for(
int i = 0; i < stmt.
dest.size(); i++)
01850 {
01851 m_code <<
" "
01852 << resolve(stmt.
dest, i)
01853 <<
" = "
01854 << resolve(stmt.
src[0], i)
01855 <<
";" << std::endl;
01856 }
01857
01858
break;
01859 }
01860
default:
01861 {
01862 m_code <<
" // *** unhandled operation "
01863 << SH::opInfo[stmt.
op].name
01864 <<
" ***" << std::endl;
01865
break;
01866 }
01867 }
01868 }
01869
01870
void GccBackendCode::emit(
SH::ShBasicBlockPtr block)
01871 {
01872
if (!block)
01873 {
01874 m_code <<
" // empty basic block" << std::endl;
01875 }
01876
else
01877 {
01878 m_code <<
" // start basic block" << std::endl;
01879
for(SH::ShBasicBlock::ShStmtList::const_iterator itr = block->begin();
01880 itr != block->end();
01881 itr++)
01882 {
01883 emit((*itr));
01884 }
01885 m_code <<
" // end basic block" << std::endl;
01886 }
01887 }
01888
01889
void GccBackendCode::emit(
SH::ShCtrlGraphNodePtr node)
01890 {
01891 m_code <<
"label_" << m_label_map[node] <<
":" << std::endl
01892 <<
" ;" << std::endl;
01893
01894
if (node->block)
01895 {
01896 emit(node->block);
01897 }
01898
01899
for(std::vector<SH::ShCtrlGraphBranch>::iterator itr = node->successors.begin();
01900 itr != node->successors.end();
01901 itr++)
01902 {
01903 m_code <<
" if (";
01904
for(
int i = 0; i < (*itr).cond.size(); i++)
01905 {
01906
if (i != 0)
01907 m_code <<
" || ";
01908
01909 m_code <<
"(";
01910 m_code << resolve((*itr).cond, i) <<
" > 0.0f";
01911 m_code <<
")";
01912 }
01913 m_code <<
")";
01914
01915 m_code <<
" goto label_"
01916 << m_label_map[(*itr).node]
01917 <<
";" << std::endl;
01918 }
01919
01920
if (node->follower)
01921 {
01922 m_code <<
" goto label_" << m_label_map[node->follower] <<
";" << std::endl;
01923 }
01924
01925
if (node->successors.empty() && !node->follower)
01926 {
01927
01928 m_code <<
" return;" << std::endl;
01929 }
01930 }
01931
01932
bool GccBackendCode::generate(
void)
01933 {
01934 SH_GCC_DEBUG_PRINT(
"Creating label map...");
01935 LabelFunctor fl(m_label_map);
01936 m_program->ctrlGraph->dfs(fl);
01937
01938 allocate_consts();
01939 allocate_inputs();
01940 allocate_outputs();
01941 allocate_streams();
01942 allocate_textures();
01943 allocate_uniforms();
01944
01945
01946 SH_GCC_DEBUG_PRINT(
"Emitting code...");
01947 EmitFunctor fe(
this);
01948 m_program->ctrlGraph->dfs(fe);
01949
01950
01951 std::stringstream prologue;
01952 prologue <<
"#include <math.h>" << std::endl;
01953 prologue << std::endl;
01954 prologue <<
"extern \"C\" void sh_gcc_backend_lookup(void*, float*, float*);" << std::endl;
01955 prologue <<
"extern \"C\" void sh_gcc_backend_lookupi(void*, float*, float*);" << std::endl;
01956 prologue << std::endl;
01957 prologue <<
"extern \"C\" "
01958 <<
" void func("
01959 <<
"float** inputs, "
01960 <<
"float** params, "
01961 <<
"float** streams, "
01962 <<
"void** textures, "
01963 <<
"float** outputs)" << std::endl;
01964 prologue <<
" {" << std::endl;
01965
01966
01967
for(std::vector<GccVariable>::iterator itr = m_temps.begin();
01968 itr != m_temps.end();
01969 itr++)
01970 {
01971
01972 prologue <<
" float "
01973 << (*itr).m_name <<
"[" << (*itr).m_size <<
"]"
01974 <<
";" << std::endl;
01975 }
01976
01977
01978 std::stringstream epilogue;
01979 epilogue <<
" }" << std::endl;
01980
01981
01982 SH_GCC_DEBUG_PRINT(prologue.str());
01983 SH_GCC_DEBUG_PRINT(m_code.str());
01984 SH_GCC_DEBUG_PRINT(epilogue.str());
01985
01986
char name[32];
01987 tmpnam(name);
01988
char ccfile[32];
01989
char sofile[32];
01990 sprintf(ccfile,
"%s.cc", name);
01991 sprintf(sofile,
"%s.so", name);
01992 FILE* f = fopen(ccfile,
"w");
01993 fprintf(f,
"%s", prologue.str().c_str());
01994 fprintf(f,
"%s", m_code.str().c_str());
01995 fprintf(f,
"%s", epilogue.str().c_str());
01996 fflush(f);
01997
01998 pid_t pid = fork();
01999
if (pid == 0)
02000 {
02001
02002 execlp(
"gcc",
"gcc",
"-O2",
"-shared",
"-o", sofile, ccfile,
02003
"-L", SH_INSTALL_PREFIX
"/lib/sh",
"-lshgcc", NULL);
02004 SH_GCC_DEBUG_PRINT(
"exec failed (" << errno <<
")");
02005 exit(-1);
02006 }
02007
else if (pid > 0)
02008 {
02009
int status;
02010 pid_t ret = waitpid(pid, &status, 0);
02011
if (ret == -1)
02012 {
02013 SH_GCC_DEBUG_PRINT(
"wait failed...");
02014
return false;
02015 }
02016
else
02017 {
02018 SH_GCC_DEBUG_PRINT(
"status = " << status);
02019 }
02020
02021 m_handle = dlopen(sofile, RTLD_NOW);
02022
if (m_handle == NULL)
02023 {
02024 SH_GCC_DEBUG_PRINT(
"dlopen failed: " << dlerror());
02025
return false;
02026 }
02027
else
02028 {
02029 m_func = (GccFunc)dlsym(m_handle,
"func");
02030
02031
if (m_func == NULL)
02032 {
02033 SH_GCC_DEBUG_PRINT(
"dlsym failed: " << dlerror());
02034
return false;
02035 }
02036 }
02037
02038
return true;
02039 }
02040
else
02041 {
02042
02043 SH_GCC_DEBUG_PRINT(
"fork failed...");
02044
return false;
02045 }
02046 }
02047
02048
bool GccBackendCode::execute(
SH::ShStream& dest)
02049 {
02050
if (!m_func)
02051 {
02052
if (!generate())
02053 {
02054 SH_GCC_DEBUG_PRINT(
"failed to generate program...");
02055
return false;
02056 }
02057 }
02058
02059
int num_outputs = dest.
size();
02060
int num_streams = m_streams.size();
02061
float** inputs = NULL;
02062
float** params = m_params;
02063
float** streams =
new float*[m_streams.size()];
02064
void** textures =
new void*[m_textures.size()];
02065
float** outputs =
new float*[dest.
size()];
02066 std::vector<int> output_sizes(num_outputs);
02067 std::vector<int> stream_sizes(num_streams);
02068
02069
int sidx = 0;
02070
for(std::vector<SH::ShChannelNodePtr>::iterator itr = m_streams.begin();
02071 itr != m_streams.end();
02072 itr++, sidx++)
02073 {
02074
SH::ShChannelNodePtr channel = (*itr);
02075
SH::ShHostStoragePtr storage = SH::shref_dynamic_cast<SH::ShHostStorage>(channel->memory()->findStorage(
"host"));
02076
if (!storage)
02077 {
02078 storage =
new SH::ShHostStorage(channel->memory().
object(),
02079
sizeof(
float)*channel->size()*channel->count());
02080 }
02081 storage->dirty();
02082 streams[sidx] = (
float*)storage->data();
02083 stream_sizes[sidx] = channel->size();
02084 }
02085
02086
int tidx = 0;
02087
for(std::vector<SH::ShTextureNodePtr>::iterator itr = m_textures.begin();
02088 itr != m_textures.end();
02089 itr++, tidx++)
02090 {
02091
SH::ShTextureNodePtr texture = (*itr);
02092 textures[tidx] = (
void*)(texture.
object());
02093 }
02094
02095
int oidx = 0;
02096
int count = 0;
02097
for(SH::ShStream::NodeList::iterator itr = dest.
begin();
02098 itr != dest.
end();
02099 itr++, oidx++)
02100 {
02101
SH::ShChannelNodePtr channel = (*itr);
02102
SH::ShHostStoragePtr storage = SH::shref_dynamic_cast<SH::ShHostStorage>(channel->memory()->findStorage(
"host"));
02103
if (!storage)
02104 {
02105 storage =
new SH::ShHostStorage(channel->memory().
object(),
02106
sizeof(
float)*channel->size()*channel->count());
02107 }
02108 storage->dirty();
02109 outputs[oidx] = (
float*)storage->data();
02110 output_sizes[oidx] = channel->size();
02111
02112
if (count == 0) count = channel->count();
02113
else
02114 {
02115
if (count != channel->count())
02116 {
02117 SH_GCC_DEBUG_PRINT(
"channel count discrepancy...");
02118
return false;
02119 }
02120 }
02121 }
02122
02123
02124
for(
int i = 0; i < count; i++)
02125 {
02126 SH_GCC_DEBUG_PRINT(
"execution " << i <<
" of " << count);
02127 m_func(inputs, params, streams, textures, outputs);
02128
02129
for(
int j = 0; j < num_streams; j++)
02130 {
02131 SH_GCC_DEBUG_PRINT(
"advancing input stream "
02132 << j
02133 <<
" by "
02134 << stream_sizes[j]);
02135 streams[j] += stream_sizes[j];
02136 }
02137
for(
int j = 0; j < num_outputs; j++)
02138 {
02139 SH_GCC_DEBUG_PRINT(
"advancing output stream "
02140 << j
02141 <<
" by "
02142 << output_sizes[j]);
02143 outputs[j] += output_sizes[j];
02144 }
02145 }
02146
02147
return true;
02148 }
02149
02150
02151 GccBackend::GccBackend(
void)
02152 {
02153 SH_GCC_DEBUG_PRINT(__FUNCTION__);
02154 }
02155
02156 GccBackend::~GccBackend(
void)
02157 {
02158 SH_GCC_DEBUG_PRINT(__FUNCTION__);
02159 }
02160
02161 std::string GccBackend::name(
void)
const
02162
{
02163 SH_GCC_DEBUG_PRINT(__FUNCTION__);
02164
return "gcc";
02165 }
02166
02167
SH::ShBackendCodePtr GccBackend::generateCode(
const std::string& target,
02168
const SH::ShProgramNodeCPtr& program)
02169 {
02170 SH_GCC_DEBUG_PRINT(__FUNCTION__);
02171 GccBackendCodePtr backendcode =
new GccBackendCode(program);
02172 backendcode->generate();
02173
return backendcode;
02174 }
02175
02176
void GccBackend::execute(
const SH::ShProgramNodeCPtr& program,
SH::ShStream& dest)
02177 {
02178 SH_GCC_DEBUG_PRINT(__FUNCTION__);
02179
02180 GccBackendCodePtr backendcode =
new GccBackendCode(program);
02181 backendcode->execute(dest);
02182 }
02183
02184
static GccBackend* backend =
new GccBackend();
02185
02186 }
02187