123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194 |
- /* eslint-disable babylonjs/available */
- /* eslint-disable jsdoc/require-jsdoc */
- import { Logger } from "../../Misc/logger.js";
- class WebGPUBindGroupCacheNode {
- constructor() {
- this.values = {};
- }
- }
- /** @internal */
- export class WebGPUCacheBindGroups {
- static get Statistics() {
- return {
- totalCreated: WebGPUCacheBindGroups.NumBindGroupsCreatedTotal,
- lastFrameCreated: WebGPUCacheBindGroups.NumBindGroupsCreatedLastFrame,
- lookupLastFrame: WebGPUCacheBindGroups.NumBindGroupsLookupLastFrame,
- noLookupLastFrame: WebGPUCacheBindGroups.NumBindGroupsNoLookupLastFrame,
- };
- }
- static ResetCache() {
- WebGPUCacheBindGroups._Cache = new WebGPUBindGroupCacheNode();
- WebGPUCacheBindGroups.NumBindGroupsCreatedTotal = 0;
- WebGPUCacheBindGroups.NumBindGroupsCreatedLastFrame = 0;
- WebGPUCacheBindGroups.NumBindGroupsLookupLastFrame = 0;
- WebGPUCacheBindGroups.NumBindGroupsNoLookupLastFrame = 0;
- WebGPUCacheBindGroups._NumBindGroupsCreatedCurrentFrame = 0;
- WebGPUCacheBindGroups._NumBindGroupsLookupCurrentFrame = 0;
- WebGPUCacheBindGroups._NumBindGroupsNoLookupCurrentFrame = 0;
- }
- constructor(device, cacheSampler, engine) {
- this.disabled = false;
- this._device = device;
- this._cacheSampler = cacheSampler;
- this._engine = engine;
- }
- endFrame() {
- WebGPUCacheBindGroups.NumBindGroupsCreatedLastFrame = WebGPUCacheBindGroups._NumBindGroupsCreatedCurrentFrame;
- WebGPUCacheBindGroups.NumBindGroupsLookupLastFrame = WebGPUCacheBindGroups._NumBindGroupsLookupCurrentFrame;
- WebGPUCacheBindGroups.NumBindGroupsNoLookupLastFrame = WebGPUCacheBindGroups._NumBindGroupsNoLookupCurrentFrame;
- WebGPUCacheBindGroups._NumBindGroupsCreatedCurrentFrame = 0;
- WebGPUCacheBindGroups._NumBindGroupsLookupCurrentFrame = 0;
- WebGPUCacheBindGroups._NumBindGroupsNoLookupCurrentFrame = 0;
- }
- /**
- * Cache is currently based on the uniform/storage buffers, samplers and textures used by the binding groups.
- * Note that all uniform buffers have an offset of 0 in Babylon and we don't have a use case where we would have the same buffer used with different capacity values:
- * that means we don't need to factor in the offset/size of the buffer in the cache, only the id
- * @param webgpuPipelineContext
- * @param drawContext
- * @param materialContext
- * @returns a bind group array
- */
- getBindGroups(webgpuPipelineContext, drawContext, materialContext) {
- let bindGroups = undefined;
- let node = WebGPUCacheBindGroups._Cache;
- const cacheIsDisabled = this.disabled || materialContext.forceBindGroupCreation;
- if (!cacheIsDisabled) {
- if (!drawContext.isDirty(materialContext.updateId) && !materialContext.isDirty) {
- WebGPUCacheBindGroups._NumBindGroupsNoLookupCurrentFrame++;
- return drawContext.bindGroups;
- }
- for (const bufferName of webgpuPipelineContext.shaderProcessingContext.bufferNames) {
- const uboId = drawContext.buffers[bufferName]?.uniqueId ?? 0;
- let nextNode = node.values[uboId];
- if (!nextNode) {
- nextNode = new WebGPUBindGroupCacheNode();
- node.values[uboId] = nextNode;
- }
- node = nextNode;
- }
- for (const samplerName of webgpuPipelineContext.shaderProcessingContext.samplerNames) {
- const samplerHashCode = materialContext.samplers[samplerName]?.hashCode ?? 0;
- let nextNode = node.values[samplerHashCode];
- if (!nextNode) {
- nextNode = new WebGPUBindGroupCacheNode();
- node.values[samplerHashCode] = nextNode;
- }
- node = nextNode;
- }
- for (const textureName of webgpuPipelineContext.shaderProcessingContext.textureNames) {
- const textureId = materialContext.textures[textureName]?.texture?.uniqueId ?? 0;
- let nextNode = node.values[textureId];
- if (!nextNode) {
- nextNode = new WebGPUBindGroupCacheNode();
- node.values[textureId] = nextNode;
- }
- node = nextNode;
- }
- bindGroups = node.bindGroups;
- }
- drawContext.resetIsDirty(materialContext.updateId);
- materialContext.isDirty = false;
- if (bindGroups) {
- drawContext.bindGroups = bindGroups;
- WebGPUCacheBindGroups._NumBindGroupsLookupCurrentFrame++;
- return bindGroups;
- }
- bindGroups = [];
- drawContext.bindGroups = bindGroups;
- if (!cacheIsDisabled) {
- node.bindGroups = bindGroups;
- }
- WebGPUCacheBindGroups.NumBindGroupsCreatedTotal++;
- WebGPUCacheBindGroups._NumBindGroupsCreatedCurrentFrame++;
- const bindGroupLayouts = webgpuPipelineContext.bindGroupLayouts[materialContext.textureState];
- for (let i = 0; i < webgpuPipelineContext.shaderProcessingContext.bindGroupLayoutEntries.length; i++) {
- const setDefinition = webgpuPipelineContext.shaderProcessingContext.bindGroupLayoutEntries[i];
- const entries = webgpuPipelineContext.shaderProcessingContext.bindGroupEntries[i];
- for (let j = 0; j < setDefinition.length; j++) {
- const entry = webgpuPipelineContext.shaderProcessingContext.bindGroupLayoutEntries[i][j];
- const entryInfo = webgpuPipelineContext.shaderProcessingContext.bindGroupLayoutEntryInfo[i][entry.binding];
- const name = entryInfo.nameInArrayOfTexture ?? entryInfo.name;
- if (entry.sampler) {
- const bindingInfo = materialContext.samplers[name];
- if (bindingInfo) {
- const sampler = bindingInfo.sampler;
- if (!sampler) {
- if (this._engine.dbgSanityChecks) {
- Logger.Error(`Trying to bind a null sampler! entry=${JSON.stringify(entry)}, name=${name}, bindingInfo=${JSON.stringify(bindingInfo, (key, value) => (key === "texture" ? "<no dump>" : value))}, materialContext.uniqueId=${materialContext.uniqueId}`, 50);
- }
- continue;
- }
- entries[j].resource = this._cacheSampler.getSampler(sampler, false, bindingInfo.hashCode, sampler.label);
- }
- else {
- Logger.Error(`Sampler "${name}" could not be bound. entry=${JSON.stringify(entry)}, materialContext=${JSON.stringify(materialContext, (key, value) => key === "texture" || key === "sampler" ? "<no dump>" : value)}`, 50);
- }
- }
- else if (entry.texture || entry.storageTexture) {
- const bindingInfo = materialContext.textures[name];
- if (bindingInfo) {
- if (this._engine.dbgSanityChecks && bindingInfo.texture === null) {
- Logger.Error(`Trying to bind a null texture! entry=${JSON.stringify(entry)}, bindingInfo=${JSON.stringify(bindingInfo, (key, value) => key === "texture" ? "<no dump>" : value)}, materialContext.uniqueId=${materialContext.uniqueId}`, 50);
- continue;
- }
- const hardwareTexture = bindingInfo.texture._hardwareTexture;
- if (this._engine.dbgSanityChecks &&
- (!hardwareTexture || (entry.texture && !hardwareTexture.view) || (entry.storageTexture && !hardwareTexture.viewForWriting))) {
- Logger.Error(`Trying to bind a null gpu texture or view! entry=${JSON.stringify(entry)}, name=${name}, bindingInfo=${JSON.stringify(bindingInfo, (key, value) => (key === "texture" ? "<no dump>" : value))}, isReady=${bindingInfo.texture?.isReady}, materialContext.uniqueId=${materialContext.uniqueId}`, 50);
- continue;
- }
- entries[j].resource = entry.storageTexture ? hardwareTexture.viewForWriting : hardwareTexture.view;
- }
- else {
- Logger.Error(`Texture "${name}" could not be bound. entry=${JSON.stringify(entry)}, materialContext=${JSON.stringify(materialContext, (key, value) => key === "texture" || key === "sampler" ? "<no dump>" : value)}`, 50);
- }
- }
- else if (entry.externalTexture) {
- const bindingInfo = materialContext.textures[name];
- if (bindingInfo) {
- if (this._engine.dbgSanityChecks && bindingInfo.texture === null) {
- Logger.Error(`Trying to bind a null external texture! entry=${JSON.stringify(entry)}, name=${name}, bindingInfo=${JSON.stringify(bindingInfo, (key, value) => (key === "texture" ? "<no dump>" : value))}, materialContext.uniqueId=${materialContext.uniqueId}`, 50);
- continue;
- }
- const externalTexture = bindingInfo.texture.underlyingResource;
- if (this._engine.dbgSanityChecks && !externalTexture) {
- Logger.Error(`Trying to bind a null gpu external texture! entry=${JSON.stringify(entry)}, name=${name}, bindingInfo=${JSON.stringify(bindingInfo, (key, value) => (key === "texture" ? "<no dump>" : value))}, isReady=${bindingInfo.texture?.isReady}, materialContext.uniqueId=${materialContext.uniqueId}`, 50);
- continue;
- }
- entries[j].resource = this._device.importExternalTexture({ source: externalTexture });
- }
- else {
- Logger.Error(`Texture "${name}" could not be bound. entry=${JSON.stringify(entry)}, materialContext=${JSON.stringify(materialContext, (key, value) => key === "texture" || key === "sampler" ? "<no dump>" : value)}`, 50);
- }
- }
- else if (entry.buffer) {
- const dataBuffer = drawContext.buffers[name];
- if (dataBuffer) {
- const webgpuBuffer = dataBuffer.underlyingResource;
- entries[j].resource.buffer = webgpuBuffer;
- entries[j].resource.size = dataBuffer.capacity;
- }
- else {
- Logger.Error(`Can't find buffer "${name}". entry=${JSON.stringify(entry)}, buffers=${JSON.stringify(drawContext.buffers)}, drawContext.uniqueId=${drawContext.uniqueId}`, 50);
- }
- }
- }
- const groupLayout = bindGroupLayouts[i];
- bindGroups[i] = this._device.createBindGroup({
- layout: groupLayout,
- entries,
- });
- }
- return bindGroups;
- }
- }
- WebGPUCacheBindGroups.NumBindGroupsCreatedTotal = 0;
- WebGPUCacheBindGroups.NumBindGroupsCreatedLastFrame = 0;
- WebGPUCacheBindGroups.NumBindGroupsLookupLastFrame = 0;
- WebGPUCacheBindGroups.NumBindGroupsNoLookupLastFrame = 0;
- WebGPUCacheBindGroups._Cache = new WebGPUBindGroupCacheNode();
- WebGPUCacheBindGroups._NumBindGroupsCreatedCurrentFrame = 0;
- WebGPUCacheBindGroups._NumBindGroupsLookupCurrentFrame = 0;
- WebGPUCacheBindGroups._NumBindGroupsNoLookupCurrentFrame = 0;
- //# sourceMappingURL=webgpuCacheBindGroups.js.map
|