HLSL中的3D缓冲区?

时间:2016-11-18 06:10:40

标签: c# unity3d gpgpu hlsl

我想使用unity以3D数组的形式向HLSL发送一系列整数。我现在已经尝试这样做了几天,但没有任何好处。我试图将缓冲区相互打包(StructuredBuffer<StructuredBuffer<StructuredBuffer<int>>>),但它根本不会起作用。而且我需要使这个东西可以调整大小,所以我不能在struct中使用数组。我该怎么办?

编辑:为了澄清我在这里要做的更多,这是一个医疗计划。当您扫描身体时,会生成一些文件。这些文件称为DICOM文件(.dcm)。这些文件是给医生的。医生应该打开程序,选择所有DICOM文件并加载它们。每个DICOM文件都包含一个图像。但是,这些图像并不像我们日常生活中使用的正常图像那样。这些图像是灰度级的,每个像素的值介于-1000到几千之间,因此每个像素保存为2个字节(或Int16)。我需要生成一个被扫描的身体的3D模型,所以我使用Marching Cubes算法生成它(看看Polygonising a Scalar Field)。问题是我习惯在大约360个512 * 512大小的图像中循环每个像素,这花费了太多时间。在我使用CPU时,我曾经需要读取每个文件中的像素数据。现在我试图让这个过程在运行时发生。我需要在处理之前将所有像素数据发送到GPU。这是我的问题。我需要GPU从磁盘读取数据。因为那是不可能的,我需要以Int的3D阵列的形式向GPU发送360 * 512 * 512 * 4字节的数据。我还计划将数据保存在那里以避免重新传输大量内存。我该怎么办? Refer to this link to know more about what I'm doing

2 个答案:

答案 0 :(得分:1)

在Unity中,我们目前拥有允许MaterialPropertyBlockSetMatrixArraySetVectorArray,为了让这更加甜蜜,我们可以使用Shader静态助手SetGlobalVectorArray全局设置SetGlobalMatrixArray。我相信这些会帮助你。

如果您更喜欢旧的方式,请查看this quite nice article,了解如何传递矢量数组。

答案 1 :(得分:1)

据我所知,我建议尝试以下方法:

  1. 展平你的数据(嵌套缓冲区不是你想要的gpu)

  2. 如果需要,可以在多个ComputeBuffers之间拆分您的数据(当我在Nvidia Titan XI上玩它们时,每个缓冲区可以存储大约1GB的数据。我正在渲染一个1.5GB的3D点云数据或其他东西,你提到的360MB数据应该不是问题然后)

  3. 如果您需要多个缓冲区:让它们根据行进多维数据集算法的需要重叠

  4. ComputeShader中完成所有计算(我认为需要DX11,如果你有多个缓冲区,多次运行并累积结果),然后在标准着色器中使用结果从OnPostRender函数调用(在内部使用Graphics.DrawProcedural只绘制点或在gpu上构建网格)

  5. 修改(可能会对你感兴趣)

    如果要将数据附加到gpu缓冲区(因为你不知道确切的大小或者你不能一次将它写入gpu),你可以使用AppendBuffers和{{1 }}

    C#脚本碎片:

    ComputeShader

    ComputeShader:

    struct DataStruct
    {
        ...
    }
    
    DataStruct[] yourData;
    yourData = loadStuff();    
    
    ComputeBuffer tmpBuffer = new ComputeBuffer(512, Marshal.SizeOf(typeof(DataStruct)));
    ComputeBuffer gpuData = new ComputeBuffer(MAX_SIZE, Marshal.SizeOf(typeof(DataStruct)), ComputeBufferType.Append);
    
    for (int i = 0; i < yourData.Length / 512; i++) {
    
        // write data subset to temporary buffer on gpu
        tmpBuffer.SetData(DataStruct.Skip(i*512).Take((i+1)*512).ToArray()); // Use fancy Linq stuff to select data subset
    
        // set up and run compute shader for appending data to "gpuData" buffer
        AppendComputeShader.SetBuffer(0, "inBuffer", tmpBuffer);
        AppendComputeShader.SetBuffer(0, "appendBuffer", gpuData);
        AppendComputeShader.Dispatch(0, 512/8, 1, 1); // 8 = gpu work group size -> use 512/8 work groups
    }
    

    注意:

    • 必须通过Inspector
    • 分配AppendComputeShader
    • 512是一个任意的批量大小,你可以一次追加到gpu缓冲区的数据有一个上限,但我认为这取决于硬件(对我而言似乎是65536 * 4字节)< / LI>
    • 你必须为gpu缓冲区提供最大大小(在Titan X上似乎是~1GB)