Question

1) The problem

I want to draw a graph with loads of points. The dataset is not static and the points are flowing. Currently I store the graph in vertex buffer and add new points as soon as they appear. The problem is when buffer runs out of space. Maybe at the moment I pass too much data to the buffer but the max size I can set it to is

   int buffer_size = 1215 * (Utilities.SizeOf<Vector4>() 
                           + Utilities.SizeOf<Vector4>() 
                           + Utilities.SizeOf<Vector2>());

which is equal 48 600.

For 48 640 I get an error

A first chance exception of type 
'System.AccessViolationException' occurred in SharpDX.Direct3D11.dll
Additional information: There was try to read or write to/from protected memory

My idea was to create two Vertex Buffers, and if one gets full write to the second one, still plotting both of them. The writing would be with flag MapMode.WriteNoOverwrite. If the second one gets full then write to the first cell of the first one with a flag MapMode.WriteDiscard, which will basically clear the buffer.

2) The question:

How to write from multiple vertex buffers?

3) Existing code

I set a layout with information for two slots:

var layout = new InputLayout(device, passSignature, new InputElement[]
    {
      new InputElement("POSITION", 0, Format.R32G32B32A32_Float, 0, 0)
     ,new InputElement("COLOR", 0, Format.R32G32B32A32_Float
                              , InputElement.AppendAligned, 0)
     ,new InputElement("TEXCOORD", 0, Format.R32G32_Float
                              , InputElement.AppendAligned, 0)

     // semantic index had also to be increased as has a slot number
     ,new InputElement("POSITION",1, Format.R32G32B32A32_Float, 0, 1)
     ,new InputElement("COLOR", 1, Format.R32G32B32A32_Float  
                              , InputElement.AppendAligned, 1)
     ,new InputElement("TEXCOORD", 1, Format.R32G32_Float
                                 , InputElement.AppendAligned, 1)
    });

Create buffers' data and set vertex buffers.

    float[] buffer_data = new float[] {
          -1.0f,   0.0f,  0.0f, 1.0f,   1.0f, 0.0f, 0.0f, 0.0f,    0.0f, 0.0f
         , 0.2f,  -0.4f,  0.0f, 1.0f,   0.0f, 1.0f, 0.0f, 0.0f,    0.0f, 0.0f 
         ......

    var vertices = Buffer.Create(device
                                    , BindFlags.VertexBuffer
                                    , buffer_data
                                    , buffer_size
                                    , ResourceUsage.Dynamic
                                    , CpuAccessFlags.Write
                                    , ResourceOptionFlags.None
                                    , 0);

    context.InputAssembler.InputLayout = layout;
    context.InputAssembler.PrimitiveTopology = PrimitiveTopology.LineList;
    context.InputAssembler.SetVertexBuffers(
                         0
                       , new Buffer[] { vertices, vertices2 }
                       , new int[] { 40, 40 }
                       , new int[] {  0,  0 }
    );    

Drawing

int sectionsToDraw = 32;
context.ClearRenderTargetView(renderView, Color.Black);

// Main loop            
RenderLoop.Run(form, () =>
{
    for (int i = 0; i < technique.Description.PassCount; ++i)
    {
        pass.Apply(context);
        context.PixelShader.SetShaderResource(0, textureView);
        context.GeometryShader.SetConstantBuffer(0, _constantBuffer);
        context.Draw(sectionsToDraw,0);  
    }
    swapChain.Present(0, PresentFlags.None);
});

and my shader's structs

struct VS_IN 
{
    float4 pos : POSITION;
    float4 col : COLOR;
    float2 tex : TEXCOORD;
};

struct GS_IN
{
    float4 pos : SV_POSITION;
    float4 col : COLOR;
    float2 tex : TEXCOORD;
};

struct PS_IN
{
    float4 pos : SV_POSITION;
    float4 col : COLOR;
    float2 tex : TEXCOORD;
};

I do not know how to draw from the 1st slot. It only draws from the buffer in slot 1.

The problem is not in: - the correct set up of points to draw in both buffers - the number of vertices to draw passed to contect.Draw in first argument - I also tried changing shader's structs to use POSITION1 or COLOR1, but it did not help, but maybe I did not do it correctly.

Was it helpful?

Solution

I managed to draw from two Vertex Buffers by simply switching buffers in InputAssambler in the render function

VertexBufferBinding vb = new VertexBufferBinding(vertices
                         , Utilities.SizeOf<Vector4>() 
                         + Utilities.SizeOf<Vector4>() 
                         + Utilities.SizeOf<Vector2>()
                         , 0);

VertexBufferBinding vb2 = new VertexBufferBinding(vertices2
                         , Utilities.SizeOf<Vector4>() 
                         + Utilities.SizeOf<Vector4>() 
                         + Utilities.SizeOf<Vector2>()
                         , 0);

Then in render loop

RenderLoop.Run(form, () =>
{
   context.ClearRenderTargetView(renderView, Color.Black);  
   .... 
   context.InputAssembler.SetVertexBuffers(0, vb);                              
   context.Draw(sectionsToDraw,0);
   context.InputAssembler.SetVertexBuffers(0, vb2);
   context.Draw(sectionsToDraw, 0);
   ....
}

Of course, with this solution also the layout can be simplified

var layout = new InputLayout(device, passSignature, new InputElement[]
    {
      new InputElement("POSITION", 0, Format.R32G32B32A32_Float, 0, 0)
     ,new InputElement("COLOR",    0, Format.R32G32B32A32_Float
                              , InputElement.AppendAligned, 0)
     ,new InputElement("TEXCOORD", 0, Format.R32G32_Float
                              , InputElement.AppendAligned, 0)
    }

but now, I am not sure if my solution does not involve copying the whole buffer every draw call. I have to read about it a bit more.

What I think is my problem is that I am using Directx 11, and I cannot find a partial Lock for buffer, like the one as I understand was in Directx 9. http://sharpdx.org/documentation/api/m-sharpdx-direct3d9-vertexbuffer-lock It looks like there is none in DirectX 11. I found that you can take MapSubresource of a resource, but according to MSDN "A buffer is defined as a single subresource". So, it is not possible to lock only a part of a buffer as I would like to.

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