introduce loadingImages & add a lock around image load/unload state
This commit is contained in:
parent
ad598e68a5
commit
33f6ee739e
71
Program.cs
71
Program.cs
@ -571,6 +571,8 @@ public class Game : GameWindow {
|
||||
List<Photo> allPhotos = new();
|
||||
List<Photo> photos = new();
|
||||
HashSet<Photo> loadedImages = new();
|
||||
HashSet<Photo> loadingImages = new();
|
||||
readonly object loadedImagesLock = new();
|
||||
int photoIndex = 0;
|
||||
int ribbonIndex = 0;
|
||||
Shader shader = new();
|
||||
@ -777,10 +779,10 @@ public class Game : GameWindow {
|
||||
|
||||
// Load photos from a directory.
|
||||
// string[] files = Directory.GetFiles(@"c:\users\colin\desktop\photos-test\");
|
||||
string[] files = Directory.GetFiles(@"c:\users\colin\pictures\photos\2023\07\14\");
|
||||
// string[] files = Directory.GetFiles(@"c:\users\colin\pictures\photos\2023\07\14\");
|
||||
// string[] files = Directory.GetFiles(@"G:\DCIM\100EOSR6\");
|
||||
// string[] files = Directory.GetFiles(@"C:\Users\colin\Pictures\photos\2018\06\23");
|
||||
// string[] files = Directory.GetFiles(@"C:\Users\colin\Desktop\Germany all\104D7000");
|
||||
string[] files = Directory.GetFiles(@"C:\Users\colin\Desktop\Germany all\104D7000");
|
||||
// string[] files = Directory.GetFiles(@"C:\Users\colin\Desktop\many-birds\");
|
||||
|
||||
for (int i = 0; i < files.Count(); i++) {
|
||||
@ -809,43 +811,62 @@ public class Game : GameWindow {
|
||||
base.OnUnload();
|
||||
}
|
||||
|
||||
private async void LoadAndUnloadImagesAsync() {
|
||||
int minLoadedImage = Math.Max(0, photoIndex - 20);
|
||||
int maxLoadedImage = Math.Min(photoIndex + 20, photos.Count - 1);
|
||||
// First, unload images that haven't been touched in a while.
|
||||
// FIXME: also cancel any of these if they still have an in-progress loading task?
|
||||
private void UnloadImages() {
|
||||
// Unload images that haven't been touched in a while.
|
||||
// FIXME: keep around thumbnail-sized textures?
|
||||
while (loadedImages.Count > 60) {
|
||||
long earliestTime = long.MaxValue;
|
||||
Photo? earliest = null;
|
||||
foreach (Photo photo in loadedImages) {
|
||||
if (photo.LastTouch < earliestTime) {
|
||||
earliest = photo;
|
||||
earliestTime = photo.LastTouch;
|
||||
lock (loadedImagesLock) {
|
||||
while (loadedImages.Count > 60) {
|
||||
long earliestTime = long.MaxValue;
|
||||
Photo? earliest = null;
|
||||
foreach (Photo photo in loadedImages) {
|
||||
if (photo.LastTouch < earliestTime) {
|
||||
earliest = photo;
|
||||
earliestTime = photo.LastTouch;
|
||||
}
|
||||
}
|
||||
if (earliest != null) {
|
||||
// Console.WriteLine($"loadedImages.Count: {loadedImages.Count}, evicting {earliest.Filename} @ {earliestTime}");
|
||||
// TODO: we have to free textures on the GL thread, but could we do that async'ly to keep the UI responsive?
|
||||
earliest.Unload();
|
||||
loadedImages.Remove(earliest);
|
||||
}
|
||||
}
|
||||
if (earliest != null) {
|
||||
Console.WriteLine($"loadedImages.Count: {loadedImages.Count}, evicting {earliest.Filename} @ {earliestTime}");
|
||||
// TODO: we have to free textures on the GL thread, but could we do that async'ly to keep the UI responsive?
|
||||
earliest.Unload();
|
||||
loadedImages.Remove(earliest);
|
||||
}
|
||||
}
|
||||
|
||||
private async void LoadImagesAsync() {
|
||||
foreach (Photo p in loadingImages) {
|
||||
if (p.Loaded) {
|
||||
lock (loadedImagesLock) {
|
||||
loadedImages.Add(p);
|
||||
loadingImages.Remove(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Then, start loading any images that are in our window but not yet loaded.
|
||||
// Start loading any images that are in our window but not yet loaded.
|
||||
int minLoadedImage = Math.Max(0, photoIndex - 20);
|
||||
int maxLoadedImage = Math.Min(photoIndex + 20, photos.Count - 1);
|
||||
List<Photo> toLoad = new();
|
||||
for (int i = minLoadedImage; i <= maxLoadedImage; i++) {
|
||||
if (!loadedImages.Contains(photos[i])) {
|
||||
Console.WriteLine("loading " + i);
|
||||
loadedImages.Add(photos[i]);
|
||||
await Task.Run( () => { photos[i].LoadAsync(); });
|
||||
lock (loadedImagesLock) {
|
||||
if (!loadedImages.Contains(photos[i]) && !loadingImages.Contains(photos[i])) {
|
||||
Console.WriteLine("loading " + i);
|
||||
loadingImages.Add(photos[i]);
|
||||
toLoad.Add(photos[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach (Photo p in toLoad) {
|
||||
await Task.Run( () => { p.LoadAsync(); });
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnRenderFrame(FrameEventArgs e) {
|
||||
base.OnRenderFrame(e);
|
||||
fpsCounter.Update();
|
||||
|
||||
LoadAndUnloadImagesAsync();
|
||||
UnloadImages();
|
||||
LoadImagesAsync();
|
||||
|
||||
GL.Clear(ClearBufferMask.ColorBufferBit);
|
||||
GL.BindBuffer(BufferTarget.ArrayBuffer, VertexBufferObject);
|
||||
|
Loading…
Reference in New Issue
Block a user