webgpuTimestampQuery.js 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. import * as WebGPUConstants from "./webgpuConstants.js";
  2. import { PerfCounter } from "../../Misc/perfCounter.js";
  3. import { WebGPUQuerySet } from "./webgpuQuerySet.js";
  4. import { Logger } from "../../Misc/logger.js";
  5. /** @internal */
  6. export class WebGPUTimestampQuery {
  7. get gpuFrameTimeCounter() {
  8. return this._gpuFrameTimeCounter;
  9. }
  10. constructor(engine, device, bufferManager) {
  11. this._enabled = false;
  12. this._gpuFrameTimeCounter = new PerfCounter();
  13. this._measureDurationState = 0;
  14. this._engine = engine;
  15. this._device = device;
  16. this._bufferManager = bufferManager;
  17. }
  18. get enable() {
  19. return this._enabled;
  20. }
  21. set enable(value) {
  22. if (this._enabled === value) {
  23. return;
  24. }
  25. this._enabled = value;
  26. this._measureDurationState = 0;
  27. if (value) {
  28. try {
  29. this._measureDuration = new WebGPUDurationMeasure(this._engine, this._device, this._bufferManager, 2000, "QuerySet_TimestampQuery");
  30. }
  31. catch (e) {
  32. this._enabled = false;
  33. Logger.Error("Could not create a WebGPUDurationMeasure!\nError: " + e.message + "\nMake sure timestamp query is supported and enabled in your browser.");
  34. return;
  35. }
  36. }
  37. else {
  38. this._measureDuration.dispose();
  39. }
  40. }
  41. startFrame(commandEncoder) {
  42. if (this._enabled && this._measureDurationState === 0) {
  43. this._measureDuration.start(commandEncoder);
  44. this._measureDurationState = 1;
  45. }
  46. }
  47. endFrame(commandEncoder) {
  48. if (this._measureDurationState === 1) {
  49. this._measureDurationState = 2;
  50. this._measureDuration.stop(commandEncoder).then((duration) => {
  51. if (duration !== null && duration >= 0) {
  52. this._gpuFrameTimeCounter.fetchNewFrame();
  53. this._gpuFrameTimeCounter.addCount(duration, true);
  54. }
  55. this._measureDurationState = 0;
  56. });
  57. }
  58. }
  59. startPass(descriptor, index) {
  60. if (this._enabled) {
  61. this._measureDuration.startPass(descriptor, index);
  62. }
  63. else {
  64. descriptor.timestampWrites = undefined;
  65. }
  66. }
  67. endPass(index, gpuPerfCounter) {
  68. if (!this._enabled || !gpuPerfCounter) {
  69. return;
  70. }
  71. const currentFrameId = this._engine.frameId;
  72. this._measureDuration.stopPass(index).then((duration_) => {
  73. gpuPerfCounter._addDuration(currentFrameId, duration_ !== null && duration_ > 0 ? duration_ : 0);
  74. });
  75. }
  76. dispose() {
  77. this._measureDuration?.dispose();
  78. }
  79. }
  80. /** @internal */
  81. export class WebGPUDurationMeasure {
  82. constructor(engine, device, bufferManager, count = 2, querySetLabel) {
  83. this._count = count;
  84. this._querySet = new WebGPUQuerySet(engine, count, WebGPUConstants.QueryType.Timestamp, device, bufferManager, true, querySetLabel);
  85. }
  86. start(encoder) {
  87. encoder.writeTimestamp?.(this._querySet.querySet, 0);
  88. }
  89. async stop(encoder) {
  90. encoder.writeTimestamp?.(this._querySet.querySet, 1);
  91. return encoder.writeTimestamp ? this._querySet.readTwoValuesAndSubtract(0) : 0;
  92. }
  93. startPass(descriptor, index) {
  94. if (index + 3 > this._count) {
  95. throw new Error("WebGPUDurationMeasure: index out of range (" + index + ")");
  96. }
  97. descriptor.timestampWrites = {
  98. querySet: this._querySet.querySet,
  99. beginningOfPassWriteIndex: index + 2,
  100. endOfPassWriteIndex: index + 3,
  101. };
  102. }
  103. async stopPass(index) {
  104. return this._querySet.readTwoValuesAndSubtract(index + 2);
  105. }
  106. dispose() {
  107. this._querySet.dispose();
  108. }
  109. }
  110. //# sourceMappingURL=webgpuTimestampQuery.js.map