Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add INIT macros with default values #422

Merged
merged 24 commits into from
Nov 21, 2024
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
8753009
Add INIT macros with default values
eliemichel Nov 16, 2024
384b717
Fix docstring trimming issue for enums
eliemichel Nov 16, 2024
08ce163
Minor changes following review
eliemichel Nov 20, 2024
ce11135
Use BindingNotUsed by default
eliemichel Nov 20, 2024
0e4241a
Initialize STypes
eliemichel Nov 20, 2024
0d12155
Add default values to docstrings
eliemichel Nov 20, 2024
243b808
Merge branch 'main' into eliemichel/default-values
eliemichel Nov 20, 2024
b78dac1
Fix typo in default value
eliemichel Nov 20, 2024
f9089c7
Add test for initializers and fix issues in default values
eliemichel Nov 21, 2024
c587ff8
Further remove unused-variable warning with MSVC
eliemichel Nov 21, 2024
5c54324
Remove any use of GNU empty initializer extension
eliemichel Nov 21, 2024
1947b2f
Roll back undefined vertex_format and use _wgpu_ZERO_INIT
eliemichel Nov 21, 2024
d543b8e
Use first non-null enum entry as default value for enum members
eliemichel Nov 21, 2024
a376c86
Always initialize pointer members to NULL
eliemichel Nov 21, 2024
c4e6545
Fix incorrect default values reported by Kai
eliemichel Nov 21, 2024
6dfb899
Remove unused tentative _wgpu_ZERO_INIT
eliemichel Nov 21, 2024
e127ef3
Revert "Use first non-null enum entry as default value for enum members"
kainino0x Nov 21, 2024
53cf21f
Use _wgpu_ENUM_ZERO_INIT
kainino0x Nov 21, 2024
1085f75
nit: remove comment that could become outdated later
kainino0x Nov 21, 2024
b84e311
Use 0xFFFFFFFF as string
kainino0x Nov 21, 2024
3b0992f
Comment formatting nits
kainino0x Nov 21, 2024
cc2fcde
Add docs to INIT macros
kainino0x Nov 21, 2024
3da031e
change featureLevel and adapterType back to 0
kainino0x Nov 21, 2024
7d6a3f0
revert temporary change
kainino0x Nov 21, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 33 additions & 1 deletion gen/cheader.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -68,14 +68,17 @@
{{- if eq .Name "webgpu"}}
#define _wgpu_COMMA ,
#if defined(__cplusplus)
# define _wgpu_ZERO_INIT {}
# if __cplusplus >= 201103L
# define _wgpu_MAKE_INIT_STRUCT(type, value) (type value)
# else
# define _wgpu_MAKE_INIT_STRUCT(type, value) value
# endif
#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
# define _wgpu_ZERO_INIT {0}
# define _wgpu_MAKE_INIT_STRUCT(type, value) ((type) value)
#else
# define _wgpu_ZERO_INIT {0}
# define _wgpu_MAKE_INIT_STRUCT(type, value) value
#endif
{{end}}
Expand Down Expand Up @@ -294,13 +297,23 @@ typedef struct WGPU{{.Name | PascalCase}}CallbackInfo{{$.ExtSuffix}} {
WGPU_NULLABLE void* userdata1;
WGPU_NULLABLE void* userdata2;
} WGPU{{.Name | PascalCase}}CallbackInfo{{$.ExtSuffix}} WGPU_STRUCTURE_ATTRIBUTE;

#define WGPU_{{.Name | ConstantCase}}_CALLBACK_INFO{{$.ExtSuffix}}_INIT _wgpu_MAKE_INIT_STRUCT(WGPU{{.Name | PascalCase}}CallbackInfo{{$.ExtSuffix}}, { \
/*.nextInChain=*/NULL _wgpu_COMMA \
{{- if eq .Style "callback_mode" }}
/*.mode=*/WGPUCallbackMode_WaitAnyOnly _wgpu_COMMA \
{{- end}}
/*.callback=*/NULL _wgpu_COMMA \
/*.userdata1=*/NULL _wgpu_COMMA \
/*.userdata2=*/NULL _wgpu_COMMA \
})
{{ end}}{{"\n" -}}

