Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Blit layered framebuffers #532

Closed
bl4ckb0ne opened this issue Aug 4, 2022 · 12 comments · Fixed by #541
Closed

Blit layered framebuffers #532

bl4ckb0ne opened this issue Aug 4, 2022 · 12 comments · Fixed by #541

Comments

@bl4ckb0ne
Copy link
Contributor

I'm trying to copy a cubemap texture between 2 framebuffers using blits. Both
framebuffers are complete layered framebuffers with 6 layers each, with the
same size.

When doing a simple blit operation, as seen below, only one face is copied.

glBindFramebuffer(GL_DRAW_FRAMEBUFFER, dst);
glClearColor(1.f, 1.f, 1.f, 1.f);
glClear(GL_COLOR_BUFFER_BIT);

glBindFramebuffer(GL_READ_FRAMEBUFFER, dst);
glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST);

According to the GLES 3.2 spec 1 9.8 Layered framebuffers

When commands such as ReadPixels read from a layered framebuffer, theimage at layer zero of the selected attachment is always used to obtain pixel values

But the glClear call before the blit behaves differently

When theClearorClearBuffer*commands described in section 15.2.3 areused to clear a layered framebuffer attachment, all layers of the attachment arecleared.

Why is the blit operation only possible on the first layer but the clear is
possible on all layers? I there another way to achieve what I want to do? Could
an extension fix this?

I'd be happy to draft something if needed to fix this issue.

@pdaniell-nv
Copy link
Contributor

On page 540 of the OpenGL 4.6 core specification when describing glBlitFramebuffer it says:

If the read framebuffer is layered (see section 9.8), pixel values are read from
layer zero. If the draw framebuffer is layered, pixel values are written to layer zero.
If both read and draw framebuffers are layered, the blit operation is still performed
only on layer zero.

To blit non-zero layers you can attach the texture to the framebuffer with glFramebufferTexture3D() or glFramebufferTextureLayer() and specify the layer parameter as non-zero.

@bl4ckb0ne
Copy link
Contributor Author

I have the following piece of code to achieve what I want but it feels heavy

glBindFramebuffer(GL_DRAW_FRAMEBUFFER, dst);
glBindFramebuffer(GL_READ_FRAMEBUFFER, src);

for (int i = 0; i < 6; ++i) {
	glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
		GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, src_tex, 0);

	glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
		GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, dst_tex, 0);

	glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, 
		GL_COLOR_BUFFER_BIT, GL_NEAREST);
}

I'd prefer to have something like this

glBindFramebuffer(GL_DRAW_FRAMEBUFFER, dst);
glBindFramebuffer(GL_READ_FRAMEBUFFER, src);

// Return GL_INVALID_OPERATION if the number of layers don't match
glBlitFramebufferLayers(0, 0, width, height, 0, 0, width, height, 
		GL_COLOR_BUFFER_BIT, GL_NEAREST);

or this

glBindFramebuffer(GL_DRAW_FRAMEBUFFER, dst);
glBindFramebuffer(GL_READ_FRAMEBUFFER, src);

for (int i = 0; i < 6; ++i) {
	glBlitFramebufferLayer(0, 0, width, height, 0, 0, width, height, /*layer*/ i,
		GL_COLOR_BUFFER_BIT, GL_NEAREST);
}

@pdaniell-nv
Copy link
Contributor

If you proposed a new extension, what platform(s) would you need it supported? You may need to convince those platforms owners to implement it.

@bl4ckb0ne
Copy link
Contributor Author

My main target is MESA/Linux, I don't mind going with a MESA extension if other platforms are not interested in this feature.

@bl4ckb0ne
Copy link
Contributor Author

Im about to draft the extension, what prefix should I use? MESA or anything else?

@cubanismo
Copy link
Contributor

Discussed internally and NVIDIA is interested in this one if it's done as an EXT.

@bl4ckb0ne
Copy link
Contributor Author

Awesome, I'll be pushing my draft in the beginning of next week.

@bl4ckb0ne
Copy link
Contributor Author

Should the extension be made against ES2 or ES3? ES2 has GL_NV_framebuffer_blit and GL_ANGLE_framebuffer_blit that could serve as dependancies, but ES3 has glBlitFramebuffer natively.

I also noticed that the file GLES3/gl3ext.h doesnt seems to be generated from the repo.

@Perksey
Copy link
Contributor

Perksey commented Sep 28, 2022

I personally don't think EXT extensions should depend on non-EXT/ARB extensions, so ES3 is probably the best one.

@bl4ckb0ne
Copy link
Contributor Author

I'll prepare a patch to get properly the gl3ext header.

@oddhack
Copy link
Contributor

oddhack commented Sep 29, 2022

Should the extension be made against ES2 or ES3? ES2 has GL_NV_framebuffer_blit and GL_ANGLE_framebuffer_blit that could serve as dependancies, but ES3 has glBlitFramebuffer natively.

I also noticed that the file GLES3/gl3ext.h doesnt seems to be generated from the repo.

We don't generate a gl3ext.h - there is an empty one floating about that has some ancient history of being related to Mesa though I don't recall the details any more. In any event, extensions in gl.xml are tagged for gles2, gles1, gl, glcore, but nothing else.

@bl4ckb0ne
Copy link
Contributor Author

Yeah that's what i understood when trying to generate the header with gles3. Is the file not generated because nobody made a gles3 ext yet?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants