UNPKG

@babylonjs/core

Version:

Getting started? Play directly with the Babylon.js API using our [playground](https://playground.babylonjs.com/). It also contains a lot of samples to learn how to use it.

254 lines (253 loc) 11.4 kB
import { InternalTexture } from "../../../Materials/Textures/internalTexture.js"; import { Logger } from "../../../Misc/logger.js"; import { WebGPUEngine } from "../../webgpuEngine.js"; WebGPUEngine.prototype.unBindMultiColorAttachmentFramebuffer = function (rtWrapper, disableGenerateMipMaps = false, onBeforeUnbind) { if (onBeforeUnbind) { onBeforeUnbind(); } this._endCurrentRenderPass(); if (!disableGenerateMipMaps) { this.generateMipMapsMultiFramebuffer(rtWrapper); } this._currentRenderTarget = null; this._mrtAttachments = []; this._cacheRenderPipeline.setMRT([]); this._cacheRenderPipeline.setMRTAttachments(this._mrtAttachments); }; WebGPUEngine.prototype.createMultipleRenderTarget = function (size, options, initializeBuffers) { let generateMipMaps = false; let generateDepthBuffer = true; let generateStencilBuffer = false; let generateDepthTexture = false; let depthTextureFormat = 15; let textureCount = 1; let samples = 1; const defaultType = 0; const defaultSamplingMode = 3; const defaultUseSRGBBuffer = false; const defaultFormat = 5; const defaultTarget = 3553; let types = []; let samplingModes = []; let useSRGBBuffers = []; let formats = []; let targets = []; let faceIndex = []; let layerIndex = []; let layers = []; let labels = []; let creationFlags = []; let dontCreateTextures = false; const rtWrapper = this._createHardwareRenderTargetWrapper(true, false, size); if (options !== undefined) { generateMipMaps = options.generateMipMaps ?? false; generateDepthBuffer = options.generateDepthBuffer ?? true; generateStencilBuffer = options.generateStencilBuffer ?? false; generateDepthTexture = options.generateDepthTexture ?? false; textureCount = options.textureCount ?? 1; depthTextureFormat = options.depthTextureFormat ?? 15; types = options.types || types; samplingModes = options.samplingModes || samplingModes; useSRGBBuffers = options.useSRGBBuffers || useSRGBBuffers; formats = options.formats || formats; targets = options.targetTypes || targets; faceIndex = options.faceIndex || faceIndex; layerIndex = options.layerIndex || layerIndex; layers = options.layerCounts || layers; labels = options.labels || labels; creationFlags = options.creationFlags || creationFlags; samples = options.samples ?? samples; dontCreateTextures = options.dontCreateTextures ?? false; } const width = size.width ?? size; const height = size.height ?? size; const textures = []; const attachments = []; const defaultAttachments = []; rtWrapper.label = options?.label ?? "MultiRenderTargetWrapper"; rtWrapper._generateDepthBuffer = generateDepthBuffer; rtWrapper._generateStencilBuffer = generateStencilBuffer; rtWrapper._attachments = attachments; rtWrapper._defaultAttachments = defaultAttachments; let depthStencilTexture = null; if ((generateDepthBuffer || generateStencilBuffer || generateDepthTexture) && !dontCreateTextures) { if (!generateDepthTexture) { // The caller doesn't want a depth texture, so we are free to use the depth texture format we want. // So, we will align with what the WebGL engine does if (generateDepthBuffer && generateStencilBuffer) { depthTextureFormat = 13; } else if (generateDepthBuffer) { depthTextureFormat = 14; } else { depthTextureFormat = 19; } } depthStencilTexture = rtWrapper.createDepthStencilTexture(0, false, generateStencilBuffer, 1, depthTextureFormat, rtWrapper.label + "-DepthStencil"); } const mipmapsCreationOnly = options !== undefined && typeof options === "object" && options.createMipMaps && !generateMipMaps; for (let i = 0; i < textureCount; i++) { let samplingMode = samplingModes[i] || defaultSamplingMode; let type = types[i] || defaultType; const format = formats[i] || defaultFormat; const useSRGBBuffer = (useSRGBBuffers[i] || defaultUseSRGBBuffer) && this._caps.supportSRGBBuffers; const target = targets[i] || defaultTarget; const layerCount = layers[i] ?? 1; const creationFlag = creationFlags[i]; if (type === 1 && !this._caps.textureFloatLinearFiltering) { // if floating point linear (FLOAT) then force to NEAREST_SAMPLINGMODE samplingMode = 1; } else if (type === 2 && !this._caps.textureHalfFloatLinearFiltering) { // if floating point linear (HALF_FLOAT) then force to NEAREST_SAMPLINGMODE samplingMode = 1; } if (type === 1 && !this._caps.textureFloat) { type = 0; Logger.Warn("Float textures are not supported. Render target forced to TEXTURETYPE_UNSIGNED_BYTE type"); } attachments.push(i + 1); defaultAttachments.push(initializeBuffers ? i + 1 : i === 0 ? 1 : 0); if (target === -1 || dontCreateTextures) { continue; } const texture = new InternalTexture(this, 6 /* InternalTextureSource.MultiRenderTarget */); textures[i] = texture; switch (target) { case 34067: texture.isCube = true; break; case 32879: texture.is3D = true; texture.baseDepth = texture.depth = layerCount; break; case 35866: texture.is2DArray = true; texture.baseDepth = texture.depth = layerCount; break; } texture.baseWidth = width; texture.baseHeight = height; texture.width = width; texture.height = height; texture.isReady = true; texture.samples = 1; texture.generateMipMaps = generateMipMaps; texture.samplingMode = samplingMode; texture.type = type; texture._cachedWrapU = 0; texture._cachedWrapV = 0; texture._useSRGBBuffer = useSRGBBuffer; texture.format = format; texture.label = labels[i] ?? rtWrapper.label + "-Texture" + i; this._internalTexturesCache.push(texture); if (mipmapsCreationOnly) { // createGPUTextureForInternalTexture will only create a texture with mipmaps if generateMipMaps is true, as InternalTexture has no createMipMaps property, separate from generateMipMaps. texture.generateMipMaps = true; } this._textureHelper.createGPUTextureForInternalTexture(texture, undefined, undefined, undefined, creationFlag, true); if (mipmapsCreationOnly) { texture.generateMipMaps = false; } } if (depthStencilTexture) { depthStencilTexture.incrementReferences(); textures[textureCount] = depthStencilTexture; this._internalTexturesCache.push(depthStencilTexture); } rtWrapper.setTextures(textures); rtWrapper.setLayerAndFaceIndices(layerIndex, faceIndex); if (!dontCreateTextures) { this.updateMultipleRenderTargetTextureSampleCount(rtWrapper, samples); } else { rtWrapper._samples = samples; } return rtWrapper; }; WebGPUEngine.prototype.updateMultipleRenderTargetTextureSampleCount = function (rtWrapper, samples) { if (!rtWrapper || !rtWrapper.textures || rtWrapper.textures.length === 0 || rtWrapper.textures[0].samples === samples) { return samples; } const count = rtWrapper.textures.length; if (count === 0) { return 1; } samples = Math.min(samples, this.getCaps().maxMSAASamples); for (let i = 0; i < count; ++i) { const texture = rtWrapper.textures[i]; const gpuTextureWrapper = texture._hardwareTexture; gpuTextureWrapper?.releaseMSAATexture(rtWrapper.getBaseArrayLayer(i)); } // Note that rtWrapper.textures can't have null textures, lastTextureIsDepthTexture can't be true if rtWrapper._depthStencilTexture is null const lastTextureIsDepthTexture = rtWrapper._depthStencilTexture === rtWrapper.textures[count - 1]; for (let i = 0; i < count; ++i) { const texture = rtWrapper.textures[i]; this._textureHelper.createMSAATexture(texture, samples, false, rtWrapper.getBaseArrayLayer(i)); texture.samples = samples; } // Note that the last texture of textures is the depth texture if the depth texture has been generated by the MRT class and so the MSAA texture // will be recreated for this texture by the loop above: in that case, there's no need to create the MSAA texture for rtWrapper._depthStencilTexture // because rtWrapper._depthStencilTexture is the same texture than the depth texture if (rtWrapper._depthStencilTexture && !lastTextureIsDepthTexture) { this._textureHelper.createMSAATexture(rtWrapper._depthStencilTexture, samples); rtWrapper._depthStencilTexture.samples = samples; } rtWrapper._samples = samples; return samples; }; WebGPUEngine.prototype.generateMipMapsMultiFramebuffer = function (texture) { const rtWrapper = texture; if (!rtWrapper.isMulti) { return; } const attachments = rtWrapper._attachments; const count = attachments.length; for (let i = 0; i < count; i++) { const texture = rtWrapper.textures[i]; if (texture.generateMipMaps && !texture.isCube && !texture.is3D) { this._generateMipmaps(texture); } } }; WebGPUEngine.prototype.resolveMultiFramebuffer = function (_texture) { throw new Error("resolveMultiFramebuffer is not yet implemented in WebGPU!"); }; WebGPUEngine.prototype.bindAttachments = function (attachments) { if (attachments.length === 0 || !this._currentRenderTarget) { return; } this._mrtAttachments = attachments; if (this._currentRenderPass) { // the render pass has already been created, we need to call setMRTAttachments to update the state of the attachments this._cacheRenderPipeline.setMRTAttachments(attachments); } else { // the render pass is not created yet so we don't need to call setMRTAttachments: it will be called as part of the render pass creation (see WebGPUEngine._startRenderTargetRenderPass) } }; WebGPUEngine.prototype.buildTextureLayout = function (textureStatus, backBufferLayout = false) { const result = []; if (backBufferLayout) { result.push(1); } else { for (let i = 0; i < textureStatus.length; i++) { if (textureStatus[i]) { result.push(i + 1); } else { result.push(0); } } } return result; }; WebGPUEngine.prototype.restoreSingleAttachment = function () { // not sure what to do, probably nothing... This function and restoreSingleAttachmentForRenderTarget are not called in Babylon.js so it's hard to know the use case }; WebGPUEngine.prototype.restoreSingleAttachmentForRenderTarget = function () { // not sure what to do, probably nothing... This function and restoreSingleAttachment are not called in Babylon.js so it's hard to know the use case }; //# sourceMappingURL=engine.multiRender.js.map