From 912a837a248c65883460f95356206d09d50dc5c4 Mon Sep 17 00:00:00 2001 From: Liam Don Date: Fri, 2 Feb 2024 09:42:25 -0800 Subject: [PATCH] Don't upload texture if locked using TEXTURELOCK_READ (#6003) * Don't upload texture if locked using TEXTURELOCK_READ * Don't expose _lockedLevel yet * Better assertions, upgrade double-unlock from log to warning --- src/platform/graphics/constants.js | 7 +++++ src/platform/graphics/texture.js | 43 ++++++++++++++++++++++++++---- 2 files changed, 45 insertions(+), 5 deletions(-) diff --git a/src/platform/graphics/constants.js b/src/platform/graphics/constants.js index e3f227aaff2..1612c4c9cc2 100644 --- a/src/platform/graphics/constants.js +++ b/src/platform/graphics/constants.js @@ -1324,6 +1324,13 @@ export const STENCILOP_DECREMENTWRAP = 6; */ export const STENCILOP_INVERT = 7; +/** + * The texture is not in a locked state. + * + * @type {number} + */ +export const TEXTURELOCK_NONE = 0; + /** * Read only. Any changes to the locked mip level's pixels will not update the texture. * diff --git a/src/platform/graphics/texture.js b/src/platform/graphics/texture.js index 5d61c393700..f082af884e6 100644 --- a/src/platform/graphics/texture.js +++ b/src/platform/graphics/texture.js @@ -16,7 +16,7 @@ import { TEXTURELOCK_WRITE, TEXTUREPROJECTION_NONE, TEXTUREPROJECTION_CUBE, TEXTURETYPE_DEFAULT, TEXTURETYPE_RGBM, TEXTURETYPE_RGBE, TEXTURETYPE_RGBP, TEXTURETYPE_SWIZZLEGGGR, - isIntegerPixelFormat, FILTER_NEAREST + isIntegerPixelFormat, FILTER_NEAREST, TEXTURELOCK_NONE, TEXTURELOCK_READ } from './constants.js'; let id = 0; @@ -47,6 +47,9 @@ class Texture { /** @protected */ _lockedLevel = -1; + /** @protected */ + _lockedMode = TEXTURELOCK_NONE; + /** * A render version used to track the last time the texture properties requiring bind group * to be updated were changed. @@ -377,6 +380,20 @@ class Texture { return this.mipmaps ? TextureUtils.calcMipLevelsCount(this.width, this.height) : 1; } + /** + * Returns the current lock mode. One of: + * + * - {@link TEXTURELOCK_NONE} + * - {@link TEXTURELOCK_READ} + * - {@link TEXTURELOCK_WRITE} + * + * @ignore + * @type {number} + */ + get lockedMode() { + return this._lockedMode; + } + /** * The minification filter to be applied to the texture. Can be: * @@ -773,6 +790,19 @@ class Texture { options.face ??= 0; options.mode ??= TEXTURELOCK_WRITE; + Debug.assert( + this._lockedMode === TEXTURELOCK_NONE, + 'The texture is already locked. Call `texture.unlock()` before attempting to lock again.', + this + ); + + Debug.assert( + options.mode === TEXTURELOCK_READ || options.mode === TEXTURELOCK_WRITE, + 'Cannot lock a texture with TEXTURELOCK_NONE. To unlock a texture, call `texture.unlock()`.', + this + ); + + this._lockedMode = options.mode; this._lockedLevel = options.level; const levels = this.cubemap ? this._levels[options.face] : this._levels; @@ -900,13 +930,16 @@ class Texture { * Unlocks the currently locked mip level and uploads it to VRAM. */ unlock() { - if (this._lockedLevel === -1) { - Debug.log("pc.Texture#unlock: Attempting to unlock a texture that is not locked.", this); + if (this._lockedMode === TEXTURELOCK_NONE) { + Debug.warn("pc.Texture#unlock: Attempting to unlock a texture that is not locked.", this); } - // Upload the new pixel data - this.upload(); + // Upload the new pixel data if locked in write mode (default) + if (this._lockedMode === TEXTURELOCK_WRITE) { + this.upload(); + } this._lockedLevel = -1; + this._lockedMode = TEXTURELOCK_NONE; } /**