Layered Cube Map Rendering (on NVIDIA Graphics Cards)

I would like to render omnidirectional shadow maps in one pass using layered rendering. Unfortunately, my implementation worked only for the POSITIVE_X face of the cube map, the other face were not rendered to.

To debug, I wrote the following minimal example for rendering to a cube map. I tested it on an Intel graphics card and it worked. However, on a NVIDIA (GTX 670) it renders only to one face (as mentioned above). Did anyone experience something similar, or did I do something terribly wrong in my implementation? Any help with this would be greatly appreciated:)

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include "../ext/opengl/program.h"
#include "../ext/opengl/texture.h"

#define TO_STRING(X) #X

static char* g_vertex_shader =
	"#version 410
"
TO_STRING(
	in vec3 position;

	void main()
	{
		gl_Position = vec4(position, 1.0);
	}

);

static char* g_geometry_shader =
	"#version 410
"
TO_STRING(
	layout(triangles, invocations = 1) in;
	layout(triangle_strip, max_vertices = 18) out;

	void main()
	{
		for (int i = 0; i < 6; i++) {
			for (int j = 0; j < 3; j++) {
				gl_Position = 1.0 / (float(i) + 1.0) * gl_in[j].gl_Position;
				gl_Position.w = 1.0;
				gl_Layer = i;
				EmitVertex();
			}
			EndPrimitive();
		}
	}
);

static char* g_fragment_shader =
	"#version 410
"
TO_STRING(
	out vec4 fragment_color;

	void main()
	{
		fragment_color = vec4(1.0, 0.0, 0.0, 1.0);
	}

);

static GLuint g_program = 0;
static GLuint g_vao = 0;
static GLuint g_vbo = 0;
static GLuint g_fbo = 0;
static GLuint g_cube_map = 0;

GLFWwindow* g_window = NULL;

static void initializeWindow()
{
	glfwInit();
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
	glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
	g_window = glfwCreateWindow(512, 512, "test", NULL, NULL);
	glfwMakeContextCurrent(g_window);

	glewExperimental = GL_TRUE;
	glewInit();
	glGetError();

	puts(glGetString(GL_VERSION));
}

static void initializeProgram()
{
	g_program = glCreateProgram();
	gl_attach_shader_with_source(g_program, GL_VERTEX_SHADER, g_vertex_shader);
	gl_attach_shader_with_source(g_program, GL_FRAGMENT_SHADER, g_fragment_shader);
	gl_attach_shader_with_source(g_program, GL_GEOMETRY_SHADER, g_geometry_shader);
	glBindAttribLocation(g_program, 0, "position");
	glBindFragDataLocation(g_program, 0, "fragment_color");
	gl_link_program(g_program);
	assert(glGetError() == GL_NO_ERROR);
}

static void initializeGeometry()
{
	static const float tri[] = {
		0.0, 0.0, 1.0,
		1.0, 0.0, 1.0,
		1.0, 1.0, 1.0,
	};

	glGenVertexArrays(1, &g_vao);
	glBindVertexArray(g_vao);
	glGenBuffers(1, &g_vbo);
	glBindBuffer(GL_ARRAY_BUFFER, g_vbo);
	glBufferData(GL_ARRAY_BUFFER, sizeof(tri), tri, GL_STATIC_DRAW);
	glEnableVertexAttribArray(0);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
	assert(GL_NO_ERROR == glGetError());
}


static void initializeLayeredFBO()
{
	GLenum drawbuffers[] = { GL_COLOR_ATTACHMENT0 };

	glGenFramebuffers(1, &g_fbo);
	glBindFramebuffer(GL_FRAMEBUFFER, g_fbo);

	glGenTextures(1, &g_cube_map);
	glBindTexture(GL_TEXTURE_CUBE_MAP, g_cube_map);
	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

	for (int i = 0; i < 6; i++) {
		glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGBA32F, 
			512, 512, 0, GL_RGBA, GL_FLOAT, NULL);
	}

	assert(GL_NO_ERROR == glGetError());
	glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, g_cube_map, 0);
	glDrawBuffers(1, drawbuffers);

	assert(GL_FRAMEBUFFER_COMPLETE == glCheckFramebufferStatus(GL_FRAMEBUFFER));
	assert(GL_NO_ERROR == glGetError());

	glBindFramebuffer(GL_FRAMEBUFFER, 0);
}

static void render()
{
	glBindFramebuffer(GL_FRAMEBUFFER, g_fbo);

	glViewport(0, 0, 512, 512);
	glDisable(GL_DEPTH_TEST);

	glClear(GL_COLOR_BUFFER_BIT);

	glBindVertexArray(g_vao);
	glUseProgram(g_program);
	glDrawArrays(GL_TRIANGLES, 0, 3);

	gl_save_cube_map_to_ppm(g_cube_map, GL_TEXTURE_CUBE_MAP_POSITIVE_X, "test-pos-x.ppm");
	gl_save_cube_map_to_ppm(g_cube_map, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, "test-neg-x.ppm");
	gl_save_cube_map_to_ppm(g_cube_map, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, "test-pos-y.ppm");
	gl_save_cube_map_to_ppm(g_cube_map, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, "test-neg-y.ppm");	
	gl_save_cube_map_to_ppm(g_cube_map, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, "test-pos-z.ppm");
	gl_save_cube_map_to_ppm(g_cube_map, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, "test-neg-z.ppm");
	glBindFramebuffer(GL_FRAMEBUFFER, 0);
}

static void pause()
{
	system("pause");
}

int main(int argc, char* argv)
{
	atexit(pause);
	initializeWindow();
	initializeProgram();
	initializeGeometry();
	initializeLayeredFBO();

	glClearColor(1.0, 1.0, 1.0, 1.0);
	render();
	return 0;
}