Bindings.js 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. import DataMap from './DataMap.js';
  2. import { AttributeType } from './Constants.js';
  3. class Bindings extends DataMap {
  4. constructor( backend, nodes, textures, attributes, pipelines, info ) {
  5. super();
  6. this.backend = backend;
  7. this.textures = textures;
  8. this.pipelines = pipelines;
  9. this.attributes = attributes;
  10. this.nodes = nodes;
  11. this.info = info;
  12. this.pipelines.bindings = this; // assign bindings to pipelines
  13. this.updateMap = new WeakMap();
  14. }
  15. getForRender( renderObject ) {
  16. const bindings = renderObject.getBindings();
  17. const data = this.get( renderObject );
  18. if ( data.bindings !== bindings ) {
  19. // each object defines an array of bindings (ubos, textures, samplers etc.)
  20. data.bindings = bindings;
  21. this._init( bindings );
  22. const pipeline = this.pipelines.getForRender( renderObject );
  23. this.backend.createBindings( bindings, pipeline );
  24. }
  25. return data.bindings;
  26. }
  27. getForCompute( computeNode ) {
  28. const data = this.get( computeNode );
  29. if ( data.bindings === undefined ) {
  30. const nodeBuilder = this.nodes.getForCompute( computeNode );
  31. const bindings = nodeBuilder.getBindings();
  32. data.bindings = bindings;
  33. this._init( bindings );
  34. const pipeline = this.pipelines.getForCompute( computeNode );
  35. this.backend.createBindings( bindings, pipeline );
  36. }
  37. return data.bindings;
  38. }
  39. updateForCompute( computeNode ) {
  40. this._update( computeNode, this.getForCompute( computeNode ) );
  41. }
  42. updateForRender( renderObject ) {
  43. this._update( renderObject, this.getForRender( renderObject ) );
  44. }
  45. _init( bindings ) {
  46. for ( const binding of bindings ) {
  47. if ( binding.isSampler || binding.isSampledTexture ) {
  48. this.textures.updateTexture( binding.texture );
  49. } else if ( binding.isStorageBuffer ) {
  50. const attribute = binding.attribute;
  51. this.attributes.update( attribute, AttributeType.STORAGE );
  52. }
  53. }
  54. }
  55. _update( object, bindings ) {
  56. const { backend } = this;
  57. const updateMap = this.updateMap;
  58. const frame = this.info.render.frame;
  59. let needsBindingsUpdate = false;
  60. // iterate over all bindings and check if buffer updates or a new binding group is required
  61. for ( const binding of bindings ) {
  62. const isShared = binding.isShared;
  63. const isUpdated = updateMap.get( binding ) === frame;
  64. if ( isShared && isUpdated ) continue;
  65. if ( binding.isUniformBuffer ) {
  66. const needsUpdate = binding.update();
  67. if ( needsUpdate ) {
  68. backend.updateBinding( binding );
  69. }
  70. } else if ( binding.isSampledTexture ) {
  71. if ( binding.needsBindingsUpdate ) needsBindingsUpdate = true;
  72. const needsUpdate = binding.update();
  73. if ( needsUpdate ) {
  74. this.textures.updateTexture( binding.texture );
  75. }
  76. }
  77. updateMap.set( binding, frame );
  78. }
  79. if ( needsBindingsUpdate === true ) {
  80. const pipeline = this.pipelines.getForRender( object );
  81. this.backend.updateBindings( bindings, pipeline );
  82. }
  83. }
  84. dispose() {
  85. super.dispose();
  86. this.updateMap = new WeakMap();
  87. }
  88. }
  89. export default Bindings;