X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=meshqueue.c;h=a5510be722631f7b7d196e555dff081c8027ad1f;hp=69593bd809a3196a63c2734b91f2750362142645;hb=f5352fd59b6c6bc5589229670655f77f9e6069ed;hpb=123d759d4e8793229127f44661afe7c1960fae99 diff --git a/meshqueue.c b/meshqueue.c index 69593bd8..a5510be7 100644 --- a/meshqueue.c +++ b/meshqueue.c @@ -2,14 +2,10 @@ #include "quakedef.h" #include "meshqueue.h" -cvar_t r_meshqueue_entries = {CVAR_SAVE, "r_meshqueue_entries", "16", "maximum number of meshes to batch together and sort before issuing render calls (unused)"}; -cvar_t r_meshqueue_immediaterender = {0, "r_meshqueue_immediaterender", "0", "immediately render non-transparent meshes rather than batching"}; -cvar_t r_meshqueue_sort = {0, "r_meshqueue_sort", "0", "whether to sort meshes in a batch before issuing calls"}; - typedef struct meshqueue_s { struct meshqueue_s *next; - void (*callback)(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight); + 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; @@ -19,106 +15,38 @@ meshqueue_t; float mqt_viewplanedist; float mqt_viewmaxdist; -meshqueue_t *mq_array, *mqt_array, *mq_listhead; -int mq_count, mqt_count; -int mq_total, mqt_total; +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); - - 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->ent, mq->surfacenumber, mq->rtlight); - mq_count = 0; - mq_listhead = NULL; -} - -static void R_MeshQueue_EnlargeTransparentArray(int newtotal) -{ - meshqueue_t *newarray; - newarray = (meshqueue_t *)Mem_Alloc(cls.mempool, 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 entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight), const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight) -{ - meshqueue_t *mq, **mqnext; - if (r_meshqueue_immediaterender.integer) - { - callback(ent, surfacenumber, rtlight); - return; - } - if (mq_count >= mq_total) - R_MeshQueue_Render(); - mq = &mq_array[mq_count++]; - mq->callback = callback; - mq->ent = ent; - mq->surfacenumber = surfacenumber; - mq->rtlight = rtlight; - - if (r_meshqueue_sort.integer) + if (mqt_count >= mqt_total || !mqt_array) { - // 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->ent == (*mqnext)->ent) - { - if (mq->surfacenumber == (*mqnext)->surfacenumber) - { - if (mq->rtlight <= (*mqnext)->rtlight) - break; - } - else if (mq->surfacenumber < (*mqnext)->surfacenumber) - break; - } - else if (mq->ent < (*mqnext)->ent) - 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 entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight), const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight) -{ - meshqueue_t *mq; - if (mqt_count >= mqt_total) - R_MeshQueue_EnlargeTransparentArray(mqt_total + 100); mq = &mqt_array[mqt_count++]; mq->callback = callback; mq->ent = ent; mq->surfacenumber = surfacenumber; mq->rtlight = rtlight; - mq->dist = DotProduct(center, r_viewforward) - mqt_viewplanedist; + mq->dist = DotProduct(center, r_refdef.view.forward) - mqt_viewplanedist; mq->next = NULL; mqt_viewmaxdist = max(mqt_viewmaxdist, mq->dist); } @@ -127,11 +55,14 @@ 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(); + static meshqueue_t *hash[4096], **hashpointer[4096]; + int batchsurfaceindex[256]; if (!mqt_count) return; memset(hash, 0, sizeof(hash)); @@ -148,49 +79,30 @@ void R_MeshQueue_RenderTransparent(void) *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->ent, mqt->surfacenumber, mqt->rtlight); - 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 = (meshqueue_t *)Mem_Alloc(cls.mempool, 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 = (meshqueue_t *)Mem_Alloc(cls.mempool, 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); - mqt_viewmaxdist = 0; -} - -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(); - } } -