Add async texture loading

This commit is contained in:
2026-06-01 14:53:18 -05:00
parent eedb7769e6
commit c4c93097cd
5 changed files with 86 additions and 10 deletions
+17 -3
View File
@@ -180,11 +180,11 @@ errorret_t assetUpdate(void) {
// If an error occured these things need to be true, basically just // If an error occured these things need to be true, basically just
// ensuring the sync loader is setting the error correctly. // ensuring the sync loader is setting the error correctly.
if(errorIsNotOk(ret)) { if(errorIsNotOk(ret)) {
errorCatch(errorPrint(ret));
assertTrue( assertTrue(
loading->entry->state == ASSET_ENTRY_STATE_ERROR, loading->entry->state == ASSET_ENTRY_STATE_ERROR,
"Loader did not set entry state to error on failed load." "Loader did not set entry state to error on failed load."
); );
errorCatch(errorPrint(ret));
} }
threadMutexUnlock(&loading->mutex); threadMutexUnlock(&loading->mutex);
@@ -236,8 +236,22 @@ void assetUpdateAsync(thread_t *thread) {
switch(loading->entry->state) { switch(loading->entry->state) {
case ASSET_ENTRY_STATE_PENDING_ASYNC: case ASSET_ENTRY_STATE_PENDING_ASYNC:
loading->entry->state = ASSET_ENTRY_STATE_LOADING_ASYNC; loading->entry->state = ASSET_ENTRY_STATE_LOADING_ASYNC;
printf("Simulated async load\n"); assertNotNull(
sleep(1); ASSET_LOADER_CALLBACKS[loading->type].loadAsync,
"Loader does not support async loading."
);
errorret_t ret = (
ASSET_LOADER_CALLBACKS[loading->type].loadAsync(loading)
);
if(errorIsNotOk(ret)) {
errorCatch(errorPrint(ret));
assertTrue(
loading->entry->state == ASSET_ENTRY_STATE_ERROR,
"Loader did not set entry state to error on failed load."
);
}
threadMutexUnlock(&loading->mutex); threadMutexUnlock(&loading->mutex);
loading++; loading++;
break; break;
+5
View File
@@ -12,26 +12,31 @@ assetloadercallbacks_t ASSET_LOADER_CALLBACKS[ASSET_LOADER_TYPE_COUNT] = {
[ASSET_LOADER_TYPE_MESH] = { [ASSET_LOADER_TYPE_MESH] = {
.loadSync = assetMeshLoaderSync, .loadSync = assetMeshLoaderSync,
.loadAsync = NULL,
.dispose = assetMeshDispose .dispose = assetMeshDispose
}, },
[ASSET_LOADER_TYPE_TEXTURE] = { [ASSET_LOADER_TYPE_TEXTURE] = {
.loadSync = assetTextureLoaderSync, .loadSync = assetTextureLoaderSync,
.loadAsync = assetTextureLoaderAsync,
.dispose = assetTextureDispose .dispose = assetTextureDispose
}, },
[ASSET_LOADER_TYPE_TILESET] = { [ASSET_LOADER_TYPE_TILESET] = {
.loadSync = assetTilesetLoaderSync, .loadSync = assetTilesetLoaderSync,
.loadAsync = NULL,
.dispose = assetTilesetDispose .dispose = assetTilesetDispose
}, },
[ASSET_LOADER_TYPE_LOCALE] = { [ASSET_LOADER_TYPE_LOCALE] = {
.loadSync = assetLocaleLoaderSync, .loadSync = assetLocaleLoaderSync,
.loadAsync = NULL,
.dispose = assetLocaleDispose .dispose = assetLocaleDispose
}, },
[ASSET_LOADER_TYPE_JSON] = { [ASSET_LOADER_TYPE_JSON] = {
.loadSync = assetJsonLoaderSync, .loadSync = assetJsonLoaderSync,
.loadAsync = NULL,
.dispose = assetJsonDispose .dispose = assetJsonDispose
}, },
}; };
+2
View File
@@ -52,10 +52,12 @@ typedef struct assetloading_s assetloading_t;
typedef struct assetentry_s assetentry_t; typedef struct assetentry_s assetentry_t;
typedef errorret_t (assetloadersynccallback_t)(assetloading_t *loading); typedef errorret_t (assetloadersynccallback_t)(assetloading_t *loading);
typedef errorret_t (assetloaderasynccallback_t)(assetloading_t *loading);
typedef errorret_t (assetloaderdisposecallback_t)(assetentry_t *entry); typedef errorret_t (assetloaderdisposecallback_t)(assetentry_t *entry);
typedef struct { typedef struct {
assetloadersynccallback_t *loadSync; assetloadersynccallback_t *loadSync;
assetloaderasynccallback_t *loadAsync;
assetloaderdisposecallback_t *dispose; assetloaderdisposecallback_t *dispose;
} assetloadercallbacks_t; } assetloadercallbacks_t;
@@ -52,10 +52,19 @@ int assetTextureEOF(void *user) {
return file->position >= file->size; return file->position >= file->size;
} }
errorret_t assetTextureLoaderSync(assetloading_t *loading) { errorret_t assetTextureLoaderAsync(assetloading_t *loading) {
assertNotNull(loading, "Loading cannot be NULL"); assertNotNull(loading, "Loading cannot be NULL");
// Only care about loading pixels.
if(loading->loading.texture.state != ASSET_TEXTURE_LOADING_STATE_LOAD_PIXELS){
errorOk();
}
// Init the file // Init the file
assertNull(
loading->loading.texture.data, "Pixels already defined?"
);
assetfile_t *file = &loading->loading.texture.file; assetfile_t *file = &loading->loading.texture.file;
assetLoaderErrorChain(loading, assetFileInit( assetLoaderErrorChain(loading, assetFileInit(
file, file,
@@ -77,13 +86,12 @@ errorret_t assetTextureLoaderSync(assetloading_t *loading) {
} }
// Load image pixels. // Load image pixels.
int width, height, channels;
loading->loading.texture.data = stbi_load_from_callbacks( loading->loading.texture.data = stbi_load_from_callbacks(
&ASSET_TEXTURE_STB_CALLBACKS, &ASSET_TEXTURE_STB_CALLBACKS,
file, file,
&width, &loading->loading.texture.width,
&height, &loading->loading.texture.height,
&channels, &loading->loading.texture.channels,
channelsDesired channelsDesired
); );
@@ -101,14 +109,43 @@ errorret_t assetTextureLoaderSync(assetloading_t *loading) {
if(!isHostLittleEndian()) { if(!isHostLittleEndian()) {
stbi__vertical_flip( stbi__vertical_flip(
loading->loading.texture.data, loading->loading.texture.data,
width, height, channelsDesired loading->loading.texture.width,
loading->loading.texture.height,
loading->loading.texture.channels
); );
} }
loading->loading.texture.state = ASSET_TEXTURE_LOADING_STATE_CREATE_TEXTURE;
loading->entry->state = ASSET_ENTRY_STATE_PENDING_SYNC;
errorOk();
}
errorret_t assetTextureLoaderSync(assetloading_t *loading) {
assertNotNull(loading, "Loading cannot be NULL");
switch(loading->loading.texture.state) {
case ASSET_TEXTURE_LOADING_STATE_INITIAL:
loading->loading.texture.state = ASSET_TEXTURE_LOADING_STATE_LOAD_PIXELS;
loading->entry->state = ASSET_ENTRY_STATE_PENDING_ASYNC;
errorOk();
break;
case ASSET_TEXTURE_LOADING_STATE_CREATE_TEXTURE:
break;
default:
errorOk();
}
// Create the texture. // Create the texture.
assertNotNull(
loading->loading.texture.data, "Pixels should have been loaded by now."
);
assetLoaderErrorChain(loading, textureInit( assetLoaderErrorChain(loading, textureInit(
(texture_t*)&loading->entry->data.texture, (texture_t*)&loading->entry->data.texture,
(int32_t)width, (int32_t)height, loading->loading.texture.width,
loading->loading.texture.height,
loading->entry->input->texture, loading->entry->input->texture,
(texturedata_t){ (texturedata_t){
.rgbaColors = (color_t*)loading->loading.texture.data .rgbaColors = (color_t*)loading->loading.texture.data
@@ -13,8 +13,18 @@ typedef struct assetloading_s assetloading_t;
typedef struct assetentry_s assetentry_t; typedef struct assetentry_s assetentry_t;
typedef textureformat_t assettextureloaderinput_t; typedef textureformat_t assettextureloaderinput_t;
typedef enum {
ASSET_TEXTURE_LOADING_STATE_INITIAL,
ASSET_TEXTURE_LOADING_STATE_LOAD_PIXELS,
ASSET_TEXTURE_LOADING_STATE_CREATE_TEXTURE,
ASSET_TEXTURE_LOADING_STATE_DONE
} assettextureloadingstate_t;
typedef struct { typedef struct {
assetfile_t file; assetfile_t file;
assettextureloadingstate_t state;
int channels, width, height;
uint8_t *data; uint8_t *data;
} assettextureloaderloading_t; } assettextureloaderloading_t;
@@ -46,6 +56,14 @@ void assetTextureSkipper(void *user, int n);
*/ */
int assetTextureEOF(void *user); int assetTextureEOF(void *user);
/**
* Synchronous loader for texture assets.
*
* @param loading Loading information for the asset being loaded.
* @return Error code indicating success or failure of the load operation.
*/
errorret_t assetTextureLoaderAsync(assetloading_t *loading);
/** /**
* Synchronous loader for texture assets. * Synchronous loader for texture assets.
* *