2
0

WebGPUAttributes.js 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. class WebGPUAttributes {
  2. constructor( device ) {
  3. this.buffers = new WeakMap();
  4. this.device = device;
  5. }
  6. get( attribute ) {
  7. return this.buffers.get( attribute );
  8. }
  9. remove( attribute ) {
  10. const data = this.buffers.get( attribute );
  11. if ( data ) {
  12. data.buffer.destroy();
  13. this.buffers.delete( attribute );
  14. }
  15. }
  16. update( attribute, isIndex = false ) {
  17. let data = this.buffers.get( attribute );
  18. if ( data === undefined ) {
  19. const usage = ( isIndex === true ) ? GPUBufferUsage.INDEX : GPUBufferUsage.VERTEX;
  20. data = this._createBuffer( attribute, usage );
  21. this.buffers.set( attribute, data );
  22. } else if ( data.version < attribute.version ) {
  23. this._writeBuffer( data.buffer, attribute );
  24. data.version = attribute.version;
  25. }
  26. }
  27. _createBuffer( attribute, usage ) {
  28. const array = attribute.array;
  29. const size = array.byteLength + ( array.byteLength % 4 ); // ensure 4 byte alignment
  30. const buffer = this.device.createBuffer( {
  31. size: size,
  32. usage: usage | GPUBufferUsage.COPY_DST,
  33. mappedAtCreation: true,
  34. } );
  35. new array.constructor( buffer.getMappedRange() ).set( array );
  36. buffer.unmap();
  37. return {
  38. version: attribute.version,
  39. buffer: buffer
  40. };
  41. }
  42. _writeBuffer( buffer, attribute ) {
  43. const array = attribute.array;
  44. const updateRange = attribute.updateRange;
  45. if ( updateRange.count === - 1 ) {
  46. // Not using update ranges
  47. this.device.defaultQueue.writeBuffer(
  48. buffer,
  49. 0,
  50. array,
  51. 0
  52. );
  53. } else {
  54. this.device.defaultQueue.writeBuffer(
  55. buffer,
  56. 0,
  57. array,
  58. updateRange.offset * array.BYTES_PER_ELEMENT,
  59. updateRange.count * array.BYTES_PER_ELEMENT
  60. );
  61. updateRange.count = - 1; // reset range
  62. }
  63. }
  64. }
  65. export default WebGPUAttributes;