Latte: Rehash texture immediately if it switches to GPU-updated mode

This commit is contained in:
Exzap
2026-09-07 20:43:02 +02:00
parent bda380dd33
commit 303915a61e
4 changed files with 28 additions and 12 deletions

View File

@@ -124,6 +124,7 @@ void LatteTexture_ReloadData(LatteTexture* hostTexture);
bool LatteTC_HasTextureChanged(LatteTexture* hostTexture, bool force = false);
void LatteTC_ResetTextureChangeTracker(LatteTexture* hostTexture, bool force = false);
void LatteTC_FlagSliceAsGPUUpdated(LatteTexture* hostTexture, uint32 sliceIndex, uint32 mipIndex);
void LatteTC_MarkTextureStillInUse(LatteTexture* texture); // lets the texture garbage collector know the texture is still in use at the time of this function call
void LatteTC_CleanupUnusedTextures();

View File

@@ -117,7 +117,7 @@ void LatteSurfaceCopy_copySurfaceNew(const LatteSurfaceCopyParam& src, const Lat
LatteTC_ResetTextureChangeTracker(destinationTexture);
// flag texture as updated
destinationTexture->lastUpdateEventCounter = LatteTexture_getNextUpdateEventCounter();
destinationTexture->isUpdatedOnGPU = true; // todo - also track update flag per-slice
LatteTC_FlagSliceAsGPUUpdated(destinationTexture, destinationView->firstSlice, destinationView->firstMip);
}
else
debug_printf("Source or destination texture does not exist\n");

View File

@@ -539,7 +539,7 @@ void LatteTexture_UpdateTextureFromDynamicChanges(LatteTexture* texture)
LatteTexture_SyncSlice(subTexture, cSliceIndex, cMipIndex, baseTexture, texRel->baseSliceIndex + cSliceIndex, texRel->baseMipIndex + cMipIndex);
baseSliceMipInfo->lastDynamicUpdate = subSliceMipInfo->lastDynamicUpdate;
if(subTexture->isUpdatedOnGPU)
texture->isUpdatedOnGPU = true;
LatteTC_FlagSliceAsGPUUpdated(texture, baseSliceMipInfo->sliceIndex, baseSliceMipInfo->mipIndex);
}
}
else
@@ -550,7 +550,7 @@ void LatteTexture_UpdateTextureFromDynamicChanges(LatteTexture* texture)
LatteTexture_SyncSlice(baseTexture, texRel->baseSliceIndex + cSliceIndex, texRel->baseMipIndex + cMipIndex, subTexture, cSliceIndex, cMipIndex);
subSliceMipInfo->lastDynamicUpdate = baseSliceMipInfo->lastDynamicUpdate;
if (baseTexture->isUpdatedOnGPU)
texture->isUpdatedOnGPU = true;
LatteTC_FlagSliceAsGPUUpdated(texture, subSliceMipInfo->sliceIndex, subSliceMipInfo->mipIndex);
}
}
}
@@ -967,7 +967,7 @@ void LatteTexture_RecreateTextureWithDifferentMipSliceCount(LatteTexture* textur
if (texture->isUpdatedOnGPU)
{
LatteTexture_copyData(texture, view->baseTexture, texture->mipLevels, texture->depth);
view->baseTexture->isUpdatedOnGPU = true;
LatteTC_FlagSliceAsGPUUpdated(view->baseTexture, view->firstSlice, view->firstMip);
}
// remove old texture
LatteTexture_Delete(texture);
@@ -1384,7 +1384,6 @@ void LatteTexture_MarkConnectedTexturesForReloadFromDynamicTextures(LatteTexture
void LatteTexture_TrackTextureGPUWrite(LatteTexture* texture, uint32 slice, uint32 mip, uint64 eventCounter)
{
LatteTexture_MarkDynamicTextureAsChanged(texture->baseView, slice, mip, eventCounter);
LatteTC_ResetTextureChangeTracker(texture);
texture->isUpdatedOnGPU = true;
LatteTC_FlagSliceAsGPUUpdated(texture, slice, mip);
texture->lastUnflushedRTDrawcallIndex = LatteGPUState.drawCallCounter;
}

View File

@@ -207,12 +207,12 @@ bool LatteTC_HasTextureChanged(LatteTexture* hostTexture, bool force)
hostTexture->forceInvalidate = false;
}
// if texture is written by GPU operations we switch to a faster hash implementation
if (hostTexture->isUpdatedOnGPU && hostTexture->useLightHash == false)
{
hostTexture->useLightHash = true;
// update hash
hostTexture->texDataHash2 = LatteTexture_CalculateTextureDataHash(hostTexture);
}
// if (hostTexture->isUpdatedOnGPU && hostTexture->useLightHash == false)
// {
// hostTexture->useLightHash = true;
// // update hash
// hostTexture->texDataHash2 = LatteTexture_CalculateTextureDataHash(hostTexture);
// }
// only check each texture for updates once a frame
// todo: Instead of relying on frames, it would be better to recheck only after any GPU wait operation occurred.
if( hostTexture->lastDataUpdateFrameCounter == LatteGPUState.frameCounter && force == false)
@@ -244,6 +244,22 @@ bool LatteTC_HasTextureChanged(LatteTexture* hostTexture, bool force)
return false;
}
// For GPU updated textures we use a lighter hash algorithm. This also resets the current hash and loses any previous untracked modifications
void LatteTC_SwitchToLightHash(LatteTexture* hostTexture)
{
if (hostTexture->useLightHash)
return;
hostTexture->useLightHash = true;
hostTexture->texDataHash2 = LatteTexture_CalculateTextureDataHash(hostTexture);
}
void LatteTC_FlagSliceAsGPUUpdated(LatteTexture* hostTexture, uint32 sliceIndex, uint32 mipIndex)
{
// todo - track gpu updated state per slice
hostTexture->isUpdatedOnGPU = true;
LatteTC_SwitchToLightHash(hostTexture);
}
void LatteTC_ResetTextureChangeTracker(LatteTexture* hostTexture, bool force)
{
if( hostTexture->lastDataUpdateFrameCounter == LatteGPUState.frameCounter && force == false)