Finished asset manager.

This commit is contained in:
2021-11-03 10:48:03 -07:00
parent 2f2f1395fa
commit 7097e7a1d4
8 changed files with 519 additions and 60 deletions

251
src/file/assetmanager.c Normal file
View File

@ -0,0 +1,251 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "assetmanager.h"
assetmanagerloaderdefinition_t ASSET_MANAGER_LOADERS[] = {
{
&_assetManagerLoaderTextureAsync,
&_assetManagerLoaderTextureSync
},
{
&_assetManagerLoaderFontAsync,
&_assetManagerLoaderFontSync
},
{
&_assetManagerLoaderShaderAsync,
&_assetManagerLoaderShaderSync
}
};
void assetManagerInit(assetmanager_t *manager) {
threadInit(&manager->thread, &_assetManagerThread);
manager->thread.user = manager;
manager->itemCount = 0;
}
void assetManagerStart(assetmanager_t *manager) {
threadStart(&manager->thread);
}
float assetManagerProgressGet(assetmanager_t *manager) {
float done;
uint8_t i;
done = 0.0f;
for(i = 0; i < manager->itemCount; i++) {
if(!assetManagerIsItemFinished(manager->items + i)) continue;
done++;
}
return done / ((float) manager->itemCount);
}
bool assetManagerIsItemFinished(assetmanageritem_t *item) {
// Sync done is always done
if(item->state == ASSET_MANAGER_STATE_SYNC_DONE) return true;
// Only check if ASYNC is done.
if(item->state != ASSET_MANAGER_STATE_ASYNC_DONE) return false;
// Does it need to still sync load?
if(ASSET_MANAGER_LOADERS[item->type].loadSync == NULL) return true;
return false;
}
// Thread Management
int32_t _assetManagerThread(thread_t *thread) {
// TODO: Can I allow multiple threads to run?
uint8_t i;
assetmanager_t *manager;
assetmanageritem_t *item;
assetmanagerloaderdefinition_t *definition;
bool result;
manager = thread->user;
for(i = 0; i < manager->itemCount; i++) {
item = manager->items + i;
definition = ASSET_MANAGER_LOADERS + item->type;
// Only bother with ASYNC items
if(definition->loadAsync == NULL) continue;
// Are we already loading or already tried to load?
if(item->state != ASSET_MANAGER_STATE_PENDING) continue;
// Begin loading
item->state = ASSET_MANAGER_STATE_ASYNC_LOADING;
result = definition->loadAsync(item);
// Finish Loading
if(!result) {
item->state = ASSET_MANAGER_STATE_ASYNC_ERROR;
} else {
item->state = ASSET_MANAGER_STATE_ASYNC_DONE;
}
}
return 0;
}
void assetManagerUpdate(assetmanager_t *manager) {
uint8_t i;
assetmanageritem_t *item;
assetmanagerloaderdefinition_t *definition;
bool result;
for(i = 0; i < manager->itemCount; i++) {
item = manager->items + i;
definition = ASSET_MANAGER_LOADERS + item->type;
// If requires ASYNC loading, then confirm it has finished loading.
if(definition->loadAsync != NULL) {
if(item->state != ASSET_MANAGER_STATE_ASYNC_DONE) continue;
} else if(item->state != ASSET_MANAGER_STATE_PENDING) {
continue;
} else if(definition->loadSync == NULL) {
continue;
}
// Begin sync loading
item->state = ASSET_MANAGER_STATE_SYNC_LOADING;
result = definition->loadSync(item);
// Finish loading
if(!result) {
item->state = ASSET_MANAGER_STATE_SYNC_ERROR;
} else {
item->state = ASSET_MANAGER_STATE_SYNC_DONE;
}
}
}
assetmanageritem_t * assetManagerItemAdd(assetmanager_t *manager) {
assetmanageritem_t *item = manager->items + manager->itemCount++;
item->state = ASSET_MANAGER_STATE_PENDING;
return item;
}
// Texture
assetmanageritem_t * assetManagerLoadTexture(
assetmanager_t *manager, texture_t *texture, char *fileName
) {
assetmanageritem_t *item = assetManagerItemAdd(manager);
item->type = ASSET_MANAGER_TYPE_TEXTURE;
item->data.texture.fileName = fileName;
item->data.texture.texture = texture;
return item;
}
bool _assetManagerLoaderTextureAsync(assetmanageritem_t *item) {
assetbuffer_t *buffer;
int channels;
stbi_io_callbacks OPENGL_STBI_CALLBACKS;
buffer = assetBufferOpen(item->data.texture.fileName);
if(buffer == NULL) return false;
// Setup the interface for STBI
OPENGL_STBI_CALLBACKS.read = &assetBufferRead;
OPENGL_STBI_CALLBACKS.skip = &assetBufferSkip;
OPENGL_STBI_CALLBACKS.eof = &assetBufferEnd;
// Buffer the image
channels = 0;
item->data.texture.data = (pixel_t *)stbi_load_from_callbacks(
&OPENGL_STBI_CALLBACKS, buffer,
&item->data.texture.width, &item->data.texture.height,
&channels, STBI_rgb_alpha
);
// Close the buffer
assetBufferClose(buffer);
if(item->data.texture.data == NULL) return false;
return true;
}
bool _assetManagerLoaderTextureSync(assetmanageritem_t *item) {
// Turn into a texture.
textureInit(
item->data.texture.texture,
item->data.texture.width,
item->data.texture.height,
item->data.texture.data
);
// Cleanup
stbi_image_free(item->data.texture.data);
return true;
}
// Font
assetmanageritem_t * assetManagerLoadFont(
assetmanager_t *manager, font_t *font, char *fileName
) {
assetmanageritem_t *item = assetManagerItemAdd(manager);
item->type = ASSET_MANAGER_TYPE_FONT;
item->data.font.fileName = fileName;
item->data.font.font = font;
return item;
}
bool _assetManagerLoaderFontAsync(assetmanageritem_t *item) {
item->data.font.data = assetStringLoad(item->data.font.fileName);
return item->data.font.data != NULL;
}
bool _assetManagerLoaderFontSync(assetmanageritem_t *item) {
fontInit(item->data.font.font, item->data.font.data);
free(item->data.font.data);
return true;
}
// Shader
assetmanageritem_t * assetManagerShaderLoad(
assetmanager_t *manager, shader_t *shader, char *fileVert, char *fileFrag
) {
assetmanageritem_t *item = assetManagerItemAdd(manager);
item->type = ASSET_MANAGER_TYPE_SHADER;
item->data.shader.shader = shader;
item->data.shader.fileVert = fileVert;
item->data.shader.fileFrag = fileFrag;
return item;
}
bool _assetManagerLoaderShaderAsync(assetmanageritem_t *item) {
item->data.shader.dataVert = assetStringLoad(item->data.shader.fileVert);
if(item->data.shader.dataVert == NULL) return false;
item->data.shader.dataFrag = assetStringLoad(item->data.shader.fileFrag);
if(item->data.shader.dataFrag == NULL) {
free(item->data.shader.fileVert);
return false;
}
return true;
}
bool _assetManagerLoaderShaderSync(assetmanageritem_t *item) {
shaderInit(
item->data.shader.shader,
item->data.shader.dataVert,
item->data.shader.dataFrag
);
free(item->data.shader.dataFrag);
free(item->data.shader.dataVert);
return true;
}

