Orillusion

    • 注册
    • 登录
    • 搜索
    • 版块
    • 最新
    • 标签

    WebGPU 更新 texture

    中文社区
    webgpu texture
    2
    2
    226
    正在加载更多帖子
    • 从旧到新
    • 从新到旧
    • 最多赞同
    回复
    • 在新帖中回复
    登录后回复
    此主题已被删除。只有拥有主题管理权限的用户可以查看。
    • 赖
      赖少 最后由 shuangliu 编辑

      我知道怎么用 queue.writeBuffer 去改矩阵的值,但对于texture,什么是比较推荐的或者正确的方法中更新texture或者sampler?另外每个texture都需要一个pipeline?

      1 条回复 最后回复 回复 引用 0
      • shuangliu
        shuangliu 最后由 shuangliu 编辑

        1.首先并不需要每个texture对应一个pipeline,可以在同一pipeline中使用不同的BindGroup,每个group对应不同的texture binding. e.g.

        let sampler = device.createSampler({
            magFilter: 'linear',
            minFilter: 'linear',
        });
        let texture1 = device.createTexture({ ... });
        let texture2 = device.createTexture({ ... });
        const group1 = device.createBindGroup({
            layout: pipeline.getBindGroupLayout(0),
            entries: [
                {
                    binding: 1,
                    resource: sampler,
                },
                {
                    binding: 2,
                    resource: texture1.createView(),
                }
            ]
        });
        const group2 = device.createBindGroup({
            layout: pipeline.getBindGroupLayout(0),
            entries: [
                {
                    binding: 1,
                    resource: sampler,
                },
                {
                    binding: 2,
                    resource: texture2.createView(),
                }
            ]
        });
        

        然后在 rendering loop 中通过 setBindGroup 切换 group1 和 group 2 即可。


        2.如果一组 textures 是同样的大小和格式,可以直接使用 texture_2d_array 去存储多个 image,这样即使一个group内,也可以在shader中通过切换array的index,来直接切换 texutre.

        对于动态的 video texuture, 我们可以直接使用 importExternalTexture 进行引入,随着video播放,texture 会自动更新

        const video = document.createElement('video');
        video.loop = true;
        video.autoplay = true;
        video.muted = true;
        video.src = '...';
        await video.play();
        
        const group = device.createBindGroup({
            layout: pipeline.getBindGroupLayout(0),
            entries: [
                {
                    binding: 1,
                    resource: sampler,
                },
                {
                    binding: 2,
                    resource: device.importExternalTexture({
                        source: video,
                    })
                }
            ]
        });
        

        3.对于更新静态的 texutre,可以根据目标 image/texture 的类型进行 copy 更新,目前 webgpu 提供多个copy command,我们一般最主要会用到的:copyExternalImageToTexture ,可以更新外部image到gpu texture:

        let texture = device.createTexture({ ... });
        const img1 = document.createElement('img');
        img1.src = '....';
        await img1.decode();
        const image1 = await createImageBitmap(img1);
        device.queue.copyExternalImageToTexture(
              { source: image1 },
              { texture: texture },
              [image1.width, image1.height]
        );
        ...
        ...js
        // 更新texture的image
        const img2 = document.createElement('img');
        img2.src = '....';
        await img2.decode();
        const image2 = await createImageBitmap(img2);
        device.queue.copyExternalImageToTexture(
              { source: image2 },
              { texture: texture },
              [image2.width, image2.height]
        );
        

        另外,也可以用 commandEncoder 执行 copyTextureToTexture 进行两个 gpu texutre 之间的copy 更新

        // e.g. 创建两个texture,texture1 用于显示,tempTexture用于接收外部图片,图片loading 后进行 copy 更新
        let texture1 = device.createTexture({ ... });
        ...
        let tempTexture = device.createTexture({ ... });
        let newImage = await loadImage() // 异步加载图片 
        device.queue.copyExternalImageToTexture(
            { source: newImage },
            { texture: tempTexture },
            [newImage.width, newImage.height]
        );
        const commandEncoder = device.createCommandEncoder();
        commandEncoder.copyTextureToTexture(
            { texture: tempTexture },
            { texture: texture1 }
        );
        device.queue.submit([commandEncoder.finish()]);
        

        其他的更新texture API 使用方法,可以参阅 https://www.orillusion.com/webgpu.html#image-copies


        4.对于 sampler,目前 webgpu 没有直接更新 sampler 的API,只能创建新的 sampler,并使用新的group进行渲染,e.g.

        let linearSampler = device.createSampler({
            magFilter: 'linear',
            minFilter: 'linear',
        });
        const group = device.createBindGroup({
            layout: pipeline.getBindGroupLayout(0),
            entries: [
                {
                    binding: 1,
                    resource: linearSampler,
                },
                {
                    binding: 2,
                    resource: texture
                }
            ]
        });
        let nearestSampler = device.createSampler({
            magFilter: 'nearest',
            minFilter: 'nearest',
        });
        const newGroup = device.createBindGroup({
            layout: pipeline.getBindGroupLayout(0),
            entries: [
                {
                    binding: 1,
                    resource: nearestSampler,
                },
                {
                    binding: 2,
                    resource: texture
                }
            ]
        });
        

        group中其他的resource并不需要重新创建,可以复用

        1 条回复 最后回复 回复 引用 1
        • First post
          Last post

        Recent Post

        • 目前可以预览demo了

          • 阅读更多
        • A

          这demo太卡了,我机器性能不算差,运行个demo cpu就将近100%

          • 阅读更多
        • A

          没有贴出app.vue的代码

          • 阅读更多
        • @aichangqing 可能是之前版本的cdn缓存没更新,可以清理本地缓存刷新再试一次

          • 阅读更多
        • 36e6af78-b023-4031-9b56-bd8713b44393-image.png

          已经是版本 113.0.5656.0(正式版本)canary (64 位)并且开启chrome://flags/#enable-unsafe-webgpu 为enable,为啥还不能预览demo

          • 阅读更多

        Copyright © 2022 Orillusion | Contact US