Example #1
0
        public ShaderOp CompositeSplatConstruct(ShaderType resultType, IShaderIR value, FrontEndContext context)
        {
            var opArgs = new List <IShaderIR>();

            if (resultType.mBaseType == OpType.Vector)
            {
                var vectorResultType = VectorType.Load(resultType);
                for (var i = 0; i < vectorResultType.GetComponentCount(); ++i)
                {
                    opArgs.Add(value);
                }
            }
            else if (resultType.mBaseType == OpType.Matrix)
            {
                var matrixResultType = MatrixType.Load(resultType);
                var vectorElement    = CompositeSplatConstruct(matrixResultType.GetComponentType(), value, context);
                for (var i = 0; i < matrixResultType.GetComponentCount(); ++i)
                {
                    opArgs.Add(vectorElement);
                }
            }
            else
            {
                throw new Exception("invalid type");
            }

            return(CreateOp(context.mCurrentBlock, OpInstructionType.OpCompositeConstruct, resultType, opArgs));
        }
Example #2
0
        public ShaderOp GenerateFunctionCall(ShaderFunction shaderFunction, IShaderIR selfOp, List <IShaderIR> arguments, FrontEndContext context)
        {
            var argumentOps = new List <IShaderIR>();

            argumentOps.Add(shaderFunction);
            if (!shaderFunction.IsStatic || selfOp != null)
            {
                argumentOps.Add(selfOp);
            }

            if (arguments != null)
            {
                for (var i = 0; i < arguments.Count; ++i)
                {
                    var argument = arguments[i];
                    var paramIR  = GetFunctionParameter(shaderFunction, i, argument, context);
                    argumentOps.Add(paramIR);
                }
            }

            var fnShaderReturnType = shaderFunction.GetReturnType();
            var functionCallOp     = CreateOp(context.mCurrentBlock, OpInstructionType.OpFunctionCall, fnShaderReturnType, argumentOps);

            return(functionCallOp);
        }
Example #3
0
 void GenerateIds(IShaderIR ir)
 {
     if (ir is ShaderOp op)
     {
         GenerateIds(op);
     }
     else if (ir is ExtensionLibraryImportOp extImportOp)
     {
         GetId(extImportOp);
     }
     else if (ir is ShaderType shaderType)
     {
         GenerateIds(shaderType);
     }
     else if (ir is ShaderConstantLiteral constantLiteral)
     {
         // No op
     }
     else if (ir is ShaderBlock shaderBlock)
     {
         // Id is already assigned from the owning function
     }
     else
     {
         throw new Exception();
     }
 }
        public override void VisitFieldDeclaration(FieldDeclarationSyntax node)
        {
            mCommonPass.mFrontEnd = mFrontEnd;
            mCommonPass.mContext  = mContext;

            var declaredShaderType = FindType(node.Declaration.Type);

            foreach (var variable in node.Declaration.Variables)
            {
                var variableSymbol = GetDeclaredSymbol(variable);
                if (variableSymbol.IsStatic)
                {
                    GlobalShaderField shaderField;
                    int fieldIndex;
                    mFrontEnd.FindStaticField(mContext.mCurrentType, variable.Identifier.ToString(), out shaderField, out fieldIndex);
                    shaderField.InitialValue = GetInitialValue(variable, shaderField);
                }
                else
                {
                    ShaderField shaderField;
                    int         fieldIndex;
                    mFrontEnd.FindField(mContext.mCurrentType, variable.Identifier.ToString(), out shaderField, out fieldIndex);

                    // If there is an initial value op then store it into the field
                    IShaderIR initialValueOp = GetInitialValue(variable, shaderField);
                    if (initialValueOp != null)
                    {
                        var variableOp = mFrontEnd.GenerateAccessChain(mContext.mThisOp, shaderField.mType, (uint)fieldIndex, mContext);
                        mFrontEnd.CreateStoreOp(mContext.mCurrentBlock, variableOp, initialValueOp);
                    }
                }
            }
        }
