diff options
author | gdkchan <gab.dark.100@gmail.com> | 2023-08-13 22:26:42 -0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-08-13 22:26:42 -0300 |
commit | b423197619dd8d9dda1c255a76105bf30e255dae (patch) | |
tree | e3898b3b1672f022b5de4522b51bd21583043996 /src/Ryujinx.Graphics.Shader/Translation/Translator.cs | |
parent | 8edfb2bc7b8507d0ef51f0544eb32a65f0bf54a1 (diff) |
Delete ShaderConfig and organize shader resources/definitions better (#5509)1.1.985
* Move some properties out of ShaderConfig
* Stop using ShaderConfig on backends
* Replace ShaderConfig usages on Translator and passes
* Move remaining properties out of ShaderConfig and delete ShaderConfig
* Remove ResourceManager property from TranslatorContext
* Move Rewriter passes to separate transform pass files
* Fix TransformPasses.RunPass on cases where a node is removed
* Move remaining ClipDistancePrimitivesWritten and UsedFeatures updates to decode stage
* Reduce excessive parameter passing a bit by using structs more
* Remove binding parameter from ShaderProperties methods since it is redundant
* Replace decoder instruction checks with switch statement
* Put GLSL on the same plan as SPIR-V for input/output declaration
* Stop mutating TranslatorContext state when Translate is called
* Pass most of the graphics state using a struct instead of individual query methods
* Auto-format
* Auto-format
* Add backend logging interface
* Auto-format
* Remove unnecessary use of interpolated strings
* Remove more modifications of AttributeUsage after decode
* PR feedback
* gl_Layer is not supported on compute
Diffstat (limited to 'src/Ryujinx.Graphics.Shader/Translation/Translator.cs')
-rw-r--r-- | src/Ryujinx.Graphics.Shader/Translation/Translator.cs | 191 |
1 files changed, 93 insertions, 98 deletions
diff --git a/src/Ryujinx.Graphics.Shader/Translation/Translator.cs b/src/Ryujinx.Graphics.Shader/Translation/Translator.cs index 010c80db..b609ac07 100644 --- a/src/Ryujinx.Graphics.Shader/Translation/Translator.cs +++ b/src/Ryujinx.Graphics.Shader/Translation/Translator.cs @@ -1,11 +1,6 @@ -using Ryujinx.Graphics.Shader.CodeGen.Glsl; -using Ryujinx.Graphics.Shader.CodeGen.Spirv; using Ryujinx.Graphics.Shader.Decoders; using Ryujinx.Graphics.Shader.IntermediateRepresentation; -using Ryujinx.Graphics.Shader.StructuredIr; -using Ryujinx.Graphics.Shader.Translation.Optimizations; using System; -using System.Collections.Generic; using System.Linq; using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; @@ -13,6 +8,7 @@ namespace Ryujinx.Graphics.Shader.Translation { public static class Translator { + private const int ThreadsPerWarp = 32; private const int HeaderSize = 0x50; internal readonly struct FunctionCode @@ -30,111 +26,112 @@ namespace Ryujinx.Graphics.Shader.Translation return DecodeShader(address, gpuAccessor, options); } - internal static ShaderProgram Translate(FunctionCode[] functions, ShaderConfig config) + private static TranslatorContext DecodeShader(ulong address, IGpuAccessor gpuAccessor, TranslationOptions options) { - var cfgs = new ControlFlowGraph[functions.Length]; - var frus = new RegisterUsage.FunctionRegisterUsage[functions.Length]; + int localMemorySize; + ShaderDefinitions definitions; + DecodedProgram program; - for (int i = 0; i < functions.Length; i++) + if (options.Flags.HasFlag(TranslationFlags.Compute)) { - cfgs[i] = ControlFlowGraph.Create(functions[i].Code); + definitions = CreateComputeDefinitions(gpuAccessor); + localMemorySize = gpuAccessor.QueryComputeLocalMemorySize(); - if (i != 0) - { - frus[i] = RegisterUsage.RunPass(cfgs[i]); - } + program = Decoder.Decode(definitions, gpuAccessor, address); } + else + { + ShaderHeader header = new(gpuAccessor, address); - List<Function> funcs = new(functions.Length); + definitions = CreateGraphicsDefinitions(gpuAccessor, header); + localMemorySize = GetLocalMemorySize(header); - for (int i = 0; i < functions.Length; i++) - { - funcs.Add(null); + program = Decoder.Decode(definitions, gpuAccessor, address + HeaderSize); } - HelperFunctionManager hfm = new(funcs, config.Stage); + ulong maxEndAddress = 0; - for (int i = 0; i < functions.Length; i++) + foreach (DecodedFunction function in program) { - var cfg = cfgs[i]; - - int inArgumentsCount = 0; - int outArgumentsCount = 0; - - if (i != 0) - { - var fru = frus[i]; - - inArgumentsCount = fru.InArguments.Length; - outArgumentsCount = fru.OutArguments.Length; - } - - if (cfg.Blocks.Length != 0) + foreach (Block block in function.Blocks) { - RegisterUsage.FixupCalls(cfg.Blocks, frus); - - Dominance.FindDominators(cfg); - Dominance.FindDominanceFrontiers(cfg.Blocks); - - Ssa.Rename(cfg.Blocks); - - Optimizer.RunPass(hfm, cfg.Blocks, config); - Rewriter.RunPass(hfm, cfg.Blocks, config); + if (maxEndAddress < block.EndAddress) + { + maxEndAddress = block.EndAddress; + } } - - funcs[i] = new Function(cfg.Blocks, $"fun{i}", false, inArgumentsCount, outArgumentsCount); } - var identification = ShaderIdentifier.Identify(funcs, config); - - var sInfo = StructuredProgram.MakeStructuredProgram(funcs, config); - - var info = config.CreateProgramInfo(identification); + int size = (int)maxEndAddress + (options.Flags.HasFlag(TranslationFlags.Compute) ? 0 : HeaderSize); - return config.Options.TargetLanguage switch - { - TargetLanguage.Glsl => new ShaderProgram(info, TargetLanguage.Glsl, GlslGenerator.Generate(sInfo, config)), - TargetLanguage.Spirv => new ShaderProgram(info, TargetLanguage.Spirv, SpirvGenerator.Generate(sInfo, config)), - _ => throw new NotImplementedException(config.Options.TargetLanguage.ToString()), - }; + return new TranslatorContext(address, size, localMemorySize, definitions, gpuAccessor, options, program); } - private static TranslatorContext DecodeShader(ulong address, IGpuAccessor gpuAccessor, TranslationOptions options) + private static ShaderDefinitions CreateComputeDefinitions(IGpuAccessor gpuAccessor) { - ShaderConfig config; - DecodedProgram program; - ulong maxEndAddress = 0; + return new ShaderDefinitions( + ShaderStage.Compute, + gpuAccessor.QueryComputeLocalSizeX(), + gpuAccessor.QueryComputeLocalSizeY(), + gpuAccessor.QueryComputeLocalSizeZ()); + } - if (options.Flags.HasFlag(TranslationFlags.Compute)) - { - config = new ShaderConfig(ShaderStage.Compute, gpuAccessor, options, gpuAccessor.QueryComputeLocalMemorySize()); + private static ShaderDefinitions CreateGraphicsDefinitions(IGpuAccessor gpuAccessor, ShaderHeader header) + { + bool transformFeedbackEnabled = + gpuAccessor.QueryTransformFeedbackEnabled() && + gpuAccessor.QueryHostSupportsTransformFeedback(); + TransformFeedbackOutput[] transformFeedbackOutputs = null; + ulong transformFeedbackVecMap = 0UL; - program = Decoder.Decode(config, address); - } - else + if (transformFeedbackEnabled) { - config = new ShaderConfig(new ShaderHeader(gpuAccessor, address), gpuAccessor, options); - - program = Decoder.Decode(config, address + HeaderSize); - } + transformFeedbackOutputs = new TransformFeedbackOutput[0xc0]; - foreach (DecodedFunction function in program) - { - foreach (Block block in function.Blocks) + for (int tfbIndex = 0; tfbIndex < 4; tfbIndex++) { - if (maxEndAddress < block.EndAddress) + var locations = gpuAccessor.QueryTransformFeedbackVaryingLocations(tfbIndex); + var stride = gpuAccessor.QueryTransformFeedbackStride(tfbIndex); + + for (int i = 0; i < locations.Length; i++) { - maxEndAddress = block.EndAddress; + byte wordOffset = locations[i]; + if (wordOffset < 0xc0) + { + transformFeedbackOutputs[wordOffset] = new TransformFeedbackOutput(tfbIndex, i * 4, stride); + transformFeedbackVecMap |= 1UL << (wordOffset / 4); + } } } } - config.SizeAdd((int)maxEndAddress + (options.Flags.HasFlag(TranslationFlags.Compute) ? 0 : HeaderSize)); + return new ShaderDefinitions( + header.Stage, + gpuAccessor.QueryGraphicsState(), + header.Stage == ShaderStage.Geometry && header.GpPassthrough, + header.ThreadsPerInputPrimitive, + header.OutputTopology, + header.MaxOutputVertexCount, + header.ImapTypes, + header.OmapTargets, + header.OmapSampleMask, + header.OmapDepth, + transformFeedbackEnabled, + transformFeedbackVecMap, + transformFeedbackOutputs); + } - return new TranslatorContext(address, program, config); + private static int GetLocalMemorySize(ShaderHeader header) + { + return header.ShaderLocalMemoryLowSize + header.ShaderLocalMemoryHighSize + (header.ShaderLocalMemoryCrsSize / ThreadsPerWarp); } - internal static FunctionCode[] EmitShader(DecodedProgram program, ShaderConfig config, bool initializeOutputs, out int initializationOperations) + internal static FunctionCode[] EmitShader( + TranslatorContext translatorContext, + ResourceManager resourceManager, + DecodedProgram program, + bool initializeOutputs, + out int initializationOperations) { initializationOperations = 0; @@ -149,11 +146,11 @@ namespace Ryujinx.Graphics.Shader.Translation for (int index = 0; index < functions.Length; index++) { - EmitterContext context = new(program, config, index != 0); + EmitterContext context = new(translatorContext, resourceManager, program, index != 0); if (initializeOutputs && index == 0) { - EmitOutputsInitialization(context, config); + EmitOutputsInitialization(context, translatorContext.AttributeUsage, translatorContext.GpuAccessor, translatorContext.Stage); initializationOperations = context.OperationsCount; } @@ -168,27 +165,27 @@ namespace Ryujinx.Graphics.Shader.Translation EmitOps(context, block); } - functions[index] = new FunctionCode(context.GetOperations()); + functions[index] = new(context.GetOperations()); } return functions; } - private static void EmitOutputsInitialization(EmitterContext context, ShaderConfig config) + private static void EmitOutputsInitialization(EmitterContext context, AttributeUsage attributeUsage, IGpuAccessor gpuAccessor, ShaderStage stage) { // Compute has no output attributes, and fragment is the last stage, so we // don't need to initialize outputs on those stages. - if (config.Stage == ShaderStage.Compute || config.Stage == ShaderStage.Fragment) + if (stage == ShaderStage.Compute || stage == ShaderStage.Fragment) { return; } - if (config.Stage == ShaderStage.Vertex) + if (stage == ShaderStage.Vertex) { InitializePositionOutput(context); } - UInt128 usedAttributes = context.Config.NextInputAttributesComponents; + UInt128 usedAttributes = context.TranslatorContext.AttributeUsage.NextInputAttributesComponents; while (usedAttributes != UInt128.Zero) { int index = (int)UInt128.TrailingZeroCount(usedAttributes); @@ -197,7 +194,7 @@ namespace Ryujinx.Graphics.Shader.Translation usedAttributes &= ~(UInt128.One << index); // We don't need to initialize passthrough attributes. - if ((context.Config.PassthroughAttributes & (1 << vecIndex)) != 0) + if ((context.TranslatorContext.AttributeUsage.PassthroughAttributes & (1 << vecIndex)) != 0) { continue; } @@ -205,30 +202,28 @@ namespace Ryujinx.Graphics.Shader.Translation InitializeOutputComponent(context, vecIndex, index & 3, perPatch: false); } - if (context.Config.NextUsedInputAttributesPerPatch != null) + if (context.TranslatorContext.AttributeUsage.NextUsedInputAttributesPerPatch != null) { - foreach (int vecIndex in context.Config.NextUsedInputAttributesPerPatch.Order()) + foreach (int vecIndex in context.TranslatorContext.AttributeUsage.NextUsedInputAttributesPerPatch.Order()) { InitializeOutput(context, vecIndex, perPatch: true); } } - if (config.NextUsesFixedFuncAttributes) + if (attributeUsage.NextUsesFixedFuncAttributes) { - bool supportsLayerFromVertexOrTess = config.GpuAccessor.QueryHostSupportsLayerVertexTessellation(); + bool supportsLayerFromVertexOrTess = gpuAccessor.QueryHostSupportsLayerVertexTessellation(); int fixedStartAttr = supportsLayerFromVertexOrTess ? 0 : 1; for (int i = fixedStartAttr; i < fixedStartAttr + 5 + AttributeConsts.TexCoordCount; i++) { - int index = config.GetFreeUserAttribute(isOutput: true, i); + int index = attributeUsage.GetFreeUserAttribute(isOutput: true, i); if (index < 0) { break; } InitializeOutput(context, index, perPatch: false); - - config.SetOutputUserAttributeFixedFunc(index); } } } @@ -253,11 +248,11 @@ namespace Ryujinx.Graphics.Shader.Translation { StorageKind storageKind = perPatch ? StorageKind.OutputPerPatch : StorageKind.Output; - if (context.Config.UsedFeatures.HasFlag(FeatureFlags.OaIndexing)) + if (context.TranslatorContext.Definitions.OaIndexing) { Operand invocationId = null; - if (context.Config.Stage == ShaderStage.TessellationControl && !perPatch) + if (context.TranslatorContext.Definitions.Stage == ShaderStage.TessellationControl && !perPatch) { invocationId = context.Load(StorageKind.Input, IoVariable.InvocationId); } @@ -268,7 +263,7 @@ namespace Ryujinx.Graphics.Shader.Translation } else { - if (context.Config.Stage == ShaderStage.TessellationControl && !perPatch) + if (context.TranslatorContext.Definitions.Stage == ShaderStage.TessellationControl && !perPatch) { Operand invocationId = context.Load(StorageKind.Input, IoVariable.InvocationId); context.Store(storageKind, IoVariable.UserDefined, Const(location), invocationId, Const(c), ConstF(c == 3 ? 1f : 0f)); @@ -286,7 +281,7 @@ namespace Ryujinx.Graphics.Shader.Translation { InstOp op = block.OpCodes[opIndex]; - if (context.Config.Options.Flags.HasFlag(TranslationFlags.DebugMode)) + if (context.TranslatorContext.Options.Flags.HasFlag(TranslationFlags.DebugMode)) { string instName; @@ -298,7 +293,7 @@ namespace Ryujinx.Graphics.Shader.Translation { instName = "???"; - context.Config.GpuAccessor.Log($"Invalid instruction at 0x{op.Address:X6} (0x{op.RawOpCode:X16})."); + context.TranslatorContext.GpuAccessor.Log($"Invalid instruction at 0x{op.Address:X6} (0x{op.RawOpCode:X16})."); } string dbgComment = $"0x{op.Address:X6}: 0x{op.RawOpCode:X16} {instName}"; |