Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Question AsyncGPUReadback w. ComputeShader in EditorWindow

Discussion in 'Shaders' started by MaxRoetzler, Dec 21, 2020.

  1. MaxRoetzler

    MaxRoetzler

    Joined:
    Jan 3, 2010
    Posts:
    136
    I'm trying to figure out the proper setup to run compute shaders from an editor window, but I must clearly be doing something wrong. The current setup usually runs for like a minute before the new texture is created in the project. (128x128 res, Unity 2020.2.0f1c1)

    Any hints on what is wrong with this setup?

    Editor Window
    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.Rendering;
    3. using UnityEditor;
    4. using System.IO;
    5.  
    6. public class ComputeTest : EditorWindow
    7. {
    8.     private Texture2D m_Input;
    9.     private Texture2D m_Output;
    10.     private RenderTexture m_RenderTexture;
    11.     private ComputeShader m_ComputeShader;
    12.  
    13.     private void OnGUI ()
    14.     {
    15.         m_ComputeShader = EditorGUILayout.ObjectField (new GUIContent ("Compute Shader"), m_ComputeShader, typeof (ComputeShader), false) as ComputeShader;
    16.         m_Input = EditorGUILayout.ObjectField (new GUIContent ("Input Texture"), m_Input, typeof (Texture2D), false) as Texture2D;
    17.         EditorGUILayout.Space ();
    18.  
    19.         if (GUILayout.Button ("Compute"))
    20.         {
    21.             if (m_Input == null)
    22.             {
    23.                 return;
    24.             }
    25.  
    26.             int size = m_Input.width;
    27.  
    28.             m_Output = new Texture2D (size, size, TextureFormat.ARGB32, false);
    29.             m_RenderTexture = new RenderTexture (size, size, 0, RenderTextureFormat.ARGB32)
    30.             {
    31.                 enableRandomWrite = true
    32.             };
    33.             m_RenderTexture.Create ();
    34.  
    35.             int kernel = m_ComputeShader.FindKernel ("CSMain");
    36.             m_ComputeShader.SetTexture (kernel, "Input", m_Input);
    37.             m_ComputeShader.SetTexture (kernel, "Output", m_RenderTexture);
    38.  
    39.             EditorUtility.DisplayProgressBar ("Compute", "Running Compute Shader", 0.5f);
    40.  
    41.             // Submit compute shader
    42.             m_ComputeShader.Dispatch (kernel,size/8, size/8, 1);
    43.             AsyncGPUReadback.Request (m_RenderTexture, 0, TextureFormat.ARGB32, OnCompleteReadback);
    44.         }
    45.     }
    46.  
    47.     private void OnCompleteReadback (AsyncGPUReadbackRequest request)
    48.     {
    49.         if (request.hasError)
    50.         {
    51.             Debug.Log ("GPU readback error detected.");
    52.             return;
    53.         }
    54.  
    55.         // Get output filepath
    56.         string filePath = AssetDatabase.GetAssetPath (m_Input);
    57.         string directory = Path.GetDirectoryName (filePath);
    58.         string extension = Path.GetExtension (filePath);
    59.         filePath = Path.Combine (directory, "Output" + extension);
    60.  
    61.         // Retrieve texture, save to disk
    62.         m_Output.LoadRawTextureData (request.GetData<uint>());
    63.         m_Output.Apply ();
    64.  
    65.         File.WriteAllBytes (filePath, ImageConversion.EncodeToTGA (m_Output));
    66.         DestroyImmediate (m_Output);
    67.  
    68.         // Update asset database
    69.         AssetDatabase.ImportAsset (filePath, ImportAssetOptions.ForceUpdate);
    70.         AssetDatabase.Refresh ();
    71.  
    72.         EditorUtility.ClearProgressBar ();
    73.     }
    74.  
    75.     [MenuItem ("Tools/ComputeTest")]
    76.     private static void Open ()
    77.     {
    78.         GetWindow<ComputeTest> ().Show ();
    79.     }
    80. }
    Compute Shader
    Code (CSharp):
    1. #pragma kernel CSMain
    2.  
    3. Texture2D<float4> Input;
    4. RWTexture2D<float4> Output;
    5.  
    6. [numthreads(8,8,1)]
    7. void CSMain (uint3 id : SV_DispatchThreadID)
    8. {
    9.     Output[id.xy] = 1.0f - Input[id.xy];
    10. }
     
  2. MaxRoetzler

    MaxRoetzler

    Joined:
    Jan 3, 2010
    Posts:
    136
    Seems like this was fixed since then, as it works fine now in Unity 2020.3.