예제 #1
0
 void WriteBlockInstructions(ShaderBlock block, List <IShaderIR> instructions)
 {
     foreach (var ir in instructions)
     {
         WriteIR(ir);
     }
 }
예제 #2
0
 public virtual void Visit(ShaderBlock shaderBlock)
 {
     foreach (var ir in shaderBlock.mOps)
     {
         Visit(ir);
     }
 }
예제 #3
0
        public ShaderBlock CreateBlock(string debugBlockName)
        {
            var block = new ShaderBlock();

            block.DebugInfo.Name = debugBlockName;
            return(block);
        }
예제 #4
0
        public ShaderOp CreateOp(ShaderBlock block, OpInstructionType opType, ShaderType resultType, List <IShaderIR> arguments)
        {
            var resultOp = CreateOp(opType, resultType, arguments);

            block.mOps.Add(resultOp);
            return(resultOp);
        }
예제 #5
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
            }));
        }
        public void VisitMethod(CSharpSyntaxNode node, ShaderFunction shaderFunction)
        {
            var fnSymbol = mFrontEnd.mSemanticModel.GetDeclaredSymbol(node) as IMethodSymbol;

            // Handle intrinsics. If we have a resolver for a special handler then call that and return.
            if (SpecialResolvers.TryProcessIntrinsicMethod(mFrontEnd, fnSymbol))
            {
                return;
            }

            // Add the current function as the active one and the parameter
            mContext.mCurrentFunction = shaderFunction;

            // Start writing out the parameters (so the parameter block is the active one)
            mContext.mCurrentBlock = shaderFunction.mParametersBlock;
            // Add the 'this' op if it exists
            if (!fnSymbol.IsStatic)
            {
                var selfType = mContext.mCurrentType;
                var thisType = selfType.FindPointerType(StorageClass.Function);
                var selfOp   = CreateOp(mContext.mCurrentBlock, OpInstructionType.OpFunctionParameter, thisType, null);
                selfOp.DebugInfo.Name = "self";
                mContext.mThisOp      = selfOp;
            }
            // Add the function parameter ops
            foreach (var parameter in fnSymbol.Parameters)
            {
                var parameterType = FindParameterType(mFrontEnd.mCurrentLibrary.FindType(new TypeKey(parameter.Type)), parameter);
                var paramOp       = CreateOp(mContext.mCurrentBlock, OpInstructionType.OpFunctionParameter, parameterType, null);

                // Extract the debug info. We can't get this from the node because the node isn't always a method with arguments.
                // // If this is a get/set then the arguments are implicit and there's no location to look at.
                if (parameter.Locations != null && parameter.Locations.Length != 0)
                {
                    paramOp.DebugInfo.Location = parameter.Locations[0];
                }
                paramOp.DebugInfo.Name = parameter.Name;

                // Also map parameter symbols in this scope to their ops so we can look them up later when visiting identifiers
                mContext.mSymbolToIRMap.Add(parameter, paramOp);
            }

            // Now set the body as the current scope and visit the function
            var firstBlock = new ShaderBlock();

            shaderFunction.mBlocks.Add(firstBlock);
            mContext.mCurrentBlock = firstBlock;
            mCommonPass.Visit(node);
            // SpirV has some special rules about returns. Make sure to address these by fixing up missing terminators or removing extra functions.
            mFrontEnd.FixupBlockTerminators(shaderFunction);

            // Clear the function out of the current context
            mContext.mThisOp          = null;
            mContext.mCurrentBlock    = null;
            mContext.mCurrentFunction = null;
        }
예제 #7
0
 void WriteDebugInstructions(ShaderBlock block)
 {
     WriteDebugName(block, block.DebugInfo.Name);
     foreach (var op in block.mLocalVariables)
     {
         WriteDebugName(op, op.DebugInfo.Name);
     }
     foreach (var op in block.mOps)
     {
         WriteDebugName(op, op.DebugInfo.Name);
     }
 }
예제 #8
0
 void GenerateIds(ShaderBlock block)
 {
     GetId(block);
     foreach (var op in block.mLocalVariables)
     {
         GenerateIds(op);
     }
     foreach (var op in block.mOps)
     {
         GenerateIds(op);
     }
 }
