コード例 #1
0
    /// <returns>(Overall areas, Unique areas)</returns>
    private (int total, int unique) getUniqueAreas(MyVector2 areaSizing, int spriteIndex, ConcurrentDictionary <string, MyArea> areas, IAreaEnumerator areaEnumerator, ProgressReport progressReport)
    {
        var areasTotal  = 0;
        var areasUnique = 0;

        areaEnumerator.EnumerateThroughSprite(areaSizing, spriteIndex, (sprite, index, x, y) =>
        {
            if (!_mapOfEmptiness.Contains(areaSizing, index, x, y))
            {
                var area = MyArea.CreateFromSprite(sprite, spriteIndex, x, y, areaSizing);
                var hash = area.UniqueString;
                if (areas.TryAdd(hash, area))
                {
                    areasUnique++;
                }
                area = areas[hash];

                area.Correlations.TryAdd(area.Correlations.Count, new MyAreaCoordinates(index, x, y, areaSizing.X, areaSizing.Y));

                areasTotal++;
            }
        });
        progressReport.OperationsDone++;
        return(areasTotal, areasUnique);
    }
コード例 #2
0
    private ConcurrentDictionary <string, MyArea> getAllAreas(MyColor[][][] sprites, IEnumerable <MyVector2> areaSizings, IAreaEnumerator areaEnumerator, ProgressReport progressReport)
    {
        var areas = new ConcurrentDictionary <string, MyArea>();

        var overallOpsCount = areaSizings.Count() * sprites.Length;

        progressReport.OperationDescription = "Fetching possible areas";
        progressReport.OperationsCount      = overallOpsCount;
        progressReport.OperationsDone       = 0;

        var sizingsList = areaSizings.ToList();

        var allAreas    = 0;
        var uniqueAreas = 0;

        try
        {
            Parallel.For(0, overallOpsCount, (int index, ParallelLoopState state) =>
            {
                if (state.IsExceptional)
                {
                    Debug.Log("Exception!");
                }
                if (_ct.IsCancellationRequested)
                {
                    state.Break();
                }
                var sizingIndex = Mathf.FloorToInt(index / sprites.Length);
                var spriteIndex = index - sizingIndex * sprites.Length;
                if (sizingIndex > sizingsList.Count - 1)
                {
                    Debug.LogError($"sizingsList[sizingIndex] is out of range! sizingIndex = {sizingIndex}, sizingsList.Count = {sizingsList.Count}");
                }
                if (sizingIndex < 0)
                {
                    Debug.LogError($"sizingIndex < 0! ({sizingIndex})");
                }
                var targetSizing = sizingsList[sizingIndex];
                var spritesAreas = getUniqueAreas(targetSizing, spriteIndex, areas, areaEnumerator, progressReport);
                allAreas        += spritesAreas.total;
                uniqueAreas     += spritesAreas.unique;
            });
        }
        catch (AggregateException ae)
        {
            Debug.Log("catch");
            ae.Handle((inner) =>
            {
                Debug.LogError($"{inner.Message}\r\n\r\n{inner.StackTrace}");
                return(true);
            });
        }
        return(areas);
    }
コード例 #3
0
    public Task <ConcurrentDictionary <string, MyArea> > FetchAreas(MyColor[][][] sprites, IEnumerable <MyVector2> areaSizings, IAreaEnumerator areaEnumerator, ProgressReport progressReport)
    {
        var result = Task.Run(() => getAllAreas(sprites, areaSizings, areaEnumerator, progressReport));

        return(result);
    }
コード例 #4
0
    /*
     * Ок, мы хотим создать задания - пройтись каждой уникальной областью по всем спрайтам. Чтобы получить уникальные области - возможно тоже придется
     * выкручиваться с помощью шейдеров. Но пока можно и тупо пройтись процессором.
     *
     * Значит, что нам надо сделать - пройтись по всем спрайтам, составить список всех уникальных областей всех размеров во всех спрайтах. Затем надо сложить
     * инжу о них в буффер так, чтобы на каждом пикселе находилась инфа о том, где находится эта область, т.е. x, y, width, height вместо r, g, b, a. Дальше
     * шейдер идут туда забираер эту область и проходится с ней по всем спрайтам, считает счет и пишет его в соответствующую клетку резултирующего буффера.
     */

    Task <ConcurrentDictionary <string, MyArea> > IAreaFetcher.FetchAreas(MyColor[][][] sprites, IEnumerable <MyVector2> areaSizings, IAreaEnumerator areaEnumerator, ProgressReport progressReport)
    {
        return(Task.Run(() =>
        {
            if (!_mapOfEmptinessInitialized)
            {
                Debug.LogError($"map estimation start");
                foreach (var area in areaSizings)
                {
                    var currentMapOfEmptiness = new bool[sprites.Length][][];
                    for (int j = 0; j < sprites.Length; j++)
                    {
                        var sprite = sprites[j];
                        var spriteMapOfEmptiness = new bool[sprite.Length - area.X][];
                        for (int x = 0; x < sprite.Length - area.X; x++)
                        {
                            spriteMapOfEmptiness[x] = new bool[sprite[x].Length - area.Y];
                            for (int y = 0; y < sprite[x].Length - area.Y; y++)
                            {
                                spriteMapOfEmptiness[x][y] = !MyArea.ContainsOpaquePixels(sprite, x, y, area);
                            }
                        }
                        currentMapOfEmptiness[j] = spriteMapOfEmptiness;
                    }
                    _mapOfEmptiness.Add(area, currentMapOfEmptiness);
                }
                _mapOfEmptinessInitialized = true;
                Debug.LogError($"map estimation end");
            }

            var result = new ConcurrentDictionary <string, MyArea>(); //Тут мы храним все уникальные области по их хешам
            var overallOpsCount = areaSizings.Count() * sprites.Length;
            var areasArray = areaSizings.ToArray();

            progressReport.OperationsCount = overallOpsCount;

            try
            {
                Parallel.For(0, overallOpsCount, (int index, ParallelLoopState state) =>
                {
                    if (state.IsExceptional)
                    {
                        Debug.Log("Exception!");
                    }
                    var areaVariantIndex = Mathf.FloorToInt(index / sprites.Length);
                    var spriteIndex = index - areaVariantIndex * sprites.Length;
                    var targetArea = areasArray[areaVariantIndex];
                    var mapOfEmptinessForAreaAndSprite = _mapOfEmptiness[targetArea][spriteIndex];
                    getUniqueAreas(targetArea, spriteIndex, sprites[spriteIndex], result, mapOfEmptinessForAreaAndSprite, progressReport);
                });
            }
            catch (AggregateException ae)
            {
                Debug.Log("catch");
                ae.Handle((inner) =>
                {
                    Debug.Log(inner.Message);
                    return true;
                });
            }

            Debug.Log($"unique areas count = {result.Count}");
            return result;
        }));

        //var algorythmKernel = _computeShader.FindKernel("CSMain");

        //var (groupSizeX, groupSizeY, groupSizeZ) = _computeShader.GetKernelThreadGroupSizes(algorythmKernel);
        //var gpuDataChunks = sprites.PrepareChunksForGpu(groupSizeX, groupSizeY, groupSizeZ);
        //for (int i = 0; i < gpuDataChunks.Length; i++)
        //{
        //    var chunk = gpuDataChunks[i];
        //    _computeShader.SetInt("MultipliedValue", chunk.MultipliedPart);
        //    _computeShader.SetInt("SpriteWidth", chunk.SpriteWidth);
        //    _computeShader.SetInt("SpriteHeight", chunk.SpriteHeight);
        //    _computeShader.SetInt("PreferredAreaWidth", 27);
        //    _computeShader.SetInt("PreferredAreaHeight", 27);
        //    _computeShader.SetBuffer(algorythmKernel, "SpriteBuffer", chunk.SpriteBuffer);
        //    _computeShader.SetBuffer(algorythmKernel, "ResultBuffer", chunk.ResultBuffer);
        //    _computeShader.Dispatch(algorythmKernel, chunk.GroupsCountX, chunk.GroupsCountY, chunk.GroupsCountZ);
        //    chunk.FetchResults();
        //    chunk.Dispose();

        //    var textureBefore = chunk.OriginalSprite.ToTexture2D();
        //    var textureAfter = chunk.Result.ToTexture2D();
        //    File.WriteAllBytes($@"C:\results\{i.ToString()}-before.png", textureBefore.EncodeToPNG());
        //    File.WriteAllBytes($@"C:\results\{i.ToString()}-after.png", textureAfter.EncodeToPNG());
        //    UnityEngine.Object.DestroyImmediate(textureBefore);
        //    UnityEngine.Object.DestroyImmediate(textureAfter);
        //}

        //Здесь что-то делаем с этими данными

        throw new System.NotImplementedException();
    }
コード例 #5
0
    Task <ConcurrentDictionary <int, MyArea> > FetchAreasLegacy(MyColor[][][] sprites, IEnumerable <MyVector2> areaSizings, IAreaEnumerator areaEnumerator, ProgressReport progressReport)
    {
        var algorythmKernel = _computeShaderLegacy.FindKernel("CSMain");

        var(groupSizeX, groupSizeY, groupSizeZ) = _computeShaderLegacy.GetKernelThreadGroupSizes(algorythmKernel);
        var gpuDataChunks = sprites.PrepareChunksForGpuLegacy(groupSizeX, groupSizeY, groupSizeZ);

        for (int i = 0; i < gpuDataChunks.Length; i++)
        {
            var chunk = gpuDataChunks[i];
            _computeShaderLegacy.SetInt("MultipliedValue", chunk.MultipliedPart);
            _computeShaderLegacy.SetInt("SpriteWidth", chunk.SpriteWidth);
            _computeShaderLegacy.SetInt("SpriteHeight", chunk.SpriteHeight);
            _computeShaderLegacy.SetInt("PreferredAreaWidth", 27);
            _computeShaderLegacy.SetInt("PreferredAreaHeight", 27);
            _computeShaderLegacy.SetBuffer(algorythmKernel, "SpriteBuffer", chunk.SpriteBuffer);
            _computeShaderLegacy.SetBuffer(algorythmKernel, "ResultBuffer", chunk.ResultBuffer);
            _computeShaderLegacy.Dispatch(algorythmKernel, chunk.GroupsCountX, chunk.GroupsCountY, chunk.GroupsCountZ);
            chunk.FetchResults();
            chunk.Dispose();

            var textureBefore = chunk.OriginalSprite.ToTexture2D();
            var textureAfter  = chunk.Result.ToTexture2D();
            File.WriteAllBytes($@"C:\results\{i.ToString()}-before.png", textureBefore.EncodeToPNG());
            File.WriteAllBytes($@"C:\results\{i.ToString()}-after.png", textureAfter.EncodeToPNG());
            UnityEngine.Object.DestroyImmediate(textureBefore);
            UnityEngine.Object.DestroyImmediate(textureAfter);
        }

        //Здесь что-то делаем с этими данными

        throw new System.NotImplementedException();
    }
コード例 #6
0
 internal async Task Initialize(IEnumerable <MyVector2> areaSizings, MyColor[][][] sprites, IAreaEnumerator enumerator)
 {
     var sizingsList = areaSizings.ToList();
     await Task.Run(() =>
     {
         Parallel.For(0, sizingsList.Count, i =>
         {
             var sizing        = sizingsList[i];
             var newSizingDict = new ConcurrentDictionary <int, List <int> >();
             _mapOfEmptiness.AddOrUpdate(sizing, newSizingDict, (_, __) => newSizingDict);
             Parallel.For(0, sprites.Length, j =>
             {
                 var newSpriteDict = new List <int>();
                 newSizingDict.AddOrUpdate(j, newSpriteDict, (_, __) => newSpriteDict);
                 enumerator.EnumerateThroughSprite(sizing, j, (sprite, spriteIndex, x, y) =>
                 {
                     var area = MyArea.CreateFromSprite(sprite, spriteIndex, x, y, sizing);
                     if (area.OpaquePixelsCount == 0)
                     {
                         newSpriteDict.Add(x + y *_yMultiplier);
                     }
                 });
             });
         });
     });
 }