2013-09-23 43 views
0

我正在尝试使用GPU实现一个复杂的算法。唯一的问题是硬件限制,最大可用功能级别是9_3。DirectX 11,结合像素着色器以防止瓶颈

算法对于两幅图像基本上是“立体匹配”类算法。由于上述限制,所有计算必须仅在顶点/像素着色器中执行(没有可用的计算API)。顶点着色器在这里毫无用处,所以我认为它们是直通顶点着色器。

让我简单的介绍它的算法:

  1. 采取两个图像,并计算成本卷映射(基本上conterting RGB到灰度 - >通过d翻译右图像和左图像中减去)。对于生成Texture3D的不同D,该步骤重复约20次。

    问题就在这里:我不能简单地创建一个支持Pixel Shader它计算 一气呵成的20次重复,因为像素 着色器的大小限制的,所以我不得不调用绘制(最大512个算术。) ()在循环 在C++中不需要涉及CPU,而所有操作都在 完成相同的两个图像 - 在我看来,我似乎有一个瓶颈在这里。我知道有多个渲染目标,但是:有最大值。 8个目标(我需要20+),如果我想在一个像素着色器中生成8个结果,那么我超过了它的大小限制(我的HW有512个算法)。

  2. 然后我需要与窗口来计算每个计算纹理箱式滤波器的其中r> 9.

    这里的另一问题:因为窗口是如此之大我需要分割盒过滤器使其成为两个像素着色器(分别为垂直和水平方向),因为循环展开阶段结果的代码很长。手动实现这些循环对于大像素着色器来说无助于它。因此,另一个瓶颈在这里 - CPU需要参与将结果从临时纹理(V pass结果)传递到第二遍(H pass)。

  3. 然后在下一步中对第一步和第二步的每对结果进行一些算术运算。

    我还没有到达这里与我的发展,所以不知道什么样的瓶颈在这里等着我。

  4. 然后最小d(从第一步骤参数的值),在步骤采取基于像素值从步骤3

    ...相同的每个像素为3

这里基本上是非常简单的图表显示我目前的实施(不包括步骤3和4)。

Problem diagram

红点,其中部分结果被存储,并在每个红点CPU被卷入/圈/无论是临时缓冲器(纹理)。

问题1:是不是有可能以某种方式让GPU知道如何执行每个分支形式直到底部而不涉及CPU并导致瓶颈?即一次编程图形管道序列,然后让GPU完成工作。

关于渲染到纹理的东西的另一个问题:即使在Draw()方法调用和Pixel/Vertex着色器切换之间,所有纹理都一直驻留在GPU内存中吗?或者从GPU到CPU的任何转移发生......因为这可能是另一个问题导致瓶颈。

任何帮助,将不胜感激!

预先感谢您。

最好的问候, 卢卡斯

回答

1

写作像素着色器的计算算法是非常困难的。编写9_3目标的算法可能是不可能的。太多的限制。但是,我想我知道如何解决你的问题。

1.着色器重复

首先,目前还不清楚,你叫什么名字“瓶颈”在这里。是的,理论上,在for循环中绘制调用是一个性能损失。但它是否是瓶颈?你的应用程序真的在这里失去了性能吗?多少?只有分析器(CPU和GPU)可以回答。但要运行它,您必须先完成算法(阶段3和阶段4)。所以,我最好坚持使用当前的解决方案,并开始实施整个算法,然后配置并修复性能问题。

但是,如果您准备好进行调整......常见的“重复”技术就是实例。您可以创建一个更多的顶点缓冲区(称为实例缓冲区),该缓冲区将包含不是针对每个顶点的参数,而是针对一个绘制实例。然后你通过一个DrawInstanced()电话完成所有的工作。

对于您的第一阶段,实例缓冲区可以包含您的D值和目标Texture3D图层的索引。你可以通过顶点着色器传递它们。

与往常一样,这里有一个交易:简单的代码(可能)表现。

2。需要参与多遍渲染

CPU通过从临时纹理结果(的 通过电压V的结果),以第二次通过(H通)

通常,您链接这样,所以没有CPU参与:

// Pass 1: from pTexture0 to pTexture1 
// ...set up pipeline state for Pass1 here... 
pContext->PSSetShaderResources(slot, 1, pTexture0); // source 
pContext->OMSetRenderTargets(1, pTexture1, 0);  // target 
pContext->Draw(...); 

// Pass 2: from pTexture1 to pTexture2 
// ...set up pipeline state for Pass1 here... 
pContext->PSSetShaderResources(slot, 1, pTexture1); // previous target is now source 
pContext->OMSetRenderTargets(1, pTexture2, 0); 
pContext->Draw(...); 
// Pass 3: ... 

注意,那pTexture1必须同时D3D11_BIND_SHADER_RESOURCED3D11_BIND_RENDER_TARGET标志。你可以有多个输入纹理和多个渲染目标。只要确保每一个下一个传球都知道以前的传球输出。 如果以前通过使用更多的资源比现在,不要忘记解除绑定不需要的,以防止难以发现的错误:

pContext->PSSetShaderResources(2, 1, 0); 
pContext->PSSetShaderResources(3, 1, 0); 
pContext->PSSetShaderResources(4, 1, 0); 
// Only 0 and 1 texture slots will be used 

3.资源数据位置

是否所有纹理一直驻留在GPU内存中,甚至在 Draw()方法调用和Pixel/Vertex着色器切换之间?

我们永远无法知道这一点。驱动程序为资源选择适当的位置。但是,如果您有使用DEFAULT使用情况和0 CPU访问标志创建的资源,则几乎可以确定它始终位于视频内存中。

希望它有帮助。快乐的编码!

+0

谢谢您的回答! –

+0

你消除了我的疑惑。我的发展问题是我为移动设备开发,无法找到合适的GPU分析器。也许我会尝试在一些具有“可比”性能的旧PC上运行我的代码,以了解它的行为。再次感谢! –