예제 #9
0
        public void GenerateLoopHeaderBlock(ShaderBlock headerBlock, ShaderBlock branchTarget, ShaderBlock mergeBlock, ShaderBlock continueBlock, FrontEndContext context)
        {
            // Mark the header block as a loop block (so we emit the LoopMerge instruction)
            headerBlock.mBlockType = BlockType.Loop;
            // Being a LoopMerge requires setting the merge and continue points
            headerBlock.mMergePoint    = mergeBlock;
            headerBlock.mContinuePoint = continueBlock;

            var loopControlMask = mFrontEnd.CreateConstantLiteral <uint>((uint)Spv.LoopControlMask.LoopControlMaskNone);

            mFrontEnd.CreateOp(headerBlock, OpInstructionType.OpLoopMerge, null, new List <IShaderIR> {
                mergeBlock, continueBlock, loopControlMask
            });
            // The header always jumps to the branch target (typically a continue)
            mFrontEnd.CreateOp(headerBlock, OpInstructionType.OpBranch, null, new List <IShaderIR> {
                branchTarget
            });
        }
예제 #10
0
        public void GenerateLoopStatements(StatementSyntax loopScopeNode, ShaderBlock loopBlock, ShaderBlock mergeBlock, ShaderBlock continueBlock, FrontEndContext context)
        {
            context.mCurrentBlock = loopBlock;
            // Set the continue and merge points for this block (mainly needed for nested loops)
            loopBlock.mContinuePoint = continueBlock;
            loopBlock.mMergePoint    = mergeBlock;
            context.PushMergePoint(continueBlock, mergeBlock);

            // Iterate over all of the statements in the loop body
            Visit(loopScopeNode);

            // Write out a jump back to the continue block of the loop. Only write this to the active block
            // which will either be the end of the loop block or something like an after if
            if (context.mCurrentBlock.mTerminatorOp == null)
            {
                var currentBlockContinue = mFrontEnd.CreateOp(context.mCurrentBlock, OpInstructionType.OpBranch, null, new List <IShaderIR> {
                    continueBlock
                });
            }
            context.PopMergePoint();
        }
예제 #11
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);
        }
예제 #12
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
         });
     }
 }
예제 #13
0
        public IShaderIR WalkAndGetValueTypeResult(ShaderBlock block, SyntaxNode node)
        {
            var ir = WalkAndGetResult(node);

            return(mFrontEnd.GetOrGenerateValueTypeFromIR(block, ir));
        }
예제 #14
0
 public ShaderOp CreateOp(ShaderBlock block, OpInstructionType opType, ShaderType resultType, List <IShaderIR> arguments)
 {
     return(mFrontEnd.CreateOp(block, opType, resultType, arguments));
 }
예제 #15
0
 void WriteBlock(ShaderBlock block)
 {
     mWriter.WriteInstruction(2, Spv.Op.OpLabel, GetId(block));
     WriteBlockInstructions(block, block.mLocalVariables);
     WriteBlockInstructions(block, block.mOps);
 }
예제 #16
0
        public static void AddDecorationBlock(FrontEndTranslator translator, ShaderType shaderType, ShaderBlock decorationsBlock)
        {
            var decorationBlockLiteral = translator.CreateConstantLiteral((int)Spv.Decoration.DecorationBlock);

            translator.CreateOp(decorationsBlock, OpInstructionType.OpDecorate, null, new List <IShaderIR>()
            {
                shaderType, decorationBlockLiteral
            });
        }
