OpenGL TextureBufferObject and normal Textures

OpenGL TextureBufferObject and normal Textures

There doesn't seem to be a dedicated forum for opengl driver problems, so please feel free to point me in the right direction.

I'm currently trying to use a shader that uses a TextureBufferObject and a normal texture.

When both are sampled from glDrawArrays or glDrawElements will generate a GL_INVALID_OPERATION error.

If only one of the two are sampled, then everything is fine. There is also glGetError's surrounding glDrawArrays to show that it is glDrawArrays generating the error when both texture types (usamplerBuffer and sampler2D) are sampled from.

I'm using Windows 7, Intel Haswell HD 4600, graphics driver 10.18.10.3621.

Built with VisualStudio 2012.

Here is a demo of the problem:

#include <windows.h>
#include <iostream>
#include <assert.h>

#include "glew/glew.h"
#include "glew/wglew.h"

using namespace std;

#define BUFFER_OFFSET(i) ((char *)NULL + (i))

namespace {
	HGLRC           hMainRenderingContext=NULL; 
	HDC             hDC=NULL; 
	HWND            hWnd=NULL;
	HINSTANCE       hInstance;
	HANDLE			ghMutex=NULL;

	bool	keys[256];
	bool	active=TRUE;

	GLuint	VAO0=0;

	GLuint	VBO0=0;

	GLuint	Program0=0;

	GLuint  Texture=0;
	GLuint  TextureBuffer=0,TextureWithBuffer=0;
	GLuint 	Width=1024,Height=1024;

	struct vec2
	{
		vec2(){}
		vec2(float _x, float _y) : x(_x), y(_y) {}
		float x;
		float y;
	};
}

GLuint createShader(GLenum type, const char* src)
{
	GLuint shader = glCreateShader(type);

	glShaderSource(shader, 1, (const GLchar**)&src, 0);
	glCompileShader(shader);

	int param;
	glGetShaderiv(shader, GL_COMPILE_STATUS, &param);

	if (param != GL_TRUE)
	{
		GLint length = 0;
		glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);
		GLchar *messages = new GLchar[length+1];
		glGetShaderInfoLog(shader, length+1, &length, messages);
		cout << messages << endl;
	}

	assert(param == GL_TRUE);

	return shader;
}

GLuint createProgram()
{
	const char *vert_src = 
		"#version 150\n"
		"in vec2 Position;\n"
		"void main(){\n"
		"	gl_Position = vec4(Position, 0,1);\n"
		"}\n";
	const char *frag_src = 
		"#version 150 // openGL version 3.2\n"
		"#extension GL_EXT_gpu_shader4 : require\n"
		"uniform usamplerBuffer TBO;\n"
		"uniform sampler2D Texture;\n"
		"out vec4 FragOut;\n"
		"void main(){\n"
		"	vec2 coord = gl_FragCoord.xy / vec2(1024, 1024);\n"
		"	int offset = int(coord.x * 100.);\n"
		"	uvec4 b = texelFetch(TBO, 90);\n"
		"	vec4 a = texture(Texture, vec2(1.));\n"
		"	FragOut = b/100.;\n"
		"}\n";

	GLuint vert = createShader(GL_VERTEX_SHADER, vert_src);
	GLuint frag = createShader(GL_FRAGMENT_SHADER, frag_src);

	GLuint program = glCreateProgram();
	glAttachShader(program, vert);
	glAttachShader(program, frag);
	glBindAttribLocation(program, 0, "Position");
	glDeleteShader(vert);
	glDeleteShader(frag);

	glLinkProgram(program);
	int param;
	glGetProgramiv(program, GL_LINK_STATUS, &param);
	assert(param == GL_TRUE);

	return program;
}