/** @} */

{{- "\n"}}
{{- range $struct := .Structs}}
{{- MComment .Doc 0}}
{{- MCommentStruct . 0}}
typedef struct WGPU{{.Name | PascalCase}}{{$.ExtSuffix}} {
{{- if eq .Type "base_in" }}
WGPUChainedStruct const * nextInChain;
Expand All @@ -322,6 +335,25 @@ typedef struct WGPU{{.Name | PascalCase}}{{$.ExtSuffix}} {
{{ StructMember $struct $memberIndex}}
{{- end}}
} WGPU{{.Name | PascalCase}}{{$.ExtSuffix}} WGPU_STRUCTURE_ATTRIBUTE;

#define WGPU_{{.Name | ConstantCase}}{{if $.ExtSuffix}}_{{$.ExtSuffix}}{{end}}_INIT _wgpu_MAKE_INIT_STRUCT(WGPU{{.Name | PascalCase}}{{$.ExtSuffix}}, { \
{{- if eq .Type "base_in" "base_out" "base_in_or_out" }}
/*.nextInChain=*/NULL _wgpu_COMMA \
{{- else if eq .Type "extension_in" }}
/*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStruct, { \
/*.next=*/NULL _wgpu_COMMA \
/*.sType=*/WGPUSType_{{.Name | PascalCase}}{{$.ExtSuffix}} _wgpu_COMMA \
}) _wgpu_COMMA \
{{- else if eq .Type "extension_out" "extension_in_or_out" }}
/*.chain=*/_wgpu_MAKE_INIT_STRUCT(WGPUChainedStructOut, { \
/*.next=*/NULL _wgpu_COMMA \
/*.sType=*/WGPUSType_{{.Name | PascalCase}}{{$.ExtSuffix}} _wgpu_COMMA \
}) _wgpu_COMMA \
{{- end }}
{{- range $memberIndex, $_ := .Members}}
{{ StructMemberInitializer $struct $memberIndex}}
{{- end}}
})
{{ end}}{{"\n" -}}

/** @} */
Expand Down
127 changes: 126 additions & 1 deletion gen/gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func (g *Generator) Gen(dst io.Writer) error {
return ""
}
value, _ := g.EnumValue(prefix, e, entryIndex)
return Comment("`"+value+"`.\n"+v, CommentTypeMultiLine, indent, true)
return Comment("`"+value+"`.\n"+strings.TrimSpace(v), CommentTypeMultiLine, indent, true)
},
"MCommentBitflag": func(v string, indent int, b Bitflag, entryIndex int) string {
if v == "" || strings.TrimSpace(v) == "TODO" {
Expand Down Expand Up @@ -122,12 +122,26 @@ func (g *Generator) Gen(dst io.Writer) error {
s += "\n\nThis is an \\ref OutputString."
}

s += "\n\nDefaults to " + g.DefaultValue(*member, true /* isDocString */)

if member.PassedWithOwnership != nil {
panic("invalid")
}

return Comment(strings.TrimSpace(s), CommentTypeMultiLine, indent, true)
},
"MCommentStruct": func(st *Struct, indent int) string {
var s string

var srcDoc = strings.TrimSpace(st.Doc)
if srcDoc != "" && srcDoc != "TODO" {
s += srcDoc
}

s += "\n\nDefault values can be set using WGPU_" + ConstantCase(st.Name) + "_INIT as initializer."

return Comment(strings.TrimSpace(s), CommentTypeMultiLine, indent, true)
},
"ConstantCase": ConstantCase,
"PascalCase": PascalCase,
"CamelCase": CamelCase,
Expand Down Expand Up @@ -159,6 +173,7 @@ func (g *Generator) Gen(dst io.Writer) error {
"FunctionArgs": g.FunctionArgs,
"CallbackArgs": g.CallbackArgs,
"StructMember": g.StructMember,
"StructMemberInitializer": g.StructMemberInitializer,
})
t, err := t.Parse(tmpl)
if err != nil {
Expand Down Expand Up @@ -446,3 +461,113 @@ func (g *Generator) StructMember(s Struct, memberIndex int) (string, error) {
}
return sb.String(), nil
}

