D3D11: Added draw indirect support.

This commit is contained in:
Branimir Karadžić 2015-04-29 17:18:51 -07:00
parent 80b6202ec0
commit d763196407
5 changed files with 224 additions and 73 deletions

View file

@ -206,6 +206,7 @@ namespace bgfx
static const uint16_t invalidHandle = UINT16_MAX;
BGFX_HANDLE(DrawIndirectBufferHandle);
BGFX_HANDLE(DynamicIndexBufferHandle);
BGFX_HANDLE(DynamicVertexBufferHandle);
BGFX_HANDLE(FrameBufferHandle);
@ -869,6 +870,12 @@ namespace bgfx
///
const InstanceDataBuffer* allocInstanceDataBuffer(uint32_t _num, uint16_t _stride);
///
DrawIndirectBufferHandle createDrawIndirectBuffer(uint32_t _num);
///
void destroyDrawIndirectBuffer(DrawIndirectBufferHandle _handle);
/// Create shader from memory buffer.
ShaderHandle createShader(const Memory* _mem);
@ -1333,6 +1340,9 @@ namespace bgfx
/// Set instance data buffer for draw primitive.
void setInstanceDataBuffer(DynamicVertexBufferHandle _handle, uint32_t _startVertex, uint32_t _num);
///
void setDrawIndirectBuffer(DrawIndirectBufferHandle _handle, uint16_t _start = 0, uint16_t _num = UINT16_MAX);
/// Set program for draw primitive.
void setProgram(ProgramHandle _handle);

View file

@ -224,8 +224,9 @@
#define BGFX_BUFFER_NONE UINT8_C(0x00)
#define BGFX_BUFFER_COMPUTE_READ UINT8_C(0x01)
#define BGFX_BUFFER_COMPUTE_WRITE UINT8_C(0x02)
#define BGFX_BUFFER_ALLOW_RESIZE UINT8_C(0x04)
#define BGFX_BUFFER_INDEX32 UINT8_C(0x08)
#define BGFX_BUFFER_DRAW_INDIRECT UINT8_C(0x04)
#define BGFX_BUFFER_ALLOW_RESIZE UINT8_C(0x08)
#define BGFX_BUFFER_INDEX32 UINT8_C(0x10)
#define BGFX_BUFFER_COMPUTE_READ_WRITE (BGFX_BUFFER_COMPUTE_READ | BGFX_BUFFER_COMPUTE_WRITE)
///
@ -319,6 +320,7 @@
#define BGFX_CAPS_SWAP_CHAIN UINT64_C(0x0000000000000400)
#define BGFX_CAPS_HMD UINT64_C(0x0000000000000800)
#define BGFX_CAPS_INDEX32 UINT64_C(0x0000000000001000)
#define BGFX_CAPS_DRAW_INDIRECT UINT64_C(0x0000000000002000)
///
#define BGFX_CAPS_FORMAT_TEXTURE_NONE UINT8_C(0x00)

View file

