Simplify things, use just one pipeline layout for all shaders (nice), remove spirv-reflect

This commit is contained in:
sergeypdev 2024-12-15 22:52:44 +04:00
parent 1181e56236
commit e229da9315
9 changed files with 54 additions and 229 deletions

View File

@ -282,12 +282,7 @@ fn buildAssetCompiler(b: *Build, optimize: std.builtin.OptimizeMode, assets_mod:
.skip_tests = true,
});
const zalgebra_dep = b.dependency("zalgebra", .{});
const spirv_reflect_dep = b.dependency("SPIRV-Reflect", .{
.target = b.host,
.optimize = optimize,
});
const assimp_lib = assimp_dep.artifact("assimp");
const spirv_reflect_lib = spirv_reflect_dep.artifact("spirv-reflect");
const assetc = b.addExecutable(.{
.name = "assetc",
@ -317,7 +312,6 @@ fn buildAssetCompiler(b: *Build, optimize: std.builtin.OptimizeMode, assets_mod:
assetc.root_module.addImport("assets", assets_mod);
assetc.linkLibrary(assimp_lib);
assetc.linkLibrary(spirv_reflect_lib);
assetc.linkLibC();
assetc.linkLibCpp();

View File

@ -51,10 +51,6 @@
.url = "https://github.com/hexops/spirv-cross/tarball/872bd405fece4bf6388abdea916356e26cb8fed9",
.hash = "12207bebf82eef06f4f80a7e54c91e4402c0055d04167fdbcf1f350846a350266976",
},
.@"SPIRV-Reflect" = .{
.url = "https://github.com/sergeypdev/SPIRV-Reflect/tarball/bb3e8b8d5dee32b65e1d16598c526415470fc863",
.hash = "122048fdee255a7ac992068d5ded4bfa88927ddc8af12a5068c69198153a60dbe779",
},
},
.paths = .{
// This makes *all* files, recursively, included in this package. It is generally

View File

@ -320,65 +320,12 @@ pub fn loadShaderProgram(self: *AssetManager, handle: Handle.ShaderProgram) Load
};
}
fn getPushConstantRanges(program: formats.ShaderProgram, buffer: []vk.PushConstantRange) []vk.PushConstantRange {
var len: usize = 0;
switch (program) {
.graphics => {
std.debug.assert(buffer.len >= 2);
if (program.graphics.vertex.push_constant_range.size > 0) {
buffer[len] = vk.PushConstantRange{
.offset = program.graphics.vertex.push_constant_range.offset,
.size = program.graphics.vertex.push_constant_range.size,
.stage_flags = .{ .vertex_bit = true },
};
len += 1;
}
if (program.graphics.fragment.push_constant_range.size > 0) {
buffer[len] = vk.PushConstantRange{
.offset = program.graphics.fragment.push_constant_range.offset,
.size = program.graphics.fragment.push_constant_range.size,
.stage_flags = .{ .fragment_bit = true },
};
len += 1;
}
},
.compute => {
std.debug.assert(buffer.len >= 1);
if (program.compute.compute.push_constant_range.size > 0) {
buffer[len] = vk.PushConstantRange{
.offset = program.compute.compute.push_constant_range.offset,
.size = program.graphics.vertex.push_constant_range.size,
.stage_flags = .{ .compute_bit = true },
};
len += 1;
}
},
}
return buffer[0..len];
}
fn loadShaderProgramErr(self: *AssetManager, id: AssetId) !LoadedShaderProgram {
const data = try self.loadFile(self.frame_arena, asset_manifest.getPath(id), SHADER_MAX_BYTES);
var serializer = formats.Serializer{ .write = false, .endian = formats.native_endian, .stream = .{ .buffer = std.io.fixedBufferStream(data.bytes) } };
var program: formats.ShaderProgram = undefined;
try program.serialize(&serializer);
var push_constant_ranges_buf: [2]vk.PushConstantRange = undefined;
const push_constant_ranges = getPushConstantRanges(program, &push_constant_ranges_buf);
std.debug.print("push constant ranges: {any}\n", .{push_constant_ranges});
// TODO: parse from shaders or something
const pipeline_layout = try self.gc.device.createPipelineLayout(&.{
.p_set_layouts = &.{self.descriptorman.descriptor_set_layouts.global},
.set_layout_count = 1,
.push_constant_range_count = @intCast(push_constant_ranges.len),
.p_push_constant_ranges = push_constant_ranges.ptr,
}, null);
const pipeline = blk: {
switch (program) {
.graphics => |graphics_pipeline| {
@ -433,7 +380,7 @@ fn loadShaderProgramErr(self: *AssetManager, id: AssetId) !LoadedShaderProgram {
.line_width = 1.0,
},
.p_viewport_state = &vk.PipelineViewportStateCreateInfo{},
.layout = pipeline_layout,
.layout = self.descriptorman.pipeline_layout,
.p_depth_stencil_state = &vk.PipelineDepthStencilStateCreateInfo{
// Dynamic States
.depth_test_enable = vk.FALSE,
@ -523,7 +470,6 @@ fn loadShaderProgramErr(self: *AssetManager, id: AssetId) !LoadedShaderProgram {
const loaded_shader_program = LoadedShaderProgram{
.pipeline = pipeline,
.layout = pipeline_layout,
};
{
@ -546,7 +492,6 @@ const NullShader = LoadedShader{
const NullShaderProgram = LoadedShaderProgram{
.pipeline = .null_handle,
.layout = .null_handle,
};
const NullMesh = LoadedMesh{
@ -836,7 +781,6 @@ const LoadedShader = struct {
const LoadedShaderProgram = struct {
pipeline: vk.Pipeline,
layout: vk.PipelineLayout,
};
pub const LoadedMesh = struct {

View File

@ -156,6 +156,8 @@ gc: *GraphicsContext,
descriptor_set_layouts: DescriptorSetLayouts = .{},
image_descriptor_array_2d: DescriptorArray(SampledImageDescriptorData, 1024) = .{},
pipeline_layout: vk.PipelineLayout = .null_handle,
pub fn init(gc: *GraphicsContext) !DescriptorManager {
var self = DescriptorManager{
.gc = gc,
@ -201,30 +203,23 @@ pub fn init(gc: *GraphicsContext) !DescriptorManager {
}, null);
}
// Post Process Pass Descriptor Set Layout
// {
// const descriptor_set_layout_bindings = [_]vk.DescriptorSetLayoutBinding{
// vk.DescriptorSetLayoutBinding{
// .binding = DescriptorSets.Passes.PostProcess.Bindings.ScreenSampler.value(),
// .descriptor_type = .sampler,
// .descriptor_count = 1,
// .stage_flags = vk.ShaderStageFlags.fromInt(0x7FFFFFFF), // SHADER_STAGE_ALL
// },
// vk.DescriptorSetLayoutBinding{
// .binding = DescriptorSets.Passes.PostProcess.Bindings.ScreenTexture.value(),
// .descriptor_type = .sampled_image,
// .descriptor_count = 1,
// .stage_flags = vk.ShaderStageFlags.fromInt(0x7FFFFFFF), // SHADER_STAGE_ALL
// },
// };
// self.descriptor_set_layouts.passes.post_process = try self.gc.device.createDescriptorSetLayout(&.{
// .flags = .{
// .push_descriptor_bit_khr = true,
// },
// .p_bindings = &descriptor_set_layout_bindings,
// .binding_count = descriptor_set_layout_bindings.len,
// }, null);
// }
self.pipeline_layout = try self.gc.device.createPipelineLayout(&.{
.set_layout_count = 1,
.p_set_layouts = &.{self.descriptor_set_layouts.global},
.push_constant_range_count = 2,
.p_push_constant_ranges = &.{
vk.PushConstantRange{
.stage_flags = .{ .vertex_bit = true },
.offset = 0,
.size = 128,
},
vk.PushConstantRange{
.stage_flags = .{ .fragment_bit = true },
.offset = 0,
.size = 128,
},
},
}, null);
return self;
}

View File

@ -520,6 +520,9 @@ fn maybeResizeSwapchain(self: *GraphicsContext) !void {
return;
}
std.debug.print("resizing swapchain {}\n", .{new_extent});
self.swapchain_extent = new_extent;
if (self.swapchain_images.len > 0) {
self.allocator.free(self.swapchain_images);
self.swapchain_images = &.{};

View File

@ -30,7 +30,7 @@ pub const Camera = struct {
var default_camera: Camera = .{};
const MAX_FRAME_LAG = 3;
const PER_FRAME_ARENA_SIZE = 64 * common.MB;
const PER_FRAME_ARENA_SIZE = 256 * common.MB;
frame_allocator: std.mem.Allocator,
gc: *GraphicsContext,
@ -116,16 +116,13 @@ pub const VulkanPerFrameArena = struct {
// Record start position of this frame
if (self.frame_regions[self.frame]) |*cur_region| {
cur_region.end = self.tail;
// std.debug.print("frame {} region: {}-{}, wraps: {}\n", .{ self.frame, cur_region.start, cur_region.end, cur_region.end < cur_region.start });
}
self.frame = frame_index;
self.frame_regions[self.frame] = FrameRegion.init(self.tail, self.tail);
}
// Caller guarantees that memory from given frame can be safely stomped, buffers destroyed etc.
pub fn resetFrame(self: *VulkanPerFrameArena, frame_index: u32) void {
self.frame_regions[frame_index] = null;
}
pub fn getModifiedMemoryRanges(self: *VulkanPerFrameArena, out_ranges: []vk.MappedMemoryRange) []const vk.MappedMemoryRange {
std.debug.assert(out_ranges.len >= 2);
std.debug.assert(self.frame_regions[self.frame] != null);
@ -178,6 +175,7 @@ pub const VulkanPerFrameArena = struct {
const allocated_region = FrameRegion.init(offset, offset + size);
if (next_frame_region.intersectsWrapping(&allocated_region, self.size)) {
// std.debug.print("overlapped alloc of size: {d}MB align: {}\n", .{ @as(f32, @floatFromInt(size)) / common.MB, alignment });
return error.OverlapsPreviousFrame;
}
}
@ -412,10 +410,10 @@ fn createPerFrameBuffer(self: *Render2, usage: vk.BufferUsageFlags, size: u64, o
error.OverlapsPreviousFrame => {
const overlapped_frame = (self.frame + 1) % MAX_FRAME_LAG;
std.debug.print("Vulkan Frame Allocator Overlapped frame {}, waiting for it to finish...", .{overlapped_frame});
std.debug.print("Vulkan Frame Allocator Overlapped frame {}, waiting for it to finish...\n", .{overlapped_frame});
try self.frame_data[overlapped_frame].waitForDrawAndReset(self);
self.vulkan_frame_arena.resetFrame(overlapped_frame);
self.vulkan_frame_arena.frame_regions[overlapped_frame] = null;
},
else => return err,
}
@ -430,10 +428,10 @@ fn createPerFrameImage(self: *Render2, create_info: *const vk.ImageCreateInfo, o
error.OverlapsPreviousFrame => {
const overlapped_frame = (self.frame + 1) % MAX_FRAME_LAG;
std.debug.print("Vulkan Frame Allocator Overlapped frame {}, waiting for it to finish...", .{overlapped_frame});
std.debug.print("Vulkan Frame Allocator Overlapped frame {}, waiting for it to finish...\n", .{overlapped_frame});
try self.frame_data[overlapped_frame].waitForDrawAndReset(self);
self.vulkan_frame_arena.resetFrame(overlapped_frame);
self.vulkan_frame_arena.frame_regions[overlapped_frame] = null;
},
else => return err,
}
@ -453,8 +451,8 @@ fn createPerFrameImageDescriptor(self: *Render2, view: vk.ImageView, layout: vk.
return result;
}
fn pushConstants(cmds: GraphicsContext.CommandBuffer, layout: vk.PipelineLayout, stage_flags: vk.ShaderStageFlags, value: anytype) void {
cmds.pushConstants(layout, stage_flags, 0, @sizeOf(@TypeOf(value)), &value);
fn pushConstants(self: *Render2, cmds: GraphicsContext.CommandBuffer, stage_flags: vk.ShaderStageFlags, value: anytype) void {
cmds.pushConstants(self.descriptorman.pipeline_layout, stage_flags, 0, @sizeOf(@TypeOf(value)), &value);
}
pub fn draw(self: *Render2) !void {
@ -463,17 +461,19 @@ pub fn draw(self: *Render2) !void {
const frame = &self.frame_data[self.frame];
try frame.waitForDrawAndReset(self);
self.vulkan_frame_arena.resetFrame(self.frame);
const swapchain_image_index: u32 = try gc.acquireSwapchainImage(frame.acquire_swapchain_image);
self.vulkan_frame_arena.startFrame(self.frame);
var global_buffer_addr: u64 = 0;
const global_uniform_buffer_handle = try self.createPerFrameBuffer(.{ .uniform_buffer_bit = true, .transfer_dst_bit = true }, @sizeOf(GlobalUniform), &global_buffer_addr);
var global_uniform_buffer = GraphicsContext.Buffer{ .gc = gc, .handle = global_uniform_buffer_handle, .size = @sizeOf(GlobalUniform) };
self.camera.aspect = @as(f32, @floatFromInt(self.gc.swapchain_extent.width)) / @as(f32, @floatFromInt(self.gc.swapchain_extent.height));
const global_uniform = blk: {
const view = self.camera.view_mat;
// const fwidth: f32 = @floatFromInt(gc.swapchain_extent.width);
// const fheight: f32 = @floatFromInt(gc.swapchain_extent.height);
const projection = self.camera.projection();
const view_projection = projection.mul(view);
@ -486,9 +486,6 @@ pub fn draw(self: *Render2) !void {
};
};
// Move this out into a separate func
const swapchain_image_index: u32 = try gc.acquireSwapchainImage(frame.acquire_swapchain_image);
var main_render_target = try self.allocateRenderTarget();
const color_image: *GraphicsContext.Image = &main_render_target.color;
@ -607,7 +604,7 @@ pub fn draw(self: *Render2) !void {
.color_attachment_count = 1,
.p_color_attachments = &.{
vk.RenderingAttachmentInfo{
.clear_value = .{ .color = .{ .float_32 = .{ 0.8, 0.7, 0.6, 1.0 } } },
.clear_value = .{ .color = .{ .float_32 = .{ 0.9, 0.8, 0.7, 1.0 } } },
.load_op = .clear,
.store_op = .store,
.image_layout = .color_attachment_optimal,
@ -644,7 +641,7 @@ pub fn draw(self: *Render2) !void {
const triangle = self.assetman.resolveShaderProgram(a.ShaderPrograms.shaders.triangle);
cmds.bindPipeline(.graphics, triangle.pipeline);
cmds.bindDescriptorSets(.graphics, triangle.layout, 0, 1, &.{global_descriptor_set}, 0, null);
cmds.bindDescriptorSets(.graphics, self.descriptorman.pipeline_layout, 0, 1, &.{global_descriptor_set}, 0, null);
cmds.setViewportWithCount(1, &.{vk.Viewport{
.x = 0,
@ -709,9 +706,9 @@ pub fn draw(self: *Render2) !void {
const post_process = self.assetman.resolveShaderProgram(a.ShaderPrograms.shaders.post_process);
cmds.bindPipeline(.graphics, post_process.pipeline);
cmds.bindDescriptorSets(.graphics, post_process.layout, 0, 1, &.{global_descriptor_set}, 0, null);
cmds.bindDescriptorSets(.graphics, self.descriptorman.pipeline_layout, 0, 1, &.{global_descriptor_set}, 0, null);
pushConstants(cmds, post_process.layout, .{ .fragment_bit = true }, PostProcessPushConstants{
self.pushConstants(cmds, .{ .vertex_bit = true, .fragment_bit = true }, PostProcessPushConstants{
.scene_color_texture = main_render_target.color_descriptor.index(),
.scene_color_sampler = 0,
});
@ -732,42 +729,6 @@ pub fn draw(self: *Render2) !void {
cmds.draw(6, 1, 0, 0);
}
// Direct blit without PP
// if (false) {
// try color_image.sync(cmds, .{ .stage_mask = .{ .blit_bit = true }, .access_mask = .{ .transfer_read_bit = true } }, .transfer_src_optimal, .{ .color_bit = true });
// try swapchain_image.sync(cmds, .{ .stage_mask = .{ .blit_bit = true }, .access_mask = .{ .transfer_write_bit = true } }, .transfer_dst_optimal, .{ .color_bit = true });
// cmds.blitImage(
// color_image.handle,
// color_image.sync_state.layout,
// swapchain_image.handle,
// swapchain_image.sync_state.layout,
// 1,
// &.{vk.ImageBlit{
// .src_subresource = vk.ImageSubresourceLayers{
// .aspect_mask = .{ .color_bit = true },
// .mip_level = 0,
// .base_array_layer = 0,
// .layer_count = 1,
// },
// .src_offsets = .{
// vk.Offset3D{ .x = 0, .y = 0, .z = 0 },
// vk.Offset3D{ .x = @intCast(gc.swapchain_extent.width), .y = @intCast(gc.swapchain_extent.height), .z = 1 },
// },
// .dst_subresource = vk.ImageSubresourceLayers{
// .aspect_mask = .{ .color_bit = true },
// .mip_level = 0,
// .base_array_layer = 0,
// .layer_count = 1,
// },
// .dst_offsets = .{
// vk.Offset3D{ .x = 0, .y = 0, .z = 0 },
// vk.Offset3D{ .x = @intCast(gc.swapchain_extent.width), .y = @intCast(gc.swapchain_extent.height), .z = 1 },
// },
// }},
// .nearest,
// );
// }
try swapchain_image.sync(cmds, .{ .stage_mask = .{}, .access_mask = .{} }, .present_src_khr, .{ .color_bit = true });
}
try cmds.endCommandBuffer();
@ -781,6 +742,7 @@ pub fn draw(self: *Render2) !void {
},
frame.draw_fence,
);
frame.draw_submitted = true;
_ = try gc.device.queuePresentKHR(gc.queues.graphics.handle, &.{
.swapchain_count = 1,
@ -814,6 +776,7 @@ const FrameData = struct {
acquire_swapchain_image: vk.Semaphore,
draw_sema: vk.Semaphore,
draw_fence: vk.Fence,
draw_submitted: bool = true,
command_buffer: GraphicsContext.CommandBuffer,
@ -861,6 +824,9 @@ const FrameData = struct {
}
pub fn waitForDrawAndReset(self: *FrameData, render: *Render2) !void {
if (!self.draw_submitted) return;
self.draw_submitted = false;
const device = render.gc.device;
_ = try device.waitForFences(1, &.{self.draw_fence}, vk.TRUE, std.math.maxInt(u64));
try device.resetFences(1, &.{self.draw_fence});

View File

@ -130,13 +130,9 @@ pub const ShaderProgram = union(ShaderProgramPipelineType) {
pub const ShaderStage = struct {
source: []align(4) u8,
push_constant_range: PushConstantRange,
pub fn serialize(self: *ShaderStage, serializer: *Serializer) !void {
try serializer.skipAlign(4);
try serializer.serializeByteSlice(&self.source);
try serializer.serializeInt(u32, &self.push_constant_range.offset);
try serializer.serializeInt(u32, &self.push_constant_range.size);
}
};

View File

@ -406,8 +406,8 @@ export fn game_update() bool {
c.SDL_WINDOWEVENT => {
switch (event.window.event) {
c.SDL_WINDOWEVENT_SIZE_CHANGED => {
c.SDL_GL_GetDrawableSize(ginit.window, &ginit.width, &ginit.height);
std.log.debug("w: {}, h: {}\n", .{ ginit.width, ginit.height });
// c.SDL_GL_GetDrawableSize(ginit.window, &ginit.width, &ginit.height);
// std.log.debug("w: {}, h: {}\n", .{ ginit.width, ginit.height });
// gl.viewport(0, 0, ginit.width, ginit.height);
},
@ -443,10 +443,6 @@ export fn game_update() bool {
move.zMut().* -= 1;
}
const f_width: f32 = @floatFromInt(ginit.width);
const f_height: f32 = @floatFromInt(ginit.height);
gmem.free_cam.camera.aspect = f_width / f_height;
gmem.rotation += 60 * gmem.delta_time;
// TODO: make this an entity

View File

@ -21,8 +21,6 @@ const c = @cImport({
@cInclude("stb_image.h");
@cInclude("ispc_texcomp.h");
@cInclude("spirv_reflect.h");
});
const ASSET_MAX_BYTES = 1024 * 1024 * 1024;
@ -585,19 +583,9 @@ fn readFileContents(allocator: std.mem.Allocator, path: []const u8) ![]u8 {
};
}
const PushConstantRange = struct {
offset: u32 = 0,
size: u32 = 0,
};
const ProcessedShader = struct {
spirv: []u8,
push_constant_range: PushConstantRange = .{},
};
// Returns spirv binary source
// Caller owns memory
fn processShader(allocator: std.mem.Allocator, flags: []const []const u8, input: []const u8, maybe_dep_file: ?[]const u8) !ProcessedShader {
fn processShader(allocator: std.mem.Allocator, flags: []const []const u8, input: []const u8, maybe_dep_file: ?[]const u8) ![]u8 {
// const old_depfile_contents = if (maybe_dep_file) |dep| try readFileContents(allocator, dep) else try allocator.alloc(u8, 0);
// defer allocator.free(old_depfile_contents);
@ -626,57 +614,7 @@ fn processShader(allocator: std.mem.Allocator, flags: []const []const u8, input:
},
}
// TODO: align pointer to 4 bytes
var result = ProcessedShader{ .spirv = compile_result.stdout };
{
var shader_module: c.SpvReflectShaderModule = std.mem.zeroes(c.SpvReflectShaderModule);
try spvReflectTry(c.spvReflectCreateShaderModule(compile_result.stdout.len, compile_result.stdout.ptr, &shader_module));
defer c.spvReflectDestroyShaderModule(&shader_module);
var spv_result: c.SpvReflectResult = c.SPV_REFLECT_RESULT_SUCCESS;
const push_constant_block: ?*const c.SpvReflectBlockVariable = @ptrCast(c.spvReflectGetEntryPointPushConstantBlock(&shader_module, "main", &spv_result));
spvReflectTry(spv_result) catch |err| switch (err) {
error.SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND => {},
else => return err,
};
if (push_constant_block) |block| {
// Assuming single push constant block per stage, this is what glslc enforces
std.debug.assert(shader_module.push_constant_block_count == 1);
result.push_constant_range = .{ .offset = block.offset, .size = block.size };
}
}
return result;
}
fn spvReflectTry(result: c.SpvReflectResult) !void {
switch (result) {
c.SPV_REFLECT_RESULT_SUCCESS => {},
c.SPV_REFLECT_RESULT_NOT_READY => return error.SPV_REFLECT_RESULT_NOT_READY,
c.SPV_REFLECT_RESULT_ERROR_PARSE_FAILED => return error.SPV_REFLECT_RESULT_ERROR_PARSE_FAILED,
c.SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED => return error.SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED,
c.SPV_REFLECT_RESULT_ERROR_RANGE_EXCEEDED => return error.SPV_REFLECT_RESULT_ERROR_RANGE_EXCEEDED,
c.SPV_REFLECT_RESULT_ERROR_NULL_POINTER => return error.SPV_REFLECT_RESULT_ERROR_NULL_POINTER,
c.SPV_REFLECT_RESULT_ERROR_INTERNAL_ERROR => return error.SPV_REFLECT_RESULT_ERROR_INTERNAL_ERROR,
c.SPV_REFLECT_RESULT_ERROR_COUNT_MISMATCH => return error.SPV_REFLECT_RESULT_ERROR_COUNT_MISMATCH,
c.SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND => return error.SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND,
c.SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_CODE_SIZE => return error.SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_CODE_SIZE,
c.SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_MAGIC_NUMBER => return error.SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_MAGIC_NUMBER,
c.SPV_REFLECT_RESULT_ERROR_SPIRV_UNEXPECTED_EOF => return error.SPV_REFLECT_RESULT_ERROR_SPIRV_UNEXPECTED_EOF,
c.SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE => return error.SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE,
c.SPV_REFLECT_RESULT_ERROR_SPIRV_SET_NUMBER_OVERFLOW => return error.SPV_REFLECT_RESULT_ERROR_SPIRV_SET_NUMBER_OVERFLOW,
c.SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_STORAGE_CLASS => return error.SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_STORAGE_CLASS,
c.SPV_REFLECT_RESULT_ERROR_SPIRV_RECURSION => return error.SPV_REFLECT_RESULT_ERROR_SPIRV_RECURSION,
c.SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_INSTRUCTION => return error.SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_INSTRUCTION,
c.SPV_REFLECT_RESULT_ERROR_SPIRV_UNEXPECTED_BLOCK_DATA => return error.SPV_REFLECT_RESULT_ERROR_SPIRV_UNEXPECTED_BLOCK_DATA,
c.SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_BLOCK_MEMBER_REFERENCE => return error.SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_BLOCK_MEMBER_REFERENCE,
c.SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ENTRY_POINT => return error.SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ENTRY_POINT,
c.SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_EXECUTION_MODE => return error.SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_EXECUTION_MODE,
c.SPV_REFLECT_RESULT_ERROR_SPIRV_MAX_RECURSIVE_EXCEEDED => return error.SPV_REFLECT_RESULT_ERROR_SPIRV_MAX_RECURSIVE_EXCEEDED,
else => unreachable,
}
return compile_result.stdout;
}
fn processShaderProgram(allocator: std.mem.Allocator, input: []const u8, output_dir: std.fs.Dir, dep_file: ?[]const u8, asset_list_writer: anytype) !void {
@ -734,8 +672,7 @@ fn processShaderProgram(allocator: std.mem.Allocator, input: []const u8, output_
const relative_path = try std.fs.path.relative(allocator, try std.fs.cwd().realpathAlloc(allocator, "."), shader_source_path);
const shader = try processShader(allocator, &.{ "-DVERTEX_SHADER=1", "-fshader-stage=vert", "-fpreserve-bindings" }, relative_path, dep_file);
result.graphics.vertex.source = @alignCast(shader.spirv);
result.graphics.vertex.push_constant_range = .{ .offset = shader.push_constant_range.offset, .size = shader.push_constant_range.size };
result.graphics.vertex.source = @alignCast(shader);
}
{
const stage = program.value.fragment.?;
@ -743,8 +680,7 @@ fn processShaderProgram(allocator: std.mem.Allocator, input: []const u8, output_
const relative_path = try std.fs.path.relative(allocator, try std.fs.cwd().realpathAlloc(allocator, "."), shader_source_path);
const shader = try processShader(allocator, &.{ "-DFRAGMENT_SHADER=1", "-fshader-stage=frag", "-fpreserve-bindings" }, relative_path, dep_file);
result.graphics.fragment.source = @alignCast(shader.spirv);
result.graphics.fragment.push_constant_range = .{ .offset = shader.push_constant_range.offset, .size = shader.push_constant_range.size };
result.graphics.fragment.source = @alignCast(shader);
}
} else if (program.value.compute != null) {
result = .{ .compute = undefined };
@ -754,8 +690,7 @@ fn processShaderProgram(allocator: std.mem.Allocator, input: []const u8, output_
const relative_path = try std.fs.path.relative(allocator, try std.fs.cwd().realpathAlloc(allocator, "."), shader_source_path);
const shader = try processShader(allocator, &.{ "-DCOMPUTE_SHADER=1", "-fshader-stage=compute" }, relative_path, dep_file);
result.compute.compute.source = @alignCast(shader.spirv);
result.compute.compute.push_constant_range = .{ .offset = shader.push_constant_range.offset, .size = shader.push_constant_range.size };
result.compute.compute.source = @alignCast(shader);
} else {
std.log.err("Provide vertex and fragment shaders for a graphics pipeline or a compute shader for a compute pipeline\n", .{});
return error.InvalidPipelines;