From 5503b6d54ae0ac3afd7353f12aeed4daf72a6273 Mon Sep 17 00:00:00 2001 From: rajveermalviya Date: Sun, 11 Feb 2024 19:53:48 +0530 Subject: [PATCH 01/10] gen-check: show better error in CI --- Makefile | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 7841d30f..550edf95 100644 --- a/Makefile +++ b/Makefile @@ -4,4 +4,8 @@ gen: schema.json webgpu.yml go run ./gen -schema schema.json -yaml webgpu.yml -header webgpu.h gen-check: gen - @git diff --quiet -- webgpu.h || { git diff -- webgpu.h; exit 1; } + @git diff --quiet -- webgpu.h || { \ + echo "error: The re-generated header from yml doesn't match the checked-in header"; \ + git diff -- webgpu.h; \ + exit 1; \ + } From 9a2769b6792d918457dd626a04e12d4d6b086eed Mon Sep 17 00:00:00 2001 From: rajveermalviya Date: Sun, 11 Feb 2024 20:00:27 +0530 Subject: [PATCH 02/10] Generation & Validation for multiple yamls --- gen/main.go | 63 +++++++++++++------------ gen/validator.go | 120 ++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 142 insertions(+), 41 deletions(-) diff --git a/gen/main.go b/gen/main.go index d90102ab..f50206aa 100644 --- a/gen/main.go +++ b/gen/main.go @@ -16,53 +16,56 @@ import ( var tmpl string var ( - schemaPath string - headerPath string - yamlPath string + schemaPath string + headerPaths StringListFlag + yamlPaths StringListFlag ) func main() { - flag.StringVar(&yamlPath, "yaml", "", "path of the yaml spec") flag.StringVar(&schemaPath, "schema", "", "path of the json schema") - flag.StringVar(&headerPath, "header", "", "output path of the header") + flag.Var(&yamlPaths, "yaml", "path of the yaml spec") + flag.Var(&headerPaths, "header", "output path of the header") flag.Parse() - if schemaPath == "" || headerPath == "" || yamlPath == "" { + if schemaPath == "" || len(headerPaths) == 0 || len(yamlPaths) == 0 || len(headerPaths) != len(yamlPaths) { flag.Usage() os.Exit(1) } - if err := ValidateYaml(schemaPath, yamlPath); err != nil { + if err := ValidateYamls(schemaPath, yamlPaths); err != nil { panic(err) } - src, err := os.ReadFile(yamlPath) - if err != nil { - panic(err) - } + for i, yamlPath := range yamlPaths { + src, err := os.ReadFile(yamlPath) + if err != nil { + panic(err) + } - var yml Yml - if err := yaml.Unmarshal(src, &yml); err != nil { - panic(err) - } + var yml Yml + if err := yaml.Unmarshal(src, &yml); err != nil { + panic(err) + } - SortAndTransform(&yml) + SortAndTransform(&yml) - dst, err := os.Create(headerPath) - if err != nil { - panic(err) - } + headerPath := headerPaths[i] + dst, err := os.Create(headerPath) + if err != nil { + panic(err) + } - fileName := filepath.Base(yamlPath) - fileNameSplit := strings.Split(fileName, ".") - if len(fileNameSplit) != 2 { - panic("got invalid file name: " + fileName) - } + fileName := filepath.Base(yamlPath) + fileNameSplit := strings.Split(fileName, ".") + if len(fileNameSplit) != 2 { + panic("got invalid file name: " + fileName) + } - var data Data - data.Yml = &yml - data.Name = fileNameSplit[0] - if err := GenCHeader(&data, dst); err != nil { - panic(err) + var data Data + data.Yml = &yml + data.Name = fileNameSplit[0] + if err := GenCHeader(&data, dst); err != nil { + panic(err) + } } } diff --git a/gen/validator.go b/gen/validator.go index ae2cef2c..2d2d804d 100644 --- a/gen/validator.go +++ b/gen/validator.go @@ -1,29 +1,127 @@ package main import ( + "errors" "fmt" "os" + "slices" "github.com/goccy/go-yaml" "github.com/santhosh-tekuri/jsonschema/v5" _ "github.com/santhosh-tekuri/jsonschema/v5/httploader" ) -func ValidateYaml(schemaPath string, yamlPath string) error { - yamlFile, err := os.ReadFile(yamlPath) - if err != nil { - return fmt.Errorf("ValidateYaml: %w", err) - } - var yml map[string]any - if err := yaml.Unmarshal(yamlFile, &yml); err != nil { - return fmt.Errorf("ValidateYaml: %w", err) +func ValidateYamls(schemaPath string, yamlPaths []string) error { + for _, yamlPath := range yamlPaths { + yamlFile, err := os.ReadFile(yamlPath) + if err != nil { + return fmt.Errorf("ValidateYaml: %w", err) + } + var yml map[string]any + if err := yaml.Unmarshal(yamlFile, &yml); err != nil { + return fmt.Errorf("ValidateYaml: %w", err) + } + + schema := jsonschema.MustCompile(schemaPath) + if err := schema.Validate(yml); err != nil { + return fmt.Errorf("ValidateYaml: %w", err) + } } - schema := jsonschema.MustCompile(schemaPath) - if err := schema.Validate(yml); err != nil { - return fmt.Errorf("ValidateYaml: %w", err) + if err := mergeAndValidateDuplicates(yamlPaths); err != nil { + panic(err) } // TODO: add dependency check validations return nil } + +func mergeAndValidateDuplicates(yamlPaths []string) (errs error) { + constants := make(map[string]Constant) + enums := make(map[string]Enum) + bitflags := make(map[string]Bitflag) + functionTypes := make(map[string]Function) + structs := make(map[string]Struct) + functions := make(map[string]Function) + objects := make(map[string]Object) + + for _, yamlPath := range yamlPaths { + src, err := os.ReadFile(yamlPath) + if err != nil { + panic(err) + } + + var data Yml + if err := yaml.Unmarshal(src, &data); err != nil { + panic(err) + } + + for _, c := range data.Constants { + if _, ok := constants[c.Name]; ok { + errs = errors.Join(errs, fmt.Errorf("merge: constants.%s in %s was already found previously while parsing, duplicates are not allowed", c.Name, yamlPath)) + } + constants[c.Name] = c + } + for _, e := range data.Enums { + if prevEnum, ok := enums[e.Name]; ok { + if !e.Extended { + errs = errors.Join(errs, fmt.Errorf("merge: enums.%s in %s is being extended but isn't marked as one", e.Name, yamlPath)) + } + for _, entry := range e.Entries { + if slices.ContainsFunc(prevEnum.Entries, func(e EnumEntry) bool { return e.Name == entry.Name }) { + errs = errors.Join(errs, fmt.Errorf("merge: enums.%s.%s in %s was already found previously while parsing, duplicates are not allowed", e.Name, entry.Name, yamlPath)) + } + prevEnum.Entries = append(prevEnum.Entries, entry) + } + enums[e.Name] = prevEnum + } else { + enums[e.Name] = e + } + } + for _, bf := range data.Bitflags { + if prevBf, ok := bitflags[bf.Name]; ok { + for _, entry := range bf.Entries { + if slices.ContainsFunc(prevBf.Entries, func(e BitflagEntry) bool { return e.Name == entry.Name }) { + errs = errors.Join(errs, fmt.Errorf("merge: bitflags.%s.%s in %s was already found previously while parsing, duplicates are not allowed", bf.Name, entry.Name, yamlPath)) + } + prevBf.Entries = append(prevBf.Entries, entry) + } + bitflags[bf.Name] = prevBf + } else { + bitflags[bf.Name] = bf + } + } + for _, ft := range data.FunctionTypes { + if _, ok := functionTypes[ft.Name]; ok { + errs = errors.Join(errs, fmt.Errorf("merge: function_types.%s in %s was already found previously while parsing, duplicates are not allowed", ft.Name, yamlPath)) + } + functionTypes[ft.Name] = ft + } + for _, s := range data.Structs { + if _, ok := structs[s.Name]; ok { + errs = errors.Join(errs, fmt.Errorf("merge: structs.%s in %s was already found previously while parsing, duplicates are not allowed", s.Name, yamlPath)) + } + structs[s.Name] = s + } + for _, f := range data.Functions { + if _, ok := functions[f.Name]; ok { + errs = errors.Join(errs, fmt.Errorf("merge: functions.%s in %s was already found previously while parsing, duplicates are not allowed", f.Name, yamlPath)) + } + functions[f.Name] = f + } + for _, o := range data.Objects { + if prevObj, ok := objects[o.Name]; ok { + for _, method := range o.Methods { + if slices.ContainsFunc(prevObj.Methods, func(f Function) bool { return f.Name == method.Name }) { + errs = errors.Join(errs, fmt.Errorf("merge: objects.%s.%s in %s was already found previously while parsing, duplicates are not allowed", o.Name, method.Name, yamlPath)) + } + prevObj.Methods = append(prevObj.Methods, method) + } + objects[o.Name] = prevObj + } else { + objects[o.Name] = o + } + } + } + return +} From 7ed6145021d98602df0da99f219345b20fe737d1 Mon Sep 17 00:00:00 2001 From: rajveermalviya Date: Sun, 11 Feb 2024 20:01:54 +0530 Subject: [PATCH 03/10] enum extensions --- gen/cheader.tmpl | 64 +++++++++++++++++++----------------------- gen/gen.go | 73 +++++++++++++++++++++++++++++++++++++++--------- gen/main.go | 9 ++++++ gen/yml.go | 11 +++----- schema.json | 4 +++ 5 files changed, 106 insertions(+), 55 deletions(-) diff --git a/gen/cheader.tmpl b/gen/cheader.tmpl index 2fad6195..3a42345b 100644 --- a/gen/cheader.tmpl +++ b/gen/cheader.tmpl @@ -37,7 +37,17 @@ #define WGPU_NULLABLE #endif{{"\n" -}} -{{if eq .Name "webgpu"}} +{{- if ne .Name "webgpu"}} +#if !defined(__WGPU_EXTEND_ENUM) +#ifdef __cplusplus +#define __WGPU_EXTEND_ENUM(E, N, V) static const E N = E(V) +#else +#define __WGPU_EXTEND_ENUM(E, N, V) static const E N = (E)(V) +#endif +#endif // !defined(__WGPU_EXTEND_ENUM) +{{ end}} + +{{- if eq .Name "webgpu"}} #include #include {{else}} @@ -46,7 +56,7 @@ {{- if .Constants}} {{- range .Constants}} -{{- MComment .Doc 0}} +{{- MComment .Doc 0}} #define WGPU_{{.Name | ConstantCase}} ({{.Value | CValue}}) {{- end}} {{ end}} @@ -71,49 +81,33 @@ struct WGPU{{.Name | PascalCase}}; {{- end}} {{ end}} -{{- range $entry := .Enums}} -{{- MComment .Doc 0}} +{{- range $enum := .Enums}} +{{- if .Extended}} +{{- range $entryIndex, $_ := .Entries}} +__WGPU_EXTEND_ENUM(WGPU{{ $enum.Name | PascalCase }}, WGPU{{ $enum.Name | PascalCase}}_{{.Name | PascalCase}}, {{EnumValue $.EnumPrefix $enum $entryIndex}}); +{{- end}} +{{- else}} +{{- MComment .Doc 0}} typedef enum WGPU{{.Name | PascalCase}} { -{{- range $entryIndex, $_ := .Entries}} -{{- MComment .Doc 4}} -{{- $entryValue := 0}} -{{- if eq .Value ""}} -{{- $entryValue = $entryIndex}} -{{- else}} -{{- $entryValue = ParseUint .Value 16}} +{{- range $entryIndex, $_ := .Entries}} +{{- MComment .Doc 4}} + WGPU{{$enum.Name | PascalCase}}_{{.Name | PascalCase}} = {{EnumValue $.EnumPrefix $enum $entryIndex}}, {{- end}} - WGPU{{$entry.Name | PascalCase}}_{{.Name | PascalCase}} = {{printf "%s%.4X," $.EnumPrefix $entryValue}} + WGPU{{$enum.Name | PascalCase}}_Force32 = 0x7FFFFFFF +} WGPU{{$enum.Name | PascalCase}} WGPU_ENUM_ATTRIBUTE; {{- end}} - WGPU{{.Name | PascalCase}}_Force32 = 0x7FFFFFFF -} WGPU{{.Name | PascalCase}} WGPU_ENUM_ATTRIBUTE; {{ end}} -{{- range $entry := .Bitflags}} +{{- range $bitflag := .Bitflags}} {{- MComment .Doc 0}} typedef enum WGPU{{.Name | PascalCase}} { {{- range $entryIndex, $_ := .Entries}} {{- MComment .Doc 4}} -{{- $entryValue := ""}} -{{- $valueCombination := .ValueCombination}} -{{- range $valueIndex, $v := .ValueCombination}} -{{- $v = printf "WGPU%s_%s" ($entry.Name | PascalCase) ($v | PascalCase)}} -{{- if IsLast $valueIndex $valueCombination}} -{{- $entryValue = print $entryValue $v}} -{{- else}} -{{- $entryValue = print $entryValue $v " | "}} -{{- end}} -{{- else}} -{{- if eq .Value ""}} -{{- $entryValue = printf "0x%.8X" (BitFlagValue $entryIndex)}} -{{- else}} -{{- $entryValue = printf "0x%.8X" (ParseUint .Value 64)}} -{{- end}} -{{- end}} - WGPU{{$entry.Name | PascalCase}}_{{.Name | PascalCase}} = {{$entryValue}}, + WGPU{{$bitflag.Name | PascalCase}}_{{.Name | PascalCase}} = {{BitflagValue $bitflag $entryIndex}}, {{- end}} - WGPU{{.Name | PascalCase}}_Force32 = 0x7FFFFFFF -} WGPU{{.Name | PascalCase}} WGPU_ENUM_ATTRIBUTE; -typedef WGPUFlags WGPU{{.Name | PascalCase}}Flags WGPU_ENUM_ATTRIBUTE; + WGPU{{$bitflag.Name | PascalCase}}_Force32 = 0x7FFFFFFF +} WGPU{{$bitflag.Name | PascalCase}} WGPU_ENUM_ATTRIBUTE; +typedef WGPUFlags WGPU{{$bitflag.Name | PascalCase}}Flags WGPU_ENUM_ATTRIBUTE; {{ end}} {{- if eq .Name "webgpu"}} diff --git a/gen/gen.go b/gen/gen.go index 7a9c323b..f9c63d26 100644 --- a/gen/gen.go +++ b/gen/gen.go @@ -28,19 +28,8 @@ func GenCHeader(data *Data, dst io.Writer) error { "CamelCase": CamelCase, "CType": CType, "CValue": CValue, - "BitFlagValue": func(index int) uint64 { return uint64(math.Pow(2, float64(index-1))) }, - "ParseUint": func(s string, bitSize int) (uint64, error) { - var num string - var base int - if strings.HasPrefix(s, "0x") { - base = 16 - num = strings.TrimPrefix(s, "0x") - } else { - base = 10 - num = s - } - return strconv.ParseUint(num, base, bitSize) - }, + "EnumValue": EnumValue, + "BitflagValue": BitflagValue, "IsArray": func(typ string) bool { return arrayTypeRegexp.Match([]byte(typ)) }, @@ -219,3 +208,61 @@ func CallbackArgs(f Function) string { sb.WriteString("WGPU_NULLABLE void * userdata") return sb.String() } + +func EnumValue(prefix string, e Enum, entryIndex int) (string, error) { + var entryValue uint16 + entry := e.Entries[entryIndex] + if entry.Value == "" { + entryValue = uint16(entryIndex) + } else { + var num string + var base int + if strings.HasPrefix(entry.Value, "0x") { + base = 16 + num = strings.TrimPrefix(entry.Value, "0x") + } else { + base = 10 + num = entry.Value + } + value, err := strconv.ParseUint(num, base, 16) + if err != nil { + return "", err + } + entryValue = uint16(value) + } + return fmt.Sprintf("%s%.4X", prefix, entryValue), nil +} + +func BitflagValue(b Bitflag, entryIndex int) (string, error) { + entry := b.Entries[entryIndex] + var entryValue string + if len(entry.ValueCombination) > 0 { + for valueIndex, v := range entry.ValueCombination { + entryValue += "WGPU" + PascalCase(b.Name) + "_" + PascalCase(v) + if valueIndex != len(entry.ValueCombination)-1 { + entryValue += " | " + } + } + } else { + if entry.Value == "" { + value := uint64(math.Pow(2, float64(entryIndex-1))) + entryValue = fmt.Sprintf("0x%.8X", value) + } else { + var num string + var base int + if strings.HasPrefix(entry.Value, "0x") { + base = 16 + num = strings.TrimPrefix(entry.Value, "0x") + } else { + base = 10 + num = entry.Value + } + value, err := strconv.ParseUint(num, base, 64) + if err != nil { + return "", err + } + entryValue = fmt.Sprintf("0x%.8X", value) + } + } + return entryValue, nil +} diff --git a/gen/main.go b/gen/main.go index f50206aa..2db8bff9 100644 --- a/gen/main.go +++ b/gen/main.go @@ -72,14 +72,22 @@ func main() { func SortAndTransform(yml *Yml) { // Sort structs SortStructs(yml.Structs) + // Sort constants slices.SortStableFunc(yml.Constants, func(a, b Constant) int { return strings.Compare(PascalCase(a.Name), PascalCase(b.Name)) }) + // Sort enums slices.SortStableFunc(yml.Enums, func(a, b Enum) int { + if a.Extended && !b.Extended { + return -1 + } else if !a.Extended && b.Extended { + return 1 + } return strings.Compare(PascalCase(a.Name), PascalCase(b.Name)) }) + // Sort bitflags slices.SortStableFunc(yml.Bitflags, func(a, b Bitflag) int { return strings.Compare(PascalCase(a.Name), PascalCase(b.Name)) @@ -99,6 +107,7 @@ func SortAndTransform(yml *Yml) { slices.SortStableFunc(yml.Objects, func(a, b Object) int { return strings.Compare(PascalCase(a.Name), PascalCase(b.Name)) }) + // Sort methods for _, obj := range yml.Objects { slices.SortStableFunc(obj.Methods, func(a, b Function) int { diff --git a/gen/yml.go b/gen/yml.go index 4201acbd..5cac21af 100644 --- a/gen/yml.go +++ b/gen/yml.go @@ -18,8 +18,6 @@ type Yml struct { Structs []Struct `yaml:"structs"` Functions []Function `yaml:"functions"` Objects []Object `yaml:"objects"` - - Copyrights []string `yaml:"-"` } type Constant struct { @@ -29,16 +27,15 @@ type Constant struct { } type Enum struct { - Name string `yaml:"name"` - Doc string `yaml:"doc"` - Entries []EnumEntry `yaml:"entries"` + Name string `yaml:"name"` + Doc string `yaml:"doc"` + Entries []EnumEntry `yaml:"entries"` + Extended bool `yaml:"extended"` } type EnumEntry struct { Name string `yaml:"name"` Doc string `yaml:"doc"` Value string `yaml:"value"` - - ValuePrefix string `yaml:"-"` } type Bitflag struct { diff --git a/schema.json b/schema.json index 0219512b..5fe3b015 100644 --- a/schema.json +++ b/schema.json @@ -196,6 +196,10 @@ "doc": { "type": "string" }, + "extended": { + "type": "boolean", + "description": "Optional property, an indicator that this enum is an extension of an already present enum" + }, "entries": { "type": "array", "items": { From 8d90f2417dcfa772206d06d53325690796e30687 Mon Sep 17 00:00:00 2001 From: rajveermalviya Date: Sun, 11 Feb 2024 20:28:52 +0530 Subject: [PATCH 04/10] yaml order matters --- gen/main.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/gen/main.go b/gen/main.go index 2db8bff9..193fc39a 100644 --- a/gen/main.go +++ b/gen/main.go @@ -31,6 +31,10 @@ func main() { os.Exit(1) } + if len(yamlPaths) > 1 && filepath.Base(yamlPaths[0]) != "webgpu.yml" { + panic(`"webgpu.yml" must be the first sequence in the order`) + } + if err := ValidateYamls(schemaPath, yamlPaths); err != nil { panic(err) } From 54d61ef8e6eda0d92df135a14c02b8cefc5425c5 Mon Sep 17 00:00:00 2001 From: rajveermalviya Date: Sun, 11 Feb 2024 20:29:13 +0530 Subject: [PATCH 05/10] add readme section --- gen/README.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/gen/README.md b/gen/README.md index a4652fc5..6b902aa2 100644 --- a/gen/README.md +++ b/gen/README.md @@ -2,6 +2,18 @@ The generator for generating `webgpu.h` header and other extension headers or implementation specific headers from the yaml spec files. +# Generate implementation specific header + +The generator also allows generating custom implementation specific headers that build on top of `webgpu.h` header. The generator accepts the combination of `-yaml` & `-header` flags in sequence, which it uses to validate the specifications and then generate their headers. + +For example, if `wgpu.yml` contains the implementation specific API, the header can be generated using: + +```shell +> go run ./gen -schema schema.json -yaml webgpu.yml -header webgpu.h -yaml wgpu.yml -header wgpu.h +``` + +Since the generator does some duplication validation, the order of the files matter, so generator mandates the core `webgpu.yml` to be first in the sequence. + # yaml spec ### Types From fcb30968fcd97d7857e440173bc292ef266d38c1 Mon Sep 17 00:00:00 2001 From: rajveermalviya Date: Sun, 11 Feb 2024 20:44:48 +0530 Subject: [PATCH 06/10] comments --- gen/main.go | 4 ++++ gen/validator.go | 2 ++ 2 files changed, 6 insertions(+) diff --git a/gen/main.go b/gen/main.go index 193fc39a..94d66ca3 100644 --- a/gen/main.go +++ b/gen/main.go @@ -31,14 +31,17 @@ func main() { os.Exit(1) } + // Order matters for validation steps, so enforce it. if len(yamlPaths) > 1 && filepath.Base(yamlPaths[0]) != "webgpu.yml" { panic(`"webgpu.yml" must be the first sequence in the order`) } + // Validate the yaml files (jsonschema, duplications) if err := ValidateYamls(schemaPath, yamlPaths); err != nil { panic(err) } + // Generate the header files for i, yamlPath := range yamlPaths { src, err := os.ReadFile(yamlPath) if err != nil { @@ -84,6 +87,7 @@ func SortAndTransform(yml *Yml) { // Sort enums slices.SortStableFunc(yml.Enums, func(a, b Enum) int { + // We want to generate extended enum declarations before the normal ones. if a.Extended && !b.Extended { return -1 } else if !a.Extended && b.Extended { diff --git a/gen/validator.go b/gen/validator.go index 2d2d804d..cb8beed8 100644 --- a/gen/validator.go +++ b/gen/validator.go @@ -12,6 +12,7 @@ import ( ) func ValidateYamls(schemaPath string, yamlPaths []string) error { + // Validation through json schema for _, yamlPath := range yamlPaths { yamlFile, err := os.ReadFile(yamlPath) if err != nil { @@ -28,6 +29,7 @@ func ValidateYamls(schemaPath string, yamlPaths []string) error { } } + // Validation of possible duplication of entries across multiple yaml files if err := mergeAndValidateDuplicates(yamlPaths); err != nil { panic(err) } From 3b3fd844f1928ac2ef6e709093d26d82ecfd7442 Mon Sep 17 00:00:00 2001 From: rajveermalviya Date: Sun, 11 Feb 2024 21:10:56 +0530 Subject: [PATCH 07/10] object extensions --- gen/cheader.tmpl | 4 ++-- gen/validator.go | 6 ++++++ gen/yml.go | 14 ++++++++------ schema.json | 8 ++++++++ 4 files changed, 24 insertions(+), 8 deletions(-) diff --git a/gen/cheader.tmpl b/gen/cheader.tmpl index 3a42345b..4fcfbc65 100644 --- a/gen/cheader.tmpl +++ b/gen/cheader.tmpl @@ -187,7 +187,7 @@ typedef WGPUProc (*WGPUProcGetProcAddress)(WGPUDevice device, char const * procN {{- MComment .Doc 0}} typedef {{FunctionReturns .}} (*WGPUProc{{$object.Name | PascalCase}}{{.Name | PascalCase}})({{FunctionArgs . $object}}) WGPU_FUNCTION_ATTRIBUTE; {{- end}} -{{- if not .IsStruct}} +{{- if not (or .IsStruct .Extended)}} typedef void (*WGPUProc{{.Name | PascalCase}}Reference)(WGPU{{.Name | PascalCase}} {{.Name | CamelCase}}) WGPU_FUNCTION_ATTRIBUTE; typedef void (*WGPUProc{{.Name | PascalCase}}Release)(WGPU{{.Name | PascalCase}} {{.Name | CamelCase}}) WGPU_FUNCTION_ATTRIBUTE; {{- end}} @@ -211,7 +211,7 @@ WGPU_EXPORT WGPUProc wgpuGetProcAddress(WGPUDevice device, char const * procName {{- MComment .Doc 0}} WGPU_EXPORT {{FunctionReturns .}} wgpu{{$object.Name | PascalCase}}{{.Name | PascalCase}}({{FunctionArgs . $object}}) WGPU_FUNCTION_ATTRIBUTE; {{- end}} -{{- if not .IsStruct}} +{{- if not (or .IsStruct .Extended)}} WGPU_EXPORT void wgpu{{.Name | PascalCase}}Reference(WGPU{{.Name | PascalCase}} {{.Name | CamelCase}}) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT void wgpu{{.Name | PascalCase}}Release(WGPU{{.Name | PascalCase}} {{.Name | CamelCase}}) WGPU_FUNCTION_ATTRIBUTE; {{- end}} diff --git a/gen/validator.go b/gen/validator.go index cb8beed8..5556347b 100644 --- a/gen/validator.go +++ b/gen/validator.go @@ -82,6 +82,9 @@ func mergeAndValidateDuplicates(yamlPaths []string) (errs error) { } for _, bf := range data.Bitflags { if prevBf, ok := bitflags[bf.Name]; ok { + if !bf.Extended { + errs = errors.Join(errs, fmt.Errorf("merge: bitflags.%s in %s is being extended but isn't marked as one", bf.Name, yamlPath)) + } for _, entry := range bf.Entries { if slices.ContainsFunc(prevBf.Entries, func(e BitflagEntry) bool { return e.Name == entry.Name }) { errs = errors.Join(errs, fmt.Errorf("merge: bitflags.%s.%s in %s was already found previously while parsing, duplicates are not allowed", bf.Name, entry.Name, yamlPath)) @@ -113,6 +116,9 @@ func mergeAndValidateDuplicates(yamlPaths []string) (errs error) { } for _, o := range data.Objects { if prevObj, ok := objects[o.Name]; ok { + if !o.Extended { + errs = errors.Join(errs, fmt.Errorf("merge: objects.%s in %s is being extended but isn't marked as one", o.Name, yamlPath)) + } for _, method := range o.Methods { if slices.ContainsFunc(prevObj.Methods, func(f Function) bool { return f.Name == method.Name }) { errs = errors.Join(errs, fmt.Errorf("merge: objects.%s.%s in %s was already found previously while parsing, duplicates are not allowed", o.Name, method.Name, yamlPath)) diff --git a/gen/yml.go b/gen/yml.go index 5cac21af..2ac36146 100644 --- a/gen/yml.go +++ b/gen/yml.go @@ -39,9 +39,10 @@ type EnumEntry struct { } type Bitflag struct { - Name string `yaml:"name"` - Doc string `yaml:"doc"` - Entries []BitflagEntry `yaml:"entries"` + Name string `yaml:"name"` + Doc string `yaml:"doc"` + Entries []BitflagEntry `yaml:"entries"` + Extended bool `yaml:"extended"` } type BitflagEntry struct { Name string `yaml:"name"` @@ -93,9 +94,10 @@ const ( ) type Object struct { - Name string `yaml:"name"` - Doc string `yaml:"doc"` - Methods []Function `yaml:"methods"` + Name string `yaml:"name"` + Doc string `yaml:"doc"` + Methods []Function `yaml:"methods"` + Extended bool `yaml:"extended"` IsStruct bool `yaml:"-"` } diff --git a/schema.json b/schema.json index 5fe3b015..3af7526e 100644 --- a/schema.json +++ b/schema.json @@ -242,6 +242,10 @@ "doc": { "type": "string" }, + "extended": { + "type": "boolean", + "description": "Optional property, an indicator that this bitflag is an extension of an already present bitflag" + }, "entries": { "type": "array", "items": { @@ -352,6 +356,10 @@ "doc": { "type": "string" }, + "extended": { + "type": "boolean", + "description": "Optional property, an indicator that this object is an extension of an already present object" + }, "methods": { "type": "array", "items": { From 21211611d96251d687d7a5f409548d0dd2ccffaf Mon Sep 17 00:00:00 2001 From: rajveermalviya Date: Sun, 11 Feb 2024 21:52:54 +0530 Subject: [PATCH 08/10] bitflag extensions --- gen/cheader.tmpl | 16 +++++++++++----- gen/main.go | 6 ++++++ gen/validator.go | 3 +++ 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/gen/cheader.tmpl b/gen/cheader.tmpl index 4fcfbc65..c844f865 100644 --- a/gen/cheader.tmpl +++ b/gen/cheader.tmpl @@ -84,7 +84,7 @@ struct WGPU{{.Name | PascalCase}}; {{- range $enum := .Enums}} {{- if .Extended}} {{- range $entryIndex, $_ := .Entries}} -__WGPU_EXTEND_ENUM(WGPU{{ $enum.Name | PascalCase }}, WGPU{{ $enum.Name | PascalCase}}_{{.Name | PascalCase}}, {{EnumValue $.EnumPrefix $enum $entryIndex}}); +__WGPU_EXTEND_ENUM(WGPU{{$enum.Name | PascalCase}}, WGPU{{$enum.Name | PascalCase}}_{{.Name | PascalCase}}, {{EnumValue $.EnumPrefix $enum $entryIndex}}); {{- end}} {{- else}} {{- MComment .Doc 0}} @@ -99,15 +99,21 @@ typedef enum WGPU{{.Name | PascalCase}} { {{ end}} {{- range $bitflag := .Bitflags}} -{{- MComment .Doc 0}} +{{- if .Extended}} +{{- range $entryIndex, $_ := .Entries}} +__WGPU_EXTEND_ENUM(WGPU{{$bitflag.Name | PascalCase}}, WGPU{{$bitflag.Name | PascalCase}}_{{.Name | PascalCase}}, {{BitflagValue $bitflag $entryIndex}}); +{{- end}} +{{- else}} +{{- MComment .Doc 0}} typedef enum WGPU{{.Name | PascalCase}} { -{{- range $entryIndex, $_ := .Entries}} -{{- MComment .Doc 4}} +{{- range $entryIndex, $_ := .Entries}} +{{- MComment .Doc 4}} WGPU{{$bitflag.Name | PascalCase}}_{{.Name | PascalCase}} = {{BitflagValue $bitflag $entryIndex}}, -{{- end}} +{{- end}} WGPU{{$bitflag.Name | PascalCase}}_Force32 = 0x7FFFFFFF } WGPU{{$bitflag.Name | PascalCase}} WGPU_ENUM_ATTRIBUTE; typedef WGPUFlags WGPU{{$bitflag.Name | PascalCase}}Flags WGPU_ENUM_ATTRIBUTE; +{{- end}} {{ end}} {{- if eq .Name "webgpu"}} diff --git a/gen/main.go b/gen/main.go index 94d66ca3..543ec74a 100644 --- a/gen/main.go +++ b/gen/main.go @@ -98,6 +98,12 @@ func SortAndTransform(yml *Yml) { // Sort bitflags slices.SortStableFunc(yml.Bitflags, func(a, b Bitflag) int { + // We want to generate extended bitflag declarations before the normal ones. + if a.Extended && !b.Extended { + return -1 + } else if !a.Extended && b.Extended { + return 1 + } return strings.Compare(PascalCase(a.Name), PascalCase(b.Name)) }) diff --git a/gen/validator.go b/gen/validator.go index 5556347b..6657be0c 100644 --- a/gen/validator.go +++ b/gen/validator.go @@ -89,6 +89,9 @@ func mergeAndValidateDuplicates(yamlPaths []string) (errs error) { if slices.ContainsFunc(prevBf.Entries, func(e BitflagEntry) bool { return e.Name == entry.Name }) { errs = errors.Join(errs, fmt.Errorf("merge: bitflags.%s.%s in %s was already found previously while parsing, duplicates are not allowed", bf.Name, entry.Name, yamlPath)) } + if entry.Value == "" && len(entry.ValueCombination) == 0 { + errs = errors.Join(errs, fmt.Errorf("merge: bitflags.%s.%s in %s was extended but doesn't have a value or value_combination, extended bitflag entries must have an explicit value", bf.Name, entry.Name, yamlPath)) + } prevBf.Entries = append(prevBf.Entries, entry) } bitflags[bf.Name] = prevBf From 158a995aa46b0a47e6a6ac53c0fbdbd312b07933 Mon Sep 17 00:00:00 2001 From: rajveermalviya Date: Sun, 25 Feb 2024 02:23:55 +0530 Subject: [PATCH 09/10] add implicit suffix & namespaces --- gen/cheader.tmpl | 65 +++++++++++++---------------- gen/gen.go | 104 ++++++++++++++++++++++++++++++++++------------- gen/main.go | 16 ++++++-- gen/yml.go | 69 ++++++++++++++----------------- schema.json | 10 +++++ 5 files changed, 157 insertions(+), 107 deletions(-) diff --git a/gen/cheader.tmpl b/gen/cheader.tmpl index c844f865..7e67feca 100644 --- a/gen/cheader.tmpl +++ b/gen/cheader.tmpl @@ -57,7 +57,7 @@ {{- if .Constants}} {{- range .Constants}} {{- MComment .Doc 0}} -#define WGPU_{{.Name | ConstantCase}} ({{.Value | CValue}}) +#define WGPU_{{.Name | ConstantCase}}{{if $.ExtSuffix}}_{{$.ExtSuffix}}{{end}} ({{.Value | CValue}}) {{- end}} {{ end}} @@ -69,7 +69,7 @@ typedef uint32_t WGPUBool; {{- if .Objects}} {{- range .Objects}} {{- if not .IsStruct}} -typedef struct WGPU{{.Name | PascalCase}}Impl* WGPU{{.Name | PascalCase}} WGPU_OBJECT_ATTRIBUTE; +typedef struct WGPU{{.Name | PascalCase}}{{$.ExtSuffix}}Impl* WGPU{{.Name | PascalCase}}{{$.ExtSuffix}} WGPU_OBJECT_ATTRIBUTE; {{- end}} {{- end}} {{ end}} @@ -77,42 +77,42 @@ typedef struct WGPU{{.Name | PascalCase}}Impl* WGPU{{.Name | PascalCase}} WGPU_O {{- if .Structs}} // Structure forward declarations {{- range .Structs}} -struct WGPU{{.Name | PascalCase}}; +struct WGPU{{.Name | PascalCase}}{{$.ExtSuffix}}; {{- end}} {{ end}} {{- range $enum := .Enums}} {{- if .Extended}} {{- range $entryIndex, $_ := .Entries}} -__WGPU_EXTEND_ENUM(WGPU{{$enum.Name | PascalCase}}, WGPU{{$enum.Name | PascalCase}}_{{.Name | PascalCase}}, {{EnumValue $.EnumPrefix $enum $entryIndex}}); +__WGPU_EXTEND_ENUM(WGPU{{$enum.Name | PascalCase}}, WGPU{{$enum.Name | PascalCase}}_{{.Name | PascalCase}}{{if $.ExtSuffix}}_{{$.ExtSuffix}}{{end}}, {{EnumValue $.EnumPrefix $enum $entryIndex}}); {{- end}} {{- else}} {{- MComment .Doc 0}} -typedef enum WGPU{{.Name | PascalCase}} { +typedef enum WGPU{{.Name | PascalCase}}{{$.ExtSuffix}} { {{- range $entryIndex, $_ := .Entries}} {{- MComment .Doc 4}} - WGPU{{$enum.Name | PascalCase}}_{{.Name | PascalCase}} = {{EnumValue $.EnumPrefix $enum $entryIndex}}, + WGPU{{$enum.Name | PascalCase}}_{{.Name | PascalCase}}{{if $.ExtSuffix}}_{{$.ExtSuffix}}{{end}} = {{EnumValue $.EnumPrefix $enum $entryIndex}}, {{- end}} - WGPU{{$enum.Name | PascalCase}}_Force32 = 0x7FFFFFFF -} WGPU{{$enum.Name | PascalCase}} WGPU_ENUM_ATTRIBUTE; + WGPU{{$enum.Name | PascalCase}}_Force32{{if $.ExtSuffix}}_{{$.ExtSuffix}}{{end}} = 0x7FFFFFFF +} WGPU{{$enum.Name | PascalCase}}{{$.ExtSuffix}} WGPU_ENUM_ATTRIBUTE; {{- end}} {{ end}} {{- range $bitflag := .Bitflags}} {{- if .Extended}} {{- range $entryIndex, $_ := .Entries}} -__WGPU_EXTEND_ENUM(WGPU{{$bitflag.Name | PascalCase}}, WGPU{{$bitflag.Name | PascalCase}}_{{.Name | PascalCase}}, {{BitflagValue $bitflag $entryIndex}}); +__WGPU_EXTEND_ENUM(WGPU{{$bitflag.Name | PascalCase}}, WGPU{{$bitflag.Name | PascalCase}}_{{.Name | PascalCase}}{{if $.ExtSuffix}}_{{$.ExtSuffix}}{{end}}, {{BitflagValue $bitflag $entryIndex}}); {{- end}} {{- else}} {{- MComment .Doc 0}} -typedef enum WGPU{{.Name | PascalCase}} { +typedef enum WGPU{{.Name | PascalCase}}{{$.ExtSuffix}} { {{- range $entryIndex, $_ := .Entries}} {{- MComment .Doc 4}} - WGPU{{$bitflag.Name | PascalCase}}_{{.Name | PascalCase}} = {{BitflagValue $bitflag $entryIndex}}, + WGPU{{$bitflag.Name | PascalCase}}_{{.Name | PascalCase}}{{if $.ExtSuffix}}_{{$.ExtSuffix}}{{end}} = {{BitflagValue $bitflag $entryIndex}}, {{- end}} - WGPU{{$bitflag.Name | PascalCase}}_Force32 = 0x7FFFFFFF -} WGPU{{$bitflag.Name | PascalCase}} WGPU_ENUM_ATTRIBUTE; -typedef WGPUFlags WGPU{{$bitflag.Name | PascalCase}}Flags WGPU_ENUM_ATTRIBUTE; + WGPU{{$bitflag.Name | PascalCase}}_Force32{{if $.ExtSuffix}}_{{$.ExtSuffix}}{{end}} = 0x7FFFFFFF +} WGPU{{$bitflag.Name | PascalCase}}{{$.ExtSuffix}} WGPU_ENUM_ATTRIBUTE; +typedef WGPUFlags WGPU{{$bitflag.Name | PascalCase}}Flags{{$.ExtSuffix}} WGPU_ENUM_ATTRIBUTE; {{- end}} {{ end}} @@ -122,7 +122,7 @@ typedef void (*WGPUProc)(void) WGPU_FUNCTION_ATTRIBUTE; {{- range .FunctionTypes}} {{- MComment .Doc 0}} -typedef {{FunctionReturns .}} (*WGPU{{.Name | PascalCase}})({{FunctionArgs . nil}}) WGPU_FUNCTION_ATTRIBUTE; +typedef {{FunctionReturns .}} (*WGPU{{.Name | PascalCase}}{{$.ExtSuffix}})({{FunctionArgs . nil}}) WGPU_FUNCTION_ATTRIBUTE; {{- end}} {{- if .Objects}} @@ -130,7 +130,7 @@ typedef {{FunctionReturns .}} (*WGPU{{.Name | PascalCase}})({{FunctionArgs . nil {{- range $method := .Methods}} {{- if .ReturnsAsync}} {{- MComment .Doc 0}} -typedef void (*WGPU{{$object.Name | PascalCase}}{{$method.Name | PascalCase}}Callback)({{CallbackArgs .}}) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPU{{$object.Name | PascalCase}}{{$method.Name | PascalCase}}Callback{{$.ExtSuffix}})({{CallbackArgs .}}) WGPU_FUNCTION_ATTRIBUTE; {{- end}} {{- end}} {{- end}} @@ -148,9 +148,9 @@ typedef struct WGPUChainedStructOut { } WGPUChainedStructOut WGPU_STRUCTURE_ATTRIBUTE; {{ end}} -{{- range .Structs}} +{{- range $struct := .Structs}} {{- MComment .Doc 0}} -typedef struct WGPU{{.Name | PascalCase}} { +typedef struct WGPU{{.Name | PascalCase}}{{$.ExtSuffix}} { {{- if eq .Type "base_in" }} WGPUChainedStruct const * nextInChain; {{- else if eq .Type "base_out" }} @@ -160,17 +160,10 @@ typedef struct WGPU{{.Name | PascalCase}} { {{- else if eq .Type "extension_out"}} WGPUChainedStructOut chain; {{- end}} -{{- range .Members}} -{{- if IsArray .Type}} - size_t {{.Name | CamelCase | Singularize}}Count; -{{- MComment .Doc 4}} - {{ArrayType .Type .Pointer}} {{.Name | CamelCase}}; -{{- else}} -{{- MComment .Doc 4}} - {{if .Optional}}WGPU_NULLABLE {{end}}{{CType .Type .Pointer}} {{.Name | CamelCase}}; -{{- end}} +{{- range $memberIndex, $_ := .Members}} + {{ StructMember $struct $memberIndex}} {{- end}} -} WGPU{{.Name | PascalCase}} WGPU_STRUCTURE_ATTRIBUTE; +} WGPU{{.Name | PascalCase}}{{$.ExtSuffix}} WGPU_STRUCTURE_ATTRIBUTE; {{ end}}{{"\n" -}} #ifdef __cplusplus @@ -181,7 +174,7 @@ extern "C" { {{- range .Functions}} {{- MComment .Doc 0}} -typedef {{FunctionReturns .}} (*WGPUProc{{.Name | PascalCase}})({{FunctionArgs . nil}}) WGPU_FUNCTION_ATTRIBUTE; +typedef {{FunctionReturns .}} (*WGPUProc{{.Name | PascalCase}}{{$.ExtSuffix}})({{FunctionArgs . nil}}) WGPU_FUNCTION_ATTRIBUTE; {{- end}} {{- if eq .Name "webgpu"}} typedef WGPUProc (*WGPUProcGetProcAddress)(WGPUDevice device, char const * procName) WGPU_FUNCTION_ATTRIBUTE; @@ -191,11 +184,11 @@ typedef WGPUProc (*WGPUProcGetProcAddress)(WGPUDevice device, char const * procN // Procs of {{$object.Name | PascalCase}} {{- range $object.Methods}} {{- MComment .Doc 0}} -typedef {{FunctionReturns .}} (*WGPUProc{{$object.Name | PascalCase}}{{.Name | PascalCase}})({{FunctionArgs . $object}}) WGPU_FUNCTION_ATTRIBUTE; +typedef {{FunctionReturns .}} (*WGPUProc{{$object.Name | PascalCase}}{{.Name | PascalCase}}{{$.ExtSuffix}})({{FunctionArgs . $object}}) WGPU_FUNCTION_ATTRIBUTE; {{- end}} {{- if not (or .IsStruct .Extended)}} -typedef void (*WGPUProc{{.Name | PascalCase}}Reference)(WGPU{{.Name | PascalCase}} {{.Name | CamelCase}}) WGPU_FUNCTION_ATTRIBUTE; -typedef void (*WGPUProc{{.Name | PascalCase}}Release)(WGPU{{.Name | PascalCase}} {{.Name | CamelCase}}) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProc{{.Name | PascalCase}}Reference{{$.ExtSuffix}})(WGPU{{.Name | PascalCase}} {{.Name | CamelCase}}) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUProc{{.Name | PascalCase}}Release{{$.ExtSuffix}})(WGPU{{.Name | PascalCase}} {{.Name | CamelCase}}) WGPU_FUNCTION_ATTRIBUTE; {{- end}} {{ end}}{{"\n" -}} @@ -205,7 +198,7 @@ typedef void (*WGPUProc{{.Name | PascalCase}}Release)(WGPU{{.Name | PascalCase}} {{- range .Functions}} {{- MComment .Doc 0}} -WGPU_EXPORT {{FunctionReturns .}} wgpu{{.Name | PascalCase}}({{FunctionArgs . nil}}) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT {{FunctionReturns .}} wgpu{{.Name | PascalCase}}{{$.ExtSuffix}}({{FunctionArgs . nil}}) WGPU_FUNCTION_ATTRIBUTE; {{- end}} {{- if eq .Name "webgpu"}} WGPU_EXPORT WGPUProc wgpuGetProcAddress(WGPUDevice device, char const * procName) WGPU_FUNCTION_ATTRIBUTE; @@ -215,11 +208,11 @@ WGPU_EXPORT WGPUProc wgpuGetProcAddress(WGPUDevice device, char const * procName // Methods of {{$object.Name | PascalCase}} {{- range $object.Methods}} {{- MComment .Doc 0}} -WGPU_EXPORT {{FunctionReturns .}} wgpu{{$object.Name | PascalCase}}{{.Name | PascalCase}}({{FunctionArgs . $object}}) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT {{FunctionReturns .}} wgpu{{$object.Name | PascalCase}}{{.Name | PascalCase}}{{$.ExtSuffix}}({{FunctionArgs . $object}}) WGPU_FUNCTION_ATTRIBUTE; {{- end}} {{- if not (or .IsStruct .Extended)}} -WGPU_EXPORT void wgpu{{.Name | PascalCase}}Reference(WGPU{{.Name | PascalCase}} {{.Name | CamelCase}}) WGPU_FUNCTION_ATTRIBUTE; -WGPU_EXPORT void wgpu{{.Name | PascalCase}}Release(WGPU{{.Name | PascalCase}} {{.Name | CamelCase}}) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpu{{.Name | PascalCase}}Reference{{$.ExtSuffix}}(WGPU{{.Name | PascalCase}} {{.Name | CamelCase}}) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpu{{.Name | PascalCase}}Release{{$.ExtSuffix}}(WGPU{{.Name | PascalCase}} {{.Name | CamelCase}}) WGPU_FUNCTION_ATTRIBUTE; {{- end}} {{ end}}{{"\n" -}} diff --git a/gen/gen.go b/gen/gen.go index f9c63d26..95f5a6fa 100644 --- a/gen/gen.go +++ b/gen/gen.go @@ -11,11 +11,12 @@ import ( ) type Data struct { - Name string + Name string + ExtSuffix string *Yml } -func GenCHeader(data *Data, dst io.Writer) error { +func (d *Data) GenCHeader(dst io.Writer) error { t := template. New(""). Funcs(template.FuncMap{ @@ -26,17 +27,17 @@ func GenCHeader(data *Data, dst io.Writer) error { "ConstantCase": ConstantCase, "PascalCase": PascalCase, "CamelCase": CamelCase, - "CType": CType, - "CValue": CValue, - "EnumValue": EnumValue, - "BitflagValue": BitflagValue, + "CType": d.CType, + "CValue": d.CValue, + "EnumValue": d.EnumValue, + "BitflagValue": d.BitflagValue, "IsArray": func(typ string) bool { return arrayTypeRegexp.Match([]byte(typ)) }, "ArrayType": func(typ string, pointer PointerType) string { matches := arrayTypeRegexp.FindStringSubmatch(typ) if len(matches) == 2 { - return CType(matches[1], pointer) + return d.CType(matches[1], pointer, "") } return "" }, @@ -44,24 +45,25 @@ func GenCHeader(data *Data, dst io.Writer) error { "IsLast": func(i int, s any) bool { return i == reflect.ValueOf(s).Len()-1 }, "FunctionReturns": func(f Function) string { if f.Returns != nil { - return CType(f.Returns.Type, f.Returns.Pointer) + return d.CType(f.Returns.Type, f.Returns.Pointer, "") } return "void" }, - "FunctionArgs": FunctionArgs, - "CallbackArgs": CallbackArgs, + "FunctionArgs": d.FunctionArgs, + "CallbackArgs": d.CallbackArgs, + "StructMember": d.StructMember, }) t, err := t.Parse(tmpl) if err != nil { return fmt.Errorf("GenCHeader: failed to parse template: %w", err) } - if err := t.Execute(dst, data); err != nil { + if err := t.Execute(dst, d); err != nil { return fmt.Errorf("GenCHeader: failed to execute template: %w", err) } return nil } -func CValue(s string) (string, error) { +func (d *Data) CValue(s string) (string, error) { switch s { case "usize_max": return "SIZE_MAX", nil @@ -93,7 +95,7 @@ func CValue(s string) (string, error) { } } -func CType(typ string, pointerType PointerType) string { +func (d *Data) CType(typ string, pointerType PointerType, suffix string) string { appendModifiers := func(s string, pointerType PointerType) string { var sb strings.Builder sb.WriteString(s) @@ -132,44 +134,59 @@ func CType(typ string, pointerType PointerType) string { switch { case strings.HasPrefix(typ, "enum."): - ctype := "WGPU" + PascalCase(strings.TrimPrefix(typ, "enum.")) + ctype := "WGPU" + PascalCase(strings.TrimPrefix(typ, "enum.")) + suffix return appendModifiers(ctype, pointerType) case strings.HasPrefix(typ, "bitflag."): - ctype := "WGPU" + PascalCase(strings.TrimPrefix(typ, "bitflag.")) + "Flags" + ctype := "WGPU" + PascalCase(strings.TrimPrefix(typ, "bitflag.")) + "Flags" + suffix return appendModifiers(ctype, pointerType) case strings.HasPrefix(typ, "struct."): - ctype := "WGPU" + PascalCase(strings.TrimPrefix(typ, "struct.")) + ctype := "WGPU" + PascalCase(strings.TrimPrefix(typ, "struct.")) + suffix return appendModifiers(ctype, pointerType) case strings.HasPrefix(typ, "function_type."): - ctype := "WGPU" + PascalCase(strings.TrimPrefix(typ, "function_type.")) + ctype := "WGPU" + PascalCase(strings.TrimPrefix(typ, "function_type.")) + suffix return appendModifiers(ctype, pointerType) case strings.HasPrefix(typ, "object."): - ctype := "WGPU" + PascalCase(strings.TrimPrefix(typ, "object.")) + ctype := "WGPU" + PascalCase(strings.TrimPrefix(typ, "object.")) + suffix return appendModifiers(ctype, pointerType) default: return "" } } -func FunctionArgs(f Function, o *Object) string { +func (d *Data) FunctionArgs(f Function, o *Object) string { sb := &strings.Builder{} if o != nil { + var typeSuffix string + if o.Namespace == "" { + typeSuffix = ConstantCase(d.ExtSuffix) + } else if o.Namespace != "webgpu" { + typeSuffix = ConstantCase(o.Namespace) + } if len(f.Args) > 0 { - fmt.Fprintf(sb, "WGPU%s %s, ", PascalCase(o.Name), CamelCase(o.Name)) + fmt.Fprintf(sb, "WGPU%s%s %s, ", PascalCase(o.Name), typeSuffix, CamelCase(o.Name)) } else { - fmt.Fprintf(sb, "WGPU%s %s", PascalCase(o.Name), CamelCase(o.Name)) + fmt.Fprintf(sb, "WGPU%s%s %s", PascalCase(o.Name), typeSuffix, CamelCase(o.Name)) } } for i, arg := range f.Args { if arg.Optional { sb.WriteString("WGPU_NULLABLE ") } + if arg.Name == "instance_enumerate_adapters_result" { + fmt.Printf("%+v", arg) + } + var typeSuffix string + if arg.Namespace == "" { + typeSuffix = ConstantCase(d.ExtSuffix) + } else if arg.Namespace != "webgpu" { + typeSuffix = ConstantCase(arg.Namespace) + } matches := arrayTypeRegexp.FindStringSubmatch(arg.Type) if len(matches) == 2 { fmt.Fprintf(sb, "size_t %sCount, ", CamelCase(Singularize(arg.Name))) - fmt.Fprintf(sb, "%s %s", CType(matches[1], arg.Pointer), CamelCase(arg.Name)) + fmt.Fprintf(sb, "%s %s", d.CType(matches[1], arg.Pointer, typeSuffix), CamelCase(arg.Name)) } else { - fmt.Fprintf(sb, "%s %s", CType(arg.Type, arg.Pointer), CamelCase(arg.Name)) + fmt.Fprintf(sb, "%s %s", d.CType(arg.Type, arg.Pointer, typeSuffix), CamelCase(arg.Name)) } if i != len(f.Args)-1 { sb.WriteString(", ") @@ -187,12 +204,18 @@ func FunctionArgs(f Function, o *Object) string { return sb.String() } -func CallbackArgs(f Function) string { +func (d *Data) CallbackArgs(f Function) string { sb := &strings.Builder{} for _, arg := range f.ReturnsAsync { if arg.Optional { sb.WriteString("WGPU_NULLABLE ") } + var typeSuffix string + if arg.Namespace == "" { + typeSuffix = ConstantCase(d.ExtSuffix) + } else if arg.Namespace != "webgpu" { + typeSuffix = ConstantCase(arg.Namespace) + } var structPrefix string if strings.HasPrefix(arg.Type, "struct.") { structPrefix = "struct " @@ -200,16 +223,16 @@ func CallbackArgs(f Function) string { matches := arrayTypeRegexp.FindStringSubmatch(arg.Type) if len(matches) == 2 { fmt.Fprintf(sb, "size_t %sCount, ", CamelCase(Singularize(arg.Name))) - fmt.Fprintf(sb, "%s%s %s, ", structPrefix, CType(matches[1], arg.Pointer), CamelCase(arg.Name)) + fmt.Fprintf(sb, "%s%s %s, ", structPrefix, d.CType(matches[1], arg.Pointer, typeSuffix), CamelCase(arg.Name)) } else { - fmt.Fprintf(sb, "%s%s %s, ", structPrefix, CType(arg.Type, arg.Pointer), CamelCase(arg.Name)) + fmt.Fprintf(sb, "%s%s %s, ", structPrefix, d.CType(arg.Type, arg.Pointer, typeSuffix), CamelCase(arg.Name)) } } sb.WriteString("WGPU_NULLABLE void * userdata") return sb.String() } -func EnumValue(prefix string, e Enum, entryIndex int) (string, error) { +func (d *Data) EnumValue(prefix string, e Enum, entryIndex int) (string, error) { var entryValue uint16 entry := e.Entries[entryIndex] if entry.Value == "" { @@ -233,12 +256,15 @@ func EnumValue(prefix string, e Enum, entryIndex int) (string, error) { return fmt.Sprintf("%s%.4X", prefix, entryValue), nil } -func BitflagValue(b Bitflag, entryIndex int) (string, error) { +func (d *Data) BitflagValue(b Bitflag, entryIndex int) (string, error) { entry := b.Entries[entryIndex] var entryValue string if len(entry.ValueCombination) > 0 { for valueIndex, v := range entry.ValueCombination { entryValue += "WGPU" + PascalCase(b.Name) + "_" + PascalCase(v) + if d.ExtSuffix != "" { + entryValue += "_" + d.ExtSuffix + } if valueIndex != len(entry.ValueCombination)-1 { entryValue += " | " } @@ -266,3 +292,25 @@ func BitflagValue(b Bitflag, entryIndex int) (string, error) { } return entryValue, nil } + +func (d *Data) StructMember(s Struct, memberIndex int) (string, error) { + member := s.Members[memberIndex] + sb := &strings.Builder{} + if member.Optional { + sb.WriteString("WGPU_NULLABLE ") + } + var typeSuffix string + if member.Namespace == "" { + typeSuffix = ConstantCase(d.ExtSuffix) + } else if member.Namespace != "webgpu" { + typeSuffix = ConstantCase(member.Namespace) + } + matches := arrayTypeRegexp.FindStringSubmatch(member.Type) + if len(matches) == 2 { + fmt.Fprintf(sb, "size_t %sCount;\n", CamelCase(Singularize(member.Name))) + fmt.Fprintf(sb, " %s %s;", d.CType(matches[1], member.Pointer, typeSuffix), CamelCase(member.Name)) + } else { + fmt.Fprintf(sb, "%s %s;", d.CType(member.Type, member.Pointer, typeSuffix), CamelCase(member.Name)) + } + return sb.String(), nil +} diff --git a/gen/main.go b/gen/main.go index 543ec74a..f0c72136 100644 --- a/gen/main.go +++ b/gen/main.go @@ -19,12 +19,14 @@ var ( schemaPath string headerPaths StringListFlag yamlPaths StringListFlag + extSuffix bool ) func main() { flag.StringVar(&schemaPath, "schema", "", "path of the json schema") flag.Var(&yamlPaths, "yaml", "path of the yaml spec") flag.Var(&headerPaths, "header", "output path of the header") + flag.BoolVar(&extSuffix, "extsuffix", true, "append suffix to extension identifiers") flag.Parse() if schemaPath == "" || len(headerPaths) == 0 || len(yamlPaths) == 0 || len(headerPaths) != len(yamlPaths) { flag.Usage() @@ -67,10 +69,16 @@ func main() { panic("got invalid file name: " + fileName) } - var data Data - data.Yml = &yml - data.Name = fileNameSplit[0] - if err := GenCHeader(&data, dst); err != nil { + suffix := "" + if fileNameSplit[0] != "webgpu" && extSuffix { + suffix = strings.ToUpper(fileNameSplit[0]) + } + d := &Data{ + Yml: &yml, + Name: fileNameSplit[0], + ExtSuffix: suffix, + } + if err := d.GenCHeader(dst); err != nil { panic(err) } } diff --git a/gen/yml.go b/gen/yml.go index 2ac36146..0e577182 100644 --- a/gen/yml.go +++ b/gen/yml.go @@ -51,41 +51,6 @@ type BitflagEntry struct { ValueCombination []string `yaml:"value_combination"` } -type Function struct { - Name string `yaml:"name"` - Doc string `yaml:"doc"` - ReturnsAsync []FunctionArg `yaml:"returns_async"` - Returns *FunctionReturns `yaml:"returns"` - Args []FunctionArg `yaml:"args"` -} -type FunctionReturns struct { - Doc string `yaml:"doc"` - Type string `yaml:"type"` - Pointer PointerType `yaml:"pointer"` -} -type FunctionArg struct { - Name string `yaml:"name"` - Doc string `yaml:"doc"` - Type string `yaml:"type"` - Pointer PointerType `yaml:"pointer"` - Optional bool `yaml:"optional"` -} - -type Struct struct { - Name string `yaml:"name"` - Type string `yaml:"type"` - Doc string `yaml:"doc"` - FreeMembers bool `yaml:"free_members"` - Members []StructMember `yaml:"members"` -} -type StructMember struct { - Name string `yaml:"name"` - Type string `yaml:"type"` - Pointer PointerType `yaml:"pointer"` - Optional bool `yaml:"optional"` - Doc string `yaml:"doc"` -} - type PointerType string const ( @@ -93,11 +58,37 @@ const ( PointerTypeImmutable PointerType = "immutable" ) +type ParameterType struct { + Name string `yaml:"name"` + Doc string `yaml:"doc"` + Type string `yaml:"type"` + Pointer PointerType `yaml:"pointer"` + Optional bool `yaml:"optional"` + Namespace string `yaml:"namespace"` +} + +type Function struct { + Name string `yaml:"name"` + Doc string `yaml:"doc"` + ReturnsAsync []ParameterType `yaml:"returns_async"` + Returns *ParameterType `yaml:"returns"` + Args []ParameterType `yaml:"args"` +} + +type Struct struct { + Name string `yaml:"name"` + Type string `yaml:"type"` + Doc string `yaml:"doc"` + FreeMembers bool `yaml:"free_members"` + Members []ParameterType `yaml:"members"` +} + type Object struct { - Name string `yaml:"name"` - Doc string `yaml:"doc"` - Methods []Function `yaml:"methods"` - Extended bool `yaml:"extended"` + Name string `yaml:"name"` + Doc string `yaml:"doc"` + Methods []Function `yaml:"methods"` + Extended bool `yaml:"extended"` + Namespace string `yaml:"namespace"` IsStruct bool `yaml:"-"` } diff --git a/schema.json b/schema.json index 3af7526e..cac3d5b5 100644 --- a/schema.json +++ b/schema.json @@ -90,6 +90,11 @@ "optional": { "type": "boolean", "description": "Optional property, to indicate if a parameter is optional" + }, + "namespace": { + "type": "string", + "description": "Optional property, specifying the external namespace where this type is defined", + "pattern": "^[a-z]+$" } }, "required": [ @@ -360,6 +365,11 @@ "type": "boolean", "description": "Optional property, an indicator that this object is an extension of an already present object" }, + "namespace": { + "type": "string", + "description": "Optional property, specifying the external namespace where this object is defined", + "pattern": "^[a-z]+$" + }, "methods": { "type": "array", "items": { From b5e31c5091c6bdda1392c8c23b3a585193e34b53 Mon Sep 17 00:00:00 2001 From: rajveermalviya Date: Sun, 3 Mar 2024 11:32:00 +0530 Subject: [PATCH 10/10] specify namespace in yaml --- gen/cheader.tmpl | 6 ++--- gen/gen.go | 66 ++++++++++++++++++++++++------------------------ gen/main.go | 38 ++++++++++++++-------------- gen/yml.go | 1 + schema.json | 5 ++++ webgpu.yml | 1 + 6 files changed, 62 insertions(+), 55 deletions(-) diff --git a/gen/cheader.tmpl b/gen/cheader.tmpl index 7e67feca..3ecac9cb 100644 --- a/gen/cheader.tmpl +++ b/gen/cheader.tmpl @@ -1,7 +1,7 @@ {{- MCommentN .Copyright 0}} -#ifndef {{.Name | ConstantCase}}_H_ -#define {{.Name | ConstantCase}}_H_ +#ifndef {{.HeaderName | ConstantCase}}_H_ +#define {{.HeaderName | ConstantCase}}_H_ #if defined(WGPU_SHARED_LIBRARY) # if defined(_WIN32) @@ -222,4 +222,4 @@ WGPU_EXPORT void wgpu{{.Name | PascalCase}}Release{{$.ExtSuffix}}(WGPU{{.Name | } // extern "C" #endif -#endif // {{.Name | ConstantCase}}_H_ +#endif // {{.HeaderName | ConstantCase}}_H_ diff --git a/gen/gen.go b/gen/gen.go index 95f5a6fa..1a15a38d 100644 --- a/gen/gen.go +++ b/gen/gen.go @@ -10,13 +10,13 @@ import ( "text/template" ) -type Data struct { - Name string - ExtSuffix string +type Generator struct { + ExtSuffix string + HeaderName string *Yml } -func (d *Data) GenCHeader(dst io.Writer) error { +func (g *Generator) Gen(dst io.Writer) error { t := template. New(""). Funcs(template.FuncMap{ @@ -27,17 +27,17 @@ func (d *Data) GenCHeader(dst io.Writer) error { "ConstantCase": ConstantCase, "PascalCase": PascalCase, "CamelCase": CamelCase, - "CType": d.CType, - "CValue": d.CValue, - "EnumValue": d.EnumValue, - "BitflagValue": d.BitflagValue, + "CType": g.CType, + "CValue": g.CValue, + "EnumValue": g.EnumValue, + "BitflagValue": g.BitflagValue, "IsArray": func(typ string) bool { return arrayTypeRegexp.Match([]byte(typ)) }, "ArrayType": func(typ string, pointer PointerType) string { matches := arrayTypeRegexp.FindStringSubmatch(typ) if len(matches) == 2 { - return d.CType(matches[1], pointer, "") + return g.CType(matches[1], pointer, "") } return "" }, @@ -45,25 +45,25 @@ func (d *Data) GenCHeader(dst io.Writer) error { "IsLast": func(i int, s any) bool { return i == reflect.ValueOf(s).Len()-1 }, "FunctionReturns": func(f Function) string { if f.Returns != nil { - return d.CType(f.Returns.Type, f.Returns.Pointer, "") + return g.CType(f.Returns.Type, f.Returns.Pointer, "") } return "void" }, - "FunctionArgs": d.FunctionArgs, - "CallbackArgs": d.CallbackArgs, - "StructMember": d.StructMember, + "FunctionArgs": g.FunctionArgs, + "CallbackArgs": g.CallbackArgs, + "StructMember": g.StructMember, }) t, err := t.Parse(tmpl) if err != nil { return fmt.Errorf("GenCHeader: failed to parse template: %w", err) } - if err := t.Execute(dst, d); err != nil { + if err := t.Execute(dst, g); err != nil { return fmt.Errorf("GenCHeader: failed to execute template: %w", err) } return nil } -func (d *Data) CValue(s string) (string, error) { +func (g *Generator) CValue(s string) (string, error) { switch s { case "usize_max": return "SIZE_MAX", nil @@ -95,7 +95,7 @@ func (d *Data) CValue(s string) (string, error) { } } -func (d *Data) CType(typ string, pointerType PointerType, suffix string) string { +func (g *Generator) CType(typ string, pointerType PointerType, suffix string) string { appendModifiers := func(s string, pointerType PointerType) string { var sb strings.Builder sb.WriteString(s) @@ -153,12 +153,12 @@ func (d *Data) CType(typ string, pointerType PointerType, suffix string) string } } -func (d *Data) FunctionArgs(f Function, o *Object) string { +func (g *Generator) FunctionArgs(f Function, o *Object) string { sb := &strings.Builder{} if o != nil { var typeSuffix string if o.Namespace == "" { - typeSuffix = ConstantCase(d.ExtSuffix) + typeSuffix = ConstantCase(g.ExtSuffix) } else if o.Namespace != "webgpu" { typeSuffix = ConstantCase(o.Namespace) } @@ -177,16 +177,16 @@ func (d *Data) FunctionArgs(f Function, o *Object) string { } var typeSuffix string if arg.Namespace == "" { - typeSuffix = ConstantCase(d.ExtSuffix) + typeSuffix = ConstantCase(g.ExtSuffix) } else if arg.Namespace != "webgpu" { typeSuffix = ConstantCase(arg.Namespace) } matches := arrayTypeRegexp.FindStringSubmatch(arg.Type) if len(matches) == 2 { fmt.Fprintf(sb, "size_t %sCount, ", CamelCase(Singularize(arg.Name))) - fmt.Fprintf(sb, "%s %s", d.CType(matches[1], arg.Pointer, typeSuffix), CamelCase(arg.Name)) + fmt.Fprintf(sb, "%s %s", g.CType(matches[1], arg.Pointer, typeSuffix), CamelCase(arg.Name)) } else { - fmt.Fprintf(sb, "%s %s", d.CType(arg.Type, arg.Pointer, typeSuffix), CamelCase(arg.Name)) + fmt.Fprintf(sb, "%s %s", g.CType(arg.Type, arg.Pointer, typeSuffix), CamelCase(arg.Name)) } if i != len(f.Args)-1 { sb.WriteString(", ") @@ -204,7 +204,7 @@ func (d *Data) FunctionArgs(f Function, o *Object) string { return sb.String() } -func (d *Data) CallbackArgs(f Function) string { +func (g *Generator) CallbackArgs(f Function) string { sb := &strings.Builder{} for _, arg := range f.ReturnsAsync { if arg.Optional { @@ -212,7 +212,7 @@ func (d *Data) CallbackArgs(f Function) string { } var typeSuffix string if arg.Namespace == "" { - typeSuffix = ConstantCase(d.ExtSuffix) + typeSuffix = ConstantCase(g.ExtSuffix) } else if arg.Namespace != "webgpu" { typeSuffix = ConstantCase(arg.Namespace) } @@ -223,16 +223,16 @@ func (d *Data) CallbackArgs(f Function) string { matches := arrayTypeRegexp.FindStringSubmatch(arg.Type) if len(matches) == 2 { fmt.Fprintf(sb, "size_t %sCount, ", CamelCase(Singularize(arg.Name))) - fmt.Fprintf(sb, "%s%s %s, ", structPrefix, d.CType(matches[1], arg.Pointer, typeSuffix), CamelCase(arg.Name)) + fmt.Fprintf(sb, "%s%s %s, ", structPrefix, g.CType(matches[1], arg.Pointer, typeSuffix), CamelCase(arg.Name)) } else { - fmt.Fprintf(sb, "%s%s %s, ", structPrefix, d.CType(arg.Type, arg.Pointer, typeSuffix), CamelCase(arg.Name)) + fmt.Fprintf(sb, "%s%s %s, ", structPrefix, g.CType(arg.Type, arg.Pointer, typeSuffix), CamelCase(arg.Name)) } } sb.WriteString("WGPU_NULLABLE void * userdata") return sb.String() } -func (d *Data) EnumValue(prefix string, e Enum, entryIndex int) (string, error) { +func (g *Generator) EnumValue(prefix string, e Enum, entryIndex int) (string, error) { var entryValue uint16 entry := e.Entries[entryIndex] if entry.Value == "" { @@ -256,14 +256,14 @@ func (d *Data) EnumValue(prefix string, e Enum, entryIndex int) (string, error) return fmt.Sprintf("%s%.4X", prefix, entryValue), nil } -func (d *Data) BitflagValue(b Bitflag, entryIndex int) (string, error) { +func (g *Generator) BitflagValue(b Bitflag, entryIndex int) (string, error) { entry := b.Entries[entryIndex] var entryValue string if len(entry.ValueCombination) > 0 { for valueIndex, v := range entry.ValueCombination { entryValue += "WGPU" + PascalCase(b.Name) + "_" + PascalCase(v) - if d.ExtSuffix != "" { - entryValue += "_" + d.ExtSuffix + if g.ExtSuffix != "" { + entryValue += "_" + g.ExtSuffix } if valueIndex != len(entry.ValueCombination)-1 { entryValue += " | " @@ -293,7 +293,7 @@ func (d *Data) BitflagValue(b Bitflag, entryIndex int) (string, error) { return entryValue, nil } -func (d *Data) StructMember(s Struct, memberIndex int) (string, error) { +func (g *Generator) StructMember(s Struct, memberIndex int) (string, error) { member := s.Members[memberIndex] sb := &strings.Builder{} if member.Optional { @@ -301,16 +301,16 @@ func (d *Data) StructMember(s Struct, memberIndex int) (string, error) { } var typeSuffix string if member.Namespace == "" { - typeSuffix = ConstantCase(d.ExtSuffix) + typeSuffix = ConstantCase(g.ExtSuffix) } else if member.Namespace != "webgpu" { typeSuffix = ConstantCase(member.Namespace) } matches := arrayTypeRegexp.FindStringSubmatch(member.Type) if len(matches) == 2 { fmt.Fprintf(sb, "size_t %sCount;\n", CamelCase(Singularize(member.Name))) - fmt.Fprintf(sb, " %s %s;", d.CType(matches[1], member.Pointer, typeSuffix), CamelCase(member.Name)) + fmt.Fprintf(sb, " %s %s;", g.CType(matches[1], member.Pointer, typeSuffix), CamelCase(member.Name)) } else { - fmt.Fprintf(sb, "%s %s;", d.CType(member.Type, member.Pointer, typeSuffix), CamelCase(member.Name)) + fmt.Fprintf(sb, "%s %s;", g.CType(member.Type, member.Pointer, typeSuffix), CamelCase(member.Name)) } return sb.String(), nil } diff --git a/gen/main.go b/gen/main.go index f0c72136..ca0bc46a 100644 --- a/gen/main.go +++ b/gen/main.go @@ -45,40 +45,40 @@ func main() { // Generate the header files for i, yamlPath := range yamlPaths { - src, err := os.ReadFile(yamlPath) - if err != nil { - panic(err) + headerPath := headerPaths[i] + headerFileName := filepath.Base(headerPath) + headerFileNameSplit := strings.Split(headerFileName, ".") + if len(headerFileNameSplit) != 2 { + panic("got invalid header file name: " + headerFileName) } - var yml Yml - if err := yaml.Unmarshal(src, &yml); err != nil { + src, err := os.ReadFile(yamlPath) + if err != nil { panic(err) } - SortAndTransform(&yml) - - headerPath := headerPaths[i] dst, err := os.Create(headerPath) if err != nil { panic(err) } - fileName := filepath.Base(yamlPath) - fileNameSplit := strings.Split(fileName, ".") - if len(fileNameSplit) != 2 { - panic("got invalid file name: " + fileName) + var yml Yml + if err := yaml.Unmarshal(src, &yml); err != nil { + panic(err) } + SortAndTransform(&yml) + suffix := "" - if fileNameSplit[0] != "webgpu" && extSuffix { - suffix = strings.ToUpper(fileNameSplit[0]) + if yml.Name != "webgpu" && extSuffix { + suffix = strings.ToUpper(yml.Name) } - d := &Data{ - Yml: &yml, - Name: fileNameSplit[0], - ExtSuffix: suffix, + g := &Generator{ + Yml: &yml, + HeaderName: headerFileNameSplit[0], + ExtSuffix: suffix, } - if err := d.GenCHeader(dst); err != nil { + if err := g.Gen(dst); err != nil { panic(err) } } diff --git a/gen/yml.go b/gen/yml.go index 0e577182..329f8994 100644 --- a/gen/yml.go +++ b/gen/yml.go @@ -9,6 +9,7 @@ import ( type Yml struct { Copyright string `yaml:"copyright"` + Name string `yaml:"name"` EnumPrefix string `yaml:"enum_prefix"` Constants []Constant `yaml:"constants"` diff --git a/schema.json b/schema.json index cac3d5b5..5b17137d 100644 --- a/schema.json +++ b/schema.json @@ -160,6 +160,10 @@ "type": "string", "description": "The license string to include at the top of the generated header" }, + "name": { + "$ref": "#/definitions/Name", + "description": "The name/namespace of the specification" + }, "enum_prefix": { "type": "string", "pattern": "^0x[0-9]{4}$", @@ -382,6 +386,7 @@ }, "required": [ "copyright", + "name", "enum_prefix", "constants", "enums", diff --git a/webgpu.yml b/webgpu.yml index 67f1da90..dba6abf6 100644 --- a/webgpu.yml +++ b/webgpu.yml @@ -3,6 +3,7 @@ copyright: | SPDX-License-Identifier: BSD-3-Clause +name: webgpu enum_prefix: '0x0000' constants: