提高绘画效果,SIMD也许是一种解决方案?

问题描述 投票:0回答:1

我没有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编写某些部分,因为所有像素的操作步骤都相同。

c# performance paint simd
1个回答
3
投票

嗨,

您的代码对我来说不是最清楚的。您是否要创建新的矩阵/图像?如果是,则创建一个新的2D分配并计算整个图像。不再需要计算后,将其设置为0。用2D图像替换Marshal.WriteByte(layerBuffer + place, colorIndex);(也许这是图像?)。

关于其余部分,这是一个问题,因为索引和跳转的偏移量不一致。这将使开发SIMD解决方案变得困难(您需要掩膜和填充物)。我的赌注是计算所有索引的所有内容,并将其保存到单独的2D矩阵中,这些矩阵在开始时就分配一次。例如:

ushort eff_y = (ushort)(vScale * (y - vStart) / 128);

是根据每个图像行计算的。现在,您可以将其作为一个数组进行一次计算,因为我不认为图像的格式大小会在运行期间发生变化。

我不知道vStart和vScale是否在程序启动时定义为常数。您应该对每个使用常量的计算都执行此操作,并稍后读取矩阵进行计算。

SIMD可以提供帮助,但前提是每次迭代都计算相同的东西并且避免分支和切换用例。

希望这会有所帮助。

© www.soinside.com 2019 - 2024. All rights reserved.