Last active
August 8, 2020 07:50
-
-
Save KoKuToru/63baa17cffbd3e89f044102dcab5f8e0 to your computer and use it in GitHub Desktop.
OpenGL Buffer (4.5?!)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//g++ test.cpp `sdl2-config --cflags --libs` -lGLEW -lGL | |
#define NO_SDL_GLEXT | |
#include <GL/glew.h> | |
#include <SDL2/SDL.h> | |
#include <stdexcept> | |
#include <iostream> | |
template<typename T> struct Vec2 { | |
T x; | |
T y; | |
}; | |
template<typename T> struct Vec3 { | |
T x; | |
T y; | |
T z; | |
}; | |
template<typename T> struct Vec4 { | |
T x; | |
T y; | |
T z; | |
T w; | |
}; | |
namespace GL { | |
void CreateBuffers(GLsizei n, GLuint *buffers) { | |
if (glCreateBuffers) { | |
glCreateBuffers(n, buffers); | |
return; | |
} | |
glGenBuffers(n, buffers); | |
for (auto i = 0; i < n; ++i) { | |
glBindBuffer(GL_ARRAY_BUFFER, buffers[i]); | |
} | |
glBindBuffer(GL_ARRAY_BUFFER, 0); | |
} | |
void NamedBufferData(GLuint buffer, GLsizeiptr size, const void *data, GLenum usage) { | |
if (glNamedBufferData) { | |
glNamedBufferData(buffer, size, data, usage); | |
return; | |
} | |
glBindBuffer(GL_ARRAY_BUFFER, buffer); | |
glBufferData(GL_ARRAY_BUFFER, size, data, usage); | |
glBindBuffer(GL_ARRAY_BUFFER, 0); | |
} | |
void* MapNamedBufferRange(GLuint buffer, GLintptr offset, GLsizeiptr length, GLbitfield access) { | |
if (glMapNamedBufferRange) { | |
return glMapNamedBufferRange(buffer, offset, length, access); | |
} | |
glBindBuffer(GL_ARRAY_BUFFER, buffer); | |
auto tmp = glMapBufferRange(GL_ARRAY_BUFFER, offset, length, access); | |
glBindBuffer(GL_ARRAY_BUFFER, 0); | |
return tmp; | |
} | |
void UnmapNamedBuffer(GLuint buffer) { | |
if (glUnmapNamedBuffer) { | |
glUnmapNamedBuffer(buffer); | |
return; | |
} | |
glBindBuffer(GL_ARRAY_BUFFER, buffer); | |
glUnmapBuffer(GL_ARRAY_BUFFER); | |
glBindBuffer(GL_ARRAY_BUFFER, 0); | |
} | |
void DeleteBuffers(GLsizei n, const GLuint * buffers) { | |
glDeleteBuffers(n, buffers); | |
} | |
void FlushMappedNamedBufferRange(GLuint buffer, GLintptr offset, GLsizeiptr length) { | |
if (glFlushMappedNamedBufferRange) { | |
glFlushMappedNamedBufferRange(buffer, offset, length); | |
return; | |
} | |
glBindBuffer(GL_ARRAY_BUFFER, buffer); | |
glFlushMappedBufferRange(GL_ARRAY_BUFFER, offset, length); | |
glBindBuffer(GL_ARRAY_BUFFER, 0); | |
} | |
void NamedBufferStorage(GLuint buffer, GLsizeiptr size, const void *data, GLbitfield flags) { | |
if (glNamedBufferStorage) { | |
glNamedBufferStorage(buffer, size, data, flags); | |
return; | |
} | |
glBindBuffer(GL_ARRAY_BUFFER, buffer); | |
glBufferStorage(GL_ARRAY_BUFFER, size, data, flags); | |
glBindBuffer(GL_ARRAY_BUFFER, 0); | |
} | |
} | |
class BufferBaseDeleter { | |
GLuint _bufferId = 0; | |
public: | |
BufferBaseDeleter(GLuint bufferId) { | |
this->_bufferId = bufferId; | |
} | |
void operator()(void* p) const { | |
p; | |
GL::UnmapNamedBuffer(this->_bufferId); | |
GL::DeleteBuffers(1, &this->_bufferId); | |
} | |
}; | |
#include <memory> | |
class BufferBase { | |
protected: | |
GLuint _bufferId = 0; | |
int _size_byte = 0; | |
std::shared_ptr<void> _ptr = nullptr; | |
public: | |
BufferBase(int size_byte) { | |
this->_size_byte = size_byte; | |
GL::CreateBuffers(1, &this->_bufferId); | |
auto flags = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT; | |
GL::NamedBufferStorage(this->_bufferId, this->_size_byte, nullptr, flags); | |
// map buffer | |
auto raw_ptr = GL::MapNamedBufferRange(this->_bufferId, 0, this->_size_byte, flags | GL_MAP_FLUSH_EXPLICIT_BIT); | |
this->_ptr = std::shared_ptr<void>(raw_ptr, BufferBaseDeleter(this->_bufferId)); | |
} | |
virtual ~BufferBase() {} | |
void flush() { | |
GL::FlushMappedNamedBufferRange(this->_bufferId, 0, this->_size_byte); | |
} | |
}; | |
template<typename T> class Buffer: public BufferBase { | |
int _size = 0; | |
public: | |
Buffer(int size): BufferBase(_size * sizeof(T)) { | |
this->_size = size; | |
} | |
~Buffer() { | |
} | |
const T& at(int index) const { | |
if (index >= this._size || index < 0) { | |
throw std::out_of_range("OUT OF RANGE"); | |
} | |
return this->operator[](index); | |
} | |
T& at(int index) { | |
if (index >= this._size || index < 0) { | |
throw std::out_of_range("OUT OF RANGE"); | |
} | |
return this->operator[](index); | |
} | |
const T& operator[](int index) const { | |
return *((T*)this->_ptr.get() + index); | |
} | |
T& operator[](int index) { | |
return *((T*)this->_ptr.get() + index); | |
} | |
const T& front() const { | |
return this->operator[](0); | |
} | |
T& front() { | |
return this->operator[](0); | |
} | |
const T& back() const { | |
return this->operator[](this->size() - 1); | |
} | |
T& back() { | |
return this->operator[](this->size() - 1); | |
} | |
const T* data() const { | |
return (T*)this->_ptr.get(); | |
} | |
T* data() { | |
return (T*)this->_ptr.get(); | |
} | |
T* begin() { | |
return &this->front(); | |
} | |
const T* begin() const { | |
return &this->front(); | |
} | |
const T* cbegin(){ | |
return &this->front(); | |
} | |
const T* cbegin() const { | |
return &this->front(); | |
} | |
T* end() { | |
return &this->back(); | |
} | |
const T* end() const { | |
return &this->back(); | |
} | |
const T* cend(){ | |
return &this->back(); | |
} | |
const T* cend() const { | |
return &this->back(); | |
} | |
int size() const { | |
return this->_size; | |
} | |
}; | |
#include <signal.h> | |
#include <iostream> | |
void debugOutput(unsigned int source, unsigned int type, unsigned int id, | |
unsigned int severity, int length, | |
const char* message, const void* userParam) | |
{ | |
if (std::string(message, std::string("Buffer detailed info").size()) == "Buffer detailed info") | |
{ | |
//filter it | |
return; | |
} | |
std::string error_source, error_type, error_severity; | |
switch(source) | |
{ | |
case GL_DEBUG_SOURCE_API_ARB: | |
error_source = "OpenGL"; | |
break; | |
case GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB: | |
error_source = "Windows"; | |
break; | |
case GL_DEBUG_SOURCE_SHADER_COMPILER_ARB: | |
error_source = "Shader Compiler"; | |
break; | |
case GL_DEBUG_SOURCE_THIRD_PARTY_ARB: | |
error_source = "Third Party"; | |
break; | |
case GL_DEBUG_SOURCE_APPLICATION_ARB: | |
error_source = "Application"; | |
break; | |
case GL_DEBUG_SOURCE_OTHER_ARB: | |
error_source = "Other"; | |
break; | |
default: | |
error_source = "UNKNOW"; | |
break; | |
} | |
switch (type) | |
{ | |
case GL_DEBUG_TYPE_ERROR_ARB: | |
error_type = "Error"; | |
break; | |
case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB: | |
error_type = "Deprecated behavior"; | |
break; | |
case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB: | |
error_type = "Undefined behavior"; | |
break; | |
case GL_DEBUG_TYPE_PORTABILITY_ARB: | |
error_type = "Portability"; | |
break; | |
case GL_DEBUG_TYPE_PERFORMANCE_ARB: | |
error_type = "Performance"; | |
break; | |
case GL_DEBUG_TYPE_OTHER_ARB: | |
error_type = "Other"; | |
default: | |
error_type = "UNKNOW"; | |
break; | |
} | |
switch (severity) | |
{ | |
case GL_DEBUG_SEVERITY_HIGH_ARB: | |
error_severity = "High"; | |
break; | |
case GL_DEBUG_SEVERITY_MEDIUM_ARB: | |
error_severity = "Medium"; | |
break; | |
case GL_DEBUG_SEVERITY_LOW_ARB: | |
error_severity = "Low"; | |
break; | |
default: | |
error_severity = "UNKNOW"; | |
break; | |
} | |
std::cout << "Source: " << error_source << " Type: " << error_type << " Severity: " << error_severity << " Message: " << message << std::endl; | |
if (severity == GL_DEBUG_SEVERITY_HIGH_ARB) | |
{ | |
raise(SIGTRAP); | |
} | |
} | |
#include <algorithm> | |
#include <vector> | |
int main() { | |
auto win = SDL_CreateWindow("test", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 640, 480, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE); | |
//OpenGL 4.2 | |
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4); | |
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); | |
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); | |
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG); | |
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); | |
auto ctx = SDL_GL_CreateContext(win); | |
glewExperimental=true; | |
glewInit(); | |
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB); | |
glDebugMessageControlARB(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_TRUE); | |
glDebugMessageCallbackARB(debugOutput, NULL); | |
Buffer<Vec2<GLfloat>> buffer(30); | |
std::fill(buffer.begin(), buffer.end(), Vec2<GLfloat>{ 0., 0.}); // zero init | |
buffer[0] = { 10., 0. }; | |
buffer[1] = { 0., 10. }; | |
buffer[2] = { 0., 0. }; | |
buffer.flush(); | |
std::vector<BufferBase> tmp; | |
tmp.push_back(buffer); | |
// .. nothing more.. | |
while (true) { | |
SDL_Event e; | |
while (SDL_PollEvent(&e)) { | |
switch(e.type) { | |
case SDL_QUIT: | |
SDL_Quit(); | |
return 0; | |
} | |
} | |
SDL_GL_SwapWindow(win); | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment