Skip to content

Commit

Permalink
Added PrimitiveBatch for drawing user primitives.
Browse files Browse the repository at this point in the history
Also now set debug object names for all D3D resources (for PIX and debug layer leak reporting)

PrimitiveBatch 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.
  • Loading branch information
ShawnHargreaves_cp authored and ShawnHargreaves_cp committed Oct 12, 2012
1 parent f887115 commit 38f1e61
Show file tree
Hide file tree
Showing 18 changed files with 652 additions and 59 deletions.
2 changes: 2 additions & 0 deletions DirectXTK_Desktop_2010.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
<ClInclude Include="Inc\GeometricPrimitive.h" />
<ClInclude Include="Inc\ScreenGrab.h" />
<ClInclude Include="Inc\SpriteBatch.h" />
<ClInclude Include="Inc\PrimitiveBatch.h" />
<ClInclude Include="Inc\SpriteFont.h" />
<ClInclude Include="Inc\VertexTypes.h" />
<ClInclude Include="Inc\WICTextureLoader.h" />
Expand Down Expand Up @@ -58,6 +59,7 @@
<ClCompile Include="Src\ScreenGrab.cpp" />
<ClCompile Include="Src\SkinnedEffect.cpp" />
<ClCompile Include="Src\SpriteBatch.cpp" />
<ClCompile Include="Src\PrimitiveBatch.cpp" />
<ClCompile Include="Src\SpriteFont.cpp" />
<ClCompile Include="Src\VertexTypes.cpp" />
<ClCompile Include="Src\WICTextureLoader.cpp" />
Expand Down
6 changes: 6 additions & 0 deletions DirectXTK_Desktop_2010.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@
<ClInclude Include="Inc\SpriteBatch.h">
<Filter>Inc</Filter>
</ClInclude>
<ClInclude Include="Inc\PrimitiveBatch.h">
<Filter>Inc</Filter>
</ClInclude>
<ClInclude Include="Inc\SpriteFont.h">
<Filter>Inc</Filter>
</ClInclude>
Expand Down Expand Up @@ -83,6 +86,9 @@
<ClCompile Include="Src\SpriteBatch.cpp">
<Filter>Src</Filter>
</ClCompile>
<ClCompile Include="Src\PrimitiveBatch.cpp">
<Filter>Src</Filter>
</ClCompile>
<ClCompile Include="Src\SpriteFont.cpp">
<Filter>Src</Filter>
</ClCompile>
Expand Down
2 changes: 2 additions & 0 deletions DirectXTK_Desktop_2012.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
<ClInclude Include="Inc\GeometricPrimitive.h" />
<ClInclude Include="Inc\ScreenGrab.h" />
<ClInclude Include="Inc\SpriteBatch.h" />
<ClInclude Include="Inc\PrimitiveBatch.h" />
<ClInclude Include="Inc\SpriteFont.h" />
<ClInclude Include="Inc\VertexTypes.h" />
<ClInclude Include="Inc\WICTextureLoader.h" />
Expand Down Expand Up @@ -58,6 +59,7 @@
<ClCompile Include="Src\ScreenGrab.cpp" />
<ClCompile Include="Src\SkinnedEffect.cpp" />
<ClCompile Include="Src\SpriteBatch.cpp" />
<ClCompile Include="Src\PrimitiveBatch.cpp" />
<ClCompile Include="Src\SpriteFont.cpp" />
<ClCompile Include="Src\VertexTypes.cpp" />
<ClCompile Include="Src\WICTextureLoader.cpp" />
Expand Down
6 changes: 6 additions & 0 deletions DirectXTK_Desktop_2012.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@
<ClInclude Include="Inc\SpriteBatch.h">
<Filter>Inc</Filter>
</ClInclude>
<ClInclude Include="Inc\PrimitiveBatch.h">
<Filter>Inc</Filter>
</ClInclude>
<ClInclude Include="Inc\SpriteFont.h">
<Filter>Inc</Filter>
</ClInclude>
Expand Down Expand Up @@ -83,6 +86,9 @@
<ClCompile Include="Src\SpriteBatch.cpp">
<Filter>Src</Filter>
</ClCompile>
<ClCompile Include="Src\PrimitiveBatch.cpp">
<Filter>Src</Filter>
</ClCompile>
<ClCompile Include="Src\SpriteFont.cpp">
<Filter>Src</Filter>
</ClCompile>
Expand Down
2 changes: 2 additions & 0 deletions DirectXTK_Windows8.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
<ClInclude Include="Inc\GeometricPrimitive.h" />
<ClInclude Include="Inc\ScreenGrab.h" />
<ClInclude Include="Inc\SpriteBatch.h" />
<ClInclude Include="Inc\PrimitiveBatch.h" />
<ClInclude Include="Inc\SpriteFont.h" />
<ClInclude Include="Inc\VertexTypes.h" />
<ClInclude Include="Inc\WICTextureLoader.h" />
Expand Down Expand Up @@ -68,6 +69,7 @@
<ClCompile Include="Src\ScreenGrab.cpp" />
<ClCompile Include="Src\SkinnedEffect.cpp" />
<ClCompile Include="Src\SpriteBatch.cpp" />
<ClCompile Include="Src\PrimitiveBatch.cpp" />
<ClCompile Include="Src\SpriteFont.cpp" />
<ClCompile Include="Src\VertexTypes.cpp" />
<ClCompile Include="Src\WICTextureLoader.cpp" />
Expand Down
6 changes: 6 additions & 0 deletions DirectXTK_Windows8.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@
<ClInclude Include="Inc\SpriteBatch.h">
<Filter>Inc</Filter>
</ClInclude>
<ClInclude Include="Inc\PrimitiveBatch.h">
<Filter>Inc</Filter>
</ClInclude>
<ClInclude Include="Inc\SpriteFont.h">
<Filter>Inc</Filter>
</ClInclude>
Expand Down Expand Up @@ -83,6 +86,9 @@
<ClCompile Include="Src\SpriteBatch.cpp">
<Filter>Src</Filter>
</ClCompile>
<ClCompile Include="Src\PrimitiveBatch.cpp">
<Filter>Src</Filter>
</ClCompile>
<ClCompile Include="Src\SpriteFont.cpp">
<Filter>Src</Filter>
</ClCompile>
Expand Down
142 changes: 142 additions & 0 deletions Inc/PrimitiveBatch.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
//--------------------------------------------------------------------------------------
// File: PrimitiveBatch.h
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// http://go.microsoft.com/fwlink/?LinkId=248929
//--------------------------------------------------------------------------------------