func (g *Generator) StructMemberInitializer(s Struct, memberIndex int) (string, error) {
member := s.Members[memberIndex]
sb := &strings.Builder{}
matches := arrayTypeRegexp.FindStringSubmatch(member.Type)
if len(matches) == 2 {
fmt.Fprintf(sb, "/*.%sCount=*/0 _wgpu_COMMA \\\n", CamelCase(Singularize(member.Name)))
fmt.Fprintf(sb, " /*.%s=*/NULL _wgpu_COMMA \\", CamelCase(member.Name))
} else {
fmt.Fprintf(sb, "/*.%s=*/%s _wgpu_COMMA \\", CamelCase(member.Name), g.DefaultValue(member, false /* isDocString */))
}
return sb.String(), nil
}

func (g *Generator) DefaultValue(member ParameterType, isDocString bool) string {
ref := ""
if (isDocString) {
ref = "@ref "
}
switch {
case member.Pointer != "":
return "NULL"
case strings.HasPrefix(member.Type, "enum."):
if member.Default == "" {
if member.Type == "enum.optional_bool" {
// This Undefined is a special one that is not the zero-value, so that
// a stdbool.h bool cast correctly to WGPUOptionalBool; this means we
// must explicitly initialize it
return ref + "WGPUOptionalBool_Undefined"
} else {
enumName := strings.TrimPrefix(member.Type, "enum.")
// Look for the first entry of this enum and use it as default
for _, enum := range g.Enums {
if enum.Name != enumName { continue }
for _, entry := range enum.Entries {
if entry == nil { continue }
return ref + "WGPU" + PascalCase(enumName) + "_" + PascalCase(entry.Name)
}
}
panic("invalid enum name: '" + enumName + "' in member '" + member.Name + "'")
}
} else {
return ref + "WGPU" + PascalCase(strings.TrimPrefix(member.Type, "enum.")) + "_" + PascalCase(member.Default)
}
case strings.HasPrefix(member.Type, "bitflag."):
if member.Default == "" {
return ref + "WGPU" + PascalCase(strings.TrimPrefix(member.Type, "bitflag.")) + "_None"
} else {
return ref + "WGPU" + PascalCase(strings.TrimPrefix(member.Type, "bitflag.")) + "_" + PascalCase(member.Default)
}
case strings.HasPrefix(member.Type, "struct."):
if member.Optional {
return "NULL"
} else {
typ := strings.TrimPrefix(member.Type, "struct.");
return ref + "WGPU_" + ConstantCase(typ) + "_INIT"
}
case strings.HasPrefix(member.Type, "callback."):
typ := strings.TrimPrefix(member.Type, "callback.");
return ref + "WGPU_" + ConstantCase(typ) + "_CALLBACK_INFO_INIT"
case strings.HasPrefix(member.Type, "object."):
return "NULL"
case strings.HasPrefix(member.Type, "array<"):
return "NULL"
case member.Type == "out_string", member.Type == "string_with_default_empty", member.Type == "nullable_string":
return ref + "WGPU_STRING_VIEW_INIT"
case member.Type == "uint16", member.Type == "uint32", member.Type == "uint64", member.Type == "usize", member.Type == "int32":
if member.Default == "" {
return "0"
} else if strings.HasPrefix(member.Default, "constant.") {
return ref + "WGPU_" + ConstantCase(strings.TrimPrefix(member.Default, "constant."))
} else {
return member.Default
}
case member.Type == "float32":
if member.Default == "" {
return "0.0f"
} else if strings.HasPrefix(member.Default, "constant.") {
return ref + "WGPU_" + ConstantCase(strings.TrimPrefix(member.Default, "constant."))
} else if strings.Contains(member.Default, ".") {
return member.Default + "f"
} else {
return member.Default + ".f"
}
case member.Type == "float64":
if member.Default == "" {
return "0.0"
} else if strings.HasPrefix(member.Default, "constant.") {
return ref + "WGPU_" + ConstantCase(strings.TrimPrefix(member.Default, "constant."))
} else {
return member.Default
}
case member.Type == "bool":
if member.Default == "" {
return "0"
} else if strings.HasPrefix(member.Default, "constant.") {
return ref + "WGPU_" + ConstantCase(strings.TrimPrefix(member.Default, "constant."))
} else if member.Default == "true" {
return "1"
} else if member.Default == "false" {
return "0"
} else {
return member.Default
}
case member.Type == "c_void":
return "NULL"
default:
panic("invalid prefix: '" + member.Type + "' in member '" + member.Name + "'")
}
}
1 change: 1 addition & 0 deletions gen/yml.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ type ParameterType struct {
Pointer PointerType `yaml:"pointer"`
Optional bool `yaml:"optional"`
Namespace string `yaml:"namespace"`
Default string `yaml:"default"`
}

