From: havoc Date: Sun, 9 Mar 2003 16:42:54 +0000 (+0000) Subject: GL_NV_vertex_array_range support added, but disabled by default because for some... X-Git-Tag: xonotic-v0.1.0preview~6729 X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=commitdiff_plain;h=0567db0111a0c7d8979222cf9979af6e28a95401 GL_NV_vertex_array_range support added, but disabled by default because for some reason it's halving my framerate rather than making it faster git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@2819 d7cf8633-e32d-0410-b094-e92efae38249 --- diff --git a/gl_backend.c b/gl_backend.c index d41570e5..8e0b2214 100644 --- a/gl_backend.c +++ b/gl_backend.c @@ -2,9 +2,13 @@ #include "quakedef.h" #include "image.h" -cvar_t gl_mesh_maxverts = {0, "gl_mesh_maxverts", "1024"}; +cvar_t gl_mesh_maxverts = {0, "gl_mesh_maxverts", "21760"}; cvar_t gl_mesh_floatcolors = {0, "gl_mesh_floatcolors", "1"}; cvar_t gl_mesh_drawrangeelements = {0, "gl_mesh_drawrangeelements", "1"}; +cvar_t gl_mesh_vertex_array_range = {0, "gl_mesh_vertex_array_range", "0"}; +cvar_t gl_mesh_vertex_array_range_readfrequency = {0, "gl_mesh_vertex_array_range_readfrequency", "0.3"}; +cvar_t gl_mesh_vertex_array_range_writefrequency = {0, "gl_mesh_vertex_array_range_writefrequency", "1"}; +cvar_t gl_mesh_vertex_array_range_priority = {0, "gl_mesh_vertex_array_range_priority", "0.7"}; cvar_t gl_delayfinish = {CVAR_SAVE, "gl_delayfinish", "0"}; cvar_t r_render = {0, "r_render", "1"}; @@ -76,6 +80,10 @@ GLfloat *varray_vertex, *varray_buf_vertex; GLfloat *varray_color, *varray_buf_color; GLfloat *varray_texcoord[MAX_TEXTUREUNITS], *varray_buf_texcoord[MAX_TEXTUREUNITS]; int mesh_maxverts; +int mesh_var; +float mesh_var_readfrequency; +float mesh_var_writefrequency; +float mesh_var_priority; int varray_offset = 0, varray_offsetnext = 0; GLuint *varray_buf_elements; int mesh_maxelements = 3072; @@ -121,11 +129,34 @@ void GL_Backend_FreeElementArray(void) varray_buf_elements = NULL; } +void GL_Backend_CheckCvars(void) +{ + // 21760 is (65536 / 3) rounded off to a multiple of 128 + if (gl_mesh_maxverts.integer < 1024) + Cvar_SetValueQuick(&gl_mesh_maxverts, 1024); + if (gl_mesh_maxverts.integer > 21760) + Cvar_SetValueQuick(&gl_mesh_maxverts, 21760); + if (gl_mesh_vertex_array_range.integer && !gl_support_var) + Cvar_SetValueQuick(&gl_mesh_vertex_array_range, 0); + if (gl_mesh_vertex_array_range_readfrequency.value < 0) + Cvar_SetValueQuick(&gl_mesh_vertex_array_range_readfrequency, 0); + if (gl_mesh_vertex_array_range_readfrequency.value > 1) + Cvar_SetValueQuick(&gl_mesh_vertex_array_range_readfrequency, 1); + if (gl_mesh_vertex_array_range_writefrequency.value < 0) + Cvar_SetValueQuick(&gl_mesh_vertex_array_range_writefrequency, 0); + if (gl_mesh_vertex_array_range_writefrequency.value > 1) + Cvar_SetValueQuick(&gl_mesh_vertex_array_range_writefrequency, 1); + if (gl_mesh_vertex_array_range_priority.value < 0) + Cvar_SetValueQuick(&gl_mesh_vertex_array_range_priority, 0); + if (gl_mesh_vertex_array_range_priority.value > 1) + Cvar_SetValueQuick(&gl_mesh_vertex_array_range_priority, 1); +} + int polygonelements[768]; void GL_Backend_AllocArrays(void) { - int i; + int i, size; if (!gl_backend_mempool) { @@ -138,53 +169,75 @@ void GL_Backend_AllocArrays(void) varray_buf_texcoord[i] = NULL; } + mesh_maxverts = gl_mesh_maxverts.integer; + mesh_var = gl_mesh_vertex_array_range.integer; + mesh_var_readfrequency = gl_mesh_vertex_array_range_readfrequency.value; + mesh_var_writefrequency = gl_mesh_vertex_array_range_writefrequency.value; + mesh_var_priority = gl_mesh_vertex_array_range_priority.value; + if (varray_buf_vertex) - Mem_Free(varray_buf_vertex); + VID_FreeVertexArrays(varray_buf_vertex); varray_buf_vertex = NULL; - if (varray_buf_color) - Mem_Free(varray_buf_color); varray_buf_color = NULL; - if (varray_buf_bcolor) - Mem_Free(varray_buf_bcolor); varray_buf_bcolor = NULL; for (i = 0;i < MAX_TEXTUREUNITS;i++) - { - if (varray_buf_texcoord[i]) - Mem_Free(varray_buf_texcoord[i]); varray_buf_texcoord[i] = NULL; - } - varray_buf_vertex = Mem_Alloc(gl_backend_mempool, mesh_maxverts * sizeof(GLfloat[4])); - varray_buf_color = Mem_Alloc(gl_backend_mempool, mesh_maxverts * sizeof(GLfloat[4])); - varray_buf_bcolor = Mem_Alloc(gl_backend_mempool, mesh_maxverts * sizeof(GLubyte[4])); + size = mesh_maxverts * (sizeof(GLfloat[4]) + sizeof(GLfloat[4]) + sizeof(GLfloat[4]) * backendunits + sizeof(GLubyte[4])); + varray_buf_vertex = VID_AllocVertexArrays(gl_backend_mempool, size, gl_mesh_vertex_array_range.integer, gl_mesh_vertex_array_range_readfrequency.value, gl_mesh_vertex_array_range_writefrequency.value, gl_mesh_vertex_array_range_priority.value); + varray_buf_color = varray_buf_vertex + 4 * mesh_maxverts; for (i = 0;i < backendunits;i++) - varray_buf_texcoord[i] = Mem_Alloc(gl_backend_mempool, mesh_maxverts * sizeof(GLfloat[4])); + varray_buf_texcoord[i] = varray_buf_vertex + (i + 2) * 4 * mesh_maxverts; for (;i < MAX_TEXTUREUNITS;i++) varray_buf_texcoord[i] = NULL; + varray_buf_bcolor = (GLubyte *)(varray_buf_vertex + (backendunits + 2) * 4 * mesh_maxverts); GL_Backend_AllocElementsArray(); + + if (gl_support_var) + { + CHECKGLERROR + qglVertexArrayRangeNV(size, varray_buf_vertex); + CHECKGLERROR + qglEnableClientState(GL_VERTEX_ARRAY_RANGE_NV); + CHECKGLERROR + } } void GL_Backend_FreeArrays(void) { int i; - Mem_FreePool(&gl_backend_mempool); + if (gl_support_var) + { + CHECKGLERROR + qglDisableClientState(GL_VERTEX_ARRAY_RANGE_NV); + CHECKGLERROR + } + + if (varray_buf_vertex) + VID_FreeVertexArrays(varray_buf_vertex); varray_buf_vertex = NULL; varray_buf_color = NULL; varray_buf_bcolor = NULL; for (i = 0;i < MAX_TEXTUREUNITS;i++) varray_buf_texcoord[i] = NULL; + Mem_FreePool(&gl_backend_mempool); + varray_buf_elements = NULL; } static void gl_backend_start(void) { + GL_Backend_CheckCvars(); + Con_Printf("OpenGL Backend started with gl_mesh_maxverts %i\n", gl_mesh_maxverts.integer); if (qglDrawRangeElements != NULL) { + CHECKGLERROR qglGetIntegerv(GL_MAX_ELEMENTS_VERTICES, &gl_maxdrawrangeelementsvertices); + CHECKGLERROR qglGetIntegerv(GL_MAX_ELEMENTS_INDICES, &gl_maxdrawrangeelementsindices); CHECKGLERROR Con_Printf("glDrawRangeElements detected (max vertices %i, max indices %i)\n", gl_maxdrawrangeelementsvertices, gl_maxdrawrangeelementsindices); @@ -212,15 +265,6 @@ static void gl_backend_shutdown(void) GL_Backend_FreeArrays(); } -void GL_Backend_CheckCvars(void) -{ - // 21760 is (65536 / 3) rounded off to a multiple of 128 - if (gl_mesh_maxverts.integer < 1024) - Cvar_SetValueQuick(&gl_mesh_maxverts, 1024); - if (gl_mesh_maxverts.integer > 21760) - Cvar_SetValueQuick(&gl_mesh_maxverts, 21760); -} - void GL_Backend_ResizeArrays(int numvertices) { Cvar_SetValueQuick(&gl_mesh_maxverts, numvertices); @@ -255,7 +299,10 @@ void gl_backend_init(void) Cvar_RegisterVariable(&gl_mesh_maxverts); Cvar_RegisterVariable(&gl_mesh_floatcolors); Cvar_RegisterVariable(&gl_mesh_drawrangeelements); - GL_Backend_CheckCvars(); + Cvar_RegisterVariable(&gl_mesh_vertex_array_range); + Cvar_RegisterVariable(&gl_mesh_vertex_array_range_readfrequency); + Cvar_RegisterVariable(&gl_mesh_vertex_array_range_writefrequency); + Cvar_RegisterVariable(&gl_mesh_vertex_array_range_priority); R_RegisterModule("GL_Backend", gl_backend_start, gl_backend_shutdown, gl_backend_newmap); } @@ -530,10 +577,22 @@ void R_Mesh_Start(void) CHECKGLERROR GL_Backend_CheckCvars(); - if (mesh_maxverts != gl_mesh_maxverts.integer) + if (mesh_maxverts != gl_mesh_maxverts.integer + || mesh_var != gl_mesh_vertex_array_range.integer + || mesh_var_readfrequency != gl_mesh_vertex_array_range_readfrequency.value + || mesh_var_writefrequency != gl_mesh_vertex_array_range_writefrequency.value + || mesh_var_priority != gl_mesh_vertex_array_range_priority.value) GL_Backend_ResizeArrays(gl_mesh_maxverts.integer); GL_Backend_ResetState(); + + if (mesh_var) + { + CHECKGLERROR + qglFlushVertexArrayRangeNV(); + CHECKGLERROR + } + varray_offset = 0; } int gl_backend_rebindtextures; @@ -601,10 +660,7 @@ void R_Mesh_GetSpace(int numverts) varray_offset = varray_offsetnext; if (varray_offset + numverts > mesh_maxverts) - { - //flush stuff here varray_offset = 0; - } if (numverts > mesh_maxverts) { BACKENDACTIVECHECK @@ -613,8 +669,16 @@ void R_Mesh_GetSpace(int numverts) varray_offset = 0; } + if (varray_offset == 0 && mesh_var) + { + CHECKGLERROR + qglFlushVertexArrayRangeNV(); + CHECKGLERROR + } + // for debugging - //varray_offset = rand() % (mesh_maxverts - numverts); + //if (!mesh_var) + // varray_offset = rand() % (mesh_maxverts - numverts); varray_vertex = varray_buf_vertex + varray_offset * 4; varray_color = varray_buf_color + varray_offset * 4; @@ -677,6 +741,13 @@ void R_Mesh_Finish(void) { int i; BACKENDACTIVECHECK + if (mesh_var) + { + CHECKGLERROR + qglFlushVertexArrayRangeNV(); + CHECKGLERROR + } + varray_offset = 0; for (i = backendunits - 1;i >= 0;i--) { diff --git a/glquake.h b/glquake.h index 4ad25be5..58068e6b 100644 --- a/glquake.h +++ b/glquake.h @@ -354,6 +354,22 @@ extern int gl_support_clamptoedge; #define GL_CLAMP_TO_EDGE 0x812F #endif +//GL_NV_vertex_array_range +extern GLvoid *(GLAPIENTRY *qglAllocateMemoryNV)(GLsizei size, GLfloat readFrequency, GLfloat writeFrequency, GLfloat priority); +extern GLvoid (GLAPIENTRY *qglFreeMemoryNV)(GLvoid *pointer); +extern GLvoid (GLAPIENTRY *qglVertexArrayRangeNV)(GLsizei length, GLvoid *pointer); +extern GLvoid (GLAPIENTRY *qglFlushVertexArrayRangeNV)(GLvoid); +#define GL_VERTEX_ARRAY_RANGE_NV 0x851D +#define GL_VERTEX_ARRAY_RANGE_LENGTH_NV 0x851E +#define GL_MAX_VERTEX_ARRAY_RANGE_ELEMENT_NV 0x8520 +#define GL_VERTEX_ARRAY_RANGE_POINTER_NV 0x8521 +extern int gl_support_var; + +//GL_NV_vertex_array_range2 +#define GL_VERTEX_ARRAY_RANGE_WITHOUT_FLUSH_NV 0x8533 +extern int gl_support_var2; + + extern void (GLAPIENTRY *qglScissor)(GLint x, GLint y, GLsizei width, GLsizei height); extern void (GLAPIENTRY *qglClearColor)(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); diff --git a/vid.h b/vid.h index 8ea82bbc..602238cb 100644 --- a/vid.h +++ b/vid.h @@ -100,6 +100,11 @@ void GL_CloseLibrary(void); void *GL_GetProcAddress(const char *name); int GL_CheckExtension(const char *name, const dllfunction_t *funcs, const char *disableparm, int silent); +// this attempts to use vendor extensions to allocate faster vertex memory if +// the fast parameter is true, if unsuccessful it uses Mem_Alloc instead +void *VID_AllocVertexArrays(mempool_t *pool, int size, int fast, float readfrequency, float writefrequency, float priority); +void VID_FreeVertexArrays(void *pointer); + void VID_Shared_Init(void); void GL_Init (void); diff --git a/vid_glx.c b/vid_glx.c index 14c09ca4..800b46c1 100644 --- a/vid_glx.c +++ b/vid_glx.c @@ -61,7 +61,7 @@ static dllfunction_t getprocaddressfuncs[] = //GLX_SGI_video_sync GLint (GLAPIENTRY *qglXGetVideoSyncSGI)(GLuint *count); -GLint (GLAPIENTRY *qglXWaitVideoSyncSGI)(int divisor, int remainder, unsigned int *count); +GLint (GLAPIENTRY *qglXWaitVideoSyncSGI)(GLint divisor, GLint remainder, GLuint *count); static dllfunction_t videosyncfuncs[] = { @@ -863,3 +863,4 @@ void *GL_GetProcAddress(const char *name) p = (void *) dlsym(prjobj, name); return p; } + diff --git a/vid_shared.c b/vid_shared.c index 37f2444b..8f337264 100644 --- a/vid_shared.c +++ b/vid_shared.c @@ -26,6 +26,10 @@ int gl_texturecubemap = false; int gl_dot3arb = false; // GL_SGIS_texture_edge_clamp int gl_support_clamptoedge = false; +// GL_NV_vertex_array_range +int gl_support_var = false; +// GL_NV_vertex_array_range2 +int gl_support_var2 = false; // LordHavoc: if window is hidden, don't update screen int vid_hidden = true; @@ -98,6 +102,11 @@ void (GLAPIENTRY *qglClientActiveTexture) (GLenum); void (GLAPIENTRY *qglLockArraysEXT) (GLint first, GLint count); void (GLAPIENTRY *qglUnlockArraysEXT) (void); +//GL_NV_vertex_array_range +GLvoid *(GLAPIENTRY *qglAllocateMemoryNV)(GLsizei size, GLfloat readFrequency, GLfloat writeFrequency, GLfloat priority); +GLvoid (GLAPIENTRY *qglFreeMemoryNV)(GLvoid *pointer); +GLvoid (GLAPIENTRY *qglVertexArrayRangeNV)(GLsizei length, GLvoid *pointer); +GLvoid (GLAPIENTRY *qglFlushVertexArrayRangeNV)(GLvoid); // general GL functions @@ -374,6 +383,25 @@ static dllfunction_t texture3dextfuncs[] = {NULL, NULL} }; +static dllfunction_t glxvarfuncs[] = +{ + {"glXAllocateMemoryNV", (void **) &qglAllocateMemoryNV}, + {"glXFreeMemoryNV", (void **) &qglFreeMemoryNV}, + {"glVertexArrayRangeNV", (void **) &qglVertexArrayRangeNV}, + {"glFlushVertexArrayRangeNV", (void **) &qglFlushVertexArrayRangeNV}, + {NULL, NULL} +}; + +static dllfunction_t wglvarfuncs[] = +{ + {"wglAllocateMemoryNV", (void **) &qglAllocateMemoryNV}, + {"wglFreeMemoryNV", (void **) &qglFreeMemoryNV}, + {"glVertexArrayRangeNV", (void **) &qglVertexArrayRangeNV}, + {"glFlushVertexArrayRangeNV", (void **) &qglFlushVertexArrayRangeNV}, + {NULL, NULL} +}; + + void VID_CheckExtensions(void) { gl_stencil = vid_stencil.integer; @@ -382,6 +410,8 @@ void VID_CheckExtensions(void) gl_supportslockarrays = false; gl_textureunits = 1; gl_support_clamptoedge = false; + gl_support_var = false; + gl_support_var2 = false; if (!GL_CheckExtension("OpenGL 1.1.0", opengl110funcs, NULL, false)) Sys_Error("OpenGL 1.1.0 functions not found\n"); @@ -410,11 +440,50 @@ void VID_CheckExtensions(void) gl_supportslockarrays = GL_CheckExtension("GL_EXT_compiled_vertex_array", compiledvertexarrayfuncs, "-nocva", false); gl_support_clamptoedge = GL_CheckExtension("GL_EXT_texture_edge_clamp", NULL, "-noedgeclamp", false) || GL_CheckExtension("GL_SGIS_texture_edge_clamp", NULL, "-noedgeclamp", false); + if (!strcmp(gl_platform, "GLX")) + gl_support_var = GL_CheckExtension("GL_NV_vertex_array_range", glxvarfuncs, "-novar", false); + else if (!strcmp(gl_platform, "WGL")) + gl_support_var = GL_CheckExtension("GL_NV_vertex_array_range", wglvarfuncs, "-novar", false); + if (gl_support_var) + gl_support_var2 = GL_CheckExtension("GL_NV_vertex_array_range2", NULL, "-novar2", false); + // we don't care if it's an extension or not, they are identical functions, so keep it simple in the rendering code if (qglDrawRangeElements == NULL) qglDrawRangeElements = qglDrawRangeElementsEXT; } +int vid_vertexarrays_are_var = false; +void *VID_AllocVertexArrays(mempool_t *pool, int size, int fast, float readfrequency, float writefrequency, float priority) +{ + void *m; + vid_vertexarrays_are_var = false; + if (fast && qglAllocateMemoryNV) + { + CHECKGLERROR + m = qglAllocateMemoryNV(size, readfrequency, writefrequency, priority); + CHECKGLERROR + if (m) + { + vid_vertexarrays_are_var = true; + return m; + } + } + return Mem_Alloc(pool, size); +} + +void VID_FreeVertexArrays(void *pointer) +{ + if (vid_vertexarrays_are_var) + { + CHECKGLERROR + qglFreeMemoryNV(pointer); + CHECKGLERROR + } + else + Mem_Free(pointer); + vid_vertexarrays_are_var = false; +} + void Force_CenterView_f (void) { cl.viewangles[PITCH] = 0; @@ -717,3 +786,4 @@ void VID_Close(void) VID_CloseSystems(); VID_Shutdown(); } +