llshadermgr.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:11k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llshadermgr.cpp
  3.  * @brief Shader manager implementation.
  4.  *
  5.  * $LicenseInfo:firstyear=2005&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2005-2010, Linden Research, Inc.
  8.  * 
  9.  * Second Life Viewer Source Code
  10.  * The source code in this file ("Source Code") is provided by Linden Lab
  11.  * to you under the terms of the GNU General Public License, version 2.0
  12.  * ("GPL"), unless you have obtained a separate licensing agreement
  13.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  14.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16.  * 
  17.  * There are special exceptions to the terms and conditions of the GPL as
  18.  * it is applied to this Source Code. View the full text of the exception
  19.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  20.  * online at
  21.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22.  * 
  23.  * By copying, modifying or distributing this software, you acknowledge
  24.  * that you have read and understood your obligations described above,
  25.  * and agree to abide by those obligations.
  26.  * 
  27.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29.  * COMPLETENESS OR PERFORMANCE.
  30.  * $/LicenseInfo$
  31.  */
  32. #include "linden_common.h"
  33. #include "llshadermgr.h"
  34. #include "llfile.h"
  35. #include "llrender.h"
  36. #if LL_DARWIN
  37. #include "OpenGL/OpenGL.h"
  38. #endif
  39. #ifdef LL_RELEASE_FOR_DOWNLOAD
  40. #define UNIFORM_ERRS LL_WARNS_ONCE("Shader")
  41. #else
  42. #define UNIFORM_ERRS LL_ERRS("Shader")
  43. #endif
  44. // Lots of STL stuff in here, using namespace std to keep things more readable
  45. using std::vector;
  46. using std::pair;
  47. using std::make_pair;
  48. using std::string;
  49. LLShaderMgr * LLShaderMgr::sInstance = NULL;
  50. LLShaderMgr::LLShaderMgr()
  51. {
  52. }
  53. LLShaderMgr::~LLShaderMgr()
  54. {
  55. }
  56. // static
  57. LLShaderMgr * LLShaderMgr::instance()
  58. {
  59. if(NULL == sInstance)
  60. {
  61. LL_ERRS("Shaders") << "LLShaderMgr should already have been instantiated by the application!" << LL_ENDL;
  62. }
  63. return sInstance;
  64. }
  65. BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
  66. {
  67. llassert_always(shader != NULL);
  68. LLShaderFeatures *features = & shader->mFeatures;
  69. //////////////////////////////////////
  70. // Attach Vertex Shader Features First
  71. //////////////////////////////////////
  72. // NOTE order of shader object attaching is VERY IMPORTANT!!!
  73. if (features->calculatesAtmospherics)
  74. {
  75. if (!shader->attachObject("windlight/atmosphericsVarsV.glsl"))
  76. {
  77. return FALSE;
  78. }
  79. }
  80. if (features->calculatesLighting)
  81. {
  82. if (!shader->attachObject("windlight/atmosphericsHelpersV.glsl"))
  83. {
  84. return FALSE;
  85. }
  86. if (features->isSpecular)
  87. {
  88. if (!shader->attachObject("lighting/lightFuncSpecularV.glsl"))
  89. {
  90. return FALSE;
  91. }
  92. if (!shader->attachObject("lighting/sumLightsSpecularV.glsl"))
  93. {
  94. return FALSE;
  95. }
  96. if (!shader->attachObject("lighting/lightSpecularV.glsl"))
  97. {
  98. return FALSE;
  99. }
  100. }
  101. else 
  102. {
  103. if (!shader->attachObject("lighting/lightFuncV.glsl"))
  104. {
  105. return FALSE;
  106. }
  107. if (!shader->attachObject("lighting/sumLightsV.glsl"))
  108. {
  109. return FALSE;
  110. }
  111. if (!shader->attachObject("lighting/lightV.glsl"))
  112. {
  113. return FALSE;
  114. }
  115. }
  116. }
  117. // NOTE order of shader object attaching is VERY IMPORTANT!!!
  118. if (features->calculatesAtmospherics)
  119. {
  120. if (!shader->attachObject("windlight/atmosphericsV.glsl"))
  121. {
  122. return FALSE;
  123. }
  124. }
  125. if (features->hasSkinning)
  126. {
  127. if (!shader->attachObject("avatar/avatarSkinV.glsl"))
  128. {
  129. return FALSE;
  130. }
  131. }
  132. ///////////////////////////////////////
  133. // Attach Fragment Shader Features Next
  134. ///////////////////////////////////////
  135. if(features->calculatesAtmospherics)
  136. {
  137. if (!shader->attachObject("windlight/atmosphericsVarsF.glsl"))
  138. {
  139. return FALSE;
  140. }
  141. }
  142. // NOTE order of shader object attaching is VERY IMPORTANT!!!
  143. if (features->hasGamma)
  144. {
  145. if (!shader->attachObject("windlight/gammaF.glsl"))
  146. {
  147. return FALSE;
  148. }
  149. }
  150. if (features->hasAtmospherics)
  151. {
  152. if (!shader->attachObject("windlight/atmosphericsF.glsl"))
  153. {
  154. return FALSE;
  155. }
  156. }
  157. if (features->hasTransport)
  158. {
  159. if (!shader->attachObject("windlight/transportF.glsl"))
  160. {
  161. return FALSE;
  162. }
  163. // Test hasFullbright and hasShiny and attach fullbright and 
  164. // fullbright shiny atmos transport if we split them out.
  165. }
  166. // NOTE order of shader object attaching is VERY IMPORTANT!!!
  167. if (features->hasWaterFog)
  168. {
  169. if (!shader->attachObject("environment/waterFogF.glsl"))
  170. {
  171. return FALSE;
  172. }
  173. }
  174. if (features->hasLighting)
  175. {
  176. if (features->hasWaterFog)
  177. {
  178. if (!shader->attachObject("lighting/lightWaterF.glsl"))
  179. {
  180. return FALSE;
  181. }
  182. }
  183. else
  184. {
  185. if (!shader->attachObject("lighting/lightF.glsl"))
  186. {
  187. return FALSE;
  188. }
  189. }
  190. }
  191. // NOTE order of shader object attaching is VERY IMPORTANT!!!
  192. else if (features->isFullbright)
  193. {
  194. if (features->hasWaterFog)
  195. {
  196. if (!shader->attachObject("lighting/lightFullbrightWaterF.glsl"))
  197. {
  198. return FALSE;
  199. }
  200. }
  201. else if (features->isShiny)
  202. {
  203. if (!shader->attachObject("lighting/lightFullbrightShinyF.glsl"))
  204. {
  205. return FALSE;
  206. }
  207. }
  208. else
  209. {
  210. if (!shader->attachObject("lighting/lightFullbrightF.glsl"))
  211. {
  212. return FALSE;
  213. }
  214. }
  215. }
  216. // NOTE order of shader object attaching is VERY IMPORTANT!!!
  217. else if (features->isShiny)
  218. {
  219. if (features->hasWaterFog)
  220. {
  221. if (!shader->attachObject("lighting/lightShinyWaterF.glsl"))
  222. {
  223. return FALSE;
  224. }
  225. }
  226. else 
  227. {
  228. if (!shader->attachObject("lighting/lightShinyF.glsl"))
  229. {
  230. return FALSE;
  231. }
  232. }
  233. }
  234. return TRUE;
  235. }
  236. //============================================================================
  237. // Load Shader
  238. static std::string get_object_log(GLhandleARB ret)
  239. {
  240. std::string res;
  241. //get log length 
  242. GLint length;
  243. glGetObjectParameterivARB(ret, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length);
  244. if (length > 0)
  245. {
  246. //the log could be any size, so allocate appropriately
  247. GLcharARB* log = new GLcharARB[length];
  248. glGetInfoLogARB(ret, length, &length, log);
  249. res = std::string((char *)log);
  250. delete[] log;
  251. }
  252. return res;
  253. }
  254. void LLShaderMgr::dumpObjectLog(GLhandleARB ret, BOOL warns) 
  255. {
  256. std::string log = get_object_log(ret);
  257. if ( log.length() > 0 )
  258. {
  259. if (warns)
  260. {
  261. LL_WARNS("ShaderLoading") << log << LL_ENDL;
  262. }
  263. else
  264. {
  265. LL_DEBUGS("ShaderLoading") << log << LL_ENDL;
  266. }
  267. }
  268. }
  269. GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type)
  270. {
  271. GLenum error;
  272. error = glGetError();
  273. if (error != GL_NO_ERROR)
  274. {
  275. LL_WARNS("ShaderLoading") << "GL ERROR entering loadShaderFile(): " << error << LL_ENDL;
  276. }
  277. LL_DEBUGS("ShaderLoading") << "Loading shader file: " << filename << " class " << shader_level << LL_ENDL;
  278. if (filename.empty()) 
  279. {
  280. return 0;
  281. }
  282. //read in from file
  283. LLFILE* file = NULL;
  284. S32 try_gpu_class = shader_level;
  285. S32 gpu_class;
  286. //find the most relevant file
  287. for (gpu_class = try_gpu_class; gpu_class > 0; gpu_class--)
  288. { //search from the current gpu class down to class 1 to find the most relevant shader
  289. std::stringstream fname;
  290. fname << getShaderDirPrefix();
  291. fname << gpu_class << "/" << filename;
  292.   LL_DEBUGS("ShaderLoading") << "Looking in " << fname.str() << LL_ENDL;
  293. file = LLFile::fopen(fname.str(), "r"); /* Flawfinder: ignore */
  294. if (file)
  295. {
  296. LL_INFOS("ShaderLoading") << "Loading file: shaders/class" << gpu_class << "/" << filename << " (Want class " << gpu_class << ")" << LL_ENDL;
  297. break; // done
  298. }
  299. }
  300. if (file == NULL)
  301. {
  302. LL_WARNS("ShaderLoading") << "GLSL Shader file not found: " << filename << LL_ENDL;
  303. return 0;
  304. }
  305. //we can't have any lines longer than 1024 characters 
  306. //or any shaders longer than 1024 lines... deal - DaveP
  307. GLcharARB buff[1024];
  308. GLcharARB* text[1024];
  309. GLuint count = 0;
  310. //copy file into memory
  311. while( fgets((char *)buff, 1024, file) != NULL && count < LL_ARRAY_SIZE(buff) ) 
  312. {
  313. text[count++] = (GLcharARB *)strdup((char *)buff); 
  314. }
  315. fclose(file);
  316. //create shader object
  317. GLhandleARB ret = glCreateShaderObjectARB(type);
  318. error = glGetError();
  319. if (error != GL_NO_ERROR)
  320. {
  321. LL_WARNS("ShaderLoading") << "GL ERROR in glCreateShaderObjectARB: " << error << LL_ENDL;
  322. }
  323. else
  324. {
  325. //load source
  326. glShaderSourceARB(ret, count, (const GLcharARB**) text, NULL);
  327. error = glGetError();
  328. if (error != GL_NO_ERROR)
  329. {
  330. LL_WARNS("ShaderLoading") << "GL ERROR in glShaderSourceARB: " << error << LL_ENDL;
  331. }
  332. else
  333. {
  334. //compile source
  335. glCompileShaderARB(ret);
  336. error = glGetError();
  337. if (error != GL_NO_ERROR)
  338. {
  339. LL_WARNS("ShaderLoading") << "GL ERROR in glCompileShaderARB: " << error << LL_ENDL;
  340. }
  341. }
  342. }
  343. //free memory
  344. for (GLuint i = 0; i < count; i++)
  345. {
  346. free(text[i]);
  347. }
  348. if (error == GL_NO_ERROR)
  349. {
  350. //check for errors
  351. GLint success = GL_TRUE;
  352. glGetObjectParameterivARB(ret, GL_OBJECT_COMPILE_STATUS_ARB, &success);
  353. error = glGetError();
  354. if (error != GL_NO_ERROR || success == GL_FALSE) 
  355. {
  356. //an error occured, print log
  357. LL_WARNS("ShaderLoading") << "GLSL Compilation Error: (" << error << ") in " << filename << LL_ENDL;
  358. dumpObjectLog(ret);
  359. ret = 0;
  360. }
  361. }
  362. else
  363. {
  364. ret = 0;
  365. }
  366. stop_glerror();
  367. //successfully loaded, save results
  368. if (ret)
  369. {
  370. // Add shader file to map
  371. mShaderObjects[filename] = ret;
  372. shader_level = try_gpu_class;
  373. }
  374. else
  375. {
  376. if (shader_level > 1)
  377. {
  378. shader_level--;
  379. return loadShaderFile(filename,shader_level,type);
  380. }
  381. LL_WARNS("ShaderLoading") << "Failed to load " << filename << LL_ENDL;
  382. }
  383. return ret;
  384. }
  385. BOOL LLShaderMgr::linkProgramObject(GLhandleARB obj, BOOL suppress_errors) 
  386. {
  387. //check for errors
  388. glLinkProgramARB(obj);
  389. GLint success = GL_TRUE;
  390. glGetObjectParameterivARB(obj, GL_OBJECT_LINK_STATUS_ARB, &success);
  391. if (!suppress_errors && success == GL_FALSE) 
  392. {
  393. //an error occured, print log
  394. LL_WARNS("ShaderLoading") << "GLSL Linker Error:" << LL_ENDL;
  395. }
  396. // NOTE: Removing LL_DARWIN block as it doesn't seem to actually give the correct answer, 
  397. // but want it for reference once I move it.
  398. #if 0
  399. // Force an evaluation of the gl state so the driver can tell if the shader will run in hardware or software
  400. // per Apple's suggestion   
  401. glBegin(gGL.mMode);
  402. glEnd();
  403. // Query whether the shader can or cannot run in hardware
  404. // http://developer.apple.com/qa/qa2007/qa1502.html
  405. long vertexGPUProcessing;
  406. CGLContextObj ctx = CGLGetCurrentContext();
  407. CGLGetParameter (ctx, kCGLCPGPUVertexProcessing, &vertexGPUProcessing);
  408. long fragmentGPUProcessing;
  409. CGLGetParameter (ctx, kCGLCPGPUFragmentProcessing, &fragmentGPUProcessing);
  410. if (!fragmentGPUProcessing || !vertexGPUProcessing)
  411. {
  412. LL_WARNS("ShaderLoading") << "GLSL Linker: Running in Software:" << LL_ENDL;
  413. success = GL_FALSE;
  414. suppress_errors = FALSE;
  415. }
  416. #else
  417. std::string log = get_object_log(obj);
  418. LLStringUtil::toLower(log);
  419. if (log.find("software") != std::string::npos)
  420. {
  421. LL_WARNS("ShaderLoading") << "GLSL Linker: Running in Software:" << LL_ENDL;
  422. success = GL_FALSE;
  423. suppress_errors = FALSE;
  424. }
  425. #endif
  426. if (!suppress_errors)
  427. {
  428.         dumpObjectLog(obj, !success);
  429. }
  430. return success;
  431. }
  432. BOOL LLShaderMgr::validateProgramObject(GLhandleARB obj)
  433. {
  434. //check program validity against current GL
  435. glValidateProgramARB(obj);
  436. GLint success = GL_TRUE;
  437. glGetObjectParameterivARB(obj, GL_OBJECT_VALIDATE_STATUS_ARB, &success);
  438. if (success == GL_FALSE)
  439. {
  440. LL_WARNS("ShaderLoading") << "GLSL program not valid: " << LL_ENDL;
  441. dumpObjectLog(obj);
  442. }
  443. else
  444. {
  445. dumpObjectLog(obj, FALSE);
  446. }
  447. return success;
  448. }