Question

==================== EDIT: the solution =====================

I finally have found the problem, and since the answer might be important for beginners who are learning DirectX I post it here. (I’m using F# and SharpDX as the .NET wrapper to DirectX)

In my program the resources (buffers, views etc.) only change when the swap chain is resized. So I put all resource allocations (IA, OM, VS, PS) into a function switchTo2DLayout. switchTo2DLayout returns immediately (without doing anything) if the swap chain was not resized. This is controlled by a flag.

Later on I detected that this flag was never reset, and so the resource allocations were done before every draw call. I corrected this mistake, but now the image was rendered only on first call to renderPixels. It turned out that I have to set the ShaderresourceView every time before the draw call.

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)  

This was completely unexpected for me. The books about DirectX that I use never state explicitly which resources can be allocated once (as long the setting is not changed), and which have to be allocated on every draw call.

For the mesh rendering I use a similar setup (here without the bug I mentioned), and again the equivalent line was missing:

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)    

This explains why the 2D rendering worked because of the bug (pixel shader reads from buffer), and the 3D did not (vertex shader reads from buffer).

======================= My original post: =================

Some days ago I posted a problem [link:] How can I feed compute shader results into vertex shader w/o using a vertex buffer? that was probably too complicated to be answered. Meanwhile I have stripped down the setup to a much simpler case:

struct PS_IN
{
float4 pos : SV_POSITION;
float4 col : COLOR;
};

RWStructuredBuffer<float4> colorOutputTable :  register (u5);
StructuredBuffer<float4> output2 :             register (t5);  

Case A: pixel shader sets color (works)

// 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)

}

Case B: vertex shader sets color (doesn't work)

// 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;
}

Obviously the pixel shader can access the “output2” buffer while the vertex shader can’t (reading always zeros).

Searching the Internet I could not find any explanation for this behavior. In my “real” application a compute shader calculates a triangle list and stores it in a RWStructuredBuffer, so I need access to this table from the vertex shader (via the mapped slot).

I guess that many people who work with compute shaders might stumble over this problem. Any idea how to solve this? (I currently can't use Level 11.1 or 11.2, I have to find a solution based on 11.0)

Was it helpful?

Solution

Just tried here, your shader seems to work (never had issues with StructuredBuffer not accessible on any stage, feature level 11).

Sample is just from SharpDX minicube (just replaced shader code inside, and added a buffer).

Only thing I had to do was to reverse winding for your trianglestrip (I could have modified the rasterizer).

Since I know you have issue with debug pipeline, one other useful way to see if something wrong is to use queries (mostly PipelineStatistics and Occlusion in your case).

Some wrong state might easily create issue, so you can immediately see if something is wrong by looking at number of pixels written/rendered primitives).

Shader code here:

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;
}

Code is here (it's quite bulky so I've put it on pastebin)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top