
基于opengl的gpu高性能编程
【代码】基于opengl的gpu高性能编程。
·
1、向量加法
// main.cpp
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <vector>
#include <iostream>
#include <fstream>
// 着色器源码加载函数
std::string loadShaderSource(const char* filePath) {
std::ifstream shaderFile(filePath);
if (!shaderFile) {
std::cerr << "无法打开着色器文件:" << filePath << std::endl;
exit(EXIT_FAILURE);
}
return std::string(std::istreambuf_iterator<char>(shaderFile), std::istreambuf_iterator<char>());
}
int main() {
// 初始化 GLFW
if (!glfwInit()) {
std::cerr << "无法初始化 GLFW" << std::endl;
exit(EXIT_FAILURE);
}
// 创建隐藏窗口
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
GLFWwindow* window = glfwCreateWindow(640, 480, "Compute", NULL, NULL);
if (!window) {
std::cerr << "无法创建 GLFW 窗口" << std::endl;
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwMakeContextCurrent(window);
// 初始化 GLEW
glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK) {
std::cerr << "无法初始化 GLEW" << std::endl;
glfwTerminate();
exit(EXIT_FAILURE);
}
// 准备数据
const int dataSize = 1024;
std::vector<float> vecA(dataSize, 1.0f); // 初始化为 1.0
std::vector<float> vecB(dataSize, 2.0f); // 初始化为 2.0
// 创建并绑定缓冲对象
GLuint bufferA, bufferB, bufferResult;
glGenBuffers(1, &bufferA);
glBindBuffer(GL_ARRAY_BUFFER, bufferA);
glBufferData(GL_ARRAY_BUFFER, vecA.size() * sizeof(float), vecA.data(), GL_STATIC_DRAW);
glGenBuffers(1, &bufferB);
glBindBuffer(GL_ARRAY_BUFFER, bufferB);
glBufferData(GL_ARRAY_BUFFER, vecB.size() * sizeof(float), vecB.data(), GL_STATIC_DRAW);
// 用于存储结果的缓冲区
glGenBuffers(1, &bufferResult);
glBindBuffer(GL_ARRAY_BUFFER, bufferResult);
glBufferData(GL_ARRAY_BUFFER, vecA.size() * sizeof(float), nullptr, GL_STATIC_READ);
// 编写并编译顶点着色器
std::string vertexShaderSource = loadShaderSource("vertex_shader.glsl");
const char* vertexShaderCode = vertexShaderSource.c_str();
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderCode, NULL);
glCompileShader(vertexShader);
// 检查编译错误
GLint success;
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if (!success) {
char infoLog[512];
glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
std::cerr << "顶点着色器编译失败:" << infoLog << std::endl;
}
// 创建程序并链接
GLuint program = glCreateProgram();
glAttachShader(program, vertexShader);
const GLchar* feedbackVaryings[] = { "outValue" };
glTransformFeedbackVaryings(program, 1, feedbackVaryings, GL_INTERLEAVED_ATTRIBS);
glLinkProgram(program);
// 检查链接错误
glGetProgramiv(program, GL_LINK_STATUS, &success);
if (!success) {
char infoLog[512];
glGetProgramInfoLog(program, 512, NULL, infoLog);
std::cerr << "程序链接失败:" << infoLog << std::endl;
}
//设置 顶点数组对象
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, bufferA);
glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, bufferB);
glVertexAttribPointer(1, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
//执行Transform Feedback
glUseProgram(program);
glBindVertexArray(vao);
glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, bufferResult);
glEnable(GL_RASTERIZER_DISCARD);//禁用光栅化
glBeginTransformFeedback(GL_POINTS);
glDrawArrays(GL_POINTS, 0, dataSize);
glEndTransformFeedback();
glDisable(GL_RASTERIZER_DISCARD);
//读取结果
std::vector<float> result(dataSize);
glBindBuffer(GL_ARRAY_BUFFER, bufferResult);
glGetBufferSubData(GL_ARRAY_BUFFER, 0, result.size() * sizeof(float), result.data());
//打印部分结果
for (int i = 0; i < result.size(); i++) {
std::cout << "result:" << result[i] << std::endl;
}
//清理资源
glDeleteBuffers(1, &bufferA);
glDeleteBuffers(1, &bufferB);
glDeleteBuffers(1, &bufferResult);
glDeleteVertexArrays(1, &vao);
glDeleteProgram(program);
glDeleteShader(vertexShader);
glfwDestroyWindow(window);
glfwTerminate();
return 0;
}
// vertex_shader.glsl
#version 330 core
layout(location = 0) in float inValueA;
layout(location = 1) in float inValueB;
out float outValue;
void main() {
outValue = inValueA + inValueB;
}
2、 矩阵乘法
#include<GL/glew.h>
#include<GLFW/glfw3.h>
#include <vector>
#include <iostream>
#include <fstream>
//着色器编码加载函数
std::string loadShaderSource(const char* filePath) {
std::ifstream shaderFile(filePath);
if (!shaderFile) {
std::cerr << "无法打开着色器文件:" << filePath << std::endl;
exit(EXIT_FAILURE);
}
return std::string(std::istreambuf_iterator<char>(shaderFile), std::istreambuf_iterator<char>());
}
int main() {
//初始化glfw
if (!glfwInit()) {
std::cerr << "无法初始化glfw" << std::endl;
exit(EXIT_FAILURE);
}
//创建隐藏窗口
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
GLFWwindow* window = glfwCreateWindow(611, 111, "Matrix Multiply", NULL, NULL);
if (!window) {
std::cerr << "无法创建GLFW 窗口" << std::endl;
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwMakeContextCurrent(window);
//初始化glew
glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK) {
std::cerr << "无法初始化 GLEW" << std::endl;
glfwTerminate();
exit(EXIT_FAILURE);
}
//准备数据
const int N = 4;//4*4
std::vector<float> matA(N * N, 1.0f);
std::vector<float> matB(N * N, 2.0f);
//创建并绑定缓冲对象
GLuint bufferA, bufferB, bufferResult;
glGenBuffers(1, &bufferA);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, bufferA);
glBufferData(GL_SHADER_STORAGE_BUFFER, matA.size() * sizeof(float), matA.data(), GL_STATIC_DRAW);
glGenBuffers(1, &bufferB);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, bufferB);
glBufferData(GL_SHADER_STORAGE_BUFFER, matB.size() * sizeof(float), matB.data(), GL_STATIC_DRAW);
//用于存储结果的缓冲区
glGenBuffers(1, &bufferResult);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, bufferResult);
glBufferData(GL_SHADER_STORAGE_BUFFER, matA.size() * sizeof(float), nullptr, GL_STATIC_DRAW);
//编写着色器 计算
std::string computeShaderSource = loadShaderSource("compute_shader.glsl");
const char* computeShaderCode = computeShaderSource.c_str();
GLuint computeShader = glCreateShader(GL_COMPUTE_SHADER);
glShaderSource(computeShader, 1, &computeShaderCode, NULL);
glCompileShader(computeShader);
// 检查编译错误
GLint success;
glGetShaderiv(computeShader, GL_COMPILE_STATUS, &success);
if (!success) {
char infoLog[512];
glGetShaderInfoLog(computeShader, 512, NULL, infoLog);
std::cerr << "计算着色器编译失败:" << infoLog << std::endl;
}
//创建程序并链接
GLuint program = glCreateProgram();
glAttachShader(program, computeShader);
glLinkProgram(program);
// 检查链接错误
glGetProgramiv(program, GL_LINK_STATUS, &success);
if (!success) {
char infoLog[512];
glGetProgramInfoLog(program, 512, NULL, infoLog);
std::cerr << "程序链接失败:" << infoLog << std::endl;
}
//绑定缓冲区
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, bufferA);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, bufferB);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, bufferResult);
//执行计算
glUseProgram(program);
glDispatchCompute((GLuint)N, (GLuint)N, 1);
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
//读取结果
std::vector<float> result(N * N);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, bufferResult);
glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, result.size() * sizeof(float), result.data());
std::cout << "结果矩阵:" << std::endl;
for (int i = 0; i < N; ++i) {
for (int j = 0; j < N; ++j) {
std::cout << result[i * N + j] << " ";
}
std::cout << std::endl;
}
// 清理资源
glDeleteBuffers(1, &bufferA);
glDeleteBuffers(1, &bufferB);
glDeleteBuffers(1, &bufferResult);
glDeleteProgram(program);
glDeleteShader(computeShader);
glfwDestroyWindow(window);
glfwTerminate();
return 0;
}
// compute_shader.glsl
#version 430 core
layout(local_size_x = 1, local_size_y = 1) in;
const uint N = 4;
layout(std430, binding = 0) readonly buffer MatA {
float elements[];
} matA;
layout(std430, binding = 1) readonly buffer MatB {
float elements[];
} matB;
layout(std430, binding = 2) writeonly buffer MatResult {
float elements[];
} result;
void main() {
uint row = gl_GlobalInvocationID.x;
uint col = gl_GlobalInvocationID.y;
if (row < N && col < N) {
float sum = 0.0;
for (uint k = 0; k < N; ++k) {
sum += matA.elements[row * N + k] * matB.elements[k * N + col];
}
result.elements[row * N + col] = sum;
}
}
3、图像处理(高斯模糊)
#define STB_IMAGE_IMPLEMENTATION
#define STB_IMAGE_WRITE_IMPLEMENTATION
#define _CRT_SECURE_NO_WARNINGS
#include "stb_image.h"
#include "stb_image_write.h"
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <vector>
#include <iostream>
#include <fstream>
// 着色器源码加载函数
std::string loadShaderSource(const char* filePath) {
std::ifstream shaderFile(filePath);
if (!shaderFile) {
std::cerr << "无法打开着色器文件:" << filePath << std::endl;
exit(EXIT_FAILURE);
}
return std::string(std::istreambuf_iterator<char>(shaderFile), std::istreambuf_iterator<char>());
}
int main() {
//初始化GLFW
if (!glfwInit()) {
std::cerr << "无法初始化 GLFW" << std::endl;
exit(EXIT_FAILURE);
}
//创建隐藏窗口
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
GLFWwindow* window = glfwCreateWindow(232, 12, "gaussian blur", NULL, NULL);
if (!window) {
std::cerr << "无法创建GLFW窗口" << std::endl;
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwMakeContextCurrent(window);
//初始化GLEW
glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK) {
std::cerr << "无法初始化 GLEW" << std::endl;
glfwTerminate();
exit(EXIT_FAILURE);
}
//加载图像
int width, height, channels;
unsigned char* imageData = stbi_load("input.jpg", &width, &height, &channels, 4);
if (!imageData) {
std::cerr << "无法加载图像" << std::endl;
glfwTerminate();
exit(EXIT_FAILURE);
}
//创建输入纹理
GLuint inputImage;
glGenTextures(1, &inputImage);
glBindTexture(GL_TEXTURE_2D, inputImage);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData);
//创建输出纹理
GLuint outputImage;
glGenTextures(1, &outputImage);
glBindTexture(GL_TEXTURE_2D, outputImage);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, width, height);
stbi_image_free(imageData);
//编写并编译计算着色器
std::string computeShaderSource = loadShaderSource("gaussian_blur.glsl");
const char* computeShaderCode = computeShaderSource.c_str();
GLuint computeShader = glCreateShader(GL_COMPUTE_SHADER);
glShaderSource(computeShader, 1, &computeShaderCode, NULL);
glCompileShader(computeShader);
// 检查编译错误
GLint success;
glGetShaderiv(computeShader, GL_COMPILE_STATUS, &success);
if (!success) {
char infoLog[512];
glGetShaderInfoLog(computeShader, 512, NULL, infoLog);
std::cerr << "计算着色器编译失败:" << infoLog << std::endl;
}
//创建程序并链接
GLuint program = glCreateProgram();
glAttachShader(program, computeShader);
glLinkProgram(program);
// 检查链接错误
glGetProgramiv(program, GL_LINK_STATUS, &success);
if (!success) {
char infoLog[512];
glGetProgramInfoLog(program, 512, NULL, infoLog);
std::cerr << "程序链接失败:" << infoLog << std::endl;
}
//绑定图像单元
glUseProgram(program);
glBindImageTexture(0, inputImage, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
glBindImageTexture(1, outputImage, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8);
//执行计算
glDispatchCompute((GLuint)ceil(width / 16.0), (GLuint)ceil(height / 16.0), 1);
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
//读取结果并保存图像
unsigned char* resultData = new unsigned char[width * height * 4];
glBindTexture(GL_TEXTURE_2D, outputImage);
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, resultData);
if (!stbi_write_png("output.png", width, height, 4, resultData, width * 4)) {
std::cerr << "无法保存图像" << std::endl;
}
else {
std::cout << "图像已保存为 output.png" << std::endl;
}
delete[] resultData;
// 清理资源
glDeleteTextures(1, &inputImage);
glDeleteTextures(1, &outputImage);
glDeleteProgram(program);
glDeleteShader(computeShader);
glfwDestroyWindow(window);
glfwTerminate();
return 0;
}
// gaussian_blur.glsl
#version 430 core
layout(local_size_x = 16, local_size_y = 16) in;
layout(binding = 0, rgba8) uniform readonly image2D inputImage;
layout(binding = 1, rgba8) uniform writeonly image2D outputImage;
const float kernel[9] = float[](
1.0 / 16.0, 2.0 / 16.0, 1.0 / 16.0,
2.0 / 16.0, 4.0 / 16.0, 2.0 / 16.0,
1.0 / 16.0, 2.0 / 16.0, 1.0 / 16.0
);
void main() {
ivec2 pos = ivec2(gl_GlobalInvocationID.xy);
ivec2 size = imageSize(inputImage);
vec4 color = vec4(0.0);
for (int i = -1; i <= 1; ++i) {
for (int j = -1; j <= 1; ++j) {
ivec2 coord = pos + ivec2(i, j);
// 边界检测
coord = clamp(coord, ivec2(0), size - ivec2(1));
vec4 pixel = imageLoad(inputImage, coord);
float weight = kernel[(i + 1) * 3 + (j + 1)];
color += pixel * weight;
}
}
imageStore(outputImage, pos, color);
}
更多推荐
所有评论(0)