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);
            }
        }
Example #4
0
        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);
                if (resourcesLookup.TryAdd(resource.Resource, resource) == false)
                {
                    throw new InvalidOperationException();
                }
            }
        }
        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
            if (resource.CurrentResidency != resource.MaxResidency)
            {
                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);
            }
        }