Browse Source

replace block nonsense with arena allocator

render_group_fix
cinnaboot 5 years ago
parent
commit
33cf7fdbed
  1. 14
      examples/render_groups/main.cpp
  2. 42
      include/renderer.h
  3. 16
      include/util.h
  4. 144
      src/renderer.cpp
  5. 35
      src/util.cpp

14
examples/render_groups/main.cpp

@ -176,16 +176,12 @@ main()
renDoRenderLoop(rs, 60, doFrameCallbackPre);
#endif
//rs->assets = memInitBlock(INITIAL_ASSET_BLOCK_SIZE);
rs->assets = memInitBlock(10 * 1024 * 1024); // NOTE: 10MB
assert(rs->assets != nullptr);
rs->arena = arenaInit();
rs->asset_list =
(render_asset*) arenaAllocateBlock(rs->arena, sizeof(render_asset));
// load assets manually
render_asset* icosphere = memPushAsset(rs->assets, "../data/icosphere.glb");
assert(icosphere != nullptr);
render_asset* ship = memPushAsset(rs->assets, "../data/spaceship.glb");
assert(ship != nullptr);
mesh_group mg;
meLoadFromFile(mg, "../data/blender/icosphere.gltf");
renShutdown(rs);
return 0;

42
include/renderer.h

@ -46,13 +46,10 @@ struct SDL_Handles
struct mesh_asset
{
// header
uint asset_size;
uint num_vertices;
uint num_indices;
mesh_asset* next;
// data
glm::mat4 model_transform;
glm::vec3* vertices;
uint* indices;
@ -62,48 +59,19 @@ struct mesh_asset
#define MAX_PATH_SIZE 256
struct render_asset
{
// header
uint total_size;
uint num_meshes;
uint name_len;
render_asset* next;
// data
char* filepath;
mesh_asset* head_mesh;
// FIXME: also need to flatten diffuse_texture->pixels and track size of
// util_image structure, ie) another heaader + pixels
//uint tex_size;
mesh_asset* meshes; // NOTE: fixed sized array
// NOTE: pointer to a texture in render_state->textures
util_image* diffuse_texture;
// FIXME: node_animation has a pointer to a render_object. need to decouple
// that somehow
//node_animation* node_anim;
};
// NOTE: This is a linearly allocated block to contain all used mesh assets
// Assets are loaded once, and then copied to video memory as needed.
// NOTE: sub-data structures are implemented as a write only single linked list,
// with no insertion or moving of items
// https://en.wikipedia.org/wiki/Region-based_memory_management
// http://cslibrary.stanford.edu/103/LinkedListBasics.pdf
struct asset_memory_block
{
size_t max_size;
render_asset* head;
render_asset* tail;
uint asset_count;
};
#define INITIAL_ASSET_BLOCK_SIZE 256 * 1024 * 1024 // 256MB
asset_memory_block*
memInitBlock(size_t initial_size = INITIAL_ASSET_BLOCK_SIZE);
render_asset*
memPushAsset(asset_memory_block* block, const char* filepath);
void
memFreeBlock(asset_memory_block* block);
// Memory allocation WIP
// --------------------------
@ -121,7 +89,11 @@ struct render_state
uint render_group_count;
// WIP
asset_memory_block* assets;
render_asset* asset_list; // NOTE: head pointer of linked list
memory_arena* arena;
// FIXME: should be a hashmap for textures loaded from assets
// ie) pallete textures
util_image* textures;
// TODO: hide shaders behind a better abstraction than 'shader_wrapper'
default_shader_program* default_shader;

16
include/util.h

@ -94,6 +94,22 @@ void* utilLogAlloc(uint item_count, uint type_size, const char* file_name, const
#define UTIL_FREE(mem_ptr) utilSafeFree((void*&) mem_ptr)
void utilSafeFree(const void* mem);
struct memory_arena
{
size_t max_size;
void* head;
void* next_free;
};
#define DEFAULT_ARENA_SIZE 10 * 1024 * 1024 // 10MB
memory_arena* arenaInit(size_t initial_size = DEFAULT_ARENA_SIZE);
void arenaFree(memory_arena*& arena);
uint arenaGetFreeSize(memory_arena* arena);
void* arenaAllocateBlock(memory_arena* arena, size_t block_size);
//-----------------
// File I/O

144
src/renderer.cpp

@ -37,146 +37,6 @@ void setDefaults(render_state* rs, glm::vec2 viewport_dims);
// interface
// WIP
size_t
getBlockFreeSpace(asset_memory_block* block)
{
return (uint8_t*) block
+ block->max_size
- (uint8_t*) block->tail
+ block->tail->total_size;
}
uint
getAssetSize(const mesh_group& mg, uint name_len)
{
uint total = sizeof(render_asset);
total += name_len;
for (uint i = 0; i < mg.num_meshes; i++) {
mesh_info* mi = mg.meshes[i];
total += sizeof(mesh_asset);
// NOTE: vertices, normals, and tex coords
total += 3 * mi->num_vertices * sizeof(glm::vec3);
total += mi->num_indices * sizeof(uint);
}
return total;
}
void*
getAddressOffset(void* address, uint offset)
{
return (void*) ((uint8_t*) address + offset);
}
// TODO: replace mesh_info structure
mesh_asset*
initMeshAsset(mesh_asset* mesh, mesh_info* mi)
{
mesh->num_vertices = mi->num_vertices;
mesh->num_indices = mi->num_indices;
mesh->asset_size = sizeof(mesh_asset);
mesh->vertices = (glm::vec3*) ((uint8_t*) mesh + mesh->asset_size);
// NOTE: vertices, normals, and tex coords
mesh->asset_size += 3 * mesh->num_vertices * sizeof(glm::vec3);
mesh->asset_size += mesh->num_indices * sizeof(uint);
mesh->asset_size += sizeof(glm::mat4);
// FIXME: this should be set in the outer loop
//mesh->next = (mesh_asset*) ((uint8_t*) mesh + mesh->asset_size);
// FIXME: copy vertices, normals, tex coords, and xform
return mesh;
}
render_asset*
getNextFreeRenderAsset(asset_memory_block* block)
{
return (render_asset*)
getAddressOffset(block->tail, block->tail->total_size);
}
#include <cstring>
render_asset*
initRenderAsset(
render_asset* ra,
uint total_size,
uint num_meshes,
const char* filepath)
{
ra->total_size = total_size;
ra->num_meshes = num_meshes;
ra->name_len = (uint) std::strlen(filepath) + 1;
ra->next = nullptr;
ra->filepath = (char*) ra + sizeof(render_asset);
std::memcpy(ra->filepath, filepath, ra->name_len);
ra->head_mesh = (mesh_asset*) ((uint8_t*) ra->filepath + ra->name_len);
// TODO: texture
//ra->diffuse_texture = (util_image*) ra->filepath;
return ra;
}
asset_memory_block*
memInitBlock(size_t initial_size)
{
// NOTE: need to alloc as uint8_t and recast here so we can get the correct
// size in bytes
asset_memory_block* block = (asset_memory_block*) UTIL_ALLOC(
sizeof(asset_memory_block) + initial_size, uint8_t);
block->max_size = initial_size - sizeof(asset_memory_block);
block->head = block->tail =
(render_asset*) ((uint8_t*) block + sizeof(asset_memory_block));
return block;
}
void
memFreeBlock(asset_memory_block* block)
{
utilSafeFree(block);
}
render_asset*
memPushAsset(asset_memory_block* block, const char* filepath)
{
// TODO: rewrite mesh.cpp to load assimp structure into render_asset
// directly
mesh_group mg;
meLoadFromFile(mg, filepath);
uint name_len = (uint) std::strlen(filepath) + 1;
assert(name_len <= MAX_PATH_SIZE);
uint asize = getAssetSize(mg, name_len);
if (getBlockFreeSpace(block) < asize) {
LOG(Error) << "not enough free space in block\n";
return nullptr;
}
render_asset* ra = getNextFreeRenderAsset(block);
initRenderAsset(ra, asize, mg.num_meshes, filepath);
block->max_size -= asize;
block->asset_count++;
// NOTE: special case when adding the first asset
if (block->head == block->tail)
block->head->next = ra;
else
block->tail->next = ra;
block->tail = ra;
mesh_asset* next = ra->head_mesh;
for (uint i = 0; i < mg.num_meshes; i++) {
mesh_asset* mesh = initMeshAsset(next, mg.meshes[i]);
next = (mesh_asset*) getAddressOffset(mesh, mesh->asset_size);
// NOTE: leave the last link as nullptr
(i < mg.num_meshes - 1) ? mesh->next = next : mesh->next = nullptr;
}
return ra;
}
// end WIP
render_state*
renInit(const char* title, glm::vec2 viewport_dims, Uint32 SDL_init_flags)
{
@ -217,8 +77,8 @@ renShutdown(render_state* rs)
lightsOut(rs->lights);
utilSafeFree(rs->render_groups);
memFreeBlock(rs->assets);
rs->assets = nullptr;
rs->render_groups = nullptr;
arenaFree(rs->arena);
meShutdownAssimp();
SDL_GL_DeleteContext(rs->handles->glContext);
SDL_DestroyWindow(rs->handles->window);

35
src/util.cpp

@ -84,6 +84,41 @@ utilSafeFree(const void* mem)
if (mem != nullptr) std::free((void *) mem);
}
memory_arena*
arenaInit(size_t initial_size)
{
uint sz = sizeof(memory_arena);
memory_arena* arena =
(memory_arena*) UTIL_ALLOC(initial_size + sz, uint8_t);
arena->head = arena->next_free = (uint8_t*) arena + sz;
arena->max_size = initial_size;
return arena;
}
void
arenaFree(memory_arena*& arena)
{
utilSafeFree(arena);
arena = nullptr;
}
uint
arenaGetFreeSize(memory_arena* arena)
{
return (uint8_t*) arena->head
+ arena->max_size
- (uint8_t*) arena->next_free;
}
void*
arenaAllocateBlock(memory_arena* arena, size_t block_size)
{
assert(arenaGetFreeSize(arena) >= block_size);
void* ret = arena->next_free;
arena->next_free = (uint8_t*) arena->next_free + block_size;
return ret;
}
//-----------------
// File I/O

Loading…
Cancel
Save