X-Git-Url: https://de.git.xonotic.org/?a=blobdiff_plain;f=meshqueue.c;h=7d5a9c3aacf4d35ea80c0b1713604886d68a8b1e;hb=31c60f86f584447beac6b654e54587229f2c9496;hp=24744f310895746d0276110450086ab4c8c776f3;hpb=805f263eee6c6b3504849972f1581d33cde86a04;p=xonotic%2Fdarkplaces.git diff --git a/meshqueue.c b/meshqueue.c index 24744f31..7d5a9c3a 100644 --- a/meshqueue.c +++ b/meshqueue.c @@ -2,185 +2,107 @@ #include "quakedef.h" #include "meshqueue.h" -cvar_t r_meshqueue_entries = {CVAR_SAVE, "r_meshqueue_entries", "16"}; -cvar_t r_meshqueue_immediaterender = {0, "r_meshqueue_immediaterender", "0"}; -cvar_t r_meshqueue_sort = {0, "r_meshqueue_sort", "0"}; - typedef struct meshqueue_s { struct meshqueue_s *next; - void (*callback)(const void *data1, int data2); - const void *data1; - int data2; + void (*callback)(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfaceindices); + const entity_render_t *ent; + int surfacenumber; + const rtlight_t *rtlight; float dist; } meshqueue_t; float mqt_viewplanedist; -meshqueue_t *mq_array, *mqt_array, *mq_listhead; -int mq_count, mqt_count; -int mq_total, mqt_total; - -mempool_t *meshqueuemempool; +float mqt_viewmaxdist; +meshqueue_t *mqt_array; +int mqt_count; +int mqt_total; -void R_MeshQueue_Init(void) +void R_MeshQueue_BeginScene(void) { - Cvar_RegisterVariable(&r_meshqueue_entries); - Cvar_RegisterVariable(&r_meshqueue_immediaterender); - Cvar_RegisterVariable(&r_meshqueue_sort); - - meshqueuemempool = Mem_AllocPool("R_MeshQueue", 0, NULL); - mq_total = 0; - mqt_total = 0; - mq_array = NULL; - mqt_array = NULL; + mqt_count = 0; + mqt_viewplanedist = DotProduct(r_refdef.view.origin, r_refdef.view.forward); + mqt_viewmaxdist = 0; } -void R_MeshQueue_Render(void) +void R_MeshQueue_AddTransparent(const vec3_t center, void (*callback)(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist), const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight) { meshqueue_t *mq; - if (!mq_count) - return; - for (mq = mq_listhead;mq;mq = mq->next) - mq->callback(mq->data1, mq->data2); - mq_count = 0; - mq_listhead = NULL; -} - -static void R_MeshQueue_EnlargeTransparentArray(int newtotal) -{ - meshqueue_t *newarray; - newarray = Mem_Alloc(meshqueuemempool, newtotal * sizeof(meshqueue_t)); - if (mqt_array) - { - memcpy(newarray, mqt_array, mqt_total * sizeof(meshqueue_t)); - Mem_Free(mqt_array); - } - mqt_array = newarray; - mqt_total = newtotal; -} - -void R_MeshQueue_Add(void (*callback)(const void *data1, int data2), const void *data1, int data2) -{ - meshqueue_t *mq, **mqnext; - if (r_meshqueue_immediaterender.integer) + if (mqt_count >= mqt_total || !mqt_array) { - callback(data1, data2); - return; - } - if (mq_count >= mq_total) - R_MeshQueue_Render(); - mq = &mq_array[mq_count++]; - mq->callback = callback; - mq->data1 = data1; - mq->data2 = data2; - - if (r_meshqueue_sort.integer) - { - // bubble-insert sort into meshqueue - for(mqnext = &mq_listhead;*mqnext;mqnext = &(*mqnext)->next) + int newtotal = max(1024, mqt_total * 2); + meshqueue_t *newarray = (meshqueue_t *)Mem_Alloc(cls.permanentmempool, newtotal * sizeof(meshqueue_t)); + if (mqt_array) { - if (mq->callback == (*mqnext)->callback) - { - if (mq->data1 == (*mqnext)->data1) - { - if (mq->data2 <= (*mqnext)->data2) - break; - } - else if (mq->data1 < (*mqnext)->data1) - break; - } - else if (mq->callback < (*mqnext)->callback) - break; + memcpy(newarray, mqt_array, mqt_total * sizeof(meshqueue_t)); + Mem_Free(mqt_array); } + mqt_array = newarray; + mqt_total = newtotal; } - else - { - // maintain the order - for(mqnext = &mq_listhead;*mqnext;mqnext = &(*mqnext)->next); - } - mq->next = *mqnext; - *mqnext = mq; -} - -void R_MeshQueue_AddTransparent(const vec3_t center, void (*callback)(const void *data1, int data2), const void *data1, int data2) -{ - meshqueue_t *mq; - if (mqt_count >= mqt_total) - R_MeshQueue_EnlargeTransparentArray(mqt_total + 100); mq = &mqt_array[mqt_count++]; mq->callback = callback; - mq->data1 = data1; - mq->data2 = data2; - mq->dist = DotProduct(center, r_viewforward) - mqt_viewplanedist; + mq->ent = ent; + mq->surfacenumber = surfacenumber; + mq->rtlight = rtlight; + mq->dist = DotProduct(center, r_refdef.view.forward) - mqt_viewplanedist; mq->next = NULL; + mqt_viewmaxdist = max(mqt_viewmaxdist, mq->dist); } void R_MeshQueue_RenderTransparent(void) { int i; int hashdist; + int batchnumsurfaces; + float distscale; + const entity_render_t *ent; + const rtlight_t *rtlight; + void (*callback)(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfaceindices); meshqueue_t *mqt; meshqueue_t *hash[4096], **hashpointer[4096]; - if (mq_count) - R_MeshQueue_Render(); + int batchsurfaceindex[256]; if (!mqt_count) return; memset(hash, 0, sizeof(hash)); for (i = 0;i < 4096;i++) hashpointer[i] = &hash[i]; + distscale = 4095.0f / max(mqt_viewmaxdist, 4095); for (i = 0, mqt = mqt_array;i < mqt_count;i++, mqt++) { // generate index - hashdist = (int) (mqt->dist); + hashdist = (int) (mqt->dist * distscale); hashdist = bound(0, hashdist, 4095); // link to tail of hash chain (to preserve render order) mqt->next = NULL; *hashpointer[hashdist] = mqt; hashpointer[hashdist] = &mqt->next; } + callback = NULL; + ent = NULL; + rtlight = NULL; + batchnumsurfaces = 0; for (i = 4095;i >= 0;i--) + { if (hash[i]) + { for (mqt = hash[i];mqt;mqt = mqt->next) - mqt->callback(mqt->data1, mqt->data2); - mqt_count = 0; -} - -void R_MeshQueue_BeginScene(void) -{ - if (r_meshqueue_entries.integer < 1) - Cvar_SetValueQuick(&r_meshqueue_entries, 1); - if (r_meshqueue_entries.integer > 65536) - Cvar_SetValueQuick(&r_meshqueue_entries, 65536); - - if (mq_total != r_meshqueue_entries.integer || mq_array == NULL) - { - mq_total = r_meshqueue_entries.integer; - if (mq_array) - Mem_Free(mq_array); - mq_array = Mem_Alloc(meshqueuemempool, mq_total * sizeof(meshqueue_t)); + { + if (ent != mqt->ent || rtlight != mqt->rtlight || callback != mqt->callback || batchnumsurfaces >= 256) + { + if (batchnumsurfaces) + callback(ent, rtlight, batchnumsurfaces, batchsurfaceindex); + batchnumsurfaces = 0; + ent = mqt->ent; + rtlight = mqt->rtlight; + callback = mqt->callback; + } + batchsurfaceindex[batchnumsurfaces++] = mqt->surfacenumber; + } + } } - - if (mqt_array == NULL) - mqt_array = Mem_Alloc(meshqueuemempool, mqt_total * sizeof(meshqueue_t)); - - mq_count = 0; + if (batchnumsurfaces) + callback(ent, rtlight, batchnumsurfaces, batchsurfaceindex); mqt_count = 0; - mq_listhead = NULL; - mqt_viewplanedist = DotProduct(r_vieworigin, r_viewforward); } - -void R_MeshQueue_EndScene(void) -{ - if (mq_count) - { - Con_Printf("R_MeshQueue_EndScene: main mesh queue still has %i items left, flushing\n", mq_count); - R_MeshQueue_Render(); - } - if (mqt_count) - { - Con_Printf("R_MeshQueue_EndScene: transparent mesh queue still has %i items left, flushing\n", mqt_count); - R_MeshQueue_RenderTransparent(); - } -} -