From 5664bfb9b646f27b7d8111b555c25eb6847014a2 Mon Sep 17 00:00:00 2001 From: Flyinghead Date: Thu, 13 Dec 2018 10:57:51 +0100 Subject: [PATCH] pvr: use u32 for vertex indices to avoid overflow Fixes alpilot glitches --- core/hw/pvr/ta_ctx.h | 8 ++++++-- core/hw/pvr/ta_vtx.cpp | 4 ++-- core/rend/gl4/gldraw.cpp | 2 +- core/rend/gles/gldraw.cpp | 32 ++++++++++++++++---------------- core/rend/soft/softrend.cpp | 4 ++-- 5 files changed, 27 insertions(+), 23 deletions(-) diff --git a/core/hw/pvr/ta_ctx.h b/core/hw/pvr/ta_ctx.h index 4aaa76fad..96e704406 100644 --- a/core/hw/pvr/ta_ctx.h +++ b/core/hw/pvr/ta_ctx.h @@ -131,7 +131,7 @@ struct rend_context u32 fog_clamp_max; List verts; - List idx; + List idx; List modtrig; List global_param_mvo; List global_param_mvo_tr; @@ -160,6 +160,8 @@ struct rend_context } }; +#define TA_DATA_SIZE (8 * 1024 * 1024) + //vertex lists struct TA_context { @@ -199,7 +201,7 @@ struct TA_context void Alloc() { - tad.Reset((u8*)OS_aligned_malloc(32, 8*1024*1024)); + tad.Reset((u8*)OS_aligned_malloc(32, TA_DATA_SIZE)); rend.verts.InitBytes(4 * 1024 * 1024, &rend.Overrun, "verts"); //up to 4 mb of vtx data/frame = ~ 96k vtx/frame rend.idx.Init(120 * 1024, &rend.Overrun, "idx"); //up to 120K indexes ( idx have stripification overhead ) @@ -218,6 +220,7 @@ struct TA_context void Reset() { + verify(tad.End() - tad.thd_root < TA_DATA_SIZE); tad.Clear(); rend_inuse.Lock(); rend.Clear(); @@ -227,6 +230,7 @@ struct TA_context void Free() { + verify(tad.End() - tad.thd_root < TA_DATA_SIZE); OS_aligned_free(tad.thd_root); rend.verts.Free(); rend.idx.Free(); diff --git a/core/hw/pvr/ta_vtx.cpp b/core/hw/pvr/ta_vtx.cpp index ee31d8108..bd5bfc5bb 100644 --- a/core/hw/pvr/ta_vtx.cpp +++ b/core/hw/pvr/ta_vtx.cpp @@ -1304,7 +1304,7 @@ public: __forceinline static void AppendSpriteVertexA(TA_Sprite1A* sv) { - u16* idx=vdrc.idx.Append(6); + u32* idx = vdrc.idx.Append(6); u32 vbase=vdrc.verts.used(); idx[0]=vbase+0; @@ -1496,7 +1496,7 @@ public: //allocate storage for BG poly vd_rc.global_param_op.Append(); - u16* idx=vd_rc.idx.Append(4); + u32* idx = vd_rc.idx.Append(4); int vbase=vd_rc.verts.used(); idx[0]=vbase+0; diff --git a/core/rend/gl4/gldraw.cpp b/core/rend/gl4/gldraw.cpp index cbf516bfb..bc3adde5e 100644 --- a/core/rend/gl4/gldraw.cpp +++ b/core/rend/gl4/gldraw.cpp @@ -285,7 +285,7 @@ static void DrawList(const List& gply, int first, int count, int pass } gl4ShaderUniforms.poly_number = params - gply.head(); SetGPState(params, pass); - glDrawElements(GL_TRIANGLE_STRIP, params->count, GL_UNSIGNED_SHORT, (GLvoid*)(2*params->first)); glCheck(); + glDrawElements(GL_TRIANGLE_STRIP, params->count, GL_UNSIGNED_INT, (GLvoid*)(sizeof(u32) * params->first)); glCheck(); } params++; diff --git a/core/rend/gles/gldraw.cpp b/core/rend/gles/gldraw.cpp index 016878a39..2e7d18f7c 100644 --- a/core/rend/gles/gldraw.cpp +++ b/core/rend/gles/gldraw.cpp @@ -275,7 +275,7 @@ void DrawList(const List& gply, int first, int count) if (params->count>2) //this actually happens for some games. No idea why .. { SetGPState(params); - glDrawElements(GL_TRIANGLE_STRIP, params->count, GL_UNSIGNED_SHORT, (GLvoid*)(2*params->first)); glCheck(); + glDrawElements(GL_TRIANGLE_STRIP, params->count, GL_UNSIGNED_INT, (GLvoid*)(sizeof(u32) * params->first)); glCheck(); } params++; @@ -296,7 +296,7 @@ void SortPParams(int first, int count) return; Vertex* vtx_base=pvrrc.verts.head(); - u16* idx_base=pvrrc.idx.head(); + u32* idx_base = pvrrc.idx.head(); PolyParam* pp = &pvrrc.global_param_tr.head()[first]; PolyParam* pp_end = pp + count; @@ -309,7 +309,7 @@ void SortPParams(int first, int count) } else { - u16* idx=idx_base+pp->first; + u32* idx = idx_base + pp->first; Vertex* vtx=vtx_base+idx[0]; Vertex* vtx_end=vtx_base + idx[pp->count-1]+1; @@ -334,7 +334,7 @@ Vertex* vtx_sort_base; struct IndexTrig { - u16 id[3]; + u32 id[3]; u16 pid; f32 z; }; @@ -343,8 +343,8 @@ struct IndexTrig struct SortTrigDrawParam { PolyParam* ppid; - u16 first; - u16 count; + u32 first; + u32 count; }; float min3(float v0,float v1,float v2) @@ -358,7 +358,7 @@ float max3(float v0,float v1,float v2) } -float minZ(Vertex* v,u16* mod) +float minZ(Vertex* v, u32* mod) { return min(min(v[mod[0]].z,v[mod[1]].z),v[mod[2]].z); } @@ -471,7 +471,7 @@ bool PP_EQ(PolyParam* pp0, PolyParam* pp1) static vector pidx_sort; -void fill_id(u16* d, Vertex* v0, Vertex* v1, Vertex* v2, Vertex* vb) +void fill_id(u32* d, Vertex* v0, Vertex* v1, Vertex* v2, Vertex* vb) { d[0]=v0-vb; d[1]=v1-vb; @@ -488,7 +488,7 @@ void GenSorted(int first, int count) return; Vertex* vtx_base=pvrrc.verts.head(); - u16* idx_base=pvrrc.idx.head(); + u32* idx_base = pvrrc.idx.head(); PolyParam* pp_base = &pvrrc.global_param_tr.head()[first]; PolyParam* pp = pp_base; @@ -524,7 +524,7 @@ void GenSorted(int first, int count) if (pp->count>2) { - u16* idx=idx_base+pp->first; + u32* idx = idx_base + pp->first; Vertex* vtx=vtx_base+idx[0]; Vertex* vtx_end=vtx_base + idx[pp->count-1]-1; @@ -694,7 +694,7 @@ void GenSorted(int first, int count) #endif //re-assemble them into drawing commands - static vector vidx_sort; + static vector vidx_sort; vidx_sort.resize(aused*3); @@ -703,7 +703,7 @@ void GenSorted(int first, int count) for (u32 i=0; i2) //this actually happens for some games. No idea why .. { SetGPState(params); - glDrawElements(GL_TRIANGLES, pidx_sort[p].count, GL_UNSIGNED_SHORT, (GLvoid*)(2*pidx_sort[p].first)); glCheck(); + glDrawElements(GL_TRIANGLES, pidx_sort[p].count, GL_UNSIGNED_INT, (GLvoid*)(sizeof(u32) * pidx_sort[p].first)); glCheck(); #if 0 //Verify restriping -- only valid if no sort @@ -806,7 +806,7 @@ void DrawSorted(bool multipass) SetCull(params->isp.CullMode ^ gcflip); - glDrawElements(GL_TRIANGLES, pidx_sort[p].count, GL_UNSIGNED_SHORT, (GLvoid*)(2 * pidx_sort[p].first)); + glDrawElements(GL_TRIANGLES, pidx_sort[p].count, GL_UNSIGNED_INT, (GLvoid*)(sizeof(u32) * pidx_sort[p].first)); } } glcache.StencilMask(0xFF); diff --git a/core/rend/soft/softrend.cpp b/core/rend/soft/softrend.cpp index 8125218db..741f38d19 100644 --- a/core/rend/soft/softrend.cpp +++ b/core/rend/soft/softrend.cpp @@ -837,7 +837,7 @@ struct softrend : Renderer void RenderParamList(List* param_list, RECT* area) { Vertex* verts = pvrrc.verts.head(); - u16* idx = pvrrc.idx.head(); + u32* idx = pvrrc.idx.head(); PolyParam* params = param_list->head(); int param_count = param_list->used(); @@ -846,7 +846,7 @@ struct softrend : Renderer { int vertex_count = params[i].count - 2; - u16* poly_idx = &idx[params[i].first]; + u32* poly_idx = &idx[params[i].first]; for (int v = 0; v < vertex_count; v++) { ////