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); } }
/// <inheritdoc /> public override int CalculateTargetResidency(StreamingQuality quality) { if (MathUtil.IsZero(quality)) { return(0); } var result = Math.Max(1, (int)(TotalMipLevels * quality)); // Compressed formats have aligment restrictions on the dimensions of the texture (minimum size must be 4) if (Format.IsCompressed() && TotalMipLevels >= 3) { result = MathUtil.Clamp(result, 3, TotalMipLevels); } return(result); }
/// <summary> /// Calculates the target residency level for this resource based on a given uniform quality. /// </summary> /// <param name="quality">The quality.</param> /// <returns>Target residency.</returns> public abstract int CalculateTargetResidency(StreamingQuality quality);