WebGPUBindingUtils.js 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. import {
  2. GPUTextureAspect, GPUTextureViewDimension
  3. } from './WebGPUConstants.js';
  4. class WebGPUBindingUtils {
  5. constructor( backend ) {
  6. this.backend = backend;
  7. }
  8. createBindings( bindings, pipeline ) {
  9. const backend = this.backend;
  10. const bindingsData = backend.get( bindings );
  11. // setup (static) binding layout and (dynamic) binding group
  12. const pipelineGPU = backend.get( pipeline ).pipeline;
  13. const bindLayoutGPU = pipelineGPU.getBindGroupLayout( 0 );
  14. const bindGroupGPU = this.createBindGroup( bindings, bindLayoutGPU );
  15. bindingsData.layout = bindLayoutGPU;
  16. bindingsData.group = bindGroupGPU;
  17. bindingsData.bindings = bindings;
  18. }
  19. updateBinding( binding ) {
  20. const backend = this.backend;
  21. const device = backend.device;
  22. const buffer = binding.buffer;
  23. const bufferGPU = backend.get( binding ).buffer;
  24. device.queue.writeBuffer( bufferGPU, 0, buffer, 0 );
  25. }
  26. createBindGroup( bindings, layoutGPU ) {
  27. const backend = this.backend;
  28. const device = backend.device;
  29. let bindingPoint = 0;
  30. const entriesGPU = [];
  31. for ( const binding of bindings ) {
  32. if ( binding.isUniformBuffer ) {
  33. const bindingData = backend.get( binding );
  34. if ( bindingData.buffer === undefined ) {
  35. const byteLength = binding.byteLength;
  36. const usage = GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST;
  37. const bufferGPU = device.createBuffer( {
  38. label: 'bindingBuffer',
  39. size: byteLength,
  40. usage: usage
  41. } );
  42. bindingData.buffer = bufferGPU;
  43. }
  44. entriesGPU.push( { binding: bindingPoint, resource: { buffer: bindingData.buffer } } );
  45. } else if ( binding.isStorageBuffer ) {
  46. const bindingData = backend.get( binding );
  47. if ( bindingData.buffer === undefined ) {
  48. const attribute = binding.attribute;
  49. //const usage = GPUBufferUsage.STORAGE | GPUBufferUsage.VERTEX | /*GPUBufferUsage.COPY_SRC |*/ GPUBufferUsage.COPY_DST;
  50. //backend.attributeUtils.createAttribute( attribute, usage ); // @TODO: Move it to universal renderer
  51. bindingData.buffer = backend.get( attribute ).buffer;
  52. }
  53. entriesGPU.push( { binding: bindingPoint, resource: { buffer: bindingData.buffer } } );
  54. } else if ( binding.isSampler ) {
  55. const textureGPU = backend.get( binding.texture );
  56. entriesGPU.push( { binding: bindingPoint, resource: textureGPU.sampler } );
  57. } else if ( binding.isSampledTexture ) {
  58. const textureData = backend.get( binding.texture );
  59. let dimensionViewGPU;
  60. if ( binding.isSampledCubeTexture ) {
  61. dimensionViewGPU = GPUTextureViewDimension.Cube;
  62. } else {
  63. dimensionViewGPU = GPUTextureViewDimension.TwoD;
  64. }
  65. let resourceGPU;
  66. if ( textureData.externalTexture !== undefined ) {
  67. resourceGPU = device.importExternalTexture( { source: textureData.externalTexture } );
  68. } else {
  69. const aspectGPU = GPUTextureAspect.All;
  70. resourceGPU = textureData.texture.createView( { aspect: aspectGPU, dimension: dimensionViewGPU } );
  71. }
  72. entriesGPU.push( { binding: bindingPoint, resource: resourceGPU } );
  73. }
  74. bindingPoint ++;
  75. }
  76. return device.createBindGroup( {
  77. layout: layoutGPU,
  78. entries: entriesGPU
  79. } );
  80. }
  81. }
  82. export default WebGPUBindingUtils;