@ -837,6 +837,7 @@ namespace bgfx
CAPS_FLAGS(BGFX_CAPS_SWAP_CHAIN),
CAPS_FLAGS(BGFX_CAPS_HMD),
CAPS_FLAGS(BGFX_CAPS_INDEX32),
CAPS_FLAGS(BGFX_CAPS_DRAW_INDIRECT),
#undef CAPS_FLAGS
};
@ -2308,6 +2309,18 @@ again:
return s_ctx->allocInstanceDataBuffer(_num, _stride);
}
DrawIndirectBufferHandle createDrawIndirectBuffer(uint32_t _num)
{
BGFX_CHECK_MAIN_THREAD();
return s_ctx->createDrawIndirectBuffer(_num);
}
void destroyDrawIndirectBuffer(DrawIndirectBufferHandle _handle)
{
BGFX_CHECK_MAIN_THREAD();
s_ctx->destroyDrawIndirectBuffer(_handle);
}
ShaderHandle createShader(const Memory* _mem)
{
BGFX_CHECK_MAIN_THREAD();
@ -2909,6 +2922,12 @@ again:
s_ctx->setInstanceDataBuffer(_handle, _startVertex, _num);
}
void setDrawIndirectBuffer(DrawIndirectBufferHandle _handle, uint16_t _start, uint16_t _num)
{
BGFX_CHECK_MAIN_THREAD();
s_ctx->setDrawIndirectBuffer(_handle, _start, _num);
}
void setProgram(ProgramHandle _handle)
{
BGFX_CHECK_MAIN_THREAD();
@ -2957,6 +2976,12 @@ again:
s_ctx->setBuffer(_stage, _handle, _access);
}
void setBuffer(uint8_t _stage, DrawIndirectBufferHandle _handle, Access::Enum _access)
{
BGFX_CHECK_MAIN_THREAD();
s_ctx->setBuffer(_stage, _handle, _access);
}
void setImage(uint8_t _stage, UniformHandle _sampler, TextureHandle _handle, uint8_t _mip, Access::Enum _access, TextureFormat::Enum _format)
{
BGFX_CHECK_MAIN_THREAD();

View file

@ -1072,6 +1072,8 @@ namespace bgfx
m_instanceDataOffset = 0;
m_instanceDataStride = 0;
m_numInstances = 1;
m_startDrawIndirect = 0;
m_numDrawIndirect = UINT16_MAX;
m_num = 1;
m_flags = BGFX_SUBMIT_EYE_FIRST;
m_scissor = UINT16_MAX;
@ -1079,6 +1081,7 @@ namespace bgfx
m_vertexDecl.idx = invalidHandle;
m_indexBuffer.idx = invalidHandle;
m_instanceDataBuffer.idx = invalidHandle;
m_drawIndirectBuffer.idx = invalidHandle;
for (uint32_t ii = 0; ii < BGFX_CONFIG_MAX_TEXTURE_SAMPLERS; ++ii)
{
@ -1100,6 +1103,8 @@ namespace bgfx
uint32_t m_instanceDataOffset;
uint16_t m_instanceDataStride;
uint16_t m_numInstances;
uint16_t m_startDrawIndirect;
uint16_t m_numDrawIndirect;
uint16_t m_num;
uint16_t m_scissor;
uint8_t m_submitFlags;
@ -1108,6 +1113,7 @@ namespace bgfx
VertexDeclHandle m_vertexDecl;
IndexBufferHandle m_indexBuffer;
VertexBufferHandle m_instanceDataBuffer;
DrawIndirectBufferHandle m_drawIndirectBuffer;
};
struct RenderCompute
@ -1381,6 +1387,13 @@ namespace bgfx
m_draw.m_instanceDataBuffer = _handle;
}
void setDrawIndirectBuffer(DrawIndirectBufferHandle _handle, uint16_t _start, uint16_t _num)
{
m_draw.m_startDrawIndirect = _start;
m_draw.m_numDrawIndirect = _num;
m_draw.m_drawIndirectBuffer = _handle;
}
void setProgram(ProgramHandle _handle)
{
m_key.m_program = _handle.idx;
@ -2496,6 +2509,36 @@ namespace bgfx
return idb;
}
DrawIndirectBufferHandle createDrawIndirectBuffer(uint32_t _num)
{
BX_UNUSED(_num);
DrawIndirectBufferHandle handle = { m_vertexBufferHandle.alloc() };
BX_WARN(isValid(handle), "Failed to allocate draw indirect buffer handle.");
if (isValid(handle) )
{
uint32_t size = _num * sizeof(uint32_t) * 5;
uint8_t flags = BGFX_BUFFER_DRAW_INDIRECT;
CommandBuffer& cmdbuf = getCommandBuffer(CommandBuffer::CreateDynamicVertexBuffer);
cmdbuf.write(handle);
cmdbuf.write(size);
cmdbuf.write(flags);
}
return handle;
}
void destroyDrawIndirectBuffer(DrawIndirectBufferHandle _handle)
{
VertexBufferHandle handle = { _handle.idx };
BGFX_CHECK_HANDLE("destroyDrawIndirectBuffer", m_vertexBufferHandle, handle);
CommandBuffer& cmdbuf = getCommandBuffer(CommandBuffer::DestroyDynamicVertexBuffer);
cmdbuf.write(handle);
m_submit->free(handle);
}
BGFX_API_FUNC(ShaderHandle createShader(const Memory* _mem) )
{
bx::MemoryReader reader(_mem->data, _mem->size);
@ -3256,6 +3299,12 @@ namespace bgfx
);
}
BGFX_API_FUNC(void setDrawIndirectBuffer(DrawIndirectBufferHandle _handle, uint16_t _start, uint16_t _num) )
{
BGFX_CHECK_HANDLE("setDrawIndirectBuffer", m_vertexBufferHandle, _handle);
m_submit->setDrawIndirectBuffer(_handle, _start, _num);
}
BGFX_API_FUNC(void setProgram(ProgramHandle _handle) )
{
BGFX_CHECK_HANDLE("setProgram", m_programHandle, _handle);
@ -3315,6 +3364,13 @@ namespace bgfx
m_submit->setBuffer(_stage, dvb.m_handle, _access);
}
BGFX_API_FUNC(void setBuffer(uint8_t _stage, DrawIndirectBufferHandle _handle, Access::Enum _access) )
{
BGFX_CHECK_HANDLE("setBuffer", m_vertexBufferHandle, _handle);
VertexBufferHandle handle = { _handle.idx };
m_submit->setBuffer(_stage, handle, _access);
}
BGFX_API_FUNC(void setImage(uint8_t _stage, UniformHandle _sampler, TextureHandle _handle, uint8_t _mip, Access::Enum _access, TextureFormat::Enum _format) )
{
_format = TextureFormat::Count == _format ? TextureFormat::Enum(m_textureRef[_handle.idx].m_format) : _format;

View file

@ -449,6 +449,7 @@ namespace bgfx { namespace d3d11
, m_numWindows(0)
, m_device(NULL)
, m_deviceCtx(NULL)
, m_infoQueue(NULL)
, m_backBufferColor(NULL)
, m_backBufferDepthStencil(NULL)
, m_currentColor(NULL)
@ -640,6 +641,8 @@ namespace bgfx { namespace d3d11
continue;
}
// Enable debug flags.
flags |= (BX_ENABLED(BGFX_CONFIG_DEBUG) ? D3D11_CREATE_DEVICE_DEBUG : 0);
++ii;
}
@ -785,14 +788,13 @@ BX_PRAGMA_DIAGNOSTIC_POP();
#if !defined(__MINGW32__)
if (BX_ENABLED(BGFX_CONFIG_DEBUG) )
{
ID3D11InfoQueue* infoQueue;
hr = m_device->QueryInterface(IID_ID3D11InfoQueue, (void**)&infoQueue);
hr = m_device->QueryInterface(IID_ID3D11InfoQueue, (void**)&m_infoQueue);
if (SUCCEEDED(hr) )
{
infoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_CORRUPTION, true);
infoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_ERROR, true);
infoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_WARNING, false);
m_infoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_CORRUPTION, true);
m_infoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_ERROR, false);
m_infoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_WARNING, false);
D3D11_INFO_QUEUE_FILTER filter;
memset(&filter, 0, sizeof(filter) );
@ -804,9 +806,9 @@ BX_PRAGMA_DIAGNOSTIC_POP();
};
filter.DenyList.NumCategories = BX_COUNTOF(catlist);
filter.DenyList.pCategoryList = catlist;
infoQueue->PushStorageFilter(&filter);
m_infoQueue->PushStorageFilter(&filter);
DX_RELEASE(infoQueue, 3);
DX_RELEASE(m_infoQueue, 3);
}
else
{
@ -829,6 +831,7 @@ BX_PRAGMA_DIAGNOSTIC_POP();
| (getIntelExtensions(m_device) ? BGFX_CAPS_FRAGMENT_ORDERING : 0)
| BGFX_CAPS_SWAP_CHAIN
| (m_ovr.isInitialized() ? BGFX_CAPS_HMD : 0)
| BGFX_CAPS_DRAW_INDIRECT
);
if (m_featureLevel <= D3D_FEATURE_LEVEL_9_2)
@ -998,6 +1001,12 @@ BX_PRAGMA_DIAGNOSTIC_POP();
mbstowcs(s_viewNameW[ii], name, BGFX_CONFIG_MAX_VIEW_NAME_RESERVED);
}
if (BX_ENABLED(BGFX_CONFIG_DEBUG)
&& NULL != m_infoQueue)
{
m_infoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_ERROR, true);
}
updateMsaa();
postReset();
}
@ -2540,6 +2549,8 @@ BX_PRAGMA_DIAGNOSTIC_POP();
ID3D11Device* m_device;
ID3D11DeviceContext* m_deviceCtx;
ID3D11InfoQueue* m_infoQueue;
ID3D11RenderTargetView* m_backBufferColor;
ID3D11DepthStencilView* m_backBufferDepthStencil;
ID3D11RenderTargetView* m_currentColor;
@ -2620,8 +2631,9 @@ BX_PRAGMA_DIAGNOSTIC_POP();
m_size = _size;
m_flags = _flags;
const bool needUav = 0 != (_flags & BGFX_BUFFER_COMPUTE_WRITE);
const bool needUav = 0 != (_flags & (BGFX_BUFFER_COMPUTE_WRITE|BGFX_BUFFER_DRAW_INDIRECT) );
const bool needSrv = 0 != (_flags & BGFX_BUFFER_COMPUTE_READ);
const bool drawIndirect = 0 != (_flags & BGFX_BUFFER_DRAW_INDIRECT);
m_dynamic = NULL == _data && !needUav;
D3D11_BUFFER_DESC desc;
@ -2631,7 +2643,9 @@ BX_PRAGMA_DIAGNOSTIC_POP();
| (needUav ? D3D11_BIND_UNORDERED_ACCESS : 0)
| (needSrv ? D3D11_BIND_SHADER_RESOURCE : 0)
;
desc.MiscFlags = 0;
desc.MiscFlags = 0
| (drawIndirect ? D3D11_RESOURCE_MISC_DRAWINDIRECT_ARGS : 0)
;
desc.StructureByteStride = 0;
const DXGI_FORMAT indexFormat = 0 == (_flags & BGFX_BUFFER_INDEX32)
@ -2654,7 +2668,7 @@ BX_PRAGMA_DIAGNOSTIC_POP();
DX_CHECK(device->CreateBuffer(&desc
, NULL
, &m_ptr
));
) );
D3D11_UNORDERED_ACCESS_VIEW_DESC uavd;
uavd.Format = format;
@ -2665,7 +2679,7 @@ BX_PRAGMA_DIAGNOSTIC_POP();
DX_CHECK(device->CreateUnorderedAccessView(m_ptr
, &uavd
, &m_uav
));
) );
}
else if (m_dynamic)
{
@ -2675,7 +2689,7 @@ BX_PRAGMA_DIAGNOSTIC_POP();
DX_CHECK(device->CreateBuffer(&desc
, NULL
, &m_ptr
));
) );
}
else
{
@ -2690,7 +2704,7 @@ BX_PRAGMA_DIAGNOSTIC_POP();
DX_CHECK(device->CreateBuffer(&desc
, &srd
, &m_ptr
));
) );
}
if (needSrv)
@ -2703,7 +2717,7 @@ BX_PRAGMA_DIAGNOSTIC_POP();
DX_CHECK(device->CreateShaderResourceView(m_ptr
, &srvd
, &m_srv
));
) );
}
}
@ -3441,6 +3455,7 @@ BX_PRAGMA_DIAGNOSTIC_POP();
uint32_t statsNumPrimsSubmitted[BX_COUNTOF(s_primInfo)] = {};
uint32_t statsNumPrimsRendered[BX_COUNTOF(s_primInfo)] = {};
uint32_t statsNumInstances[BX_COUNTOF(s_primInfo)] = {};
uint32_t statsNumDrawIndirect[BX_COUNTOF(s_primInfo)] = {};
uint32_t statsNumIndices = 0;
uint32_t statsKeyType[2] = {};
@ -3986,7 +4001,47 @@ BX_PRAGMA_DIAGNOSTIC_POP();
uint32_t numPrimsSubmitted = 0;
uint32_t numInstances = 0;
uint32_t numPrimsRendered = 0;
uint32_t numDrawIndirect = 0;
if (isValid(draw.m_drawIndirectBuffer) )
{
if (isValid(draw.m_indexBuffer) )
{
const VertexBufferD3D11& vb = m_vertexBuffers[draw.m_drawIndirectBuffer.idx];
ID3D11Buffer* ptr = vb.m_ptr;
const uint32_t commandSize = 5 * sizeof(uint32_t);
numDrawIndirect = UINT16_MAX == draw.m_numDrawIndirect ? vb.m_size/commandSize : draw.m_numDrawIndirect;
uint32_t args = draw.m_startDrawIndirect * commandSize;
for (uint32_t ii = 0; ii < numDrawIndirect; ++ii)
{
deviceCtx->DrawIndexedInstancedIndirect(ptr
, args
);
args += commandSize;
}
}
else
{
const VertexBufferD3D11& vb = m_vertexBuffers[draw.m_drawIndirectBuffer.idx];
ID3D11Buffer* ptr = vb.m_ptr;
const uint32_t commandSize = 4 * sizeof(uint32_t);
numDrawIndirect = UINT16_MAX == draw.m_numDrawIndirect ? vb.m_size/commandSize : draw.m_numDrawIndirect;
uint32_t args = draw.m_startDrawIndirect * commandSize;
for (uint32_t ii = 0; ii < numDrawIndirect; ++ii)
{
deviceCtx->DrawInstancedIndirect(ptr
, args
);
args += commandSize;
}
}
}
else
{
if (isValid(draw.m_indexBuffer) )
{
if (UINT32_MAX == draw.m_numIndices)
@ -4061,10 +4116,12 @@ BX_PRAGMA_DIAGNOSTIC_POP();
);
}
}
}
statsNumPrimsSubmitted[primIndex] += numPrimsSubmitted;
statsNumPrimsRendered[primIndex] += numPrimsRendered;
statsNumInstances[primIndex] += numInstances;
statsNumDrawIndirect[primIndex] += numDrawIndirect;
statsNumIndices += numIndices;
}
}
@ -4174,11 +4231,12 @@ BX_PRAGMA_DIAGNOSTIC_POP();
);
for (uint32_t ii = 0; ii < BX_COUNTOF(s_primName); ++ii)
{
tvm.printf(10, pos++, 0x8e, " %9s: %7d (#inst: %5d), submitted: %7d"
tvm.printf(10, pos++, 0x8e, " %9s: %7d (#inst: %5d), submitted: %7d, indirect %7d"
, s_primName[ii]
, statsNumPrimsRendered[ii]
, statsNumInstances[ii]
, statsNumPrimsSubmitted[ii]
, statsNumDrawIndirect[ii]
);
}