From: Eleni Maria Stea Date: Thu, 8 Mar 2018 10:37:22 +0000 (+0200) Subject: test program that renders a quad using spirv shaders, used for debugging X-Git-Url: https://eleni.mutantstargoat.com/git/?p=glquad-spirv;a=commitdiff_plain test program that renders a quad using spirv shaders, used for debugging SPIR-V at work --- 3558254a2400ae27a2e147681ba0848c1a1b19a1 diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..210b083 --- /dev/null +++ b/Makefile @@ -0,0 +1,21 @@ +src = $(wildcard src/*.cc) +obj = $(src:.cc=.o) +bin = glquad + +GLSLANG = glslangValidator + +CXXFLAGS = -pedantic -Wall -g +LDFLAGS = -lGL -lGLU -lglut -lGLEW + +$(bin): $(obj) data/spirv/vertex.spv data/spirv/pixel.spv + $(CXX) -o $@ $(obj) $(LDFLAGS) + +data/spirv/vertex.spv: data/test.v.glsl + $(GLSLANG) -G -V -S vert -o $@ $< + +data/spirv/pixel.spv: data/test.f.glsl data/pixel2.f.glsl + $(GLSLANG) -l -G -V -S frag -o $@ $^ + +.PHONY: clean +clean: + rm -f $(obj) $(bin) data/spirv/* diff --git a/data/pixel2.f.glsl b/data/pixel2.f.glsl new file mode 100644 index 0000000..7357abd --- /dev/null +++ b/data/pixel2.f.glsl @@ -0,0 +1,11 @@ +#version 450 + +vec4 ambient(float num, vec4 c) +{ + float r = min(c.r + num, 1.0); + float g = min(c.g + num, 1.0); + float b = min(c.b + num, 1.0); + float a = 1.0; + + return vec4(r, g, b, a); +} diff --git a/data/spirv/pixel.spv b/data/spirv/pixel.spv new file mode 100644 index 0000000..46a1aae Binary files /dev/null and b/data/spirv/pixel.spv differ diff --git a/data/spirv/vertex.spv b/data/spirv/vertex.spv new file mode 100644 index 0000000..d116011 Binary files /dev/null and b/data/spirv/vertex.spv differ diff --git a/data/test.f.glsl b/data/test.f.glsl new file mode 100644 index 0000000..3f827db --- /dev/null +++ b/data/test.f.glsl @@ -0,0 +1,16 @@ +#version 450 + +//layout(location = 1) in vec4 vcol; +layout(location = 0) out vec4 out_color; +const vec4 vcol = vec4(0.1, 1.0, 1.0, 1.0); + +/*layout(std140, binding = 0) uniform Ubo { + vec4 color; +} u;*/ + +vec4 ambient(float num, vec4 c); + +void main() +{ + out_color = ambient(0.1, vcol);// + u.color); +} diff --git a/data/test.v.glsl b/data/test.v.glsl new file mode 100644 index 0000000..a2fd8aa --- /dev/null +++ b/data/test.v.glsl @@ -0,0 +1,10 @@ +#version 450 + +layout(location = 0) in vec4 vertex; +layout(location = 1) out vec4 vcol; + +void main() +{ + vcol = vec4(1.0, 0.0, 0.0, 1.0); + gl_Position = vertex; +} diff --git a/src/main.cc b/src/main.cc new file mode 100644 index 0000000..5042980 --- /dev/null +++ b/src/main.cc @@ -0,0 +1,249 @@ +#include + +#include +#include +#include + +#include + +#include +#include +#include + +#define VERTEX_LOC 0 + +struct Ubo { + float color[4] = {0, 1, 0, 1}; +}; + +static bool init(); +static void cleanup(); + +static void display(); +static void keydown(unsigned char key, int x, int y); +static unsigned int load_shader(const char *fname, int type); +static unsigned int create_program(const char *vfname, const char *pfname); +static bool link_program(unsigned int prog); + +static const char *vs_path = "data/spirv/vertex.spv"; +static const char *fs_path = "data/spirv/pixel.spv"; + +static unsigned int sprog; +static unsigned int vbo; +static unsigned int vao; + +static float vertices[] = { + -0.5, -0.5, + 0.5, -0.5, + 0.5, 0.5, + + -0.5, -0.5, + 0.5, 0.5, + -0.5, 0.5 +}; + +static int num_vertices = 6; +static Ubo test_ubo; +static unsigned int ubo; + +int main(int argc, char **argv) +{ + glutInitContextProfile(GLUT_CORE_PROFILE); + glutInitContextVersion(4, 5); + + glutInit(&argc, argv); + + glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE); + glutInitWindowSize(800, 600); + glutCreateWindow("gltest"); + + + glClear(GL_COLOR_BUFFER_BIT); + + glutDisplayFunc(display); + glutKeyboardFunc(keydown); + + if(!init()) + return 1; + + atexit(cleanup); + glutMainLoop(); +} + +static bool init() +{ + glewInit(); + + glClearColor(0.0, 0.0, 1.0, 1.0); + + glGenBuffers(1, &ubo); + glBindBuffer(GL_UNIFORM_BUFFER, ubo); + glBufferData(GL_UNIFORM_BUFFER, sizeof test_ubo, &test_ubo, GL_STREAM_DRAW); + + glGenVertexArrays(1, &vao); + glBindVertexArray(vao); + + glGenBuffers(1, &vbo); + glBindBuffer(GL_ARRAY_BUFFER, vbo); + glBufferData(GL_ARRAY_BUFFER, sizeof vertices, vertices, GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + if(!(sprog = create_program(vs_path, fs_path))) { + fprintf(stderr, "Failed to create shader program.\n"); + return false; + } + + glUseProgram(sprog); + + assert(glGetError() == GL_NO_ERROR); + return true; +} + +static void display() +{ + glEnableVertexAttribArray(VERTEX_LOC); + glBindBuffer(GL_ARRAY_BUFFER, vbo); + + glVertexAttribPointer(VERTEX_LOC, 2, GL_FLOAT, GL_FALSE, 0, 0); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + + glBindBuffer(GL_UNIFORM_BUFFER, ubo); + glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof test_ubo, &test_ubo); + glBindBufferBase(GL_UNIFORM_BUFFER, 0, ubo); + + glDrawArrays(GL_TRIANGLES, 0, num_vertices); + + assert(glGetError() == GL_NO_ERROR); + + glutSwapBuffers(); +} + +static void keydown(unsigned char key, int /*x*/, int /*y*/) +{ + switch(key) { + case 27: + exit(0); + } +} + +static unsigned int create_program(const char *vfname, const char *pfname) +{ + unsigned int vs, ps; + unsigned int prog; + + if(!(vs = load_shader(vfname, GL_VERTEX_SHADER))) + return false; + if(!(ps = load_shader(pfname, GL_FRAGMENT_SHADER))) { + glDeleteShader(vs); + return false; + } + + prog = glCreateProgram(); + glAttachShader(prog, vs); + glAttachShader(prog, ps); + + if(!link_program(prog)) { + glDeleteShader(vs); + glDeleteShader(ps); + glDeleteProgram(prog); + return false; + } + + glDetachShader(prog, vs); + glDetachShader(prog, ps); + + return prog; +} + +static bool link_program(unsigned int prog) +{ + int status, loglen; + char *buf; + + glLinkProgram(prog); + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if(status) { + printf("successfully linked shader program\n"); + } else { + printf("failed to link shader program\n"); + } + + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &loglen); + if(loglen > 0 && (buf = (char*)malloc(loglen + 1))) { + glGetProgramInfoLog(prog, loglen, 0, buf); + buf[loglen] = 0; + printf("%s\n", buf); + free(buf); + } + + return status ? true : false; +} + +unsigned int load_shader(const char *fname, int type) +{ + unsigned int sdr; + unsigned int fsz; + char *buf; + FILE *fp; + int status, loglen; + + if(!(fp = fopen(fname, "rb"))) { + fprintf(stderr, "failed to open shader: %s\n", fname); + return 0; + } + fseek(fp, 0, SEEK_END); + fsz = ftell(fp); + rewind(fp); + + if(!(buf = (char*)malloc(fsz + 1))) { + fprintf(stderr, "failed to allocate %d bytes\n", fsz + 1); + fclose(fp); + return 0; + } + if(fread(buf, 1, fsz, fp) < fsz) { + fprintf(stderr, "failed to read shader: %s\n", fname); + free(buf); + fclose(fp); + return 0; + } + buf[fsz] = 0; + fclose(fp); + + sdr = glCreateShader(type); + + glShaderBinary(1, &sdr, GL_SHADER_BINARY_FORMAT_SPIR_V_ARB, buf, fsz); + glSpecializeShaderARB(sdr, "main", 0, 0, 0); + + free(buf); + + glGetShaderiv(sdr, GL_COMPILE_STATUS, &status); + if(status) { + printf("successfully compiled shader: %s\n", fname); + } else { + printf("failed to compile shader: %s\n", fname); + } + + glGetShaderiv(sdr, GL_INFO_LOG_LENGTH, &loglen); + if(loglen > 0 && (buf = (char*)malloc(loglen + 1))) { + glGetShaderInfoLog(sdr, loglen, 0, buf); + buf[loglen] = 0; + printf("%s\n", buf); + free(buf); + } + + if(!status) { + glDeleteShader(sdr); + return 0; + } + + return sdr; +} + +static void cleanup() +{ + glDeleteVertexArrays(1, &vao); + glDeleteBuffers(1, &vbo); + glDeleteBuffers(1, &ubo); +}