compute shaders!

main
Dominik Madarász 2023-09-08 08:16:32 +02:00
parent 1d7e68f18c
commit 51320bfab1
10 changed files with 344 additions and 6 deletions

19
demos/99-compute.c 100644
View File

@ -0,0 +1,19 @@
#include "v4k.h"
int main() {
// 75% sized, MSAAx2
window_create(50, WINDOW_SQUARE);
window_title(__FILE__);
unsigned comp = compute(vfs_read("shaders/compute-test.glsl"));
texture_t tex = texture_create(512, 512, 4, 0, TEXTURE_LINEAR|TEXTURE_FLOAT);
while ( window_swap() && !input_down(KEY_ESC) ){
shader_bind(comp);
shader_float("t", (float)window_time());
shader_image(&tex, 0, 0, -1, READ);
dispatch(512, 512, 1);
imageWriteBarrier();
fullscreen_quad_rgb(tex, 2.2);
}
}

View File

@ -0,0 +1,18 @@
layout (local_size_x = 10, local_size_y = 10, local_size_z = 1) in;
layout(rgba32f, binding = 0) uniform image2D imgOutput;
layout (location = 0) uniform float t; /** Time */
void main() {
vec4 value = vec4(0.0, 0.0, 0.0, 1.0);
ivec2 texelCoord = ivec2(gl_GlobalInvocationID.xy);
float speed = 100;
// the width of the texture
float width = 1000;
value.x = mod(float(texelCoord.x) + t * speed, width) / (gl_NumWorkGroups.x * gl_WorkGroupSize.x);
value.y = float(texelCoord.y)/(gl_NumWorkGroups.y*gl_WorkGroupSize.y);
imageStore(imgOutput, texelCoord, value);
}

View File

