Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I'm trying to use a geometry shader to continuously modify the positions of vertices, and save the modfied verts in a buffer.

I have two vertex buffers, one is bound to the IA stage / the vertex shader input, the other to the SO stage / the geometry shader output. After I draw a frame, I swap those two buffers so that (ideally) the saved vertices get modified and saved by the GS again.

What actually happens though is this: I have two buffers, outVB and inVB, both are empty, and an initial, vertex generating vertex shader is set

  1. (Frame 1) Draw(..), the initial vertices are processed, saved to outVB, and drawn
  2. I set inVB as the SO target, and outVB as the input vertex buffer
  3. (Frame 2) Draw(..), vertices are read from outVB, processed, saved to inVB, and drawn
  4. I swap the buffers
  5. (Frame 3) Draw(..), vertices are read from inVB, processed, (apparently not)saved, and drawn
  6. I swap the buffers
  7. (Frame 4) the same output appears as in Frame 2
  8. I swap the buffers
  9. (Frame 5) the same output appars as in Frame 3

and it continues alternating between those two frames, which lead me to believe the buffers still contain the data they held the first time they were written to.

Which makes sense, as the GS can only append new data to the provided buffer.

So I tried releasing and recreating the buffer that is to become the new stream out target before swapping them (I couldn't find any way to clear it), which makes it produce 5 unique frames (including the initial one), and it loops over the last 4 frames, which makes no sense to me at all.

Destroying the buffer holding the old data and recreating it seems to work, since it progresses beyond the states of Frame 2 and 3, but if it worked how can it revert back to the states of Frames 2 and 3 after drawing two more?

my shaders are really simple so far:

struct GS_OUT {
    float4 Pos : SV_POSITION;
    float4 Col : COLOR;
};

GS_OUT VS(GS_OUT input)
{
    return input;
}

[maxvertexcount(10)]
void GS(point GS_OUT input[1], inout PointStream<GS_OUT> PStream )
{
    float4 position = input[0].Pos + float4(0.1f, 0.1f, 0, 1);

    GS_OUT output;
    output.Pos = position;
    output.Col = float4(1,1,1,1);

    PStream.Append(output);
}

float4 PS(GS_OUT input) : SV_TARGET
{
    return inut.Col;
}

My code for flipping the buffers (not neat, I know I could just flip the pointers then assign, but I wanted to make sure everything happened in exactly the order I want):

void swapVBs()
{
    static bool flip = true;

    UINT bufferstride = 2*sizeof(XMFLOAT4);
    ID3D11Buffer *nobuffer = NULL;
    UINT offset = 0;

    D3D11_BUFFER_DESC vbdesc;
    vbdesc.BindFlags = D3D11_BIND_STREAM_OUTPUT | D3D11_BIND_VERTEX_BUFFER;
    vbdesc.ByteWidth = 640*360*2*sizeof(XMFLOAT4);
    vbdesc.CPUAccessFlags = 0;
    vbdesc.MiscFlags = 0;
    vbdesc.StructureByteStride = 0;
    vbdesc.Usage = D3D11_USAGE_DEFAULT;

    if (flip) // SO Target == inVB, Vertex Buffer == outVB
    {

        //clear SO target
        devcon->SOSetTargets(1, &nobuffer, 0);
        //make inVB Vertex Buffer
        devcon->IASetVertexBuffers(0, 1, &inVB, &bufferstride, &offset);

        outVB->Release();
        device->CreateBuffer(&vbdesc, NULL, &outVB);

        //make outVB SO target
        devcon->SOSetTargets(1, &outVB, 0);

    }

    if (! flip) // SO Target == outVB, Vertex Buffer == inVB
    {

        //clear SO target
        devcon->SOSetTargets(1, &nobuffer, 0);
        //make outVB Vertex Buffer
        devcon->IASetVertexBuffers(0, 1, &outVB, &bufferstride,  &offset);


        inVB->Release();
        device->CreateBuffer(&vbdesc, NULL, &inVB);

        //make inVB SO target
        devcon->SOSetTargets(1, &inVB, 0);

    }

    flip = !flip;
}

and the draw code is nothing more than

devcon->DrawAuto();
swapVBs();

So I guess I'm asking...how do I properly clear a ID3D11Buffer? Why in the world does releasing and creating a new buffer not give me an empty buffer?

share|improve this question

1 Answer 1

up vote 3 down vote accepted

I found the problem, ID3D11DeviceContext::SOSetTargets(..) expects a pointer to an array of offsets as the third param, but I've been passing a nullpointer (thinking it would assume I don't want an offset).

The default behavoir seems to be to assume a value of -1, which makes the GS append writes to the last position in the buffer that was written to, which in my case always seems to have been the end, causing no new vertices to be written.

Passing an actual pointer to an UINT offset = 0; works like a charm and the geometry shader overwrites the contents of the buffer.

share|improve this answer
    
Yikes. Good to know. That definitely seems like a bug in D3D11, if that's what it's doing. –  Nathan Reed Mar 2 '12 at 20:44

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.