Пример #1
0
        internal void Update(ParameterUpdaterDefinition definition)
        {
            var sortedKeyHashes       = definition.SortedKeyHashes;
            var sortedKeyHashesLength = sortedKeyHashes.Length;

            if (sortedKeyHashesLength == 0)
            {
                return;
            }

            if (sortedKeyHashesLength > InternalValues.Length)
            {
                InternalValues = new BoundInternalValue[sortedKeyHashesLength];
            }


            // Optimization: nothing changed?
            if (previousParameterCollections == null || previousParameterCollections.Length < parameterCollections.Length)
            {
                previousParameterCollections = new int[parameterCollections.Length];
            }

            bool needUpdate = false;

            for (int levelIndex = 0; levelIndex < parameterCollections.Length; ++levelIndex)
            {
                var parameterCollection = parameterCollections[levelIndex];
                var keyCounter          = parameterCollection.KeyVersion;
                if (keyCounter != previousParameterCollections[levelIndex])
                {
                    needUpdate = true;
                    previousParameterCollections[levelIndex] = keyCounter;
                }
            }

            if (!needUpdate)
            {
                return;
            }

            // Temporary clear data for debug/test purposes (shouldn't necessary)
            for (int i = 0; i < sortedKeyHashesLength; ++i)
            {
                InternalValues[i] = new BoundInternalValue();
            }

            // Optimization: List is already prepared (with previous SetKeyMapping() call)
            var collection = parameterCollections[0];
            var keys       = collection.IndexedInternalValues;

            for (int i = 0; i < keys.Length; ++i)
            {
                var internalValue = keys[i];
                if (internalValue != null)
                {
                    InternalValues[i] = new BoundInternalValue(0, internalValue);
                }
            }

            // Iterate over parameter collections
            for (int levelIndex = 1; levelIndex < parameterCollections.Length; ++levelIndex)
            {
                var level              = parameterCollections[levelIndex].InternalValues;
                int index              = 0;
                var currentHash        = sortedKeyHashes[index];
                int internalValueCount = level.Count;
                var items              = level.Items;

                // Iterate over each items
                // Since both expected values and parameter collection values are sorted,
                // we iterate over both of them together so that we can easily detect what needs to be copied.
                // Note: We use a 64-bit hash that we assume has no collision (maybe we should
                //       detect unlikely collision when registering them?)
                for (int i = 0; i < internalValueCount; ++i)
                {
                    var internalValue = items[i];
                    var expectedHash  = internalValue.Key.HashCode;
                    //index = InternalValueBinarySearch(sortedKeyHashes, internalValue.Key.GetHashCode());
                    while (currentHash < expectedHash)
                    {
                        if (++index >= sortedKeyHashesLength)
                        {
                            break;
                        }
                        currentHash = sortedKeyHashes[index];
                    }
                    if (currentHash == expectedHash)
                    {
                        // Update element
                        InternalValues[index] = new BoundInternalValue(levelIndex, internalValue.Value);
                    }
                }
            }
        }
        internal void Update(GraphicsDevice graphicsDevice, EffectParameterUpdaterDefinition definition)
        {
            Update(definition);

            // ----------------------------------------------------------------
            // Update dynamic values
            // Definitions based on Default+Pass lists
            // ----------------------------------------------------------------
            var dependencies = definition.Dependencies;

            for (int dependencyIndex = 0; dependencyIndex < dependencies.Length; ++dependencyIndex)
            {
                var dependency       = dependencies[dependencyIndex];
                int highestLevel     = 0;
                int destinationLevel = InternalValues[dependency.Destination].DirtyCount;

                var  destination = InternalValues[dependency.Destination];
                bool needUpdate  = false;
                for (int i = 0; i < dependency.Sources.Length; ++i)
                {
                    var source      = InternalValues[dependency.Sources[i]];
                    var sourceLevel = source.DirtyCount;

                    if (highestLevel < sourceLevel)
                    {
                        highestLevel = sourceLevel;
                    }
                }

                if (destinationLevel < highestLevel)
                {
                    // Dynamic value: the sources of this dynamic value are defined in a most derived collection than its destination collection
                    // as a result, we need to create or use a new dynamic value at the appropriate level.

                    // Find last collection index (excluding parameterOverrides)
                    int maxLevelNoOverride = parameterCollections.Length - 1;
                    if (highestLevel <= maxLevelNoOverride)
                    {
                        // TODO: Choose target level more properly (i.e. mesh*pass => meshpass)
                        // Sources all comes from normal collections => override in the most derived collection
                        // For now, use maxLevelNoOverride instead of highestLevel just to be safe.
                        var bestCollectionForDynamicValue = parameterCollections[maxLevelNoOverride];
                        var key = definition.SortedKeys[dependency.Destination];
                        bestCollectionForDynamicValue.SetDefault(key, true);
                        InternalValues[dependency.Destination] = destination = new BoundInternalValue(highestLevel, bestCollectionForDynamicValue.GetInternalValue(key));
                    }
                    else
                    {
                        // At least one source comes from TLS override, so use dynamic from TLS dynamic storage as well.
                        InternalValues[dependency.Destination] = destination = new BoundInternalValue(parameterCollections.Length, definition.ThreadLocalDynamicValues[graphicsDevice.ThreadIndex][dependencyIndex]);
                    }

                    needUpdate = true;
                }

                // Force updating (even if no parameters has been updated)
                if (!dependency.Dynamic.AutoCheckDependencies)
                {
                    needUpdate = true;
                }

                if (destination.Value.Dependencies == null || destination.Value.Dependencies.Length < dependency.Sources.Length)
                {
                    destination.Value.Dependencies = new ParameterCollection.InternalValueReference[dependency.Sources.Length];
                }

                var dependencyParameters = destination.Value.Dependencies;
                for (int i = 0; i < dependency.Sources.Length; ++i)
                {
                    var source        = InternalValues[dependency.Sources[i]];
                    var internalValue = source.Value;

                    if (dependencyParameters[i].Entry != internalValue)
                    {
                        needUpdate = true;
                        dependencyParameters[i].Entry   = internalValue;
                        dependencyParameters[i].Counter = internalValue.Counter;
                    }
                    else if (dependencyParameters[i].Counter != internalValue.Counter)
                    {
                        needUpdate = true;
                        dependencyParameters[i].Counter = internalValue.Counter;
                    }
                }

                if (needUpdate)
                {
                    // At least one source was updated
                    dependency.Dynamic.GetValue(destination.Value);
                    destination.Value.Counter++;
                }
            }
        }
        internal void Update(ParameterUpdaterDefinition definition)
        {
            var sortedKeyHashes = definition.SortedKeyHashes;
            var sortedKeyHashesLength = sortedKeyHashes.Length;
            if (sortedKeyHashesLength == 0)
                return;

            if (sortedKeyHashesLength > InternalValues.Length)
                InternalValues = new BoundInternalValue[sortedKeyHashesLength];


            // Optimization: nothing changed?
            if (previousParameterCollections == null || previousParameterCollections.Length < parameterCollections.Length)
            {
                previousParameterCollections = new int[parameterCollections.Length];
            }

            bool needUpdate = false;
            for (int levelIndex = 0; levelIndex < parameterCollections.Length; ++levelIndex)
            {
                var parameterCollection = parameterCollections[levelIndex];
                var keyCounter = parameterCollection.KeyVersion;
                if (keyCounter != previousParameterCollections[levelIndex])
                {
                    needUpdate = true;
                    previousParameterCollections[levelIndex] = keyCounter;
                }
            }

            if (!needUpdate)
            {
                return;
            }

            // Temporary clear data for debug/test purposes (shouldn't necessary)
            for (int i = 0; i < sortedKeyHashesLength; ++i)
                InternalValues[i] = new BoundInternalValue();

            // Optimization: List is already prepared (with previous SetKeyMapping() call)
            var collection = parameterCollections[0];
            var keys = collection.IndexedInternalValues;
            for (int i = 0; i < keys.Length; ++i)
            {
                var internalValue = keys[i];
                if (internalValue != null)
                    InternalValues[i] = new BoundInternalValue(0, internalValue);
            }

            // Iterate over parameter collections
            for (int levelIndex = 1; levelIndex < parameterCollections.Length; ++levelIndex)
            {
                var level = parameterCollections[levelIndex].InternalValues;
                int index = 0;
                var currentHash = sortedKeyHashes[index];
                int internalValueCount = level.Count;
                var items = level.Items;

                // Iterate over each items
                // Since both expected values and parameter collection values are sorted,
                // we iterate over both of them together so that we can easily detect what needs to be copied.
                // Note: We use a 64-bit hash that we assume has no collision (maybe we should
                //       detect unlikely collision when registering them?)
                for (int i = 0; i < internalValueCount; ++i)
                {
                    var internalValue = items[i];
                    var expectedHash = internalValue.Key.HashCode;
                    //index = InternalValueBinarySearch(sortedKeyHashes, internalValue.Key.GetHashCode());
                    while (currentHash < expectedHash)
                    {
                        if (++index >= sortedKeyHashesLength)
                            break;
                        currentHash = sortedKeyHashes[index];
                    }
                    if (currentHash == expectedHash)
                    {
                        // Update element
                        InternalValues[index] = new BoundInternalValue(levelIndex, internalValue.Value);
                    }
                }
            }
        }