// Get the operands for the runtime evaluation
        public Operands GetOperands(VFXExpressionGraph graph)
        {
            var addOperands = additionnalOperands;

            if (parents.Length + addOperands.Length > 4)
            {
                throw new Exception("Too much parameter for expression : " + this);
            }

            var data = new Operands(-1);

            if (graph != null)
            {
                for (int i = 0; i < parents.Length; ++i)
                {
                    data[i] = graph.GetFlattenedIndex(parents[i]);
                }
            }

            for (int i = 0; i < addOperands.Length; ++i)
            {
                data[Operands.OperandCount - addOperands.Length + i] = addOperands[i];
            }

            return(data);
        }
예제 #2
0
 private static void FillExposedDescs(List <VFXMapping> outExposedParameters, VFXExpressionGraph graph, IEnumerable <VFXParameter> parameters)
 {
     foreach (var parameter in parameters)
     {
         if (parameter.exposed)
         {
             CollectExposedDesc(outExposedParameters, parameter.exposedName, parameter.GetOutputSlot(0), graph);
         }
     }
 }
예제 #3
0
 public virtual void FillDescs(
     List <VFXGPUBufferDesc> outBufferDescs,
     List <VFXEditorSystemDesc> outSystemDescs,
     VFXExpressionGraph expressionGraph,
     Dictionary <VFXContext, VFXContextCompiledData> contextToCompiledData,
     Dictionary <VFXContext, int> contextSpawnToBufferIndex,
     Dictionary <VFXData, int> attributeBuffer,
     Dictionary <VFXData, int> eventBuffer)
 {
     // Empty implementation by default
 }
예제 #4
0
 public virtual void FillDescs(
     List <VFXGPUBufferDesc> outBufferDescs,
     List <VFXTemporaryGPUBufferDesc> outTemporaryBufferDescs,
     List <VFXEditorSystemDesc> outSystemDescs,
     VFXExpressionGraph expressionGraph,
     Dictionary <VFXContext, VFXContextCompiledData> contextToCompiledData,
     Dictionary <VFXContext, int> contextSpawnToBufferIndex,
     VFXDependentBuffersData dependentBuffers,
     Dictionary <VFXContext, List <VFXContextLink>[]> effectiveFlowInputLinks)
 {
     // Empty implementation by default
 }
예제 #5
0
        private static void GenerateShaders(List <GeneratedCodeData> outGeneratedCodeData, VFXExpressionGraph graph, IEnumerable <VFXContext> contexts, Dictionary <VFXContext, VFXContextCompiledData> contextToCompiledData, VFXCompilationMode compilationMode)
        {
            Profiler.BeginSample("VFXEditor.GenerateShaders");
            try
            {
                foreach (var context in contexts)
                {
                    var gpuMapper     = graph.BuildGPUMapper(context);
                    var uniformMapper = new VFXUniformMapper(gpuMapper, context.doesGenerateShader);

                    // Add gpu and uniform mapper
                    var contextData = contextToCompiledData[context];
                    contextData.gpuMapper          = gpuMapper;
                    contextData.uniformMapper      = uniformMapper;
                    contextToCompiledData[context] = contextData;

                    if (context.doesGenerateShader)
                    {
                        var generatedContent = VFXCodeGenerator.Build(context, compilationMode, contextData);

                        outGeneratedCodeData.Add(new GeneratedCodeData()
                        {
                            context       = context,
                            computeShader = context.codeGeneratorCompute,
                            compilMode    = compilationMode,
                            content       = generatedContent
                        });
                    }
                }
            }
            finally
            {
                Profiler.EndSample();
            }
        }
예제 #6
0
        private static void FillSpawner(Dictionary <VFXContext, SpawnInfo> outContextSpawnToSpawnInfo, List <VFXCPUBufferDesc> outCpuBufferDescs, List <VFXEditorSystemDesc> outSystemDescs, IEnumerable <VFXContext> contexts, VFXExpressionGraph graph, List <VFXLayoutElementDesc> globalEventAttributeDescs, Dictionary <VFXContext, VFXContextCompiledData> contextToCompiledData)
        {
            var spawners = CollectSpawnersHierarchy(contexts);

            foreach (var it in spawners.Select((spawner, index) => new { spawner, index }))
            {
                outContextSpawnToSpawnInfo.Add(it.spawner, new SpawnInfo()
                {
                    bufferIndex = outCpuBufferDescs.Count, systemIndex = it.index
                });
                outCpuBufferDescs.Add(new VFXCPUBufferDesc()
                {
                    capacity    = 1u,
                    stride      = globalEventAttributeDescs.First().offset.structure,
                    layout      = globalEventAttributeDescs.ToArray(),
                    initialData = ComputeArrayOfStructureInitialData(globalEventAttributeDescs)
                });
            }
            foreach (var spawnContext in spawners)
            {
                var buffers = new List <VFXMapping>();
                buffers.Add(new VFXMapping()
                {
                    index = outContextSpawnToSpawnInfo[spawnContext].bufferIndex,
                    name  = "spawner_output"
                });

                for (int indexSlot = 0; indexSlot < 2; ++indexSlot)
                {
                    foreach (var input in spawnContext.inputFlowSlot[indexSlot].link)
                    {
                        var inputContext = input.context as VFXContext;
                        if (outContextSpawnToSpawnInfo.ContainsKey(inputContext))
                        {
                            buffers.Add(new VFXMapping()
                            {
                                index = outContextSpawnToSpawnInfo[inputContext].bufferIndex,
                                name  = "spawner_input_" + (indexSlot == 0 ? "OnPlay" : "OnStop")
                            });
                        }
                    }
                }

                var contextData = contextToCompiledData[spawnContext];
                outSystemDescs.Add(new VFXEditorSystemDesc()
                {
                    buffers  = buffers.ToArray(),
                    capacity = 0u,
                    flags    = VFXSystemFlag.SystemDefault,
                    layer    = uint.MaxValue,
                    tasks    = spawnContext.activeChildrenWithImplicit.Select((b, index) =>
                    {
                        var spawnerBlock = b as VFXAbstractSpawner;
                        if (spawnerBlock == null)
                        {
                            throw new InvalidCastException("Unexpected block type in spawnerContext");
                        }
                        if (spawnerBlock.spawnerType == VFXTaskType.CustomCallbackSpawner && spawnerBlock.customBehavior == null)
                        {
                            throw new InvalidOperationException("VFXAbstractSpawner excepts a custom behavior for custom callback type");
                        }
                        if (spawnerBlock.spawnerType != VFXTaskType.CustomCallbackSpawner && spawnerBlock.customBehavior != null)
                        {
                            throw new InvalidOperationException("VFXAbstractSpawner only expects a custom behavior for custom callback type");
                        }

                        var cpuExpression = contextData.cpuMapper.CollectExpression(index, false).Select(o =>
                        {
                            return(new VFXMapping
                            {
                                index = graph.GetFlattenedIndex(o.exp),
                                name = o.name
                            });
                        }).ToArray();

                        Object processor = null;
                        if (spawnerBlock.customBehavior != null)
                        {
                            var assets = AssetDatabase.FindAssets("t:TextAsset " + spawnerBlock.customBehavior.Name);
                            if (assets.Length != 1)
                            {
                                // AssetDatabase.FindAssets will not search in package by default. Search in our package explicitely
                                assets = AssetDatabase.FindAssets("t:TextAsset " + spawnerBlock.customBehavior.Name, new string[] { VisualEffectGraphPackageInfo.assetPackagePath });
                                if (assets.Length != 1)
                                {
                                    throw new InvalidOperationException("Unable to find the definition .cs file for " + spawnerBlock.customBehavior + " Make sure that the class name and file name match");
                                }
                            }

                            var assetPath = AssetDatabase.GUIDToAssetPath(assets[0]);
                            processor     = AssetDatabase.LoadAssetAtPath <TextAsset>(assetPath);
                        }

                        return(new VFXEditorTaskDesc
                        {
                            type = spawnerBlock.spawnerType,
                            buffers = new VFXMapping[0],
                            values = cpuExpression.ToArray(),
                            parameters = contextData.parameters,
                            externalProcessor = processor
                        });
                    }).ToArray()
                });
            }
        }
예제 #7
0
        private static void FillEventAttributeDescs(List <VFXLayoutElementDesc> eventAttributeDescs, VFXExpressionGraph graph, IEnumerable <VFXContext> contexts)
        {
            foreach (var context in contexts.Where(o => o.contextType == VFXContextType.kSpawner))
            {
                foreach (var linked in context.outputContexts)
                {
                    var data = linked.GetData();
                    if (data)
                    {
                        foreach (var attribute in data.GetAttributes())
                        {
                            if ((attribute.mode & VFXAttributeMode.ReadSource) != 0 && !eventAttributeDescs.Any(o => o.name == attribute.attrib.name))
                            {
                                eventAttributeDescs.Add(new VFXLayoutElementDesc()
                                {
                                    name = attribute.attrib.name,
                                    type = attribute.attrib.type
                                });
                            }
                        }
                    }
                }
            }

            var structureLayoutTotalSize = (uint)eventAttributeDescs.Sum(e => (long)VFXExpression.TypeToSize(e.type));
            var currentLayoutSize        = 0u;
            var listWithOffset           = new List <VFXLayoutElementDesc>();

            eventAttributeDescs.ForEach(e =>
            {
                e.offset.element   = currentLayoutSize;
                e.offset.structure = structureLayoutTotalSize;
                currentLayoutSize += (uint)VFXExpression.TypeToSize(e.type);
                listWithOffset.Add(e);
            });

            eventAttributeDescs.Clear();
            eventAttributeDescs.AddRange(listWithOffset);
        }
예제 #8
0
        private static void CollectExposedDesc(List <VFXMapping> outExposedParameters, string name, VFXSlot slot, VFXExpressionGraph graph)
        {
            var expression = slot.valueType != VFXValueType.None ? slot.GetInExpression() : null;

            if (expression != null)
            {
                var exprIndex = graph.GetFlattenedIndex(expression);
                if (exprIndex == -1)
                {
                    throw new InvalidOperationException("Unable to retrieve value from exposed for " + name);
                }

                outExposedParameters.Add(new VFXMapping()
                {
                    name  = name,
                    index = exprIndex
                });
            }
            else
            {
                foreach (var child in slot.children)
                {
                    CollectExposedDesc(outExposedParameters, name + "_" + child.name, child, graph);
                }
            }
        }
