00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #ifndef __VOP_CodeGenerator_h__
00015 #define __VOP_CodeGenerator_h__
00016
00017 #include "VOP_API.h"
00018 #include "VOP_Error.h"
00019 #include "VOP_Node.h"
00020 #include "VOP_Parameter.h"
00021 #include "VOP_ParmGenerator.h"
00022 #include <OP/OP_Node.h>
00023 #include <PI/PI_EditScriptedParms.h>
00024 #include <PI/PI_OldParms.h>
00025 #include <UT/UT_Assert.h>
00026
00027 #include <map>
00028 #include <string>
00029
00030
00031
00032 #define VOP_MININPUTS_NAME "mininputs"
00033 #define VOP_MAXINPUTS_NAME "maxinputs"
00034
00035 class UT_IStream;
00036 class UT_WorkArgs;
00037 class UT_StringArray;
00038 class CH_LocalVariable;
00039 class OP_OTLDefinition;
00040 class OP_Network;
00041 class VOP_Collect;
00042 class VOP_Node;
00043 class VOP_Language;
00044 class VOP_CodeGenerator;
00045 class VOP_CodeVarMapper;
00046 class VOP_CodeVarMapperContext;
00047 class VOP_CodeVarLookupData;
00048 class VOP_CodeCompilerArgs;
00049 class VOP_LanguageContextTypeList;
00050 class VOP_ParmContextInfo;
00051
00052 typedef std::map < VOP_ContextType, std::string > TContextTypeStringMap;
00053
00054 class VOP_API VOP_CodeParm
00055 {
00056 public:
00057 typedef enum {
00058 ENDGROUP,
00059 STARTGROUP,
00060 ENTRY
00061 } VOP_CodeParmType;
00062
00063 VOP_CodeParm()
00064 : myType(ENDGROUP), myNodeId(OP_INVALID_NODE_ID) { }
00065 VOP_CodeParm(const char *groupname)
00066 : myType(STARTGROUP), myName(groupname, 1),
00067 myNodeId(OP_INVALID_NODE_ID)
00068 { }
00069 VOP_CodeParm(VOP_ParmGenerator *vop)
00070 : myType(ENTRY), myNodeId(vop->getUniqueId()) {
00071 myName = vop->getParmNameCache();
00072 }
00073 VOP_CodeParm(const VOP_CodeParm &src)
00074 : myType(src.myType), myName(src.myName, 1), myNodeId(src.myNodeId) { }
00075
00076 VOP_CodeParmType getType() const
00077 { return myType; }
00078 const char *getName() const
00079 { return myName; }
00080 void setName(const char *name)
00081 { myName.harden(name); }
00082 VOP_ParmGenerator *getOp() const
00083 {
00084 OP_Node *node = OP_Node::lookupNode(myNodeId);
00085 if (!node)
00086 return NULL;
00087
00088 return dynamic_cast<VOP_ParmGenerator *>(node);
00089 }
00090 int getOpId() const
00091 { return myNodeId; }
00092 bool operator==(const VOP_CodeParm &s) const
00093 {
00094 return myType == s.myType &&
00095 myNodeId == s.myNodeId &&
00096 myName == s.myName;
00097 }
00098 bool operator!=(const VOP_CodeParm &s) const
00099 { return !(*this == s); }
00100 const VOP_CodeParm &operator=(const VOP_CodeParm &src)
00101 {
00102 myType = src.myType;
00103 myName.harden(src.myName);
00104 myNodeId = src.myNodeId;
00105 return *this;
00106 }
00107
00108 private:
00109 VOP_CodeParmType myType;
00110 UT_String myName;
00111 int myNodeId;
00112 };
00113
00114 class VOP_CodeParmList
00115 {
00116 public:
00117 VOP_CodeParmList()
00118 { }
00119 VOP_CodeParmList(const VOP_CodeParmList &src_list)
00120 {
00121 clear();
00122
00123 int i;
00124 for (i=0; i<src_list.entries(); i++)
00125 append(src_list(i));
00126 }
00127 ~VOP_CodeParmList()
00128 { clear(); }
00129
00130 const VOP_CodeParmList &operator=(const VOP_CodeParmList &src)
00131 {
00132 if (&src != this)
00133 {
00134 int i;
00135 clear();
00136 for (i=0; i<src.entries(); i++)
00137 append(src(i));
00138 }
00139 return *this;
00140 }
00141 bool operator==(const VOP_CodeParmList &src) const
00142 {
00143 int i;
00144 if (entries() != src.entries())
00145 return false;
00146 for (i = 0; i < entries(); ++i)
00147 if ((*this)(i) != src(i))
00148 return false;
00149 return true;
00150 }
00151 bool operator!=(const VOP_CodeParmList &s) const
00152 { return !(*this == s); }
00153
00154 void append(const VOP_CodeParm &parm)
00155 {
00156 VOP_CodeParm *new_parm;
00157 new_parm = new VOP_CodeParm(parm);
00158
00159 myParms.append(new_parm);
00160 myParmNodes.addSymbol(
00161 UT_Hash_Int(new_parm->getOpId()),
00162 UT_Thing(new_parm));
00163 }
00164 void insert(const VOP_CodeParm &parm, int idx)
00165 {
00166 VOP_CodeParm *new_parm;
00167 new_parm = new VOP_CodeParm(parm);
00168
00169 myParms.insert(new_parm, idx);
00170 myParmNodes.addSymbol(
00171 UT_Hash_Int(new_parm->getOpId()),
00172 UT_Thing(new_parm));
00173 }
00174 void move(int first, int last, int newpos)
00175 {
00176 myParms.move(first, last, newpos);
00177 }
00178 void remove(int idx)
00179 {
00180 VOP_CodeParm *parm;
00181 int node_id;
00182
00183 node_id = myParms(idx)->getOpId();
00184 parm = myParms(idx);
00185
00186 myParms.removeIndex(idx);
00187 myParmNodes.deleteSymbol(UT_Hash_Int(node_id));
00188 delete parm;
00189 }
00190 void clear()
00191 {
00192 int i;
00193 for (i=0; i<myParms.entries(); i++)
00194 delete myParms(i);
00195 myParms.clear();
00196 myParmNodes.clear();
00197 }
00198
00199
00200
00201
00202 int getParmIndex(const char *parm_name) const
00203 {
00204 if (!parm_name)
00205 return -1;
00206
00207 for (int i=0; i<myParms.entries(); i++)
00208 {
00209 const char *code_parm_name;
00210 code_parm_name = myParms(i)->getName();
00211 if (!code_parm_name)
00212 continue;
00213
00214 if (::strcmp(code_parm_name, parm_name) == 0)
00215 return i;
00216 }
00217
00218 return -1;
00219 }
00220
00221
00222
00223 const char *getParmName(int node_id) const
00224 {
00225 VOP_CodeParm *code_parm;
00226 UT_Thing thing;
00227
00228 if (!myParmNodes.findSymbol(
00229 UT_Hash_Int(node_id), &thing))
00230 return NULL;
00231
00232 code_parm = thing.asPointer<VOP_CodeParm>();
00233 return code_parm->getName();
00234 }
00235
00236 const VOP_CodeParm &operator()(int idx) const
00237 {
00238 return *myParms(idx);
00239 }
00240 VOP_CodeParm &operator()(int idx)
00241 {
00242 return *myParms(idx);
00243 }
00244 int entries() const
00245 {
00246 return myParms.entries();
00247 }
00248 bool hasNode(int node_id) const
00249 {
00250 UT_Thing thing;
00251
00252 return myParmNodes.findSymbol(
00253 UT_Hash_Int(node_id), &thing) != 0;
00254 }
00255 bool hasParmName(const char *parm_name) const
00256 {
00257 if (!parm_name)
00258 return false;
00259
00260 for (int i=0; i<myParms.entries(); i++)
00261 {
00262 const char *code_parm_name;
00263 code_parm_name = myParms(i)->getName();
00264 if (!code_parm_name)
00265 continue;
00266
00267 if (::strcmp(code_parm_name, parm_name) == 0)
00268 return true;
00269 }
00270
00271 return false;
00272 }
00273
00274
00275
00276 private:
00277 UT_PtrArray<VOP_CodeParm*> myParms;
00278 UT_HashTable myParmNodes;
00279 };
00280
00281 class VOP_API VOP_CodeOperatorFilter : public OP_OperatorFilter
00282 {
00283 public:
00284 VOP_CodeOperatorFilter(const char *optypename, VOP_CodeGenerator *owner);
00285 virtual ~VOP_CodeOperatorFilter();
00286
00287 virtual bool allowOperatorAsChild(OP_Operator *op);
00288
00289 private:
00290 UT_StringArray myVopnetTypes;
00291 VOP_CodeGenerator *myOwner;
00292 };
00293
00294
00295 class VOP_API VOP_CodeGenerator
00296 {
00297 public:
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310 VOP_CodeGenerator(OP_Network *owner,
00311 VOP_LanguageContextTypeList * context_type,
00312 int mininputs,
00313 int maxinputs);
00314 virtual ~VOP_CodeGenerator(void);
00315
00316 OP_OperatorFilter *getOperatorFilter();
00317 UT_ErrorManager &getErrorManager();
00318
00319 void beforeAddNode(OP_Node *node);
00320 void afterAddNode(OP_Node *node);
00321 void appendCompileErrors(OP_NodeInfoParms &info,
00322 bool addseparator) const;
00323
00324
00325
00326 void resetTables(VOP_Node *node);
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343 int beginUpdate();
00344 void endUpdate(int update_level);
00345
00346 void clearAllUpdateFlags()
00347 {
00348 myNeedsErrorUpdate = false;
00349 myNeedsParmUpdate = false;
00350 myNeedsCodeUpdate = false;
00351 }
00352 void setNeedsErrorUpdate()
00353 {
00354 UT_ASSERT(myUpdateLevel > 0);
00355 myNeedsErrorUpdate = true;
00356 }
00357 void setNeedsParmUpdate()
00358 {
00359 UT_ASSERT(myUpdateLevel > 0);
00360 myNeedsParmUpdate = true;
00361 }
00362 void setNeedsCodeUpdate()
00363 {
00364 UT_ASSERT(myUpdateLevel > 0);
00365 myNeedsCodeUpdate = true;
00366 }
00367 void performFullUpdate()
00368 {
00369 int update_id = beginUpdate();
00370 setNeedsErrorUpdate();
00371 setNeedsParmUpdate();
00372 setNeedsCodeUpdate();
00373 endUpdate(update_id);
00374 }
00375
00376
00377
00378
00379
00380
00381 void setContextParmTagDirty()
00382 {
00383 myContextParmTagDirty = true;
00384 }
00385 bool isContextParmTagDirty() const
00386 {
00387 return myContextParmTagDirty;
00388 }
00389
00390
00391 void ownerChanged(OP_EventType reason, void *data);
00392 void ownerFinishedLoadingNetwork();
00393 void generateVopErrors();
00394 bool getVariableString(int index, UT_String &value);
00395
00396
00397
00398
00399
00400 void updateExportedParameters();
00401
00402
00403
00404
00405
00406
00407
00408
00409 void updateExportedParameterLayout(
00410 const PI_EditScriptedParms &new_parm_layout,
00411 const PI_OldParms &old_parms,
00412 bool apply_changes_to_parm_vops=false);
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423 void getExportedParameterLayout(
00424 PI_EditScriptedParms &parm_layout,
00425 bool use_incoming_layout=false);
00426
00427 const char *getEnglishName();
00428
00429
00430
00431
00432 const char *getFunctionName(UT_WorkBuffer &storage) const;
00433 const char *getInternalFunctionName(UT_WorkBuffer &storage) const;
00434
00435
00436 const char *getFunctionPath(UT_WorkBuffer &storage) const;
00437 int getMinimumInputs() const;
00438 int getMaximumInputs() const;
00439 void getInternalOperatorInfo(OP_OTLDefinition &info);
00440 void getInternalScriptDefinition(UT_String &definition);
00441
00442
00443 bool canGenerateCode( VOP_Type shader_type) const;
00444
00445 void setVexCodeDirty();
00446 bool outputVexCode(ostream &os, const char *shadername,
00447 VOP_ContextType context_type =
00448 VOP_CONTEXT_TYPE_INVALID);
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466 void outputVflCode(ostream &os, const char *shadername,
00467 VOP_ContextType context_type =
00468 VOP_CONTEXT_TYPE_INVALID,
00469 bool skipheader = false,
00470 const char * output_node_name = NULL);
00471
00472
00473
00474 int getCachedCodeTimeStamp(VOP_ContextType context_type) const;
00475
00476
00477 void outputExportedParameterLayout(ostream &os);
00478
00479 void generateRslObject(UT_String &ofile,
00480 const char *cache_directory,
00481 const char *renderer,
00482 int major_version,
00483 int minor_version,
00484 const char *shaderpath,
00485 const char *shadername,
00486 VOP_ContextType context_type,
00487 bool ignore_dirty_flag,
00488 UT_String *error_return);
00489
00490
00491 void getParameterNodes(VOP_CodeParmList &list,
00492 bool includeInvisible);
00493
00494
00495 void getOutputNodes(VOP_NodeList & outputs) const;
00496
00497
00498 VOP_Collect *getCollectNode() const;
00499
00500
00501
00502 VOP_Node *getEncapsulatedShader(VOP_ContextType context) const;
00503
00504
00505
00506 bool hasParmNode(const char *parm_name) const;
00507
00508
00509
00510
00511 VOP_ParmGenerator *getParmNode(const char *parm_name) const;
00512
00513
00514
00515
00516 const char *getParmName(int node_id) const;
00517
00518
00519 const char *getCompiler(UT_String &compiler, fpreal now,
00520 const char *defcompiler);
00521 const char *getCompiler(UT_WorkBuffer &wbuf, fpreal now,
00522 const char *defcompiler);
00523
00524
00525
00526 bool getCompilerErrors(UT_String * errors) const;
00527
00528
00529 const VOP_Language *getLanguage() const
00530 { return myLanguage; }
00531
00532
00533
00534
00535 const VOP_LanguageContextTypeList * getLanguageContextTypeList() const
00536 { return myContextTypeList; }
00537
00538
00539 VOP_LanguageType getLanguageType() const;
00540
00541
00542
00543 bool isSingleContextType() const;
00544
00545
00546
00547 bool getOwnerHasParameters() const
00548 { return myOwnerHasParameters; }
00549
00550
00551
00552
00553
00554 VOP_ContextType getVopContextType() const;
00555
00556
00557
00558
00559
00560 VEX_ContextType getVexContextType() const;
00561
00562
00563
00564
00565
00566 RSL_ContextType getRslContextType() const;
00567
00568
00569 VOP_CodeCompilerArgs*getCompilerArgs()
00570 { return myCompilerArgs; }
00571
00572
00573
00574
00575 void setLockedCompiledCode(const char *code, VOP_ContextType context_type);
00576 void setLockedCompiledDs(const char *ds);
00577
00578
00579
00580 static VOP_CodeGenerator * findCodeGenerator( const OP_Node * node );
00581
00582
00583 static void getRegisteredRslContexts(
00584 UT_RefArray<RSL_ContextType> & context_types );
00585
00586 static const char *getRslContextName( RSL_ContextType context_type );
00587
00588
00589 static RSL_ContextType getRslContextTypeFromName( const char * name );
00590
00591
00592 static const char *getRslContextLabel( RSL_ContextType context_type );
00593
00594
00595
00596 static CH_LocalVariable theLocalVariables[];
00597
00598
00599 static void installCommands();
00600
00601
00602
00603 static bool convertVopOpToVopOpType(OP_Node *node,
00604 UT_String &err);
00605
00606
00607
00608 static PRM_Name theVopCompilerName;
00609 static PRM_Default theVopCompilerVexDefault;
00610 static PRM_Default theVopCompilerRslDefault;
00611 static PRM_ChoiceList theVopCompilerChoices;
00612 static PRM_Name theVopForceCompileName;
00613
00614 static bool forceCompile(OP_Node *node);
00615 static int forceCompile(void *data, int, fpreal,
00616 const PRM_Template *);
00617
00618
00619
00620
00621 VEX_ContextType pickVexContextType(VOP_ContextType context_type) const;
00622
00623
00624
00625
00626 RSL_ContextType pickRslContextType(VOP_ContextType context_type) const;
00627
00628
00629
00630
00631
00632 VOP_ContextType pickContextType(VOP_ContextType context_type) const;
00633
00634
00635
00636 VOP_Node *getProcedural(VOP_Type interpret_type) const;
00637
00638
00639 void getPropertiesNodes(VOP_NodeList &properties);
00640
00641 const VOP_CodeParmList &getCodeParmList() const
00642 { return myExportedCodeParms; }
00643
00644 bool isCompiled(VOP_ContextType context_type) { return myLockedCompiledCode[context_type].length() > 0; }
00645
00646 private:
00647
00648
00649
00650
00651 bool getNodesForShader(VOP_NodeList &nodes,
00652 VOP_ContextType picked_context_type,
00653 VOP_CodeVarMapperContext &varmap_context,
00654 const char *output_node_name);
00655
00656
00657 void cleanupNodesForShader(VOP_NodeList &nodes);
00658
00659 void outputBodyCodeWithIndents(ostream &os,
00660 UT_WorkBuffer &code);
00661 void outputVflHeaderComment(ostream &os);
00662 bool outputVflPragmasAndFunctionBlock(ostream &os,
00663 const char *shadername,
00664 VOP_ContextType context_type,
00665 const char *output_node_name);
00666 void outputVflPragmas(ostream &os,
00667 const VOP_NodeList & nodes,
00668 VOP_ContextType context_type);
00669 bool outputVflFunctionBlock(ostream &os,
00670 const VOP_NodeList & nodes,
00671 VOP_CodeVarMapperContext & root_varmap_context,
00672 const char *shadername,
00673 VOP_ContextType context_type);
00674 void outputVflFunctionDeclaration(ostream &os,
00675 const VOP_NodeList & nodes,
00676 const char *shadername,
00677 VOP_ContextType context_type);
00678 void outputVflEmptyFunction(ostream &os,
00679 const char *shadername,
00680 VOP_ContextType context_type);
00681 void outputChildrenParameterBlocks(OP_Network *net,
00682 ostream &os);
00683 void outputParameterDeclarations(ostream &os,
00684 const VOP_NodeList & nodes,
00685 const char *indent,
00686 VOP_ContextType context_type);
00687 void outputDSNodeInfo(ostream &os);
00688
00689 void clearFileCache();
00690
00691
00692
00693 void generateScriptDefinition(UT_String &definition);
00694
00695
00696
00697
00698
00699 void generateLayoutScriptDefinition(UT_String &definition);
00700
00701
00702 void buildParmContextInfo(VOP_ParmContextInfo &info);
00703
00704
00705
00706 void getParameterNodes(OP_Network *net,
00707 VOP_CodeParmList &list,
00708 ostream *os,
00709 bool includeInvisible,
00710 const VOP_ParmContextInfo &info);
00711 void getParameterNodes(VOP_CodeParmList &list,
00712 ostream *os,
00713 bool includeInvisible);
00714 void assignSubnetInOutVariables(VOP_Node *node,
00715 VOP_Node *subnet,
00716 UT_SymbolTable &localVarTables,
00717 VOP_CodeVarLookupData &data) const;
00718
00719
00720
00721
00722 void expandSubnetsAndFetchVOPs(VOP_NodeList &nodes,
00723 VOP_ContextType context_type,
00724 VOP_CodeVarMapperContext &root_context) const;
00725
00726
00727 static const char *createUniqueVariableName(const char *str,
00728 UT_SymbolTable &varTable);
00729 static const char *doVariableReplacement(const char *str,
00730 void *userdata);
00731
00732
00733
00734
00735
00736 static void resolveVariableFromNodeInput(VOP_Node *vop,
00737 int inputidx, VOP_CodeVarLookupData *data,
00738 VOP_CodeVarMapperContext *context,
00739 UT_String &variable);
00740
00741 void addVariableNames(VOP_Node *vop,
00742 UT_SymbolTable &varTable,
00743 VOP_CodeVarMapper &varMapper,
00744 VOP_CodeVarMapperContext *context);
00745
00746
00747
00748
00749
00750
00751 void ensureTempFilesCreated(VOP_ContextType context_type,
00752 UT_String & vfl_file,
00753 UT_String & err_file);
00754
00755
00756
00757 void getRslFileSuffix( UT_String & suffix,
00758 VOP_ContextType context_type );
00759
00760
00761
00762
00763 struct VOP_CodeCacheData
00764 {
00765 VOP_ContextType myContextType;
00766 UT_String myCode;
00767 UT_String myErrorMessages;
00768 unsigned int myTimeStamp;
00769 };
00770
00771
00772 bool hasCachedCode() const;
00773 VOP_CodeCacheData * findCachedCode( VOP_ContextType context_type ) const;
00774 VOP_CodeCacheData * addCachedCode( VOP_ContextType context_type,
00775 const char * code,
00776 const UT_String * errors );
00777 void deleteCachedCode( VOP_ContextType context_type );
00778 VOP_CodeCacheData * removeCachedCode( VOP_ContextType context_type );
00779 void addCachedCode( VOP_ContextType context_type,
00780 VOP_CodeCacheData * cache_data );
00781 void clearCachedCode();
00782
00783
00784
00785
00786
00787 void getRenamedAndDeletedParms(
00788 const VOP_CodeParmList &old_code_parms,
00789 const VOP_CodeParmList &new_code_parms,
00790 PI_OldParms &old_parms) const;
00791
00792
00793
00794 void propagateChangesToParmVOPs(
00795 const PI_OldParms &old_parms) const;
00796
00797
00798
00799
00800 void mergeSpareParms(PI_EditScriptedParms &merge_to,
00801 PI_EditScriptedParms &merge_from) const;
00802
00803
00804
00805
00806 bool isMetaSwitchParm(long parm_index) const;
00807
00808
00809 OP_Network *myOwner;
00810 VOP_LanguageContextTypeList *myContextTypeList;
00811
00812 TContextTypeStringMap myLockedCompiledCode;
00813 UT_WorkBuffer myLockedCompiledDs;
00814 UT_SymbolTable myGlobalVariables;
00815 UT_SymbolTable myLocalVariables;
00816 UT_SymbolTable myLocalChannels;
00817 VOP_CodeOperatorFilter myOperatorFilter;
00818 VOP_Language *myLanguage;
00819 VOP_CodeCompilerArgs *myCompilerArgs;
00820 UT_ErrorManager myErrorManager;
00821 UT_PtrArray<VOP_CodeCacheData*> myCachedCode;
00822 UT_SymbolTable myTempVflFiles;
00823 UT_SymbolTable myTempErrFiles;
00824 UT_String myHipName;
00825 UT_String myCachedEnglishName;
00826 UT_String myCachedDialogScript;
00827 UT_String myCachedLayoutDialogScript;
00828 int myCachedMinInputs;
00829 int myCachedMaxInputs;
00830 int myMinimumNumberOfInputs;
00831 int myMaximumNumberOfInputs;
00832 VOP_CodeParmList myExportedCodeParms;
00833
00834 int myUpdateLevel;
00835 bool myNeedsErrorUpdate;
00836 bool myNeedsParmUpdate;
00837 bool myNeedsCodeUpdate;
00838
00839 bool myOwnerHasParameters;
00840 bool myIsChangingOwnerSpareParms;
00841 bool myIsReCookingOwner;
00842 bool myNeedAutoConvertCleanup;
00843
00844 bool myContextParmTagDirty;
00845 };
00846
00847 class VOP_CodeGeneratorErrorThief
00848 {
00849 public:
00850 VOP_CodeGeneratorErrorThief(OP_Node &node)
00851 : myNode(node)
00852 {
00853 }
00854 ~VOP_CodeGeneratorErrorThief()
00855 {
00856 if( myNode.getVopCodeGenerator() )
00857 {
00858 myNode.stealErrors(
00859 myNode.getVopCodeGenerator()->getErrorManager(),
00860 true);
00861 }
00862 }
00863
00864 private:
00865 OP_Node &myNode;
00866 };
00867
00868 #endif