From e74101a2fb2c594c0c07e36bbf60c57be50e52a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 17 Dec 2024 18:15:52 +0100 Subject: [PATCH 1/3] applySkinInDecode belongs in the VertexTypeID, not in the options. --- GPU/Common/DrawEngineCommon.cpp | 14 +++++++------- GPU/Common/DrawEngineCommon.h | 11 +++-------- GPU/Common/SplineCommon.cpp | 4 ++-- GPU/Common/VertexDecoderCommon.cpp | 5 +++-- GPU/Common/VertexDecoderCommon.h | 16 ++++++++++++++-- GPU/D3D11/DrawEngineD3D11.cpp | 8 ++++---- GPU/Directx9/DrawEngineDX9.cpp | 8 ++++---- GPU/GLES/DrawEngineGLES.cpp | 10 +++++----- GPU/Software/TransformUnit.cpp | 6 +++--- GPU/Vulkan/DrawEngineVulkan.cpp | 12 ++++++------ UI/ImDebugger/ImGe.cpp | 8 +++----- Windows/GEDebugger/TabVertices.cpp | 4 ++-- unittest/TestVertexJit.cpp | 16 ++++++++-------- 13 files changed, 64 insertions(+), 58 deletions(-) diff --git a/GPU/Common/DrawEngineCommon.cpp b/GPU/Common/DrawEngineCommon.cpp index 8724325f17..6847ca75a3 100644 --- a/GPU/Common/DrawEngineCommon.cpp +++ b/GPU/Common/DrawEngineCommon.cpp @@ -133,11 +133,11 @@ void DrawEngineCommon::NotifyConfigChanged() { useHWTransform_ = g_Config.bHardwareTransform; useHWTessellation_ = UpdateUseHWTessellation(g_Config.bHardwareTessellation); - decOptions_.applySkinInDecode = g_Config.bSoftwareSkinning; + 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(), decOptions_.applySkinInDecode); + const u32 vertTypeID = GetVertTypeID(vertType, gstate.getUVGenMode(), applySkinInDecode_); VertexDecoder *dec = GetVertexDecoder(vertTypeID); if (vertexSize) *vertexSize = dec->VertexSize(); @@ -185,7 +185,7 @@ void DrawEngineCommon::DispatchSubmitImm(GEPrimitiveType prim, TransformedVertex } int bytesRead; - uint32_t vertTypeID = GetVertTypeID(vtype, 0, decOptions_.applySkinInDecode); + uint32_t vertTypeID = GetVertTypeID(vtype, 0, applySkinInDecode_); bool clockwise = !gstate.isCullEnabled() || gstate.getCullMode() == cullMode; SubmitPrim(&temp[0], nullptr, prim, vertexCount, vertTypeID, clockwise, &bytesRead); @@ -303,10 +303,10 @@ bool DrawEngineCommon::TestBoundingBox(const void *vdata, const void *inds, int } // TODO: Avoid normalization if just plain skinning. // Force software skinning. - bool wasApplyingSkinInDecode = decOptions_.applySkinInDecode; - decOptions_.applySkinInDecode = true; + bool wasApplyingSkinInDecode = applySkinInDecode_; + applySkinInDecode_ = true; NormalizeVertices((u8 *)corners, temp_buffer, (const u8 *)vdata, indexLowerBound, indexUpperBound, vertType); - decOptions_.applySkinInDecode = wasApplyingSkinInDecode; + applySkinInDecode_ = wasApplyingSkinInDecode; IndexConverter conv(vertType, inds); for (int i = 0; i < vertexCount; i++) { @@ -985,7 +985,7 @@ bool DrawEngineCommon::SubmitPrim(const void *verts, const void *inds, GEPrimiti } } - bool applySkin = (vertTypeID & GE_VTYPE_WEIGHT_MASK) && decOptions_.applySkinInDecode; + bool applySkin = dec_->skinInDecode; DeferredInds &di = drawInds_[numDrawInds_++]; di.inds = inds; diff --git a/GPU/Common/DrawEngineCommon.h b/GPU/Common/DrawEngineCommon.h index 7b236da599..a1cea4ebe0 100644 --- a/GPU/Common/DrawEngineCommon.h +++ b/GPU/Common/DrawEngineCommon.h @@ -53,12 +53,6 @@ enum FBOTexState { FBO_TEX_READ_FRAMEBUFFER, }; -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) | (skinInDecode << 26); -} - struct SimpleVertex; namespace Spline { struct Weight2D; } @@ -114,8 +108,7 @@ public: bool TestBoundingBoxThrough(const void *vdata, int vertexCount, u32 vertType); void FlushSkin() { - bool applySkin = (lastVType_ & GE_VTYPE_WEIGHT_MASK) && decOptions_.applySkinInDecode; - if (applySkin) { + if (dec_->skinInDecode) { DecodeVerts(decoded_); } } @@ -314,6 +307,8 @@ protected: bool anyCCWOrIndexed_ = 0; bool anyIndexed_ = 0; + bool applySkinInDecode_ = false; + // Vertex collector state IndexGenerator indexGen; int numDecodedVerts_ = 0; diff --git a/GPU/Common/SplineCommon.cpp b/GPU/Common/SplineCommon.cpp index 9100e0b21e..06bebe5617 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(), decOptions_.applySkinInDecode)); + VertexDecoder *origVDecoder = GetVertexDecoder(GetVertTypeID(vertType, gstate.getUVGenMode(), applySkinInDecode_)); *bytesRead = num_points * origVDecoder->VertexSize(); // Simplify away bones and morph before proceeding @@ -574,7 +574,7 @@ void DrawEngineCommon::SubmitCurve(const void *control_points, const void *indic gstate_c.uv.vOff = 0; } - uint32_t vertTypeID = GetVertTypeID(vertTypeWithIndex16, gstate.getUVGenMode(), decOptions_.applySkinInDecode); + uint32_t vertTypeID = GetVertTypeID(vertTypeWithIndex16, gstate.getUVGenMode(), applySkinInDecode_); int generatedBytesRead; if (output.count) DispatchSubmitPrim(output.vertices, output.indices, PatchPrimToPrim(surface.primType), output.count, vertTypeID, true, &generatedBytesRead); diff --git a/GPU/Common/VertexDecoderCommon.cpp b/GPU/Common/VertexDecoderCommon.cpp index 9885aa0069..ef26be2f96 100644 --- a/GPU/Common/VertexDecoderCommon.cpp +++ b/GPU/Common/VertexDecoderCommon.cpp @@ -1125,7 +1125,7 @@ void VertexDecoder::SetVertexType(u32 fmt, const VertexDecoderOptions &options, DEBUG_LOG(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 && options.applySkinInDecode; + skinInDecode = weighttype != 0 && VertTypeIDSkinInDecode(fmt); if (weighttype) { // && nweights? weightoff = size; @@ -1182,7 +1182,8 @@ void VertexDecoder::SetVertexType(u32 fmt, const VertexDecoderOptions &options, // NOTE: That we check getUVGenMode here means that we must include it in the decoder ID! // throughmode is automatically included though, because it's part of the vertType. - if (!throughmode && (gstate.getUVGenMode() == GE_TEXMAP_TEXTURE_COORDS || gstate.getUVGenMode() == GE_TEXMAP_UNKNOWN)) { + GETexMapMode mode = VertTypeIDUVGenMode(fmt); + if (!throughmode && (mode == GE_TEXMAP_TEXTURE_COORDS || mode == GE_TEXMAP_UNKNOWN)) { if (g_DoubleTextureCoordinates) steps_[numSteps_++] = morphcount == 1 ? tcstep_prescale_remaster[tc] : tcstep_prescale_morph_remaster[tc]; else diff --git a/GPU/Common/VertexDecoderCommon.h b/GPU/Common/VertexDecoderCommon.h index 7a40701e01..2793ad80ee 100644 --- a/GPU/Common/VertexDecoderCommon.h +++ b/GPU/Common/VertexDecoderCommon.h @@ -325,9 +325,22 @@ typedef void (*JittedVertexDecoder)(const u8 *src, u8 *dst, int count, const UVS struct VertexDecoderOptions { bool expandAllWeightsToFloat; bool expand8BitNormalsToFloat; - bool applySkinInDecode; }; +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) | (skinInDecode << 26); +} + +inline bool VertTypeIDSkinInDecode(uint32_t vertType) { + return ((vertType >> 26) & 1) != 0; +} + +inline GETexMapMode VertTypeIDUVGenMode(uint32_t vertType) { + return (GETexMapMode)((vertType >> 24) & 3); +} + class VertexDecoder { public: // A jit cache is not mandatory. @@ -512,7 +525,6 @@ public: // Returns a pointer to the code to run. JittedVertexDecoder Compile(const VertexDecoder &dec, int32_t *jittedSize); - bool DescribeCodePtr(const u8 *ptr, std::string &name) const; void Clear(); void Jit_WeightsU8(); diff --git a/GPU/D3D11/DrawEngineD3D11.cpp b/GPU/D3D11/DrawEngineD3D11.cpp index 2d6a372830..c770531f3d 100644 --- a/GPU/D3D11/DrawEngineD3D11.cpp +++ b/GPU/D3D11/DrawEngineD3D11.cpp @@ -303,7 +303,7 @@ void DrawEngineD3D11::Flush() { D3D11VertexShader *vshader; D3D11FragmentShader *fshader; - shaderManager_->GetShaders(prim, dec_, &vshader, &fshader, pipelineState_, useHWTransform, useHWTessellation_, decOptions_.expandAllWeightsToFloat, decOptions_.applySkinInDecode); + shaderManager_->GetShaders(prim, dec_, &vshader, &fshader, pipelineState_, useHWTransform, useHWTessellation_, decOptions_.expandAllWeightsToFloat, applySkinInDecode_); ID3D11InputLayout *inputLayout = SetupDecFmtForDraw(vshader, dec_->GetDecVtxFmt(), dec_->VertexType()); context_->PSSetShader(fshader->GetShader(), nullptr, 0); context_->VSSetShader(vshader->GetShader(), nullptr, 0); @@ -346,8 +346,8 @@ void DrawEngineD3D11::Flush() { } } else { PROFILE_THIS_SCOPE("soft"); - if (!decOptions_.applySkinInDecode) { - decOptions_.applySkinInDecode = true; + if (!applySkinInDecode_) { + applySkinInDecode_ = true; lastVType_ |= (1 << 26); dec_ = GetVertexDecoder(lastVType_); } @@ -478,7 +478,7 @@ void DrawEngineD3D11::Flush() { framebufferManager_->ApplyClearToMemory(scissorX1, scissorY1, scissorX2, scissorY2, clearColor); } } - decOptions_.applySkinInDecode = g_Config.bSoftwareSkinning; + applySkinInDecode_ = g_Config.bSoftwareSkinning; } ResetAfterDrawInline(); diff --git a/GPU/Directx9/DrawEngineDX9.cpp b/GPU/Directx9/DrawEngineDX9.cpp index 6cc0618a24..62bd815b07 100644 --- a/GPU/Directx9/DrawEngineDX9.cpp +++ b/GPU/Directx9/DrawEngineDX9.cpp @@ -276,7 +276,7 @@ void DrawEngineDX9::Flush() { ApplyDrawState(prim); ApplyDrawStateLate(); - VSShader *vshader = shaderManager_->ApplyShader(true, useHWTessellation_, dec_, decOptions_.expandAllWeightsToFloat, decOptions_.applySkinInDecode, pipelineState_); + VSShader *vshader = shaderManager_->ApplyShader(true, useHWTessellation_, dec_, decOptions_.expandAllWeightsToFloat, applySkinInDecode_, pipelineState_); ComPtr pHardwareVertexDecl; SetupDecFmtForDraw(dec_->GetDecVtxFmt(), dec_->VertexType(), &pHardwareVertexDecl); @@ -301,8 +301,8 @@ void DrawEngineDX9::Flush() { } } } else { - if (!decOptions_.applySkinInDecode) { - decOptions_.applySkinInDecode = true; + if (!applySkinInDecode_) { + applySkinInDecode_ = true; lastVType_ |= (1 << 26); dec_ = GetVertexDecoder(lastVType_); } @@ -414,7 +414,7 @@ void DrawEngineDX9::Flush() { framebufferManager_->ApplyClearToMemory(scissorX1, scissorY1, scissorX2, scissorY2, clearColor); } } - decOptions_.applySkinInDecode = g_Config.bSoftwareSkinning; + applySkinInDecode_ = g_Config.bSoftwareSkinning; } ResetAfterDrawInline(); diff --git a/GPU/GLES/DrawEngineGLES.cpp b/GPU/GLES/DrawEngineGLES.cpp index 7d2e7cce0e..b3621c6e5f 100644 --- a/GPU/GLES/DrawEngineGLES.cpp +++ b/GPU/GLES/DrawEngineGLES.cpp @@ -264,7 +264,7 @@ void DrawEngineGLES::Flush() { GEPrimitiveType prim = prevPrim_; - Shader *vshader = shaderManager_->ApplyVertexShader(CanUseHardwareTransform(prim), useHWTessellation_, dec_, decOptions_.expandAllWeightsToFloat, decOptions_.applySkinInDecode || !CanUseHardwareTransform(prim), &vsid); + Shader *vshader = shaderManager_->ApplyVertexShader(CanUseHardwareTransform(prim), useHWTessellation_, dec_, decOptions_.expandAllWeightsToFloat, applySkinInDecode_ || !CanUseHardwareTransform(prim), &vsid); GLRBuffer *vertexBuffer = nullptr; GLRBuffer *indexBuffer = nullptr; @@ -272,7 +272,7 @@ void DrawEngineGLES::Flush() { uint32_t indexBufferOffset = 0; if (vshader->UseHWTransform()) { - if (decOptions_.applySkinInDecode && (lastVType_ & GE_VTYPE_WEIGHT_MASK)) { + if (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 = numDecodedVerts_ * dec_->GetDecVtxFmt().stride; @@ -328,8 +328,8 @@ void DrawEngineGLES::Flush() { } } else { PROFILE_THIS_SCOPE("soft"); - if (!decOptions_.applySkinInDecode) { - decOptions_.applySkinInDecode = true; + if (!applySkinInDecode_) { + applySkinInDecode_ = true; lastVType_ |= (1 << 26); dec_ = GetVertexDecoder(lastVType_); } @@ -447,7 +447,7 @@ void DrawEngineGLES::Flush() { } gstate_c.Dirty(DIRTY_BLEND_STATE); // Make sure the color mask gets re-applied. } - decOptions_.applySkinInDecode = g_Config.bSoftwareSkinning; + applySkinInDecode_ = g_Config.bSoftwareSkinning; } bail: diff --git a/GPU/Software/TransformUnit.cpp b/GPU/Software/TransformUnit.cpp index 12a520b30f..ea03a5b360 100644 --- a/GPU/Software/TransformUnit.cpp +++ b/GPU/Software/TransformUnit.cpp @@ -63,7 +63,7 @@ SoftwareDrawEngine::~SoftwareDrawEngine() {} void SoftwareDrawEngine::NotifyConfigChanged() { DrawEngineCommon::NotifyConfigChanged(); - decOptions_.applySkinInDecode = true; + applySkinInDecode_ = true; } void SoftwareDrawEngine::Flush() { @@ -973,8 +973,8 @@ bool TransformUnit::GetCurrentSimpleVertices(int count, std::vectorGetDecVtxFmt().stride; @@ -302,7 +302,7 @@ void DrawEngineVulkan::Flush() { VulkanFragmentShader *fshader = nullptr; VulkanGeometryShader *gshader = nullptr; - shaderManager_->GetShaders(prim, dec_, &vshader, &fshader, &gshader, pipelineState_, true, useHWTessellation_, decOptions_.expandAllWeightsToFloat, decOptions_.applySkinInDecode); + shaderManager_->GetShaders(prim, dec_, &vshader, &fshader, &gshader, pipelineState_, true, useHWTessellation_, decOptions_.expandAllWeightsToFloat, applySkinInDecode_); _dbg_assert_msg_(vshader->UseHWTransform(), "Bad vshader"); VulkanPipeline *pipeline = pipelineManager_->GetOrCreatePipeline(renderManager, pipelineLayout_, pipelineKey_, &dec_->decFmt, vshader, fshader, gshader, true, 0, framebufferManager_->GetMSAALevel(), false); if (!pipeline || !pipeline->pipeline) { @@ -381,8 +381,8 @@ void DrawEngineVulkan::Flush() { } } else { PROFILE_THIS_SCOPE("soft"); - if (!decOptions_.applySkinInDecode) { - decOptions_.applySkinInDecode = true; + if (!applySkinInDecode_) { + applySkinInDecode_ = true; lastVType_ |= (1 << 26); dec_ = GetVertexDecoder(lastVType_); } @@ -563,7 +563,7 @@ void DrawEngineVulkan::Flush() { framebufferManager_->ApplyClearToMemory(scissorX1, scissorY1, scissorX2, scissorY2, result.color); } } - decOptions_.applySkinInDecode = g_Config.bSoftwareSkinning; + applySkinInDecode_ = g_Config.bSoftwareSkinning; } ResetAfterDrawInline(); @@ -581,7 +581,7 @@ void DrawEngineVulkan::ResetAfterDraw() { vertexCountInDrawCalls_ = 0; decodeIndsCounter_ = 0; decodeVertsCounter_ = 0; - decOptions_.applySkinInDecode = g_Config.bSoftwareSkinning; + applySkinInDecode_ = g_Config.bSoftwareSkinning; gstate_c.vertexFullAlpha = true; } diff --git a/UI/ImDebugger/ImGe.cpp b/UI/ImDebugger/ImGe.cpp index e2c14320ec..d9e2159437 100644 --- a/UI/ImDebugger/ImGe.cpp +++ b/UI/ImDebugger/ImGe.cpp @@ -1360,15 +1360,13 @@ void ImGeStateWindow::Draw(ImConfig &cfg, ImControl &control, GPUDebugInterface if (!gpuDebug->GetCurrentSimpleVertices(rowCount_, vertices, indices)) { rowCount_ = 0; } - VertexDecoderOptions options{}; - // TODO: Maybe an option? - options.applySkinInDecode = true; - auto buildVertexTable = [&](bool raw) { // Ignore indices for now. if (ImGui::BeginTable("rawverts", VERTEXLIST_COL_COUNT + 1, tableFlags)) { static VertexDecoder decoder; - decoder.SetVertexType(state.vertType, options); + u32 vertTypeID = GetVertTypeID(state.vertType, state.getUVGenMode(), true); + VertexDecoderOptions options{}; + decoder.SetVertexType(vertTypeID, options); static const char * const colNames[] = { "Index", diff --git a/Windows/GEDebugger/TabVertices.cpp b/Windows/GEDebugger/TabVertices.cpp index 464471398e..0091d358a6 100644 --- a/Windows/GEDebugger/TabVertices.cpp +++ b/Windows/GEDebugger/TabVertices.cpp @@ -175,8 +175,8 @@ int CtrlVertexList::GetRowCount() { } VertexDecoderOptions options{}; // TODO: Maybe an option? - options.applySkinInDecode = true; - decoder->SetVertexType(state.vertType, options); + u32 vertTypeID = GetVertTypeID(state.vertType, state.getUVGenMode(), true); + decoder->SetVertexType(vertTypeID, options); return rowCount_; } diff --git a/unittest/TestVertexJit.cpp b/unittest/TestVertexJit.cpp index f5561c0fa9..cd6dc5625d 100644 --- a/unittest/TestVertexJit.cpp +++ b/unittest/TestVertexJit.cpp @@ -51,7 +51,7 @@ public: void Reset() { memset(src_, 0, BUFFER_SIZE); memset(dst_, 0, BUFFER_SIZE); - memset(&options_, 0, sizeof(options_)); + options_ = {}; delete dec_; dec_ = nullptr; indexLowerBound_ = 0; @@ -65,7 +65,7 @@ public: if (needsReset_) { Reset(); } - memcpy(&options_, &opts, sizeof(options_)); + options_ = opts; } void SetIndexLowerBound(const int lower) { @@ -543,7 +543,6 @@ static bool TestVertexColor565() { static bool TestVertex8Skin() { VertexDecoderTestHarness dec; VertexDecoderOptions opts{}; - opts.applySkinInDecode = true; dec.SetOptions(opts); for (int i = 0; i < 8 * 12; ++i) { @@ -558,13 +557,14 @@ static bool TestVertex8Skin() { gstate.boneMatrix[20] = 5.0f; int vtype = GE_VTYPE_POS_8BIT | GE_VTYPE_NRM_8BIT | GE_VTYPE_WEIGHT_8BIT | (1 << GE_VTYPE_WEIGHTCOUNT_SHIFT); + u32 vertTypeID = GetVertTypeID(vtype, 0, true); // enable skinning in decode dec.Add8(128 + 64, 128 - 64); dec.Add8(127, 0, 128); dec.Add8(127, 0, 128); for (int jit = 0; jit <= 1; ++jit) { - dec.Execute(vtype, 0, jit == 1); + dec.Execute(vertTypeID, 0, jit == 1); dec.AssertFloat("TestVertex8Skin-Nrm", (2.0f * 1.5f + 1.0f * 0.5f) * 127.0f / 128.0f, 0.0f, 2.0f * 5.0f * -1.0f); dec.AssertFloat("TestVertex8Skin-Pos", (2.0f * 1.5f + 1.0f * 0.5f) * 127.0f / 128.0f, 0.0f, 2.0f * 5.0f * -1.0f); } @@ -575,7 +575,6 @@ static bool TestVertex8Skin() { static bool TestVertex16Skin() { VertexDecoderTestHarness dec; VertexDecoderOptions opts{}; - opts.applySkinInDecode = true; dec.SetOptions(opts); for (int i = 0; i < 8 * 12; ++i) { @@ -590,13 +589,14 @@ static bool TestVertex16Skin() { gstate.boneMatrix[20] = 5.0f; int vtype = GE_VTYPE_POS_16BIT | GE_VTYPE_NRM_16BIT | GE_VTYPE_WEIGHT_16BIT | (1 << GE_VTYPE_WEIGHTCOUNT_SHIFT); + u32 vertTypeID = GetVertTypeID(vtype, 0, true); // enable skinning in decode dec.Add16(32768 + 16384, 32768 - 16384); dec.Add16(32767, 0, 32768); dec.Add16(32767, 0, 32768); for (int jit = 0; jit <= 1; ++jit) { - dec.Execute(vtype, 0, jit == 1); + dec.Execute(vertTypeID, 0, jit == 1); dec.AssertFloat("TestVertex16Skin-Nrm", (2.0f * 1.5f + 1.0f * 0.5f) * 32767.0f / 32768.0f, 0.0f, 2.0f * 5.0f * -1.0f); dec.AssertFloat("TestVertex16Skin-Pos", (2.0f * 1.5f + 1.0f * 0.5f) * 32767.0f / 32768.0f, 0.0f, 2.0f * 5.0f * -1.0f); } @@ -607,7 +607,6 @@ static bool TestVertex16Skin() { static bool TestVertexFloatSkin() { VertexDecoderTestHarness dec; VertexDecoderOptions opts{}; - opts.applySkinInDecode = true; dec.SetOptions(opts); for (int i = 0; i < 8 * 12; ++i) { @@ -622,13 +621,14 @@ static bool TestVertexFloatSkin() { gstate.boneMatrix[20] = 5.0f; int vtype = GE_VTYPE_POS_FLOAT | GE_VTYPE_NRM_FLOAT | GE_VTYPE_WEIGHT_FLOAT | (1 << GE_VTYPE_WEIGHTCOUNT_SHIFT); + u32 vertTypeID = GetVertTypeID(vtype, 0, true); // enable skinning in decode dec.AddFloat(1.5f, 0.5f); dec.AddFloat(1.0f, 0, -1.0f); dec.AddFloat(1.0f, 0, -1.0f); for (int jit = 0; jit <= 1; ++jit) { - dec.Execute(vtype, 0, jit == 1); + dec.Execute(vertTypeID, 0, jit == 1); dec.AssertFloat("TestVertexFloatSkin-Nrm", (2.0f * 1.5f + 1.0f * 0.5f) * 1.0f, 0.0f, 2.0f * 5.0f * -1.0f); dec.AssertFloat("TestVertexFloatSkin-Pos", (2.0f * 1.5f + 1.0f * 0.5f) * 1.0f, 0.0f, 2.0f * 5.0f * -1.0f); } From 20ecbfdf57d55939cbcc99d5e01fdd9d306fbdff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 17 Dec 2024 18:24:26 +0100 Subject: [PATCH 2/3] Pass the VertexDecoder pointer around --- GPU/Common/DrawEngineCommon.cpp | 6 +++--- GPU/Common/DrawEngineCommon.h | 4 ++-- GPU/D3D11/DrawEngineD3D11.cpp | 4 ++-- GPU/D3D11/DrawEngineD3D11.h | 2 +- GPU/Directx9/DrawEngineDX9.cpp | 4 ++-- GPU/Directx9/DrawEngineDX9.h | 2 +- GPU/GLES/DrawEngineGLES.cpp | 8 ++++---- GPU/Vulkan/DrawEngineVulkan.cpp | 7 ++++--- 8 files changed, 19 insertions(+), 18 deletions(-) diff --git a/GPU/Common/DrawEngineCommon.cpp b/GPU/Common/DrawEngineCommon.cpp index 6847ca75a3..9079666ed7 100644 --- a/GPU/Common/DrawEngineCommon.cpp +++ b/GPU/Common/DrawEngineCommon.cpp @@ -1038,10 +1038,10 @@ bool DrawEngineCommon::SubmitPrim(const void *verts, const void *inds, GEPrimiti return true; } -void DrawEngineCommon::DecodeVerts(u8 *dest) { +void DrawEngineCommon::DecodeVerts(VertexDecoder *dec, u8 *dest) { // 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; + int stride = (int)dec->GetDecVtxFmt().stride; for (; i < numDrawVerts_; i++) { DeferredVerts &dv = drawVerts_[i]; @@ -1056,7 +1056,7 @@ void DrawEngineCommon::DecodeVerts(u8 *dest) { } // Decode the verts (and at the same time apply morphing/skinning). Simple. - dec_->DecodeVerts(dest + numDecodedVerts_ * stride, dv.verts, &dv.uvScale, indexLowerBound, indexUpperBound); + 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 a1cea4ebe0..19f26749a5 100644 --- a/GPU/Common/DrawEngineCommon.h +++ b/GPU/Common/DrawEngineCommon.h @@ -109,7 +109,7 @@ public: void FlushSkin() { if (dec_->skinInDecode) { - DecodeVerts(decoded_); + DecodeVerts(dec_, decoded_); } } @@ -153,7 +153,7 @@ protected: virtual bool UpdateUseHWTessellation(bool enabled) const { return enabled; } void UpdatePlanes(); - void DecodeVerts(u8 *dest); + void DecodeVerts(VertexDecoder *dec, u8 *dest); int DecodeInds(); // Preprocessing for spline/bezier diff --git a/GPU/D3D11/DrawEngineD3D11.cpp b/GPU/D3D11/DrawEngineD3D11.cpp index c770531f3d..78d45e1cfb 100644 --- a/GPU/D3D11/DrawEngineD3D11.cpp +++ b/GPU/D3D11/DrawEngineD3D11.cpp @@ -282,7 +282,7 @@ void DrawEngineD3D11::Flush() { int vertexCount; int maxIndex; bool useElements; - DecodeVerts(decoded_); + DecodeVerts(dec_, decoded_); DecodeIndsAndGetData(&prim, &vertexCount, &maxIndex, &useElements, false); gpuStats.numUncachedVertsDrawn += vertexCount; @@ -351,7 +351,7 @@ void DrawEngineD3D11::Flush() { lastVType_ |= (1 << 26); dec_ = GetVertexDecoder(lastVType_); } - DecodeVerts(decoded_); + DecodeVerts(dec_, decoded_); int vertexCount = DecodeInds(); bool hasColor = (lastVType_ & GE_VTYPE_COL_MASK) != GE_VTYPE_COL_NONE; diff --git a/GPU/D3D11/DrawEngineD3D11.h b/GPU/D3D11/DrawEngineD3D11.h index d870ae1850..b43cc50a53 100644 --- a/GPU/D3D11/DrawEngineD3D11.h +++ b/GPU/D3D11/DrawEngineD3D11.h @@ -80,7 +80,7 @@ public: void Flush() override; void FinishDeferred() { - DecodeVerts(decoded_); + DecodeVerts(dec_, decoded_); } void NotifyConfigChanged() override; diff --git a/GPU/Directx9/DrawEngineDX9.cpp b/GPU/Directx9/DrawEngineDX9.cpp index 62bd815b07..3f31075454 100644 --- a/GPU/Directx9/DrawEngineDX9.cpp +++ b/GPU/Directx9/DrawEngineDX9.cpp @@ -256,7 +256,7 @@ void DrawEngineDX9::Flush() { int vertexCount; int maxIndex; bool useElements; - DecodeVerts(decoded_); + DecodeVerts(dec_, decoded_); DecodeIndsAndGetData(&prim, &vertexCount, &maxIndex, &useElements, false); gpuStats.numUncachedVertsDrawn += vertexCount; @@ -306,7 +306,7 @@ void DrawEngineDX9::Flush() { lastVType_ |= (1 << 26); dec_ = GetVertexDecoder(lastVType_); } - DecodeVerts(decoded_); + DecodeVerts(dec_, decoded_); int vertexCount = DecodeInds(); bool hasColor = (lastVType_ & GE_VTYPE_COL_MASK) != GE_VTYPE_COL_NONE; diff --git a/GPU/Directx9/DrawEngineDX9.h b/GPU/Directx9/DrawEngineDX9.h index 6bbf6ffcab..6073ed4494 100644 --- a/GPU/Directx9/DrawEngineDX9.h +++ b/GPU/Directx9/DrawEngineDX9.h @@ -71,7 +71,7 @@ public: void Flush() override; void FinishDeferred() { - DecodeVerts(decoded_); + DecodeVerts(dec_, decoded_); } protected: diff --git a/GPU/GLES/DrawEngineGLES.cpp b/GPU/GLES/DrawEngineGLES.cpp index b3621c6e5f..dfff8b395b 100644 --- a/GPU/GLES/DrawEngineGLES.cpp +++ b/GPU/GLES/DrawEngineGLES.cpp @@ -274,7 +274,7 @@ void DrawEngineGLES::Flush() { if (vshader->UseHWTransform()) { if (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_); + DecodeVerts(dec_, decoded_); uint32_t size = numDecodedVerts_ * dec_->GetDecVtxFmt().stride; u8 *dest = (u8 *)frameData.pushVertex->Allocate(size, 4, &vertexBuffer, &vertexBufferOffset); memcpy(dest, decoded_, size); @@ -282,13 +282,13 @@ void DrawEngineGLES::Flush() { // Figure out how much pushbuffer space we need to allocate. int vertsToDecode = ComputeNumVertsToDecode(); u8 *dest = (u8 *)frameData.pushVertex->Allocate(vertsToDecode * dec_->GetDecVtxFmt().stride, 4, &vertexBuffer, &vertexBufferOffset); - DecodeVerts(dest); + DecodeVerts(dec_, dest); } int vertexCount; int maxIndex; bool useElements; - DecodeVerts(decoded_); + DecodeVerts(dec_, decoded_); DecodeIndsAndGetData(&prim, &vertexCount, &maxIndex, &useElements, false); if (useElements) { @@ -333,7 +333,7 @@ void DrawEngineGLES::Flush() { lastVType_ |= (1 << 26); dec_ = GetVertexDecoder(lastVType_); } - DecodeVerts(decoded_); + DecodeVerts(dec_, decoded_); int vertexCount = DecodeInds(); bool hasColor = (lastVType_ & GE_VTYPE_COL_MASK) != GE_VTYPE_COL_NONE; diff --git a/GPU/Vulkan/DrawEngineVulkan.cpp b/GPU/Vulkan/DrawEngineVulkan.cpp index ec1e7a6b87..43917028b6 100644 --- a/GPU/Vulkan/DrawEngineVulkan.cpp +++ b/GPU/Vulkan/DrawEngineVulkan.cpp @@ -260,7 +260,7 @@ void DrawEngineVulkan::Flush() { VkBuffer vbuf = VK_NULL_HANDLE; if (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_); + DecodeVerts(dec_, decoded_); VkDeviceSize size = numDecodedVerts_ * dec_->GetDecVtxFmt().stride; u8 *dest = (u8 *)pushVertex_->Allocate(size, 4, &vbuf, &vbOffset); memcpy(dest, decoded_, size); @@ -269,7 +269,7 @@ void DrawEngineVulkan::Flush() { int vertsToDecode = ComputeNumVertsToDecode(); // Decode directly into the pushbuffer u8 *dest = pushVertex_->Allocate(vertsToDecode * dec_->GetDecVtxFmt().stride, 4, &vbuf, &vbOffset); - DecodeVerts(dest); + DecodeVerts(dec_, dest); } int vertexCount; @@ -381,6 +381,7 @@ void DrawEngineVulkan::Flush() { } } else { PROFILE_THIS_SCOPE("soft"); + if (!applySkinInDecode_) { applySkinInDecode_ = true; lastVType_ |= (1 << 26); @@ -388,7 +389,7 @@ void DrawEngineVulkan::Flush() { } int prevDecodedVerts = numDecodedVerts_; - DecodeVerts(decoded_); + DecodeVerts(dec_, decoded_); int vertexCount = DecodeInds(); bool hasColor = (lastVType_ & GE_VTYPE_COL_MASK) != GE_VTYPE_COL_NONE; From abb255853523fd973581eaaca8884e1b335c84e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 17 Dec 2024 18:47:20 +0100 Subject: [PATCH 3/3] When overriding skinning in sw transform mode, don't write/restore member variables --- GPU/Common/DrawEngineCommon.cpp | 8 +++++++- GPU/Common/DrawEngineCommon.h | 2 ++ GPU/D3D11/DrawEngineD3D11.cpp | 22 +++++++++++++--------- GPU/D3D11/DrawEngineD3D11.h | 2 +- GPU/Directx9/DrawEngineDX9.cpp | 20 +++++++++++--------- GPU/Directx9/DrawEngineDX9.h | 2 +- GPU/GLES/DrawEngineGLES.cpp | 19 +++++++++++-------- GPU/GLES/DrawEngineGLES.h | 2 +- GPU/Vulkan/DrawEngineVulkan.cpp | 25 +++++++++++++------------ GPU/Vulkan/DrawEngineVulkan.h | 2 +- 10 files changed, 61 insertions(+), 43 deletions(-) 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();