| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155 |
- using Ryujinx.Graphics.Shader.Decoders;
- using Ryujinx.Graphics.Shader.IntermediateRepresentation;
- using System.Collections.Generic;
- using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
- using static Ryujinx.Graphics.Shader.Translation.Translator;
- namespace Ryujinx.Graphics.Shader.Translation
- {
- public class TranslatorContext
- {
- private readonly Block[][] _cfg;
- private ShaderConfig _config;
- public ulong Address { get; }
- public ShaderStage Stage => _config.Stage;
- public int Size => _config.Size;
- public FeatureFlags UsedFeatures => _config.UsedFeatures;
- public HashSet<int> TextureHandlesForCache => _config.TextureHandlesForCache;
- public IGpuAccessor GpuAccessor => _config.GpuAccessor;
- internal TranslatorContext(ulong address, Block[][] cfg, ShaderConfig config)
- {
- Address = address;
- _config = config;
- _cfg = cfg;
- }
- private static bool IsUserAttribute(Operand operand)
- {
- return operand != null &&
- operand.Type == OperandType.Attribute &&
- operand.Value >= AttributeConsts.UserAttributeBase &&
- operand.Value < AttributeConsts.UserAttributeEnd;
- }
- private static FunctionCode[] Combine(FunctionCode[] a, FunctionCode[] b, int aStart)
- {
- // Here we combine two shaders.
- // For shader A:
- // - All user attribute stores on shader A are turned into copies to a
- // temporary variable. It's assumed that shader B will consume them.
- // - All return instructions are turned into branch instructions, the
- // branch target being the start of the shader B code.
- // For shader B:
- // - All user attribute loads on shader B are turned into copies from a
- // temporary variable, as long that attribute is written by shader A.
- FunctionCode[] output = new FunctionCode[a.Length + b.Length - 1];
- List<Operation> ops = new List<Operation>(a.Length + b.Length);
- Operand[] temps = new Operand[AttributeConsts.UserAttributesCount * 4];
- Operand lblB = Label();
- for (int index = aStart; index < a[0].Code.Length; index++)
- {
- Operation operation = a[0].Code[index];
- if (IsUserAttribute(operation.Dest))
- {
- int tIndex = (operation.Dest.Value - AttributeConsts.UserAttributeBase) / 4;
- Operand temp = temps[tIndex];
- if (temp == null)
- {
- temp = Local();
- temps[tIndex] = temp;
- }
- operation.Dest = temp;
- }
- if (operation.Inst == Instruction.Return)
- {
- ops.Add(new Operation(Instruction.Branch, lblB));
- }
- else
- {
- ops.Add(operation);
- }
- }
- ops.Add(new Operation(Instruction.MarkLabel, lblB));
- for (int index = 0; index < b[0].Code.Length; index++)
- {
- Operation operation = b[0].Code[index];
- for (int srcIndex = 0; srcIndex < operation.SourcesCount; srcIndex++)
- {
- Operand src = operation.GetSource(srcIndex);
- if (IsUserAttribute(src))
- {
- Operand temp = temps[(src.Value - AttributeConsts.UserAttributeBase) / 4];
- if (temp != null)
- {
- operation.SetSource(srcIndex, temp);
- }
- }
- }
- ops.Add(operation);
- }
- output[0] = new FunctionCode(ops.ToArray());
- for (int i = 1; i < a.Length; i++)
- {
- output[i] = a[i];
- }
- for (int i = 1; i < b.Length; i++)
- {
- output[a.Length + i - 1] = b[i];
- }
- return output;
- }
- public ShaderProgram Translate(
- out ShaderProgramInfo shaderProgramInfo,
- TranslatorContext nextStage = null,
- TranslatorContext other = null)
- {
- if (nextStage != null)
- {
- _config.MergeOutputUserAttributes(nextStage._config.UsedInputAttributes);
- }
- FunctionCode[] code = EmitShader(_cfg, _config, initializeOutputs: other == null, out _);
- if (other != null)
- {
- other._config.MergeOutputUserAttributes(_config.UsedOutputAttributes);
- FunctionCode[] otherCode = EmitShader(other._cfg, other._config, initializeOutputs: true, out int aStart);
- code = Combine(otherCode, code, aStart);
- _config.InheritFrom(other._config);
- }
- return Translator.Translate(code, _config, out shaderProgramInfo);
- }
- }
- }
|