| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168 |
- using System;
- using System.Collections.Generic;
- using System.Numerics;
- namespace Ryujinx.Graphics.Shader.Translation
- {
- class AttributeUsage
- {
- public bool NextUsesFixedFuncAttributes { get; private set; }
- public int UsedInputAttributes { get; private set; }
- public int UsedOutputAttributes { get; private set; }
- public HashSet<int> UsedInputAttributesPerPatch { get; }
- public HashSet<int> UsedOutputAttributesPerPatch { get; }
- public HashSet<int> NextUsedInputAttributesPerPatch { get; private set; }
- public int PassthroughAttributes { get; private set; }
- private int _nextUsedInputAttributes;
- private int _thisUsedInputAttributes;
- private Dictionary<int, int> _perPatchAttributeLocations;
- private readonly IGpuAccessor _gpuAccessor;
- public UInt128 NextInputAttributesComponents { get; private set; }
- public UInt128 ThisInputAttributesComponents { get; private set; }
- public AttributeUsage(IGpuAccessor gpuAccessor)
- {
- _gpuAccessor = gpuAccessor;
- UsedInputAttributesPerPatch = [];
- UsedOutputAttributesPerPatch = [];
- }
- public void SetInputUserAttribute(int index, int component)
- {
- int mask = 1 << index;
- UsedInputAttributes |= mask;
- _thisUsedInputAttributes |= mask;
- ThisInputAttributesComponents |= UInt128.One << (index * 4 + component);
- }
- public void SetInputUserAttributePerPatch(int index)
- {
- UsedInputAttributesPerPatch.Add(index);
- }
- public void SetOutputUserAttribute(int index)
- {
- UsedOutputAttributes |= 1 << index;
- }
- public void SetOutputUserAttributePerPatch(int index)
- {
- UsedOutputAttributesPerPatch.Add(index);
- }
- public void MergeFromtNextStage(bool gpPassthrough, bool nextUsesFixedFunctionAttributes, AttributeUsage nextStage)
- {
- NextInputAttributesComponents = nextStage.ThisInputAttributesComponents;
- NextUsedInputAttributesPerPatch = nextStage.UsedInputAttributesPerPatch;
- NextUsesFixedFuncAttributes = nextUsesFixedFunctionAttributes;
- MergeOutputUserAttributes(gpPassthrough, nextStage.UsedInputAttributes, nextStage.UsedInputAttributesPerPatch);
- if (UsedOutputAttributesPerPatch.Count != 0)
- {
- // Regular and per-patch input/output locations can't overlap,
- // so we must assign on our location using unused regular input/output locations.
- Dictionary<int, int> locationsMap = new();
- int freeMask = ~UsedOutputAttributes;
- foreach (int attr in UsedOutputAttributesPerPatch)
- {
- int location = BitOperations.TrailingZeroCount(freeMask);
- if (location == 32)
- {
- _gpuAccessor.Log($"No enough free locations for patch input/output 0x{attr:X}.");
- break;
- }
- locationsMap.Add(attr, location);
- freeMask &= ~(1 << location);
- }
- // Both stages must agree on the locations, so use the same "map" for both.
- _perPatchAttributeLocations = locationsMap;
- nextStage._perPatchAttributeLocations = locationsMap;
- }
- }
- private void MergeOutputUserAttributes(bool gpPassthrough, int mask, IEnumerable<int> perPatch)
- {
- _nextUsedInputAttributes = mask;
- if (gpPassthrough)
- {
- PassthroughAttributes = mask & ~UsedOutputAttributes;
- }
- else
- {
- UsedOutputAttributes |= mask;
- UsedOutputAttributesPerPatch.UnionWith(perPatch);
- }
- }
- public int GetPerPatchAttributeLocation(int index)
- {
- if (_perPatchAttributeLocations == null || !_perPatchAttributeLocations.TryGetValue(index, out int location))
- {
- return index;
- }
- return location;
- }
- public bool IsUsedOutputAttribute(int attr)
- {
- // The check for fixed function attributes on the next stage is conservative,
- // returning false if the output is just not used by the next stage is also valid.
- if (NextUsesFixedFuncAttributes &&
- attr >= AttributeConsts.UserAttributeBase &&
- attr < AttributeConsts.UserAttributeEnd)
- {
- int index = (attr - AttributeConsts.UserAttributeBase) >> 4;
- return (_nextUsedInputAttributes & (1 << index)) != 0;
- }
- return true;
- }
- public int GetFreeUserAttribute(bool isOutput, int index)
- {
- int useMask = isOutput ? _nextUsedInputAttributes : _thisUsedInputAttributes;
- int bit = -1;
- while (useMask != -1)
- {
- bit = BitOperations.TrailingZeroCount(~useMask);
- if (bit == 32)
- {
- bit = -1;
- break;
- }
- else if (index < 1)
- {
- break;
- }
- useMask |= 1 << bit;
- index--;
- }
- return bit;
- }
- public void SetAllInputUserAttributes()
- {
- UsedInputAttributes |= Constants.AllAttributesMask;
- ThisInputAttributesComponents |= ~UInt128.Zero >> (128 - Constants.MaxAttributes * 4);
- }
- public void SetAllOutputUserAttributes()
- {
- UsedOutputAttributes |= Constants.AllAttributesMask;
- }
- }
- }
|