Skip to content

Commit

Permalink
Merge pull request #17582 from hrydgard/uvscaleoffset-fix
Browse files Browse the repository at this point in the history
Update the uvscale uniform a bit more conservatively on framebuffer-texture changes
  • Loading branch information
hrydgard authored Jun 15, 2023
2 parents 4a4cd3d + def09bf commit fee65be
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 29 deletions.
16 changes: 10 additions & 6 deletions GPU/Common/ShaderUniforms.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
19 changes: 12 additions & 7 deletions GPU/Common/TextureCacheCommon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -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");
Expand Down
16 changes: 10 additions & 6 deletions GPU/Directx9/ShaderManagerDX9.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
16 changes: 10 additions & 6 deletions GPU/GLES/ShaderManagerGLES.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
10 changes: 6 additions & 4 deletions GPU/GPUCommonHW.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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.
Expand Down Expand Up @@ -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) {
Expand All @@ -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.
Expand Down
5 changes: 5 additions & 0 deletions GPU/GPUState.h
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down

0 comments on commit fee65be

Please sign in to comment.