Kaynağa Gözat

By default issue a flushFramebufer before a readPixels

Popov72 4 yıl önce
ebeveyn
işleme
ec77972f18

+ 6 - 2
src/Engines/Extensions/engine.readTexture.ts

@@ -5,11 +5,11 @@ import { Nullable } from '../../types';
 declare module "../../Engines/thinEngine" {
     export interface ThinEngine {
         /** @hidden */
-        _readTexturePixels(texture: InternalTexture, width: number, height: number, faceIndex?: number, level?: number, buffer?: Nullable<ArrayBufferView>): Promise<ArrayBufferView>;
+        _readTexturePixels(texture: InternalTexture, width: number, height: number, faceIndex?: number, level?: number, buffer?: Nullable<ArrayBufferView>, flushRenderer?: boolean): Promise<ArrayBufferView>;
     }
 }
 
-ThinEngine.prototype._readTexturePixels = function(texture: InternalTexture, width: number, height: number, faceIndex = -1, level = 0, buffer: Nullable<ArrayBufferView> = null): Promise<ArrayBufferView> {
+ThinEngine.prototype._readTexturePixels = function(texture: InternalTexture, width: number, height: number, faceIndex = -1, level = 0, buffer: Nullable<ArrayBufferView> = null, flushRenderer = true): Promise<ArrayBufferView> {
     let gl = this._gl;
     if (!gl) {
         throw new Error ("Engine does not have gl rendering context.");
@@ -48,6 +48,10 @@ ThinEngine.prototype._readTexturePixels = function(texture: InternalTexture, wid
             break;
     }
 
+    if (flushRenderer) {
+        this.flushFramebuffer();
+    }
+
     gl.readPixels(0, 0, width, height, gl.RGBA, readType, <DataView>buffer);
     gl.bindFramebuffer(gl.FRAMEBUFFER, this._currentFramebuffer);
 

+ 5 - 1
src/Engines/thinEngine.ts

@@ -4501,12 +4501,16 @@ export class ThinEngine {
      * @param width defines the width of the rectangle where pixels must be read
      * @param height defines the height of the rectangle where pixels must be read
      * @param hasAlpha defines whether the output should have alpha or not (defaults to true)
+     * @param flushRenderer true to flush the renderer from the pending commands before reading the pixels
      * @returns a ArrayBufferView (Uint8Array) containing RGBA colors
      */
-    public readPixels(x: number, y: number, width: number, height: number, hasAlpha = true): Promise<ArrayBufferView> {
+    public readPixels(x: number, y: number, width: number, height: number, hasAlpha = true, flushRenderer = true): Promise<ArrayBufferView> {
         const numChannels = hasAlpha ? 4 : 3;
         const format = hasAlpha ? this._gl.RGBA : this._gl.RGB;
         const data = new Uint8Array(height * width * numChannels);
+        if (flushRenderer) {
+            this.flushFramebuffer();
+        }
         this._gl.readPixels(x, y, width, height, format, this._gl.UNSIGNED_BYTE, data);
         return Promise.resolve(data);
     }

+ 9 - 2
src/Engines/webgpuEngine.ts

@@ -2011,7 +2011,7 @@ export class WebGPUEngine extends Engine {
         texture.isReady = true;
     }
 
-    public readPixels(x: number, y: number, width: number, height: number, hasAlpha = true): Promise<ArrayBufferView> {
+    public readPixels(x: number, y: number, width: number, height: number, hasAlpha = true, flushRenderer = true): Promise<ArrayBufferView> {
         const renderPassWrapper = this._rttRenderPassWrapper.renderPass ? this._rttRenderPassWrapper : this._mainRenderPassWrapper;
         const gpuTexture = renderPassWrapper.colorAttachmentGPUTextures![0].underlyingResource;
         const gpuTextureFormat = renderPassWrapper.colorAttachmentGPUTextures![0].format;
@@ -2019,13 +2019,20 @@ export class WebGPUEngine extends Engine {
             // we are calling readPixels before startMainRenderPass has been called and no RTT is bound, so swapChainTexture is not setup yet!
             return Promise.resolve(new Uint8Array(0));
         }
+        if (flushRenderer) {
+            this.flushFramebuffer();
+        }
         return this._textureHelper.readPixels(gpuTexture, x, y, width, height, gpuTextureFormat);
     }
 
     /** @hidden */
-    public _readTexturePixels(texture: InternalTexture, width: number, height: number, faceIndex = -1, level = 0, buffer: Nullable<ArrayBufferView> = null): Promise<ArrayBufferView> {
+    public _readTexturePixels(texture: InternalTexture, width: number, height: number, faceIndex = -1, level = 0, buffer: Nullable<ArrayBufferView> = null, flushRenderer = true): Promise<ArrayBufferView> {
         let gpuTextureWrapper = texture._hardwareTexture as WebGPUHardwareTexture;
 
+        if (flushRenderer) {
+            this.flushFramebuffer();
+        }
+
         return this._textureHelper.readPixels(gpuTextureWrapper.underlyingResource!, 0, 0, width, height, gpuTextureWrapper.format, faceIndex, level, buffer);
     }
 

+ 4 - 3
src/Materials/Textures/baseTexture.ts

@@ -698,9 +698,10 @@ export class BaseTexture implements IAnimatable {
      * @param faceIndex defines the face of the texture to read (in case of cube texture)
      * @param level defines the LOD level of the texture to read (in case of Mip Maps)
      * @param buffer defines a user defined buffer to fill with data (can be null)
+     * @param flushRenderer true to flush the renderer from the pending commands before reading the pixels
      * @returns The Array buffer promise containing the pixels data.
      */
-    public readPixels(faceIndex = 0, level = 0, buffer: Nullable<ArrayBufferView> = null): Nullable<Promise<ArrayBufferView>> {
+    public readPixels(faceIndex = 0, level = 0, buffer: Nullable<ArrayBufferView> = null, flushRenderer = true): Nullable<Promise<ArrayBufferView>> {
         if (!this._texture) {
             return null;
         }
@@ -724,10 +725,10 @@ export class BaseTexture implements IAnimatable {
 
         try {
             if (this._texture.isCube) {
-                return engine._readTexturePixels(this._texture, width, height, faceIndex, level, buffer);
+                return engine._readTexturePixels(this._texture, width, height, faceIndex, level, buffer, flushRenderer);
             }
 
-            return engine._readTexturePixels(this._texture, width, height, -1, level, buffer);
+            return engine._readTexturePixels(this._texture, width, height, -1, level, buffer, flushRenderer);
         } catch (e) {
             return null;
         }

+ 10 - 8
src/Misc/HighDynamicRange/cubemapToSphericalPolynomial.ts

@@ -50,23 +50,25 @@ export class CubeMapToSphericalPolynomialTools {
             return null;
         }
 
+        texture.getScene()?.getEngine().flushFramebuffer();
+
         var size = texture.getSize().width;
-        var rightPromise = texture.readPixels(0);
-        var leftPromise = texture.readPixels(1);
+        var rightPromise = texture.readPixels(0, undefined, undefined, false);
+        var leftPromise = texture.readPixels(1, undefined, undefined, false);
 
         var upPromise: Nullable<Promise<ArrayBufferView>>;
         var downPromise: Nullable<Promise<ArrayBufferView>>;
         if (texture.isRenderTarget) {
-            upPromise = texture.readPixels(3);
-            downPromise = texture.readPixels(2);
+            upPromise = texture.readPixels(3, undefined, undefined, false);
+            downPromise = texture.readPixels(2, undefined, undefined, false);
         }
         else {
-            upPromise = texture.readPixels(2);
-            downPromise = texture.readPixels(3);
+            upPromise = texture.readPixels(2, undefined, undefined, false);
+            downPromise = texture.readPixels(3, undefined, undefined, false);
         }
 
-        var frontPromise = texture.readPixels(4);
-        var backPromise = texture.readPixels(5);
+        var frontPromise = texture.readPixels(4, undefined, undefined, false);
+        var backPromise = texture.readPixels(5, undefined, undefined, false);
 
         var gammaSpace = texture.gammaSpace;
         // Always read as RGBA.

+ 1 - 3
src/Misc/environmentTextureTools.ts

@@ -181,14 +181,12 @@ export class EnvironmentTextureTools {
 
             // All faces of the cube.
             for (let face = 0; face < 6; face++) {
-                let faceData = await texture.readPixels(face, i);
+                let faceData = await texture.readPixels(face, i, undefined, false);
 
                 let tempTexture = engine.createRawTexture(faceData, faceWidth, faceWidth, Constants.TEXTUREFORMAT_RGBA, false, true, Constants.TEXTURE_NEAREST_SAMPLINGMODE, null, textureType);
 
                 await RGBDTextureTools.EncodeTextureToRGBD(tempTexture, hostingScene, textureType);
 
-                engine.flushFramebuffer(); // make sure the tempTexture has its data up to date when reading them just below
-
                 const rgbdEncodedData = await engine._readTexturePixels(tempTexture, faceWidth, faceWidth);
 
                 const pngEncodedata = await Tools.DumpDataAsync(faceWidth, faceWidth, rgbdEncodedData, "image/png", undefined, false, true);

+ 1 - 1
src/Misc/minMaxReducer.ts

@@ -150,7 +150,7 @@ export class MinMaxReducer {
                     let buffer = new Float32Array(4 * w * h),
                         minmax = { min: 0, max: 0};
                     return () => {
-                        scene.getEngine()._readTexturePixels(reduction.inputTexture, w, h, -1, 0, buffer);
+                        scene.getEngine()._readTexturePixels(reduction.inputTexture, w, h, -1, 0, buffer, false);
                         minmax.min = buffer[0];
                         minmax.max = buffer[1];
                         this.onAfterReductionPerformed.notifyObservers(minmax);

+ 1 - 1
src/Misc/screenshotTools.ts

@@ -140,7 +140,7 @@ export class ScreenshotTools {
         texture.samples = samples;
         texture.renderSprites = renderSprites;
         engine.onEndFrameObservable.addOnce(() => {
-            texture.readPixels()!.then((data) => {
+            texture.readPixels(undefined, undefined, undefined, false)!.then((data) => {
                 Tools.DumpData(width, height, data, successCallback as (data: string | ArrayBuffer) => void, mimeType, fileName, true);
                 texture.dispose();