ShaderCache.js 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. /*global define*/
  2. define([
  3. '../Core/defined',
  4. '../Core/destroyObject',
  5. './ShaderProgram',
  6. './ShaderSource'
  7. ], function(
  8. defined,
  9. destroyObject,
  10. ShaderProgram,
  11. ShaderSource) {
  12. "use strict";
  13. /**
  14. * @private
  15. */
  16. var ShaderCache = function(context) {
  17. this._context = context;
  18. this._shaders = {};
  19. this._shadersToRelease = {};
  20. };
  21. /**
  22. * Returns a shader program from the cache, or creates and caches a new shader program,
  23. * given the GLSL vertex and fragment shader source and attribute locations.
  24. * <p>
  25. * The difference between this and {@link ShaderCache#getShaderProgram}, is this is used to
  26. * replace an existing reference to a shader program, which is passed as the first argument.
  27. * </p>
  28. *
  29. * @param {ShaderProgram} shaderProgram The shader program that is being reassigned. This can be <code>undefined</code>.
  30. * @param {String|ShaderSource} vertexShaderSource The GLSL source for the vertex shader.
  31. * @param {String|ShaderSource} fragmentShaderSource The GLSL source for the fragment shader.
  32. * @param {Object} attributeLocations Indices for the attribute inputs to the vertex shader.
  33. * @returns {ShaderProgram} The cached or newly created shader program.
  34. *
  35. * @see ShaderCache#getShaderProgram
  36. *
  37. * @example
  38. * this._shaderProgram = context.shaderCache.replaceShaderProgram(this._shaderProgram, vs, fs, attributeLocations);
  39. */
  40. ShaderCache.prototype.replaceShaderProgram = function(shaderProgram, vertexShaderSource, fragmentShaderSource, attributeLocations) {
  41. if (defined(shaderProgram)) {
  42. shaderProgram.destroy();
  43. }
  44. return this.getShaderProgram(vertexShaderSource, fragmentShaderSource, attributeLocations);
  45. };
  46. /**
  47. * Returns a shader program from the cache, or creates and caches a new shader program,
  48. * given the GLSL vertex and fragment shader source and attribute locations.
  49. *
  50. * @param {String|ShaderSource} vertexShaderSource The GLSL source for the vertex shader.
  51. * @param {String|ShaderSource} fragmentShaderSource The GLSL source for the fragment shader.
  52. * @param {Object} attributeLocations Indices for the attribute inputs to the vertex shader.
  53. *
  54. * @returns {ShaderProgram} The cached or newly created shader program.
  55. */
  56. ShaderCache.prototype.getShaderProgram = function(vertexShaderSource, fragmentShaderSource, attributeLocations) {
  57. // convert shaders which are provided as strings into ShaderSource objects
  58. // because ShaderSource handles all the automatic including of built-in functions, etc.
  59. if (typeof vertexShaderSource === 'string') {
  60. vertexShaderSource = new ShaderSource({
  61. sources : [vertexShaderSource]
  62. });
  63. }
  64. if (typeof fragmentShaderSource === 'string') {
  65. fragmentShaderSource = new ShaderSource({
  66. sources : [fragmentShaderSource]
  67. });
  68. }
  69. var vertexShaderText = vertexShaderSource.createCombinedVertexShader();
  70. var fragmentShaderText = fragmentShaderSource.createCombinedFragmentShader();
  71. var keyword = vertexShaderText + fragmentShaderText + JSON.stringify(attributeLocations);
  72. var cachedShader;
  73. if (this._shaders[keyword]) {
  74. cachedShader = this._shaders[keyword];
  75. // No longer want to release this if it was previously released.
  76. delete this._shadersToRelease[keyword];
  77. } else {
  78. var context = this._context;
  79. var shaderProgram = new ShaderProgram({
  80. gl : context._gl,
  81. logShaderCompilation : context.logShaderCompilation,
  82. debugShaders : context.debugShaders,
  83. vertexShaderSource : vertexShaderSource,
  84. vertexShaderText : vertexShaderText,
  85. fragmentShaderSource : fragmentShaderSource,
  86. fragmentShaderText : fragmentShaderText,
  87. attributeLocations : attributeLocations
  88. });
  89. cachedShader = {
  90. cache : this,
  91. shaderProgram : shaderProgram,
  92. keyword : keyword,
  93. count : 0
  94. };
  95. // A shader can't be in more than one cache.
  96. shaderProgram._cachedShader = cachedShader;
  97. this._shaders[keyword] = cachedShader;
  98. }
  99. ++cachedShader.count;
  100. return cachedShader.shaderProgram;
  101. };
  102. ShaderCache.prototype.destroyReleasedShaderPrograms = function() {
  103. var shadersToRelease = this._shadersToRelease;
  104. for ( var keyword in shadersToRelease) {
  105. if (shadersToRelease.hasOwnProperty(keyword)) {
  106. var cachedShader = shadersToRelease[keyword];
  107. delete this._shaders[cachedShader.keyword];
  108. cachedShader.shaderProgram.finalDestroy();
  109. }
  110. }
  111. this._shadersToRelease = {};
  112. };
  113. ShaderCache.prototype.releaseShaderProgram = function(shaderProgram) {
  114. if (shaderProgram) {
  115. var cachedShader = shaderProgram._cachedShader;
  116. if (cachedShader && (--cachedShader.count === 0)) {
  117. this._shadersToRelease[cachedShader.keyword] = cachedShader;
  118. }
  119. }
  120. };
  121. ShaderCache.prototype.isDestroyed = function() {
  122. return false;
  123. };
  124. ShaderCache.prototype.destroy = function() {
  125. var shaders = this._shaders;
  126. for ( var keyword in shaders) {
  127. if (shaders.hasOwnProperty(keyword)) {
  128. shaders[keyword].shaderProgram.finalDestroy();
  129. }
  130. }
  131. return destroyObject(this);
  132. };
  133. return ShaderCache;
  134. });