예제 #1
0
        private static SpvInstruction ApplyScaling2DArray(CodeGenContext context, SpvInstruction vector, int index)
        {
            // The array index is not scaled, just x and y.
            var vectorXY       = context.VectorShuffle(context.TypeVector(context.TypeS32(), 2), vector, vector, 0, 1);
            var vectorZ        = context.CompositeExtract(context.TypeS32(), vector, 2);
            var vectorXYScaled = ApplyScaling2D(context, vectorXY, index);
            var vectorScaled   = context.CompositeConstruct(context.TypeVector(context.TypeS32(), 3), vectorXYScaled, vectorZ);

            return(vectorScaled);
        }
예제 #2
0
        public static SpvInstruction ApplyUnscaling(
            CodeGenContext context,
            AstTextureOperation texOp,
            SpvInstruction size,
            bool isBindless,
            bool isIndexed)
        {
            if (context.Config.Stage.SupportsRenderScale() &&
                !isBindless &&
                !isIndexed)
            {
                int index = context.Config.FindTextureDescriptorIndex(texOp);

                var pointerType = context.TypePointer(StorageClass.Uniform, context.TypeFP32());
                var fieldIndex  = context.Constant(context.TypeU32(), 4);
                var scaleIndex  = context.Constant(context.TypeU32(), index);

                if (context.Config.Stage == ShaderStage.Vertex)
                {
                    var scaleCountPointerType = context.TypePointer(StorageClass.Uniform, context.TypeS32());
                    var scaleCountElemPointer = context.AccessChain(scaleCountPointerType, context.SupportBuffer, context.Constant(context.TypeU32(), 3));
                    var scaleCount            = context.Load(context.TypeS32(), scaleCountElemPointer);

                    scaleIndex = context.IAdd(context.TypeU32(), scaleIndex, scaleCount);
                }

                scaleIndex = context.IAdd(context.TypeU32(), scaleIndex, context.Constant(context.TypeU32(), 1));

                var scaleElemPointer = context.AccessChain(pointerType, context.SupportBuffer, fieldIndex, scaleIndex);
                var scale            = context.GlslFAbs(context.TypeFP32(), context.Load(context.TypeFP32(), scaleElemPointer));

                var passthrough = context.FOrdEqual(context.TypeBool(), scale, context.Constant(context.TypeFP32(), 1f));

                var sizeFloat       = context.ConvertSToF(context.TypeFP32(), size);
                var sizeUnscaled    = context.FDiv(context.TypeFP32(), sizeFloat, scale);
                var sizeUnscaledInt = context.ConvertFToS(context.TypeS32(), sizeUnscaled);

                return(context.Select(context.TypeS32(), passthrough, size, sizeUnscaledInt));
            }

            return(size);
        }
예제 #3
0
        private static void ApplyScalingNoInterpolation(CodeGenContext context, SpvInstruction output, SpvInstruction vector, SpvInstruction scale)
        {
            if (context.Config.Stage == ShaderStage.Vertex)
            {
                scale = context.GlslFAbs(context.TypeFP32(), scale);
            }

            var vector2Type = context.TypeVector(context.TypeFP32(), 2);

            var vectorFloat  = context.ConvertSToF(vector2Type, vector);
            var vectorScaled = context.VectorTimesScalar(vector2Type, vectorFloat, scale);

            context.Store(output, context.ConvertFToS(context.TypeVector(context.TypeS32(), 2), vectorScaled));
        }
예제 #4
0
        public static void DeclareLocals(CodeGenContext context, StructuredFunction function)
        {
            foreach (AstOperand local in function.Locals)
            {
                var localPointerType = context.TypePointer(StorageClass.Function, context.GetType(local.VarType.Convert()));
                var spvLocal         = context.Variable(localPointerType, StorageClass.Function);

                context.AddLocalVariable(spvLocal);
                context.DeclareLocal(local, spvLocal);
            }

            var ivector2Type         = context.TypeVector(context.TypeS32(), 2);
            var coordTempPointerType = context.TypePointer(StorageClass.Function, ivector2Type);
            var coordTemp            = context.Variable(coordTempPointerType, StorageClass.Function);

            context.AddLocalVariable(coordTemp);
            context.CoordTemp = coordTemp;
        }
예제 #5
0
        private static void ApplyScalingInterpolated(CodeGenContext context, SpvInstruction output, SpvInstruction vector, SpvInstruction scale)
        {
            var vector2Type = context.TypeVector(context.TypeFP32(), 2);

            var scaleNegated = context.FNegate(context.TypeFP32(), scale);
            var scaleVector  = context.CompositeConstruct(vector2Type, scaleNegated, scaleNegated);

            var vectorFloat  = context.ConvertSToF(vector2Type, vector);
            var vectorScaled = context.VectorTimesScalar(vector2Type, vectorFloat, scaleNegated);

            var fragCoordPointer = context.Inputs[AttributeConsts.PositionX];
            var fragCoord        = context.Load(context.TypeVector(context.TypeFP32(), 4), fragCoordPointer);
            var fragCoordXY      = context.VectorShuffle(vector2Type, fragCoord, fragCoord, 0, 1);

            var scaleMod           = context.FMod(vector2Type, fragCoordXY, scaleVector);
            var vectorInterpolated = context.FAdd(vector2Type, vectorScaled, scaleMod);

            context.Store(output, context.ConvertFToS(context.TypeVector(context.TypeS32(), 2), vectorInterpolated));
        }
예제 #6
0
        private static void DeclareSupportBuffer(CodeGenContext context)
        {
            if (!context.Config.Stage.SupportsRenderScale() && !(context.Config.LastInVertexPipeline && context.Config.GpuAccessor.QueryViewportTransformDisable()))
            {
                return;
            }

            var isBgraArrayType           = context.TypeArray(context.TypeU32(), context.Constant(context.TypeU32(), SupportBuffer.FragmentIsBgraCount));
            var viewportInverseVectorType = context.TypeVector(context.TypeFP32(), 4);
            var renderScaleArrayType      = context.TypeArray(context.TypeFP32(), context.Constant(context.TypeU32(), SupportBuffer.RenderScaleMaxCount));

            context.Decorate(isBgraArrayType, Decoration.ArrayStride, (LiteralInteger)SupportBuffer.FieldSize);
            context.Decorate(renderScaleArrayType, Decoration.ArrayStride, (LiteralInteger)SupportBuffer.FieldSize);

            var supportBufferStructType = context.TypeStruct(false, context.TypeU32(), isBgraArrayType, viewportInverseVectorType, context.TypeS32(), renderScaleArrayType);

            context.MemberDecorate(supportBufferStructType, 0, Decoration.Offset, (LiteralInteger)SupportBuffer.FragmentAlphaTestOffset);
            context.MemberDecorate(supportBufferStructType, 1, Decoration.Offset, (LiteralInteger)SupportBuffer.FragmentIsBgraOffset);
            context.MemberDecorate(supportBufferStructType, 2, Decoration.Offset, (LiteralInteger)SupportBuffer.ViewportInverseOffset);
            context.MemberDecorate(supportBufferStructType, 3, Decoration.Offset, (LiteralInteger)SupportBuffer.FragmentRenderScaleCountOffset);
            context.MemberDecorate(supportBufferStructType, 4, Decoration.Offset, (LiteralInteger)SupportBuffer.GraphicsRenderScaleOffset);
            context.Decorate(supportBufferStructType, Decoration.Block);

            var supportBufferPointerType = context.TypePointer(StorageClass.Uniform, supportBufferStructType);
            var supportBufferVariable    = context.Variable(supportBufferPointerType, StorageClass.Uniform);

            context.Decorate(supportBufferVariable, Decoration.DescriptorSet, (LiteralInteger)0);
            context.Decorate(supportBufferVariable, Decoration.Binding, (LiteralInteger)0);

            context.AddGlobalVariable(supportBufferVariable);

            context.SupportBuffer = supportBufferVariable;
        }