예제 #9
0
        public override void FillDescs(
            List <VFXGPUBufferDesc> outBufferDescs,
            List <VFXTemporaryGPUBufferDesc> outTemporaryBufferDescs,
            List <VFXEditorSystemDesc> outSystemDescs,
            VFXExpressionGraph expressionGraph,
            Dictionary <VFXContext, VFXContextCompiledData> contextToCompiledData,
            Dictionary <VFXContext, int> contextSpawnToBufferIndex,
            VFXDependentBuffersData dependentBuffers,
            Dictionary <VFXContext, List <VFXContextLink>[]> effectiveFlowInputLinks,
            VFXSystemNames systemNames = null)
        {
            var context     = m_Owners[0];
            var contextData = contextToCompiledData[context];

            var mappings = new List <VFXMapping>();

            foreach (var uniform in contextData.uniformMapper.uniforms.Concat(contextData.uniformMapper.textures))
            {
                int exprIndex = expressionGraph.GetFlattenedIndex(uniform);
                foreach (var name in contextData.uniformMapper.GetNames(uniform))
                {
                    mappings.Add(new VFXMapping(name, exprIndex));
                }
            }

            var paramList = new List <VFXMapping>(contextData.parameters);

            // TODO Remove once material are serialized
            {
                var mat         = GetOrCreateMaterial();
                var keywordsStr = new StringBuilder();

                foreach (var k in mat.shaderKeywords)
                {
                    keywordsStr.Append(k);
                    keywordsStr.Append(' ');
                }

                const int kKeywordID = 0x5a93713b;
                paramList.Add(new VFXMapping(keywordsStr.ToString(), kKeywordID));

                // Add material properties mappings
                for (int i = 0; i < ShaderUtil.GetPropertyCount(shader); ++i)
                {
                    if (ShaderUtil.IsShaderPropertyHidden(shader, i))
                    {
                        var name    = ShaderUtil.GetPropertyName(shader, i);
                        var propExp = contextData.cpuMapper.FromNameAndId(name, -1);
                        if (propExp != null)
                        {
                            int propIndex = expressionGraph.GetFlattenedIndex(propExp);
                            if (propIndex != -1)
                            {
                                paramList.Add(new VFXMapping(name, propIndex));
                            }
                        }
                    }
                }
            }

            var task = new VFXEditorTaskDesc()
            {
                externalProcessor = shader,
                values            = mappings.ToArray(),
                parameters        = paramList.ToArray(),
                type = (UnityEngine.VFX.VFXTaskType)VFXTaskType.Output
            };

            mappings.Clear();
            var mapper = contextData.cpuMapper;

            // TODO Factorize that
            var meshExp      = mapper.FromNameAndId("mesh", -1);
            var transformExp = mapper.FromNameAndId("transform", -1);
            var subMaskExp   = mapper.FromNameAndId("subMeshMask", -1);

            int meshIndex = meshExp != null?expressionGraph.GetFlattenedIndex(meshExp) : -1;

            int transformIndex = transformExp != null?expressionGraph.GetFlattenedIndex(transformExp) : -1;

            int subMaskIndex = subMaskExp != null?expressionGraph.GetFlattenedIndex(subMaskExp) : -1;

            if (meshIndex != -1)
            {
                mappings.Add(new VFXMapping("mesh", meshIndex));
            }
            if (transformIndex != -1)
            {
                mappings.Add(new VFXMapping("transform", transformIndex));
            }
            if (subMaskIndex != -1)
            {
                mappings.Add(new VFXMapping("subMeshMask", subMaskIndex));
            }

            outSystemDescs.Add(new VFXEditorSystemDesc()
            {
                tasks = new VFXEditorTaskDesc[1] {
                    task
                },
                values = mappings.ToArray(),
                type   = VFXSystemType.Mesh,
                layer  = uint.MaxValue,
            });
        }
예제 #10
0
        public override void FillDescs(
            List <VFXGPUBufferDesc> outBufferDescs,
            List <VFXEditorSystemDesc> outSystemDescs,
            VFXExpressionGraph expressionGraph,
            Dictionary <VFXContext, VFXContextCompiledData> contextToCompiledData,
            Dictionary <VFXContext, int> contextSpawnToBufferIndex,
            Dictionary <VFXData, int> attributeBuffer,
            Dictionary <VFXData, int> eventBuffer,
            Dictionary <VFXContext, List <VFXContextLink>[]> effectiveFlowInputLinks)
        {
            bool hasKill = IsAttributeStored(VFXAttribute.Alive);

            var deadListBufferIndex = -1;
            var deadListCountIndex  = -1;

            var systemBufferMappings = new List <VFXMapping>();
            var systemValueMappings  = new List <VFXMapping>();

            var attributeBufferIndex = attributeBuffer[this];

            int attributeSourceBufferIndex = -1;
            int eventGPUFrom = -1;

            if (m_DependenciesIn.Any())
            {
                if (m_DependenciesIn.Count != 1)
                {
                    throw new InvalidOperationException("Unexpected multiple input dependency for GPU event");
                }
                attributeSourceBufferIndex = attributeBuffer[m_DependenciesIn.FirstOrDefault()];
                eventGPUFrom = eventBuffer[this];
            }

            if (attributeBufferIndex != -1)
            {
                outBufferDescs.Add(m_layoutAttributeCurrent.GetBufferDesc(alignedCapacity));
                systemBufferMappings.Add(new VFXMapping("attributeBuffer", attributeBufferIndex));
            }

            if (m_ownAttributeSourceBuffer && m_layoutAttributeSource.GetBufferSize(sourceCount) > 0u)
            {
                if (attributeSourceBufferIndex != -1)
                {
                    throw new InvalidOperationException("Unexpected source while filling description of data particle");
                }

                attributeSourceBufferIndex = outBufferDescs.Count;
                outBufferDescs.Add(m_layoutAttributeSource.GetBufferDesc(sourceCount));
            }

            if (attributeSourceBufferIndex != -1)
            {
                systemBufferMappings.Add(new VFXMapping("sourceAttributeBuffer", attributeSourceBufferIndex));
            }

            var systemFlag = VFXSystemFlag.SystemDefault;

            if (eventGPUFrom != -1)
            {
                systemFlag |= VFXSystemFlag.SystemReceivedEventGPU;
                systemBufferMappings.Add(new VFXMapping("eventList", eventGPUFrom));
            }

            if (hasKill)
            {
                systemFlag |= VFXSystemFlag.SystemHasKill;

                deadListBufferIndex = outBufferDescs.Count;
                outBufferDescs.Add(new VFXGPUBufferDesc()
                {
                    type = ComputeBufferType.Counter, size = capacity, stride = 4
                });
                systemBufferMappings.Add(new VFXMapping("deadList", deadListBufferIndex));

                deadListCountIndex = outBufferDescs.Count;
                outBufferDescs.Add(new VFXGPUBufferDesc()
                {
                    type = ComputeBufferType.Raw, size = 1, stride = 4
                });
                systemBufferMappings.Add(new VFXMapping("deadListCount", deadListCountIndex));
            }

            var initContext = m_Contexts.FirstOrDefault(o => o.contextType == VFXContextType.Init);

            if (initContext != null)
            {
                systemBufferMappings.AddRange(effectiveFlowInputLinks[initContext].SelectMany(t => t.Select(u => u.context)).Where(o => o.contextType == VFXContextType.Spawner).Select(o => new VFXMapping("spawner_input", contextSpawnToBufferIndex[o])));
            }
            if (m_Contexts.Count() > 0 && m_Contexts.First().contextType == VFXContextType.Init) // TODO This test can be removed once we ensure priorly the system is valid
            {
                var mapper = contextToCompiledData[m_Contexts.First()].cpuMapper;

                var boundsCenterExp = mapper.FromNameAndId("bounds_center", -1);
                var boundsSizeExp   = mapper.FromNameAndId("bounds_size", -1);

                int boundsCenterIndex = boundsCenterExp != null?expressionGraph.GetFlattenedIndex(boundsCenterExp) : -1;

                int boundsSizeIndex = boundsSizeExp != null?expressionGraph.GetFlattenedIndex(boundsSizeExp) : -1;

                if (boundsCenterIndex != -1 && boundsSizeIndex != -1)
                {
                    systemValueMappings.Add(new VFXMapping("bounds_center", boundsCenterIndex));
                    systemValueMappings.Add(new VFXMapping("bounds_size", boundsSizeIndex));
                }
            }

            int  indirectBufferIndex = -1;
            bool needsIndirectBuffer = NeedsIndirectBuffer();

            if (needsIndirectBuffer)
            {
                systemFlag         |= VFXSystemFlag.SystemHasIndirectBuffer;
                indirectBufferIndex = outBufferDescs.Count;
                outBufferDescs.Add(new VFXGPUBufferDesc()
                {
                    type = ComputeBufferType.Counter, size = capacity, stride = 4
                });
                systemBufferMappings.Add(new VFXMapping("indirectBuffer", indirectBufferIndex));
            }

            // sort buffers
            int  sortBufferAIndex = -1;
            int  sortBufferBIndex = -1;
            bool needsSort        = NeedsSort();

            if (needsSort)
            {
                sortBufferAIndex = outBufferDescs.Count;
                sortBufferBIndex = sortBufferAIndex + 1;

                outBufferDescs.Add(new VFXGPUBufferDesc()
                {
                    type = ComputeBufferType.Default, size = capacity, stride = 8
                });
                systemBufferMappings.Add(new VFXMapping("sortBufferA", sortBufferAIndex));

                outBufferDescs.Add(new VFXGPUBufferDesc()
                {
                    type = ComputeBufferType.Default, size = capacity, stride = 8
                });
                systemBufferMappings.Add(new VFXMapping("sortBufferB", sortBufferBIndex));
            }


            var taskDescs       = new List <VFXEditorTaskDesc>();
            var bufferMappings  = new List <VFXMapping>();
            var uniformMappings = new List <VFXMapping>();

            for (int i = 0; i < m_Contexts.Count; ++i)
            {
                var context     = m_Contexts[i];
                var contextData = contextToCompiledData[context];

                var taskDesc = new VFXEditorTaskDesc();
                taskDesc.type = context.taskType;

                bufferMappings.Clear();

                if (attributeBufferIndex != -1)
                {
                    bufferMappings.Add(new VFXMapping("attributeBuffer", attributeBufferIndex));
                }

                if (eventGPUFrom != -1 && context.contextType == VFXContextType.Init)
                {
                    bufferMappings.Add(new VFXMapping("eventList", eventGPUFrom));
                }

                if (deadListBufferIndex != -1 && context.contextType != VFXContextType.Output && context.taskType != VFXTaskType.CameraSort)
                {
                    bufferMappings.Add(new VFXMapping(context.contextType == VFXContextType.Update ? "deadListOut" : "deadListIn", deadListBufferIndex));
                }

                if (deadListCountIndex != -1 && context.contextType == VFXContextType.Init)
                {
                    bufferMappings.Add(new VFXMapping("deadListCount", deadListCountIndex));
                }

                if (attributeSourceBufferIndex != -1 && context.contextType == VFXContextType.Init)
                {
                    bufferMappings.Add(new VFXMapping("sourceAttributeBuffer", attributeSourceBufferIndex));
                }

                if (indirectBufferIndex != -1 &&
                    (context.contextType == VFXContextType.Update ||
                     (context.contextType == VFXContextType.Output && (context as VFXAbstractParticleOutput).HasIndirectDraw())))
                {
                    bufferMappings.Add(new VFXMapping(context.taskType == VFXTaskType.CameraSort ? "inputBuffer" : "indirectBuffer", indirectBufferIndex));
                }

                if (deadListBufferIndex != -1 && context.contextType == VFXContextType.Output && (context as VFXAbstractParticleOutput).NeedsDeadListCount())
                {
                    bufferMappings.Add(new VFXMapping("deadListCount", deadListCountIndex));
                }

                if (context.taskType == VFXTaskType.CameraSort)
                {
                    bufferMappings.Add(new VFXMapping("outputBuffer", sortBufferAIndex));
                    if (deadListCountIndex != -1)
                    {
                        bufferMappings.Add(new VFXMapping("deadListCount", deadListCountIndex));
                    }
                }

                var gpuTarget = context.allLinkedOutputSlot.SelectMany(o => (o.owner as VFXContext).outputContexts)
                                .Where(c => c.CanBeCompiled())
                                .Select(o => eventBuffer[o.GetData()])
                                .ToArray();
                for (uint indexTarget = 0; indexTarget < (uint)gpuTarget.Length; ++indexTarget)
                {
                    var prefix = VFXCodeGeneratorHelper.GeneratePrefix(indexTarget);
                    bufferMappings.Add(new VFXMapping(string.Format("eventListOut_{0}", prefix), gpuTarget[indexTarget]));
                }

                uniformMappings.Clear();
                foreach (var uniform in contextData.uniformMapper.uniforms.Concat(contextData.uniformMapper.textures))
                {
                    uniformMappings.Add(new VFXMapping(contextData.uniformMapper.GetName(uniform), expressionGraph.GetFlattenedIndex(uniform)));
                }

                // Retrieve all cpu mappings at context level (-1)
                var cpuMappings = contextData.cpuMapper.CollectExpression(-1).Select(exp => new VFXMapping(exp.name, expressionGraph.GetFlattenedIndex(exp.exp))).ToArray();

                //Check potential issue with invalid operation on CPU
                foreach (var mapping in cpuMappings)
                {
                    if (mapping.index < 0)
                    {
                        throw new InvalidOperationException("Unable to compute CPU expression for mapping : " + mapping.name);
                    }
                }

                taskDesc.buffers           = bufferMappings.ToArray();
                taskDesc.values            = uniformMappings.ToArray();
                taskDesc.parameters        = cpuMappings.Concat(contextData.parameters).ToArray();
                taskDesc.shaderSourceIndex = contextToCompiledData[context].indexInShaderSource;

                taskDescs.Add(taskDesc);
            }

            outSystemDescs.Add(new VFXEditorSystemDesc()
            {
                flags    = systemFlag,
                tasks    = taskDescs.ToArray(),
                capacity = capacity,
                buffers  = systemBufferMappings.ToArray(),
                values   = systemValueMappings.ToArray(),
                type     = VFXSystemType.Particle,
                layer    = m_Layer
            });
        }