GLuint createVBO()
{
	vec2 positions[6];
	positions[0] = vec2(-0.5f,-0.5f);
	positions[1] = vec2( 0.5f,-0.5f);
	positions[2] = vec2( 0.5f, 0.5f);

	positions[3] = vec2( 0.5f, 0.5f);
	positions[4] = vec2(-0.5f, 0.5f);
	positions[5] = vec2(-0.5f,-0.5f);

	GLuint buffer;
	glGenBuffers(1, &buffer);
    GLenum err = glGetError();
    cerr << err << endl;
	glBindBuffer(GL_ARRAY_BUFFER, buffer);
    err = glGetError();
    glBufferData(GL_ARRAY_BUFFER, sizeof(positions), (GLvoid*)positions, GL_STATIC_DRAW);
    err = glGetError();
	glVertexAttribPointer( 0, 2, GL_FLOAT, GL_FALSE, sizeof(vec2), BUFFER_OFFSET(0) );
    err = glGetError();
	glFinish();
    err = glGetError();
	return buffer;
}

GLuint createVAO()
{
	GLuint vao;
	glGenVertexArrays(1, &vao);
	glBindVertexArray(vao);
	glEnableVertexAttribArray(0);
	return vao;
}

void createTexture()
{
    glGenTextures(1, &Texture);
    glBindTexture(GL_TEXTURE_2D, Texture);

	float data[] = {.25f,.5f,.75f,100.f};
    // Nvidia has a bug that if these were intergal textures
    // GL_LINEAR cannot be used and must be GL_NEAREST
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
    glTexImage2D( GL_TEXTURE_2D, 0, GL_R32F, 4, 1, 0, GL_RED, GL_FLOAT, data);
	glBindTexture(GL_TEXTURE_2D, 0);

    GLenum err = glGetError();
    cerr << "createTexture: " << err << endl;

	// create a textureBufferObject
	unsigned int size = 100;
	unsigned int *tbo_data = new unsigned int[size];
	for (unsigned int i=0; i<size; ++i) tbo_data[i] = i;

	glGenBuffers(1, &TextureBuffer);
	glBindBuffer(GL_TEXTURE_BUFFER, TextureBuffer);
	glBufferData(GL_TEXTURE_BUFFER, size * sizeof(float), tbo_data, GL_STATIC_DRAW);
	glBindBuffer(GL_TEXTURE_BUFFER, 0);

	glGenTextures(1, &TextureWithBuffer);
	glBindTexture(GL_TEXTURE_BUFFER, TextureWithBuffer);
	glTexBuffer(GL_TEXTURE_BUFFER, GL_R32UI, TextureBuffer);
	glBindTexture(GL_TEXTURE_BUFFER, 0);
	glFinish();
	
	delete [] tbo_data;
	err = glGetError();
	cerr << "createTextureBuffer: " << err << endl;
}

void initGLObjects()
{
	wglMakeCurrent(hDC,hMainRenderingContext);
    GLenum err = glGetError();

	VAO0 = createVAO();
	VBO0 = createVBO();
    Program0 = createProgram();
    createTexture();
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	switch (uMsg)									// Check For Windows Messages
	{
	case WM_ACTIVATE:							// Watch For Window Activate Message
		{
			if (!HIWORD(wParam))					// Check Minimization State
			{
				active=TRUE;						// Program Is Active
			}
			else
			{
				active=FALSE;						// Program Is No Longer Active
			}

			return 0;								// Return To The Message Loop
		}

	case WM_SYSCOMMAND:							// Intercept System Commands
		{
			switch (wParam)							// Check System Calls
			{
			case SC_SCREENSAVE:					// Screensaver Trying To Start?
			case SC_MONITORPOWER:				// Monitor Trying To Enter Powersave?
				return 0;							// Prevent From Happening
			}
			break;									// Exit
		}

	case WM_CLOSE:								// Did We Receive A Close Message?
		{
			PostQuitMessage(0);						// Send A Quit Message
			return 0;								// Jump Back
		}

	case WM_KEYDOWN:							// Is A Key Being Held Down?
		{
			keys[wParam] = TRUE;					// If So, Mark It As TRUE
            if (wParam == VK_ESCAPE)
            {
                PostQuitMessage(0);						// Send A Quit Message
            }
			return 0;								// Jump Back
		}

	case WM_KEYUP:								// Has A Key Been Released?
		{
			keys[wParam] = FALSE;					// If So, Mark It As FALSE
			return 0;								// Jump Back
		}
	}

	// Pass All Unhandled Messages To DefWindowProc
	return DefWindowProc(hWnd,uMsg,wParam,lParam);
}

