mirror of
https://git.naxdy.org/Mirror/Ryujinx.git
synced 2025-02-19 07:43:35 +00:00
Pool Spv.Generator resources, cache delegates, spv opts
- Pools for Instructions and LiteralIntegers. Can be passed in when creating the generator module. - NewInstruction is called instead of new Instruction() - Ryujinx SpirvGenerator passes in some pools that are static. The idea is for these to be shared between threads eventually. - Estimate code size when creating the output MemoryStream - LiteralInteger pools using ThreadStatic pools that are initialized before and after creation... not sure of a better way since the way these are created is via implicit cast. Also, cache delegates for Spv.Generator for functions that are passed around to GenerateBinary etc, since passing the function raw creates a delegate on each call. TODO: update python spv cs generator to make the coregrammar with NewInstruction and the `params` overloads.
This commit is contained in:
parent
bf94f4c7d6
commit
dd718fbe97
9 changed files with 973 additions and 526 deletions
|
@ -63,7 +63,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||
|
||||
public AstBlock CurrentBlock { get; private set; }
|
||||
|
||||
public CodeGenContext(ShaderConfig config) : base(0x00010300)
|
||||
public SpirvDelegates Delegates { get; }
|
||||
|
||||
public CodeGenContext(ShaderConfig config, GeneratorPool<Instruction> instPool, GeneratorPool<LiteralInteger> integerPool) : base(0x00010300, instPool, integerPool)
|
||||
{
|
||||
Config = config;
|
||||
|
||||
|
@ -86,6 +88,8 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||
AddCapability(Capability.Float64);
|
||||
|
||||
SetMemoryModel(AddressingModel.Logical, MemoryModel.GLSL450);
|
||||
|
||||
Delegates = new SpirvDelegates(this);
|
||||
}
|
||||
|
||||
public void StartFunction()
|
||||
|
|
|
@ -153,22 +153,22 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||
|
||||
private static OperationResult GenerateAbsolute(CodeGenContext context, AstOperation operation)
|
||||
{
|
||||
return GenerateUnary(context, operation, context.GlslFAbs, context.GlslSAbs);
|
||||
return GenerateUnary(context, operation, context.Delegates.GlslFAbs, context.Delegates.GlslSAbs);
|
||||
}
|
||||
|
||||
private static OperationResult GenerateAdd(CodeGenContext context, AstOperation operation)
|
||||
{
|
||||
return GenerateBinary(context, operation, context.FAdd, context.IAdd);
|
||||
return GenerateBinary(context, operation, context.Delegates.FAdd, context.Delegates.IAdd);
|
||||
}
|
||||
|
||||
private static OperationResult GenerateAtomicAdd(CodeGenContext context, AstOperation operation)
|
||||
{
|
||||
return GenerateAtomicMemoryBinary(context, operation, context.AtomicIAdd);
|
||||
return GenerateAtomicMemoryBinary(context, operation, context.Delegates.AtomicIAdd);
|
||||
}
|
||||
|
||||
private static OperationResult GenerateAtomicAnd(CodeGenContext context, AstOperation operation)
|
||||
{
|
||||
return GenerateAtomicMemoryBinary(context, operation, context.AtomicAnd);
|
||||
return GenerateAtomicMemoryBinary(context, operation, context.Delegates.AtomicAnd);
|
||||
}
|
||||
|
||||
private static OperationResult GenerateAtomicCompareAndSwap(CodeGenContext context, AstOperation operation)
|
||||
|
@ -178,37 +178,37 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||
|
||||
private static OperationResult GenerateAtomicMinS32(CodeGenContext context, AstOperation operation)
|
||||
{
|
||||
return GenerateAtomicMemoryBinary(context, operation, context.AtomicSMin);
|
||||
return GenerateAtomicMemoryBinary(context, operation, context.Delegates.AtomicSMin);
|
||||
}
|
||||
|
||||
private static OperationResult GenerateAtomicMinU32(CodeGenContext context, AstOperation operation)
|
||||
{
|
||||
return GenerateAtomicMemoryBinary(context, operation, context.AtomicUMin);
|
||||
return GenerateAtomicMemoryBinary(context, operation, context.Delegates.AtomicUMin);
|
||||
}
|
||||
|
||||
private static OperationResult GenerateAtomicMaxS32(CodeGenContext context, AstOperation operation)
|
||||
{
|
||||
return GenerateAtomicMemoryBinary(context, operation, context.AtomicSMax);
|
||||
return GenerateAtomicMemoryBinary(context, operation, context.Delegates.AtomicSMax);
|
||||
}
|
||||
|
||||
private static OperationResult GenerateAtomicMaxU32(CodeGenContext context, AstOperation operation)
|
||||
{
|
||||
return GenerateAtomicMemoryBinary(context, operation, context.AtomicUMax);
|
||||
return GenerateAtomicMemoryBinary(context, operation, context.Delegates.AtomicUMax);
|
||||
}
|
||||
|
||||
private static OperationResult GenerateAtomicOr(CodeGenContext context, AstOperation operation)
|
||||
{
|
||||
return GenerateAtomicMemoryBinary(context, operation, context.AtomicOr);
|
||||
return GenerateAtomicMemoryBinary(context, operation, context.Delegates.AtomicOr);
|
||||
}
|
||||
|
||||
private static OperationResult GenerateAtomicSwap(CodeGenContext context, AstOperation operation)
|
||||
{
|
||||
return GenerateAtomicMemoryBinary(context, operation, context.AtomicExchange);
|
||||
return GenerateAtomicMemoryBinary(context, operation, context.Delegates.AtomicExchange);
|
||||
}
|
||||
|
||||
private static OperationResult GenerateAtomicXor(CodeGenContext context, AstOperation operation)
|
||||
{
|
||||
return GenerateAtomicMemoryBinary(context, operation, context.AtomicXor);
|
||||
return GenerateAtomicMemoryBinary(context, operation, context.Delegates.AtomicXor);
|
||||
}
|
||||
|
||||
private static OperationResult GenerateBallot(CodeGenContext context, AstOperation operation)
|
||||
|
@ -236,47 +236,47 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||
|
||||
private static OperationResult GenerateBitCount(CodeGenContext context, AstOperation operation)
|
||||
{
|
||||
return GenerateUnaryS32(context, operation, context.BitCount);
|
||||
return GenerateUnaryS32(context, operation, context.Delegates.BitCount);
|
||||
}
|
||||
|
||||
private static OperationResult GenerateBitfieldExtractS32(CodeGenContext context, AstOperation operation)
|
||||
{
|
||||
return GenerateTernaryS32(context, operation, context.BitFieldSExtract);
|
||||
return GenerateTernaryS32(context, operation, context.Delegates.BitFieldSExtract);
|
||||
}
|
||||
|
||||
private static OperationResult GenerateBitfieldExtractU32(CodeGenContext context, AstOperation operation)
|
||||
{
|
||||
return GenerateTernaryS32(context, operation, context.BitFieldUExtract);
|
||||
return GenerateTernaryS32(context, operation, context.Delegates.BitFieldUExtract);
|
||||
}
|
||||
|
||||
private static OperationResult GenerateBitfieldInsert(CodeGenContext context, AstOperation operation)
|
||||
{
|
||||
return GenerateQuaternaryS32(context, operation, context.BitFieldInsert);
|
||||
return GenerateQuaternaryS32(context, operation, context.Delegates.BitFieldInsert);
|
||||
}
|
||||
|
||||
private static OperationResult GenerateBitfieldReverse(CodeGenContext context, AstOperation operation)
|
||||
{
|
||||
return GenerateUnaryS32(context, operation, context.BitReverse);
|
||||
return GenerateUnaryS32(context, operation, context.Delegates.BitReverse);
|
||||
}
|
||||
|
||||
private static OperationResult GenerateBitwiseAnd(CodeGenContext context, AstOperation operation)
|
||||
{
|
||||
return GenerateBinaryS32(context, operation, context.BitwiseAnd);
|
||||
return GenerateBinaryS32(context, operation, context.Delegates.BitwiseAnd);
|
||||
}
|
||||
|
||||
private static OperationResult GenerateBitwiseExclusiveOr(CodeGenContext context, AstOperation operation)
|
||||
{
|
||||
return GenerateBinaryS32(context, operation, context.BitwiseXor);
|
||||
return GenerateBinaryS32(context, operation, context.Delegates.BitwiseXor);
|
||||
}
|
||||
|
||||
private static OperationResult GenerateBitwiseNot(CodeGenContext context, AstOperation operation)
|
||||
{
|
||||
return GenerateUnaryS32(context, operation, context.Not);
|
||||
return GenerateUnaryS32(context, operation, context.Delegates.Not);
|
||||
}
|
||||
|
||||
private static OperationResult GenerateBitwiseOr(CodeGenContext context, AstOperation operation)
|
||||
{
|
||||
return GenerateBinaryS32(context, operation, context.BitwiseOr);
|
||||
return GenerateBinaryS32(context, operation, context.Delegates.BitwiseOr);
|
||||
}
|
||||
|
||||
private static OperationResult GenerateCall(CodeGenContext context, AstOperation operation)
|
||||
|
@ -316,17 +316,17 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||
|
||||
private static OperationResult GenerateCeiling(CodeGenContext context, AstOperation operation)
|
||||
{
|
||||
return GenerateUnary(context, operation, context.GlslCeil, null);
|
||||
return GenerateUnary(context, operation, context.Delegates.GlslCeil, null);
|
||||
}
|
||||
|
||||
private static OperationResult GenerateClamp(CodeGenContext context, AstOperation operation)
|
||||
{
|
||||
return GenerateTernary(context, operation, context.GlslFClamp, context.GlslSClamp);
|
||||
return GenerateTernary(context, operation, context.Delegates.GlslFClamp, context.Delegates.GlslSClamp);
|
||||
}
|
||||
|
||||
private static OperationResult GenerateClampU32(CodeGenContext context, AstOperation operation)
|
||||
{
|
||||
return GenerateTernaryU32(context, operation, context.GlslUClamp);
|
||||
return GenerateTernaryU32(context, operation, context.Delegates.GlslUClamp);
|
||||
}
|
||||
|
||||
private static OperationResult GenerateComment(CodeGenContext context, AstOperation operation)
|
||||
|
@ -336,52 +336,52 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||
|
||||
private static OperationResult GenerateCompareEqual(CodeGenContext context, AstOperation operation)
|
||||
{
|
||||
return GenerateCompare(context, operation, context.FOrdEqual, context.IEqual);
|
||||
return GenerateCompare(context, operation, context.Delegates.FOrdEqual, context.Delegates.IEqual);
|
||||
}
|
||||
|
||||
private static OperationResult GenerateCompareGreater(CodeGenContext context, AstOperation operation)
|
||||
{
|
||||
return GenerateCompare(context, operation, context.FOrdGreaterThan, context.SGreaterThan);
|
||||
return GenerateCompare(context, operation, context.Delegates.FOrdGreaterThan, context.Delegates.SGreaterThan);
|
||||
}
|
||||
|
||||
private static OperationResult GenerateCompareGreaterOrEqual(CodeGenContext context, AstOperation operation)
|
||||
{
|
||||
return GenerateCompare(context, operation, context.FOrdGreaterThanEqual, context.SGreaterThanEqual);
|
||||
return GenerateCompare(context, operation, context.Delegates.FOrdGreaterThanEqual, context.Delegates.SGreaterThanEqual);
|
||||
}
|
||||
|
||||
private static OperationResult GenerateCompareGreaterOrEqualU32(CodeGenContext context, AstOperation operation)
|
||||
{
|
||||
return GenerateCompareU32(context, operation, context.UGreaterThanEqual);
|
||||
return GenerateCompareU32(context, operation, context.Delegates.UGreaterThanEqual);
|
||||
}
|
||||
|
||||
private static OperationResult GenerateCompareGreaterU32(CodeGenContext context, AstOperation operation)
|
||||
{
|
||||
return GenerateCompareU32(context, operation, context.UGreaterThan);
|
||||
return GenerateCompareU32(context, operation, context.Delegates.UGreaterThan);
|
||||
}
|
||||
|
||||
private static OperationResult GenerateCompareLess(CodeGenContext context, AstOperation operation)
|
||||
{
|
||||
return GenerateCompare(context, operation, context.FOrdLessThan, context.SLessThan);
|
||||
return GenerateCompare(context, operation, context.Delegates.FOrdLessThan, context.Delegates.SLessThan);
|
||||
}
|
||||
|
||||
private static OperationResult GenerateCompareLessOrEqual(CodeGenContext context, AstOperation operation)
|
||||
{
|
||||
return GenerateCompare(context, operation, context.FOrdLessThanEqual, context.SLessThanEqual);
|
||||
return GenerateCompare(context, operation, context.Delegates.FOrdLessThanEqual, context.Delegates.SLessThanEqual);
|
||||
}
|
||||
|
||||
private static OperationResult GenerateCompareLessOrEqualU32(CodeGenContext context, AstOperation operation)
|
||||
{
|
||||
return GenerateCompareU32(context, operation, context.ULessThanEqual);
|
||||
return GenerateCompareU32(context, operation, context.Delegates.ULessThanEqual);
|
||||
}
|
||||
|
||||
private static OperationResult GenerateCompareLessU32(CodeGenContext context, AstOperation operation)
|
||||
{
|
||||
return GenerateCompareU32(context, operation, context.ULessThan);
|
||||
return GenerateCompareU32(context, operation, context.Delegates.ULessThan);
|
||||
}
|
||||
|
||||
private static OperationResult GenerateCompareNotEqual(CodeGenContext context, AstOperation operation)
|
||||
{
|
||||
return GenerateCompare(context, operation, context.FOrdNotEqual, context.INotEqual);
|
||||
return GenerateCompare(context, operation, context.Delegates.FOrdNotEqual, context.Delegates.INotEqual);
|
||||
}
|
||||
|
||||
private static OperationResult GenerateConditionalSelect(CodeGenContext context, AstOperation operation)
|
||||
|
@ -478,17 +478,17 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||
|
||||
private static OperationResult GenerateCosine(CodeGenContext context, AstOperation operation)
|
||||
{
|
||||
return GenerateUnary(context, operation, context.GlslCos, null);
|
||||
return GenerateUnary(context, operation, context.Delegates.GlslCos, null);
|
||||
}
|
||||
|
||||
private static OperationResult GenerateDdx(CodeGenContext context, AstOperation operation)
|
||||
{
|
||||
return GenerateUnaryFP32(context, operation, context.DPdx);
|
||||
return GenerateUnaryFP32(context, operation, context.Delegates.DPdx);
|
||||
}
|
||||
|
||||
private static OperationResult GenerateDdy(CodeGenContext context, AstOperation operation)
|
||||
{
|
||||
return GenerateUnaryFP32(context, operation, context.DPdy);
|
||||
return GenerateUnaryFP32(context, operation, context.Delegates.DPdy);
|
||||
}
|
||||
|
||||
private static OperationResult GenerateDiscard(CodeGenContext context, AstOperation operation)
|
||||
|
@ -499,7 +499,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||
|
||||
private static OperationResult GenerateDivide(CodeGenContext context, AstOperation operation)
|
||||
{
|
||||
return GenerateBinary(context, operation, context.FDiv, context.SDiv);
|
||||
return GenerateBinary(context, operation, context.Delegates.FDiv, context.Delegates.SDiv);
|
||||
}
|
||||
|
||||
private static OperationResult GenerateEmitVertex(CodeGenContext context, AstOperation operation)
|
||||
|
@ -518,7 +518,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||
|
||||
private static OperationResult GenerateExponentB2(CodeGenContext context, AstOperation operation)
|
||||
{
|
||||
return GenerateUnary(context, operation, context.GlslExp2, null);
|
||||
return GenerateUnary(context, operation, context.Delegates.GlslExp2, null);
|
||||
}
|
||||
|
||||
private static OperationResult GenerateFindLSB(CodeGenContext context, AstOperation operation)
|
||||
|
@ -541,12 +541,12 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||
|
||||
private static OperationResult GenerateFloor(CodeGenContext context, AstOperation operation)
|
||||
{
|
||||
return GenerateUnary(context, operation, context.GlslFloor, null);
|
||||
return GenerateUnary(context, operation, context.Delegates.GlslFloor, null);
|
||||
}
|
||||
|
||||
private static OperationResult GenerateFusedMultiplyAdd(CodeGenContext context, AstOperation operation)
|
||||
{
|
||||
return GenerateTernary(context, operation, context.GlslFma, null);
|
||||
return GenerateTernary(context, operation, context.Delegates.GlslFma, null);
|
||||
}
|
||||
|
||||
private static OperationResult GenerateGroupMemoryBarrier(CodeGenContext context, AstOperation operation)
|
||||
|
@ -961,22 +961,22 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||
|
||||
private static OperationResult GenerateLogarithmB2(CodeGenContext context, AstOperation operation)
|
||||
{
|
||||
return GenerateUnary(context, operation, context.GlslLog2, null);
|
||||
return GenerateUnary(context, operation, context.Delegates.GlslLog2, null);
|
||||
}
|
||||
|
||||
private static OperationResult GenerateLogicalAnd(CodeGenContext context, AstOperation operation)
|
||||
{
|
||||
return GenerateBinaryBool(context, operation, context.LogicalAnd);
|
||||
return GenerateBinaryBool(context, operation, context.Delegates.LogicalAnd);
|
||||
}
|
||||
|
||||
private static OperationResult GenerateLogicalNot(CodeGenContext context, AstOperation operation)
|
||||
{
|
||||
return GenerateUnaryBool(context, operation, context.LogicalNot);
|
||||
return GenerateUnaryBool(context, operation, context.Delegates.LogicalNot);
|
||||
}
|
||||
|
||||
private static OperationResult GenerateLogicalOr(CodeGenContext context, AstOperation operation)
|
||||
{
|
||||
return GenerateBinaryBool(context, operation, context.LogicalOr);
|
||||
return GenerateBinaryBool(context, operation, context.Delegates.LogicalOr);
|
||||
}
|
||||
|
||||
private static OperationResult GenerateLoopBreak(CodeGenContext context, AstOperation operation)
|
||||
|
@ -1009,12 +1009,12 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||
|
||||
private static OperationResult GenerateMaximum(CodeGenContext context, AstOperation operation)
|
||||
{
|
||||
return GenerateBinary(context, operation, context.GlslFMax, context.GlslSMax);
|
||||
return GenerateBinary(context, operation, context.Delegates.GlslFMax, context.Delegates.GlslSMax);
|
||||
}
|
||||
|
||||
private static OperationResult GenerateMaximumU32(CodeGenContext context, AstOperation operation)
|
||||
{
|
||||
return GenerateBinaryU32(context, operation, context.GlslUMax);
|
||||
return GenerateBinaryU32(context, operation, context.Delegates.GlslUMax);
|
||||
}
|
||||
|
||||
private static OperationResult GenerateMemoryBarrier(CodeGenContext context, AstOperation operation)
|
||||
|
@ -1025,22 +1025,22 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||
|
||||
private static OperationResult GenerateMinimum(CodeGenContext context, AstOperation operation)
|
||||
{
|
||||
return GenerateBinary(context, operation, context.GlslFMin, context.GlslSMin);
|
||||
return GenerateBinary(context, operation, context.Delegates.GlslFMin, context.Delegates.GlslSMin);
|
||||
}
|
||||
|
||||
private static OperationResult GenerateMinimumU32(CodeGenContext context, AstOperation operation)
|
||||
{
|
||||
return GenerateBinaryU32(context, operation, context.GlslUMin);
|
||||
return GenerateBinaryU32(context, operation, context.Delegates.GlslUMin);
|
||||
}
|
||||
|
||||
private static OperationResult GenerateMultiply(CodeGenContext context, AstOperation operation)
|
||||
{
|
||||
return GenerateBinary(context, operation, context.FMul, context.IMul);
|
||||
return GenerateBinary(context, operation, context.Delegates.FMul, context.Delegates.IMul);
|
||||
}
|
||||
|
||||
private static OperationResult GenerateNegate(CodeGenContext context, AstOperation operation)
|
||||
{
|
||||
return GenerateUnary(context, operation, context.FNegate, context.SNegate);
|
||||
return GenerateUnary(context, operation, context.Delegates.FNegate, context.Delegates.SNegate);
|
||||
}
|
||||
|
||||
private static OperationResult GeneratePackDouble2x32(CodeGenContext context, AstOperation operation)
|
||||
|
@ -1065,7 +1065,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||
|
||||
private static OperationResult GenerateReciprocalSquareRoot(CodeGenContext context, AstOperation operation)
|
||||
{
|
||||
return GenerateUnary(context, operation, context.GlslInverseSqrt, null);
|
||||
return GenerateUnary(context, operation, context.Delegates.GlslInverseSqrt, null);
|
||||
}
|
||||
|
||||
private static OperationResult GenerateReturn(CodeGenContext context, AstOperation operation)
|
||||
|
@ -1076,22 +1076,22 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||
|
||||
private static OperationResult GenerateRound(CodeGenContext context, AstOperation operation)
|
||||
{
|
||||
return GenerateUnary(context, operation, context.GlslRoundEven, null);
|
||||
return GenerateUnary(context, operation, context.Delegates.GlslRoundEven, null);
|
||||
}
|
||||
|
||||
private static OperationResult GenerateShiftLeft(CodeGenContext context, AstOperation operation)
|
||||
{
|
||||
return GenerateBinaryS32(context, operation, context.ShiftLeftLogical);
|
||||
return GenerateBinaryS32(context, operation, context.Delegates.ShiftLeftLogical);
|
||||
}
|
||||
|
||||
private static OperationResult GenerateShiftRightS32(CodeGenContext context, AstOperation operation)
|
||||
{
|
||||
return GenerateBinaryS32(context, operation, context.ShiftRightArithmetic);
|
||||
return GenerateBinaryS32(context, operation, context.Delegates.ShiftRightArithmetic);
|
||||
}
|
||||
|
||||
private static OperationResult GenerateShiftRightU32(CodeGenContext context, AstOperation operation)
|
||||
{
|
||||
return GenerateBinaryS32(context, operation, context.ShiftRightLogical);
|
||||
return GenerateBinaryS32(context, operation, context.Delegates.ShiftRightLogical);
|
||||
}
|
||||
|
||||
private static OperationResult GenerateShuffle(CodeGenContext context, AstOperation operation)
|
||||
|
@ -1213,12 +1213,12 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||
|
||||
private static OperationResult GenerateSine(CodeGenContext context, AstOperation operation)
|
||||
{
|
||||
return GenerateUnary(context, operation, context.GlslSin, null);
|
||||
return GenerateUnary(context, operation, context.Delegates.GlslSin, null);
|
||||
}
|
||||
|
||||
private static OperationResult GenerateSquareRoot(CodeGenContext context, AstOperation operation)
|
||||
{
|
||||
return GenerateUnary(context, operation, context.GlslSqrt, null);
|
||||
return GenerateUnary(context, operation, context.Delegates.GlslSqrt, null);
|
||||
}
|
||||
|
||||
private static OperationResult GenerateStoreLocal(CodeGenContext context, AstOperation operation)
|
||||
|
@ -1256,7 +1256,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||
|
||||
private static OperationResult GenerateSubtract(CodeGenContext context, AstOperation operation)
|
||||
{
|
||||
return GenerateBinary(context, operation, context.FSub, context.ISub);
|
||||
return GenerateBinary(context, operation, context.Delegates.FSub, context.Delegates.ISub);
|
||||
}
|
||||
|
||||
private static OperationResult GenerateTextureSample(CodeGenContext context, AstOperation operation)
|
||||
|
@ -1609,7 +1609,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||
|
||||
private static OperationResult GenerateTruncate(CodeGenContext context, AstOperation operation)
|
||||
{
|
||||
return GenerateUnary(context, operation, context.GlslTrunc, null);
|
||||
return GenerateUnary(context, operation, context.Delegates.GlslTrunc, null);
|
||||
}
|
||||
|
||||
private static OperationResult GenerateUnpackDouble2x32(CodeGenContext context, AstOperation operation)
|
||||
|
|
224
Ryujinx.Graphics.Shader/CodeGen/Spirv/SpirvDelegates.cs
Normal file
224
Ryujinx.Graphics.Shader/CodeGen/Spirv/SpirvDelegates.cs
Normal file
|
@ -0,0 +1,224 @@
|
|||
using FuncUnaryInstruction = System.Func<Spv.Generator.Instruction, Spv.Generator.Instruction, Spv.Generator.Instruction>;
|
||||
using FuncBinaryInstruction = System.Func<Spv.Generator.Instruction, Spv.Generator.Instruction, Spv.Generator.Instruction, Spv.Generator.Instruction>;
|
||||
using FuncTernaryInstruction = System.Func<Spv.Generator.Instruction, Spv.Generator.Instruction, Spv.Generator.Instruction, Spv.Generator.Instruction, Spv.Generator.Instruction>;
|
||||
using FuncQuaternaryInstruction = System.Func<Spv.Generator.Instruction, Spv.Generator.Instruction, Spv.Generator.Instruction, Spv.Generator.Instruction, Spv.Generator.Instruction, Spv.Generator.Instruction>;
|
||||
|
||||
namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
{
|
||||
/// <summary>
|
||||
/// Delegate cache for SPIR-V instruction generators. Avoids delegate allocation when passing generators as arguments.
|
||||
/// </summary>
|
||||
internal struct SpirvDelegates
|
||||
{
|
||||
// Unary
|
||||
public readonly FuncUnaryInstruction GlslFAbs;
|
||||
public readonly FuncUnaryInstruction GlslSAbs;
|
||||
public readonly FuncUnaryInstruction GlslCeil;
|
||||
public readonly FuncUnaryInstruction GlslCos;
|
||||
public readonly FuncUnaryInstruction GlslExp2;
|
||||
public readonly FuncUnaryInstruction GlslFloor;
|
||||
public readonly FuncUnaryInstruction GlslLog2;
|
||||
public readonly FuncUnaryInstruction FNegate;
|
||||
public readonly FuncUnaryInstruction SNegate;
|
||||
public readonly FuncUnaryInstruction GlslInverseSqrt;
|
||||
public readonly FuncUnaryInstruction GlslRoundEven;
|
||||
public readonly FuncUnaryInstruction GlslSin;
|
||||
public readonly FuncUnaryInstruction GlslSqrt;
|
||||
public readonly FuncUnaryInstruction GlslTrunc;
|
||||
|
||||
// UnaryBool
|
||||
public readonly FuncUnaryInstruction LogicalNot;
|
||||
|
||||
// UnaryFP32
|
||||
public readonly FuncUnaryInstruction DPdx;
|
||||
public readonly FuncUnaryInstruction DPdy;
|
||||
|
||||
// UnaryS32
|
||||
public readonly FuncUnaryInstruction BitCount;
|
||||
public readonly FuncUnaryInstruction BitReverse;
|
||||
public readonly FuncUnaryInstruction Not;
|
||||
|
||||
// Compare
|
||||
public readonly FuncBinaryInstruction FOrdEqual;
|
||||
public readonly FuncBinaryInstruction IEqual;
|
||||
public readonly FuncBinaryInstruction FOrdGreaterThan;
|
||||
public readonly FuncBinaryInstruction SGreaterThan;
|
||||
public readonly FuncBinaryInstruction FOrdGreaterThanEqual;
|
||||
public readonly FuncBinaryInstruction SGreaterThanEqual;
|
||||
public readonly FuncBinaryInstruction FOrdLessThan;
|
||||
public readonly FuncBinaryInstruction SLessThan;
|
||||
public readonly FuncBinaryInstruction FOrdLessThanEqual;
|
||||
public readonly FuncBinaryInstruction SLessThanEqual;
|
||||
public readonly FuncBinaryInstruction FOrdNotEqual;
|
||||
public readonly FuncBinaryInstruction INotEqual;
|
||||
|
||||
// CompareU32
|
||||
public readonly FuncBinaryInstruction UGreaterThanEqual;
|
||||
public readonly FuncBinaryInstruction UGreaterThan;
|
||||
public readonly FuncBinaryInstruction ULessThanEqual;
|
||||
public readonly FuncBinaryInstruction ULessThan;
|
||||
|
||||
// Binary
|
||||
public readonly FuncBinaryInstruction FAdd;
|
||||
public readonly FuncBinaryInstruction IAdd;
|
||||
public readonly FuncBinaryInstruction FDiv;
|
||||
public readonly FuncBinaryInstruction SDiv;
|
||||
public readonly FuncBinaryInstruction GlslFMax;
|
||||
public readonly FuncBinaryInstruction GlslSMax;
|
||||
public readonly FuncBinaryInstruction GlslFMin;
|
||||
public readonly FuncBinaryInstruction GlslSMin;
|
||||
public readonly FuncBinaryInstruction FMul;
|
||||
public readonly FuncBinaryInstruction IMul;
|
||||
public readonly FuncBinaryInstruction FSub;
|
||||
public readonly FuncBinaryInstruction ISub;
|
||||
|
||||
// BinaryBool
|
||||
public readonly FuncBinaryInstruction LogicalAnd;
|
||||
public readonly FuncBinaryInstruction LogicalOr;
|
||||
|
||||
// BinaryS32
|
||||
public readonly FuncBinaryInstruction BitwiseAnd;
|
||||
public readonly FuncBinaryInstruction BitwiseXor;
|
||||
public readonly FuncBinaryInstruction BitwiseOr;
|
||||
public readonly FuncBinaryInstruction ShiftLeftLogical;
|
||||
public readonly FuncBinaryInstruction ShiftRightArithmetic;
|
||||
public readonly FuncBinaryInstruction ShiftRightLogical;
|
||||
|
||||
// BinaryU32
|
||||
public readonly FuncBinaryInstruction GlslUMax;
|
||||
public readonly FuncBinaryInstruction GlslUMin;
|
||||
|
||||
// AtomicMemoryBinary
|
||||
public readonly FuncQuaternaryInstruction AtomicIAdd;
|
||||
public readonly FuncQuaternaryInstruction AtomicAnd;
|
||||
public readonly FuncQuaternaryInstruction AtomicSMin;
|
||||
public readonly FuncQuaternaryInstruction AtomicUMin;
|
||||
public readonly FuncQuaternaryInstruction AtomicSMax;
|
||||
public readonly FuncQuaternaryInstruction AtomicUMax;
|
||||
public readonly FuncQuaternaryInstruction AtomicOr;
|
||||
public readonly FuncQuaternaryInstruction AtomicExchange;
|
||||
public readonly FuncQuaternaryInstruction AtomicXor;
|
||||
|
||||
// Ternary
|
||||
public readonly FuncTernaryInstruction GlslFClamp;
|
||||
public readonly FuncTernaryInstruction GlslSClamp;
|
||||
public readonly FuncTernaryInstruction GlslFma;
|
||||
|
||||
// TernaryS32
|
||||
public readonly FuncTernaryInstruction BitFieldSExtract;
|
||||
public readonly FuncTernaryInstruction BitFieldUExtract;
|
||||
|
||||
// TernaryU32
|
||||
public readonly FuncTernaryInstruction GlslUClamp;
|
||||
|
||||
// QuaternaryS32
|
||||
public readonly FuncQuaternaryInstruction BitFieldInsert;
|
||||
|
||||
public SpirvDelegates(CodeGenContext context)
|
||||
{
|
||||
// Unary
|
||||
GlslFAbs = context.GlslFAbs;
|
||||
GlslSAbs = context.GlslSAbs;
|
||||
GlslCeil = context.GlslCeil;
|
||||
GlslCos = context.GlslCos;
|
||||
GlslExp2 = context.GlslExp2;
|
||||
GlslFloor = context.GlslFloor;
|
||||
GlslLog2 = context.GlslLog2;
|
||||
FNegate = context.FNegate;
|
||||
SNegate = context.SNegate;
|
||||
GlslInverseSqrt = context.GlslInverseSqrt;
|
||||
GlslRoundEven = context.GlslRoundEven;
|
||||
GlslSin = context.GlslSin;
|
||||
GlslSqrt = context.GlslSqrt;
|
||||
GlslTrunc = context.GlslTrunc;
|
||||
|
||||
// UnaryBool
|
||||
LogicalNot = context.LogicalNot;
|
||||
|
||||
// UnaryFP32
|
||||
DPdx = context.DPdx;
|
||||
DPdy = context.DPdy;
|
||||
|
||||
// UnaryS32
|
||||
BitCount = context.BitCount;
|
||||
BitReverse = context.BitReverse;
|
||||
Not = context.Not;
|
||||
|
||||
// Compare
|
||||
FOrdEqual = context.FOrdEqual;
|
||||
IEqual = context.IEqual;
|
||||
FOrdGreaterThan = context.FOrdGreaterThan;
|
||||
SGreaterThan = context.SGreaterThan;
|
||||
FOrdGreaterThanEqual = context.FOrdGreaterThanEqual;
|
||||
SGreaterThanEqual = context.SGreaterThanEqual;
|
||||
FOrdLessThan = context.FOrdLessThan;
|
||||
SLessThan = context.SLessThan;
|
||||
FOrdLessThanEqual = context.FOrdLessThanEqual;
|
||||
SLessThanEqual = context.SLessThanEqual;
|
||||
FOrdNotEqual = context.FOrdNotEqual;
|
||||
INotEqual = context.INotEqual;
|
||||
|
||||
// CompareU32
|
||||
UGreaterThanEqual = context.UGreaterThanEqual;
|
||||
UGreaterThan = context.UGreaterThan;
|
||||
ULessThanEqual = context.ULessThanEqual;
|
||||
ULessThan = context.ULessThan;
|
||||
|
||||
// Binary
|
||||
FAdd = context.FAdd;
|
||||
IAdd = context.IAdd;
|
||||
FDiv = context.FDiv;
|
||||
SDiv = context.SDiv;
|
||||
GlslFMax = context.GlslFMax;
|
||||
GlslSMax = context.GlslSMax;
|
||||
GlslFMin = context.GlslFMin;
|
||||
GlslSMin = context.GlslSMin;
|
||||
FMul = context.FMul;
|
||||
IMul = context.IMul;
|
||||
FSub = context.FSub;
|
||||
ISub = context.ISub;
|
||||
|
||||
// BinaryBool
|
||||
LogicalAnd = context.LogicalAnd;
|
||||
LogicalOr = context.LogicalOr;
|
||||
|
||||
// BinaryS32
|
||||
BitwiseAnd = context.BitwiseAnd;
|
||||
BitwiseXor = context.BitwiseXor;
|
||||
BitwiseOr = context.BitwiseOr;
|
||||
ShiftLeftLogical = context.ShiftLeftLogical;
|
||||
ShiftRightArithmetic = context.ShiftRightArithmetic;
|
||||
ShiftRightLogical = context.ShiftRightLogical;
|
||||
|
||||
// BinaryU32
|
||||
GlslUMax = context.GlslUMax;
|
||||
GlslUMin = context.GlslUMin;
|
||||
|
||||
// AtomicMemoryBinary
|
||||
AtomicIAdd = context.AtomicIAdd;
|
||||
AtomicAnd = context.AtomicAnd;
|
||||
AtomicSMin = context.AtomicSMin;
|
||||
AtomicUMin = context.AtomicUMin;
|
||||
AtomicSMax = context.AtomicSMax;
|
||||
AtomicUMax = context.AtomicUMax;
|
||||
AtomicOr = context.AtomicOr;
|
||||
AtomicExchange = context.AtomicExchange;
|
||||
AtomicXor = context.AtomicXor;
|
||||
|
||||
// Ternary
|
||||
GlslFClamp = context.GlslFClamp;
|
||||
GlslSClamp = context.GlslSClamp;
|
||||
GlslFma = context.GlslFma;
|
||||
|
||||
// TernaryS32
|
||||
BitFieldSExtract = context.BitFieldSExtract;
|
||||
BitFieldUExtract = context.BitFieldUExtract;
|
||||
|
||||
// TernaryU32
|
||||
GlslUClamp = context.GlslUClamp;
|
||||
|
||||
// QuaternaryS32
|
||||
BitFieldInsert = context.BitFieldInsert;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
using Ryujinx.Graphics.Shader.IntermediateRepresentation;
|
||||
using Ryujinx.Common;
|
||||
using Ryujinx.Graphics.Shader.IntermediateRepresentation;
|
||||
using Ryujinx.Graphics.Shader.StructuredIr;
|
||||
using Ryujinx.Graphics.Shader.Translation;
|
||||
using System;
|
||||
|
@ -10,8 +11,24 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||
using SpvInstruction = Spv.Generator.Instruction;
|
||||
using SpvLiteralInteger = Spv.Generator.LiteralInteger;
|
||||
|
||||
using SpvInstructionPool = Spv.Generator.GeneratorPool<Spv.Generator.Instruction>;
|
||||
using SpvLiteralIntegerPool = Spv.Generator.GeneratorPool<Spv.Generator.LiteralInteger>;
|
||||
|
||||
static class SpirvGenerator
|
||||
{
|
||||
// Resource pools for Spirv generation. Note: Increase count when more threads are being used.
|
||||
private const int GeneratorPoolCount = 1;
|
||||
private static ObjectPool<SpvInstructionPool> InstructionPool;
|
||||
private static ObjectPool<SpvLiteralIntegerPool> IntegerPool;
|
||||
private static object PoolLock;
|
||||
|
||||
static SpirvGenerator()
|
||||
{
|
||||
InstructionPool = new (() => new SpvInstructionPool(), GeneratorPoolCount);
|
||||
IntegerPool = new (() => new SpvLiteralIntegerPool(), GeneratorPoolCount);
|
||||
PoolLock = new object();
|
||||
}
|
||||
|
||||
private const HelperFunctionsMask NeedsInvocationIdMask =
|
||||
HelperFunctionsMask.Shuffle |
|
||||
HelperFunctionsMask.ShuffleDown |
|
||||
|
@ -21,7 +38,16 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||
|
||||
public static byte[] Generate(StructuredProgramInfo info, ShaderConfig config)
|
||||
{
|
||||
CodeGenContext context = new CodeGenContext(config);
|
||||
SpvInstructionPool instPool;
|
||||
SpvLiteralIntegerPool integerPool;
|
||||
|
||||
lock (PoolLock)
|
||||
{
|
||||
instPool = InstructionPool.Allocate();
|
||||
integerPool = IntegerPool.Allocate();
|
||||
}
|
||||
|
||||
CodeGenContext context = new CodeGenContext(config, instPool, integerPool);
|
||||
|
||||
context.AddCapability(Capability.GroupNonUniformBallot);
|
||||
context.AddCapability(Capability.ImageBuffer);
|
||||
|
@ -70,7 +96,15 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||
Generate(context, info, funcIndex);
|
||||
}
|
||||
|
||||
return context.Generate();
|
||||
byte[] result = context.Generate();
|
||||
|
||||
lock (PoolLock)
|
||||
{
|
||||
InstructionPool.Release(instPool);
|
||||
IntegerPool.Release(integerPool);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void Generate(CodeGenContext context, StructuredProgramInfo info, int funcIndex)
|
||||
|
|
File diff suppressed because it is too large
Load diff
58
Spv.Generator/GeneratorPool.cs
Normal file
58
Spv.Generator/GeneratorPool.cs
Normal file
|
@ -0,0 +1,58 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace Spv.Generator
|
||||
{
|
||||
public class GeneratorPool<T> where T : class, new()
|
||||
{
|
||||
private List<T[]> _pool;
|
||||
private int _chunkIndex = -1;
|
||||
private int _poolIndex = -1;
|
||||
private int _initialSize;
|
||||
private int _poolSizeIncrement;
|
||||
|
||||
public GeneratorPool(): this(1000, 200) { }
|
||||
|
||||
public GeneratorPool(int chunkSizeLimit, int poolSizeIncrement)
|
||||
{
|
||||
_initialSize = chunkSizeLimit;
|
||||
_poolSizeIncrement = poolSizeIncrement;
|
||||
|
||||
_pool = new(chunkSizeLimit * 2);
|
||||
|
||||
AddChunkIfNeeded();
|
||||
}
|
||||
|
||||
public T Allocate()
|
||||
{
|
||||
if (++_poolIndex >= _poolSizeIncrement)
|
||||
{
|
||||
AddChunkIfNeeded();
|
||||
|
||||
_poolIndex = 0;
|
||||
}
|
||||
|
||||
return _pool[_chunkIndex][_poolIndex];
|
||||
}
|
||||
|
||||
private void AddChunkIfNeeded()
|
||||
{
|
||||
if (++_chunkIndex >= _pool.Count)
|
||||
{
|
||||
T[] pool = new T[_poolSizeIncrement];
|
||||
|
||||
for (int i = 0; i < _poolSizeIncrement; i++)
|
||||
{
|
||||
pool[i] = new T();
|
||||
}
|
||||
|
||||
_pool.Add(pool);
|
||||
}
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
_chunkIndex = 0;
|
||||
_poolIndex = -1;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -14,7 +14,9 @@ namespace Spv.Generator
|
|||
|
||||
public uint Id { get; set; }
|
||||
|
||||
public Instruction(Specification.Op opcode, uint id = InvalidId, Instruction resultType = null)
|
||||
public Instruction() { }
|
||||
|
||||
public void Set(Specification.Op opcode, uint id = InvalidId, Instruction resultType = null)
|
||||
{
|
||||
Opcode = opcode;
|
||||
Id = id;
|
||||
|
@ -55,7 +57,7 @@ namespace Spv.Generator
|
|||
|
||||
public ushort WordCount => 1;
|
||||
|
||||
private void AddOperand(Operand value)
|
||||
public void AddOperand(Operand value)
|
||||
{
|
||||
Debug.Assert(value != null);
|
||||
_operands.Add(value);
|
||||
|
@ -102,11 +104,6 @@ namespace Spv.Generator
|
|||
|
||||
public void AddOperand<T>(T value) where T: Enum
|
||||
{
|
||||
if (!typeof(T).IsPrimitive && !typeof(T).IsEnum)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
AddOperand(LiteralInteger.CreateForEnum(value));
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,19 @@ namespace Spv.Generator
|
|||
{
|
||||
public class LiteralInteger : Operand, IEquatable<LiteralInteger>
|
||||
{
|
||||
[ThreadStatic]
|
||||
private static GeneratorPool<LiteralInteger> _pool;
|
||||
|
||||
internal static void RegisterPool(GeneratorPool<LiteralInteger> pool)
|
||||
{
|
||||
_pool = pool;
|
||||
}
|
||||
|
||||
internal static void UnregisterPool()
|
||||
{
|
||||
_pool = null;
|
||||
}
|
||||
|
||||
public OperandType Type => OperandType.Number;
|
||||
|
||||
private enum IntegerType
|
||||
|
@ -20,26 +33,35 @@ namespace Spv.Generator
|
|||
private IntegerType _integerType;
|
||||
private ulong _data;
|
||||
|
||||
public ushort WordCount { get; }
|
||||
public ushort WordCount { get; private set; }
|
||||
|
||||
private LiteralInteger(ulong data, IntegerType integerType, ushort wordCount)
|
||||
public LiteralInteger() { }
|
||||
|
||||
private static LiteralInteger New()
|
||||
{
|
||||
return _pool.Allocate();
|
||||
}
|
||||
|
||||
private LiteralInteger Set(ulong data, IntegerType integerType, ushort wordCount)
|
||||
{
|
||||
_data = data;
|
||||
_integerType = integerType;
|
||||
|
||||
WordCount = wordCount;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public static implicit operator LiteralInteger(int value) => new LiteralInteger((ulong)value, IntegerType.Int32, 1);
|
||||
public static implicit operator LiteralInteger(uint value) => new LiteralInteger(value, IntegerType.UInt32, 1);
|
||||
public static implicit operator LiteralInteger(long value) => new LiteralInteger((ulong)value, IntegerType.Int64, 2);
|
||||
public static implicit operator LiteralInteger(ulong value) => new LiteralInteger(value, IntegerType.UInt64, 2);
|
||||
public static implicit operator LiteralInteger(float value) => new LiteralInteger(BitConverter.SingleToUInt32Bits(value), IntegerType.Float32, 1);
|
||||
public static implicit operator LiteralInteger(double value) => new LiteralInteger(BitConverter.DoubleToUInt64Bits(value), IntegerType.Float64, 2);
|
||||
public static implicit operator LiteralInteger(Enum value) => new LiteralInteger((ulong)Convert.ChangeType(value, typeof(ulong)), IntegerType.Int32, 1);
|
||||
public static implicit operator LiteralInteger(int value) => New().Set((ulong)value, IntegerType.Int32, 1);
|
||||
public static implicit operator LiteralInteger(uint value) => New().Set(value, IntegerType.UInt32, 1);
|
||||
public static implicit operator LiteralInteger(long value) => New().Set((ulong)value, IntegerType.Int64, 2);
|
||||
public static implicit operator LiteralInteger(ulong value) => New().Set(value, IntegerType.UInt64, 2);
|
||||
public static implicit operator LiteralInteger(float value) => New().Set(BitConverter.SingleToUInt32Bits(value), IntegerType.Float32, 1);
|
||||
public static implicit operator LiteralInteger(double value) => New().Set(BitConverter.DoubleToUInt64Bits(value), IntegerType.Float64, 2);
|
||||
public static implicit operator LiteralInteger(Enum value) => New().Set((ulong)(int)(object)value, IntegerType.Int32, 1);
|
||||
|
||||
// NOTE: this is not in the standard, but this is some syntax sugar useful in some instructions (TypeInt ect)
|
||||
public static implicit operator LiteralInteger(bool value) => new LiteralInteger(Convert.ToUInt64(value), IntegerType.Int32, 1);
|
||||
public static implicit operator LiteralInteger(bool value) => New().Set(Convert.ToUInt64(value), IntegerType.Int32, 1);
|
||||
|
||||
public static LiteralInteger CreateForEnum<T>(T value) where T : Enum
|
||||
{
|
||||
|
|
|
@ -37,7 +37,10 @@ namespace Spv.Generator
|
|||
|
||||
private List<Instruction> _functionsDefinitions;
|
||||
|
||||
public Module(uint version)
|
||||
private GeneratorPool<Instruction> _instPool;
|
||||
private GeneratorPool<LiteralInteger> _integerPool;
|
||||
|
||||
public Module(uint version, GeneratorPool<Instruction> instPool = null, GeneratorPool<LiteralInteger> integerPool = null)
|
||||
{
|
||||
_version = version;
|
||||
_bound = 1;
|
||||
|
@ -55,6 +58,11 @@ namespace Spv.Generator
|
|||
_globals = new List<Instruction>();
|
||||
_functionsDeclarations = new List<Instruction>();
|
||||
_functionsDefinitions = new List<Instruction>();
|
||||
|
||||
_instPool = instPool ?? new GeneratorPool<Instruction>();
|
||||
_integerPool = integerPool ?? new GeneratorPool<LiteralInteger>();
|
||||
|
||||
LiteralInteger.RegisterPool(_integerPool);
|
||||
}
|
||||
|
||||
private uint GetNewId()
|
||||
|
@ -72,6 +80,14 @@ namespace Spv.Generator
|
|||
_extensions.Add(extension);
|
||||
}
|
||||
|
||||
public Instruction NewInstruction(Op opcode, uint id = Instruction.InvalidId, Instruction resultType = null)
|
||||
{
|
||||
var result = _instPool.Allocate();
|
||||
result.Set(opcode, id, resultType);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public Instruction AddExtInstImport(string import)
|
||||
{
|
||||
var key = new DeterministicStringKey(import);
|
||||
|
@ -82,7 +98,7 @@ namespace Spv.Generator
|
|||
return extInstImport;
|
||||
}
|
||||
|
||||
Instruction instruction = new Instruction(Op.OpExtInstImport);
|
||||
Instruction instruction = NewInstruction(Op.OpExtInstImport);
|
||||
instruction.AddOperand(import);
|
||||
|
||||
instruction.SetId(GetNewId());
|
||||
|
@ -117,7 +133,7 @@ namespace Spv.Generator
|
|||
{
|
||||
Debug.Assert(function.Opcode == Op.OpFunction);
|
||||
|
||||
Instruction entryPoint = new Instruction(Op.OpEntryPoint);
|
||||
Instruction entryPoint = NewInstruction(Op.OpEntryPoint);
|
||||
|
||||
entryPoint.AddOperand(executionModel);
|
||||
entryPoint.AddOperand(function);
|
||||
|
@ -131,7 +147,7 @@ namespace Spv.Generator
|
|||
{
|
||||
Debug.Assert(function.Opcode == Op.OpFunction);
|
||||
|
||||
Instruction executionModeInstruction = new Instruction(Op.OpExecutionMode);
|
||||
Instruction executionModeInstruction = NewInstruction(Op.OpExecutionMode);
|
||||
|
||||
executionModeInstruction.AddOperand(function);
|
||||
executionModeInstruction.AddOperand(mode);
|
||||
|
@ -212,7 +228,7 @@ namespace Spv.Generator
|
|||
|
||||
public Instruction ExtInst(Instruction resultType, Instruction set, LiteralInteger instruction, params Operand[] parameters)
|
||||
{
|
||||
Instruction result = new Instruction(Op.OpExtInst, GetNewId(), resultType);
|
||||
Instruction result = NewInstruction(Op.OpExtInst, GetNewId(), resultType);
|
||||
|
||||
result.AddOperand(set);
|
||||
result.AddOperand(instruction);
|
||||
|
@ -231,7 +247,7 @@ namespace Spv.Generator
|
|||
// TODO: Found a way to make the auto generate one used.
|
||||
public Instruction OpenClPrintf(Instruction resultType, Instruction format, params Instruction[] additionalarguments)
|
||||
{
|
||||
Instruction result = new Instruction(Op.OpExtInst, GetNewId(), resultType);
|
||||
Instruction result = NewInstruction(Op.OpExtInst, GetNewId(), resultType);
|
||||
|
||||
result.AddOperand(AddExtInstImport("OpenCL.std"));
|
||||
result.AddOperand((LiteralInteger)184);
|
||||
|
@ -244,7 +260,10 @@ namespace Spv.Generator
|
|||
|
||||
public byte[] Generate()
|
||||
{
|
||||
using (MemoryStream stream = new MemoryStream())
|
||||
// Estimate the size needed for the generated code, to avoid expanding the MemoryStream.
|
||||
int sizeEstimate = 1024 + _functionsDefinitions.Count * 32;
|
||||
|
||||
using (MemoryStream stream = new MemoryStream(sizeEstimate))
|
||||
{
|
||||
BinaryWriter writer = new BinaryWriter(stream, System.Text.Encoding.ASCII);
|
||||
|
||||
|
@ -258,7 +277,7 @@ namespace Spv.Generator
|
|||
// 1.
|
||||
foreach (Capability capability in _capabilities)
|
||||
{
|
||||
Instruction capabilityInstruction = new Instruction(Op.OpCapability);
|
||||
Instruction capabilityInstruction = NewInstruction(Op.OpCapability);
|
||||
|
||||
capabilityInstruction.AddOperand(capability);
|
||||
capabilityInstruction.Write(writer);
|
||||
|
@ -267,7 +286,7 @@ namespace Spv.Generator
|
|||
// 2.
|
||||
foreach (string extension in _extensions)
|
||||
{
|
||||
Instruction extensionInstruction = new Instruction(Op.OpExtension);
|
||||
Instruction extensionInstruction = NewInstruction(Op.OpExtension);
|
||||
|
||||
extensionInstruction.AddOperand(extension);
|
||||
extensionInstruction.Write(writer);
|
||||
|
@ -280,7 +299,7 @@ namespace Spv.Generator
|
|||
}
|
||||
|
||||
// 4.
|
||||
Instruction memoryModelInstruction = new Instruction(Op.OpMemoryModel);
|
||||
Instruction memoryModelInstruction = NewInstruction(Op.OpMemoryModel);
|
||||
memoryModelInstruction.AddOperand(_addressingModel);
|
||||
memoryModelInstruction.AddOperand(_memoryModel);
|
||||
memoryModelInstruction.Write(writer);
|
||||
|
@ -335,6 +354,11 @@ namespace Spv.Generator
|
|||
functionDefinition.Write(writer);
|
||||
}
|
||||
|
||||
_instPool.Clear();
|
||||
_integerPool.Clear();
|
||||
|
||||
LiteralInteger.UnregisterPool();
|
||||
|
||||
return stream.ToArray();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue