Передача байтового массива в PixelShaderEffect
Я быстро анимирую изображения из файла на основе нестандартного пиксельного формата в приложении C#/UWP/Win2D. Между изображениями есть корреляция (подумайте, анимация флипбука), но ничего программного.
Я написал прототип и включил соответствующий код ниже. Цвета "Белый" и "Черный" будут в конечном итоге преобразованы в таблицу соответствия цветов (например, 5 = Белый)
....
//Create render target in function elsewhere
CanvasRenderTarget crt = new CanvasRenderTarget(Sender, FrameWidth, FrameHeight, defaultDpi);
GenerateNextFrame(crt);
....
private void GenerateNextFrame(CanvasRenderTarget frame)
{
var frameSize = FrameHeight * FrameWidth * sizeof(ushort);
var frameBytes = new byte[frameSize];
var frameShorts = new ushort[FrameWidth * FrameHeight];
var colors = new Color[FrameWidth * FrameHeight];
var white = Colors.White;
var black = Colors.Black;
var comp = (ushort.MaxValue / 2);
//read bytes from file
FrameFileStream.AsStreamForRead().Read(frameBytes, 0, frameSize);
//convert bytes to shorts
System.Buffer.BlockCopy(frameBytes, 0, frameShorts, 0, frameSize);
//convert shorts to colors
for (var i = 0; i < colors.Length; i++)
{
colors[i] = (frameShorts[i] < comp) ? white : black;
}
//set colors on frame
frame.SetPixelColors(colors);
}
Производительность составляет ~60 кадров в секунду с FrameWidth/FrameHeight 512, но падает до ~30 кадров в секунду в 1024. Все, что больше, работает еще хуже.
Профилирование этого с большими данными показывает, что узким местом являются циклический массив цветов и вызовы SetPixelColors.
Я пробовал несколько методов, чтобы ускорить это (PLINQ, Parallel.ForEach, предварительная постановка данных в очередь), но не смог получить его быстрее, чем в приведенной выше форме.
Я считаю, что правильный способ справиться с этим - создать новый поддерживаемый тип DirectXPixelFormat для CanvasRenderTarget, чтобы я мог просто использовать SetPixelBytes. Это кажется невозможным.
Следующая правильная опция, кажется, пишет PixelShaderEffect, который принимает frameBytes, создает пиксели в оттенках серого, а затем использует их в качестве источника другого эффекта для установки цвета.
Я не смог найти никаких примеров создания IGraphicsEffectSource.
Будем весьма благодарны за любые советы, документацию или, что лучше всего, за работающее "так вы передаете байтовый массив в PixelShaderEffect".