shithub: gpufs

Download patch

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,