tools: Expand / clean-up the template WGSL type helpers

Fix `IsAbstract()` so that it doesn't consider most-nested element types.
Add `ElementType()` and `DeepestElementType()` helpers.
Add `OverloadUsesF16` as a helper for https://dawn-review.googlesource.com/c/dawn/+/96722.

Simplifies template code.

Change-Id: Iff5a9a7258caea06e00ee37c29e5298d9c35b799
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/97361
Commit-Queue: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Dan Sinclair <dsinclair@chromium.org>
This commit is contained in:
Ben Clayton 2022-07-27 19:36:49 +00:00 committed by Dawn LUCI CQ
parent 8dbd4d0280
commit a253a5f7e7
4 changed files with 57 additions and 15 deletions

View File

@ -116,7 +116,7 @@ fn {{$permutation}}() {
{{/* Build the parameters either as 'var' or inline values */ -}}
{{- range $i, $p := $overload.Parameters -}}
{{- $class := Eval "StorageClass" $p.Type -}}
{{- $is_abstract := IsAbstract $p.Type -}}
{{- $is_abstract := DeepestElementType $p.Type | IsAbstract -}}
{{- if eq "function" $class -}}
{{- if eq "ptr" $p.Type.Target.Name -}}
{{template "Type" index $p.Type.TemplateArguments 1}};
@ -270,10 +270,10 @@ enable chromium_experimental_dp4a;
{{- else if eq $ty.Target.Name "ia" -}}1.0
{{- else if eq $ty.Target.Name "bool" -}}true
{{- else if eq $ty.Target.Name "vec" -}}
{{- $el := Eval "ArgumentValue" "Type" (index $ty.TemplateArguments 1) "Name" ""}}
{{- $el := Eval "ArgumentValue" "Type" (ElementType .Type) "Name" ""}}
{{- template "Type" $ty}}({{$el}})
{{- else if eq $ty.Target.Name "mat" -}}{{template "Type" $ty}}(
{{- $el := Eval "ArgumentValue" "Type" (index $ty.TemplateArguments 2) "Name" ""}}
{{- $el := Eval "ArgumentValue" "Type" (ElementType .Type) "Name" ""}}
{{- range $col := Iterate (index $ty.TemplateArguments 0) }}
{{- range $row := Iterate (index $ty.TemplateArguments 1) }}
{{- if or $col $row -}}, {{end}}{{$el}}
@ -289,13 +289,13 @@ enable chromium_experimental_dp4a;
{{- /* Emits the WGSL for the Fully Qualified Name argument */ -}}
{{- /* ------------------------------------------------------------------ */ -}}
{{- if IsType .Target -}}
{{- if IsAbstract . -}}
{{- if DeepestElementType . | IsAbstract -}}
{{- if eq .Target.Name "vec" -}}vec{{index .TemplateArguments 0}}
{{- else if eq .Target.Name "mat" -}}mat{{index .TemplateArguments 0}}x{{index .TemplateArguments 1}}
{{- else -}}
{{- end -}}
{{- else if eq .Target.Name "vec" -}}vec{{index .TemplateArguments 0}}<{{template "Type" index .TemplateArguments 1}}>
{{- else if eq .Target.Name "mat" -}}mat{{index .TemplateArguments 0}}x{{index .TemplateArguments 1}}<{{template "Type" index .TemplateArguments 2}}>
{{- else if eq .Target.Name "vec" -}}vec{{index .TemplateArguments 0}}<{{template "Type" (ElementType .)}}>
{{- else if eq .Target.Name "mat" -}}mat{{index .TemplateArguments 0}}x{{index .TemplateArguments 1}}<{{template "Type" (ElementType .)}}>
{{- else -}}{{.Target.Name}}{{template "TemplateArguments" .TemplateArguments}}
{{- end -}}
{{- else if IsEnumEntry .Target -}}{{.Target.Name}}

View File

@ -302,8 +302,11 @@ func (g *generator) bindAndParse(t *template.Template, text string) error {
"IsTemplateNumberParam": is(sem.TemplateNumberParam{}),
"IsTemplateTypeParam": is(sem.TemplateTypeParam{}),
"IsType": is(sem.Type{}),
"ElementType": gen.ElementType,
"DeepestElementType": gen.DeepestElementType,
"IsAbstract": gen.IsAbstract,
"IsDeclarable": gen.IsDeclarable,
"OverloadUsesF16": gen.OverloadUsesF16,
"IsFirstIn": isFirstIn,
"IsLastIn": isLastIn,
"Sem": g.cache.sem,

View File

@ -444,16 +444,40 @@ func SplitDisplayName(displayName string) []string {
return parts
}
// IsAbstract returns true if the FullyQualifiedName refers to an abstract
// numeric type
// ElementType returns the nested type for type represented by the fully qualified name.
// If the type is not a composite type, then the fully qualified name is returned
func ElementType(fqn sem.FullyQualifiedName) sem.FullyQualifiedName {
switch fqn.Target.GetName() {
case "vec":
return fqn.TemplateArguments[1].(sem.FullyQualifiedName)
case "mat":
return fqn.TemplateArguments[2].(sem.FullyQualifiedName)
case "array":
return fqn.TemplateArguments[0].(sem.FullyQualifiedName)
}
return fqn
}
// DeepestElementType returns the inner most nested type for type represented by the
// fully qualified name.
func DeepestElementType(fqn sem.FullyQualifiedName) sem.FullyQualifiedName {
switch fqn.Target.GetName() {
case "vec":
return fqn.TemplateArguments[1].(sem.FullyQualifiedName)
case "mat":
return DeepestElementType(fqn.TemplateArguments[2].(sem.FullyQualifiedName))
case "array":
return DeepestElementType(fqn.TemplateArguments[0].(sem.FullyQualifiedName))
}
return fqn
}
// IsAbstract returns true if the FullyQualifiedName refers to an abstract numeric type float.
// Use DeepestElementType if you want to include vector, matrices and arrays of abstract types.
func IsAbstract(fqn sem.FullyQualifiedName) bool {
switch fqn.Target.GetName() {
case "ia", "fa":
return true
case "vec":
return IsAbstract(fqn.TemplateArguments[1].(sem.FullyQualifiedName))
case "mat":
return IsAbstract(fqn.TemplateArguments[2].(sem.FullyQualifiedName))
}
return false
}
@ -461,5 +485,20 @@ func IsAbstract(fqn sem.FullyQualifiedName) bool {
// IsDeclarable returns false if the FullyQualifiedName refers to an abstract
// numeric type, or if it starts with a leading underscore.
func IsDeclarable(fqn sem.FullyQualifiedName) bool {
return !IsAbstract(fqn) && !strings.HasPrefix(fqn.Target.GetName(), "_")
return !IsAbstract(DeepestElementType(fqn)) && !strings.HasPrefix(fqn.Target.GetName(), "_")
}
// OverloadUsesF16 returns true if the overload uses the f16 type anywhere in the signature.
func OverloadUsesF16(overload *sem.Overload, typename string) bool {
for _, param := range overload.Parameters {
if DeepestElementType(param.Type).Target.GetName() == "f16" {
return true
}
}
if ret := overload.ReturnType; ret != nil {
if DeepestElementType(*overload.ReturnType).Target.GetName() == "f16" {
return true
}
}
return false
}

View File

@ -336,8 +336,8 @@ func validate(fqn sem.FullyQualifiedName, uses *sem.StageUses) bool {
strings.Contains(elTyName, "sampler"),
strings.Contains(elTyName, "texture"):
return false // Not storable
case IsAbstract(elTy):
return false // Abstract types are not typeable nor supported by arrays
case IsAbstract(DeepestElementType(elTy)):
return false // Abstract types are not typeable
}
case "ptr":
// https://gpuweb.github.io/gpuweb/wgsl/#storage-class