private void Update(StreamableResource resource, ref DateTime now) { Debug.Assert(resource != null && resource.CanBeUpdated, $"resource[{resource}] != null && resource.CanBeUpdated[{resource?.CanBeUpdated}]"); var options = resource.StreamingOptions ?? StreamingOptions.Default; var isUnderBudget = AllocatedMemory < TargetedMemoryBudget; // Calculate target quality for that asset StreamingQuality targetQuality = StreamingQuality.Mininum; if (isUnderBudget || resource.LastTimeUsed > 0 || options.KeepLoaded) { var lastUsageTimespan = new TimeSpan((frameIndex - resource.LastTimeUsed) * ManagerUpdatesInterval.Ticks); if (isUnderBudget || lastUsageTimespan <= ResourceLiveTimeout || options.KeepLoaded) { targetQuality = StreamingQuality.Maximum; #if USE_TEST_MANUAL_QUALITY targetQuality = (testQuality / 100.0f); // apply quality scale for testing #endif // TODO: here we should apply resources group master scale (based on game settings quality level and memory level) } } targetQuality.Normalize(); // Calculate target residency level (discrete value) var currentResidency = resource.CurrentResidency; var allocatedResidency = resource.AllocatedResidency; var targetResidency = resource.CalculateTargetResidency(targetQuality); Debug.Assert(allocatedResidency >= currentResidency && allocatedResidency >= 0, $"allocatedResidency[{allocatedResidency}] >= currentResidency[{currentResidency }] && allocatedResidency[{allocatedResidency }] >= 0"); // Update target residency smoothing // TODO: use move quality samples and use max or avg value - make that input it smooth - or use PID //resource.QualitySamples.Add(targetResidency); //targetResidency = resource.QualitySamples.Maximum(); // Assign last update time resource.LastUpdate = now; // Check if a target residency level has been changed if (targetResidency != resource.TargetResidency) { // Register change resource.TargetResidency = targetResidency; resource.TargetResidencyChange = now; } // Check if need to change resource current residency if (targetResidency != currentResidency) { // Calculate residency level to stream in (resources may want to incease/decrease it's quality in steps rather than at once) var requestedResidency = resource.CalculateRequestedResidency(targetResidency); if (options.ForceHighestQuality) { requestedResidency = targetResidency; } // Create streaming task (resource type specific) StreamAsync(resource, requestedResidency); } }
private Task StreamAsync(StreamableResource resource, int residency) { activeStreaming.Add(resource); var task = resource.StreamAsyncInternal(residency); task.Start(); return(task); }
internal void RegisterResource(StreamableResource resource) { Debug.Assert(resource != null && isDisposing == false, $"resource[{resource}] != null && isDisposing[{isDisposing }] == false"); lock (resources) { Debug.Assert(!resources.Contains(resource), "!resources.Contains(resource)"); resources.Add(resource); resourcesLookup.Add(resource.Resource, resource); } }
private void FullyLoadResource(StreamableResource resource) { if (resource.AllocatedResidency == resource.MaxResidency) { return; } // Stream resource to the maximum level // Note: this does not care about MaxTasksRunningSimultaneously limit var task = StreamAsync(resource, resource.MaxResidency); task.Wait(); // Synchronize FlushSync(); }
internal void UnregisterResource(StreamableResource resource) { if (isDisposing) { return; } Debug.Assert(resource != null, "resource != null"); lock (resources) { Debug.Assert(resources.Contains(resource), "resources.Contains(resource)"); resources.Remove(resource); resourcesLookup.Remove(resource.Resource); activeStreaming.Remove(resource); } }