MSAA using glFramebufferTexture2D?

Is it possible to get an MSAA FBO using
glFramebufferTexture2D to supply the colour
buffers? No luck for me so far on a GL3.0 +
Linux machine as it keeps saying GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE.

The example code I’ve found online on setting
up MSAA FBOs all use:
glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, GL_RGBA8, width, height);

so I’m wondering if using Texture2D is possible
too, assuming the depth+stencil buffers are
setup using glRenderbufferStorageMultisample.

I think it should work.

After calling FramebufferTexture* on the current fbo you might try a few glGetIntegerv’s to verify basic goodness, like

SAMPLE_BUFFERS
SAMPLE_COVERAGE
SAMPLE_COVERAGE_VALUE
SAMPLE_MASK
SAMPLE_MASK_VALUE
SAMPLES
SAMPLE_POSITION

and what have you.

I’m using textures for depth too so dunno first hand what works and doesn’t work renderbuffer-wise on current os/hw/driver combos so ymmv.

This is for 3.2 :


ILFBO ilCreateFBO_MSAA(int wid,int hei,int NumTextures,IL_TEX_FORMAT* formats,IL_TEX_FORMAT depthFormat,int NumSamples){
	if(NumSamples<=1)return ilCreateFBO(wid,hei,NumTextures,formats,depthFormat);

	ILFBO f = new ILI_FBO;
	f->wid = wid;
	f->hei = hei;
	f->NumTextures = NumTextures;
	for(int i=0;i<8;i++)f->Textures[i]=0;
	f->DepthTex = 0;
	f->glFBO = 0;
	f->msaaType = ILMSAA_MSAA;
	
	
	bool IsComplete = false;

	glGenFramebuffers(1, &f->glFBO);
	glBindFramebuffer(GL_FRAMEBUFFER, f->glFBO);

	for(int i=0;i<NumTextures;i++){
		f->Textures[i] = ilCreateMSAATexture2D(wid,hei,formats[i],NumSamples);
		f->IsTexExtern[i]=false;
		glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+i, f->Textures[i]->glTexHandle, 0);
	}

	f->DepthTex = ilCreateMSAATexture2D(wid,hei,depthFormat,NumSamples);
	glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, f->DepthTex->glTexHandle, 0);

	

	GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
	if(status == GL_FRAMEBUFFER_COMPLETE) {	
		IsComplete = true;
	}else{
		printh(status);
	}
	glBindFramebuffer(GL_FRAMEBUFFER,0);
	_RegisterObject(f,(DELPROC)ilDeleteFBO);

	if(!IsComplete){
		prints("Incomplete MSAA FBO");
		ilDeleteFBO(f); ilGetError(); return 0;
	}
	return f;

}

