playcanvas / engine

JavaScript game engine built on WebGL, WebGPU, WebXR and glTF

Home Page:https://playcanvas.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

WebGPU: RenderTarget is upside down

erikdubbelboer opened this issue · comments

The flipY of pc.RenderTarget is inverted for WebGPU.

Project that reproduces the bug: https://playcanvas.com/project/1176285/overview/webgpu-rendertarget-bug

WebGL:
Screenshot 2024-05-02 at 09 46 54

WebGPU:
Screenshot 2024-05-02 at 09 47 01

Script used to generate the image:

var Render = pc.createScript('render');

Render.prototype.initialize = function () {
    const device = this.app.graphicsDevice;

    this.colorBuffer = new pc.Texture(device, {
        width: 400,
        height: 400,
        format: pc.PIXELFORMAT_R8_G8_B8_A8,
        mipmaps: true,
        anisotropy: 1,
        minFilter: pc.FILTER_LINEAR_MIPMAP_NEAREST,
        magFilter: pc.FILTER_LINEAR,
        addressU: pc.ADDRESS_CLAMP_TO_EDGE,
        addressV: pc.ADDRESS_CLAMP_TO_EDGE,
        addressW: pc.ADDRESS_CLAMP_TO_EDGE,
    });

    const renderTarget = new pc.RenderTarget(device, this.colorBuffer, {
        depth: true,
        flipY: true, // Bug can be fixed using !device.isWebGPU
        samples: 1,
    });

    this.camera = this.app.root.findByName('Camera2').camera;

    this.camera.renderTarget = renderTarget;

    this.frameCounter = 0;
};

Render.prototype.update = function () {
    this.frameCounter++;

    // Wait a couple of frames to do this, doing it right away will fail.
    if (this.frameCounter == 10) {
        // This line isn't needed on WebGL, but on WebGPU causes:
        // Texture (unlabeled 400x400 px, TextureFormat::RGBA8Unorm)] usage (TextureUsage::(TextureBinding|RenderAttachment)) includes writable usage and another usage in the same synchronization scope.
        this.camera.renderTarget = null;

        this.entity.element.texture = this.colorBuffer;
    }
};

There is a simple fix to set flipY to !device.isWebGPU, but it's probably better if this gets fixed.

As you can see in the script another minor issue is that the renderTarget can't be in use by a camera at the same time as being used as a texture in WebGPU, with WebGL this is fine. I understand this is not something that can be fixed, but it's maybe nice to have documented somewhere if people search for this error.

Yep, thanks, I'm aware of this, and have tried to fix it, but do not have a generic solution yet - there are many parts to it.

As you said, there is this workaround currently: set flipY to !device.isWebGPU but this depends on what gets rendered to the target. If forward renderer renders to it, the flip is internally handled by the adjusted projection matrix as well, but when custom shaders are used, this is different. Extra complication comes with cubemaps too.