diff --git a/GPU/Common/ShaderUniforms.cpp b/GPU/Common/ShaderUniforms.cpp index c020eb1088..f196563428 100644 --- a/GPU/Common/ShaderUniforms.cpp +++ b/GPU/Common/ShaderUniforms.cpp @@ -215,12 +215,16 @@ void BaseUpdateUniforms(UB_VS_FS_Base *ub, uint64_t dirtyUniforms, bool flipView // Texturing if (dirtyUniforms & DIRTY_UVSCALEOFFSET) { - const float invW = 1.0f / (float)gstate_c.curTextureWidth; - const float invH = 1.0f / (float)gstate_c.curTextureHeight; - const int w = gstate.getTextureWidth(0); - const int h = gstate.getTextureHeight(0); - const float widthFactor = (float)w * invW; - const float heightFactor = (float)h * invH; + float widthFactor = 1.0f; + float heightFactor = 1.0f; + if (gstate_c.textureIsFramebuffer) { + const float invW = 1.0f / (float)gstate_c.curTextureWidth; + const float invH = 1.0f / (float)gstate_c.curTextureHeight; + const int w = gstate.getTextureWidth(0); + const int h = gstate.getTextureHeight(0); + widthFactor = (float)w * invW; + heightFactor = (float)h * invH; + } if (gstate_c.submitType == SubmitType::HW_BEZIER || gstate_c.submitType == SubmitType::HW_SPLINE) { // When we are generating UV coordinates through the bezier/spline, we need to apply the scaling. // However, this is missing a check that we're not getting our UV:s supplied for us in the vertices. diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index c6193c1999..bf05e7a02e 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -1141,23 +1141,26 @@ void TextureCacheCommon::SetTextureFramebuffer(const AttachCandidate &candidate) bool needsDepthXSwizzle = depthUpperBits == 2; // We need to force it, since we may have set it on a texture before attaching. - gstate_c.curTextureWidth = framebuffer->bufferWidth; - gstate_c.curTextureHeight = framebuffer->bufferHeight; - + int texWidth = framebuffer->bufferWidth; + int texHeight = framebuffer->bufferHeight; if (candidate.channel == RASTER_COLOR && gstate.getTextureFormat() == GE_TFMT_CLUT8 && framebuffer->fb_format == GE_FORMAT_5551 && PSP_CoreParameter().compat.flags().SOCOMClut8Replacement) { // See #16210. UV must be adjusted as if the texture was twice the width. - gstate_c.curTextureWidth *= 2.0f; + texWidth *= 2.0f; } if (needsDepthXSwizzle) { - gstate_c.curTextureWidth = RoundUpToPowerOf2(gstate_c.curTextureWidth); + texWidth = RoundUpToPowerOf2(texWidth); } + gstate_c.curTextureWidth = texWidth; + gstate_c.curTextureHeight = texHeight; + gstate_c.SetTextureIsFramebuffer(true); + gstate_c.SetTextureIsBGRA(false); + if ((gstate_c.curTextureXOffset == 0) != (fbInfo.xOffset == 0) || (gstate_c.curTextureYOffset == 0) != (fbInfo.yOffset == 0)) { gstate_c.Dirty(DIRTY_FRAGMENTSHADER_STATE); } - gstate_c.SetTextureIsBGRA(false); - gstate_c.SetTextureIsFramebuffer(true); + gstate_c.curTextureXOffset = fbInfo.xOffset; gstate_c.curTextureYOffset = fbInfo.yOffset; u32 texW = (u32)gstate.getTextureWidth(0); @@ -2364,6 +2367,7 @@ void TextureCacheCommon::ApplyTextureFramebuffer(VirtualFramebuffer *framebuffer gpuStats.numDepal++; gstate_c.curTextureWidth = texWidth; + gstate_c.Dirty(DIRTY_UVSCALEOFFSET); draw_->BindTexture(0, nullptr); framebufferManager_->RebindFramebuffer("ApplyTextureFramebuffer"); @@ -2465,6 +2469,7 @@ void TextureCacheCommon::ApplyTextureDepal(TexCacheEntry *entry) { gpuStats.numDepal++; gstate_c.curTextureWidth = texWidth; + gstate_c.Dirty(DIRTY_UVSCALEOFFSET); draw_->BindTexture(0, nullptr); framebufferManager_->RebindFramebuffer("ApplyTextureFramebuffer"); diff --git a/GPU/Directx9/ShaderManagerDX9.cpp b/GPU/Directx9/ShaderManagerDX9.cpp index 9582989017..2bf18f2130 100644 --- a/GPU/Directx9/ShaderManagerDX9.cpp +++ b/GPU/Directx9/ShaderManagerDX9.cpp @@ -436,12 +436,16 @@ void ShaderManagerDX9::VSUpdateUniforms(u64 dirtyUniforms) { // Texturing if (dirtyUniforms & DIRTY_UVSCALEOFFSET) { - const float invW = 1.0f / (float)gstate_c.curTextureWidth; - const float invH = 1.0f / (float)gstate_c.curTextureHeight; - const int w = gstate.getTextureWidth(0); - const int h = gstate.getTextureHeight(0); - const float widthFactor = (float)w * invW; - const float heightFactor = (float)h * invH; + float widthFactor = 1.0f; + float heightFactor = 1.0f; + if (gstate_c.textureIsFramebuffer) { + const float invW = 1.0f / (float)gstate_c.curTextureWidth; + const float invH = 1.0f / (float)gstate_c.curTextureHeight; + const int w = gstate.getTextureWidth(0); + const int h = gstate.getTextureHeight(0); + widthFactor = (float)w * invW; + heightFactor = (float)h * invH; + } float uvscaleoff[4]; uvscaleoff[0] = widthFactor; uvscaleoff[1] = heightFactor; diff --git a/GPU/GLES/ShaderManagerGLES.cpp b/GPU/GLES/ShaderManagerGLES.cpp index 4787c18717..797a51b8aa 100644 --- a/GPU/GLES/ShaderManagerGLES.cpp +++ b/GPU/GLES/ShaderManagerGLES.cpp @@ -504,12 +504,16 @@ void LinkedShader::UpdateUniforms(const ShaderID &vsid, bool useBufferedRenderin render_->SetUniformF(&u_fogcoef, 2, fogcoef); } if (dirty & DIRTY_UVSCALEOFFSET) { - const float invW = 1.0f / (float)gstate_c.curTextureWidth; - const float invH = 1.0f / (float)gstate_c.curTextureHeight; - const int w = gstate.getTextureWidth(0); - const int h = gstate.getTextureHeight(0); - const float widthFactor = (float)w * invW; - const float heightFactor = (float)h * invH; + float widthFactor = 1.0f; + float heightFactor = 1.0f; + if (gstate_c.textureIsFramebuffer) { + const float invW = 1.0f / (float)gstate_c.curTextureWidth; + const float invH = 1.0f / (float)gstate_c.curTextureHeight; + const int w = gstate.getTextureWidth(0); + const int h = gstate.getTextureHeight(0); + widthFactor = (float)w * invW; + heightFactor = (float)h * invH; + } float uvscaleoff[4]; if (gstate_c.submitType == SubmitType::HW_BEZIER || gstate_c.submitType == SubmitType::HW_SPLINE) { // When we are generating UV coordinates through the bezier/spline, we need to apply the scaling. diff --git a/GPU/GPUCommonHW.cpp b/GPU/GPUCommonHW.cpp index f554e4e2c1..d9bcae2087 100644 --- a/GPU/GPUCommonHW.cpp +++ b/GPU/GPUCommonHW.cpp @@ -1192,7 +1192,8 @@ void GPUCommonHW::Execute_Bezier(u32 op, u32 diff) { SetDrawType(DRAW_BEZIER, PatchPrimToPrim(surface.primType)); - gstate_c.Dirty(DIRTY_RASTER_STATE | DIRTY_VERTEXSHADER_STATE | DIRTY_GEOMETRYSHADER_STATE); + // We need to dirty UVSCALEOFFSET here because we look at the submit type when setting that uniform. + gstate_c.Dirty(DIRTY_RASTER_STATE | DIRTY_VERTEXSHADER_STATE | DIRTY_GEOMETRYSHADER_STATE | DIRTY_UVSCALEOFFSET); if (drawEngineCommon_->CanUseHardwareTessellation(surface.primType)) { gstate_c.submitType = SubmitType::HW_BEZIER; if (gstate_c.spline_num_points_u != surface.num_points_u) { @@ -1207,7 +1208,7 @@ void GPUCommonHW::Execute_Bezier(u32 op, u32 diff) { UpdateUVScaleOffset(); drawEngineCommon_->SubmitCurve(control_points, indices, surface, gstate.vertType, &bytesRead, "bezier"); - gstate_c.Dirty(DIRTY_RASTER_STATE | DIRTY_VERTEXSHADER_STATE | DIRTY_GEOMETRYSHADER_STATE); + gstate_c.Dirty(DIRTY_RASTER_STATE | DIRTY_VERTEXSHADER_STATE | DIRTY_GEOMETRYSHADER_STATE | DIRTY_UVSCALEOFFSET); gstate_c.submitType = SubmitType::DRAW; // After drawing, we advance pointers - see SubmitPrim which does the same. @@ -1265,7 +1266,8 @@ void GPUCommonHW::Execute_Spline(u32 op, u32 diff) { SetDrawType(DRAW_SPLINE, PatchPrimToPrim(surface.primType)); - gstate_c.Dirty(DIRTY_RASTER_STATE | DIRTY_VERTEXSHADER_STATE | DIRTY_GEOMETRYSHADER_STATE); + // We need to dirty UVSCALEOFFSET here because we look at the submit type when setting that uniform. + gstate_c.Dirty(DIRTY_RASTER_STATE | DIRTY_VERTEXSHADER_STATE | DIRTY_GEOMETRYSHADER_STATE | DIRTY_UVSCALEOFFSET); if (drawEngineCommon_->CanUseHardwareTessellation(surface.primType)) { gstate_c.submitType = SubmitType::HW_SPLINE; if (gstate_c.spline_num_points_u != surface.num_points_u) { @@ -1280,7 +1282,7 @@ void GPUCommonHW::Execute_Spline(u32 op, u32 diff) { UpdateUVScaleOffset(); drawEngineCommon_->SubmitCurve(control_points, indices, surface, gstate.vertType, &bytesRead, "spline"); - gstate_c.Dirty(DIRTY_RASTER_STATE | DIRTY_VERTEXSHADER_STATE | DIRTY_GEOMETRYSHADER_STATE); + gstate_c.Dirty(DIRTY_RASTER_STATE | DIRTY_VERTEXSHADER_STATE | DIRTY_GEOMETRYSHADER_STATE | DIRTY_UVSCALEOFFSET); gstate_c.submitType = SubmitType::DRAW; // After drawing, we advance pointers - see SubmitPrim which does the same. diff --git a/GPU/GPUState.h b/GPU/GPUState.h index 9e2c31b0d9..6a1f14b81f 100644 --- a/GPU/GPUState.h +++ b/GPU/GPUState.h @@ -584,6 +584,11 @@ struct GPUStateCache { if (textureIsFramebuffer != isFramebuffer) { textureIsFramebuffer = isFramebuffer; Dirty(DIRTY_UVSCALEOFFSET); + } else if (isFramebuffer) { + // Always dirty if it's a framebuffer, since the uniform value depends both + // on the specified texture size and the bound texture size. Makes things easier. + // TODO: Look at this again later. + Dirty(DIRTY_UVSCALEOFFSET); } } void SetUseFlags(u32 newFlags) {