互斥锁和适当循环的并行处理
嗯,我猜你和我得出了同样的结论。并行化的 drawTriangle 循环方案似乎并没有成为一个很好的选择。我们需要另外的东西来让线程切换更加高效。我们要并行处理多个三角形,而不是绘制一个三角形。总之,每一个核心都要绘制一个完整的三角形。
这种方法的问题将会在 PutPixel 方法中出现。现在我们要并行处理几个面,我们可能会陷入 2 个内核/线程试图并行访问同一个像素的情况。这是,我们只需要保护要访问的像素就可以了。事实上,如果我们用更多时间去保护正在工作中的数据,并行化将会非常有用。
解决的办法是使用一个锁:
private object[] lockBuffer;
public Device(WriteableBitmap bmp)
{
this.bmp = bmp;
renderWidth = bmp.PixelWidth;
renderHeight = bmp.PixelHeight;
// 后台缓冲区大小值是要绘制的像素
// 屏幕(width*height) * 4 (R,G,B & Alpha 值)
backBuffer = new byte[renderWidth * renderHeight * 4];
depthBuffer = new float[renderWidth * renderHeight];
lockBuffer = new object[renderWidth * renderHeight];
for (var i = 0; i < lockBuffer.Length; i++)
{
lockBuffer[i] = new object();
}
}
// 调用此方法把一个像素绘制到指定的 X, Y 坐标上
public void PutPixel(int x, int y, float z, Color4 color)
{
// 我们的后台缓冲区是一维数组
// 这里我们简单计算,将 X 和 Y 对应到此一维数组中
var index = (x + y * renderWidth);
var index4 = index * 4;
// 使用锁来保护缓冲区不被并行处理扰乱
lock (lockBuffer[index])
{
if (depthBuffer[index] < z)
{
return; // 深度测试不通过
}
depthBuffer[index] = z;
backBuffer[index4] = (byte)(color.Blue * 255);
backBuffer[index4 + 1] = (byte)(color.Green * 255);
backBuffer[index4 + 2] = (byte)(color.Red * 255);
backBuffer[index4 + 3] = (byte)(color.Alpha * 255);
}
}
使用第二种方法,从 45 FPS 提升到了 53 FPS。你可能会认为这点性能提升并不能让人影响深刻。但是在接下来的教程中,drawTriangle 方法将更加复杂,比如处理阴影和照明之类的,并行处理几乎可以得到两倍的性能提升。
我们还可以看看这个并行处理方法分析的核心利用图:
比较以前的核心图,你就会明白为什么它更加高效了。
你可以在这里下载含有这种优化的 C#版本解决方案:
那么,在 Html5/JavaScript 中为什么不能应用这种方法呢?Html5 在 JavaScript 中卫开发人员提供了一个新的 API 用于处理类似的情况。它叫 Web Workers,使用它可以处理使用多核心的情况。
David Catuhe 和我已经在这三篇话题中讨论过这个东西:
介绍 Html5 的 Web Workers:JavaScript 的多线程方法 :如果你还不知道 Web Workers,那么你应该先阅读这篇文章
使用 Web Workers,用于提高图像处理性能 :一篇很有意思的文章,我们使用 Web Workers 来获得像素操作的性能提升
- 教程系列:在 Windows 8 中使用 WinJS 和 WinRT 构建一个有趣的 Html5 摄像头应用程序 :在这个教程中使用 Web Workers 来进行摄像头拍摄的图像效果处理
我们使用 message 与 workers 进行沟通。这意味着大多数时间被用于从 UI 线程给 workers 线程传输拷贝数据。我们只有很少部分的类型可以使用。事实上,随着 转换对象 ,当转移到 workers 时原始对象将从呼叫者上下文(UI 线程) 中清除。
但是在我们加速 Html5 的 3D 软件渲染引擎时,这并不是主要的问题。在发送数据的时候将有memcpy()进行操作,这是一个非常快速的过程。但真正的问题是,当 workers 完成了处理后,需要将结果发送回主线程而且这个主线程还需要将数据重新填充回像素数组中。这个操作将很简单的抵消掉所有 Web Workers 带来的性能增益。
所以最后,我还没有找到一个有效的并行处理方法来实现 Html5 中 3D 软件渲染引擎的性能提升。不过,可能我有一些东西还不知道。如果您可以解决当前 Web Workers 的局限,获得到一个显著的性能提升的话,我非常乐意接受建议!
在接下来的教程中,我们将讨论 平面着色和高氏着色 。我们的实现将开始真正耀眼!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论