Search Unity

[Resolved] How do you Create and Allocate Textures for use in ComputeShader?

Discussion in 'Shaders' started by kiriri, May 10, 2017.

  1. kiriri

    kiriri

    Joined:
    Jan 14, 2011
    Posts:
    107
    Hi,
    I want to create an image at runtime and modify it in a Compute Shader. However, none of my changes appear to make it back to the CPU.
    Simple example script :

    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class ImAnIdiotTests : MonoBehaviour
    4. {
    5.     private int size = 16;
    6.     public ComputeShader fillShader;
    7.  
    8.     void Start () {
    9.         var tempTex = new Texture2D(size, size,TextureFormat.ARGB32,false,true);
    10.  
    11.         int[] data = new int[size*size];
    12.         tempTex.SetPixels(new Color[size*size]);
    13.         tempTex.Apply();
    14.  
    15.         var cB = new ComputeBuffer(size*size,sizeof(int)); // computeBuffers work, so I use it to make sure the ComputeShader itself is working
    16.  
    17.         Debug.Log(tempTex.GetPixel(0,0)*255); // Values prior to CS
    18.  
    19.         int kernelIndex = fillShader.FindKernel("CSMain");
    20.  
    21.         fillShader.SetTexture(kernelIndex,"Result",tempTex);
    22.         fillShader.SetFloat("val",2f); // should be assigned to all pixels in Result/tempTex
    23.         fillShader.SetInt("bufferWidth",size);
    24.         fillShader.SetBuffer(kernelIndex,"buff",cB);
    25.         fillShader.Dispatch(0,size/8,size/8,1); // threadgroups of 8
    26.  
    27.         cB.GetData(data);
    28.  
    29.         //tempTex.SetPixel(0, 0, new Color(1f, 0f, 0f, 0f)); // This DOES change the texture
    30.  
    31.         int l = 0;
    32.         foreach (var color32 in tempTex.GetPixels32())
    33.         {
    34.             Debug.Log(color32 + " " + data[l]); // all should return (2,2,2,2) and 1 if working properly
    35.             l++;
    36.         }
    37.     }
    38.  
    39. }
    40.  
    Code (CSharp):
    1. #pragma kernel CSMain
    2.  
    3. RWStructuredBuffer<int> buff;
    4. RWTexture2D<float4> Result;
    5. int bufferWidth;
    6.  
    7. float val = 1;
    8.  
    9. [numthreads(8,8,1)]
    10. void CSMain (uint3 id : SV_DispatchThreadID)
    11. {
    12.     Result[id.xy] = float4(val,val,val,val);
    13.     buff[id.y * bufferWidth + id.x] = 1;
    14. }
    The resulting log is nothing but (0,0,0,0) 1, meaning the texture wasn't set but the buffer was.
    What am I doing wrong? I tried it with an imported read/write enabled texture too, same results. None of the tutorials on compute shaders seem to mention anything special, so what am I missing?

    Thanks
     
  2. jvo3dc

    jvo3dc

    Joined:
    Oct 11, 2013
    Posts:
    1,520
    kiriri likes this.
  3. MD_Reptile

    MD_Reptile

    Joined:
    Jan 19, 2012
    Posts:
    2,664
    Why does it need to come back cpu side? You need to save it or something? If it has to come back cpu side it is slow, and might defeat the purpose of doing work on the gpu...
     
  4. kiriri

    kiriri

    Joined:
    Jan 14, 2011
    Posts:
    107
    It should go directly into a shader, but I wanted to debug it first. I assumed there was a bug where perhaps everything was fine.
    Using RenderTextures and copy via active works great, thank you.

    Edit : I assume you'd use Graphics.CopyTexture for Texture2DArrays
     
  5. npatch

    npatch

    Joined:
    Jun 26, 2015
    Posts:
    247
    If you want to debug them, use RenderDoc. Capture a frame and then go to the appropriate Dispatch call and check the output of the ComputeShader. No need to get them back to CPU side and dump them.
     
    MD_Reptile likes this.