DirectX 11 States in HLSL or C++ D3DAPI?

Started by
2 comments, last by Kurt-olsson 11 years, 6 months ago
I have a question about setting states in DirectX11.
Is it best to do this in HLSL or in C++ D3dAPI?

Today i use this method each frame. I don´t like using functions that is called create on each frame.
Is this a bad idea of using this method?
I need to be able to update the states whenever i need in the game. especially alpha mode.

[source lang="java"]void UpdateStates(ID3D11Device* dev, bool alpha) {

D3D11_RASTERIZER_DESC rd;
rd.FillMode = D3D11_FILL_SOLID;
rd.CullMode = D3D11_CULL_BACK; //DENNA MÅSTE SÄTTAS TILL NONE, VISA BÅDA FACES!
rd.FrontCounterClockwise = FALSE;
rd.DepthClipEnable = TRUE;
rd.ScissorEnable = FALSE;
rd.AntialiasedLineEnable = FALSE;
rd.MultisampleEnable = FALSE;
rd.DepthBias = 0;
rd.DepthBiasClamp = 0.0f;
rd.SlopeScaledDepthBias = 0.0f;

dev->CreateRasterizerState(&rd, &pRS);

D3D11_SAMPLER_DESC sd;
sd.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
sd.MaxAnisotropy = 16;
sd.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
sd.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
sd.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
sd.BorderColor[0] = 0.0f;
sd.BorderColor[1] = 0.0f;
sd.BorderColor[2] = 0.0f;
sd.BorderColor[3] = 0.0f;
sd.MinLOD = 0.0f;
sd.MaxLOD = FLT_MAX;
sd.MipLODBias = 0.0f;

dev->CreateSamplerState(&sd, &pSS);

D3D11_BLEND_DESC bd;
bd.RenderTarget[0].BlendEnable = alpha;
bd.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
bd.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
bd.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
bd.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
bd.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
bd.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
bd.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
bd.IndependentBlendEnable = FALSE;
bd.AlphaToCoverageEnable = FALSE;

dev->CreateBlendState(&bd, &pBS);
}[/source]
Advertisement
I'd prefer to do them from the C++ API (it gives more flexibility for use of different states with the same shaders) but you shouldn't create them every frame. Creating resources (and states are resources) at runtime is expensive. Instead what you should do is create common states at startup time; e.g. for depth/stencil you'll probably want at least one with normal depth testing and writing, one with testing enabled and writing disabled, and one with both testing and writing disabled.

Another option involves taking advantage of the fact that you can have up to 4096 of each state type. So you declare an array of 4096 of each, construct a bitwise mask that defines the settings you want in your state, use that as an index into the array, and if the corresponding state is NULL then create it on demand, otherwise just reuse the one that's already there.

See http://msdn.microsoft.com/en-us/library/windows/desktop/bb205071%28v=vs.85%29.aspx#Performance_Considerations (for 10 but still relevant to 11) for more info.

Direct3D has need of instancing, but we do not. We have plenty of glVertexAttrib calls.

Setting particular states is not interchangeable between HLSL and C++. This means that it's not possible to enable/disable/change e.g. culling mode or other in HLSL code, but the draw calls are rendered with whatever rasterizer state you have currently enabled when the draw call is submitted.

You should call CreateSamplerState and CreateBlendState only once for each state set you want to use at load time, and then for each frame, reuse the state objects you created.
Ahhh i see. Of course, i create one state that is alpha and one that is not and set those objects if i want to change modes!
I feel so stupid, but sometimes you need someone to tell you what to do! =)

This topic is closed to new replies.

Advertisement