예제 #17
0
        public static void AddDecorationLocations(FrontEndTranslator translator, ShaderType shaderType, ShaderInterfaceSet interfaceSet, LocationCallback locationCallback, ShaderBlock decorationsBlock)
        {
            int GetNextLocation(Dictionary <int, ShaderInterfaceField> usedLocations, int currLocation)
            {
                while (usedLocations.ContainsKey(currLocation))
                {
                    ++currLocation;
                }
                return(currLocation);
            };
            var usedLocations = new Dictionary <int, ShaderInterfaceField>();
            List <(ShaderInterfaceField Field, ShaderOp FieldOp)> unknownLocationFields = new List <(ShaderInterfaceField Field, ShaderOp FieldOp)>();

            foreach (var field in interfaceSet)
            {
                var fieldOp = interfaceSet.GetFieldInstance(translator, field, null);

                int location  = -1;
                int component = -1;
                locationCallback(field.ShaderField, out location, out component);
                if (location != -1)
                {
                    Decorations.AddDecorationLocation(translator, fieldOp, location, decorationsBlock);
                    usedLocations.Add(location, field);
                    if (component != -1)
                    {
                        Decorations.AddDecorationComponent(translator, fieldOp, location, decorationsBlock);
                    }
                }
                else
                {
                    unknownLocationFields.Add((field, fieldOp));
                }
            }

            var nextLocation = 0;

            foreach (var pair in unknownLocationFields)
            {
                nextLocation = GetNextLocation(usedLocations, nextLocation);
                Decorations.AddDecorationLocation(translator, pair.FieldOp, nextLocation, decorationsBlock);
                usedLocations.Add(nextLocation, pair.Field);
            }
        }
예제 #18
0
        public static void AddDecorationMemberMatrixMajor(FrontEndTranslator translator, ShaderType shaderType, int fieldIndex, Spv.Decoration decoration, ShaderBlock decorationsBlock)
        {
            var decorationOffsetLiteral = translator.CreateConstantLiteral((int)decoration);
            var fieldIndexLiteral       = translator.CreateConstantLiteral(fieldIndex);

            translator.CreateOp(decorationsBlock, OpInstructionType.OpMemberDecorate, null, new List <IShaderIR>()
            {
                shaderType, fieldIndexLiteral, decorationOffsetLiteral
            });
        }
예제 #19
0
        public static void AddDecorationBuiltIn(FrontEndTranslator translator, ShaderOp instanceOp, Spv.BuiltIn builtInType, ShaderBlock decorationsBlock)
        {
            var decorationBuiltInLiteral = translator.CreateConstantLiteral((int)Spv.Decoration.DecorationBuiltIn);
            var builtInTypeLiteral       = translator.CreateConstantLiteral((int)builtInType);

            translator.CreateOp(decorationsBlock, OpInstructionType.OpDecorate, null, new List <IShaderIR>()
            {
                instanceOp, decorationBuiltInLiteral, builtInTypeLiteral
            });
        }
예제 #20
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
            });
        }
예제 #21
0
 public static void DecorateMatrixMajor(FrontEndTranslator translator, ShaderType shaderType, ShaderBlock decorationsBlock)
 {
     for (var fieldIndex = 0; fieldIndex < shaderType.mFields.Count; ++fieldIndex)
     {
         var field     = shaderType.mFields[fieldIndex];
         var fieldType = field.mType;
         // Recursively decorate structs
         if (fieldType.mBaseType == OpType.Struct)
         {
             DecorateMatrixMajor(translator, fieldType, decorationsBlock);
         }
         else if (fieldType.mBaseType == OpType.Matrix)
         {
             AddDecorationMemberColMajor(translator, shaderType, fieldIndex, decorationsBlock);
         }
     }
 }
예제 #22
0
 public override void Visit(ShaderBlock shaderblock)
 {
     GetId(shaderblock);
     base.Visit(shaderblock);
 }
예제 #23
0
 public void GenerateLoopContinueBlock(IEnumerable <SyntaxNode> iteratorNodes, ShaderBlock continueBlock, ShaderBlock headerBlock, FrontEndContext context)
 {
     // Mark the continue block as the active block
     context.mCurrentBlock = continueBlock;
     // If it exists, walk the iterator statement
     if (iteratorNodes != null)
     {
         foreach (var iteratorNode in iteratorNodes)
         {
             Visit(iteratorNode);
         }
     }
     // Always jump back to the header block
     mFrontEnd.CreateOp(continueBlock, OpInstructionType.OpBranch, null, new List <IShaderIR> {
         headerBlock
     });
 }
예제 #24
0
        public static void DecorateUniforms(FrontEndTranslator translator, ShaderOp instanceOp, ShaderBlock decorationsBlock)
        {
            var instanceType = instanceOp.mResultType.GetDereferenceType();

            AddDecorationDescriptorSet(translator, instanceType, 0, decorationsBlock);
            AddDecorationBinding(translator, instanceType, 0, decorationsBlock);
            AddDecorationBlock(translator, instanceType, decorationsBlock);
            DecorateOffsets(translator, instanceType, decorationsBlock);
        }