Example #5
0
 public void Visit(IShaderIR ir)
 {
     if (ir is ShaderType shaderType)
     {
         Visit(shaderType);
     }
     else if (ir is ShaderFunction shaderFunction)
     {
         Visit(shaderFunction);
     }
     else if (ir is ShaderConstantLiteral constantLiteral)
     {
         Visit(constantLiteral);
     }
     else if (ir is ShaderOp shaderOp)
     {
         Visit(shaderOp);
     }
     else if (ir is ExtensionLibraryImportOp extLibraryImportOp)
     {
         Visit(extLibraryImportOp);
     }
     else if (ir is ShaderBlock shaderBlock)
     {
         // Skip blocks as an ir. This is a target of some other op (like a branch) and it's body will be visited elsewhere (typically on the function)
     }
     else
     {
         throw new Exception();
     }
 }
Example #6
0
        public ShaderOp CastBoolToFloat(ShaderType resultType, IShaderIR expressionOp, FrontEndContext context)
        {
            var constantOp0 = CreateConstantOp <float>(0.0f);
            var constantOp1 = CreateConstantOp <float>(1.0f);

            return(CastFromBool(resultType, expressionOp, constantOp0, constantOp1, context));
        }
Example #7
0
 public ShaderOp TryGenerateFunctionCall(ShaderFunction shaderFunction, IShaderIR selfOp, List <IShaderIR> arguments, FrontEndContext context)
 {
     if (shaderFunction == null)
     {
         return(null);
     }
     return(GenerateFunctionCall(shaderFunction, selfOp, arguments, context));
 }
Example #8
0
        public ShaderOp CreateStoreOp(ShaderBlock block, IShaderIR variable, IShaderIR result)
        {
            var valueResult = GetOrGenerateValueTypeFromIR(block, result);

            return(CreateOp(block, OpInstructionType.OpStore, null, new List <IShaderIR> {
                variable, valueResult
            }));
        }
Example #9
0
 UInt32 GetId(IShaderIR ir)
 {
     if (!mIdMap.ContainsKey(ir))
     {
         mIdMap.Add(ir, mId);
         ++mId;
     }
     return(mIdMap[ir]);
 }
Example #10
0
        public static void AddDecorationDescriptorSet(FrontEndTranslator translator, IShaderIR ir, int descriptorSetId, ShaderBlock decorationsBlock)
        {
            var decorationBindingLiteral = translator.CreateConstantLiteral((int)Spv.Decoration.DecorationDescriptorSet);
            var descriptorSetIdLiteral   = translator.CreateConstantLiteral(descriptorSetId);

            translator.CreateOp(decorationsBlock, OpInstructionType.OpDecorate, null, new List <IShaderIR>()
            {
                ir, decorationBindingLiteral, descriptorSetIdLiteral
            });
        }
Example #11
0
        public ShaderOp GenerateAccessChain(IShaderIR selfIR, string fieldName, FrontEndContext context)
        {
            var         selfOp   = selfIR as ShaderOp;
            var         selfType = selfOp.mResultType.GetDereferenceType();
            ShaderField shaderField;
            int         fieldIndex;

            FindField(selfType, fieldName, out shaderField, out fieldIndex);
            return(GenerateAccessChain(selfIR, shaderField.mType, (uint)fieldIndex, context));
        }
Example #12
0
        public ShaderOp GenerateAccessChain(IShaderIR selfIR, ShaderType resultType, uint fieldIndex, FrontEndContext context)
        {
            var selfOp              = selfIR as ShaderOp;
            var constantLiteral     = CreateConstantLiteral(fieldIndex);
            var memberIndexConstant = CreateConstantOp(FindType(typeof(uint)), constantLiteral);

            resultType = FindOrCreatePointerType(resultType.GetDereferenceType(), selfOp.mResultType.mStorageClass);
            var memberVariableOp = CreateOp(context.mCurrentBlock, OpInstructionType.OpAccessChain, resultType, new List <IShaderIR> {
                selfOp, memberIndexConstant
            });

            return(memberVariableOp);
        }
