webgpuOcclusionQuery.js 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. import * as WebGPUConstants from "./webgpuConstants.js";
  2. import { WebGPUQuerySet } from "./webgpuQuerySet.js";
  3. /** @internal */
  4. export class WebGPUOcclusionQuery {
  5. get querySet() {
  6. return this._querySet.querySet;
  7. }
  8. get hasQueries() {
  9. return this._currentTotalIndices !== this._availableIndices.length;
  10. }
  11. canBeginQuery(index) {
  12. if (this._frameQuerySetIsDirty === this._engine.frameId || this._queryFrameId[index] === this._engine.frameId) {
  13. return false;
  14. }
  15. const canBegin = this._engine._getCurrentRenderPassWrapper().renderPassDescriptor.occlusionQuerySet !== undefined;
  16. if (canBegin) {
  17. this._queryFrameId[index] = this._engine.frameId;
  18. }
  19. return canBegin;
  20. }
  21. constructor(engine, device, bufferManager, startCount = 50, incrementCount = 100) {
  22. this._availableIndices = [];
  23. this._frameQuerySetIsDirty = -1;
  24. this._queryFrameId = [];
  25. this._engine = engine;
  26. this._device = device;
  27. this._bufferManager = bufferManager;
  28. this._frameLastBuffer = -1;
  29. this._currentTotalIndices = 0;
  30. this._countIncrement = incrementCount;
  31. this._allocateNewIndices(startCount);
  32. }
  33. createQuery() {
  34. if (this._availableIndices.length === 0) {
  35. this._allocateNewIndices();
  36. }
  37. const index = this._availableIndices[this._availableIndices.length - 1];
  38. this._availableIndices.length--;
  39. return index;
  40. }
  41. deleteQuery(index) {
  42. this._availableIndices[this._availableIndices.length] = index;
  43. }
  44. isQueryResultAvailable(index) {
  45. this._retrieveQueryBuffer();
  46. return !!this._lastBuffer && index < this._lastBuffer.length;
  47. }
  48. getQueryResult(index) {
  49. return Number(this._lastBuffer?.[index] ?? -1);
  50. }
  51. _retrieveQueryBuffer() {
  52. if (this._lastBuffer && this._frameLastBuffer === this._engine.frameId) {
  53. return;
  54. }
  55. if (this._frameLastBuffer !== this._engine.frameId) {
  56. this._frameLastBuffer = this._engine.frameId;
  57. this._querySet.readValues(0, this._currentTotalIndices).then((arrayBuffer) => {
  58. this._lastBuffer = arrayBuffer;
  59. });
  60. }
  61. }
  62. _allocateNewIndices(numIndices) {
  63. numIndices = numIndices ?? this._countIncrement;
  64. this._delayQuerySetDispose();
  65. for (let i = 0; i < numIndices; ++i) {
  66. this._availableIndices.push(this._currentTotalIndices + i);
  67. }
  68. this._currentTotalIndices += numIndices;
  69. this._querySet = new WebGPUQuerySet(this._engine, this._currentTotalIndices, WebGPUConstants.QueryType.Occlusion, this._device, this._bufferManager, false, "QuerySet_OcclusionQuery_count_" + this._currentTotalIndices);
  70. this._frameQuerySetIsDirty = this._engine.frameId;
  71. }
  72. _delayQuerySetDispose() {
  73. const querySet = this._querySet;
  74. if (querySet) {
  75. // Wait a bit before disposing of the queryset, in case some queries are still running for it
  76. setTimeout(() => querySet.dispose, 1000);
  77. }
  78. }
  79. dispose() {
  80. this._querySet?.dispose();
  81. this._availableIndices.length = 0;
  82. }
  83. }
  84. //# sourceMappingURL=webgpuOcclusionQuery.js.map