• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
caballero

DX11
Using multiple constant buffer

10 posts in this topic

Hi,
I've started to learn dx11 with the slimdx framework.
Currently i tried to use two constant buffer to update informations more frequent then other.

But with my current shader code I get some strange behaviour using the two constant buffers:
// cbuffer definition
struct ShaderLightBuffer
{
public Vector3 Ambient;
public float Alpha;
public Vector3 Diffuse;
public float Shininess;
public Vector3 Specular;
public float padding;
public Vector2 SpecularTextured;
public Vector2 padding2;
}

struct ShaderMatrixBuffer
{
public Matrix World;
public Matrix WorldViewProjection;
public Vector3 CameraPosition;
public float padding1;
}

// buffer initialization
_light_constant_buffer = new Buffer(Device, Marshal.SizeOf(typeof(ShaderLightBuffer)), ResourceUsage.Default, BindFlags.ConstantBuffer, CpuAccessFlags.None, ResourceOptionFlags.None, 0);
_matrix_constant_buffer = new Buffer(Device, Marshal.SizeOf(typeof(ShaderMatrixBuffer)), ResourceUsage.Default, BindFlags.ConstantBuffer, CpuAccessFlags.None, ResourceOptionFlags.None, 0);

// render logic
ImmediateContext.InputAssembler.InputLayout = _input_layout;
ImmediateContext.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList;

ImmediateContext.InputAssembler.SetVertexBuffers(0, _buffer_bindings.ToArray());
ImmediateContext.VertexShader.Set(_vertex_shader);

ImmediateContext.VertexShader.SetConstantBuffer(_matrix_constant_buffer, 0);
ImmediateContext.VertexShader.SetConstantBuffer(_light_constant_buffer, 1);

ImmediateContext.Rasterizer.SetViewports(Engine.DeviceManager.Viewport);

ImmediateContext.PixelShader.Set(_pixel_shader);
ImmediateContext.PixelShader.SetConstantBuffer(_light_constant_buffer, 2);

ImmediateContext.OutputMerger.SetTargets(DepthBuffer, RenderTarget);

// .. set wvp, world, camera position to matrix buffer..
ShaderMatrixBuffer matrix_buffer = new ShaderMatrixBuffer();
matrix_buffer.WorldViewProjection = view_proj;
matrix_buffer.World = world_matrix;
matrix_buffer.CameraPosition = Engine.Camera.Eye;

// update matrix constant buffer
var matrix_stream = new DataStream(Marshal.SizeOf(typeof(ShaderMatrixBuffer)), true, true);
matrix_stream.Write(matrix_buffer);
matrix_stream.Position = 0;

ImmediateContext.UpdateSubresource(new DataBox(0, 0, matrix_stream), _matrix_constant_buffer, 0);
ImmediateContext.VertexShader.SetConstantBuffer(_matrix_constant_buffer, 0);

foreach (var material in Materials)
{
ShaderLightBuffer light_buffer = new ShaderLightBuffer();
light_buffer.Alpha = 1f;
light_buffer.Ambient = material.Ambient;
light_buffer.Diffuse = material.Diffuse;
light_buffer.Specular = material.Specular;
light_buffer.Shininess = (int)material.Shininess;
light_buffer.SpecularTextured = new Vector2 (0);

if (!string.IsNullOrEmpty(material.TextureFilename))
{
light_buffer.SpecularTextured = new Vector2(1);
if (_shader_resource == null)
{
var texture = Texture2D.FromFile(Device, Path.Combine(material.Path, material.TextureFilename));
_shader_resource = new ShaderResourceView(Device, texture);
}

ImmediateContext.PixelShader.SetShaderResource(_shader_resource, 0);
}

ImmediateContext.PixelShader.SetSampler(_sampler_state, 0);

var light_stream = new DataStream(Marshal.SizeOf(typeof(ShaderLightBuffer)), true, true);
light_stream.Write(light_buffer);
light_stream.Position = 0;

ImmediateContext.UpdateSubresource(new DataBox(0, 0, light_stream), _light_constant_buffer, 0);

ImmediateContext.VertexShader.SetConstantBuffer(_light_constant_buffer, 1);
ImmediateContext.VertexShader.SetConstantBuffer(_light_constant_buffer, 2);

ImmediateContext.Draw(_vertices_count[i], 0);
}
// end render logic
Alright, I hope this code is straight forward, just setting all infos for the pipeline stages, updating the general constant buffer and the cbuffer
for each material used for the geometry.

