X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=gl_rmain.c;h=671786c8893d2ab9831143e4f3bcaa8d05fe1bbd;hp=9a1b09e586e71c5ee5a367730b303a8356a5bc26;hb=78b6fb46fb00b5c74f08337becebc27e4e8688b8;hpb=c53c8b42b4c5acb7184e2d037415232541ec98a6 diff --git a/gl_rmain.c b/gl_rmain.c index 9a1b09e5..671786c8 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -54,8 +54,6 @@ cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambi cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"}; cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"}; -cvar_t r_animcache = {CVAR_SAVE, "r_animcache", "1", "cache animation frames to save CPU usage, primarily optimizes shadows and reflections"}; - cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"}; cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"}; cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"}; @@ -159,6 +157,8 @@ cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "widt cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"}; cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"}; +cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "1", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"}; + extern cvar_t v_glslgamma; extern qboolean v_flipped_state; @@ -2972,6 +2972,9 @@ void gl_main_start(void) break; } + R_AnimCache_Free(); + R_FrameData_Reset(); + r_numqueries = 0; r_maxqueries = 0; memset(r_queries, 0, sizeof(r_queries)); @@ -3007,6 +3010,9 @@ void gl_main_start(void) extern rtexture_t *loadingscreentexture; void gl_main_shutdown(void) { + R_AnimCache_Free(); + R_FrameData_Reset(); + R_Main_FreeViewCache(); if (r_maxqueries) @@ -3070,6 +3076,8 @@ void gl_main_newmap(void) CL_ParseEntityLump(cl.worldmodel->brush.entities); } R_Main_FreeViewCache(); + + R_FrameData_Reset(); } void GL_Main_Init(void) @@ -3102,7 +3110,6 @@ void GL_Main_Init(void) Cvar_RegisterVariable(&r_equalize_entities_minambient); Cvar_RegisterVariable(&r_equalize_entities_by); Cvar_RegisterVariable(&r_equalize_entities_to); - Cvar_RegisterVariable(&r_animcache); Cvar_RegisterVariable(&r_depthfirst); Cvar_RegisterVariable(&r_useinfinitefarclip); Cvar_RegisterVariable(&r_farclip_base); @@ -3182,6 +3189,7 @@ void GL_Main_Init(void) Cvar_RegisterVariable(&r_test); Cvar_RegisterVariable(&r_batchmode); Cvar_RegisterVariable(&r_glsl_saturation); + Cvar_RegisterVariable(&r_framedatasize); if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE) Cvar_SetValue("r_fullbrights", 0); R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap); @@ -3355,6 +3363,69 @@ int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, c //================================================================================== +// LordHavoc: this stores temporary data used within the same frame + +qboolean r_framedata_failed; +static size_t r_framedata_size; +static size_t r_framedata_current; +static void *r_framedata_base; + +void R_FrameData_Reset(void) +{ + if (r_framedata_base); + Mem_Free(r_framedata_base); + r_framedata_base = NULL; + r_framedata_size = 0; + r_framedata_current = 0; +} + +void R_FrameData_NewFrame(void) +{ + size_t wantedsize; + if (r_framedata_failed) + Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value * 1.25f); + wantedsize = (size_t)(r_framedatasize.value * 1024*1024); + wantedsize = bound(65536, wantedsize, 128*1024*1024); + if (r_framedata_size < wantedsize) + { + r_framedata_size = wantedsize; + if (!r_framedata_base) + r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size); + } + r_framedata_current = 0; + r_framedata_failed = false; +} + +void *R_FrameData_Alloc(size_t size) +{ + void *data; + + // align to 16 byte boundary + size = (size + 15) & ~15; + data = r_framedata_base + r_framedata_current; + r_framedata_current += size; + + // check overflow + if (r_framedata_current > r_framedata_size) + r_framedata_failed = true; + + // return NULL on everything after a failure + if (r_framedata_failed) + return NULL; + + return data; +} + +void *R_FrameData_Store(size_t size, void *data) +{ + void *d = R_FrameData_Alloc(size); + if (d) + memcpy(d, data, size); + return d; +} + +//================================================================================== + // LordHavoc: animcache written by Echon, refactored and reformatted by me /** @@ -3369,9 +3440,6 @@ typedef struct r_animcache_entity_s float *normal3f; float *svector3f; float *tvector3f; - int maxvertices; - qboolean wantnormals; - qboolean wanttangents; } r_animcache_entity_t; @@ -3387,105 +3455,88 @@ static r_animcache_t r_animcachestate; void R_AnimCache_Free(void) { - int idx; - for (idx=0 ; idxmaxvertices >= numvertices) - return; - - // Release existing memory - if (cache->vertex3f) - Mem_Free(cache->vertex3f); - - // Pad by 1024 verts - cache->maxvertices = (numvertices + 1023) & ~1023; - arraySize = cache->maxvertices * 3; - - // Allocate, even if we don't need this memory in this instance it will get ignored and potentially used later - base = (float *)Mem_Alloc(r_main_mempool, arraySize * sizeof(float) * 4); - r_animcachestate.entity[cacheIdx].vertex3f = base; - r_animcachestate.entity[cacheIdx].normal3f = base + arraySize; - r_animcachestate.entity[cacheIdx].svector3f = base + arraySize*2; - r_animcachestate.entity[cacheIdx].tvector3f = base + arraySize*3; - -// Con_Printf("allocated cache for %i (%f KB)\n", cacheIdx, (arraySize*sizeof(float)*4)/1024.0f); -} - -void R_AnimCache_NewFrame(void) +void R_AnimCache_ClearCache(void) { int i; + entity_render_t *ent; - if (r_animcache.integer && r_drawentities.integer) - r_animcachestate.maxindex = sizeof(r_animcachestate.entity) / sizeof(r_animcachestate.entity[0]); - else if (r_animcachestate.maxindex) - R_AnimCache_Free(); - + r_animcachestate.maxindex = sizeof(r_animcachestate.entity) / sizeof(r_animcachestate.entity[0]); r_animcachestate.currentindex = 0; for (i = 0;i < r_refdef.scene.numentities;i++) - r_refdef.scene.entities[i]->animcacheindex = -1; + { + ent = r_refdef.scene.entities[i]; + ent->animcacheindex = -1; + } } qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents) { dp_model_t *model = ent->model; r_animcache_entity_t *c; + int numvertices; // see if it's already cached this frame if (ent->animcacheindex >= 0) { // add normals/tangents if needed - c = r_animcachestate.entity + ent->animcacheindex; - if (c->wantnormals) - wantnormals = false; - if (c->wanttangents) - wanttangents = false; if (wantnormals || wanttangents) - model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? c->normal3f : NULL, wanttangents ? c->svector3f : NULL, wanttangents ? c->tvector3f : NULL); + { + c = r_animcachestate.entity + ent->animcacheindex; + if (c->normal3f) + wantnormals = false; + if (c->svector3f) + wanttangents = false; + if (wantnormals || wanttangents) + { + numvertices = model->surfmesh.num_vertices; + if (wantnormals) + c->normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices); + if (wanttangents) + { + c->svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices); + c->tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices); + } + if (!r_framedata_failed) + model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? c->normal3f : NULL, wanttangents ? c->svector3f : NULL, wanttangents ? c->tvector3f : NULL); + } + } } else { // see if this ent is worth caching if (r_animcachestate.maxindex <= r_animcachestate.currentindex) return false; - if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0)) + if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton)) return false; - // assign it a cache entry and make sure the arrays are big enough - R_AnimCache_ResizeEntityCache(r_animcachestate.currentindex, model->surfmesh.num_vertices); + // assign it a cache entry and get some temp memory ent->animcacheindex = r_animcachestate.currentindex++; c = r_animcachestate.entity + ent->animcacheindex; - c->wantnormals = wantnormals; - c->wanttangents = wanttangents; - model->AnimateVertices(model, ent->frameblend, ent->skeleton, c->vertex3f, wantnormals ? c->normal3f : NULL, wanttangents ? c->svector3f : NULL, wanttangents ? c->tvector3f : NULL); + numvertices = model->surfmesh.num_vertices; + memset(c, 0, sizeof(*c)); + c->vertex3f = R_FrameData_Alloc(sizeof(float[3])*numvertices); + if (wantnormals) + c->normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices); + if (wanttangents) + { + c->svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices); + c->tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices); + } + if (!r_framedata_failed) + model->AnimateVertices(model, ent->frameblend, ent->skeleton, c->vertex3f, c->normal3f, c->svector3f, c->tvector3f); } - return true; + return !r_framedata_failed; } void R_AnimCache_CacheVisibleEntities(void) { int i; + entity_render_t *ent; qboolean wantnormals = !r_showsurfaces.integer; qboolean wanttangents = !r_showsurfaces.integer; - if (!r_animcachestate.maxindex) - return; - switch(vid.renderpath) { case RENDERPATH_GL20: @@ -3496,13 +3547,16 @@ void R_AnimCache_CacheVisibleEntities(void) break; } - // TODO: thread this? + // TODO: thread this for (i = 0;i < r_refdef.scene.numentities;i++) { if (!r_refdef.viewcache.entityvisible[i]) continue; - R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents); + ent = r_refdef.scene.entities[i]; + if (ent->animcacheindex >= 0) + continue; + R_AnimCache_GetEntity(ent, wantnormals, wanttangents); } } @@ -4949,7 +5003,8 @@ void R_RenderView(void) r_frame++; // used only by R_GetCurrentTexture rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity - R_AnimCache_NewFrame(); + R_AnimCache_ClearCache(); + R_FrameData_NewFrame(); if (r_refdef.view.isoverlay) { @@ -5101,6 +5156,7 @@ void R_RenderScene(void) } R_AnimCache_CacheVisibleEntities(); + R_PrepareRTLights(); if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth) {