Example #1
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);
        }
Example #2
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));
            }
        }