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 }
/// <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); }
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)); }
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(); }
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)); }
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(); }