From c6b55459b13c53447901c7c73a4af0f8cc3819fc Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 16 May 2015 21:47:13 -0700 Subject: [PATCH 1/3] vertexjit: Skip soft skinning setup when morphing. This makes x86 match arm. --- GPU/Common/VertexDecoderX86.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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))); From 425ff3d78fe979c0c328c33bd6a5db1951e885e7 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 16 May 2015 21:49:25 -0700 Subject: [PATCH 2/3] Track bone matrix updates for future morph usage. This makes them upload later, if/when they're needed. Fixes #7746, Shadow of Destiny artifacts when software skinning is enabled. --- GPU/GLES/GLES_GPU.cpp | 28 ++++++++++++++++++++++------ GPU/GPUState.h | 1 + 2 files changed, 23 insertions(+), 6 deletions(-) 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; From 7d2507e0cc756c2708aada4d323c16e8e3400041 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 16 May 2015 21:54:07 -0700 Subject: [PATCH 3/3] d3d9: Also track bone matrices for morph here. --- GPU/Directx9/GPU_DX9.cpp | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) 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); }