Texture application to terrain too heavy

Im working on a script that applies textures to terrain on realtime but its laggy as hell although i used compute shaders. Is there any optimization i can do?

Script
Compute Shader
Profiler

The GPU → CPU conversion is the killer here, no surprise. It looks like you generate the data on the GPU, pull it back (slow) and convert it to a texture, then take the pixels from the texture and fill out the alphamap array, then send that to the terrain as a new alphamap (which means another CPU->GPU conversion).

If you can keep the work in rendertextures instead, CopyActiveRenderTextureToHeightmap() and CopyActiveRenderTextureToTexture() will be faster than going GPU->CPU->GPU as you’re doing now. This thread might be a good reference for using a compute shader to populate splatmaps

Thanks for the help! I altered the main function to this, but doesnt work correctly and there is still lag:

    public void Paint()
    {
        if (terrainLayers == null || terrainData.terrainLayers.Length != 3)
            InitializeTerrainLayers();

        if (!texturesInitialized)
            InitializeTextures();

        UpdateHeightmapTexture();
        UpdateTerrainLayerTiling();

        // Set up the compute shader
        int kernelHandle = textureApplierShader.FindKernel("CSMain");

        textureApplierShader.SetTexture(kernelHandle, "Result", splatmapRT);
        textureApplierShader.SetTexture(kernelHandle, "HeightMap", heightmapTexture);
        textureApplierShader.SetFloat("slopeThreshold", slopeThreshold);
        textureApplierShader.SetFloat("highAltitudeThreshold", 1 - highAltitudeThreshold);
        textureApplierShader.SetFloat("slopeBlendRange", slopeBlendRange);
        textureApplierShader.SetFloat("altitudeBlendRange", altitudeBlendRange);
        textureApplierShader.SetFloat("terrainHeight", terrainData.size.y);
        textureApplierShader.SetFloat("lowestPoint", Utilities.LowestPoint(Terrain.activeTerrain));
        textureApplierShader.SetFloat("highestPoint", Utilities.HighestPoint(Terrain.activeTerrain));

        // Dispatch the compute shader
        textureApplierShader.Dispatch(kernelHandle, terrainData.alphamapWidth / 8, terrainData.alphamapHeight / 8, 1);

        // Set the active render texture
        RenderTexture previousActive = RenderTexture.active;
        RenderTexture.active = splatmapRT;

        // Apply the splatmap directly to the terrain
        try
        {
            RectInt sourceRect = new RectInt(0, 0, splatmapRT.width, splatmapRT.height);
            Vector2Int destPos = new Vector2Int(0, 0);
            terrainData.CopyActiveRenderTextureToTexture(
                TerrainData.AlphamapTextureName,  // dest
                0,                                // mipLevel
                sourceRect,                       // sourceRect
                destPos,                          // destPos
                false                             // allowDelayedCPUSync
            );

            // Force the terrain to update
            Terrain.activeTerrain.Flush();
        }
        finally
        {
            // Restore the previous active render texture
            RenderTexture.active = previousActive;
        }
    }