#pragma once

#include <d3d11.h>
#include <memory.h>
#include <memory>

#pragma warning(push)
#pragma warning(disable: 4005)
#include <stdint.h>
#pragma warning(pop)


namespace DirectX
{
namespace Internal
{
// Base class, not to be used directly: clients should access this via the derived PrimitiveBatch<T>.
class PrimitiveBatchBase
{
protected:
PrimitiveBatchBase(_In_ ID3D11DeviceContext* deviceContext, size_t maxIndices, size_t maxVertices, size_t vertexSize);
PrimitiveBatchBase(PrimitiveBatchBase&& moveFrom);
PrimitiveBatchBase& operator= (PrimitiveBatchBase&& moveFrom);
virtual ~PrimitiveBatchBase();

public:
// Begin/End a batch of primitive drawing operations.
void Begin();
void End();

protected:
// Internal, untyped drawing method.
void Draw(D3D11_PRIMITIVE_TOPOLOGY topology, bool isIndexed, _In_opt_count_(indexCount) uint16_t const* indices, size_t indexCount, size_t vertexCount, _Out_ void** pMappedVertices);

private:
// Private implementation.
class Impl;

std::unique_ptr<Impl> pImpl;

// Prevent copying.
PrimitiveBatchBase(PrimitiveBatchBase const&);
PrimitiveBatchBase& operator= (PrimitiveBatchBase const&);
};
}


// Template makes the API typesafe, eg. PrimitiveBatch<VertexPositionColor>.
template<typename TVertex>
class PrimitiveBatch : public Internal::PrimitiveBatchBase
{
static const size_t DefaultBatchSize = 2048;

public:
PrimitiveBatch(_In_ ID3D11DeviceContext* deviceContext, size_t maxIndices = DefaultBatchSize * 3, size_t maxVertices = DefaultBatchSize)
: PrimitiveBatchBase(deviceContext, maxIndices, maxVertices, sizeof(TVertex))
{ }

PrimitiveBatch(PrimitiveBatch&& moveFrom)
: PrimitiveBatchBase(std::move(moveFrom))
{ }

PrimitiveBatch& operator= (PrimitiveBatch&& moveFrom)
{
PrimitiveBatchBase::operator=(std::move(moveFrom));
return *this;
}


// Similar to the D3D9 API DrawPrimitiveUP.
void Draw(D3D11_PRIMITIVE_TOPOLOGY topology, _In_reads_(vertexCount) TVertex const* vertices, size_t vertexCount)
{
void* mappedVertices;

PrimitiveBatchBase::Draw(topology, false, nullptr, 0, vertexCount, &mappedVertices);

memcpy(mappedVertices, vertices, vertexCount * sizeof(TVertex));
}


// Similar to the D3D9 API DrawIndexedPrimitiveUP.
void DrawIndexed(D3D11_PRIMITIVE_TOPOLOGY topology, _In_reads_(indexCount) uint16_t const* indices, size_t indexCount, _In_reads_(vertexCount) TVertex const* vertices, size_t vertexCount)
{
void* mappedVertices;

PrimitiveBatchBase::Draw(topology, true, indices, indexCount, vertexCount, &mappedVertices);

memcpy(mappedVertices, vertices, vertexCount * sizeof(TVertex));
}


void DrawLine(TVertex const& v1, TVertex const& v2)
{
TVertex* mappedVertices;

PrimitiveBatchBase::Draw(D3D11_PRIMITIVE_TOPOLOGY_LINELIST, false, nullptr, 0, 2, reinterpret_cast<void**>(&mappedVertices));

mappedVertices[0] = v1;
mappedVertices[1] = v2;
}


void DrawTriangle(TVertex const& v1, TVertex const& v2, TVertex const& v3)
{
TVertex* mappedVertices;

PrimitiveBatchBase::Draw(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST, false, nullptr, 0, 3, reinterpret_cast<void**>(&mappedVertices));

mappedVertices[0] = v1;
mappedVertices[1] = v2;
mappedVertices[2] = v3;
}


void DrawQuad(TVertex const& v1, TVertex const& v2, TVertex const& v3, TVertex const& v4)
{
static const uint16_t quadIndices[] = { 0, 1, 2, 0, 2, 3 };

TVertex* mappedVertices;

PrimitiveBatchBase::Draw(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST, true, quadIndices, 6, 4, reinterpret_cast<void**>(&mappedVertices));

mappedVertices[0] = v1;
mappedVertices[1] = v2;
mappedVertices[2] = v3;
mappedVertices[3] = v4;
}
};
}
95 changes: 91 additions & 4 deletions Readme.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ DirectXTK - the DirectX Tool Kit

