【发布时间】:2020-02-06 16:21:21
【问题描述】:
我没有使用 SIMD 的经验,但是有一种方法太慢了。我知道获得 40fps,我需要更多。 有谁知道我怎样才能使这种绘画方法更快?也许 SIMD 指令是一种解决方案?
sourceData 现在是 byte[] (videoBytes) 但也可以使用指针。
public bool PaintFrame(IntPtr layerBuffer, ushort vStart, byte vScale)
{
for (ushort y = 0; y < height; y++)
{
ushort eff_y = (ushort)(vScale * (y - vStart) / 128);
var newY = tileHeight > 0 ? eff_y % tileHeight : 0;
uint y_add = (uint)(newY * tileWidth * bitsPerPixel >> 3);
for (int x = 0; x < width; x++)
{
var newX = tileWidth > 0 ? x % tileWidth : 0;
ushort x_add = (ushort)(newX * bitsPerPixel >> 3);
uint tile_offset = y_add + x_add;
byte color = videoBytes[tile_offset];
var colorIndex = BitsPerPxlCalculation(color, newX);
// Apply Palette Offset
if (paletteOffset > 0)
colorIndex += paletteOffset;
var place = x + eff_y * width;
Marshal.WriteByte(layerBuffer + place, colorIndex);
}
}
return true;
}
private void UpdateBitPerPixelMethod()
{
// Convert tile byte to indexed color
switch (bitsPerPixel)
{
case 1:
BitsPerPxlCalculation = (color, newX) => color;
break;
case 2:
BitsPerPxlCalculation = (color, newX) => (byte)(color >> 6 - ((newX & 3) << 1) & 3);
break;
case 4:
BitsPerPxlCalculation = (color, newX) => (byte)(color >> 4 - ((newX & 1) << 2) & 0xf);
break;
case 8:
BitsPerPxlCalculation = (color, newX) => color;
break;
}
}
更多信息
根据设置,可以更改 bpp。索引颜色和调色板颜色分开存储。这里我必须重新创建图像像素索引,所以稍后我使用 WPF(Windows) 或 SDL(Linux, Mac) 中的调色板和颜色索引来显示图像。
vStart 是在顶部裁剪图像的能力。
UpdateBitPerPixelMethod() 在帧渲染期间不会改变,只会在之前改变。在for期间,不能更改任何设置数据。
所以我希望某些部分可以用 SIMD 编写,因为所有像素的过程都是相同的。
【问题讨论】:
-
Marshal.WriteByte一定是一个瓶颈,因为它被调用了数百万次。您可以尝试减少Marshall.*调用,例如使用一个Marshal.Copy而不是一百万个Marshal.WriteByte -
这太笼统了,太多“奇怪的东西”正在发生。一些特殊情况可以转化为 SIMD 代码。
-
@Renat 比 Marchal.WriteByte 快一个 byte[] 吗?
-
@harold ,您能说明一下可以更改的部分吗?我添加了更多信息。
标签: c# performance paint simd