diff --git a/GPU/Common/VertexDecoderX86.cpp b/GPU/Common/VertexDecoderX86.cpp index 85eb948de1..5330cc3708 100644 --- a/GPU/Common/VertexDecoderX86.cpp +++ b/GPU/Common/VertexDecoderX86.cpp @@ -191,7 +191,7 @@ JittedVertexDecoder VertexDecoderJitCache::Compile(const VertexDecoder &dec) { // Later we might want to do this when the matrices are loaded instead. // This is mostly proof of concept. int boneCount = 0; - if (dec.weighttype && g_Config.bSoftwareSkinning) { + if (dec.weighttype && g_Config.bSoftwareSkinning && dec.morphcount == 1) { MOVAPS(XMM4, M(&threeMasks)); for (int i = 0; i < 8; i++) { MOVUPS(XMM0, M((gstate.boneMatrix + 12 * i))); diff --git a/GPU/Directx9/GPU_DX9.cpp b/GPU/Directx9/GPU_DX9.cpp index 0b523aa0cb..51e364c8be 100644 --- a/GPU/Directx9/GPU_DX9.cpp +++ b/GPU/Directx9/GPU_DX9.cpp @@ -707,6 +707,12 @@ void DIRECTX9_GPU::Execute_VertexTypeSkinning(u32 op, u32 diff) { gstate.vertType ^= diff; if (diff & (GE_VTYPE_TC_MASK | GE_VTYPE_THROUGH_MASK)) shaderManager_->DirtyUniform(DIRTY_UVSCALEOFFSET); + // In this case, we may be doing weights and morphs. + // Update any bone matrix uniforms so it uses them correctly. + if ((op & GE_VTYPE_MORPHCOUNT_MASK) != 0) { + shaderManager_->DirtyUniform(gstate_c.deferredVertTypeDirty); + gstate_c.deferredVertTypeDirty = 0; + } } } @@ -1269,6 +1275,11 @@ void DIRECTX9_GPU::Execute_BoneMtxNum(u32 op, u32 diff) { break; } } + + const int numPlusCount = (op & 0x7F) + i; + for (int num = op & 0x7F; num < numPlusCount; num += 12) { + gstate_c.deferredVertTypeDirty |= DIRTY_BONEMATRIX0 << (num / 12); + } } const int count = i; @@ -1288,6 +1299,8 @@ void DIRECTX9_GPU::Execute_BoneMtxData(u32 op, u32 diff) { if (!g_Config.bSoftwareSkinning || (gstate.vertType & GE_VTYPE_MORPHCOUNT_MASK) != 0) { Flush(); shaderManager_->DirtyUniform(DIRTY_BONEMATRIX0 << (num / 12)); + } else { + gstate_c.deferredVertTypeDirty |= DIRTY_BONEMATRIX0 << (num / 12); } ((u32 *)gstate.boneMatrix)[num] = newVal; } @@ -1776,15 +1789,18 @@ void DIRECTX9_GPU::Execute_Generic(u32 op, u32 diff) { } void DIRECTX9_GPU::FastLoadBoneMatrix(u32 target) { + const int num = gstate.boneMatrixNumber & 0x7F; + const int mtxNum = num / 12; + uint32_t uniformsToDirty = DIRTY_BONEMATRIX0 << mtxNum; + if ((num - 12 * mtxNum) != 0) { + uniformsToDirty |= DIRTY_BONEMATRIX0 << ((mtxNum + 1) & 7); + } + if (!g_Config.bSoftwareSkinning || (gstate.vertType & GE_VTYPE_MORPHCOUNT_MASK) != 0) { Flush(); - const int num = gstate.boneMatrixNumber & 0x7F; - int mtxNum = num / 12; - uint32_t uniformsToDirty = DIRTY_BONEMATRIX0 << mtxNum; - if ((num - 12 * mtxNum) != 0) { - uniformsToDirty |= DIRTY_BONEMATRIX0 << ((mtxNum + 1) & 7); - } shaderManager_->DirtyUniform(uniformsToDirty); + } else { + gstate_c.deferredVertTypeDirty |= uniformsToDirty; } gstate.FastLoadBoneMatrix(target); } diff --git a/GPU/GLES/GLES_GPU.cpp b/GPU/GLES/GLES_GPU.cpp index e5a39ddba0..bef26c0b30 100644 --- a/GPU/GLES/GLES_GPU.cpp +++ b/GPU/GLES/GLES_GPU.cpp @@ -868,6 +868,12 @@ void GLES_GPU::Execute_VertexTypeSkinning(u32 op, u32 diff) { gstate.vertType ^= diff; if (diff & (GE_VTYPE_TC_MASK | GE_VTYPE_THROUGH_MASK)) shaderManager_->DirtyUniform(DIRTY_UVSCALEOFFSET); + // In this case, we may be doing weights and morphs. + // Update any bone matrix uniforms so it uses them correctly. + if ((op & GE_VTYPE_MORPHCOUNT_MASK) != 0) { + shaderManager_->DirtyUniform(gstate_c.deferredVertTypeDirty); + gstate_c.deferredVertTypeDirty = 0; + } } } @@ -1346,6 +1352,11 @@ void GLES_GPU::Execute_BoneMtxNum(u32 op, u32 diff) { break; } } + + const int numPlusCount = (op & 0x7F) + i; + for (int num = op & 0x7F; num < numPlusCount; num += 12) { + gstate_c.deferredVertTypeDirty |= DIRTY_BONEMATRIX0 << (num / 12); + } } const int count = i; @@ -1365,6 +1376,8 @@ void GLES_GPU::Execute_BoneMtxData(u32 op, u32 diff) { if (!g_Config.bSoftwareSkinning || (gstate.vertType & GE_VTYPE_MORPHCOUNT_MASK) != 0) { Flush(); shaderManager_->DirtyUniform(DIRTY_BONEMATRIX0 << (num / 12)); + } else { + gstate_c.deferredVertTypeDirty |= DIRTY_BONEMATRIX0 << (num / 12); } ((u32 *)gstate.boneMatrix)[num] = newVal; } @@ -1915,15 +1928,18 @@ void GLES_GPU::Execute_Generic(u32 op, u32 diff) { } void GLES_GPU::FastLoadBoneMatrix(u32 target) { + const int num = gstate.boneMatrixNumber & 0x7F; + const int mtxNum = num / 12; + uint32_t uniformsToDirty = DIRTY_BONEMATRIX0 << mtxNum; + if ((num - 12 * mtxNum) != 0) { + uniformsToDirty |= DIRTY_BONEMATRIX0 << ((mtxNum + 1) & 7); + } + if (!g_Config.bSoftwareSkinning || (gstate.vertType & GE_VTYPE_MORPHCOUNT_MASK) != 0) { Flush(); - const int num = gstate.boneMatrixNumber & 0x7F; - int mtxNum = num / 12; - uint32_t uniformsToDirty = DIRTY_BONEMATRIX0 << mtxNum; - if ((num - 12 * mtxNum) != 0) { - uniformsToDirty |= DIRTY_BONEMATRIX0 << ((mtxNum + 1) & 7); - } shaderManager_->DirtyUniform(uniformsToDirty); + } else { + gstate_c.deferredVertTypeDirty |= uniformsToDirty; } gstate.FastLoadBoneMatrix(target); } diff --git a/GPU/GPUState.h b/GPU/GPUState.h index 81c367c370..a23d4e615b 100644 --- a/GPU/GPUState.h +++ b/GPU/GPUState.h @@ -469,6 +469,7 @@ struct GPUStateCache bool allowShaderBlend; float morphWeights[8]; + u32 deferredVertTypeDirty; u32 curTextureWidth; u32 curTextureHeight;