Exemplo n.º 1
0
        public DataStorageItem <T> Add <T>(string name, int length)
        {
            DataStorageItem <T> ret = new DataStorageItem <T>(name, length);

            m_Storage.Add(name, ret);
            return(ret);
        }
Exemplo n.º 2
0
        private void PrepareShaderStage(StageType stage, object shaderInstance)
        {
            Type       type = shaderInstance.GetType();
            Expression primiteVertexIndexExpression = IntrospectionUtil.GetFieldExpression(this, nameof(PrimitiveVertexIndex));

            foreach (var fieldInfo in type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public))
            {
                string debugFieldName = string.Format("{0}.{1}", type.Name, fieldInfo.Name);

                var fieldExpression = IntrospectionUtil.GetFieldExpression(shaderInstance, fieldInfo);

                // BUILTIN
                if (m_ShaderBuiltins.IsBuiltin(stage, fieldInfo.Name))
                {
                    if (!m_ShaderBuiltins.Validate(stage, fieldInfo))
                    {
                        DebugMsg(string.Format("ERROR: failed to bind: invalid builtin {0}", debugFieldName));
                        continue;
                    }

                    var builtin      = m_ShaderBuiltins.Get(stage, fieldInfo.Name);
                    var directionIn  = builtin.Flags.HasFlag(BuiltinFlags.In);
                    var directionOut = builtin.Flags.HasFlag(BuiltinFlags.Out);

                    if (directionIn || directionOut)
                    {
                        Expression builtinVarExpression = IntrospectionUtil.GetFieldExpression(this, builtin.Name);
                        Expression builtinExpression    = builtinVarExpression;

                        // Indexed?
                        if (builtin.Flags.HasFlag(BuiltinFlags.IndexedPerVertex))
                        {
                            builtinExpression = IntrospectionUtil.GetArrayAccessExpression(builtinVarExpression, primiteVertexIndexExpression);
                        }

                        if (!ValidateFieldType(fieldInfo, builtinExpression.Type))
                        {
                            continue;
                        }

                        if (directionIn)
                        {
                            // m_Stages[stage].AddPreaction(IntrospectionUtil.CreateAssign(fieldExpression, builtinExpression));
                            m_PipelineProgramDefinition.PreActions[stage].Add(Expression.Assign(fieldExpression, builtinExpression));
                        }

                        if (directionOut)
                        {
                            // m_Stages[stage].AddPostAction(IntrospectionUtil.CreateAssign(builtinExpression, fieldExpression));
                            m_PipelineProgramDefinition.PostActions[stage].Add(Expression.Assign(builtinExpression, fieldExpression));
                        }
                    }

                    if (builtin.Flags.HasFlag(BuiltinFlags.HasAction))
                    {
                        builtin.UseAction.Invoke();
                    }

                    continue;
                }

                // ----- Verify ShaderAttribute -----

                var attrs = fieldInfo.GetCustomAttributes(typeof(ShaderLayoutAttribute)).ToArray();

                if (attrs.Length < 1)
                {
                    continue;
                }

                if (attrs.Length > 1)
                {
                    DebugMsg(string.Format("Ambiguous attributes for field {0}", debugFieldName));
                    continue;
                }

                ShaderLayoutAttribute atr = (ShaderLayoutAttribute)attrs[0];

                // ----- User variable with ShaderAttribute -----

                if (atr.type == ShaderLayoutType.Uniform)
                {
                    var readUniformCall = GetReadUniformExpression(fieldInfo, atr.binding, atr.set);
                    if (readUniformCall != null)
                    {
                        m_PipelineProgramDefinition.UniformLoader.Add(Expression.Assign(fieldExpression, readUniformCall));
                    }
                    continue;
                }

                if (stage == StageType.VertexShader)
                {
                    // IF IN:  obj.var = ReadVertexBuffer(location)
                    // IF OUT: storage[var][index] = obj.var

                    if (atr.type == ShaderLayoutType.In)
                    {
                        Type vertexBufferType = GetVertexBufferType(fieldInfo, atr.location);
                        if (vertexBufferType == null)
                        {
                            // incompatible or not found
                            continue;
                        }

                        if (!ValidateFieldType(fieldInfo, vertexBufferType))
                        {
                            continue;
                        }

                        var readVertexBufferCall = GetReadVertexBufferExpression(fieldInfo, atr.location);
                        if (readVertexBufferCall != null)
                        {
                            m_PipelineProgramDefinition.PreActions[stage].Add(Expression.Assign(fieldExpression, readVertexBufferCall));
                        }
                    }
                    else if (atr.type == ShaderLayoutType.Out)
                    {
                        DataStorageItem storage           = m_Storage.AddGeneric(fieldInfo.Name, fieldInfo.FieldType, PrimitiveLength);
                        Expression      storageExpression = storage.GetIndexedExpression(primiteVertexIndexExpression);
                        m_PipelineProgramDefinition.PostActions[stage].Add(Expression.Assign(storageExpression, fieldExpression));
                    }
                }
                else if (stage == StageType.FragmentShader)
                {
                    // IF IN:  obj.var = ReadSmoth(storage[var])
                    // IF OUT: WriteColorOutput(location, obj.var)

                    if (atr.type == ShaderLayoutType.In)
                    {
                        if (!m_Storage.HasKey(fieldInfo.Name))
                        {
                            DebugMsg(string.Format("ERROR: failed to bind field {0} (not found)", debugFieldName));
                            continue;
                        }

                        DataStorageItem storage = m_Storage.Get(fieldInfo.Name);

                        if (!ValidateFieldType(fieldInfo, storage.DataType))
                        {
                            continue;
                        }

                        var storageArrayExpression = storage.GetArrayExpression();
                        var readSmothCall          = GetReadSmothExpression(fieldInfo, storageArrayExpression);
                        m_PipelineProgramDefinition.PreActions[stage].Add(Expression.Assign(fieldExpression, readSmothCall));
                    }
                    else if (atr.type == ShaderLayoutType.Out)
                    {
                        if (!ValidateFieldType(fieldInfo, P_WRITE_COLOR_TYPE))
                        {
                            continue;
                        }

                        var writeColorOutputCall = GetWriteColorOutputExpression(atr.location, fieldExpression);
                        m_PipelineProgramDefinition.PostActions[stage].Add(writeColorOutputCall);
                    }
                }
            }
        }