/*


ILFBO ilCreateFBO_CSAA(int wid,int hei,IL_TEX_FORMAT format,int NumCoverageSamples,int NumColorSamples){
	if(NumCoverageSamples==0 || NumColorSamples==0){
		return ilCreateFBO(wid,hei,format,1,ILTEXFMT_DEPTH24);
	}
	if(!glRenderbufferStorageMultisampleCoverageNV)return 0;
	ILFBO prevFBO = gil_CurRenderTarget; gil_CurRenderTarget=0;
	ILFBO f = new ILI_FBO;
	f->wid = wid;
	f->hei = hei;
	f->NumTextures = 1;
	f->IsTexExtern[0]=false;
	f->DepthTex = 0;
	f->msaaType = ILMSAA_CSAA;
	f->glFBO = 0;
	f->glNativeDepth=0;

	bool IsComplete = false;


	//=============[ create multisampled FBO ]=======================================[
	// Create a multisampled color buffer.
	GLuint msaa_color;
	GLuint msaa_depth;
	GLuint msaa_fbo;
	glGenFramebuffers(1, &msaa_fbo);
	glBindFramebuffer(GL_FRAMEBUFFER, msaa_fbo);

	glGenRenderbuffers(1, &msaa_color);
	glBindRenderbuffer(GL_RENDERBUFFER, msaa_color);
	glRenderbufferStorageMultisampleCoverageNV(GL_RENDERBUFFER,NumCoverageSamples,NumColorSamples,TEX_FORMATS[format].iformat, wid, hei);
	//int query;
	//glGetRenderbufferParameteriv( GL_RENDERBUFFER, GL_RENDERBUFFER_COVERAGE_SAMPLES_NV, &query);	print(query);
	//glGetRenderbufferParameteriv( GL_RENDERBUFFER, GL_RENDERBUFFER_COLOR_SAMPLES_NV, &query);	print(query);
	glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,GL_RENDERBUFFER, msaa_color);


	// Create a multisampled depth buffer
	glGenRenderbuffers(1, &msaa_depth);
	glBindRenderbuffer(GL_RENDERBUFFER, msaa_depth);
	glRenderbufferStorageMultisampleCoverageNV(GL_RENDERBUFFER,NumCoverageSamples,NumColorSamples,GL_DEPTH_COMPONENT24,wid,hei);
	//glGetRenderbufferParameteriv( GL_RENDERBUFFER, GL_RENDERBUFFER_COVERAGE_SAMPLES_NV, &query);	print(query);
	//glGetRenderbufferParameteriv( GL_RENDERBUFFER, GL_RENDERBUFFER_COLOR_SAMPLES_NV, &query);	print(query);
	glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,GL_RENDERBUFFER, msaa_depth);

	f->gl_msaaColor[0] = msaa_color;
	f->gl_msaaDepth = msaa_depth;
	f->gl_msaaFBO = msaa_fbo;
	
	if(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE) {	
		IsComplete = true; // gets complete only if the two FBOs are complete
	}
	//===============================================================================/

	//===========[ create singlesampled FBO ]==================================[
	// Create an fbo for blitting the multisampled fbo to a texture.
	f->Textures[0] = ilCreateTexture2D(wid,hei,format);	ilUploadTex2D_LOD(f->Textures[0],0,0);
	f->IsTexExtern[0]=false;
	f->DepthTex = ilCreateTexture2D(wid,hei,ILTEXFMT_DEPTH24);ilUploadTex2D_LOD(f->DepthTex,0,0);

	
	GLuint fbo;
	glGenFramebuffers(1, &fbo);
	glBindFramebuffer(GL_FRAMEBUFFER, fbo);
	f->glFBO = fbo;

	// Draw into the texture.
	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
		GL_TEXTURE_2D, f->Textures[0]->glTexHandle, 0);
	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
		GL_TEXTURE_2D, f->DepthTex->glTexHandle, 0);
	if(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE) {	
		IsComplete &= true;
	}
	//=========================================================================/

	

	
	ilSetRenderTarget(prevFBO);
	_RegisterObject(f,(DELPROC)ilDeleteFBO);

	if(!IsComplete){ilDeleteFBO(f); ilGetError(); return 0;}
	return f;
}
*/


The CSAA version has not been updated, I’m yet to experiment on it. (on somehow using it for custom-HDR AA resolve via texture2DMS or renderBufferMS)

Ah, the ilCreateMSAATexture2D() basically only calls:


glGenTextures( 1, &glTexHandle);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE,glTexHandle);
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, NumSamples, TEX_FORMATS[format].iformat, wid, hei, false);

Hey thanks guys!

Now I know the part I missed was this:
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, NumSamples, TEX_FORMATS[format].iformat, wid, hei, false);

I kept feeding my FBO code with the texture object
from my texture class, which was using glTexImage2D
all along and it completely slipped my mind.

Many thanks again!

BTW, what is the advantage of glTexImage2DMultisample
over MSAA renderbuffers? Can you bind and render MSAA
textures directly? Or is it used for custom resolves?

BTW, what is the advantage of glTexImage2DMultisample
over MSAA renderbuffers?

Renderbuffers can only be used as render targets. Textures can be used as both render targets and textures.

if you are never going to use a surface as a texture, we recommend that you use render buffer. this allows the implementation to make better optimizations for those surfaces (compression or hiz for depth, compression for msaa surface)