diff --git a/GPU/Common/DrawEngineCommon.cpp b/GPU/Common/DrawEngineCommon.cpp index 9079666ed7..502d115b53 100644 --- a/GPU/Common/DrawEngineCommon.cpp +++ b/GPU/Common/DrawEngineCommon.cpp @@ -133,7 +133,6 @@ void DrawEngineCommon::NotifyConfigChanged() { useHWTransform_ = g_Config.bHardwareTransform; useHWTessellation_ = UpdateUseHWTessellation(g_Config.bHardwareTessellation); - applySkinInDecode_ = g_Config.bSoftwareSkinning; } u32 DrawEngineCommon::NormalizeVertices(u8 *outPtr, u8 *bufPtr, const u8 *inPtr, int lowerBound, int upperBound, u32 vertType, int *vertexSize) { @@ -1038,7 +1037,14 @@ bool DrawEngineCommon::SubmitPrim(const void *verts, const void *inds, GEPrimiti return true; } +void DrawEngineCommon::BeginFrame() { + applySkinInDecode_ = g_Config.bSoftwareSkinning; +} + void DrawEngineCommon::DecodeVerts(VertexDecoder *dec, u8 *dest) { + if (!numDrawVerts_) { + return; + } // Note that this should be able to continue a partial decode - we don't necessarily start from zero here (although we do most of the time). int i = decodeVertsCounter_; int stride = (int)dec->GetDecVtxFmt().stride; diff --git a/GPU/Common/DrawEngineCommon.h b/GPU/Common/DrawEngineCommon.h index 19f26749a5..c8733ecbaa 100644 --- a/GPU/Common/DrawEngineCommon.h +++ b/GPU/Common/DrawEngineCommon.h @@ -77,6 +77,8 @@ public: void Init(); + virtual void BeginFrame(); + void SetGPUCommon(GPUCommon *gpuCommon) { gpuCommon_ = gpuCommon; } diff --git a/GPU/D3D11/DrawEngineD3D11.cpp b/GPU/D3D11/DrawEngineD3D11.cpp index 78d45e1cfb..4ad2b8bf51 100644 --- a/GPU/D3D11/DrawEngineD3D11.cpp +++ b/GPU/D3D11/DrawEngineD3D11.cpp @@ -239,6 +239,8 @@ ID3D11InputLayout *DrawEngineD3D11::SetupDecFmtForDraw(D3D11VertexShader *vshade } void DrawEngineD3D11::BeginFrame() { + DrawEngineCommon::BeginFrame(); + pushVerts_->Reset(); pushInds_->Reset(); @@ -346,12 +348,15 @@ void DrawEngineD3D11::Flush() { } } else { PROFILE_THIS_SCOPE("soft"); - if (!applySkinInDecode_) { - applySkinInDecode_ = true; - lastVType_ |= (1 << 26); - dec_ = GetVertexDecoder(lastVType_); + VertexDecoder *swDec = dec_; + if (swDec->nweights != 0) { + u32 withSkinning = lastVType_ | (1 << 26); + if (withSkinning != lastVType_) { + swDec = GetVertexDecoder(withSkinning); + } } - DecodeVerts(dec_, decoded_); + + DecodeVerts(swDec, decoded_); int vertexCount = DecodeInds(); bool hasColor = (lastVType_ & GE_VTYPE_COL_MASK) != GE_VTYPE_COL_NONE; @@ -400,7 +405,7 @@ void DrawEngineD3D11::Flush() { 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.Transform(prim, dec_->VertexType(), dec_->GetDecVtxFmt(), numDecodedVerts_, &result); + swTransform.Transform(prim, swDec->VertexType(), swDec->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) @@ -416,7 +421,7 @@ void DrawEngineD3D11::Flush() { ApplyDrawState(prim); if (result.action == SW_NOT_READY) - swTransform.BuildDrawingParams(prim, vertexCount, dec_->VertexType(), inds, RemainingIndices(inds), numDecodedVerts_, VERTEX_BUFFER_MAX, &result); + swTransform.BuildDrawingParams(prim, vertexCount, swDec->VertexType(), inds, RemainingIndices(inds), numDecodedVerts_, VERTEX_BUFFER_MAX, &result); if (result.setSafeSize) framebufferManager_->SetSafeSize(result.safeWidth, result.safeHeight); @@ -425,7 +430,7 @@ void DrawEngineD3D11::Flush() { if (result.action == SW_DRAW_INDEXED) { D3D11VertexShader *vshader; D3D11FragmentShader *fshader; - shaderManager_->GetShaders(prim, dec_, &vshader, &fshader, pipelineState_, false, false, decOptions_.expandAllWeightsToFloat, true); + shaderManager_->GetShaders(prim, swDec, &vshader, &fshader, pipelineState_, false, false, decOptions_.expandAllWeightsToFloat, true); context_->PSSetShader(fshader->GetShader(), nullptr, 0); context_->VSSetShader(vshader->GetShader(), nullptr, 0); shaderManager_->UpdateUniforms(framebufferManager_->UseBufferedRendering()); @@ -478,7 +483,6 @@ void DrawEngineD3D11::Flush() { framebufferManager_->ApplyClearToMemory(scissorX1, scissorY1, scissorX2, scissorY2, clearColor); } } - applySkinInDecode_ = g_Config.bSoftwareSkinning; } ResetAfterDrawInline(); diff --git a/GPU/D3D11/DrawEngineD3D11.h b/GPU/D3D11/DrawEngineD3D11.h index b43cc50a53..1b69736d13 100644 --- a/GPU/D3D11/DrawEngineD3D11.h +++ b/GPU/D3D11/DrawEngineD3D11.h @@ -75,7 +75,7 @@ public: void InitDeviceObjects(); void DestroyDeviceObjects(); - void BeginFrame(); + void BeginFrame() override; void Flush() override; diff --git a/GPU/Directx9/DrawEngineDX9.cpp b/GPU/Directx9/DrawEngineDX9.cpp index 3f31075454..d557148beb 100644 --- a/GPU/Directx9/DrawEngineDX9.cpp +++ b/GPU/Directx9/DrawEngineDX9.cpp @@ -219,6 +219,7 @@ static uint32_t SwapRB(uint32_t c) { } void DrawEngineDX9::BeginFrame() { + DrawEngineCommon::BeginFrame(); lastRenderStepId_ = -1; } @@ -301,12 +302,14 @@ void DrawEngineDX9::Flush() { } } } else { - if (!applySkinInDecode_) { - applySkinInDecode_ = true; - lastVType_ |= (1 << 26); - dec_ = GetVertexDecoder(lastVType_); + VertexDecoder *swDec = dec_; + if (swDec->nweights != 0) { + u32 withSkinning = lastVType_ | (1 << 26); + if (withSkinning != lastVType_) { + swDec = GetVertexDecoder(withSkinning); + } } - DecodeVerts(dec_, decoded_); + DecodeVerts(swDec, decoded_); int vertexCount = DecodeInds(); bool hasColor = (lastVType_ & GE_VTYPE_COL_MASK) != GE_VTYPE_COL_NONE; @@ -361,7 +364,7 @@ void DrawEngineDX9::Flush() { 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.Transform(prim, dec_->VertexType(), dec_->GetDecVtxFmt(), numDecodedVerts_, &result); + swTransform.Transform(prim, swDec->VertexType(), swDec->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) @@ -376,13 +379,13 @@ void DrawEngineDX9::Flush() { ApplyDrawState(prim); if (result.action == SW_NOT_READY) - swTransform.BuildDrawingParams(prim, vertexCount, dec_->VertexType(), inds, RemainingIndices(inds), numDecodedVerts_, VERTEX_BUFFER_MAX, &result); + swTransform.BuildDrawingParams(prim, vertexCount, swDec->VertexType(), inds, RemainingIndices(inds), numDecodedVerts_, VERTEX_BUFFER_MAX, &result); if (result.setSafeSize) framebufferManager_->SetSafeSize(result.safeWidth, result.safeHeight); ApplyDrawStateLate(); - VSShader *vshader = shaderManager_->ApplyShader(false, false, dec_, decOptions_.expandAllWeightsToFloat, true, pipelineState_); + VSShader *vshader = shaderManager_->ApplyShader(false, false, swDec, decOptions_.expandAllWeightsToFloat, true, pipelineState_); if (result.action == SW_DRAW_INDEXED) { if (result.setStencil) { @@ -414,7 +417,6 @@ void DrawEngineDX9::Flush() { framebufferManager_->ApplyClearToMemory(scissorX1, scissorY1, scissorX2, scissorY2, clearColor); } } - applySkinInDecode_ = g_Config.bSoftwareSkinning; } ResetAfterDrawInline(); diff --git a/GPU/Directx9/DrawEngineDX9.h b/GPU/Directx9/DrawEngineDX9.h index 6073ed4494..9165955c6f 100644 --- a/GPU/Directx9/DrawEngineDX9.h +++ b/GPU/Directx9/DrawEngineDX9.h @@ -65,7 +65,7 @@ public: void InitDeviceObjects(); void DestroyDeviceObjects(); - void BeginFrame(); + void BeginFrame() override; // So that this can be inlined void Flush() override; diff --git a/GPU/GLES/DrawEngineGLES.cpp b/GPU/GLES/DrawEngineGLES.cpp index dfff8b395b..d96631174c 100644 --- a/GPU/GLES/DrawEngineGLES.cpp +++ b/GPU/GLES/DrawEngineGLES.cpp @@ -147,6 +147,8 @@ void DrawEngineGLES::ClearInputLayoutMap() { } void DrawEngineGLES::BeginFrame() { + DrawEngineCommon::BeginFrame(); + FrameData &frameData = frameData_[render_->GetCurFrame()]; frameData.pushIndex->Begin(); frameData.pushVertex->Begin(); @@ -328,12 +330,14 @@ void DrawEngineGLES::Flush() { } } else { PROFILE_THIS_SCOPE("soft"); - if (!applySkinInDecode_) { - applySkinInDecode_ = true; - lastVType_ |= (1 << 26); - dec_ = GetVertexDecoder(lastVType_); + VertexDecoder *swDec = dec_; + if (swDec->nweights != 0) { + u32 withSkinning = lastVType_ | (1 << 26); + if (withSkinning != lastVType_) { + swDec = GetVertexDecoder(withSkinning); + } } - DecodeVerts(dec_, decoded_); + DecodeVerts(swDec, decoded_); int vertexCount = DecodeInds(); bool hasColor = (lastVType_ & GE_VTYPE_COL_MASK) != GE_VTYPE_COL_NONE; @@ -387,7 +391,7 @@ void DrawEngineGLES::Flush() { 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.Transform(prim, dec_->VertexType(), dec_->GetDecVtxFmt(), numDecodedVerts_, &result); + swTransform.Transform(prim, swDec->VertexType(), swDec->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) @@ -403,7 +407,7 @@ void DrawEngineGLES::Flush() { ApplyDrawState(prim); if (result.action == SW_NOT_READY) - swTransform.BuildDrawingParams(prim, vertexCount, dec_->VertexType(), inds, RemainingIndices(inds), numDecodedVerts_, VERTEX_BUFFER_MAX, &result); + swTransform.BuildDrawingParams(prim, vertexCount, swDec->VertexType(), inds, RemainingIndices(inds), numDecodedVerts_, VERTEX_BUFFER_MAX, &result); if (result.setSafeSize) framebufferManager_->SetSafeSize(result.safeWidth, result.safeHeight); @@ -447,7 +451,6 @@ void DrawEngineGLES::Flush() { } gstate_c.Dirty(DIRTY_BLEND_STATE); // Make sure the color mask gets re-applied. } - applySkinInDecode_ = g_Config.bSoftwareSkinning; } bail: diff --git a/GPU/GLES/DrawEngineGLES.h b/GPU/GLES/DrawEngineGLES.h index 167635af5a..9d05fdb429 100644 --- a/GPU/GLES/DrawEngineGLES.h +++ b/GPU/GLES/DrawEngineGLES.h @@ -81,7 +81,7 @@ public: void ClearTrackedVertexArrays() override {} - void BeginFrame(); + void BeginFrame() override; void EndFrame(); // So that this can be inlined diff --git a/GPU/Vulkan/DrawEngineVulkan.cpp b/GPU/Vulkan/DrawEngineVulkan.cpp index 43917028b6..8500ee5d9e 100644 --- a/GPU/Vulkan/DrawEngineVulkan.cpp +++ b/GPU/Vulkan/DrawEngineVulkan.cpp @@ -164,6 +164,8 @@ void DrawEngineVulkan::DeviceRestore(Draw::DrawContext *draw) { } void DrawEngineVulkan::BeginFrame() { + DrawEngineCommon::BeginFrame(); + lastPipeline_ = nullptr; // These will be re-bound if needed, let's not let old bindings linger around too long. @@ -381,15 +383,16 @@ void DrawEngineVulkan::Flush() { } } else { PROFILE_THIS_SCOPE("soft"); - - if (!applySkinInDecode_) { - applySkinInDecode_ = true; - lastVType_ |= (1 << 26); - dec_ = GetVertexDecoder(lastVType_); + VertexDecoder *swDec = dec_; + if (swDec->nweights != 0) { + u32 withSkinning = lastVType_ | (1 << 26); + if (withSkinning != lastVType_) { + swDec = GetVertexDecoder(withSkinning); + } } int prevDecodedVerts = numDecodedVerts_; - DecodeVerts(dec_, decoded_); + DecodeVerts(swDec, decoded_); int vertexCount = DecodeInds(); bool hasColor = (lastVType_ & GE_VTYPE_COL_MASK) != GE_VTYPE_COL_NONE; @@ -445,7 +448,7 @@ void DrawEngineVulkan::Flush() { 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.Transform(prim, dec_->VertexType(), dec_->GetDecVtxFmt(), numDecodedVerts_, &result); + swTransform.Transform(prim, swDec->VertexType(), swDec->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) @@ -453,7 +456,7 @@ void DrawEngineVulkan::Flush() { if (result.action == SW_NOT_READY) { // decIndex_ here is always equal to inds currently, but it may not be in the future. - swTransform.BuildDrawingParams(prim, vertexCount, dec_->VertexType(), inds, RemainingIndices(inds), numDecodedVerts_, VERTEX_BUFFER_MAX, &result); + swTransform.BuildDrawingParams(prim, vertexCount, swDec->VertexType(), inds, RemainingIndices(inds), numDecodedVerts_, VERTEX_BUFFER_MAX, &result); } if (result.setSafeSize) @@ -481,9 +484,9 @@ void DrawEngineVulkan::Flush() { VulkanFragmentShader *fshader = nullptr; VulkanGeometryShader *gshader = nullptr; - shaderManager_->GetShaders(prim, dec_, &vshader, &fshader, &gshader, pipelineState_, false, false, decOptions_.expandAllWeightsToFloat, true); + shaderManager_->GetShaders(prim, swDec, &vshader, &fshader, &gshader, pipelineState_, false, false, decOptions_.expandAllWeightsToFloat, true); _dbg_assert_msg_(!vshader->UseHWTransform(), "Bad vshader"); - VulkanPipeline *pipeline = pipelineManager_->GetOrCreatePipeline(renderManager, pipelineLayout_, pipelineKey_, &dec_->decFmt, vshader, fshader, gshader, false, 0, framebufferManager_->GetMSAALevel(), false); + VulkanPipeline *pipeline = pipelineManager_->GetOrCreatePipeline(renderManager, pipelineLayout_, pipelineKey_, &swDec->decFmt, vshader, fshader, gshader, false, 0, framebufferManager_->GetMSAALevel(), false); if (!pipeline || !pipeline->pipeline) { // Already logged, let's bail out. ResetAfterDraw(); @@ -564,7 +567,6 @@ void DrawEngineVulkan::Flush() { framebufferManager_->ApplyClearToMemory(scissorX1, scissorY1, scissorX2, scissorY2, result.color); } } - applySkinInDecode_ = g_Config.bSoftwareSkinning; } ResetAfterDrawInline(); @@ -582,7 +584,6 @@ void DrawEngineVulkan::ResetAfterDraw() { vertexCountInDrawCalls_ = 0; decodeIndsCounter_ = 0; decodeVertsCounter_ = 0; - applySkinInDecode_ = g_Config.bSoftwareSkinning; gstate_c.vertexFullAlpha = true; } diff --git a/GPU/Vulkan/DrawEngineVulkan.h b/GPU/Vulkan/DrawEngineVulkan.h index 185f66f9a2..2d7aceaf90 100644 --- a/GPU/Vulkan/DrawEngineVulkan.h +++ b/GPU/Vulkan/DrawEngineVulkan.h @@ -136,7 +136,7 @@ public: return pipelineLayout_; } - void BeginFrame(); + void BeginFrame() override; void EndFrame(); void DirtyAllUBOs();