Make sure attributes used on subsequent shader stages are initialized (#2538)
This commit is contained in:
		
							parent
							
								
									10d649e6d3
								
							
						
					
					
						commit
						ed754af8d5
					
				
					 15 changed files with 347 additions and 262 deletions
				
			
		|  | @ -1,4 +1,5 @@ | |||
| using Ryujinx.Graphics.Shader.Instructions; | ||||
| using Ryujinx.Graphics.Shader.Translation; | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
|  | @ -9,10 +10,8 @@ namespace Ryujinx.Graphics.Shader.Decoders | |||
| { | ||||
|     static class Decoder | ||||
|     { | ||||
|         public static Block[][] Decode(IGpuAccessor gpuAccessor, ulong startAddress, out bool hasBindless) | ||||
|         public static Block[][] Decode(ShaderConfig config, ulong startAddress) | ||||
|         { | ||||
|             hasBindless = false; | ||||
| 
 | ||||
|             List<Block[]> funcs = new List<Block[]>(); | ||||
| 
 | ||||
|             Queue<ulong> funcQueue = new Queue<ulong>(); | ||||
|  | @ -90,8 +89,7 @@ namespace Ryujinx.Graphics.Shader.Decoders | |||
|                             } | ||||
|                         } | ||||
| 
 | ||||
|                         FillBlock(gpuAccessor, currBlock, limitAddress, startAddress, out bool blockHasBindless); | ||||
|                         hasBindless |= blockHasBindless; | ||||
|                         FillBlock(config, currBlock, limitAddress, startAddress); | ||||
| 
 | ||||
|                         if (currBlock.OpCodes.Count != 0) | ||||
|                         { | ||||
|  | @ -168,7 +166,7 @@ namespace Ryujinx.Graphics.Shader.Decoders | |||
| 
 | ||||
|                             for (int i = 0; i < cbOffsetsCount; i++) | ||||
|                             { | ||||
|                                 uint targetOffset = gpuAccessor.ConstantBuffer1Read(cbBaseOffset + i * 4); | ||||
|                                 uint targetOffset = config.GpuAccessor.ConstantBuffer1Read(cbBaseOffset + i * 4); | ||||
|                                 Block target = GetBlock(baseOffset + targetOffset); | ||||
|                                 opBrIndir.PossibleTargets.Add(target); | ||||
|                                 target.Predecessors.Add(block); | ||||
|  | @ -224,15 +222,11 @@ namespace Ryujinx.Graphics.Shader.Decoders | |||
|             return false; | ||||
|         } | ||||
| 
 | ||||
|         private static void FillBlock( | ||||
|             IGpuAccessor gpuAccessor, | ||||
|             Block        block, | ||||
|             ulong        limitAddress, | ||||
|             ulong        startAddress, | ||||
|             out bool     hasBindless) | ||||
|         private static void FillBlock(ShaderConfig config, Block block, ulong limitAddress, ulong startAddress) | ||||
|         { | ||||
|             IGpuAccessor gpuAccessor = config.GpuAccessor; | ||||
| 
 | ||||
|             ulong address = block.Address; | ||||
|             hasBindless = false; | ||||
| 
 | ||||
|             do | ||||
|             { | ||||
|  | @ -274,13 +268,38 @@ namespace Ryujinx.Graphics.Shader.Decoders | |||
|                 OpCode op = makeOp(emitter, opAddress, opCode); | ||||
| 
 | ||||
|                 // We check these patterns to figure out the presence of bindless access | ||||
|                 hasBindless |= (op is OpCodeImage image && image.IsBindless) || | ||||
|                 if ((op is OpCodeImage image && image.IsBindless) || | ||||
|                     (op is OpCodeTxd txd && txd.IsBindless) || | ||||
|                     (op is OpCodeTld4B) || | ||||
|                     (emitter == InstEmit.TexB) || | ||||
|                     (emitter == InstEmit.TldB) || | ||||
|                     (emitter == InstEmit.TmmlB) || | ||||
|                     (emitter == InstEmit.TxqB); | ||||
|                     (emitter == InstEmit.TxqB)) | ||||
|                 { | ||||
|                     config.SetUsedFeature(FeatureFlags.Bindless); | ||||
|                 } | ||||
| 
 | ||||
|                 // Populate used attributes. | ||||
|                 if (op is IOpCodeAttribute opAttr) | ||||
|                 { | ||||
|                     for (int elemIndex = 0; elemIndex < opAttr.Count; elemIndex++) | ||||
|                     { | ||||
|                         int attr = opAttr.AttributeOffset + elemIndex * 4; | ||||
|                         if (attr >= AttributeConsts.UserAttributeBase && attr < AttributeConsts.UserAttributeEnd) | ||||
|                         { | ||||
|                             int index = (attr - AttributeConsts.UserAttributeBase) / 16; | ||||
| 
 | ||||
|                             if (op.Emitter == InstEmit.Ast) | ||||
|                             { | ||||
|                                 config.SetOutputUserAttribute(index); | ||||
|                             } | ||||
|                             else | ||||
|                             { | ||||
|                                 config.SetInputUserAttribute(index); | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
| 
 | ||||
|                 block.OpCodes.Add(op); | ||||
|             } | ||||
|  |  | |||
							
								
								
									
										8
									
								
								Ryujinx.Graphics.Shader/Decoders/IOpCodeAttribute.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								Ryujinx.Graphics.Shader/Decoders/IOpCodeAttribute.cs
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,8 @@ | |||
| namespace Ryujinx.Graphics.Shader.Decoders | ||||
| { | ||||
|     interface IOpCodeAttribute | ||||
|     { | ||||
|         int AttributeOffset { get; } | ||||
|         int Count { get; } | ||||
|     } | ||||
| } | ||||
|  | @ -2,7 +2,7 @@ using Ryujinx.Graphics.Shader.Instructions; | |||
| 
 | ||||
| namespace Ryujinx.Graphics.Shader.Decoders | ||||
| { | ||||
|     class OpCodeAttribute : OpCodeAluReg | ||||
|     class OpCodeAttribute : OpCodeAluReg, IOpCodeAttribute | ||||
|     { | ||||
|         public int AttributeOffset { get; } | ||||
|         public int Count           { get; } | ||||
|  |  | |||
|  | @ -2,9 +2,10 @@ using Ryujinx.Graphics.Shader.Instructions; | |||
| 
 | ||||
| namespace Ryujinx.Graphics.Shader.Decoders | ||||
| { | ||||
|     class OpCodeIpa : OpCodeAluReg | ||||
|     class OpCodeIpa : OpCodeAluReg, IOpCodeAttribute | ||||
|     { | ||||
|         public int AttributeOffset { get; } | ||||
|         public int Count => 1; | ||||
| 
 | ||||
|         public InterpolationMode Mode { get; } | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 gdkchan
						gdkchan