Ejemplo n.º 1
0
        public LSystemState <float> StepSystem(LSystemState <float> systemState, float[] globalParameters = null, bool disposeOldSystem = true)
        {
#if UNITY_EDITOR
            try
            {
#endif
            var stepper = StepSystemJob(systemState, globalParameters);
            while (!stepper.IsComplete())
            {
                stepper = stepper.StepNextTyped();
            }
            if (disposeOldSystem)
            {
                systemState.currentSymbols.Dispose();
            }
            if (stepper.HasErrored())
            {
                throw new LSystemRuntimeException("Error during stepping");
            }
            return(stepper.GetData());

#if UNITY_EDITOR
        }

        catch (System.Exception e)
        {
            Debug.LogException(e);
            throw;
        }
#endif
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Step the given <paramref name="systemState"/>. returning the new system state. No modifications are made the the system sate
        /// Rough system step process:
        ///     1. iterate through the current system state, retrieving the maximum # of parameters that can be captured for each symbol.
        ///         Track symbols with conditionals seperately. during the match phase, every rule which is a conditional will match if possible
        ///         and if no higher-ranking rule has matched yet. Allocate memory for the possible match array, and the parameter match array
        ///     2. batch process each potential match, and each possible conditional. stop processing rules for a specific symbol once any non-conditional
        ///         rule matches. write all matched parameters for every matched rule into temporary parameter memory space.
        ///     3. Match selection: For each symbol, iterate through the possible matches identified in #2. When the first match is found, populate info about the selected
        ///         match and the size of the replacement into singleton
        ///     4. Sum up the new symbol string length, and allocate memory for it.
        ///     5. Batch process each symbol in parallel again, this time writing the replacement symbols themselves into memory. Will rely on reading parameters
        ///         out of the memory allocated in
        /// </summary>
        /// <param name="systemState">The entire state of the L-system. no modifications are made to this object or the contained properties.</param>
        /// <param name="globalParameters">The global parameters, if any</param>
        public ICompletable <LSystemState <float> > StepSystemJob(LSystemState <float> systemState, float[] globalParameters = null, JobHandle parameterWriteDependency = default)
        {
            if (isDisposed)
            {
                Debug.LogError($"LSystem has already been disposed");
                return(null);
            }
            UnityEngine.Profiling.Profiler.BeginSample("L system step");
            if (globalParameters == null)
            {
                globalParameters = new float[0];
            }

            var globalParamSize = globalParameters.Length;

            if (globalParamSize != GlobalParameters)
            {
                throw new LSystemRuntimeException($"Incomplete parameters provided. Expected {GlobalParameters} parameters but got {globalParamSize}");
            }

            var result = new LSystemParameterSizeCountingCompletable(
                systemState,
                nativeRuleData,
                globalParameters,
                includedCharacters,
                customSymbols,
                parameterWriteDependency);

            UnityEngine.Profiling.Profiler.EndSample();
            return(result);
        }
Ejemplo n.º 3
0
        public ICompletable StepNext()
        {
            currentJobHandle.Complete();
            branchingCache.Dispose();
            matchSingletonData.Dispose();
            if (diffusionHelper.IsCreated)
            {
                diffusionHelper.Dispose();
            }

            var hasImmatureSymbols = false;

            if (isImmature.IsCreated)
            {
                hasImmatureSymbols = isImmature[0];
                isImmature.Dispose();
            }

            var newResult = new LSystemState <float>
            {
                randomProvider     = randResult,
                currentSymbols     = new DependencyTracker <SymbolString <float> >(target),
                maxUniqueOrganIds  = maxIdReached[0],
                hasImmatureSymbols = hasImmatureSymbols,
                firstUniqueOrganId = lastSystemState.firstUniqueOrganId,
                uniquePlantId      = lastSystemState.uniquePlantId,
            };

            maxIdReached.Dispose();
            return(new CompleteCompletable <LSystemState <float> >(newResult));
        }
Ejemplo n.º 4
0
        public LSystemParameterSizeCountingCompletable(
            LSystemState <float> systemState,
            DependencyTracker <SystemLevelRuleNativeData> lSystemNativeData,
            float[] globalParameters,
            ISet <int>[] includedCharactersByRuleIndex,
            CustomRuleSymbols customSymbols,
            JobHandle parameterModificationJobDependency)
        {
            currentJobHandle = default;

            this.globalParameters            = globalParameters;
            this.paramModificationDependency = parameterModificationJobDependency;

            this.systemState   = systemState;
            this.customSymbols = customSymbols;
            nativeData         = lSystemNativeData;

            // 1.
            UnityEngine.Profiling.Profiler.BeginSample("Paramter counts");

            UnityEngine.Profiling.Profiler.BeginSample("allocating");
            matchSingletonData = new NativeArray <LSystemSingleSymbolMatchData>(systemState.currentSymbols.Data.Length, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);
            parameterTotalSum  = new NativeArray <int>(1, Allocator.TempJob);
            UnityEngine.Profiling.Profiler.EndSample();

            var memorySizeJob = new SymbolStringMemoryRequirementsJob
            {
                matchSingletonData          = matchSingletonData,
                memoryRequirementsPerSymbol = nativeData.Data.maxParameterMemoryRequirementsPerSymbol,
                parameterTotalSum           = parameterTotalSum,
                sourceSymbolString          = systemState.currentSymbols.Data
            };

            currentJobHandle = memorySizeJob.Schedule();
            systemState.currentSymbols.RegisterDependencyOnData(currentJobHandle);
            nativeData.RegisterDependencyOnData(currentJobHandle);


            UnityEngine.Profiling.Profiler.EndSample();

            // 2.1
            UnityEngine.Profiling.Profiler.BeginSample("branch cache");
            branchingCache = new SymbolStringBranchingCache(
                customSymbols.branchOpenSymbol,
                customSymbols.branchCloseSymbol,
                includedCharactersByRuleIndex,
                nativeData.Data);
            branchingCache.BuildJumpIndexesFromSymbols(systemState.currentSymbols);
            UnityEngine.Profiling.Profiler.EndSample();
        }
Ejemplo n.º 5
0
        private JobHandle ScheduleIdAssignmentJob(
            JobHandle dependency,
            CustomRuleSymbols customSymbols,
            LSystemState <float> lastSystemState)
        {
            // identity assignment job is not dependent on the source string or any other native data. can skip assigning it as a dependent
            maxIdReached = new NativeArray <uint>(1, Allocator.TempJob);
            var identityAssignmentJob = new IdentityAssignmentPostProcessRule
            {
                targetData            = target,
                maxIdentityId         = maxIdReached,
                customSymbols         = customSymbols,
                lastMaxIdReached      = lastSystemState.maxUniqueOrganIds,
                uniquePlantId         = lastSystemState.uniquePlantId,
                originOfUniqueIndexes = lastSystemState.firstUniqueOrganId,
            };

            return(identityAssignmentJob.Schedule(dependency));
        }
Ejemplo n.º 6
0
        public LSystemSymbolReplacementCompletable(
            Unity.Mathematics.Random randResult,
            LSystemState <float> lastSystemState,
            int totalNewSymbolSize,
            int totalNewParamSize,
            NativeArray <float> globalParamNative,
            NativeArray <float> tmpParameterMemory,
            NativeArray <LSystemSingleSymbolMatchData> matchSingletonData,
            DependencyTracker <SystemLevelRuleNativeData> nativeData,
            SymbolStringBranchingCache branchingCache,
            CustomRuleSymbols customSymbols)
        {
            this.lastSystemState    = lastSystemState;
            this.matchSingletonData = matchSingletonData;
            this.branchingCache     = branchingCache;
            UnityEngine.Profiling.Profiler.BeginSample("allocating");
            target = new SymbolString <float>(totalNewSymbolSize, totalNewParamSize, Allocator.Persistent);
            UnityEngine.Profiling.Profiler.EndSample();

            this.randResult = randResult;

            this.nativeData = nativeData;

            // 5
            UnityEngine.Profiling.Profiler.BeginSample("generating replacements");

            var replacementJob = new RuleReplacementJob
            {
                globalParametersArray = globalParamNative,

                parameterMatchMemory = tmpParameterMemory,
                matchSingletonData   = matchSingletonData,

                sourceData            = lastSystemState.currentSymbols.Data,
                structExpressionSpace = nativeData.Data.structExpressionMemorySpace,
                globalOperatorData    = nativeData.Data.dynamicOperatorMemory,
                replacementSymbolData = nativeData.Data.replacementsSymbolMemorySpace,
                outcomeData           = nativeData.Data.ruleOutcomeMemorySpace,

                targetData = target,
                blittableRulesByTargetSymbol = nativeData.Data.blittableRulesByTargetSymbol,
                branchingCache = branchingCache,
                customSymbols  = customSymbols
            };

            currentJobHandle = replacementJob.Schedule(
                matchSingletonData.Length,
                100
                );

            if (customSymbols.hasDiffusion && !customSymbols.independentDiffusionUpdate)
            {
                diffusionHelper = new DiffusionWorkingDataPack(10, 5, 2, customSymbols, Allocator.TempJob);
                var diffusionJob = new ParallelDiffusionReplacementJob
                {
                    matchSingletonData = matchSingletonData,
                    sourceData         = lastSystemState.currentSymbols.Data,
                    targetData         = target,
                    customSymbols      = customSymbols,
                    working            = diffusionHelper
                };
                currentJobHandle = JobHandle.CombineDependencies(
                    currentJobHandle,
                    diffusionJob.Schedule()
                    );
            }
            // only parameter modifications beyond this point
            lastSystemState.currentSymbols.RegisterDependencyOnData(currentJobHandle);
            nativeData.RegisterDependencyOnData(currentJobHandle);

            currentJobHandle = JobHandle.CombineDependencies(
                JobHandle.CombineDependencies(
                    ScheduleIdAssignmentJob(currentJobHandle, customSymbols, lastSystemState),
                    ScheduleIndependentDiffusion(currentJobHandle, customSymbols)
                    ),
                JobHandle.CombineDependencies(
                    ScheduleAutophagyJob(currentJobHandle, customSymbols),
                    ScheduleImmaturityJob(currentJobHandle)
                    ));

            UnityEngine.Profiling.Profiler.EndSample();
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="lastSystemState"></param>
        /// <param name="lSystemNativeData"></param>
        /// <param name="globalParameters"></param>
        /// <param name="maxMemoryRequirementsPerSymbol"></param>
        /// <param name="branchOpenSymbol"></param>
        /// <param name="branchCloseSymbol"></param>
        /// <param name="includedCharactersByRuleIndex"></param>
        /// <param name="customSymbols"></param>
        /// <param name="parameterModificationJobDependency">A dependency on a job which only makes changes to the parameters of the source symbol string.
        ///     the symbols themselves must be constant</param>
        public LSystemRuleMatchCompletable(
            NativeArray <LSystemSingleSymbolMatchData> matchSingletonData,
            int parameterTotalSum,
            SymbolStringBranchingCache branchingCache,
            LSystemState <float> lastSystemState,
            DependencyTracker <SystemLevelRuleNativeData> lSystemNativeData,
            float[] globalParameters,
            CustomRuleSymbols customSymbols,
            JobHandle parameterModificationJobDependency)
        {
            this.customSymbols   = customSymbols;
            this.lastSystemState = lastSystemState;
            randResult           = lastSystemState.randomProvider;
            nativeData           = lSystemNativeData;

            this.matchSingletonData = matchSingletonData;
            this.branchingCache     = branchingCache;

            // 1.
            UnityEngine.Profiling.Profiler.BeginSample("allocating");
            tmpParameterMemory = new NativeArray <float>(parameterTotalSum, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);
            globalParamNative  = new NativeArray <float>(globalParameters, Allocator.Persistent);
            UnityEngine.Profiling.Profiler.EndSample();

            // 2.
            UnityEngine.Profiling.Profiler.BeginSample("matching");


            var prematchJob = new RuleCompleteMatchJob
            {
                matchSingletonData = matchSingletonData,

                sourceData         = lastSystemState.currentSymbols.Data,
                tmpParameterMemory = tmpParameterMemory,

                globalOperatorData = nativeData.Data.dynamicOperatorMemory,
                outcomes           = nativeData.Data.ruleOutcomeMemorySpace,
                globalParams       = globalParamNative,

                blittableRulesByTargetSymbol = nativeData.Data.blittableRulesByTargetSymbol,
                branchingCache = branchingCache,
                seed           = randResult.NextUInt()
            };

            var matchingJobHandle = prematchJob.ScheduleBatch(
                matchSingletonData.Length,
                100,
                parameterModificationJobDependency);


            UnityEngine.Profiling.Profiler.EndSample();

            // 4.
            UnityEngine.Profiling.Profiler.BeginSample("replacement counting");

            UnityEngine.Profiling.Profiler.BeginSample("allocating");
            totalSymbolCount          = new NativeArray <int>(1, Allocator.Persistent);
            totalSymbolParameterCount = new NativeArray <int>(1, Allocator.Persistent);
            UnityEngine.Profiling.Profiler.EndSample();

            var totalSymbolLengthJob = new RuleReplacementSizeJob
            {
                matchSingletonData        = matchSingletonData,
                totalResultSymbolCount    = totalSymbolCount,
                totalResultParameterCount = totalSymbolParameterCount,
                sourceData    = lastSystemState.currentSymbols.Data,
                customSymbols = customSymbols
            };

            currentJobHandle = totalSymbolLengthJob.Schedule(matchingJobHandle);
            lastSystemState.currentSymbols.RegisterDependencyOnData(currentJobHandle);
            nativeData.RegisterDependencyOnData(currentJobHandle);

            UnityEngine.Profiling.Profiler.EndSample();
        }