Now the odd part - shader code
PS_INPUT VS( VS_INPUT input )
{
PS_INPUT output;

// Transform the position into world space for lighting, and projected space
float4 vPosWorld = mul( float4(input.position,1), World );
output.position = mul( float4(input.position,1), WorldViewProjection );

// pass texture coordinate
output.texcoord = input.texcoord;

// transform normal into world space for lighting
float3 normal_world = mul( input.normal, (float3x3) World);
float3 light_vector = normalize( LightPosition - vPosWorld.xyz );

// compute the ambient and diffuse components of illumination
output.color.rgb = LightColor * MaterialAmbient;
output.color.rgb += LightColor * MaterialDiffuse * saturate( dot( light_vector, normal_world ) );

if( SpecularTextured.x > 0)
{
float3 camera = normalize( vPosWorld.xyz - CameraPosition );
float3 reflection = reflect ( light_vector, normal_world );
float phone_value = saturate( dot( reflection, camera ) );
output.color.rgb += MaterialSpecular * pow( phone_value, MaterialShininess );
}

// odd things happens if i comment the next line -> [7480] D3D11: WARNING: ID3D11DeviceContext::Draw: The size of the Constant Buffer at slot 1 of the Vertex Shader unit is too small (64 bytes provided, 144 bytes, at least, expected). This is OK, as out-of-bounds reads are defined to return 0. It is also possible the developer knows the missing data will not be used anyway. This is only a problem if the developer actually intended to bind a sufficiently large Constant Buffer for what the shader expects. [ EXECUTION WARNING #351: DEVICE_DRAW_CONSTANT_BUFFER_TOO_SMALL ]
output.color.rgb = MaterialDiffuse;
output.color.a = MaterialShininess;

return output;
}

float4 PS( PS_INPUT input ) : SV_Target
{
float4 output = input.color;
//// Sample and modulate the texture
if ( SpecularTextured.y > 0 )
output.rgb *= MeshTexture.Sample( samLinear, input.texcoord );
return output;
}
If I set the color values to diffuse the in the vertex shader it draws my geometry correctly with the defined color.
But commenting out the color assignment (since this line was used for debugging), will give me the following warning:
[7480] D3D11: WARNING: ID3D11DeviceContext::Draw: The size of the Constant Buffer at slot 1 of the Vertex Shader unit is too small (64 bytes provided, 144 bytes, at least, expected). This is OK, as out-of-bounds reads are defined to return 0. It is also possible the developer knows the missing data will not be used anyway. This is only a problem if the developer actually intended to bind a sufficiently large Constant Buffer for what the shader expects. [ EXECUTION WARNING #351: DEVICE_DRAW_CONSTANT_BUFFER_TOO_SMALL ]

This happens also if I use UpdateSubResource method to update both constant buffers.
It seems that the second constant buffer update overwrites also the first constant buffer.

I wanted to ask how to handle multiple constant buffer updates? Am I missing something?
0

Share this post


Link to post
Share on other sites
When you have multiple constant buffers, you have to put them in separate slots. i don't know how to use slimdx, but in regular dx11, you can set the vertex's constant buffer by calling VSSetConstantBuffers of the device context, and setting the second parameter as 0 for the first constant buffer, and 1 for the second. If the vertex and pixel shader share a constant buffer, you will have to bind the same constant buffer separately to each shader, using VSSetConstantBuffers and VSSetConstantBuffers.
2

Share this post


Link to post
Share on other sites
Thanks for the quick response!
I think you meant VSSetConstantBuffer and PSSetConstantBuffer in the last sentence.

I've replaced setting both cbuffer at the same time

[color=#660066]ImmediateContext[/color][color=#666600].[/color][color=#660066]VertexShader[/color][color=#666600].[/color][color=#660066]SetConstantBuffers[/color][color=#666600]([/color][color=#000088]new[/color][color=#666600][][/color][color=#000000] [/color][color=#666600]{[/color][color=#000000] _matrix_constant_buffer[/color][color=#666600],[/color][color=#000000] _light_constant_buffer [/color][color=#666600]},[/color][color=#000000] [/color][color=#006666]0[/color][color=#666600],[/color][color=#006666]2[/color][color=#666600]);[/color]

with

ImmediateContext.VertexShader.SetConstantBuffer(_matrix_constant_buffer, 0);
ImmediateContext.VertexShader.SetConstantBuffer(_light_constant_buffer, 1);

and also set the cbuffer to the pixel shader
ImmediateContext.PixelShader.SetConstantBuffer(_light_constant_buffer, 1);

I also tried to attach - : register(cbx) to the cbuffer declaration in the shader code.
but the result is the same error message [img]http://public.gamedev.net//public/style_emoticons/default/sad.png[/img]

Alright, I tried the same code with the sharpdx framework with the same ouput.. Edited by caballero
0

Share this post


Link to post
Share on other sites
sorry it didn't work for you, but one other thing, iis (as far as i know) you have to put each buffer in it's own slot, even if two shaders use the same buffer, they should go into separate slots, so when you bind your pixel shaders buffer, you should try changing the '1' to a '2'

also, can you show the structure of your constant buffers?
1

Share this post


Link to post
Share on other sites
The structure of the constant buffer is


[code]cbuffer Matrixbuffer : register(cb0)
{
matrix World;
matrix WorldViewProjection;
float3 CameraPosition;
float padding;
};
[/code]
and

[code]cbuffer LightBuffer : register(cb1)
{
float3 MaterialAmbient; // Material's ambient color
float MaterialAlpha;
float3 MaterialDiffuse; // Material's diffuse color
float MaterialShininess;
float3 MaterialSpecular; // Material's specular color
float padding2;
float2 SpecularTextured;
float2 padding3;
};[/code]

It seems to me that updating the constant buffer in the foreach loop overwrites the first "global" constant buffer.
Could there be something that I am missing?

Would a pix run file help you to get more information out of it?
0

Share this post


Link to post
Share on other sites
actually, could you post the constant buffers in your main app?

This might not be the problem, but just check it out. Are you making sure you are packaging your constant buffers correctly in your app? the shader takes 16 byte chunks for the constant buffer, so if you have a variable that's split between two chunks, it will cause problems. float variables are 4 bytes, float3's are 12 bytes, matrices are 16 bytes. I see you have it aligned correctly in the shader, so i'm guessing it's probably the same for your app, but double check.
1

Share this post


Link to post
Share on other sites
I just noticed you are not setting your constant buffers after you change them. I think you have to reset them every time they change. also, try using update subresource instead:
[code]ImmediateContext->UpdateSubresource( light_buffer, 0, NULL, &_light_constant_buffer, 0, 0 );[/code]
Somethng like that anyway
0

Share this post


Link to post
Share on other sites
[quote name='caballero' timestamp='1327867442' post='4907410']
[7480] D3D11: WARNING: ID3D11DeviceContext::Draw: The size of the Constant Buffer at slot 1 of the Vertex Shader unit is too small (64 bytes provided, 144 bytes, at least, expected). This is OK, as out-of-bounds reads are defined to return 0. It is also possible the developer knows the missing data will not be used anyway. This is only a problem if the developer actually intended to bind a sufficiently large Constant Buffer for what the shader expects. [ EXECUTION WARNING #351: DEVICE_DRAW_CONSTANT_BUFFER_TOO_SMALL ]
[/quote]

The error message has all the information about the problem. Your constant buffer bound at slot 1 has size of 64 bytes, but the shader is reading data from area outside of the 64 bytes area.

[left]This means that you have the light buffer bound to slot 1, but on the shader expects the matrix buffer to be at slot 1. You have to have same registers at the program side and at the shader side. Remember that the register indices are 0-based.[/left]

[left]Cheers![/left]
2

Share this post


Link to post
Share on other sites
Hi, I've updated all code parts in my previous posts.

Thx kauna for the hint since after changing the slots in the code no warnings or errors occur.

// I've set the following for slots for the buffers to be comprehensible
vs.setconstantbuffer(matrix_buffer, 1);
vs.setconstantbuffer(light_buffer, 0);
ps.setconstantbuffer(light_buffer, 2);

I thought that the cbuffers in the shader will be declared in sequential order since I'm defining first the Matrix cbuffer then the Light cbuffer. I tried to fixate that by setting : register(cb#).

Obviously i was wrong with this assumption.

Now it's all black (of course it is black, I think I am really learning dx the hard way) without any warnings thanks for your help!

Theoretically, if I define more cbuffers, how can I find out which slots they were assigned to?
0

Share this post


Link to post
Share on other sites
[quote name='caballero' timestamp='1327931547' post='4907621']
// I've set the following for slots for the buffers to be comprehensible
vs.setconstantbuffer(matrix_buffer, 1);
vs.setconstantbuffer(light_buffer, 0);
ps.setconstantbuffer(light_buffer, 2);
[/quote]

Hi, you may set the light_buffer to slot 0 for vertex shader and pixel shader. I assume that in the shader code you have probably slot 0 (both vs and ps) for the light_buffer?

You may use shader reflection API to extract information from the shaders (including which constant buffer is expected at which register ...)

Best regards!
0

Share this post


Link to post
Share on other sites
Thanks for info!

Additionally some further gamedev redirections:
how to find the constant buffer slots via shader reflection
[url="http://www.gamedev.net/topic/607104-d3d11shaderreflection-and-constant-buffer-slot/"]http://www.gamedev.net/topic/607104-d3d11shaderreflection-and-constant-buffer-slot/[/url]

some thoughts about UpdateSubResource vs Map/Unmap
[url="http://www.gamedev.net/topic/616350-dx11-fastest-way-to-update-a-constant-buffer-per-draw-call/"]http://www.gamedev.net/topic/616350-dx11-fastest-way-to-update-a-constant-buffer-per-draw-call/[/url]
0

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0

  • Similar Content

    • By YixunLiu
      Hi,
      I have a surface mesh and I want to use a cone to cut a hole on the surface mesh.
      Anybody know a fast method to calculate the intersected boundary of these two geometries?
       
      Thanks.
       
      YL
       
    • By hiya83
      Hi, I tried searching for this but either I failed or couldn't find anything. I know there's D11/D12 interop and there are extensions for GL/D11 (though not very efficient). I was wondering if there's any Vulkan/D11 or Vulkan/D12 interop?
      Thanks!
    • By lonewolff
      Hi Guys,
      I am just wondering if it is possible to acquire the address of the backbuffer if an API (based on DX11) only exposes the 'device' and 'context' pointers?
      Any advice would be greatly appreciated
    • By MarcusAseth
      bool InitDirect3D::Init() { if (!D3DApp::Init()) { return false; } //Additional Initialization //Disable Alt+Enter Fullscreen Toggle shortkey IDXGIFactory* factory; CreateDXGIFactory(__uuidof(IDXGIFactory), reinterpret_cast<void**>(&factory)); factory->MakeWindowAssociation(mhWindow, DXGI_MWA_NO_WINDOW_CHANGES); factory->Release(); return true; }  
      As stated on the title and displayed on the code above, regardless of it Alt+Enter still takes effect...
      I recall something from the book during the swapChain creation, where in order to create it one has to use the same factory used to create the ID3D11Device, therefore I tested and indeed using that same factory indeed it work.
      How is that one particular factory related to my window and how come the MakeWindowAssociation won't take effect with a newly created factory?
      Also what's even the point of being able to create this Factories if they won't work,?(except from that one associated with the ID3D11Device) 
    • By ProfL
      Can anyone recommend a wrapper for Direct3D 11 that is similarly simple to use as SFML? I don't need all the image formats etc. BUT I want a simple way to open a window, allocate a texture, buffer, shader.
  • Popular Now