diff --git a/Source/gs/GSH_Vulkan/GSH_Vulkan.cpp b/Source/gs/GSH_Vulkan/GSH_Vulkan.cpp index ca97ec8fcf..2262f3ba5f 100644 --- a/Source/gs/GSH_Vulkan/GSH_Vulkan.cpp +++ b/Source/gs/GSH_Vulkan/GSH_Vulkan.cpp @@ -258,6 +258,7 @@ void CGSH_Vulkan::ResetImpl() m_primitiveType = PRIM_INVALID; m_pendingPrim = false; m_pendingPrimValue = 0; + m_regState.isValid = false; memset(&m_clutStates, 0, sizeof(m_clutStates)); memset(m_memoryCache, 0, RAMSIZE); WriteBackMemoryCache(); @@ -739,6 +740,8 @@ void CGSH_Vulkan::SetRenderingContext(uint64 primReg) auto zbuf = make_convertible(m_nReg[GS_REG_ZBUF_1 + context]); auto tex0 = make_convertible(m_nReg[GS_REG_TEX0_1 + context]); auto tex1 = make_convertible(m_nReg[GS_REG_TEX1_1 + context]); + auto miptbp1 = make_convertible(m_nReg[GS_REG_MIPTBP1_1 + context]); + auto miptbp2 = make_convertible(m_nReg[GS_REG_MIPTBP2_1 + context]); auto clamp = make_convertible(m_nReg[GS_REG_CLAMP_1 + context]); auto alpha = make_convertible(m_nReg[GS_REG_ALPHA_1 + context]); auto scissor = make_convertible(m_nReg[GS_REG_SCISSOR_1 + context]); @@ -798,8 +801,6 @@ void CGSH_Vulkan::SetRenderingContext(uint64 primReg) uint32 texBufWidth = tex0.GetBufWidth(); uint32 texMipLevel = 0; - CDraw::MipBufs mipBufs; - if(prim.nTexture) { bool minLinear = false; @@ -836,15 +837,9 @@ void CGSH_Vulkan::SetRenderingContext(uint64 primReg) } else { - //Check if game uses nearest mip - bool mipNearest = - (tex1.nMinFilter == MIN_FILTER_NEAREST_MIP_NEAREST) || - (tex1.nMinFilter == MIN_FILTER_LINEAR_MIP_NEAREST); - if(mipNearest) + bool hasMip = (tex1.nMinFilter >= MIN_FILTER_NEAREST_MIP_NEAREST); + if(hasMip) { - auto miptbp1 = make_convertible(m_nReg[GS_REG_MIPTBP1_1 + context]); - auto miptbp2 = make_convertible(m_nReg[GS_REG_MIPTBP2_1 + context]); - if(tex1.nLODMethod == LOD_CALC_STATIC) { int k = trunc(tex1.GetK()); @@ -858,15 +853,6 @@ void CGSH_Vulkan::SetRenderingContext(uint64 primReg) } else { - for(int i = 1; i <= tex1.nMaxMip; i++) - { - mipBufs[i - 1] = GetMipLevelInfo(i, miptbp1, miptbp2); - } - for(int i = tex1.nMaxMip + 1; i <= 6; i++) - { - mipBufs[i - 1] = std::pair(0, 0); - } - pipelineCaps.textureUseDynamicMipLOD = true; } } @@ -976,8 +962,22 @@ void CGSH_Vulkan::SetRenderingContext(uint64 primReg) m_draw->SetFramebufferParams(frame.GetBasePtr(), frame.GetWidth(), fbWriteMask); m_draw->SetDepthbufferParams(zbuf.GetBasePtr(), frame.GetWidth()); m_draw->SetTextureParams(texBufPtr, texBufWidth, tex0.GetWidth(), tex0.GetHeight(), texMipLevel, tex0.nCSA * 0x10); - if(pipelineCaps.textureUseDynamicMipLOD) - { + if( + pipelineCaps.textureUseDynamicMipLOD && + (!m_regState.isValid || + (m_regState.tex1 != tex1) || + (m_regState.miptbp1 != miptbp1) || + (m_regState.miptbp2 != miptbp2))) + { + CDraw::MipBufs mipBufs; + for(int i = 1; i <= tex1.nMaxMip; i++) + { + mipBufs[i - 1] = GetMipLevelInfo(i, miptbp1, miptbp2); + } + for(int i = tex1.nMaxMip + 1; i <= 6; i++) + { + mipBufs[i - 1] = std::pair(0, 0); + } m_draw->SetMipParams(mipBufs, tex1.nMaxMip, tex1.GetK(), tex1.nLODL); } m_draw->SetTextureAlphaParams(texA.nTA0, texA.nTA1); @@ -1001,6 +1001,11 @@ void CGSH_Vulkan::SetRenderingContext(uint64 primReg) m_texWidth = tex0.GetWidth(); m_texHeight = tex0.GetHeight(); + + m_regState.isValid = true; + m_regState.tex1 = tex1; + m_regState.miptbp1 = miptbp1; + m_regState.miptbp2 = miptbp2; } void CGSH_Vulkan::Prim_Point() diff --git a/Source/gs/GSH_Vulkan/GSH_Vulkan.h b/Source/gs/GSH_Vulkan/GSH_Vulkan.h index adebdeaffe..5904fedeb7 100644 --- a/Source/gs/GSH_Vulkan/GSH_Vulkan.h +++ b/Source/gs/GSH_Vulkan/GSH_Vulkan.h @@ -90,6 +90,14 @@ class CGSH_Vulkan : public CGSHandler, public CGsDebuggerInterface CLUT_CACHE_SIZE = 32, }; + struct REG_STATE + { + bool isValid = false; + uint64 tex1 = 0; + uint64 miptbp1 = 0; + uint64 miptbp2 = 0; + }; + struct LOCAL_TO_HOST_XFER_HISTORY { static constexpr int MAX_FRAME_COUNT = 16; @@ -236,6 +244,7 @@ class CGSH_Vulkan : public CGSHandler, public CGsDebuggerInterface uint64 m_pendingPrimValue = 0; uint32 m_primitiveType = 0; PRMODE m_primitiveMode; + REG_STATE m_regState; uint32 m_fbBasePtr = 0; float m_primOfsX = 0; float m_primOfsY = 0; diff --git a/Source/gs/GSH_Vulkan/GSH_VulkanDraw.cpp b/Source/gs/GSH_Vulkan/GSH_VulkanDraw.cpp index 9b5327bc67..b945cb1808 100644 --- a/Source/gs/GSH_Vulkan/GSH_VulkanDraw.cpp +++ b/Source/gs/GSH_Vulkan/GSH_VulkanDraw.cpp @@ -114,22 +114,19 @@ void CDraw::SetTextureParams(uint32 bufAddr, uint32 bufWidth, uint32 width, uint void CDraw::SetMipParams(const MipBufs& mipBufs, uint32 maxMip, float lodK, uint32 lodL) { assert(m_pipelineCaps.textureUseDynamicMipLOD); - bool changed = false; - auto& frame = m_frames[m_frameCommandBuffer->GetCurrentFrame()]; - auto mipParamsUniforms = frame.mipParamsBufferPtr + m_mipParamsIndex; - changed |= (mipBufs != mipParamsUniforms->mipBufs); - changed |= (maxMip != mipParamsUniforms->maxMip); - changed |= (lodK != mipParamsUniforms->lodK); - changed |= (lodL != mipParamsUniforms->lodL); - if(!changed) return; + //Assume it's always dirty, check for changes should be done by caller FlushVertices(); + auto& frame = m_frames[m_frameCommandBuffer->GetCurrentFrame()]; m_mipParamsIndex++; - mipParamsUniforms++; assert(m_mipParamsIndex < MAX_MIPPARAMS_COUNT); - mipParamsUniforms->mipBufs = mipBufs; - mipParamsUniforms->maxMip = maxMip; - mipParamsUniforms->lodK = lodK; - mipParamsUniforms->lodL = lodL; + if(m_mipParamsIndex < MAX_MIPPARAMS_COUNT) + { + auto mipParamsUniforms = frame.mipParamsBufferPtr + m_mipParamsIndex; + mipParamsUniforms->mipBufs = mipBufs; + mipParamsUniforms->maxMip = maxMip; + mipParamsUniforms->lodK = lodK; + mipParamsUniforms->lodL = lodL; + } } void CDraw::SetClutBufferOffset(uint32 clutBufferOffset)