@ -2230,6 +2230,7 @@ union { unsigned y, h; };
union { unsigned z, d; };
union { unsigned n, bpp; };
handle id, unit;
unsigned texel_type;
unsigned flags;
char* filename;
bool transparent;
@ -2358,6 +2359,16 @@ int texture_width;
void shader_colormap(const char *name, colormap_t cm);
unsigned shader_get_active();
void shader_destroy(unsigned shader);
enum ACCESS_MODE {
READ,
WRITE,
READ_WRITE
};
unsigned compute(const char *cs);
void dispatch(unsigned wx, unsigned wy, unsigned wz);
void shader_image(texture_t *t, unsigned unit, unsigned level, int layer , unsigned access);
void shader_image_unit(unsigned texture, unsigned unit, unsigned level, int layer , unsigned texel_type, unsigned access);
void imageWriteBarrier();
enum MESH_FLAGS {
MESH_STATIC = 0,
MESH_STREAM = 1,

View File

@ -16280,6 +16280,7 @@ typedef struct texture_t {
union { unsigned z, d; };
union { unsigned n, bpp; };
handle id, unit;
unsigned texel_type;
unsigned flags;
char* filename;
bool transparent;
@ -16481,6 +16482,19 @@ API void shader_colormap(const char *name, colormap_t cm);
API unsigned shader_get_active();
API void shader_destroy(unsigned shader);
// compute shaders
enum ACCESS_MODE {
READ,
WRITE,
READ_WRITE
};
API unsigned compute(const char *cs);
API void dispatch(unsigned wx, unsigned wy, unsigned wz);
API void shader_image(texture_t *t, unsigned unit, unsigned level, int layer /* -1 to disable layered access */, unsigned access);
API void shader_image_unit(unsigned texture, unsigned unit, unsigned level, int layer /* -1 to disable layered access */, unsigned texel_type, unsigned access);
API void imageWriteBarrier();
// -----------------------------------------------------------------------------
// meshes (@fixme: deprecate?)
@ -340094,6 +340108,56 @@ unsigned shader(const char *vs, const char *fs, const char *attribs, const char
return program;
}
unsigned compute(const char *cs){
#if is(ems)
return 0;
#else
PRINTF(/*"!"*/"Compiling compute shader\n");
cs = cs[0] == '#' && cs[1] == 'c' ? cs : va("#version 430 core\n%s", cs ? cs : "");
GLuint comp = shader_compile(GL_COMPUTE_SHADER, cs);
GLuint program = 0;
if( comp ) {
program = glCreateProgram();
glAttachShader(program, comp);
glLinkProgram(program);
GLint status = GL_FALSE, length;
glGetProgramiv(program, GL_LINK_STATUS, &status);
#ifdef DEBUG_SHADER
if (status != GL_FALSE && program == DEBUG_SHADER) {
#else
if (status == GL_FALSE) {
#endif
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length);
char *buf = stack(length+1);
glGetProgramInfoLog(program, length, NULL, buf);
puts("--- cs:");
shader_print(cs);
}
if (status == GL_FALSE) {
PANIC("ERROR: shader(): Shader/program link: %s\n", buf);
return 0;
}
glDeleteShader(comp);
}
return program;
#endif
}
void dispatch(unsigned wx, unsigned wy, unsigned wz){
glDispatchCompute(wx, wy, wz);
}
void imageWriteBarrier(){
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
}
void shader_destroy(unsigned program){
if( program == ~0u ) return;
glDeleteProgram(program);
@ -340126,6 +340190,13 @@ void shader_texture_unit(const char *sampler, unsigned id, unsigned unit) {
glActiveTexture(GL_TEXTURE0 + unit);
glBindTexture(GL_TEXTURE_2D, id);
}
void shader_image(texture_t *t, unsigned unit, unsigned level, int layer /* -1 to disable layered access */, unsigned access){
shader_image_unit(t->id, unit, level, layer, t->texel_type, access);
}
void shader_image_unit(unsigned texture, unsigned unit, unsigned level, int layer, unsigned texel_type, unsigned access){
GLenum gl_access[] = {GL_READ_ONLY, GL_WRITE_ONLY, GL_READ_WRITE};
glBindImageTexture(unit, texture, level, layer!=-1, layer!=-1?layer:0, gl_access[access], texel_type);
}
void shader_colormap(const char *name, colormap_t c ) {
// assumes shader uses `struct { vec4 color; bool has_tex } name + sampler2D name_tex;`
@ -340251,7 +340322,7 @@ unsigned texture_update(texture_t *t, unsigned w, unsigned h, unsigned n, const
GLuint pixel_types[] = { GL_RED, GL_RED, GL_RG, GL_RGB, GL_RGBA, GL_R32F, GL_R32F, GL_RG32F, GL_RGB32F, GL_RGBA32F };
GLenum pixel_storage = flags & TEXTURE_FLOAT ? GL_FLOAT : GL_UNSIGNED_BYTE;
GLuint pixel_type = pixel_types[ n ];
GLuint texel_type = pixel_types[ n + 5 * !!(flags & TEXTURE_FLOAT) ];
GLuint texel_type = t->texel_type = pixel_types[ n + 5 * !!(flags & TEXTURE_FLOAT) ];
GLenum wrap = GL_CLAMP_TO_EDGE;
GLenum min_filter = GL_NEAREST, mag_filter = GL_NEAREST;
// GLfloat color = (flags&7)/7.f, border_color[4] = { color, color, color, 1.f };
@ -349463,9 +349534,14 @@ void window_hints(unsigned flags) {
//glfwWindowHint( GLFW_COCOA_MENUBAR, GLFW_FALSE );
#endif
#ifdef __APPLE__
/* We need to explicitly ask for a 3.2 context on OS X */
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); // osx
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2); // osx, 2:#version150,3:330
#else
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
#endif
#ifdef __APPLE__
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); //osx
#endif

View File

@ -194,6 +194,56 @@ unsigned shader(const char *vs, const char *fs, const char *attribs, const char
return program;
}
unsigned compute(const char *cs){
#if is(ems)
return 0;
#else
PRINTF(/*"!"*/"Compiling compute shader\n");
cs = cs[0] == '#' && cs[1] == 'c' ? cs : va("#version 430 core\n%s", cs ? cs : "");
GLuint comp = shader_compile(GL_COMPUTE_SHADER, cs);
GLuint program = 0;
if( comp ) {
program = glCreateProgram();
glAttachShader(program, comp);
glLinkProgram(program);
GLint status = GL_FALSE, length;
glGetProgramiv(program, GL_LINK_STATUS, &status);
#ifdef DEBUG_SHADER
if (status != GL_FALSE && program == DEBUG_SHADER) {
#else
if (status == GL_FALSE) {
#endif
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length);
char *buf = stack(length+1);
glGetProgramInfoLog(program, length, NULL, buf);
puts("--- cs:");
shader_print(cs);
}
if (status == GL_FALSE) {
PANIC("ERROR: shader(): Shader/program link: %s\n", buf);
return 0;
}
glDeleteShader(comp);
}
return program;
#endif
}
void dispatch(unsigned wx, unsigned wy, unsigned wz){
glDispatchCompute(wx, wy, wz);
}
void imageWriteBarrier(){
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
}
void shader_destroy(unsigned program){
if( program == ~0u ) return;
glDeleteProgram(program);
@ -226,6 +276,13 @@ void shader_texture_unit(const char *sampler, unsigned id, unsigned unit) {
glActiveTexture(GL_TEXTURE0 + unit);
glBindTexture(GL_TEXTURE_2D, id);
}
void shader_image(texture_t *t, unsigned unit, unsigned level, int layer /* -1 to disable layered access */, unsigned access){
shader_image_unit(t->id, unit, level, layer, t->texel_type, access);
}
void shader_image_unit(unsigned texture, unsigned unit, unsigned level, int layer, unsigned texel_type, unsigned access){
GLenum gl_access[] = {GL_READ_ONLY, GL_WRITE_ONLY, GL_READ_WRITE};
glBindImageTexture(unit, texture, level, layer!=-1, layer!=-1?layer:0, gl_access[access], texel_type);
}
void shader_colormap(const char *name, colormap_t c ) {
// assumes shader uses `struct { vec4 color; bool has_tex } name + sampler2D name_tex;`
@ -351,7 +408,7 @@ unsigned texture_update(texture_t *t, unsigned w, unsigned h, unsigned n, const
GLuint pixel_types[] = { GL_RED, GL_RED, GL_RG, GL_RGB, GL_RGBA, GL_R32F, GL_R32F, GL_RG32F, GL_RGB32F, GL_RGBA32F };
GLenum pixel_storage = flags & TEXTURE_FLOAT ? GL_FLOAT : GL_UNSIGNED_BYTE;
GLuint pixel_type = pixel_types[ n ];
GLuint texel_type = pixel_types[ n + 5 * !!(flags & TEXTURE_FLOAT) ];
GLuint texel_type = t->texel_type = pixel_types[ n + 5 * !!(flags & TEXTURE_FLOAT) ];
GLenum wrap = GL_CLAMP_TO_EDGE;
GLenum min_filter = GL_NEAREST, mag_filter = GL_NEAREST;
// GLfloat color = (flags&7)/7.f, border_color[4] = { color, color, color, 1.f };

View File

@ -125,6 +125,7 @@ typedef struct texture_t {
union { unsigned z, d; };
union { unsigned n, bpp; };
handle id, unit;
unsigned texel_type;
unsigned flags;
char* filename;
bool transparent;
@ -326,6 +327,19 @@ API void shader_colormap(const char *name, colormap_t cm);
API unsigned shader_get_active();
API void shader_destroy(unsigned shader);
// compute shaders
enum ACCESS_MODE {
READ,
WRITE,
READ_WRITE
};
API unsigned compute(const char *cs);
API void dispatch(unsigned wx, unsigned wy, unsigned wz);
API void shader_image(texture_t *t, unsigned unit, unsigned level, int layer /* -1 to disable layered access */, unsigned access);
API void shader_image_unit(unsigned texture, unsigned unit, unsigned level, int layer /* -1 to disable layered access */, unsigned texel_type, unsigned access);
API void imageWriteBarrier();
// -----------------------------------------------------------------------------
// meshes (@fixme: deprecate?)

View File

@ -169,9 +169,14 @@ void window_hints(unsigned flags) {
//glfwWindowHint( GLFW_COCOA_MENUBAR, GLFW_FALSE );
#endif
#ifdef __APPLE__
/* We need to explicitly ask for a 3.2 context on OS X */
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); // osx
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2); // osx, 2:#version150,3:330
#else
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
#endif
#ifdef __APPLE__
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); //osx
#endif

View File

@ -11108,6 +11108,56 @@ unsigned shader(const char *vs, const char *fs, const char *attribs, const char
return program;
}
unsigned compute(const char *cs){
#if is(ems)
return 0;
#else
PRINTF(/*"!"*/"Compiling compute shader\n");
cs = cs[0] == '#' && cs[1] == 'c' ? cs : va("#version 430 core\n%s", cs ? cs : "");
GLuint comp = shader_compile(GL_COMPUTE_SHADER, cs);
GLuint program = 0;
if( comp ) {
program = glCreateProgram();
glAttachShader(program, comp);
glLinkProgram(program);
GLint status = GL_FALSE, length;
glGetProgramiv(program, GL_LINK_STATUS, &status);
#ifdef DEBUG_SHADER
if (status != GL_FALSE && program == DEBUG_SHADER) {
#else
if (status == GL_FALSE) {
#endif
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length);
char *buf = stack(length+1);
glGetProgramInfoLog(program, length, NULL, buf);
puts("--- cs:");
shader_print(cs);
}
if (status == GL_FALSE) {
PANIC("ERROR: shader(): Shader/program link: %s\n", buf);
return 0;
}
glDeleteShader(comp);
}
return program;
#endif
}
void dispatch(unsigned wx, unsigned wy, unsigned wz){
glDispatchCompute(wx, wy, wz);
}
void imageWriteBarrier(){
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
}
void shader_destroy(unsigned program){
if( program == ~0u ) return;
glDeleteProgram(program);
@ -11140,6 +11190,13 @@ void shader_texture_unit(const char *sampler, unsigned id, unsigned unit) {
glActiveTexture(GL_TEXTURE0 + unit);
glBindTexture(GL_TEXTURE_2D, id);
}
void shader_image(texture_t *t, unsigned unit, unsigned level, int layer /* -1 to disable layered access */, unsigned access){
shader_image_unit(t->id, unit, level, layer, t->texel_type, access);
}
void shader_image_unit(unsigned texture, unsigned unit, unsigned level, int layer, unsigned texel_type, unsigned access){
GLenum gl_access[] = {GL_READ_ONLY, GL_WRITE_ONLY, GL_READ_WRITE};
glBindImageTexture(unit, texture, level, layer!=-1, layer!=-1?layer:0, gl_access[access], texel_type);
}
void shader_colormap(const char *name, colormap_t c ) {
// assumes shader uses `struct { vec4 color; bool has_tex } name + sampler2D name_tex;`
@ -11265,7 +11322,7 @@ unsigned texture_update(texture_t *t, unsigned w, unsigned h, unsigned n, const
GLuint pixel_types[] = { GL_RED, GL_RED, GL_RG, GL_RGB, GL_RGBA, GL_R32F, GL_R32F, GL_RG32F, GL_RGB32F, GL_RGBA32F };
GLenum pixel_storage = flags & TEXTURE_FLOAT ? GL_FLOAT : GL_UNSIGNED_BYTE;
GLuint pixel_type = pixel_types[ n ];
GLuint texel_type = pixel_types[ n + 5 * !!(flags & TEXTURE_FLOAT) ];
GLuint texel_type = t->texel_type = pixel_types[ n + 5 * !!(flags & TEXTURE_FLOAT) ];
GLenum wrap = GL_CLAMP_TO_EDGE;
GLenum min_filter = GL_NEAREST, mag_filter = GL_NEAREST;
// GLfloat color = (flags&7)/7.f, border_color[4] = { color, color, color, 1.f };
@ -20477,9 +20534,14 @@ void window_hints(unsigned flags) {
//glfwWindowHint( GLFW_COCOA_MENUBAR, GLFW_FALSE );
#endif
#ifdef __APPLE__
/* We need to explicitly ask for a 3.2 context on OS X */
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); // osx
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2); // osx, 2:#version150,3:330
#else
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
#endif
#ifdef __APPLE__
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); //osx
#endif

View File

@ -2363,6 +2363,7 @@ typedef struct texture_t {
union { unsigned z, d; };
union { unsigned n, bpp; };
handle id, unit;
unsigned texel_type;
unsigned flags;
char* filename;
bool transparent;
@ -2564,6 +2565,19 @@ API void shader_colormap(const char *name, colormap_t cm);
API unsigned shader_get_active();
API void shader_destroy(unsigned shader);
// compute shaders
enum ACCESS_MODE {
READ,
WRITE,
READ_WRITE
};
API unsigned compute(const char *cs);
API void dispatch(unsigned wx, unsigned wy, unsigned wz);
API void shader_image(texture_t *t, unsigned unit, unsigned level, int layer /* -1 to disable layered access */, unsigned access);
API void shader_image_unit(unsigned texture, unsigned unit, unsigned level, int layer /* -1 to disable layered access */, unsigned texel_type, unsigned access);
API void imageWriteBarrier();
// -----------------------------------------------------------------------------
// meshes (@fixme: deprecate?)

File diff suppressed because one or more lines are too long