[Solved] Custom shader bug on macOS (High Sierra)

Solved. The problem was with Graphics.CopyTexture() function which is for some reason unsupported in High Sierra on OpenGL.

I changed it to SetPixels32():

       for (int i = 0; i < unitTextures.Length; i++)
           unitTextureArray.SetPixels32(unitTextures[i].GetPixels32(0), i, 0);

       unitTextureArray.Apply();

Not sure if I should ask it here or in OSX subforum.

Some user has trouble with my game, he has black textures. His specs (it doesn’t support Apple Metal API, if that matters):

We tested it on Mojave and it was good there.

Log file from High Sierra looks fine. There are some versions what it could be: textures, prefabs, lights or custom shader. And as long as I am pretty noob at writing shaders (also I wrote one long ago), I am pretty sure it causes the bug. It also seems that black textures are on only objects that use that shader. It is also pretty short and simple, but I have no clue how to fix it. I made it to be able to use GPU instancing with multiple textures.

Shader "SeekSick6/Unit" {
    Properties {
        _Textures("Textures", 2DArray) = "" {}
        _Glossiness("Smoothness", Range(0, 1)) = 1
        _Metallic("Metallic", Range(0, 1)) = 0
    }
    SubShader {
        Tags { "RenderType"="Opaque" }
        LOD 200
 
        CGPROGRAM
        // Physically based Standard lighting model, and enable shadows on all light types
        #pragma surface surf Standard fullforwardshadows

        // Use shader model 3.0 target, to get nicer looking lighting
        #pragma target 3.5
        #include "UnityCG.cginc"

        // Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader.
        // See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing.
        #pragma instancing_options assumeuniformscaling

        UNITY_DECLARE_TEX2DARRAY(_Textures);
 
        struct Input
        {
            float2 uv_Textures;
        };

        half _Glossiness;
        half _Metallic;

        UNITY_INSTANCING_BUFFER_START(Props)
            UNITY_DEFINE_INSTANCED_PROP(float, _TextureIndex)
        #define _TextureIndex_arr Props
        UNITY_INSTANCING_BUFFER_END(Props)

        void surf (Input IN, inout SurfaceOutputStandard o)
        {
            fixed4 c = UNITY_SAMPLE_TEX2DARRAY(_Textures, float3(IN.uv_Textures, UNITY_ACCESS_INSTANCED_PROP(_TextureIndex_arr, _TextureIndex)));
            o.Albedo = c.rgb;
            o.Metallic = _Metallic;
            o.Smoothness = _Glossiness;
            o.Alpha = c.a;
        }
        ENDCG
    }
    FallBack "Diffuse"
}

His log, just in case:

How it should be:

How it is (BTW it seems objects receive light):

Works here on 10.13.6, using Metal or OpenGL, so you can rule out it being High Sierra-specific anyway.

–Eric

1 Like

Interesting… Maybe it is hardware… But he said all other games (including ones using Unity) are fine, the problem only with this one specifically.

I’ve added 2 builds and screenshots in main post, could you check if you have black textures or not (maybe at least first build, “MacOS (2018.2.12f1)”, as it was original build).

I tried the first build, but it seems to have some Steam dependency and won’t launch. I assume the “receiving light” thing is because of FallBack “Diffuse”.

–Eric

Either “steam_appid.txt” must be placed somewhere else or Steam must be running.

Anyway, I’ve updated archives.

It launches Steam, but the game itself closes. I’ll take another look if you have a non-Steam build, but otherwise this is getting a little too involved. Sorry I can’t be of more help.

–Eric

1 Like

iMac 21.5 inch, Mid 2011 (A1311), whatever it means.

You can’t really run out of texture memory. With OpenGL, it’s virtualized, so if it doesn’t fit in VRAM, it’s swapped out with main memory. The worst that happens is things get slow. Also 512MB of VRAM, though smallish by 2019 standards, is wayyyyyyy more than enough. Plus even if it was possible, it would be random, and not always affect one specific shader.

–Eric

1 Like

No, it’s definitely true, and there’s a 0% chance this has anything to do with VRAM. Otherwise games would mysteriously have missing textures constantly and that simply never happens. As mentioned above, it looks like the shader isn’t working at all and is using the fallback.

–Eric

1 Like

Can you please download any of those archives and try to run now? They should work as they worked on user’s Mac (still with bug though).

So my guess is that his Mac doesn’t support GPU instancing for some reason. Question is how can I extend this shader so it would support both cases? I change textures by script:

    [SerializeField] Material unitMaterial = null;
    Dictionary<Elements, int> typeIndices = new Dictionary<Elements, int>();
    Texture2DArray unitTextureArray = null;

...

    void OnEnable()
   {
        // Load cube nets.
        Texture2D[] unitTextures = Resources.LoadAll<Texture2D>("Unit textures");
        unitTextureArray = new Texture2DArray(unitTextures[0].width, unitTextures[0].height, unitTextures.Length, unitTextures[0].format, true);

        for (int i = 0; i < unitTextures.Length; i++)
        {
            typeIndices[(Elements)System.Enum.Parse(typeof(Elements), unitTextures[i].name.Split(new char[] { ' ' }, System.StringSplitOptions.RemoveEmptyEntries)[0])] = i;
            Graphics.CopyTexture(unitTextures[i], 0, unitTextureArray, i);
        }

        unitMaterial.SetTexture("_Textures", unitTextureArray);
    }

    void SetUnitTexture(MeshRenderer mr, Elements type)
    {
        MaterialPropertyBlock props = new MaterialPropertyBlock();
        props.SetFloat("_TextureIndex", typeIndices[type]);
        mr.SetPropertyBlock(props);
    }

Would be really cool to keep the script unchanged.

I found this:

BTW, in the latest version this description is different:

Not sure if it is what I need but seems like it is. Though I am too sleepy now to understand things… Any ideas are welcome!

Seems to be the same file; it just starts Steam and quits.

–Eric

1 Like

Oops, yes, sorry, my bad. I thought it just reuses links like other clouds do. I now updated links.

Nope, sorry, same thing. I’ll take a look if the Steam stuff is disabled, since it’s preventing the app from running.

–Eric

I also realized he used the first version and it worked. Maybe player just has to have the game on his account to be able to play…

So I changed LOD to 100, added #pragma multi_compile_instancing, and made 4 builds:

  • With no fallback
  • With diffuse fallback
  • With specular fallback
  • With defuse fallback and no GPU instancing

In all cases textures are still black. I have no idea what can be done else… Maybe I can add some string for debug to tell where it fails?

OK, some new info. The user was randomly, while trying to grab a screenshot, was getting red (#FF0000) screenshot instead during testing those 4 builds.

So I made development build and got log from it. I see there:

Full log:

Should I create new thread or perhaps bug report?

Update: I tested it on Windows and got the same warnings, so it’s unrelated.

I’ve updated build link in main post, should work without Steam now. I’ve also added 2 planes, one is just with texture, second plane takes texture from Texture2DArray:

        Texture2D testTex = new Texture2D(unitTextures[0].width, unitTextures[0].height, TextureFormat.ARGB32, true);
        testTex.SetPixels32(unitTextureArray.GetPixels32(7));
        testTex.Apply();
        fromCode.material.mainTexture = testTex;

Both planes use standard shader.