Example #13
0
        public bool TryCallSetterFunction(FunctionKey functionKey, IShaderIR selfInstanceIR, IShaderIR rhsIR)
        {
            var setterShaderFunction = mFrontEnd.mCurrentLibrary.FindFunction(functionKey);

            if (setterShaderFunction == null)
            {
                return(false);
            }

            GenerateFunctionCall(setterShaderFunction, selfInstanceIR, new List <IShaderIR>()
            {
                rhsIR
            });
            return(true);
        }
 void WriteIR(IShaderIR ir)
 {
     if (ir is ShaderOp op)
     {
         WriteOp(op);
     }
     else if (ir is ShaderConstantLiteral constantLiteral)
     {
         WriteConstantLiteral(constantLiteral);
     }
     else
     {
         throw new Exception();
     }
 }
        void WriteDebugName(IShaderIR ir, string debugName)
        {
            if (string.IsNullOrEmpty(debugName))
            {
                return;
            }

            var id              = GetId(ir);
            var wordCount       = mWriter.GetPaddedWordCount(debugName);
            var instructionSize = (UInt16)(2 + wordCount);

            mWriter.WriteInstruction(instructionSize, Spv.Op.OpName);
            mWriter.Write(id);
            mWriter.Write(debugName);
        }
Example #16
0
        public bool TryCallIntrinsicsSetterFunction(FunctionKey functionKey, IShaderIR setter, IShaderIR argumentIR)
        {
            var instrinsicDelegate = mFrontEnd.mCurrentLibrary.FindIntrinsicSetterFunction(functionKey);

            if (instrinsicDelegate == null)
            {
                return(false);
            }

            // Build the arguments up
            var argumentIRs = new List <IShaderIR>();

            instrinsicDelegate(mFrontEnd, setter, argumentIR, mContext);

            return(true);
        }
Example #17
0
        ///////////////////////////////////////////////////////////////Conversions
        public ShaderOp CastFromBool(ShaderType resultType, IShaderIR expressionOp, IShaderIR zeroScalar, IShaderIR oneScalar, FrontEndContext context)
        {
            var zeroExpression = zeroScalar;
            var oneExpression  = oneScalar;

            if (resultType.mBaseType == OpType.Vector)
            {
                zeroExpression = CompositeSplatConstruct(resultType, zeroScalar, context);
                oneExpression  = CompositeSplatConstruct(resultType, oneScalar, context);
            }
            var castOp = CreateOp(context.mCurrentBlock, OpInstructionType.OpSelect, resultType, new List <IShaderIR> {
                expressionOp, zeroScalar, oneScalar
            });

            context.Push(castOp);
            return(castOp);
        }
Example #18
0
        public ShaderOp GenerateCompositeExtract(IShaderIR selfIR, string fieldName, FrontEndContext context)
        {
            var         selfOp   = selfIR as ShaderOp;
            var         selfType = selfOp.mResultType.GetDereferenceType();
            ShaderField shaderField;
            int         fieldIndex;

            FindField(selfType, fieldName, out shaderField, out fieldIndex);

            var resultType       = shaderField.mType.GetDereferenceType();
            var constantLiteral  = CreateConstantLiteral <uint>((uint)fieldIndex);
            var memberVariableOp = CreateOp(context.mCurrentBlock, OpInstructionType.OpCompositeExtract, resultType, new List <IShaderIR> {
                selfOp, constantLiteral
            });

            return(memberVariableOp);
        }
Example #19
0
 void IncDecOp(FrontEndTranslator translator, ShaderType resultType, string opToken, ShaderType operandType, OpInstructionType instructionType)
 {
     CreateUnaryOpIntrinsic(new UnaryOpKey(opToken, operandType), (IShaderIR operandIR, FrontEndContext context) =>
     {
         var operandValueOp      = translator.GetOrGenerateValueTypeFromIR(context.mCurrentBlock, operandIR);
         IShaderIR oneConstantOp = null;
         if (resultType.mBaseType == OpType.Int)
         {
             oneConstantOp = translator.CreateConstantOp(operandType, 1);
         }
         else if (resultType.mBaseType == OpType.Float)
         {
             oneConstantOp = translator.CreateConstantOp(operandType, 1.0f);
         }
         return(translator.CreateOp(context.mCurrentBlock, instructionType, resultType, new List <IShaderIR> {
             operandValueOp, oneConstantOp
         }));
     });
 }
