Skip to content

Instantly share code, notes, and snippets.

@rygorous
Created October 25, 2013 21:10
Embed
What would you like to do?
D3D10/11 dyn buffer management
////////////////////////////////////////////////////////////////////////
//
// Dynamic buffer (D3D11-specific code)
//
#define D3D1X_(id) D3D11_##id
#define ID3D1X(id) ID3D11##id
#define gdraw_D3D1X_(id) gdraw_D3D11_##id
#define GDRAW_D3D1X_(id) GDRAW_D3D11_##id
typedef ID3D11Device ID3D1XDevice;
typedef ID3D11DeviceContext ID3D1XContext;
static void report_d3d_error(HRESULT hr, char *call, char *context);
static void *map_buffer(ID3D1XContext *ctx, ID3D11Buffer *buf, bool discard)
{
D3D11_MAPPED_SUBRESOURCE msr;
HRESULT hr = ctx->Map(buf, 0, discard ? D3D11_MAP_WRITE_DISCARD : D3D11_MAP_WRITE_NO_OVERWRITE, 0, &msr);
if (FAILED(hr)) {
report_d3d_error(hr, "Map", "of buffer");
return NULL;
} else
return msr.pData;
}
static void unmap_buffer(ID3D1XContext *ctx, ID3D11Buffer *buf)
{
ctx->Unmap(buf, 0);
}
////////////////////////////////////////////////////////////////////////
//
// Dynamic buffer (generic code)
//
struct DynBuffer
{
ID3D1X(Buffer) *buffer;
U32 size; // size of buffer
U32 write_pos; // start of most recently allocated chunk (=start offset for draw calls)
U32 alloc_pos; // end of most recently allocated chunk (=start of next allocation)
};
static void *start_write_dyn(DynBuffer *buf, U32 size)
{
U8 *ptr = NULL;
if (size > buf->size) {
IggyGDrawSendWarning(NULL, "GDraw dynamic vertex buffer usage of %d bytes in one call larger than buffer size %d", size, buf->size);
return NULL;
}
// update statistics
gdraw->dyn_maxalloc = RR_MAX(gdraw->dyn_maxalloc, size);
// invariant: current alloc_pos is in [0,size]
assert(buf->alloc_pos <= buf->size);
// wrap around when less than "size" bytes left in buffer
buf->write_pos = ((buf->size - buf->alloc_pos) < size) ? 0 : buf->alloc_pos;
// discard buffer whenever the current write position is 0;
// done this way so that if a DISCARD Map() were to fail, we would
// just keep retrying the next time around.
ptr = (U8 *) map_buffer(gdraw->d3d_context, buf->buffer, buf->write_pos == 0);
if (ptr) {
ptr += buf->write_pos; // we return pointer to write position in buffer
buf->alloc_pos = buf->write_pos + size; // bump alloc position
assert(buf->alloc_pos <= buf->size); // invariant again
}
// if map_buffer fails, it will have sent a warning
return ptr;
}
static U32 end_write_dyn(DynBuffer *buf)
{
unmap_buffer(gdraw->d3d_context, buf->buffer);
return buf->write_pos;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment