我没有SIMD经验,但是方法太慢。我知道40fps,我还需要更多。有谁知道我该如何使这种绘画方法更快?也许SIMD指令是一种解决方案?
sourceData现在是一个字节[](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编写某些部分,因为所有像素的操作步骤都相同。
嗨,
您的代码对我来说不是最清楚的。您是否要创建新的矩阵/图像?如果是,则创建一个新的2D分配并计算整个图像。不再需要计算后,将其设置为0。用2D图像替换Marshal.WriteByte(layerBuffer + place, colorIndex);
(也许这是图像?)。
关于其余部分,这是一个问题,因为索引和跳转的偏移量不一致。这将使开发SIMD解决方案变得困难(您需要掩膜和填充物)。我的赌注是计算所有索引的所有内容,并将其保存到单独的2D矩阵中,这些矩阵在开始时就分配一次。例如:
ushort eff_y = (ushort)(vScale * (y - vStart) / 128);
是根据每个图像行计算的。现在,您可以将其作为一个数组进行一次计算,因为我不认为图像的格式大小会在运行期间发生变化。
我不知道vStart和vScale是否在程序启动时定义为常数。您应该对每个使用常量的计算都执行此操作,并稍后读取矩阵进行计算。
SIMD可以提供帮助,但前提是每次迭代都计算相同的东西并且避免分支和切换用例。
希望这会有所帮助。