From 1b2f87bf1a31a7842ab39a66dc3618fbf24d3c0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 30 Jun 2026 16:24:15 +0200 Subject: [PATCH 1/5] Rename GPUgstate to GEState --- GPU/Common/FramebufferManagerCommon.cpp | 2 +- GPU/Common/FramebufferManagerCommon.h | 6 +++--- GPU/Common/GPUDebugInterface.cpp | 2 +- GPU/Common/GPUStateUtils.h | 2 +- GPU/Common/ShaderUniforms.cpp | 2 +- GPU/Common/ShaderUniforms.h | 4 ++-- GPU/Common/SoftwareTransformCommon.cpp | 4 ++-- GPU/Common/TextureCacheCommon.cpp | 2 +- GPU/Debugger/Stepping.cpp | 4 ++-- GPU/Debugger/Stepping.h | 2 +- GPU/GPUCommon.cpp | 2 +- GPU/GPUCommon.h | 4 ++-- GPU/GPUState.cpp | 10 +++++----- GPU/GPUState.h | 4 ++-- GPU/GPUStateSIMDUtil.h | 6 +++--- UI/ImDebugger/ImGe.cpp | 2 +- Windows/GEDebugger/GEDebugger.cpp | 18 +++++++++--------- Windows/GEDebugger/GEDebugger.h | 12 ++++++------ Windows/GEDebugger/TabVertices.cpp | 4 ++-- Windows/GEDebugger/TabVertices.h | 4 ++-- 20 files changed, 48 insertions(+), 48 deletions(-) diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index e56122ad26..7d4644b279 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -313,7 +313,7 @@ void FramebufferManagerCommon::EstimateDrawingSize(u32 fb_address, int fb_stride DEBUG_LOG(Log::G3D, "Est: %08x V: %ix%i, R: %ix%i, S: %ix%i, STR: %i, THR:%i, Z:%08x = %ix%i %s", fb_address, viewport_width,viewport_height, region_width, region_height, scissor_width, scissor_height, fb_stride, gstate.isModeThrough(), gstate.isDepthWriteEnabled() ? gstate.getDepthBufAddress() : 0, drawing_width, drawing_height, margin ? " (margin!)" : ""); } -void GetFramebufferHeuristicInputs(FramebufferHeuristicParams *params, const GPUgstate &gstate) { +void GetFramebufferHeuristicInputs(FramebufferHeuristicParams *params, const GEState &gstate) { // GetFramebufferHeuristicInputs is only called from rendering, and thus, it's VRAM. params->fb_address = gstate.getFrameBufRawAddress() | 0x04000000; params->fb_stride = gstate.FrameBufStride(); diff --git a/GPU/Common/FramebufferManagerCommon.h b/GPU/Common/FramebufferManagerCommon.h index 0072a48d18..6bfb46af8f 100644 --- a/GPU/Common/FramebufferManagerCommon.h +++ b/GPU/Common/FramebufferManagerCommon.h @@ -195,10 +195,10 @@ struct FramebufferHeuristicParams { int16_t scissorBottom; }; -struct GPUgstate; -extern GPUgstate gstate; +struct GEState; +extern GEState gstate; -void GetFramebufferHeuristicInputs(FramebufferHeuristicParams *params, const GPUgstate &gstate); +void GetFramebufferHeuristicInputs(FramebufferHeuristicParams *params, const GEState &gstate); enum BindFramebufferColorFlags { BINDFBCOLOR_SKIP_COPY = 0, diff --git a/GPU/Common/GPUDebugInterface.cpp b/GPU/Common/GPUDebugInterface.cpp index 32418754fc..959d6d7c72 100644 --- a/GPU/Common/GPUDebugInterface.cpp +++ b/GPU/Common/GPUDebugInterface.cpp @@ -621,7 +621,7 @@ bool GEExpressionFunctions::parseSymbol(char *str, uint32_t &symbolValue) { } uint32_t GEExpressionFunctions::getReferenceValue(uint32_t referenceIndex) { - GPUgstate state = gpu_->GetGState(); + GEState state = gpu_->GetGState(); if (referenceIndex < 0x100) { GECmdFormat fmt = GECmdInfoByCmd(GECommand(referenceIndex)).cmdFmt; uint32_t value = state.cmdmem[referenceIndex]; diff --git a/GPU/Common/GPUStateUtils.h b/GPU/Common/GPUStateUtils.h index 707d60c505..f43c95b3c7 100644 --- a/GPU/Common/GPUStateUtils.h +++ b/GPU/Common/GPUStateUtils.h @@ -59,7 +59,7 @@ bool NeedsTestDiscard(); bool IsDepthTestEffectivelyDisabled(); bool IsStencilTestOutputDisabled(); -inline bool CanForceBilinear(const GPUgstate &gstate) { +inline bool CanForceBilinear(const GEState &gstate) { return ((!gstate.isColorTestEnabled() || IsColorTestTriviallyTrue()) && (!gstate.isAlphaTestEnabled() || IsAlphaTestTriviallyTrue())); } diff --git a/GPU/Common/ShaderUniforms.cpp b/GPU/Common/ShaderUniforms.cpp index 89a61fed3d..ca27ff6628 100644 --- a/GPU/Common/ShaderUniforms.cpp +++ b/GPU/Common/ShaderUniforms.cpp @@ -254,7 +254,7 @@ void BoneUpdateUniforms(UB_VS_Bones *ub, uint64_t dirtyUniforms) { } } -void UpdateFogCoef(const GPUgstate &state, float fogCoef[2]) { +void UpdateFogCoef(const GEState &state, float fogCoef[2]) { fogCoef[0] = getFloat24(gstate.fog1); fogCoef[1] = getFloat24(gstate.fog2); // The PSP just ignores infnan here (ignoring IEEE), so take it down to a valid float. diff --git a/GPU/Common/ShaderUniforms.h b/GPU/Common/ShaderUniforms.h index 76413051aa..8d48cff974 100644 --- a/GPU/Common/ShaderUniforms.h +++ b/GPU/Common/ShaderUniforms.h @@ -123,10 +123,10 @@ void BoneUpdateUniforms(UB_VS_Bones *ub, uint64_t dirtyUniforms); uint32_t PackLightControlBits(); uint32_t PackDepalBits(); -void UpdateFogCoef(const GPUgstate &state, float fogCoef[2]); +void UpdateFogCoef(const GEState &state, float fogCoef[2]); // This happens so much that I want it inline. -inline void UpdateUVScaleOff(const GPUgstate &state, float uvScaleOff[4]) { +inline void UpdateUVScaleOff(const GEState &state, float uvScaleOff[4]) { float widthFactor; float heightFactor; if (gstate_c.textureIsFramebuffer) { diff --git a/GPU/Common/SoftwareTransformCommon.cpp b/GPU/Common/SoftwareTransformCommon.cpp index 9f9289c714..0c100d8c51 100644 --- a/GPU/Common/SoftwareTransformCommon.cpp +++ b/GPU/Common/SoftwareTransformCommon.cpp @@ -80,7 +80,7 @@ static void RotateUV(TransformedVertex v[4]) { } } -static bool ShouldApplySpriteBorderFix(const GPUgstate &gstate) { +static bool ShouldApplySpriteBorderFix(const GEState &gstate) { return gstate.isMagnifyFilteringEnabled() && gstate.isAlphaBlendEnabled() && gstate.getBlendFuncA() != GE_SRCBLEND_FIXA && gstate.isTextureAlphaUsed(); } @@ -407,7 +407,7 @@ SoftwareTransformAction RunSoftwareTransform(SoftwareTransformParams ¶ms, in // Modifies the vertices in-place. Applies viewport and projection. // TODO: SIMD. -static void ProjectVertices(const GPUgstate &gstate, TransformedVertex *transformed, int vertexCount) { +static void ProjectVertices(const GEState &gstate, TransformedVertex *transformed, int vertexCount) { #if 0 Lin::Vec3 vpOffset(gstate.getViewportXCenter(), gstate.getViewportYCenter(), gstate.getViewportZCenter()); Lin::Vec3 vpScale(gstate.getViewportXScale(), gstate.getViewportYScale(), gstate.getViewportZScale()); diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index 6e85e362aa..579a25b5f4 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -2301,7 +2301,7 @@ static bool CanDepalettizeBufferAs(GETextureFormat texFormat, GEBufferFormat buf // But we only do it if the mask/shift exactly matches a color channel, else something different might be going // on and we definitely don't want to interpolate. // Great enhancement for Test Drive and Manhunt 2. -static bool CanUseSmoothDepal(const GPUgstate &gstate, GEBufferFormat framebufferFormat, const ClutTexture &clutTexture) { +static bool CanUseSmoothDepal(const GEState &gstate, GEBufferFormat framebufferFormat, const ClutTexture &clutTexture) { for (int i = 0; i < ClutTexture::MAX_RAMPS; i++) { if (gstate.getClutIndexStartPos() == clutTexture.rampStarts[i] && gstate.getClutIndexMask() < clutTexture.rampLengths[i]) { diff --git a/GPU/Debugger/Stepping.cpp b/GPU/Debugger/Stepping.cpp index 6710c7b7fc..9b5f155207 100644 --- a/GPU/Debugger/Stepping.cpp +++ b/GPU/Debugger/Stepping.cpp @@ -68,7 +68,7 @@ static bool lastWasFramebuffer; static u32 pauseSetCmdValue; // This is used only to highlight differences. Should really be owned by the debugger. -static GPUgstate lastGState; +static GEState lastGState; const char *PauseActionToString(PauseAction action) { switch (action) { @@ -291,7 +291,7 @@ bool GPU_FlushDrawing() { return true; } -const GPUgstate &LastState() { +const GEState &LastState() { return lastGState; } diff --git a/GPU/Debugger/Stepping.h b/GPU/Debugger/Stepping.h index cf02a0c39e..95ec53895a 100644 --- a/GPU/Debugger/Stepping.h +++ b/GPU/Debugger/Stepping.h @@ -47,5 +47,5 @@ namespace GPUStepping { bool GPU_FlushDrawing(); // Can be used to highlight differences in a debugger. - const GPUgstate &LastState(); + const GEState &LastState(); }; diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index 4e6e416e57..36b1edd434 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -1707,7 +1707,7 @@ u32 GPUCommon::GetIndexAddress() { return gstate_c.indexAddr; } -const GPUgstate &GPUCommon::GetGState() { +const GEState &GPUCommon::GetGState() { return gstate; } diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index 8178114656..af1553be34 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -30,7 +30,7 @@ class TextureCacheCommon; class DrawEngineCommon; class GraphicsContext; struct PspGeListArgs; -struct GPUgstate; +struct GEState; class PointerWrap; struct VirtualFramebuffer; @@ -221,7 +221,7 @@ public: u32 GetRelativeAddress(u32 data); u32 GetVertexAddress(); u32 GetIndexAddress(); - const GPUgstate &GetGState(); + const GEState &GetGState(); void SetCmdValue(u32 op); DisplayList* getList(int listid) { diff --git a/GPU/GPUState.cpp b/GPU/GPUState.cpp index b8323eada2..ccc970a32b 100644 --- a/GPU/GPUState.cpp +++ b/GPU/GPUState.cpp @@ -27,7 +27,7 @@ #include "GPU/GPUState.h" // This must be aligned so that the matrices within are aligned. -alignas(16) GPUgstate gstate; +alignas(16) GEState gstate; // Let's align this one too for good measure. alignas(16) GPUStateCache gstate_c; @@ -102,7 +102,7 @@ static const u32_le *LoadMatrix(const u32_le *cmds, float *mtx, int sz) { return cmds; } -void GPUgstate::Reset() { +void GEState::Reset() { memset(gstate.cmdmem, 0, sizeof(gstate.cmdmem)); for (int i = 0; i < 256; i++) { gstate.cmdmem[i] = i << 24; @@ -120,7 +120,7 @@ void GPUgstate::Reset() { gstate_c.Dirty(DIRTY_WORLD_VIEW_PROJ_MATRIX | DIRTY_VIEW_PROJ_MATRIX | DIRTY_CULL_MATRIX); } -void GPUgstate::Save(u32_le *ptr) { +void GEState::Save(u32_le *ptr) { // Not sure what the first 10 values are, exactly, but these seem right. ptr[5] = gstate_c.vertexAddr; ptr[6] = gstate_c.indexAddr; @@ -168,7 +168,7 @@ void GPUgstate::Save(u32_le *ptr) { } } -void GPUgstate::FastLoadBoneMatrix(u32 addr) { +void GEState::FastLoadBoneMatrix(u32 addr) { const u32 *src = (const u32 *)Memory::GetPointerUnchecked(addr); u32 num = boneMatrixNumber; u32 *dst = (u32 *)(boneMatrix + (num & 0x7F)); @@ -204,7 +204,7 @@ void GPUgstate::FastLoadBoneMatrix(u32 addr) { gstate.boneMatrixNumber = (GE_CMD_BONEMATRIXNUMBER << 24) | (num & 0x00FFFFFF); } -void GPUgstate::Restore(const u32_le *ptr) { +void GEState::Restore(const u32_le *ptr) { // Not sure what the first 10 values are, exactly, but these seem right. gstate_c.vertexAddr = ptr[5]; gstate_c.indexAddr = ptr[6]; diff --git a/GPU/GPUState.h b/GPU/GPUState.h index c86b71e19f..2da2e260c2 100644 --- a/GPU/GPUState.h +++ b/GPU/GPUState.h @@ -31,7 +31,7 @@ class PointerWrap; -struct GPUgstate { +struct GEState { // Getting rid of this ugly union in favor of the accessor functions // might be a good idea.... union { @@ -514,7 +514,7 @@ enum class SubmitType { SPLINE, }; -extern GPUgstate gstate; +extern GEState gstate; struct GPUStateCache { bool Use(u32 flags) const { return (useFlags_ & flags) != 0; } // Return true if ANY of flags are true. diff --git a/GPU/GPUStateSIMDUtil.h b/GPU/GPUStateSIMDUtil.h index 175944a60f..b7d956ac94 100644 --- a/GPU/GPUStateSIMDUtil.h +++ b/GPU/GPUStateSIMDUtil.h @@ -3,14 +3,14 @@ #include "Common/Math/CrossSIMD.h" #include "GPU/GPUState.h" -inline Vec4F32 LoadViewportOffsetVec(const GPUgstate &gstate) { +inline Vec4F32 LoadViewportOffsetVec(const GEState &gstate) { // We ignore the last member. return Vec4F32::LoadF24x4(&gstate.viewportxcenter); } -inline Vec4F32 LoadViewportScaleVec(const GPUgstate &gstate) { +inline Vec4F32 LoadViewportScaleVec(const GEState &gstate) { // We ignore the last member. return Vec4F32::LoadF24x4(&gstate.viewportxscale); } -inline Vec4F32 LoadUVScaleOffsetVec(const GPUgstate &gstate) { +inline Vec4F32 LoadUVScaleOffsetVec(const GEState &gstate) { return Vec4F32::LoadF24x4(&gstate.texscaleu); } diff --git a/UI/ImDebugger/ImGe.cpp b/UI/ImDebugger/ImGe.cpp index ff3890973d..00b3fecd65 100644 --- a/UI/ImDebugger/ImGe.cpp +++ b/UI/ImDebugger/ImGe.cpp @@ -1643,7 +1643,7 @@ void ImGeStateWindow::Draw(ImConfig &cfg, ImControl &control, GPUCommon *gpuDebu bool sectionOpen = false; for (size_t i = 0; i < numRows; i++) { const GECmdInfo &info = GECmdInfoByCmd(rows[i].cmd); - const GPUgstate &lastState = GPUStepping::LastState(); + const GEState &lastState = GPUStepping::LastState(); bool diff = lastState.cmdmem[rows[i].cmd] != gstate.cmdmem[rows[i].cmd]; if (rows[i].header) { diff --git a/Windows/GEDebugger/GEDebugger.cpp b/Windows/GEDebugger/GEDebugger.cpp index 3942d1d7ba..d39bf1ed87 100644 --- a/Windows/GEDebugger/GEDebugger.cpp +++ b/Windows/GEDebugger/GEDebugger.cpp @@ -377,7 +377,7 @@ void CGEDebugger::SetupPreviews() { } } -void CGEDebugger::DescribePrimaryPreview(const GPUgstate &state, char desc[256]) { +void CGEDebugger::DescribePrimaryPreview(const GEState &state, char desc[256]) { if (primaryTrackX_ < primaryBuffer_->GetStride() && primaryTrackY_ < primaryBuffer_->GetHeight()) { u32 pix = primaryBuffer_->GetRawPixel(primaryTrackX_, primaryTrackY_); DescribePixel(pix, primaryBuffer_->GetFormat(), primaryTrackX_, primaryTrackY_, desc); @@ -410,7 +410,7 @@ void CGEDebugger::DescribePrimaryPreview(const GPUgstate &state, char desc[256]) } } -void CGEDebugger::DescribeSecondPreview(const GPUgstate &state, char desc[256]) { +void CGEDebugger::DescribeSecondPreview(const GEState &state, char desc[256]) { if (secondTrackX_ != 0xFFFFFFFF) { uint32_t x = secondTrackX_; uint32_t y = secondTrackY_; @@ -557,7 +557,7 @@ void CGEDebugger::UpdatePreviews() { return; } - GPUgstate state{}; + GEState state{}; if (gpu != nullptr) { state = gpu->GetGState(); @@ -663,7 +663,7 @@ int CGEDebugger::HasTabIndex(GEDebuggerTab *tab, GETabPosition pos) { return -1; } -u32 CGEDebugger::TexturePreviewFlags(const GPUgstate &state) { +u32 CGEDebugger::TexturePreviewFlags(const GEState &state) { if (state.isTextureAlphaUsed() && !forceOpaque_) { return SimpleGLWindow::ALPHA_BLEND | SimpleGLWindow::RESIZE_BEST_CENTER; } else { @@ -671,7 +671,7 @@ u32 CGEDebugger::TexturePreviewFlags(const GPUgstate &state) { } } -void CGEDebugger::UpdatePrimaryPreview(const GPUgstate &state) { +void CGEDebugger::UpdatePrimaryPreview(const GEState &state) { bool bufferResult = false; u32 flags = SimpleGLWindow::ALPHA_IGNORE | SimpleGLWindow::RESIZE_SHRINK_CENTER; @@ -724,7 +724,7 @@ void CGEDebugger::UpdatePrimaryPreview(const GPUgstate &state) { } } -void CGEDebugger::UpdateSecondPreview(const GPUgstate &state) { +void CGEDebugger::UpdateSecondPreview(const GEState &state) { bool bufferResult = false; SetupPreviews(); @@ -784,7 +784,7 @@ void CGEDebugger::PrimaryPreviewHover(int x, int y) { desc[0] = 0; } else if (x < 0 || y < 0) { // This means they left the area. - GPUgstate state{}; + GEState state{}; if (gpu != nullptr) { state = gpu->GetGState(); } @@ -812,7 +812,7 @@ void CGEDebugger::SecondPreviewHover(int x, int y) { desc[0] = 0; } else if (x < 0 || y < 0) { // This means they left the area. - GPUgstate state{}; + GEState state{}; if (gpu != nullptr) { state = gpu->GetGState(); } @@ -834,7 +834,7 @@ void CGEDebugger::SecondPreviewHover(int x, int y) { } void CGEDebugger::UpdateTextureLevel(int level) { - GPUgstate state{}; + GEState state{}; if (gpu != nullptr) { state = gpu->GetGState(); } diff --git a/Windows/GEDebugger/GEDebugger.h b/Windows/GEDebugger/GEDebugger.h index 2f908025c4..34c692a362 100644 --- a/Windows/GEDebugger/GEDebugger.h +++ b/Windows/GEDebugger/GEDebugger.h @@ -43,7 +43,7 @@ class TabStateSettings; class TabVertices; class TabMatrices; class TabStateWatch; -struct GPUgstate; +struct GEState; enum class GETabPosition { LEFT = 1, @@ -100,8 +100,8 @@ protected: private: void SetupPreviews(); void UpdatePreviews(); - void UpdatePrimaryPreview(const GPUgstate &state); - void UpdateSecondPreview(const GPUgstate &state); + void UpdatePrimaryPreview(const GEState &state); + void UpdateSecondPreview(const GEState &state); static u32 PrimPreviewOp(); void UpdatePrimPreview(u32 op, int which); void CleanupPrimPreview(); @@ -109,8 +109,8 @@ private: void UpdateSize(WORD width, WORD height); void SavePosition(); void UpdateTextureLevel(int level); - void DescribePrimaryPreview(const GPUgstate &state, char desc[256]); - void DescribeSecondPreview(const GPUgstate &state, char desc[256]); + void DescribePrimaryPreview(const GEState &state, char desc[256]); + void DescribeSecondPreview(const GEState &state, char desc[256]); void PrimaryPreviewHover(int x, int y); void SecondPreviewHover(int x, int y); void PreviewExport(const GPUDebugBuffer *buffer); @@ -122,7 +122,7 @@ private: int HasTabIndex(GEDebuggerTab *tab, GETabPosition pos); void CheckTabMessage(TabControl *t, GETabPosition pos, LPARAM lParam); - u32 TexturePreviewFlags(const GPUgstate &state); + u32 TexturePreviewFlags(const GEState &state); SimpleGLWindow *primaryWindow = nullptr; SimpleGLWindow *secondWindow = nullptr; diff --git a/Windows/GEDebugger/TabVertices.cpp b/Windows/GEDebugger/TabVertices.cpp index 799f8a15b2..feecf3b626 100644 --- a/Windows/GEDebugger/TabVertices.cpp +++ b/Windows/GEDebugger/TabVertices.cpp @@ -328,7 +328,7 @@ bool CtrlMatrixList::OnColPrePaint(int row, int col, LPNMLVCUSTOMDRAW msg) { return false; } -bool CtrlMatrixList::ColChanged(const GPUgstate &lastState, const GPUgstate &state, int row, int col) { +bool CtrlMatrixList::ColChanged(const GEState &lastState, const GEState &state, int row, int col) { union { float f; uint32_t u; @@ -340,7 +340,7 @@ bool CtrlMatrixList::ColChanged(const GPUgstate &lastState, const GPUgstate &sta return newVal.u != oldVal.u; } -bool CtrlMatrixList::GetValue(const GPUgstate &state, int row, int col, float &val) { +bool CtrlMatrixList::GetValue(const GEState &state, int row, int col, float &val) { if (!gpu || row < 0 || row >= MATRIXLIST_ROW_COUNT || col < 0 || col >= MATRIXLIST_COL_COUNT) return false; diff --git a/Windows/GEDebugger/TabVertices.h b/Windows/GEDebugger/TabVertices.h index c39824642b..cd873a66be 100644 --- a/Windows/GEDebugger/TabVertices.h +++ b/Windows/GEDebugger/TabVertices.h @@ -83,8 +83,8 @@ protected: bool OnColPrePaint(int row, int col, LPNMLVCUSTOMDRAW msg) override; private: - bool GetValue(const GPUgstate &state, int row, int col, float &val); - bool ColChanged(const GPUgstate &lastState, const GPUgstate &state, int row, int col); + bool GetValue(const GEState &state, int row, int col, float &val); + bool ColChanged(const GEState &lastState, const GEState &state, int row, int col); void ToggleBreakpoint(int row); void PromptBreakpointCond(int row); }; From 50970153c9cb04f2609bb6d947e0713eb8a05bf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 3 Jul 2026 12:02:55 +0200 Subject: [PATCH 2/5] Minor cleanup --- GPU/Common/FragmentShaderGenerator.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/GPU/Common/FragmentShaderGenerator.cpp b/GPU/Common/FragmentShaderGenerator.cpp index d2d2c4b680..f317d7d8fa 100644 --- a/GPU/Common/FragmentShaderGenerator.cpp +++ b/GPU/Common/FragmentShaderGenerator.cpp @@ -154,10 +154,7 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu ReplaceBlendType replaceBlend = static_cast(id.Bits(FS_BIT_REPLACE_BLEND, 3)); - bool blueToAlpha = false; - if (replaceBlend == ReplaceBlendType::REPLACE_BLEND_BLUE_TO_ALPHA) { - blueToAlpha = true; - } + const bool blueToAlpha = replaceBlend == ReplaceBlendType::REPLACE_BLEND_BLUE_TO_ALPHA; bool isModeClear = id.Bit(FS_BIT_CLEARMODE); @@ -854,8 +851,8 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu // This happens before fog is applied. *uniformMask |= DIRTY_TEX_ALPHA_MUL; - // We only need a clamp if the color will be further processed. Otherwise the hardware color conversion will clamp for us. - // TODO: Clamp is so cheap that this probably is pretty meaningless. + // We only need a clamp if the color will be further processed directly in the shader. + // Otherwise the hardware color conversion will clamp for us (unless we start using FP formats for fake HDR but then we probably don't want the clamp...) if (enableFog || enableColorTest || replaceBlend != REPLACE_BLEND_NO || simulateLogicOpType != LOGICOPTYPE_NORMAL || colorWriteMask || blueToAlpha) { WRITE(p, " v.rgb = clamp(v.rgb * u_texNoAlphaMul.y, 0.0, 1.0);\n"); } else { From 8804042a9d05b5a426a9234e963ffe5a200e5e67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 3 Jul 2026 12:45:46 +0200 Subject: [PATCH 3/5] NormalizeVertices: Take UV scale as a parameter --- GPU/Common/DrawEngineCommon.cpp | 2 +- GPU/Common/SoftwareTransformCommon.cpp | 4 +-- GPU/Common/SoftwareTransformCommon.h | 2 +- GPU/Common/SplineCommon.cpp | 4 ++- GPU/Common/SplineCommon.h | 45 +++++++++++++------------- 5 files changed, 30 insertions(+), 27 deletions(-) diff --git a/GPU/Common/DrawEngineCommon.cpp b/GPU/Common/DrawEngineCommon.cpp index f6779f3292..9a2e1e6a2a 100644 --- a/GPU/Common/DrawEngineCommon.cpp +++ b/GPU/Common/DrawEngineCommon.cpp @@ -232,7 +232,7 @@ bool DrawEngineCommon::TestBoundingBox(const void *vdata, const void *inds, int // TODO: Avoid normalization if just plain skinning. // Force software skinning. const u32 vertTypeID = GetVertTypeID(vertType, gstate.getUVGenMode(), true); - ::NormalizeVertices(corners, temp_buffer, (const u8 *)vdata, indexLowerBound, indexUpperBound, dec, vertType); + ::NormalizeVertices(corners, temp_buffer, (const u8 *)vdata, indexLowerBound, indexUpperBound, gstate_c.uv, dec, vertType); IndexConverter conv(vertType, inds); for (int i = 0; i < vertexCount; i++) { verts[i * 3] = corners[conv(i)].pos.x; diff --git a/GPU/Common/SoftwareTransformCommon.cpp b/GPU/Common/SoftwareTransformCommon.cpp index 0c100d8c51..390aa0dc07 100644 --- a/GPU/Common/SoftwareTransformCommon.cpp +++ b/GPU/Common/SoftwareTransformCommon.cpp @@ -1366,13 +1366,13 @@ static bool ExpandPoints(int vertexCount, int &maxIndex, int vertsSize, u16 *&in // The rest of the transform pipeline like lighting will go as normal, either hardware or software. // The implementation is initially a bit inefficient but shouldn't be a big deal. // An intermediate buffer of not-easy-to-predict size is stored at bufPtr. -u32 NormalizeVertices(SimpleVertex *sverts, u8 *bufPtr, const u8 *inPtr, int lowerBound, int upperBound, const VertexDecoder *dec, u32 vertType) { +u32 NormalizeVertices(SimpleVertex *sverts, u8 *bufPtr, const u8 *inPtr, int lowerBound, int upperBound, const UVScale &uvScale, const VertexDecoder *dec, u32 vertType) { // First, decode the vertices into a GPU compatible format. This step can be eliminated but will need a separate // implementation of the vertex decoder. // Actually if software transform is off, we could enforce it in the vertex decoder lookup before calling this, // avoiding having to implement it again below. const int count = upperBound + 1 - lowerBound; - dec->DecodeVerts(bufPtr, inPtr + lowerBound * dec->VertexSize(), &gstate_c.uv, count); + dec->DecodeVerts(bufPtr, inPtr + lowerBound * dec->VertexSize(), &uvScale, count); // OK, morphing eliminated but bones still remain to be taken care of. // Let's do a partial software transform where we only do skinning. diff --git a/GPU/Common/SoftwareTransformCommon.h b/GPU/Common/SoftwareTransformCommon.h index 7943658fd0..b5bf3f3677 100644 --- a/GPU/Common/SoftwareTransformCommon.h +++ b/GPU/Common/SoftwareTransformCommon.h @@ -83,7 +83,7 @@ SoftwareTransformAction RunSoftwareTransform(SoftwareTransformParams ¶ms, in class DrawEngineCommon; // Slow. See description in the cpp file. -u32 NormalizeVertices(SimpleVertex *sverts, u8 *bufPtr, const u8 *inPtr, int lowerBound, int upperBound, const VertexDecoder *dec, u32 vertType); +u32 NormalizeVertices(SimpleVertex *sverts, u8 *bufPtr, const u8 *inPtr, int lowerBound, int upperBound, const UVScale &uvScale, const VertexDecoder *dec, u32 vertType); // In the returned data, you should subtract the value of lowerIndexBound from the indices to get the actual vertex index in the vertices array. // This is because some draws in some games use very large indices, but they only use a small range of them in each PRIM submission. diff --git a/GPU/Common/SplineCommon.cpp b/GPU/Common/SplineCommon.cpp index 6f5e4d95d7..f8ed5aa607 100644 --- a/GPU/Common/SplineCommon.cpp +++ b/GPU/Common/SplineCommon.cpp @@ -159,6 +159,8 @@ private: } static void CalcWeights(float t, const float *knots, const KnotDiv &div, Weight &w) { + // TODO: This SSE code doesn't look like it's worth it. We need to parallelize across another + // dimension. #ifdef _M_SSE const __m128 knot012 = _mm_loadu_ps(knots); const __m128 t012 = _mm_sub_ps(_mm_set_ps1(t), knot012); @@ -485,7 +487,7 @@ void DrawEngineCommon::SubmitCurve(const void *control_points, const void *indic } const u32 origVertType = vertType; - vertType = ::NormalizeVertices(simplified_control_points, temp_buffer, (u8 *)control_points, index_lower_bound, index_upper_bound, origVDecoder, vertType); + vertType = ::NormalizeVertices(simplified_control_points, temp_buffer, (u8 *)control_points, index_lower_bound, index_upper_bound, gstate_c.uv, origVDecoder, vertType); VertexDecoder *vdecoder = GetVertexDecoder(vertType); diff --git a/GPU/Common/SplineCommon.h b/GPU/Common/SplineCommon.h index eadcaffed5..b6c2834544 100644 --- a/GPU/Common/SplineCommon.h +++ b/GPU/Common/SplineCommon.h @@ -27,7 +27,7 @@ #include "Core/Config.h" -#define HALF_CEIL(x) (x + 1) / 2 // Integer ceil = (int)ceil((float)x / 2.0f) +inline int half_ceil(int x) { return (x + 1) / 2; } // Integer ceil = (int)ceil((float)x / 2.0f) class SimpleBufferManager; @@ -61,8 +61,8 @@ struct SurfaceInfo { break; case SplineQuality::MEDIUM_QUALITY: // Don't cut below 2, though. - if (tess_u > 2) tess_u = HALF_CEIL(tess_u); - if (tess_v > 2) tess_v = HALF_CEIL(tess_v); + if (tess_u > 2) tess_u = half_ceil(tess_u); + if (tess_v > 2) tess_v = half_ceil(tess_v); break; default: break; @@ -140,7 +140,8 @@ struct SplineSurface : public SurfaceInfo { }; struct Weight { - float basis[4], deriv[4]; + float basis[4]; + float deriv[4]; }; template @@ -207,10 +208,10 @@ struct NAME { \ } \ }; -template +template class TemplateParameterDispatcher { - /* Store all combinations of template functions into an array */ + // Store all combinations of template functions into an array template struct Initializer { static void Init(Func funcs[]) { @@ -218,7 +219,7 @@ class TemplateParameterDispatcher { Initializer::Init(funcs); // false } }; - /* Specialized for terminates the recursive loop */ + // Specialized for terminates the recursive loop template struct Initializer<0, Index, Params...> { static void Init(Func funcs[]) { @@ -226,19 +227,19 @@ class TemplateParameterDispatcher { } }; -private: - Func funcs[1 << NumParams]; /* Function pointers array */ -public: - TemplateParameterDispatcher() { - Initializer::Init(funcs); - } - - Func GetFunc(const bool params[]) const { - /* Convert bool parameters to index of the array */ - int index = 0; - for (int i = 0; i < NumParams; ++i) - index |= params[i] << i; - - return funcs[index]; - } +private: + Func funcs[1 << NumParams]; /* Function pointers array */ +public: + TemplateParameterDispatcher() { + Initializer::Init(funcs); + } + + Func GetFunc(const bool params[]) const { + // Convert bool parameters to index of the array + int index = 0; + for (int i = 0; i < NumParams; ++i) { + index |= params[i] << i; + } + return funcs[index]; + } }; From e2fbf295cfffc11a0dce8bd0831eac0decb55a34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 3 Jul 2026 12:51:53 +0200 Subject: [PATCH 4/5] Spline: Avoid having to modify and restore gstate_c.uv --- GPU/Common/SplineCommon.cpp | 31 +++++++++++-------------------- 1 file changed, 11 insertions(+), 20 deletions(-) diff --git a/GPU/Common/SplineCommon.cpp b/GPU/Common/SplineCommon.cpp index f8ed5aa607..6f4bf6ccc4 100644 --- a/GPU/Common/SplineCommon.cpp +++ b/GPU/Common/SplineCommon.cpp @@ -465,8 +465,9 @@ void DrawEngineCommon::SubmitCurve(const void *control_points, const void *indic u16 index_lower_bound = 0; u16 index_upper_bound = num_points - 1; IndexConverter ConvertIndex(vertType, indices); - if (indices) + if (indices) { GetIndexBounds(indices, num_points, vertType, &index_lower_bound, &index_upper_bound); + } u32 vertTypeID = GetVertTypeID(vertType, gstate.getUVGenMode(), applySkinInDecode_); VertexDecoder *origVDecoder = GetVertexDecoder(vertTypeID); @@ -487,7 +488,8 @@ void DrawEngineCommon::SubmitCurve(const void *control_points, const void *indic } const u32 origVertType = vertType; - vertType = ::NormalizeVertices(simplified_control_points, temp_buffer, (u8 *)control_points, index_lower_bound, index_upper_bound, gstate_c.uv, origVDecoder, vertType); + UVScale neutralUVScale{1.0f, 1.0f, 0.0f, 0.0f}; // Avoid rescaling UV during normalization, it will happen anyway later (in DispatchSubmitPrim). Although ideally we should avoid running Decode at all there. + vertType = ::NormalizeVertices(simplified_control_points, temp_buffer, (u8 *)control_points, index_lower_bound, index_upper_bound, neutralUVScale, origVDecoder, vertType); VertexDecoder *vdecoder = GetVertexDecoder(vertType); @@ -502,8 +504,9 @@ void DrawEngineCommon::SubmitCurve(const void *control_points, const void *indic ERROR_LOG(Log::G3D, "Failed to allocate space for control point pointers, skipping curve draw"); return; } - for (int idx = 0; idx < num_points; idx++) + for (int idx = 0; idx < num_points; idx++) { points[idx] = simplified_control_points + (indices ? ConvertIndex(idx) : idx); + } OutputBuffers output; output.vertices = (SimpleVertex *)(decoded_ + DECODED_VERTEX_BUFFER_SIZE / 2); @@ -515,23 +518,15 @@ void DrawEngineCommon::SubmitCurve(const void *control_points, const void *indic surface.Init(maxVerts); ControlPoints cpoints(points, num_points, managedBuf); - if (cpoints.IsValid()) + if (cpoints.IsValid()) { + // Run the tessellation! SoftwareTessellation(output, surface, origVertType, cpoints); - else + } else { ERROR_LOG(Log::G3D, "Failed to allocate space for control point values, skipping curve draw"); + } u32 vertTypeWithIndex16 = (vertType & ~GE_VTYPE_IDX_MASK) | GE_VTYPE_IDX_16BIT; - UVScale prevUVScale; - if (origVertType & GE_VTYPE_TC_MASK) { - // We scaled during Normalize already so let's turn it off when drawing. - prevUVScale = gstate_c.uv; - gstate_c.uv.uScale = 1.0f; - gstate_c.uv.vScale = 1.0f; - gstate_c.uv.uOff = 0; - gstate_c.uv.vOff = 0; - } - vertTypeID = GetVertTypeID(vertTypeWithIndex16, gstate.getUVGenMode(), applySkinInDecode_); int generatedBytesRead; if (output.count) { @@ -539,11 +534,7 @@ void DrawEngineCommon::SubmitCurve(const void *control_points, const void *indic DispatchSubmitPrim(output.vertices, output.indices, PatchPrimToPrim(surface.primType), output.count, vertTypeID, true, &generatedBytesRead, flags); } - if (flushOnParams_) + if (flushOnParams_) { Flush(); - - if (origVertType & GE_VTYPE_TC_MASK) { - // If analysis says this is uninitialized, it's wrong. - gstate_c.uv = prevUVScale; } } From 6d2948a09bc31e6c06a84b0a499ccf4a0df1a8e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 3 Jul 2026 13:10:05 +0200 Subject: [PATCH 5/5] Remove the cached UVScale in gstate_c. Conversion is cheap enough to do directly from gstate, no point in caching. --- GPU/Common/DrawEngineCommon.cpp | 6 ++++-- GPU/Common/SoftwareTransformCommon.cpp | 4 +--- GPU/GPUCommon.cpp | 2 -- GPU/GPUCommonHW.cpp | 8 -------- GPU/GPUState.cpp | 3 ++- GPU/GPUState.h | 18 ------------------ GPU/GPUStateSIMDUtil.h | 6 ++++-- GPU/Software/SoftGpu.cpp | 3 --- GPU/Software/TransformUnit.cpp | 4 +++- unittest/TestVertexJit.cpp | 9 ++++----- 10 files changed, 18 insertions(+), 45 deletions(-) diff --git a/GPU/Common/DrawEngineCommon.cpp b/GPU/Common/DrawEngineCommon.cpp index 9a2e1e6a2a..5cfc1389dd 100644 --- a/GPU/Common/DrawEngineCommon.cpp +++ b/GPU/Common/DrawEngineCommon.cpp @@ -232,7 +232,8 @@ bool DrawEngineCommon::TestBoundingBox(const void *vdata, const void *inds, int // TODO: Avoid normalization if just plain skinning. // Force software skinning. const u32 vertTypeID = GetVertTypeID(vertType, gstate.getUVGenMode(), true); - ::NormalizeVertices(corners, temp_buffer, (const u8 *)vdata, indexLowerBound, indexUpperBound, gstate_c.uv, dec, vertType); + UVScale uvScale{}; // We don't care about UV. + ::NormalizeVertices(corners, temp_buffer, (const u8 *)vdata, indexLowerBound, indexUpperBound, uvScale, dec, vertType); IndexConverter conv(vertType, inds); for (int i = 0; i < vertexCount; i++) { verts[i * 3] = corners[conv(i)].pos.x; @@ -891,7 +892,7 @@ bool DrawEngineCommon::SubmitPrim(const void *verts, const void *inds, GEPrimiti numDrawVerts_ = numDrawVerts + 1; // Increment the uncached variable dv.verts = verts; dv.vertexCount = vertexCount; - dv.uvScale = gstate_c.uv; + dv.uvScale = LoadUVScaleOffset(gstate); // Does handle the unindexed case. GetIndexBounds(inds, vertexCount, vertTypeID, &dv.indexLowerBound, &dv.indexUpperBound); } @@ -1064,6 +1065,7 @@ Mat4F32 ComputeFinalProjMatrix() { 0.0f, }; + // TODO: Simply use Mat4F32 m(gstate_c.worldviewproj); Mat4F32 wv = Mul4x3By4x4(Mat4x3F32(gstate.worldMatrix), Mat4F32::Load4x3(gstate.viewMatrix)); Mat4F32 m = Mul4x4By4x4(wv, Mat4F32(gstate.projMatrix)); // NOTE: Applying the translation actually works pre-divide, since W is also affected. diff --git a/GPU/Common/SoftwareTransformCommon.cpp b/GPU/Common/SoftwareTransformCommon.cpp index 390aa0dc07..a84bbcd793 100644 --- a/GPU/Common/SoftwareTransformCommon.cpp +++ b/GPU/Common/SoftwareTransformCommon.cpp @@ -1543,12 +1543,10 @@ bool GetCurrentDrawAsDebugVertices(DrawEngineCommon *drawEngine, GECommand cmd, const int stride = (int)dec->GetDecVtxFmt().stride; vertsTemp.resize(stride * verticesToDecode + 32); // Add some padding bytes for "over-writes". - UVScale uvScale{}; - LoadUVScaleOffsetVec(gstate).Store(&uvScale.uScale); - const u8 *startPos = verts + indexLowerBound * dec->VertexSize(); bool savedVertexFullAlpha = gstate_c.vertexFullAlpha; + const UVScale uvScale = LoadUVScaleOffset(gstate); dec->DecodeVerts(vertsTemp.data(), startPos, &uvScale, verticesToDecode); gstate_c.vertexFullAlpha = savedVertexFullAlpha; diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index 36b1edd434..7babc15025 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -1325,8 +1325,6 @@ void GPUCommon::FlushImm() { SetDrawType(DRAW_PRIM, immPrim_); - gstate_c.UpdateUVScaleOffset(); - VirtualFramebuffer *vfb = nullptr; if (framebufferManager_) { bool changed; diff --git a/GPU/GPUCommonHW.cpp b/GPU/GPUCommonHW.cpp index f64f2110c0..1d54435528 100644 --- a/GPU/GPUCommonHW.cpp +++ b/GPU/GPUCommonHW.cpp @@ -967,8 +967,6 @@ void GPUCommonHW::Execute_Prim(u32 op, u32 diff) { canExtend = false; } - gstate_c.UpdateUVScaleOffset(); - // cull mode int cullMode = gstate.getCullMode(); @@ -1190,22 +1188,18 @@ void GPUCommonHW::Execute_Prim(u32 op, u32 diff) { // when texscale commands are in line with the prims like this, they actually have an effect // and requires us to stop extending strips anyway. gstate.cmdmem[GE_CMD_TEXSCALEU] = data; - gstate_c.uv.uScale = getFloat24(data); canExtend = false; break; case GE_CMD_TEXSCALEV: gstate.cmdmem[GE_CMD_TEXSCALEV] = data; - gstate_c.uv.vScale = getFloat24(data); canExtend = false; break; case GE_CMD_TEXOFFSETU: gstate.cmdmem[GE_CMD_TEXOFFSETU] = data; - gstate_c.uv.uOff = getFloat24(data); canExtend = false; break; case GE_CMD_TEXOFFSETV: gstate.cmdmem[GE_CMD_TEXOFFSETV] = data; - gstate_c.uv.vOff = getFloat24(data); canExtend = false; break; case GE_CMD_TEXLEVEL: @@ -1333,7 +1327,6 @@ void GPUCommonHW::Execute_Bezier(u32 op, u32 diff) { gstate_c.submitType = SubmitType::BEZIER; int bytesRead = 0; - gstate_c.UpdateUVScaleOffset(); drawEngineCommon_->SubmitCurve(control_points, indices, surface, gstate.vertType, &bytesRead, "bezier"); gstate_c.Dirty(DIRTY_RASTER_STATE | DIRTY_VERTEXSHADER_STATE | DIRTY_UVSCALEOFFSET); @@ -1405,7 +1398,6 @@ void GPUCommonHW::Execute_Spline(u32 op, u32 diff) { gstate_c.submitType = SubmitType::SPLINE; int bytesRead = 0; - gstate_c.UpdateUVScaleOffset(); drawEngineCommon_->SubmitCurve(control_points, indices, surface, gstate.vertType, &bytesRead, "spline"); gstate_c.Dirty(DIRTY_RASTER_STATE | DIRTY_VERTEXSHADER_STATE | DIRTY_UVSCALEOFFSET); diff --git a/GPU/GPUState.cpp b/GPU/GPUState.cpp index ccc970a32b..22a8bd8f5f 100644 --- a/GPU/GPUState.cpp +++ b/GPU/GPUState.cpp @@ -292,7 +292,6 @@ void GPUStateCache::DoState(PointerWrap &p) { textureSolidAlpha = old.textureSolidAlpha; vertexFullAlpha = old.vertexFullAlpha; skipDrawReason = old.skipDrawReason; - uv = old.uv; savedContextVersion = 0; } else { @@ -310,6 +309,8 @@ void GPUStateCache::DoState(PointerWrap &p) { Do(p, skipDrawReason); + // Legacy, remove in the next bump. + UVScale uv{}; Do(p, uv); bool oldFlipTexture = false; diff --git a/GPU/GPUState.h b/GPU/GPUState.h index 2da2e260c2..c30b2acfcf 100644 --- a/GPU/GPUState.h +++ b/GPU/GPUState.h @@ -26,7 +26,6 @@ #include "GPU/GPU.h" #include "GPU/ge_constants.h" #include "GPU/Common/ShaderCommon.h" -#include "Common/Math/SIMDHeaders.h" #include "Common/Math/lin/vec3.h" class PointerWrap; @@ -588,21 +587,6 @@ struct GPUStateCache { return useFlags_; } - void UpdateUVScaleOffset() { -#if defined(_M_SSE) - __m128i values = _mm_slli_epi32(_mm_load_si128((const __m128i *)&gstate.texscaleu), 8); - _mm_storeu_si128((__m128i *)&uv, values); -#elif PPSSPP_ARCH(ARM_NEON) - const uint32x4_t values = vshlq_n_u32(vld1q_u32((const u32 *)&gstate.texscaleu), 8); - vst1q_u32((u32 *)&uv, values); -#else - uv.uScale = getFloat24(gstate.texscaleu); - uv.vScale = getFloat24(gstate.texscalev); - uv.uOff = getFloat24(gstate.texoffsetu); - uv.vOff = getFloat24(gstate.texoffsetv); -#endif - } - private: u32 useFlags_; public: @@ -625,8 +609,6 @@ public: int skipDrawReason; - UVScale uv; - bool bgraTexture; bool needShaderTexClamp; bool textureIsArray; diff --git a/GPU/GPUStateSIMDUtil.h b/GPU/GPUStateSIMDUtil.h index b7d956ac94..465d37f8c2 100644 --- a/GPU/GPUStateSIMDUtil.h +++ b/GPU/GPUStateSIMDUtil.h @@ -11,6 +11,8 @@ inline Vec4F32 LoadViewportScaleVec(const GEState &gstate) { // We ignore the last member. return Vec4F32::LoadF24x4(&gstate.viewportxscale); } -inline Vec4F32 LoadUVScaleOffsetVec(const GEState &gstate) { - return Vec4F32::LoadF24x4(&gstate.texscaleu); +inline UVScale LoadUVScaleOffset(const GEState &gstate) { + UVScale uvScale; + Vec4F32::LoadF24x4(&gstate.texscaleu).Store(&uvScale.uScale); + return uvScale; } diff --git a/GPU/Software/SoftGpu.cpp b/GPU/Software/SoftGpu.cpp index 9cb12b5078..336df8343c 100644 --- a/GPU/Software/SoftGpu.cpp +++ b/GPU/Software/SoftGpu.cpp @@ -863,7 +863,6 @@ void SoftGPU::Execute_Prim(u32 op, u32 diff) { cyclesExecuted += EstimatePerVertexCost() * count; int bytesRead; - gstate_c.UpdateUVScaleOffset(); drawEngine_->transformUnit.SetDirty(dirtyFlags_); drawEngine_->transformUnit.SubmitPrimitive(verts, indices, prim, count, gstate.vertType, &bytesRead, drawEngine_); dirtyFlags_ = drawEngine_->transformUnit.GetDirty(); @@ -916,7 +915,6 @@ void SoftGPU::Execute_Bezier(u32 op, u32 diff) { SetDrawType(DRAW_BEZIER, PatchPrimToPrim(surface.primType)); int bytesRead = 0; - gstate_c.UpdateUVScaleOffset(); drawEngine_->transformUnit.SetDirty(dirtyFlags_); drawEngineCommon_->SubmitCurve(control_points, indices, surface, gstate.vertType, &bytesRead, "bezier"); dirtyFlags_ = drawEngine_->transformUnit.GetDirty(); @@ -970,7 +968,6 @@ void SoftGPU::Execute_Spline(u32 op, u32 diff) { SetDrawType(DRAW_SPLINE, PatchPrimToPrim(surface.primType)); int bytesRead = 0; - gstate_c.UpdateUVScaleOffset(); drawEngine_->transformUnit.SetDirty(dirtyFlags_); drawEngineCommon_->SubmitCurve(control_points, indices, surface, gstate.vertType, &bytesRead, "spline"); dirtyFlags_ = drawEngine_->transformUnit.GetDirty(); diff --git a/GPU/Software/TransformUnit.cpp b/GPU/Software/TransformUnit.cpp index f57c1fcc02..706bac6bab 100644 --- a/GPU/Software/TransformUnit.cpp +++ b/GPU/Software/TransformUnit.cpp @@ -29,6 +29,7 @@ #include "GPU/Common/VertexDecoderCommon.h" #include "GPU/Common/SoftwareTransformCommon.h" #include "GPU/Common/VertexReader.h" +#include "GPU/GPUStateSIMDUtil.h" #include "Common/Math/SIMDHeaders.h" #include "GPU/Software/BinManager.h" #include "GPU/Software/Clipper.h" @@ -482,7 +483,8 @@ public: GetIndexBounds(indices, vertex_count, vertex_type, &lowerBound_, &upperBound_); if (vertex_count != 0) { const int count = upperBound_ - lowerBound_ + 1; - vdecoder.DecodeVerts(base, (const u8 *)vertices + vdecoder.VertexSize() * lowerBound_, &gstate_c.uv, count); + const UVScale uvScale = LoadUVScaleOffset(gstate); + vdecoder.DecodeVerts(base, (const u8 *)vertices + vdecoder.VertexSize() * lowerBound_, &uvScale, count); } // If we're only using a subset of verts, it's better to decode with random access (usually.) diff --git a/unittest/TestVertexJit.cpp b/unittest/TestVertexJit.cpp index 1646a67bf9..119c6394bb 100644 --- a/unittest/TestVertexJit.cpp +++ b/unittest/TestVertexJit.cpp @@ -27,6 +27,8 @@ #include "unittest/TestVertexJit.h" #include "unittest/UnitTest.h" +const UVScale g_uvScale{1.0f, 1.0f, 0.0f, 0.0f}; + class VertexDecoderTestHarness { static const int BUFFER_SIZE = 64 * 65536; static const int ROUNDS = 200; @@ -37,9 +39,6 @@ public: src_ = new u8[BUFFER_SIZE]; dst_ = new u8[BUFFER_SIZE]; cache_ = new VertexDecoderJitCache(); - - gstate_c.uv.uScale = 1.0f; - gstate_c.uv.vScale = 1.0f; } ~VertexDecoderTestHarness() { delete [] src_; @@ -69,7 +68,7 @@ public: void Execute(int vtype, int count, bool useJit) { SetupExecute(vtype, useJit); - dec_->DecodeVerts(dst_, src_, &gstate_c.uv, count); + dec_->DecodeVerts(dst_, src_, &g_uvScale, count); } double ExecuteTimed(int vtype, int count, bool useJit) { @@ -79,7 +78,7 @@ public: double st = time_now_d(); do { for (int j = 0; j < ROUNDS; ++j) { - dec_->DecodeVerts(dst_, src_, &gstate_c.uv, count); + dec_->DecodeVerts(dst_, src_, &g_uvScale, count); ++total; } } while (time_now_d() - st < 0.5);