예제 #11
0
        public override void FillDescs(
            List <VFXGPUBufferDesc> outBufferDescs,
            List <VFXTemporaryGPUBufferDesc> outTemporaryBufferDescs,
            List <VFXEditorSystemDesc> outSystemDescs,
            VFXExpressionGraph expressionGraph,
            Dictionary <VFXContext, VFXContextCompiledData> contextToCompiledData,
            Dictionary <VFXContext, int> contextSpawnToBufferIndex,
            Dictionary <VFXData, int> attributeBuffer,
            Dictionary <VFXData, int> eventBuffer,
            Dictionary <VFXContext, List <VFXContextLink>[]> effectiveFlowInputLinks)
        {
            var context     = m_Owners[0];
            var contextData = contextToCompiledData[context];

            var mappings = new List <VFXMapping>();

            foreach (var uniform in contextData.uniformMapper.uniforms.Concat(contextData.uniformMapper.textures))
            {
                int exprIndex = expressionGraph.GetFlattenedIndex(uniform);
                foreach (var name in contextData.uniformMapper.GetNames(uniform))
                {
                    mappings.Add(new VFXMapping(name, exprIndex));
                }
            }

            var task = new VFXEditorTaskDesc()
            {
                externalProcessor = shader,
                values            = mappings.ToArray(),
                parameters        = contextData.parameters,
                type = (UnityEngine.VFX.VFXTaskType)VFXTaskType.Output
            };

            mappings.Clear();
            var mapper = contextData.cpuMapper;

            // TODO Factorize that
            var meshExp      = mapper.FromNameAndId("mesh", -1);
            var transformExp = mapper.FromNameAndId("transform", -1);
            var subMaskExp   = mapper.FromNameAndId("subMeshMask", -1);

            int meshIndex = meshExp != null?expressionGraph.GetFlattenedIndex(meshExp) : -1;

            int transformIndex = transformExp != null?expressionGraph.GetFlattenedIndex(transformExp) : -1;

            int subMaskIndex = subMaskExp != null?expressionGraph.GetFlattenedIndex(subMaskExp) : -1;

            if (meshIndex != -1)
            {
                mappings.Add(new VFXMapping("mesh", meshIndex));
            }
            if (transformIndex != -1)
            {
                mappings.Add(new VFXMapping("transform", transformIndex));
            }
            if (subMaskIndex != -1)
            {
                mappings.Add(new VFXMapping("subMeshMask", subMaskIndex));
            }

            outSystemDescs.Add(new VFXEditorSystemDesc()
            {
                tasks = new VFXEditorTaskDesc[1] {
                    task
                },
                values = mappings.ToArray(),
                type   = VFXSystemType.Mesh,
                layer  = uint.MaxValue,
            });
        }
예제 #12
0
        public override void FillDescs(
            VFXCompileErrorReporter reporter,
            List <VFXGPUBufferDesc> outBufferDescs,
            List <VFXTemporaryGPUBufferDesc> outTemporaryBufferDescs,
            List <VFXEditorSystemDesc> outSystemDescs,
            VFXExpressionGraph expressionGraph,
            Dictionary <VFXContext, VFXContextCompiledData> contextToCompiledData,
            Dictionary <VFXContext, int> contextSpawnToBufferIndex,
            VFXDependentBuffersData dependentBuffers,
            Dictionary <VFXContext, List <VFXContextLink>[]> effectiveFlowInputLinks,
            VFXSystemNames systemNames = null)
        {
            bool hasKill = IsAttributeStored(VFXAttribute.Alive);

            var deadListBufferIndex = -1;
            var deadListCountIndex  = -1;

            var systemBufferMappings = new List <VFXMapping>();
            var systemValueMappings  = new List <VFXMapping>();

            var attributeBufferIndex = dependentBuffers.attributeBuffers[this];

            int attributeSourceBufferIndex = -1;
            int eventGPUFrom = -1;

            var stripDataIndex    = -1;
            var boundsBufferIndex = -1;

            if (m_DependenciesIn.Any())
            {
                if (m_DependenciesIn.Count != 1)
                {
                    throw new InvalidOperationException("Unexpected multiple input dependency for GPU event");
                }
                attributeSourceBufferIndex = dependentBuffers.attributeBuffers[m_DependenciesIn.FirstOrDefault()];
                eventGPUFrom = dependentBuffers.eventBuffers[this];
            }

            if (attributeBufferIndex != -1)
            {
                systemBufferMappings.Add(new VFXMapping("attributeBuffer", attributeBufferIndex));
            }

            if (m_ownAttributeSourceBuffer)
            {
                if (attributeSourceBufferIndex != -1)
                {
                    throw new InvalidOperationException("Unexpected source while filling description of data particle");
                }

                attributeSourceBufferIndex = outBufferDescs.Count;
                outBufferDescs.Add(m_layoutAttributeSource.GetBufferDesc(staticSourceCount));
            }

            if (attributeSourceBufferIndex != -1)
            {
                systemBufferMappings.Add(new VFXMapping("sourceAttributeBuffer", attributeSourceBufferIndex));
            }

            var systemFlag = VFXSystemFlag.SystemDefault;

            if (eventGPUFrom != -1)
            {
                systemFlag |= VFXSystemFlag.SystemReceivedEventGPU;
                systemBufferMappings.Add(new VFXMapping("eventList", eventGPUFrom));
            }

            if (hasKill)
            {
                systemFlag |= VFXSystemFlag.SystemHasKill;

                deadListBufferIndex = outBufferDescs.Count;
                outBufferDescs.Add(new VFXGPUBufferDesc()
                {
                    type = ComputeBufferType.Counter, size = capacity, stride = 4
                });
                systemBufferMappings.Add(new VFXMapping("deadList", deadListBufferIndex));

                deadListCountIndex = outBufferDescs.Count;
                outBufferDescs.Add(new VFXGPUBufferDesc()
                {
                    type = ComputeBufferType.Raw, size = 1, stride = 4
                });
                systemBufferMappings.Add(new VFXMapping("deadListCount", deadListCountIndex));
            }

            if (hasStrip)
            {
                systemFlag |= VFXSystemFlag.SystemHasStrips;

                systemValueMappings.Add(new VFXMapping("stripCount", (int)stripCapacity));
                systemValueMappings.Add(new VFXMapping("particlePerStripCount", (int)particlePerStripCount));

                stripDataIndex = dependentBuffers.stripBuffers[this];
                systemBufferMappings.Add(new VFXMapping("stripDataBuffer", stripDataIndex));
            }

            if (hasDynamicSourceCount)
            {
                systemFlag |= VFXSystemFlag.SystemHasDirectLink;
            }

            if (needsComputeBounds || boundsSettingMode == BoundsSettingMode.Automatic)
            {
                systemFlag |= VFXSystemFlag.SystemNeedsComputeBounds;

                boundsBufferIndex = dependentBuffers.boundsBuffers[this];
                systemBufferMappings.Add(new VFXMapping("boundsBuffer", boundsBufferIndex));
            }

            if (boundsSettingMode == BoundsSettingMode.Automatic)
            {
                systemFlag |= VFXSystemFlag.SystemAutomaticBounds;
            }

            if (space == VFXCoordinateSpace.World)
            {
                systemFlag |= VFXSystemFlag.SystemInWorldSpace;
            }

            var initContext = m_Contexts.FirstOrDefault(o => o.contextType == VFXContextType.Init);

            if (initContext != null)
            {
                systemBufferMappings.AddRange(effectiveFlowInputLinks[initContext].SelectMany(t => t.Select(u => u.context)).Where(o => o.contextType == VFXContextType.Spawner).Select(o => new VFXMapping("spawner_input", contextSpawnToBufferIndex[o])));
            }
            if (m_Contexts.Count() > 0 && m_Contexts.First().contextType == VFXContextType.Init) // TODO This test can be removed once we ensure priorly the system is valid
            {
                var mapper = contextToCompiledData[m_Contexts.First()].cpuMapper;

                var boundsCenterExp  = mapper.FromNameAndId("bounds_center", -1);
                var boundsSizeExp    = mapper.FromNameAndId("bounds_size", -1);
                var boundsPaddingExp = mapper.FromNameAndId("boundsPadding", -1);

                int boundsCenterIndex = boundsCenterExp != null?expressionGraph.GetFlattenedIndex(boundsCenterExp) : -1;

                int boundsSizeIndex = boundsSizeExp != null?expressionGraph.GetFlattenedIndex(boundsSizeExp) : -1;

                int boundsPaddingIndex = boundsPaddingExp != null?expressionGraph.GetFlattenedIndex(boundsPaddingExp) : -1;

                if (boundsCenterIndex != -1 && boundsSizeIndex != -1)
                {
                    systemValueMappings.Add(new VFXMapping("bounds_center", boundsCenterIndex));
                    systemValueMappings.Add(new VFXMapping("bounds_size", boundsSizeIndex));
                }
                if (boundsPaddingIndex != -1)
                {
                    systemValueMappings.Add(new VFXMapping("boundsPadding", boundsPaddingIndex));
                }
            }

            Dictionary <VFXContext, VFXOutputUpdate> indirectOutputToCuller = null;
            bool needsIndirectBuffer       = NeedsIndirectBuffer();
            int  globalIndirectBufferIndex = -1;
            bool needsGlobalIndirectBuffer = false;

            if (needsIndirectBuffer)
            {
                indirectOutputToCuller = new Dictionary <VFXContext, VFXOutputUpdate>();
                foreach (var cullCompute in m_Contexts.OfType <VFXOutputUpdate>())
                {
                    if (cullCompute.HasFeature(VFXOutputUpdate.Features.IndirectDraw))
                    {
                        indirectOutputToCuller.Add(cullCompute.output, cullCompute);
                    }
                }

                var allIndirectOutputs = owners.OfType <VFXAbstractParticleOutput>().Where(o => o.HasIndirectDraw());

                needsGlobalIndirectBuffer = NeedsGlobalIndirectBuffer();
                if (needsGlobalIndirectBuffer)
                {
                    globalIndirectBufferIndex = outBufferDescs.Count;
                    systemBufferMappings.Add(new VFXMapping("indirectBuffer0", outBufferDescs.Count));
                    outBufferDescs.Add(new VFXGPUBufferDesc()
                    {
                        type = ComputeBufferType.Counter, size = capacity, stride = 4
                    });
                }

                int currentIndirectBufferIndex = globalIndirectBufferIndex == -1 ? 0 : 1;
                foreach (var indirectOutput in allIndirectOutputs)
                {
                    if (indirectOutputToCuller.ContainsKey(indirectOutput))
                    {
                        VFXOutputUpdate culler      = indirectOutputToCuller[indirectOutput];
                        uint            bufferCount = culler.bufferCount;
                        culler.bufferIndex = outBufferDescs.Count;
                        bool perCamera    = culler.isPerCamera;
                        uint bufferStride = culler.HasFeature(VFXOutputUpdate.Features.Sort) ? 8u : 4u;
                        for (uint i = 0; i < bufferCount; ++i)
                        {
                            string bufferName = "indirectBuffer" + currentIndirectBufferIndex++;
                            if (perCamera)
                            {
                                bufferName += "PerCamera";
                            }
                            systemBufferMappings.Add(new VFXMapping(bufferName, outBufferDescs.Count));
                            outBufferDescs.Add(new VFXGPUBufferDesc()
                            {
                                type = ComputeBufferType.Counter, size = capacity, stride = bufferStride
                            });
                        }

                        if (culler.HasFeature(VFXOutputUpdate.Features.Sort))
                        {
                            culler.sortedBufferIndex = outBufferDescs.Count;
                            for (uint i = 0; i < bufferCount; ++i)
                            {
                                outBufferDescs.Add(new VFXGPUBufferDesc()
                                {
                                    type = ComputeBufferType.Default, size = capacity, stride = 4
                                });
                            }
                        }
                        else
                        {
                            culler.sortedBufferIndex = culler.bufferIndex;
                        }
                    }
                }
            }

            // sort buffers
            int  sortBufferAIndex = -1;
            int  sortBufferBIndex = -1;
            bool needsSort        = NeedsGlobalSort();

            if (needsSort)
            {
                sortBufferAIndex = outBufferDescs.Count;
                sortBufferBIndex = sortBufferAIndex + 1;

                outBufferDescs.Add(new VFXGPUBufferDesc()
                {
                    type = ComputeBufferType.Default, size = capacity, stride = 8
                });
                systemBufferMappings.Add(new VFXMapping("sortBufferA", sortBufferAIndex));

                outBufferDescs.Add(new VFXGPUBufferDesc()
                {
                    type = ComputeBufferType.Default, size = capacity, stride = 8
                });
                systemBufferMappings.Add(new VFXMapping("sortBufferB", sortBufferBIndex));
            }

            var elementToVFXBufferMotionVector = new Dictionary <VFXContext, int>();

            foreach (VFXOutputUpdate context in m_Contexts.OfType <VFXOutputUpdate>())
            {
                if (context.HasFeature(VFXOutputUpdate.Features.MotionVector))
                {
                    uint sizePerElement = 12U * 4U;
                    if (context.output.SupportsMotionVectorPerVertex(out uint vertsCount))
                    {
                        // 2 floats per vertex
                        sizePerElement = vertsCount * 2U * 4U;
                    }
                    // add previous frame index
                    sizePerElement += 4U;
                    int currentElementToVFXBufferMotionVector = outTemporaryBufferDescs.Count;
                    outTemporaryBufferDescs.Add(new VFXTemporaryGPUBufferDesc()
                    {
                        frameCount = 2u, desc = new VFXGPUBufferDesc {
                            type = ComputeBufferType.Raw, size = capacity * sizePerElement, stride = 4
                        }
                    });
                    elementToVFXBufferMotionVector.Add(context.output, currentElementToVFXBufferMotionVector);
                }
            }

            var taskDescs            = new List <VFXEditorTaskDesc>();
            var bufferMappings       = new List <VFXMapping>();
            var uniformMappings      = new List <VFXMapping>();
            var additionalParameters = new List <VFXMapping>();

            for (int i = 0; i < m_Contexts.Count; ++i)
            {
                var temporaryBufferMappings = new List <VFXMappingTemporary>();

                var context = m_Contexts[i];
                if (!contextToCompiledData.TryGetValue(context, out var contextData))
                {
                    throw new InvalidOperationException("Unexpected context which hasn't been compiled : " + context);
                }

                var taskDesc = new VFXEditorTaskDesc();
                taskDesc.type = (UnityEngine.VFX.VFXTaskType)context.taskType;

                bufferMappings.Clear();
                additionalParameters.Clear();

                if (context is VFXOutputUpdate)
                {
                    var update = (VFXOutputUpdate)context;
                    if (update.HasFeature(VFXOutputUpdate.Features.MotionVector))
                    {
                        var currentIndex = elementToVFXBufferMotionVector[update.output];
                        temporaryBufferMappings.Add(new VFXMappingTemporary()
                        {
                            pastFrameIndex = 0u, perCameraBuffer = true, mapping = new VFXMapping("elementToVFXBuffer", currentIndex)
                        });
                    }
                }
                else if (context.contextType == VFXContextType.Output && (context is IVFXSubRenderer) && (context as IVFXSubRenderer).hasMotionVector)
                {
                    var currentIndex = elementToVFXBufferMotionVector[context];
                    temporaryBufferMappings.Add(new VFXMappingTemporary()
                    {
                        pastFrameIndex = 1u, perCameraBuffer = true, mapping = new VFXMapping("elementToVFXBufferPrevious", currentIndex)
                    });
                }

                if (attributeBufferIndex != -1)
                {
                    bufferMappings.Add(new VFXMapping("attributeBuffer", attributeBufferIndex));
                }

                if (eventGPUFrom != -1 && context.contextType == VFXContextType.Init)
                {
                    bufferMappings.Add(new VFXMapping("eventList", eventGPUFrom));
                }

                if (deadListBufferIndex != -1 && (context.taskType == VFXTaskType.Initialize || context.taskType == VFXTaskType.Update))
                {
                    bufferMappings.Add(new VFXMapping(context.contextType == VFXContextType.Update ? "deadListOut" : "deadListIn", deadListBufferIndex));
                }

                if (deadListCountIndex != -1 && context.contextType == VFXContextType.Init)
                {
                    bufferMappings.Add(new VFXMapping("deadListCount", deadListCountIndex));
                }

                if (attributeSourceBufferIndex != -1 && context.contextType == VFXContextType.Init)
                {
                    bufferMappings.Add(new VFXMapping("sourceAttributeBuffer", attributeSourceBufferIndex));
                }

                if (stripDataIndex != -1 && context.ownedType == VFXDataType.ParticleStrip)
                {
                    bufferMappings.Add(new VFXMapping("stripDataBuffer", stripDataIndex));
                }

                bool hasAttachedStrip = IsAttributeStored(VFXAttribute.StripAlive);
                if (hasAttachedStrip)
                {
                    var stripData = dependenciesOut.First(d => ((VFXDataParticle)d).hasStrip); // TODO Handle several strip attached
                    bufferMappings.Add(new VFXMapping("attachedStripDataBuffer", dependentBuffers.stripBuffers[stripData]));
                }

                if (needsIndirectBuffer)
                {
                    systemFlag |= VFXSystemFlag.SystemHasIndirectBuffer;

                    if (context.contextType == VFXContextType.Output && (context as VFXAbstractParticleOutput).HasIndirectDraw())
                    {
                        bool hasCuller = indirectOutputToCuller.ContainsKey(context);
                        additionalParameters.Add(new VFXMapping("indirectIndex", hasCuller ? indirectOutputToCuller[context].bufferIndex : globalIndirectBufferIndex));
                        bufferMappings.Add(new VFXMapping("indirectBuffer", hasCuller ? indirectOutputToCuller[context].sortedBufferIndex : globalIndirectBufferIndex));
                    }

                    if (context.contextType == VFXContextType.Update)
                    {
                        if (context.taskType == VFXTaskType.Update && needsGlobalIndirectBuffer)
                        {
                            bufferMappings.Add(new VFXMapping("indirectBuffer", globalIndirectBufferIndex));
                        }
                    }

                    if (context.contextType == VFXContextType.Filter)
                    {
                        if (context.taskType == VFXTaskType.CameraSort && needsGlobalIndirectBuffer)
                        {
                            bufferMappings.Add(new VFXMapping("inputBuffer", globalIndirectBufferIndex));
                        }
                        else if (context is VFXOutputUpdate)
                        {
                            var  outputUpdate = (VFXOutputUpdate)context;
                            int  startIndex   = outputUpdate.bufferIndex;
                            uint bufferCount  = outputUpdate.bufferCount;
                            for (int j = 0; j < bufferCount; ++j)
                            {
                                bufferMappings.Add(new VFXMapping("outputBuffer" + j, startIndex + j));
                            }
                        }
                    }
                }

                if (deadListBufferIndex != -1 && context.contextType == VFXContextType.Output && (context as VFXAbstractParticleOutput).NeedsDeadListCount())
                {
                    bufferMappings.Add(new VFXMapping("deadListCount", deadListCountIndex));
                }

                if (context.taskType == VFXTaskType.CameraSort)
                {
                    bufferMappings.Add(new VFXMapping("outputBuffer", sortBufferAIndex));
                    if (deadListCountIndex != -1)
                    {
                        bufferMappings.Add(new VFXMapping("deadListCount", deadListCountIndex));
                    }
                }

                var gpuTarget = context.allLinkedOutputSlot.SelectMany(o => (o.owner as VFXContext).outputContexts)
                                .Where(c => c.CanBeCompiled())
                                .Select(o => dependentBuffers.eventBuffers[o.GetData()])
                                .ToArray();
                for (uint indexTarget = 0; indexTarget < (uint)gpuTarget.Length; ++indexTarget)
                {
                    var prefix = VFXCodeGeneratorHelper.GeneratePrefix(indexTarget);
                    bufferMappings.Add(new VFXMapping(string.Format("eventListOut_{0}", prefix), gpuTarget[indexTarget]));
                }

                uniformMappings.Clear();

                foreach (var uniform in contextData.uniformMapper.uniforms)
                {
                    uniformMappings.Add(new VFXMapping(contextData.uniformMapper.GetName(uniform), expressionGraph.GetFlattenedIndex(uniform)));
                }
                foreach (var buffer in contextData.uniformMapper.buffers)
                {
                    uniformMappings.Add(new VFXMapping(contextData.uniformMapper.GetName(buffer), expressionGraph.GetFlattenedIndex(buffer)));
                }
                foreach (var texture in contextData.uniformMapper.textures)
                {
                    // TODO At the moment issue all names sharing the same texture as different texture slots. This is not optimized as it required more texture binding than necessary
                    foreach (var name in contextData.uniformMapper.GetNames(texture))
                    {
                        uniformMappings.Add(new VFXMapping(name, expressionGraph.GetFlattenedIndex(texture)));
                    }
                }

                // Retrieve all cpu mappings at context level (-1)
                var cpuMappings = contextData.cpuMapper.CollectExpression(-1).Select(exp => new VFXMapping(exp.name, expressionGraph.GetFlattenedIndex(exp.exp))).ToArray();

                //Check potential issue with invalid operation on CPU
                foreach (var mapping in cpuMappings)
                {
                    if (mapping.index < 0)
                    {
                        reporter?.RegisterError(context.GetSlotByPath(true, mapping.name), "GPUNodeLinkedTOCPUSlot", VFXErrorType.Error, "Can not link a GPU operator to a system wide (CPU) input.");;
                        throw new InvalidOperationException("Unable to compute CPU expression for mapping : " + mapping.name);
                    }
                }

                taskDesc.buffers           = bufferMappings.ToArray();
                taskDesc.temporaryBuffers  = temporaryBufferMappings.ToArray();
                taskDesc.values            = uniformMappings.ToArray();
                taskDesc.parameters        = cpuMappings.Concat(contextData.parameters).Concat(additionalParameters).ToArray();
                taskDesc.shaderSourceIndex = contextToCompiledData[context].indexInShaderSource;
                taskDesc.model             = context;

                if (context is IVFXMultiMeshOutput) // If the context is a multi mesh output, split and patch task desc into several tasks
                {
                    var multiMeshOutput = (IVFXMultiMeshOutput)context;
                    for (int j = (int)multiMeshOutput.meshCount - 1; j >= 0; --j) // Back to front to be consistent with LOD and alpha
                    {
                        VFXEditorTaskDesc singleMeshTaskDesc = taskDesc;
                        singleMeshTaskDesc.parameters = VFXMultiMeshHelper.PatchCPUMapping(taskDesc.parameters, multiMeshOutput.meshCount, j).ToArray();
                        singleMeshTaskDesc.buffers    = VFXMultiMeshHelper.PatchBufferMapping(taskDesc.buffers, j).ToArray();
                        taskDescs.Add(singleMeshTaskDesc);
                    }
                }
                else
                {
                    taskDescs.Add(taskDesc);
                }

                // if task is a per camera update with sorting, add sort tasks
                if (context is VFXOutputUpdate)
                {
                    var update = (VFXOutputUpdate)context;

                    if (update.HasFeature(VFXOutputUpdate.Features.Sort))
                    {
                        for (int j = 0; j < update.bufferCount; ++j)
                        {
                            VFXEditorTaskDesc sortTaskDesc = new VFXEditorTaskDesc();
                            sortTaskDesc.type = UnityEngine.VFX.VFXTaskType.PerCameraSort;
                            sortTaskDesc.externalProcessor = null;
                            sortTaskDesc.model             = context;

                            sortTaskDesc.buffers    = new VFXMapping[3];
                            sortTaskDesc.buffers[0] = new VFXMapping("srcBuffer", update.bufferIndex + j);
                            if (capacity > 4096) // Add scratch buffer
                            {
                                sortTaskDesc.buffers[1] = new VFXMapping("scratchBuffer", outBufferDescs.Count);
                                outBufferDescs.Add(new VFXGPUBufferDesc()
                                {
                                    type = ComputeBufferType.Default, size = capacity, stride = 8
                                });
                            }
                            else
                            {
                                sortTaskDesc.buffers[1] = new VFXMapping("scratchBuffer", -1); // No scratchBuffer needed
                            }
                            sortTaskDesc.buffers[2] = new VFXMapping("dstBuffer", update.sortedBufferIndex + j);

                            sortTaskDesc.parameters    = new VFXMapping[1];
                            sortTaskDesc.parameters[0] = new VFXMapping("globalSort", 0);

                            taskDescs.Add(sortTaskDesc);
                        }
                    }
                }
            }

            string nativeName = string.Empty;

            if (systemNames != null)
            {
                nativeName = systemNames.GetUniqueSystemName(this);
            }
            else
            {
                throw new InvalidOperationException("system names manager cannot be null");
            }

            outSystemDescs.Add(new VFXEditorSystemDesc()
            {
                flags    = systemFlag,
                tasks    = taskDescs.ToArray(),
                capacity = capacity,
                name     = nativeName,
                buffers  = systemBufferMappings.ToArray(),
                values   = systemValueMappings.ToArray(),
                type     = VFXSystemType.Particle,
                layer    = m_Layer
            });
        }
