webgpuQuerySet.js 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. import * as WebGPUConstants from "./webgpuConstants.js";
  2. /** @internal */
  3. export class WebGPUQuerySet {
  4. get querySet() {
  5. return this._querySet;
  6. }
  7. constructor(engine, count, type, device, bufferManager, canUseMultipleBuffers = true, label) {
  8. this._dstBuffers = [];
  9. this._engine = engine;
  10. this._device = device;
  11. this._bufferManager = bufferManager;
  12. this._count = count;
  13. this._canUseMultipleBuffers = canUseMultipleBuffers;
  14. this._querySet = device.createQuerySet({
  15. label: label ?? "QuerySet",
  16. type,
  17. count,
  18. });
  19. this._queryBuffer = bufferManager.createRawBuffer(8 * count, WebGPUConstants.BufferUsage.QueryResolve | WebGPUConstants.BufferUsage.CopySrc, undefined, "QueryBuffer");
  20. if (!canUseMultipleBuffers) {
  21. this._dstBuffers.push(this._bufferManager.createRawBuffer(8 * this._count, WebGPUConstants.BufferUsage.MapRead | WebGPUConstants.BufferUsage.CopyDst, undefined, "QueryBufferNoMultipleBuffers"));
  22. }
  23. }
  24. _getBuffer(firstQuery, queryCount) {
  25. if (!this._canUseMultipleBuffers && this._dstBuffers.length === 0) {
  26. return null;
  27. }
  28. const encoderResult = this._device.createCommandEncoder();
  29. let buffer;
  30. if (this._dstBuffers.length === 0) {
  31. buffer = this._bufferManager.createRawBuffer(8 * this._count, WebGPUConstants.BufferUsage.MapRead | WebGPUConstants.BufferUsage.CopyDst, undefined, "QueryBufferAdditionalBuffer");
  32. }
  33. else {
  34. buffer = this._dstBuffers[this._dstBuffers.length - 1];
  35. this._dstBuffers.length--;
  36. }
  37. encoderResult.resolveQuerySet(this._querySet, firstQuery, queryCount, this._queryBuffer, 0);
  38. encoderResult.copyBufferToBuffer(this._queryBuffer, 0, buffer, 0, 8 * queryCount);
  39. this._device.queue.submit([encoderResult.finish()]);
  40. return buffer;
  41. }
  42. async readValues(firstQuery = 0, queryCount = 1) {
  43. const buffer = this._getBuffer(firstQuery, queryCount);
  44. if (buffer === null) {
  45. return null;
  46. }
  47. const engineId = this._engine.uniqueId;
  48. return buffer.mapAsync(WebGPUConstants.MapMode.Read).then(() => {
  49. const arrayBuf = new BigUint64Array(buffer.getMappedRange()).slice();
  50. buffer.unmap();
  51. this._dstBuffers[this._dstBuffers.length] = buffer;
  52. return arrayBuf;
  53. }, (err) => {
  54. if (this._engine.isDisposed || this._engine.uniqueId !== engineId) {
  55. // Engine disposed or context loss/restoration
  56. return null;
  57. }
  58. throw err;
  59. });
  60. }
  61. async readValue(firstQuery = 0) {
  62. const buffer = this._getBuffer(firstQuery, 1);
  63. if (buffer === null) {
  64. return null;
  65. }
  66. const engineId = this._engine.uniqueId;
  67. return buffer.mapAsync(WebGPUConstants.MapMode.Read).then(() => {
  68. const arrayBuf = new BigUint64Array(buffer.getMappedRange());
  69. const value = Number(arrayBuf[0]);
  70. buffer.unmap();
  71. this._dstBuffers[this._dstBuffers.length] = buffer;
  72. return value;
  73. }, (err) => {
  74. if (this._engine.isDisposed || this._engine.uniqueId !== engineId) {
  75. // Engine disposed or context loss/restoration
  76. return 0;
  77. }
  78. throw err;
  79. });
  80. }
  81. async readTwoValuesAndSubtract(firstQuery = 0) {
  82. const buffer = this._getBuffer(firstQuery, 2);
  83. if (buffer === null) {
  84. return null;
  85. }
  86. const engineId = this._engine.uniqueId;
  87. return buffer.mapAsync(WebGPUConstants.MapMode.Read).then(() => {
  88. const arrayBuf = new BigUint64Array(buffer.getMappedRange());
  89. const value = Number(arrayBuf[1] - arrayBuf[0]);
  90. buffer.unmap();
  91. this._dstBuffers[this._dstBuffers.length] = buffer;
  92. return value;
  93. }, (err) => {
  94. if (this._engine.isDisposed || this._engine.uniqueId !== engineId) {
  95. // Engine disposed or context loss/restoration
  96. return 0;
  97. }
  98. throw err;
  99. });
  100. }
  101. dispose() {
  102. this._querySet.destroy();
  103. this._bufferManager.releaseBuffer(this._queryBuffer);
  104. for (let i = 0; i < this._dstBuffers.length; ++i) {
  105. this._bufferManager.releaseBuffer(this._dstBuffers[i]);
  106. }
  107. }
  108. }
  109. //# sourceMappingURL=webgpuQuerySet.js.map