Example #20
0
        public void GenerateFunctionCall(ShaderFunction shaderFunction, IShaderIR selfOp, List <CSharpSyntaxNode> arguments)
        {
            var argumentOps = new List <IShaderIR>();

            argumentOps.Add(shaderFunction);
            if (!shaderFunction.IsStatic)
            {
                argumentOps.Add(selfOp);
            }

            for (var i = 0; i < arguments.Count; ++i)
            {
                var argument = arguments[i];
                var paramIR  = GetFunctionParameter(shaderFunction, i, argument);
                argumentOps.Add(paramIR);
            }

            var fnShaderReturnType = shaderFunction.GetReturnType();
            var functionCallOp     = mFrontEnd.CreateOp(mContext.mCurrentBlock, OpInstructionType.OpFunctionCall, fnShaderReturnType, argumentOps);

            mContext.Push(functionCallOp);
        }
Example #21
0
 public void GenerateLoopConditionBlock(SyntaxNode conditionalNode, ShaderBlock conditionBlock, ShaderBlock branchTrueBlock, ShaderBlock branchFalseBlock, FrontEndContext context)
 {
     // The condition builds the conditional and then jumps either to the body of the loop or to the end
     context.mCurrentBlock = conditionBlock;
     // If the conditional node exists
     if (conditionalNode != null)
     {
         //ExtractDebugInfo(conditionalNode->Condition, context->mDebugInfo);
         // Get the conditional value (must be a bool via how zilch works)
         IShaderIR conditional = WalkAndGetValueTypeResult(context.mCurrentBlock, conditionalNode);
         // Branch to either the true or false branch
         mFrontEnd.CreateOp(context.mCurrentBlock, OpInstructionType.OpBranchConditional, null, new List <IShaderIR> {
             conditional, branchTrueBlock, branchFalseBlock
         });
     }
     // Otherwise there is no conditional (e.g. loop) so unconditionally branch to the true block
     else
     {
         mFrontEnd.CreateOp(context.mCurrentBlock, OpInstructionType.OpBranch, null, new List <IShaderIR> {
             branchTrueBlock
         });
     }
 }
Example #22
0
        public ShaderOp GetOrGenerateValueTypeFromIR(ShaderBlock block, IShaderIR ir)
        {
            var op = ir as ShaderOp;

            if (op == null)
            {
                return(null);
            }

            var opResultType = GetOpResultType(op);

            if (opResultType.mBaseType != OpType.Pointer)
            {
                return(op);
            }

            var opValueType = GetValueType(opResultType);
            var valueOp     = CreateOp(block, OpInstructionType.OpLoad, opValueType, new List <IShaderIR> {
                op
            });

            return(valueOp);
        }