예제 #13
0
        public override void FillDescs(
            List <VFXGPUBufferDesc> outBufferDescs,
            List <VFXTemporaryGPUBufferDesc> outTemporaryBufferDescs,
            List <VFXEditorSystemDesc> outSystemDescs,
            VFXExpressionGraph expressionGraph,
            Dictionary <VFXContext, VFXContextCompiledData> contextToCompiledData,
            Dictionary <VFXContext, int> contextSpawnToBufferIndex,
            VFXDependentBuffersData dependentBuffers,
            Dictionary <VFXContext, List <VFXContextLink>[]> effectiveFlowInputLinks,
            VFXSystemNames systemNames = null)
        {
            bool hasKill = IsAttributeStored(VFXAttribute.Alive);

            var deadListBufferIndex = -1;
            var deadListCountIndex  = -1;

            var systemBufferMappings = new List <VFXMapping>();
            var systemValueMappings  = new List <VFXMapping>();

            var attributeBufferIndex = dependentBuffers.attributeBuffers[this];

            int attributeSourceBufferIndex = -1;
            int eventGPUFrom = -1;

            var stripDataIndex = -1;

            if (m_DependenciesIn.Any())
            {
                if (m_DependenciesIn.Count != 1)
                {
                    throw new InvalidOperationException("Unexpected multiple input dependency for GPU event");
                }
                attributeSourceBufferIndex = dependentBuffers.attributeBuffers[m_DependenciesIn.FirstOrDefault()];
                eventGPUFrom = dependentBuffers.eventBuffers[this];
            }

            if (attributeBufferIndex != -1)
            {
                systemBufferMappings.Add(new VFXMapping("attributeBuffer", attributeBufferIndex));
            }

            if (m_ownAttributeSourceBuffer && m_layoutAttributeSource.GetBufferSize(sourceCount) > 0u)
            {
                if (attributeSourceBufferIndex != -1)
                {
                    throw new InvalidOperationException("Unexpected source while filling description of data particle");
                }

                attributeSourceBufferIndex = outBufferDescs.Count;
                outBufferDescs.Add(m_layoutAttributeSource.GetBufferDesc(sourceCount));
            }

            if (attributeSourceBufferIndex != -1)
            {
                systemBufferMappings.Add(new VFXMapping("sourceAttributeBuffer", attributeSourceBufferIndex));
            }

            var systemFlag = VFXSystemFlag.SystemDefault;

            if (eventGPUFrom != -1)
            {
                systemFlag |= VFXSystemFlag.SystemReceivedEventGPU;
                systemBufferMappings.Add(new VFXMapping("eventList", eventGPUFrom));
            }

            if (hasKill)
            {
                systemFlag |= VFXSystemFlag.SystemHasKill;

                deadListBufferIndex = outBufferDescs.Count;
                outBufferDescs.Add(new VFXGPUBufferDesc()
                {
                    type = ComputeBufferType.Counter, size = capacity, stride = 4
                });
                systemBufferMappings.Add(new VFXMapping("deadList", deadListBufferIndex));

                deadListCountIndex = outBufferDescs.Count;
                outBufferDescs.Add(new VFXGPUBufferDesc()
                {
                    type = ComputeBufferType.Raw, size = 1, stride = 4
                });
                systemBufferMappings.Add(new VFXMapping("deadListCount", deadListCountIndex));
            }

            if (hasStrip)
            {
                systemFlag |= VFXSystemFlag.SystemHasStrips;

                systemValueMappings.Add(new VFXMapping("stripCount", (int)stripCapacity));
                systemValueMappings.Add(new VFXMapping("particlePerStripCount", (int)particlePerStripCount));

                stripDataIndex = dependentBuffers.stripBuffers[this];
                systemBufferMappings.Add(new VFXMapping("stripDataBuffer", stripDataIndex));
            }

            var initContext = m_Contexts.FirstOrDefault(o => o.contextType == VFXContextType.Init);

            if (initContext != null)
            {
                systemBufferMappings.AddRange(effectiveFlowInputLinks[initContext].SelectMany(t => t.Select(u => u.context)).Where(o => o.contextType == VFXContextType.Spawner).Select(o => new VFXMapping("spawner_input", contextSpawnToBufferIndex[o])));
            }
            if (m_Contexts.Count() > 0 && m_Contexts.First().contextType == VFXContextType.Init) // TODO This test can be removed once we ensure priorly the system is valid
            {
                var mapper = contextToCompiledData[m_Contexts.First()].cpuMapper;

                var boundsCenterExp = mapper.FromNameAndId("bounds_center", -1);
                var boundsSizeExp   = mapper.FromNameAndId("bounds_size", -1);

                int boundsCenterIndex = boundsCenterExp != null?expressionGraph.GetFlattenedIndex(boundsCenterExp) : -1;

                int boundsSizeIndex = boundsSizeExp != null?expressionGraph.GetFlattenedIndex(boundsSizeExp) : -1;

                if (boundsCenterIndex != -1 && boundsSizeIndex != -1)
                {
                    systemValueMappings.Add(new VFXMapping("bounds_center", boundsCenterIndex));
                    systemValueMappings.Add(new VFXMapping("bounds_size", boundsSizeIndex));
                }
            }

            int  indirectBufferIndex = -1;
            bool needsIndirectBuffer = NeedsIndirectBuffer();

            if (needsIndirectBuffer)
            {
                systemFlag         |= VFXSystemFlag.SystemHasIndirectBuffer;
                indirectBufferIndex = outBufferDescs.Count;
                outBufferDescs.Add(new VFXGPUBufferDesc()
                {
                    type = ComputeBufferType.Counter, size = capacity, stride = 4
                });
                systemBufferMappings.Add(new VFXMapping("indirectBuffer", indirectBufferIndex));
            }

            // sort buffers
            int  sortBufferAIndex = -1;
            int  sortBufferBIndex = -1;
            bool needsSort        = NeedsSort();

            if (needsSort)
            {
                sortBufferAIndex = outBufferDescs.Count;
                sortBufferBIndex = sortBufferAIndex + 1;

                outBufferDescs.Add(new VFXGPUBufferDesc()
                {
                    type = ComputeBufferType.Default, size = capacity, stride = 8
                });
                systemBufferMappings.Add(new VFXMapping("sortBufferA", sortBufferAIndex));

                outBufferDescs.Add(new VFXGPUBufferDesc()
                {
                    type = ComputeBufferType.Default, size = capacity, stride = 8
                });
                systemBufferMappings.Add(new VFXMapping("sortBufferB", sortBufferBIndex));
            }

            var elementToVFXBufferMotionVector = new Dictionary <VFXContext, int>();

            foreach (VFXMotionVector motionVectorContext in m_Contexts.OfType <VFXMotionVector>())
            {
                int currentElementToVFXBufferMotionVector = outTemporaryBufferDescs.Count;
                outTemporaryBufferDescs.Add(new VFXTemporaryGPUBufferDesc()
                {
                    frameCount = 2u, desc = new VFXGPUBufferDesc {
                        type = ComputeBufferType.Raw, size = capacity * 64, stride = 4
                    }
                });
                elementToVFXBufferMotionVector.Add(motionVectorContext.encapsulatedOutput, currentElementToVFXBufferMotionVector);
            }

            var taskDescs       = new List <VFXEditorTaskDesc>();
            var bufferMappings  = new List <VFXMapping>();
            var uniformMappings = new List <VFXMapping>();

            for (int i = 0; i < m_Contexts.Count; ++i)
            {
                var temporaryBufferMappings = new List <VFXMappingTemporary>();

                var context     = m_Contexts[i];
                var contextData = contextToCompiledData[context];

                var taskDesc = new VFXEditorTaskDesc();
                taskDesc.type = (UnityEngine.VFX.VFXTaskType)context.taskType;

                bufferMappings.Clear();

                if (context is VFXMotionVector)
                {
                    var currentIndex = elementToVFXBufferMotionVector[(context as VFXMotionVector).encapsulatedOutput];
                    temporaryBufferMappings.Add(new VFXMappingTemporary()
                    {
                        pastFrameIndex = 0u, perCameraBuffer = true, mapping = new VFXMapping("elementToVFXBuffer", currentIndex)
                    });
                }
                else if (context.contextType == VFXContextType.Output && (context is IVFXSubRenderer) && (context as IVFXSubRenderer).hasMotionVector)
                {
                    var currentIndex = elementToVFXBufferMotionVector[context];
                    temporaryBufferMappings.Add(new VFXMappingTemporary()
                    {
                        pastFrameIndex = 1u, perCameraBuffer = true, mapping = new VFXMapping("elementToVFXBufferPrevious", currentIndex)
                    });
                }

                if (attributeBufferIndex != -1)
                {
                    bufferMappings.Add(new VFXMapping("attributeBuffer", attributeBufferIndex));
                }

                if (eventGPUFrom != -1 && context.contextType == VFXContextType.Init)
                {
                    bufferMappings.Add(new VFXMapping("eventList", eventGPUFrom));
                }

                if (deadListBufferIndex != -1 && context.contextType != VFXContextType.Output && context.taskType != VFXTaskType.CameraSort)
                {
                    bufferMappings.Add(new VFXMapping(context.contextType == VFXContextType.Update ? "deadListOut" : "deadListIn", deadListBufferIndex));
                }

                if (deadListCountIndex != -1 && context.contextType == VFXContextType.Init)
                {
                    bufferMappings.Add(new VFXMapping("deadListCount", deadListCountIndex));
                }

                if (attributeSourceBufferIndex != -1 && context.contextType == VFXContextType.Init)
                {
                    bufferMappings.Add(new VFXMapping("sourceAttributeBuffer", attributeSourceBufferIndex));
                }

                if (stripDataIndex != -1 && context.ownedType == VFXDataType.ParticleStrip)
                {
                    bufferMappings.Add(new VFXMapping("stripDataBuffer", stripDataIndex));
                }

                bool hasAttachedStrip = IsAttributeStored(VFXAttribute.StripAlive);
                if (hasAttachedStrip)
                {
                    var stripData = dependenciesOut.First(d => ((VFXDataParticle)d).hasStrip); // TODO Handle several strip attached
                    bufferMappings.Add(new VFXMapping("attachedStripDataBuffer", dependentBuffers.stripBuffers[stripData]));
                }

                if (indirectBufferIndex != -1 &&
                    (context.contextType == VFXContextType.Update ||
                     (context.contextType == VFXContextType.Output && (context as VFXAbstractParticleOutput).HasIndirectDraw())))
                {
                    bufferMappings.Add(new VFXMapping(context.taskType == VFXTaskType.CameraSort ? "inputBuffer" : "indirectBuffer", indirectBufferIndex));
                }

                if (deadListBufferIndex != -1 && context.contextType == VFXContextType.Output && (context as VFXAbstractParticleOutput).NeedsDeadListCount())
                {
                    bufferMappings.Add(new VFXMapping("deadListCount", deadListCountIndex));
                }

                if (context.taskType == VFXTaskType.CameraSort)
                {
                    bufferMappings.Add(new VFXMapping("outputBuffer", sortBufferAIndex));
                    if (deadListCountIndex != -1)
                    {
                        bufferMappings.Add(new VFXMapping("deadListCount", deadListCountIndex));
                    }
                }

                var gpuTarget = context.allLinkedOutputSlot.SelectMany(o => (o.owner as VFXContext).outputContexts)
                                .Where(c => c.CanBeCompiled())
                                .Select(o => dependentBuffers.eventBuffers[o.GetData()])
                                .ToArray();
                for (uint indexTarget = 0; indexTarget < (uint)gpuTarget.Length; ++indexTarget)
                {
                    var prefix = VFXCodeGeneratorHelper.GeneratePrefix(indexTarget);
                    bufferMappings.Add(new VFXMapping(string.Format("eventListOut_{0}", prefix), gpuTarget[indexTarget]));
                }

                uniformMappings.Clear();
                foreach (var uniform in contextData.uniformMapper.uniforms)
                {
                    uniformMappings.Add(new VFXMapping(contextData.uniformMapper.GetName(uniform), expressionGraph.GetFlattenedIndex(uniform)));
                }
                foreach (var texture in contextData.uniformMapper.textures)
                {
                    // TODO At the moment issue all names sharing the same texture as different texture slots. This is not optimized as it required more texture binding than necessary
                    foreach (var name in contextData.uniformMapper.GetNames(texture))
                    {
                        uniformMappings.Add(new VFXMapping(name, expressionGraph.GetFlattenedIndex(texture)));
                    }
                }

                // Retrieve all cpu mappings at context level (-1)
                var cpuMappings = contextData.cpuMapper.CollectExpression(-1).Select(exp => new VFXMapping(exp.name, expressionGraph.GetFlattenedIndex(exp.exp))).ToArray();

                //Check potential issue with invalid operation on CPU
                foreach (var mapping in cpuMappings)
                {
                    if (mapping.index < 0)
                    {
                        throw new InvalidOperationException("Unable to compute CPU expression for mapping : " + mapping.name);
                    }
                }

                taskDesc.buffers           = bufferMappings.ToArray();
                taskDesc.temporaryBuffers  = temporaryBufferMappings.ToArray();
                taskDesc.values            = uniformMappings.ToArray();
                taskDesc.parameters        = cpuMappings.Concat(contextData.parameters).ToArray();
                taskDesc.shaderSourceIndex = contextToCompiledData[context].indexInShaderSource;

                taskDescs.Add(taskDesc);
            }

            string nativeName = string.Empty;

            if (systemNames != null)
            {
                nativeName = systemNames.GetUniqueSystemName(this);
            }
            else
            {
                throw new InvalidOperationException("system names manager cannot be null");
            }

            outSystemDescs.Add(new VFXEditorSystemDesc()
            {
                flags    = systemFlag,
                tasks    = taskDescs.ToArray(),
                capacity = capacity,
                name     = nativeName,
                buffers  = systemBufferMappings.ToArray(),
                values   = systemValueMappings.ToArray(),
                type     = VFXSystemType.Particle,
                layer    = m_Layer
            });
        }
