Use faster framebuffer blits whenever possible.

This commit is contained in:
James Canete 2012-04-06 01:38:40 +00:00
parent 015c28072a
commit 9f6328817a
5 changed files with 164 additions and 111 deletions

View File

@ -1354,7 +1354,8 @@ const void *RB_SwapBuffers( const void *data ) {
{
// copy final image to screen
vec2_t texScale;
vec4_t srcBox, dstBox, white;
vec4i_t srcBox, dstBox;
vec4_t white;
FBO_t *srcFbo, *dstFbo;
texScale[0] =
@ -1370,37 +1371,39 @@ const void *RB_SwapBuffers( const void *data ) {
if (backEnd.framePostProcessed)
{
// frame was postprocessed into screen fbo, copy from there
srcFbo = tr.screenScratchFbo;
}
else if (tr.msaaResolveFbo)
else if (!glRefConfig.framebuffer_srgb)
{
// Resolve the MSAA before copying
FBO_ResolveMSAA(tr.renderFbo, tr.msaaResolveFbo);
// need to copy from resolve to screenscratch to fix gamma
srcFbo = tr.msaaResolveFbo;
dstFbo = tr.screenScratchFbo;
VectorSet4(srcBox, 0, 0, srcFbo->width, srcFbo->height);
VectorSet4(dstBox, 0, 0, dstFbo->width, dstFbo->height);
FBO_Blit(srcFbo, srcBox, texScale, dstFbo, dstBox, &tr.textureColorShader, white, 0);
srcFbo = tr.screenScratchFbo;
}
else
{
// need to copy from render to screenscratch to fix gamma
// Copy render to screenscratch, possibly resolving MSAA
srcFbo = tr.renderFbo;
dstFbo = tr.screenScratchFbo;
FBO_FastBlit(srcFbo, NULL, dstFbo, NULL, GL_COLOR_BUFFER_BIT, GL_NEAREST);
}
else
{
srcFbo = tr.renderFbo;
if (tr.msaaResolveFbo)
{
// Resolve the MSAA before copying
dstFbo = tr.msaaResolveFbo;
FBO_FastBlit(srcFbo, NULL, dstFbo, NULL, GL_COLOR_BUFFER_BIT, GL_NEAREST);
srcFbo = tr.msaaResolveFbo;
}
// need to copy from resolve to screenscratch to fix gamma
dstFbo = tr.screenScratchFbo;
VectorSet4(srcBox, 0, 0, srcFbo->width, srcFbo->height);
VectorSet4(dstBox, 0, 0, dstFbo->width, dstFbo->height);
FBO_Blit(srcFbo, srcBox, texScale, dstFbo, dstBox, &tr.textureColorShader, white, 0);
}
srcFbo = tr.screenScratchFbo;
}
VectorSet4(srcBox, 0, 0, srcFbo->width, srcFbo->height);
VectorSet4(dstBox, 0, 0, glConfig.vidWidth, glConfig.vidHeight);
@ -1411,10 +1414,13 @@ const void *RB_SwapBuffers( const void *data ) {
white[3] = 1.0f;
// turn off colormask when copying final image
if (backEnd.colorMask[0] || backEnd.colorMask[1] || backEnd.colorMask[2] || backEnd.colorMask[3])
qglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
FBO_Blit(srcFbo, srcBox, texScale, NULL, dstBox, &tr.textureColorShader, white, 0);
qglColorMask(!backEnd.colorMask[0], !backEnd.colorMask[1], !backEnd.colorMask[2], !backEnd.colorMask[3]);
FBO_Blit(srcFbo, srcBox, texScale, NULL, dstBox, &tr.textureColorShader, white, 0);
if (backEnd.colorMask[0] || backEnd.colorMask[1] || backEnd.colorMask[2] || backEnd.colorMask[3])
qglColorMask(!backEnd.colorMask[0], !backEnd.colorMask[1], !backEnd.colorMask[2], !backEnd.colorMask[3]);
}
if ( !glState.finishCalled ) {
@ -1477,60 +1483,35 @@ const void *RB_PostProcess(const void *data)
texScale[0] =
texScale[1] = 1.0f;
if (glRefConfig.framebufferObject)
if (!glRefConfig.framebufferObject)
{
if (tr.msaaResolveFbo)
{
// Resolve the MSAA before anything else
FBO_ResolveMSAA(tr.renderFbo, tr.msaaResolveFbo);
hdrFbo = tr.msaaResolveFbo;
}
else
hdrFbo = tr.renderFbo;
}
if (!r_postProcess->integer || !glRefConfig.framebufferObject)
{
// if we have an FBO, just copy it out, otherwise, do nothing.
if (glRefConfig.framebufferObject)
{
vec4_t srcBox, dstBox, color;
VectorSet4(srcBox, 0, 0, hdrFbo->width, hdrFbo->height);
//VectorSet4(dstBox, 0, 0, glConfig.vidWidth, glConfig.vidHeight);
VectorSet4(dstBox, 0, 0, tr.screenScratchFbo->width, tr.screenScratchFbo->height);
color[0] =
color[1] =
color[2] = pow(2, r_cameraExposure->value); //exp2(r_cameraExposure->value);
color[3] = 1.0f;
//FBO_Blit(hdrFbo, srcBox, texScale, NULL, dstBox, &tr.textureColorShader, color, 0);
FBO_Blit(hdrFbo, srcBox, texScale, tr.screenScratchFbo, dstBox, &tr.textureColorShader, color, 0);
}
// do nothing
backEnd.framePostProcessed = qtrue;
return (const void *)(cmd + 1);
}
#if 0
if (!glRefConfig.framebufferObject)
hdrFbo = tr.renderFbo;
if (tr.msaaResolveFbo)
{
// we couldn't render straight to it, so just cap the screen instead
GL_Bind(tr.renderImage);
qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, glConfig.vidWidth, glConfig.vidHeight);
// Resolve the MSAA before anything else
FBO_FastBlit(tr.renderFbo, NULL, tr.msaaResolveFbo, NULL, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST);
hdrFbo = tr.msaaResolveFbo;
}
#endif
if (r_hdr->integer && (r_toneMap->integer == 2 || (r_toneMap->integer == 1 && tr.autoExposure)))
if (r_postProcess->integer && r_hdr->integer && (r_toneMap->integer == 2 || (r_toneMap->integer == 1 && tr.autoExposure)))
{
autoExposure = (r_autoExposure->integer == 1 && tr.autoExposure) || (r_autoExposure->integer == 2);
RB_ToneMap(hdrFbo, autoExposure);
}
else if (!glRefConfig.framebuffer_srgb && r_cameraExposure->value == 0.0f)
{
FBO_FastBlit(hdrFbo, NULL, tr.screenScratchFbo, NULL, GL_COLOR_BUFFER_BIT, GL_NEAREST);
}
else
{
vec4_t srcBox, dstBox, color;
vec4i_t srcBox, dstBox;
vec4_t color;
VectorSet4(srcBox, 0, 0, hdrFbo->width, hdrFbo->height);
VectorSet4(dstBox, 0, 0, tr.screenScratchFbo->width, tr.screenScratchFbo->height);
@ -1544,12 +1525,15 @@ const void *RB_PostProcess(const void *data)
}
#ifdef REACTION
if (r_postProcess->integer && glRefConfig.framebufferObject)
{
RB_GodRays();
if (1)
RB_BokehBlur(backEnd.refdef.blurFactor);
else
RB_GaussianBlur(backEnd.refdef.blurFactor);
}
#endif
backEnd.framePostProcessed = qtrue;

View File

@ -26,7 +26,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
typedef vec_t matrix_t[16];
typedef int vec2i_t[2];
typedef int vec3i_t[2];
typedef int vec3i_t[3];
typedef int vec4i_t[4];
void Matrix16Zero( matrix_t out );
void Matrix16Identity( matrix_t out );

View File

@ -396,7 +396,7 @@ void FBO_Init(void)
multisample = r_ext_framebuffer_multisample->integer;
}
if (multisample < 2)
if (multisample < 2 || !glRefConfig.framebufferBlit)
multisample = 0;
if (multisample != r_ext_framebuffer_multisample->integer)
@ -499,13 +499,6 @@ void FBO_Init(void)
}
{
int format;
if (glRefConfig.texture_srgb && glRefConfig.framebuffer_srgb)
format = GL_SRGB8_ALPHA8_EXT;
else
format = GL_RGBA8;
//tr.screenScratchFbo = FBO_Create("_screenscratch", width, height);
tr.screenScratchFbo = FBO_Create("_screenscratch", tr.screenScratchImage->width, tr.screenScratchImage->height);
FBO_Bind(tr.screenScratchFbo);
@ -606,7 +599,7 @@ void R_FBOList_f(void)
// FIXME
extern void RB_SetGL2D (void);
void FBO_BlitFromTexture(struct image_s *src, vec4_t srcBox, vec2_t srcTexScale, FBO_t *dst, vec4_t dstBox, struct shaderProgram_s *shaderProgram, vec4_t color, int blend)
void FBO_BlitFromTexture(struct image_s *src, vec4i_t srcBox, vec2_t srcTexScale, FBO_t *dst, vec4i_t dstBox, struct shaderProgram_s *shaderProgram, vec4_t color, int blend)
{
vec4_t quadVerts[4];
vec2_t texCoords[4];
@ -638,24 +631,105 @@ void FBO_BlitFromTexture(struct image_s *src, vec4_t srcBox, vec2_t srcTexScale,
RB_InstantQuad2(quadVerts, texCoords, color, shaderProgram, invTexRes);
}
void FBO_Blit(FBO_t *src, vec4_t srcBox, vec2_t srcTexScale, FBO_t *dst, vec4_t dstBox, struct shaderProgram_s *shaderProgram, vec4_t color, int blend)
void FBO_Blit(FBO_t *src, vec4i_t srcBox, vec2_t srcTexScale, FBO_t *dst, vec4i_t dstBox, struct shaderProgram_s *shaderProgram, vec4_t color, int blend)
{
if (1) //(glRefConfig.extFramebufferBlit && (sp == NULL || sp == &tr.textureColorShader))
{
FBO_BlitFromTexture(src->colorImage[0], srcBox, srcTexScale, dst, dstBox, shaderProgram, color, blend);
}
}
void FBO_ResolveMSAA(FBO_t *src, FBO_t *dst)
void FBO_FastBlit(FBO_t *src, vec4i_t srcBox, FBO_t *dst, vec4i_t dstBox, int buffers, int filter)
{
vec4i_t srcBoxFinal, dstBoxFinal;
GLuint srcFb, dstFb;
if (!glRefConfig.framebufferBlit)
{
vec2_t texScale;
vec4_t white;
texScale[0] =
texScale[1] = 1.0f;
white[0] =
white[1] =
white[2] =
white[3] = 1.0f;
if (!src || !src->colorImage[0])
return;
if (srcBox)
{
VectorSet4(srcBoxFinal, srcBox[0], srcBox[1], srcBox[2], srcBox[3]);
}
else
{
VectorSet4(srcBoxFinal, 0, 0, src->width, src->height);
}
if (dstBox)
{
VectorSet4(dstBoxFinal, dstBox[0], dstBox[1], dstBox[2], dstBox[3]);
}
else
{
if (dst)
{
VectorSet4(dstBoxFinal, 0, 0, dst->width, dst->height);
}
else
{
VectorSet4(dstBoxFinal, 0, 0, glConfig.vidWidth, glConfig.vidHeight);
}
}
FBO_Blit(src, srcBoxFinal, texScale, dst, dstBoxFinal, &tr.textureColorShader, white, 0);
return;
}
// get to a neutral state first
FBO_Bind(NULL);
qglBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, src->frameBuffer);
qglBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, dst->frameBuffer);
qglBlitFramebufferEXT(0, 0, src->width, src->height, 0, 0, dst->width, dst->height, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST);
srcFb = src ? src->frameBuffer : 0;
dstFb = dst ? dst->frameBuffer : 0;
if (!srcBox)
{
if (src)
{
VectorSet4(srcBoxFinal, 0, 0, src->width, src->height);
}
else
{
VectorSet4(srcBoxFinal, 0, 0, glConfig.vidWidth, glConfig.vidHeight);
}
}
else
{
VectorSet4(srcBoxFinal, srcBox[0], srcBox[1], srcBox[0] + srcBox[2], srcBox[1] + srcBox[3]);
}
if (!dstBox)
{
if (dst)
{
VectorSet4(dstBoxFinal, 0, 0, dst->width, dst->height);
}
else
{
VectorSet4(dstBoxFinal, 0, 0, glConfig.vidWidth, glConfig.vidHeight);
}
}
else
{
VectorSet4(dstBoxFinal, dstBox[0], dstBox[1], dstBox[0] + dstBox[2], dstBox[1] + dstBox[3]);
}
qglBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, srcFb);
qglBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, dstFb);
qglBlitFramebufferEXT(srcBoxFinal[0], srcBoxFinal[1], srcBoxFinal[2], srcBoxFinal[3],
dstBoxFinal[0], dstBoxFinal[1], dstBoxFinal[2], dstBoxFinal[3],
buffers, filter);
qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
glState.currentFBO = NULL;
}

