diff --git a/core/hw/pvr/helper_classes.h b/core/hw/pvr/helper_classes.h index 2df7f690..b279d23a 100644 --- a/core/hw/pvr/helper_classes.h +++ b/core/hw/pvr/helper_classes.h @@ -41,11 +41,19 @@ struct List } __forceinline - T* LastPtr(int n=1) const + T* LastPtr(int n = 1) const { return daty-n; } + T* PopLast() + { + daty--; + avail++; + + return daty; + } + T* head() const { return daty-used(); } void InitBytes(int maxbytes,bool* ovrn, const char *name) @@ -78,4 +86,7 @@ struct List Clear(); free(daty); } + + T* begin() const { return head(); } + T* end() const { return LastPtr(0); } }; diff --git a/core/hw/pvr/ta_vtx.cpp b/core/hw/pvr/ta_vtx.cpp index 364b9f44..2a11f4f5 100644 --- a/core/hw/pvr/ta_vtx.cpp +++ b/core/hw/pvr/ta_vtx.cpp @@ -3,7 +3,7 @@ Parsing of the TA stream and generation of vertex data ! */ - +#include #include "ta.h" #include "ta_ctx.h" #include "pvr_mem.h" @@ -34,9 +34,9 @@ extern int screen_height; #define TA_V64H //cache state vars -u32 tileclip_val = 0; +static u32 tileclip_val = 0; -u8 f32_su8_tbl[65536]; +static u8 f32_su8_tbl[65536]; #define float_to_satu8(val) f32_su8_tbl[((u32&)val)>>16] /* @@ -67,12 +67,12 @@ static PolyParam* CurrentPP; static List* CurrentPPlist; //TA state vars -DECL_ALIGN(4) u8 FaceBaseColor[4]; -DECL_ALIGN(4) u8 FaceOffsColor[4]; -DECL_ALIGN(4) u8 FaceBaseColor1[4]; -DECL_ALIGN(4) u8 FaceOffsColor1[4]; -DECL_ALIGN(4) u32 SFaceBaseColor; -DECL_ALIGN(4) u32 SFaceOffsColor; +DECL_ALIGN(4) static u8 FaceBaseColor[4]; +DECL_ALIGN(4) static u8 FaceOffsColor[4]; +DECL_ALIGN(4) static u8 FaceBaseColor1[4]; +DECL_ALIGN(4) static u8 FaceOffsColor1[4]; +DECL_ALIGN(4) static u32 SFaceBaseColor; +DECL_ALIGN(4) static u32 SFaceOffsColor; //splitter function lookup extern u32 ta_type_lut[256]; @@ -728,6 +728,8 @@ public: __forceinline static void EndList(u32 ListType) { + if (CurrentPP != NULL && CurrentPP->count == 0) + CurrentPPlist->PopLast(); CurrentPP = NULL; CurrentPPlist = NULL; @@ -740,36 +742,29 @@ public: template static void glob_param_bdc_(T* pp) { - if (CurrentPP == NULL - || CurrentPP->pcw.full != pp->pcw.full - || CurrentPP->tcw.full != pp->tcw.full - || CurrentPP->tsp.full != pp->tsp.full - || CurrentPP->isp.full != pp->isp.full) + PolyParam* d_pp = CurrentPP; + if (d_pp == NULL || d_pp->count != 0) { - PolyParam* d_pp=CurrentPP; - if (d_pp == NULL || d_pp->count != 0) - { - d_pp=CurrentPPlist->Append(); - CurrentPP=d_pp; - } - d_pp->first=vdrc.idx.used(); - d_pp->count=0; - - d_pp->isp=pp->isp; - d_pp->tsp=pp->tsp; - d_pp->tcw=pp->tcw; - d_pp->pcw=pp->pcw; - d_pp->tileclip=tileclip_val; - - d_pp->texid = -1; - - if (d_pp->pcw.Texture) { - d_pp->texid = renderer->GetTexture(d_pp->tsp,d_pp->tcw); - } - d_pp->tsp1.full = -1; - d_pp->tcw1.full = -1; - d_pp->texid1 = -1; + d_pp = CurrentPPlist->Append(); + CurrentPP = d_pp; } + d_pp->first = vdrc.verts.used(); + d_pp->count = 0; + + d_pp->isp = pp->isp; + d_pp->tsp = pp->tsp; + d_pp->tcw = pp->tcw; + d_pp->pcw = pp->pcw; + d_pp->tileclip = tileclip_val; + + d_pp->texid = -1; + + if (d_pp->pcw.Texture) + d_pp->texid = renderer->GetTexture(d_pp->tsp,d_pp->tcw); + + d_pp->tsp1.full = -1; + d_pp->tcw1.full = -1; + d_pp->texid1 = -1; } #define glob_param_bdc(pp) glob_param_bdc_( (TA_PolyParam0*)pp) @@ -864,26 +859,16 @@ public: __forceinline static void EndPolyStrip() { - CurrentPP->count=vdrc.idx.used() - CurrentPP->first; + CurrentPP->count = vdrc.verts.used() - CurrentPP->first; - if (CurrentPPlist==&vdrc.global_param_tr) - { - PolyParam* d_pp =CurrentPPlist->Append(); - *d_pp=*CurrentPP; - CurrentPP=d_pp; - d_pp->first=vdrc.idx.used(); - d_pp->count=0; - } - else - { - int vbase=vdrc.verts.used(); - - *vdrc.idx.Append()=vbase-1; - *vdrc.idx.Append()=vbase; - - if (CurrentPP->count&1) - *vdrc.idx.Append()=vbase; - } + if (CurrentPP->count > 0) + { + PolyParam* d_pp = CurrentPPlist->Append(); + *d_pp = *CurrentPP; + CurrentPP = d_pp; + d_pp->first = vdrc.verts.used(); + d_pp->count = 0; + } } @@ -900,7 +885,6 @@ public: static Vertex* vert_cvt_base_(T* vtx) { f32 invW=vtx->xyz[2]; - *vdrc.idx.Append()=vdrc.verts.used(); Vertex* cv=vdrc.verts.Append(); cv->x=vtx->xyz[0]; cv->y=vtx->xyz[1]; @@ -1227,7 +1211,7 @@ public: CurrentPP=d_pp; } - d_pp->first=vdrc.idx.used(); + d_pp->first = vdrc.verts.used(); d_pp->count=0; d_pp->isp=spr->isp; d_pp->tsp=spr->tsp; @@ -1269,17 +1253,7 @@ public: __forceinline static void AppendSpriteVertexA(TA_Sprite1A* sv) { - u32* idx = vdrc.idx.Append(6); - u32 vbase=vdrc.verts.used(); - - idx[0]=vbase+0; - idx[1]=vbase+1; - idx[2]=vbase+2; - idx[3]=vbase+3; - idx[4]=vbase+3; - idx[5]=vbase+4; - - CurrentPP->count=vdrc.idx.used()-CurrentPP->first-2; + CurrentPP->count = 4; Vertex* cv = vdrc.verts.Append(4); @@ -1372,24 +1346,12 @@ public: update_fz(cv[0].z); - /* - if (CurrentPP->count) - { - Vertex* vert=vert_reappend; - vert[-1].x=vert[0].x; - vert[-1].y=vert[0].y; - vert[-1].z=vert[0].z; - CurrentPP->count+=2; - }*/ #if STRIPS_AS_PPARAMS - if (CurrentPPlist==&vdrc.global_param_tr) - { - PolyParam* d_pp =CurrentPPlist->Append(); - *d_pp=*CurrentPP; - CurrentPP=d_pp; - d_pp->first=vdrc.idx.used(); - d_pp->count=0; - } + PolyParam* d_pp = CurrentPPlist->Append(); + *d_pp = *CurrentPP; + CurrentPP = d_pp; + d_pp->first = vdrc.verts.used(); + d_pp->count = 0; #endif } @@ -1406,8 +1368,11 @@ public: return; if (list->used() > 0) { - ModifierVolumeParam *p = &(list->head()[list->used() - 1]); + ModifierVolumeParam *p = list->LastPtr(); p->count = vdrc.modtrig.used() - p->first; + if (p->count == 0) + list->PopLast(); + } } @@ -1463,13 +1428,6 @@ public: //allocate storage for BG poly vd_rc.global_param_op.Append(); - u32* idx = vd_rc.idx.Append(4); - int vbase=vd_rc.verts.used(); - - idx[0]=vbase+0; - idx[1]=vbase+1; - idx[2]=vbase+2; - idx[3]=vbase+3; vd_rc.verts.Append(4); } }; @@ -1481,6 +1439,99 @@ FifoSplitter<0> TAFifo0; int ta_parse_cnt = 0; +// +// Check if a vertex has huge x,y,z values or negative z +// +static bool is_vertex_inf(const Vertex& vtx) +{ + return std::isnan(vtx.x) || fabsf(vtx.x) > 3.4e37f + || std::isnan(vtx.y) || fabsf(vtx.y) > 3.4e37f + || std::isnan(vtx.z) || vtx.z < 0.f || vtx.z > 3.4e37f; +} + +// +// Create the vertex index, eliminating invalid vertices and merging strips when possible. +// +static void make_index(const List *polys, int first, int end, bool merge, rend_context* ctx) +{ + const u32 *indices = ctx->idx.head(); + const Vertex *vertices = ctx->verts.head(); + + PolyParam *last_poly = nullptr; + const PolyParam *end_poly = &polys->head()[end]; + for (PolyParam *poly = &polys->head()[first]; poly != end_poly; poly++) + { + int first_index; + bool dupe_next_vtx = false; + if (merge + && last_poly != nullptr + && poly->pcw.full == last_poly->pcw.full + && poly->tcw.full == last_poly->tcw.full + && poly->tsp.full == last_poly->tsp.full + && poly->isp.full == last_poly->isp.full + // FIXME tcw1, tsp1, tileclip? + ) + { + const u32 last_vtx = indices[last_poly->first + last_poly->count - 1]; + *ctx->idx.Append() = last_vtx; + dupe_next_vtx = true; + first_index = last_poly->first; + } + else + { + last_poly = poly; + first_index = ctx->idx.used(); + } + int last_good_vtx = -1; + for (int i = 0; i < poly->count; i++) + { + const Vertex& vtx = vertices[poly->first + i]; + if (is_vertex_inf(vtx)) + { + while (i < poly->count - 1) + { + const Vertex& next_vtx = vertices[poly->first + i + 1]; + if (!is_vertex_inf(next_vtx)) + { + // repeat last and next vertices to link strips + if (last_good_vtx >= 0) + { + verify(!dupe_next_vtx); + *ctx->idx.Append() = last_good_vtx; + dupe_next_vtx = true; + } + break; + } + i++; + } + } + else + { + last_good_vtx = poly->first + i; + if (dupe_next_vtx) + { + *ctx->idx.Append() = last_good_vtx; + dupe_next_vtx = false; + } + const u32 count = ctx->idx.used() - first_index; + if ((i ^ count) & 1) + *ctx->idx.Append() = last_good_vtx; + *ctx->idx.Append() = last_good_vtx; + } + } + if (last_poly == poly) + { + poly->first = first_index; + poly->count = ctx->idx.used() - first_index; + } + else + { + last_poly->count = ctx->idx.used() - last_poly->first; + poly->count = 0; + } + } +} + static void fix_texture_bleeding(const List *list) { for (const PolyParam *pp = list->head(); pp <= list->LastPtr(); pp++) @@ -1529,9 +1580,9 @@ static void fix_texture_bleeding(const List *list) */ bool ta_parse_vdrc(TA_context* ctx) { - bool rv=false; + bool rv=false; vd_ctx = ctx; - vd_rc = vd_ctx->rend; + vd_rc = vd_ctx->rend; ta_parse_cnt++; @@ -1539,12 +1590,15 @@ bool ta_parse_vdrc(TA_context* ctx) { TAFifo0.vdec_init(); - for (int pass = 0; pass <= ctx->tad.render_pass_count; pass++) - { - ctx->MarkRend(pass); + int op_poly_count = 0; + int pt_poly_count = 0; + int tr_poly_count = 0; - vd_rc.proc_start = ctx->rend.proc_start; - vd_rc.proc_end = ctx->rend.proc_end; + for (int pass = 0; pass <= ctx->tad.render_pass_count; pass++) + { + ctx->MarkRend(pass); + vd_rc.proc_start = ctx->rend.proc_start; + vd_rc.proc_end = ctx->rend.proc_end; Ta_Dma* ta_data=(Ta_Dma*)vd_rc.proc_start; Ta_Dma* ta_data_end=((Ta_Dma*)vd_rc.proc_end)-1; @@ -1556,13 +1610,22 @@ bool ta_parse_vdrc(TA_context* ctx) RenderPass *render_pass = vd_rc.render_passes.Append(); render_pass->op_count = vd_rc.global_param_op.used(); + make_index(&vd_rc.global_param_op, op_poly_count, + render_pass->op_count, true, &vd_rc); + op_poly_count = render_pass->op_count; render_pass->mvo_count = vd_rc.global_param_mvo.used(); render_pass->pt_count = vd_rc.global_param_pt.used(); + make_index(&vd_rc.global_param_pt, pt_poly_count, + render_pass->pt_count, true, &vd_rc); + pt_poly_count = render_pass->pt_count; render_pass->tr_count = vd_rc.global_param_tr.used(); + make_index(&vd_rc.global_param_tr, tr_poly_count, + render_pass->tr_count, false, &vd_rc); + tr_poly_count = render_pass->tr_count; render_pass->mvo_tr_count = vd_rc.global_param_mvo_tr.used(); render_pass->autosort = UsingAutoSort(pass); render_pass->z_clear = ClearZBeforePass(pass); - } + } if (screen_height > 480) { diff --git a/core/rend/gl4/gles.cpp b/core/rend/gl4/gles.cpp index 2b8e59e6..ba54649a 100644 --- a/core/rend/gl4/gles.cpp +++ b/core/rend/gl4/gles.cpp @@ -51,11 +51,6 @@ void main() vtx_offs1 = in_offs1; vtx_uv1 = in_uv1; vec4 vpos=in_pos; - if (vpos.z < 0.0 || vpos.z > 3.4e37) - { - gl_Position = vec4(0.0, 0.0, 1.0, 1.0 / vpos.z); - return; - } vpos.w = extra_depth_scale / vpos.z; vpos.z = vpos.w; diff --git a/core/rend/gles/gles.cpp b/core/rend/gles/gles.cpp index 31b1ff42..9ca0338c 100644 --- a/core/rend/gles/gles.cpp +++ b/core/rend/gles/gles.cpp @@ -85,11 +85,6 @@ void main() vtx_offs=in_offs; vtx_uv=in_uv; highp vec4 vpos = in_pos; - if (vpos.z < 0.0 || vpos.z > 3.4e37) - { - gl_Position = vec4(0.0, 0.0, 1.0, 1.0 / vpos.z); - return; - } vpos.w = extra_depth_scale / vpos.z; #if TARGET_GL != GLES2 diff --git a/core/rend/sorter.cpp b/core/rend/sorter.cpp index 17d53fa9..1f99d5b5 100644 --- a/core/rend/sorter.cpp +++ b/core/rend/sorter.cpp @@ -24,6 +24,7 @@ struct IndexTrig f32 z; }; +#if 0 static float min3(float v0, float v1, float v2) { return min(min(v0,v1),v2); @@ -33,6 +34,7 @@ static float max3(float v0, float v1, float v2) { return max(max(v0,v1),v2); } +#endif static float minZ(const Vertex *v, const u32 *mod) { @@ -194,10 +196,10 @@ static bool PP_EQ(const PolyParam *pp0, const PolyParam *pp1) } static void fill_id(u32 *d, const Vertex *v0, const Vertex *v1, const Vertex *v2, const Vertex *vb) -{ - d[0]=v0-vb; - d[1]=v1-vb; - d[2]=v2-vb; +{ + d[0] = (u32)(v0 - vb); + d[1] = (u32)(v1 - vb); + d[2] = (u32)(v2 - vb); } void GenSorted(int first, int count, vector& pidx_sort, vector& vidx_sort) @@ -216,12 +218,11 @@ void GenSorted(int first, int count, vector& pidx_sort, vecto const PolyParam *pp = pp_base; const PolyParam *pp_end = pp + count; - const Vertex *vtx_arr = vtx_base + idx_base[pp->first]; vtx_sort_base=vtx_base; static u32 vtx_cnt; - int vtx_count=idx_base[pp_end[-1].first+pp_end[-1].count-1]-idx_base[pp->first]; + int vtx_count = pvrrc.verts.used() - idx_base[pp->first]; if (vtx_count>vtx_cnt) vtx_cnt=vtx_count; @@ -242,32 +243,29 @@ void GenSorted(int first, int count, vector& pidx_sort, vecto while(pp!=pp_end) { - u32 ppid=(pp-pp_base); + u32 ppid = (u32)(pp - pp_base); if (pp->count>2) { const u32 *idx = idx_base + pp->first; + u32 flip = 0; - const Vertex *vtx = vtx_base + idx[0]; - const Vertex *vtx_end = vtx_base + idx[pp->count - 1] - 1; - u32 flip=0; - while(vtx!=vtx_end) + for (int i = 0; i < pp->count - 2; i++) { - const Vertex *v0, *v1, *v2, *v3, *v4, *v5; - + const Vertex *v0, *v1; if (flip) { - v0=&vtx[1]; - v1=&vtx[0]; - v2=&vtx[2]; + v0 = vtx_base + idx[i + 1]; + v1 = vtx_base + idx[i]; } else { - v0=&vtx[0]; - v1=&vtx[1]; - v2=&vtx[2]; + v0 = vtx_base + idx[i]; + v1 = vtx_base + idx[i + 1]; } + const Vertex *v2 = vtx_base + idx[i + 2]; #if 0 + const Vertex *v3, *v4, *v5; if (settings.pvr.subdivide_transp) { u32 tess_x=(max3(v0->x,v1->x,v2->x)-min3(v0->x,v1->x,v2->x))/32; @@ -350,8 +348,6 @@ void GenSorted(int first, int count, vector& pidx_sort, vecto } flip ^= 1; - - vtx++; } } pp++; diff --git a/core/rend/vulkan/oit/oit_shaders.cpp b/core/rend/vulkan/oit/oit_shaders.cpp index d2357d54..12a26b70 100644 --- a/core/rend/vulkan/oit/oit_shaders.cpp +++ b/core/rend/vulkan/oit/oit_shaders.cpp @@ -60,11 +60,6 @@ void main() vtx_offs1 = vec4(in_offs1) / 255.0; vtx_uv1 = in_uv1; vec4 vpos = in_pos; - if (vpos.z < 0.0 || vpos.z > 3.4e37) - { - gl_Position = vec4(0.0, 0.0, 1.0, 1.0 / vpos.z); - return; - } vpos = uniformBuffer.normal_matrix * vpos; vpos.w = 1.0 / vpos.z; vpos.z = vpos.w; diff --git a/core/rend/vulkan/shaders.cpp b/core/rend/vulkan/shaders.cpp index b6dced2a..b5bb53bf 100644 --- a/core/rend/vulkan/shaders.cpp +++ b/core/rend/vulkan/shaders.cpp @@ -52,11 +52,6 @@ void main() vtx_offs = vec4(in_offs) / 255.0; vtx_uv = in_uv; vec4 vpos = in_pos; - if (vpos.z < 0.0 || vpos.z > 3.4e37) - { - gl_Position = vec4(0.0, 0.0, 1.0, 1.0 / vpos.z); - return; - } vpos = uniformBuffer.normal_matrix * vpos; vpos.w = 1.0 / vpos.z; vpos.z = vpos.w;