Copyright (c) Microsoft Corporation. All rights reserved.

October 2, 2012
October 12, 2012

This package contains the "DirectX Tool Kit", a collection of helper classes for
writing Direct3D 11 C++ code for Windows Store apps, Windows 8 Win32 desktop
Expand All @@ -26,6 +26,7 @@ Inc\
SpriteBatch.h - simple & efficient 2D sprite rendering
SpriteFont.h - bitmap based text rendering
Effects.h - set of built-in shaders for common rendering tasks
PrimitiveBatch.h - simple and efficient way to draw user primitives
GeometricPrimitive.h - draws basic shapes such as cubes and spheres
CommonStates.h - factory providing commonly used D3D state objects
VertexTypes.h - structures for commonly used vertex data formats
Expand All @@ -45,6 +46,7 @@ All content and source code for this package are bound to the Microsoft Public L
http://go.microsoft.com/fwlink/?LinkId=248929



-----------
SpriteBatch
-----------
Expand Down Expand Up @@ -332,6 +334,88 @@ Further reading:



--------------
PrimitiveBatch
--------------

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.

To initialize a PrimitiveBatch for drawing VertexPositionColor data:

std::unique_ptr<PrimitiveBatch<VertexPositionColor>> primitiveBatch(new PrimitiveBatch<VertexPositionColor>(deviceContext));

To 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);

To draw a line:

basicEffect->Apply(deviceContext);
deviceContext->IASetInputLayout(inputLayout.Get());

primitiveBatch->Begin();
primitiveBatch->DrawLine(VertexPositionColor(...), VertexPositionColor(...));
primitiveBatch->End();

PrimitiveBatch provides five drawing methods:

- 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.



------------------
GeometricPrimitive
------------------
Expand Down Expand Up @@ -529,9 +613,9 @@ Further reading:



----------------
----------
ScreenGrab
----------------
----------

ScreenGrab.h contains routines for writing out a texture, usually a render-target,
to either a .dds file or a WIC-supported bitmap file (BMP, JPEG, PNG, TIFF, etc.).
Expand Down Expand Up @@ -567,7 +651,6 @@ Capturing a screenshot:
hr = SaveWICTextureToFile( pContext, backBuffer, GUID_ContainerFormatBmp, L"SCREENSHOT.BMP" ) );
}


Threading model:

Since these functions use ID3D11DeviceContext, they are not thread-safe.
Expand All @@ -583,6 +666,10 @@ Further reading:
RELEASE HISTORY
---------------

October 12, 2012
Added PrimitiveBatch for drawing user primitives
Debug object names for all D3D resources (for PIX and debug layer leak reporting)

October 2, 2012
Added ScreenGrab module
Added CreateGeoSphere for drawing a geodesic sphere
Expand Down
Loading

0 comments on commit 38f1e61

Please sign in to comment.