From 7c93727b5efc0ada18820d4c6224b00e5b2d619a Mon Sep 17 00:00:00 2001 From: Flyinghead Date: Tue, 26 Jun 2018 14:24:45 +0200 Subject: [PATCH] Improve modifier volume parsing and drawing logic. Parse modifier volumes similarily to other polys (first, count, params). Draw all triangles in one shot and use quad to sum up instead of redrawing entire strip. Use OR operation for open volumes/quads (Soulcalibur). --- core/hw/pvr/ta_ctx.h | 7 +- core/hw/pvr/ta_vtx.cpp | 40 +++++++---- core/rend/gles/gldraw.cpp | 141 ++++++++++++++------------------------ core/rend/gles/gles.h | 2 + 4 files changed, 84 insertions(+), 106 deletions(-) diff --git a/core/hw/pvr/ta_ctx.h b/core/hw/pvr/ta_ctx.h index 703ba0721..5dc6f499d 100644 --- a/core/hw/pvr/ta_ctx.h +++ b/core/hw/pvr/ta_ctx.h @@ -37,10 +37,11 @@ struct PolyParam //float zMin,zMax; }; -struct ModParam +struct ModifierVolumeParam { - u32 first; //entry index , holds vertex/pos data + u32 first; u32 count; + ISP_Modvol isp; }; struct ModTriangle @@ -117,7 +118,7 @@ struct rend_context List verts; List idx; List modtrig; - List global_param_mvo; + List global_param_mvo; List global_param_op; List global_param_pt; diff --git a/core/hw/pvr/ta_vtx.cpp b/core/hw/pvr/ta_vtx.cpp index ce67dd956..360aaad73 100644 --- a/core/hw/pvr/ta_vtx.cpp +++ b/core/hw/pvr/ta_vtx.cpp @@ -768,12 +768,9 @@ public: { CurrentPP=&nullPP; CurrentPPlist=0; - if (ListType==ListType_Opaque_Modifier_Volume) - { - ISP_Modvol p; - p.id=vdrc.modtrig.used(); - *vdrc.global_param_mvo.Append()=p; - } + + if (ListType == ListType_Opaque_Modifier_Volume) + EndModVol(); } /* @@ -1368,17 +1365,34 @@ public: #endif } - //ModVolumes + // Modifier Volumes Vertex handlers + + static void EndModVol() + { + List *list = NULL; + if (CurrentList == ListType_Opaque_Modifier_Volume) + list = &vdrc.global_param_mvo; + else + return; + if (list->used() > 0) + { + ModifierVolumeParam *p = &(list->head()[list->used() - 1]); + p->count = vdrc.modtrig.used() - p->first; + } + } - //Mod Volume Vertex handlers static void StartModVol(TA_ModVolParam* param) { - if (CurrentList!=ListType_Opaque_Modifier_Volume) + EndModVol(); + + ModifierVolumeParam *p = NULL; + if (CurrentList == ListType_Opaque_Modifier_Volume) + p = vdrc.global_param_mvo.Append(); + else return; - ISP_Modvol* p=vdrc.global_param_mvo.Append(); - p->full=param->isp.full; - p->VolumeLast=param->pcw.Volume; - p->id=vdrc.modtrig.used(); + p->isp.full = param->isp.full; + p->isp.VolumeLast = param->pcw.Volume != 0; + p->first = vdrc.modtrig.used(); } __forceinline static void AppendModVolVertexA(TA_ModVolA* mvv) diff --git a/core/rend/gles/gldraw.cpp b/core/rend/gles/gldraw.cpp index 646d37966..191dd395c 100644 --- a/core/rend/gles/gldraw.cpp +++ b/core/rend/gles/gldraw.cpp @@ -812,35 +812,46 @@ void DrawSorted(bool multipass) 10 -> 00 11 -> 01 */ -void SetMVS_Mode(u32 mv_mode,ISP_Modvol ispc) +void SetMVS_Mode(ModifierVolumeMode mv_mode, ISP_Modvol ispc) { - if (mv_mode==0) //normal trigs + if (mv_mode == Xor) { - //set states + // set states glcache.Enable(GL_DEPTH_TEST); - //write only bit 1 + // write only bit 1 glcache.StencilMask(2); - //no stencil testing - glcache.StencilFunc(GL_ALWAYS,0,2); - //count the number of pixels in front of the Z buffer (xor zpass) - glcache.StencilOp(GL_KEEP,GL_KEEP,GL_INVERT); + // no stencil testing + glcache.StencilFunc(GL_ALWAYS, 0, 2); + // count the number of pixels in front of the Z buffer (xor zpass) + glcache.StencilOp(GL_KEEP, GL_KEEP, GL_INVERT); - //Cull mode needs to be set + // Cull mode needs to be set + SetCull(ispc.CullMode); + } + else if (mv_mode == Or) + { + // set states + glcache.Enable(GL_DEPTH_TEST); + // write only bit 1 + glcache.StencilMask(2); + // no stencil testing + glcache.StencilFunc(GL_ALWAYS, 2, 2); + // Or'ing of all triangles + glcache.StencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + + // Cull mode needs to be set SetCull(ispc.CullMode); } else { - //1 (last in) or 2 (last out) - //each triangle forms the last of a volume + // Inclusion or Exclusion volume - //common states - - //no depth test + // no depth test glcache.Disable(GL_DEPTH_TEST); - //write bits 1:0 + // write bits 1:0 glcache.StencilMask(3); - if (mv_mode==1) + if (mv_mode == Inclusion) { // Inclusion volume //res : old : final @@ -849,9 +860,9 @@ void SetMVS_Mode(u32 mv_mode,ISP_Modvol ispc) //1 : 0 : 01 //1 : 1 : 01 - //if (1<=st) st=1; else st=0; + // if (1<=st) st=1; else st=0; glcache.StencilFunc(GL_LEQUAL,1,3); - glcache.StencilOp(GL_ZERO,GL_ZERO,GL_REPLACE); + glcache.StencilOp(GL_ZERO, GL_ZERO, GL_REPLACE); } else { @@ -869,7 +880,7 @@ void SetMVS_Mode(u32 mv_mode,ISP_Modvol ispc) // if (1 == st) st = 1; else st = 0; glcache.StencilFunc(GL_EQUAL, 1, 3); - glcache.StencilOp(GL_ZERO, GL_ZERO, GL_REPLACE); + glcache.StencilOp(GL_ZERO, GL_ZERO, GL_KEEP); } } } @@ -939,85 +950,35 @@ void DrawModVols(int first, int count) } else { - /* - mode : - normal trig : flip - last *in* : flip, merge*in* &clear from last merge - last *out* : flip, merge*out* &clear from last merge - */ + //Full emulation - /* + glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); - Do not write to color - Do not write to depth + ModifierVolumeParam* params = &pvrrc.global_param_mvo.head()[first]; - read from stencil bits 1:0 - write to stencil bits 1:0 - */ - - glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE); - - if (0) + for (u32 cmv = 0; cmv < count; cmv++) { - //simple single level stencil - glcache.Enable(GL_STENCIL_TEST); - glcache.StencilFunc(GL_ALWAYS,0x1,0x1); - glcache.StencilOp(GL_KEEP,GL_KEEP,GL_INVERT); - glcache.StencilMask(0x1); - SetCull(0); - glDrawArrays(GL_TRIANGLES, first, count * 3); - } - else if (true) - { - //Full emulation - //the *out* mode is buggy + ModifierVolumeParam& param = params[cmv]; - u32 mod_base=0; //cur start triangle - u32 mod_last=0; //last merge + if (param.count == 0) + continue; - u32 cmv_count = count - 1; - ISP_Modvol* params = &pvrrc.global_param_mvo.head()[first]; + u32 mv_mode = param.isp.DepthMode; - //ISP_Modvol - for (u32 cmv=0;cmv 0) + SetMVS_Mode(Or, param.isp); // OR'ing (open volume or quad) + else + SetMVS_Mode(Xor, param.isp); // XOR'ing (closed volume) + glDrawArrays(GL_TRIANGLES, param.first * 3, param.count * 3); + + if (mv_mode == 1 || mv_mode == 2) { - - ISP_Modvol ispc=params[cmv]; - mod_base=ispc.id; - u32 sz=params[cmv+1].id-mod_base; - if (sz == 0) - continue; - - u32 mv_mode = ispc.DepthMode; - - - if (mv_mode==0) //normal trigs - { - SetMVS_Mode(0,ispc); - //Render em (counts intersections) - //verifyc(dev->DrawPrimitiveUP(D3DPT_TRIANGLELIST,sz,pvrrc.modtrig.data+mod_base,3*4)); - glDrawArrays(GL_TRIANGLES,mod_base*3,sz*3); - } - else if (mv_mode<3) - { - while(sz) - { - //merge and clear all the prev. stencil bits - - //Count Intersections (last poly) - SetMVS_Mode(0,ispc); - glDrawArrays(GL_TRIANGLES,mod_base*3,3); - - //Sum the area - SetMVS_Mode(mv_mode,ispc); - glDrawArrays(GL_TRIANGLES,mod_last*3,(mod_base-mod_last+1)*3); - - //update pointers - mod_last=mod_base+1; - sz--; - mod_base++; - } - } + // Sum the area + SetMVS_Mode(mv_mode == 1 ? Inclusion : Exclusion, param.isp); + // Use the background poly as a quad to do the sum up + SetupMainVBO(); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + SetupModvolVBO(); } } //disable culling diff --git a/core/rend/gles/gles.h b/core/rend/gles/gles.h index 0cbe8761e..68cd9d711 100755 --- a/core/rend/gles/gles.h +++ b/core/rend/gles/gles.h @@ -126,3 +126,5 @@ int GetProgramID(u32 cp_AlphaTest, u32 pp_ClipTestMode, bool CompilePipelineShader(PipelineShader* s); #define TEXTURE_LOAD_ERROR 0 GLuint loadPNG(const string& subpath, int &width, int &height); + +enum ModifierVolumeMode { Xor, Or, Inclusion, Exclusion, ModeCount };