Search Unity

Stream Out for Geometry Shader

Discussion in 'Shaders' started by musashi917, Apr 22, 2013.

  1. musashi917

    musashi917

    Joined:
    Jan 6, 2013
    Posts:
    19
    Hello
    I just wanted to know if we are able to use Stream Output stage of the pipeline in Unity to read back the geometry generated by the Geometry Shader on the CPU, or to resend it for another pass on the GPU. If someone already tried this, a little example on how to declare everything could be useful as I cant find any doc on this ;)
     
    Last edited: Apr 24, 2013
  2. Pyromuffin

    Pyromuffin

    Joined:
    Aug 5, 2012
    Posts:
    85
    Here's an example pass from the examples Aras posted a while back.
    Hope this helps. If it's unclear, outStream.RestartStrip() starts a new strip (allowing for unconnected triangles to be output).
    There is also the simple billboard shader, that I found on the forums as well. It might be a simpler example.

    Hope this helps!

    Code (csharp):
    1. Pass {
    2.  
    3.     ZWrite Off ZTest Always Cull Off Fog { Mode Off }
    4.     Blend SrcAlpha One
    5.  
    6.     CGPROGRAM
    7.     #pragma target 5.0
    8.  
    9.     #pragma vertex vert
    10.     #pragma geometry geom
    11.     #pragma fragment frag
    12.  
    13.     #include "UnityCG.cginc"
    14.  
    15.     StructuredBuffer<float2> pointBuffer;
    16.  
    17.     struct vs_out {
    18.         float4 pos : SV_POSITION;
    19.     };
    20.  
    21.     vs_out vert (uint id : SV_VertexID)
    22.     {
    23.         vs_out o;
    24.         o.pos = float4(pointBuffer[id] * 2.0 - 1.0, 0, 1);
    25.         return o;
    26.     }
    27.  
    28.     struct gs_out {
    29.         float4 pos : SV_POSITION;
    30.         float2 uv : TEXCOORD0;
    31.     };
    32.  
    33.     float _Size;
    34.  
    35.     [maxvertexcount(4)]
    36.     void geom (point vs_out input[1], inout TriangleStream<gs_out> outStream)
    37.     {
    38.         float dx = _Size;
    39.         float dy = _Size * _ScreenParams.x / _ScreenParams.y;
    40.         gs_out output;
    41.         output.pos = input[0].pos + float4(-dx, dy,0,0); output.uv=float2(0,0); outStream.Append (output);
    42.         output.pos = input[0].pos + float4( dx, dy,0,0); output.uv=float2(1,0); outStream.Append (output);
    43.         output.pos = input[0].pos + float4(-dx,-dy,0,0); output.uv=float2(0,1); outStream.Append (output);
    44.         output.pos = input[0].pos + float4( dx,-dy,0,0); output.uv=float2(1,1); outStream.Append (output);
    45.         outStream.RestartStrip();
    46.     }
    47.  
    48.     sampler2D _Sprite;
    49.     fixed4 _Color;
    50.  
    51.     fixed4 frag (gs_out i) : COLOR0
    52.     {
    53.         fixed4 col = tex2D (_Sprite, i.uv);
    54.         return _Color * col;
    55.     }
    56.  
    57.     ENDCG
    58.  
    59. }
    60.  
    61. }

    billboard shader:
    Code (csharp):
    1. Shader "Custom/GS Billboard"
    2. {
    3.     Properties
    4.     {
    5.         _SpriteTex ("Base (RGB)", 2D) = "white" {}
    6.         _Size ("Size", Range(0, 3)) = 0.5
    7.     }
    8.  
    9.     SubShader
    10.     {
    11.         Pass
    12.         {
    13.             Tags { "RenderType"="Opaque" }
    14.             LOD 200
    15.        
    16.             CGPROGRAM
    17.                 #pragma target 5.0
    18.                 #pragma vertex VS_Main
    19.                 #pragma fragment FS_Main
    20.                 #pragma geometry GS_Main
    21.                 #include "UnityCG.cginc"
    22.  
    23.                 // **************************************************************
    24.                 // Data structures                                              *
    25.                 // **************************************************************
    26.                 struct GS_INPUT
    27.                 {
    28.                     float4  pos     : POSITION;
    29.                     float3  normal  : NORMAL;
    30.                     float2  tex0    : TEXCOORD0;
    31.                 };
    32.  
    33.                 struct FS_INPUT
    34.                 {
    35.                     float4  pos     : POSITION;
    36.                     float2  tex0    : TEXCOORD0;
    37.                 };
    38.  
    39.  
    40.                 // **************************************************************
    41.                 // Vars                                                         *
    42.                 // **************************************************************
    43.  
    44.                 float _Size;
    45.                 float4x4 _VP;
    46.                 Texture2D _SpriteTex;
    47.                 SamplerState sampler_SpriteTex;
    48.  
    49.                 // **************************************************************
    50.                 // Shader Programs                                              *
    51.                 // **************************************************************
    52.  
    53.                 // Vertex Shader ------------------------------------------------
    54.                 GS_INPUT VS_Main(appdata_base v)
    55.                 {
    56.                     GS_INPUT output = (GS_INPUT)0;
    57.  
    58.                     output.pos =  mul(_Object2World, v.vertex);
    59.                     output.normal = v.normal;
    60.                     output.tex0 = float2(0, 0);
    61.  
    62.                     return output;
    63.                 }
    64.  
    65.  
    66.  
    67.                 // Geometry Shader -----------------------------------------------------
    68.                 [maxvertexcount(4)]
    69.                 void GS_Main(point GS_INPUT p[1], inout TriangleStream<FS_INPUT> triStream)
    70.                 {
    71.                     float3 up = float3(0, 1, 0);
    72.                     float3 look = _WorldSpaceCameraPos - p[0].pos;
    73.                     look.y = 0;
    74.                     look = normalize(look);
    75.                     float3 right = cross(up, look);
    76.                    
    77.                     float halfS = 0.5f * _Size;
    78.                            
    79.                     float4 v[4];
    80.                     v[0] = float4(p[0].pos + halfS * right - halfS * up, 1.0f);
    81.                     v[1] = float4(p[0].pos + halfS * right + halfS * up, 1.0f);
    82.                     v[2] = float4(p[0].pos - halfS * right - halfS * up, 1.0f);
    83.                     v[3] = float4(p[0].pos - halfS * right + halfS * up, 1.0f);
    84.  
    85.                     float4x4 vp = mul(UNITY_MATRIX_MVP, _World2Object);
    86.                     FS_INPUT pIn;
    87.                     pIn.pos = mul(vp, v[0]);
    88.                     pIn.tex0 = float2(1.0f, 0.0f);
    89.                     triStream.Append(pIn);
    90.  
    91.                     pIn.pos =  mul(vp, v[1]);
    92.                     pIn.tex0 = float2(1.0f, 1.0f);
    93.                     triStream.Append(pIn);
    94.  
    95.                     pIn.pos =  mul(vp, v[2]);
    96.                     pIn.tex0 = float2(0.0f, 0.0f);
    97.                     triStream.Append(pIn);
    98.  
    99.                     pIn.pos =  mul(vp, v[3]);
    100.                     pIn.tex0 = float2(0.0f, 1.0f);
    101.                     triStream.Append(pIn);
    102.                 }
    103.  
    104.  
    105.  
    106.                 // Fragment Shader -----------------------------------------------
    107.                 float4 FS_Main(FS_INPUT input) : COLOR
    108.                 {
    109.                     return _SpriteTex.Sample(sampler_SpriteTex, input.tex0);
    110.                 }
    111.  
    112.             ENDCG
    113.         }
    114.     }
    115. }
    116.  
     
    deus0 and paskal007r like this.
  3. musashi917

    musashi917

    Joined:
    Jan 6, 2013
    Posts:
    19
    Thanks for your answer Pyromuffin! I was refering more specifically to the stream output stage of the pipeline as described here
    This a step of the pipeline where you can read back on the CPU the data generated by the geometry shader - it can be useful to generate static geometry on the GPU.
    I would like to know the syntax to setup this more on Unity application side. There is no documentation at all on geo shader, so I am not even not sure if we can do that. :neutral:
     
  4. Pyromuffin

    Pyromuffin

    Joined:
    Aug 5, 2012
    Posts:
    85
    ah, I see. My mistake. My best guess would be to put it into a (append)structured buffer and then use getData() to read it into an array on the CPU side, though it doesn't seem to utilize that specific feature, it would accomplish close to the same thing.
     
  5. musashi917

    musashi917

    Joined:
    Jan 6, 2013
    Posts:
    19
    Yes I used a compute shader and getData() on a compute buffer as a backup for now ;) . Not sure how it compares in term of speed to the real solution though.
     
  6. Pyromuffin

    Pyromuffin

    Joined:
    Aug 5, 2012
    Posts:
    85
    can you not use structured buffers in the geometry shader? It looks like the append buffer is not allowed, but a regular structured buffer is. maybe using it with the primitive ID as index?
     
  7. musashi917

    musashi917

    Joined:
    Jan 6, 2013
    Posts:
    19
    Are you sure that you can use a RW Structured Buffer in a geo shader ? Arent those reserved to pixel or compute shader ?
     
  8. Pyromuffin

    Pyromuffin

    Joined:
    Aug 5, 2012
    Posts:
    85
    Ah, you're right again! I feel dumb. Indeed, all of the write-enabled objects are reserved for pixel or compute shaders. Given that limitation, the only way to do this with the geometry shader is to get access to the steam-output stage, like you requested. Hah, I'm sorry I couldn't help you, but at least I learned something new!

    Maybe try to get the attention of some unity staff?

    Thanks again!
     
  9. musashi917

    musashi917

    Joined:
    Jan 6, 2013
    Posts:
    19
    No pb and thanks for answering !
    Ok I will try to rename my post it might not be very clear ...
     
  10. DeanNorth

    DeanNorth

    Joined:
    May 15, 2015
    Posts:
    4
    I need to use the stream out shader stage too. Is this possible in Unity 5 yet?
     
  11. gaiomed

    gaiomed

    Joined:
    May 5, 2013
    Posts:
    48
    Would need this feature too, any news dear unity staff...
     
    Desoxi likes this.
  12. drcrck

    drcrck

    Joined:
    May 23, 2017
    Posts:
    328
    Still not available, right?