예제 #14
0
        public static void DebugExpressionGraph(VFXGraph graph, VFXExpressionContextOption option, string fileName = "expGraph.dot")
        {
            var expressionGraph = new VFXExpressionGraph();

            expressionGraph.CompileExpressions(graph, option, true);

            var mainExpressions = new Dictionary <VFXExpression, List <string> >();

            FillMainExpressions(mainExpressions, expressionGraph.GPUExpressionsToReduced, expressionGraph);
            FillMainExpressions(mainExpressions, expressionGraph.CPUExpressionsToReduced, expressionGraph);

            var expressions = expressionGraph.Expressions;

            DotGraph dotGraph = new DotGraph();

            var expressionsToDot = new Dictionary <VFXExpression, DotNode>();

            foreach (var exp in expressions)
            {
                var dotNode = new DotNode();

                string name = exp.GetType().Name;
                name += " " + exp.valueType.ToString();
                string valueStr = GetExpressionValue(exp);
                if (!string.IsNullOrEmpty(valueStr))
                {
                    name += string.Format(" ({0})", valueStr);
                }

                dotNode.attributes[DotAttribute.Shape] = DotShape.Box;

                if (mainExpressions.ContainsKey(exp))
                {
                    string allOwnersStr = string.Empty;
                    foreach (var str in mainExpressions[exp])
                    {
                        allOwnersStr += "\n" + str;
                    }

                    name += string.Format("{0}", allOwnersStr);

                    if (exp.IsAny(VFXExpression.Flags.NotCompilableOnCPU))
                    {
                        dotNode.attributes[DotAttribute.Color] = DotColor.Orange;
                    }
                    else if (exp.Is(VFXExpression.Flags.Constant))
                    {
                        dotNode.attributes[DotAttribute.Color] = DotColor.SteelBlue;
                    }
                    else
                    {
                        dotNode.attributes[DotAttribute.Color] = DotColor.Cyan;
                    }
                }
                else if (exp.IsAny(VFXExpression.Flags.NotCompilableOnCPU))
                {
                    dotNode.attributes[DotAttribute.Color] = DotColor.Yellow;
                }
                else if (exp.Is(VFXExpression.Flags.Constant))
                {
                    dotNode.attributes[DotAttribute.Color] = DotColor.SlateGray;
                }
                else if (exp.Is(VFXExpression.Flags.Foldable))
                {
                    dotNode.attributes[DotAttribute.Color] = DotColor.LightGray;
                }

                if (dotNode.attributes.ContainsKey(DotAttribute.Color))
                {
                    dotNode.attributes[DotAttribute.Style] = DotStyle.Filled;
                }

                dotNode.Label = name;

                expressionsToDot[exp] = dotNode;
                dotGraph.AddElement(dotNode);
            }

            foreach (var exp in expressionsToDot)
            {
                var parents = exp.Key.parents;
                for (int i = 0; i < parents.Length; ++i)
                {
                    var dotEdge = new DotEdge(expressionsToDot[parents[i]], exp.Value);
                    if (parents.Length > 1)
                    {
                        dotEdge.attributes[DotAttribute.HeadLabel] = i.ToString();
                    }
                    dotGraph.AddElement(dotEdge);
                }
            }

            var basePath = Application.dataPath;

            basePath = basePath.Replace("/Assets", "");
            basePath = basePath.Replace("/", "\\");

            var outputfile = basePath + "\\GraphViz\\output\\" + fileName;

            dotGraph.OutputToDotFile(outputfile);

            var proc = new Process();

            proc.StartInfo.WindowStyle     = ProcessWindowStyle.Hidden;
            proc.StartInfo.CreateNoWindow  = true;
            proc.StartInfo.UseShellExecute = false;
            proc.StartInfo.FileName        = "C:\\Windows\\system32\\cmd.exe";
            var path = basePath + "\\GraphViz\\Postbuild.bat";

            proc.StartInfo.Arguments = "/c" + path + " \"" + outputfile + "\"";
            proc.EnableRaisingEvents = true;
            proc.Start();
        }
예제 #15
0
        private static void FillMainExpressions(Dictionary <VFXExpression, List <string> > mainExpressions, Dictionary <VFXExpression, VFXExpression> inputExpressions, VFXExpressionGraph graph)
        {
            foreach (var kvp in inputExpressions)
            {
                var exp     = kvp.Key;
                var reduced = kvp.Value;

                if (mainExpressions.ContainsKey(reduced))
                {
                    mainExpressions[reduced].AddRange(graph.GetAllNames(exp));
                }
                else
                {
                    var list = new List <string>();
                    list.AddRange(graph.GetAllNames(exp));
                    mainExpressions[reduced] = list;
                }
            }
        }
예제 #16
0
        public void Compile(VFXCompilationMode compilationMode)
        {
            // Prevent doing anything ( and especially showing progesses ) in an empty graph.
            if (m_Graph.children.Count() < 1)
            {
                // Cleaning
                if (m_Graph.visualEffectResource != null)
                {
                    m_Graph.visualEffectResource.ClearRuntimeData();
                }

                m_ExpressionGraph  = new VFXExpressionGraph();
                m_ExpressionValues = new VFXExpressionValueContainerDesc[] {};
                return;
            }

            Profiler.BeginSample("VFXEditor.CompileAsset");
            try
            {
                float  nbSteps          = 12.0f;
                string assetPath        = AssetDatabase.GetAssetPath(visualEffectResource);
                string progressBarTitle = "Compiling " + assetPath;

                EditorUtility.DisplayProgressBar(progressBarTitle, "Collecting dependencies", 0 / nbSteps);
                var models = new HashSet <ScriptableObject>();
                m_Graph.CollectDependencies(models);

                var contexts = models.OfType <VFXContext>().ToArray();

                foreach (var c in contexts) // Unflag all contexts
                {
                    c.MarkAsCompiled(false);
                }

                var compilableContexts = models.OfType <VFXContext>().Where(c => c.CanBeCompiled());
                var compilableData     = models.OfType <VFXData>().Where(d => d.CanBeCompiled());

                IEnumerable <VFXContext> implicitContexts = Enumerable.Empty <VFXContext>();
                foreach (var d in compilableData) // Flag compiled contexts
                {
                    implicitContexts = implicitContexts.Concat(d.InitImplicitContexts());
                }
                compilableContexts = compilableContexts.Concat(implicitContexts.ToArray());

                foreach (var c in compilableContexts) // Flag compiled contexts
                {
                    c.MarkAsCompiled(true);
                }

                EditorUtility.DisplayProgressBar(progressBarTitle, "Collecting attributes", 1 / nbSteps);
                foreach (var data in compilableData)
                {
                    data.CollectAttributes();
                }

                EditorUtility.DisplayProgressBar(progressBarTitle, "Computing layers", 2 / nbSteps);
                foreach (var data in compilableData)
                {
                    data.ComputeLayer();
                }

                EditorUtility.DisplayProgressBar(progressBarTitle, "Compiling expression Graph", 3 / nbSteps);
                m_ExpressionGraph = new VFXExpressionGraph();
                var exposedExpressionContext = ScriptableObject.CreateInstance <VFXImplicitContextOfExposedExpression>();
                exposedExpressionContext.FillExpression(m_Graph); //Force all exposed expression to be visible, only for registering in CompileExpressions

                var expressionContextOptions = compilationMode == VFXCompilationMode.Runtime ? VFXExpressionContextOption.ConstantFolding : VFXExpressionContextOption.Reduction;
                m_ExpressionGraph.CompileExpressions(compilableContexts.Concat(new VFXContext[] { exposedExpressionContext }), expressionContextOptions);

                EditorUtility.DisplayProgressBar(progressBarTitle, "Generating bytecode", 4 / nbSteps);
                var expressionDescs = new List <VFXExpressionDesc>();
                var valueDescs      = new List <VFXExpressionValueContainerDesc>();
                FillExpressionDescs(expressionDescs, valueDescs, m_ExpressionGraph);

                Dictionary <VFXContext, VFXContextCompiledData> contextToCompiledData = new Dictionary <VFXContext, VFXContextCompiledData>();
                foreach (var context in compilableContexts)
                {
                    contextToCompiledData.Add(context, new VFXContextCompiledData());
                }

                EditorUtility.DisplayProgressBar(progressBarTitle, "Generating mappings", 5 / nbSteps);
                foreach (var context in compilableContexts)
                {
                    var cpuMapper   = m_ExpressionGraph.BuildCPUMapper(context);
                    var contextData = contextToCompiledData[context];
                    contextData.cpuMapper          = cpuMapper;
                    contextData.parameters         = context.additionalMappings.ToArray();
                    contextToCompiledData[context] = contextData;
                }

                var exposedParameterDescs = new List <VFXMapping>();
                FillExposedDescs(exposedParameterDescs, m_ExpressionGraph, models.OfType <VFXParameter>());
                var globalEventAttributeDescs = new List <VFXLayoutElementDesc>()
                {
                    new VFXLayoutElementDesc()
                    {
                        name = "spawnCount", type = VFXValueType.Float
                    }
                };
                FillEventAttributeDescs(globalEventAttributeDescs, m_ExpressionGraph, compilableContexts);

                EditorUtility.DisplayProgressBar(progressBarTitle, "Generating Attribute layouts", 6 / nbSteps);
                foreach (var data in compilableData)
                {
                    data.GenerateAttributeLayout();
                }

                var generatedCodeData = new List <GeneratedCodeData>();

                EditorUtility.DisplayProgressBar(progressBarTitle, "Generating shaders", 7 / nbSteps);
                GenerateShaders(generatedCodeData, m_ExpressionGraph, compilableContexts, contextToCompiledData, compilationMode);

                EditorUtility.DisplayProgressBar(progressBarTitle, "Saving shaders", 8 / nbSteps);
                SaveShaderFiles(m_Graph.visualEffectResource, generatedCodeData, contextToCompiledData);

                var bufferDescs    = new List <VFXGPUBufferDesc>();
                var cpuBufferDescs = new List <VFXCPUBufferDesc>();
                var systemDescs    = new List <VFXEditorSystemDesc>();

                EditorUtility.DisplayProgressBar(progressBarTitle, "Generating systems", 9 / nbSteps);
                cpuBufferDescs.Add(new VFXCPUBufferDesc()
                {
                    capacity    = 1u,
                    layout      = globalEventAttributeDescs.ToArray(),
                    stride      = globalEventAttributeDescs.First().offset.structure,
                    initialData = ComputeArrayOfStructureInitialData(globalEventAttributeDescs)
                });
                var contextSpawnToSpawnInfo = new Dictionary <VFXContext, SpawnInfo>();
                FillSpawner(contextSpawnToSpawnInfo, cpuBufferDescs, systemDescs, compilableContexts, m_ExpressionGraph, globalEventAttributeDescs, contextToCompiledData);

                var eventDescs = new List <VFXEventDesc>();
                FillEvent(eventDescs, contextSpawnToSpawnInfo, compilableContexts);

                var attributeBufferDictionnary = new Dictionary <VFXData, int>();
                var eventGpuBufferDictionnary  = new Dictionary <VFXData, int>();
                FillDependentBuffer(compilableData, bufferDescs, attributeBufferDictionnary, eventGpuBufferDictionnary);

                var contextSpawnToBufferIndex = contextSpawnToSpawnInfo.Select(o => new { o.Key, o.Value.bufferIndex }).ToDictionary(o => o.Key, o => o.bufferIndex);
                foreach (var data in compilableData)
                {
                    data.FillDescs(bufferDescs,
                                   systemDescs,
                                   m_ExpressionGraph,
                                   contextToCompiledData,
                                   contextSpawnToBufferIndex,
                                   attributeBufferDictionnary,
                                   eventGpuBufferDictionnary);
                }

                // Update renderer settings
                VFXRendererSettings rendererSettings = GetRendererSettings(m_Graph.visualEffectResource.rendererSettings, compilableContexts.OfType <IVFXSubRenderer>());
                m_Graph.visualEffectResource.rendererSettings = rendererSettings;

                EditorUtility.DisplayProgressBar(progressBarTitle, "Setting up systems", 10 / nbSteps);
                var expressionSheet = new VFXExpressionSheet();
                expressionSheet.expressions = expressionDescs.ToArray();
                expressionSheet.values      = valueDescs.OrderBy(o => o.expressionIndex).ToArray();
                expressionSheet.exposed     = exposedParameterDescs.OrderBy(o => o.name).ToArray();

                m_Graph.visualEffectResource.SetRuntimeData(expressionSheet, systemDescs.ToArray(), eventDescs.ToArray(), bufferDescs.ToArray(), cpuBufferDescs.ToArray());
                m_ExpressionValues = expressionSheet.values;

                EditorUtility.DisplayProgressBar(progressBarTitle, "Importing VFX", 11 / nbSteps);
                Profiler.BeginSample("VFXEditor.CompileAsset:ImportAsset");
                AssetDatabase.ImportAsset(assetPath, ImportAssetOptions.ForceUpdate); //This should compile the shaders on the C++ size
                Profiler.EndSample();
            }
            catch (Exception e)
            {
                Debug.LogError(string.Format("Exception while compiling expression graph: {0}: {1}", e, e.StackTrace));

                // Cleaning
                if (m_Graph.visualEffectResource != null)
                {
                    m_Graph.visualEffectResource.ClearRuntimeData();
                }

                m_ExpressionGraph  = new VFXExpressionGraph();
                m_ExpressionValues = new VFXExpressionValueContainerDesc[] {};
            }
            finally
            {
                Profiler.EndSample();
                EditorUtility.ClearProgressBar();
            }
        }
