4 using System.Collections.Generic;
7 using SiliconStudio.Core.Mathematics;
8 using SiliconStudio.Paradox.Shaders.Parser.Ast;
9 using SiliconStudio.Paradox.Shaders.Parser.Mixins;
10 using SiliconStudio.Paradox.Shaders.Parser.Utility;
11 using SiliconStudio.Shaders.Ast;
12 using SiliconStudio.Shaders.Ast.Hlsl;
13 using SiliconStudio.Shaders.Visitor;
14 using SiliconStudio.Paradox.Graphics;
18 namespace SiliconStudio.
Paradox.Shaders.Parser
25 private readonly Dictionary<string, SamplerStateDescription> samplers =
new Dictionary<string, SamplerStateDescription>();
26 private readonly EffectReflection effectReflection;
27 private readonly Dictionary<ShaderConstantBufferDescription, List<EffectParameterValueData>> valueBindings =
new Dictionary<ShaderConstantBufferDescription, List<EffectParameterValueData>>();
28 private readonly ShaderMixinParsingResult parsingResult;
34 public ShaderLinker(ShaderMixinParsingResult parsingResult)
37 this.parsingResult = parsingResult;
38 this.effectReflection = parsingResult.Reflection;
56 public void Run(
Shader shader)
58 PrepareConstantBuffers(shader);
60 foreach (var valueBinding
in valueBindings)
62 valueBinding.Key.Members = valueBinding.Value.ToArray();
66 private void PrepareConstantBuffers(
Shader shader)
70 var declarations = shader.Declarations.Where(declaration => !(declaration is
MethodDeclaration) && !(declaration is
Variable)).ToList();
71 var variables = shader.Declarations.OfType<Variable>();
73 var newVariables =
new List<Node>();
75 var constantBuffers =
new Dictionary<string, ConstantBuffer>();
77 foreach (var variableGroup
in variables)
79 foreach (var variable
in variableGroup.Instances())
83 var type = variable.Type;
86 var arrayType = (ArrayType)type;
87 type = arrayType.Type;
92 if (constantBufferName == null && !(type.ResolveType() is
ObjectType)
94 && !variable.Qualifiers.Contains(SiliconStudio.Shaders.Ast.Hlsl.StorageQualifier.Static)
95 && !variable.Qualifiers.Contains(SiliconStudio.Shaders.Ast.Hlsl.StorageQualifier.Groupshared))
97 constantBufferName =
"Globals";
100 if (constantBufferName == null)
102 declarations.Insert(0, variable);
108 variable.InitialValue = null;
111 if (!constantBuffers.TryGetValue(constantBufferName, out constantBuffer))
113 constantBuffer =
new ConstantBuffer {Name = constantBufferName, Type = SiliconStudio.Shaders.Ast.Hlsl.ConstantBufferType.Constant};
114 constantBuffers.Add(constantBufferName, constantBuffer);
115 newVariables.Add(constantBuffer);
118 constantBuffer.Members.Add(variable);
123 declarations.AddRange(newVariables);
124 declarations.AddRange(methods);
126 shader.Declarations = declarations;
136 protected void Visit(
Variable variable)
138 var parameterKey = GetLinkParameterKey(variable);
139 if (parameterKey == null)
return;
141 var resolvedType = variable.Type.ResolveType();
144 resolvedType = ((ArrayType)resolvedType).Type;
148 var samplerState = SamplerStateDescription.Default;
151 if (stateInitializer != null)
155 string key = samplerField.Target.ToString();
156 string value = samplerField.Value.ToString();
162 case "COMPARISON_MIN_MAG_LINEAR_MIP_POINT":
163 samplerState.Filter = TextureFilter.ComparisonMinMagLinearMipPoint;
165 case "COMPARISON_MIN_MAG_MIP_POINT":
166 samplerState.Filter = TextureFilter.ComparisonPoint;
168 case "MIN_MAG_LINEAR_MIP_POINT":
169 samplerState.Filter = TextureFilter.MinMagLinearMipPoint;
171 case "MIN_MAG_MIP_LINEAR":
172 samplerState.Filter = TextureFilter.Linear;
175 samplerState.Filter = TextureFilter.Anisotropic;
177 case "MIN_MAG_MIP_POINT":
181 parsingResult.Error(ParadoxMessageCode.SamplerFilterNotSupported, variable.Span, value);
185 else if (key ==
"ComparisonFunc")
188 Enum.TryParse(value,
true, out compareFunction);
189 samplerState.CompareFunction = compareFunction;
191 else if (key ==
"AddressU" || key ==
"AddressV" || key ==
"AddressW")
194 Enum.TryParse(value,
true, out textureAddressMode);
198 samplerState.AddressU = textureAddressMode;
201 samplerState.AddressV = textureAddressMode;
204 samplerState.AddressW = textureAddressMode;
207 parsingResult.Error(ParadoxMessageCode.SamplerAddressModeNotSupported, variable.Span, key);
211 else if (key ==
"BorderColor")
214 if (borderColor != null)
217 if (targetType != null && targetType.Type.ResolveType() == VectorType.Float4 && borderColor.Arguments.Count == 4)
219 var values =
new float[4];
220 for (
int i = 0; i < 4; i++)
223 if (argValue != null)
225 values[i] = (float)
Convert.ChangeType(argValue.Value, typeof(
float));
229 parsingResult.Error(ParadoxMessageCode.SamplerBorderColorNotSupported, variable.Span, borderColor.Arguments[i]);
233 samplerState.BorderColor =
new Color4(values);
237 parsingResult.Error(ParadoxMessageCode.SamplerBorderColorNotSupported, variable.Span, variable);
242 parsingResult.Error(ParadoxMessageCode.SamplerBorderColorNotSupported, variable.Span, variable);
245 else if (key ==
"MinLOD")
247 samplerState.MinMipLevel = float.Parse(value);
249 else if (key ==
"MaxLOD")
251 samplerState.MaxMipLevel = float.Parse(value);
253 else if (key ==
"MaxAnisotropy")
255 samplerState.MaxAnisotropy = int.Parse(value);
259 parsingResult.Error(ParadoxMessageCode.SamplerFieldNotSupported, variable.Span, variable);
264 effectReflection.SamplerStates.Add(
new EffectSamplerStateBinding(parameterKey.Name, samplerState));
265 LinkVariable(effectReflection, variable.
Name, parameterKey);
269 LinkVariable(effectReflection, variable.
Name, parameterKey);
273 ParseConstantBufferVariable(
"$Globals", variable);
285 foreach (var variable
in constantBuffer.
Members.OfType<
Variable>().SelectMany(x => x.Instances()))
287 ParseConstantBufferVariable(constantBuffer.
Name, variable);
296 var streamOutputAttribute = method.Attributes.OfType<
AttributeDeclaration>().FirstOrDefault(x => x.Name ==
"StreamOutput");
297 if (streamOutputAttribute != null)
299 var rasterizedStream = streamOutputAttribute.Parameters.LastOrDefault();
303 if (rasterizedStream != null && !(rasterizedStream.Value is
int))
304 rasterizedStream = null;
306 int[] streamOutputStrides;
310 StreamOutputParser.Parse(effectReflection.ShaderStreamOutputDeclarations, out streamOutputStrides, streamOutputAttribute, ((
StructType)FindDeclaration(
"GS_OUTPUT")).Fields);
312 effectReflection.StreamOutputStrides = streamOutputStrides;
313 effectReflection.StreamOutputRasterizedStream = rasterizedStream != null ? (int)rasterizedStream.Value : -1;
319 protected override Node Visit(
Node node)
323 var parameterKey = this.GetLinkParameterKey(node);
324 if (parameterKey != null)
325 LinkVariable(effectReflection, ((IDeclaration)node).Name, parameterKey);
328 node.Childrens(OnProcessor);
334 return VisitDynamic(nodeArg);
337 private LocalParameterKey GetLinkParameterKey(
Node node)
342 if ((qualifiers != null && (qualifiers.Qualifiers.Contains(SiliconStudio.Shaders.Ast.Hlsl.StorageQualifier.Static) ||
343 qualifiers.Qualifiers.Contains(StorageQualifier.Const) ||
344 qualifiers.Qualifiers.Contains(SiliconStudio.Shaders.Ast.Hlsl.StorageQualifier.Groupshared)
345 )) || attributable == null)
350 bool isColor = attributable.Attributes.OfType<
AttributeDeclaration>().Any(x => x.Name ==
"Color");
354 if (annotation.Name !=
"Link" || annotation.Parameters.Count < 1)
359 var variableName = (string)annotation.Parameters[0].Value;
360 var parameterKey =
new LocalParameterKey() {Name = variableName};
362 if (variable != null)
364 var variableType = variable.Type;
366 if (variableType.TypeInference.TargetType != null)
367 variableType = variableType.TypeInference.TargetType;
371 var arrayType = (ArrayType)variableType;
372 variableType = arrayType.Type;
375 if (variableType.TypeInference.TargetType != null)
376 variableType = variableType.TypeInference.TargetType;
379 if (variableType.IsBuiltIn)
381 var variableTypeName = variableType.Name.Text.ToLower();
383 switch (variableTypeName)
391 parameterKey.Class = EffectParameterClass.TextureBuffer;
392 parameterKey.Type = EffectParameterType.TextureBuffer;
395 case "structuredbuffer":
396 parameterKey.Class = EffectParameterClass.ShaderResourceView;
397 parameterKey.Type = EffectParameterType.StructuredBuffer;
399 case "rwstructuredbuffer":
400 parameterKey.Class = EffectParameterClass.UnorderedAccessView;
401 parameterKey.Type = EffectParameterType.RWStructuredBuffer;
403 case "consumestructuredbuffer":
404 parameterKey.Class = EffectParameterClass.UnorderedAccessView;
405 parameterKey.Type = EffectParameterType.ConsumeStructuredBuffer;
407 case "appendstructuredbuffer":
408 parameterKey.Class = EffectParameterClass.UnorderedAccessView;
409 parameterKey.Type = EffectParameterType.AppendStructuredBuffer;
412 parameterKey.Class = EffectParameterClass.ShaderResourceView;
416 parameterKey.Class = EffectParameterClass.UnorderedAccessView;
417 parameterKey.Type = EffectParameterType.RWBuffer;
419 case "byteaddressbuffer":
420 parameterKey.Class = EffectParameterClass.ShaderResourceView;
421 parameterKey.Type = EffectParameterType.ByteAddressBuffer;
423 case "rwbyteaddressbuffer":
424 parameterKey.Class = EffectParameterClass.UnorderedAccessView;
425 parameterKey.Type = EffectParameterType.RWByteAddressBuffer;
429 parameterKey.Class = EffectParameterClass.ShaderResourceView;
430 parameterKey.Type = EffectParameterType.Texture1D;
434 parameterKey.Class = EffectParameterClass.ShaderResourceView;
435 parameterKey.Type = EffectParameterType.TextureCube;
439 parameterKey.Class = EffectParameterClass.ShaderResourceView;
440 parameterKey.Type = EffectParameterType.Texture2D;
444 parameterKey.Class = EffectParameterClass.ShaderResourceView;
445 parameterKey.Type = EffectParameterType.Texture3D;
449 parameterKey.Class = EffectParameterClass.UnorderedAccessView;
450 parameterKey.Type = EffectParameterType.RWTexture1D;
454 parameterKey.Class = EffectParameterClass.UnorderedAccessView;
455 parameterKey.Type = EffectParameterType.RWTexture2D;
459 parameterKey.Class = EffectParameterClass.UnorderedAccessView;
460 parameterKey.Type = EffectParameterType.RWTexture3D;
464 parameterKey.Class = EffectParameterClass.Sampler;
465 parameterKey.Type = EffectParameterType.Sampler;
472 if (variableType == ScalarType.Int || variableType == ScalarType.UInt)
474 parameterKey.Class = EffectParameterClass.Scalar;
475 parameterKey.Type = variableType == ScalarType.Int ? EffectParameterType.Int : EffectParameterType.UInt;
477 else if (variableType == ScalarType.Float)
479 parameterKey.Class = EffectParameterClass.Scalar;
480 parameterKey.Type = EffectParameterType.Float;
482 else if (variableType == ScalarType.Bool)
484 parameterKey.Class = EffectParameterClass.Scalar;
485 parameterKey.Type = EffectParameterType.Bool;
488 parameterKey.RowCount = 1;
489 parameterKey.ColumnCount = 1;
493 if (variableType == VectorType.Float2 || variableType == VectorType.Float3 || variableType == VectorType.Float4)
495 parameterKey.Class = isColor ? EffectParameterClass.Color : EffectParameterClass.Vector;
496 parameterKey.Type = EffectParameterType.Float;
498 else if (variableType == VectorType.Int2 || variableType == VectorType.Int3 || variableType == VectorType.Int4)
500 parameterKey.Class = EffectParameterClass.Vector;
501 parameterKey.Type = EffectParameterType.Int;
503 else if (variableType == VectorType.UInt2 || variableType == VectorType.UInt3 || variableType == VectorType.UInt4)
505 parameterKey.Class = EffectParameterClass.Vector;
506 parameterKey.Type = EffectParameterType.UInt;
509 parameterKey.RowCount = 1;
510 parameterKey.ColumnCount = (variableType as VectorType).Dimension;
514 parameterKey.Class = EffectParameterClass.MatrixColumns;
515 parameterKey.Type = EffectParameterType.Float;
516 parameterKey.RowCount = (variableType as MatrixType).RowCount;
517 parameterKey.ColumnCount = (variableType as MatrixType).ColumnCount;
521 parameterKey.Class = EffectParameterClass.Struct;
522 parameterKey.RowCount = 1;
523 parameterKey.ColumnCount = 1;
533 private void ParseConstantBufferVariable(
string cbName,
Variable variable)
535 if (variable.
Qualifiers.
Contains(SiliconStudio.Shaders.Ast.Hlsl.StorageQualifier.Static) ||
536 variable.Qualifiers.Contains(StorageQualifier.Const) ||
537 variable.
Qualifiers.
Contains(SiliconStudio.Shaders.Ast.Hlsl.StorageQualifier.Groupshared)
543 parsingResult.Error(ParadoxMessageCode.StreamVariableWithoutPrefix, variable.Span, variable);
549 if (attribute.Name ==
"Link")
551 if (attribute.Parameters.Count != 1)
553 parsingResult.Error(ParadoxMessageCode.LinkArgumentsError, variable.Span);
559 var parameterKey = GetLinkParameterKey(variable);
561 if (parameterKey != null)
563 LinkConstant(cbName, variable, parameterKey);
567 parsingResult.Error(ParadoxMessageCode.LinkError, variable.Span, variable);
571 private static void LinkVariable(EffectReflection reflection,
string variableName, LocalParameterKey parameterKey)
573 var binding =
new EffectParameterResourceData {Param = {KeyName = parameterKey.Name, Class = parameterKey.Class, Type = parameterKey.Type, RawName = variableName}};
574 reflection.ResourceBindings.Add(binding);
577 private void LinkConstant(
string cbName,
Variable variable, LocalParameterKey parameterKey)
580 var constantBuffer = effectReflection.ConstantBuffers.FirstOrDefault(buffer => buffer.Name == cbName);
581 if (constantBuffer == null)
583 constantBuffer =
new ShaderConstantBufferDescription() {Name = cbName};
584 effectReflection.ConstantBuffers.Add(constantBuffer);
586 effectReflection.ResourceBindings.Add(constantBufferBinding);
587 valueBindings.Add(constantBuffer,
new List<EffectParameterValueData>());
591 var members = valueBindings[constantBuffer];
593 var binding =
new EffectParameterValueData
597 KeyName = parameterKey.Name,
598 Class = parameterKey.Class,
599 Type = parameterKey.Type,
600 RawName = variable.Name
602 RowCount = parameterKey.RowCount,
603 ColumnCount = parameterKey.ColumnCount,
604 Count = parameterKey.Count,
607 members.Add(binding);
610 private class LocalParameterKey
620 public int ColumnCount;
622 public int Count = 1;
Base class for all vector types
SiliconStudio.Shaders.Ast.Hlsl.ConstantBuffer ConstantBuffer
Identifier Name
Gets or sets the name.
TypeBase Type
Gets or sets the type.
SiliconStudio.Shaders.Ast.StorageQualifier StorageQualifier
static readonly SiliconStudio.Shaders.Ast.StorageQualifier Stream
Stream keyword (stream).
Qualifier Qualifiers
Gets or sets the qualifiers.
TextureAddressMode
Identify a technique for resolving texture coordinates that are outside of the boundaries of a textur...
Represents a color in the form of rgba.
Base interface for all node providing qualifiers.
static readonly StorageQualifier Const
Const qualifier.
SiliconStudio.Paradox.Graphics.Buffer Buffer
A method definition with a body of statements.
A reference to a variable.
Identifier Name
Gets or sets the name.
object Value
Gets or sets the value.
CompareFunction
Comparison options.
HRESULT Convert(_In_ const Image &srcImage, _In_ DXGI_FORMAT format, _In_ DWORD filter, _In_ float threshold, _Out_ ScratchImage &image)
List< Node > Members
Gets or sets the members.
EffectParameterClass
Values that identify the class of a shader variable.
Base class for all generic types.
Declaration of a constant buffer.
Toplevel container of a shader parsing result.
List< AttributeBase > Attributes
bool Contains(CompositeEnum enumValue)
Determines whether [contains] [the specified enum value].
Toplevel interface for a declaration.
object GetTag(object tagKey)
Gets a tag value associated to this node..
System.Windows.Point Point