Bindings.js 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  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. this.backend.createBindings( bindings );
  23. }
  24. return data.bindings;
  25. }
  26. getForCompute( computeNode ) {
  27. const data = this.get( computeNode );
  28. if ( data.bindings === undefined ) {
  29. const nodeBuilderState = this.nodes.getForCompute( computeNode );
  30. const bindings = nodeBuilderState.bindings;
  31. data.bindings = bindings;
  32. this._init( bindings );
  33. this.backend.createBindings( bindings );
  34. }
  35. return data.bindings;
  36. }
  37. updateForCompute( computeNode ) {
  38. this._update( computeNode, this.getForCompute( computeNode ) );
  39. }
  40. updateForRender( renderObject ) {
  41. this._update( renderObject, this.getForRender( renderObject ) );
  42. }
  43. _init( bindings ) {
  44. for ( const binding of bindings ) {
  45. if ( binding.isSampledTexture ) {
  46. this.textures.updateTexture( binding.texture );
  47. } else if ( binding.isStorageBuffer ) {
  48. const attribute = binding.attribute;
  49. this.attributes.update( attribute, AttributeType.STORAGE );
  50. }
  51. }
  52. }
  53. _update( object, bindings ) {
  54. const { backend } = this;
  55. const updateMap = this.updateMap;
  56. const frame = this.info.render.frame;
  57. let needsBindingsUpdate = false;
  58. // iterate over all bindings and check if buffer updates or a new binding group is required
  59. for ( const binding of bindings ) {
  60. const isUpdated = updateMap.get( binding ) === frame;
  61. if ( isUpdated ) continue;
  62. if ( binding.isUniformBuffer ) {
  63. const needsUpdate = binding.update();
  64. if ( needsUpdate ) {
  65. backend.updateBinding( binding );
  66. }
  67. } else if ( binding.isSampledTexture ) {
  68. if ( binding.needsBindingsUpdate ) needsBindingsUpdate = true;
  69. const needsUpdate = binding.update();
  70. if ( needsUpdate ) {
  71. this.textures.updateTexture( binding.texture );
  72. }
  73. }
  74. updateMap.set( binding, frame );
  75. }
  76. if ( needsBindingsUpdate === true ) {
  77. const pipeline = this.pipelines.getForRender( object );
  78. this.backend.updateBindings( bindings, pipeline );
  79. }
  80. }
  81. dispose() {
  82. super.dispose();
  83. this.updateMap = new WeakMap();
  84. }
  85. }
  86. export default Bindings;