Skip to content

Instantly share code, notes, and snippets.

@Yves-G
Created August 23, 2015 19:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Yves-G/bfc72d71710e6f5eb5c9 to your computer and use it in GitHub Desktop.
Save Yves-G/bfc72d71710e6f5eb5c9 to your computer and use it in GitHub Desktop.
Example program to reproduce SSBO related driver crashes.
/*
* Copyright © 2012-2013 Graham Sellers
*
* 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 (including the next
* paragraph) 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 <sb6.h>
#include <iostream>
#include <algorithm>
#include <memory>
#include "ShaderProgram.h"
class singlepoint_app : public sb6::application
{
public:
void init()
{
static const char title[] = "Example program: SSBOs related crashes";
sb6::application::init();
memcpy(info.title, title, sizeof(title));
}
virtual void startup()
{
static const char * vs_source1[] =
{
"#version 420 core \n"
"out vec4 vFragColor; \n"
" \n"
" \n"
"in vec4 vVertex; \n"
" \n"
"buffer ColorIndexBlock \n"
"{ \n"
" uint index[20000]; \n"
"}; \n"
"buffer AColorBlock \n"
"{ \n"
" vec4 testcolor[20000]; \n"
"}; \n"
" \n"
"void main(void) \n"
"{ \n"
" gl_Position = vVertex; \n"
" if (index[0] == 2) \n"
" vFragColor = vec4(0.0, 0.0, 1.0, 1.0); \n"
" else \n"
" { \n"
" vFragColor = vec4(0.0, 0.0, 1.0, 1.0); \n"
" vFragColor.g = testcolor[index[0]].g; \n"
" } \n"
"} \n"
};
static const char * fs_source1[] =
{
"#version 420 core \n"
" \n"
"in vec4 vFragColor; \n"
"out vec4 color; \n"
" \n"
"buffer ColorIndexBlock \n"
"{ \n"
" uint index[20000]; \n"
"}; \n"
" \n"
"void main(void) \n"
"{ \n"
" if (index[10000] < 2) \n"
" color = vec4(1.0, 0.0, 0.0, 1.0); \n"
" else \n"
" color = vFragColor; \n"
"} \n"
};
shader.reset(new CShaderProgram(*vs_source1, *fs_source1));
// Acquire the indices of the two blocks by querying the names
// Observation: Blocks are ordered alphabetically, IDs are 0 and 1
GLuint colorBlockIx = 0;
GLuint colorIndexBlockIx = 0;
colorBlockIx = glGetProgramResourceIndex(shader->GetProgram(), GL_SHADER_STORAGE_BLOCK, "AColorBlock");
colorIndexBlockIx = glGetProgramResourceIndex(shader->GetProgram(), GL_SHADER_STORAGE_BLOCK, "ColorIndexBlock");
// Acquire the single uniform from each of the two blocks
GLint testcolorUnifIx = 0;
GLint indexUnifIx = 0;
const GLenum activeUnifProp[1] = { GL_ACTIVE_VARIABLES };
GLint numActiveUnifs = 1;
glGetProgramResourceiv(shader->GetProgram(), GL_SHADER_STORAGE_BLOCK, colorBlockIx, 1, activeUnifProp, numActiveUnifs, NULL, &testcolorUnifIx);
glGetProgramResourceiv(shader->GetProgram(), GL_SHADER_STORAGE_BLOCK, colorIndexBlockIx, 1, activeUnifProp, numActiveUnifs, NULL, &indexUnifIx);
// Query buffer size, request a buffer and make it the queried size
const GLenum bufferDataSizeProperty[1] = { GL_BUFFER_DATA_SIZE };
glGetProgramResourceiv(shader->GetProgram(), GL_SHADER_STORAGE_BLOCK, colorBlockIx, 1, bufferDataSizeProperty, 1, NULL, &colorBlockSize);
colorBlockSourceBuffer = std::unique_ptr<GLubyte>(new GLubyte[colorBlockSize]);
glGenBuffers(1, &colorBlockBufferID);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, colorBlockBufferID);
glBufferData(GL_SHADER_STORAGE_BUFFER, colorBlockSize, NULL, GL_DYNAMIC_DRAW);
glGetProgramResourceiv(shader->GetProgram(), GL_SHADER_STORAGE_BLOCK, colorIndexBlockIx, 1, bufferDataSizeProperty, 1, NULL, &colorIndexBlockSize);
colorIndexBlockSourceBuffer = std::unique_ptr<GLubyte>(new GLubyte[colorIndexBlockSize]);
glGenBuffers(1, &colorIndexBlockBufferID);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, colorIndexBlockBufferID);
glBufferData(GL_SHADER_STORAGE_BUFFER, colorIndexBlockSize, NULL, GL_DYNAMIC_DRAW);
// Generate a single vertex array (actually only required in the CORE profile)
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
// Setup vertex- and indexbuffer
SetupGeometry();
// Query the buffer layout and store values in the two buffers accordingly
const GLenum offsetProp[] = { GL_OFFSET };
const GLenum arrayStrideProp[] = { GL_ARRAY_STRIDE };
GLint memberOffset = 0;
GLint memberArrayStride = 0;
glGetProgramResourceiv(shader->GetProgram(), GL_BUFFER_VARIABLE, indexUnifIx, 1, offsetProp, 1, NULL, &memberOffset);
glGetProgramResourceiv(shader->GetProgram(), GL_BUFFER_VARIABLE, indexUnifIx, 1, arrayStrideProp, 1, NULL, &memberArrayStride);
for (GLuint i=0; i<20000; ++i)
{
GLuint offset = memberOffset + memberArrayStride * i;
*((GLuint*)(colorIndexBlockSourceBuffer.get() + offset)) = GLuint(2);
}
glGetProgramResourceiv(shader->GetProgram(), GL_BUFFER_VARIABLE, testcolorUnifIx, 1, offsetProp, 1, NULL, &memberOffset);
glGetProgramResourceiv(shader->GetProgram(), GL_BUFFER_VARIABLE, testcolorUnifIx, 1, arrayStrideProp, 1, NULL, &memberArrayStride);
for (GLuint i=0; i<20000; ++i)
{
GLuint offset = memberOffset + memberArrayStride * i;
*((float*)(colorBlockSourceBuffer.get() + offset + 0 * sizeof(float))) = 0.5f;
*((float*)(colorBlockSourceBuffer.get() + offset + 1 * sizeof(float))) = 0.0f;
*((float*)(colorBlockSourceBuffer.get() + offset + 2 * sizeof(float))) = 0.0f;
*((float*)(colorBlockSourceBuffer.get() + offset + 3 * sizeof(float))) = 1.0f;
}
// Upload the generated data
glBindBuffer(GL_SHADER_STORAGE_BUFFER, colorBlockBufferID);
glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, colorBlockSize, colorBlockSourceBuffer.get());
glBindBuffer(GL_SHADER_STORAGE_BUFFER, colorIndexBlockBufferID);
glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, colorIndexBlockSize, colorIndexBlockSourceBuffer.get());
// Bind the blocks to binding points
glShaderStorageBlockBinding(shader->GetProgram(), colorBlockIx, 0);
glShaderStorageBlockBinding(shader->GetProgram(), colorIndexBlockIx, 1);
}
void SetupGeometry()
{
static const GLushort vertex_indices[] =
{
0, 1, 2
};
static const GLfloat vertex_positions[] =
{
0.25f, -0.25f, 0.5f, 1.0f,
-0.25f, -0.25f, 0.5f, 1.0f,
0.25f, 0.25f, 0.5f, 1.0f
};
glGenBuffers(1, &my_buffer);
glBindBuffer(GL_ARRAY_BUFFER, my_buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_positions), vertex_positions, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
glGenBuffers(1, &my_index_buffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, my_index_buffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(vertex_indices), vertex_indices, GL_STATIC_DRAW);
}
void FreeGeometry()
{
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glDeleteBuffers(1, &my_buffer);
glDeleteBuffers(1, &my_index_buffer);
}
virtual void render(double currentTime)
{
static const GLfloat green[] = { 0.0f, 0.25f, 0.0f, 1.0f };
static const GLfloat one[] = { 1.0f };
glViewport(0, 0, info.windowWidth, info.windowHeight);
glClearBufferfv(GL_COLOR, 0, green);
glClearBufferfv(GL_DEPTH, 0, one);
glUseProgram(shader->GetProgram());
// associate the binding points with buffers
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, colorBlockBufferID);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, colorIndexBlockBufferID);
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, 0);
}
virtual void shutdown()
{
FreeGeometry();
glDeleteVertexArrays(1, &vao);
glDeleteBuffers(1, &colorBlockBufferID);
glDeleteBuffers(1, &colorIndexBlockBufferID);
}
private:
CShaderProgramPtr shader;
GLuint vao;
GLuint my_buffer;
GLuint my_index_buffer;
std::unique_ptr<GLubyte> colorBlockSourceBuffer;
GLuint colorBlockBufferID;
GLint colorBlockSize;
std::unique_ptr<GLubyte> colorIndexBlockSourceBuffer;
GLuint colorIndexBlockBufferID;
GLint colorIndexBlockSize;
};
DECLARE_MAIN(singlepoint_app)
/* Copyright (C) 2015 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef INCLUDED_SHADERPROGRAM
#define INCLUDED_SHADERPROGRAM
class CShaderProgram
{
public:
CShaderProgram(const char* vsCode, const char* fsCode) :
m_VSCode(vsCode),
m_FSCode(fsCode)
{
m_Program = glCreateProgram();
m_FS = glCreateShader(GL_FRAGMENT_SHADER);
m_VS = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(m_VS, 1, &m_VSCode, NULL);
glShaderSource(m_FS, 1, &m_FSCode, NULL);
compileShader(m_VS);
compileShader(m_FS);
glAttachShader(m_Program, m_VS);
glAttachShader(m_Program, m_FS);
glLinkProgram(m_Program);
}
~CShaderProgram()
{
glDeleteProgram(m_Program);
}
GLuint GetProgram() const
{
return m_Program;
}
private:
void compileShader(GLuint shader)
{
glCompileShader(shader);
GLint length=0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);
if (length)
{
GLchar* strInfoLog = new GLchar[length + 1];
glGetShaderInfoLog(shader, length, NULL, strInfoLog);
std::cout << strInfoLog << std::endl;
delete[] strInfoLog;
}
}
const char* m_VSCode;
const char* m_FSCode;
GLuint m_VS;
GLuint m_FS;
GLuint m_Program;
};
typedef std::shared_ptr<CShaderProgram> CShaderProgramPtr;
#endif // INCLUDED_SHADERPROGRAM
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment