Simplify things, use just one pipeline layout for all shaders (nice), remove spirv-reflect
This commit is contained in:
parent
1181e56236
commit
e229da9315
@ -282,12 +282,7 @@ fn buildAssetCompiler(b: *Build, optimize: std.builtin.OptimizeMode, assets_mod:
|
|||||||
.skip_tests = true,
|
.skip_tests = true,
|
||||||
});
|
});
|
||||||
const zalgebra_dep = b.dependency("zalgebra", .{});
|
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 assimp_lib = assimp_dep.artifact("assimp");
|
||||||
const spirv_reflect_lib = spirv_reflect_dep.artifact("spirv-reflect");
|
|
||||||
|
|
||||||
const assetc = b.addExecutable(.{
|
const assetc = b.addExecutable(.{
|
||||||
.name = "assetc",
|
.name = "assetc",
|
||||||
@ -317,7 +312,6 @@ fn buildAssetCompiler(b: *Build, optimize: std.builtin.OptimizeMode, assets_mod:
|
|||||||
assetc.root_module.addImport("assets", assets_mod);
|
assetc.root_module.addImport("assets", assets_mod);
|
||||||
|
|
||||||
assetc.linkLibrary(assimp_lib);
|
assetc.linkLibrary(assimp_lib);
|
||||||
assetc.linkLibrary(spirv_reflect_lib);
|
|
||||||
assetc.linkLibC();
|
assetc.linkLibC();
|
||||||
assetc.linkLibCpp();
|
assetc.linkLibCpp();
|
||||||
|
|
||||||
|
@ -51,10 +51,6 @@
|
|||||||
.url = "https://github.com/hexops/spirv-cross/tarball/872bd405fece4bf6388abdea916356e26cb8fed9",
|
.url = "https://github.com/hexops/spirv-cross/tarball/872bd405fece4bf6388abdea916356e26cb8fed9",
|
||||||
.hash = "12207bebf82eef06f4f80a7e54c91e4402c0055d04167fdbcf1f350846a350266976",
|
.hash = "12207bebf82eef06f4f80a7e54c91e4402c0055d04167fdbcf1f350846a350266976",
|
||||||
},
|
},
|
||||||
.@"SPIRV-Reflect" = .{
|
|
||||||
.url = "https://github.com/sergeypdev/SPIRV-Reflect/tarball/bb3e8b8d5dee32b65e1d16598c526415470fc863",
|
|
||||||
.hash = "122048fdee255a7ac992068d5ded4bfa88927ddc8af12a5068c69198153a60dbe779",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
.paths = .{
|
.paths = .{
|
||||||
// This makes *all* files, recursively, included in this package. It is generally
|
// This makes *all* files, recursively, included in this package. It is generally
|
||||||
|
@ -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 {
|
fn loadShaderProgramErr(self: *AssetManager, id: AssetId) !LoadedShaderProgram {
|
||||||
const data = try self.loadFile(self.frame_arena, asset_manifest.getPath(id), SHADER_MAX_BYTES);
|
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 serializer = formats.Serializer{ .write = false, .endian = formats.native_endian, .stream = .{ .buffer = std.io.fixedBufferStream(data.bytes) } };
|
||||||
var program: formats.ShaderProgram = undefined;
|
var program: formats.ShaderProgram = undefined;
|
||||||
try program.serialize(&serializer);
|
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: {
|
const pipeline = blk: {
|
||||||
switch (program) {
|
switch (program) {
|
||||||
.graphics => |graphics_pipeline| {
|
.graphics => |graphics_pipeline| {
|
||||||
@ -433,7 +380,7 @@ fn loadShaderProgramErr(self: *AssetManager, id: AssetId) !LoadedShaderProgram {
|
|||||||
.line_width = 1.0,
|
.line_width = 1.0,
|
||||||
},
|
},
|
||||||
.p_viewport_state = &vk.PipelineViewportStateCreateInfo{},
|
.p_viewport_state = &vk.PipelineViewportStateCreateInfo{},
|
||||||
.layout = pipeline_layout,
|
.layout = self.descriptorman.pipeline_layout,
|
||||||
.p_depth_stencil_state = &vk.PipelineDepthStencilStateCreateInfo{
|
.p_depth_stencil_state = &vk.PipelineDepthStencilStateCreateInfo{
|
||||||
// Dynamic States
|
// Dynamic States
|
||||||
.depth_test_enable = vk.FALSE,
|
.depth_test_enable = vk.FALSE,
|
||||||
@ -523,7 +470,6 @@ fn loadShaderProgramErr(self: *AssetManager, id: AssetId) !LoadedShaderProgram {
|
|||||||
|
|
||||||
const loaded_shader_program = LoadedShaderProgram{
|
const loaded_shader_program = LoadedShaderProgram{
|
||||||
.pipeline = pipeline,
|
.pipeline = pipeline,
|
||||||
.layout = pipeline_layout,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -546,7 +492,6 @@ const NullShader = LoadedShader{
|
|||||||
|
|
||||||
const NullShaderProgram = LoadedShaderProgram{
|
const NullShaderProgram = LoadedShaderProgram{
|
||||||
.pipeline = .null_handle,
|
.pipeline = .null_handle,
|
||||||
.layout = .null_handle,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const NullMesh = LoadedMesh{
|
const NullMesh = LoadedMesh{
|
||||||
@ -836,7 +781,6 @@ const LoadedShader = struct {
|
|||||||
|
|
||||||
const LoadedShaderProgram = struct {
|
const LoadedShaderProgram = struct {
|
||||||
pipeline: vk.Pipeline,
|
pipeline: vk.Pipeline,
|
||||||
layout: vk.PipelineLayout,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const LoadedMesh = struct {
|
pub const LoadedMesh = struct {
|
||||||
|
@ -156,6 +156,8 @@ gc: *GraphicsContext,
|
|||||||
descriptor_set_layouts: DescriptorSetLayouts = .{},
|
descriptor_set_layouts: DescriptorSetLayouts = .{},
|
||||||
image_descriptor_array_2d: DescriptorArray(SampledImageDescriptorData, 1024) = .{},
|
image_descriptor_array_2d: DescriptorArray(SampledImageDescriptorData, 1024) = .{},
|
||||||
|
|
||||||
|
pipeline_layout: vk.PipelineLayout = .null_handle,
|
||||||
|
|
||||||
pub fn init(gc: *GraphicsContext) !DescriptorManager {
|
pub fn init(gc: *GraphicsContext) !DescriptorManager {
|
||||||
var self = DescriptorManager{
|
var self = DescriptorManager{
|
||||||
.gc = gc,
|
.gc = gc,
|
||||||
@ -201,30 +203,23 @@ pub fn init(gc: *GraphicsContext) !DescriptorManager {
|
|||||||
}, null);
|
}, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Post Process Pass Descriptor Set Layout
|
self.pipeline_layout = try self.gc.device.createPipelineLayout(&.{
|
||||||
// {
|
.set_layout_count = 1,
|
||||||
// const descriptor_set_layout_bindings = [_]vk.DescriptorSetLayoutBinding{
|
.p_set_layouts = &.{self.descriptor_set_layouts.global},
|
||||||
// vk.DescriptorSetLayoutBinding{
|
.push_constant_range_count = 2,
|
||||||
// .binding = DescriptorSets.Passes.PostProcess.Bindings.ScreenSampler.value(),
|
.p_push_constant_ranges = &.{
|
||||||
// .descriptor_type = .sampler,
|
vk.PushConstantRange{
|
||||||
// .descriptor_count = 1,
|
.stage_flags = .{ .vertex_bit = true },
|
||||||
// .stage_flags = vk.ShaderStageFlags.fromInt(0x7FFFFFFF), // SHADER_STAGE_ALL
|
.offset = 0,
|
||||||
// },
|
.size = 128,
|
||||||
// vk.DescriptorSetLayoutBinding{
|
},
|
||||||
// .binding = DescriptorSets.Passes.PostProcess.Bindings.ScreenTexture.value(),
|
vk.PushConstantRange{
|
||||||
// .descriptor_type = .sampled_image,
|
.stage_flags = .{ .fragment_bit = true },
|
||||||
// .descriptor_count = 1,
|
.offset = 0,
|
||||||
// .stage_flags = vk.ShaderStageFlags.fromInt(0x7FFFFFFF), // SHADER_STAGE_ALL
|
.size = 128,
|
||||||
// },
|
},
|
||||||
// };
|
},
|
||||||
// self.descriptor_set_layouts.passes.post_process = try self.gc.device.createDescriptorSetLayout(&.{
|
}, null);
|
||||||
// .flags = .{
|
|
||||||
// .push_descriptor_bit_khr = true,
|
|
||||||
// },
|
|
||||||
// .p_bindings = &descriptor_set_layout_bindings,
|
|
||||||
// .binding_count = descriptor_set_layout_bindings.len,
|
|
||||||
// }, null);
|
|
||||||
// }
|
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
@ -520,6 +520,9 @@ fn maybeResizeSwapchain(self: *GraphicsContext) !void {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std.debug.print("resizing swapchain {}\n", .{new_extent});
|
||||||
|
self.swapchain_extent = new_extent;
|
||||||
|
|
||||||
if (self.swapchain_images.len > 0) {
|
if (self.swapchain_images.len > 0) {
|
||||||
self.allocator.free(self.swapchain_images);
|
self.allocator.free(self.swapchain_images);
|
||||||
self.swapchain_images = &.{};
|
self.swapchain_images = &.{};
|
||||||
|
@ -30,7 +30,7 @@ pub const Camera = struct {
|
|||||||
var default_camera: Camera = .{};
|
var default_camera: Camera = .{};
|
||||||
|
|
||||||
const MAX_FRAME_LAG = 3;
|
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,
|
frame_allocator: std.mem.Allocator,
|
||||||
gc: *GraphicsContext,
|
gc: *GraphicsContext,
|
||||||
@ -116,16 +116,13 @@ pub const VulkanPerFrameArena = struct {
|
|||||||
// Record start position of this frame
|
// Record start position of this frame
|
||||||
if (self.frame_regions[self.frame]) |*cur_region| {
|
if (self.frame_regions[self.frame]) |*cur_region| {
|
||||||
cur_region.end = self.tail;
|
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 = frame_index;
|
||||||
self.frame_regions[self.frame] = FrameRegion.init(self.tail, self.tail);
|
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 {
|
pub fn getModifiedMemoryRanges(self: *VulkanPerFrameArena, out_ranges: []vk.MappedMemoryRange) []const vk.MappedMemoryRange {
|
||||||
std.debug.assert(out_ranges.len >= 2);
|
std.debug.assert(out_ranges.len >= 2);
|
||||||
std.debug.assert(self.frame_regions[self.frame] != null);
|
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);
|
const allocated_region = FrameRegion.init(offset, offset + size);
|
||||||
|
|
||||||
if (next_frame_region.intersectsWrapping(&allocated_region, self.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;
|
return error.OverlapsPreviousFrame;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -412,10 +410,10 @@ fn createPerFrameBuffer(self: *Render2, usage: vk.BufferUsageFlags, size: u64, o
|
|||||||
error.OverlapsPreviousFrame => {
|
error.OverlapsPreviousFrame => {
|
||||||
const overlapped_frame = (self.frame + 1) % MAX_FRAME_LAG;
|
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);
|
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,
|
else => return err,
|
||||||
}
|
}
|
||||||
@ -430,10 +428,10 @@ fn createPerFrameImage(self: *Render2, create_info: *const vk.ImageCreateInfo, o
|
|||||||
error.OverlapsPreviousFrame => {
|
error.OverlapsPreviousFrame => {
|
||||||
const overlapped_frame = (self.frame + 1) % MAX_FRAME_LAG;
|
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);
|
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,
|
else => return err,
|
||||||
}
|
}
|
||||||
@ -453,8 +451,8 @@ fn createPerFrameImageDescriptor(self: *Render2, view: vk.ImageView, layout: vk.
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pushConstants(cmds: GraphicsContext.CommandBuffer, layout: vk.PipelineLayout, stage_flags: vk.ShaderStageFlags, value: anytype) void {
|
fn pushConstants(self: *Render2, cmds: GraphicsContext.CommandBuffer, stage_flags: vk.ShaderStageFlags, value: anytype) void {
|
||||||
cmds.pushConstants(layout, stage_flags, 0, @sizeOf(@TypeOf(value)), &value);
|
cmds.pushConstants(self.descriptorman.pipeline_layout, stage_flags, 0, @sizeOf(@TypeOf(value)), &value);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw(self: *Render2) !void {
|
pub fn draw(self: *Render2) !void {
|
||||||
@ -463,17 +461,19 @@ pub fn draw(self: *Render2) !void {
|
|||||||
const frame = &self.frame_data[self.frame];
|
const frame = &self.frame_data[self.frame];
|
||||||
|
|
||||||
try frame.waitForDrawAndReset(self);
|
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);
|
self.vulkan_frame_arena.startFrame(self.frame);
|
||||||
|
|
||||||
var global_buffer_addr: u64 = 0;
|
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);
|
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) };
|
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 global_uniform = blk: {
|
||||||
const view = self.camera.view_mat;
|
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 projection = self.camera.projection();
|
||||||
const view_projection = projection.mul(view);
|
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();
|
var main_render_target = try self.allocateRenderTarget();
|
||||||
|
|
||||||
const color_image: *GraphicsContext.Image = &main_render_target.color;
|
const color_image: *GraphicsContext.Image = &main_render_target.color;
|
||||||
@ -607,7 +604,7 @@ pub fn draw(self: *Render2) !void {
|
|||||||
.color_attachment_count = 1,
|
.color_attachment_count = 1,
|
||||||
.p_color_attachments = &.{
|
.p_color_attachments = &.{
|
||||||
vk.RenderingAttachmentInfo{
|
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,
|
.load_op = .clear,
|
||||||
.store_op = .store,
|
.store_op = .store,
|
||||||
.image_layout = .color_attachment_optimal,
|
.image_layout = .color_attachment_optimal,
|
||||||
@ -644,7 +641,7 @@ pub fn draw(self: *Render2) !void {
|
|||||||
const triangle = self.assetman.resolveShaderProgram(a.ShaderPrograms.shaders.triangle);
|
const triangle = self.assetman.resolveShaderProgram(a.ShaderPrograms.shaders.triangle);
|
||||||
|
|
||||||
cmds.bindPipeline(.graphics, triangle.pipeline);
|
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{
|
cmds.setViewportWithCount(1, &.{vk.Viewport{
|
||||||
.x = 0,
|
.x = 0,
|
||||||
@ -709,9 +706,9 @@ pub fn draw(self: *Render2) !void {
|
|||||||
const post_process = self.assetman.resolveShaderProgram(a.ShaderPrograms.shaders.post_process);
|
const post_process = self.assetman.resolveShaderProgram(a.ShaderPrograms.shaders.post_process);
|
||||||
|
|
||||||
cmds.bindPipeline(.graphics, post_process.pipeline);
|
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_texture = main_render_target.color_descriptor.index(),
|
||||||
.scene_color_sampler = 0,
|
.scene_color_sampler = 0,
|
||||||
});
|
});
|
||||||
@ -732,42 +729,6 @@ pub fn draw(self: *Render2) !void {
|
|||||||
cmds.draw(6, 1, 0, 0);
|
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 swapchain_image.sync(cmds, .{ .stage_mask = .{}, .access_mask = .{} }, .present_src_khr, .{ .color_bit = true });
|
||||||
}
|
}
|
||||||
try cmds.endCommandBuffer();
|
try cmds.endCommandBuffer();
|
||||||
@ -781,6 +742,7 @@ pub fn draw(self: *Render2) !void {
|
|||||||
},
|
},
|
||||||
frame.draw_fence,
|
frame.draw_fence,
|
||||||
);
|
);
|
||||||
|
frame.draw_submitted = true;
|
||||||
|
|
||||||
_ = try gc.device.queuePresentKHR(gc.queues.graphics.handle, &.{
|
_ = try gc.device.queuePresentKHR(gc.queues.graphics.handle, &.{
|
||||||
.swapchain_count = 1,
|
.swapchain_count = 1,
|
||||||
@ -814,6 +776,7 @@ const FrameData = struct {
|
|||||||
acquire_swapchain_image: vk.Semaphore,
|
acquire_swapchain_image: vk.Semaphore,
|
||||||
draw_sema: vk.Semaphore,
|
draw_sema: vk.Semaphore,
|
||||||
draw_fence: vk.Fence,
|
draw_fence: vk.Fence,
|
||||||
|
draw_submitted: bool = true,
|
||||||
|
|
||||||
command_buffer: GraphicsContext.CommandBuffer,
|
command_buffer: GraphicsContext.CommandBuffer,
|
||||||
|
|
||||||
@ -861,6 +824,9 @@ const FrameData = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn waitForDrawAndReset(self: *FrameData, render: *Render2) !void {
|
pub fn waitForDrawAndReset(self: *FrameData, render: *Render2) !void {
|
||||||
|
if (!self.draw_submitted) return;
|
||||||
|
|
||||||
|
self.draw_submitted = false;
|
||||||
const device = render.gc.device;
|
const device = render.gc.device;
|
||||||
_ = try device.waitForFences(1, &.{self.draw_fence}, vk.TRUE, std.math.maxInt(u64));
|
_ = try device.waitForFences(1, &.{self.draw_fence}, vk.TRUE, std.math.maxInt(u64));
|
||||||
try device.resetFences(1, &.{self.draw_fence});
|
try device.resetFences(1, &.{self.draw_fence});
|
||||||
|
@ -130,13 +130,9 @@ pub const ShaderProgram = union(ShaderProgramPipelineType) {
|
|||||||
|
|
||||||
pub const ShaderStage = struct {
|
pub const ShaderStage = struct {
|
||||||
source: []align(4) u8,
|
source: []align(4) u8,
|
||||||
push_constant_range: PushConstantRange,
|
|
||||||
|
|
||||||
pub fn serialize(self: *ShaderStage, serializer: *Serializer) !void {
|
pub fn serialize(self: *ShaderStage, serializer: *Serializer) !void {
|
||||||
try serializer.skipAlign(4);
|
try serializer.skipAlign(4);
|
||||||
try serializer.serializeByteSlice(&self.source);
|
try serializer.serializeByteSlice(&self.source);
|
||||||
try serializer.serializeInt(u32, &self.push_constant_range.offset);
|
|
||||||
try serializer.serializeInt(u32, &self.push_constant_range.size);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -406,8 +406,8 @@ export fn game_update() bool {
|
|||||||
c.SDL_WINDOWEVENT => {
|
c.SDL_WINDOWEVENT => {
|
||||||
switch (event.window.event) {
|
switch (event.window.event) {
|
||||||
c.SDL_WINDOWEVENT_SIZE_CHANGED => {
|
c.SDL_WINDOWEVENT_SIZE_CHANGED => {
|
||||||
c.SDL_GL_GetDrawableSize(ginit.window, &ginit.width, &ginit.height);
|
// c.SDL_GL_GetDrawableSize(ginit.window, &ginit.width, &ginit.height);
|
||||||
std.log.debug("w: {}, h: {}\n", .{ ginit.width, ginit.height });
|
// std.log.debug("w: {}, h: {}\n", .{ ginit.width, ginit.height });
|
||||||
|
|
||||||
// gl.viewport(0, 0, ginit.width, ginit.height);
|
// gl.viewport(0, 0, ginit.width, ginit.height);
|
||||||
},
|
},
|
||||||
@ -443,10 +443,6 @@ export fn game_update() bool {
|
|||||||
move.zMut().* -= 1;
|
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;
|
gmem.rotation += 60 * gmem.delta_time;
|
||||||
|
|
||||||
// TODO: make this an entity
|
// TODO: make this an entity
|
||||||
|
@ -21,8 +21,6 @@ const c = @cImport({
|
|||||||
@cInclude("stb_image.h");
|
@cInclude("stb_image.h");
|
||||||
|
|
||||||
@cInclude("ispc_texcomp.h");
|
@cInclude("ispc_texcomp.h");
|
||||||
|
|
||||||
@cInclude("spirv_reflect.h");
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const ASSET_MAX_BYTES = 1024 * 1024 * 1024;
|
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
|
// Returns spirv binary source
|
||||||
// Caller owns memory
|
// 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);
|
// 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);
|
// 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
|
return compile_result.stdout;
|
||||||
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,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn processShaderProgram(allocator: std.mem.Allocator, input: []const u8, output_dir: std.fs.Dir, dep_file: ?[]const u8, asset_list_writer: anytype) !void {
|
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 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);
|
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.source = @alignCast(shader);
|
||||||
result.graphics.vertex.push_constant_range = .{ .offset = shader.push_constant_range.offset, .size = shader.push_constant_range.size };
|
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const stage = program.value.fragment.?;
|
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 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);
|
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.source = @alignCast(shader);
|
||||||
result.graphics.fragment.push_constant_range = .{ .offset = shader.push_constant_range.offset, .size = shader.push_constant_range.size };
|
|
||||||
}
|
}
|
||||||
} else if (program.value.compute != null) {
|
} else if (program.value.compute != null) {
|
||||||
result = .{ .compute = undefined };
|
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 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);
|
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.source = @alignCast(shader);
|
||||||
result.compute.compute.push_constant_range = .{ .offset = shader.push_constant_range.offset, .size = shader.push_constant_range.size };
|
|
||||||
} else {
|
} else {
|
||||||
std.log.err("Provide vertex and fragment shaders for a graphics pipeline or a compute shader for a compute pipeline\n", .{});
|
std.log.err("Provide vertex and fragment shaders for a graphics pipeline or a compute shader for a compute pipeline\n", .{});
|
||||||
return error.InvalidPipelines;
|
return error.InvalidPipelines;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user