From 9f6328817a0133960cd8a9451213a83e12f8962e Mon Sep 17 00:00:00 2001 From: James Canete Date: Fri, 6 Apr 2012 01:38:40 +0000 Subject: [PATCH] Use faster framebuffer blits whenever possible. --- reaction/code/renderergl2/tr_backend.c | 122 +++++++++------------ reaction/code/renderergl2/tr_extramath.h | 3 +- reaction/code/renderergl2/tr_fbo.c | 114 +++++++++++++++---- reaction/code/renderergl2/tr_fbo.h | 6 +- reaction/code/renderergl2/tr_postprocess.c | 30 ++--- 5 files changed, 164 insertions(+), 111 deletions(-) diff --git a/reaction/code/renderergl2/tr_backend.c b/reaction/code/renderergl2/tr_backend.c index 619df448..a227523a 100644 --- a/reaction/code/renderergl2/tr_backend.c +++ b/reaction/code/renderergl2/tr_backend.c @@ -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; } + + 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 - qglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + 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]); - + + 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 - RB_GodRays(); + if (r_postProcess->integer && glRefConfig.framebufferObject) + { + RB_GodRays(); - if (1) - RB_BokehBlur(backEnd.refdef.blurFactor); - else - RB_GaussianBlur(backEnd.refdef.blurFactor); + if (1) + RB_BokehBlur(backEnd.refdef.blurFactor); + else + RB_GaussianBlur(backEnd.refdef.blurFactor); + } #endif backEnd.framePostProcessed = qtrue; diff --git a/reaction/code/renderergl2/tr_extramath.h b/reaction/code/renderergl2/tr_extramath.h index e74b7a24..d41d5145 100644 --- a/reaction/code/renderergl2/tr_extramath.h +++ b/reaction/code/renderergl2/tr_extramath.h @@ -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 ); diff --git a/reaction/code/renderergl2/tr_fbo.c b/reaction/code/renderergl2/tr_fbo.c index 107aaedb..004cc336 100644 --- a/reaction/code/renderergl2/tr_fbo.c +++ b/reaction/code/renderergl2/tr_fbo.c @@ -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) @@ -439,7 +439,7 @@ void FBO_Init(void) R_CheckFBO(tr.renderFbo); } - + // clear render buffer // this fixes the corrupt screen bug with r_hdr 1 on older hardware FBO_Bind(tr.renderFbo); @@ -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); - } + 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; } \ No newline at end of file diff --git a/reaction/code/renderergl2/tr_fbo.h b/reaction/code/renderergl2/tr_fbo.h index 34f27c61..0257398f 100644 --- a/reaction/code/renderergl2/tr_fbo.h +++ b/reaction/code/renderergl2/tr_fbo.h @@ -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 diff --git a/reaction/code/renderergl2/tr_postprocess.c b/reaction/code/renderergl2/tr_postprocess.c index e3eb5f07..bdf94643 100644 --- a/reaction/code/renderergl2/tr_postprocess.c +++ b/reaction/code/renderergl2/tr_postprocess.c @@ -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); + FBO_Blit(hdrFbo, srcBox, texScale, tr.screenScratchFbo, dstBox, &tr.tonemapShader, 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;