diff options
Diffstat (limited to 'src/Ryujinx.Graphics.Shader/CodeGen/Glsl')
10 files changed, 95 insertions, 193 deletions
diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs index 81b79ec4..8d805e32 100644 --- a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs +++ b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs @@ -3,6 +3,7 @@ using Ryujinx.Graphics.Shader.StructuredIr; using Ryujinx.Graphics.Shader.Translation; using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Numerics; @@ -102,13 +103,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl context.AppendLine(); } - var cBufferDescriptors = context.Config.GetConstantBufferDescriptors(); - if (cBufferDescriptors.Length != 0) - { - DeclareUniforms(context, cBufferDescriptors); - - context.AppendLine(); - } + DeclareConstantBuffers(context, context.Config.Properties.ConstantBuffers.Values); var sBufferDescriptors = context.Config.GetStorageBufferDescriptors(); if (sBufferDescriptors.Length != 0) @@ -265,18 +260,12 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl scaleElements++; // Also includes render target scale, for gl_FragCoord. } - DeclareSupportUniformBlock(context, context.Config.Stage, scaleElements); - if (context.Config.UsedFeatures.HasFlag(FeatureFlags.IntegerSampling) && scaleElements != 0) { AppendHelperFunction(context, $"Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/TexelFetchScale_{stage}.glsl"); context.AppendLine(); } } - else if (isFragment || context.Config.Stage == ShaderStage.Vertex) - { - DeclareSupportUniformBlock(context, context.Config.Stage, 0); - } } if ((info.HelperFunctionsMask & HelperFunctionsMask.AtomicMinMaxS32Shared) != 0) @@ -389,36 +378,38 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl }; } - private static void DeclareUniforms(CodeGenContext context, BufferDescriptor[] descriptors) + private static void DeclareConstantBuffers(CodeGenContext context, IEnumerable<BufferDefinition> buffers) { - string ubSize = "[" + NumberFormatter.FormatInt(Constants.ConstantBufferSize / 16) + "]"; - - if (context.Config.UsedFeatures.HasFlag(FeatureFlags.CbIndexing)) + foreach (BufferDefinition buffer in buffers) { - string ubName = OperandManager.GetShaderStagePrefix(context.Config.Stage); - - ubName += "_" + DefaultNames.UniformNamePrefix; - - string blockName = $"{ubName}_{DefaultNames.BlockSuffix}"; + string layout = buffer.Layout switch + { + BufferLayout.Std140 => "std140", + _ => "std430" + }; - context.AppendLine($"layout (binding = {context.Config.FirstConstantBufferBinding}, std140) uniform {blockName}"); + context.AppendLine($"layout (binding = {buffer.Binding}, {layout}) uniform _{buffer.Name}"); context.EnterScope(); - context.AppendLine("vec4 " + DefaultNames.DataName + ubSize + ";"); - context.LeaveScope($" {ubName}[{NumberFormatter.FormatInt(descriptors.Max(x => x.Slot) + 1)}];"); - } - else - { - foreach (var descriptor in descriptors) + + foreach (StructureField field in buffer.Type.Fields) { - string ubName = OperandManager.GetShaderStagePrefix(context.Config.Stage); + if (field.Type.HasFlag(AggregateType.Array)) + { + string typeName = GetVarTypeName(context, field.Type & ~AggregateType.Array); + string arraySize = field.ArrayLength.ToString(CultureInfo.InvariantCulture); - ubName += "_" + DefaultNames.UniformNamePrefix + descriptor.Slot; + context.AppendLine($"{typeName} {field.Name}[{arraySize}];"); + } + else + { + string typeName = GetVarTypeName(context, field.Type); - context.AppendLine($"layout (binding = {descriptor.Binding}, std140) uniform {ubName}"); - context.EnterScope(); - context.AppendLine("vec4 " + OperandManager.GetUbName(context.Config.Stage, descriptor.Slot, false) + ubSize + ";"); - context.LeaveScope(";"); + context.AppendLine($"{typeName} {field.Name};"); + } } + + context.LeaveScope($" {buffer.Name};"); + context.AppendLine(); } } @@ -759,39 +750,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl context.AppendLine($"layout (location = {location}) patch out vec4 {name};"); } - private static void DeclareSupportUniformBlock(CodeGenContext context, ShaderStage stage, int scaleElements) - { - bool needsSupportBlock = stage == ShaderStage.Fragment || - (context.Config.LastInVertexPipeline && context.Config.GpuAccessor.QueryViewportTransformDisable()); - - if (!needsSupportBlock && scaleElements == 0) - { - return; - } - - context.AppendLine($"layout (binding = 0, std140) uniform {DefaultNames.SupportBlockName}"); - context.EnterScope(); - - switch (stage) - { - case ShaderStage.Fragment: - case ShaderStage.Vertex: - context.AppendLine($"uint {DefaultNames.SupportBlockAlphaTestName};"); - context.AppendLine($"bool {DefaultNames.SupportBlockIsBgraName}[{SupportBuffer.FragmentIsBgraCount}];"); - context.AppendLine($"vec4 {DefaultNames.SupportBlockViewportInverse};"); - context.AppendLine($"int {DefaultNames.SupportBlockFragmentScaleCount};"); - break; - case ShaderStage.Compute: - context.AppendLine($"uint s_reserved[{SupportBuffer.ComputeRenderScaleOffset / SupportBuffer.FieldSize}];"); - break; - } - - context.AppendLine($"float {DefaultNames.SupportBlockRenderScaleName}[{SupportBuffer.RenderScaleMaxCount}];"); - - context.LeaveScope(";"); - context.AppendLine(); - } - private static void AppendHelperFunction(CodeGenContext context, string filename) { string code = EmbeddedResources.ReadAllText(filename); diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/DefaultNames.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/DefaultNames.cs index 3ab4814c..fc3004a8 100644 --- a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/DefaultNames.cs +++ b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/DefaultNames.cs @@ -15,18 +15,8 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl public const string DataName = "data"; - public const string SupportBlockName = "support_block"; - public const string SupportBlockAlphaTestName = "s_alpha_test"; - public const string SupportBlockIsBgraName = "s_is_bgra"; - public const string SupportBlockViewportInverse = "s_viewport_inverse"; - public const string SupportBlockFragmentScaleCount = "s_frag_scale_count"; - public const string SupportBlockRenderScaleName = "s_render_scale"; - public const string BlockSuffix = "block"; - public const string UniformNamePrefix = "c"; - public const string UniformNameSuffix = "data"; - public const string LocalMemoryName = "local_mem"; public const string SharedMemoryName = "shared_mem"; diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/TexelFetchScale_cp.glsl b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/TexelFetchScale_cp.glsl index 4ebade5e..08c62548 100644 --- a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/TexelFetchScale_cp.glsl +++ b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/TexelFetchScale_cp.glsl @@ -1,6 +1,6 @@ ivec2 Helper_TexelFetchScale(ivec2 inputVec, int samplerIndex) { - float scale = s_render_scale[samplerIndex]; + float scale = support_buffer.s_render_scale[1 + samplerIndex]; if (scale == 1.0) { return inputVec; @@ -10,7 +10,7 @@ int Helper_TextureSizeUnscale(int size, int samplerIndex) { - float scale = s_render_scale[samplerIndex]; + float scale = support_buffer.s_render_scale[1 + samplerIndex]; if (scale == 1.0) { return size; diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/TexelFetchScale_fp.glsl b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/TexelFetchScale_fp.glsl index 6c670f91..07a38a7a 100644 --- a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/TexelFetchScale_fp.glsl +++ b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/TexelFetchScale_fp.glsl @@ -1,6 +1,6 @@ ivec2 Helper_TexelFetchScale(ivec2 inputVec, int samplerIndex) { - float scale = s_render_scale[1 + samplerIndex]; + float scale = support_buffer.s_render_scale[1 + samplerIndex]; if (scale == 1.0) { return inputVec; @@ -17,7 +17,7 @@ int Helper_TextureSizeUnscale(int size, int samplerIndex) { - float scale = abs(s_render_scale[1 + samplerIndex]); + float scale = abs(support_buffer.s_render_scale[1 + samplerIndex]); if (scale == 1.0) { return size; diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/TexelFetchScale_vp.glsl b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/TexelFetchScale_vp.glsl index 19eb119d..72baa441 100644 --- a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/TexelFetchScale_vp.glsl +++ b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/TexelFetchScale_vp.glsl @@ -1,6 +1,6 @@ ivec2 Helper_TexelFetchScale(ivec2 inputVec, int samplerIndex) { - float scale = abs(s_render_scale[1 + samplerIndex + s_frag_scale_count]); + float scale = abs(support_buffer.s_render_scale[1 + samplerIndex + support_buffer.s_frag_scale_count]); if (scale == 1.0) { return inputVec; @@ -11,7 +11,7 @@ int Helper_TextureSizeUnscale(int size, int samplerIndex) { - float scale = abs(s_render_scale[1 + samplerIndex + s_frag_scale_count]); + float scale = abs(support_buffer.s_render_scale[1 + samplerIndex + support_buffer.s_frag_scale_count]); if (scale == 1.0) { return size; diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGen.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGen.cs index 01bd11e5..24ea66d0 100644 --- a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGen.cs +++ b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGen.cs @@ -167,9 +167,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions case Instruction.Load: return Load(context, operation); - case Instruction.LoadConstant: - return LoadConstant(context, operation); - case Instruction.LoadLocal: return LoadLocal(context, operation); diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenHelper.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenHelper.cs index 00478f6a..71e40fe7 100644 --- a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenHelper.cs +++ b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenHelper.cs @@ -83,7 +83,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions Add(Instruction.ImageAtomic, InstType.Special); Add(Instruction.IsNan, InstType.CallUnary, "isnan"); Add(Instruction.Load, InstType.Special); - Add(Instruction.LoadConstant, InstType.Special); Add(Instruction.LoadLocal, InstType.Special); Add(Instruction.LoadShared, InstType.Special); Add(Instruction.LoadStorage, InstType.Special); diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenMemory.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenMemory.cs index 99519837..ef5260d1 100644 --- a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenMemory.cs +++ b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenMemory.cs @@ -215,29 +215,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions return GenerateLoadOrStore(context, operation, isStore: false); } - public static string LoadConstant(CodeGenContext context, AstOperation operation) - { - IAstNode src1 = operation.GetSource(0); - IAstNode src2 = operation.GetSource(1); - - string offsetExpr = GetSoureExpr(context, src2, GetSrcVarType(operation.Inst, 1)); - offsetExpr = Enclose(offsetExpr, src2, Instruction.ShiftRightS32, isLhs: true); - - var config = context.Config; - bool indexElement = !config.GpuAccessor.QueryHostHasVectorIndexingBug(); - - if (src1 is AstOperand operand && operand.Type == OperandType.Constant) - { - bool cbIndexable = config.UsedFeatures.HasFlag(Translation.FeatureFlags.CbIndexing); - return OperandManager.GetConstantBufferName(operand.Value, offsetExpr, config.Stage, cbIndexable, indexElement); - } - else - { - string slotExpr = GetSoureExpr(context, src1, GetSrcVarType(operation.Inst, 0)); - return OperandManager.GetConstantBufferName(slotExpr, offsetExpr, config.Stage, indexElement); - } - } - public static string LoadLocal(CodeGenContext context, AstOperation operation) { return LoadLocalOrShared(context, operation, DefaultNames.LocalMemoryName); @@ -809,9 +786,29 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions string varName; AggregateType varType; int srcIndex = 0; + int inputsCount = isStore ? operation.SourcesCount - 1 : operation.SourcesCount; switch (storageKind) { + case StorageKind.ConstantBuffer: + if (!(operation.GetSource(srcIndex++) is AstOperand bindingIndex) || bindingIndex.Type != OperandType.Constant) + { + throw new InvalidOperationException($"First input of {operation.Inst} with {storageKind} storage must be a constant operand."); + } + + int binding = bindingIndex.Value; + BufferDefinition buffer = context.Config.Properties.ConstantBuffers[binding]; + + if (!(operation.GetSource(srcIndex++) is AstOperand fieldIndex) || fieldIndex.Type != OperandType.Constant) + { + throw new InvalidOperationException($"Second input of {operation.Inst} with {storageKind} storage must be a constant operand."); + } + + StructureField field = buffer.Type.Fields[fieldIndex.Value]; + varName = $"{buffer.Name}.{field.Name}"; + varType = field.Type; + break; + case StorageKind.Input: case StorageKind.InputPerPatch: case StorageKind.Output: @@ -864,40 +861,39 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions varName = $"gl_out[{expr}].{varName}"; } } - - int firstSrcIndex = srcIndex; - int inputsCount = isStore ? operation.SourcesCount - 1 : operation.SourcesCount; - - for (; srcIndex < inputsCount; srcIndex++) - { - IAstNode src = operation.GetSource(srcIndex); - - if ((varType & AggregateType.ElementCountMask) != 0 && - srcIndex == inputsCount - 1 && - src is AstOperand elementIndex && - elementIndex.Type == OperandType.Constant) - { - varName += "." + "xyzw"[elementIndex.Value & 3]; - } - else if (srcIndex == firstSrcIndex && context.Config.Stage == ShaderStage.TessellationControl && storageKind == StorageKind.Output) - { - // GLSL requires that for tessellation control shader outputs, - // that the index expression must be *exactly* "gl_InvocationID", - // otherwise the compilation fails. - // TODO: Get rid of this and use expression propagation to make sure we generate the correct code from IR. - varName += "[gl_InvocationID]"; - } - else - { - varName += $"[{GetSoureExpr(context, src, AggregateType.S32)}]"; - } - } break; default: throw new InvalidOperationException($"Invalid storage kind {storageKind}."); } + int firstSrcIndex = srcIndex; + + for (; srcIndex < inputsCount; srcIndex++) + { + IAstNode src = operation.GetSource(srcIndex); + + if ((varType & AggregateType.ElementCountMask) != 0 && + srcIndex == inputsCount - 1 && + src is AstOperand elementIndex && + elementIndex.Type == OperandType.Constant) + { + varName += "." + "xyzw"[elementIndex.Value & 3]; + } + else if (srcIndex == firstSrcIndex && context.Config.Stage == ShaderStage.TessellationControl && storageKind == StorageKind.Output) + { + // GLSL requires that for tessellation control shader outputs, + // that the index expression must be *exactly* "gl_InvocationID", + // otherwise the compilation fails. + // TODO: Get rid of this and use expression propagation to make sure we generate the correct code from IR. + varName += "[gl_InvocationID]"; + } + else + { + varName += $"[{GetSoureExpr(context, src, AggregateType.S32)}]"; + } + } + if (isStore) { varType &= AggregateType.ElementTypeMask; diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/IoMap.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/IoMap.cs index 093ee232..2a73b8b0 100644 --- a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/IoMap.cs +++ b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/IoMap.cs @@ -27,7 +27,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions IoVariable.FragmentCoord => ("gl_FragCoord", AggregateType.Vector4 | AggregateType.FP32), IoVariable.FragmentOutputColor => GetFragmentOutputColorVariableName(config, location), IoVariable.FragmentOutputDepth => ("gl_FragDepth", AggregateType.FP32), - IoVariable.FragmentOutputIsBgra => (DefaultNames.SupportBlockIsBgraName, AggregateType.Array | AggregateType.Bool), IoVariable.FrontColorDiffuse => ("gl_FrontColor", AggregateType.Vector4 | AggregateType.FP32), // Deprecated. IoVariable.FrontColorSpecular => ("gl_FrontSecondaryColor", AggregateType.Vector4 | AggregateType.FP32), // Deprecated. IoVariable.FrontFacing => ("gl_FrontFacing", AggregateType.Bool), @@ -46,8 +45,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions IoVariable.SubgroupLaneId => GetSubgroupInvocationIdVariableName(config), IoVariable.SubgroupLeMask => GetSubgroupMaskVariableName(config, "Le"), IoVariable.SubgroupLtMask => GetSubgroupMaskVariableName(config, "Lt"), - IoVariable.SupportBlockRenderScale => (DefaultNames.SupportBlockRenderScaleName, AggregateType.Array | AggregateType.FP32), - IoVariable.SupportBlockViewInverse => (DefaultNames.SupportBlockViewportInverse, AggregateType.Vector2 | AggregateType.FP32), IoVariable.TessellationCoord => ("gl_TessCoord", AggregateType.Vector3 | AggregateType.FP32), IoVariable.TessellationLevelInner => ("gl_TessLevelInner", AggregateType.Array | AggregateType.FP32), IoVariable.TessellationLevelOuter => ("gl_TessLevelOuter", AggregateType.Array | AggregateType.FP32), diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs index 92e83358..e34e4e07 100644 --- a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs +++ b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs @@ -36,63 +36,12 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl { OperandType.Argument => GetArgumentName(operand.Value), OperandType.Constant => NumberFormatter.FormatInt(operand.Value), - OperandType.ConstantBuffer => GetConstantBufferName(operand, context.Config), OperandType.LocalVariable => _locals[operand], OperandType.Undefined => DefaultNames.UndefinedName, _ => throw new ArgumentException($"Invalid operand type \"{operand.Type}\".") }; } - private static string GetConstantBufferName(AstOperand operand, ShaderConfig config) - { - return GetConstantBufferName(operand.CbufSlot, operand.CbufOffset, config.Stage, config.UsedFeatures.HasFlag(FeatureFlags.CbIndexing)); - } - - public static string GetConstantBufferName(int slot, int offset, ShaderStage stage, bool cbIndexable) - { - return $"{GetUbName(stage, slot, cbIndexable)}[{offset >> 2}].{GetSwizzleMask(offset & 3)}"; - } - - private static string GetVec4Indexed(string vectorName, string indexExpr, bool indexElement) - { - if (indexElement) - { - return $"{vectorName}[{indexExpr}]"; - } - - string result = $"{vectorName}.x"; - for (int i = 1; i < 4; i++) - { - result = $"(({indexExpr}) == {i}) ? ({vectorName}.{GetSwizzleMask(i)}) : ({result})"; - } - return $"({result})"; - } - - public static string GetConstantBufferName(int slot, string offsetExpr, ShaderStage stage, bool cbIndexable, bool indexElement) - { - return GetVec4Indexed(GetUbName(stage, slot, cbIndexable) + $"[{offsetExpr} >> 2]", offsetExpr + " & 3", indexElement); - } - - public static string GetConstantBufferName(string slotExpr, string offsetExpr, ShaderStage stage, bool indexElement) - { - return GetVec4Indexed(GetUbName(stage, slotExpr) + $"[{offsetExpr} >> 2]", offsetExpr + " & 3", indexElement); - } - - public static string GetUbName(ShaderStage stage, int slot, bool cbIndexable) - { - if (cbIndexable) - { - return GetUbName(stage, NumberFormatter.FormatInt(slot, AggregateType.S32)); - } - - return $"{GetShaderStagePrefix(stage)}_{DefaultNames.UniformNamePrefix}{slot}_{DefaultNames.UniformNameSuffix}"; - } - - private static string GetUbName(ShaderStage stage, string slotExpr) - { - return $"{GetShaderStagePrefix(stage)}_{DefaultNames.UniformNamePrefix}[{slotExpr}].{DefaultNames.DataName}"; - } - public static string GetSamplerName(ShaderStage stage, AstTextureOperation texOp, string indexExpr) { return GetSamplerName(stage, texOp.CbufSlot, texOp.Handle, texOp.Type.HasFlag(SamplerType.Indexed), indexExpr); @@ -168,6 +117,22 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl { switch (operation.StorageKind) { + case StorageKind.ConstantBuffer: + if (!(operation.GetSource(0) is AstOperand bindingIndex) || bindingIndex.Type != OperandType.Constant) + { + throw new InvalidOperationException($"First input of {operation.Inst} with {operation.StorageKind} storage must be a constant operand."); + } + + if (!(operation.GetSource(1) is AstOperand fieldIndex) || fieldIndex.Type != OperandType.Constant) + { + throw new InvalidOperationException($"Second input of {operation.Inst} with {operation.StorageKind} storage must be a constant operand."); + } + + BufferDefinition buffer = context.Config.Properties.ConstantBuffers[bindingIndex.Value]; + StructureField field = buffer.Type.Fields[fieldIndex.Value]; + + return field.Type & AggregateType.ElementTypeMask; + case StorageKind.Input: case StorageKind.InputPerPatch: case StorageKind.Output: |