ref: 8b6238bf263ac5d1f357c0f4a4d0e113b83f1570
parent: d53100c1bdfb9036a824fa60cd2dd58d02120210
author: sirjofri <sirjofri@sirjofri.de>
date: Sat Feb 24 11:43:02 EST 2024
hopefully, ready to run
--- a/README
+++ b/README
@@ -17,7 +17,7 @@
/ShaderId/ctl
c(ompile) - compile shader
-r(un) - run shader
+r(un) <entrypoint> - run shader
b(ind) <pool> - bind shader to pool
--- a/cops.c
+++ b/cops.c
@@ -1,26 +1,34 @@
#include <u.h>
#include <libc.h>
+#include "objects.h"
#include "vm.h"
#include "ops.h"
#include "names.h"
extern int debug;
-extern int compile;
-void
-printresult(int should, uint varid)
+#define DPRINT(m) if (debug) fprint(2, (m));
+
+int
+lstrlen(int len)
{
- char *s;
-
- if (!should) {
- print("%10s ", " ");
- return;
- }
- s = smprint("$%d", varid);
- print("%10s = ", s);
- free(s);
+ int nlen = len + 1;
+ return (nlen)%4 == 0 ? (nlen/4) : (nlen/4)+1;
}
+
+// true if updated
+int
+updatenitems(Shader *s, long id)
+{
+ if (id >= s->maxitems)
+ return 0;
+ if (id < s->nitems)
+ return 1;
+ s->nitems = id + 1;
+ return 1;
+}
+
void
OpTypeFloat(Frame *f, u32int)
{
@@ -27,11 +35,7 @@
u32int varid = *(f->pc+1);
u32int tlen = *(f->pc+2);
- if (compile) {
- printresult(1, varid);
- print("OpTypeFloat %d\n", tlen);
- return;
- }
+ DPRINT("OpTypeFloat\n");
}
void
@@ -40,42 +44,147 @@
u32int varid = *(f->pc+1);
u32int tlen = *(f->pc+2);
- if (compile) {
- printresult(1, varid);
- print("OpTypeInt %d\n", tlen);
+ DPRINT("OpTypeInt\n");
+}
+
+void
+OpName(Frame *f, u32int)
+{ DPRINT("OpName\n"); return; }
+
+void
+OpNop(Frame*, u32int)
+{ DPRINT("OpNop\n"); return; }
+
+void
+OpEntryPoint(Frame* f, u32int len)
+{
+ if (f->ctxt.type == COMPILE) {
+ EntryPoint *p;
+ Shader *s;
+ u32int emodel = f->pc[1];
+ u32int epoint = f->pc[2];
+ char *name = (char*)&f->pc[3];
+ int l = lstrlen(strlen(name)) + 3;
+ u32int *argv = &f->pc[l];
+ u32int argc = len - l;
+
+ DPRINT("OpEntryPoint\n");
+
+ // only support GLCompute shaders
+ if (emodel != 5)
+ return;
+
+ s = f->ctxt.c.shader;
+ p = malloc(sizeof(EntryPoint));
+ p->name = strdup(name);
+ p->func = epoint;
+
+ if (s->entrypoints) {
+ p->next = s->entrypoints;
+ s->entrypoints = p;
+ } else {
+ p->next = nil;
+ s->entrypoints = p;
+ }
return;
}
+ return;
}
void
-OpName(Frame *f, u32int)
+OpTypeFunction(Frame *f, u32int len)
{
- u32int varid = *(f->pc+1);
- char *varname = (char*)(f->pc+2);
-
- nameadd(varid, varname);
-
- if (compile) {
- printresult(0, 0);
- print("OpName $%d \"%s\"\n", varid, varname);
+ if (f->ctxt.type == COMPILE) {
+ Shader *s = f->ctxt.c.shader;
+ u32int varid = f->pc[1];
+ u32int rettype = f->pc[2];
+ u32int *argv = &f->pc[3];
+ u32int argc = len - 3;
+
+ DPRINT("OpTypeFunction\n");
+
+ // TODO error!
+ if (!updatenitems(s, varid))
+ return;
+
+ s->items[varid].type = TTYPE;
+ s->items[varid].t.optype = 33;
+ }
+ return;
+}
+
+void
+OpFunction(Frame *f, u32int len)
+{
+ if (f->ctxt.type == COMPILE) {
+ Shader *s = f->ctxt.c.shader;
+ u32int result = f->pc[1];
+ u32int retvar = f->pc[2];
+ u32int fctl = f->pc[3];
+ u32int ftype = f->pc[4];
+
+ DPRINT("OpFunction\n");
+
+ // TODO error!
+ if (!updatenitems(s, result))
+ return;
+
+ s->items[result].type = TFUNCTION;
+ s->items[result].f.rettype = retvar;
+ s->items[result].f.label = -1;
+ s->lastfunction = result;
return;
}
+ // TODO: new stack
+ return;
}
void
-OpNop(Frame*, u32int)
+OpFunctionEnd(Frame *f, u32int len)
{
- if (compile) {
- printresult(0, 0);
- print("OpNop\n");
+ DPRINT("OpFunctionEnd\n");
+
+ if (f->ctxt.type == COMPILE)
+ return;
+
+ // TODO: pop stack
+ return;
+}
+
+void
+OpLabel(Frame *f, u32int len)
+{
+ if (f->ctxt.type == COMPILE) {
+ Shader *s = f->ctxt.c.shader;
+ u32int retvar = f->pc[1];
+
+ DPRINT("OpLabel\n");
+
+ if (!updatenitems(s, retvar))
+ return;
+
+ s->items[retvar].type = TLABEL;
+ s->items[retvar].l.ptr = &f->pc[len + 1];
+
+ if (s->lastfunction >= 0) {
+ s->items[s->lastfunction].f.label = retvar;
+ s->lastfunction = -1;
+ }
+ return;
}
+ return;
}
Op oplist[] = {
- { 5, OpName },
- { 21, OpTypeInt },
- { 22, OpTypeFloat },
- { nil, OpNop },
+ { 5, OpName },
+ { 15, OpEntryPoint },
+ { 21, OpTypeInt },
+ { 22, OpTypeFloat },
+ { 33, OpTypeFunction },
+ { 54, OpFunction },
+ { 56, OpFunctionEnd },
+ { 248, OpLabel },
+ { nil, OpNop },
};
int
--- a/dops.c
+++ b/dops.c
@@ -1,5 +1,6 @@
#include <u.h>
#include <libc.h>
+#include "objects.h"
#include "vm.h"
#include "ops.h"
#include "names.h"
--- a/gpufs.c
+++ b/gpufs.c
@@ -86,8 +86,6 @@
static char *user;
static long time0;
-u32int magic = 0x07230203;
-
static void*
wfaux(Gpufid *f)
{
@@ -447,7 +445,7 @@
objectcommand(Req *r, int argc, char **argv)
{
// c(ompile)
- // r(un)
+ // r(un) <entrypoint>
// b(ind) <pool>
Gpufid* f;
@@ -467,7 +465,14 @@
}
}
if (strcmp(argv[0], "r") == 0) {
- respond(r, "not implemented");
+ if (argc != 2) {
+ respond(r, "bad command");
+ return;
+ }
+ if (!runshader(f->id, argv[1])) {
+ responderr(r);
+ return;
+ }
return;
}
if (strcmp(argv[0], "b") == 0) {
--- a/mkfile
+++ b/mkfile
@@ -4,6 +4,12 @@
gpufs\
spirvd\
+HFILES=\
+ names.h\
+ objects.h\
+ ops.h\
+ vm.h\
+
</sys/src/cmd/mkmany
$O.gpufs: gpufs.$O vm.$O cops.$O names.$O
--- a/objects.h
+++ b/objects.h
@@ -4,11 +4,66 @@
long len;
};
+typedef struct Variable Variable;
+struct Variable {
+ long type;
+};
+
+typedef struct Type Type;
+struct Type {
+ u32int len;
+ u32int optype;
+};
+
+typedef struct Function Function;
+struct Function {
+ long rettype;
+ long label;
+};
+
+typedef struct Label Label;
+struct Label {
+ u32int *ptr;
+};
+
+enum {
+ TTYPE,
+ TVARIABLE,
+ TFUNCTION,
+ TLABEL,
+};
+
+typedef struct Item Item;
+struct Item {
+ short type;
+ union {
+ Variable v;
+ Type t;
+ Function f;
+ Label l;
+ };
+};
+
+typedef struct EntryPoint EntryPoint;
+struct EntryPoint {
+ char *name;
+ long func;
+ EntryPoint *next;
+};
+
typedef struct Shader Shader;
struct Shader {
u32int *buffer;
long len;
int descpool;
+ int compiled; // is the shader compiled?
+
+ Item *items;
+ long nitems;
+ long maxitems;
+ EntryPoint *entrypoints;
+
+ long lastfunction;
};
typedef struct DescSet DescSet;
--- a/ops.h
+++ b/ops.h
@@ -1,6 +1,25 @@
+typedef struct CompileTimeContext CompileTimeContext;
+struct CompileTimeContext {
+ Shader *shader;
+};
+
+enum {
+ COMPILE,
+ RUNTIME,
+};
+
+typedef struct FrameContext FrameContext;
+struct FrameContext {
+ short type;
+ union {
+ CompileTimeContext c;
+ };
+};
+
typedef struct Frame Frame;
struct Frame {
u32int *pc;
+ FrameContext ctxt;
Frame *next;
};
--- a/spirvd.c
+++ b/spirvd.c
@@ -1,5 +1,6 @@
#include <u.h>
#include <libc.h>
+#include "objects.h"
#include "vm.h"
#include "ops.h"
--- a/vm.c
+++ b/vm.c
@@ -1,12 +1,14 @@
#include <u.h>
#include <libc.h>
#include <String.h>
-#include "vm.h"
-#include "ops.h"
#include "objects.h"
+#include "ops.h"
+#include "vm.h"
extern int debug;
+u32int magic = 0x07230203;
+
static char *Einvalid = "invalid id %lld";
static char *Ewrongtype = "wrong object type %lld != %s";
@@ -74,8 +76,6 @@
runstack(ptr);
}
-int compile = 0;
-
typedef struct Object Object;
struct Object {
int id;
@@ -112,17 +112,91 @@
return 1;
}
+int
+runshader(vlong id, char *entrypoint)
+{
+ Shader *s;
+ EntryPoint *ep;
+
+ if (!validate(id, SHADER))
+ return 0;
+
+ s = &objects[id].s;
+
+ if (!s->compiled) {
+ werrstr("Shader %lld not compiled", id);
+ return 0;
+ }
+
+ for (ep = s->entrypoints; ep; ep = ep->next) {
+ if (strcmp(ep->name, entrypoint) == 0)
+ break;
+ }
+ if (!ep) {
+ werrstr("entry point %s not found", entrypoint);
+ return 0;
+ }
+
+ for (int i = 0; i < s->nitems; i++) {
+ fprint(2, "%d → %d\n", i, s->items[i].type);
+ }
+
+ if (s->items[ep->func].type != TFUNCTION) {
+ werrstr("entry point function not found (object %ld type %d)", ep->func, s->items[ep->func].type);
+ return 0;
+ }
+
+ long label = s->items[ep->func].f.label;
+ if (label < 0) {
+ werrstr("entry point function has no label");
+ return 0;
+ }
+
+ if (s->items[label].type != TLABEL) {
+ werrstr("entry point function label is not valid");
+ return 0;
+ }
+
+ u32int *ptr = s->items[label].l.ptr;
+
+ werrstr("passed tests, but not implemented yet");
+ return 0;
+}
+
+String*
+getentrypointlist(Shader *sh)
+{
+ String *s;
+ EntryPoint *ep;
+ s = s_new();
+
+ for (ep = sh->entrypoints; ep; ep = ep->next) {
+ s_append(s, "\nEntryPoint ");
+ s_append(s, ep->name);
+ }
+ return s;
+}
+
void
updateinfostring(vlong id)
{
+ String *s;
+
switch (objects[id].type) {
case SHADER:
if (objects[id].info)
free(objects[id].info);
+
+ s = getentrypointlist(&objects[id].s);
objects[id].info = smprint(
- "DescriptorPool %d\n",
- objects[id].s.descpool
+ "DescriptorPool %d\n"
+ "Compiled %s"
+ "%s\n",
+ objects[id].s.descpool,
+ objects[id].s.compiled ? "yes" : "no",
+ s_to_c(s)
);
+ s_free(s);
break;
case BUFFER:
if (objects[id].info)
@@ -149,6 +223,12 @@
objects[id].s.buffer = nil;
objects[id].s.len = -1;
objects[id].s.descpool = -1;
+ objects[id].s.compiled = 0;
+ objects[id].s.items = nil;
+ objects[id].s.nitems = -1;
+ objects[id].s.maxitems = -1;
+ objects[id].s.entrypoints = nil;
+ objects[id].s.lastfunction = -1;
updateinfostring(id);
return id;
}
@@ -275,6 +355,9 @@
compileshader(vlong id)
{
Shader *sh;
+ Frame f;
+ u32int *lastbuf;
+
if (!validate(id, SHADER)) {
return 0;
}
@@ -290,8 +373,47 @@
return 0;
}
- werrstr("not implemented!");
- return 0;
+ if (sh->compiled) {
+ werrstr("shader is already compiled");
+ return 0;
+ }
+
+ if (*sh->buffer != magic) {
+ werrstr("invalid shader format");
+ return 0;
+ }
+
+ sh->maxitems = 100;
+ sh->items = malloc(sh->maxitems*sizeof(Item));
+ sh->nitems = 0;
+
+ f.pc = &sh->buffer[1]; // ignore magic number
+ f.next = nil;
+ f.ctxt.type = COMPILE;
+ f.ctxt.c.shader = sh;
+ lastbuf = &sh->buffer[sh->len-1];
+
+ while (f.pc < lastbuf) {
+ u32int len, opcode;
+ u32int *oldpc = f.pc;
+ void (*func)(Frame*,u32int);
+ opcode = (*f.pc) & 0x0000ffff;
+ len = ((*f.pc) & 0xffff0000) >> 16;
+
+ if (!len)
+ break;
+
+ if (oplookup(opcode, &func)) {
+ func(&f, len);
+ }
+
+ if (oldpc == f.pc) {
+ f.pc += len;
+ }
+ }
+
+ updateinfostring(id);
+ return sh->compiled = 1;
}
int
--- a/vm.h
+++ b/vm.h
@@ -1,6 +1,7 @@
void vmrun(u32int *ptr);
void runstack(u32int *ptr);
void retstack(void);
+int runshader(vlong id, char *entrypoint);
enum {
BUFFER,