View File

@ -56,9 +56,9 @@ void FBO_Bind(FBO_t *fbo);
void FBO_Init(void);
void FBO_Shutdown(void);
void FBO_BlitFromTexture(struct image_s *src, vec4_t srcBox, vec2_t srcTexScale, FBO_t *dst, vec4_t dstBox, struct shaderProgram_s *shaderProgram, vec4_t color, int blend);
void FBO_Blit(FBO_t *src, vec4_t srcBox, vec2_t srcTexScale, FBO_t *dst, vec4_t dstBox, struct shaderProgram_s *shaderProgram, vec4_t color, int blend);
void FBO_ResolveMSAA(FBO_t *src, FBO_t *dst);
void FBO_BlitFromTexture(struct image_s *src, vec4i_t srcBox, vec2_t srcTexScale, FBO_t *dst, vec4i_t dstBox, struct shaderProgram_s *shaderProgram, vec4_t color, int blend);
void FBO_Blit(FBO_t *src, vec4i_t srcBox, vec2_t srcTexScale, FBO_t *dst, vec4i_t dstBox, struct shaderProgram_s *shaderProgram, vec4_t color, int blend);
void FBO_FastBlit(FBO_t *src, vec4i_t srcBox, FBO_t *dst, vec4i_t dstBox, int buffers, int filter);
#endif