Example #23
0
        public override void VisitAssignmentExpression(AssignmentExpressionSyntax node)
        {
            // Always get the right IR but not always the left. In some cases with setters we don't need the left. This avoids loading the left twice.
            IShaderIR leftIR  = null;
            IShaderIR rightIR = WalkAndGetResult(node.Right);

            // If the token isn't the assignment op, then this must be a compound assignment (e.g. '+=').
            var token = node.OperatorToken.Text;

            if (token != "=")
            {
                // To do the compound we have to load the left now.
                leftIR = WalkAndGetResult(node.Left);
                var lhsType = GetSymbolType(node.Left);
                var rhsType = GetSymbolType(node.Right);

                // Generate the token for the binary op in the compound (just strip the '=' off) and then visit the binary expression.
                var binaryOp = token.Substring(0, token.Length - 1);
                VisitBinaryExpression(node, lhsType, leftIR, rhsType, rightIR, binaryOp);
                // Do whatever remaining logic for the assignment with the result of the binary expression.
                rightIR = mContext.Pop();
            }

            // If the left side is actually a setter, then we have to flip the assignment around to call the setter
            var leftSymbol = GetSymbol(node.Left);

            // One complicated case is if the left is actually a member access (e.g. Vec3.XY = rhs).
            // In this case, we need to call the setter on Vec3 (the expression of the member access)
            if (node.Left is MemberAccessExpressionSyntax memberAccessNode && leftSymbol.IsStatic == false)
            {
                FunctionKey functionKey = null;
                // Try and get the function key for this symbol depending on if it's a field, property, etc...
                if (leftSymbol is IPropertySymbol propertySymbol && !propertySymbol.IsReadOnly)
                {
                    functionKey = new FunctionKey(propertySymbol.SetMethod);
                }
Example #24
0
 public void AddIRForSymbol(ISymbol symbol, IShaderIR ir)
 {
     mContext.mSymbolToIRMap.Add(symbol, ir);
 }
Example #25
0
 public override void Visit(IShaderIR shaderIR)
 {
     GetId(shaderIR);
     base.Visit(shaderIR);
 }
Example #26
0
 public void GenerateFunctionCall(ShaderFunction shaderFunction, IShaderIR selfOp, List <IShaderIR> arguments)
 {
     mFrontEnd.GenerateFunctionCall(shaderFunction, selfOp, arguments, mContext);
 }
Example #27
0
 public IShaderIR GetFunctionParameter(ShaderFunction shaderFunction, int paramIndex, IShaderIR argumentOp)
 {
     return(mFrontEnd.GetFunctionParameter(shaderFunction, paramIndex, argumentOp, mContext));
 }
Example #28
0
 public void ExtractDebugInfo(IShaderIR ir, ISymbol symbol, SyntaxNode node)
 {
     ir.DebugInfo.Name     = symbol.Name;
     ir.DebugInfo.Location = node.GetLocation();
 }
Example #29
0
        public static void ResolveVectorSwizzleSetter(FrontEndTranslator translator, FrontEndContext context, AttributeData attribute, ISymbol returnType, IShaderIR selfInstance, IShaderIR rhsIR)
        {
            var swizzleElements = attribute.ConstructorArguments[0].Values;
            var selfValue       = translator.GetOrGenerateValueTypeFromIR(context.mCurrentBlock, selfInstance);
            var selfValueType   = selfValue.mResultType.GetDereferenceType();
            var componentCount  = (UInt32)(selfValueType.mParameters[1] as ShaderConstantLiteral).mValue;

            var rhs = translator.GetOrGenerateValueTypeFromIR(context.mCurrentBlock, rhsIR);

            // If we're setting just a single element, then do an access chain and to set that element
            if (swizzleElements.Length == 1)
            {
                // Find what element we're setting
                var constantLiteral     = translator.CreateConstantLiteral((UInt32)swizzleElements[0].Value);
                var memberIndexConstant = translator.CreateConstantOp(translator.FindType(typeof(uint)), constantLiteral);
                // Lookup the result type
                var resultType = translator.mCurrentLibrary.FindType(new TypeKey(returnType));
                resultType = resultType.FindPointerType(selfValue.mResultType.mStorageClass);
                // Build the access chain to the element
                var memberVariableOp = translator.CreateOp(context.mCurrentBlock, OpInstructionType.OpAccessChain, resultType, new List <IShaderIR> {
                    selfInstance, memberIndexConstant
                });

                // Then set this back to the lhs side
                translator.CreateStoreOp(context.mCurrentBlock, memberVariableOp, rhs);
            }
            // Otherwise construct a new vector and set it over
            else
            {
                var swizzleArgs = new List <IShaderIR>()
                {
                    selfValue, rhs
                };

                // Build up a set of what element indices were in the swizzle
                var elementSet = new HashSet <UInt32>();
                foreach (var element in swizzleElements)
                {
                    elementSet.Add((UInt32)element.Value);
                }

                // Foreach element in the new vector, choose if we take it from the rhs or the lhs. If the element index is in the swizzle ops,
                // then take the next element from rhs, otherwise take the same index from lhs.
                var rhsElementIndex = 0u;
                for (uint element = 0; element < componentCount; ++element)
                {
                    if (elementSet.Contains(element))
                    {
                        swizzleArgs.Add(translator.CreateConstantLiteral(componentCount + rhsElementIndex));
                        ++rhsElementIndex;
                    }
                    else
                    {
                        swizzleArgs.Add(translator.CreateConstantLiteral(element));
                    }
                }
                // To build the setter, first create the new vector from components in the lhs/rhs as appropriate.
                var op = translator.CreateOp(context.mCurrentBlock, OpInstructionType.OpVectorShuffle, selfValueType, swizzleArgs);
                // Then set this back to the lhs side
                translator.CreateStoreOp(context.mCurrentBlock, selfInstance, op);
            }
        }
Example #30
0
 public void ExtractDebugInfo(IShaderIR ir, SyntaxNode node)
 {
     ir.DebugInfo.Location = node.GetLocation();
 }