コード例 #1
0
        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
        private Task StreamAsync(StreamableResource resource, int residency)
        {
            activeStreaming.Add(resource);
            var task = resource.StreamAsyncInternal(residency);

            task.Start();

            return(task);
        }
コード例 #3
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);
                resourcesLookup.Add(resource.Resource, resource);
            }
        }
コード例 #4
0
        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();
        }
コード例 #5
0
        internal void UnregisterResource(StreamableResource resource)
        {
            if (isDisposing)
            {
                return;
            }

            Debug.Assert(resource != null, "resource != null");

            using (resourceLocker.WriteLock())
            {
                Debug.Assert(resources.Contains(resource), "resources.Contains(resource)");

                resources.Remove(resource);
                resourcesLookup.TryRemove(resource.Resource, out var _);
                activeStreaming.Remove(resource);
            }
        }
コード例 #6
0
        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);
            }
        }
コード例 #7
0
        public override void Update(GameTime gameTime)
        {
            base.Update(gameTime);

            // Make sure enough time passed
            if (gameTime.Total < lastUpdate + ManagerUpdatesInterval)
            {
                return;
            }

            // Update resources
            if (Enabled)
            {
                // Perform synchronization
                FlushSync();

#if USE_TEST_MANUAL_QUALITY // Temporary testing code used for testing quality changing using K/L keys
                if (((Game)Game).Input.IsKeyPressed(Xenko.Input.Keys.K))
                {
                    testQuality = Math.Min(testQuality + 5, 100);
                }
                if (((Game)Game).Input.IsKeyPressed(Xenko.Input.Keys.L))
                {
                    testQuality = Math.Max(testQuality - 5, 0);
                }
#endif
                var now      = DateTime.UtcNow;
                int toUpdate = -1;

                do
                {
                    if (HasActiveTaskSlotFree == false)
                    {
                        goto skip;
                    }

                    StreamableResource resource = null;

                    using (resourceLocker.ReadLock())
                    {
                        int cnt = Resources.Count;
                        if (cnt == 0)
                        {
                            goto skip;
                        }
                        if (toUpdate == -1)
                        {
                            toUpdate = cnt - 1;
                        }
                        else
                        {
                            toUpdate--;
                        }

                        // Move forward
                        // Note: we update resources like in a ring buffer
                        lastUpdateResourcesIndex++;
                        if (lastUpdateResourcesIndex >= cnt)
                        {
                            lastUpdateResourcesIndex = 0;
                        }

                        // Update resource
                        resource = resources[lastUpdateResourcesIndex];
                    }

                    var ignoreResource = resource.StreamingOptions?.IgnoreResource ?? false;
                    if (resource.CanBeUpdated && !ignoreResource)
                    {
                        Update(resource, ref now);
                    }
                } while (toUpdate > 0);
            }

            skip : ContentStreaming.Update();

            frameIndex++;

            lastUpdate = gameTime.Total;
        }