Skip to content

Instantly share code, notes, and snippets.

@Groovounet
Created March 4, 2014 21:18
Show Gist options
  • Save Groovounet/9355895 to your computer and use it in GitHub Desktop.
Save Groovounet/9355895 to your computer and use it in GitHub Desktop.
///////////////////////////////////////////////////////////////////////////////////
/// OpenGL Samples Pack (ogl-samples.g-truc.net)
///
/// Copyright (c) 2004 - 2014 G-Truc Creation (www.g-truc.net)
/// Permission is hereby granted, free of charge, to any person obtaining a copy
/// of this software and associated documentation files (the "Software"), to deal
/// in the Software without restriction, including without limitation the rights
/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
/// copies of the Software, and to permit persons to whom the Software is
/// furnished to do so, subject to the following conditions:
///
/// The above copyright notice and this permission notice shall be included in
/// all copies or substantial portions of the Software.
///
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
/// THE SOFTWARE.
///////////////////////////////////////////////////////////////////////////////////
#include "test.hpp"
namespace
{
#define PAGE_SIZE 4*1024
void *OriginalBufferAddress = NULL;
char const * VERT_SHADER_SOURCE("gl-420/texture-2d.vert");
char const * FRAG_SHADER_SOURCE("gl-420/texture-2d.frag");
char const * TEXTURE_DIFFUSE("kueken1-bgr8.dds");
GLsizei const VertexCount(4);
GLsizeiptr const VertexSize = VertexCount * sizeof(glf::vertex_v2fv2f);
glf::vertex_v2fv2f const VertexData[VertexCount] =
{
glf::vertex_v2fv2f(glm::vec2(-1.0f,-1.0f), glm::vec2(0.0f, 1.0f)),
glf::vertex_v2fv2f(glm::vec2( 1.0f,-1.0f), glm::vec2(1.0f, 1.0f)),
glf::vertex_v2fv2f(glm::vec2( 1.0f, 1.0f), glm::vec2(1.0f, 0.0f)),
glf::vertex_v2fv2f(glm::vec2(-1.0f, 1.0f), glm::vec2(0.0f, 0.0f))
};
GLsizei const ElementCount(6);
GLsizeiptr const ElementSize = ElementCount * sizeof(GLushort);
GLushort const ElementData[ElementCount] =
{
0, 1, 2,
2, 3, 0
};
namespace program
{
enum type
{
VERTEX,
FRAGMENT,
MAX
};
}//namespace program
namespace buffer
{
enum type
{
VERTEX,
ELEMENT,
TRANSFORM,
MAX
};
}//namespace buffer
GLuint PipelineName(0);
GLuint ProgramName(0);
GLuint VertexArrayName(0);
GLuint BufferName[buffer::MAX] = {0, 0, 0};
GLuint TextureName(0);
}//namespace
class gl_420_buffer_pinned_amd : public test
{
public:
gl_420_buffer_pinned_amd(int argc, char* argv[]) :
test(argc, argv, "gl-420-buffer-pinned-amd", test::CORE, 4, 2)
{}
private:
bool initProgram()
{
bool Validated(true);
glGenProgramPipelines(1, &PipelineName);
glBindProgramPipeline(PipelineName);
if(Validated)
{
compiler Compiler;
GLuint VertShaderName = Compiler.create(GL_VERTEX_SHADER, getDataDirectory() + VERT_SHADER_SOURCE, "--version 420 --profile core");
GLuint FragShaderName = Compiler.create(GL_FRAGMENT_SHADER, getDataDirectory() + FRAG_SHADER_SOURCE, "--version 420 --profile core");
Validated = Validated && Compiler.check();
ProgramName = glCreateProgram();
glProgramParameteri(ProgramName, GL_PROGRAM_SEPARABLE, GL_TRUE);
glAttachShader(ProgramName, VertShaderName);
glAttachShader(ProgramName, FragShaderName);
glLinkProgram(ProgramName);
Validated = Validated && Compiler.checkProgram(ProgramName);
}
if(Validated)
glUseProgramStages(PipelineName, GL_VERTEX_SHADER_BIT | GL_FRAGMENT_SHADER_BIT, ProgramName);
glBindProgramPipeline(0);
return Validated;
}
void *initExternalMemoryBuffer(void)
{
OriginalBufferAddress = malloc(VertexSize + PAGE_SIZE - 1);
long addr = (long)OriginalBufferAddress;
long returnAddress = (addr + PAGE_SIZE - 1) & (~0xfff);
memcpy((void *)returnAddress, (void *)VertexData, VertexSize);
return (void *)returnAddress;
}
bool initBuffer()
{
bool Validated(true);
glGenBuffers(1, &BufferName[buffer::ELEMENT]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, BufferName[buffer::ELEMENT]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, ElementSize, ElementData, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glGenBuffers(1, &BufferName[buffer::VERTEX]);
glBindBuffer(GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, BufferName[buffer::VERTEX]);
void *realVertexBuffer = initExternalMemoryBuffer();
glBufferData(GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, VertexSize, realVertexBuffer, GL_STREAM_COPY);
glBindBuffer(GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, 0);
glBindBuffer(GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, 0);
return Validated;
}
bool initTexture()
{
bool Validated(true);
gli::texture2D Texture(gli::load_dds((getDataDirectory() + TEXTURE_DIFFUSE).c_str()));
assert(!Texture.empty());
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glGenTextures(1, &TextureName);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, TextureName);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_RED);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_GREEN);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_BLUE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_ALPHA);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, GLint(Texture.levels() - 1));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexStorage2D(GL_TEXTURE_2D, GLint(Texture.levels()), GL_RGBA8, GLsizei(Texture[0].dimensions().x), GLsizei(Texture[0].dimensions().y));
for(gli::texture2D::size_type Level = 0; Level < Texture.levels(); ++Level)
{
glTexSubImage2D(GL_TEXTURE_2D,
GLint(Level),
0, 0,
GLsizei(Texture[Level].dimensions().x),
GLsizei(Texture[Level].dimensions().y),
GL_BGR, GL_UNSIGNED_BYTE,
Texture[Level].data());
}
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
return Validated;
}
bool initVertexArray()
{
bool Validated(true);
glGenVertexArrays(1, &VertexArrayName);
glBindVertexArray(VertexArrayName);
glBindBuffer(GL_ARRAY_BUFFER, BufferName[buffer::VERTEX]);
glVertexAttribPointer(semantic::attr::POSITION, 2, GL_FLOAT, GL_FALSE, sizeof(glf::vertex_v2fv2f), BUFFER_OFFSET(0));
glVertexAttribPointer(semantic::attr::TEXCOORD, 2, GL_FLOAT, GL_FALSE, sizeof(glf::vertex_v2fv2f), BUFFER_OFFSET(sizeof(glm::vec2)));
glBindBuffer(GL_ARRAY_BUFFER, 0);
glEnableVertexAttribArray(semantic::attr::POSITION);
glEnableVertexAttribArray(semantic::attr::TEXCOORD);
glBindVertexArray(0);
return Validated;
}
bool initUniformBuffer()
{
bool Validated(true);
GLint UniformBufferOffset(0);
glGetIntegerv(
GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT,
&UniformBufferOffset);
{
GLint UniformBlockSize = glm::max(GLint(sizeof(glm::mat4)), UniformBufferOffset);
glGenBuffers(1, &BufferName[buffer::TRANSFORM]);
glBindBuffer(GL_UNIFORM_BUFFER, BufferName[buffer::TRANSFORM]);
glBufferData(GL_UNIFORM_BUFFER, UniformBlockSize, nullptr, GL_DYNAMIC_DRAW);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
}
return Validated;
}
bool begin()
{
bool Validated(true);
Validated = Validated && this->checkExtension("GL_AMD_pinned_memory");
if(Validated)
Validated = initTexture();
if(Validated)
Validated = initProgram();
if(Validated)
Validated = initBuffer();
if(Validated)
Validated = initVertexArray();
if(Validated)
Validated = initUniformBuffer();
return Validated;
}
bool end()
{
glDeleteProgramPipelines(1, &PipelineName);
glDeleteProgram(ProgramName);
glDeleteBuffers(buffer::MAX, BufferName);
glDeleteTextures(1, &TextureName);
glDeleteVertexArrays(1, &VertexArrayName);
free(OriginalBufferAddress);
return true;
}
bool render()
{
glm::vec2 WindowSize(this->getWindowSize());
{
glBindBuffer(GL_UNIFORM_BUFFER, BufferName[buffer::TRANSFORM]);
glm::mat4* Pointer = (glm::mat4*)glMapBufferRange(
GL_UNIFORM_BUFFER, 0, sizeof(glm::mat4),
GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT);
glm::mat4 Projection = glm::perspective(glm::pi<float>() * 0.25f, WindowSize.x / WindowSize.y, 0.1f, 100.0f);
glm::mat4 Model = glm::mat4(1.0f);
*Pointer = Projection * this->view() * Model;
}
glViewportIndexedf(0, 0, 0, WindowSize.x, WindowSize.y);
glClearBufferfv(GL_COLOR, 0, &glm::vec4(1.0f, 0.5f, 0.0f, 1.0f)[0]);
// Bind rendering objects
glBindProgramPipeline(PipelineName);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, TextureName);
glBindBufferBase(GL_UNIFORM_BUFFER, semantic::uniform::TRANSFORM0, BufferName[buffer::TRANSFORM]);
glBindVertexArray(VertexArrayName);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, BufferName[buffer::ELEMENT]);
// Make sure the uniform buffer is uploaded
glUnmapBuffer(GL_UNIFORM_BUFFER);
glDrawElementsInstancedBaseVertexBaseInstance(GL_TRIANGLES, ElementCount, GL_UNSIGNED_SHORT, 0, 1, 0, 0);
return true;
}
};
int main(int argc, char* argv[])
{
int Error(0);
gl_420_buffer_pinned_amd Test(argc, argv);
Error += Test();
return Error;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment