[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.
This commit is contained in:
Bill Currie 2022-03-07 23:32:44 +09:00
parent e1d38a9373
commit af0c66dff9
19 changed files with 524 additions and 544 deletions

View file

@ -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;

View file

@ -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;

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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];

View file

@ -28,38 +28,16 @@
# include "config.h"
#endif
#define NH_DEFINE
#include "namehack.h"
#include <stdlib.h>
#ifdef HAVE_STRING_H
# include <string.h>
#endif
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#include <time.h>
#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;
}
}

View file

@ -31,169 +31,17 @@
# include "config.h"
#endif
#define NH_DEFINE
#include "namehack.h"
#include <stdlib.h>
#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)
{

View file

@ -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;

View file

@ -28,36 +28,18 @@
# include "config.h"
#endif
#ifdef HAVE_STRING_H
# include <string.h>
#endif
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#include <stdlib.h>
#include <time.h>
#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);
}

View file

@ -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

View file

@ -28,33 +28,12 @@
# include "config.h"
#endif
#define NH_DEFINE
#include "namehack.h"
#include <stdlib.h>
#ifdef HAVE_STRING_H
# include <string.h>
#endif
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#include <time.h>
#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);
}

View file

@ -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
};

View file

@ -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
};

View file

@ -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
};

View file

@ -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
};

View file

@ -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
};

View file

@ -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);
}