From a5d3af9cb0e2d3f254c1a686e524fb7fcbdd754c Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 6 Nov 2022 07:59:01 -0800 Subject: [PATCH 1/6] GPU: Cleanup GetVertTypeID() usage. --- GPU/Common/DrawEngineCommon.cpp | 2 +- GPU/Common/SplineCommon.cpp | 2 +- GPU/Software/TransformUnit.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/GPU/Common/DrawEngineCommon.cpp b/GPU/Common/DrawEngineCommon.cpp index 35cfb7dfa9..bf6d7a432d 100644 --- a/GPU/Common/DrawEngineCommon.cpp +++ b/GPU/Common/DrawEngineCommon.cpp @@ -184,7 +184,7 @@ void DrawEngineCommon::Resized() { } u32 DrawEngineCommon::NormalizeVertices(u8 *outPtr, u8 *bufPtr, const u8 *inPtr, int lowerBound, int upperBound, u32 vertType, int *vertexSize) { - const u32 vertTypeID = (vertType & 0xFFFFFF) | (gstate.getUVGenMode() << 24); + const u32 vertTypeID = GetVertTypeID(vertType, gstate.getUVGenMode()); VertexDecoder *dec = GetVertexDecoder(vertTypeID); if (vertexSize) *vertexSize = dec->VertexSize(); diff --git a/GPU/Common/SplineCommon.cpp b/GPU/Common/SplineCommon.cpp index b2358f401b..c5468e1203 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((vertType & 0xFFFFFF) | (gstate.getUVGenMode() << 24)); + VertexDecoder *origVDecoder = GetVertexDecoder(GetVertTypeID(vertType, gstate.getUVGenMode())); *bytesRead = num_points * origVDecoder->VertexSize(); // Simplify away bones and morph before proceeding diff --git a/GPU/Software/TransformUnit.cpp b/GPU/Software/TransformUnit.cpp index 043683b88c..795d39635f 100644 --- a/GPU/Software/TransformUnit.cpp +++ b/GPU/Software/TransformUnit.cpp @@ -137,7 +137,7 @@ void SoftwareDrawEngine::DispatchSubmitImm(GEPrimitiveType prim, TransformedVert } VertexDecoder *SoftwareDrawEngine::FindVertexDecoder(u32 vtype) { - const u32 vertTypeID = (vtype & 0xFFFFFF) | (gstate.getUVGenMode() << 24); + const u32 vertTypeID = GetVertTypeID(vtype, gstate.getUVGenMode()); return DrawEngineCommon::GetVertexDecoder(vertTypeID); } From 66472c39ce1f20089c30022f0dfd5ecc476edcef Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 6 Nov 2022 08:09:01 -0800 Subject: [PATCH 2/6] GPU: Use skinned position always in bounding check. Meanwhile, move to a flag on decoder options instead of global check. --- GPU/Common/DrawEngineCommon.cpp | 10 ++++++++-- GPU/Common/DrawEngineCommon.h | 4 ++-- GPU/Common/SplineCommon.cpp | 4 ++-- GPU/Common/VertexDecoderCommon.cpp | 2 +- GPU/Common/VertexDecoderCommon.h | 1 + GPU/GPUCommon.cpp | 4 ++-- GPU/Software/TransformUnit.cpp | 7 ++++--- Windows/GEDebugger/TabVertices.cpp | 2 ++ unittest/TestVertexJit.cpp | 12 +++++++++--- 9 files changed, 31 insertions(+), 15 deletions(-) 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; } From 6c36f03a0dc35cccf366363ceaed52b470782835 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 6 Nov 2022 08:40:54 -0800 Subject: [PATCH 3/6] GPU: Purify vertTypeIsSkinningEnabled(). --- GPU/Common/DrawEngineCommon.cpp | 8 +++----- GPU/Common/DrawEngineCommon.h | 2 +- GPU/Common/ShaderId.cpp | 4 ++-- GPU/Common/ShaderId.h | 2 +- GPU/Common/SoftwareTransformCommon.cpp | 2 +- GPU/D3D11/DrawEngineD3D11.cpp | 10 +++++----- GPU/D3D11/DrawEngineD3D11.h | 2 +- GPU/D3D11/GPU_D3D11.cpp | 2 +- GPU/D3D11/ShaderManagerD3D11.cpp | 4 ++-- GPU/D3D11/ShaderManagerD3D11.h | 2 +- GPU/Directx9/DrawEngineDX9.cpp | 6 +++--- GPU/Directx9/GPU_DX9.cpp | 4 ++-- GPU/Directx9/ShaderManagerDX9.cpp | 6 +++--- GPU/Directx9/ShaderManagerDX9.h | 2 +- GPU/GLES/DrawEngineGLES.cpp | 4 ++-- GPU/GLES/GPU_GLES.cpp | 4 ++-- GPU/GLES/ShaderManagerGLES.cpp | 6 +++--- GPU/GLES/ShaderManagerGLES.h | 2 +- GPU/GPUState.cpp | 5 +---- GPU/Software/TransformUnit.cpp | 2 +- GPU/Vulkan/DrawEngineVulkan.cpp | 8 ++++---- GPU/Vulkan/GPU_Vulkan.cpp | 2 +- GPU/Vulkan/ShaderManagerVulkan.cpp | 4 ++-- GPU/Vulkan/ShaderManagerVulkan.h | 2 +- 24 files changed, 45 insertions(+), 50 deletions(-) diff --git a/GPU/Common/DrawEngineCommon.cpp b/GPU/Common/DrawEngineCommon.cpp index b1f4ca7049..e02da46179 100644 --- a/GPU/Common/DrawEngineCommon.cpp +++ b/GPU/Common/DrawEngineCommon.cpp @@ -52,9 +52,7 @@ DrawEngineCommon::~DrawEngineCommon() { } void DrawEngineCommon::Init() { - useHWTransform_ = g_Config.bHardwareTransform; - useHWTessellation_ = UpdateUseHWTessellation(g_Config.bHardwareTessellation); - decOptions_.applySkinInDecode = g_Config.bSoftwareSkinning; + NotifyConfigChanged(); } VertexDecoder *DrawEngineCommon::GetVertexDecoder(u32 vtype) { @@ -170,7 +168,7 @@ static Vec3f ScreenToDrawing(const Vec3f& coords) { return ret; } -void DrawEngineCommon::Resized() { +void DrawEngineCommon::NotifyConfigChanged() { decJitCache_->Clear(); lastVType_ = -1; dec_ = nullptr; @@ -838,7 +836,7 @@ void DrawEngineCommon::SubmitPrim(const void *verts, const void *inds, GEPrimiti numDrawCalls++; vertexCountInDrawCalls_ += vertexCount; - if (g_Config.bSoftwareSkinning && (vertTypeID & GE_VTYPE_WEIGHT_MASK)) { + if (decOptions_.applySkinInDecode && (vertTypeID & GE_VTYPE_WEIGHT_MASK)) { DecodeVertsStep(decoded, decodeCounter_, decodedVerts_); decodeCounter_++; } diff --git a/GPU/Common/DrawEngineCommon.h b/GPU/Common/DrawEngineCommon.h index c0125b28b2..4b62f48c14 100644 --- a/GPU/Common/DrawEngineCommon.h +++ b/GPU/Common/DrawEngineCommon.h @@ -105,7 +105,7 @@ public: std::vector DebugGetVertexLoaderIDs(); std::string DebugGetVertexLoaderString(std::string id, DebugShaderStringType stringType); - virtual void Resized(); + virtual void NotifyConfigChanged(); bool IsCodePtrVertexDecoder(const u8 *ptr) const { return decJitCache_->IsInSpace(ptr); diff --git a/GPU/Common/ShaderId.cpp b/GPU/Common/ShaderId.cpp index aee52476cf..0f034c7709 100644 --- a/GPU/Common/ShaderId.cpp +++ b/GPU/Common/ShaderId.cpp @@ -67,7 +67,7 @@ std::string VertexShaderDesc(const VShaderID &id) { return desc.str(); } -void ComputeVertexShaderID(VShaderID *id_out, u32 vertType, bool useHWTransform, bool useHWTessellation, bool weightsAsFloat) { +void ComputeVertexShaderID(VShaderID *id_out, u32 vertType, bool useHWTransform, bool useHWTessellation, bool weightsAsFloat, bool useSkinInDecode) { bool isModeThrough = (vertType & GE_VTYPE_THROUGH) != 0; bool doTexture = gstate.isTextureMapEnabled() && !gstate.isModeClear(); bool doShadeMapping = doTexture && (gstate.getUVGenMode() == GE_TEXMAP_ENVIRONMENT_MAP); @@ -118,7 +118,7 @@ void ComputeVertexShaderID(VShaderID *id_out, u32 vertType, bool useHWTransform, } // Bones. - bool enableBones = vertTypeIsSkinningEnabled(vertType); + bool enableBones = !useSkinInDecode && vertTypeIsSkinningEnabled(vertType); id.SetBit(VS_BIT_ENABLE_BONES, enableBones); if (enableBones) { id.SetBits(VS_BIT_BONES, 3, TranslateNumBones(vertTypeGetNumBoneWeights(vertType)) - 1); diff --git a/GPU/Common/ShaderId.h b/GPU/Common/ShaderId.h index effe330763..06b252d87d 100644 --- a/GPU/Common/ShaderId.h +++ b/GPU/Common/ShaderId.h @@ -275,7 +275,7 @@ namespace Draw { class Bugs; } -void ComputeVertexShaderID(VShaderID *id, uint32_t vertexType, bool useHWTransform, bool useHWTessellation, bool weightsAsFloat); +void ComputeVertexShaderID(VShaderID *id, uint32_t vertexType, bool useHWTransform, bool useHWTessellation, bool weightsAsFloat, bool useSkinInDecode); // Generates a compact string that describes the shader. Useful in a list to get an overview // of the current flora of shaders. std::string VertexShaderDesc(const VShaderID &id); diff --git a/GPU/Common/SoftwareTransformCommon.cpp b/GPU/Common/SoftwareTransformCommon.cpp index 0f841d1709..dc86e9ec13 100644 --- a/GPU/Common/SoftwareTransformCommon.cpp +++ b/GPU/Common/SoftwareTransformCommon.cpp @@ -204,7 +204,7 @@ void SoftwareTransform::Decode(int prim, u32 vertType, const DecVtxFormat &decVt vscale /= gstate_c.curTextureHeight; } - bool skinningEnabled = vertTypeIsSkinningEnabled(vertType); + bool skinningEnabled = vertTypeIsSkinningEnabled(vertType) && !g_Config.bSoftwareSkinning; const int w = gstate.getTextureWidth(0); const int h = gstate.getTextureHeight(0); diff --git a/GPU/D3D11/DrawEngineD3D11.cpp b/GPU/D3D11/DrawEngineD3D11.cpp index c5c4669ba9..2a537a83a3 100644 --- a/GPU/D3D11/DrawEngineD3D11.cpp +++ b/GPU/D3D11/DrawEngineD3D11.cpp @@ -130,8 +130,8 @@ void DrawEngineD3D11::ClearInputLayoutMap() { inputLayoutMap_.Clear(); } -void DrawEngineD3D11::Resized() { - DrawEngineCommon::Resized(); +void DrawEngineD3D11::NotifyConfigChanged() { + DrawEngineCommon::NotifyConfigChanged(); ClearInputLayoutMap(); } @@ -365,7 +365,7 @@ void DrawEngineD3D11::DoFlush() { // Cannot cache vertex data with morph enabled. bool useCache = g_Config.bVertexCache && !(lastVType_ & GE_VTYPE_MORPHCOUNT_MASK); // Also avoid caching when software skinning. - if (g_Config.bSoftwareSkinning && (lastVType_ & GE_VTYPE_WEIGHT_MASK)) + if (decOptions_.applySkinInDecode && (lastVType_ & GE_VTYPE_WEIGHT_MASK)) useCache = false; if (useCache) { @@ -538,7 +538,7 @@ rotateVBO: D3D11VertexShader *vshader; D3D11FragmentShader *fshader; - shaderManager_->GetShaders(prim, lastVType_, &vshader, &fshader, pipelineState_, useHWTransform, useHWTessellation_, decOptions_.expandAllWeightsToFloat); + shaderManager_->GetShaders(prim, lastVType_, &vshader, &fshader, pipelineState_, useHWTransform, useHWTessellation_, decOptions_.expandAllWeightsToFloat, decOptions_.applySkinInDecode); ID3D11InputLayout *inputLayout = SetupDecFmtForDraw(vshader, dec_->GetDecVtxFmt(), dec_->VertexType()); context_->PSSetShader(fshader->GetShader(), nullptr, 0); context_->VSSetShader(vshader->GetShader(), nullptr, 0); @@ -648,7 +648,7 @@ rotateVBO: if (result.action == SW_DRAW_PRIMITIVES) { D3D11VertexShader *vshader; D3D11FragmentShader *fshader; - shaderManager_->GetShaders(prim, lastVType_, &vshader, &fshader, pipelineState_, false, false, decOptions_.expandAllWeightsToFloat); + shaderManager_->GetShaders(prim, lastVType_, &vshader, &fshader, pipelineState_, false, false, decOptions_.expandAllWeightsToFloat, decOptions_.applySkinInDecode); context_->PSSetShader(fshader->GetShader(), nullptr, 0); context_->VSSetShader(vshader->GetShader(), nullptr, 0); shaderManager_->UpdateUniforms(framebufferManager_->UseBufferedRendering()); diff --git a/GPU/D3D11/DrawEngineD3D11.h b/GPU/D3D11/DrawEngineD3D11.h index ca7fb04dbb..03f5f47ad7 100644 --- a/GPU/D3D11/DrawEngineD3D11.h +++ b/GPU/D3D11/DrawEngineD3D11.h @@ -150,7 +150,7 @@ public: void ClearTrackedVertexArrays() override; - void Resized() override; + void NotifyConfigChanged() override; void ClearInputLayoutMap(); diff --git a/GPU/D3D11/GPU_D3D11.cpp b/GPU/D3D11/GPU_D3D11.cpp index 19155b0df5..d1c5edcce3 100644 --- a/GPU/D3D11/GPU_D3D11.cpp +++ b/GPU/D3D11/GPU_D3D11.cpp @@ -176,7 +176,7 @@ void GPU_D3D11::BeginHostFrame() { if (resized_) { gstate_c.useFlags = CheckGPUFeatures(); framebufferManager_->Resized(); - drawEngine_.Resized(); + drawEngine_.NotifyConfigChanged(); textureCache_->NotifyConfigChanged(); shaderManagerD3D11_->DirtyLastShader(); resized_ = false; diff --git a/GPU/D3D11/ShaderManagerD3D11.cpp b/GPU/D3D11/ShaderManagerD3D11.cpp index 0c9fec1817..f8788f6df5 100644 --- a/GPU/D3D11/ShaderManagerD3D11.cpp +++ b/GPU/D3D11/ShaderManagerD3D11.cpp @@ -179,13 +179,13 @@ void ShaderManagerD3D11::BindUniforms() { context_->PSSetConstantBuffers(0, 1, ps_cbs); } -void ShaderManagerD3D11::GetShaders(int prim, u32 vertType, D3D11VertexShader **vshader, D3D11FragmentShader **fshader, const ComputedPipelineState &pipelineState, bool useHWTransform, bool useHWTessellation, bool weightsAsFloat) { +void ShaderManagerD3D11::GetShaders(int prim, u32 vertType, D3D11VertexShader **vshader, D3D11FragmentShader **fshader, const ComputedPipelineState &pipelineState, bool useHWTransform, bool useHWTessellation, bool weightsAsFloat, bool useSkinInDecode) { VShaderID VSID; FShaderID FSID; if (gstate_c.IsDirty(DIRTY_VERTEXSHADER_STATE)) { gstate_c.Clean(DIRTY_VERTEXSHADER_STATE); - ComputeVertexShaderID(&VSID, vertType, useHWTransform, useHWTessellation, weightsAsFloat); + ComputeVertexShaderID(&VSID, vertType, useHWTransform, useHWTessellation, weightsAsFloat, useSkinInDecode); } else { VSID = lastVSID_; } diff --git a/GPU/D3D11/ShaderManagerD3D11.h b/GPU/D3D11/ShaderManagerD3D11.h index 0f7a297965..d239daff8f 100644 --- a/GPU/D3D11/ShaderManagerD3D11.h +++ b/GPU/D3D11/ShaderManagerD3D11.h @@ -85,7 +85,7 @@ public: ShaderManagerD3D11(Draw::DrawContext *draw, ID3D11Device *device, ID3D11DeviceContext *context, D3D_FEATURE_LEVEL featureLevel); ~ShaderManagerD3D11(); - void GetShaders(int prim, u32 vertType, D3D11VertexShader **vshader, D3D11FragmentShader **fshader, const ComputedPipelineState &pipelineState, bool useHWTransform, bool useHWTessellation, bool weightsAsFloat); + void GetShaders(int prim, u32 vertType, D3D11VertexShader **vshader, D3D11FragmentShader **fshader, const ComputedPipelineState &pipelineState, bool useHWTransform, bool useHWTessellation, bool weightsAsFloat, bool useSkinInDecode); void ClearShaders(); void DirtyLastShader() override; diff --git a/GPU/Directx9/DrawEngineDX9.cpp b/GPU/Directx9/DrawEngineDX9.cpp index 8d0bac74ea..40790c1648 100644 --- a/GPU/Directx9/DrawEngineDX9.cpp +++ b/GPU/Directx9/DrawEngineDX9.cpp @@ -349,7 +349,7 @@ void DrawEngineDX9::DoFlush() { // Cannot cache vertex data with morph enabled. bool useCache = g_Config.bVertexCache && !(lastVType_ & GE_VTYPE_MORPHCOUNT_MASK); // Also avoid caching when software skinning. - if (g_Config.bSoftwareSkinning && (lastVType_ & GE_VTYPE_WEIGHT_MASK)) + if (decOptions_.applySkinInDecode && (lastVType_ & GE_VTYPE_WEIGHT_MASK)) useCache = false; if (useCache) { @@ -522,7 +522,7 @@ rotateVBO: ApplyDrawState(prim); ApplyDrawStateLate(); - VSShader *vshader = shaderManager_->ApplyShader(true, useHWTessellation_, lastVType_, decOptions_.expandAllWeightsToFloat, pipelineState_); + VSShader *vshader = shaderManager_->ApplyShader(true, useHWTessellation_, lastVType_, decOptions_.expandAllWeightsToFloat, decOptions_.applySkinInDecode, pipelineState_); IDirect3DVertexDeclaration9 *pHardwareVertexDecl = SetupDecFmtForDraw(vshader, dec_->GetDecVtxFmt(), dec_->VertexType()); if (pHardwareVertexDecl) { @@ -613,7 +613,7 @@ rotateVBO: ApplyDrawStateLate(); - VSShader *vshader = shaderManager_->ApplyShader(false, false, lastVType_, decOptions_.expandAllWeightsToFloat, pipelineState_); + VSShader *vshader = shaderManager_->ApplyShader(false, false, lastVType_, decOptions_.expandAllWeightsToFloat, decOptions_.applySkinInDecode, pipelineState_); if (result.action == SW_DRAW_PRIMITIVES) { if (result.setStencil) { diff --git a/GPU/Directx9/GPU_DX9.cpp b/GPU/Directx9/GPU_DX9.cpp index 32d9d248c4..beb701796a 100644 --- a/GPU/Directx9/GPU_DX9.cpp +++ b/GPU/Directx9/GPU_DX9.cpp @@ -165,9 +165,9 @@ void GPU_DX9::BeginHostFrame() { if (resized_) { gstate_c.useFlags = CheckGPUFeatures(); framebufferManager_->Resized(); - drawEngine_.Resized(); - shaderManagerDX9_->DirtyShader(); + drawEngine_.NotifyConfigChanged(); textureCache_->NotifyConfigChanged(); + shaderManagerDX9_->DirtyShader(); resized_ = false; } } diff --git a/GPU/Directx9/ShaderManagerDX9.cpp b/GPU/Directx9/ShaderManagerDX9.cpp index 1e56e5ab37..0b419cfe76 100644 --- a/GPU/Directx9/ShaderManagerDX9.cpp +++ b/GPU/Directx9/ShaderManagerDX9.cpp @@ -544,11 +544,11 @@ void ShaderManagerDX9::DirtyLastShader() { // disables vertex arrays lastPShader_ = nullptr; } -VSShader *ShaderManagerDX9::ApplyShader(bool useHWTransform, bool useHWTessellation, u32 vertType, bool weightsAsFloat, const ComputedPipelineState &pipelineState) { +VSShader *ShaderManagerDX9::ApplyShader(bool useHWTransform, bool useHWTessellation, u32 vertType, bool weightsAsFloat, bool useSkinInDecode, const ComputedPipelineState &pipelineState) { VShaderID VSID; if (gstate_c.IsDirty(DIRTY_VERTEXSHADER_STATE)) { gstate_c.Clean(DIRTY_VERTEXSHADER_STATE); - ComputeVertexShaderID(&VSID, vertType, useHWTransform, useHWTessellation, weightsAsFloat); + ComputeVertexShaderID(&VSID, vertType, useHWTransform, useHWTessellation, weightsAsFloat, useSkinInDecode); } else { VSID = lastVSID_; } @@ -597,7 +597,7 @@ VSShader *ShaderManagerDX9::ApplyShader(bool useHWTransform, bool useHWTessellat } delete vs; - ComputeVertexShaderID(&VSID, vertType, false, false, weightsAsFloat); + ComputeVertexShaderID(&VSID, vertType, false, false, weightsAsFloat, useSkinInDecode); // TODO: Look for existing shader with the appropriate ID, use that instead of generating a new one - however, need to make sure // that that shader ID is not used when computing the linked shader ID below, because then IDs won't match diff --git a/GPU/Directx9/ShaderManagerDX9.h b/GPU/Directx9/ShaderManagerDX9.h index 9c7404d856..6ee812b2e6 100644 --- a/GPU/Directx9/ShaderManagerDX9.h +++ b/GPU/Directx9/ShaderManagerDX9.h @@ -78,7 +78,7 @@ public: ~ShaderManagerDX9(); void ClearCache(bool deleteThem); // TODO: deleteThem currently not respected - VSShader *ApplyShader(bool useHWTransform, bool useHWTessellation, u32 vertType, bool weightsAsFloat, const ComputedPipelineState &pipelineState); + VSShader *ApplyShader(bool useHWTransform, bool useHWTessellation, u32 vertType, bool weightsAsFloat, bool useSkinInDecode, const ComputedPipelineState &pipelineState); void DirtyShader(); void DirtyLastShader() override; diff --git a/GPU/GLES/DrawEngineGLES.cpp b/GPU/GLES/DrawEngineGLES.cpp index dd3395abd2..318cb19a02 100644 --- a/GPU/GLES/DrawEngineGLES.cpp +++ b/GPU/GLES/DrawEngineGLES.cpp @@ -267,7 +267,7 @@ void DrawEngineGLES::DoFlush() { GEPrimitiveType prim = prevPrim_; VShaderID vsid; - Shader *vshader = shaderManager_->ApplyVertexShader(CanUseHardwareTransform(prim), useHWTessellation_, lastVType_, decOptions_.expandAllWeightsToFloat, &vsid); + Shader *vshader = shaderManager_->ApplyVertexShader(CanUseHardwareTransform(prim), useHWTessellation_, lastVType_, decOptions_.expandAllWeightsToFloat, decOptions_.applySkinInDecode, &vsid); GLRBuffer *vertexBuffer = nullptr; GLRBuffer *indexBuffer = nullptr; @@ -278,7 +278,7 @@ void DrawEngineGLES::DoFlush() { int vertexCount = 0; bool useElements = true; - if (g_Config.bSoftwareSkinning && (lastVType_ & GE_VTYPE_WEIGHT_MASK)) { + if (decOptions_.applySkinInDecode && (lastVType_ & GE_VTYPE_WEIGHT_MASK)) { // If software skinning, we've already predecoded into "decoded". So push that content. size_t size = decodedVerts_ * dec_->GetDecVtxFmt().stride; u8 *dest = (u8 *)frameData.pushVertex->Push(size, &vertexBufferOffset, &vertexBuffer); diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index b6b2b6a661..1798960b4d 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -291,9 +291,9 @@ void GPU_GLES::BeginHostFrame() { if (resized_) { gstate_c.useFlags = CheckGPUFeatures(); framebufferManager_->Resized(); - drawEngine_.Resized(); - shaderManagerGL_->DirtyShader(); + drawEngine_.NotifyConfigChanged(); textureCache_->NotifyConfigChanged(); + shaderManagerGL_->DirtyShader(); resized_ = false; } diff --git a/GPU/GLES/ShaderManagerGLES.cpp b/GPU/GLES/ShaderManagerGLES.cpp index e4a6350de1..c976e79b5c 100644 --- a/GPU/GLES/ShaderManagerGLES.cpp +++ b/GPU/GLES/ShaderManagerGLES.cpp @@ -754,10 +754,10 @@ Shader *ShaderManagerGLES::CompileVertexShader(VShaderID VSID) { return new Shader(render_, codeBuffer_, desc, params); } -Shader *ShaderManagerGLES::ApplyVertexShader(bool useHWTransform, bool useHWTessellation, u32 vertType, bool weightsAsFloat, VShaderID *VSID) { +Shader *ShaderManagerGLES::ApplyVertexShader(bool useHWTransform, bool useHWTessellation, u32 vertType, bool weightsAsFloat, bool useSkinInDecode, VShaderID *VSID) { if (gstate_c.IsDirty(DIRTY_VERTEXSHADER_STATE)) { gstate_c.Clean(DIRTY_VERTEXSHADER_STATE); - ComputeVertexShaderID(VSID, vertType, useHWTransform, useHWTessellation, weightsAsFloat); + ComputeVertexShaderID(VSID, vertType, useHWTransform, useHWTessellation, weightsAsFloat, useSkinInDecode); } else { *VSID = lastVSID_; } @@ -788,7 +788,7 @@ Shader *ShaderManagerGLES::ApplyVertexShader(bool useHWTransform, bool useHWTess // Can still work with software transform. VShaderID vsidTemp; - ComputeVertexShaderID(&vsidTemp, vertType, false, false, weightsAsFloat); + ComputeVertexShaderID(&vsidTemp, vertType, false, false, weightsAsFloat, useSkinInDecode); vs = CompileVertexShader(vsidTemp); } diff --git a/GPU/GLES/ShaderManagerGLES.h b/GPU/GLES/ShaderManagerGLES.h index a937318dd1..97ffe6c010 100644 --- a/GPU/GLES/ShaderManagerGLES.h +++ b/GPU/GLES/ShaderManagerGLES.h @@ -161,7 +161,7 @@ public: // This is the old ApplyShader split into two parts, because of annoying information dependencies. // If you call ApplyVertexShader, you MUST call ApplyFragmentShader soon afterwards. - Shader *ApplyVertexShader(bool useHWTransform, bool useHWTessellation, u32 vertType, bool weightsAsFloat, VShaderID *VSID); + Shader *ApplyVertexShader(bool useHWTransform, bool useHWTessellation, u32 vertType, bool weightsAsFloat, bool useSkinInDecode, VShaderID *VSID); LinkedShader *ApplyFragmentShader(VShaderID VSID, Shader *vs, const ComputedPipelineState &pipelineState, u32 vertType, bool useBufferedRendering); void DeviceLost(); diff --git a/GPU/GPUState.cpp b/GPU/GPUState.cpp index 374816fa76..bae93b34b1 100644 --- a/GPU/GPUState.cpp +++ b/GPU/GPUState.cpp @@ -261,10 +261,7 @@ void GPUgstate::Restore(u32_le *ptr) { } bool vertTypeIsSkinningEnabled(u32 vertType) { - if (g_Config.bSoftwareSkinning) - return false; - else - return ((vertType & GE_VTYPE_WEIGHT_MASK) != GE_VTYPE_WEIGHT_NONE); + return ((vertType & GE_VTYPE_WEIGHT_MASK) != GE_VTYPE_WEIGHT_NONE); } struct GPUStateCache_v0 { diff --git a/GPU/Software/TransformUnit.cpp b/GPU/Software/TransformUnit.cpp index afd7d15920..731e4078f3 100644 --- a/GPU/Software/TransformUnit.cpp +++ b/GPU/Software/TransformUnit.cpp @@ -257,7 +257,7 @@ void ComputeTransformState(TransformState *state, const VertexReader &vreader) { state->enableLighting = gstate.isLightingEnabled(); state->enableFog = gstate.isFogEnabled(); state->readUV = !gstate.isModeClear() && gstate.isTextureMapEnabled() && vreader.hasUV(); - state->readWeights = vreader.skinningEnabled() && state->enableTransform; + state->readWeights = vreader.skinningEnabled() && state->enableTransform && !g_Config.bSoftwareSkinning; state->negateNormals = gstate.areNormalsReversed(); state->uvGenMode = gstate.getUVGenMode(); diff --git a/GPU/Vulkan/DrawEngineVulkan.cpp b/GPU/Vulkan/DrawEngineVulkan.cpp index f54afee3a9..01c356f34d 100644 --- a/GPU/Vulkan/DrawEngineVulkan.cpp +++ b/GPU/Vulkan/DrawEngineVulkan.cpp @@ -599,7 +599,7 @@ void DrawEngineVulkan::DoFlush() { // Also avoid caching when software skinning. VkBuffer vbuf = VK_NULL_HANDLE; VkBuffer ibuf = VK_NULL_HANDLE; - if (g_Config.bSoftwareSkinning && (lastVType_ & GE_VTYPE_WEIGHT_MASK)) { + if (decOptions_.applySkinInDecode && (lastVType_ & GE_VTYPE_WEIGHT_MASK)) { useCache = false; } @@ -739,7 +739,7 @@ void DrawEngineVulkan::DoFlush() { break; } } else { - if (g_Config.bSoftwareSkinning && (lastVType_ & GE_VTYPE_WEIGHT_MASK)) { + if (decOptions_.applySkinInDecode && (lastVType_ & GE_VTYPE_WEIGHT_MASK)) { // If software skinning, we've already predecoded into "decoded". So push that content. VkDeviceSize size = decodedVerts_ * dec_->GetDecVtxFmt().stride; u8 *dest = (u8 *)frameData.pushVertex->Push(size, &vbOffset, &vbuf); @@ -784,7 +784,7 @@ void DrawEngineVulkan::DoFlush() { VulkanFragmentShader *fshader = nullptr; VulkanGeometryShader *gshader = nullptr; - shaderManager_->GetShaders(prim, lastVType_, &vshader, &fshader, &gshader, pipelineState_, true, useHWTessellation_, decOptions_.expandAllWeightsToFloat); // usehwtransform + shaderManager_->GetShaders(prim, lastVType_, &vshader, &fshader, &gshader, pipelineState_, true, useHWTessellation_, decOptions_.expandAllWeightsToFloat, decOptions_.applySkinInDecode); if (!vshader) { // We're screwed. return; @@ -919,7 +919,7 @@ void DrawEngineVulkan::DoFlush() { VulkanFragmentShader *fshader = nullptr; VulkanGeometryShader *gshader = nullptr; - shaderManager_->GetShaders(prim, lastVType_, &vshader, &fshader, &gshader, pipelineState_, false, false, decOptions_.expandAllWeightsToFloat); // usehwtransform + shaderManager_->GetShaders(prim, lastVType_, &vshader, &fshader, &gshader, pipelineState_, false, false, decOptions_.expandAllWeightsToFloat, decOptions_.applySkinInDecode); _dbg_assert_msg_(!vshader->UseHWTransform(), "Bad vshader"); VulkanPipeline *pipeline = pipelineManager_->GetOrCreatePipeline(renderManager, pipelineLayout_, pipelineKey_, &dec_->decFmt, vshader, fshader, gshader, false, 0); if (!pipeline || !pipeline->pipeline) { diff --git a/GPU/Vulkan/GPU_Vulkan.cpp b/GPU/Vulkan/GPU_Vulkan.cpp index 12d0328f98..754ef6ffce 100644 --- a/GPU/Vulkan/GPU_Vulkan.cpp +++ b/GPU/Vulkan/GPU_Vulkan.cpp @@ -292,7 +292,7 @@ void GPU_Vulkan::BeginHostFrame() { // In case the GPU changed. BuildReportingInfo(); framebufferManager_->Resized(); - drawEngine_.Resized(); + drawEngine_.NotifyConfigChanged(); textureCache_->NotifyConfigChanged(); resized_ = false; } diff --git a/GPU/Vulkan/ShaderManagerVulkan.cpp b/GPU/Vulkan/ShaderManagerVulkan.cpp index 6356f43e0a..1d478325da 100644 --- a/GPU/Vulkan/ShaderManagerVulkan.cpp +++ b/GPU/Vulkan/ShaderManagerVulkan.cpp @@ -280,11 +280,11 @@ uint64_t ShaderManagerVulkan::UpdateUniforms(bool useBufferedRendering) { return dirty; } -void ShaderManagerVulkan::GetShaders(int prim, u32 vertType, VulkanVertexShader **vshader, VulkanFragmentShader **fshader, VulkanGeometryShader **gshader, const ComputedPipelineState &pipelineState, bool useHWTransform, bool useHWTessellation, bool weightsAsFloat) { +void ShaderManagerVulkan::GetShaders(int prim, u32 vertType, VulkanVertexShader **vshader, VulkanFragmentShader **fshader, VulkanGeometryShader **gshader, const ComputedPipelineState &pipelineState, bool useHWTransform, bool useHWTessellation, bool weightsAsFloat, bool useSkinInDecode) { VShaderID VSID; if (gstate_c.IsDirty(DIRTY_VERTEXSHADER_STATE)) { gstate_c.Clean(DIRTY_VERTEXSHADER_STATE); - ComputeVertexShaderID(&VSID, vertType, useHWTransform, useHWTessellation, weightsAsFloat); + ComputeVertexShaderID(&VSID, vertType, useHWTransform, useHWTessellation, weightsAsFloat, useSkinInDecode); } else { VSID = lastVSID_; } diff --git a/GPU/Vulkan/ShaderManagerVulkan.h b/GPU/Vulkan/ShaderManagerVulkan.h index 88f138d923..8e6ce2636a 100644 --- a/GPU/Vulkan/ShaderManagerVulkan.h +++ b/GPU/Vulkan/ShaderManagerVulkan.h @@ -115,7 +115,7 @@ public: void DeviceLost(); void DeviceRestore(Draw::DrawContext *draw); - void GetShaders(int prim, u32 vertType, VulkanVertexShader **vshader, VulkanFragmentShader **fshader, VulkanGeometryShader **gshader, const ComputedPipelineState &pipelineState, bool useHWTransform, bool useHWTessellation, bool weightsAsFloat); + void GetShaders(int prim, u32 vertType, VulkanVertexShader **vshader, VulkanFragmentShader **fshader, VulkanGeometryShader **gshader, const ComputedPipelineState &pipelineState, bool useHWTransform, bool useHWTessellation, bool weightsAsFloat, bool useSkinInDecode); void ClearShaders(); void DirtyShader(); void DirtyLastShader() override; From 7880eb15c103ec0e95344446f2d4d296f02384e8 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 6 Nov 2022 08:44:22 -0800 Subject: [PATCH 4/6] softgpu: Always use software skinning. There's only software skinning, after all. --- GPU/Common/VertexDecoderCommon.h | 2 -- GPU/Software/TransformUnit.cpp | 34 ++++++++------------------------ GPU/Software/TransformUnit.h | 1 + 3 files changed, 9 insertions(+), 28 deletions(-) diff --git a/GPU/Common/VertexDecoderCommon.h b/GPU/Common/VertexDecoderCommon.h index e4c886cbd4..7c2dcb2cfc 100644 --- a/GPU/Common/VertexDecoderCommon.h +++ b/GPU/Common/VertexDecoderCommon.h @@ -300,8 +300,6 @@ public: bool hasNormal() const { return decFmt_.nrmfmt != 0; } bool hasUV() const { return decFmt_.uvfmt != 0; } bool isThrough() const { return (vtype_ & GE_VTYPE_THROUGH) != 0; } - bool skinningEnabled() const { return vertTypeIsSkinningEnabled(vtype_); } - int numBoneWeights() const { return vertTypeGetNumBoneWeights(vtype_); } void Goto(int index) { data_ = base_ + index * decFmt_.stride; } diff --git a/GPU/Software/TransformUnit.cpp b/GPU/Software/TransformUnit.cpp index 731e4078f3..bc1f8679eb 100644 --- a/GPU/Software/TransformUnit.cpp +++ b/GPU/Software/TransformUnit.cpp @@ -62,6 +62,11 @@ SoftwareDrawEngine::~SoftwareDrawEngine() { FreeMemoryPages(decIndex, DECODED_INDEX_BUFFER_SIZE); } +void SoftwareDrawEngine::NotifyConfigChanged() { + DrawEngineCommon::NotifyConfigChanged(); + decOptions_.applySkinInDecode = true; +} + void SoftwareDrawEngine::DispatchFlush() { transformUnit.Flush("debug"); } @@ -72,7 +77,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(), decOptions_.applySkinInDecode); + uint32_t vertTypeID = GetVertTypeID(gstate.vertType | GE_VTYPE_POS_FLOAT, gstate.getUVGenMode(), true); int flipCull = cullMode != gstate.getCullMode() ? 1 : 0; // TODO: For now, just setting all dirty. @@ -137,7 +142,7 @@ void SoftwareDrawEngine::DispatchSubmitImm(GEPrimitiveType prim, TransformedVert } VertexDecoder *SoftwareDrawEngine::FindVertexDecoder(u32 vtype) { - const u32 vertTypeID = GetVertTypeID(vtype, gstate.getUVGenMode(), decOptions_.applySkinInDecode); + const u32 vertTypeID = GetVertTypeID(vtype, gstate.getUVGenMode(), true); return DrawEngineCommon::GetVertexDecoder(vertTypeID); } @@ -245,7 +250,6 @@ struct TransformState { bool enableLighting : 1; bool enableFog : 1; bool readUV : 1; - bool readWeights : 1; bool negateNormals : 1; uint8_t uvGenMode : 2; uint8_t matrixMode : 2; @@ -257,7 +261,6 @@ void ComputeTransformState(TransformState *state, const VertexReader &vreader) { state->enableLighting = gstate.isLightingEnabled(); state->enableFog = gstate.isFogEnabled(); state->readUV = !gstate.isModeClear() && gstate.isTextureMapEnabled() && vreader.hasUV(); - state->readWeights = vreader.skinningEnabled() && state->enableTransform && !g_Config.bSoftwareSkinning; state->negateNormals = gstate.areNormalsReversed(); state->uvGenMode = gstate.getUVGenMode(); @@ -344,27 +347,6 @@ ClipVertexData TransformUnit::ReadVertex(VertexReader &vreader, const TransformS if (state.negateNormals) normal = -normal; - if (state.readWeights) { - float W[8] = { 1.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f }; - vreader.ReadWeights(W); - - Vec3 tmppos(0.f, 0.f, 0.f); - Vec3 tmpnrm(0.f, 0.f, 0.f); - - for (int i = 0; i < vreader.numBoneWeights(); ++i) { - Vec3 step = Vec3ByMatrix43(pos, gstate.boneMatrix + i * 12); - tmppos += step * W[i]; - if (vreader.hasNormal()) { - step = Norm3ByMatrix43(normal, gstate.boneMatrix + i * 12); - tmpnrm += step * W[i]; - } - } - - pos = tmppos; - if (vreader.hasNormal()) - normal = tmpnrm; - } - if (vreader.hasColor0()) { vreader.ReadColor0_8888((u8 *)&vertex.v.color0); } else { @@ -858,7 +840,7 @@ void TransformUnit::SubmitImmVertex(const ClipVertexData &vert, SoftwareDrawEngi break; } - uint32_t vertTypeID = GetVertTypeID(gstate.vertType | GE_VTYPE_POS_FLOAT, gstate.getUVGenMode(), g_Config.bSoftwareSkinning); + uint32_t vertTypeID = GetVertTypeID(gstate.vertType | GE_VTYPE_POS_FLOAT, gstate.getUVGenMode(), true); // 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); diff --git a/GPU/Software/TransformUnit.h b/GPU/Software/TransformUnit.h index 3c022523d2..a55c824a91 100644 --- a/GPU/Software/TransformUnit.h +++ b/GPU/Software/TransformUnit.h @@ -171,6 +171,7 @@ public: SoftwareDrawEngine(); ~SoftwareDrawEngine(); + void NotifyConfigChanged() override; void DispatchFlush() override; void DispatchSubmitPrim(const void *verts, const void *inds, GEPrimitiveType prim, int vertexCount, u32 vertType, int cullMode, int *bytesRead) override; void DispatchSubmitImm(GEPrimitiveType prim, TransformedVertex *buffer, int vertexCount, int cullMode, bool continuation) override; From 3de2557ecb50aba2ea59e61c4900918a5d99b725 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 6 Nov 2022 08:55:07 -0800 Subject: [PATCH 5/6] GPU: Always skin in decode for software transform. --- GPU/Common/SoftwareTransformCommon.cpp | 81 +++++--------------------- GPU/D3D11/DrawEngineD3D11.cpp | 2 + GPU/Directx9/DrawEngineDX9.cpp | 2 + GPU/GLES/DrawEngineGLES.cpp | 3 + GPU/Vulkan/DrawEngineVulkan.cpp | 3 + 5 files changed, 24 insertions(+), 67 deletions(-) diff --git a/GPU/Common/SoftwareTransformCommon.cpp b/GPU/Common/SoftwareTransformCommon.cpp index dc86e9ec13..67ba97af4c 100644 --- a/GPU/Common/SoftwareTransformCommon.cpp +++ b/GPU/Common/SoftwareTransformCommon.cpp @@ -168,29 +168,6 @@ void SoftwareTransform::SetProjMatrix(float mtx[14], bool invertedX, bool invert projMatrix_.translateAndScale(trans, scale); } -static void ReadWeightedNormal(Vec3f &source, VertexReader &reader, u32 vertType, bool skinningEnabled) { - if (reader.hasNormal()) - reader.ReadNrm(source.AsArray()); - if (skinningEnabled) { - float weights[8]; - reader.ReadWeights(weights); - - // Have to recalculate this, unfortunately. Please use software skinning... - Vec3f nsum(0, 0, 0); - for (int i = 0; i < vertTypeGetNumBoneWeights(vertType); i++) { - if (weights[i] != 0.0f) { - Vec3f norm; - Norm3ByMatrix43(norm.AsArray(), source.AsArray(), gstate.boneMatrix + i * 12); - nsum += norm * weights[i]; - } - } - - source = nsum; - } - if (gstate.areNormalsReversed()) - source = -source; -} - void SoftwareTransform::Decode(int prim, u32 vertType, const DecVtxFormat &decVtxFormat, int maxIndex, SoftwareTransformResult *result) { u8 *decoded = params_.decoded; TransformedVertex *transformed = params_.transformed; @@ -204,8 +181,6 @@ void SoftwareTransform::Decode(int prim, u32 vertType, const DecVtxFormat &decVt vscale /= gstate_c.curTextureHeight; } - bool skinningEnabled = vertTypeIsSkinningEnabled(vertType) && !g_Config.bSoftwareSkinning; - const int w = gstate.getTextureWidth(0); const int h = gstate.getTextureHeight(0); float widthFactor = (float) w / (float) gstate_c.curTextureWidth; @@ -296,47 +271,13 @@ void SoftwareTransform::Decode(int prim, u32 vertType, const DecVtxFormat &decVt if (reader.hasNormal()) reader.ReadNrm(normal.AsArray()); - if (!skinningEnabled) { - Vec3ByMatrix43(out, pos, gstate.worldMatrix); - if (reader.hasNormal()) { - if (gstate.areNormalsReversed()) { - normal = -normal; - } - Norm3ByMatrix43(worldnormal.AsArray(), normal.AsArray(), gstate.worldMatrix); - worldnormal = worldnormal.NormalizedOr001(cpu_info.bSSE4_1); - } - } else { - float weights[8]; - // For flat, we need the vertex weights. - reader.Goto(index); - reader.ReadWeights(weights); - - // Skinning - Vec3f psum(0, 0, 0); - Vec3f nsum(0, 0, 0); - for (int i = 0; i < vertTypeGetNumBoneWeights(vertType); i++) { - if (weights[i] != 0.0f) { - Vec3ByMatrix43(out, pos, gstate.boneMatrix+i*12); - Vec3f tpos(out); - psum += tpos * weights[i]; - if (reader.hasNormal()) { - Vec3f norm; - Norm3ByMatrix43(norm.AsArray(), normal.AsArray(), gstate.boneMatrix+i*12); - nsum += norm * weights[i]; - } - } - } - - // Yes, we really must multiply by the world matrix too. - Vec3ByMatrix43(out, psum.AsArray(), gstate.worldMatrix); - if (reader.hasNormal()) { - normal = nsum; - if (gstate.areNormalsReversed()) { - normal = -normal; - } - Norm3ByMatrix43(worldnormal.AsArray(), normal.AsArray(), gstate.worldMatrix); - worldnormal = worldnormal.NormalizedOr001(cpu_info.bSSE4_1); + Vec3ByMatrix43(out, pos, gstate.worldMatrix); + if (reader.hasNormal()) { + if (gstate.areNormalsReversed()) { + normal = -normal; } + Norm3ByMatrix43(worldnormal.AsArray(), normal.AsArray(), gstate.worldMatrix); + worldnormal = worldnormal.NormalizedOr001(cpu_info.bSSE4_1); } // Perform lighting here if enabled. @@ -398,7 +339,10 @@ void SoftwareTransform::Decode(int prim, u32 vertType, const DecVtxFormat &decVt source = normal.Normalized(cpu_info.bSSE4_1); } else { reader.Goto(index); - ReadWeightedNormal(source, reader, vertType, skinningEnabled); + if (reader.hasNormal()) + reader.ReadNrm(source.AsArray()); + if (gstate.areNormalsReversed()) + source = -source; source.Normalize(); } if (!reader.hasNormal()) { @@ -413,7 +357,10 @@ void SoftwareTransform::Decode(int prim, u32 vertType, const DecVtxFormat &decVt } else { // Need to read the normal for this vertex and weight it again.. reader.Goto(index); - ReadWeightedNormal(source, reader, vertType, skinningEnabled); + if (reader.hasNormal()) + reader.ReadNrm(source.AsArray()); + if (gstate.areNormalsReversed()) + source = -source; } if (!reader.hasNormal()) { ERROR_LOG_REPORT(G3D, "Normal projection mapping without normal?"); diff --git a/GPU/D3D11/DrawEngineD3D11.cpp b/GPU/D3D11/DrawEngineD3D11.cpp index 2a537a83a3..e0c33e5d76 100644 --- a/GPU/D3D11/DrawEngineD3D11.cpp +++ b/GPU/D3D11/DrawEngineD3D11.cpp @@ -581,6 +581,7 @@ rotateVBO: } } else { PROFILE_THIS_SCOPE("soft"); + decOptions_.applySkinInDecode = true; DecodeVerts(decoded); bool hasColor = (lastVType_ & GE_VTYPE_COL_MASK) != GE_VTYPE_COL_NONE; if (gstate.isModeThrough()) { @@ -709,6 +710,7 @@ rotateVBO: framebufferManager_->ApplyClearToMemory(scissorX1, scissorY1, scissorX2, scissorY2, clearColor); } } + decOptions_.applySkinInDecode = g_Config.bSoftwareSkinning; } gpuStats.numDrawCalls += numDrawCalls; diff --git a/GPU/Directx9/DrawEngineDX9.cpp b/GPU/Directx9/DrawEngineDX9.cpp index 40790c1648..33117be1c9 100644 --- a/GPU/Directx9/DrawEngineDX9.cpp +++ b/GPU/Directx9/DrawEngineDX9.cpp @@ -546,6 +546,7 @@ rotateVBO: } } } else { + decOptions_.applySkinInDecode = true; DecodeVerts(decoded); bool hasColor = (lastVType_ & GE_VTYPE_COL_MASK) != GE_VTYPE_COL_NONE; if (gstate.isModeThrough()) { @@ -653,6 +654,7 @@ rotateVBO: framebufferManager_->ApplyClearToMemory(scissorX1, scissorY1, scissorX2, scissorY2, clearColor); } } + decOptions_.applySkinInDecode = g_Config.bSoftwareSkinning; } gpuStats.numDrawCalls += numDrawCalls; diff --git a/GPU/GLES/DrawEngineGLES.cpp b/GPU/GLES/DrawEngineGLES.cpp index 318cb19a02..e95afe57ed 100644 --- a/GPU/GLES/DrawEngineGLES.cpp +++ b/GPU/GLES/DrawEngineGLES.cpp @@ -331,7 +331,9 @@ void DrawEngineGLES::DoFlush() { } } else { PROFILE_THIS_SCOPE("soft"); + decOptions_.applySkinInDecode = true; DecodeVerts(decoded); + bool hasColor = (lastVType_ & GE_VTYPE_COL_MASK) != GE_VTYPE_COL_NONE; if (gstate.isModeThrough()) { gstate_c.vertexFullAlpha = gstate_c.vertexFullAlpha && (hasColor || gstate.getMaterialAmbientA() == 255); @@ -446,6 +448,7 @@ void DrawEngineGLES::DoFlush() { } gstate_c.Dirty(DIRTY_BLEND_STATE); // Make sure the color mask gets re-applied. } + decOptions_.applySkinInDecode = g_Config.bSoftwareSkinning; } gpuStats.numDrawCalls += numDrawCalls; diff --git a/GPU/Vulkan/DrawEngineVulkan.cpp b/GPU/Vulkan/DrawEngineVulkan.cpp index 01c356f34d..d8c8b740e5 100644 --- a/GPU/Vulkan/DrawEngineVulkan.cpp +++ b/GPU/Vulkan/DrawEngineVulkan.cpp @@ -841,6 +841,7 @@ void DrawEngineVulkan::DoFlush() { } } else { PROFILE_THIS_SCOPE("soft"); + decOptions_.applySkinInDecode = true; DecodeVerts(decoded); bool hasColor = (lastVType_ & GE_VTYPE_COL_MASK) != GE_VTYPE_COL_NONE; if (gstate.isModeThrough()) { @@ -927,6 +928,7 @@ void DrawEngineVulkan::DoFlush() { decodedVerts_ = 0; numDrawCalls = 0; decodeCounter_ = 0; + decOptions_.applySkinInDecode = g_Config.bSoftwareSkinning; return; } BindShaderBlendTex(); // This might cause copies so super important to do before BindPipeline. @@ -994,6 +996,7 @@ void DrawEngineVulkan::DoFlush() { framebufferManager_->ApplyClearToMemory(scissorX1, scissorY1, scissorX2, scissorY2, result.color); } } + decOptions_.applySkinInDecode = g_Config.bSoftwareSkinning; } gpuStats.numDrawCalls += numDrawCalls; From 527947fd81c09804606b867677ab590d24d2f391 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 6 Nov 2022 09:06:07 -0800 Subject: [PATCH 6/6] GPU: Correct softgpu curve issue. --- GPU/Common/DrawEngineCommon.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GPU/Common/DrawEngineCommon.cpp b/GPU/Common/DrawEngineCommon.cpp index e02da46179..664b90823e 100644 --- a/GPU/Common/DrawEngineCommon.cpp +++ b/GPU/Common/DrawEngineCommon.cpp @@ -514,7 +514,7 @@ u32 DrawEngineCommon::NormalizeVertices(u8 *outPtr, u8 *bufPtr, const u8 *inPtr, }; // Let's have two separate loops, one for non skinning and one for skinning. - if (!g_Config.bSoftwareSkinning && (vertType & GE_VTYPE_WEIGHT_MASK) != GE_VTYPE_WEIGHT_NONE) { + if (!dec->skinInDecode && (vertType & GE_VTYPE_WEIGHT_MASK) != GE_VTYPE_WEIGHT_NONE) { int numBoneWeights = vertTypeGetNumBoneWeights(vertType); for (int i = lowerBound; i <= upperBound; i++) { reader.Goto(i - lowerBound);