예제 #17
0
        private static void FillExpressionDescs(List <VFXExpressionDesc> outExpressionDescs, List <VFXExpressionValueContainerDesc> outValueDescs, VFXExpressionGraph graph)
        {
            var flatGraph = graph.FlattenedExpressions;
            var numFlattenedExpressions = flatGraph.Count;

            for (int i = 0; i < numFlattenedExpressions; ++i)
            {
                var exp = flatGraph[i];

                // Must match data in C++ expression
                if (exp.Is(VFXExpression.Flags.Value))
                {
                    VFXExpressionValueContainerDesc value;
                    switch (exp.valueType)
                    {
                    case VFXValueType.Float: value = CreateValueDesc <float>(exp, i); break;

                    case VFXValueType.Float2: value = CreateValueDesc <Vector2>(exp, i); break;

                    case VFXValueType.Float3: value = CreateValueDesc <Vector3>(exp, i); break;

                    case VFXValueType.Float4: value = CreateValueDesc <Vector4>(exp, i); break;

                    case VFXValueType.Int32: value = CreateValueDesc <int>(exp, i); break;

                    case VFXValueType.Uint32: value = CreateValueDesc <uint>(exp, i); break;

                    case VFXValueType.Texture2D:
                    case VFXValueType.Texture2DArray:
                    case VFXValueType.Texture3D:
                    case VFXValueType.TextureCube:
                    case VFXValueType.TextureCubeArray:
                        value = CreateValueDesc <Texture>(exp, i);
                        break;

                    case VFXValueType.Matrix4x4: value = CreateValueDesc <Matrix4x4>(exp, i); break;

                    case VFXValueType.Curve: value = CreateValueDesc <AnimationCurve>(exp, i); break;

                    case VFXValueType.ColorGradient: value = CreateValueDesc <Gradient>(exp, i); break;

                    case VFXValueType.Mesh: value = CreateValueDesc <Mesh>(exp, i); break;

                    case VFXValueType.Boolean: value = CreateValueDesc <bool>(exp, i); break;

                    default: throw new InvalidOperationException("Invalid type");
                    }
                    value.expressionIndex = (uint)i;
                    outValueDescs.Add(value);
                }

                outExpressionDescs.Add(new VFXExpressionDesc
                {
                    op   = exp.operation,
                    data = exp.GetOperands(graph).ToArray(),
                });
            }
        }
        public override void FillDescs(
            VFXCompileErrorReporter reporter,
            List <VFXGPUBufferDesc> outBufferDescs,
            List <VFXTemporaryGPUBufferDesc> outTemporaryBufferDescs,
            List <VFXEditorSystemDesc> outSystemDescs,
            VFXExpressionGraph expressionGraph,
            Dictionary <VFXContext, VFXContextCompiledData> contextToCompiledData,
            Dictionary <VFXContext, int> contextSpawnToBufferIndex,
            VFXDependentBuffersData dependentBuffers,
            Dictionary <VFXContext, List <VFXContextLink>[]> effectiveFlowInputLinks,
            VFXSystemNames systemNames)
        {
            if (m_Contexts.Count != 1)
            {
                throw new InvalidOperationException("VFXDataOutputEvent unexpected context count : " + m_Contexts.Count);
            }

            if (m_Contexts.Any(o => o.contextType != VFXContextType.OutputEvent))
            {
                throw new InvalidOperationException("VFXDataOutputEvent unexpected context type");
            }

            var nativeName = eventName;

            if (outSystemDescs.Any(o => o.name == nativeName && o.type == VFXSystemType.OutputEvent))
            {
                //Check if already processed, it already present, this VFXDataOutputEvent has been gather with previous entry.
                return;
            }

            var allMatchingVFXDataOutputEvent = contextToCompiledData.Keys.Where(context =>
            {
                if (context.contextType == VFXContextType.OutputEvent)
                {
                    if (((VFXDataOutputEvent)context.GetData()).eventName == nativeName)
                    {
                        return(true);
                    }
                }
                return(false);
            }).Select(o => o.GetData()).Cast <VFXDataOutputEvent>().ToArray();

            var flowInputLinks = allMatchingVFXDataOutputEvent.SelectMany(data => data.m_Contexts.SelectMany(context =>
            {
                if (effectiveFlowInputLinks.ContainsKey(context))
                {
                    var r = effectiveFlowInputLinks[context];
                    return(r.SelectMany(o => o));
                }
                //A context could have been filtered out due because there isn't any flow input link
                return(Enumerable.Empty <VFXContextLink>());
            }));
            var inputSpawnerContext = flowInputLinks.Select(l => l.context).Distinct();

            var systemBufferMappings = new List <VFXMapping>();

            foreach (var spawner in inputSpawnerContext)
            {
                if (spawner.contextType != VFXContextType.Spawner)
                {
                    throw new InvalidOperationException("VFXDataOutputEvent unexpected link on Output event");
                }

                systemBufferMappings.Add(new VFXMapping()
                {
                    name  = "spawner_input",
                    index = contextSpawnToBufferIndex[spawner]
                });
            }

            outSystemDescs.Add(new VFXEditorSystemDesc()
            {
                flags   = VFXSystemFlag.SystemDefault,
                name    = nativeName,
                buffers = systemBufferMappings.ToArray(),
                type    = VFXSystemType.OutputEvent,
                layer   = m_Layer
            });
        }