This is a helper for easily and efficiently drawing dynamically generated geometry such as lines or trianges. It fills the same role as the legacy D3D9 APIs DrawPrimitiveUP and DrawIndexedPrimitiveUP. Dynamic submission is a highly effective pattern for drawing procedural geometry, and convenient for debug rendering, but is not nearly as efficient as static vertex buffers. Excessive dynamic submission is a common source of performance problems in apps.
PrimitiveBatch manages the vertex and index buffers for you, using DISCARD and NO_OVERWRITE hints to avoid stalling the GPU pipeline. It automatically merges adjacent draw requests, so if you call DrawLine 100 times in a row, only a single GPU draw call will be generated.
PrimitiveBatch is responsible for setting the vertex buffer, index buffer, and primitive topology, then issuing the final draw call. Unlike the higher level SpriteBatch helper, it does not provide shaders, set the input layout, or set any state objects. PrimitiveBatch is often used in conjunction with BasicEffect and the structures from VertexTypes.h, but it can work with any other shader or vertex formats of your own.
Initialize a PrimitiveBatch for drawing VertexPositionColor data
Set up a suitable BasicEffect and input layout
Draw a line
PrimitiveBatch provides five drawing methods:
Optimization
For best performance, draw as much as possible inside the fewest separate Begin/End blocks. This will reduce overhead and maximize potential for batching.
The PrimitiveBatch constructor allows you to specify what size index and vertex buffers to allocate. You may want to tweak these values to fit your workload, or if you only intend to draw non-indexed geometry, specify maxIndices = 0 to entirely skip creating the index buffer.
Threading model
Each PrimitiveBatch instance only supports drawing from one thread at a time, but you can simultaneously submit primitives on multiple threads if you create a separate PrimitiveBatch instance per D3D11 deferred context.
PrimitiveBatch manages the vertex and index buffers for you, using DISCARD and NO_OVERWRITE hints to avoid stalling the GPU pipeline. It automatically merges adjacent draw requests, so if you call DrawLine 100 times in a row, only a single GPU draw call will be generated.
PrimitiveBatch is responsible for setting the vertex buffer, index buffer, and primitive topology, then issuing the final draw call. Unlike the higher level SpriteBatch helper, it does not provide shaders, set the input layout, or set any state objects. PrimitiveBatch is often used in conjunction with BasicEffect and the structures from VertexTypes.h, but it can work with any other shader or vertex formats of your own.
Initialize a PrimitiveBatch for drawing VertexPositionColor data
std::unique_ptr<PrimitiveBatch<VertexPositionColor>> primitiveBatch(new PrimitiveBatch<VertexPositionColor>(deviceContext));
Set up a suitable BasicEffect and input layout
std::unique_ptr<BasicEffect> basicEffect(new BasicEffect(device)); basicEffect->SetProjection(XMMatrixOrthographicOffCenterRH(0, screenHeight, screenWidth, 0, 0, 1)); basicEffect->SetVertexColorEnabled(true); void const* shaderByteCode; size_t byteCodeLength; basicEffect->GetVertexShaderBytecode(&shaderByteCode, &byteCodeLength); ComPtr<ID3D11InputLayout> inputLayout; device->CreateInputLayout(VertexPositionColor::InputElements, VertexPositionColor::InputElementCount, shaderByteCode, byteCodeLength, &inputLayout);
Draw a line
basicEffect->Apply(deviceContext); deviceContext->IASetInputLayout(inputLayout.Get()); primitiveBatch->Begin(); primitiveBatch->DrawLine(VertexPositionColor(...), VertexPositionColor(...)); primitiveBatch->End();
- DrawLine(v1, v2)
- DrawTriangle(v1, v2, v3)
- DrawQuad(v1, v2, v3, v4)
- Draw(topology, vertices, vertexCount)
- DrawIndexed(topology, indices, indexCount, vertices, vertexCount)
Optimization
For best performance, draw as much as possible inside the fewest separate Begin/End blocks. This will reduce overhead and maximize potential for batching.
The PrimitiveBatch constructor allows you to specify what size index and vertex buffers to allocate. You may want to tweak these values to fit your workload, or if you only intend to draw non-indexed geometry, specify maxIndices = 0 to entirely skip creating the index buffer.
Threading model
Each PrimitiveBatch instance only supports drawing from one thread at a time, but you can simultaneously submit primitives on multiple threads if you create a separate PrimitiveBatch instance per D3D11 deferred context.