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.

Bug Half fragment shader precision instead float on Oculus Quest2

Discussion in 'Shaders' started by moroc, Oct 18, 2022.

  1. moroc

    moroc

    Joined:
    Jan 20, 2014
    Posts:
    12
    I use a RenderTexture (ARGBFloat), Graphics.Blit and a shader to calculate world position.
    On Desktop build all works fine. But on the Quest (Android, vulkan) shader decreases precision of output to half instead float.
    I tried:
    1. Different sampler declarations:
    Texture2D<float4> _Position;
    SamplerState sampler_Position;
    or
    sampler2D_float _Position;
    or
    UNITY_DECLARE_TEX2D(_Position);
    2. #pragma fragmentoption ARB_precision_hint_nicest
    Nothing helps.

    Is it possible to force using float precision on Oculus Quest?
     
  2. aleksandrk

    aleksandrk

    Unity Technologies

    Joined:
    Jul 3, 2017
    Posts:
    2,659
    This should work fine.
    Can you share the whole shader?
     
  3. moroc

    moroc

    Joined:
    Jan 20, 2014
    Posts:
    12
    Hi, relevant code.
    Code (CSharp):
    1. positionBuffer_1 = new RenderTexture(width, height, 0, RenderTextureFormat.ARGBFloat);
    2. positionBuffer_1.filterMode = FilterMode.Point;
    3. positionBuffer_1.autoGenerateMips = false;
    4. positionBuffer_1.Create();
    5. ...//prepare material and assign texture
    6. Graphics.Blit(positionBuffer_1, positionBuffer_2, calculatePosition, 0);
    For testing purposes I use light version of shader wich simply return float4 with constant. I also tried with suffix f.

    Shader "GPUParticles/Internal/Position"
    {
    Properties
    {
    _Position("Position", 2D) = "white" {}
    }
    SubShader
    {
    Cull Off ZWrite Off ZTest Always
    Pass
    {
    CGPROGRAM
    #pragma vertex vert
    #pragma fragment frag

    #include "UnityCG.cginc"
    #include "../Includes/GPUParticles.cginc"

    sampler2D_float _Position;
    struct appdata
    {
    float4 vertex : POSITION;
    float2 uv : TEXCOORD0;
    };
    struct v2f
    {
    float2 uv : TEXCOORD0;
    float4 vertex : SV_POSITION;
    };
    v2f vert (appdata v)
    {
    v2f o;
    o.vertex = UnityObjectToClipPos(v.vertex);
    o.uv = v.uv;
    return o;
    }
    float4 frag (v2f i) : SV_Target
    {
    float4 pos = tex2D(_Position, i.uv);
    return float4(0.1f,500.12345f,500.12345f,1);
    }
    ENDCG
    }
    }
    }

    To check value in RenderTexture I use this code:
    Code (CSharp):
    1.         var textPoints = (RenderTexture)calculatePosition.GetTexture("_Position");
    2.         RenderTexture.active = textPoints;
    3.         Texture2D temp = new Texture2D(textPoints.width, textPoints.height, TextureFormat.RGBAFloat, false);
    4.         temp.Apply(false);
    5.         temp.ReadPixels(new Rect(0, 0, textPoints.width, textPoints.height), 0, 0);
    6.         temp.Apply(false);
    7.         RenderTexture.active = null;
    8.  
    9.         var positionArray = temp.GetPixels();
    10.         for(int i = 0; i < 10; i++)
    11.         {
    12.             Debug.Log($"Positions {positionArray[i]}");
    13.         }
    At desktop I get:
    Positions RGBA(0.100, 500.123, 500.123, 1.000)
    At device through Logcat:
    Positions RGBA(0.100, 500.000, 500.000, 1.000)
     
  4. aleksandrk

    aleksandrk

    Unity Technologies

    Joined:
    Jul 3, 2017
    Posts:
    2,659
    The shader code looks fine to me.
    Not sure about the C# part, though.
     
  5. moroc

    moroc

    Joined:
    Jan 20, 2014
    Posts:
    12
    If I change RenderTexture format on RenderTextureFormat.ARGBHalf, problem become reproducable on Desktop. I also tried UnityEngine.Experimental.Rendering.GraphicsFormat.R32G32B32A32_SFloat, no sense.
    From logcat I saw that device doesn't decrease texture precision and R32G32B32A32_SFloat is supported