所有DirectX书籍和教程都强烈建议将绘制调用之间的资源分配减少到最低限度 - 但我找不到任何可以深入了解细节的指南.回顾网上发现的大量示例代码,我得出结论,程序员对此主题有完全不同的编码原则.有些甚至设置和取消设置
VS/PS
VS/PS ResourceViews
RasterizerStage
DepthStencilState
PrimitiveTopology
...
Run Code Online (Sandbox Code Playgroud)
在每次绘制调用之前和之后(虽然设置保持不变),而其他人则没有.
我猜这有点过头了......
从我自己的实验,我发现,我不得不在每次绘制调用绑定的唯一资源是ShaderResourceViews(以VS和PS在我的情况).此要求可能是由于使用计算着色器引起的,因为我绑定/取消绑定UAVs到绑定到VS/ PS稍后的缓冲区.
在我发现这种重新绑定是必要的之前,我已经失去了许多小时的工作.而且我想许多程序员也不确定,并且更愿意解开并重新绑定"有点太多"而不是陷入类似的陷阱.
问题1:关于这个问题至少有一些经验法则吗?
问题2:我的ShaderResourceViews绑定是否可能VS/PS被驱动程序/ DirectX核心解除绑定,因为我UAVs 在CS调度调用之前绑定了相同的缓冲区(我没有解除绑定SRVs自己)?
问题3:VS/PS在使用计算着色器之前,我甚至没有设置为null.没有问题的工作但我总是不确定我是否正在使用这种"懒惰"的方法挖掘我的下一个陷阱.
我刚开始学习DirectX编程,使用F#和SharpDX作为.NET包装器.作为测试用例,我渲染了Mandelbrot集.使用2个计算着色器完成计算.
第一个着色器计算每个像素的深度(函数"CalcMandel"),结果存储在RWStructuredBuffer中.这种计算需要大量的单次或双次乘法,但它在我的GPU(AMD 7790)上的速度非常快."CalcMandel"具有该属性
[numthreads(16, 16, 1)]
Run Code Online (Sandbox Code Playgroud)
并通过发送
context.Dispatch (imageWidth / 16, imageHeight / 16, 1)
Run Code Online (Sandbox Code Playgroud)
这里没有问题 - "核心"Mandelbrot集的1000 x 800像素图像以超过1000 fps的速度运行(在GPU上使用单精度).
第二个着色器几乎没有做任何事情:它计算先前计算的最小值,最大值和平均值(函数"CalcMinMax")."CalcMinMax"具有该属性
[numthreads(1, 1, 1)]
Run Code Online (Sandbox Code Playgroud)
并被称为通过
context.Dispatch (1,1,1)
Run Code Online (Sandbox Code Playgroud)
对于当时给定的图像大小,单个GPU线程必须遍历超过800.000个整数的缓冲区以计算最小值,最大值和平均值.我使用单个线程,因为我不知道如何以并行方式实现此计算.
问题:"CalcMinMax"非常慢:帧速率从1000 fps下降到5 fps!
我的问题:这里有什么问题?我使用了错误的设置/参数(numthreads)吗?如何加快min-max计算?
我的想法:我的第一个假设是访问RWBuffer可能会很慢 - 事实并非如此.当我用常量替换缓冲区访问时,帧速率没有增加.
我的GPU有appr.900个着色器核心并使用数千个线程来计算Mandelbrot集合,而"CalcMinMax"仅使用一个线程.然而,我仍然不明白为什么事情变得如此缓慢.
我很感激任何建议!
================================================
// HLSL CONTENT(省略Mandelbrot集计算):
cbuffer cbCSMandel : register( b0 )
{
double a0, b0, da, db;
double ja0, jb0;
int max_iterations;
bool julia; int cycle;
int width; int height;
double colorFactor;
int algoIndex;
int step;
};
struct statistics
{
int minDepth;
int …Run Code Online (Sandbox Code Playgroud)