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);
            }
        }
예제 #2
0
        /// <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);
        }
예제 #3
0
 /// <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);