Vulkan TRIANGLE!!!
This commit is contained in:
parent
f0c9e04887
commit
fe69fa1f51
@ -1,12 +1,21 @@
|
|||||||
#if VERTEX_SHADER
|
#if VERTEX_SHADER
|
||||||
|
|
||||||
vec2 positions[3] = vec2[](
|
vec2 positions[3] = vec2[](
|
||||||
vec2(0.0, -0.5),
|
vec2(-0.5, 0.5),
|
||||||
vec2(0.5, 0.5),
|
vec2(0.5, 0.5),
|
||||||
vec2(-0.5, 0.5)
|
vec2(0.0, -0.5)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
vec3 colors[3] = vec3[](
|
||||||
|
vec3(1.0, 0.0, 0.0),
|
||||||
|
vec3(0.0, 1.0, 0.0),
|
||||||
|
vec3(0.0, 0.0, 1.0)
|
||||||
|
);
|
||||||
|
|
||||||
|
layout(location = 0) out vec3 VertexColor;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
VertexColor = colors[gl_VertexIndex];
|
||||||
gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0);
|
gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -14,10 +23,12 @@ void main() {
|
|||||||
|
|
||||||
#if FRAGMENT_SHADER
|
#if FRAGMENT_SHADER
|
||||||
|
|
||||||
|
layout(location = 0) in vec3 VertexColor;
|
||||||
|
|
||||||
layout(location = 0) out vec4 FragColor;
|
layout(location = 0) out vec4 FragColor;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
FragColor = vec4(0.6, 0.8, 1.0, 1.0);
|
FragColor = vec4(VertexColor, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -27,6 +27,8 @@ const Vec3 = @import("zalgebra").Vec3;
|
|||||||
const Mat4 = @import("zalgebra").Mat4;
|
const Mat4 = @import("zalgebra").Mat4;
|
||||||
const sdl = @import("sdl.zig");
|
const sdl = @import("sdl.zig");
|
||||||
const tracy = @import("tracy");
|
const tracy = @import("tracy");
|
||||||
|
const vk = @import("vk");
|
||||||
|
const GraphicsContext = @import("GraphicsContext.zig");
|
||||||
|
|
||||||
pub const AssetId = assets.AssetId;
|
pub const AssetId = assets.AssetId;
|
||||||
pub const Handle = assets.Handle;
|
pub const Handle = assets.Handle;
|
||||||
@ -56,6 +58,7 @@ rw_lock: std.Thread.RwLock.DefaultRwLock = .{},
|
|||||||
asset_watcher: AssetWatcher = undefined,
|
asset_watcher: AssetWatcher = undefined,
|
||||||
|
|
||||||
vertex_heap: VertexBufferHeap,
|
vertex_heap: VertexBufferHeap,
|
||||||
|
gc: *GraphicsContext,
|
||||||
|
|
||||||
const AssetWatcher = struct {
|
const AssetWatcher = struct {
|
||||||
assetman: *AssetManager,
|
assetman: *AssetManager,
|
||||||
@ -145,7 +148,7 @@ const AssetWatcher = struct {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn init(allocator: std.mem.Allocator, frame_arena: std.mem.Allocator) AssetManager {
|
pub fn init(allocator: std.mem.Allocator, frame_arena: std.mem.Allocator, gc: *GraphicsContext) AssetManager {
|
||||||
var buf: [std.fs.MAX_PATH_BYTES]u8 = undefined;
|
var buf: [std.fs.MAX_PATH_BYTES]u8 = undefined;
|
||||||
const exe_dir_path = std.fs.selfExeDirPath(&buf) catch @panic("can't find self exe dir path");
|
const exe_dir_path = std.fs.selfExeDirPath(&buf) catch @panic("can't find self exe dir path");
|
||||||
const exe_dir = std.fs.openDirAbsolute(exe_dir_path, .{}) catch @panic("can't open self exe dir path");
|
const exe_dir = std.fs.openDirAbsolute(exe_dir_path, .{}) catch @panic("can't open self exe dir path");
|
||||||
@ -155,6 +158,7 @@ pub fn init(allocator: std.mem.Allocator, frame_arena: std.mem.Allocator) AssetM
|
|||||||
.frame_arena = frame_arena,
|
.frame_arena = frame_arena,
|
||||||
.exe_dir = exe_dir,
|
.exe_dir = exe_dir,
|
||||||
.vertex_heap = VertexBufferHeap.init(allocator) catch @panic("OOM"),
|
.vertex_heap = VertexBufferHeap.init(allocator) catch @panic("OOM"),
|
||||||
|
.gc = gc,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -212,16 +216,14 @@ pub fn resolveShaderWithDefines(self: *AssetManager, handle: Handle.Shader, defi
|
|||||||
return self.loadShader(handle.id, permuted_asset_id, defines);
|
return self.loadShader(handle.id, permuted_asset_id, defines);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// pub fn resolveShaderProgram(self: *AssetManager, handle: Handle.ShaderProgram) LoadedShaderProgram {
|
||||||
|
// return self.resolveShaderProgramWithDefines(handle, &.{});
|
||||||
|
// }
|
||||||
|
//
|
||||||
pub fn resolveShaderProgram(self: *AssetManager, handle: Handle.ShaderProgram) LoadedShaderProgram {
|
pub fn resolveShaderProgram(self: *AssetManager, handle: Handle.ShaderProgram) LoadedShaderProgram {
|
||||||
return self.resolveShaderProgramWithDefines(handle, &.{});
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn resolveShaderProgramWithDefines(self: *AssetManager, handle: Handle.ShaderProgram, defines: []const DefinePair) LoadedShaderProgram {
|
|
||||||
if (handle.id == 0) return NullShaderProgram;
|
if (handle.id == 0) return NullShaderProgram;
|
||||||
|
|
||||||
const permuted_asset_id = permuteAssetIdDefines(handle.id, defines);
|
if (self.resolveAsset(handle.id)) |asset| {
|
||||||
|
|
||||||
if (self.resolveAsset(permuted_asset_id)) |asset| {
|
|
||||||
switch (asset.*) {
|
switch (asset.*) {
|
||||||
.shaderProgram => |shader| {
|
.shaderProgram => |shader| {
|
||||||
return shader;
|
return shader;
|
||||||
@ -230,7 +232,7 @@ pub fn resolveShaderProgramWithDefines(self: *AssetManager, handle: Handle.Shade
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return self.loadShaderProgram(handle, permuted_asset_id, defines);
|
return self.loadShaderProgram(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn resolveMesh(self: *AssetManager, handle: Handle.Mesh) LoadedMesh {
|
pub fn resolveMesh(self: *AssetManager, handle: Handle.Mesh) LoadedMesh {
|
||||||
@ -307,88 +309,147 @@ pub const ShaderProgramDefinition = struct {
|
|||||||
compute: []const u8,
|
compute: []const u8,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn loadShaderProgram(self: *AssetManager, handle: Handle.ShaderProgram, permuted_id: AssetId, defines: []const DefinePair) LoadedShaderProgram {
|
pub fn loadShaderProgram(self: *AssetManager, handle: Handle.ShaderProgram) LoadedShaderProgram {
|
||||||
return self.loadShaderProgramErr(handle.id, permuted_id, defines) catch |err| {
|
return self.loadShaderProgramErr(handle.id) catch |err| {
|
||||||
std.log.err("Failed to load shader program {}\n", .{err});
|
std.log.err("Failed to load shader program {}\n", .{err});
|
||||||
|
|
||||||
return NullShaderProgram;
|
return NullShaderProgram;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn loadShaderProgramErr(self: *AssetManager, id: AssetId, permuted_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 = .{ .const_buffer = 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);
|
||||||
|
|
||||||
const prog = gl.createProgram();
|
const pipeline = blk: {
|
||||||
errdefer gl.deleteProgram(prog);
|
switch (program) {
|
||||||
|
.graphics => |graphics_pipeline| {
|
||||||
|
const vertex_shader_modle = try self.gc.device.createShaderModule(&.{
|
||||||
|
.code_size = graphics_pipeline.vertex.source.len,
|
||||||
|
.p_code = @alignCast(@ptrCast(graphics_pipeline.vertex.source.ptr)),
|
||||||
|
}, null);
|
||||||
|
defer self.gc.device.destroyShaderModule(vertex_shader_modle, null);
|
||||||
|
const fragment_shader_modle = try self.gc.device.createShaderModule(&.{
|
||||||
|
.code_size = graphics_pipeline.fragment.source.len,
|
||||||
|
.p_code = @alignCast(@ptrCast(graphics_pipeline.fragment.source.ptr)),
|
||||||
|
}, null);
|
||||||
|
defer self.gc.device.destroyShaderModule(fragment_shader_modle, null);
|
||||||
|
|
||||||
switch (program) {
|
const dynamic_states = [_]vk.DynamicState{
|
||||||
.graphics => |graphics_pipeline| {
|
.viewport_with_count,
|
||||||
const vertex_shader = try self.compileShader(graphics_pipeline.vertex.source, .vertex);
|
.scissor_with_count,
|
||||||
defer gl.deleteShader(vertex_shader);
|
};
|
||||||
const fragment_shader = try self.compileShader(graphics_pipeline.fragment.source, .fragment);
|
|
||||||
defer gl.deleteShader(fragment_shader);
|
|
||||||
|
|
||||||
gl.attachShader(prog, vertex_shader);
|
const pipeline_layout = try self.gc.device.createPipelineLayout(&.{}, null);
|
||||||
defer gl.detachShader(prog, vertex_shader);
|
defer self.gc.device.destroyPipelineLayout(pipeline_layout, null);
|
||||||
gl.attachShader(prog, fragment_shader);
|
|
||||||
defer gl.detachShader(prog, fragment_shader);
|
|
||||||
|
|
||||||
gl.linkProgram(prog);
|
var pipelines = [1]vk.Pipeline{.null_handle};
|
||||||
},
|
_ = try self.gc.device.createGraphicsPipelines(self.gc.pipeline_cache, 1, &.{
|
||||||
.compute => |compute_pipeline| {
|
vk.GraphicsPipelineCreateInfo{
|
||||||
const compute_shader = try self.compileShader(compute_pipeline.compute.source, .compute);
|
.base_pipeline_index = 0,
|
||||||
defer gl.deleteShader(compute_shader);
|
.p_input_assembly_state = &vk.PipelineInputAssemblyStateCreateInfo{
|
||||||
|
.primitive_restart_enable = vk.FALSE,
|
||||||
|
.topology = .triangle_list,
|
||||||
|
},
|
||||||
|
.p_vertex_input_state = &vk.PipelineVertexInputStateCreateInfo{},
|
||||||
|
.p_rasterization_state = &vk.PipelineRasterizationStateCreateInfo{
|
||||||
|
.depth_clamp_enable = vk.FALSE,
|
||||||
|
.rasterizer_discard_enable = vk.FALSE,
|
||||||
|
.polygon_mode = .fill,
|
||||||
|
.cull_mode = .{ .back_bit = true },
|
||||||
|
.front_face = .counter_clockwise,
|
||||||
|
.depth_bias_enable = vk.FALSE,
|
||||||
|
.depth_bias_constant_factor = 0.0,
|
||||||
|
.depth_bias_clamp = 0.0,
|
||||||
|
.depth_bias_slope_factor = 0.0,
|
||||||
|
.line_width = 1.0,
|
||||||
|
},
|
||||||
|
.p_viewport_state = &vk.PipelineViewportStateCreateInfo{},
|
||||||
|
.layout = pipeline_layout,
|
||||||
|
// .p_depth_stencil_state = &vk.PipelineDepthStencilStateCreateInfo{
|
||||||
|
// .depth_test_enable = true,
|
||||||
|
// .depth_write_enable = true,
|
||||||
|
// .depth_compare_op = .less,
|
||||||
|
// .depth_bounds_test_enable = true,
|
||||||
|
// .stencil_test_enable = false,
|
||||||
|
// .front = std.mem.zeroes(vk.StencilOpState),
|
||||||
|
// .back = std.mem.zeroes(vk.StencilOpState),
|
||||||
|
// .min_depth_bounds = 0.0,
|
||||||
|
// .max_depth_bounds = 1.0,
|
||||||
|
// },
|
||||||
|
.p_dynamic_state = &vk.PipelineDynamicStateCreateInfo{
|
||||||
|
.dynamic_state_count = @intCast(dynamic_states.len),
|
||||||
|
.p_dynamic_states = &dynamic_states,
|
||||||
|
},
|
||||||
|
.p_multisample_state = &vk.PipelineMultisampleStateCreateInfo{
|
||||||
|
.sample_shading_enable = vk.FALSE,
|
||||||
|
.rasterization_samples = .{ .@"1_bit" = true },
|
||||||
|
.min_sample_shading = 1.0,
|
||||||
|
.alpha_to_coverage_enable = vk.FALSE,
|
||||||
|
.alpha_to_one_enable = vk.FALSE,
|
||||||
|
},
|
||||||
|
.p_color_blend_state = &vk.PipelineColorBlendStateCreateInfo{
|
||||||
|
.logic_op_enable = vk.FALSE,
|
||||||
|
.logic_op = .copy,
|
||||||
|
.attachment_count = 0,
|
||||||
|
.blend_constants = [4]f32{ 0.0, 0.0, 0.0, 0.0 },
|
||||||
|
},
|
||||||
|
.stage_count = 2,
|
||||||
|
.p_stages = &.{
|
||||||
|
vk.PipelineShaderStageCreateInfo{
|
||||||
|
.module = vertex_shader_modle,
|
||||||
|
.stage = .{ .vertex_bit = true },
|
||||||
|
.p_name = "main",
|
||||||
|
},
|
||||||
|
vk.PipelineShaderStageCreateInfo{
|
||||||
|
.module = fragment_shader_modle,
|
||||||
|
.stage = .{ .fragment_bit = true },
|
||||||
|
.p_name = "main",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
.subpass = 0,
|
||||||
|
},
|
||||||
|
}, null, &pipelines);
|
||||||
|
break :blk pipelines[0];
|
||||||
|
},
|
||||||
|
.compute => |compute_pipeline| {
|
||||||
|
_ = compute_pipeline; // autofix
|
||||||
|
return error.ComputeNotSupportedYet;
|
||||||
|
// const compute_shader_module = try self.gc.device.createShaderModule(&.{
|
||||||
|
// .code_size = compute_pipeline.compute.source.len,
|
||||||
|
// .p_code = compute_pipeline.compute.source.ptr,
|
||||||
|
// }, null);
|
||||||
|
// defer self.gc.device.destroyShaderModule(compute_shader_module, null);
|
||||||
|
|
||||||
gl.attachShader(prog, compute_shader);
|
// var pipelines = [1]vk.Pipeline{.null_handle};
|
||||||
defer gl.detachShader(prog, compute_shader);
|
// _ = try self.gc.device.createGraphicsPipelines(self.gc.pipeline_cache, 1, &.{
|
||||||
|
// vk.GraphicsPipelineCreateInfo{
|
||||||
gl.linkProgram(prog);
|
// .p_stages = &.{
|
||||||
},
|
// vk.PipelineShaderStageCreateInfo{
|
||||||
}
|
// .module = compute_shader_module,
|
||||||
|
// .stage = .{ .compute_bit = true },
|
||||||
var success: c_int = 0;
|
// .p_name = "main",
|
||||||
gl.getProgramiv(prog, gl.LINK_STATUS, &success);
|
// },
|
||||||
|
// },
|
||||||
if (success == 0) {
|
// .stage_count = 1,
|
||||||
var info_len: gl.GLint = 0;
|
// },
|
||||||
gl.getProgramiv(prog, gl.INFO_LOG_LENGTH, &info_len);
|
// }, null, &pipelines);
|
||||||
if (info_len > 0) {
|
// return pipelines[0];
|
||||||
const info_log = try self.frame_arena.allocSentinel(u8, @intCast(info_len - 1), 0);
|
},
|
||||||
gl.getProgramInfoLog(prog, @intCast(info_log.len), null, info_log);
|
|
||||||
std.log.err("ERROR::PROGRAM::LINK_FAILED\n{s}\n", .{info_log});
|
|
||||||
} else {
|
|
||||||
std.log.err("ERROR::PROGRAM::LINK_FAILED\nNo info log.\n", .{});
|
|
||||||
}
|
}
|
||||||
return error.ProgramLinkFailed;
|
};
|
||||||
}
|
|
||||||
|
|
||||||
var program_length: gl.GLsizei = 0;
|
|
||||||
gl.getProgramiv(prog, gl.PROGRAM_BINARY_LENGTH, &program_length);
|
|
||||||
|
|
||||||
if (program_length > 0) {
|
|
||||||
const program_binary = try self.frame_arena.allocSentinel(u8, @intCast(program_length - 1), 0);
|
|
||||||
var binary_format: gl.GLenum = gl.NONE;
|
|
||||||
var return_len: gl.GLsizei = 0;
|
|
||||||
gl.getProgramBinary(prog, program_length, &return_len, &binary_format, @ptrCast(program_binary.ptr));
|
|
||||||
checkGLError();
|
|
||||||
if (program_length == return_len) {
|
|
||||||
std.log.debug("Program {s} binary:\n{s}\n", .{ asset_manifest.getPath(id), program_binary[0..@intCast(return_len)] });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const loaded_shader_program = LoadedShaderProgram{
|
const loaded_shader_program = LoadedShaderProgram{
|
||||||
.program = prog,
|
.pipeline = pipeline,
|
||||||
.permuted_id = permuted_id,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
{
|
{
|
||||||
self.rw_lock.lock();
|
self.rw_lock.lock();
|
||||||
defer self.rw_lock.unlock();
|
defer self.rw_lock.unlock();
|
||||||
|
|
||||||
try self.loaded_assets.put(self.allocator, permuted_id, .{
|
try self.loaded_assets.put(self.allocator, id, .{
|
||||||
.shaderProgram = loaded_shader_program,
|
.shaderProgram = loaded_shader_program,
|
||||||
});
|
});
|
||||||
try self.modified_times.put(self.allocator, id, data.modified);
|
try self.modified_times.put(self.allocator, id, data.modified);
|
||||||
@ -403,8 +464,7 @@ const NullShader = LoadedShader{
|
|||||||
};
|
};
|
||||||
|
|
||||||
const NullShaderProgram = LoadedShaderProgram{
|
const NullShaderProgram = LoadedShaderProgram{
|
||||||
.program = 0,
|
.pipeline = .null_handle,
|
||||||
.permuted_id = 0,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const NullMesh = LoadedMesh{
|
const NullMesh = LoadedMesh{
|
||||||
@ -693,8 +753,7 @@ const LoadedShader = struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const LoadedShaderProgram = struct {
|
const LoadedShaderProgram = struct {
|
||||||
program: gl.GLuint,
|
pipeline: vk.Pipeline,
|
||||||
permuted_id: AssetId,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const LoadedMesh = struct {
|
pub const LoadedMesh = struct {
|
||||||
@ -1512,7 +1571,12 @@ fn freeAsset(self: *AssetManager, asset: *LoadedAsset) void {
|
|||||||
self.allocator.free(shader.source);
|
self.allocator.free(shader.source);
|
||||||
},
|
},
|
||||||
.shaderProgram => |*program| {
|
.shaderProgram => |*program| {
|
||||||
gl.deleteProgram(program.program);
|
self.gc.queues.graphics.mu.lock();
|
||||||
|
defer self.gc.queues.graphics.mu.unlock();
|
||||||
|
|
||||||
|
self.gc.device.queueWaitIdle(self.gc.queues.graphics.handle) catch @panic("Wait Idle failed");
|
||||||
|
|
||||||
|
self.gc.device.destroyPipeline(program.pipeline, null);
|
||||||
},
|
},
|
||||||
.texture => |*texture| {
|
.texture => |*texture| {
|
||||||
gl.GL_ARB_bindless_texture.makeTextureHandleNonResidentARB(texture.handle);
|
gl.GL_ARB_bindless_texture.makeTextureHandleNonResidentARB(texture.handle);
|
||||||
|
@ -13,20 +13,19 @@ const apis: []const vk.ApiInfo = &.{
|
|||||||
vk.extensions.khr_swapchain,
|
vk.extensions.khr_swapchain,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const Instance = vk.InstanceProxy(apis);
|
||||||
|
pub const Device = vk.DeviceProxy(apis);
|
||||||
|
pub const CommandBuffer = vk.CommandBufferProxy(apis);
|
||||||
|
|
||||||
const BaseDispatch = vk.BaseWrapper(apis);
|
const BaseDispatch = vk.BaseWrapper(apis);
|
||||||
const InstanceDispatch = vk.InstanceWrapper(apis);
|
const InstanceDispatch = vk.InstanceWrapper(apis);
|
||||||
const Instance = vk.InstanceProxy(apis);
|
|
||||||
const Device = vk.DeviceProxy(apis);
|
|
||||||
const DeviceDispatch = Device.Wrapper;
|
const DeviceDispatch = Device.Wrapper;
|
||||||
const CommandBuffer = vk.CommandBufferProxy(apis);
|
|
||||||
|
|
||||||
const device_extensions = [_][:0]const u8{
|
const device_extensions = [_][:0]const u8{
|
||||||
vk.extensions.khr_swapchain.name,
|
vk.extensions.khr_swapchain.name,
|
||||||
};
|
};
|
||||||
const vk_layers = [_][:0]const u8{"VK_LAYER_KHRONOS_validation"};
|
const vk_layers = [_][:0]const u8{"VK_LAYER_KHRONOS_validation"};
|
||||||
|
|
||||||
const MAX_FRAME_LAG = 3;
|
|
||||||
|
|
||||||
allocator: std.mem.Allocator = undefined,
|
allocator: std.mem.Allocator = undefined,
|
||||||
window: *c.SDL_Window = undefined,
|
window: *c.SDL_Window = undefined,
|
||||||
vkb: BaseDispatch = undefined,
|
vkb: BaseDispatch = undefined,
|
||||||
@ -41,19 +40,20 @@ swapchain: vk.SwapchainKHR = .null_handle,
|
|||||||
swapchain_extent: vk.Extent2D = .{ .width = 0, .height = 0 },
|
swapchain_extent: vk.Extent2D = .{ .width = 0, .height = 0 },
|
||||||
swapchain_images: []vk.Image = &.{},
|
swapchain_images: []vk.Image = &.{},
|
||||||
|
|
||||||
// NOTE: TEST
|
pipeline_cache: vk.PipelineCache = .null_handle,
|
||||||
frame: u32 = 0,
|
|
||||||
frame_syncs: [MAX_FRAME_LAG]Sync = [1]Sync{.{}} ** MAX_FRAME_LAG,
|
|
||||||
command_pool: vk.CommandPool = .null_handle,
|
|
||||||
|
|
||||||
const Sync = struct {
|
pub const CommandPool = struct {
|
||||||
acquire_swapchain_image: vk.Semaphore = .null_handle,
|
device: Device,
|
||||||
draw_sema: vk.Semaphore = .null_handle,
|
handle: vk.CommandPool,
|
||||||
draw_fence: vk.Fence = .null_handle,
|
|
||||||
|
|
||||||
pub fn waitForDrawAndReset(self: *Sync, gc: *GraphicsContext) !void {
|
pub fn allocateCommandBuffer(self: *const CommandPool) !CommandBuffer {
|
||||||
_ = try gc.device.waitForFences(1, &.{self.draw_fence}, vk.TRUE, std.math.maxInt(u64));
|
var cmd_bufs = [_]vk.CommandBuffer{.null_handle};
|
||||||
try gc.device.resetFences(1, &.{self.draw_fence});
|
try self.device.allocateCommandBuffers(&.{
|
||||||
|
.command_pool = self.handle,
|
||||||
|
.level = .primary,
|
||||||
|
.command_buffer_count = cmd_bufs.len,
|
||||||
|
}, &cmd_bufs);
|
||||||
|
return CommandBuffer.init(cmd_bufs[0], self.device.wrapper);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -110,7 +110,10 @@ pub fn init(self: *GraphicsContext, allocator: std.mem.Allocator, window: *c.SDL
|
|||||||
const queue_config = try selectQueues(self.instance, self.device_info.physical_device);
|
const queue_config = try selectQueues(self.instance, self.device_info.physical_device);
|
||||||
|
|
||||||
const device_create_config = vk.DeviceCreateInfo{
|
const device_create_config = vk.DeviceCreateInfo{
|
||||||
.p_next = @ptrCast(&vk.PhysicalDeviceSynchronization2Features{ .synchronization_2 = vk.TRUE }),
|
.p_next = &vk.PhysicalDeviceVulkan13Features{
|
||||||
|
.dynamic_rendering = vk.TRUE,
|
||||||
|
.synchronization_2 = vk.TRUE,
|
||||||
|
},
|
||||||
.p_queue_create_infos = &queue_config.queue_create_info,
|
.p_queue_create_infos = &queue_config.queue_create_info,
|
||||||
.queue_create_info_count = queue_config.queue_count,
|
.queue_create_info_count = queue_config.queue_count,
|
||||||
.p_enabled_features = &self.device_info.features,
|
.p_enabled_features = &self.device_info.features,
|
||||||
@ -158,140 +161,42 @@ pub fn init(self: *GraphicsContext, allocator: std.mem.Allocator, window: *c.SDL
|
|||||||
.device_to_host = device_to_host_queue,
|
.device_to_host = device_to_host_queue,
|
||||||
};
|
};
|
||||||
|
|
||||||
for (0..MAX_FRAME_LAG) |i| {
|
self.pipeline_cache = try self.device.createPipelineCache(&.{}, null);
|
||||||
self.frame_syncs[i].acquire_swapchain_image = try self.device.createSemaphore(&.{}, null);
|
|
||||||
self.frame_syncs[i].draw_sema = try self.device.createSemaphore(&.{}, null);
|
|
||||||
self.frame_syncs[i].draw_fence = try self.device.createFence(&.{ .flags = .{ .signaled_bit = true } }, null);
|
|
||||||
}
|
|
||||||
self.command_pool = try self.queues.graphics.createCommandPool(.{});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw(self: *GraphicsContext) !void {
|
pub fn acquireSwapchainImage(self: *GraphicsContext, acuire_semaphore: vk.Semaphore) !u32 {
|
||||||
var cmd_bufs = [_]vk.CommandBuffer{.null_handle};
|
var found = false;
|
||||||
try self.device.allocateCommandBuffers(&.{
|
var swapchain_img: u32 = 0;
|
||||||
.command_pool = self.command_pool,
|
|
||||||
.level = .primary,
|
|
||||||
.command_buffer_count = cmd_bufs.len,
|
|
||||||
}, &cmd_bufs);
|
|
||||||
const test_cmd_buf = CommandBuffer.init(cmd_bufs[0], &self.vkd);
|
|
||||||
|
|
||||||
const sync = &self.frame_syncs[self.frame];
|
try self.maybeResizeSwapchain();
|
||||||
|
|
||||||
try sync.waitForDrawAndReset(self);
|
while (!found) {
|
||||||
|
const acquire_result = try self.device.acquireNextImageKHR(self.swapchain, std.math.maxInt(u64), acuire_semaphore, .null_handle);
|
||||||
|
|
||||||
// Move this out into a separate func
|
switch (acquire_result.result) {
|
||||||
const swapchain_image_index: u32 = blk: {
|
.success, .suboptimal_khr => {
|
||||||
var found = false;
|
swapchain_img = acquire_result.image_index;
|
||||||
var swapchain_img: u32 = 0;
|
found = true;
|
||||||
|
},
|
||||||
try self.maybeResizeSwapchain();
|
.error_out_of_date_khr => {
|
||||||
|
// TODO: resize swapchain
|
||||||
while (!found) {
|
std.debug.print("Out of date swapchain\n", .{});
|
||||||
const acquire_result = try self.device.acquireNextImageKHR(self.swapchain, std.math.maxInt(u64), sync.acquire_swapchain_image, .null_handle);
|
try self.maybeResizeSwapchain();
|
||||||
|
},
|
||||||
switch (acquire_result.result) {
|
.error_surface_lost_khr => {
|
||||||
.success, .suboptimal_khr => {
|
// TODO: recreate surface
|
||||||
swapchain_img = acquire_result.image_index;
|
return error.SurfaceLost;
|
||||||
found = true;
|
},
|
||||||
},
|
.not_ready => return error.SwapchainImageNotReady,
|
||||||
.error_out_of_date_khr => {
|
.timeout => return error.SwapchainImageTimeout,
|
||||||
// TODO: resize swapchain
|
else => {
|
||||||
std.debug.print("Out of date swapchain\n", .{});
|
std.debug.print("Unexpected value: {}\n", .{acquire_result.result});
|
||||||
try self.maybeResizeSwapchain();
|
@panic("Unexpected");
|
||||||
},
|
},
|
||||||
.error_surface_lost_khr => {
|
|
||||||
// TODO: recreate surface
|
|
||||||
return error.SurfaceLost;
|
|
||||||
},
|
|
||||||
.not_ready => return error.SwapchainImageNotReady,
|
|
||||||
.timeout => return error.SwapchainImageTimeout,
|
|
||||||
else => {
|
|
||||||
std.debug.print("Unexpected value: {}\n", .{acquire_result.result});
|
|
||||||
@panic("Unexpected");
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break :blk swapchain_img;
|
|
||||||
};
|
|
||||||
|
|
||||||
const current_image = self.swapchain_images[swapchain_image_index];
|
|
||||||
|
|
||||||
try test_cmd_buf.beginCommandBuffer(&.{});
|
|
||||||
{
|
|
||||||
{
|
|
||||||
const img_barrier = vk.ImageMemoryBarrier2{
|
|
||||||
.image = current_image,
|
|
||||||
.old_layout = .undefined,
|
|
||||||
.new_layout = .transfer_dst_optimal,
|
|
||||||
.src_access_mask = .{},
|
|
||||||
.dst_access_mask = .{},
|
|
||||||
.src_queue_family_index = self.queues.graphics.family,
|
|
||||||
.dst_queue_family_index = self.queues.graphics.family,
|
|
||||||
.subresource_range = .{
|
|
||||||
.aspect_mask = .{ .color_bit = true },
|
|
||||||
.base_array_layer = 0,
|
|
||||||
.base_mip_level = 0,
|
|
||||||
.layer_count = 1,
|
|
||||||
.level_count = 1,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
test_cmd_buf.pipelineBarrier2(&.{
|
|
||||||
.p_image_memory_barriers = &.{img_barrier},
|
|
||||||
.image_memory_barrier_count = 1,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
test_cmd_buf.clearColorImage(current_image, .transfer_dst_optimal, &.{ .float_32 = .{ 0.8, 0.7, 0.6, 1.0 } }, 1, &.{.{
|
|
||||||
.aspect_mask = .{ .color_bit = true },
|
|
||||||
.base_array_layer = 0,
|
|
||||||
.base_mip_level = 0,
|
|
||||||
.layer_count = 1,
|
|
||||||
.level_count = 1,
|
|
||||||
}});
|
|
||||||
{
|
|
||||||
const img_barrier = vk.ImageMemoryBarrier2{
|
|
||||||
.image = current_image,
|
|
||||||
.old_layout = .transfer_dst_optimal,
|
|
||||||
.new_layout = .present_src_khr,
|
|
||||||
.src_access_mask = .{},
|
|
||||||
.dst_access_mask = .{},
|
|
||||||
.src_queue_family_index = self.queues.graphics.family,
|
|
||||||
.dst_queue_family_index = self.queues.graphics.family,
|
|
||||||
.subresource_range = .{
|
|
||||||
.aspect_mask = .{ .color_bit = true },
|
|
||||||
.base_array_layer = 0,
|
|
||||||
.base_mip_level = 0,
|
|
||||||
.layer_count = 1,
|
|
||||||
.level_count = 1,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
test_cmd_buf.pipelineBarrier2(&.{
|
|
||||||
.p_image_memory_barriers = &.{img_barrier},
|
|
||||||
.image_memory_barrier_count = 1,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
try test_cmd_buf.endCommandBuffer();
|
|
||||||
|
|
||||||
try self.queues.graphics.submit(
|
return swapchain_img;
|
||||||
&SubmitInfo{
|
|
||||||
.wait_semaphores = &.{sync.acquire_swapchain_image},
|
|
||||||
.wait_dst_stage_mask = &.{.{ .transfer_bit = true }},
|
|
||||||
.command_buffers = &.{test_cmd_buf.handle},
|
|
||||||
.signal_semaphores = &.{sync.draw_sema},
|
|
||||||
},
|
|
||||||
sync.draw_fence,
|
|
||||||
);
|
|
||||||
|
|
||||||
_ = try self.device.queuePresentKHR(self.queues.graphics.handle, &.{
|
|
||||||
.swapchain_count = 1,
|
|
||||||
.wait_semaphore_count = 1,
|
|
||||||
.p_wait_semaphores = &.{sync.draw_sema},
|
|
||||||
.p_swapchains = &.{self.swapchain},
|
|
||||||
.p_image_indices = &.{swapchain_image_index},
|
|
||||||
});
|
|
||||||
|
|
||||||
self.frame = (self.frame + 1) % MAX_FRAME_LAG;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn maybeResizeSwapchain(self: *GraphicsContext) !void {
|
fn maybeResizeSwapchain(self: *GraphicsContext) !void {
|
||||||
@ -353,11 +258,14 @@ pub const QueueInstance = struct {
|
|||||||
handle: vk.Queue,
|
handle: vk.Queue,
|
||||||
family: u32,
|
family: u32,
|
||||||
|
|
||||||
pub fn createCommandPool(self: *Self, flags: vk.CommandPoolCreateFlags) !vk.CommandPool {
|
pub fn createCommandPool(self: *Self, flags: vk.CommandPoolCreateFlags) !CommandPool {
|
||||||
return self.device.createCommandPool(&.{
|
return .{
|
||||||
.flags = flags,
|
.handle = try self.device.createCommandPool(&.{
|
||||||
.queue_family_index = self.family,
|
.flags = flags,
|
||||||
}, null);
|
.queue_family_index = self.family,
|
||||||
|
}, null),
|
||||||
|
.device = self.device,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn submit(self: *Self, info: *const SubmitInfo, fence: vk.Fence) Device.QueueSubmitError!void {
|
pub fn submit(self: *Self, info: *const SubmitInfo, fence: vk.Fence) Device.QueueSubmitError!void {
|
||||||
|
181
src/Render2.zig
Normal file
181
src/Render2.zig
Normal file
@ -0,0 +1,181 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
const AssetManager = @import("AssetManager.zig");
|
||||||
|
const GraphicsContext = @import("GraphicsContext.zig");
|
||||||
|
const vk = @import("vk");
|
||||||
|
const a = @import("asset_manifest");
|
||||||
|
|
||||||
|
const Render2 = @This();
|
||||||
|
|
||||||
|
const MAX_FRAME_LAG = 3;
|
||||||
|
|
||||||
|
assetman: *AssetManager,
|
||||||
|
gc: *GraphicsContext,
|
||||||
|
command_pool: GraphicsContext.CommandPool,
|
||||||
|
|
||||||
|
// NOTE: TEST
|
||||||
|
frame: u32 = 0,
|
||||||
|
frame_syncs: [MAX_FRAME_LAG]Sync = [1]Sync{.{}} ** MAX_FRAME_LAG,
|
||||||
|
|
||||||
|
pub fn init(assetman: *AssetManager, gc: *GraphicsContext) !Render2 {
|
||||||
|
var self = Render2{
|
||||||
|
.assetman = assetman,
|
||||||
|
.gc = gc,
|
||||||
|
.command_pool = try gc.queues.graphics.createCommandPool(.{}),
|
||||||
|
};
|
||||||
|
|
||||||
|
// NOTE: TEST
|
||||||
|
for (0..MAX_FRAME_LAG) |i| {
|
||||||
|
self.frame_syncs[i].acquire_swapchain_image = try self.gc.device.createSemaphore(&.{}, null);
|
||||||
|
self.frame_syncs[i].draw_sema = try self.gc.device.createSemaphore(&.{}, null);
|
||||||
|
self.frame_syncs[i].draw_fence = try self.gc.device.createFence(&.{ .flags = .{ .signaled_bit = true } }, null);
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn draw(self: *Render2) !void {
|
||||||
|
const sync = &self.frame_syncs[self.frame];
|
||||||
|
|
||||||
|
try sync.waitForDrawAndReset(self.gc.device);
|
||||||
|
|
||||||
|
// Move this out into a separate func
|
||||||
|
const swapchain_image_index: u32 = try self.gc.acquireSwapchainImage(sync.acquire_swapchain_image);
|
||||||
|
|
||||||
|
const current_image = self.gc.swapchain_images[swapchain_image_index];
|
||||||
|
const current_image_view = try self.gc.device.createImageView(&.{
|
||||||
|
.components = .{ .r = .r, .g = .g, .b = .b, .a = .a },
|
||||||
|
.format = .r8g8b8a8_unorm,
|
||||||
|
.view_type = .@"2d",
|
||||||
|
.subresource_range = .{
|
||||||
|
.aspect_mask = .{ .color_bit = true },
|
||||||
|
.base_array_layer = 0,
|
||||||
|
.base_mip_level = 0,
|
||||||
|
.layer_count = 1,
|
||||||
|
.level_count = 1,
|
||||||
|
},
|
||||||
|
.image = current_image,
|
||||||
|
}, null);
|
||||||
|
defer self.gc.device.destroyImageView(current_image_view, null);
|
||||||
|
|
||||||
|
const cmds = try self.command_pool.allocateCommandBuffer();
|
||||||
|
|
||||||
|
try cmds.beginCommandBuffer(&.{});
|
||||||
|
{
|
||||||
|
{
|
||||||
|
const img_barrier = vk.ImageMemoryBarrier2{
|
||||||
|
.image = current_image,
|
||||||
|
.old_layout = .undefined,
|
||||||
|
.new_layout = .color_attachment_optimal,
|
||||||
|
.src_access_mask = .{},
|
||||||
|
.dst_access_mask = .{ .color_attachment_write_bit = true },
|
||||||
|
.dst_stage_mask = .{ .color_attachment_output_bit = true },
|
||||||
|
.src_queue_family_index = self.gc.queues.graphics.family,
|
||||||
|
.dst_queue_family_index = self.gc.queues.graphics.family,
|
||||||
|
.subresource_range = .{
|
||||||
|
.aspect_mask = .{ .color_bit = true },
|
||||||
|
.base_array_layer = 0,
|
||||||
|
.base_mip_level = 0,
|
||||||
|
.layer_count = 1,
|
||||||
|
.level_count = 1,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
cmds.pipelineBarrier2(&.{
|
||||||
|
.p_image_memory_barriers = &.{img_barrier},
|
||||||
|
.image_memory_barrier_count = 1,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
cmds.beginRendering(&.{
|
||||||
|
.render_area = vk.Rect2D{ .offset = .{ .x = 0, .y = 0 }, .extent = self.gc.swapchain_extent },
|
||||||
|
.layer_count = 1,
|
||||||
|
.view_mask = 0,
|
||||||
|
.color_attachment_count = 1,
|
||||||
|
.p_color_attachments = &.{
|
||||||
|
vk.RenderingAttachmentInfo{
|
||||||
|
.clear_value = .{ .color = .{ .float_32 = .{ 0.8, 0.7, 0.6, 1.0 } } },
|
||||||
|
.load_op = .clear,
|
||||||
|
.store_op = .store,
|
||||||
|
.image_layout = .color_attachment_optimal,
|
||||||
|
.image_view = current_image_view,
|
||||||
|
.resolve_image_layout = .color_attachment_optimal,
|
||||||
|
.resolve_mode = .{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
defer cmds.endRendering();
|
||||||
|
|
||||||
|
cmds.bindPipeline(.graphics, self.assetman.resolveShaderProgram(a.ShaderPrograms.shaders.triangle).pipeline);
|
||||||
|
|
||||||
|
cmds.setViewportWithCount(1, &.{vk.Viewport{
|
||||||
|
.x = 0,
|
||||||
|
.y = 0,
|
||||||
|
.width = @floatFromInt(self.gc.swapchain_extent.width),
|
||||||
|
.height = @floatFromInt(self.gc.swapchain_extent.height),
|
||||||
|
.min_depth = 0,
|
||||||
|
.max_depth = 1,
|
||||||
|
}});
|
||||||
|
cmds.setScissorWithCount(1, &.{vk.Rect2D{
|
||||||
|
.offset = .{ .x = 0, .y = 0 },
|
||||||
|
.extent = self.gc.swapchain_extent,
|
||||||
|
}});
|
||||||
|
|
||||||
|
cmds.draw(3, 1, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const img_barrier = vk.ImageMemoryBarrier2{
|
||||||
|
.image = current_image,
|
||||||
|
.old_layout = .color_attachment_optimal,
|
||||||
|
.new_layout = .present_src_khr,
|
||||||
|
.src_access_mask = .{ .color_attachment_write_bit = true },
|
||||||
|
.dst_access_mask = .{},
|
||||||
|
.src_stage_mask = .{ .color_attachment_output_bit = true },
|
||||||
|
.src_queue_family_index = self.gc.queues.graphics.family,
|
||||||
|
.dst_queue_family_index = self.gc.queues.graphics.family,
|
||||||
|
.subresource_range = .{
|
||||||
|
.aspect_mask = .{ .color_bit = true },
|
||||||
|
.base_array_layer = 0,
|
||||||
|
.base_mip_level = 0,
|
||||||
|
.layer_count = 1,
|
||||||
|
.level_count = 1,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
cmds.pipelineBarrier2(&.{
|
||||||
|
.p_image_memory_barriers = &.{img_barrier},
|
||||||
|
.image_memory_barrier_count = 1,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try cmds.endCommandBuffer();
|
||||||
|
|
||||||
|
try self.gc.queues.graphics.submit(
|
||||||
|
&GraphicsContext.SubmitInfo{
|
||||||
|
.wait_semaphores = &.{sync.acquire_swapchain_image},
|
||||||
|
.wait_dst_stage_mask = &.{.{ .transfer_bit = true }},
|
||||||
|
.command_buffers = &.{cmds.handle},
|
||||||
|
.signal_semaphores = &.{sync.draw_sema},
|
||||||
|
},
|
||||||
|
sync.draw_fence,
|
||||||
|
);
|
||||||
|
|
||||||
|
_ = try self.gc.device.queuePresentKHR(self.gc.queues.graphics.handle, &.{
|
||||||
|
.swapchain_count = 1,
|
||||||
|
.wait_semaphore_count = 1,
|
||||||
|
.p_wait_semaphores = &.{sync.draw_sema},
|
||||||
|
.p_swapchains = &.{self.gc.swapchain},
|
||||||
|
.p_image_indices = &.{swapchain_image_index},
|
||||||
|
});
|
||||||
|
|
||||||
|
self.frame = (self.frame + 1) % MAX_FRAME_LAG;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Sync = struct {
|
||||||
|
acquire_swapchain_image: vk.Semaphore = .null_handle,
|
||||||
|
draw_sema: vk.Semaphore = .null_handle,
|
||||||
|
draw_fence: vk.Fence = .null_handle,
|
||||||
|
|
||||||
|
pub fn waitForDrawAndReset(self: *Sync, device: GraphicsContext.Device) !void {
|
||||||
|
_ = try device.waitForFences(1, &.{self.draw_fence}, vk.TRUE, std.math.maxInt(u64));
|
||||||
|
try device.resetFences(1, &.{self.draw_fence});
|
||||||
|
}
|
||||||
|
};
|
@ -153,13 +153,16 @@ pub const ShaderProgram = union(ShaderProgramPipelineType) {
|
|||||||
if (!serializer.write) {
|
if (!serializer.write) {
|
||||||
self.* = .{ .graphics = undefined };
|
self.* = .{ .graphics = undefined };
|
||||||
}
|
}
|
||||||
|
try serializer.skipAlign(4);
|
||||||
try serializer.serializeByteSlice(&self.graphics.vertex.source);
|
try serializer.serializeByteSlice(&self.graphics.vertex.source);
|
||||||
|
try serializer.skipAlign(4);
|
||||||
try serializer.serializeByteSlice(&self.graphics.fragment.source);
|
try serializer.serializeByteSlice(&self.graphics.fragment.source);
|
||||||
},
|
},
|
||||||
.compute => {
|
.compute => {
|
||||||
if (!serializer.write) {
|
if (!serializer.write) {
|
||||||
self.* = .{ .compute = undefined };
|
self.* = .{ .compute = undefined };
|
||||||
}
|
}
|
||||||
|
try serializer.skipAlign(4);
|
||||||
try serializer.serializeByteSlice(&self.compute.compute.source);
|
try serializer.serializeByteSlice(&self.compute.compute.source);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -217,11 +220,23 @@ pub const Serializer = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn skipAlign(self: *Serializer, alignment: u64) !void {
|
||||||
|
const pos = try self.stream.getPos();
|
||||||
|
const new_pos = std.mem.alignForward(u64, pos, alignment);
|
||||||
|
try self.stream.seekTo(new_pos);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn serializeBytes(self: *Serializer, data: *[]u8) !void {
|
pub fn serializeBytes(self: *Serializer, data: *[]u8) !void {
|
||||||
if (self.write) {
|
if (self.write) {
|
||||||
_ = try self.stream.write(data.*);
|
_ = try self.stream.write(data.*);
|
||||||
} else {
|
} else {
|
||||||
_ = try self.stream.read(data.*);
|
switch (self.stream) {
|
||||||
|
.buffer => |*buf| {
|
||||||
|
data.* = buf.buffer[buf.pos .. buf.pos + data.len];
|
||||||
|
buf.seekBy(@intCast(data.len)) catch @panic("INVALID READ STREAM SIZE");
|
||||||
|
},
|
||||||
|
else => @panic("UNSUPPORTED READ STREAM"),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ const c = @import("sdl.zig");
|
|||||||
// const gl = @import("gl.zig");
|
// const gl = @import("gl.zig");
|
||||||
const AssetManager = @import("AssetManager.zig");
|
const AssetManager = @import("AssetManager.zig");
|
||||||
const Render = @import("Render.zig");
|
const Render = @import("Render.zig");
|
||||||
|
const Render2 = @import("Render2.zig");
|
||||||
const formats = @import("formats.zig");
|
const formats = @import("formats.zig");
|
||||||
const za = @import("zalgebra");
|
const za = @import("zalgebra");
|
||||||
const Vec2 = za.Vec2;
|
const Vec2 = za.Vec2;
|
||||||
@ -173,7 +174,8 @@ export fn game_init(global_allocator: *std.mem.Allocator) void {
|
|||||||
globals.g_mem.* = .{
|
globals.g_mem.* = .{
|
||||||
.global_allocator = global_allocator.*,
|
.global_allocator = global_allocator.*,
|
||||||
.frame_fba = std.heap.FixedBufferAllocator.init(frame_arena_buffer),
|
.frame_fba = std.heap.FixedBufferAllocator.init(frame_arena_buffer),
|
||||||
.assetman = AssetManager.init(global_allocator.*, globals.g_mem.frame_fba.allocator()),
|
.assetman = AssetManager.init(global_allocator.*, globals.g_mem.frame_fba.allocator(), &globals.g_init.gc),
|
||||||
|
.render2 = Render2.init(&globals.g_mem.assetman, &globals.g_init.gc) catch @panic("OOM"),
|
||||||
// .render = Render.init(global_allocator.*, globals.g_mem.frame_fba.allocator(), &globals.g_mem.assetman),
|
// .render = Render.init(global_allocator.*, globals.g_mem.frame_fba.allocator(), &globals.g_mem.assetman),
|
||||||
.world = .{ .frame_arena = globals.g_mem.frame_fba.allocator() },
|
.world = .{ .frame_arena = globals.g_mem.frame_fba.allocator() },
|
||||||
};
|
};
|
||||||
@ -461,7 +463,7 @@ export fn game_update() bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ginit.gc.draw() catch @panic("draw error");
|
gmem.render2.draw() catch @panic("RENDER ERROR");
|
||||||
|
|
||||||
// Render
|
// Render
|
||||||
if (false) {
|
if (false) {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const c = @import("sdl.zig");
|
const c = @import("sdl.zig");
|
||||||
const Render = @import("Render.zig");
|
const Render = @import("Render.zig");
|
||||||
|
const Render2 = @import("Render2.zig");
|
||||||
const AssetManager = @import("AssetManager.zig");
|
const AssetManager = @import("AssetManager.zig");
|
||||||
const World = @import("entity.zig").World;
|
const World = @import("entity.zig").World;
|
||||||
const GraphicsContext = @import("GraphicsContext.zig");
|
const GraphicsContext = @import("GraphicsContext.zig");
|
||||||
@ -36,6 +37,7 @@ pub const GameMemory = struct {
|
|||||||
frame_fba: std.heap.FixedBufferAllocator,
|
frame_fba: std.heap.FixedBufferAllocator,
|
||||||
assetman: AssetManager,
|
assetman: AssetManager,
|
||||||
render: Render = undefined,
|
render: Render = undefined,
|
||||||
|
render2: Render2,
|
||||||
performance_frequency: u64 = 0,
|
performance_frequency: u64 = 0,
|
||||||
last_frame_time: u64 = 0,
|
last_frame_time: u64 = 0,
|
||||||
delta_time: f32 = 0.0000001,
|
delta_time: f32 = 0.0000001,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user