180
src/file/assetmanager.h Normal file
View File

@ -0,0 +1,180 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "asset.h"
#include "../util/flags.h"
#include "../engine/thread.h"
#include "../display/shader.h"
#include "../display/texture.h"
#include "../display/font.h"
#include "../script/scripter.h"
#include "xml.h"
#define ASSET_MANAGER_ITEMS_MAX 64
#define ASSET_MANAGER_STATE_PENDING 0x00
#define ASSET_MANAGER_STATE_ASYNC_LOADING 0x01
#define ASSET_MANAGER_STATE_ASYNC_ERROR 0x02
#define ASSET_MANAGER_STATE_ASYNC_DONE 0x03
#define ASSET_MANAGER_STATE_SYNC_LOADING 0x04
#define ASSET_MANAGER_STATE_SYNC_ERROR 0x05
#define ASSET_MANAGER_STATE_SYNC_DONE 0x06
#define ASSET_MANAGER_TYPE_TEXTURE 0x00
#define ASSET_MANAGER_TYPE_FONT 0x01
#define ASSET_MANAGER_TYPE_SHADER 0x02
// Types
typedef struct {
texture_t *texture;
char *fileName;
int32_t width, height;
pixel_t *data;
} assetmanagertexture_t;
typedef struct {
shader_t *shader;
char *fileVert;
char *fileFrag;
char *dataVert;
char *dataFrag;
} assetmanagershader_t;
typedef struct {
font_t *font;
char *fileName;
char *data;
} assetmanagerfont_t;
// Item
typedef union {
assetmanagertexture_t texture;
assetmanagershader_t shader;
assetmanagerfont_t font;
} assetmanagerassetdata_t;
typedef struct {
uint8_t type;
uint8_t state;
assetmanagerassetdata_t data;
} assetmanageritem_t;
// Loader
typedef bool assetmanagerloader_t(assetmanageritem_t *item);
typedef struct {
assetmanagerloader_t *loadAsync;
assetmanagerloader_t *loadSync;
} assetmanagerloaderdefinition_t;
// Manager
typedef struct {
thread_t thread;
assetmanageritem_t items[ASSET_MANAGER_ITEMS_MAX];
uint8_t itemCount;
} assetmanager_t;
extern assetmanagerloaderdefinition_t ASSET_MANAGER_LOADERS[];
/**
* Initialize the asset manager
*
* @param manager Manager to initialize.
*/
void assetManagerInit(assetmanager_t *manager);
/**
* Begin asynchronously loading all of the assets
*
* @param manager Manager to begin async loading.
*/
void assetManagerStart(assetmanager_t *manager);
/**
* Synchronously tick the asset manager. Some assets require some form of sync
* operations, such as buffering to the GPU, so make sure this is called at a
* good time for that task, such as right at the end of a frame.
*
* @param manager Manager to synchronously tick.
*/
void assetManagerUpdate(assetmanager_t *manager);
/**
* Returns whether or not the given item is finished.
*
* @param item Item to check state of.
* @return True if finished, otherwise false.
*/
bool assetManagerIsItemFinished(assetmanageritem_t *item);
/**
* Gets the progress of the asset manager as a representation of 0-1 as a % that
* has loaded.
*
* @param manager Manager to check the state of.
* @return The progress percent as a representation of 0-1
*/
float assetManagerProgressGet(assetmanager_t *manager);
/** Private Thread that is executed asynchronously */
int32_t _assetManagerThread(thread_t *thread);
/**
* Private method, simply adds an item to the manager and resets the state.
*
* @param manager Manager to add to.
* @return The added and reset item.
*/
assetmanageritem_t * assetManagerItemAdd(assetmanager_t *manager);
/**
* Queue a texture load onto the asset manager buffer.
*
* @param manager Manager to queue on to.
* @param texture Texture to push the result in to.
* @param fileName Texture filename to load.
* @return A pointer to the asset manager item for tracking.
*/
assetmanageritem_t * assetManagerLoadTexture(
assetmanager_t *manager, texture_t *texture, char *fileName
);
bool _assetManagerLoaderTextureAsync(assetmanageritem_t *item);
bool _assetManagerLoaderTextureSync(assetmanageritem_t *item);
/**
* Queue a font load onto the asset manager buffer.
*
* @param manager Manager to queue on to.
* @param font Font to push the result in to.
* @param fileName Filename of the asset to load.
* @return A pointer to the asset manager item for tracking.
*/
assetmanageritem_t * assetManagerLoadFont(
assetmanager_t *manager, font_t *font, char *fileName
);
bool _assetManagerLoaderFontAsync(assetmanageritem_t *item);
bool _assetManagerLoaderFontSync(assetmanageritem_t *item);
/**
* Queues a shader load onto the asset manager buffer.
*
* @param manager Manager to queue on to.
* @param shader Shader to push the result in to.
* @param fileVert Vertex file in question to load.
* @param fileFrag Fragment file in question to load.
* @return A pointer to the asset manager item for tracking.
*/
assetmanageritem_t * assetManagerShaderLoad(
assetmanager_t *manager, shader_t *shader, char *fileVert, char *fileFrag
);
bool _assetManagerLoaderShaderAsync(assetmanageritem_t *item);
bool _assetManagerLoaderShaderSync(assetmanageritem_t *item);