-
-
Save Yves-G/bfc72d71710e6f5eb5c9 to your computer and use it in GitHub Desktop.
Example program to reproduce SSBO related driver crashes.
This file contains 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
/* | |
* 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) |
This file contains 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
/* 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