/// <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); }
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); }
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); }
/* * Ок, мы хотим создать задания - пройтись каждой уникальной областью по всем спрайтам. Чтобы получить уникальные области - возможно тоже придется * выкручиваться с помощью шейдеров. Но пока можно и тупо пройтись процессором. * * Значит, что нам надо сделать - пройтись по всем спрайтам, составить список всех уникальных областей всех размеров во всех спрайтах. Затем надо сложить * инжу о них в буффер так, чтобы на каждом пикселе находилась инфа о том, где находится эта область, т.е. 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(); }
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(); }
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); } }); }); }); }); }