From b02db70775fe74d95f1bf802fe69be333d801bf8 Mon Sep 17 00:00:00 2001 From: Catalin Moldovan Date: Tue, 21 May 2024 10:42:27 +0300 Subject: [PATCH 1/2] Add immediate upload option to textures --- .../graphics/texture-array.example.mjs | 4 ++-- src/platform/graphics/texture.js | 20 +++++++++++-------- src/platform/graphics/webgl/webgl-texture.js | 13 ++++++++++++ 3 files changed, 27 insertions(+), 10 deletions(-) diff --git a/examples/src/examples/graphics/texture-array.example.mjs b/examples/src/examples/graphics/texture-array.example.mjs index 0e0ecbc929e..fff6f760c96 100644 --- a/examples/src/examples/graphics/texture-array.example.mjs +++ b/examples/src/examples/graphics/texture-array.example.mjs @@ -147,11 +147,11 @@ assetListLoader.load(() => { assets.aerialRocks.resource.getSource(), assets.coastSand.resource.getSource() ] - ] + ], + immediate: true }; const textureArray = new pc.Texture(app.graphicsDevice, textureArrayOptions); - textureArray.upload(); // generate mipmaps for visualization const mipmaps = generateMipmaps(textureArrayOptions.width, textureArrayOptions.height); diff --git a/src/platform/graphics/texture.js b/src/platform/graphics/texture.js index 5b41b854a29..5f1ba4b7bed 100644 --- a/src/platform/graphics/texture.js +++ b/src/platform/graphics/texture.js @@ -185,6 +185,7 @@ class Texture { * of Uint8Array if options.arrayLength is defined and greater than zero. * @param {boolean} [options.storage] - Defines if texture can be used as a storage texture by * a compute shader. Defaults to false. + * @param {boolean} [options.immediate] - If set and true, the texture will be uploaded to the GPU immediately. * @example * // Create a 8x8x24-bit texture * const texture = new pc.Texture(graphicsDevice, { @@ -267,7 +268,7 @@ class Texture { this._levels = options.levels; if (this._levels) { - this.upload(); + this.upload(options.immediate ?? false); } else { this._levels = this._cubemap ? [[null, null, null, null, null, null]] : [null]; } @@ -878,8 +879,9 @@ class Texture { * @param {number} [mipLevel] - A non-negative integer specifying the image level of detail. * Defaults to 0, which represents the base image source. A level value of N, that is greater * than 0, represents the image source for the Nth mipmap reduction level. + * @param {boolean} [immediate] - When set to true it forces an immediate upload upon assignment. Defaults to false. */ - setSource(source, mipLevel = 0) { + setSource(source, mipLevel = 0, immediate = false) { let invalid = false; let width, height; @@ -959,7 +961,7 @@ class Texture { this._invalid = invalid; // reupload - this.upload(); + this.upload(immediate); } } @@ -979,15 +981,16 @@ class Texture { /** * Unlocks the currently locked mip level and uploads it to VRAM. + * @param {boolean} [immediate] - When set to true it forces an immediate upload upon unlocking. Defaults to false. */ - unlock() { + unlock(immediate = false) { 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 if locked in write mode (default) if (this._lockedMode === TEXTURELOCK_WRITE) { - this.upload(); + this.upload(immediate); } this._lockedLevel = -1; this._lockedMode = TEXTURELOCK_NONE; @@ -995,15 +998,16 @@ class Texture { /** * Forces a reupload of the textures pixel data to graphics memory. Ordinarily, this function - * is called by internally by {@link Texture#setSource} and {@link Texture#unlock}. However, it + * is called internally by {@link Texture#setSource} and {@link Texture#unlock}. However, it * still needs to be called explicitly in the case where an HTMLVideoElement is set as the * source of the texture. Normally, this is done once every frame before video textured * geometry is rendered. + * @param {boolean} [immediate] - When set to true it forces an immediate upload. Defaults to false. */ - upload() { + upload(immediate = false) { this._needsUpload = true; this._needsMipmapsUpload = this._mipmaps; - this.impl.uploadImmediate?.(this.device, this); + this.impl.uploadImmediate(this.device, this, immediate); } /** diff --git a/src/platform/graphics/webgl/webgl-texture.js b/src/platform/graphics/webgl/webgl-texture.js index 6dbfb90862e..bff4f18af34 100644 --- a/src/platform/graphics/webgl/webgl-texture.js +++ b/src/platform/graphics/webgl/webgl-texture.js @@ -376,6 +376,19 @@ class WebglTexture { this._glCreated = false; } + uploadImmediate(device, texture, immediate) { + if (immediate) { + if (!texture._glTexture) { + this.initialize(device, texture); + } + + device.bindTexture(texture); + this.upload(device, texture); + texture._needsUpload = false; + texture._needsMipmapsUpload = false; + } + } + /** * @param {import('./webgl-graphics-device.js').WebglGraphicsDevice} device - The device. * @param {import('../texture.js').Texture} texture - The texture to update. From cd3c826691f9ad0b0e2219f1df7a4a802ae04a47 Mon Sep 17 00:00:00 2001 From: Catalin Moldovan Date: Fri, 14 Jun 2024 10:10:39 +0300 Subject: [PATCH 2/2] Fix null-texture for tests. --- src/platform/graphics/null/null-texture.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/platform/graphics/null/null-texture.js b/src/platform/graphics/null/null-texture.js index dad979f9d44..300bb144f33 100644 --- a/src/platform/graphics/null/null-texture.js +++ b/src/platform/graphics/null/null-texture.js @@ -12,6 +12,9 @@ class NullTexture { loseContext() { } + + uploadImmediate(device, texture, immediate) { + } } export { NullTexture };