diff --git a/src/rendering/Device.zig b/src/rendering/Device.zig index 972fc56..dd14ff0 100644 --- a/src/rendering/Device.zig +++ b/src/rendering/Device.zig @@ -17,6 +17,7 @@ graphics_family: u32, present_family: u32, device_properties: c.VkPhysicalDeviceProperties, memory_properties: c.VkPhysicalDeviceMemoryProperties, +msaa_samples: c.VkSampleCountFlags, const Self = @This(); diff --git a/src/rendering/GraphicsPipeline.zig b/src/rendering/GraphicsPipeline.zig index d477dfa..f750132 100644 --- a/src/rendering/GraphicsPipeline.zig +++ b/src/rendering/GraphicsPipeline.zig @@ -264,7 +264,7 @@ pub fn init(allocator: Allocator, device: vk.Device, swapchain: vk.Swapchain, re const multisampling_info: c.VkPipelineMultisampleStateCreateInfo = .{ .sType = c.VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, .sampleShadingEnable = c.VK_FALSE, - .rasterizationSamples = c.VK_SAMPLE_COUNT_1_BIT, + .rasterizationSamples = device.msaa_samples, }; const color_blend_attachment: c.VkPipelineColorBlendAttachmentState = .{ diff --git a/src/rendering/PhysicalDevice.zig b/src/rendering/PhysicalDevice.zig index 58bd40c..fe6a913 100644 --- a/src/rendering/PhysicalDevice.zig +++ b/src/rendering/PhysicalDevice.zig @@ -162,6 +162,14 @@ pub fn create_device(self: *PhysicalDevice, surface: vk.Surface, allocator: Allo var device_properties: c.VkPhysicalDeviceProperties = undefined; c.vkGetPhysicalDeviceProperties(self.handle, &device_properties); + const counts = device_properties.limits.framebufferColorSampleCounts & device_properties.limits.framebufferDepthSampleCounts; + var msaa_samples = c.VK_SAMPLE_COUNT_1_BIT; + if ((counts & c.VK_SAMPLE_COUNT_64_BIT) != 0) { msaa_samples = c.VK_SAMPLE_COUNT_64_BIT; } + if ((counts & c.VK_SAMPLE_COUNT_32_BIT) != 0) { msaa_samples = c.VK_SAMPLE_COUNT_32_BIT; } + if ((counts & c.VK_SAMPLE_COUNT_16_BIT) != 0) { msaa_samples = c.VK_SAMPLE_COUNT_16_BIT; } + if ((counts & c.VK_SAMPLE_COUNT_8_BIT) != 0) { msaa_samples = c.VK_SAMPLE_COUNT_8_BIT; } + if ((counts & c.VK_SAMPLE_COUNT_4_BIT) != 0) { msaa_samples = c.VK_SAMPLE_COUNT_4_BIT; } + if ((counts & c.VK_SAMPLE_COUNT_2_BIT) != 0) { msaa_samples = c.VK_SAMPLE_COUNT_2_BIT; } return .{ .handle = device, @@ -176,5 +184,6 @@ pub fn create_device(self: *PhysicalDevice, surface: vk.Surface, allocator: Allo .present_family = present_queue_index, .memory_properties = memory_properties, .device_properties = device_properties, + .msaa_samples = @bitCast(msaa_samples), }; } diff --git a/src/rendering/Renderer.zig b/src/rendering/Renderer.zig index 6893713..4e72a52 100644 --- a/src/rendering/Renderer.zig +++ b/src/rendering/Renderer.zig @@ -19,8 +19,7 @@ swapchain: vk.Swapchain, graphics_pipeline: vk.GraphicsPipeline, current_frame: u32, mesh: Mesh, -transform: math.Transform, -transform2: math.Transform, +transforms: std.ArrayList(math.Transform), previous_time: std.time.Instant, pub fn init(allocator: Allocator, instance_handle: vk.c.VkInstance, surface_handle: vk.c.VkSurfaceKHR) !Renderer { @@ -67,7 +66,7 @@ pub fn init(allocator: Allocator, instance_handle: vk.c.VkInstance, surface_hand graphics_pipeline.point_lights[0].diffuse = .{0.5, 0.5, 0.5}; graphics_pipeline.point_lights[0].specular = .{1.0, 1.0, 1.0}; - graphics_pipeline.point_lights[1].position = .{-1.0, 1.0, 0.0}; + graphics_pipeline.point_lights[1].position = .{1.0, 1.0, 0.0}; graphics_pipeline.point_lights[1].data[0] = 1.0; graphics_pipeline.point_lights[1].data[1] = 0.9; graphics_pipeline.point_lights[1].data[2] = 0.8; @@ -75,6 +74,11 @@ pub fn init(allocator: Allocator, instance_handle: vk.c.VkInstance, surface_hand graphics_pipeline.point_lights[1].diffuse = .{0.5, 0.5, 0.5}; graphics_pipeline.point_lights[1].specular = .{1.0, 1.0, 1.0}; + var transforms = std.ArrayList(math.Transform).init(allocator); + + try transforms.append(math.Transform.init(.{0.0, 0.0, -1.0}, .{0.5, 0.5, 0.5}, .{0.0, 0.0, 0.0})); + try transforms.append(math.Transform.init(.{0.0, 0.0, 0.0}, .{0.5, 0.5, 0.5}, .{0.0, 0.0, 0.0})); + return Renderer{ .instance = instance, .surface = surface, @@ -84,8 +88,7 @@ pub fn init(allocator: Allocator, instance_handle: vk.c.VkInstance, surface_hand .swapchain = swapchain, .graphics_pipeline = graphics_pipeline, .current_frame = 0, - .transform = math.Transform.init(.{0.0, 0.0, -1.0}, .{0.5, 0.5, 0.5}, .{0.0, 0.0, 0.0}), - .transform2 = math.Transform.init(.{0.0, 0.0, 0.0}, .{0.5, 0.5, 0.5}, .{0.0, 0.0, 0.0}), + .transforms = transforms, .previous_time = try std.time.Instant.now(), .mesh = mesh, }; @@ -118,15 +121,8 @@ pub fn render(pool: *ecs.Pool) anyerror!void { view_pos[2] = camera.position[2]; _ = delta_time; - //renderer.transform.rotate(math.rad(15) * delta_time, .{0.0, 1.0, 0.0}); - //renderer.transform2.rotate(math.rad(-15) * delta_time, .{0.0, 1.0, 0.0}); - - //renderer.transform.rotate(math.rad(15) * delta_time, .{1.0, 0.0, 0.0}); - //renderer.transform2.rotate(math.rad(-15) * delta_time, .{1.0, 0.0, 0.0}); const transform_memory = renderer.graphics_pipeline.transform_buffer.mapped_memory; - transform_memory[0] = renderer.transform; - transform_memory[1] = renderer.transform2; try renderer.device.waitFence(renderer.current_frame); const image = try renderer.swapchain.nextImage(renderer.device, renderer.current_frame); @@ -138,13 +134,16 @@ pub fn render(pool: *ecs.Pool) anyerror!void { renderer.device.bindIndexBuffer(renderer.graphics_pipeline.index_buffer, renderer.current_frame); renderer.device.bindDescriptorSets(renderer.graphics_pipeline, renderer.current_frame, 0); var lights: u32 = 2; - renderer.device.pushConstant(renderer.graphics_pipeline, c.VK_SHADER_STAGE_FRAGMENT_BIT, 0, 4, @ptrCast(&lights), renderer.current_frame); - var transform: u32 = 0; - renderer.device.pushConstant(renderer.graphics_pipeline, c.VK_SHADER_STAGE_VERTEX_BIT, 4, 4, @ptrCast(&transform), renderer.current_frame); - renderer.device.draw(renderer.mesh.index_count, renderer.current_frame, renderer.mesh); - transform = 1; - renderer.device.pushConstant(renderer.graphics_pipeline, c.VK_SHADER_STAGE_VERTEX_BIT, 4, 4, @ptrCast(&transform), renderer.current_frame); - renderer.device.draw(renderer.mesh.index_count, renderer.current_frame, renderer.mesh); + + for (renderer.transforms.items, 0..) |transform, i| { + transform_memory[i] = transform; + var index = i; + + renderer.device.pushConstant(renderer.graphics_pipeline, c.VK_SHADER_STAGE_FRAGMENT_BIT, 0, 4, @ptrCast(&lights), renderer.current_frame); + renderer.device.pushConstant(renderer.graphics_pipeline, c.VK_SHADER_STAGE_VERTEX_BIT, 4, 4, @ptrCast(&index), renderer.current_frame); + renderer.device.draw(renderer.mesh.index_count, renderer.current_frame, renderer.mesh); + } + renderer.render_pass.end(renderer.device, renderer.current_frame); try renderer.device.endCommand(renderer.current_frame); diff --git a/src/rendering/Swapchain.zig b/src/rendering/Swapchain.zig index 6aaa932..b5d9de0 100644 --- a/src/rendering/Swapchain.zig +++ b/src/rendering/Swapchain.zig @@ -11,6 +11,9 @@ image_views: []c.VkImageView, format: c.VkSurfaceFormatKHR, extent: c.VkExtent2D, framebuffers: []c.VkFramebuffer, +color_image: c.VkImage, +color_image_memory: c.VkDeviceMemory, +color_image_view: c.VkImageView, allocator: Allocator, @@ -133,13 +136,15 @@ pub fn init(allocator: Allocator, surface: vk.Surface, device: vk.Device, physic try vk.mapError(c.vkCreateImageView(device.handle, &view_create_info, null, &(image_views[index]))); } + const color_image, const color_image_view, const color_image_memory = try createColorResources(device, device.msaa_samples, format.format); + const framebuffers = try allocator.alloc(c.VkFramebuffer, image_count); for (image_views, 0..) |view, index| { - const attachments = &[_]c.VkImageView { view, render_pass.depth_view }; + const attachments = &[_]c.VkImageView {color_image_view, render_pass.depth_view, view}; const framebuffer_info: c.VkFramebufferCreateInfo = .{ .sType = c.VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, .renderPass = render_pass.handle, - .attachmentCount = 2, + .attachmentCount = 3, .pAttachments = attachments[0..].ptr, .width = extent.width, .height = extent.height, @@ -157,6 +162,9 @@ pub fn init(allocator: Allocator, surface: vk.Surface, device: vk.Device, physic .image_views = image_views[0..image_count], .framebuffers = framebuffers, .allocator = allocator, + .color_image = color_image, + .color_image_view = color_image_view, + .color_image_memory = color_image_memory, }; } @@ -168,6 +176,63 @@ pub fn nextImage(self: Self, device: vk.Device, frame: usize) !usize { return @intCast(index); } +fn createColorResources(device: vk.Device, samples: c.VkSampleCountFlags, format: c.VkFormat) !struct { c.VkImage, c.VkImageView, c.VkDeviceMemory } { + const create_info: c.VkImageCreateInfo = .{ + .sType = c.VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, + .imageType = c.VK_IMAGE_TYPE_2D, + .extent = .{ + .width = @intCast(800), + .height = @intCast(600), + .depth = 1, + }, + .mipLevels = 1, + .arrayLayers = 1, + .format = format, + .tiling = c.VK_IMAGE_TILING_OPTIMAL, + .initialLayout = c.VK_IMAGE_LAYOUT_UNDEFINED, + .usage = c.VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | c.VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, + .sharingMode = c.VK_SHARING_MODE_EXCLUSIVE, + .samples = samples, + .flags = 0, + }; + + var image: c.VkImage = undefined; + var image_memory: c.VkDeviceMemory = undefined; + try vk.mapError(c.vkCreateImage(device.handle, &create_info, null, &image)); + + var memory_requirements: c.VkMemoryRequirements = undefined; + c.vkGetImageMemoryRequirements(device.handle, image, &memory_requirements); + + const alloc_info: c.VkMemoryAllocateInfo = .{ + .sType = c.VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, + .allocationSize = memory_requirements.size, + .memoryTypeIndex = try device.findMemoryType(memory_requirements.memoryTypeBits, c.VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT), + }; + + try vk.mapError(c.vkAllocateMemory(device.handle, &alloc_info, null, &image_memory)); + try vk.mapError(c.vkBindImageMemory(device.handle, image, image_memory, 0)); + + const view_create_info: c.VkImageViewCreateInfo = .{ + .sType = c.VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, + .image = image, + .viewType = c.VK_IMAGE_VIEW_TYPE_2D, + .format = format, + .subresourceRange = .{ + .aspectMask = c.VK_IMAGE_ASPECT_COLOR_BIT, + .baseMipLevel = 0, + .levelCount = 1, + .baseArrayLayer = 0, + .layerCount = 1, + }, + }; + + var image_view: c.VkImageView = undefined; + + try vk.mapError(c.vkCreateImageView(device.handle, &view_create_info, null, &image_view)); + + return .{ image, image_view, image_memory }; +} + pub fn deinit(self: Self, device: vk.Device) void { for (self.image_views) |view| { c.vkDestroyImageView(device.handle, view, null); diff --git a/src/rendering/vulkan.zig b/src/rendering/vulkan.zig index 5e27035..99a7c59 100644 --- a/src/rendering/vulkan.zig +++ b/src/rendering/vulkan.zig @@ -150,17 +150,19 @@ pub const RenderPass = struct { const Self = @This(); pub fn init(allocator: Allocator, device: Device, surface: Surface, physical_device: PhysicalDevice) !Self { + const swapchain_format = (try Swapchain.pickFormat(allocator, surface, physical_device)).format; + const depth_image, const depth_view , const depth_memory, const depth_format = try createDepthResources(device, physical_device); const color_attachment: c.VkAttachmentDescription = .{ - .format = (try Swapchain.pickFormat(allocator, surface, physical_device)).format, - .samples = c.VK_SAMPLE_COUNT_1_BIT, + .format = swapchain_format, + .samples = device.msaa_samples, .loadOp = c.VK_ATTACHMENT_LOAD_OP_CLEAR, .storeOp = c.VK_ATTACHMENT_STORE_OP_STORE, .stencilLoadOp = c.VK_ATTACHMENT_LOAD_OP_DONT_CARE, .stencilStoreOp = c.VK_ATTACHMENT_STORE_OP_DONT_CARE, .initialLayout = c.VK_IMAGE_LAYOUT_UNDEFINED, - .finalLayout = c.VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, + .finalLayout = c.VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, }; const color_attachment_reference: c.VkAttachmentReference = .{ @@ -168,9 +170,25 @@ pub const RenderPass = struct { .layout = c.VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, }; + const color_attachment_resolve: c.VkAttachmentDescription = .{ + .format = swapchain_format, + .samples = c.VK_SAMPLE_COUNT_1_BIT, + .loadOp = c.VK_ATTACHMENT_LOAD_OP_DONT_CARE, + .storeOp = c.VK_ATTACHMENT_STORE_OP_DONT_CARE, + .stencilLoadOp = c.VK_ATTACHMENT_LOAD_OP_DONT_CARE, + .stencilStoreOp = c.VK_ATTACHMENT_STORE_OP_DONT_CARE, + .initialLayout = c.VK_IMAGE_LAYOUT_UNDEFINED, + .finalLayout = c.VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, + }; + + const color_attachment_resolve_reference: c.VkAttachmentReference = .{ + .attachment = 2, + .layout = c.VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + }; + const depth_attachment: c.VkAttachmentDescription = .{ .format = depth_format, - .samples = c.VK_SAMPLE_COUNT_1_BIT, + .samples = device.msaa_samples, .loadOp = c.VK_ATTACHMENT_LOAD_OP_CLEAR, .storeOp = c.VK_ATTACHMENT_STORE_OP_DONT_CARE, .stencilLoadOp = c.VK_ATTACHMENT_LOAD_OP_DONT_CARE, @@ -189,22 +207,23 @@ pub const RenderPass = struct { .colorAttachmentCount = 1, .pColorAttachments = &color_attachment_reference, .pDepthStencilAttachment = &depth_attachment_reference, + .pResolveAttachments = &color_attachment_resolve_reference, }; const dependency: c.VkSubpassDependency = .{ .srcSubpass = c.VK_SUBPASS_EXTERNAL, .dstSubpass = 0, .srcStageMask = c.VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | c.VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, - .srcAccessMask = c.VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + .srcAccessMask = c.VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | c.VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, .dstStageMask = c.VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | c.VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, .dstAccessMask = c.VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | c.VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, }; - const attachments = &[_]c.VkAttachmentDescription { color_attachment, depth_attachment }; + const attachments = &[_]c.VkAttachmentDescription { color_attachment, depth_attachment, color_attachment_resolve }; const render_pass_info: c.VkRenderPassCreateInfo = .{ .sType = c.VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, - .attachmentCount = 2, + .attachmentCount = 3, .pAttachments = attachments[0..].ptr, .subpassCount = 1, .pSubpasses = &subpass, @@ -289,7 +308,7 @@ pub const RenderPass = struct { .initialLayout = c.VK_IMAGE_LAYOUT_UNDEFINED, .usage = c.VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, .sharingMode = c.VK_SHARING_MODE_EXCLUSIVE, - .samples = c.VK_SAMPLE_COUNT_1_BIT, + .samples = device.msaa_samples, .flags = 0, };