From b470e424fb2ecd7f697fa30fb79332a8b05cee0b Mon Sep 17 00:00:00 2001 From: IntegratedQuantum Date: Sun, 16 Aug 2026 09:03:52 +0200 Subject: [PATCH 01/16] Make an options struct for the pipeline vulkan info --- src/block_entity.zig | 9 +-- src/graphics.zig | 63 ++++++++++--------- src/graphics/pipelines.zig | 31 +++++---- src/gui/GuiWindow.zig | 18 +++--- src/gui/components/Button.zig | 9 +-- src/gui/windows/crosshair.zig | 23 +++---- src/gui/windows/performance_graph.zig | 9 +-- src/itemdrop.zig | 9 +-- src/particles.zig | 9 +-- src/renderer.zig | 90 +++++++++++++++------------ src/renderer/chunk_meshing.zig | 60 +++++++++--------- src/systems/modelRenderer.zig | 9 +-- 12 files changed, 189 insertions(+), 150 deletions(-) diff --git a/src/block_entity.zig b/src/block_entity.zig index 18962f71ed..02f0c25b57 100644 --- a/src/block_entity.zig +++ b/src/block_entity.zig @@ -338,10 +338,11 @@ pub const BlockEntityTypes = struct { // MARK: BlockEntityTypes "", &uniforms, graphics.VertexArray.EmptyVertex, - &.{}, - .{}, - .{.depthTest = true, .depthCompare = .equal, .depthWrite = false}, - .{.attachments = &.{.alphaBlending}, .formats = &.{.world}}, + .{ + .rasterState = .{}, + .depthStencilState = .{.depthTest = true, .depthCompare = .equal, .depthWrite = false}, + .blendState = .{.attachments = &.{.alphaBlending}, .formats = &.{.world}}, + }, ); } } diff --git a/src/graphics.zig b/src/graphics.zig index 6bb541961e..a6f5803ec1 100644 --- a/src/graphics.zig +++ b/src/graphics.zig @@ -157,10 +157,11 @@ pub const draw = struct { // MARK: draw "", &rectUniforms, SimpleVertex2D, - &.{}, - .{.cullMode = .none}, - .{.depthTest = false, .depthWrite = false}, - .{.attachments = &.{.alphaBlending}, .formats = &.{.swapChain}}, + .{ + .rasterState = .{.cullMode = .none}, + .depthStencilState = .{.depthTest = false, .depthWrite = false}, + .blendState = .{.attachments = &.{.alphaBlending}, .formats = &.{.swapChain}}, + }, ); const rawData = [_]SimpleVertex2D{ .{.pos = .{0, 0}}, @@ -227,10 +228,11 @@ pub const draw = struct { // MARK: draw "", &rectBorderUniforms, RectBorderVertex, - &.{}, - .{.cullMode = .none}, - .{.depthTest = false, .depthWrite = false}, - .{.attachments = &.{.alphaBlending}, .formats = &.{.swapChain}}, + .{ + .rasterState = .{.cullMode = .none}, + .depthStencilState = .{.depthTest = false, .depthWrite = false}, + .blendState = .{.attachments = &.{.alphaBlending}, .formats = &.{.swapChain}}, + }, ); const rawData = [_]RectBorderVertex{ .{.pos = .{0, 0, 0, 0}}, @@ -294,10 +296,11 @@ pub const draw = struct { // MARK: draw "", &lineUniforms, SimpleVertex2D, - &.{}, - .{.cullMode = .none}, - .{.depthTest = false, .depthWrite = false}, - .{.attachments = &.{.alphaBlending}, .formats = &.{.swapChain}}, + .{ + .rasterState = .{.cullMode = .none}, + .depthStencilState = .{.depthTest = false, .depthWrite = false}, + .blendState = .{.attachments = &.{.alphaBlending}, .formats = &.{.swapChain}}, + }, ); const rawData = [_]SimpleVertex2D{ .{.pos = .{0, 0}}, @@ -371,10 +374,11 @@ pub const draw = struct { // MARK: draw "", &circleUniforms, SimpleVertex2D, - &.{}, - .{.cullMode = .none}, - .{.depthTest = false, .depthWrite = false}, - .{.attachments = &.{.alphaBlending}, .formats = &.{.swapChain}}, + .{ + .rasterState = .{.cullMode = .none}, + .depthStencilState = .{.depthTest = false, .depthWrite = false}, + .blendState = .{.attachments = &.{.alphaBlending}, .formats = &.{.swapChain}}, + }, ); const rawData = [_]SimpleVertex2D{ .{.pos = .{-1, -1}}, @@ -430,10 +434,11 @@ pub const draw = struct { // MARK: draw "", &imageUniforms, SimpleVertex2D, - &.{}, - .{.cullMode = .none}, - .{.depthTest = false, .depthWrite = false}, - .{.attachments = &.{.alphaBlending}, .formats = &.{.swapChain}}, + .{ + .rasterState = .{.cullMode = .none}, + .depthStencilState = .{.depthTest = false, .depthWrite = false}, + .blendState = .{.attachments = &.{.alphaBlending}, .formats = &.{.swapChain}}, + }, ); } @@ -1165,10 +1170,11 @@ const TextRendering = struct { // MARK: TextRendering "", &uniforms, draw.SimpleVertex2D, - &.{}, - .{.cullMode = .none}, - .{.depthTest = false, .depthWrite = false}, - .{.attachments = &.{.alphaBlending}, .formats = &.{.{.custom = c.VK_FORMAT_R8_UNORM}}}, + .{ + .rasterState = .{.cullMode = .none}, + .depthStencilState = .{.depthTest = false, .depthWrite = false}, + .blendState = .{.attachments = &.{.alphaBlending}, .formats = &.{.{.custom = c.VK_FORMAT_R8_UNORM}}}, + }, ); pipeline.bind(null); errdefer pipeline.deinit(); @@ -2209,10 +2215,11 @@ const block_texture = struct { // MARK: block_texture "", &uniforms, VertexArray.EmptyVertex, - &.{}, - .{.cullMode = .none}, - .{.depthTest = false, .depthWrite = false}, - .{.attachments = &.{.noBlending}, .formats = &.{.{.custom = c.VK_FORMAT_R8G8B8A8_UNORM}}}, + .{ + .rasterState = .{.cullMode = .none}, + .depthStencilState = .{.depthTest = false, .depthWrite = false}, + .blendState = .{.attachments = &.{.noBlending}, .formats = &.{.{.custom = c.VK_FORMAT_R8G8B8A8_UNORM}}}, + }, ); depthTexture = .init(); depthTexture.bind(); diff --git a/src/graphics/pipelines.zig b/src/graphics/pipelines.zig index cb9a1462c7..daed4184b4 100644 --- a/src/graphics/pipelines.zig +++ b/src/graphics/pipelines.zig @@ -616,7 +616,7 @@ pub const Pipeline = struct { // MARK: Pipeline descriptorSetLayout: c.VkDescriptorSetLayout = undefined, graphicsPipeline: c.VkPipeline = undefined, - fn initVulkan(self: *Pipeline, vertexPath: []const u8, fragmentPath: []const u8, defines: []const u8, VertexType: type, bindings: []const DescriptorSetLayoutBinding) !void { + fn initVulkan(self: *Pipeline, vertexPath: []const u8, fragmentPath: []const u8, defines: []const u8, VertexType: type, options: Options) !void { const vertModule = try Shader.createShaderModule(vertexPath, defines, .vert); defer c.vkDestroyShaderModule(vulkan.device, vertModule, null); const fragModule = try Shader.createShaderModule(fragmentPath, defines, .frag); @@ -684,8 +684,8 @@ pub const Pipeline = struct { // MARK: Pipeline const descriptorSetLayoutInfo = c.VkDescriptorSetLayoutCreateInfo{ .sType = c.VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, - .bindingCount = @intCast(bindings.len), - .pBindings = @ptrCast(bindings.ptr), + .bindingCount = @intCast(options.bindings.len), + .pBindings = @ptrCast(options.bindings.ptr), }; try vulkan.checkResultErr(c.vkCreateDescriptorSetLayout(vulkan.device, &descriptorSetLayoutInfo, null, &self.descriptorSetLayout)); errdefer c.vkDestroyDescriptorSetLayout(vulkan.device, self.descriptorSetLayout, null); @@ -736,20 +736,27 @@ pub const Pipeline = struct { // MARK: Pipeline self.vulkanCreationSuccessful = true; } - pub fn init(vertexPath: []const u8, fragmentPath: []const u8, defines: []const u8, uniformStruct: anytype, VertexType: type, bindings: []const DescriptorSetLayoutBinding, rasterState: RasterizationState, depthStencilState: DepthStencilState, blendState: ColorBlendState) Pipeline { - std.debug.assert(depthStencilState.depthBoundsTest == null); // Only available in Vulkan 1.3 - std.debug.assert(depthStencilState.stencilTest == null); // TODO: Not yet implemented - std.debug.assert(rasterState.lineWidth <= 1); // Larger values are poorly supported among drivers - std.debug.assert(blendState.logicOp == null); // TODO: Not yet implemented + const Options = struct { + rasterState: RasterizationState, + depthStencilState: DepthStencilState, + blendState: ColorBlendState, + bindings: []const DescriptorSetLayoutBinding = &.{}, + }; + + pub fn init(vertexPath: []const u8, fragmentPath: []const u8, defines: []const u8, uniformStruct: anytype, VertexType: type, options: Options) Pipeline { + std.debug.assert(options.depthStencilState.depthBoundsTest == null); // Only available in Vulkan 1.3 + std.debug.assert(options.depthStencilState.stencilTest == null); // TODO: Not yet implemented + std.debug.assert(options.rasterState.lineWidth <= 1); // Larger values are poorly supported among drivers + std.debug.assert(options.blendState.logicOp == null); // TODO: Not yet implemented var self: Pipeline = .{ .shader = .init(vertexPath, fragmentPath, defines, uniformStruct), - .rasterState = rasterState, + .rasterState = options.rasterState, .multisampleState = .{}, // TODO: Not implemented - .depthStencilState = depthStencilState, - .blendState = blendState, + .depthStencilState = options.depthStencilState, + .blendState = options.blendState, }; if (main.settings.launchConfig.vulkanTestingMode) { - self.initVulkan(vertexPath, fragmentPath, defines, VertexType, bindings) catch |err| { + self.initVulkan(vertexPath, fragmentPath, defines, VertexType, options) catch |err| { std.log.err("Vulkan pipeline creation for paths {s} {s} failed with error {s}", .{vertexPath, fragmentPath, @errorName(err)}); }; } diff --git a/src/gui/GuiWindow.zig b/src/gui/GuiWindow.zig index f759ea917d..4b10bf4e64 100644 --- a/src/gui/GuiWindow.zig +++ b/src/gui/GuiWindow.zig @@ -108,10 +108,11 @@ pub fn globalInit() void { "", &windowUniforms, graphics.draw.SimpleVertex2D, - &.{}, - .{.cullMode = .none}, - .{.depthTest = false, .depthWrite = false}, - .{.attachments = &.{.alphaBlending}, .formats = &.{.swapChain}}, + .{ + .rasterState = .{.cullMode = .none}, + .depthStencilState = .{.depthTest = false, .depthWrite = false}, + .blendState = .{.attachments = &.{.alphaBlending}, .formats = &.{.swapChain}}, + }, ); borderPipeline = graphics.Pipeline.init( "assets/cubyz/shaders/ui/window_border.vert", @@ -119,10 +120,11 @@ pub fn globalInit() void { "", &borderUniforms, graphics.draw.SimpleVertex2D, - &.{}, - .{.cullMode = .none}, - .{.depthTest = false, .depthWrite = false}, - .{.attachments = &.{.alphaBlending}, .formats = &.{.swapChain}}, + .{ + .rasterState = .{.cullMode = .none}, + .depthStencilState = .{.depthTest = false, .depthWrite = false}, + .blendState = .{.attachments = &.{.alphaBlending}, .formats = &.{.swapChain}}, + }, ); backgroundTexture = Texture.initFromFile("assets/cubyz/ui/window_background.png"); diff --git a/src/gui/components/Button.zig b/src/gui/components/Button.zig index 5d3d601196..d977f8181b 100644 --- a/src/gui/components/Button.zig +++ b/src/gui/components/Button.zig @@ -67,10 +67,11 @@ pub fn globalInit() void { "", &buttonUniforms, graphics.draw.SimpleVertex2D, - &.{}, - .{.cullMode = .none}, - .{.depthTest = false, .depthWrite = false}, - .{.attachments = &.{.alphaBlending}, .formats = &.{.swapChain}}, + .{ + .rasterState = .{.cullMode = .none}, + .depthStencilState = .{.depthTest = false, .depthWrite = false}, + .blendState = .{.attachments = &.{.alphaBlending}, .formats = &.{.swapChain}}, + }, ); normalTextures = Textures.init("assets/cubyz/ui/button"); hoveredTextures = Textures.init("assets/cubyz/ui/button_hovered"); diff --git a/src/gui/windows/crosshair.zig b/src/gui/windows/crosshair.zig index 1b049b1d78..997909490e 100644 --- a/src/gui/windows/crosshair.zig +++ b/src/gui/windows/crosshair.zig @@ -39,17 +39,18 @@ pub fn init() void { "", &uniforms, graphics.draw.SimpleVertex2D, - &.{}, - .{.cullMode = .none}, - .{.depthTest = false, .depthWrite = false}, - .{.attachments = &.{.{ - .srcColorBlendFactor = .one, - .dstColorBlendFactor = .one, - .colorBlendOp = .subtract, - .srcAlphaBlendFactor = .one, - .dstAlphaBlendFactor = .one, - .alphaBlendOp = .subtract, - }}, .formats = &.{.swapChain}}, + .{ + .rasterState = .{.cullMode = .none}, + .depthStencilState = .{.depthTest = false, .depthWrite = false}, + .blendState = .{.attachments = &.{.{ + .srcColorBlendFactor = .one, + .dstColorBlendFactor = .one, + .colorBlendOp = .subtract, + .srcAlphaBlendFactor = .one, + .dstAlphaBlendFactor = .one, + .alphaBlendOp = .subtract, + }}, .formats = &.{.swapChain}}, + }, ); texture = Texture.initFromFile("assets/cubyz/ui/hud/crosshair.png"); } diff --git a/src/gui/windows/performance_graph.zig b/src/gui/windows/performance_graph.zig index 208d45a9c3..cf0b5e7e3d 100644 --- a/src/gui/windows/performance_graph.zig +++ b/src/gui/windows/performance_graph.zig @@ -49,10 +49,11 @@ pub fn init() void { "", &uniforms, graphics.VertexArray.EmptyVertex, - &.{}, - .{.cullMode = .none}, - .{.depthTest = false, .depthWrite = false}, - .{.attachments = &.{.alphaBlending}, .formats = &.{.swapChain}}, + .{ + .rasterState = .{.cullMode = .none}, + .depthStencilState = .{.depthTest = false, .depthWrite = false}, + .blendState = .{.attachments = &.{.alphaBlending}, .formats = &.{.swapChain}}, + }, ); } diff --git a/src/itemdrop.zig b/src/itemdrop.zig index 1d1621a28d..5f79c979a8 100644 --- a/src/itemdrop.zig +++ b/src/itemdrop.zig @@ -615,10 +615,11 @@ pub const ItemDropRenderer = struct { // MARK: ItemDropRenderer "", &itemUniforms, graphics.VertexArray.EmptyVertex, - &.{}, - .{}, - .{.depthTest = true}, - .{.attachments = &.{.alphaBlending}, .formats = &.{.world}}, + .{ + .rasterState = .{}, + .depthStencilState = .{.depthTest = true}, + .blendState = .{.attachments = &.{.alphaBlending}, .formats = &.{.world}}, + }, ); itemModelSSBO = .init(); itemModelSSBO.bufferData(i32, &[3]i32{1, 1, 1}); diff --git a/src/particles.zig b/src/particles.zig index 0c08f275d4..cc33e6cd0a 100644 --- a/src/particles.zig +++ b/src/particles.zig @@ -187,10 +187,11 @@ pub const ParticleSystem = struct { "", &uniforms, graphics.VertexArray.EmptyVertex, - &.{}, - .{}, - .{.depthTest = true, .depthWrite = true}, - .{.attachments = &.{.noBlending}, .formats = &.{.world}}, + .{ + .rasterState = .{}, + .depthStencilState = .{.depthTest = true, .depthWrite = true}, + .blendState = .{.attachments = &.{.noBlending}, .formats = &.{.world}}, + }, ); particlesSSBO = SSBO.init(); diff --git a/src/renderer.zig b/src/renderer.zig index 841979cac1..09c164971f 100644 --- a/src/renderer.zig +++ b/src/renderer.zig @@ -69,10 +69,11 @@ pub fn init() void { "", &deferredUniforms, graphics.draw.SimpleVertex2D, - &.{}, - .{.cullMode = .none}, - .{.depthTest = false, .depthWrite = false}, - .{.attachments = &.{.noBlending}, .formats = &.{.world}}, + .{ + .rasterState = .{.cullMode = .none}, + .depthStencilState = .{.depthTest = false, .depthWrite = false}, + .blendState = .{.attachments = &.{.noBlending}, .formats = &.{.world}}, + }, ); fakeReflectionPipeline = graphics.Pipeline.init( "assets/cubyz/shaders/fake_reflection.vert", @@ -80,10 +81,11 @@ pub fn init() void { "", &fakeReflectionUniforms, graphics.draw.SimpleVertex2D, - &.{}, - .{.cullMode = .none}, - .{.depthTest = false, .depthWrite = false}, - .{.attachments = &.{.noBlending}, .formats = &.{.{.custom = c.VK_FORMAT_R8G8B8A8_UNORM}}}, + .{ + .rasterState = .{.cullMode = .none}, + .depthStencilState = .{.depthTest = false, .depthWrite = false}, + .blendState = .{.attachments = &.{.noBlending}, .formats = &.{.{.custom = c.VK_FORMAT_R8G8B8A8_UNORM}}}, + }, ); worldFrameBuffer.init(true, c.GL_NEAREST, c.GL_CLAMP_TO_EDGE); worldFrameBuffer.updateSize(Window.width, Window.height, c.GL_RGB16F); @@ -366,10 +368,12 @@ const Bloom = struct { // MARK: Bloom "", null, graphics.draw.SimpleVertex2D, - &.{.sampler(3, .{.fragment = true})}, - .{.cullMode = .none}, - .{.depthTest = false, .depthWrite = false}, - .{.attachments = &.{.noBlending}, .formats = &.{.{.custom = c.VK_FORMAT_R16G16B16A16_SFLOAT}}}, + .{ + .bindings = &.{.sampler(3, .{.fragment = true})}, + .rasterState = .{.cullMode = .none}, + .depthStencilState = .{.depthTest = false, .depthWrite = false}, + .blendState = .{.attachments = &.{.noBlending}, .formats = &.{.{.custom = c.VK_FORMAT_R16G16B16A16_SFLOAT}}}, + }, ); secondPassPipeline = graphics.Pipeline.init( "assets/cubyz/shaders/bloom/second_pass.vert", @@ -377,10 +381,12 @@ const Bloom = struct { // MARK: Bloom "", null, graphics.draw.SimpleVertex2D, - &.{.sampler(3, .{.fragment = true})}, - .{.cullMode = .none}, - .{.depthTest = false, .depthWrite = false}, - .{.attachments = &.{.noBlending}, .formats = &.{.{.custom = c.VK_FORMAT_R16G16B16A16_SFLOAT}}}, + .{ + .bindings = &.{.sampler(3, .{.fragment = true})}, + .rasterState = .{.cullMode = .none}, + .depthStencilState = .{.depthTest = false, .depthWrite = false}, + .blendState = .{.attachments = &.{.noBlending}, .formats = &.{.{.custom = c.VK_FORMAT_R16G16B16A16_SFLOAT}}}, + } ); colorExtractAndDownsamplePipeline = graphics.Pipeline.init( "assets/cubyz/shaders/bloom/color_extractor_downsample.vert", @@ -388,10 +394,11 @@ const Bloom = struct { // MARK: Bloom "", &colorExtractUniforms, graphics.draw.SimpleVertex2D, - &.{}, - .{.cullMode = .none}, - .{.depthTest = false, .depthWrite = false}, - .{.attachments = &.{.noBlending}, .formats = &.{.{.custom = c.VK_FORMAT_R16G16B16A16_SFLOAT}}}, + .{ + .rasterState = .{.cullMode = .none}, + .depthStencilState = .{.depthTest = false, .depthWrite = false}, + .blendState = .{.attachments = &.{.noBlending}, .formats = &.{.{.custom = c.VK_FORMAT_R16G16B16A16_SFLOAT}}}, + }, ); } @@ -508,10 +515,12 @@ pub const MenuBackGround = struct { "", null, MenuBackgroundVertex, - &.{.sampler(0, .{.fragment = true})}, - .{.cullMode = .none}, - .{.depthTest = false, .depthWrite = false}, - .{.attachments = &.{.noBlending}, .formats = &.{.swapChain}}, + .{ + .bindings = &.{.sampler(0, .{.fragment = true})}, + .rasterState = .{.cullMode = .none}, + .depthStencilState = .{.depthTest = false, .depthWrite = false}, + .blendState = .{.attachments = &.{.noBlending}, .formats = &.{.swapChain}}, + }, ); // 4 sides of a simple cube with some panorama texture on it. const rawData = [_]MenuBackgroundVertex{ @@ -730,17 +739,19 @@ pub const Skybox = struct { "", &starUniforms, graphics.VertexArray.EmptyVertex, - &.{}, - .{.cullMode = .none}, - .{.depthTest = false, .depthWrite = false}, - .{.attachments = &.{.{ - .srcColorBlendFactor = .one, - .dstColorBlendFactor = .one, - .colorBlendOp = .add, - .srcAlphaBlendFactor = .one, - .dstAlphaBlendFactor = .one, - .alphaBlendOp = .add, - }}, .formats = &.{.world}}, + .{ + .bindings = &.{}, + .rasterState = .{.cullMode = .none}, + .depthStencilState = .{.depthTest = false, .depthWrite = false}, + .blendState = .{.attachments = &.{.{ + .srcColorBlendFactor = .one, + .dstColorBlendFactor = .one, + .colorBlendOp = .add, + .srcAlphaBlendFactor = .one, + .dstAlphaBlendFactor = .one, + .alphaBlendOp = .add, + }}, .formats = &.{.world}}, + }, ); var starData: [numStars*20]f32 = undefined; @@ -885,10 +896,11 @@ pub const MeshSelection = struct { // MARK: MeshSelection "", &uniforms, graphics.VertexArray.EmptyVertex, - &.{}, - .{.cullMode = .none}, - .{.depthTest = true, .depthWrite = true}, - .{.attachments = &.{.alphaBlending}, .formats = &.{.world}}, + .{ + .rasterState = .{.cullMode = .none}, + .depthStencilState = .{.depthTest = true, .depthWrite = true}, + .blendState = .{.attachments = &.{.alphaBlending}, .formats = &.{.world}}, + }, ); } diff --git a/src/renderer/chunk_meshing.zig b/src/renderer/chunk_meshing.zig index 14cebc9985..5eb4456d75 100644 --- a/src/renderer/chunk_meshing.zig +++ b/src/renderer/chunk_meshing.zig @@ -70,10 +70,11 @@ pub fn init() void { "", &uniforms, graphics.VertexArray.EmptyVertex, - &.{}, - .{}, - .{.depthTest = true, .depthWrite = true}, - .{.attachments = &.{.noBlending}, .formats = &.{.world}}, + .{ + .rasterState = .{}, + .depthStencilState = .{.depthTest = true, .depthWrite = true}, + .blendState = .{.attachments = &.{.noBlending}, .formats = &.{.world}}, + }, ); transparentPipeline = graphics.Pipeline.init( "assets/cubyz/shaders/chunks/chunk_vertex.vert", @@ -81,17 +82,18 @@ pub fn init() void { "#define transparent\n", &transparentUniforms, graphics.VertexArray.EmptyVertex, - &.{}, - .{}, - .{.depthTest = true, .depthWrite = false, .depthCompare = .lessOrEqual}, - .{.attachments = &.{.{ - .srcColorBlendFactor = .one, - .dstColorBlendFactor = .src1Color, - .colorBlendOp = .add, - .srcAlphaBlendFactor = .one, - .dstAlphaBlendFactor = .src1Alpha, - .alphaBlendOp = .add, - }}, .formats = &.{.world}}, + .{ + .rasterState = .{}, + .depthStencilState = .{.depthTest = true, .depthWrite = false, .depthCompare = .lessOrEqual}, + .blendState = .{.attachments = &.{.{ + .srcColorBlendFactor = .one, + .dstColorBlendFactor = .src1Color, + .colorBlendOp = .add, + .srcAlphaBlendFactor = .one, + .dstAlphaBlendFactor = .src1Alpha, + .alphaBlendOp = .add, + }}, .formats = &.{.world}}, + }, ); commandPipeline = graphics.ComputePipeline.init("assets/cubyz/shaders/chunks/fillIndirectBuffer.comp", "", &commandUniforms); occlusionTestPipeline = graphics.Pipeline.init( @@ -100,19 +102,21 @@ pub fn init() void { "", null, graphics.VertexArray.EmptyVertex, - &.{.ssbo(6, .{.vertex = true, .fragment = true}), .ssbo(9, .{.vertex = true})}, - .{}, - .{.depthTest = true, .depthWrite = false}, - .{.attachments = &.{.{ - .enabled = false, - .srcColorBlendFactor = .zero, - .dstColorBlendFactor = .zero, - .colorBlendOp = .add, - .srcAlphaBlendFactor = .zero, - .dstAlphaBlendFactor = .zero, - .alphaBlendOp = .add, - .colorWriteMask = .none, - }}, .formats = &.{.world}}, + .{ + .bindings = &.{.ssbo(6, .{.vertex = true, .fragment = true}), .ssbo(9, .{.vertex = true})}, + .rasterState = .{}, + .depthStencilState = .{.depthTest = true, .depthWrite = false}, + .blendState = .{.attachments = &.{.{ + .enabled = false, + .srcColorBlendFactor = .zero, + .dstColorBlendFactor = .zero, + .colorBlendOp = .add, + .srcAlphaBlendFactor = .zero, + .dstAlphaBlendFactor = .zero, + .alphaBlendOp = .add, + .colorWriteMask = .none, + }}, .formats = &.{.world}}, + }, ); var rawData: [6*maxQuadsInIndexBuffer]u32 = undefined; diff --git a/src/systems/modelRenderer.zig b/src/systems/modelRenderer.zig index a86968dc42..6703f9d846 100644 --- a/src/systems/modelRenderer.zig +++ b/src/systems/modelRenderer.zig @@ -48,10 +48,11 @@ pub const client = struct { "", &uniforms, main.entityModel.EntityModel.Vertex, - &.{}, - .{}, - .{.depthTest = true}, - .{.attachments = &.{.alphaBlending}, .formats = &.{.world}}, + .{ + .rasterState = .{}, + .depthStencilState = .{.depthTest = true}, + .blendState = .{.attachments = &.{.alphaBlending}, .formats = &.{.world}}, + }, ); nodeBuffer.init(main.globalAllocator, 1 << 20, 15); From b9723ec5f46356621337705cfbc138457a88bea8 Mon Sep 17 00:00:00 2001 From: IntegratedQuantum Date: Sun, 16 Aug 2026 09:18:36 +0200 Subject: [PATCH 02/16] Small fixes: typos, init should happen before shaders are used, remove unused function --- src/graphics.zig | 22 +--------------------- src/graphics/pipelines.zig | 10 +++++----- src/renderer.zig | 10 +++++----- 3 files changed, 11 insertions(+), 31 deletions(-) diff --git a/src/graphics.zig b/src/graphics.zig index a6f5803ec1..6c01ba6f69 100644 --- a/src/graphics.zig +++ b/src/graphics.zig @@ -336,26 +336,6 @@ pub const draw = struct { // MARK: draw c.glDrawArrays(c.GL_LINE_STRIP, 0, 2); } - pub fn rectOutline(_pos: Vec2f, _dim: Vec2f) void { - var pos = _pos; - var dim = _dim; - pos *= @splat(scale); - pos += translation; - dim *= @splat(scale); - - linePipeline.bind(getScissor()); - - var viewport: [4]c_int = undefined; - c.glGetIntegerv(c.GL_VIEWPORT, &viewport); - c.glUniform2f(lineUniforms.screen, @floatFromInt(viewport[2]), @floatFromInt(viewport[3])); - c.glUniform2f(lineUniforms.start, pos[0], pos[1]); // Move the coordinates, so they are in the center of a pixel. - c.glUniform2f(lineUniforms.direction, dim[0] - 1, dim[1] - 1); // The height is a lot smaller because the inner edge of the rect is drawn. - c.glUniform1i(lineUniforms.lineColor, @bitCast(getColor())); - - lineVao.bind(); - c.glDrawArrays(c.GL_LINE_LOOP, 0, 5); - } - // ---------------------------------------------------------------------------- // MARK: fillCircle() var circleUniforms: struct { @@ -1289,6 +1269,7 @@ const TextRendering = struct { // MARK: TextRendering }; pub fn init() void { // MARK: init() + pipelines.init(); draw.initCircle(); draw.initImage(); draw.initLine(); @@ -1298,7 +1279,6 @@ pub fn init() void { // MARK: init() std.log.err("Error while initializing TextRendering: {s}", .{@errorName(err)}); }; block_texture.init(); - pipelines.init(); frame_uniforms.init(); } diff --git a/src/graphics/pipelines.zig b/src/graphics/pipelines.zig index daed4184b4..93770088cc 100644 --- a/src/graphics/pipelines.zig +++ b/src/graphics/pipelines.zig @@ -567,7 +567,7 @@ pub const DescriptorSetLayoutBinding = extern struct { // MARK: DescriptorSetLay inputAttachment = c.VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, }, count: u32, - stageFlags: packed struct(c_int) { + stageFlags: packed struct(c.VkShaderStageFlags) { vertex: bool = false, tessellationControl: bool = false, tessellationEvaluation: bool = false, @@ -693,7 +693,7 @@ pub const Pipeline = struct { // MARK: Pipeline const pipelineLayoutInfo = c.VkPipelineLayoutCreateInfo{ // TODO: Configure push constants .sType = c.VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, .setLayoutCount = 2, - .pSetLayouts = &[_]c.VkDescriptorSetLayout{self.descriptorSetLayout, frameUnformDescriptorSetLayout}, + .pSetLayouts = &[_]c.VkDescriptorSetLayout{self.descriptorSetLayout, frameUniformDescriptorSetLayout}, }; try vulkan.checkResultErr(c.vkCreatePipelineLayout(vulkan.device, &pipelineLayoutInfo, null, &self.pipelineLayout)); errdefer c.vkDestroyPipelineLayout(vulkan.device, self.pipelineLayout, null); @@ -873,7 +873,7 @@ pub const ComputePipeline = struct { // MARK: ComputePipeline } }; -var frameUnformDescriptorSetLayout: c.VkDescriptorSetLayout = undefined; +var frameUniformDescriptorSetLayout: c.VkDescriptorSetLayout = undefined; pub fn init() void { // MARK: init() if (c.glslang_initialize_process() == c.false) std.log.err("glslang_initialize_process failed", .{}); @@ -889,13 +889,13 @@ pub fn init() void { // MARK: init() .type = .uniformBuffer, }), }; - vulkan.checkResultErr(c.vkCreateDescriptorSetLayout(vulkan.device, &descriptorSetLayoutInfo, null, &frameUnformDescriptorSetLayout)) catch @panic("Driver Bug"); + vulkan.checkResultErr(c.vkCreateDescriptorSetLayout(vulkan.device, &descriptorSetLayoutInfo, null, &frameUniformDescriptorSetLayout)) catch @panic("Driver Bug"); } } pub fn deinit() void { // MARK: deinit() c.glslang_finalize_process(); if (main.settings.launchConfig.vulkanTestingMode) { - c.vkDestroyDescriptorSetLayout(vulkan.device, frameUnformDescriptorSetLayout, null); + c.vkDestroyDescriptorSetLayout(vulkan.device, frameUniformDescriptorSetLayout, null); } } diff --git a/src/renderer.zig b/src/renderer.zig index 09c164971f..62508ec770 100644 --- a/src/renderer.zig +++ b/src/renderer.zig @@ -695,7 +695,7 @@ pub const Skybox = struct { starOpacity: c_int, } = undefined; - var starVao: graphics.VertexArray = undefined; + var starVao: c_uint = undefined; var starSsbo: graphics.SSBO = undefined; @@ -810,14 +810,14 @@ pub const Skybox = struct { } starSsbo = graphics.SSBO.initStatic(f32, &starData); - - starVao = .init(graphics.VertexArray.EmptyVertex, &.{}, null); + + c.glGenVertexArrays(1, &starVao); } pub fn deinit() void { starPipeline.deinit(); starSsbo.deinit(); - starVao.deinit(); + c.glDeleteVertexArrays(1, &starVao); } pub fn render() void { @@ -835,7 +835,7 @@ pub const Skybox = struct { c.glUniform1f(starUniforms.starOpacity, starOpacity); c.glUniformMatrix4fv(starUniforms.mvp, 1, c.GL_TRUE, @ptrCast(&starMatrix)); - starVao.bind(); + c.glBindVertexArray(starVao); c.glDrawArrays(c.GL_TRIANGLES, 0, numStars*3); c.glBindBuffer(c.GL_SHADER_STORAGE_BUFFER, 0); From d9de9f8a6d4e033599748626c97e06755179870d Mon Sep 17 00:00:00 2001 From: IntegratedQuantum Date: Sun, 16 Aug 2026 09:19:45 +0200 Subject: [PATCH 03/16] Add input assembly state to the Pipeline creation --- src/graphics/pipelines.zig | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/graphics/pipelines.zig b/src/graphics/pipelines.zig index 93770088cc..c4989c0a9e 100644 --- a/src/graphics/pipelines.zig +++ b/src/graphics/pipelines.zig @@ -605,6 +605,23 @@ pub const DescriptorSetLayoutBinding = extern struct { // MARK: DescriptorSetLay } }; +pub const InputAssemblyState = struct { // MARK: InputAssemblyState + topology: enum(c.VkPrimitiveTopology) { + pointList = c.VK_PRIMITIVE_TOPOLOGY_POINT_LIST, + lineList = c.VK_PRIMITIVE_TOPOLOGY_LINE_LIST, + lineStrip = c.VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, + triangleList = c.VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, + triangleStrip = c.VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, + triangleFan = c.VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN, + lineListWithAdjacency = c.VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY, + lineStripWithAdjacency = c.VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY, + triangleListWithAdjacency = c.VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY, + triangleStripWithAdjacency = c.VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY, + patchList = c.VK_PRIMITIVE_TOPOLOGY_PATCH_LIST, + } = .triangleList, + primitiveRestartEnable: bool = false, +}; + pub const Pipeline = struct { // MARK: Pipeline shader: Shader, rasterState: RasterizationState, @@ -660,8 +677,8 @@ pub const Pipeline = struct { // MARK: Pipeline }; const inputAssembly: c.VkPipelineInputAssemblyStateCreateInfo = .{ .sType = c.VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, - .topology = c.VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // TODO: Make this an input - .primitiveRestartEnable = c.VK_FALSE, // TODO: Make this an input + .topology = @intFromEnum(options.inputAssemblyState.topology), + .primitiveRestartEnable = if (options.inputAssemblyState.primitiveRestartEnable) c.VK_TRUE else c.VK_FALSE, }; const viewport: c.VkViewport = .{}; // overwritten dynamically const scissor: c.VkRect2D = .{}; // overwritten dynamically @@ -740,6 +757,7 @@ pub const Pipeline = struct { // MARK: Pipeline rasterState: RasterizationState, depthStencilState: DepthStencilState, blendState: ColorBlendState, + inputAssemblyState: InputAssemblyState = .{}, bindings: []const DescriptorSetLayoutBinding = &.{}, }; From 8a11e86cc1a578f24bf912d48aeb0d9fac308030 Mon Sep 17 00:00:00 2001 From: IntegratedQuantum Date: Sun, 16 Aug 2026 09:20:36 +0200 Subject: [PATCH 04/16] Add push constants --- src/graphics/CommandBuffer.zig | 4 ++++ src/graphics/pipelines.zig | 3 +++ 2 files changed, 7 insertions(+) diff --git a/src/graphics/CommandBuffer.zig b/src/graphics/CommandBuffer.zig index da43f5e121..949678fc92 100644 --- a/src/graphics/CommandBuffer.zig +++ b/src/graphics/CommandBuffer.zig @@ -178,6 +178,10 @@ pub fn bindPipeline(self: CommandBuffer, pipeline: main.graphics.Pipeline) void }); } +pub fn pushConstants(self: CommandBuffer, pipeline: main.graphics.Pipeline, constants: anytype, options: struct {stageFlags: u32, offset: u32 = 0}) void { + c.vkCmdPushConstants(self.handle, pipeline.pipelineLayout, options.stageFlags, options.offset, @sizeOf(@TypeOf(constants.*)), constants); +} + pub fn setViewport(self: CommandBuffer, viewport: c.VkViewport) void { c.vkCmdSetViewport(self.handle, 0, 1, &viewport); } diff --git a/src/graphics/pipelines.zig b/src/graphics/pipelines.zig index c4989c0a9e..663356cfc5 100644 --- a/src/graphics/pipelines.zig +++ b/src/graphics/pipelines.zig @@ -711,6 +711,8 @@ pub const Pipeline = struct { // MARK: Pipeline .sType = c.VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, .setLayoutCount = 2, .pSetLayouts = &[_]c.VkDescriptorSetLayout{self.descriptorSetLayout, frameUniformDescriptorSetLayout}, + .pushConstantRangeCount = @intCast(options.pushConstantRanges.len), + .pPushConstantRanges = options.pushConstantRanges.ptr, }; try vulkan.checkResultErr(c.vkCreatePipelineLayout(vulkan.device, &pipelineLayoutInfo, null, &self.pipelineLayout)); errdefer c.vkDestroyPipelineLayout(vulkan.device, self.pipelineLayout, null); @@ -759,6 +761,7 @@ pub const Pipeline = struct { // MARK: Pipeline blendState: ColorBlendState, inputAssemblyState: InputAssemblyState = .{}, bindings: []const DescriptorSetLayoutBinding = &.{}, + pushConstantRanges: []const c.VkPushConstantRange = &.{}, }; pub fn init(vertexPath: []const u8, fragmentPath: []const u8, defines: []const u8, uniformStruct: anytype, VertexType: type, options: Options) Pipeline { From ac2260fd1c3f17566f39930945e082f100444325 Mon Sep 17 00:00:00 2001 From: IntegratedQuantum Date: Sun, 16 Aug 2026 09:24:25 +0200 Subject: [PATCH 05/16] Add support for vertex arrays --- src/graphics.zig | 19 +++++++++++++++++++ src/graphics/CommandBuffer.zig | 7 +++++++ 2 files changed, 26 insertions(+) diff --git a/src/graphics.zig b/src/graphics.zig index 6c01ba6f69..7b0fdc1bf1 100644 --- a/src/graphics.zig +++ b/src/graphics.zig @@ -1298,6 +1298,9 @@ pub const VertexArray = struct { // MARK: VertexArray vao: c_uint, vbo: c_uint, ibo: ?c_uint, + buffer: vulkan.Buffer, + indicesOffset: usize, + hasIndices: bool, pub const EmptyVertex = struct { pub const attributeDescriptions: []const c.VkVertexInputAttributeDescription = &.{}; @@ -1311,12 +1314,15 @@ pub const VertexArray = struct { // MARK: VertexArray c.glBindBuffer(c.GL_ARRAY_BUFFER, result.vbo); c.glBufferData(c.GL_ARRAY_BUFFER, @intCast(data.len*@sizeOf(T)), data.ptr, c.GL_STATIC_DRAW); if (indices_) |indices| { + std.debug.assert(indices.len != 0); + result.hasIndices = true; result.ibo = 0; c.glGenBuffers(1, &result.ibo.?); c.glBindBuffer(c.GL_ELEMENT_ARRAY_BUFFER, result.ibo.?); c.glBufferData(c.GL_ELEMENT_ARRAY_BUFFER, @intCast(indices.len*@sizeOf(u32)), indices.ptr, c.GL_STATIC_DRAW); } else { result.ibo = null; + result.hasIndices = false; } const attributeDescriptions: []const c.VkVertexInputAttributeDescription = T.attributeDescriptions; @@ -1347,6 +1353,16 @@ pub const VertexArray = struct { // MARK: VertexArray } c.glBindVertexArray(0); + if (main.settings.launchConfig.vulkanTestingMode) { + const indices = indices_ orelse &.{}; + result.indicesOffset = std.mem.alignForward(usize, data.len*@sizeOf(T), @alignOf(u32)); + result.buffer = .init( + result.indicesOffset + indices.len*@sizeOf(u32), + .{.usage = c.VK_BUFFER_USAGE_TRANSFER_DST_BIT | c.VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | c.VK_BUFFER_USAGE_INDEX_BUFFER_BIT}, + ); + result.buffer.uploadData(0, std.mem.sliceAsBytes(data)); + result.buffer.uploadData(result.indicesOffset, std.mem.sliceAsBytes(indices)); + } return result; } @@ -1356,6 +1372,9 @@ pub const VertexArray = struct { // MARK: VertexArray if (self.ibo != null) { c.glDeleteBuffers(1, &self.ibo.?); } + if (main.settings.launchConfig.vulkanTestingMode) { + self.buffer.deferredDeinit(); + } } pub fn bind(self: VertexArray) void { diff --git a/src/graphics/CommandBuffer.zig b/src/graphics/CommandBuffer.zig index 949678fc92..565c9292a1 100644 --- a/src/graphics/CommandBuffer.zig +++ b/src/graphics/CommandBuffer.zig @@ -178,6 +178,13 @@ pub fn bindPipeline(self: CommandBuffer, pipeline: main.graphics.Pipeline) void }); } +pub fn bindVertexArray(self: CommandBuffer, buffer: main.graphics.VertexArray) void { + c.vkCmdBindVertexBuffers(self.handle, 0, 1, &buffer.buffer.handle, &@as(usize, 0)); + if (buffer.hasIndices) { + c.vkCmdBindIndexBuffer(self.handle, buffer.buffer.handle, buffer.indicesOffset, c.VK_INDEX_TYPE_UINT32); + } +} + pub fn pushConstants(self: CommandBuffer, pipeline: main.graphics.Pipeline, constants: anytype, options: struct {stageFlags: u32, offset: u32 = 0}) void { c.vkCmdPushConstants(self.handle, pipeline.pipelineLayout, options.stageFlags, options.offset, @sizeOf(@TypeOf(constants.*)), constants); } From 8e39123db439bf9cdb5b5dc8af03e813ae1f1775 Mon Sep 17 00:00:00 2001 From: IntegratedQuantum Date: Sun, 16 Aug 2026 09:45:06 +0200 Subject: [PATCH 06/16] Add scissor support when binding pipeline --- src/graphics/CommandBuffer.zig | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/graphics/CommandBuffer.zig b/src/graphics/CommandBuffer.zig index 565c9292a1..0bc2df5ed0 100644 --- a/src/graphics/CommandBuffer.zig +++ b/src/graphics/CommandBuffer.zig @@ -162,7 +162,7 @@ pub fn endRendering(self: CommandBuffer) void { c.vkCmdEndRendering(self.handle); } -pub fn bindPipeline(self: CommandBuffer, pipeline: main.graphics.Pipeline) void { +pub fn bindPipeline(self: CommandBuffer, pipeline: main.graphics.Pipeline, scissor: ?c.VkRect2D) void { c.vkCmdBindPipeline(self.handle, c.VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.graphicsPipeline); self.setViewport(.{ .x = 0, @@ -172,10 +172,14 @@ pub fn bindPipeline(self: CommandBuffer, pipeline: main.graphics.Pipeline) void .minDepth = 0, .maxDepth = 1, }); - self.setScissor(.{ - .offset = .{.x = 0, .y = 0}, - .extent = vulkan.SwapChain.extent, - }); + if (scissor) |s| { + self.setScissor(s); + } else { + self.setScissor(.{ + .offset = .{.x = 0, .y = 0}, + .extent = vulkan.SwapChain.extent, + }); + } } pub fn bindVertexArray(self: CommandBuffer, buffer: main.graphics.VertexArray) void { From e9a29f7d4d1b79c31073609971f29875f8c74ca6 Mon Sep 17 00:00:00 2001 From: IntegratedQuantum Date: Sun, 16 Aug 2026 09:45:32 +0200 Subject: [PATCH 07/16] Dont define a second descriptor set when it would be empty --- src/graphics/pipelines.zig | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/src/graphics/pipelines.zig b/src/graphics/pipelines.zig index 663356cfc5..11478722ea 100644 --- a/src/graphics/pipelines.zig +++ b/src/graphics/pipelines.zig @@ -630,7 +630,7 @@ pub const Pipeline = struct { // MARK: Pipeline blendState: ColorBlendState, vulkanCreationSuccessful: bool = false, // TODO: Remove after all Vulkan pipelines compile pipelineLayout: c.VkPipelineLayout = undefined, - descriptorSetLayout: c.VkDescriptorSetLayout = undefined, + descriptorSetLayout: ?c.VkDescriptorSetLayout = null, graphicsPipeline: c.VkPipeline = undefined, fn initVulkan(self: *Pipeline, vertexPath: []const u8, fragmentPath: []const u8, defines: []const u8, VertexType: type, options: Options) !void { @@ -699,18 +699,27 @@ pub const Pipeline = struct { // MARK: Pipeline } const blendState = self.blendState.toVulkan(attachments); - const descriptorSetLayoutInfo = c.VkDescriptorSetLayoutCreateInfo{ - .sType = c.VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, - .bindingCount = @intCast(options.bindings.len), - .pBindings = @ptrCast(options.bindings.ptr), - }; - try vulkan.checkResultErr(c.vkCreateDescriptorSetLayout(vulkan.device, &descriptorSetLayoutInfo, null, &self.descriptorSetLayout)); - errdefer c.vkDestroyDescriptorSetLayout(vulkan.device, self.descriptorSetLayout, null); + var descriptorSetLayouts: main.List(c.VkDescriptorSetLayout) = .empty; + defer descriptorSetLayouts.deinit(main.stackAllocator); + + if (options.bindings.len != 0) { + self.descriptorSetLayout = @as(c.VkDescriptorSetLayout, undefined); + + const descriptorSetLayoutInfo = c.VkDescriptorSetLayoutCreateInfo{ + .sType = c.VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, + .bindingCount = @intCast(options.bindings.len), + .pBindings = @ptrCast(options.bindings.ptr), + }; + try vulkan.checkResultErr(c.vkCreateDescriptorSetLayout(vulkan.device, &descriptorSetLayoutInfo, null, &self.descriptorSetLayout.?)); + descriptorSetLayouts.append(main.stackAllocator, self.descriptorSetLayout.?); + } + + descriptorSetLayouts.append(main.stackAllocator, frameUniformDescriptorSetLayout); const pipelineLayoutInfo = c.VkPipelineLayoutCreateInfo{ // TODO: Configure push constants .sType = c.VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, - .setLayoutCount = 2, - .pSetLayouts = &[_]c.VkDescriptorSetLayout{self.descriptorSetLayout, frameUniformDescriptorSetLayout}, + .setLayoutCount = @intCast(descriptorSetLayouts.items.len), + .pSetLayouts = descriptorSetLayouts.items.ptr, .pushConstantRangeCount = @intCast(options.pushConstantRanges.len), .pPushConstantRanges = options.pushConstantRanges.ptr, }; @@ -789,7 +798,7 @@ pub const Pipeline = struct { // MARK: Pipeline if (self.vulkanCreationSuccessful) { c.vkDestroyPipeline(vulkan.device, self.graphicsPipeline, null); c.vkDestroyPipelineLayout(vulkan.device, self.pipelineLayout, null); - c.vkDestroyDescriptorSetLayout(vulkan.device, self.descriptorSetLayout, null); + if(self.descriptorSetLayout) |layout| c.vkDestroyDescriptorSetLayout(vulkan.device, layout, null); } } From ca74d55c2be6c1654b7350845b51f676efd518f9 Mon Sep 17 00:00:00 2001 From: IntegratedQuantum Date: Sun, 16 Aug 2026 09:45:54 +0200 Subject: [PATCH 08/16] Make the currentFrame public --- src/graphics/vulkan.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/graphics/vulkan.zig b/src/graphics/vulkan.zig index 10db4f9955..2405c82b67 100644 --- a/src/graphics/vulkan.zig +++ b/src/graphics/vulkan.zig @@ -557,7 +557,7 @@ const FrameData = struct { var frames: [2]FrameData = undefined; -var currentFrame: *const FrameData = undefined; +pub var currentFrame: *const FrameData = undefined; pub const SwapChain = struct { // MARK: SwapChain var swapChain: c.VkSwapchainKHR = null; From 281e41aaa1d2d371c5ec6ffaa18379e1e51d61cb Mon Sep 17 00:00:00 2001 From: IntegratedQuantum Date: Sun, 16 Aug 2026 09:46:19 +0200 Subject: [PATCH 09/16] Convert the first few graphics.draw operations to vulkan --- assets/cubyz/shaders/graphics/Line.vert | 9 +++ assets/cubyz/shaders/graphics/Rect.vert | 9 +++ assets/cubyz/shaders/graphics/RectBorder.vert | 10 +++ src/graphics.zig | 74 +++++++++++++++++++ 4 files changed, 102 insertions(+) diff --git a/assets/cubyz/shaders/graphics/Line.vert b/assets/cubyz/shaders/graphics/Line.vert index e683b8fdb7..7ed8bf410a 100644 --- a/assets/cubyz/shaders/graphics/Line.vert +++ b/assets/cubyz/shaders/graphics/Line.vert @@ -4,12 +4,21 @@ layout(location = 0) in vec2 vertex_pos; layout(location = 0) flat out vec4 color; +#ifdef OPEN_GL // in pixel layout(location = 0) uniform vec2 start; layout(location = 1) uniform vec2 direction; layout(location = 2) uniform vec2 screen; layout(location = 3) uniform int lineColor; +#else +layout(push_constant, std430) uniform _ { + vec2 start; + vec2 direction; + vec2 screen; + int lineColor; +}; +#endif void main() { // Convert to opengl coordinates: diff --git a/assets/cubyz/shaders/graphics/Rect.vert b/assets/cubyz/shaders/graphics/Rect.vert index c6371a9146..7e2727f5c5 100644 --- a/assets/cubyz/shaders/graphics/Rect.vert +++ b/assets/cubyz/shaders/graphics/Rect.vert @@ -5,11 +5,20 @@ layout(location = 0) in vec2 vertex_pos; layout(location = 0) flat out vec4 color; // in pixel +#ifdef OPEN_GL layout(location = 0) uniform vec2 start; layout(location = 1) uniform vec2 size; layout(location = 2) uniform vec2 screen; layout(location = 3) uniform int rectColor; +#else +layout(push_constant, std430) uniform _ { + vec2 start; + vec2 size; + vec2 screen; + int rectColor; +}; +#endif void main() { // Convert to opengl coordinates: diff --git a/assets/cubyz/shaders/graphics/RectBorder.vert b/assets/cubyz/shaders/graphics/RectBorder.vert index 88e6431d57..232708ca2c 100644 --- a/assets/cubyz/shaders/graphics/RectBorder.vert +++ b/assets/cubyz/shaders/graphics/RectBorder.vert @@ -5,12 +5,22 @@ layout(location = 0) in vec4 vertex_pos; layout(location = 0) flat out vec4 color; // in pixel +#ifdef OPEN_GL layout(location = 0) uniform vec2 start; layout(location = 1) uniform vec2 size; layout(location = 2) uniform vec2 screen; layout(location = 3) uniform float lineWidth; layout(location = 4) uniform int rectColor; +#else +layout(push_constant, std430) uniform _ { + vec2 start; + vec2 size; + vec2 screen; + float lineWidth; + int rectColor; +}; +#endif void main() { // Convert to opengl coordinates: diff --git a/src/graphics.zig b/src/graphics.zig index 7b0fdc1bf1..2998259182 100644 --- a/src/graphics.zig +++ b/src/graphics.zig @@ -147,6 +147,12 @@ pub const draw = struct { // MARK: draw size: c_int, rectColor: c_int, } = undefined; + const RectUniforms = struct { + start: [2]f32 align(8), + size: [2]f32 align(8), + screen: [2]f32 align(8), + rectColor: i32, + }; var rectPipeline: Pipeline = undefined; pub var rectVao: VertexArray = undefined; @@ -161,6 +167,12 @@ pub const draw = struct { // MARK: draw .rasterState = .{.cullMode = .none}, .depthStencilState = .{.depthTest = false, .depthWrite = false}, .blendState = .{.attachments = &.{.alphaBlending}, .formats = &.{.swapChain}}, + .inputAssemblyState = .{.topology = .triangleStrip}, + .pushConstantRanges = &.{.{ + .stageFlags = c.VK_SHADER_STAGE_VERTEX_BIT, + .offset = 0, + .size = @sizeOf(RectUniforms), + }}, }, ); const rawData = [_]SimpleVertex2D{ @@ -196,6 +208,18 @@ pub const draw = struct { // MARK: draw rectVao.bind(); c.glDrawArrays(c.GL_TRIANGLE_STRIP, 0, 4); + + if (main.settings.launchConfig.vulkanTestingMode) { + vulkan.currentFrame.guiCommands.bindPipeline(rectPipeline, getScissor()); + vulkan.currentFrame.guiCommands.pushConstants(rectPipeline, &RectUniforms{ + .start = pos, + .size = dim, + .screen = .{@floatFromInt(viewport[2]), @floatFromInt(viewport[3])}, + .rectColor = @bitCast(getColor()), + }, .{.stageFlags = c.VK_SHADER_STAGE_VERTEX_BIT}); + vulkan.currentFrame.guiCommands.bindVertexArray(rectVao); + vulkan.currentFrame.guiCommands.draw(4, 0); + } } // ---------------------------------------------------------------------------- @@ -207,6 +231,13 @@ pub const draw = struct { // MARK: draw rectColor: c_int, lineWidth: c_int, } = undefined; + const RectBorderUniforms = struct { + start: [2]f32 align(8), + size: [2]f32 align(8), + screen: [2]f32 align(8), + lineWidth: f32, + rectColor: i32, + }; var rectBorderPipeline: Pipeline = undefined; var rectBorderVao: VertexArray = undefined; @@ -232,6 +263,12 @@ pub const draw = struct { // MARK: draw .rasterState = .{.cullMode = .none}, .depthStencilState = .{.depthTest = false, .depthWrite = false}, .blendState = .{.attachments = &.{.alphaBlending}, .formats = &.{.swapChain}}, + .inputAssemblyState = .{.topology = .triangleStrip}, + .pushConstantRanges = &.{.{ + .stageFlags = c.VK_SHADER_STAGE_VERTEX_BIT, + .offset = 0, + .size = @sizeOf(RectBorderUniforms), + }}, }, ); const rawData = [_]RectBorderVertex{ @@ -276,6 +313,19 @@ pub const draw = struct { // MARK: draw rectBorderVao.bind(); c.glDrawArrays(c.GL_TRIANGLE_STRIP, 0, 10); + + if (main.settings.launchConfig.vulkanTestingMode) { + vulkan.currentFrame.guiCommands.bindPipeline(rectBorderPipeline, getScissor()); + vulkan.currentFrame.guiCommands.pushConstants(rectBorderPipeline, &RectBorderUniforms{ + .start = pos, + .size = dim, + .screen = .{@floatFromInt(viewport[2]), @floatFromInt(viewport[3])}, + .lineWidth = width, + .rectColor = @bitCast(getColor()), + }, .{.stageFlags = c.VK_SHADER_STAGE_VERTEX_BIT}); + vulkan.currentFrame.guiCommands.bindVertexArray(rectBorderVao); + vulkan.currentFrame.guiCommands.draw(10, 0); + } } // ---------------------------------------------------------------------------- @@ -286,6 +336,12 @@ pub const draw = struct { // MARK: draw direction: c_int, lineColor: c_int, } = undefined; + const LineUniforms = struct { + start: [2]f32 align(8), + direction: [2]f32 align(8), + screen: [2]f32 align(8), + lineColor: i32, + }; var linePipeline: Pipeline = undefined; var lineVao: VertexArray = undefined; @@ -300,6 +356,12 @@ pub const draw = struct { // MARK: draw .rasterState = .{.cullMode = .none}, .depthStencilState = .{.depthTest = false, .depthWrite = false}, .blendState = .{.attachments = &.{.alphaBlending}, .formats = &.{.swapChain}}, + .inputAssemblyState = .{.topology = .lineStrip}, + .pushConstantRanges = &.{.{ + .stageFlags = c.VK_SHADER_STAGE_VERTEX_BIT, + .offset = 0, + .size = @sizeOf(LineUniforms), + }}, }, ); const rawData = [_]SimpleVertex2D{ @@ -334,6 +396,18 @@ pub const draw = struct { // MARK: draw lineVao.bind(); c.glDrawArrays(c.GL_LINE_STRIP, 0, 2); + + if (main.settings.launchConfig.vulkanTestingMode) { + vulkan.currentFrame.guiCommands.bindPipeline(linePipeline, getScissor()); + vulkan.currentFrame.guiCommands.pushConstants(linePipeline, &LineUniforms{ + .start = pos1, + .direction = pos2 - pos1, + .screen = .{@floatFromInt(viewport[2]), @floatFromInt(viewport[3])}, + .lineColor = @bitCast(getColor()), + }, .{.stageFlags = c.VK_SHADER_STAGE_VERTEX_BIT}); + vulkan.currentFrame.guiCommands.bindVertexArray(rectBorderVao); + vulkan.currentFrame.guiCommands.draw(10, 0); + } } // ---------------------------------------------------------------------------- From 6c35d05c271bd422e2810708a5f5b95154b0401a Mon Sep 17 00:00:00 2001 From: IntegratedQuantum Date: Sun, 16 Aug 2026 10:01:21 +0200 Subject: [PATCH 10/16] Format --- src/graphics/CommandBuffer.zig | 2 +- src/graphics/pipelines.zig | 2 +- src/renderer.zig | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/graphics/CommandBuffer.zig b/src/graphics/CommandBuffer.zig index 0bc2df5ed0..8f840602b2 100644 --- a/src/graphics/CommandBuffer.zig +++ b/src/graphics/CommandBuffer.zig @@ -189,7 +189,7 @@ pub fn bindVertexArray(self: CommandBuffer, buffer: main.graphics.VertexArray) v } } -pub fn pushConstants(self: CommandBuffer, pipeline: main.graphics.Pipeline, constants: anytype, options: struct {stageFlags: u32, offset: u32 = 0}) void { +pub fn pushConstants(self: CommandBuffer, pipeline: main.graphics.Pipeline, constants: anytype, options: struct { stageFlags: u32, offset: u32 = 0 }) void { c.vkCmdPushConstants(self.handle, pipeline.pipelineLayout, options.stageFlags, options.offset, @sizeOf(@TypeOf(constants.*)), constants); } diff --git a/src/graphics/pipelines.zig b/src/graphics/pipelines.zig index 11478722ea..4f43caa8f7 100644 --- a/src/graphics/pipelines.zig +++ b/src/graphics/pipelines.zig @@ -798,7 +798,7 @@ pub const Pipeline = struct { // MARK: Pipeline if (self.vulkanCreationSuccessful) { c.vkDestroyPipeline(vulkan.device, self.graphicsPipeline, null); c.vkDestroyPipelineLayout(vulkan.device, self.pipelineLayout, null); - if(self.descriptorSetLayout) |layout| c.vkDestroyDescriptorSetLayout(vulkan.device, layout, null); + if (self.descriptorSetLayout) |layout| c.vkDestroyDescriptorSetLayout(vulkan.device, layout, null); } } diff --git a/src/renderer.zig b/src/renderer.zig index 62508ec770..ff430ae4ba 100644 --- a/src/renderer.zig +++ b/src/renderer.zig @@ -386,7 +386,7 @@ const Bloom = struct { // MARK: Bloom .rasterState = .{.cullMode = .none}, .depthStencilState = .{.depthTest = false, .depthWrite = false}, .blendState = .{.attachments = &.{.noBlending}, .formats = &.{.{.custom = c.VK_FORMAT_R16G16B16A16_SFLOAT}}}, - } + }, ); colorExtractAndDownsamplePipeline = graphics.Pipeline.init( "assets/cubyz/shaders/bloom/color_extractor_downsample.vert", @@ -810,7 +810,7 @@ pub const Skybox = struct { } starSsbo = graphics.SSBO.initStatic(f32, &starData); - + c.glGenVertexArrays(1, &starVao); } From f2415613d9c3aacd71f51815cec6d9edcf036a72 Mon Sep 17 00:00:00 2001 From: IntegratedQuantum Date: Sun, 16 Aug 2026 10:02:57 +0200 Subject: [PATCH 11/16] More format --- assets/cubyz/shaders/graphics/Line.vert | 2 +- assets/cubyz/shaders/graphics/Rect.vert | 2 +- assets/cubyz/shaders/graphics/RectBorder.vert | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/assets/cubyz/shaders/graphics/Line.vert b/assets/cubyz/shaders/graphics/Line.vert index 7ed8bf410a..f2eaf246fd 100644 --- a/assets/cubyz/shaders/graphics/Line.vert +++ b/assets/cubyz/shaders/graphics/Line.vert @@ -13,7 +13,7 @@ layout(location = 2) uniform vec2 screen; layout(location = 3) uniform int lineColor; #else layout(push_constant, std430) uniform _ { - vec2 start; + vec2 start; vec2 direction; vec2 screen; int lineColor; diff --git a/assets/cubyz/shaders/graphics/Rect.vert b/assets/cubyz/shaders/graphics/Rect.vert index 7e2727f5c5..405b647061 100644 --- a/assets/cubyz/shaders/graphics/Rect.vert +++ b/assets/cubyz/shaders/graphics/Rect.vert @@ -13,7 +13,7 @@ layout(location = 2) uniform vec2 screen; layout(location = 3) uniform int rectColor; #else layout(push_constant, std430) uniform _ { - vec2 start; + vec2 start; vec2 size; vec2 screen; int rectColor; diff --git a/assets/cubyz/shaders/graphics/RectBorder.vert b/assets/cubyz/shaders/graphics/RectBorder.vert index 232708ca2c..db1c6e1cdb 100644 --- a/assets/cubyz/shaders/graphics/RectBorder.vert +++ b/assets/cubyz/shaders/graphics/RectBorder.vert @@ -14,7 +14,7 @@ layout(location = 3) uniform float lineWidth; layout(location = 4) uniform int rectColor; #else layout(push_constant, std430) uniform _ { - vec2 start; + vec2 start; vec2 size; vec2 screen; float lineWidth; From e49e91cc435095a8cfe2821759d8adb52b5473e9 Mon Sep 17 00:00:00 2001 From: IntegratedQuantum Date: Sun, 16 Aug 2026 11:19:13 +0200 Subject: [PATCH 12/16] Only make the push constant size configurable offset isn't needed for now, and as far as I can tell there should be no performance impact from always specifying all flags --- src/graphics.zig | 18 +++--------------- src/graphics/pipelines.zig | 10 +++++++--- 2 files changed, 10 insertions(+), 18 deletions(-) diff --git a/src/graphics.zig b/src/graphics.zig index 2998259182..c91dfd40bb 100644 --- a/src/graphics.zig +++ b/src/graphics.zig @@ -168,11 +168,7 @@ pub const draw = struct { // MARK: draw .depthStencilState = .{.depthTest = false, .depthWrite = false}, .blendState = .{.attachments = &.{.alphaBlending}, .formats = &.{.swapChain}}, .inputAssemblyState = .{.topology = .triangleStrip}, - .pushConstantRanges = &.{.{ - .stageFlags = c.VK_SHADER_STAGE_VERTEX_BIT, - .offset = 0, - .size = @sizeOf(RectUniforms), - }}, + .pushConstantSize = @sizeOf(RectUniforms), }, ); const rawData = [_]SimpleVertex2D{ @@ -264,11 +260,7 @@ pub const draw = struct { // MARK: draw .depthStencilState = .{.depthTest = false, .depthWrite = false}, .blendState = .{.attachments = &.{.alphaBlending}, .formats = &.{.swapChain}}, .inputAssemblyState = .{.topology = .triangleStrip}, - .pushConstantRanges = &.{.{ - .stageFlags = c.VK_SHADER_STAGE_VERTEX_BIT, - .offset = 0, - .size = @sizeOf(RectBorderUniforms), - }}, + .pushConstantSize = @sizeOf(RectUniforms), }, ); const rawData = [_]RectBorderVertex{ @@ -357,11 +349,7 @@ pub const draw = struct { // MARK: draw .depthStencilState = .{.depthTest = false, .depthWrite = false}, .blendState = .{.attachments = &.{.alphaBlending}, .formats = &.{.swapChain}}, .inputAssemblyState = .{.topology = .lineStrip}, - .pushConstantRanges = &.{.{ - .stageFlags = c.VK_SHADER_STAGE_VERTEX_BIT, - .offset = 0, - .size = @sizeOf(LineUniforms), - }}, + .pushConstantSize = @sizeOf(RectUniforms), }, ); const rawData = [_]SimpleVertex2D{ diff --git a/src/graphics/pipelines.zig b/src/graphics/pipelines.zig index 4f43caa8f7..985f4d3910 100644 --- a/src/graphics/pipelines.zig +++ b/src/graphics/pipelines.zig @@ -720,8 +720,12 @@ pub const Pipeline = struct { // MARK: Pipeline .sType = c.VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, .setLayoutCount = @intCast(descriptorSetLayouts.items.len), .pSetLayouts = descriptorSetLayouts.items.ptr, - .pushConstantRangeCount = @intCast(options.pushConstantRanges.len), - .pPushConstantRanges = options.pushConstantRanges.ptr, + .pushConstantRangeCount = if (options.pushConstantSize == 0) 0 else 1, + .pPushConstantRanges = &.{ + .stageFlags = c.VK_SHADER_STAGE_ALL_GRAPHICS, + .offset = 0, + .size = @intCast(options.pushConstantSize), + }, }; try vulkan.checkResultErr(c.vkCreatePipelineLayout(vulkan.device, &pipelineLayoutInfo, null, &self.pipelineLayout)); errdefer c.vkDestroyPipelineLayout(vulkan.device, self.pipelineLayout, null); @@ -770,7 +774,7 @@ pub const Pipeline = struct { // MARK: Pipeline blendState: ColorBlendState, inputAssemblyState: InputAssemblyState = .{}, bindings: []const DescriptorSetLayoutBinding = &.{}, - pushConstantRanges: []const c.VkPushConstantRange = &.{}, + pushConstantSize: usize = 0, }; pub fn init(vertexPath: []const u8, fragmentPath: []const u8, defines: []const u8, uniformStruct: anytype, VertexType: type, options: Options) Pipeline { From 4d3d0167f650b5445b21591a54a3e13ceaa2314a Mon Sep 17 00:00:00 2001 From: IntegratedQuantum Date: Sun, 16 Aug 2026 11:24:21 +0200 Subject: [PATCH 13/16] Fix validation errors --- src/graphics.zig | 6 +++--- src/graphics/CommandBuffer.zig | 4 ++-- src/graphics/pipelines.zig | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/graphics.zig b/src/graphics.zig index c91dfd40bb..00d128a751 100644 --- a/src/graphics.zig +++ b/src/graphics.zig @@ -212,7 +212,7 @@ pub const draw = struct { // MARK: draw .size = dim, .screen = .{@floatFromInt(viewport[2]), @floatFromInt(viewport[3])}, .rectColor = @bitCast(getColor()), - }, .{.stageFlags = c.VK_SHADER_STAGE_VERTEX_BIT}); + }); vulkan.currentFrame.guiCommands.bindVertexArray(rectVao); vulkan.currentFrame.guiCommands.draw(4, 0); } @@ -314,7 +314,7 @@ pub const draw = struct { // MARK: draw .screen = .{@floatFromInt(viewport[2]), @floatFromInt(viewport[3])}, .lineWidth = width, .rectColor = @bitCast(getColor()), - }, .{.stageFlags = c.VK_SHADER_STAGE_VERTEX_BIT}); + }); vulkan.currentFrame.guiCommands.bindVertexArray(rectBorderVao); vulkan.currentFrame.guiCommands.draw(10, 0); } @@ -392,7 +392,7 @@ pub const draw = struct { // MARK: draw .direction = pos2 - pos1, .screen = .{@floatFromInt(viewport[2]), @floatFromInt(viewport[3])}, .lineColor = @bitCast(getColor()), - }, .{.stageFlags = c.VK_SHADER_STAGE_VERTEX_BIT}); + }); vulkan.currentFrame.guiCommands.bindVertexArray(rectBorderVao); vulkan.currentFrame.guiCommands.draw(10, 0); } diff --git a/src/graphics/CommandBuffer.zig b/src/graphics/CommandBuffer.zig index 8f840602b2..517cd12701 100644 --- a/src/graphics/CommandBuffer.zig +++ b/src/graphics/CommandBuffer.zig @@ -189,8 +189,8 @@ pub fn bindVertexArray(self: CommandBuffer, buffer: main.graphics.VertexArray) v } } -pub fn pushConstants(self: CommandBuffer, pipeline: main.graphics.Pipeline, constants: anytype, options: struct { stageFlags: u32, offset: u32 = 0 }) void { - c.vkCmdPushConstants(self.handle, pipeline.pipelineLayout, options.stageFlags, options.offset, @sizeOf(@TypeOf(constants.*)), constants); +pub fn pushConstants(self: CommandBuffer, pipeline: main.graphics.Pipeline, constants: anytype) void { + c.vkCmdPushConstants(self.handle, pipeline.pipelineLayout, c.VK_SHADER_STAGE_ALL, 0, @sizeOf(@TypeOf(constants.*)), constants); } pub fn setViewport(self: CommandBuffer, viewport: c.VkViewport) void { diff --git a/src/graphics/pipelines.zig b/src/graphics/pipelines.zig index 985f4d3910..25a935ba54 100644 --- a/src/graphics/pipelines.zig +++ b/src/graphics/pipelines.zig @@ -722,7 +722,7 @@ pub const Pipeline = struct { // MARK: Pipeline .pSetLayouts = descriptorSetLayouts.items.ptr, .pushConstantRangeCount = if (options.pushConstantSize == 0) 0 else 1, .pPushConstantRanges = &.{ - .stageFlags = c.VK_SHADER_STAGE_ALL_GRAPHICS, + .stageFlags = c.VK_SHADER_STAGE_ALL, .offset = 0, .size = @intCast(options.pushConstantSize), }, From 14a4116befbf94552531b1c24e1fd25c33e7824e Mon Sep 17 00:00:00 2001 From: IntegratedQuantum Date: Sun, 16 Aug 2026 11:26:26 +0200 Subject: [PATCH 14/16] Remove drawCircle, it was never used and it can be easily reintroduced when needed --- assets/cubyz/shaders/graphics/Circle.frag | 19 ------- assets/cubyz/shaders/graphics/Circle.vert | 26 ---------- src/graphics.zig | 60 ----------------------- 3 files changed, 105 deletions(-) delete mode 100644 assets/cubyz/shaders/graphics/Circle.frag delete mode 100644 assets/cubyz/shaders/graphics/Circle.vert diff --git a/assets/cubyz/shaders/graphics/Circle.frag b/assets/cubyz/shaders/graphics/Circle.frag deleted file mode 100644 index 93f07bbce1..0000000000 --- a/assets/cubyz/shaders/graphics/Circle.frag +++ /dev/null @@ -1,19 +0,0 @@ -#version 460 - -layout(location = 0) out vec4 frag_color; - -layout(location = 0) in vec2 unitPosition; -layout(location = 1) flat in vec4 color; - -// Like smooth step, but with linear interpolation instead of s-curve. -float linearstep(float edge0, float edge1, float x) { - return clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0); -} - -void main(){ - float distSqr = sqrt(dot(unitPosition, unitPosition)); - float delta = fwidth(distSqr)/2; - float alpha = linearstep(1+delta, 1-delta, distSqr); - frag_color = color; - frag_color.a *= alpha; -} diff --git a/assets/cubyz/shaders/graphics/Circle.vert b/assets/cubyz/shaders/graphics/Circle.vert deleted file mode 100644 index 5946d1dcad..0000000000 --- a/assets/cubyz/shaders/graphics/Circle.vert +++ /dev/null @@ -1,26 +0,0 @@ -#version 460 - -layout(location = 0) in vec2 vertex_pos; - -layout(location = 0) out vec2 unitPosition; -layout(location = 1) flat out vec4 color; - -// in pixel -layout(location = 0) uniform vec2 center; -layout(location = 1) uniform float radius; -layout(location = 2) uniform vec2 screen; - -layout(location = 3) uniform int circleColor; - -void main() { - // Convert to opengl coordinates: - vec2 position_percentage = (center + vertex_pos*radius)/screen; - - vec2 position = vec2(position_percentage.x, -position_percentage.y)*2+vec2(-1, 1); - - gl_Position = vec4(position, 0, 1); - - color = vec4((circleColor & 0xff0000)>>16, (circleColor & 0xff00)>>8, circleColor & 0xff, (circleColor>>24) & 255)/255.0; - - unitPosition = vertex_pos; -} diff --git a/src/graphics.zig b/src/graphics.zig index 00d128a751..e69f1da52e 100644 --- a/src/graphics.zig +++ b/src/graphics.zig @@ -398,64 +398,6 @@ pub const draw = struct { // MARK: draw } } - // ---------------------------------------------------------------------------- - // MARK: fillCircle() - var circleUniforms: struct { - screen: c_int, - center: c_int, - radius: c_int, - circleColor: c_int, - } = undefined; - var circlePipeline: Pipeline = undefined; - var circleVao: VertexArray = undefined; - - fn initCircle() void { - circlePipeline = Pipeline.init( - "assets/cubyz/shaders/graphics/Circle.vert", - "assets/cubyz/shaders/graphics/Circle.frag", - "", - &circleUniforms, - SimpleVertex2D, - .{ - .rasterState = .{.cullMode = .none}, - .depthStencilState = .{.depthTest = false, .depthWrite = false}, - .blendState = .{.attachments = &.{.alphaBlending}, .formats = &.{.swapChain}}, - }, - ); - const rawData = [_]SimpleVertex2D{ - .{.pos = .{-1, -1}}, - .{.pos = .{-1, 1}}, - .{.pos = .{1, -1}}, - .{.pos = .{1, 1}}, - }; - - circleVao = .init(SimpleVertex2D, &rawData, null); - } - - fn deinitCircle() void { - circlePipeline.deinit(); - circleVao.deinit(); - } - - pub fn circle(_center: Vec2f, _radius: f32) void { - var center = _center; - var radius = _radius; - center *= @splat(scale); - center += translation; - radius *= scale; - circlePipeline.bind(getScissor()); - - var viewport: [4]c_int = undefined; - c.glGetIntegerv(c.GL_VIEWPORT, &viewport); - c.glUniform2f(circleUniforms.screen, @floatFromInt(viewport[2]), @floatFromInt(viewport[3])); - c.glUniform2f(circleUniforms.center, center[0], center[1]); // Move the coordinates, so they are in the center of a pixel. - c.glUniform1f(circleUniforms.radius, radius); // The height is a lot smaller because the inner edge of the rect is drawn. - c.glUniform1i(circleUniforms.circleColor, @bitCast(getColor())); - - circleVao.bind(); - c.glDrawArrays(c.GL_TRIANGLE_STRIP, 0, 4); - } - // ---------------------------------------------------------------------------- // MARK: drawImage() // Luckily the vao of the regular rect can used. @@ -1332,7 +1274,6 @@ const TextRendering = struct { // MARK: TextRendering pub fn init() void { // MARK: init() pipelines.init(); - draw.initCircle(); draw.initImage(); draw.initLine(); draw.initRect(); @@ -1346,7 +1287,6 @@ pub fn init() void { // MARK: init() pub fn deinit() void { frame_uniforms.deinit(); - draw.deinitCircle(); draw.deinitImage(); draw.deinitLine(); draw.deinitRect(); From cbea2ad8d0b4fe47275426e19cb46cf7f43745fd Mon Sep 17 00:00:00 2001 From: IntegratedQuantum Date: Sun, 16 Aug 2026 13:39:58 +0200 Subject: [PATCH 15/16] Enforce push constant limit --- src/graphics/pipelines.zig | 1 + 1 file changed, 1 insertion(+) diff --git a/src/graphics/pipelines.zig b/src/graphics/pipelines.zig index 25a935ba54..2e79a737fc 100644 --- a/src/graphics/pipelines.zig +++ b/src/graphics/pipelines.zig @@ -716,6 +716,7 @@ pub const Pipeline = struct { // MARK: Pipeline descriptorSetLayouts.append(main.stackAllocator, frameUniformDescriptorSetLayout); + std.debug.assert(options.pushConstantSize <= 128); // Some devices have a limit of just 128 bytes for push constants const pipelineLayoutInfo = c.VkPipelineLayoutCreateInfo{ // TODO: Configure push constants .sType = c.VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, .setLayoutCount = @intCast(descriptorSetLayouts.items.len), From 00464fa8de375fdd245eb86185ac2df20e376ea3 Mon Sep 17 00:00:00 2001 From: IntegratedQuantum Date: Sun, 16 Aug 2026 15:20:53 +0200 Subject: [PATCH 16/16] They should be extern --- src/graphics.zig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/graphics.zig b/src/graphics.zig index e69f1da52e..9e88593613 100644 --- a/src/graphics.zig +++ b/src/graphics.zig @@ -147,7 +147,7 @@ pub const draw = struct { // MARK: draw size: c_int, rectColor: c_int, } = undefined; - const RectUniforms = struct { + const RectUniforms = extern struct { start: [2]f32 align(8), size: [2]f32 align(8), screen: [2]f32 align(8), @@ -227,7 +227,7 @@ pub const draw = struct { // MARK: draw rectColor: c_int, lineWidth: c_int, } = undefined; - const RectBorderUniforms = struct { + const RectBorderUniforms = extern struct { start: [2]f32 align(8), size: [2]f32 align(8), screen: [2]f32 align(8), @@ -328,7 +328,7 @@ pub const draw = struct { // MARK: draw direction: c_int, lineColor: c_int, } = undefined; - const LineUniforms = struct { + const LineUniforms = extern struct { start: [2]f32 align(8), direction: [2]f32 align(8), screen: [2]f32 align(8),