void killWindow()
{
	wglMakeCurrent(hDC,hMainRenderingContext);
	glDeleteProgram(Program0);
	glDeleteBuffers(1, &VBO0);
	glDeleteVertexArrays(1, &VAO0);

	if (!wglMakeCurrent(NULL,NULL))
	{
		MessageBox(NULL,"Release Of DC And RC Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
	}
	if (hMainRenderingContext)
	{
		if (!wglDeleteContext(hMainRenderingContext))	
		{
			MessageBox(NULL,"Release Rendering Context Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
		}
		hMainRenderingContext=NULL;
	}

	if (hDC && !ReleaseDC(hWnd,hDC))
	{
		MessageBox(NULL,"Release Device Context Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
		hDC=NULL;
	}

	if (hWnd && !DestroyWindow(hWnd))
	{
		MessageBox(NULL,"Could Not Release hWnd.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
		hWnd=NULL;
	}

	if (!UnregisterClass("MultiContextThreaded",hInstance))
	{
		MessageBox(NULL,"Could Not Unregister Class.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
		hInstance=NULL;
	}
}

BOOL initWindowsAndContexts(char* title)
{
	GLuint		PixelFormat;	
	WNDCLASS	wc;				
	DWORD		dwExStyle;		
	DWORD		dwStyle;		
	RECT		WindowRect;		
	WindowRect.left=(long)0;	
	WindowRect.right=(long)800;
	WindowRect.top=(long)0;		
	WindowRect.bottom=(long)640;

	hInstance			= GetModuleHandle(NULL);				
	wc.style			= CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
	wc.lpfnWndProc		= (WNDPROC) WndProc;					
	wc.cbClsExtra		= 0;									
	wc.cbWndExtra		= 0;									
	wc.hInstance		= hInstance;							
	wc.hIcon			= LoadIcon(NULL, IDI_WINLOGO);			
	wc.hCursor			= LoadCursor(NULL, IDC_ARROW);			
	wc.hbrBackground	= NULL;									
	wc.lpszMenuName		= NULL;									
	wc.lpszClassName	= "MultiContextThreaded";				

	if (!RegisterClass(&wc))									
	{
		MessageBox(NULL,"Failed To Register The Window Class.","ERROR",MB_OK|MB_ICONEXCLAMATION);
		return FALSE;											// Return FALSE
	}

	dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
	dwStyle=WS_OVERLAPPEDWINDOW;

	AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle);

	// Create The Window
	if (!(hWnd=CreateWindowEx(	
		dwExStyle,							// Extended Style For The Window
		"MultiContextThreaded",				// Class Name
		title,								// Window Title
		dwStyle |							// Defined Window Style
		WS_CLIPSIBLINGS |					// Required Window Style
		WS_CLIPCHILDREN,					// Required Window Style
		0, 0,								// Window Position
		WindowRect.right-WindowRect.left,	// Calculate Window Width
		WindowRect.bottom-WindowRect.top,	// Calculate Window Height
		NULL,								// No Parent Window
		NULL,								// No Menu
		hInstance,							
		NULL)))								
	{
		MessageBox(NULL,"Window Creation Error.","ERROR",MB_OK|MB_ICONEXCLAMATION);
		killWindow();
		return FALSE;
	}

	static	PIXELFORMATDESCRIPTOR pfd=				// pfd Tells Windows How We Want Things To Be
	{
		sizeof(PIXELFORMATDESCRIPTOR),				// Size Of This Pixel Format Descriptor
		1,											// Version Number
		PFD_DRAW_TO_WINDOW |						// Format Must Support Window
		PFD_SUPPORT_OPENGL |						// Format Must Support OpenGL
		PFD_DOUBLEBUFFER,							// Must Support Double Buffering
		PFD_TYPE_RGBA,								// Request An RGBA Format
		16,											// Select Our Color Depth
		0, 0, 0, 0, 0, 0,							// Color Bits Ignored
		0,											// No Alpha Buffer
		0,											// Shift Bit Ignored
		0,											// No Accumulation Buffer
		0, 0, 0, 0,									// Accumulation Bits Ignored
		16,											// 16Bit Z-Buffer (Depth Buffer)  
		0,											// No Stencil Buffer
		0,											// No Auxiliary Buffer
		PFD_MAIN_PLANE,								// Main Drawing Layer
		0,											// Reserved
		0, 0, 0										// Layer Masks Ignored
	};

	if (!(hDC=GetDC(hWnd)))							// Did We Get A Device Context?
	{
		killWindow();								// Reset The Display
		MessageBox(NULL,"Can't Create A GL Device Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
		return FALSE;								// Return FALSE
	}

	if (!(PixelFormat=ChoosePixelFormat(hDC,&pfd)))	// Did Windows Find A Matching Pixel Format?
	{
		killWindow();								// Reset The Display
		MessageBox(NULL,"Can't Find A Suitable PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION);
		return FALSE;								// Return FALSE
	}

	if(!SetPixelFormat(hDC,PixelFormat,&pfd))		// Are We Able To Set The Pixel Format?
	{
		killWindow();								// Reset The Display
		MessageBox(NULL,"Can't Set The PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION);
		return FALSE;								// Return FALSE
	}

	HGLRC tempContext = wglCreateContext(hDC); 
	wglMakeCurrent(hDC,tempContext);
	int attribs[] =
	{
		WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
		WGL_CONTEXT_MINOR_VERSION_ARB, 2, 
		WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB | WGL_CONTEXT_DEBUG_BIT_ARB,
		WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB, //0x9126 , 0x00000001,
		0
	};

	PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = NULL;
	wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC) wglGetProcAddress("wglCreateContextAttribsARB");
	if(wglCreateContextAttribsARB != NULL)
	{
		hMainRenderingContext = wglCreateContextAttribsARB(hDC,0, attribs);
	}

	// bind the shared context to the MainThread
	if(!wglMakeCurrent(hDC,hMainRenderingContext))
	{
		killWindow();
		MessageBox(NULL,"Can't Activate The GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
		return FALSE;
	}

	wglDeleteContext(tempContext);
	ShowWindow(hWnd,SW_SHOW);	
	SetForegroundWindow(hWnd);	
	SetFocus(hWnd);				
	return TRUE;	
}

void plainRender()
{

	glClearColor(0,0,0,0);
	glClear(GL_COLOR_BUFFER_BIT);

	glBindVertexArray(VAO0);

	glUseProgram(Program0);

	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_BUFFER, TextureWithBuffer);

	glActiveTexture(GL_TEXTURE1);
	glBindTexture(GL_TEXTURE_2D, Texture);

	glEnableVertexAttribArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, VBO0);
    glVertexAttribPointer( 0, 2, GL_FLOAT, GL_FALSE, sizeof(vec2), BUFFER_OFFSET(0) );

	GLenum err = glGetError();
	if (err != GL_NO_ERROR)
		cerr << "createTextureBuffer: " << err << endl;

	glDrawArrays(GL_TRIANGLES, 0, 6);

	err = glGetError();
	if (err != GL_NO_ERROR)
		cerr << "createTextureBuffer: " << err << endl;

	glActiveTexture(GL_TEXTURE0);

    SwapBuffers(hDC);
    glFlush();
}

int main(int argc, char *argv[])
{
	BOOL done = FALSE;

	initWindowsAndContexts("OpenGL TextureBufferObject");	
    glewExperimental = GL_TRUE;
    GLenum err = glewInit();
    glGetError();

	initGLObjects();

	MSG		msg;
	// clear out message buffer and get a window displayed.
	while (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
	{
		if (msg.message==WM_QUIT)
		{
			done=TRUE;
		}
		else
		{
			TranslateMessage(&msg);		
			DispatchMessage(&msg);		
		}
	}

    while (!done){
        plainRender();
        if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
        {
            if (msg.message==WM_QUIT)
            {
                done=TRUE;
            }
            else
            {
                TranslateMessage(&msg);		
                DispatchMessage(&msg);		
            }
        }
    }
			
	return 0;
}

 

2 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

This forum specializes in OpenCL.  Unless the topic is OpenCL/OpenGL interoperability, OpenGL is likely to be out of scope.  For OpenGL you may find more answers here: https://software.intel.com/en-us/forums/developing-software-for-visual-computing

If I can find any other relevant forums I'll let you know.  Thanks!

Login to leave a comment.