public static byte[] Generate(StructuredProgramInfo info, ShaderConfig config) { CodeGenContext context = new CodeGenContext(config); context.AddCapability(Capability.GroupNonUniformBallot); context.AddCapability(Capability.ImageBuffer); context.AddCapability(Capability.SampledBuffer); context.AddCapability(Capability.SubgroupBallotKHR); context.AddCapability(Capability.SubgroupVoteKHR); context.AddExtension("SPV_KHR_shader_ballot"); context.AddExtension("SPV_KHR_subgroup_vote"); Declarations.DeclareAll(context, info); if ((info.HelperFunctionsMask & NeedsInvocationIdMask) != 0) { Declarations.DeclareInvocationId(context); } for (int funcIndex = 0; funcIndex < info.Functions.Count; funcIndex++) { var function = info.Functions[funcIndex]; var retType = context.GetType(function.ReturnType.Convert()); var funcArgs = new SpvInstruction[function.InArguments.Length + function.OutArguments.Length]; for (int argIndex = 0; argIndex < funcArgs.Length; argIndex++) { var argType = context.GetType(function.GetArgumentType(argIndex).Convert()); var argPointerType = context.TypePointer(StorageClass.Function, argType); funcArgs[argIndex] = argPointerType; } var funcType = context.TypeFunction(retType, false, funcArgs); var spvFunc = context.Function(retType, FunctionControlMask.MaskNone, funcType); context.DeclareFunction(funcIndex, function, spvFunc); } for (int funcIndex = 0; funcIndex < info.Functions.Count; funcIndex++) { Generate(context, info, funcIndex); } return(context.Generate()); }
private static void DeclareParameters(CodeGenContext context, IEnumerable <VariableType> argTypes, int argIndex) { foreach (var argType in argTypes) { var argPointerType = context.TypePointer(StorageClass.Function, context.GetType(argType.Convert())); var spvArg = context.FunctionParameter(argPointerType); context.DeclareArgument(argIndex++, spvArg); } }
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); } }
private static void DeclareImages(CodeGenContext context, TextureDescriptor[] descriptors) { foreach (var descriptor in descriptors) { var meta = new TextureMeta(descriptor.CbufSlot, descriptor.HandleIndex, descriptor.Format); if (context.Images.ContainsKey(meta)) { continue; } int setIndex = context.Config.Options.TargetApi == TargetApi.Vulkan ? 3 : 0; var dim = GetDim(descriptor.Type); var imageType = context.TypeImage( context.GetType(meta.Format.GetComponentType().Convert()), dim, descriptor.Type.HasFlag(SamplerType.Shadow), descriptor.Type.HasFlag(SamplerType.Array), descriptor.Type.HasFlag(SamplerType.Multisample), AccessQualifier.ReadWrite, GetImageFormat(meta.Format)); var nameSuffix = meta.CbufSlot < 0 ? $"_tcb_{meta.Handle:X}_{meta.Format.ToGlslFormat()}" : $"_cb{meta.CbufSlot}_{meta.Handle:X}_{meta.Format.ToGlslFormat()}"; var imagePointerType = context.TypePointer(StorageClass.UniformConstant, imageType); var imageVariable = context.Variable(imagePointerType, StorageClass.UniformConstant); context.Images.Add(meta, (imageType, imageVariable)); context.Name(imageVariable, $"{GetStagePrefix(context.Config.Stage)}_img{nameSuffix}"); context.Decorate(imageVariable, Decoration.DescriptorSet, (LiteralInteger)setIndex); context.Decorate(imageVariable, Decoration.Binding, (LiteralInteger)descriptor.Binding); if (descriptor.Flags.HasFlag(TextureUsageFlags.ImageCoherent)) { context.Decorate(imageVariable, Decoration.Coherent); } context.AddGlobalVariable(imageVariable); } }
public static void DeclareLocalForArgs(CodeGenContext context, List <StructuredFunction> functions) { for (int funcIndex = 0; funcIndex < functions.Count; funcIndex++) { StructuredFunction function = functions[funcIndex]; SpvInstruction[] locals = new SpvInstruction[function.InArguments.Length]; for (int i = 0; i < function.InArguments.Length; i++) { var type = function.GetArgumentType(i).Convert(); var localPointerType = context.TypePointer(StorageClass.Function, context.GetType(type)); var spvLocal = context.Variable(localPointerType, StorageClass.Function); context.AddLocalVariable(spvLocal); locals[i] = spvLocal; } context.DeclareLocalForArgs(funcIndex, locals); } }
public static byte[] Generate(StructuredProgramInfo info, ShaderConfig config) { SpvInstructionPool instPool; SpvLiteralIntegerPool integerPool; lock (PoolLock) { instPool = InstructionPool.Allocate(); integerPool = IntegerPool.Allocate(); } CodeGenContext context = new CodeGenContext(info, config, instPool, integerPool); context.AddCapability(Capability.GroupNonUniformBallot); context.AddCapability(Capability.ImageBuffer); context.AddCapability(Capability.ImageGatherExtended); context.AddCapability(Capability.ImageQuery); context.AddCapability(Capability.SampledBuffer); context.AddCapability(Capability.SubgroupBallotKHR); context.AddCapability(Capability.SubgroupVoteKHR); if (config.TransformFeedbackEnabled && config.LastInVertexPipeline) { context.AddCapability(Capability.TransformFeedback); } if (config.Stage == ShaderStage.Fragment && context.Config.GpuAccessor.QueryHostSupportsFragmentShaderInterlock()) { context.AddCapability(Capability.FragmentShaderPixelInterlockEXT); context.AddExtension("SPV_EXT_fragment_shader_interlock"); } else if (config.Stage == ShaderStage.Geometry) { context.AddCapability(Capability.Geometry); if (config.GpPassthrough && context.Config.GpuAccessor.QueryHostSupportsGeometryShaderPassthrough()) { context.AddExtension("SPV_NV_geometry_shader_passthrough"); context.AddCapability(Capability.GeometryShaderPassthroughNV); } } else if (config.Stage == ShaderStage.TessellationControl || config.Stage == ShaderStage.TessellationEvaluation) { context.AddCapability(Capability.Tessellation); } context.AddExtension("SPV_KHR_shader_ballot"); context.AddExtension("SPV_KHR_subgroup_vote"); Declarations.DeclareAll(context, info); if ((info.HelperFunctionsMask & NeedsInvocationIdMask) != 0) { Declarations.DeclareInvocationId(context); } for (int funcIndex = 0; funcIndex < info.Functions.Count; funcIndex++) { var function = info.Functions[funcIndex]; var retType = context.GetType(function.ReturnType.Convert()); var funcArgs = new SpvInstruction[function.InArguments.Length + function.OutArguments.Length]; for (int argIndex = 0; argIndex < funcArgs.Length; argIndex++) { var argType = context.GetType(function.GetArgumentType(argIndex).Convert()); var argPointerType = context.TypePointer(StorageClass.Function, argType); funcArgs[argIndex] = argPointerType; } var funcType = context.TypeFunction(retType, false, funcArgs); var spvFunc = context.Function(retType, FunctionControlMask.MaskNone, funcType); context.DeclareFunction(funcIndex, function, spvFunc); } for (int funcIndex = 0; funcIndex < info.Functions.Count; funcIndex++) { Generate(context, info, funcIndex); } byte[] result = context.Generate(); lock (PoolLock) { InstructionPool.Release(instPool); IntegerPool.Release(integerPool); } return(result); }