-
Notifications
You must be signed in to change notification settings - Fork 0
/
flair_gpu.cpp
127 lines (120 loc) · 5.16 KB
/
flair_gpu.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <chrono>
#include <iostream>
// Make a compute shader for a simple multiply-add operation of two vectors
const char *computeShaderSource = "#version 430 core\n"
"layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
"layout (std430, binding = 0) buffer Input {\n"
" float data[];\n"
"} ainput;\n"
"layout (std430, binding = 1) buffer Input2 {\n"
" float data[];\n"
"} binput;\n"
"layout (std430, binding = 2) buffer Output {\n"
" float data[];\n"
"} coutput;\n"
"void main() {\n"
" uint index = gl_GlobalInvocationID.x;\n"
" coutput.data[index] = ainput.data[index] * binput.data[index] + 10.0;\n"
"}\n";
int main() {
int startTime = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
// Initialize GLFW
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
// Create a windowed mode window and its OpenGL context
GLFWwindow *window = glfwCreateWindow(640, 480, "Compute Shader", nullptr, nullptr);
if (window == nullptr) {
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
// Initialize GLAD
if (!gladLoadGLLoader((GLADloadproc) glfwGetProcAddress)) {
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
// Create a compute shader
GLuint computeShader = glCreateShader(GL_COMPUTE_SHADER);
glShaderSource(computeShader, 1, &computeShaderSource, nullptr);
glCompileShader(computeShader);
// Check for compile time errors
GLint success;
GLchar infoLog[512];
glGetShaderiv(computeShader, GL_COMPILE_STATUS, &success);
if (!success) {
glGetShaderInfoLog(computeShader, 512, nullptr, infoLog);
std::cout << "ERROR::SHADER::COMPUTE::COMPILATION_FAILED" << std::endl << infoLog << std::endl;
}
// Create the compute program
GLuint computeProgram = glCreateProgram();
glAttachShader(computeProgram, computeShader);
glLinkProgram(computeProgram);
// Check for linking errors
glGetProgramiv(computeProgram, GL_LINK_STATUS, &success);
if (!success) {
glGetProgramInfoLog(computeProgram, 512, nullptr, infoLog);
std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED" << std::endl << infoLog << std::endl;
}
// set up data
const int N = 10000000;
float *a = new float[N];
float *b = new float[N];
float *c = new float[N];
for (int i = 0; i < N; i++) {
a[i] = i;
b[i] = i;
}
// create buffers
GLuint ainputBuffer, binputBuffer, coutputBuffer;
glGenBuffers(1, &ainputBuffer);
glGenBuffers(1, &coutputBuffer);
// bind buffers
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ainputBuffer);
glBufferData(GL_SHADER_STORAGE_BUFFER, N * sizeof(float), nullptr, GL_STATIC_DRAW);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, binputBuffer);
glBufferData(GL_SHADER_STORAGE_BUFFER, N * sizeof(float), nullptr, GL_STATIC_DRAW);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, coutputBuffer);
glBufferData(GL_SHADER_STORAGE_BUFFER, N * sizeof(float), nullptr, GL_STATIC_DRAW);
// copy data to buffers
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ainputBuffer);
glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, N * sizeof(float), a);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, binputBuffer);
glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, N * sizeof(float), b);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, coutputBuffer);
glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, N * sizeof(float), c);
// bind buffers to binding points
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ainputBuffer);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, binputBuffer);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, coutputBuffer);
// use the program
glUseProgram(computeProgram);
// run the compute shader
glDispatchCompute(N, 1, 1);
// wait for the compute shader to finish
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
// copy the result back to the host
glBindBuffer(GL_SHADER_STORAGE_BUFFER, coutputBuffer);
glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, N * sizeof(float), c);
// print the result
// for (int i = 0; i < N; i++) {
// std::cout << c[i] << std::endl;
// }
// clean up
glDeleteBuffers(1, &ainputBuffer);
glDeleteBuffers(1, &binputBuffer);
glDeleteBuffers(1, &coutputBuffer);
glDeleteProgram(computeProgram);
glDeleteShader(computeShader);
glfwTerminate();
int endTime = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
int totalTimeDifferenceInMilliseconds = endTime - startTime;
std::cout<<"Total time: "<<totalTimeDifferenceInMilliseconds<<std::endl;
return 0;
}