initial work on GPU

This commit is contained in:
2026-03-31 14:43:10 +02:00
parent 76b14524c5
commit 917427c2e1
4 changed files with 180 additions and 2 deletions

View File

@@ -414,7 +414,7 @@ int main(int argc, char **argv) {
double wattage = 0;
nn_Component *screen = ncl_createScreen(u, NULL, &nn_defaultScreens[3]);
//nn_Component *gpu = ncl_createGPU(u, NULL, &nn_defaultGPUs[3]);
nn_Component *gpuCard = ncl_createGPU(u, NULL, &nn_defaultGPUs[3]);
{
// draw test
@@ -444,6 +444,7 @@ restart:;
nn_mountComponent(c, ocelotCard, -1);
nn_mountComponent(c, eepromCard, 0);
nn_mountComponent(c, managedfs, 1);
nn_mountComponent(c, gpuCard, 2);
while(true) {
if(WindowShouldClose()) break;
@@ -578,6 +579,7 @@ cleanup:;
nn_dropComponent(eepromCard);
nn_dropComponent(managedfs);
nn_dropComponent(screen);
nn_dropComponent(gpuCard);
// rip the universe
nn_destroyUniverse(u);
UnloadFont(font);

View File

@@ -438,6 +438,30 @@ static ncl_VRAMBuf *ncl_allocVRAM(nn_Context *ctx, int width, int height) {
return buf;
}
static ncl_ScreenPixel *ncl_vramPtr(ncl_VRAMBuf *buf, int x, int y) {
x--;
y--;
if(x < 0 || y < 0 || x >= buf->width || y >= buf->height) return NULL;
return &buf->pixels[x + y * buf->width];
}
static ncl_ScreenPixel ncl_vramGet(ncl_VRAMBuf *buf, int x, int y) {
ncl_ScreenPixel *ptr = ncl_vramPtr(buf, x, y);
if(ptr != NULL) return *ptr;
return (ncl_ScreenPixel) {
.codepoint = ' ',
.storedFg = 0xFFFFFF,
.storedBg = 0x000000,
.realFg = 0xFFFFFF,
.realBg = 0x000000,
};
}
static void ncl_vramSet(ncl_VRAMBuf *buf, int x, int y, ncl_ScreenPixel pixel) {
ncl_ScreenPixel *ptr = ncl_vramPtr(buf, x, y);
if(ptr != NULL) *ptr = pixel;
}
typedef struct ncl_FSState {
nn_Context *ctx;
nn_Lock *lock;
@@ -590,6 +614,11 @@ static nn_Exit ncl_fsHandler(nn_FSRequest *req) {
}
state->fds[fd] = file;
req->fd = fd;
if(mode[0] == 'w') {
// file cleared
state->spaceUsed = 0;
state->realSpaceUsed = 0;
}
nn_unlock(ctx, state->lock);
return NN_OK;
}
@@ -1008,7 +1037,88 @@ fail:;
return NULL;
}
nn_Component *ncl_createGPU(nn_Universe *universe, const char *address, const nn_GPU *gpu);
static ncl_ScreenState *ncl_getBoundScreen(ncl_GPUState *gpu, nn_Computer *C) {
if(gpu->screenAddress == NULL) return NULL;
nn_Component *c = nn_getComponent(C, gpu->screenAddress);
if(c == NULL) return NULL;
return nn_getComponentState(c);
}
static void ncl_getGPULimits(ncl_GPUState *gpu, nn_Computer *C, int *maxWidth, int *maxHeight, char *maxDepth) {
int w = gpu->conf.maxWidth, h = gpu->conf.maxHeight;
char d = gpu->conf.maxDepth;
ncl_ScreenState *screen = ncl_getBoundScreen(gpu, C);
if(screen != NULL) {
if(w > screen->conf.maxWidth) w = screen->conf.maxWidth;
if(h > screen->conf.maxHeight) h = screen->conf.maxHeight;
if(d > screen->conf.maxDepth) d = screen->conf.maxDepth;
}
*maxWidth = w;
*maxHeight = h;
*maxDepth = d;
}
static nn_Exit ncl_gpuHandler(nn_GPURequest *req) {
nn_Context *ctx = req->ctx;
nn_Computer *C = req->computer;
ncl_GPUState *state = req->state;
const nn_GPU *gpu = req->gpu;
if(req->action == NN_GPU_DROP) {
for(size_t i = 0; i < NCL_MAX_VRAMBUF; i++) {
if(state->vram[i] != NULL) ncl_freeVRAM(ctx, state->vram[i]);
}
if(state->screenAddress != NULL) nn_strfree(ctx, state->screenAddress);
nn_free(ctx, state, sizeof(*state));
return NN_OK;
}
if(C != NULL) nn_setError(C, "ncl-gpu: not implemented yet");
return NN_EBADCALL;
}
nn_Component *ncl_createGPU(nn_Universe *universe, const char *address, const nn_GPU *gpu) {
nn_Context *ctx = nn_getUniverseContext(universe);
nn_Lock *lock = NULL;
ncl_GPUState *state = NULL;
nn_Component *c = NULL;
lock = nn_createLock(ctx);
if(lock == NULL) goto fail;
state = nn_alloc(ctx, sizeof(*state));
if(state == NULL) goto fail;
state->ctx = ctx;
state->lock = lock;
state->conf = *gpu;
state->vramFree = gpu->totalVRAM;
state->screenAddress = NULL;
state->currentFg = 0xFFFFFF;
state->currentBg = 0x000000;
state->activeBuffer = 0;
state->isFgPalette = false;
state->isBgPalette = false;
for(size_t i = 0; i < NCL_MAX_VRAMBUF; i++) {
state->vram[i] = NULL;
}
c = nn_createGPU(universe, address, gpu, state, ncl_gpuHandler);
if(c == NULL) goto fail;
if(nn_setComponentTypeID(c, NCL_GPU)) goto fail;
return c;
fail:
if(c != NULL) {
nn_dropComponent(c);
return NULL;
}
if(lock != NULL) nn_destroyLock(ctx, lock);
nn_free(ctx, state, sizeof(*state));
return NULL;
}
void ncl_lockScreen(ncl_ScreenState *state) {
nn_lock(state->ctx, state->lock);

View File

@@ -1821,6 +1821,8 @@ bool nn_costComponent(nn_Computer *computer, const char *address, double perTick
}
bool nn_costComponentN(nn_Computer *computer, const char *address, double amount, double perTick) {
// this means 0 per tick means free
if(perTick == 0) return false;
nn_ComponentEntry *c = nn_getInternalComponent(computer, address);
if(c == NULL) return false;
c->budgetUsed += (NN_COMPONENT_CALLBUDGET * amount) / perTick;
@@ -3825,3 +3827,51 @@ nn_Component *nn_createScreen(nn_Universe *universe, const char *address, const
nn_setComponentHandler(c, nn_screenHandler);
return c;
}
typedef struct nn_GPUState {
nn_Context *ctx;
nn_GPU gpu;
nn_GPUHandler *handler;
} nn_GPUState;
static nn_Exit nn_gpuHandler(nn_ComponentRequest *req) {
if(req->action == NN_COMP_CHECKMETHOD) return NN_OK;
if(req->action == NN_COMP_SIGNAL) return NN_OK;
nn_Context *ctx = req->ctx;
nn_GPUState *state = req->classState;
nn_Computer *C = req->computer;
nn_GPURequest greq;
greq.ctx = ctx;
greq.state = req->state;
greq.computer = C;
greq.gpu = &state->gpu;
if(req->action == NN_COMP_DROP) {
greq.action = NN_GPU_DROP;
state->handler(&greq);
nn_free(ctx, state, sizeof(*state));
return NN_OK;
}
nn_setError(C, "gpu: not yet implemented");
return NN_EBADCALL;
}
nn_Component *nn_createGPU(nn_Universe *universe, const char *address, const nn_GPU *gpu, void *state, nn_GPUHandler *handler) {
nn_Component *c = nn_createComponent(universe, address, "gpu");
if(c == NULL) return NULL;
// TODO: methods
nn_Context *ctx = &universe->ctx;
nn_GPUState *gpustate = nn_alloc(ctx, sizeof(*gpustate));
if(gpustate == NULL) {
nn_dropComponent(c);
return NULL;
}
gpustate->ctx = ctx;
gpustate->gpu = *gpu;
gpustate->handler = handler;
nn_setComponentState(c, state);
nn_setComponentClassState(c, gpustate);
nn_setComponentHandler(c, nn_gpuHandler);
return c;
}

View File

@@ -1220,6 +1220,22 @@ typedef struct nn_GPU {
// 1 GPU tier for every screen.
extern const nn_GPU nn_defaultGPUs[4];
typedef enum nn_GPUAction {
NN_GPU_DROP,
} nn_GPUAction;
typedef struct nn_GPURequest {
nn_Context *ctx;
nn_Computer *computer;
void *state;
const nn_GPU *gpu;
nn_GPUAction action;
} nn_GPURequest;
typedef nn_Exit (nn_GPUHandler)(nn_GPURequest *req);
nn_Component *nn_createGPU(nn_Universe *universe, const char *address, const nn_GPU *gpu, void *state, nn_GPUHandler *handler);
// Colors and palettes.
// Do note that the