diff --git a/GPU/Common/DrawEngineCommon.cpp b/GPU/Common/DrawEngineCommon.cpp index bf6d7a432d..b1f4ca7049 100644 --- a/GPU/Common/DrawEngineCommon.cpp +++ b/GPU/Common/DrawEngineCommon.cpp @@ -54,6 +54,7 @@ DrawEngineCommon::~DrawEngineCommon() { void DrawEngineCommon::Init() { useHWTransform_ = g_Config.bHardwareTransform; useHWTessellation_ = UpdateUseHWTessellation(g_Config.bHardwareTessellation); + decOptions_.applySkinInDecode = g_Config.bSoftwareSkinning; } VertexDecoder *DrawEngineCommon::GetVertexDecoder(u32 vtype) { @@ -181,10 +182,11 @@ void DrawEngineCommon::Resized() { useHWTransform_ = g_Config.bHardwareTransform; useHWTessellation_ = UpdateUseHWTessellation(g_Config.bHardwareTessellation); + decOptions_.applySkinInDecode = g_Config.bSoftwareSkinning; } u32 DrawEngineCommon::NormalizeVertices(u8 *outPtr, u8 *bufPtr, const u8 *inPtr, int lowerBound, int upperBound, u32 vertType, int *vertexSize) { - const u32 vertTypeID = GetVertTypeID(vertType, gstate.getUVGenMode()); + const u32 vertTypeID = GetVertTypeID(vertType, gstate.getUVGenMode(), decOptions_.applySkinInDecode); VertexDecoder *dec = GetVertexDecoder(vertTypeID); if (vertexSize) *vertexSize = dec->VertexSize(); @@ -232,7 +234,7 @@ void DrawEngineCommon::DispatchSubmitImm(GEPrimitiveType prim, TransformedVertex } int bytesRead; - uint32_t vertTypeID = GetVertTypeID(vtype, 0); + uint32_t vertTypeID = GetVertTypeID(vtype, 0, decOptions_.applySkinInDecode); SubmitPrim(&temp[0], nullptr, prim, vertexCount, vertTypeID, cullMode, &bytesRead); DispatchFlush(); @@ -280,7 +282,11 @@ bool DrawEngineCommon::TestBoundingBox(const void *control_points, const void *i GetIndexBounds(inds, vertexCount, vertType, &indexLowerBound, &indexUpperBound); } + // Force software skinning. + bool wasApplyingSkinInDecode = decOptions_.applySkinInDecode; + decOptions_.applySkinInDecode = true; NormalizeVertices((u8 *)corners, temp_buffer, (const u8 *)control_points, indexLowerBound, indexUpperBound, vertType); + decOptions_.applySkinInDecode = wasApplyingSkinInDecode; IndexConverter conv(vertType, inds); for (int i = 0; i < vertexCount; i++) { diff --git a/GPU/Common/DrawEngineCommon.h b/GPU/Common/DrawEngineCommon.h index ea14a07884..c0125b28b2 100644 --- a/GPU/Common/DrawEngineCommon.h +++ b/GPU/Common/DrawEngineCommon.h @@ -52,10 +52,10 @@ enum FBOTexState { FBO_TEX_READ_FRAMEBUFFER, }; -inline uint32_t GetVertTypeID(uint32_t vertType, int uvGenMode) { +inline uint32_t GetVertTypeID(uint32_t vertType, int uvGenMode, bool skinInDecode) { // As the decoder depends on the UVGenMode when we use UV prescale, we simply mash it // into the top of the verttype where there are unused bits. - return (vertType & 0xFFFFFF) | (uvGenMode << 24); + return (vertType & 0xFFFFFF) | (uvGenMode << 24) | (skinInDecode << 26); } struct SimpleVertex; diff --git a/GPU/Common/SplineCommon.cpp b/GPU/Common/SplineCommon.cpp index c5468e1203..6fe6436291 100644 --- a/GPU/Common/SplineCommon.cpp +++ b/GPU/Common/SplineCommon.cpp @@ -507,7 +507,7 @@ void DrawEngineCommon::SubmitCurve(const void *control_points, const void *indic if (indices) GetIndexBounds(indices, num_points, vertType, &index_lower_bound, &index_upper_bound); - VertexDecoder *origVDecoder = GetVertexDecoder(GetVertTypeID(vertType, gstate.getUVGenMode())); + VertexDecoder *origVDecoder = GetVertexDecoder(GetVertTypeID(vertType, gstate.getUVGenMode(), decOptions_.applySkinInDecode)); *bytesRead = num_points * origVDecoder->VertexSize(); // Simplify away bones and morph before proceeding @@ -572,7 +572,7 @@ void DrawEngineCommon::SubmitCurve(const void *control_points, const void *indic gstate_c.uv.vOff = 0; } - uint32_t vertTypeID = GetVertTypeID(vertTypeWithIndex16, gstate.getUVGenMode()); + uint32_t vertTypeID = GetVertTypeID(vertTypeWithIndex16, gstate.getUVGenMode(), decOptions_.applySkinInDecode); int generatedBytesRead; if (output.count) DispatchSubmitPrim(output.vertices, output.indices, PatchPrimToPrim(surface.primType), output.count, vertTypeID, gstate.getCullMode(), &generatedBytesRead); diff --git a/GPU/Common/VertexDecoderCommon.cpp b/GPU/Common/VertexDecoderCommon.cpp index 62eb20ef84..3a77375cba 100644 --- a/GPU/Common/VertexDecoderCommon.cpp +++ b/GPU/Common/VertexDecoderCommon.cpp @@ -1089,7 +1089,7 @@ void VertexDecoder::SetVertexType(u32 fmt, const VertexDecoderOptions &options, DEBUG_LOG(G3D, "VTYPE: THRU=%i TC=%i COL=%i POS=%i NRM=%i WT=%i NW=%i IDX=%i MC=%i", (int)throughmode, tc, col, pos, nrm, weighttype, nweights, idx, morphcount); } - skinInDecode = weighttype != 0 && g_Config.bSoftwareSkinning; + skinInDecode = weighttype != 0 && options.applySkinInDecode; if (weighttype) { // && nweights? weightoff = size; diff --git a/GPU/Common/VertexDecoderCommon.h b/GPU/Common/VertexDecoderCommon.h index d3785e13c9..e4c886cbd4 100644 --- a/GPU/Common/VertexDecoderCommon.h +++ b/GPU/Common/VertexDecoderCommon.h @@ -335,6 +335,7 @@ typedef void(*JittedVertexDecoder)(const u8 *src, u8 *dst, int count); struct VertexDecoderOptions { bool expandAllWeightsToFloat; bool expand8BitNormalsToFloat; + bool applySkinInDecode; }; class VertexDecoder { diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index b8c80a76ed..ddaf02bab8 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -1834,7 +1834,7 @@ void GPUCommon::Execute_Prim(u32 op, u32 diff) { // cull mode int cullMode = gstate.getCullMode(); - uint32_t vertTypeID = GetVertTypeID(vertexType, gstate.getUVGenMode()); + uint32_t vertTypeID = GetVertTypeID(vertexType, gstate.getUVGenMode(), g_Config.bSoftwareSkinning); drawEngineCommon_->SubmitPrim(verts, inds, prim, count, vertTypeID, cullMode, &bytesRead); // After drawing, we advance the vertexAddr (when non indexed) or indexAddr (when indexed). // Some games rely on this, they don't bother reloading VADDR and IADDR. @@ -1892,7 +1892,7 @@ void GPUCommon::Execute_Prim(u32 op, u32 diff) { goto bail; } else { vertexType = data; - vertTypeID = GetVertTypeID(vertexType, gstate.getUVGenMode()); + vertTypeID = GetVertTypeID(vertexType, gstate.getUVGenMode(), g_Config.bSoftwareSkinning); } break; } diff --git a/GPU/Software/TransformUnit.cpp b/GPU/Software/TransformUnit.cpp index 795d39635f..afd7d15920 100644 --- a/GPU/Software/TransformUnit.cpp +++ b/GPU/Software/TransformUnit.cpp @@ -72,7 +72,7 @@ void SoftwareDrawEngine::DispatchSubmitPrim(const void *verts, const void *inds, } void SoftwareDrawEngine::DispatchSubmitImm(GEPrimitiveType prim, TransformedVertex *buffer, int vertexCount, int cullMode, bool continuation) { - uint32_t vertTypeID = GetVertTypeID(gstate.vertType | GE_VTYPE_POS_FLOAT, gstate.getUVGenMode()); + uint32_t vertTypeID = GetVertTypeID(gstate.vertType | GE_VTYPE_POS_FLOAT, gstate.getUVGenMode(), decOptions_.applySkinInDecode); int flipCull = cullMode != gstate.getCullMode() ? 1 : 0; // TODO: For now, just setting all dirty. @@ -137,7 +137,7 @@ void SoftwareDrawEngine::DispatchSubmitImm(GEPrimitiveType prim, TransformedVert } VertexDecoder *SoftwareDrawEngine::FindVertexDecoder(u32 vtype) { - const u32 vertTypeID = GetVertTypeID(vtype, gstate.getUVGenMode()); + const u32 vertTypeID = GetVertTypeID(vtype, gstate.getUVGenMode(), decOptions_.applySkinInDecode); return DrawEngineCommon::GetVertexDecoder(vertTypeID); } @@ -858,7 +858,7 @@ void TransformUnit::SubmitImmVertex(const ClipVertexData &vert, SoftwareDrawEngi break; } - uint32_t vertTypeID = GetVertTypeID(gstate.vertType | GE_VTYPE_POS_FLOAT, gstate.getUVGenMode()); + uint32_t vertTypeID = GetVertTypeID(gstate.vertType | GE_VTYPE_POS_FLOAT, gstate.getUVGenMode(), g_Config.bSoftwareSkinning); // This now processes the step with shared logic, given the existing data_. isImmDraw_ = true; SubmitPrimitive(nullptr, nullptr, GE_PRIM_KEEP_PREVIOUS, 0, vertTypeID, nullptr, drawEngine); @@ -958,6 +958,7 @@ bool TransformUnit::GetCurrentSimpleVertices(int count, std::vectorSetVertexType(state.vertType, options); return rowCount_; } diff --git a/unittest/TestVertexJit.cpp b/unittest/TestVertexJit.cpp index 573247ba38..12dad2f5aa 100644 --- a/unittest/TestVertexJit.cpp +++ b/unittest/TestVertexJit.cpp @@ -545,8 +545,10 @@ static bool TestVertexColor565() { static bool TestVertex8Skin() { VertexDecoderTestHarness dec; + VertexDecoderOptions opts{}; + opts.applySkinInDecode = true; + dec.SetOptions(opts); - g_Config.bSoftwareSkinning = true; for (int i = 0; i < 8 * 12; ++i) { gstate.boneMatrix[i] = 0.0f; } @@ -575,8 +577,10 @@ static bool TestVertex8Skin() { static bool TestVertex16Skin() { VertexDecoderTestHarness dec; + VertexDecoderOptions opts{}; + opts.applySkinInDecode = true; + dec.SetOptions(opts); - g_Config.bSoftwareSkinning = true; for (int i = 0; i < 8 * 12; ++i) { gstate.boneMatrix[i] = 0.0f; } @@ -605,8 +609,10 @@ static bool TestVertex16Skin() { static bool TestVertexFloatSkin() { VertexDecoderTestHarness dec; + VertexDecoderOptions opts{}; + opts.applySkinInDecode = true; + dec.SetOptions(opts); - g_Config.bSoftwareSkinning = true; for (int i = 0; i < 8 * 12; ++i) { gstate.boneMatrix[i] = 0.0f; }