dispatch computy boi

This commit is contained in:
ktyl 2021-07-10 16:16:01 +01:00
parent 5082b4abc7
commit 7fe29a1ab9
4 changed files with 147 additions and 24 deletions

23
res/shader/compute.glsl Normal file
View File

@ -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);
}

View File

@ -1,9 +1,6 @@
#include "gfx.h"
#include "stb_image.h"
const char* vertShaderPath = "res/shader/shader.vert";
const char* fragShaderPath = "res/shader/shader.frag";
float vertices[] = {
// position color uvs
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);
SDL_Window* gfxInit()
SDL_Window* gfxInit(int width, int height)
{
// load sdl modules
if (SDL_Init(SDL_INIT_VIDEO) != 0)
@ -40,8 +37,8 @@ SDL_Window* gfxInit()
"oglc",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
800,
600,
width,
height,
SDL_WINDOW_OPENGL);
sdlContext = SDL_GL_CreateContext(sdlWindow);
@ -58,10 +55,10 @@ SDL_Window* gfxInit()
return sdlWindow;
}
unsigned int compileShaderProgram()
unsigned int compileQuadShaderProgram(const char* vsPath, const char* fsPath)
{
GLuint vs = compileShader(vertShaderPath, GL_VERTEX_SHADER);
GLuint fs = compileShader(fragShaderPath, GL_FRAGMENT_SHADER);
GLuint vs = compileShader(vsPath, GL_VERTEX_SHADER);
GLuint fs = compileShader(fsPath, GL_FRAGMENT_SHADER);
unsigned int shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vs);
@ -70,12 +67,41 @@ unsigned int compileShaderProgram()
// TODO: check program linking success
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(fs);
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)
{
// read shader file into buffer
@ -129,7 +155,7 @@ void setVertexAttributes()
glEnableVertexAttribArray(2);
}
void createTextureFromFile()
void createTextureFromFile(const char* imagePath)
{
// create an opengl texture and bind it to the GL_TEXTURE_2D target
unsigned int texture;
@ -141,7 +167,6 @@ void createTextureFromFile()
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_REPEAT);
// load image data from file
const char* imagePath = "res/tex.png";
int width, height, nrChannels;
stbi_set_flip_vertically_on_load(1);
unsigned char* data = stbi_load(imagePath, &width, &height, &nrChannels, 0);
@ -160,6 +185,24 @@ void createTextureFromFile()
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()
{
unsigned int VAO, VBO, EBO;
@ -175,3 +218,30 @@ void initBuffers()
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
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);
}

View File

@ -3,17 +3,20 @@
#define GLEW_STATIC
#include "GL/glew.h"
#include <SDL2/SDL.h>
#include <SDL2/SDL_opengl.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 initBuffers();

View File

@ -12,26 +12,53 @@ float time();
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();
setVertexAttributes();
unsigned int shaderProgram = compileShaderProgram();
glUseProgram(shaderProgram);
// render loop
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);
glClear(GL_COLOR_BUFFER_BIT);
// draw
glActiveTexture(GL_TEXTURE0); // use computed texture
glBindTexture(GL_TEXTURE_2D, textureOutput);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
// swip swap
SDL_GL_SwapWindow(window);
}