type Callback struct {
Expand Down
4 changes: 4 additions & 0 deletions schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,10 @@
"type": "string",
"description": "Optional property, specifying the external namespace where this type is defined",
"pattern": "^[a-z]+$"
},
"default": {
"type": [ "string", "number", "boolean" ],
"description": "Default value assigned to this parameter when using initializer macro"
}
},
"required": [
Expand Down
83 changes: 83 additions & 0 deletions tests/compile/main.inl
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,87 @@ int main(void) {
a.beginningOfPassWriteIndex = WGPU_QUERY_SET_INDEX_UNDEFINED;
a.endOfPassWriteIndex = WGPU_QUERY_SET_INDEX_UNDEFINED;
}

// Check that generated initializers are valid
// TODO: Would be nice to autogenerate this so we don't forget to test any new structs.
{ WGPUBufferMapCallbackInfo x = WGPU_BUFFER_MAP_CALLBACK_INFO_INIT; }
{ WGPUCompilationInfoCallbackInfo x = WGPU_COMPILATION_INFO_CALLBACK_INFO_INIT; }
{ WGPUCreateComputePipelineAsyncCallbackInfo x = WGPU_CREATE_COMPUTE_PIPELINE_ASYNC_CALLBACK_INFO_INIT; }
{ WGPUCreateRenderPipelineAsyncCallbackInfo x = WGPU_CREATE_RENDER_PIPELINE_ASYNC_CALLBACK_INFO_INIT; }
{ WGPUDeviceLostCallbackInfo x = WGPU_DEVICE_LOST_CALLBACK_INFO_INIT; }
{ WGPUPopErrorScopeCallbackInfo x = WGPU_POP_ERROR_SCOPE_CALLBACK_INFO_INIT; }
{ WGPUQueueWorkDoneCallbackInfo x = WGPU_QUEUE_WORK_DONE_CALLBACK_INFO_INIT; }
{ WGPURequestAdapterCallbackInfo x = WGPU_REQUEST_ADAPTER_CALLBACK_INFO_INIT; }
{ WGPURequestDeviceCallbackInfo x = WGPU_REQUEST_DEVICE_CALLBACK_INFO_INIT; }
{ WGPUUncapturedErrorCallbackInfo x = WGPU_UNCAPTURED_ERROR_CALLBACK_INFO_INIT; }
{ WGPUAdapterInfo x = WGPU_ADAPTER_INFO_INIT; }
{ WGPUBindGroupEntry x = WGPU_BIND_GROUP_ENTRY_INIT; }
{ WGPUBlendComponent x = WGPU_BLEND_COMPONENT_INIT; }
{ WGPUBufferBindingLayout x = WGPU_BUFFER_BINDING_LAYOUT_INIT; }
{ WGPUBufferDescriptor x = WGPU_BUFFER_DESCRIPTOR_INIT; }
{ WGPUColor x = WGPU_COLOR_INIT; }
{ WGPUCommandBufferDescriptor x = WGPU_COMMAND_BUFFER_DESCRIPTOR_INIT; }
{ WGPUCommandEncoderDescriptor x = WGPU_COMMAND_ENCODER_DESCRIPTOR_INIT; }
{ WGPUCompilationMessage x = WGPU_COMPILATION_MESSAGE_INIT; }
{ WGPUComputePassTimestampWrites x = WGPU_COMPUTE_PASS_TIMESTAMP_WRITES_INIT; }
{ WGPUConstantEntry x = WGPU_CONSTANT_ENTRY_INIT; }
{ WGPUFuture x = WGPU_FUTURE_INIT; }
{ WGPUInstanceCapabilities x = WGPU_INSTANCE_CAPABILITIES_INIT; }
{ WGPULimits x = WGPU_LIMITS_INIT; }
{ WGPUMultisampleState x = WGPU_MULTISAMPLE_STATE_INIT; }
{ WGPUPipelineLayoutDescriptor x = WGPU_PIPELINE_LAYOUT_DESCRIPTOR_INIT; }
{ WGPUPrimitiveState x = WGPU_PRIMITIVE_STATE_INIT; }
{ WGPUQuerySetDescriptor x = WGPU_QUERY_SET_DESCRIPTOR_INIT; }
{ WGPUQueueDescriptor x = WGPU_QUEUE_DESCRIPTOR_INIT; }
{ WGPURenderBundleDescriptor x = WGPU_RENDER_BUNDLE_DESCRIPTOR_INIT; }
{ WGPURenderBundleEncoderDescriptor x = WGPU_RENDER_BUNDLE_ENCODER_DESCRIPTOR_INIT; }
{ WGPURenderPassDepthStencilAttachment x = WGPU_RENDER_PASS_DEPTH_STENCIL_ATTACHMENT_INIT; }
{ WGPURenderPassMaxDrawCount x = WGPU_RENDER_PASS_MAX_DRAW_COUNT_INIT; }
{ WGPURenderPassTimestampWrites x = WGPU_RENDER_PASS_TIMESTAMP_WRITES_INIT; }
{ WGPURequestAdapterOptions x = WGPU_REQUEST_ADAPTER_OPTIONS_INIT; }
{ WGPUSamplerBindingLayout x = WGPU_SAMPLER_BINDING_LAYOUT_INIT; }
{ WGPUSamplerDescriptor x = WGPU_SAMPLER_DESCRIPTOR_INIT; }
{ WGPUShaderModuleDescriptor x = WGPU_SHADER_MODULE_DESCRIPTOR_INIT; }
{ WGPUShaderSourceSPIRV x = WGPU_SHADER_SOURCE_SPIRV_INIT; }
{ WGPUShaderSourceWGSL x = WGPU_SHADER_SOURCE_WGSL_INIT; }
{ WGPUStencilFaceState x = WGPU_STENCIL_FACE_STATE_INIT; }
{ WGPUStorageTextureBindingLayout x = WGPU_STORAGE_TEXTURE_BINDING_LAYOUT_INIT; }
{ WGPUSupportedFeatures x = WGPU_SUPPORTED_FEATURES_INIT; }
{ WGPUSupportedWGSLLanguageFeatures x = WGPU_SUPPORTED_WGSL_LANGUAGE_FEATURES_INIT; }
{ WGPUSurfaceCapabilities x = WGPU_SURFACE_CAPABILITIES_INIT; }
{ WGPUSurfaceConfiguration x = WGPU_SURFACE_CONFIGURATION_INIT; }
{ WGPUSurfaceDescriptor x = WGPU_SURFACE_DESCRIPTOR_INIT; }
{ WGPUSurfaceSourceAndroidNativeWindow x = WGPU_SURFACE_SOURCE_ANDROID_NATIVE_WINDOW_INIT; }
{ WGPUSurfaceSourceMetalLayer x = WGPU_SURFACE_SOURCE_METAL_LAYER_INIT; }
{ WGPUSurfaceSourceWaylandSurface x = WGPU_SURFACE_SOURCE_WAYLAND_SURFACE_INIT; }
{ WGPUSurfaceSourceWindowsHWND x = WGPU_SURFACE_SOURCE_WINDOWS_HWND_INIT; }
{ WGPUSurfaceSourceXCBWindow x = WGPU_SURFACE_SOURCE_XCB_WINDOW_INIT; }
{ WGPUSurfaceSourceXlibWindow x = WGPU_SURFACE_SOURCE_XLIB_WINDOW_INIT; }
{ WGPUSurfaceTexture x = WGPU_SURFACE_TEXTURE_INIT; }
{ WGPUTexelCopyBufferLayout x = WGPU_TEXEL_COPY_BUFFER_LAYOUT_INIT; }
{ WGPUTextureBindingLayout x = WGPU_TEXTURE_BINDING_LAYOUT_INIT; }
{ WGPUTextureViewDescriptor x = WGPU_TEXTURE_VIEW_DESCRIPTOR_INIT; }
{ WGPUVertexAttribute x = WGPU_VERTEX_ATTRIBUTE_INIT; }
{ WGPUBindGroupDescriptor x = WGPU_BIND_GROUP_DESCRIPTOR_INIT; }
{ WGPUBindGroupLayoutEntry x = WGPU_BIND_GROUP_LAYOUT_ENTRY_INIT; }
{ WGPUBlendState x = WGPU_BLEND_STATE_INIT; }
{ WGPUCompilationInfo x = WGPU_COMPILATION_INFO_INIT; }
{ WGPUComputePassDescriptor x = WGPU_COMPUTE_PASS_DESCRIPTOR_INIT; }
{ WGPUComputeStage x = WGPU_COMPUTE_STAGE_INIT; }
{ WGPUDepthStencilState x = WGPU_DEPTH_STENCIL_STATE_INIT; }
{ WGPUDeviceDescriptor x = WGPU_DEVICE_DESCRIPTOR_INIT; }
{ WGPUFutureWaitInfo x = WGPU_FUTURE_WAIT_INFO_INIT; }
{ WGPUInstanceDescriptor x = WGPU_INSTANCE_DESCRIPTOR_INIT; }
{ WGPURenderPassColorAttachment x = WGPU_RENDER_PASS_COLOR_ATTACHMENT_INIT; }
{ WGPUTexelCopyBufferInfo x = WGPU_TEXEL_COPY_BUFFER_INFO_INIT; }
{ WGPUTexelCopyTextureInfo x = WGPU_TEXEL_COPY_TEXTURE_INFO_INIT; }
{ WGPUTextureDescriptor x = WGPU_TEXTURE_DESCRIPTOR_INIT; }
{ WGPUVertexBufferLayout x = WGPU_VERTEX_BUFFER_LAYOUT_INIT; }
{ WGPUBindGroupLayoutDescriptor x = WGPU_BIND_GROUP_LAYOUT_DESCRIPTOR_INIT; }
{ WGPUColorTargetState x = WGPU_COLOR_TARGET_STATE_INIT; }
{ WGPUComputePipelineDescriptor x = WGPU_COMPUTE_PIPELINE_DESCRIPTOR_INIT; }
{ WGPURenderPassDescriptor x = WGPU_RENDER_PASS_DESCRIPTOR_INIT; }
{ WGPUVertexState x = WGPU_VERTEX_STATE_INIT; }
{ WGPUFragmentState x = WGPU_FRAGMENT_STATE_INIT; }
{ WGPURenderPipelineDescriptor x = WGPU_RENDER_PIPELINE_DESCRIPTOR_INIT; }
}
2 changes: 1 addition & 1 deletion tests/compile/windows/makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ all: build-c build-cpp
clean:
rm -f main-c.exe main-cpp.exe main.obj

MSVC_WARNINGS = /Wall /WX /options:strict /wd4820 /wd4464 /wd4189
MSVC_WARNINGS = /Wall /WX /options:strict /wd4820 /wd4464 /wd4189 /wd4101

build-c: ../main.c ../main.inl ../../../webgpu.h Makefile
cl.exe /Fe:main-c.exe ../main.c /std:c11 $(MSVC_WARNINGS)
Expand Down
Loading
Loading