UNPKG

playcanvas

Version:

Open-source WebGL/WebGPU 3D engine for the web

260 lines (259 loc) 9.28 kB
var __defProp = Object.defineProperty; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); import { TRACEID_BINDGROUPFORMAT_ALLOC } from "../../core/constants.js"; import { Debug, DebugHelper } from "../../core/debug.js"; import { TEXTUREDIMENSION_2D, SAMPLETYPE_FLOAT, PIXELFORMAT_RGBA8, SHADERSTAGE_COMPUTE, SHADERSTAGE_VERTEX } from "./constants.js"; import { DebugGraphics } from "./debug-graphics.js"; let id = 0; class BindBaseFormat { /** * Create a new instance. * * @param {string} name - The name of the resource. * @param {number} visibility - A bit-flag that specifies the shader stages in which the resource * is visible. Can be: * * - {@link SHADERSTAGE_VERTEX} * - {@link SHADERSTAGE_FRAGMENT} * - {@link SHADERSTAGE_COMPUTE} */ constructor(name, visibility) { /** @ignore */ __publicField(this, "slot", -1); /** * @type {ScopeId|null} * @ignore */ __publicField(this, "scopeId", null); this.name = name; this.visibility = visibility; } } class BindUniformBufferFormat extends BindBaseFormat { } class BindStorageBufferFormat extends BindBaseFormat { /** * Create a new instance. * * @param {string} name - The name of the storage buffer. * @param {number} visibility - A bit-flag that specifies the shader stages in which the storage * buffer is visible. Can be: * * - {@link SHADERSTAGE_VERTEX} * - {@link SHADERSTAGE_FRAGMENT} * - {@link SHADERSTAGE_COMPUTE} * * @param {boolean} [readOnly] - Whether the storage buffer is read-only, or read-write. Defaults * to false. This has to be true for the storage buffer used in the vertex shader. */ constructor(name, visibility, readOnly = false) { super(name, visibility); /** * Format, extracted from vertex and fragment shader. * * @ignore */ __publicField(this, "format", ""); this.readOnly = readOnly; Debug.assert(readOnly || !(visibility & SHADERSTAGE_VERTEX), "Storage buffer can only be used in read-only mode in SHADERSTAGE_VERTEX."); } } class BindTextureFormat extends BindBaseFormat { /** * Create a new instance. * * @param {string} name - The name of the storage buffer. * @param {number} visibility - A bit-flag that specifies the shader stages in which the storage * buffer is visible. Can be: * * - {@link SHADERSTAGE_VERTEX} * - {@link SHADERSTAGE_FRAGMENT} * - {@link SHADERSTAGE_COMPUTE} * * @param {string} [textureDimension] - The dimension of the texture. Defaults to * {@link TEXTUREDIMENSION_2D}. Can be: * * - {@link TEXTUREDIMENSION_1D} * - {@link TEXTUREDIMENSION_2D} * - {@link TEXTUREDIMENSION_2D_ARRAY} * - {@link TEXTUREDIMENSION_CUBE} * - {@link TEXTUREDIMENSION_CUBE_ARRAY} * - {@link TEXTUREDIMENSION_3D} * * @param {number} [sampleType] - The type of the texture samples. Defaults to * {@link SAMPLETYPE_FLOAT}. Can be: * * - {@link SAMPLETYPE_FLOAT} * - {@link SAMPLETYPE_UNFILTERABLE_FLOAT} * - {@link SAMPLETYPE_DEPTH} * - {@link SAMPLETYPE_INT} * - {@link SAMPLETYPE_UINT} * * @param {boolean} [hasSampler] - True if the sampler for the texture is needed. Note that if the * sampler is used, it will take up an additional slot, directly following the texture slot. * Defaults to true. * @param {string|null} [samplerName] - Optional name of the sampler. Defaults to null. */ constructor(name, visibility, textureDimension = TEXTUREDIMENSION_2D, sampleType = SAMPLETYPE_FLOAT, hasSampler = true, samplerName = null) { super(name, visibility); this.textureDimension = textureDimension; this.sampleType = sampleType; this.hasSampler = hasSampler; this.samplerName = samplerName ?? `${name}_sampler`; } } class BindStorageTextureFormat extends BindBaseFormat { /** * Create a new instance. * * @param {string} name - The name of the storage buffer. * @param {number} [format] - The pixel format of the texture. Note that not all formats can be * used. Defaults to {@link PIXELFORMAT_RGBA8}. * @param {string} [textureDimension] - The dimension of the texture. Defaults to * {@link TEXTUREDIMENSION_2D}. Can be: * * - {@link TEXTUREDIMENSION_1D} * - {@link TEXTUREDIMENSION_2D} * - {@link TEXTUREDIMENSION_2D_ARRAY} * - {@link TEXTUREDIMENSION_3D} * * @param {boolean} [write] - Whether the storage texture is writeable. Defaults to true. * @param {boolean} [read] - Whether the storage texture is readable. Defaults to false. Note * that storage texture reads are only supported if * {@link GraphicsDevice#supportsStorageTextureRead} is true. Also note that only a subset of * pixel formats can be used for storage texture reads - as an example, PIXELFORMAT_RGBA8 is not * compatible, but PIXELFORMAT_R32U is. */ constructor(name, format = PIXELFORMAT_RGBA8, textureDimension = TEXTUREDIMENSION_2D, write = true, read = false) { super(name, SHADERSTAGE_COMPUTE); this.format = format; this.textureDimension = textureDimension; this.write = write; this.read = read; } } class BindGroupFormat { /** * Create a new instance. * * @param {GraphicsDevice} graphicsDevice - The graphics device used to manage this vertex format. * @param {(BindTextureFormat|BindStorageTextureFormat|BindUniformBufferFormat|BindStorageBufferFormat)[]} formats - * An array of bind formats. Note that each entry in the array uses up one slot. The exception * is a texture format that has a sampler, which uses up two slots. The slots are allocated * sequentially, starting from 0. */ constructor(graphicsDevice, formats) { /** * @type {BindUniformBufferFormat[]} * @private */ __publicField(this, "uniformBufferFormats", []); /** * @type {BindTextureFormat[]} * @private */ __publicField(this, "textureFormats", []); /** * @type {BindStorageTextureFormat[]} * @private */ __publicField(this, "storageTextureFormats", []); /** * @type {BindStorageBufferFormat[]} * @private */ __publicField(this, "storageBufferFormats", []); this.id = id++; DebugHelper.setName(this, `BindGroupFormat_${this.id}`); Debug.assert(formats); let slot = 0; formats.forEach((format) => { format.slot = slot++; if (format instanceof BindTextureFormat && format.hasSampler) { slot++; } if (format instanceof BindUniformBufferFormat) { this.uniformBufferFormats.push(format); } else if (format instanceof BindTextureFormat) { this.textureFormats.push(format); } else if (format instanceof BindStorageTextureFormat) { this.storageTextureFormats.push(format); } else if (format instanceof BindStorageBufferFormat) { this.storageBufferFormats.push(format); } else { Debug.assert("Invalid bind format", format); } }); this.device = graphicsDevice; const scope = graphicsDevice.scope; this.bufferFormatsMap = /* @__PURE__ */ new Map(); this.uniformBufferFormats.forEach((bf, i) => this.bufferFormatsMap.set(bf.name, i)); this.textureFormatsMap = /* @__PURE__ */ new Map(); this.textureFormats.forEach((tf, i) => { this.textureFormatsMap.set(tf.name, i); tf.scopeId = scope.resolve(tf.name); }); this.storageTextureFormatsMap = /* @__PURE__ */ new Map(); this.storageTextureFormats.forEach((tf, i) => { this.storageTextureFormatsMap.set(tf.name, i); tf.scopeId = scope.resolve(tf.name); }); this.storageBufferFormatsMap = /* @__PURE__ */ new Map(); this.storageBufferFormats.forEach((bf, i) => { this.storageBufferFormatsMap.set(bf.name, i); bf.scopeId = scope.resolve(bf.name); }); this.impl = graphicsDevice.createBindGroupFormatImpl(this); Debug.trace(TRACEID_BINDGROUPFORMAT_ALLOC, `Alloc: Id ${this.id}, while rendering [${DebugGraphics.toString()}]`, this); } /** * Frees resources associated with this bind group. */ destroy() { this.impl.destroy(); } /** * Returns format of texture with specified name. * * @param {string} name - The name of the texture slot. * @returns {BindTextureFormat|null} - The format. * @ignore */ getTexture(name) { const index = this.textureFormatsMap.get(name); if (index !== void 0) { return this.textureFormats[index]; } return null; } /** * Returns format of storage texture with specified name. * * @param {string} name - The name of the texture slot. * @returns {BindStorageTextureFormat|null} - The format. * @ignore */ getStorageTexture(name) { const index = this.storageTextureFormatsMap.get(name); if (index !== void 0) { return this.storageTextureFormats[index]; } return null; } loseContext() { } } export { BindGroupFormat, BindStorageBufferFormat, BindStorageTextureFormat, BindTextureFormat, BindUniformBufferFormat };