diff --git a/src/Cafe/HW/Latte/Core/Latte.h b/src/Cafe/HW/Latte/Core/Latte.h index 711bb087..d99e7dba 100644 --- a/src/Cafe/HW/Latte/Core/Latte.h +++ b/src/Cafe/HW/Latte/Core/Latte.h @@ -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(); diff --git a/src/Cafe/HW/Latte/Core/LatteSurfaceCopy.cpp b/src/Cafe/HW/Latte/Core/LatteSurfaceCopy.cpp index 4f8e8ed3..a018fe83 100644 --- a/src/Cafe/HW/Latte/Core/LatteSurfaceCopy.cpp +++ b/src/Cafe/HW/Latte/Core/LatteSurfaceCopy.cpp @@ -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"); diff --git a/src/Cafe/HW/Latte/Core/LatteTexture.cpp b/src/Cafe/HW/Latte/Core/LatteTexture.cpp index 4f47e1a6..80cc9acd 100644 --- a/src/Cafe/HW/Latte/Core/LatteTexture.cpp +++ b/src/Cafe/HW/Latte/Core/LatteTexture.cpp @@ -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; } diff --git a/src/Cafe/HW/Latte/Core/LatteTextureCache.cpp b/src/Cafe/HW/Latte/Core/LatteTextureCache.cpp index 3145e90e..d39d8753 100644 --- a/src/Cafe/HW/Latte/Core/LatteTextureCache.cpp +++ b/src/Cafe/HW/Latte/Core/LatteTextureCache.cpp @@ -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)