ref: 2ea9cb1ccca882e47c316cde52302cd108310649
dir: /vm.c/
#include <u.h> #include <libc.h> #include "vm.h" #include "ops.h" #include "objects.h" extern int debug; static char *Einvalid = "invalid id %lld"; static char *Ewrongtype = "wrong object type %lld != %s"; #define IDVALID(c) (c < numobjects) Frame *stack = nil; u32int runinst(u32int *ptr) { u32int len, opcode; void (*func)(Frame*,u32int); opcode = (*ptr) & 0x0000ffff; len = ((*ptr) & 0xffff0000) >> 16; if (oplookup(opcode, &func)) { func(stack, len); // if (func) changes pc, ignore it if (ptr == stack->pc) { stack->pc += len; } return len; } fprint(2, "error: %r\n"); return 0; } void runstack(u32int *ptr) { Frame *n = malloc(sizeof(Frame)); n->next = stack; stack = n; stack->pc = ptr; while (runinst(stack->pc)) { ; } } void retstack(void) { Frame *p, *c; p = stack->next; c = stack; if (!p) goto fin; stack = p; fin: free(c); } void vmrun(u32int *ptr) { stack = nil; // TODO clean stack runstack(ptr); } int compile = 0; typedef struct Object Object; struct Object { int id; char type; char *info; union { Shader s; Buffer b; }; }; Object objects[256]; int numobjects = 0; DescPool descpools[8]; int numdescpools = 0; static char* typenames[] = { "BUFFER", "SHADER", }; int validate(vlong id, int type) { if (!IDVALID(id)) { werrstr(Einvalid, id); return 0; } if (objects[id].type != type) { werrstr(Ewrongtype, id, typenames[type]); return 0; } return 1; } void updateinfostring(vlong id) { switch (objects[id].type) { case SHADER: if (objects[id].info) free(objects[id].info); objects[id].info = smprint( "DescriptorPool %d\n", objects[id].s.descpool ); break; case BUFFER: if (objects[id].info) free(objects[id].info); objects[id].info = smprint( "Length %ld\n", objects[id].b.len ); break; } } vlong genshader(void) { vlong id; if (numobjects >= 256) { werrstr("not enough free objects!"); return -1; } id = numobjects++; objects[id].id = id; objects[id].type = SHADER; objects[id].s.buffer = nil; objects[id].s.len = -1; updateinfostring(id); return id; } vlong genbuffer(long size) { vlong id; if (numobjects >= 256) { werrstr("not enough free objects!"); return -1; } id = numobjects++; objects[id].id = id; objects[id].type = BUFFER; objects[id].b.len = size; objects[id].b.buffer = malloc(size); if (!objects[id].b.buffer) { werrstr("cannot allocate memory: %r"); return -1; } updateinfostring(id); return id; } vlong getnumobjects() { return numobjects; } long getbufferlength(vlong id) { if (objects[id].type != BUFFER) { werrstr("invalid object type!"); return -1; } return objects[id].b.len; } long getshaderlength(vlong id) { long len; if (objects[id].type != SHADER) { werrstr("invalid object type!"); return -1; } len = objects[id].s.len; return len < 0 ? 0 : len; } int getobjecttype(vlong id) { return objects[id].type; } vlong getobjectid(vlong num) { if (num >= numobjects) { werrstr("invalid object number: %lld", num); return -1; } return objects[num].id; } int writeshader(vlong id, void *data, long n, long offset) { char *buf; if (!validate(id, SHADER)) { return 0; } buf = (char*)objects[id].s.buffer; if (!buf) { objects[id].s.len = n+offset; objects[id].s.buffer = malloc(objects[id].s.len); buf = (char*)objects[id].s.buffer; } if (!buf) { sysfatal("out of memory"); return 0; } if (offset+n > objects[id].s.len) { objects[id].s.len = n+offset; objects[id].s.buffer = realloc(objects[id].s.buffer, objects[id].s.len); buf = (char*)objects[id].s.buffer; } if (!buf) { sysfatal("out of memory!"); return 0; } buf += offset; memcpy(buf, data, n); updateinfostring(id); return n; } int writebuffer(vlong id, void *data, long n, long offset) { char *buf; if (!validate(id, BUFFER)) { return 0; } if (offset+n > objects[id].b.len) { return -1; } buf = &objects[id].b.buffer[offset]; memcpy(buf, data, n); updateinfostring(id); return n; } int compileshader(vlong id) { werrstr("not implemented!"); return 0; } int readshader(vlong id, void *data, long n, long offset) { char *buf; if (!validate(id, SHADER)) { return 0; } buf = (char*)objects[id].s.buffer; if (!buf) { werrstr("shader is empty"); return 0; } if (offset+n > objects[id].b.len) { n = objects[id].s.len - offset; } if (n <= 0) return 0; buf = &buf[offset]; memcpy(data, buf, n); return n; } int readbuffer(vlong id, void *data, long n, long offset) { char *buf; if (!validate(id, BUFFER)) { return 0; } if (offset+n > objects[id].b.len) { n = objects[id].b.len - offset; } if (n <= 0) return 0; buf = &objects[id].b.buffer[offset]; memcpy(data, buf, n); return n; } int gendescpool(int numsets) { int id; if (numdescpools >= 8) { werrstr("not enough pools reserved"); return -1; } id = numdescpools++; descpools[id].sets = malloc(sizeof(DescSet)*numsets); if (!descpools[id].sets) { sysfatal("out of memory"); return -1; } descpools[id].numsets = numsets; memset(descpools[id].sets, 0, sizeof(DescSet)*numsets); return id; } int allocdescset(int pool, int set, int numbindings) { if (pool >= numdescpools) { werrstr("invalid pool id %d", pool); return 0; } if (set >= descpools[pool].numsets) { werrstr("invalid set id %d", pool); return 0; } descpools[pool].sets[set].bindings = malloc(sizeof(vlong)*numbindings); if (!descpools[pool].sets[set].bindings) { sysfatal("out of memory"); return 0; } for (int i = 0; i < numbindings; i++) { descpools[pool].sets[set].bindings[i] = -1; } descpools[pool].sets[set].numbindings = numbindings; return 1; } int binduniform(vlong id, int pool, int set, int binding) { if (!validate(id, BUFFER)) { return 0; } if (pool >= numdescpools) { werrstr("invalid pool id %d", pool); return 0; } if (set >= descpools[pool].numsets) { werrstr("pool has not enough sets"); return 0; } if (binding >= descpools[pool].sets[set].numbindings) { werrstr("set has not enough bindings"); return 0; } descpools[pool].sets[set].bindings[binding] = id; return 1; } int bindshader(vlong id, int pool) { if (!validate(id, SHADER)) { return 0; } objects[id].s.descpool = pool; updateinfostring(id); return 1; } char* getobjectinfo(vlong id) { if (!IDVALID(id)) { werrstr(Einvalid, id); return nil; } return objects[id].info; }