0
\$\begingroup\$

I am trying to use a constant buffer in a program using SharpDX.Toolkit. I use the Toolkit because it has nice font support for writing on the screen.

The problem I face is in assigning data to the constant buffer.

In the screen below you may see a debug of my code. When it comes to the Draw event the buffer gets empty (obj:9 is active) and in Geometry Shader all values are 0.0f. On event 76 - GSSetShader the obj:16 is active, which contains the data I want to use, non-zero values. I have no idea why it gets overwritten/cleared. I tried assigning or updating buffer in numerous places in the draw method, but none of them helped. For sure it is not a problem of a slot, as in the debug window both (populated and empty) buffers are in slot 0.

NOTE: this way of loading data to constant buffer worked before I switched to using Toolkit, but then the device was explicitly created with SwapChain. I am not so experienced to tell if it may make any difference.

enter image description here

In my effect file I have defined the buffer as

cbuffer ConstantBuffer : register(b0)
{
    float slideX;
    float sinPi075;
    float cosPi075;
    float scaleK;
}

and in the main program

[StructLayout(LayoutKind.Explicit, Size = 16)]
struct GS_CONSTANT_BUF_DATA
{
    [FieldOffset(0)]
    public float slideX;
    [FieldOffset(4)]
    public float sinPi075;
    [FieldOffset(8)]
    public float cosPi075;
    [FieldOffset(12)]
    public float scaleK;
};

followed by

private SharpDX.Direct3D11.Buffer _constantBuffer;
private GS_CONSTANT_BUF_DATA constData;
private int sizeOfconstData;
private SharpDX.Direct3D11.Device _device;
private void InitializeConstantBuffer()
{
    System.Diagnostics.Debug.WriteLine("InitializeConstantBuffer");
    constData = new GS_CONSTANT_BUF_DATA
    {
        slideX = 0.0f,
        sinPi075 = (float)Math.Sin(Math.PI * 0.75),
        cosPi075 = (float)Math.Cos(Math.PI * 0.75),
        scaleK = 0.003f
    };
    _device = (SharpDX.Direct3D11.Device)GraphicsDevice.MainDevice;
    sizeOfconstData = Utilities.SizeOf<GS_CONSTANT_BUF_DATA>();
    _constantBuffer = new SharpDX.Direct3D11.Buffer(
                                       _device
                                     , sizeOfconstData
                                     , ResourceUsage.Default
                                     , BindFlags.ConstantBuffer
                                     , CpuAccessFlags.None
                                     , ResourceOptionFlags.None
                                     , 0);
    _device.ImmediateContext.GeometryShader.SetConstantBuffer(0, _constantBuffer);
    _device.ImmediateContext.UpdateSubresource(ref constData, _constantBuffer);
}

Draw method in the main program

  protected override void Draw(GameTime gameTime)
    {
 GraphicsDevice.Clear(Color.CornflowerBlue);
 for (int i = 0; i < technique.Passes.Count; ++i)
    {
     _device.ImmediateContext.GeometryShader.SetConstantBuffer(0, _constantBuffer);
    _chartGeometry.Draw(
                        GraphicsDevice
                      , SharpDX.Toolkit.Graphics.PrimitiveType.LineList
                      , technique.Passes[i]);
    }
}

And the Draw method associated with _chartGeometry

 public void Draw(GraphicsDevice graphicsDevice, PrimitiveType primitiveType, EffectPass pass)
    {
        if (pass != null)
            pass.Apply();

        // Setup the Vertex Buffer
        graphicsDevice.SetVertexBuffer(0, vertexBuffer);

        // Setup the Vertex Buffer Input layout
        graphicsDevice.SetVertexInputLayout(InputLayout);

        graphicsDevice.Draw(primitiveType, 4, 0);
    }

I have also tried changing buffer to dynamic, and hence, changing UpdateSubresource to Map/Unmap. The result is the same, see creen below, this time obj:16 (has data) and obj:8 (does not).

enter image description here

and while debuging GeometryShader locals show enter image description here

\$\endgroup\$
5
  • \$\begingroup\$ I have a solution, will post it soon somewhere. A long description might be too long for stackexchange.com so I will post a link. \$\endgroup\$
    – MPękalski
    Apr 13, 2014 at 23:19
  • \$\begingroup\$ As the effect is handling all the constant buffers, why don't you update the variable slideX...etc. directly on the effect? \$\endgroup\$
    – xoofx
    Apr 14, 2014 at 1:12
  • \$\begingroup\$ @MPękalski Please refrain from having all content off-site as it more often than not rots and makes the answer unusable. You could link for in-depth elaborations, but the contents of the answer itself should stand on its own. \$\endgroup\$ Apr 14, 2014 at 6:20
  • \$\begingroup\$ @LarsViklund - I have just posted short soluton \$\endgroup\$
    – MPękalski
    Apr 14, 2014 at 17:21
  • \$\begingroup\$ @xoofx - sorry, I am just learning and I do not know what do you exactly mean by 'directly on the effect', is that what I have done (see the answer below)? \$\endgroup\$
    – MPękalski
    Apr 14, 2014 at 17:22

2 Answers 2

3
\$\begingroup\$

When using an Effect in the Toolkit (which is similar to the XNA Effect or the native D3D11 Effect API), you are not suppose to access directly the constant buffer but instead setting parameters directly on the effect:

_effect.Parameters["slideX"].SetValue(0.0f);
_effect.Parameters["sinPi075"].SetValue((float)Math.Sin(Math.PI * 0.75));
_effect.Parameters["cosPi075"].SetValue((float)Math.Cos(Math.PI * 0.75));
_effect.Parameters["scaleK"].SetValue(0.003f);
_effect.Apply();

The effect is automatically managing to update the constant buffer, upload it if it changes since last apply...etc. Though you can still update the constant buffer directly as you did.

\$\endgroup\$
2
  • \$\begingroup\$ Thank you for the explanation. Both ways work like charm. Is there any performance advantage of using one over the other? \$\endgroup\$
    – MPękalski
    Apr 15, 2014 at 18:28
  • \$\begingroup\$ Found the answer myself, gamedev.stackexchange.com/questions/40643/… \$\endgroup\$
    – MPękalski
    Apr 15, 2014 at 20:52
0
\$\begingroup\$

After investingating the source of the SharpDX.Toolkit I found out that all contant buffers are cleared if they are not dirty. So, the solution was to create a constant buffer on the effect, and make it dirty, see code below.

compiledEffect = (new EffectCompiler()).CompileFromFile(
                                 @"Content\MiniTri - Copy.fx"
                                 , EffectCompilerFlags.Debug 
                                  |EffectCompilerFlags.SkipOptimization
                                  |EffectCompilerFlags.WarningsAreErrors
                                 );
_effect = new Effect(GraphicsDevice, compiledEffect.EffectData);

constData = new GS_CONSTANT_BUF_DATA
{
    slideX = 0.0f,
    sinPi075 = (float)Math.Sin(Math.PI * 0.75),
    cosPi075 = (float)Math.Cos(Math.PI * 0.75),
    scaleK = 0.003f
};

_effect.ConstantBuffers[0].Set<GS_CONSTANT_BUF_DATA>(0, constData);
_effect.ConstantBuffers[0].IsDirty = true;
\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .