c++ - 我正在寻找可以在图形编辑程序中进行的任何优化

标签 c++ windows performance image directx

嘿嘿,我是第一次在这里提问,如果我搞砸了请原谅我>~<

我正在开发一个类似于 openCanvas 的程序,早期的程序允许多人通过 Internet 在同一 Canvas 上实时绘图。 OC 确实有很多问题并且有很多限制,这就是我想写这篇文章的原因。

我已将其设置为使 Canvas 在所有方向“无限期”延伸,并由 512x512 像素 block 组成,这些像素 block 在绘制之前不会激活,这应该很容易制作,而且我正在考虑使用 Direct3D 使其硬件加速,因此 512 方 block 。

当我想使用层时,我的问题就来了,我不太确定如何在不使用大量内存的情况下快速组合层,因为我的目标是具有 128m 内存的 DirectX9 兼容视频卡,以及具有大约 3.2 GHz 的 CPU 功率和 2 到 8 GB 的内存。我有几种不同的方法正在考虑使用,并且想知道哪种方法可能是最好的,以及是否有任何我可以研究的方法可以让它运行得更好。

我的第一个想法是让 gfx 硬件做尽可能多的工作,方法是让所有 block 上的所有层都用作纹理,并通过锁定更改的区域来更新它们,在 cpu 上更新它们,并且解锁它们。当前未更改的 block 被展平为一个纹理,各个层本身保存在系统内存中,这将减少使用的 gfx 内存,但可能会显着增加系统和 gfx 内存之间的带宽使用。我可以看到持续的锁定和解锁也可能会非常糟糕地减慢系统速度。另一个可能的问题是,我听说有人使用多达 200 层,鉴于上述情况,我想不出任何优化方法。

我的另一个想法是在系统内存中完全组合纹理,将它们写入纹理,然后将该纹理复制到 gfx 内存以在每个 block 中渲染。这似乎消除了其他方法的很多问题,但同时我将所有工作转移到 CPU 中,而不是平衡它。不过,只要它仍然快速运行,这就没什么大不了的。然而,再一次,有几百层的问题。不过在这种情况下,我可能只能更新实际发生变化的最终像素,我认为这就是 Sai 和 Photoshop 等大牌程序所做的。

我主要是在寻找建议、可能改进上述内容的建议、更好的方法或可能与此类项目相关的文章链接。当我用 C++ 编写它时,我可以毫不费力地从其他语言进行翻译。谢谢你的时间~

最佳答案

数据结构
您绝对应该使用四叉树(或其他分层数据结构)来存储您的 Canvas ,并且它的节点应该包含很多小于 512x512 像素的 block 。也许不会像 1x1 像素那么小,因为那样的话分层开销会让你丧命 - 你会通过测试找到一个很好的平衡点。

绘图
让您的用户仅使用一种(最高分辨率)分辨率。想象一个无限大的均匀网格(二维数组)。由于您知道鼠标的位置和用户从原点滚动的量,因此您可以得出绝对坐标。将四叉树遍历到该区域(最终添加新节点)并在用户将 block 绘制到四叉树时插入 block (例如 32x32)。我会缓冲用户在二维数组中绘制的内容(例如与他的屏幕分辨率一样大)并使用单独的线程遍历/更改四叉树并从缓冲区复制数据以规避任何延迟。

渲染
遍历四叉树并将所有图 block 复制到一个纹理并将其发送到 GPU?不!你看,发送一个与屏幕分辨率一样大的纹理不是问题(带宽方面)。但是遍历四叉树并组装最终图像是(至少如果你想要很多 fps)。答案是将四叉树存储在系统内存中并从 GPU 流式传输。意思是:另一个线程异步地进行遍历,并尽可能快地将当前查看的数据分块复制到 GPU。如果您的用户没有以全分辨率查看 Canvas ,则您不必遍历树到叶级别,这会为您提供自动细节级别 (LOD)。

关于所提议策略的一些随机想法

  • 四叉树方法很棒,因为它的内存效率很高。
  • 流媒体的想法可以扩展到硬盘... SeaDragon
  • 复杂的实现需要 CUDA 之类的东西。
  • 如果您的 GPU 不提供必要的性能/可编程性,只需在 CPU 上实现遍历 - 在图像完全显示之前稍微延迟一点,但应该可以接受。不要忘记使用多线程异步编程,这样屏幕在等待 CPU 时不会卡住。您可以使用不同的效果:一次显示整个图像,开始时模糊,然后慢慢增加细节(广度优先搜索 (BFS))或逐 block 渲染(深度优先搜索 (DFS))——可能混合一些很酷的效果.
  • 只要允许以全分辨率查看 Canvas ,软件实现应该非常简单。如果可以逐步缩小,那是对遍历的微小改变。如果可以无缝缩放,则需要在相邻四叉树节点的图 block 之间进行线性插值 - 这不再微不足道,但可行。
  • 层:四叉树应该给你足够低的内存消耗,让你只需在每一层存储一个四叉树。但是当你有很多层时,你需要一些优化来保持实时:你不能每帧组装 200 个纹理并将它们发送到 GPU。 也许(不完全确定这是否是最佳解决方案)对于每一层删除该层下方的四叉树的所有节点,其图 block 的像素完全被上面的层覆盖。这需要在运行时完成,同时需要绘制和深度缓冲区。如果您提供橡皮擦工具,则无法删除节点,但必须将它们标记为“不可见”,以便在遍历过程中可以省略它们。

..在我的头顶。如果您还有其他问题,请告诉我!

关于c++ - 我正在寻找可以在图形编辑程序中进行的任何优化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4986847/

相关文章:

c++ - OpenCV:断言失败(src.checkVector(2,CV_32F)

c++ - 在 FOR 循环中声明变量

java - 如何制作包含多个类的 .jar 文件?

ios - 文件大小(代码行数)是否会影响应用程序性能?

CSS 动画背景颜色需要太多的性能!寻找选择

c++ - 怀疑在构造函数中工作的一个缺点

c++ - 如何在 cout 上使用 isatty(),或者我可以假设 cout == 文件描述符 1?

c++ - 如何确定 PdhExpandWildCardPath 结果中的主要网络适配器?

java - 如何在 Windows 中增加 IE 应用程序的堆内存大小?

performance - 像素修改代码在主应用程序中运行很快,在 Delphi 6 DirectShow 过滤器中运行速度非常慢,还有其他问题