예제 #25
0
 public static void AddDecorationMemberColMajor(FrontEndTranslator translator, ShaderType shaderType, int fieldIndex, ShaderBlock decorationsBlock)
 {
     AddDecorationMemberMatrixMajor(translator, shaderType, fieldIndex, Spv.Decoration.DecorationColMajor, decorationsBlock);
 }
예제 #26
0
        public static void AddDecorationLocation(FrontEndTranslator translator, ShaderOp instanceOp, int location, ShaderBlock decorationsBlock)
        {
            var decorationLocationLiteral = translator.CreateConstantLiteral((int)Spv.Decoration.DecorationLocation);
            var locationLiteral           = translator.CreateConstantLiteral(location);

            translator.CreateOp(decorationsBlock, OpInstructionType.OpDecorate, null, new List <IShaderIR>()
            {
                instanceOp, decorationLocationLiteral, locationLiteral
            });
        }
예제 #27
0
        public static void DecorateOffsets(FrontEndTranslator translator, ShaderType shaderType, ShaderBlock decorationsBlock)
        {
            UInt32 currentByteOffset = 0;

            for (var fieldIndex = 0; fieldIndex < shaderType.mFields.Count; ++fieldIndex)
            {
                var field     = shaderType.mFields[fieldIndex];
                var fieldType = field.mType;
                // Recursively decorate structs
                if (fieldType.mBaseType == OpType.Struct)
                {
                    DecorateOffsets(translator, fieldType, decorationsBlock);
                }

                var requiredAlignment = fieldType.ComputeByteAlignment();
                var byteSize          = fieldType.ComputeByteSize();
                currentByteOffset = ShaderType.ComputeSizeAfterAlignment(currentByteOffset, requiredAlignment);
                AddDecorationMemberOffset(translator, shaderType, fieldIndex, currentByteOffset, decorationsBlock);

                currentByteOffset += byteSize;
            }
        }
예제 #28
0
        public static void GenerateHardwareBuiltIns(FrontEndTranslator translator, ShaderInterfaceSet interfaceSet, StorageClass storageClass, ShaderBlock declarationBlock, ShaderBlock decorationsBlock)
        {
            foreach (var builtInInterfaceField in interfaceSet)
            {
                var pointerType     = translator.FindOrCreatePointerType(builtInInterfaceField.ShaderField.mType, storageClass);
                var fieldInstanceOp = translator.CreateOp(OpInstructionType.OpVariable, pointerType, null);
                declarationBlock.mLocalVariables.Add(fieldInstanceOp);

                Decorations.AddDecorationBuiltIn(translator, fieldInstanceOp, builtInInterfaceField.BuiltInType, decorationsBlock);

                ShaderInterfaceField.InstanceAccessDelegate fieldInstanceGetFunction = (FrontEndTranslator translator, ShaderInterfaceField interfaceField, FrontEndContext context) =>
                {
                    return(fieldInstanceOp);
                };
                builtInInterfaceField.GetInstance = fieldInstanceGetFunction;
            }
        }
예제 #29
0
 public void Visit(ShaderBlock block)
 {
     Visit(block.mLocalVariables);
     Visit(block.mOps);
 }
예제 #30
0
 public static void DecorateStrides(FrontEndTranslator translator, ShaderType shaderType, ShaderBlock decorationsBlock)
 {
     for (var fieldIndex = 0; fieldIndex < shaderType.mFields.Count; ++fieldIndex)
     {
         var field     = shaderType.mFields[fieldIndex];
         var fieldType = field.mType;
         // Recursively decorate structs
         if (fieldType.mBaseType == OpType.Struct)
         {
             DecorateStrides(translator, fieldType, decorationsBlock);
         }
         else if (fieldType.mBaseType == OpType.Matrix)
         {
             // Hardcode stride to size of a vec4 for performance reasons.
             // @JoshD: Maybe make a packing option for this later?
             int matrixStride = 16;
             AddDecorationMemberMatrixStride(translator, shaderType, fieldIndex, matrixStride, decorationsBlock);
         }
     }
 }