shaderdirectx-11sharpdxcompute-shader

Updating constant Buffer in a compute shader


I've created a simple program to test the compute shader.

Just pasing a few VERTEX and a constant buffer. The compute shader adds the values in the constant buffer to the vertex and puts the vertex in a appendable buffer.

Then I recover the appendable buffer and see the results.

The results are that the constantbuffer is updated only the first time so I always get the same results.

Here is my compute shader:

struct VERTEX {
    float3 Position;
    float3 Normal;
};
cbuffer Ray : register(b0)
{
    float3 Origin;
    float kk1;
};

RWStructuredBuffer<VERTEX> vertex: register(u0);
AppendStructuredBuffer<VERTEX> changedVertex: register(u1);

[numthreads(2, 1, 1)] //I just want to update 2 vertex, to test
void CS_BuscaHitPoints(uint3 DTid : SV_DispatchThreadID)
{
    vertex[DTid.x].Normal.z = DTid.x;
    vertex[DTid.x].Normal.x = Origin.x;
    vertex[DTid.x].Normal.y = Origin.y;
    changedVertex.Append(vertex[DTid.x]);
}

The constant buffer:

bd = new BufferDescription
{
    Usage = ResourceUsage.Dynamic,
    BindFlags = BindFlags.ConstantBuffer,
    CpuAccessFlags = CpuAccessFlags.Write,
    OptionFlags = ResourceOptionFlags.None,
    SizeInBytes = Utilities.SizeOf<Rayo>(),
    StructureByteStride = 0,
};
bufferConElRayo = new Buffer(device, bd);
context.ComputeShader.SetConstantBuffer(0, bufferConElRayo);

Setting the constant buffer every time I press a button:

rayo.Origin.X += 1;
rayo.Origin.Y += 2;
DataStream ds;
DataBox db = context.MapSubresource(bufferConElRayo, MapMode.WriteDiscard, MapFlags.None, out ds);
IntPtr offset = db.DataPointer;
offset = Utilities.WriteAndPosition<Rayo>(offset,ref rayo);
context.UnmapSubresource(bufferConElRayo, 0);

context.Dispatch(1, 1, 1);

// If I create the constantbuffer with ResourceUsage.Default I update it with // context.UpdateSubresource(ref rayo, bufferConElRayo); but it works only the first time as // well

For the Appendable buffer:

bd = new BufferDescription()
 {
    Usage = ResourceUsage.Default,
    BindFlags = BindFlags.ShaderResource | BindFlags.UnorderedAccess,
    CpuAccessFlags = CpuAccessFlags.None,
    OptionFlags = ResourceOptionFlags.BufferStructured,
    SizeInBytes = Utilities.SizeOf<VERTEX>() * vertices.Length,
    StructureByteStride = Utilities.SizeOf<VERTEX>()
};
bufferApendable = new Buffer(device, bd);
uavd = new UnorderedAccessViewDescription()
{
    Format = SharpDX.DXGI.Format.Unknown,
    Dimension = UnorderedAccessViewDimension.Buffer,
    Buffer = new UnorderedAccessViewDescription.BufferResource()
    {
        ElementCount = vertices.Length,
        FirstElement = 0,
        Flags = UnorderedAccessViewBufferFlags.Append
    }
};
uavParaElBufferApendable = new UnorderedAccessView(device, bufferApendable, uavd);
context.ComputeShader.SetUnorderedAccessView(1, uavParaElBufferApendable);

To recover the result:

context.CopyResource(bufferApendable, bufferParaObtenerElResultado);
DataStream ds;
DataBox db = context.MapSubresource(bufferParaObtenerElResultado, MapMode.Read, MapFlags.None, out ds);
VERTEX v0 = ds.Read<VERTEX>();
VERTEX v1 = ds.Read<VERTEX>();
context.UnmapSubresource(bufferParaObtenerElResultado, 0);

I get the vertex always with the value of the constantbuffer that set the first time

I'm used to use constant buffers in the vertex shader and pixel shader and they works ok. I dont know if there is any limit in the computer shader?

Any Idea? Thanks for you responses


Solution

  • This code :

    uavParaElBufferApendable = new UnorderedAccessView(device, bufferApendable, uavd);
    context.ComputeShader.SetUnorderedAccessView(1, uavParaElBufferApendable);
    

    does not reset the internal counter of your append buffer. Internally it does :

    context.ComputeShader.SetUnorderedAccessView(1, uavParaElBufferApendable, -1);
    

    So every call to dispatch will actually write in the next parts of your buffer.

    You need to replace the call by :

    context.ComputeShader.SetUnorderedAccessView(1, uavParaElBufferApendable,0);