1 /* 2 A* ------------------------------------------------------------------- 3 B* This file contains source code for the PyMOL computer program 4 C* copyright Schrodinger, LLC. 5 D* ------------------------------------------------------------------- 6 E* It is unlawful to modify or remove this copyright notice. 7 F* ------------------------------------------------------------------- 8 G* Please see the accompanying LICENSE file for further information. 9 H* ------------------------------------------------------------------- 10 I* Additional authors of this source file include: 11 -* 12 -* 13 -* 14 Z* ------------------------------------------------------------------- 15 */ 16 #ifndef _SHADER_MGR_H 17 #define _SHADER_MGR_H 18 19 #include "os_gl.h" 20 #include "PyMOLGlobals.h" 21 #include "Executive_pre.h" 22 #include "OVContext.h" 23 #include "Rep.h" 24 #include "GenericBuffer.h" 25 #include "SceneDef.h" 26 #include "PostProcess.h" 27 #include <map> 28 #include <set> 29 #include <string> 30 #include <unordered_map> 31 32 #ifdef _WEBGL 33 #define GET_FRAGDEPTH_SUPPORT() webpymol_get_fragdepth_support() 34 #elif defined(_PYMOL_IOS) 35 #define GET_FRAGDEPTH_SUPPORT() 0 36 #else 37 #define GET_FRAGDEPTH_SUPPORT() 1 38 #endif 39 40 #if !defined(_WEBGL) 41 #include <mutex> 42 #define LOCK_GUARD_MUTEX(name, var) std::lock_guard<std::mutex> name(var) 43 #else 44 #define LOCK_GUARD_MUTEX(name, var) 45 #endif 46 47 #ifndef GL_FRAGMENT_PROGRAM_ARB 48 #define GL_FRAGMENT_PROGRAM_ARB 0x8804 49 #endif 50 51 /* BEGIN PROPRIETARY CODE SEGMENT (see disclaimer in "os_proprietary.h") */ 52 #if 0 53 PFNGLTEXIMAGE3DPROC getTexImage3D(); 54 static PFNGLTEXIMAGE3DPROC glTexImage3D; 55 static PFNGLGENPROGRAMSARBPROC glGenProgramsARB; 56 static PFNGLBINDPROGRAMARBPROC glBindProgramARB; 57 static PFNGLDELETEPROGRAMSARBPROC glDeleteProgramsARB; 58 static PFNGLPROGRAMSTRINGARBPROC glProgramStringARB; 59 static PFNGLPROGRAMENVPARAMETER4FARBPROC glProgramEnvParameter4fARB; 60 static PFNGLGETPROGRAMIVARBPROC glGetProgramivARB; 61 #endif 62 /* END PROPRIETARY CODE SEGMENT */ 63 64 class CShaderPrg { 65 public: 66 const std::string name, geomfile, vertfile, fragfile; 67 68 std::map<int, std::string> uniformLocations; 69 70 GLenum gsInput, gsOutput; 71 int ngsVertsOut; 72 73 std::string derivative; 74 bool is_valid; 75 bool is_linked; 76 77 CShaderPrg(PyMOLGlobals * G_, 78 const std::string &name, 79 const std::string &vertfile, 80 const std::string &fragfile, 81 const std::string &geomfile = "", 82 GLenum gsInput = 0, 83 GLenum gsOutput = 0, 84 int ngsVertsOut = 0) : name(name)85 name(name), 86 geomfile(geomfile), vertfile(vertfile), fragfile(fragfile), 87 gsInput(gsInput), gsOutput(gsOutput), ngsVertsOut(ngsVertsOut), 88 is_valid(false), is_linked(false), G(G_), 89 id(0), gid(0), vid(0), fid(0), uniform_set(0) {} 90 ~CShaderPrg()91 ~CShaderPrg() {} 92 93 bool reload(); 94 95 /* 96 * Create a derivative copy. This will reload with ShaderMgr::Reload_Derivatives. 97 */ DerivativeCopy(const std::string & name,const std::string & variable)98 CShaderPrg * DerivativeCopy(const std::string &name, const std::string &variable) { 99 CShaderPrg * copy = new CShaderPrg(G, name, vertfile, fragfile, geomfile, gsInput, gsOutput, ngsVertsOut); 100 copy->derivative = variable; 101 return copy; 102 } 103 104 #ifdef _PYMOL_ARB_SHADERS 105 static CShaderPrg *NewARB(PyMOLGlobals * G, const char * name, const std::string& vert, const std::string& frag); 106 int DisableARB(); 107 #endif 108 109 /* Enable */ 110 int Enable(); 111 112 /* Disable */ 113 int Disable(); 114 115 /* Link and IsLinked */ 116 int Link(); 117 int IsLinked(); 118 119 /* accessors/mutators/uniform setters */ 120 int Set1i(const char * name, int i); 121 int Set1f(const char * name, float f); 122 int Set2f(const char * name, float f1, float f2); 123 int Set3f(const char * name, float f1, float f2, float f3); 124 int Set4fv(const char * name, const float *f); 125 int Set3fv(const char * name, const float *f); 126 int Set4f(const char * name, float f1, float f2, float f3, float f4); 127 int SetMat3fc(const char * name, const GLfloat * m); 128 int SetMat4fc(const char * name, const GLfloat * m); 129 130 int GetUniformLocation(const char * name); 131 int GetAttribLocation(const char * name); 132 void SetAttrib4fLocation(const char * name, float f1, float f2, float f3, float f4); 133 void SetAttrib1fLocation(const char * name, float f1); 134 135 int SetLightingEnabled(int); 136 void SetBgUniforms(); 137 void Set_Stereo_And_AnaglyphMode(); 138 void Set_AnaglyphMode(int mode); 139 void Set_Matrices(); 140 void Set_Specular_Values(); 141 142 void Invalidate(); 143 void ErrorMsgWithShaderInfoLog(const GLuint sid, const char * msg); 144 145 public: 146 PyMOLGlobals * G; 147 148 /* openGL assigned id */ 149 int id; 150 151 /* openGL fragment and vertex shader ids */ 152 GLuint gid; 153 GLuint vid; 154 GLuint fid; 155 156 std::map<std::string, int> uniforms; 157 std::map<std::string, int> attributes; 158 159 int uniform_set ; // bitmask 160 }; 161 162 /* ============================================================================ 163 * CShaderMgr class -- simple ShaderMgr for PyMOL 164 * ============================================================================*/ 165 class CShaderMgr { 166 public: 167 CShaderMgr(PyMOLGlobals * G); 168 ~CShaderMgr(); 169 170 void Config(); 171 void Set_Reload_Bits(int bits); 172 void Check_Reload(); 173 GLfloat *GetLineWidthRange(); 174 175 template <typename T, typename... TArgs> newGPUBuffer(TArgs &&...args)176 T * newGPUBuffer(TArgs&&... args) { 177 std::hash<gpuBuffer_t *> hash_fn; 178 T * buffer = new T(std::forward<TArgs>(args)...); 179 auto bufptr = dynamic_cast<gpuBuffer_t *>(buffer); 180 const size_t hashid = hash_fn(bufptr); 181 buffer->set_hash_id(hashid); 182 _gpu_object_map[hashid] = buffer; 183 return buffer; 184 } 185 186 template <typename T> getGPUBuffer(size_t hashid)187 T * getGPUBuffer(size_t hashid) { 188 auto search = _gpu_object_map.find(hashid); 189 if (search != _gpu_object_map.end()) 190 return dynamic_cast<T*>(search->second); 191 else 192 return nullptr; 193 } 194 195 void bindGPUBuffer(size_t hashid); 196 void freeGPUBuffer(size_t handle); 197 void freeGPUBuffers(std::vector<size_t> && handles); 198 void freeGPUBuffers(size_t * arr, size_t len); 199 200 #ifndef _PYMOL_NO_AA_SHADERS 201 bool Reload_SMAA_Shaders(); 202 int SMAAShadersPresent(); 203 CShaderPrg *Enable_FXAAShader(); 204 CShaderPrg *Enable_SMAA1Shader(); 205 CShaderPrg *Enable_SMAA2Shader(); 206 CShaderPrg *Enable_SMAA3Shader(); 207 CShaderPrg *Enable_SMAAShader(const char *shaderName); 208 #endif 209 void Reload_Shader_Variables(); 210 211 /* AddShader -- Adds to the global shader library */ 212 int AddShaderPrg(CShaderPrg * s); 213 214 /* RemoveShader -- Removes shader program by name */ 215 int RemoveShaderPrg(const std::string& name); 216 217 /* GetShaderPrg -- gets a ptr to the installed shader */ 218 CShaderPrg * GetShaderPrg(std::string name, short set_current_shader = 1, short pass = 0); 219 220 int ShaderPrgExists(const char * name); 221 222 /* runtime check for shaders */ 223 int ShadersPresent(); 224 int GeometryShadersPresent(); 225 226 void AddVBOsToFree(GLuint *vboid, int nvbos); 227 void AddVBOToFree(GLuint vboid); 228 void FreeAllVBOs(); 229 230 CShaderPrg *Enable_DefaultShader(int pass); 231 CShaderPrg *Enable_LineShader(int pass); 232 CShaderPrg *Enable_SurfaceShader(int pass); 233 CShaderPrg *Enable_DefaultShaderWithSettings(const CSetting * set1, const CSetting * set2, int pass); 234 CShaderPrg *Enable_CylinderShader(const char *, int pass); 235 CShaderPrg *Enable_CylinderShader(int pass); 236 CShaderPrg *Enable_DefaultSphereShader(int pass); 237 #ifdef _PYMOL_ARB_SHADERS 238 CShaderPrg *Enable_SphereShaderARB(); 239 #endif 240 CShaderPrg *Enable_RampShader(); 241 CShaderPrg *Enable_ConnectorShader(int pass); 242 CShaderPrg *Enable_TriLinesShader(); 243 CShaderPrg *Enable_ScreenShader(); 244 CShaderPrg *Enable_LabelShader(int pass); 245 CShaderPrg *Enable_OITShader(); 246 CShaderPrg *Enable_OITCopyShader(); 247 CShaderPrg *Enable_IndicatorShader(); 248 CShaderPrg *Enable_BackgroundShader(); 249 250 void Disable_Current_Shader(); 251 252 CShaderPrg *Get_ScreenShader(); 253 CShaderPrg *Get_ConnectorShader(int pass); 254 CShaderPrg *Get_DefaultShader(int pass); 255 CShaderPrg *Get_LineShader(int pass); 256 CShaderPrg *Get_SurfaceShader(int pass); 257 CShaderPrg *Get_CylinderShader(int pass, short set_current_shader=1); 258 CShaderPrg *Get_CylinderNewShader(int pass, short set_current_shader=1); 259 CShaderPrg *Get_DefaultSphereShader(int pass); 260 CShaderPrg *Get_RampShader(); 261 CShaderPrg *Get_Current_Shader(); 262 CShaderPrg *Get_IndicatorShader(); 263 CShaderPrg *Get_BackgroundShader(); 264 CShaderPrg *Get_LabelShader(int pass); 265 266 void Reload_CallComputeColorForLight(); 267 void Reload_All_Shaders(); 268 269 void Invalidate_All_Shaders(); 270 271 void ResetUniformSet(); 272 273 void CShaderPrg_SetIsPicking(int is_picking); 274 275 void Generate_LightingTexture(); 276 277 std::string GetShaderSource(const std::string &filename); 278 279 CShaderPrg *Setup_LabelShader(CShaderPrg *shaderPrg); 280 CShaderPrg *Setup_DefaultShader(CShaderPrg *shaderPrg, const CSetting *set1, const CSetting *set2); 281 282 void SetIsPicking(int is_picking); 283 int GetIsPicking(); 284 285 void SetPreprocVar(const std::string &key, bool value, bool invshaders = true); 286 287 private: 288 void freeAllGPUBuffers(); 289 void RegisterDependantFileNames(CShaderPrg * shader); 290 void CollectDependantFileNames(const std::string &filename, std::vector<std::string> &filenames); 291 void MakeDerivatives(const std::string &suffix, const std::string &variable); 292 void Reload_Derivatives(const std::string &variable, bool value = true); 293 void ShaderSourceInvalidate(const char * filename, bool invshaders = true); 294 void SetShaderSource(const char * filename, const std::string &contents); 295 296 public: 297 PyMOLGlobals * G; 298 int shaders_present; 299 300 #ifndef _WEBGL 301 // for deleting buffers in the correct thread 302 std::vector<GLuint> vbos_to_free; 303 std::mutex vbos_to_free_mutex; 304 std::mutex gpu_objects_to_free_mutex; 305 #endif 306 307 CShaderPrg *current_shader; 308 int is_picking; 309 GLuint lightingTexture; 310 311 /* These lookups and arrays are used to dynamically change the shaders 312 based on preprocessor-like statements within the shaders. These need 313 string lookups. */ 314 315 private: 316 // filename -> processed shader source, for #include preprocessor 317 std::map<std::string, std::string> shader_cache_processed; 318 319 // variable -> boolean value for #ifdef preprocessor 320 std::map<std::string, bool> preproc_vars; 321 322 std::unordered_map<size_t, gpuBuffer_t*> _gpu_object_map; 323 std::vector<size_t> _gpu_objects_to_free_vector; 324 public: 325 std::map<std::string, CShaderPrg*> programs; 326 327 std::map<int, std::string> attribute_uids; 328 std::map<const std::string, int> attribute_uids_by_name; 329 int GetAttributeUID(const char * name); 330 const char *GetAttributeName(int); 331 332 short print_warnings; 333 int reload_bits; 334 GLfloat line_width_range[2]; 335 short stereo_flag; /* -1 left; 0 = off; 1 = right */ 336 short stereo_blend; /* 0 - no blend, 1 - blend : for right eye stereo in full-screen e.g., anaglyph */ 337 bool stereo_draw_buffer_pass; 338 GLint default_framebuffer_id { 0 }; 339 private: 340 bool is_configured { false }; 341 public: IsConfigured()342 bool IsConfigured(){ return is_configured; } 343 // filename -> used by shader 344 std::map<std::string, std::vector<std::string> > shader_deps; 345 346 // Post process render targets 347 std::size_t offscreen_rt { 0 }; //Texture before postprocessing; 348 #ifndef _PYMOL_NO_AA_SHADERS 349 std::unique_ptr<PostProcess> smaa_pp; 350 #endif 351 std::unique_ptr<PostProcess> oit_pp; 352 353 void bindOffscreen(int width, int height, GridInfo * grid); 354 void bindOffscreenOIT(int width, int height, int drawbuf = 0); 355 356 /** 357 * Activates/Binds offscreen render target. 358 * @param textureIdx offset of texture unit to assign (0 for GL_TEXTURE0, 1 359 * for GL_TEXTURE1, etc...) 360 * @Note: indices should preferably be passed in as enum or named variable for 361 * clarity 362 */ 363 void activateOffscreenTexture(GLuint textureIdx); 364 }; 365 366 bool ShaderMgrInit(PyMOLGlobals * G); 367 368 /* for reload_bits */ 369 enum { 370 RELOAD_VARIABLES = 0x01, 371 RELOAD_CALLCOMPUTELIGHTING = 0x02, 372 RELOAD_ALL_SHADERS = 0xff, 373 }; 374 375 #define VERTEX_POS_SIZE 3 376 #define VERTEX_COLOR_SIZE 4 377 378 #define VERTEX_POS 0 379 #define VERTEX_NORMAL 1 380 #define VERTEX_COLOR 2 381 382 #define CYLINDER_VERTEX1 0 383 #define CYLINDER_VERTEX2 1 384 #define CYLINDER_COLOR 2 385 #define CYLINDER_COLOR2 3 386 #define CYLINDER_RADIUS 4 387 #define CYLINDER_CAP 5 388 389 #define RAMP_OFFSETPT 0 390 391 #endif 392 393 // vi:sw=2:expandtab 394