dispatch computy boi
This commit is contained in:
parent
5082b4abc7
commit
7fe29a1ab9
|
@ -0,0 +1,23 @@
|
||||||
|
#version 430
|
||||||
|
|
||||||
|
layout (location = 1) uniform float t;
|
||||||
|
|
||||||
|
// size of local work group - 1 pixel
|
||||||
|
layout(local_size_x = 1, local_size_y = 1) in;
|
||||||
|
|
||||||
|
// rgba32f defines internal format, image2d for random write to output texture
|
||||||
|
layout(rgba32f, binding = 0) uniform image2D img_output;
|
||||||
|
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
// base pixel colour for the image
|
||||||
|
vec4 pixel = vec4(1.0, t, 0.0, 1.0);
|
||||||
|
// get index in global work group ie xy position
|
||||||
|
ivec2 pixel_coords = ivec2(gl_GlobalInvocationID.xy);
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
// output to a specific pixel in the image
|
||||||
|
imageStore(img_output, pixel_coords, pixel);
|
||||||
|
}
|
92
src/gfx.c
92
src/gfx.c
|
@ -1,9 +1,6 @@
|
||||||
#include "gfx.h"
|
#include "gfx.h"
|
||||||
#include "stb_image.h"
|
#include "stb_image.h"
|
||||||
|
|
||||||
const char* vertShaderPath = "res/shader/shader.vert";
|
|
||||||
const char* fragShaderPath = "res/shader/shader.frag";
|
|
||||||
|
|
||||||
float vertices[] = {
|
float vertices[] = {
|
||||||
// position color uvs
|
// position color uvs
|
||||||
1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // top right
|
1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // top right
|
||||||
|
@ -22,7 +19,7 @@ SDL_GLContext* sdlContext;
|
||||||
|
|
||||||
GLuint compileShader(const char* path, GLenum type);
|
GLuint compileShader(const char* path, GLenum type);
|
||||||
|
|
||||||
SDL_Window* gfxInit()
|
SDL_Window* gfxInit(int width, int height)
|
||||||
{
|
{
|
||||||
// load sdl modules
|
// load sdl modules
|
||||||
if (SDL_Init(SDL_INIT_VIDEO) != 0)
|
if (SDL_Init(SDL_INIT_VIDEO) != 0)
|
||||||
|
@ -40,8 +37,8 @@ SDL_Window* gfxInit()
|
||||||
"oglc",
|
"oglc",
|
||||||
SDL_WINDOWPOS_UNDEFINED,
|
SDL_WINDOWPOS_UNDEFINED,
|
||||||
SDL_WINDOWPOS_UNDEFINED,
|
SDL_WINDOWPOS_UNDEFINED,
|
||||||
800,
|
width,
|
||||||
600,
|
height,
|
||||||
SDL_WINDOW_OPENGL);
|
SDL_WINDOW_OPENGL);
|
||||||
|
|
||||||
sdlContext = SDL_GL_CreateContext(sdlWindow);
|
sdlContext = SDL_GL_CreateContext(sdlWindow);
|
||||||
|
@ -58,10 +55,10 @@ SDL_Window* gfxInit()
|
||||||
return sdlWindow;
|
return sdlWindow;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int compileShaderProgram()
|
unsigned int compileQuadShaderProgram(const char* vsPath, const char* fsPath)
|
||||||
{
|
{
|
||||||
GLuint vs = compileShader(vertShaderPath, GL_VERTEX_SHADER);
|
GLuint vs = compileShader(vsPath, GL_VERTEX_SHADER);
|
||||||
GLuint fs = compileShader(fragShaderPath, GL_FRAGMENT_SHADER);
|
GLuint fs = compileShader(fsPath, GL_FRAGMENT_SHADER);
|
||||||
|
|
||||||
unsigned int shaderProgram = glCreateProgram();
|
unsigned int shaderProgram = glCreateProgram();
|
||||||
glAttachShader(shaderProgram, vs);
|
glAttachShader(shaderProgram, vs);
|
||||||
|
@ -70,12 +67,41 @@ unsigned int compileShaderProgram()
|
||||||
// TODO: check program linking success
|
// TODO: check program linking success
|
||||||
glLinkProgram(shaderProgram);
|
glLinkProgram(shaderProgram);
|
||||||
|
|
||||||
|
GLint result = GL_FALSE;
|
||||||
|
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &result);
|
||||||
|
if (result == GL_FALSE)
|
||||||
|
{
|
||||||
|
GLint logLength = 0;
|
||||||
|
glGetProgramiv(shaderProgram, GL_INFO_LOG_LENGTH, &logLength);
|
||||||
|
|
||||||
|
char err[logLength];
|
||||||
|
glGetProgramInfoLog(shaderProgram, logLength, NULL, err);
|
||||||
|
|
||||||
|
fputs("error linking quad shader program:\n", stderr);
|
||||||
|
fputs(err, stderr);
|
||||||
|
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
glDeleteShader(vs);
|
glDeleteShader(vs);
|
||||||
glDeleteShader(fs);
|
glDeleteShader(fs);
|
||||||
|
|
||||||
return shaderProgram;
|
return shaderProgram;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned int compileComputeShaderProgram(const char* computeShaderPath)
|
||||||
|
{
|
||||||
|
GLuint cs = compileShader(computeShaderPath, GL_COMPUTE_SHADER);
|
||||||
|
GLuint computeProgram = glCreateProgram();
|
||||||
|
glAttachShader(computeProgram, cs);
|
||||||
|
|
||||||
|
glLinkProgram(computeProgram);
|
||||||
|
|
||||||
|
glDeleteShader(cs);
|
||||||
|
|
||||||
|
return computeProgram;
|
||||||
|
}
|
||||||
|
|
||||||
GLuint compileShader(const char* path, GLenum type)
|
GLuint compileShader(const char* path, GLenum type)
|
||||||
{
|
{
|
||||||
// read shader file into buffer
|
// read shader file into buffer
|
||||||
|
@ -129,7 +155,7 @@ void setVertexAttributes()
|
||||||
glEnableVertexAttribArray(2);
|
glEnableVertexAttribArray(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void createTextureFromFile()
|
void createTextureFromFile(const char* imagePath)
|
||||||
{
|
{
|
||||||
// create an opengl texture and bind it to the GL_TEXTURE_2D target
|
// create an opengl texture and bind it to the GL_TEXTURE_2D target
|
||||||
unsigned int texture;
|
unsigned int texture;
|
||||||
|
@ -141,7 +167,6 @@ void createTextureFromFile()
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_REPEAT);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_REPEAT);
|
||||||
|
|
||||||
// load image data from file
|
// load image data from file
|
||||||
const char* imagePath = "res/tex.png";
|
|
||||||
int width, height, nrChannels;
|
int width, height, nrChannels;
|
||||||
stbi_set_flip_vertically_on_load(1);
|
stbi_set_flip_vertically_on_load(1);
|
||||||
unsigned char* data = stbi_load(imagePath, &width, &height, &nrChannels, 0);
|
unsigned char* data = stbi_load(imagePath, &width, &height, &nrChannels, 0);
|
||||||
|
@ -160,6 +185,24 @@ void createTextureFromFile()
|
||||||
stbi_image_free(data);
|
stbi_image_free(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLuint createWriteOnlyTexture(int width, int height)
|
||||||
|
{
|
||||||
|
GLuint texture;
|
||||||
|
glGenTextures(1, &texture);
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, texture);
|
||||||
|
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, NULL);
|
||||||
|
glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
|
||||||
|
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
|
|
||||||
void initBuffers()
|
void initBuffers()
|
||||||
{
|
{
|
||||||
unsigned int VAO, VBO, EBO;
|
unsigned int VAO, VBO, EBO;
|
||||||
|
@ -175,3 +218,30 @@ void initBuffers()
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
|
||||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void printWorkGroupLimits()
|
||||||
|
{
|
||||||
|
int workGroupCount[3];
|
||||||
|
glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, 0, &workGroupCount[0]);
|
||||||
|
glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, 1, &workGroupCount[1]);
|
||||||
|
glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, 2, &workGroupCount[2]);
|
||||||
|
printf(
|
||||||
|
"max work group counts x:%i y:%i z:%i\n",
|
||||||
|
workGroupCount[0],
|
||||||
|
workGroupCount[1],
|
||||||
|
workGroupCount[2]);
|
||||||
|
|
||||||
|
int workGroupSize[3];
|
||||||
|
glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_SIZE, 0, &workGroupSize[0]);
|
||||||
|
glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_SIZE, 1, &workGroupSize[1]);
|
||||||
|
glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_SIZE, 2, &workGroupSize[2]);
|
||||||
|
printf(
|
||||||
|
"max work group sizes x:%i y:%i z:%i\n",
|
||||||
|
workGroupSize[0],
|
||||||
|
workGroupSize[1],
|
||||||
|
workGroupSize[2]);
|
||||||
|
|
||||||
|
int workGroupInvocations;
|
||||||
|
glGetIntegerv(GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS, &workGroupInvocations);
|
||||||
|
printf("max work group invocations %i\n", workGroupInvocations);
|
||||||
|
}
|
||||||
|
|
11
src/gfx.h
11
src/gfx.h
|
@ -3,17 +3,20 @@
|
||||||
#define GLEW_STATIC
|
#define GLEW_STATIC
|
||||||
#include "GL/glew.h"
|
#include "GL/glew.h"
|
||||||
|
|
||||||
|
|
||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
#include <SDL2/SDL_opengl.h>
|
#include <SDL2/SDL_opengl.h>
|
||||||
|
|
||||||
#include "io.h"
|
#include "io.h"
|
||||||
|
|
||||||
SDL_Window* gfxInit();
|
SDL_Window* gfxInit(int width, int height);
|
||||||
|
|
||||||
unsigned int compileShaderProgram();
|
unsigned int compileQuadShaderProgram(const char* vsPath, const char* fsPath);
|
||||||
|
unsigned int compileComputeShaderProgram();
|
||||||
|
|
||||||
|
void createTextureFromFile(const char* path);
|
||||||
|
GLuint createWriteOnlyTexture(int width, int height);
|
||||||
|
void printWorkGroupLimits();
|
||||||
|
|
||||||
void createTextureFromFile();
|
|
||||||
void setVertexAttributes();
|
void setVertexAttributes();
|
||||||
void initBuffers();
|
void initBuffers();
|
||||||
|
|
||||||
|
|
45
src/main.c
45
src/main.c
|
@ -12,26 +12,53 @@ float time();
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
SDL_Window* window = gfxInit();
|
int width = 800;
|
||||||
|
int height = 600;
|
||||||
|
const char* texPath = "res/tex.png";
|
||||||
|
|
||||||
createTextureFromFile();
|
// create a window and opengl context
|
||||||
|
SDL_Window* window = gfxInit(width, height);
|
||||||
|
|
||||||
|
// create a texture for the compute shader to write to
|
||||||
|
GLuint textureOutput = createWriteOnlyTexture(width, height);
|
||||||
|
printWorkGroupLimits();
|
||||||
|
|
||||||
|
// compile shader programs
|
||||||
|
unsigned int computeProgram = compileComputeShaderProgram("res/shader/compute.glsl");
|
||||||
|
unsigned int quadProgram = compileQuadShaderProgram(
|
||||||
|
"res/shader/shader.vert",
|
||||||
|
"res/shader/shader.frag");
|
||||||
|
|
||||||
|
// initialise quad
|
||||||
initBuffers();
|
initBuffers();
|
||||||
|
|
||||||
setVertexAttributes();
|
setVertexAttributes();
|
||||||
|
|
||||||
unsigned int shaderProgram = compileShaderProgram();
|
|
||||||
glUseProgram(shaderProgram);
|
|
||||||
|
|
||||||
// render loop
|
// render loop
|
||||||
while (!checkQuit())
|
while (!checkQuit())
|
||||||
{
|
{
|
||||||
// clear background
|
glUseProgram(computeProgram);
|
||||||
|
|
||||||
|
// update uniforms
|
||||||
|
float t = time();
|
||||||
|
t = (sin(t)/2.0f)+0.5f;
|
||||||
|
int tLocation = glGetUniformLocation(computeProgram, "t");
|
||||||
|
glUniform1f(tLocation, t);
|
||||||
|
|
||||||
|
// dispatch compute shader
|
||||||
|
glDispatchCompute((GLuint)width, (GLuint)height, 1);
|
||||||
|
|
||||||
|
// make sure we're finished writing to the texture before trying to read it
|
||||||
|
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
|
||||||
|
|
||||||
|
// normal drawing pass
|
||||||
|
glUseProgram(quadProgram);
|
||||||
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
|
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
glActiveTexture(GL_TEXTURE0); // use computed texture
|
||||||
// draw
|
glBindTexture(GL_TEXTURE_2D, textureOutput);
|
||||||
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
|
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
|
||||||
|
|
||||||
|
// swip swap
|
||||||
SDL_GL_SwapWindow(window);
|
SDL_GL_SwapWindow(window);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue