zoukankan      html  css  js  c++  java
  • ComputeShader中Consume与AppendStructuredBuffer的使用

    上个月写了一篇使用像素shader返回累加信息的Trick:https://www.cnblogs.com/hont/p/9977401.html

    后来无意中发现DX11/Compute shader有一类Append/Consume数据格式更适合这类操作。

    c sharp脚本:

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class ComputeShaderTest : MonoBehaviour
    {
        public ComputeShader computeShader;
    
    
        void Awake()
        {
            //reference: https://answers.unity.com/questions/1035132/how-can-i-read-in-the-actual-elements-from-an-appe.html
    
            var kernelID = computeShader.FindKernel("CSMain");
            var appendBuffer = new ComputeBuffer(64, sizeof(int), ComputeBufferType.Append);
            appendBuffer.SetCounterValue(0);
            //定义了缓冲区长度为64*结构大小的appendBuffer.
    
            var consumeBuffer = new ComputeBuffer(64, sizeof(int), ComputeBufferType.Append);
            consumeBuffer.SetCounterValue(0);
            consumeBuffer.SetData(new int[] { 97, 98, 99 });
            consumeBuffer.SetCounterValue(3);
            //consume类型结构相当于栈,所以取到的第一个值是99。
    
            computeShader.SetBuffer(kernelID, "appendBuffer", appendBuffer);
            computeShader.SetBuffer(kernelID, "consumeBuffer", consumeBuffer);
            computeShader.Dispatch(kernelID, 1, 1, 1);
            //单个线程组的大小为8,定义了1个线程组。也就是说会返回8个数据。
    
            var countBuffer = new ComputeBuffer(1, sizeof(int), ComputeBufferType.IndirectArguments);
            ComputeBuffer.CopyCount(appendBuffer, countBuffer, 0);
            //通过这个方法拿到第一个数据。
    
            int[] counter = new int[1] { 0 };
            countBuffer.GetData(counter);
    
            int count = counter[0];
    
            Debug.Log("count: " + count);
    
            var data = new int[count];
            appendBuffer.GetData(data);
    
            Debug.Log("data length: " + data.Length);
    
            for (int i = 0; i < data.Length; i++)
            {
                Debug.Log(data[i]);
            }
    
            consumeBuffer.Release();
            consumeBuffer.Dispose();
    
            appendBuffer.Release();
            appendBuffer.Dispose();
    
            countBuffer.Release();
            countBuffer.Dispose();
        }
    }

    compute shader:

    #pragma kernel CSMain
    
    AppendStructuredBuffer<int> appendBuffer;
    ConsumeStructuredBuffer<int> consumeBuffer;
    
    [numthreads(8,1,1)]
    void CSMain (uint3 id : SV_DispatchThreadID)
    {
        if (id.x == 2)
        {
            int value = consumeBuffer.Consume();
            appendBuffer.Append(value);
        }
    
        if (id.x > 2)
        {
            appendBuffer.Append(id.x);
        }
    }

    传入的线程组是8,1,1。并且Dispatch只运行了一个线程组,所以每一次传入id的x值依次为0,1,2,3,4,5,6,7

    在id是2的时候读consume里的值,所以第一个是99.

    最终输出:99,3,4,5,6,7。

  • 相关阅读:
    异步编程系列第04章 编写Async方法
    异步编程系列第03章 自己写异步代码
    异步编程系列第02章 你有什么理由使用Async异步编程
    异步编程系列第01章 Async异步编程简介
    初探asp.net异步编程之await
    Sql Server 覆盖索引
    把cookie以json形式返回,用js来set cookie.(解决手机浏览器未知情况下获取不到cookie)
    redis+cookies实现session机制(解决 手机浏览器不自动回传cookies导致session不可用问题)
    把阅读当作一种人生习惯来培养
    SAS中的剔除空格函数
  • 原文地址:https://www.cnblogs.com/hont/p/10122129.html
Copyright © 2011-2022 走看看