00001 /* 00002 * PROPRIETARY INFORMATION. This software is proprietary to 00003 * Side Effects Software Inc., and is not to be reproduced, 00004 * transmitted, or disclosed in any way without written permission. 00005 * 00006 * Produced by: 00007 * Mark Alexander 00008 * Side Effects 00009 * 123 Front Street West, Suite 1401 00010 * Toronto, Ontario 00011 * Canada M5J 2M2 00012 * 416-504-9876 00013 * 00014 * NAME: RE_OGLComputeGPU.h ( RE Library, C++) 00015 * 00016 * COMMENTS: 00017 * A high level interface to allow GP-GPU computing (general purpose 00018 * computation on the GPU, or video card). This uses RE_FrameBuffer (output), 00019 * textures (array input), and RE_Shaders (GLSL or Cg program) to perform the 00020 * computation. 00021 * 00022 * Setting up the computation is relatively expensive, so this should only 00023 * be used for large volumes of data. 00024 * 00025 * Once you have set up the program, output and input(s), you can change one 00026 * or all of them for the next run. If you call setConstant() or setArray() 00027 * with the same name as an existing constant or array, the data will be 00028 * updated as long as the data format and size remains the same (otherwise 00029 * another constant or texture will be created for it). 00030 * 00031 * You can use special macros to read from the input arrays (which are 00032 * textures) using integer indices rather than floating point texture 00033 * coords: 00034 * 00035 * IN_array_name // at current output pos. 00036 * ABS_array_name (int_pos) // at an absolute position. 00037 * REL_array_name (int_offset) // offset from current pos. 00038 * 00039 * (Note: 2D Arrays will have 2 pos / offset parms) 00040 * 00041 * You can use the first version to grab the corresponding input element 00042 * only if it matches the output in size and dimensions (1d/2d). Otherwise, 00043 * you'll get array bounds issues. 00044 */ 00045 #ifndef RE_OGLComputeGPU_h 00046 #define RE_OGLComputeGPU_h 00047 00048 #include "RE_API.h" 00049 #include "RE_Types.h" 00050 #include <PXL/PXL_Common.h> 00051 #include <IMG/IMG_FileTypes.h> 00052 #include <UT/UT_LinkList.h> 00053 #include <UT/UT_PtrArray.h> 00054 00055 class UT_String; 00056 class re_GPUConstant; 00057 class re_GPUInputArray; 00058 class re_GPUFrameBuffer; 00059 class re_GPUInputArrayProxy; 00060 class re_GPUData; 00061 class re_ProgramRun; 00062 class re_GPUProgram; 00063 00064 RE_API RE_GPUType REconvertIMGType(IMG_DataType t); 00065 RE_API RE_GPUType REconvertPXLType(PXL_DataFormat t); 00066 00067 00068 class RE_API RE_OGLComputeGPU 00069 { 00070 public: 00071 RE_OGLComputeGPU(); 00072 ~RE_OGLComputeGPU(); 00073 00074 enum RE_OGLComputeLanguage 00075 { 00076 OGL_GLSL, // OpenGL GLSL (must have OpenGL 2.0 or shader exts) 00077 OGL_CG // Nvidia Cg (must have Cg toolkit installed) 00078 }; 00079 00080 static void initStandalone(); 00081 00082 // Returns true if the graphics hardware has proper support to use this 00083 // class. 00084 static bool hasGPUSupport(); 00085 00086 // 0. If you're doing multiple passes, you should set how many passes you 00087 // wish to do. This is optional - it defaults to 1 pass. 00088 // TODO: This is not supported yet. 00089 void setNumPasses(int passes); 00090 00091 // If enabled, your shader is using integer bit operations. Not all cards 00092 // support this. 00093 void needBitOps(bool enable); 00094 bool needsBitOps() const { return myBitOpsUsed; } 00095 static bool areBitOpsSupported(); 00096 00097 // 1. Inputs to computation. 00098 // You may rewrite to existing values to begin another computation. 00099 // This class does not take ownership of the value array you pass in - 00100 // you are responsible for deleting it, but do not do so until compute() 00101 // has been called. 00102 // The OpenGL texture size limits the maximum array size. 1D Arrays 00103 // have a max of this size squared, 2D arrays must have both dimensions 00104 // under this size (see RE_OGLRender::getMaxTextureSize()). setArray() 00105 // will return NULL if these limits are exceeeded. 00106 00107 // Data types available for I/O 00108 // - constants are usually int32's, float32's or matrices. 00109 // - input and output arrays cannot be arrays of matrices (currently) 00110 00111 // Constants are usually RE_GPU_FLOAT32, RE_GPU_(U)INT32 OR 00112 // RE_GPU_MATRIX[n]. They can be a small array, but GLSL will not allow 00113 // you to dynamically index them (ie, [x], only [1] or using fixed range 00114 // loop variables like x=1 to 10). If you need to dynamically index, 00115 // use an Array. Constant arrays are very lightweight, though. 00116 void setConstant(const char *name, 00117 RE_GPUType type, 00118 int vectorsize, 00119 const void *value, 00120 int array_size = 1, 00121 bool global_var = false); 00122 00123 void * setArray(const char *name, 00124 RE_GPUType type, 00125 int vectorsize, 00126 int size, 00127 const void *values); 00128 00129 void * setArray2D(const char *name, 00130 RE_GPUType type, 00131 int vectorsize, 00132 int width, 00133 int height, 00134 const void *values); // in rows. 00135 00136 // flat arrays to vectors (interleaves to 1,2,3,4, 1,2,3,4). Not all 00137 // components need to be specified. 00138 void * setArray(const char *name, 00139 RE_GPUType type, 00140 int vectorsize, 00141 int size, 00142 const void *values1, 00143 const void *values2, 00144 const void *values3 = NULL, 00145 const void *values4 = NULL); 00146 00147 void * setArray2D(const char *name, 00148 RE_GPUType type, 00149 int vectorsize, 00150 int width, 00151 int height, 00152 const void *values1, 00153 const void *values2, 00154 const void *values3 = NULL, 00155 const void *values4 = NULL); 00156 00157 // 2. Output data. 00158 // You can add multiple outputs, but they all must be the same size, type 00159 // and vectorsize. 'dest_data' is where the results are written. 00160 00161 void setOutputArray(const char *name, 00162 RE_GPUType type, 00163 int vectorsize, 00164 int size, 00165 void *dest_data); 00166 00167 void setOutputArray2D(const char *name, 00168 RE_GPUType type, 00169 int vectorsize, 00170 int width, 00171 int height, 00172 void *dest_data); 00173 00174 // Convienience method to determine the size of the array you will need 00175 // for an output buffer (or need to provide for an input buffer). 00176 // 1D arrays only need to pass xsize. 00177 int getDataByteSize(RE_GPUType type, int vectorsize, 00178 int xsize, int ysize = 1); 00179 00180 // 3. GLSL/Cg Program (false if it fails to compile) 00181 // 'name' is arbitrary, for debug messages. 00182 // 'program' is the actual program code. 00183 // If 'auto_generate_framework' is true, this class prepends the GLSL 00184 // constant and texture declarations (as named above), then 00185 // 'void main(void) {', your code, and then '}' (so all you need to do is 00186 // fill in the actual code). If non-NULL, 'preamble_code' will be placed 00187 // before the declarations. 00188 00189 void setLanguage(RE_OGLComputeLanguage lang); 00190 00191 bool setProgram(const char *name, 00192 const char *program, 00193 bool auto_generate_framework = true, 00194 const char *preamble_code = NULL, 00195 const char *function_code = NULL); 00196 00197 // This allows you to define macros and symbols for preprocessing. 00198 void defineSymbol(const char *symbol, 00199 const char *value); 00200 00201 // 4. Computation 00202 // Runs the program on the inputs to produce the output. Returns a 00203 // pointer to the result (in the output format and dimensions specified 00204 // above). Returns false if an opengl error occured. 00205 // Once you have called compute, you may begin another computation 00206 // before fetching the results (just go back to step 1). 00207 00208 // 'async_read' starts the DMA transfer of the results after the 00209 // computation is finshed. Useful when you have more than one output, 00210 // or more work to do between compute() and getResult(). Note 00211 // that this call will block until the computation is done, so for long 00212 // computations, you may want to take the latency hit. If pixel buffer 00213 // objects are not supported, this is ignored. 00214 00215 bool compute(UT_String &errors, bool async_read = false); 00216 00217 // 5. Fetch Results 00218 // Notify the engine that you'd like to use your results. With multiple 00219 // active computations, this removes the oldest and another getResult() 00220 // will begin fetching from the next oldest computation. 00221 // 00222 // Your results will be available _after_ this method is called. This 00223 // returns false if your results could not be read. 00224 bool getResults(); 00225 00226 // Alternatively, you can use a deferred scheme to retrive the data. 00227 // 1. Call deferred fetch to grab a key to the results. 00228 // 2. You can optionally call beginDeferredRead() some time afterward 00229 // to start the asynchronouse read. 00230 // 3. Call endDeferredRead() to ensure that all results have been read. 00231 // The key is no longer valid after step 3. 00232 00233 void *useDeferredFetch(); 00234 00235 static void beginDeferredRead(void *key); 00236 static bool endDeferredRead(void *key); 00237 static void cancelDeferredRead(void *key); 00238 00239 // Returns true if texture rectangles must be used (because standard 2D 00240 // textures do not support most higher formats on some hardware) 00241 static bool useTextureRectangles(); 00242 00243 // The largest sizes that this GPU can handle. 00244 static int getMaxArraySize(); 00245 static int getMaxArraySize2D(); 00246 00247 // Clears all the GP-GPU allocated objects. You don't normally need to 00248 // call this. 00249 static void reset(); 00250 00251 static void restoreState(); 00252 static void cleanupState(); 00253 private: 00254 bool initFrameBuffers(); 00255 00256 re_ProgramRun *myProgram; 00257 bool myProgramRunFlag; 00258 bool myBitOpsUsed; 00259 }; 00260 00261 #endif
1.5.9