예제 #7
0
        private static SpvInstruction ApplyScaling2D(CodeGenContext context, SpvInstruction vector, int index)
        {
            var pointerType = context.TypePointer(StorageClass.Uniform, context.TypeFP32());
            var fieldIndex  = context.Constant(context.TypeU32(), 4);
            var scaleIndex  = context.Constant(context.TypeU32(), index);

            if (context.Config.Stage == ShaderStage.Vertex)
            {
                var scaleCountPointerType = context.TypePointer(StorageClass.Uniform, context.TypeS32());
                var scaleCountElemPointer = context.AccessChain(scaleCountPointerType, context.SupportBuffer, context.Constant(context.TypeU32(), 3));
                var scaleCount            = context.Load(context.TypeS32(), scaleCountElemPointer);

                scaleIndex = context.IAdd(context.TypeU32(), scaleIndex, scaleCount);
            }

            scaleIndex = context.IAdd(context.TypeU32(), scaleIndex, context.Constant(context.TypeU32(), 1));

            var scaleElemPointer = context.AccessChain(pointerType, context.SupportBuffer, fieldIndex, scaleIndex);
            var scale            = context.Load(context.TypeFP32(), scaleElemPointer);

            var ivector2Type = context.TypeVector(context.TypeS32(), 2);
            var localVector  = context.CoordTemp;

            var passthrough = context.FOrdEqual(context.TypeBool(), scale, context.Constant(context.TypeFP32(), 1f));

            var mergeLabel = context.Label();

            if (context.Config.Stage == ShaderStage.Fragment)
            {
                var scaledInterpolatedLabel    = context.Label();
                var scaledNoInterpolationLabel = context.Label();

                var needsInterpolation = context.FOrdLessThan(context.TypeBool(), scale, context.Constant(context.TypeFP32(), 0f));

                context.SelectionMerge(mergeLabel, SelectionControlMask.MaskNone);
                context.BranchConditional(needsInterpolation, scaledInterpolatedLabel, scaledNoInterpolationLabel);

                // scale < 0.0
                context.AddLabel(scaledInterpolatedLabel);

                ApplyScalingInterpolated(context, localVector, vector, scale);
                context.Branch(mergeLabel);

                // scale >= 0.0
                context.AddLabel(scaledNoInterpolationLabel);

                ApplyScalingNoInterpolation(context, localVector, vector, scale);
                context.Branch(mergeLabel);

                context.AddLabel(mergeLabel);

                var passthroughLabel = context.Label();
                var finalMergeLabel  = context.Label();

                context.SelectionMerge(finalMergeLabel, SelectionControlMask.MaskNone);
                context.BranchConditional(passthrough, passthroughLabel, finalMergeLabel);

                context.AddLabel(passthroughLabel);

                context.Store(localVector, vector);
                context.Branch(finalMergeLabel);

                context.AddLabel(finalMergeLabel);

                return(context.Load(ivector2Type, localVector));
            }
            else
            {
                var passthroughLabel = context.Label();
                var scaledLabel      = context.Label();

                context.SelectionMerge(mergeLabel, SelectionControlMask.MaskNone);
                context.BranchConditional(passthrough, passthroughLabel, scaledLabel);

                // scale == 1.0
                context.AddLabel(passthroughLabel);

                context.Store(localVector, vector);
                context.Branch(mergeLabel);

                // scale != 1.0
                context.AddLabel(scaledLabel);

                ApplyScalingNoInterpolation(context, localVector, vector, scale);
                context.Branch(mergeLabel);

                context.AddLabel(mergeLabel);

                return(context.Load(ivector2Type, localVector));
            }
        }