test program that renders a quad using spirv shaders, used for debugging master
authorEleni Maria Stea <estea@igalia.com>
Thu, 8 Mar 2018 10:37:22 +0000 (12:37 +0200)
committerEleni Maria Stea <estea@igalia.com>
Thu, 8 Mar 2018 10:37:22 +0000 (12:37 +0200)
SPIR-V at work

Makefile [new file with mode: 0644]
data/pixel2.f.glsl [new file with mode: 0644]
data/spirv/pixel.spv [new file with mode: 0644]
data/spirv/vertex.spv [new file with mode: 0644]
data/test.f.glsl [new file with mode: 0644]
data/test.v.glsl [new file with mode: 0644]
src/main.cc [new file with mode: 0644]

diff --git a/Makefile b/Makefile
new file mode 100644 (file)
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 (file)
index 0000000..7357abd
--- /dev/null
@@ -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 (file)
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 (file)
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 (file)
index 0000000..3f827db
--- /dev/null
@@ -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 (file)
index 0000000..a2fd8aa
--- /dev/null
@@ -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 (file)
index 0000000..5042980
--- /dev/null
@@ -0,0 +1,249 @@
+#include <GL/glew.h>
+
+#include <GL/freeglut.h>
+#include <GL/glext.h>
+#include <GL/glx.h>
+
+#include <assert.h>
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#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);
+}