使用Opengl调用显卡运行计算任务

⌚Time: 2023-07-21 16:29:31

👨‍💻Author: Jack Ge


#include <stdio.h>

#include <stdlib.h>

#include <GL/glew.h>

#include <gl/freeglut.h>



// 用于保存传递给GPU的数据的缓冲区对象

GLuint bufferId;



// 用于保存计算结果的缓冲区对象

GLuint resultId;



// 用于保存计算结果的缓冲区对象

float* resultData;



// 用于设置OpenGL和应用程序的初始状态

void init(void)

{

    glewInit();

    // 创建一个缓冲区对象

    glGenBuffers(1, &bufferId);



    // 绑定缓冲区对象

    glBindBuffer(GL_SHADER_STORAGE_BUFFER, bufferId);



    // 分配缓冲区大小,并将数据存储在其中

    float data[] = { 1.0f, 2.0f, 3.0f, 4.0f };

    glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);



    // 解除缓冲区绑定

    glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);



    // 创建一个缓冲区对象来保存计算结果

    glGenBuffers(1, &resultId);

    glBindBuffer(GL_SHADER_STORAGE_BUFFER, resultId);

    glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(float), NULL, GL_DYNAMIC_COPY);

    glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);



    // 分配用于保存计算结果的缓冲区的内存

    resultData = (float*)malloc(sizeof(float));

}



// 用于绘制场景

void display(void)

{

    // 清除缓冲区

    glClear(GL_COLOR_BUFFER_BIT);



    // 绑定缓冲区对象

    glBindBuffer(GL_SHADER_STORAGE_BUFFER, bufferId);

    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, bufferId);



    // 绑定计算结果缓冲区对象

    glBindBuffer(GL_SHADER_STORAGE_BUFFER, resultId);

    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, resultId);



    // 加载计算着色器程序

    GLuint computeShader = glCreateShader(GL_COMPUTE_SHADER);

    const GLchar* source =

        "#version 430 core\n"

        "layout(local_size_x = 1) in;\n"

        "layout(std430, binding = 0) buffer InputData {\n"

        "   float data[4];\n"

        "};\n"

        "layout(std430, binding = 1) buffer OutputData {\n"

        "   float result;\n"

        "};\n"

        "void main() {\n"

        "    result = data[0] + data[1] + data[2] + data[3];\n"

        "}";

    glShaderSource(computeShader, 1, &source, NULL);

    glCompileShader(computeShader);



    // 创建计算着色器程序

    GLuint program = glCreateProgram();

    glAttachShader(program, computeShader);

    glLinkProgram(program);



    // 执行计算着色器程序

    glUseProgram(program);

    glDispatchCompute(1, 1, 1);



    // 将计算结果从GPU中读取到主机内存中

    glBindBuffer(GL_SHADER_STORAGE_BUFFER, resultId);

    float* data = (float*)glMapBuffer(GL_SHADER_STORAGE_BUFFER, GL_READ_ONLY);

    *resultData = *data;

    glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);



    // 输出计算结果

    printf("Result: %f\n", *resultData);



    // 删除计算着色器程序

    glDeleteShader(computeShader);

    glDeleteProgram(program);



    // 交换颜色缓冲区

    glutSwapBuffers();

}



// 用于清除应用程序使用的资源

void cleanup()

{

    // 删除缓冲区对象

    glDeleteBuffers(1, &bufferId);

    glDeleteBuffers(1, &resultId);



    // 释放保存计算结果的缓冲区的内存

    free(resultData);

}



// 应用程序入口点

int main(int argc, char** argv)

{

    // 初始化GLUT库

    glutInit(&argc, argv);

    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);

    glutInitWindowSize(640, 480);

    glutCreateWindow("OpenGL GPU Compute Example");



    // 设置OpenGL状态和回调函数

    init();

    glutDisplayFunc(display);

    glutCloseFunc(cleanup);



    // 启动GLUT主循环

    glutMainLoop();



    return 0;

}