forked from mirror/vulkan-zig
Compare commits
14 Commits
zig-0.8.0-
...
zig-0.8.1-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d87813312e | ||
|
|
e17c3593d1 | ||
|
|
9513d33bf8 | ||
|
|
59c5b88d17 | ||
|
|
4588c0fcad | ||
|
|
f55409f98a | ||
|
|
cbf06a8d42 | ||
|
|
c5bb254766 | ||
|
|
5980bac303 | ||
|
|
3bfacc7e16 | ||
|
|
1e594c0f09 | ||
|
|
397e663296 | ||
|
|
933010cfff | ||
|
|
0eccd593ce |
6
.github/workflows/build.yml
vendored
6
.github/workflows/build.yml
vendored
@@ -2,9 +2,9 @@ name: Build
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [ zig-0.8.0-compat ]
|
branches: [ zig-0.8.1-compat ]
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: [ zig-0.8.0-compat ]
|
branches: [ zig-0.8.1-compat ]
|
||||||
schedule:
|
schedule:
|
||||||
- cron: '0 6 * * *'
|
- cron: '0 6 * * *'
|
||||||
|
|
||||||
@@ -27,7 +27,7 @@ jobs:
|
|||||||
- name: Fetch Vulkan SDK
|
- name: Fetch Vulkan SDK
|
||||||
run: |
|
run: |
|
||||||
wget -qO - https://packages.lunarg.com/lunarg-signing-key-pub.asc | sudo apt-key add -
|
wget -qO - https://packages.lunarg.com/lunarg-signing-key-pub.asc | sudo apt-key add -
|
||||||
sudo wget -qO /etc/apt/sources.list.d/lunarg-vulkan-1.2.176-focal.list https://packages.lunarg.com/vulkan/1.2.176/lunarg-vulkan-1.2.176-focal.list
|
sudo wget -qO /etc/apt/sources.list.d/lunarg-vulkan-1.2.189-focal.list https://packages.lunarg.com/vulkan/1.2.189/lunarg-vulkan-1.2.189-focal.list
|
||||||
sudo apt update
|
sudo apt update
|
||||||
sudo apt install shaderc libglfw3 libglfw3-dev
|
sudo apt install shaderc libglfw3 libglfw3-dev
|
||||||
|
|
||||||
|
|||||||
10
README.md
10
README.md
@@ -36,10 +36,10 @@ pub fn build(b: *Builder) void {
|
|||||||
exe.step.dependOn(&gen.step);
|
exe.step.dependOn(&gen.step);
|
||||||
|
|
||||||
// Add the generated file as package to the final executable
|
// Add the generated file as package to the final executable
|
||||||
exe.addPackagePath("vulkan", gen.full_out_path);
|
exe.addPackage(gen.package);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
This reads vk.xml, parses its contents, and renders the Vulkan bindings to "vk.zig", which is then formatted and placed in `zig-cache`. The resulting file can then be added to an executable by using `addPackagePath`.
|
This reads vk.xml, parses its contents, and renders the Vulkan bindings to "vk.zig", which is then formatted and placed in `zig-cache`. The resulting file can then be added to an executable by using `addPackage`, after which the bindings will be made available to the executable under the name `vulkan`.
|
||||||
|
|
||||||
### Function & field renaming
|
### Function & field renaming
|
||||||
Functions and fields are renamed to be more or less in line with [Zig's standard library style](https://ziglang.org/documentation/master/#Style-Guide):
|
Functions and fields are renamed to be more or less in line with [Zig's standard library style](https://ziglang.org/documentation/master/#Style-Guide):
|
||||||
@@ -231,7 +231,7 @@ pub fn build(b: *Builder) void {
|
|||||||
|
|
||||||
const gen = vkgen.VkGenerateStep(b, "path/to/vk.xml", "vk.zig");
|
const gen = vkgen.VkGenerateStep(b, "path/to/vk.xml", "vk.zig");
|
||||||
exe.step.dependOn(&gen.step);
|
exe.step.dependOn(&gen.step);
|
||||||
exe.addPackagePath("vulkan", gen.full_out_path);
|
exe.addPackage(gen.package);
|
||||||
|
|
||||||
const shader_comp = vkgen.ShaderCompileStep.init(
|
const shader_comp = vkgen.ShaderCompileStep.init(
|
||||||
builder,
|
builder,
|
||||||
@@ -252,5 +252,7 @@ Upon compilation, glslc is then invoked to compile each shader, and the result i
|
|||||||
A partial implementation of https://vulkan-tutorial.org is implemented in [examples/triangle.zig](examples/triangle.zig). This example can be ran by executing `zig build run-triangle` in vulkan-zig's root.
|
A partial implementation of https://vulkan-tutorial.org is implemented in [examples/triangle.zig](examples/triangle.zig). This example can be ran by executing `zig build run-triangle` in vulkan-zig's root.
|
||||||
|
|
||||||
## See also
|
## See also
|
||||||
* Implementation of https://vulkan-tutorial.org: https://github.com/andrewrk/zig-vulkan-triangle.
|
* Implementation of https://vulkan-tutorial.org using `@cImport`'ed bindings: https://github.com/andrewrk/zig-vulkan-triangle.
|
||||||
* Alternative binding generator: https://github.com/SpexGuy/Zig-Vulkan-Headers
|
* Alternative binding generator: https://github.com/SpexGuy/Zig-Vulkan-Headers
|
||||||
|
* Zig bindings for GLFW: https://github.com/hexops/mach-glfw
|
||||||
|
* With vulkan-zig integration example: https://github.com/hexops/mach-glfw-vulkan-example
|
||||||
|
|||||||
@@ -5,77 +5,77 @@ const Allocator = std.mem.Allocator;
|
|||||||
|
|
||||||
const required_device_extensions = [_][]const u8{vk.extension_info.khr_swapchain.name};
|
const required_device_extensions = [_][]const u8{vk.extension_info.khr_swapchain.name};
|
||||||
|
|
||||||
const BaseDispatch = vk.BaseWrapper(.{
|
const BaseDispatch = vk.BaseWrapper(&.{
|
||||||
.CreateInstance,
|
.createInstance,
|
||||||
});
|
});
|
||||||
|
|
||||||
const InstanceDispatch = vk.InstanceWrapper(.{
|
const InstanceDispatch = vk.InstanceWrapper(&.{
|
||||||
.DestroyInstance,
|
.destroyInstance,
|
||||||
.CreateDevice,
|
.createDevice,
|
||||||
.DestroySurfaceKHR,
|
.destroySurfaceKHR,
|
||||||
.EnumeratePhysicalDevices,
|
.enumeratePhysicalDevices,
|
||||||
.GetPhysicalDeviceProperties,
|
.getPhysicalDeviceProperties,
|
||||||
.EnumerateDeviceExtensionProperties,
|
.enumerateDeviceExtensionProperties,
|
||||||
.GetPhysicalDeviceSurfaceFormatsKHR,
|
.getPhysicalDeviceSurfaceFormatsKHR,
|
||||||
.GetPhysicalDeviceSurfacePresentModesKHR,
|
.getPhysicalDeviceSurfacePresentModesKHR,
|
||||||
.GetPhysicalDeviceSurfaceCapabilitiesKHR,
|
.getPhysicalDeviceSurfaceCapabilitiesKHR,
|
||||||
.GetPhysicalDeviceQueueFamilyProperties,
|
.getPhysicalDeviceQueueFamilyProperties,
|
||||||
.GetPhysicalDeviceSurfaceSupportKHR,
|
.getPhysicalDeviceSurfaceSupportKHR,
|
||||||
.GetPhysicalDeviceMemoryProperties,
|
.getPhysicalDeviceMemoryProperties,
|
||||||
.GetDeviceProcAddr,
|
.getDeviceProcAddr,
|
||||||
});
|
});
|
||||||
|
|
||||||
const DeviceDispatch = vk.DeviceWrapper(.{
|
const DeviceDispatch = vk.DeviceWrapper(&.{
|
||||||
.DestroyDevice,
|
.destroyDevice,
|
||||||
.GetDeviceQueue,
|
.getDeviceQueue,
|
||||||
.CreateSemaphore,
|
.createSemaphore,
|
||||||
.CreateFence,
|
.createFence,
|
||||||
.CreateImageView,
|
.createImageView,
|
||||||
.DestroyImageView,
|
.destroyImageView,
|
||||||
.DestroySemaphore,
|
.destroySemaphore,
|
||||||
.DestroyFence,
|
.destroyFence,
|
||||||
.GetSwapchainImagesKHR,
|
.getSwapchainImagesKHR,
|
||||||
.CreateSwapchainKHR,
|
.createSwapchainKHR,
|
||||||
.DestroySwapchainKHR,
|
.destroySwapchainKHR,
|
||||||
.AcquireNextImageKHR,
|
.acquireNextImageKHR,
|
||||||
.DeviceWaitIdle,
|
.deviceWaitIdle,
|
||||||
.WaitForFences,
|
.waitForFences,
|
||||||
.ResetFences,
|
.resetFences,
|
||||||
.QueueSubmit,
|
.queueSubmit,
|
||||||
.QueuePresentKHR,
|
.queuePresentKHR,
|
||||||
.CreateCommandPool,
|
.createCommandPool,
|
||||||
.DestroyCommandPool,
|
.destroyCommandPool,
|
||||||
.AllocateCommandBuffers,
|
.allocateCommandBuffers,
|
||||||
.FreeCommandBuffers,
|
.freeCommandBuffers,
|
||||||
.QueueWaitIdle,
|
.queueWaitIdle,
|
||||||
.CreateShaderModule,
|
.createShaderModule,
|
||||||
.DestroyShaderModule,
|
.destroyShaderModule,
|
||||||
.CreatePipelineLayout,
|
.createPipelineLayout,
|
||||||
.DestroyPipelineLayout,
|
.destroyPipelineLayout,
|
||||||
.CreateRenderPass,
|
.createRenderPass,
|
||||||
.DestroyRenderPass,
|
.destroyRenderPass,
|
||||||
.CreateGraphicsPipelines,
|
.createGraphicsPipelines,
|
||||||
.DestroyPipeline,
|
.destroyPipeline,
|
||||||
.CreateFramebuffer,
|
.createFramebuffer,
|
||||||
.DestroyFramebuffer,
|
.destroyFramebuffer,
|
||||||
.BeginCommandBuffer,
|
.beginCommandBuffer,
|
||||||
.EndCommandBuffer,
|
.endCommandBuffer,
|
||||||
.AllocateMemory,
|
.allocateMemory,
|
||||||
.FreeMemory,
|
.freeMemory,
|
||||||
.CreateBuffer,
|
.createBuffer,
|
||||||
.DestroyBuffer,
|
.destroyBuffer,
|
||||||
.GetBufferMemoryRequirements,
|
.getBufferMemoryRequirements,
|
||||||
.MapMemory,
|
.mapMemory,
|
||||||
.UnmapMemory,
|
.unmapMemory,
|
||||||
.BindBufferMemory,
|
.bindBufferMemory,
|
||||||
.CmdBeginRenderPass,
|
.cmdBeginRenderPass,
|
||||||
.CmdEndRenderPass,
|
.cmdEndRenderPass,
|
||||||
.CmdBindPipeline,
|
.cmdBindPipeline,
|
||||||
.CmdDraw,
|
.cmdDraw,
|
||||||
.CmdSetViewport,
|
.cmdSetViewport,
|
||||||
.CmdSetScissor,
|
.cmdSetScissor,
|
||||||
.CmdBindVertexBuffers,
|
.cmdBindVertexBuffers,
|
||||||
.CmdCopyBuffer,
|
.cmdCopyBuffer,
|
||||||
});
|
});
|
||||||
|
|
||||||
pub const GraphicsContext = struct {
|
pub const GraphicsContext = struct {
|
||||||
|
|||||||
@@ -251,7 +251,7 @@ fn initSwapchainImages(gc: *const GraphicsContext, swapchain: vk.SwapchainKHR, f
|
|||||||
_ = try gc.vkd.getSwapchainImagesKHR(gc.dev, swapchain, &count, images.ptr);
|
_ = try gc.vkd.getSwapchainImagesKHR(gc.dev, swapchain, &count, images.ptr);
|
||||||
|
|
||||||
const swap_images = try allocator.alloc(SwapImage, count);
|
const swap_images = try allocator.alloc(SwapImage, count);
|
||||||
errdefer allocator.free(images);
|
errdefer allocator.free(swap_images);
|
||||||
|
|
||||||
var i: usize = 0;
|
var i: usize = 0;
|
||||||
errdefer for (swap_images[0..i]) |si| si.deinit(gc);
|
errdefer for (swap_images[0..i]) |si| si.deinit(gc);
|
||||||
|
|||||||
@@ -150,7 +150,6 @@ pub fn main() !void {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
c.glfwSwapBuffers(window);
|
|
||||||
c.glfwPollEvents();
|
c.glfwPollEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ pub const GenerateStep = struct {
|
|||||||
try generate(self.builder.allocator, spec, out_buffer.writer());
|
try generate(self.builder.allocator, spec, out_buffer.writer());
|
||||||
|
|
||||||
const tree = try std.zig.parse(self.builder.allocator, out_buffer.items);
|
const tree = try std.zig.parse(self.builder.allocator, out_buffer.items);
|
||||||
|
std.debug.assert(tree.errors.len == 0); // If this triggers, vulkan-zig produced invalid code.
|
||||||
|
|
||||||
var formatted = try tree.render(self.builder.allocator);
|
var formatted = try tree.render(self.builder.allocator);
|
||||||
|
|
||||||
|
|||||||
@@ -9,41 +9,30 @@ const Allocator = mem.Allocator;
|
|||||||
const FeatureLevel = reg.FeatureLevel;
|
const FeatureLevel = reg.FeatureLevel;
|
||||||
|
|
||||||
const EnumFieldMerger = struct {
|
const EnumFieldMerger = struct {
|
||||||
const EnumExtensionMap = std.StringArrayHashMap(std.ArrayListUnmanaged(reg.Enum.Field));
|
const EnumExtensionMap = std.StringArrayHashMapUnmanaged(std.ArrayListUnmanaged(reg.Enum.Field));
|
||||||
const FieldSet = std.StringArrayHashMap(void);
|
const FieldSet = std.StringArrayHashMapUnmanaged(void);
|
||||||
|
|
||||||
gpa: *Allocator,
|
arena: *Allocator,
|
||||||
reg_arena: *Allocator,
|
|
||||||
registry: *reg.Registry,
|
registry: *reg.Registry,
|
||||||
enum_extensions: EnumExtensionMap,
|
enum_extensions: EnumExtensionMap,
|
||||||
field_set: FieldSet,
|
field_set: FieldSet,
|
||||||
|
|
||||||
fn init(gpa: *Allocator, reg_arena: *Allocator, registry: *reg.Registry) EnumFieldMerger {
|
fn init(arena: *Allocator, registry: *reg.Registry) EnumFieldMerger {
|
||||||
return .{
|
return .{
|
||||||
.gpa = gpa,
|
.arena = arena,
|
||||||
.reg_arena = reg_arena,
|
|
||||||
.registry = registry,
|
.registry = registry,
|
||||||
.enum_extensions = EnumExtensionMap.init(gpa),
|
.enum_extensions = .{},
|
||||||
.field_set = FieldSet.init(gpa),
|
.field_set = .{},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deinit(self: *EnumFieldMerger) void {
|
|
||||||
for (self.enum_extensions.values()) |*value| {
|
|
||||||
value.deinit(self.gpa);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.field_set.deinit();
|
|
||||||
self.enum_extensions.deinit();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn putEnumExtension(self: *EnumFieldMerger, enum_name: []const u8, field: reg.Enum.Field) !void {
|
fn putEnumExtension(self: *EnumFieldMerger, enum_name: []const u8, field: reg.Enum.Field) !void {
|
||||||
const res = try self.enum_extensions.getOrPut(enum_name);
|
const res = try self.enum_extensions.getOrPut(self.arena, enum_name);
|
||||||
if (!res.found_existing) {
|
if (!res.found_existing) {
|
||||||
res.value_ptr.* = std.ArrayListUnmanaged(reg.Enum.Field){};
|
res.value_ptr.* = std.ArrayListUnmanaged(reg.Enum.Field){};
|
||||||
}
|
}
|
||||||
|
|
||||||
try res.value_ptr.append(self.gpa, field);
|
try res.value_ptr.append(self.arena, field);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn addRequires(self: *EnumFieldMerger, reqs: []const reg.Require) !void {
|
fn addRequires(self: *EnumFieldMerger, reqs: []const reg.Require) !void {
|
||||||
@@ -61,11 +50,11 @@ const EnumFieldMerger = struct {
|
|||||||
self.field_set.clearRetainingCapacity();
|
self.field_set.clearRetainingCapacity();
|
||||||
|
|
||||||
const n_fields_upper_bound = base_enum.fields.len + extensions.items.len;
|
const n_fields_upper_bound = base_enum.fields.len + extensions.items.len;
|
||||||
const new_fields = try self.reg_arena.alloc(reg.Enum.Field, n_fields_upper_bound);
|
const new_fields = try self.arena.alloc(reg.Enum.Field, n_fields_upper_bound);
|
||||||
var i: usize = 0;
|
var i: usize = 0;
|
||||||
|
|
||||||
for (base_enum.fields) |field| {
|
for (base_enum.fields) |field| {
|
||||||
const res = try self.field_set.getOrPut(field.name);
|
const res = try self.field_set.getOrPut(self.arena, field.name);
|
||||||
if (!res.found_existing) {
|
if (!res.found_existing) {
|
||||||
new_fields[i] = field;
|
new_fields[i] = field;
|
||||||
i += 1;
|
i += 1;
|
||||||
@@ -74,16 +63,16 @@ const EnumFieldMerger = struct {
|
|||||||
|
|
||||||
// Assume that if a field name clobbers, the value is the same
|
// Assume that if a field name clobbers, the value is the same
|
||||||
for (extensions.items) |field| {
|
for (extensions.items) |field| {
|
||||||
const res = try self.field_set.getOrPut(field.name);
|
const res = try self.field_set.getOrPut(self.arena, field.name);
|
||||||
if (!res.found_existing) {
|
if (!res.found_existing) {
|
||||||
new_fields[i] = field;
|
new_fields[i] = field;
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Existing base_enum.fields was allocatued by `self.reg_arena`, so
|
// Existing base_enum.fields was allocated by `self.arena`, so
|
||||||
// it gets cleaned up whenever that is deinited.
|
// it gets cleaned up whenever that is deinited.
|
||||||
base_enum.fields = self.reg_arena.shrink(new_fields, i);
|
base_enum.fields = self.arena.shrink(new_fields, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn merge(self: *EnumFieldMerger) !void {
|
fn merge(self: *EnumFieldMerger) !void {
|
||||||
@@ -106,8 +95,7 @@ const EnumFieldMerger = struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
pub const Generator = struct {
|
pub const Generator = struct {
|
||||||
gpa: *Allocator,
|
arena: std.heap.ArenaAllocator,
|
||||||
reg_arena: std.heap.ArenaAllocator,
|
|
||||||
registry: reg.Registry,
|
registry: reg.Registry,
|
||||||
id_renderer: IdRenderer,
|
id_renderer: IdRenderer,
|
||||||
|
|
||||||
@@ -118,16 +106,14 @@ pub const Generator = struct {
|
|||||||
for (tags) |*tag, i| tag.* = result.registry.tags[i].name;
|
for (tags) |*tag, i| tag.* = result.registry.tags[i].name;
|
||||||
|
|
||||||
return Generator{
|
return Generator{
|
||||||
.gpa = allocator,
|
.arena = result.arena,
|
||||||
.reg_arena = result.arena,
|
|
||||||
.registry = result.registry,
|
.registry = result.registry,
|
||||||
.id_renderer = IdRenderer.init(allocator, tags),
|
.id_renderer = IdRenderer.init(allocator, tags),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deinit(self: Generator) void {
|
fn deinit(self: Generator) void {
|
||||||
self.gpa.free(self.id_renderer.tags);
|
self.arena.deinit();
|
||||||
self.reg_arena.deinit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn stripFlagBits(self: Generator, name: []const u8) []const u8 {
|
fn stripFlagBits(self: Generator, name: []const u8) []const u8 {
|
||||||
@@ -142,14 +128,13 @@ pub const Generator = struct {
|
|||||||
|
|
||||||
// Solve `registry.declarations` according to `registry.extensions` and `registry.features`.
|
// Solve `registry.declarations` according to `registry.extensions` and `registry.features`.
|
||||||
fn mergeEnumFields(self: *Generator) !void {
|
fn mergeEnumFields(self: *Generator) !void {
|
||||||
var merger = EnumFieldMerger.init(self.gpa, &self.reg_arena.allocator, &self.registry);
|
var merger = EnumFieldMerger.init(&self.arena.allocator, &self.registry);
|
||||||
defer merger.deinit();
|
|
||||||
try merger.merge();
|
try merger.merge();
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://github.com/KhronosGroup/Vulkan-Docs/pull/1556
|
// https://github.com/KhronosGroup/Vulkan-Docs/pull/1556
|
||||||
fn fixupBitFlags(self: *Generator) !void {
|
fn fixupBitFlags(self: *Generator) !void {
|
||||||
var seen_bits = std.StringArrayHashMap(void).init(&self.reg_arena.allocator);
|
var seen_bits = std.StringArrayHashMap(void).init(&self.arena.allocator);
|
||||||
defer seen_bits.deinit();
|
defer seen_bits.deinit();
|
||||||
|
|
||||||
for (self.registry.decls) |decl| {
|
for (self.registry.decls) |decl| {
|
||||||
@@ -181,7 +166,7 @@ pub const Generator = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn render(self: *Generator, writer: anytype) !void {
|
fn render(self: *Generator, writer: anytype) !void {
|
||||||
try renderRegistry(writer, &self.reg_arena.allocator, &self.registry, &self.id_renderer);
|
try renderRegistry(writer, &self.arena.allocator, &self.registry, &self.id_renderer);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -205,6 +205,18 @@ fn parseContainer(allocator: *Allocator, ty: *xml.Element, is_union: bool) !regi
|
|||||||
|
|
||||||
members = allocator.shrink(members, i);
|
members = allocator.shrink(members, i);
|
||||||
|
|
||||||
|
var maybe_extends: ?[][]const u8 = null;
|
||||||
|
if (ty.getAttribute("structextends")) |extends| {
|
||||||
|
const n_structs = std.mem.count(u8, extends, ",") + 1;
|
||||||
|
maybe_extends = try allocator.alloc([]const u8, n_structs);
|
||||||
|
var struct_extends = std.mem.split(extends, ",");
|
||||||
|
var j: usize = 0;
|
||||||
|
while (struct_extends.next()) |struct_extend| {
|
||||||
|
maybe_extends.?[j] = struct_extend;
|
||||||
|
j += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
it = ty.findChildrenByTag("member");
|
it = ty.findChildrenByTag("member");
|
||||||
for (members) |*member| {
|
for (members) |*member| {
|
||||||
const member_elem = it.next().?;
|
const member_elem = it.next().?;
|
||||||
@@ -218,6 +230,7 @@ fn parseContainer(allocator: *Allocator, ty: *xml.Element, is_union: bool) !regi
|
|||||||
.stype = maybe_stype,
|
.stype = maybe_stype,
|
||||||
.fields = members,
|
.fields = members,
|
||||||
.is_union = is_union,
|
.is_union = is_union,
|
||||||
|
.extends = maybe_extends,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ pub const Container = struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
stype: ?[]const u8,
|
stype: ?[]const u8,
|
||||||
|
extends: ?[]const []const u8,
|
||||||
fields: []Field,
|
fields: []Field,
|
||||||
is_union: bool,
|
is_union: bool,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -185,10 +185,6 @@ fn Renderer(comptime WriterType: type) type {
|
|||||||
declarations_by_name: std.StringHashMap(*const reg.DeclarationType),
|
declarations_by_name: std.StringHashMap(*const reg.DeclarationType),
|
||||||
|
|
||||||
fn init(writer: WriterType, allocator: *Allocator, registry: *const reg.Registry, id_renderer: *IdRenderer) !Self {
|
fn init(writer: WriterType, allocator: *Allocator, registry: *const reg.Registry, id_renderer: *IdRenderer) !Self {
|
||||||
const tags = try allocator.alloc([]const u8, registry.tags.len);
|
|
||||||
errdefer allocator.free(tags);
|
|
||||||
for (tags) |*tag, i| tag.* = registry.tags[i].name;
|
|
||||||
|
|
||||||
var declarations_by_name = std.StringHashMap(*const reg.DeclarationType).init(allocator);
|
var declarations_by_name = std.StringHashMap(*const reg.DeclarationType).init(allocator);
|
||||||
errdefer declarations_by_name.deinit();
|
errdefer declarations_by_name.deinit();
|
||||||
|
|
||||||
@@ -212,8 +208,6 @@ fn Renderer(comptime WriterType: type) type {
|
|||||||
|
|
||||||
fn deinit(self: *Self) void {
|
fn deinit(self: *Self) void {
|
||||||
self.declarations_by_name.deinit();
|
self.declarations_by_name.deinit();
|
||||||
self.allocator.free(self.id_renderer.tags);
|
|
||||||
self.id_renderer.deinit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn writeIdentifier(self: Self, id: []const u8) !void {
|
fn writeIdentifier(self: Self, id: []const u8) !void {
|
||||||
@@ -446,19 +440,70 @@ fn Renderer(comptime WriterType: type) type {
|
|||||||
|
|
||||||
try self.writer.print("pub const {s}Command = enum {{\n", .{dispatch_type_name});
|
try self.writer.print("pub const {s}Command = enum {{\n", .{dispatch_type_name});
|
||||||
for (self.registry.decls) |decl| {
|
for (self.registry.decls) |decl| {
|
||||||
if (decl.decl_type == .command) {
|
const command = switch (decl.decl_type) {
|
||||||
const command = decl.decl_type.command;
|
.command => |cmd| cmd,
|
||||||
|
else => continue,
|
||||||
|
};
|
||||||
|
|
||||||
if (classifyCommandDispatch(decl.name, command) == dispatch_type) {
|
if (classifyCommandDispatch(decl.name, command) == dispatch_type) {
|
||||||
try self.writer.print("{s},\n", .{trimVkNamespace(decl.name)});
|
try self.writeIdentifierWithCase(.camel, trimVkNamespace(decl.name));
|
||||||
|
try self.writer.writeAll(",\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
try self.writer.writeAll("};\n");
|
{
|
||||||
try self.writer.print(
|
try self.writer.print(
|
||||||
\\fn {s}CommandToString(cmd: {s}Command) []const u8 {{
|
\\
|
||||||
\\ return std.meta.tagName(cmd);
|
\\pub fn symbol(self: {s}Command) [:0]const u8 {{
|
||||||
\\}}
|
\\ return switch (self) {{
|
||||||
, .{ dispatch_type_name, dispatch_type_name });
|
\\
|
||||||
|
, .{dispatch_type_name}
|
||||||
|
);
|
||||||
|
|
||||||
|
for (self.registry.decls) |decl| {
|
||||||
|
const command = switch (decl.decl_type) {
|
||||||
|
.command => |cmd| cmd,
|
||||||
|
else => continue,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (classifyCommandDispatch(decl.name, command) == dispatch_type) {
|
||||||
|
try self.writer.writeAll(".");
|
||||||
|
try self.writeIdentifierWithCase(.camel, trimVkNamespace(decl.name));
|
||||||
|
try self.writer.print(" => \"{s}\",\n", .{ decl.name });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try self.writer.writeAll("};\n}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
try self.writer.print(
|
||||||
|
\\
|
||||||
|
\\pub fn PfnType(comptime self: {s}Command) type {{
|
||||||
|
\\ return switch (self) {{
|
||||||
|
\\
|
||||||
|
, .{dispatch_type_name}
|
||||||
|
);
|
||||||
|
|
||||||
|
for (self.registry.decls) |decl| {
|
||||||
|
const command = switch (decl.decl_type) {
|
||||||
|
.command => |cmd| cmd,
|
||||||
|
else => continue,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (classifyCommandDispatch(decl.name, command) == dispatch_type) {
|
||||||
|
try self.writer.writeAll(".");
|
||||||
|
try self.writeIdentifierWithCase(.camel, trimVkNamespace(decl.name));
|
||||||
|
try self.writer.writeAll(" => ");
|
||||||
|
try self.renderCommandPtrName(decl.name);
|
||||||
|
try self.writer.writeAll(",\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try self.writer.writeAll("};\n}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
try self.writer.writeAll("};\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn renderCopyright(self: *Self) !void {
|
fn renderCopyright(self: *Self) !void {
|
||||||
@@ -705,7 +750,7 @@ fn Renderer(comptime WriterType: type) type {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
try self.renderTypeInfo(field.field_type);
|
try self.renderTypeInfo(field.field_type);
|
||||||
try self.renderContainerDefaultField(container, field);
|
try self.renderContainerDefaultField(name, container, field);
|
||||||
try self.writer.writeAll(", ");
|
try self.writer.writeAll(", ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -713,7 +758,7 @@ fn Renderer(comptime WriterType: type) type {
|
|||||||
try self.writer.writeAll("};\n");
|
try self.writer.writeAll("};\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn renderContainerDefaultField(self: *Self, container: reg.Container, field: reg.Container.Field) !void {
|
fn renderContainerDefaultField(self: *Self, name: []const u8, container: reg.Container, field: reg.Container.Field) !void {
|
||||||
if (mem.eql(u8, field.name, "pNext")) {
|
if (mem.eql(u8, field.name, "pNext")) {
|
||||||
try self.writer.writeAll(" = null");
|
try self.writer.writeAll(" = null");
|
||||||
} else if (mem.eql(u8, field.name, "sType")) {
|
} else if (mem.eql(u8, field.name, "sType")) {
|
||||||
@@ -728,9 +773,21 @@ fn Renderer(comptime WriterType: type) type {
|
|||||||
|
|
||||||
try self.writer.writeAll(" = .");
|
try self.writer.writeAll(" = .");
|
||||||
try self.writeIdentifierWithCase(.snake, stype["VK_STRUCTURE_TYPE_".len..]);
|
try self.writeIdentifierWithCase(.snake, stype["VK_STRUCTURE_TYPE_".len..]);
|
||||||
|
} else if (field.field_type == .name and !container.is_union and mem.eql(u8, "VkBool32", field.field_type.name) and isFeatureStruct(name, container.extends)) {
|
||||||
|
try self.writer.writeAll(" = FALSE");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn isFeatureStruct(name: []const u8, maybe_extends: ?[]const []const u8) bool {
|
||||||
|
if (std.mem.eql(u8, name, "VkPhysicalDeviceFeatures")) return true;
|
||||||
|
if (maybe_extends) |extends| {
|
||||||
|
return for (extends) |extend| {
|
||||||
|
if (mem.eql(u8, extend, "VkDeviceCreateInfo")) break true;
|
||||||
|
} else false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
fn renderEnumFieldName(self: *Self, name: []const u8, field_name: []const u8) !void {
|
fn renderEnumFieldName(self: *Self, name: []const u8, field_name: []const u8) !void {
|
||||||
try self.writeIdentifierWithCase(.snake, try self.extractEnumFieldName(name, field_name));
|
try self.writeIdentifierWithCase(.snake, try self.extractEnumFieldName(name, field_name));
|
||||||
}
|
}
|
||||||
@@ -743,7 +800,7 @@ fn Renderer(comptime WriterType: type) type {
|
|||||||
|
|
||||||
try self.writer.writeAll("pub const ");
|
try self.writer.writeAll("pub const ");
|
||||||
try self.renderName(name);
|
try self.renderName(name);
|
||||||
try self.writer.writeAll(" = enum(c_int) {");
|
try self.writer.writeAll(" = enum(i32) {");
|
||||||
|
|
||||||
for (enumeration.fields) |field| {
|
for (enumeration.fields) |field| {
|
||||||
if (field.value == .alias)
|
if (field.value == .alias)
|
||||||
@@ -958,18 +1015,16 @@ fn Renderer(comptime WriterType: type) type {
|
|||||||
};
|
};
|
||||||
|
|
||||||
try self.writer.print(
|
try self.writer.print(
|
||||||
\\pub fn {s}Wrapper(comptime cmds: anytype) type {{
|
\\pub fn {s}Wrapper(comptime cmds: []const {s}Command) type {{
|
||||||
\\ comptime var fields: [cmds.len]std.builtin.TypeInfo.StructField = undefined;
|
\\ comptime var fields: [cmds.len]std.builtin.TypeInfo.StructField = undefined;
|
||||||
\\ inline for (cmds) |cmd, i| {{
|
\\ inline for (cmds) |cmd, i| {{
|
||||||
\\ const cmd_name = {s}CommandToString(cmd);
|
\\ const PfnType = cmd.PfnType();
|
||||||
\\ const cmd_type_name = "Pfn" ++ cmd_name;
|
|
||||||
\\ const cmd_type = @field(GlobalScope, cmd_type_name);
|
|
||||||
\\ fields[i] = .{{
|
\\ fields[i] = .{{
|
||||||
\\ .name = "vk" ++ cmd_name,
|
\\ .name = cmd.symbol(),
|
||||||
\\ .field_type = cmd_type,
|
\\ .field_type = PfnType,
|
||||||
\\ .default_value = null,
|
\\ .default_value = null,
|
||||||
\\ .is_comptime = false,
|
\\ .is_comptime = false,
|
||||||
\\ .alignment = @alignOf(*cmd_type),
|
\\ .alignment = @alignOf(PfnType),
|
||||||
\\ }};
|
\\ }};
|
||||||
\\ }}
|
\\ }}
|
||||||
\\ const Dispatch = @Type(.{{
|
\\ const Dispatch = @Type(.{{
|
||||||
|
|||||||
Reference in New Issue
Block a user