From aca3bbc9a0a0e265355b8f3372c57c7a25bdcb40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 10 Dec 2023 11:58:47 +0100 Subject: [PATCH 1/2] DrawEngine: Remove the confusing MaxIndex accessor, replace with directly reading numDecodedVerts_ --- GPU/Common/DrawEngineCommon.cpp | 6 +++--- GPU/Common/DrawEngineCommon.h | 8 ++------ GPU/Common/SoftwareTransformCommon.cpp | 2 +- GPU/Common/SoftwareTransformCommon.h | 5 ++--- GPU/D3D11/DrawEngineD3D11.cpp | 12 +++++------- GPU/Directx9/DrawEngineDX9.cpp | 14 ++++++-------- GPU/GLES/DrawEngineGLES.cpp | 13 ++++++------- GPU/Vulkan/DrawEngineVulkan.cpp | 13 ++++++------- 8 files changed, 31 insertions(+), 42 deletions(-) diff --git a/GPU/Common/DrawEngineCommon.cpp b/GPU/Common/DrawEngineCommon.cpp index 978e2e7545a6..eec4070f51d3 100644 --- a/GPU/Common/DrawEngineCommon.cpp +++ b/GPU/Common/DrawEngineCommon.cpp @@ -958,12 +958,12 @@ void DrawEngineCommon::DecodeVerts(u8 *dest) { DeferredVerts &dv = drawVerts_[i]; int indexLowerBound = dv.indexLowerBound; - drawVertexOffsets_[i] = decodedVerts_ - indexLowerBound; + drawVertexOffsets_[i] = numDecodedVerts_ - indexLowerBound; int indexUpperBound = dv.indexUpperBound; // Decode the verts (and at the same time apply morphing/skinning). Simple. - dec_->DecodeVerts(dest + decodedVerts_ * stride, dv.verts, &dv.uvScale, indexLowerBound, indexUpperBound); - decodedVerts_ += indexUpperBound - indexLowerBound + 1; + dec_->DecodeVerts(dest + numDecodedVerts_ * stride, dv.verts, &dv.uvScale, indexLowerBound, indexUpperBound); + numDecodedVerts_ += indexUpperBound - indexLowerBound + 1; } decodeVertsCounter_ = i; } diff --git a/GPU/Common/DrawEngineCommon.h b/GPU/Common/DrawEngineCommon.h index 147a1178bd56..a91623af8c54 100644 --- a/GPU/Common/DrawEngineCommon.h +++ b/GPU/Common/DrawEngineCommon.h @@ -158,10 +158,6 @@ class DrawEngineCommon { void DecodeVerts(u8 *dest); void DecodeInds(); - int MaxIndex() const { - return decodedVerts_; - } - // Preprocessing for spline/bezier u32 NormalizeVertices(u8 *outPtr, u8 *bufPtr, const u8 *inPtr, int lowerBound, int upperBound, u32 vertType, int *vertexSize = nullptr); @@ -204,7 +200,7 @@ class DrawEngineCommon { gpuStats.numVertsSubmitted += vertexCountInDrawCalls_; indexGen.Reset(); - decodedVerts_ = 0; + numDecodedVerts_ = 0; numDrawVerts_ = 0; numDrawInds_ = 0; vertexCountInDrawCalls_ = 0; @@ -278,7 +274,7 @@ class DrawEngineCommon { // Vertex collector state IndexGenerator indexGen; - int decodedVerts_ = 0; + int numDecodedVerts_ = 0; GEPrimitiveType prevPrim_ = GE_PRIM_INVALID; // Shader blending state diff --git a/GPU/Common/SoftwareTransformCommon.cpp b/GPU/Common/SoftwareTransformCommon.cpp index 15ae074d1c60..95f4aa16fd46 100644 --- a/GPU/Common/SoftwareTransformCommon.cpp +++ b/GPU/Common/SoftwareTransformCommon.cpp @@ -171,7 +171,7 @@ void SoftwareTransform::SetProjMatrix(const float mtx[14], bool invertedX, bool projMatrix_.translateAndScale(trans, scale); } -void SoftwareTransform::Decode(int prim, u32 vertType, const DecVtxFormat &decVtxFormat, int maxIndex, SoftwareTransformResult *result) { +void SoftwareTransform::Transform(int prim, u32 vertType, const DecVtxFormat &decVtxFormat, int maxIndex, SoftwareTransformResult *result) { u8 *decoded = params_.decoded; TransformedVertex *transformed = params_.transformed; bool throughmode = (vertType & GE_VTYPE_THROUGH_MASK) != 0; diff --git a/GPU/Common/SoftwareTransformCommon.h b/GPU/Common/SoftwareTransformCommon.h index 480bd18e519e..47c79a82de32 100644 --- a/GPU/Common/SoftwareTransformCommon.h +++ b/GPU/Common/SoftwareTransformCommon.h @@ -62,11 +62,10 @@ struct SoftwareTransformParams { class SoftwareTransform { public: - SoftwareTransform(SoftwareTransformParams ¶ms) : params_(params) { - } + SoftwareTransform(SoftwareTransformParams ¶ms) : params_(params) {} void SetProjMatrix(const float mtx[14], bool invertedX, bool invertedY, const Lin::Vec3 &trans, const Lin::Vec3 &scale); - void Decode(int prim, u32 vertexType, const DecVtxFormat &decVtxFormat, int maxIndex, SoftwareTransformResult *result); + void Transform(int prim, u32 vertexType, const DecVtxFormat &decVtxFormat, int maxIndex, SoftwareTransformResult *result); void DetectOffsetTexture(int maxIndex); void BuildDrawingParams(int prim, int vertexCount, u32 vertType, u16 *&inds, int &maxIndex, SoftwareTransformResult *result); diff --git a/GPU/D3D11/DrawEngineD3D11.cpp b/GPU/D3D11/DrawEngineD3D11.cpp index 08c0ae6b6388..5bd6f5991895 100644 --- a/GPU/D3D11/DrawEngineD3D11.cpp +++ b/GPU/D3D11/DrawEngineD3D11.cpp @@ -292,7 +292,6 @@ void DrawEngineD3D11::DoFlush() { bool useElements = !indexGen.SeenOnlyPurePrims() || prim == GE_PRIM_TRIANGLE_FAN; int vertexCount = indexGen.VertexCount(); gpuStats.numUncachedVertsDrawn += vertexCount; - int maxIndex = MaxIndex(); if (!useElements && indexGen.PureCount()) { vertexCount = indexGen.PureCount(); } @@ -329,7 +328,7 @@ void DrawEngineD3D11::DoFlush() { if (!vb_) { // Push! UINT vOffset; - int vSize = (maxIndex + 1) * dec_->GetDecVtxFmt().stride; + int vSize = numDecodedVerts_ * dec_->GetDecVtxFmt().stride; uint8_t *vptr = pushVerts_->BeginPush(context_, &vOffset, vSize); memcpy(vptr, decoded_, vSize); pushVerts_->EndPush(context_); @@ -403,20 +402,19 @@ void DrawEngineD3D11::DoFlush() { UpdateCachedViewportState(vpAndScissor); } - int maxIndex = MaxIndex(); SoftwareTransform swTransform(params); const Lin::Vec3 trans(gstate_c.vpXOffset, -gstate_c.vpYOffset, gstate_c.vpZOffset * 0.5f + 0.5f); const Lin::Vec3 scale(gstate_c.vpWidthScale, -gstate_c.vpHeightScale, gstate_c.vpDepthScale * 0.5f); swTransform.SetProjMatrix(gstate.projMatrix, gstate_c.vpWidth < 0, gstate_c.vpHeight < 0, trans, scale); - swTransform.Decode(prim, dec_->VertexType(), dec_->GetDecVtxFmt(), maxIndex, &result); + swTransform.Transform(prim, dec_->VertexType(), dec_->GetDecVtxFmt(), numDecodedVerts_, &result); // Non-zero depth clears are unusual, but some drivers don't match drawn depth values to cleared values. // Games sometimes expect exact matches (see #12626, for example) for equal comparisons. if (result.action == SW_CLEAR && everUsedEqualDepth_ && gstate.isClearModeDepthMask() && result.depth > 0.0f && result.depth < 1.0f) result.action = SW_NOT_READY; if (result.action == SW_NOT_READY) { - swTransform.DetectOffsetTexture(maxIndex); + swTransform.DetectOffsetTexture(numDecodedVerts_); } if (textureNeedsApply) @@ -426,7 +424,7 @@ void DrawEngineD3D11::DoFlush() { ApplyDrawState(prim); if (result.action == SW_NOT_READY) - swTransform.BuildDrawingParams(prim, indexGen.VertexCount(), dec_->VertexType(), inds, maxIndex, &result); + swTransform.BuildDrawingParams(prim, indexGen.VertexCount(), dec_->VertexType(), inds, numDecodedVerts_, &result); if (result.setSafeSize) framebufferManager_->SetSafeSize(result.safeWidth, result.safeHeight); @@ -454,7 +452,7 @@ void DrawEngineD3D11::DoFlush() { UINT stride = sizeof(TransformedVertex); UINT vOffset = 0; - int vSize = maxIndex * stride; + int vSize = numDecodedVerts_ * stride; uint8_t *vptr = pushVerts_->BeginPush(context_, &vOffset, vSize); memcpy(vptr, result.drawBuffer, vSize); pushVerts_->EndPush(context_); diff --git a/GPU/Directx9/DrawEngineDX9.cpp b/GPU/Directx9/DrawEngineDX9.cpp index 506856556f6f..fd248da2d6d2 100644 --- a/GPU/Directx9/DrawEngineDX9.cpp +++ b/GPU/Directx9/DrawEngineDX9.cpp @@ -264,7 +264,6 @@ void DrawEngineDX9::DoFlush() { bool useElements = !indexGen.SeenOnlyPurePrims(); int vertexCount = indexGen.VertexCount(); gpuStats.numUncachedVertsDrawn += vertexCount; - int maxIndex = MaxIndex(); if (!useElements && indexGen.PureCount()) { vertexCount = indexGen.PureCount(); } @@ -293,7 +292,7 @@ void DrawEngineDX9::DoFlush() { device_->SetVertexDeclaration(pHardwareVertexDecl); if (vb_ == NULL) { if (useElements) { - device_->DrawIndexedPrimitiveUP(d3d_prim[prim], 0, maxIndex + 1, D3DPrimCount(d3d_prim[prim], vertexCount), decIndex_, D3DFMT_INDEX16, decoded_, dec_->GetDecVtxFmt().stride); + device_->DrawIndexedPrimitiveUP(d3d_prim[prim], 0, numDecodedVerts_, D3DPrimCount(d3d_prim[prim], vertexCount), decIndex_, D3DFMT_INDEX16, decoded_, dec_->GetDecVtxFmt().stride); } else { device_->DrawPrimitiveUP(d3d_prim[prim], D3DPrimCount(d3d_prim[prim], vertexCount), decoded_, dec_->GetDecVtxFmt().stride); } @@ -303,7 +302,7 @@ void DrawEngineDX9::DoFlush() { if (useElements) { device_->SetIndices(ib_); - device_->DrawIndexedPrimitive(d3d_prim[prim], 0, 0, maxIndex + 1, 0, D3DPrimCount(d3d_prim[prim], vertexCount)); + device_->DrawIndexedPrimitive(d3d_prim[prim], 0, 0, numDecodedVerts_, 0, D3DPrimCount(d3d_prim[prim], vertexCount)); } else { device_->DrawPrimitive(d3d_prim[prim], 0, D3DPrimCount(d3d_prim[prim], vertexCount)); } @@ -355,7 +354,6 @@ void DrawEngineDX9::DoFlush() { UpdateCachedViewportState(vpAndScissor); } - int maxIndex = MaxIndex(); SoftwareTransform swTransform(params); // Half pixel offset hack. @@ -366,13 +364,13 @@ void DrawEngineDX9::DoFlush() { const Lin::Vec3 scale(gstate_c.vpWidthScale, gstate_c.vpHeightScale, gstate_c.vpDepthScale * 0.5f); swTransform.SetProjMatrix(gstate.projMatrix, gstate_c.vpWidth < 0, gstate_c.vpHeight > 0, trans, scale); - swTransform.Decode(prim, dec_->VertexType(), dec_->GetDecVtxFmt(), maxIndex, &result); + swTransform.Transform(prim, dec_->VertexType(), dec_->GetDecVtxFmt(), numDecodedVerts_, &result); // Non-zero depth clears are unusual, but some drivers don't match drawn depth values to cleared values. // Games sometimes expect exact matches (see #12626, for example) for equal comparisons. if (result.action == SW_CLEAR && everUsedEqualDepth_ && gstate.isClearModeDepthMask() && result.depth > 0.0f && result.depth < 1.0f) result.action = SW_NOT_READY; if (result.action == SW_NOT_READY) { - swTransform.DetectOffsetTexture(maxIndex); + swTransform.DetectOffsetTexture(numDecodedVerts_); } if (textureNeedsApply) @@ -381,7 +379,7 @@ void DrawEngineDX9::DoFlush() { ApplyDrawState(prim); if (result.action == SW_NOT_READY) - swTransform.BuildDrawingParams(prim, indexGen.VertexCount(), dec_->VertexType(), inds, maxIndex, &result); + swTransform.BuildDrawingParams(prim, indexGen.VertexCount(), dec_->VertexType(), inds, numDecodedVerts_, &result); if (result.setSafeSize) framebufferManager_->SetSafeSize(result.safeWidth, result.safeHeight); @@ -401,7 +399,7 @@ void DrawEngineDX9::DoFlush() { device_->SetVertexDeclaration(transformedVertexDecl_); if (result.drawIndexed) { - device_->DrawIndexedPrimitiveUP(d3d_prim[prim], 0, maxIndex, D3DPrimCount(d3d_prim[prim], result.drawNumTrans), inds, D3DFMT_INDEX16, result.drawBuffer, sizeof(TransformedVertex)); + device_->DrawIndexedPrimitiveUP(d3d_prim[prim], 0, numDecodedVerts_, D3DPrimCount(d3d_prim[prim], result.drawNumTrans), inds, D3DFMT_INDEX16, result.drawBuffer, sizeof(TransformedVertex)); } else { device_->DrawPrimitiveUP(d3d_prim[prim], D3DPrimCount(d3d_prim[prim], result.drawNumTrans), result.drawBuffer, sizeof(TransformedVertex)); } diff --git a/GPU/GLES/DrawEngineGLES.cpp b/GPU/GLES/DrawEngineGLES.cpp index 4d6de3d202f2..26c01dcd0780 100644 --- a/GPU/GLES/DrawEngineGLES.cpp +++ b/GPU/GLES/DrawEngineGLES.cpp @@ -242,7 +242,7 @@ void DrawEngineGLES::DoFlush() { _dbg_assert_msg_(false, "Trying to DoFlush while not in a render pass. This is bad."); // can't goto bail here, skips too many variable initializations. So let's wipe the most important stuff. indexGen.Reset(); - decodedVerts_ = 0; + numDecodedVerts_ = 0; numDrawVerts_ = 0; numDrawInds_ = 0; vertexCountInDrawCalls_ = 0; @@ -274,7 +274,7 @@ void DrawEngineGLES::DoFlush() { if (decOptions_.applySkinInDecode && (lastVType_ & GE_VTYPE_WEIGHT_MASK)) { // If software skinning, we're predecoding into "decoded". So make sure we're done, then push that content. DecodeVerts(decoded_); - uint32_t size = decodedVerts_ * dec_->GetDecVtxFmt().stride; + uint32_t size = numDecodedVerts_ * dec_->GetDecVtxFmt().stride; u8 *dest = (u8 *)frameData.pushVertex->Allocate(size, 4, &vertexBuffer, &vertexBufferOffset); memcpy(dest, decoded_, size); } else { @@ -376,7 +376,6 @@ void DrawEngineGLES::DoFlush() { UpdateCachedViewportState(vpAndScissor_); } - int maxIndex = MaxIndex(); int vertexCount = indexGen.VertexCount(); // TODO: Split up into multiple draw calls for GLES 2.0 where you can't guarantee support for more than 0x10000 verts. @@ -395,13 +394,13 @@ void DrawEngineGLES::DoFlush() { const bool invertedY = gstate_c.vpHeight * (params.flippedY ? 1.0 : -1.0f) < 0; swTransform.SetProjMatrix(gstate.projMatrix, gstate_c.vpWidth < 0, invertedY, trans, scale); - swTransform.Decode(prim, dec_->VertexType(), dec_->GetDecVtxFmt(), maxIndex, &result); + swTransform.Transform(prim, dec_->VertexType(), dec_->GetDecVtxFmt(), numDecodedVerts_, &result); // Non-zero depth clears are unusual, but some drivers don't match drawn depth values to cleared values. // Games sometimes expect exact matches (see #12626, for example) for equal comparisons. if (result.action == SW_CLEAR && everUsedEqualDepth_ && gstate.isClearModeDepthMask() && result.depth > 0.0f && result.depth < 1.0f) result.action = SW_NOT_READY; if (result.action == SW_NOT_READY) - swTransform.DetectOffsetTexture(maxIndex); + swTransform.DetectOffsetTexture(numDecodedVerts_); if (textureNeedsApply) textureCache_->ApplyTexture(); @@ -410,7 +409,7 @@ void DrawEngineGLES::DoFlush() { ApplyDrawState(prim); if (result.action == SW_NOT_READY) - swTransform.BuildDrawingParams(prim, vertexCount, dec_->VertexType(), inds, maxIndex, &result); + swTransform.BuildDrawingParams(prim, vertexCount, dec_->VertexType(), inds, numDecodedVerts_, &result); if (result.setSafeSize) framebufferManager_->SetSafeSize(result.safeWidth, result.safeHeight); @@ -424,7 +423,7 @@ void DrawEngineGLES::DoFlush() { if (result.action == SW_DRAW_PRIMITIVES) { if (result.drawIndexed) { - vertexBufferOffset = (uint32_t)frameData.pushVertex->Push(result.drawBuffer, maxIndex * sizeof(TransformedVertex), 4, &vertexBuffer); + vertexBufferOffset = (uint32_t)frameData.pushVertex->Push(result.drawBuffer, numDecodedVerts_ * sizeof(TransformedVertex), 4, &vertexBuffer); indexBufferOffset = (uint32_t)frameData.pushIndex->Push(inds, sizeof(uint16_t) * result.drawNumTrans, 2, &indexBuffer); render_->DrawIndexed( softwareInputLayout_, vertexBuffer, vertexBufferOffset, indexBuffer, indexBufferOffset, diff --git a/GPU/Vulkan/DrawEngineVulkan.cpp b/GPU/Vulkan/DrawEngineVulkan.cpp index cd81b7caf32d..5149a37c41e3 100644 --- a/GPU/Vulkan/DrawEngineVulkan.cpp +++ b/GPU/Vulkan/DrawEngineVulkan.cpp @@ -248,7 +248,7 @@ void DrawEngineVulkan::DoFlush() { if (decOptions_.applySkinInDecode && (lastVType_ & GE_VTYPE_WEIGHT_MASK)) { // If software skinning, we're predecoding into "decoded". So make sure we're done, then push that content. DecodeVerts(decoded_); - VkDeviceSize size = decodedVerts_ * dec_->GetDecVtxFmt().stride; + VkDeviceSize size = numDecodedVerts_ * dec_->GetDecVtxFmt().stride; u8 *dest = (u8 *)pushVertex_->Allocate(size, 4, &vbuf, &vbOffset); memcpy(dest, decoded_, size); } else { @@ -420,21 +420,20 @@ void DrawEngineVulkan::DoFlush() { UpdateCachedViewportState(vpAndScissor); } - int maxIndex = MaxIndex(); SoftwareTransform swTransform(params); const Lin::Vec3 trans(gstate_c.vpXOffset, gstate_c.vpYOffset, gstate_c.vpZOffset * 0.5f + 0.5f); const Lin::Vec3 scale(gstate_c.vpWidthScale, gstate_c.vpHeightScale, gstate_c.vpDepthScale * 0.5f); swTransform.SetProjMatrix(gstate.projMatrix, gstate_c.vpWidth < 0, gstate_c.vpHeight < 0, trans, scale); - swTransform.Decode(prim, dec_->VertexType(), dec_->GetDecVtxFmt(), maxIndex, &result); + swTransform.Transform(prim, dec_->VertexType(), dec_->GetDecVtxFmt(), numDecodedVerts_, &result); // Non-zero depth clears are unusual, but some drivers don't match drawn depth values to cleared values. // Games sometimes expect exact matches (see #12626, for example) for equal comparisons. if (result.action == SW_CLEAR && everUsedEqualDepth_ && gstate.isClearModeDepthMask() && result.depth > 0.0f && result.depth < 1.0f) result.action = SW_NOT_READY; if (result.action == SW_NOT_READY) { - swTransform.DetectOffsetTexture(maxIndex); - swTransform.BuildDrawingParams(prim, indexGen.VertexCount(), dec_->VertexType(), inds, maxIndex, &result); + swTransform.DetectOffsetTexture(numDecodedVerts_); + swTransform.BuildDrawingParams(prim, indexGen.VertexCount(), dec_->VertexType(), inds, numDecodedVerts_, &result); } if (result.setSafeSize) @@ -519,7 +518,7 @@ void DrawEngineVulkan::DoFlush() { if (result.drawIndexed) { VkBuffer vbuf, ibuf; - vbOffset = (uint32_t)pushVertex_->Push(result.drawBuffer, maxIndex * sizeof(TransformedVertex), 4, &vbuf); + vbOffset = (uint32_t)pushVertex_->Push(result.drawBuffer, numDecodedVerts_ * sizeof(TransformedVertex), 4, &vbuf); ibOffset = (uint32_t)pushIndex_->Push(inds, sizeof(short) * result.drawNumTrans, 4, &ibuf); renderManager->DrawIndexed(descSetIndex, ARRAY_SIZE(dynamicUBOOffsets), dynamicUBOOffsets, vbuf, vbOffset, ibuf, ibOffset, result.drawNumTrans, 1); } else { @@ -564,7 +563,7 @@ void DrawEngineVulkan::DoFlush() { void DrawEngineVulkan::ResetAfterDraw() { indexGen.Reset(); - decodedVerts_ = 0; + numDecodedVerts_ = 0; numDrawVerts_ = 0; numDrawInds_ = 0; vertexCountInDrawCalls_ = 0; From 71aaad23fba5e4ab4e9610b99384078d1c0d6d96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 10 Dec 2023 12:21:07 +0100 Subject: [PATCH 2/2] Fix issue with zero-vertex draw calls. Though, should maybe just filter them out earlier. --- GPU/Common/DrawEngineCommon.cpp | 17 ++++++++--------- GPU/Common/VertexDecoderCommon.cpp | 6 +++++- GPU/Vulkan/DrawEngineVulkan.cpp | 8 ++++++++ 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/GPU/Common/DrawEngineCommon.cpp b/GPU/Common/DrawEngineCommon.cpp index eec4070f51d3..190f6160d4cd 100644 --- a/GPU/Common/DrawEngineCommon.cpp +++ b/GPU/Common/DrawEngineCommon.cpp @@ -899,8 +899,11 @@ bool DrawEngineCommon::SubmitPrim(const void *verts, const void *inds, GEPrimiti *bytesRead = vertexCount * dec_->VertexSize(); // Check that we have enough vertices to form the requested primitive. - if (vertexCount < 3 && ((vertexCount < 2 && prim > 0) || (prim > GE_PRIM_LINE_STRIP && prim != GE_PRIM_RECTANGLES))) - return false; + if (vertexCount < 3) { + if ((vertexCount < 2 && prim > 0) || (prim > GE_PRIM_LINE_STRIP && prim != GE_PRIM_RECTANGLES)) { + return false; + } + } bool applySkin = (vertTypeID & GE_VTYPE_WEIGHT_MASK) && decOptions_.applySkinInDecode; @@ -919,10 +922,10 @@ bool DrawEngineCommon::SubmitPrim(const void *verts, const void *inds, GEPrimiti if (inds && numDrawVerts_ > decodeVertsCounter_ && drawVerts_[numDrawVerts_ - 1].verts == verts && !applySkin) { // Same vertex pointer as a previous un-decoded draw call - let's just extend the decode! di.vertDecodeIndex = numDrawVerts_ - 1; - DeferredVerts &dv = drawVerts_[numDrawVerts_ - 1]; u16 lb; u16 ub; GetIndexBounds(inds, vertexCount, vertTypeID, &lb, &ub); + DeferredVerts &dv = drawVerts_[numDrawVerts_ - 1]; if (lb < dv.indexLowerBound) dv.indexLowerBound = lb; if (ub > dv.indexUpperBound) @@ -933,12 +936,8 @@ bool DrawEngineCommon::SubmitPrim(const void *verts, const void *inds, GEPrimiti dv.verts = verts; dv.vertexCount = vertexCount; dv.uvScale = gstate_c.uv; - if (inds) { - GetIndexBounds(inds, vertexCount, vertTypeID, &dv.indexLowerBound, &dv.indexUpperBound); - } else { - dv.indexLowerBound = 0; - dv.indexUpperBound = vertexCount - 1; - } + // Does handle the unindexed case. + GetIndexBounds(inds, vertexCount, vertTypeID, &dv.indexLowerBound, &dv.indexUpperBound); } vertexCountInDrawCalls_ += vertexCount; diff --git a/GPU/Common/VertexDecoderCommon.cpp b/GPU/Common/VertexDecoderCommon.cpp index cc8b6452e2b1..e500c69db5fa 100644 --- a/GPU/Common/VertexDecoderCommon.cpp +++ b/GPU/Common/VertexDecoderCommon.cpp @@ -154,7 +154,11 @@ void GetIndexBounds(const void *inds, int count, u32 vertType, u16 *indexLowerBo *indexUpperBound = (u16)upperBound; } else { *indexLowerBound = 0; - *indexUpperBound = count - 1; + if (count > 0) { + *indexUpperBound = count - 1; + } else { + *indexUpperBound = 0; + } } } diff --git a/GPU/Vulkan/DrawEngineVulkan.cpp b/GPU/Vulkan/DrawEngineVulkan.cpp index 5149a37c41e3..670338bbb4d2 100644 --- a/GPU/Vulkan/DrawEngineVulkan.cpp +++ b/GPU/Vulkan/DrawEngineVulkan.cpp @@ -376,8 +376,11 @@ void DrawEngineVulkan::DoFlush() { lastVType_ |= (1 << 26); dec_ = GetVertexDecoder(lastVType_); } + int prevDecodedVerts = numDecodedVerts_; + DecodeVerts(decoded_); DecodeInds(); + bool hasColor = (lastVType_ & GE_VTYPE_COL_MASK) != GE_VTYPE_COL_NONE; if (gstate.isModeThrough()) { gstate_c.vertexFullAlpha = gstate_c.vertexFullAlpha && (hasColor || gstate.getMaterialAmbientA() == 255); @@ -385,6 +388,11 @@ void DrawEngineVulkan::DoFlush() { gstate_c.vertexFullAlpha = gstate_c.vertexFullAlpha && ((hasColor && (gstate.materialupdate & 1)) || gstate.getMaterialAmbientA() == 255) && (!gstate.isLightingEnabled() || gstate.getAmbientA() == 255); } + int vcount = indexGen.VertexCount(); + if (numDecodedVerts_ > 10 * vcount) { + decIndex_ = decIndex_; + } + gpuStats.numUncachedVertsDrawn += indexGen.VertexCount(); prim = indexGen.Prim(); // Undo the strip optimization, not supported by the SW code yet.