From af0c66dff92ea1cc12cc0514f6b779e83e88112d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 7 Mar 2022 23:32:44 +0900 Subject: [PATCH] [renderer] Move frame rendering out a layer. This is a step towards high-level unification of the renderers, as far as possible keeping only actual low-level implementation details in the individual renderers (some higher level stuff, eg shadows, is expected to be per-renderer as some things are just not feasible to implement in all renderers). However, the idea is to move the high-level functionality into scene rendering. --- include/QF/plugin/vid_render.h | 6 +- include/r_screen.h | 6 - include/vid_gl.h | 8 + include/vid_sw.h | 3 + libs/video/renderer/gl/gl_mod_alias.c | 3 +- libs/video/renderer/gl/gl_rmain.c | 5 - libs/video/renderer/gl/gl_rsurf.c | 7 +- libs/video/renderer/gl/gl_screen.c | 117 +------- libs/video/renderer/glsl/glsl_screen.c | 154 +--------- libs/video/renderer/r_screen.c | 14 +- libs/video/renderer/sw/screen.c | 63 +--- libs/video/renderer/sw32/namehack.h | 1 - libs/video/renderer/sw32/screen.c | 64 +---- libs/video/renderer/vid_render_gl.c | 97 ++++++- libs/video/renderer/vid_render_glsl.c | 136 ++++++++- libs/video/renderer/vid_render_sw.c | 57 +++- libs/video/renderer/vid_render_sw32.c | 54 +++- libs/video/renderer/vid_render_vulkan.c | 271 ++++++++++-------- .../video/renderer/vulkan/vulkan_vid_common.c | 2 +- 19 files changed, 524 insertions(+), 544 deletions(-) diff --git a/include/QF/plugin/vid_render.h b/include/QF/plugin/vid_render.h index aa17f35ec..26233dcaa 100644 --- a/include/QF/plugin/vid_render.h +++ b/include/QF/plugin/vid_render.h @@ -104,13 +104,17 @@ typedef struct vid_render_funcs_s { struct psystem_s *(*ParticleSystem) (void); void (*R_Init) (void); - void (*R_RenderFrame) (SCR_Func *scr_funcs); void (*R_ClearState) (void); void (*R_LoadSkys) (const char *); void (*R_NewMap) (model_t *worldmodel, model_t **models, int num_models); void (*R_LineGraph) (int x, int y, int *h_vals, int count, int height); void (*R_ViewChanged) (void); + void (*begin_frame) (void); + void (*render_view) (void); + void (*set_2d) (void); + void (*end_frame) (void); + vid_model_funcs_t *model_funcs; } vid_render_funcs_t; diff --git a/include/r_screen.h b/include/r_screen.h index 1a0b91860..41963b400 100644 --- a/include/r_screen.h +++ b/include/r_screen.h @@ -31,12 +31,6 @@ #ifndef __r_screen_h #define __r_screen_h -struct tex_s *SCR_CaptureBGR (void); -struct tex_s *SCR_ScreenShot (unsigned width, unsigned height); -void SCR_DrawStringToSnap (const char *s, struct tex_s *tex, int x, int y); -void SCR_ScreenShot_f (void); -int MipColor (int r, int g, int b); - extern int scr_copytop; extern qboolean scr_skipupdate; diff --git a/include/vid_gl.h b/include/vid_gl.h index 7ad9378b1..b4cd3b45f 100644 --- a/include/vid_gl.h +++ b/include/vid_gl.h @@ -12,9 +12,17 @@ typedef struct gl_ctx_s { void (*init_gl) (void); void *(*get_proc_address) (const char *name, qboolean crit); void (*end_rendering) (void); + + int begun; + double start_time; + int brush_polys; + int alias_polys; } gl_ctx_t; extern gl_ctx_t *gl_ctx; extern gl_ctx_t *glsl_ctx; +struct tex_s *gl_SCR_CaptureBGR (void); +struct tex_s *glsl_SCR_CaptureBGR (void); + #endif//__vid_gl_h diff --git a/include/vid_sw.h b/include/vid_sw.h index cd60a6d56..1515bae65 100644 --- a/include/vid_sw.h +++ b/include/vid_sw.h @@ -13,4 +13,7 @@ typedef struct sw_ctx_s { extern sw_ctx_t *sw_ctx; extern sw_ctx_t *sw32_ctx; +struct tex_s *sw_SCR_CaptureBGR (void); +struct tex_s *sw32_SCR_CaptureBGR (void); + #endif//__vid_sw_h diff --git a/libs/video/renderer/gl/gl_mod_alias.c b/libs/video/renderer/gl/gl_mod_alias.c index f41821031..e968586cb 100644 --- a/libs/video/renderer/gl/gl_mod_alias.c +++ b/libs/video/renderer/gl/gl_mod_alias.c @@ -62,6 +62,7 @@ #include "compat.h" #include "r_internal.h" +#include "vid_gl.h" typedef struct { vec3_t normal; @@ -559,7 +560,7 @@ gl_R_DrawAliasModel (entity_t *e) if (!(paliashdr = e->renderer.model->aliashdr)) { paliashdr = Cache_Get (&e->renderer.model->cache); } - gl_c_alias_polys += paliashdr->mdl.numtris; + gl_ctx->alias_polys += paliashdr->mdl.numtris; // if the model has a colorised/external skin, use it, otherwise use // the skin embedded in the model data diff --git a/libs/video/renderer/gl/gl_rmain.c b/libs/video/renderer/gl/gl_rmain.c index 07dd2a8b2..0875da139 100644 --- a/libs/video/renderer/gl/gl_rmain.c +++ b/libs/video/renderer/gl/gl_rmain.c @@ -67,8 +67,6 @@ #include "r_internal.h" #include "varrays.h" -int gl_c_brush_polys, gl_c_alias_polys; - qboolean gl_envmap; // true during envmap command capture int gl_mirrortexturenum; // quake texturenum, not gltexturenum @@ -348,9 +346,6 @@ gl_R_SetupFrame (void) r_viewleaf = Mod_PointInLeaf (r_origin, r_worldentity.renderer.model); r_cache_thrash = false; - - gl_c_brush_polys = 0; - gl_c_alias_polys = 0; } static void diff --git a/libs/video/renderer/gl/gl_rsurf.c b/libs/video/renderer/gl/gl_rsurf.c index 8a131ff44..775b9ee03 100644 --- a/libs/video/renderer/gl/gl_rsurf.c +++ b/libs/video/renderer/gl/gl_rsurf.c @@ -61,6 +61,7 @@ #include "compat.h" #include "r_internal.h" +#include "vid_gl.h" static instsurf_t *waterchain = NULL; static instsurf_t **waterchain_tail = &waterchain; @@ -222,7 +223,7 @@ R_RenderBrushPoly_3 (msurface_t *surf) float *v; int i; - gl_c_brush_polys++; + gl_ctx->brush_polys++; qfglBegin (GL_POLYGON); v = surf->polys->verts[0]; @@ -243,7 +244,7 @@ R_RenderBrushPoly_2 (msurface_t *surf) float *v; int i; - gl_c_brush_polys++; + gl_ctx->brush_polys++; qfglBegin (GL_POLYGON); v = surf->polys->verts[0]; @@ -263,7 +264,7 @@ R_RenderBrushPoly_1 (msurface_t *surf) float *v; int i; - gl_c_brush_polys++; + gl_ctx->brush_polys++; qfglBegin (GL_POLYGON); v = surf->polys->verts[0]; diff --git a/libs/video/renderer/gl/gl_screen.c b/libs/video/renderer/gl/gl_screen.c index 3647b2c53..8bd6c462d 100644 --- a/libs/video/renderer/gl/gl_screen.c +++ b/libs/video/renderer/gl/gl_screen.c @@ -28,38 +28,16 @@ # include "config.h" #endif -#define NH_DEFINE -#include "namehack.h" +#include -#ifdef HAVE_STRING_H -# include -#endif -#ifdef HAVE_STRINGS_H -# include -#endif - -#include - -#include "QF/cvar.h" -#include "QF/draw.h" -#include "QF/dstring.h" #include "QF/image.h" -#include "QF/quakefs.h" -#include "QF/render.h" -#include "QF/screen.h" #include "QF/sys.h" -#include "QF/tga.h" -#include "QF/va.h" + #include "QF/GL/defines.h" #include "QF/GL/funcs.h" -#include "QF/GL/qf_draw.h" #include "QF/GL/qf_rmain.h" -#include "QF/GL/qf_vid.h" -#include "QF/ui/view.h" -#include "compat.h" #include "r_internal.h" -#include "sbar.h" #include "vid_gl.h" /* SCREEN SHOTS */ @@ -82,94 +60,3 @@ gl_SCR_CaptureBGR (void) GL_UNSIGNED_BYTE, tex->data); return tex; } - -static void -SCR_TileClear (void) -{ - if (r_refdef.vrect.x > 0) { - // left - Draw_TileClear (0, 0, r_refdef.vrect.x, vid.height - vr_data.lineadj); - // right - Draw_TileClear (r_refdef.vrect.x + r_refdef.vrect.width, 0, - vid.width - r_refdef.vrect.x + r_refdef.vrect.width, - vid.height - vr_data.lineadj); - } - if (r_refdef.vrect.y > 0) { - // top - Draw_TileClear (r_refdef.vrect.x, 0, - r_refdef.vrect.x + r_refdef.vrect.width, - r_refdef.vrect.y); - // bottom - Draw_TileClear (r_refdef.vrect.x, - r_refdef.vrect.y + r_refdef.vrect.height, - r_refdef.vrect.width, - vid.height - vr_data.lineadj - - (r_refdef.vrect.height + r_refdef.vrect.y)); - } -} - -static void -R_Clear (void) -{ - if (gl_clear->int_val) - qfglClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - else - qfglClear (GL_DEPTH_BUFFER_BIT); -} - -void -gl_R_RenderFrame (SCR_Func *scr_funcs) -{ - double time1 = 0, time2; - static int begun = 0; - - if (begun) { - gl_ctx->end_rendering (); - begun = 0; - } - - //FIXME forces the status bar to redraw. needed because it does not fully - //update in sw modes but must in gl mode - vr_data.scr_copyeverything = 1; - - R_Clear (); - - begun = 1; - - if (r_speeds->int_val) { - time1 = Sys_DoubleTime (); - } - - // do 3D refresh drawing, and then update the screen - gl_R_RenderView (); - - GL_Set2D (); - GL_DrawReset (); - - // draw any areas not covered by the refresh - SCR_TileClear (); - - GL_Set2DScaled (); - - view_draw (vr_data.scr_view); - while (*scr_funcs) { - (*scr_funcs)(); - scr_funcs++; - } - - if (r_speeds->int_val) { -// qfglFinish (); - time2 = Sys_DoubleTime (); - Sys_MaskPrintf (SYS_dev, "%3i ms %4i wpoly %4i epoly %4i parts\n", - (int) ((time2 - time1) * 1000), gl_c_brush_polys, - gl_c_alias_polys, r_psystem.numparticles); - } - - GL_FlushText (); - qfglFlush (); - - if (gl_finish->int_val) { - gl_ctx->end_rendering (); - begun = 0; - } -} diff --git a/libs/video/renderer/glsl/glsl_screen.c b/libs/video/renderer/glsl/glsl_screen.c index ff110f5fa..4848b9018 100644 --- a/libs/video/renderer/glsl/glsl_screen.c +++ b/libs/video/renderer/glsl/glsl_screen.c @@ -31,169 +31,17 @@ # include "config.h" #endif -#define NH_DEFINE -#include "namehack.h" +#include -#ifdef HAVE_STRING_H -# include "string.h" -#endif -#ifdef HAVE_STRINGS_H -# include "strings.h" -#endif - -#include "QF/cvar.h" -#include "QF/draw.h" -#include "QF/dstring.h" #include "QF/image.h" -#include "QF/png.h" -#include "QF/quakefs.h" -#include "QF/render.h" -#include "QF/screen.h" -#include "QF/skin.h" #include "QF/sys.h" -#include "QF/va.h" #include "QF/GLSL/defines.h" #include "QF/GLSL/funcs.h" -#include "QF/GLSL/qf_draw.h" -#include "QF/GLSL/qf_textures.h" -#include "QF/GLSL/qf_vid.h" -#include "QF/ui/view.h" #include "r_internal.h" #include "vid_gl.h" -/* Unknown renamed to GLErr_Unknown to solve conflict with winioctl.h */ -static unsigned int GLErr_InvalidEnum; -static unsigned int GLErr_InvalidValue; -static unsigned int GLErr_InvalidOperation; -static unsigned int GLErr_OutOfMemory; -static unsigned int GLErr_Unknown; - -extern void (*R_DrawSpriteModel) (struct entity_s *ent); - - -static unsigned int -R_TestErrors (unsigned int numerous) -{ - switch (qfeglGetError ()) { - case GL_NO_ERROR: - return numerous; - break; - case GL_INVALID_ENUM: - GLErr_InvalidEnum++; - R_TestErrors (numerous++); - break; - case GL_INVALID_VALUE: - GLErr_InvalidValue++; - R_TestErrors (numerous++); - break; - case GL_INVALID_OPERATION: - GLErr_InvalidOperation++; - R_TestErrors (numerous++); - break; - case GL_OUT_OF_MEMORY: - GLErr_OutOfMemory++; - R_TestErrors (numerous++); - break; - default: - GLErr_Unknown++; - R_TestErrors (numerous++); - break; - } - - return numerous; -} - -static void -R_DisplayErrors (void) -{ - if (GLErr_InvalidEnum) - printf ("%d OpenGL errors: Invalid Enum!\n", GLErr_InvalidEnum); - if (GLErr_InvalidValue) - printf ("%d OpenGL errors: Invalid Value!\n", GLErr_InvalidValue); - if (GLErr_InvalidOperation) - printf ("%d OpenGL errors: Invalid Operation!\n", GLErr_InvalidOperation); - if (GLErr_OutOfMemory) - printf ("%d OpenGL errors: Out Of Memory!\n", GLErr_OutOfMemory); - if (GLErr_Unknown) - printf ("%d Unknown OpenGL errors!\n", GLErr_Unknown); -} - -static void -R_ClearErrors (void) -{ - GLErr_InvalidEnum = 0; - GLErr_InvalidValue = 0; - GLErr_InvalidOperation = 0; - GLErr_OutOfMemory = 0; - GLErr_Unknown = 0; -} - -static void -SCR_TileClear (void) -{ - if (r_refdef.vrect.x > 0) { - // left - Draw_TileClear (0, 0, r_refdef.vrect.x, vid.height - vr_data.lineadj); - // right - Draw_TileClear (r_refdef.vrect.x + r_refdef.vrect.width, 0, - vid.width - r_refdef.vrect.x + r_refdef.vrect.width, - vid.height - vr_data.lineadj); - } - if (r_refdef.vrect.y > 0) { - // top - Draw_TileClear (r_refdef.vrect.x, 0, - r_refdef.vrect.x + r_refdef.vrect.width, - r_refdef.vrect.y); - // bottom - Draw_TileClear (r_refdef.vrect.x, - r_refdef.vrect.y + r_refdef.vrect.height, - r_refdef.vrect.width, - vid.height - vr_data.lineadj - - (r_refdef.vrect.height + r_refdef.vrect.y)); - } -} - -void -glsl_R_RenderFrame (SCR_Func *scr_funcs) -{ - static int begun = 0; - - if (R_TestErrors (0)) - R_DisplayErrors (); - R_ClearErrors (); - - if (begun) { - begun = 0; - glsl_ctx->end_rendering (); - } - - //FIXME forces the status bar to redraw. needed because it does not fully - //update in sw modes but must in glsl mode - vr_data.scr_copyeverything = 1; - - qfeglClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - begun = 1; - - glsl_R_RenderView (); - - GLSL_Set2D (); - GLSL_DrawReset (); - SCR_TileClear (); - GLSL_Set2DScaled (); - - view_draw (vr_data.scr_view); - while (*scr_funcs) { - (*scr_funcs)(); - scr_funcs++; - GLSL_FlushText (); - } - GLSL_End2D (); - qfeglFlush (); -} - tex_t * glsl_SCR_CaptureBGR (void) { diff --git a/libs/video/renderer/r_screen.c b/libs/video/renderer/r_screen.c index 740b97640..4daff497c 100644 --- a/libs/video/renderer/r_screen.c +++ b/libs/video/renderer/r_screen.c @@ -71,9 +71,9 @@ R_SetVrect (const vrect_t *vrectin, vrect_t *vrect, int lineadj) float size; int h; - // intermission is always full screen size = min (r_viewsize, 100); if (r_data->force_fullscreen) { + // intermission is always full screen size = 100.0; lineadj = 0; } @@ -175,7 +175,15 @@ SCR_UpdateScreen (transform_t *camera, double realtime, SCR_Func *scr_funcs) SCR_CalcRefdef (); } - r_funcs->R_RenderFrame (scr_funcs); + r_funcs->begin_frame (); + r_funcs->render_view (); + r_funcs->set_2d(); + view_draw (vr_data.scr_view); + while (*scr_funcs) { + (*scr_funcs)(); + scr_funcs++; + } + r_funcs->end_frame (); } void @@ -289,7 +297,7 @@ SCR_DrawPause (void) /* Find closest color in the palette for named color */ -int +static int MipColor (int r, int g, int b) { float bestdist, dist; diff --git a/libs/video/renderer/sw/screen.c b/libs/video/renderer/sw/screen.c index 27a3741d1..30a60379e 100644 --- a/libs/video/renderer/sw/screen.c +++ b/libs/video/renderer/sw/screen.c @@ -28,36 +28,18 @@ # include "config.h" #endif -#ifdef HAVE_STRING_H -# include -#endif -#ifdef HAVE_STRINGS_H -# include -#endif +#include -#include - -#include "QF/cvar.h" -#include "QF/draw.h" -#include "QF/dstring.h" #include "QF/image.h" -#include "QF/pcx.h" -#include "QF/quakefs.h" -#include "QF/render.h" -#include "QF/screen.h" #include "QF/sys.h" -#include "QF/va.h" -#include "QF/ui/view.h" -#include "compat.h" #include "r_internal.h" -#include "vid_internal.h" #include "vid_sw.h" /* SCREEN SHOTS */ tex_t * -SCR_CaptureBGR (void) +sw_SCR_CaptureBGR (void) { int count, x, y; tex_t *tex; @@ -84,44 +66,3 @@ SCR_CaptureBGR (void) } return tex; } - -void -R_RenderFrame (SCR_Func *scr_funcs) -{ - // do 3D refresh drawing, and then update the screen - if (vr_data.scr_fullupdate++ < vid.numpages) { // clear the entire screen - vr_data.scr_copyeverything = 1; - Draw_TileClear (0, 0, vid.width, vid.height); - } - - R_RenderView (); - - view_draw (vr_data.scr_view); - while (*scr_funcs) { - (*scr_funcs)(); - scr_funcs++; - } - - // update one of three areas - vrect_t vrect; - if (vr_data.scr_copyeverything) { - vrect.x = 0; - vrect.y = 0; - vrect.width = vid.width; - vrect.height = vid.height; - vrect.next = 0; - } else if (scr_copytop) { - vrect.x = 0; - vrect.y = 0; - vrect.width = vid.width; - vrect.height = vid.height - vr_data.lineadj; - vrect.next = 0; - } else { - vrect.x = vr_data.scr_view->xpos; - vrect.y = vr_data.scr_view->ypos; - vrect.width = vr_data.scr_view->xlen; - vrect.height = vr_data.scr_view->ylen; - vrect.next = 0; - } - sw_ctx->update (sw_ctx, &vrect); -} diff --git a/libs/video/renderer/sw32/namehack.h b/libs/video/renderer/sw32/namehack.h index 9cbbfe348..ff78b73b6 100644 --- a/libs/video/renderer/sw32/namehack.h +++ b/libs/video/renderer/sw32/namehack.h @@ -104,7 +104,6 @@ #define R_TransformPlane sw32_R_TransformPlane #define R_ViewChanged sw32_R_ViewChanged #define R_ZDrawSubmodelPolys sw32_R_ZDrawSubmodelPolys -#define SCR_CaptureBGR sw32_SCR_CaptureBGR #define SCR_ScreenShot sw32_SCR_ScreenShot #define SCR_ScreenShot_f sw32_SCR_ScreenShot_f #define R_RenderFrame sw32_R_RenderFrame diff --git a/libs/video/renderer/sw32/screen.c b/libs/video/renderer/sw32/screen.c index 072c88182..77fc155e6 100644 --- a/libs/video/renderer/sw32/screen.c +++ b/libs/video/renderer/sw32/screen.c @@ -28,33 +28,12 @@ # include "config.h" #endif -#define NH_DEFINE -#include "namehack.h" +#include -#ifdef HAVE_STRING_H -# include -#endif -#ifdef HAVE_STRINGS_H -# include -#endif - -#include - -#include "QF/cvar.h" -#include "QF/draw.h" -#include "QF/dstring.h" #include "QF/image.h" -#include "QF/pcx.h" -#include "QF/quakefs.h" -#include "QF/render.h" -#include "QF/screen.h" #include "QF/sys.h" -#include "QF/va.h" -#include "QF/ui/view.h" -#include "compat.h" #include "r_internal.h" -#include "vid_internal.h" #include "vid_sw.h" /* SCREEN SHOTS */ @@ -87,44 +66,3 @@ sw32_SCR_CaptureBGR (void) } return tex; } - -void -sw32_R_RenderFrame (SCR_Func *scr_funcs) -{ - vrect_t vrect; - - if (vr_data.scr_fullupdate++ < vid.numpages) { // clear the entire screen - vr_data.scr_copyeverything = 1; - sw32_Draw_TileClear (0, 0, vid.width, vid.height); - } - - sw32_R_RenderView (); - - view_draw (vr_data.scr_view); - while (*scr_funcs) { - (*scr_funcs)(); - scr_funcs++; - } - - // update one of three areas - if (vr_data.scr_copyeverything) { - vrect.x = 0; - vrect.y = 0; - vrect.width = vid.width; - vrect.height = vid.height; - vrect.next = 0; - } else if (scr_copytop) { - vrect.x = 0; - vrect.y = 0; - vrect.width = vid.width; - vrect.height = vid.height - vr_data.lineadj; - vrect.next = 0; - } else { - vrect.x = vr_data.scr_view->xpos; - vrect.y = vr_data.scr_view->ypos; - vrect.width = vr_data.scr_view->xlen; - vrect.height = vr_data.scr_view->ylen; - vrect.next = 0; - } - sw32_ctx->update (sw32_ctx, &vrect); -} diff --git a/libs/video/renderer/vid_render_gl.c b/libs/video/renderer/vid_render_gl.c index c68cd8c9e..6b9bc08ed 100644 --- a/libs/video/renderer/vid_render_gl.c +++ b/libs/video/renderer/vid_render_gl.c @@ -31,13 +31,18 @@ #define NH_DEFINE #include "gl/namehack.h" +#include "QF/cvar.h" + #include "QF/plugin/general.h" #include "QF/plugin/vid_render.h" +#include "QF/GL/funcs.h" +#include "QF/GL/qf_draw.h" #include "QF/GL/qf_rsurf.h" #include "QF/GL/qf_vid.h" #include "mod_internal.h" +#include "r_cvar.h" #include "r_internal.h" #include "vid_internal.h" #include "vid_gl.h" @@ -108,6 +113,93 @@ gl_vid_render_shutdown (void) { } +static void +gl_begin_frame (void) +{ + if (gl_ctx->begun) { + gl_ctx->end_rendering (); + gl_ctx->begun = 0; + } + + //FIXME forces the status bar to redraw. needed because it does not fully + //update in sw modes but must in gl mode + vr_data.scr_copyeverything = 1; + + if (gl_clear->int_val) { + qfglClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + } else { + qfglClear (GL_DEPTH_BUFFER_BIT); + } + + gl_ctx->begun = 1; + + if (r_speeds->int_val) { + gl_ctx->start_time = Sys_DoubleTime (); + gl_ctx->brush_polys = 0; + gl_ctx->alias_polys = 0; + } + + GL_Set2D (); + GL_DrawReset (); + + // draw any areas not covered by the refresh + if (r_refdef.vrect.x > 0) { + // left + Draw_TileClear (0, 0, r_refdef.vrect.x, vid.height - vr_data.lineadj); + // right + Draw_TileClear (r_refdef.vrect.x + r_refdef.vrect.width, 0, + vid.width - r_refdef.vrect.x + r_refdef.vrect.width, + vid.height - vr_data.lineadj); + } + if (r_refdef.vrect.y > 0) { + // top + Draw_TileClear (r_refdef.vrect.x, 0, + r_refdef.vrect.x + r_refdef.vrect.width, + r_refdef.vrect.y); + // bottom + Draw_TileClear (r_refdef.vrect.x, + r_refdef.vrect.y + r_refdef.vrect.height, + r_refdef.vrect.width, + vid.height - vr_data.lineadj - + (r_refdef.vrect.height + r_refdef.vrect.y)); + } +} + +static void +gl_render_view (void) +{ + // do 3D refresh drawing, and then update the screen + gl_R_RenderView (); +} + +static void +gl_set_2d (void) +{ + GL_Set2DScaled (); +} + +static void +gl_end_frame (void) +{ + if (r_speeds->int_val) { +// qfglFinish (); + double start_time = gl_ctx->start_time; + double end_time = Sys_DoubleTime (); + Sys_MaskPrintf (SYS_dev, "%3i ms %4i wpoly %4i epoly %4i parts\n", + (int) ((end_time - start_time) * 1000), + gl_ctx->brush_polys, gl_ctx->alias_polys, + r_psystem.numparticles); + } + + GL_FlushText (); + qfglFlush (); + + if (gl_finish->int_val) { + gl_ctx->end_rendering (); + gl_ctx->begun = 0; + } +} + vid_render_funcs_t gl_vid_render_funcs = { gl_vid_render_init, gl_Draw_Character, @@ -138,12 +230,15 @@ vid_render_funcs_t gl_vid_render_funcs = { gl_ParticleSystem, gl_R_Init, - gl_R_RenderFrame, gl_R_ClearState, gl_R_LoadSkys, gl_R_NewMap, gl_R_LineGraph, gl_R_ViewChanged, + gl_begin_frame, + gl_render_view, + gl_set_2d, + gl_end_frame, &model_funcs }; diff --git a/libs/video/renderer/vid_render_glsl.c b/libs/video/renderer/vid_render_glsl.c index 2ca14d425..9bf4c6b35 100644 --- a/libs/video/renderer/vid_render_glsl.c +++ b/libs/video/renderer/vid_render_glsl.c @@ -34,7 +34,10 @@ #include "QF/plugin/general.h" #include "QF/plugin/vid_render.h" +#include "QF/GLSL/funcs.h" +#include "QF/GLSL/defines.h" #include "QF/GLSL/qf_bsp.h" +#include "QF/GLSL/qf_draw.h" #include "QF/GLSL/qf_vid.h" #include "mod_internal.h" @@ -107,6 +110,134 @@ glsl_vid_render_shutdown (void) { } +static unsigned int GLErr_InvalidEnum; +static unsigned int GLErr_InvalidValue; +static unsigned int GLErr_InvalidOperation; +static unsigned int GLErr_OutOfMemory; +static unsigned int GLErr_Unknown; + +static unsigned int +R_TestErrors (unsigned int numerous) +{ + switch (qfeglGetError ()) { + case GL_NO_ERROR: + return numerous; + break; + case GL_INVALID_ENUM: + GLErr_InvalidEnum++; + R_TestErrors (numerous++); + break; + case GL_INVALID_VALUE: + GLErr_InvalidValue++; + R_TestErrors (numerous++); + break; + case GL_INVALID_OPERATION: + GLErr_InvalidOperation++; + R_TestErrors (numerous++); + break; + case GL_OUT_OF_MEMORY: + GLErr_OutOfMemory++; + R_TestErrors (numerous++); + break; + default: + GLErr_Unknown++; + R_TestErrors (numerous++); + break; + } + + return numerous; +} + +static void +R_DisplayErrors (void) +{ + if (GLErr_InvalidEnum) + printf ("%d OpenGL errors: Invalid Enum!\n", GLErr_InvalidEnum); + if (GLErr_InvalidValue) + printf ("%d OpenGL errors: Invalid Value!\n", GLErr_InvalidValue); + if (GLErr_InvalidOperation) + printf ("%d OpenGL errors: Invalid Operation!\n", GLErr_InvalidOperation); + if (GLErr_OutOfMemory) + printf ("%d OpenGL errors: Out Of Memory!\n", GLErr_OutOfMemory); + if (GLErr_Unknown) + printf ("%d Unknown OpenGL errors!\n", GLErr_Unknown); +} + +static void +R_ClearErrors (void) +{ + GLErr_InvalidEnum = 0; + GLErr_InvalidValue = 0; + GLErr_InvalidOperation = 0; + GLErr_OutOfMemory = 0; + GLErr_Unknown = 0; +} + +static void +glsl_begin_frame (void) +{ + if (R_TestErrors (0)) + R_DisplayErrors (); + R_ClearErrors (); + + if (glsl_ctx->begun) { + glsl_ctx->begun = 0; + glsl_ctx->end_rendering (); + } + + //FIXME forces the status bar to redraw. needed because it does not fully + //update in sw modes but must in glsl mode + vr_data.scr_copyeverything = 1; + + qfeglClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glsl_ctx->begun = 1; + + GLSL_Set2D (); + GLSL_DrawReset (); + + if (r_refdef.vrect.x > 0) { + // left + Draw_TileClear (0, 0, r_refdef.vrect.x, vid.height - vr_data.lineadj); + // right + Draw_TileClear (r_refdef.vrect.x + r_refdef.vrect.width, 0, + vid.width - r_refdef.vrect.x + r_refdef.vrect.width, + vid.height - vr_data.lineadj); + } + if (r_refdef.vrect.y > 0) { + // top + Draw_TileClear (r_refdef.vrect.x, 0, + r_refdef.vrect.x + r_refdef.vrect.width, + r_refdef.vrect.y); + // bottom + Draw_TileClear (r_refdef.vrect.x, + r_refdef.vrect.y + r_refdef.vrect.height, + r_refdef.vrect.width, + vid.height - vr_data.lineadj - + (r_refdef.vrect.height + r_refdef.vrect.y)); + } +} + +static void +glsl_render_view (void) +{ + glsl_R_RenderView (); +} + +static void +glsl_set_2d (void) +{ + GLSL_Set2DScaled (); +} + +static void +glsl_end_frame (void) +{ + GLSL_FlushText (); + GLSL_End2D (); + qfeglFlush (); +} + vid_render_funcs_t glsl_vid_render_funcs = { glsl_vid_render_init, glsl_Draw_Character, @@ -137,12 +268,15 @@ vid_render_funcs_t glsl_vid_render_funcs = { glsl_ParticleSystem, glsl_R_Init, - glsl_R_RenderFrame, glsl_R_ClearState, glsl_R_LoadSkys, glsl_R_NewMap, glsl_R_LineGraph, glsl_R_ViewChanged, + glsl_begin_frame, + glsl_render_view, + glsl_set_2d, + glsl_end_frame, &model_funcs }; diff --git a/libs/video/renderer/vid_render_sw.c b/libs/video/renderer/vid_render_sw.c index 9ad7939ec..b994bf579 100644 --- a/libs/video/renderer/vid_render_sw.c +++ b/libs/video/renderer/vid_render_sw.c @@ -31,6 +31,8 @@ #include "QF/plugin/general.h" #include "QF/plugin/vid_render.h" +#include "QF/ui/view.h" + #include "mod_internal.h" #include "r_internal.h" #include "vid_internal.h" @@ -104,6 +106,54 @@ sw_vid_render_shutdown (void) { } +static void +sw_begin_frame (void) +{ + // do 3D refresh drawing, and then update the screen + if (vr_data.scr_fullupdate++ < vid.numpages) { + vr_data.scr_copyeverything = 1; + Draw_TileClear (0, 0, vid.width, vid.height); + } +} + +static void +sw_render_view (void) +{ + R_RenderView (); +} + +static void +sw_set_2d (void) +{ +} + +static void +sw_end_frame (void) +{ + // update one of three areas + vrect_t vrect; + if (vr_data.scr_copyeverything) { + vrect.x = 0; + vrect.y = 0; + vrect.width = vid.width; + vrect.height = vid.height; + vrect.next = 0; + } else if (scr_copytop) { + vrect.x = 0; + vrect.y = 0; + vrect.width = vid.width; + vrect.height = vid.height - vr_data.lineadj; + vrect.next = 0; + } else { + vrect.x = vr_data.scr_view->xpos; + vrect.y = vr_data.scr_view->ypos; + vrect.width = vr_data.scr_view->xlen; + vrect.height = vr_data.scr_view->ylen; + vrect.next = 0; + } + sw_ctx->update (sw_ctx, &vrect); +} + vid_render_funcs_t sw_vid_render_funcs = { sw_vid_render_init, Draw_Character, @@ -127,19 +177,22 @@ vid_render_funcs_t sw_vid_render_funcs = { Draw_Picf, Draw_SubPic, - SCR_CaptureBGR, + sw_SCR_CaptureBGR, 0, 0, sw_ParticleSystem, sw_R_Init, - R_RenderFrame, R_ClearState, R_LoadSkys, R_NewMap, R_LineGraph, R_ViewChanged, + sw_begin_frame, + sw_render_view, + sw_set_2d, + sw_end_frame, &model_funcs }; diff --git a/libs/video/renderer/vid_render_sw32.c b/libs/video/renderer/vid_render_sw32.c index 4f417d840..2d30ec65c 100644 --- a/libs/video/renderer/vid_render_sw32.c +++ b/libs/video/renderer/vid_render_sw32.c @@ -34,6 +34,8 @@ #include "QF/plugin/general.h" #include "QF/plugin/vid_render.h" +#include "QF/ui/view.h" + #include "mod_internal.h" #include "r_internal.h" #include "vid_internal.h" @@ -109,6 +111,53 @@ sw32_vid_render_shutdown (void) { } +static void +sw32_begin_frame (void) +{ + if (vr_data.scr_fullupdate++ < vid.numpages) { // clear the entire screen + vr_data.scr_copyeverything = 1; + sw32_Draw_TileClear (0, 0, vid.width, vid.height); + } +} + +static void +sw32_render_view (void) +{ + sw32_R_RenderView (); +} + +static void +sw32_set_2d (void) +{ +} + +static void +sw32_end_frame (void) +{ + // update one of three areas + vrect_t vrect; + if (vr_data.scr_copyeverything) { + vrect.x = 0; + vrect.y = 0; + vrect.width = vid.width; + vrect.height = vid.height; + vrect.next = 0; + } else if (scr_copytop) { + vrect.x = 0; + vrect.y = 0; + vrect.width = vid.width; + vrect.height = vid.height - vr_data.lineadj; + vrect.next = 0; + } else { + vrect.x = vr_data.scr_view->xpos; + vrect.y = vr_data.scr_view->ypos; + vrect.width = vr_data.scr_view->xlen; + vrect.height = vr_data.scr_view->ylen; + vrect.next = 0; + } + sw32_ctx->update (sw32_ctx, &vrect); +} + vid_render_funcs_t sw32_vid_render_funcs = { sw32_vid_render_init, sw32_Draw_Character, @@ -139,12 +188,15 @@ vid_render_funcs_t sw32_vid_render_funcs = { sw32_ParticleSystem, sw32_R_Init, - sw32_R_RenderFrame, sw32_R_ClearState, sw32_R_LoadSkys, sw32_R_NewMap, sw32_R_LineGraph, sw32_R_ViewChanged, + sw32_begin_frame, + sw32_render_view, + sw32_set_2d, + sw32_end_frame, &model_funcs }; diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 72e6caa5e..524580ecb 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -112,131 +112,6 @@ vulkan_R_Init (void) SCR_Init (); } -static void -vulkan_R_RenderFrame (SCR_Func *scr_funcs) -{ - uint32_t imageIndex = 0; - qfv_device_t *device = vulkan_ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - VkDevice dev = device->dev; - qfv_queue_t *queue = &vulkan_ctx->device->queue; - - __auto_type frame = &vulkan_ctx->frames.a[vulkan_ctx->curFrame]; - - dfunc->vkWaitForFences (dev, 1, &frame->fence, VK_TRUE, 2000000000); - QFV_AcquireNextImage (vulkan_ctx->swapchain, - frame->imageAvailableSemaphore, - 0, &imageIndex); - vulkan_ctx->swapImageIndex = imageIndex; - - view_draw (vr_data.scr_view); - while (*scr_funcs) { - (*scr_funcs) (); - scr_funcs++; - } - - for (size_t i = 0; i < vulkan_ctx->renderPasses.size; i++) { - __auto_type rp = vulkan_ctx->renderPasses.a[i]; - __auto_type rpFrame = &rp->frames.a[vulkan_ctx->curFrame]; - frame->framebuffer = rp->framebuffers->a[imageIndex]; - rp->draw (rpFrame); - } - - VkCommandBufferBeginInfo beginInfo - = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO }; - - VkRenderPassBeginInfo renderPassInfo = { - .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, - .renderArea = { {0, 0}, vulkan_ctx->swapchain->extent }, - }; - - dfunc->vkBeginCommandBuffer (frame->cmdBuffer, &beginInfo); - for (size_t i = 0; i < vulkan_ctx->renderPasses.size; i++) { - __auto_type rp = vulkan_ctx->renderPasses.a[i]; - __auto_type rpFrame = &rp->frames.a[vulkan_ctx->curFrame]; - - if (rpFrame->renderpass) { - renderPassInfo.framebuffer = frame->framebuffer, - renderPassInfo.renderPass = rp->renderpass; - renderPassInfo.clearValueCount = rp->clearValues->size; - renderPassInfo.pClearValues = rp->clearValues->a; - - dfunc->vkCmdBeginRenderPass (frame->cmdBuffer, &renderPassInfo, - rpFrame->subpassContents); - - for (int j = 0; j < rpFrame->subpassCount; j++) { - __auto_type cmdSet = &rpFrame->subpassCmdSets[j]; - if (cmdSet->size) { - dfunc->vkCmdExecuteCommands (frame->cmdBuffer, - cmdSet->size, cmdSet->a); - } - // reset for next time around - cmdSet->size = 0; - - //Regardless of whether any commands were submitted for this - //subpass, must step through each and every subpass, otherwise - //the attachments won't be transitioned correctly. - if (j < rpFrame->subpassCount - 1) { - dfunc->vkCmdNextSubpass (frame->cmdBuffer, - rpFrame->subpassContents); - } - } - dfunc->vkCmdEndRenderPass (frame->cmdBuffer); - } else { - for (int j = 0; j < rpFrame->subpassCount; j++) { - __auto_type cmdSet = &rpFrame->subpassCmdSets[j]; - if (cmdSet->size) { - dfunc->vkCmdExecuteCommands (frame->cmdBuffer, - cmdSet->size, cmdSet->a); - } - // reset for next time around - cmdSet->size = 0; - } - } - } - - if (vulkan_ctx->capture_callback) { - VkImage srcImage = vulkan_ctx->swapchain->images->a[imageIndex]; - VkCommandBuffer cmd = QFV_CaptureImage (vulkan_ctx->capture, srcImage, - vulkan_ctx->curFrame); - dfunc->vkCmdExecuteCommands (frame->cmdBuffer, 1, &cmd); - } - dfunc->vkEndCommandBuffer (frame->cmdBuffer); - - VkPipelineStageFlags waitStage - = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - VkSubmitInfo submitInfo = { - VK_STRUCTURE_TYPE_SUBMIT_INFO, 0, - 1, &frame->imageAvailableSemaphore, &waitStage, - 1, &frame->cmdBuffer, - 1, &frame->renderDoneSemaphore, - }; - dfunc->vkResetFences (dev, 1, &frame->fence); - dfunc->vkQueueSubmit (queue->queue, 1, &submitInfo, frame->fence); - - if (vulkan_ctx->capture_callback) { - //FIXME look into "threading" this rather than waiting here - dfunc->vkWaitForFences (device->dev, 1, &frame->fence, VK_TRUE, - 1000000000ull); - vulkan_ctx->capture_callback (QFV_CaptureData (vulkan_ctx->capture, - vulkan_ctx->curFrame), - vulkan_ctx->capture->extent.width, - vulkan_ctx->capture->extent.height); - vulkan_ctx->capture_callback = 0; - } - - VkPresentInfoKHR presentInfo = { - VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, 0, - 1, &frame->renderDoneSemaphore, - 1, &vulkan_ctx->swapchain->swapchain, &imageIndex, - 0 - }; - dfunc->vkQueuePresentKHR (queue->queue, &presentInfo); - - vulkan_ctx->curFrame++; - vulkan_ctx->curFrame %= vulkan_ctx->frames.size; -} - static void vulkan_R_ClearState (void) { @@ -389,6 +264,147 @@ vulkan_R_ViewChanged (void) Vulkan_CalcProjectionMatrices (vulkan_ctx); } +static void +vulkan_begin_frame (void) +{ + uint32_t imageIndex = 0; + qfv_device_t *device = vulkan_ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + VkDevice dev = device->dev; + + __auto_type frame = &vulkan_ctx->frames.a[vulkan_ctx->curFrame]; + + dfunc->vkWaitForFences (dev, 1, &frame->fence, VK_TRUE, 2000000000); + QFV_AcquireNextImage (vulkan_ctx->swapchain, + frame->imageAvailableSemaphore, + 0, &imageIndex); + vulkan_ctx->swapImageIndex = imageIndex; +} + +static void +vulkan_render_view (void) +{ + __auto_type frame = &vulkan_ctx->frames.a[vulkan_ctx->curFrame]; + uint32_t imageIndex = vulkan_ctx->swapImageIndex; + + for (size_t i = 0; i < vulkan_ctx->renderPasses.size; i++) { + __auto_type rp = vulkan_ctx->renderPasses.a[i]; + __auto_type rpFrame = &rp->frames.a[vulkan_ctx->curFrame]; + frame->framebuffer = rp->framebuffers->a[imageIndex]; + rp->draw (rpFrame); + } +} + +static void +vulkan_set_2d (void) +{ +} + +static void +vulkan_end_frame (void) +{ + qfv_device_t *device = vulkan_ctx->device; + VkDevice dev = device->dev; + qfv_devfuncs_t *dfunc = device->funcs; + qfv_queue_t *queue = &device->queue; + __auto_type frame = &vulkan_ctx->frames.a[vulkan_ctx->curFrame]; + uint32_t imageIndex = vulkan_ctx->swapImageIndex; + + VkCommandBufferBeginInfo beginInfo + = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO }; + + VkRenderPassBeginInfo renderPassInfo = { + .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, + .renderArea = { {0, 0}, vulkan_ctx->swapchain->extent }, + }; + + dfunc->vkBeginCommandBuffer (frame->cmdBuffer, &beginInfo); + for (size_t i = 0; i < vulkan_ctx->renderPasses.size; i++) { + __auto_type rp = vulkan_ctx->renderPasses.a[i]; + __auto_type rpFrame = &rp->frames.a[vulkan_ctx->curFrame]; + + if (rpFrame->renderpass) { + renderPassInfo.framebuffer = frame->framebuffer, + renderPassInfo.renderPass = rp->renderpass; + renderPassInfo.clearValueCount = rp->clearValues->size; + renderPassInfo.pClearValues = rp->clearValues->a; + + dfunc->vkCmdBeginRenderPass (frame->cmdBuffer, &renderPassInfo, + rpFrame->subpassContents); + + for (int j = 0; j < rpFrame->subpassCount; j++) { + __auto_type cmdSet = &rpFrame->subpassCmdSets[j]; + if (cmdSet->size) { + dfunc->vkCmdExecuteCommands (frame->cmdBuffer, + cmdSet->size, cmdSet->a); + } + // reset for next time around + cmdSet->size = 0; + + //Regardless of whether any commands were submitted for this + //subpass, must step through each and every subpass, otherwise + //the attachments won't be transitioned correctly. + if (j < rpFrame->subpassCount - 1) { + dfunc->vkCmdNextSubpass (frame->cmdBuffer, + rpFrame->subpassContents); + } + } + dfunc->vkCmdEndRenderPass (frame->cmdBuffer); + } else { + for (int j = 0; j < rpFrame->subpassCount; j++) { + __auto_type cmdSet = &rpFrame->subpassCmdSets[j]; + if (cmdSet->size) { + dfunc->vkCmdExecuteCommands (frame->cmdBuffer, + cmdSet->size, cmdSet->a); + } + // reset for next time around + cmdSet->size = 0; + } + } + } + + if (vulkan_ctx->capture_callback) { + VkImage srcImage = vulkan_ctx->swapchain->images->a[imageIndex]; + VkCommandBuffer cmd = QFV_CaptureImage (vulkan_ctx->capture, srcImage, + vulkan_ctx->curFrame); + dfunc->vkCmdExecuteCommands (frame->cmdBuffer, 1, &cmd); + } + dfunc->vkEndCommandBuffer (frame->cmdBuffer); + + VkPipelineStageFlags waitStage + = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + VkSubmitInfo submitInfo = { + VK_STRUCTURE_TYPE_SUBMIT_INFO, 0, + 1, &frame->imageAvailableSemaphore, &waitStage, + 1, &frame->cmdBuffer, + 1, &frame->renderDoneSemaphore, + }; + dfunc->vkResetFences (dev, 1, &frame->fence); + dfunc->vkQueueSubmit (queue->queue, 1, &submitInfo, frame->fence); + + if (vulkan_ctx->capture_callback) { + //FIXME look into "threading" this rather than waiting here + dfunc->vkWaitForFences (device->dev, 1, &frame->fence, VK_TRUE, + 1000000000ull); + vulkan_ctx->capture_callback (QFV_CaptureData (vulkan_ctx->capture, + vulkan_ctx->curFrame), + vulkan_ctx->capture->extent.width, + vulkan_ctx->capture->extent.height); + vulkan_ctx->capture_callback = 0; + } + + VkPresentInfoKHR presentInfo = { + VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, 0, + 1, &frame->renderDoneSemaphore, + 1, &vulkan_ctx->swapchain->swapchain, &imageIndex, + 0 + }; + dfunc->vkQueuePresentKHR (queue->queue, &presentInfo); + + vulkan_ctx->curFrame++; + vulkan_ctx->curFrame %= vulkan_ctx->frames.size; +} + static int is_bgr (VkFormat format) { @@ -658,12 +674,15 @@ vid_render_funcs_t vulkan_vid_render_funcs = { vulkan_ParticleSystem, vulkan_R_Init, - vulkan_R_RenderFrame, vulkan_R_ClearState, vulkan_R_LoadSkys, vulkan_R_NewMap, vulkan_R_LineGraph, vulkan_R_ViewChanged, + vulkan_begin_frame, + vulkan_render_view, + vulkan_set_2d, + vulkan_end_frame, &model_funcs }; diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 3d85fcd08..e6c1bea5b 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -339,7 +339,7 @@ renderpass_draw (qfv_renderframe_t *rFrame) { Vulkan_Matrix_Draw (rFrame); Vulkan_RenderView (rFrame); - Vulkan_FlushText (rFrame); + Vulkan_FlushText (rFrame);//FIXME delayed by a frame? Vulkan_Lighting_Draw (rFrame); Vulkan_Compose_Draw (rFrame); }