View File

@ -24,6 +24,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
void RB_ToneMap(FBO_t *hdrFbo, int autoExposure)
{
vec4i_t srcBox, dstBox;
vec4_t color;
vec4_t white;
vec2_t texScale;
@ -35,7 +37,6 @@ void RB_ToneMap(FBO_t *hdrFbo, int autoExposure)
if (glRefConfig.framebufferObject && autoExposure)
{
// determine average log luminance
vec4_t srcBox, dstBox, color;
int size = 256, currentScratch, nextScratch, tmp;
VectorSet4(srcBox, 0, 0, hdrFbo->width, hdrFbo->height);
@ -77,8 +78,6 @@ void RB_ToneMap(FBO_t *hdrFbo, int autoExposure)
if (glRefConfig.framebufferObject)
{
// tonemap
vec4_t srcBox, dstBox, color;
VectorSet4(srcBox, 0, 0, hdrFbo->width, hdrFbo->height);
VectorSet4(dstBox, 0, 0, tr.screenScratchFbo->width, tr.screenScratchFbo->height);
@ -92,16 +91,15 @@ void RB_ToneMap(FBO_t *hdrFbo, int autoExposure)
else
GL_BindToTMU(tr.fixedLevelsImage, TB_LEVELSMAP);
if (r_hdr->integer)
FBO_Blit(hdrFbo, srcBox, texScale, tr.screenScratchFbo, dstBox, &tr.tonemapShader, color, 0);
else
FBO_Blit(hdrFbo, srcBox, texScale, tr.screenScratchFbo, dstBox, &tr.textureColorShader, color, 0);
}
}
void RB_BokehBlur(float blur)
{
vec4i_t srcBox, dstBox;
vec4_t color;
vec4_t white;
vec2_t texScale;
@ -118,8 +116,6 @@ void RB_BokehBlur(float blur)
if (glRefConfig.framebufferObject)
{
// bokeh blur
vec4_t srcBox, dstBox, color;
if (blur > 0.0f)
{
// create a quarter texture
@ -249,12 +245,13 @@ void RB_BokehBlur(float blur)
#ifdef REACTION
static void RB_RadialBlur(FBO_t *srcFbo, FBO_t *dstFbo, int passes, float stretch, float x, float y, float w, float h, float xcenter, float ycenter, float alpha)
{
vec4i_t srcBox, dstBox;
vec4_t color;
const float inc = 1.f / passes;
const float mul = powf(stretch, inc);
float scale;
{
vec4_t srcBox, dstBox, color;
vec2_t texScale;
texScale[0] =
@ -322,6 +319,8 @@ static qboolean RB_UpdateSunFlareVis(void)
void RB_GodRays(void)
{
vec4i_t srcBox, dstBox;
vec4_t color;
vec3_t dir;
float dot;
const float cutoff = 0.25f;
@ -366,9 +365,6 @@ void RB_GodRays(void)
// initialize quarter buffers
{
float mul = 1.f;
vec4_t srcBox, dstBox;
vec4_t color;
vec2_t texScale;
texScale[0] =
@ -404,9 +400,6 @@ void RB_GodRays(void)
// add result back on top of the main buffer
{
float mul = 1.f;
vec4_t srcBox, dstBox;
vec4_t color;
vec2_t texScale;
texScale[0] =
@ -443,7 +436,8 @@ static void RB_BlurAxis(FBO_t *srcFbo, FBO_t *dstFbo, float strength, qboolean h
ymul *= strength;
{
vec4_t srcBox, dstBox, color;
vec4i_t srcBox, dstBox;
vec4_t color;
vec2_t texScale;
texScale[0] =
@ -491,7 +485,7 @@ void RB_GaussianBlur(float blur)
return;
{
vec4_t srcBox, dstBox;
vec4i_t srcBox, dstBox;
vec4_t color;
vec2_t texScale;