====================编辑:解决方案=====================
我终于找到了问题,因为对于正在学习DirectX的初学者来说,答案可能很重要,我在这里发布。 (我使用F#和SharpDX作为DirectX的.NET包装器)
在我的程序中,资源(缓冲区,视图等)仅在调整交换链的大小时才会更改。所以我将所有资源分配(IA,OM,VS,PS)放入函数switchTo2DLayout
。如果交换链不调整大小,switchTo2DLayout
会立即返回(不做任何操作)。这由一面旗帜控制。
后来我发现这个标志从未被重置,因此资源分配在每次绘制调用之前完成。我纠正了这个错误,但现在只在第一次调用renderPixels
时才渲染图像。事实证明,我必须在绘制调用之前设置ShaderresourceView
每次。
let renderPixels () =
switchTo2DLayout()
// this line was missing:
context.PixelShader.SetShaderResource(COUNT_COLOR_SLOT, countColorSRV_2D)
context.ClearRenderTargetView (renderTargetView2D, Color.White.ToColor4())
context.Draw(4,0)
swapChain.Present(1, PresentFlags.None)
这对我来说完全出乎意料。关于我使用的DirectX的书籍从未明确说明可以分配哪些资源一次(只要设置不变),并且必须在每次抽奖调用上分配
对于网格渲染,我使用类似的设置(这里没有我提到的错误),同样缺少等效的行:
let draw3D() =
switchTo3DLayout()
// this line was missing:
context.VertexShader.SetShaderResource(TRIANGLE_SLOT, triangleSRV )
context.ClearDepthStencilView(depthView3D, DepthStencilClearFlags.Depth, 1.0f, 0uy
context.ClearRenderTargetView(renderTargetView2D, Color4.Black )
context.Draw(triangleCount, 0)
swapChain.Present(1, PresentFlags.None)
这解释了为什么2D渲染因为错误(像素着色器从缓冲区读取)而工作,而3D没有(顶点着色器从缓冲区读取)。
=======================我的原帖:=================
前几天我发布了一个问题[link:] How can I feed compute shader results into vertex shader w/o using a vertex buffer?,这个问题可能太复杂了,无法回答。与此同时,我将设置简化为更简单的情况:
struct PS_IN
{
float4 pos : SV_POSITION;
float4 col : COLOR;
};
RWStructuredBuffer<float4> colorOutputTable : register (u5);
StructuredBuffer<float4> output2 : register (t5);
案例A:像素着色器设置颜色(工作)
// vertex shader A
PS_IN VS_A ( uint vid : SV_VertexID )
{
PS_IN output = (PS_IN)0;
if (vid == 0) output.pos = float4(-1, -1, 0, 1);
if (vid == 1) output.pos = float4( 1, -1, 0, 1);
if (vid == 2) output.pos = float4(-1, 1, 0, 1);
if (vid == 3) output.pos = float4( 1, 1, 0, 1);
return output;
}
// pixel shader A
float4 PS_A ( float4 input : SV_Position) : SV_Target
{
uint2 pixel = uint2(input.x, input.y);
return output2[ pixel.y * width + pixel.x]; // PS accesses buffer (works)
}
案例B:顶点着色器设置颜色(不起作用)
// vertex shader B
PS_IN VS_B ( uint vid : SV_VertexID )
{
PS_IN output = (PS_IN)0;
if (vid == 0) output.pos = float4(-1, -1, 0, 1);
if (vid == 1) output.pos = float4( 1, -1, 0, 1);
if (vid == 2) output.pos = float4(-1, 1, 0, 1);
if (vid == 3) output.pos = float4( 1, 1, 0, 1);
output.col = output2[vid]; // VS accesses buffer (does not work)
return output;
}
// pixel shader B
float4 PS_B (PS_IN input ) : SV_Target
{
return input.col;
}
显然,像素着色器可以访问“output2”缓冲区,而顶点着色器不能(读取始终为零)。
搜索互联网我找不到任何有关此行为的解释。在我的“真实”应用程序中,计算着色器计算三角形列表并将其存储在RWStructuredBuffer中,因此我需要从顶点着色器(通过映射的插槽)访问此表。
我想许多使用计算着色器的人可能会遇到这个问题。不知道怎么解决这个问题? (我目前无法使用Level 11.1或11.2,我必须找到基于11.0的解决方案)
答案 0 :(得分:1)
刚刚在这里试过,你的着色器似乎有效(从未遇到任何阶段无法访问StructuredBuffer的问题,功能级别11)。
示例来自SharpDX minicube(刚刚更换了着色器代码,并添加了一个缓冲区)。
我唯一要做的就是为你的三角形带来反转(我可以修改光栅化器)。
由于我知道调试管道存在问题,另一种有用的方法是查看是否有错误使用查询(在您的情况下主要是PipelineStatistics和Occlusion)。
某些错误的状态可能很容易产生问题,因此您可以通过查看写入/渲染的基元数量来立即查看是否有错误。
这里的着色器代码:
struct PS_IN
{
float4 pos : SV_POSITION;
float4 col : COLOR;
};
RWStructuredBuffer<float4> colorOutputTable : register (u5);
StructuredBuffer<float4> output2 : register (t5);
PS_IN VS_B(uint vid : SV_VertexID)
{
PS_IN output = (PS_IN)0;
if (vid == 1) output.pos = float4(-1, -1, 0, 1);
if (vid == 0) output.pos = float4(1, -1, 0, 1);
if (vid == 3) output.pos = float4(-1, 1, 0, 1);
if (vid == 2) output.pos = float4(1, 1, 0, 1);
output.col = output2[vid]; // VS accesses buffer (does not work)
return output;
}
// pixel shader B
float4 PS_B(PS_IN input) : SV_Target
{
return input.col;
}
代码是here(它非常笨重,所以我把它放在了pastebin上)