D3D10/11 dyn buffer management
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| //////////////////////////////////////////////////////////////////////// | |
| // | |
| // 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