mirror of
				https://github.com/ryujinx-mirror/ryujinx.git
				synced 2025-11-04 08:59:04 -06:00 
			
		
		
		
	Vulkan: Extend full bindless to cover cases with phi nodes (#6853)
* Key textures using set and binding (rather than just binding) * Extend full bindless to cover cases with phi nodes * Log error on bindless access failure * Shader cache version bump * Remove constant buffer match to reduce the chances of full bindless triggering * Re-enable it for constant buffers, paper mario does actually need it * Format whitespace
This commit is contained in:
		@@ -22,7 +22,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
 | 
			
		||||
        private const ushort FileFormatVersionMajor = 1;
 | 
			
		||||
        private const ushort FileFormatVersionMinor = 2;
 | 
			
		||||
        private const uint FileFormatVersionPacked = ((uint)FileFormatVersionMajor << 16) | FileFormatVersionMinor;
 | 
			
		||||
        private const uint CodeGenVersion = 6870;
 | 
			
		||||
        private const uint CodeGenVersion = 6852;
 | 
			
		||||
 | 
			
		||||
        private const string SharedTocFileName = "shared.toc";
 | 
			
		||||
        private const string SharedDataFileName = "shared.data";
 | 
			
		||||
 
 | 
			
		||||
@@ -38,6 +38,12 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
 | 
			
		||||
                    // If we can't do bindless elimination, remove the texture operation.
 | 
			
		||||
                    // Set any destination variables to zero.
 | 
			
		||||
 | 
			
		||||
                    string typeName = texOp.Inst.IsImage()
 | 
			
		||||
                        ? texOp.Type.ToGlslImageType(texOp.Format.GetComponentType())
 | 
			
		||||
                        : texOp.Type.ToGlslTextureType();
 | 
			
		||||
 | 
			
		||||
                    gpuAccessor.Log($"Failed to find handle source for bindless access of type \"{typeName}\".");
 | 
			
		||||
 | 
			
		||||
                    for (int destIndex = 0; destIndex < texOp.DestsCount; destIndex++)
 | 
			
		||||
                    {
 | 
			
		||||
                        block.Operations.AddBefore(node, new Operation(Instruction.Copy, texOp.GetDest(destIndex), OperandHelper.Const(0)));
 | 
			
		||||
@@ -62,17 +68,22 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            Operand nvHandle = texOp.GetSource(0);
 | 
			
		||||
            Operand bindlessHandle = texOp.GetSource(0);
 | 
			
		||||
 | 
			
		||||
            if (nvHandle.AsgOp is not Operation handleOp ||
 | 
			
		||||
                handleOp.Inst != Instruction.Load ||
 | 
			
		||||
                (handleOp.StorageKind != StorageKind.Input && handleOp.StorageKind != StorageKind.StorageBuffer))
 | 
			
		||||
            if (bindlessHandle.AsgOp is PhiNode phi)
 | 
			
		||||
            {
 | 
			
		||||
                // Right now, we only allow bindless access when the handle comes from a shader input or storage buffer.
 | 
			
		||||
                // This is an artificial limitation to prevent it from being used in cases where it
 | 
			
		||||
                // would have a large performance impact of loading all textures in the pool.
 | 
			
		||||
                // It might be removed in the future, if we can mitigate the performance impact.
 | 
			
		||||
                for (int srcIndex = 0; srcIndex < phi.SourcesCount; srcIndex++)
 | 
			
		||||
                {
 | 
			
		||||
                    Operand phiSource = phi.GetSource(srcIndex);
 | 
			
		||||
 | 
			
		||||
                    if (phiSource.AsgOp is not PhiNode && !IsBindlessAccessAllowed(phiSource))
 | 
			
		||||
                    {
 | 
			
		||||
                        return false;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else if (!IsBindlessAccessAllowed(bindlessHandle))
 | 
			
		||||
            {
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@@ -80,8 +91,8 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
 | 
			
		||||
            Operand samplerHandle = OperandHelper.Local();
 | 
			
		||||
            Operand textureIndex = OperandHelper.Local();
 | 
			
		||||
 | 
			
		||||
            block.Operations.AddBefore(node, new Operation(Instruction.BitwiseAnd, textureHandle, nvHandle, OperandHelper.Const(0xfffff)));
 | 
			
		||||
            block.Operations.AddBefore(node, new Operation(Instruction.ShiftRightU32, samplerHandle, nvHandle, OperandHelper.Const(20)));
 | 
			
		||||
            block.Operations.AddBefore(node, new Operation(Instruction.BitwiseAnd, textureHandle, bindlessHandle, OperandHelper.Const(0xfffff)));
 | 
			
		||||
            block.Operations.AddBefore(node, new Operation(Instruction.ShiftRightU32, samplerHandle, bindlessHandle, OperandHelper.Const(20)));
 | 
			
		||||
 | 
			
		||||
            int texturePoolLength = Math.Max(BindlessToArray.MinimumArrayLength, gpuAccessor.QueryTextureArrayLengthFromPool());
 | 
			
		||||
 | 
			
		||||
@@ -130,6 +141,30 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private static bool IsBindlessAccessAllowed(Operand nvHandle)
 | 
			
		||||
        {
 | 
			
		||||
            if (nvHandle.Type == OperandType.ConstantBuffer)
 | 
			
		||||
            {
 | 
			
		||||
                // Bindless access with handles from constant buffer is allowed.
 | 
			
		||||
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (nvHandle.AsgOp is not Operation handleOp ||
 | 
			
		||||
                handleOp.Inst != Instruction.Load ||
 | 
			
		||||
                (handleOp.StorageKind != StorageKind.Input && handleOp.StorageKind != StorageKind.StorageBuffer))
 | 
			
		||||
            {
 | 
			
		||||
                // Right now, we only allow bindless access when the handle comes from a shader input or storage buffer.
 | 
			
		||||
                // This is an artificial limitation to prevent it from being used in cases where it
 | 
			
		||||
                // would have a large performance impact of loading all textures in the pool.
 | 
			
		||||
                // It might be removed in the future, if we can mitigate the performance impact.
 | 
			
		||||
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private static bool TryConvertBindless(BasicBlock block, ResourceManager resourceManager, IGpuAccessor gpuAccessor, TextureOperation texOp)
 | 
			
		||||
        {
 | 
			
		||||
            if (texOp.Inst == Instruction.TextureSample || texOp.Inst.IsTextureQuery())
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user