最近打算使用 Win32 C++ 在 D3D11 写着色器(SM4.0)渲染墨迹(为了兼容 win7 sp1 + KB2670838 的系统和设备,所以是 dx11.1 和 SM4.0)。但是我觉得当前的方案还有非常大的优化空间,但是我作为 HLSL 萌新似乎已经有点懵了,所以需要大佬的指引。
首先,我的着色器用于渲染墨迹,墨迹的每个节点拥有一个宽度,并且我们绘制的是 round cup 和 round join 的墨迹。最初的方案是打算分段渲染每一个胶囊(当然贝塞尔已经处理好了,这里画折线中的一段就是),在矩形包围盒中,使用 PS 和 SDF 对每个点运算(这里我参考过 IQ 的写法写 SDF)并且抗锯齿。
这种方案目前的问题就是有大量的像素(特别是连接处,如果墨迹该节点宽度很宽,那么问题愈发严重)。我目前构思的优化方案是先实例化。然后改变包围盒,大概是使用 OBB,主要是去除会重复计算的问题。然后渲染逻辑也改为不是一段一段胶囊渲染,而是直接传入节点坐标和节点宽度,直接绘制整段的墨迹。
我有一个测试的 demo,可以看看(代码注释还是比较多的)。
Alan-CRL/Inkeys3-Draw3

我进行了一些统计,发现速度确实不如我写 D2D (CPU 算路径 + GPU Fill),当然这里的 GPU 时间统计并不准确,主要是这类 profile 在其他电脑上测试的时候不好解决。所以项目中的计时是冷启动+渲染+强制同步(如果是正常情况下我会设置 `dxgiDevice1->SetMaximumFrameLatency(1);` 来提供一帧的 GPU 缓冲时间)的时间。
当然,使用 PIX 得出的结果也并不理想,也使用了两秒多。

希望这个问题可以得到解决,谢谢。
当然,单个胶囊的绘制的冷启动问题我也不知道是为啥,反正 PIX 给出的是 0.8ms 左右的 GPU 时间,所以我想后面应该不是什么问题(可能是当前强制同步的锅)