Add chess GUI and move generation
This commit is contained in:
+101
-38
@@ -15,6 +15,15 @@ pub const VertexBufferContext = struct {
|
||||
ldc.vkd.freeMemory(ldc.device, self.memory, null);
|
||||
}
|
||||
};
|
||||
pub const BufferContext = struct {
|
||||
buffer: vk.Buffer,
|
||||
memory: vk.DeviceMemory,
|
||||
|
||||
pub fn destroy(self: *const BufferContext, ldc: *const device.LogicalDeviceContext) void {
|
||||
ldc.vkd.destroyBuffer(ldc.device, self.buffer, null);
|
||||
ldc.vkd.freeMemory(ldc.device, self.memory, null);
|
||||
}
|
||||
};
|
||||
|
||||
pub fn initVertexBuffer(
|
||||
vc: context.VulkanContext,
|
||||
@@ -22,50 +31,24 @@ pub fn initVertexBuffer(
|
||||
vertices: []const geometry.Vertex,
|
||||
) !VertexBufferContext {
|
||||
const buffer_size: vk.DeviceSize = @intCast(@sizeOf(geometry.Vertex) * vertices.len);
|
||||
|
||||
const buffer_create_info = vk.BufferCreateInfo{
|
||||
.size = buffer_size,
|
||||
.usage = .{
|
||||
.vertex_buffer_bit = true,
|
||||
},
|
||||
.sharing_mode = .exclusive,
|
||||
const usage: vk.BufferUsageFlags = .{
|
||||
.vertex_buffer_bit = true,
|
||||
};
|
||||
const memory_properties: vk.MemoryPropertyFlags = .{
|
||||
.host_visible_bit = true,
|
||||
.host_coherent_bit = true,
|
||||
};
|
||||
|
||||
const buffer = try ldc.vkd.createBuffer(ldc.device, &buffer_create_info, null);
|
||||
errdefer ldc.vkd.destroyBuffer(ldc.device, buffer, null);
|
||||
|
||||
const memory_requirements = ldc.vkd.getBufferMemoryRequirements(
|
||||
ldc.device,
|
||||
buffer,
|
||||
);
|
||||
const memory_index = try findMemoryType(
|
||||
vc,
|
||||
ldc,
|
||||
memory_requirements.memory_type_bits,
|
||||
.{
|
||||
.host_visible_bit = true,
|
||||
.host_coherent_bit = true,
|
||||
},
|
||||
);
|
||||
|
||||
const alloc_info = vk.MemoryAllocateInfo{
|
||||
.allocation_size = memory_requirements.size,
|
||||
.memory_type_index = memory_index,
|
||||
};
|
||||
|
||||
const memory = try ldc.vkd.allocateMemory(ldc.device, &alloc_info, null);
|
||||
errdefer ldc.vkd.freeMemory(ldc.device, memory, null);
|
||||
|
||||
try ldc.vkd.bindBufferMemory(ldc.device, buffer, memory, 0);
|
||||
const buffer_context = try createBuffer(vc, ldc, buffer_size, usage, memory_properties);
|
||||
|
||||
const mapped = try ldc.vkd.mapMemory(
|
||||
ldc.device,
|
||||
memory,
|
||||
buffer_context.memory,
|
||||
0,
|
||||
buffer_size,
|
||||
.{},
|
||||
);
|
||||
defer ldc.vkd.unmapMemory(ldc.device, memory);
|
||||
defer ldc.vkd.unmapMemory(ldc.device, buffer_context.memory);
|
||||
|
||||
const dst: [*]u8 = @ptrCast(mapped);
|
||||
const dst_slice = dst[0..buffer_size];
|
||||
@@ -74,13 +57,13 @@ pub fn initVertexBuffer(
|
||||
std.mem.copyForwards(u8, dst_slice, src_bytes);
|
||||
|
||||
return .{
|
||||
.buffer = buffer,
|
||||
.memory = memory,
|
||||
.buffer = buffer_context.buffer,
|
||||
.memory = buffer_context.memory,
|
||||
.vertex_count = @intCast(vertices.len),
|
||||
};
|
||||
}
|
||||
|
||||
fn findMemoryType(
|
||||
pub fn findMemoryType(
|
||||
vc: context.VulkanContext,
|
||||
ldc: device.LogicalDeviceContext,
|
||||
type_filter: u32,
|
||||
@@ -107,3 +90,83 @@ fn findMemoryType(
|
||||
|
||||
return error.NoSuitableMemoryType;
|
||||
}
|
||||
|
||||
pub fn createBuffer(
|
||||
vc: context.VulkanContext,
|
||||
ldc: device.LogicalDeviceContext,
|
||||
size: vk.DeviceSize,
|
||||
usage: vk.BufferUsageFlags,
|
||||
properties: vk.MemoryPropertyFlags,
|
||||
) !BufferContext {
|
||||
const buffer_create_info = vk.BufferCreateInfo{
|
||||
.size = size,
|
||||
.usage = usage,
|
||||
.sharing_mode = .exclusive,
|
||||
};
|
||||
|
||||
const buffer = try ldc.vkd.createBuffer(ldc.device, &buffer_create_info, null);
|
||||
errdefer ldc.vkd.destroyBuffer(ldc.device, buffer, null);
|
||||
|
||||
const memory_requirements = ldc.vkd.getBufferMemoryRequirements(
|
||||
ldc.device,
|
||||
buffer,
|
||||
);
|
||||
const memory_index = try findMemoryType(
|
||||
vc,
|
||||
ldc,
|
||||
memory_requirements.memory_type_bits,
|
||||
properties,
|
||||
);
|
||||
|
||||
const alloc_info = vk.MemoryAllocateInfo{
|
||||
.allocation_size = memory_requirements.size,
|
||||
.memory_type_index = memory_index,
|
||||
};
|
||||
|
||||
const memory = try ldc.vkd.allocateMemory(ldc.device, &alloc_info, null);
|
||||
errdefer ldc.vkd.freeMemory(ldc.device, memory, null);
|
||||
|
||||
try ldc.vkd.bindBufferMemory(ldc.device, buffer, memory, 0);
|
||||
|
||||
return .{
|
||||
.buffer = buffer,
|
||||
.memory = memory,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn initStagingBuffer(
|
||||
vc: context.VulkanContext,
|
||||
ldc: device.LogicalDeviceContext,
|
||||
bytes: []const u8,
|
||||
) !BufferContext {
|
||||
const buffer_size: vk.DeviceSize = @intCast(bytes.len);
|
||||
|
||||
const buffer_context = try createBuffer(
|
||||
vc,
|
||||
ldc,
|
||||
buffer_size,
|
||||
.{
|
||||
.transfer_src_bit = true,
|
||||
},
|
||||
.{
|
||||
.host_visible_bit = true,
|
||||
.host_coherent_bit = true,
|
||||
},
|
||||
);
|
||||
|
||||
const mapped = try ldc.vkd.mapMemory(
|
||||
ldc.device,
|
||||
buffer_context.memory,
|
||||
0,
|
||||
buffer_size,
|
||||
.{},
|
||||
);
|
||||
defer ldc.vkd.unmapMemory(ldc.device, buffer_context.memory);
|
||||
|
||||
const dst: [*]u8 = @ptrCast(mapped);
|
||||
const dst_slice = dst[0..buffer_size];
|
||||
|
||||
std.mem.copyForwards(u8, dst_slice, bytes);
|
||||
|
||||
return buffer_context;
|
||||
}
|
||||
|
||||
+124
-31
@@ -1,4 +1,5 @@
|
||||
const std = @import("std");
|
||||
const log = std.log.scoped(.graphics);
|
||||
const vk = @import("vulkan");
|
||||
|
||||
const device = @import("device.zig");
|
||||
@@ -7,6 +8,8 @@ const render_pass = @import("render_pass.zig");
|
||||
const swapchain = @import("swapchain.zig");
|
||||
const pipeline = @import("pipeline.zig");
|
||||
const buffer = @import("buffer.zig");
|
||||
const descriptors = @import("descriptors.zig");
|
||||
const piece_render = @import("../piece_render.zig");
|
||||
|
||||
pub const CommandContext = struct {
|
||||
command_pool: vk.CommandPool,
|
||||
@@ -19,13 +22,8 @@ pub const CommandContext = struct {
|
||||
}
|
||||
};
|
||||
|
||||
pub fn initCommandBuffers(
|
||||
pub fn initCommandPoolOnly(
|
||||
ldc: device.LogicalDeviceContext,
|
||||
render_pass_context: render_pass.RenderPassContext,
|
||||
framebuffer_context: framebuffers.FramebufferContext,
|
||||
pipeline_context: pipeline.PipelineContext,
|
||||
swapchain_context: swapchain.SwapchainContext,
|
||||
vertex_buffer_context: buffer.VertexBufferContext,
|
||||
allocator: std.mem.Allocator,
|
||||
) !CommandContext {
|
||||
const command_pool_create_info = vk.CommandPoolCreateInfo{
|
||||
@@ -41,32 +39,56 @@ pub fn initCommandBuffers(
|
||||
null,
|
||||
);
|
||||
errdefer ldc.vkd.destroyCommandPool(ldc.device, command_pool, null);
|
||||
std.debug.print("created command pool\n", .{});
|
||||
|
||||
const command_buffers = try allocator.alloc(vk.CommandBuffer, framebuffer_context.framebuffers.len);
|
||||
const command_buffers = try allocator.alloc(vk.CommandBuffer, 0);
|
||||
errdefer allocator.free(command_buffers);
|
||||
|
||||
const command_buffer_allocate_info = vk.CommandBufferAllocateInfo{
|
||||
return .{
|
||||
.command_pool = command_pool,
|
||||
.command_buffers = command_buffers,
|
||||
.allocator = allocator,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn initCommandBuffers(
|
||||
ldc: device.LogicalDeviceContext,
|
||||
render_pass_context: render_pass.RenderPassContext,
|
||||
framebuffer_context: framebuffers.FramebufferContext,
|
||||
board_pipeline_context: pipeline.PipelineContext,
|
||||
piece_pipeline_context: pipeline.PipelineContext,
|
||||
descriptor_contexts: [piece_render.PieceGroupCount]?descriptors.DescriptorContext,
|
||||
swapchain_context: swapchain.SwapchainContext,
|
||||
board_vertex_buffer_context: buffer.VertexBufferContext,
|
||||
piece_vertex_buffers: [piece_render.PieceGroupCount]?buffer.VertexBufferContext,
|
||||
allocator: std.mem.Allocator,
|
||||
) !CommandContext {
|
||||
var command_context = try initCommandPoolOnly(ldc, allocator);
|
||||
errdefer command_context.destroy(&ldc);
|
||||
log.debug("created command pool", .{});
|
||||
|
||||
allocator.free(command_context.command_buffers);
|
||||
command_context.command_buffers = try allocator.alloc(vk.CommandBuffer, framebuffer_context.framebuffers.len);
|
||||
errdefer allocator.free(command_context.command_buffers);
|
||||
|
||||
const command_buffer_allocate_info = vk.CommandBufferAllocateInfo{
|
||||
.command_pool = command_context.command_pool,
|
||||
.level = .primary,
|
||||
.command_buffer_count = @intCast(command_buffers.len),
|
||||
.command_buffer_count = @intCast(command_context.command_buffers.len),
|
||||
};
|
||||
|
||||
try ldc.vkd.allocateCommandBuffers(
|
||||
ldc.device,
|
||||
&command_buffer_allocate_info,
|
||||
command_buffers.ptr,
|
||||
command_context.command_buffers.ptr,
|
||||
);
|
||||
|
||||
std.debug.print("allocated command buffers: {}\n", .{command_buffers.len});
|
||||
log.debug("allocated command buffers: {}", .{command_context.command_buffers.len});
|
||||
|
||||
for (command_buffers, 0..) |command_buffer, i| {
|
||||
for (command_context.command_buffers, 0..) |command_buffer, i| {
|
||||
const begin_info = vk.CommandBufferBeginInfo{};
|
||||
|
||||
try ldc.vkd.beginCommandBuffer(command_buffer, &begin_info);
|
||||
|
||||
// This is the only "drawing" currently happening: begin a render pass
|
||||
// and clear the swapchain image. The embedded shaders are not used yet.
|
||||
const clear_color = vk.ClearValue{
|
||||
.color = .{
|
||||
.float_32 = .{ 0.02, 0.02, 0.08, 1.0 },
|
||||
@@ -93,36 +115,107 @@ pub fn initCommandBuffers(
|
||||
ldc.vkd.cmdBindPipeline(
|
||||
command_buffer,
|
||||
.graphics,
|
||||
pipeline_context.graphics_pipeline,
|
||||
board_pipeline_context.graphics_pipeline,
|
||||
);
|
||||
|
||||
const vertex_buffers = [_]vk.Buffer{
|
||||
vertex_buffer_context.buffer,
|
||||
};
|
||||
|
||||
const offsets = [_]vk.DeviceSize{
|
||||
0,
|
||||
};
|
||||
const board_vertex_buffers = [_]vk.Buffer{board_vertex_buffer_context.buffer};
|
||||
const board_offsets = [_]vk.DeviceSize{0};
|
||||
|
||||
ldc.vkd.cmdBindVertexBuffers(
|
||||
command_buffer,
|
||||
0,
|
||||
&vertex_buffers,
|
||||
&offsets,
|
||||
&board_vertex_buffers,
|
||||
&board_offsets,
|
||||
);
|
||||
|
||||
ldc.vkd.cmdDraw(command_buffer, vertex_buffer_context.vertex_count, 1, 0, 0);
|
||||
ldc.vkd.cmdDraw(command_buffer, board_vertex_buffer_context.vertex_count, 1, 0, 0);
|
||||
|
||||
ldc.vkd.cmdBindPipeline(
|
||||
command_buffer,
|
||||
.graphics,
|
||||
piece_pipeline_context.graphics_pipeline,
|
||||
);
|
||||
|
||||
for (piece_vertex_buffers, descriptor_contexts) |maybe_piece_buffer, maybe_descriptor_context| {
|
||||
const piece_buffer = maybe_piece_buffer orelse continue;
|
||||
const piece_descriptor_context = maybe_descriptor_context orelse continue;
|
||||
|
||||
const descriptor_sets = [_]vk.DescriptorSet{piece_descriptor_context.descriptor_set};
|
||||
ldc.vkd.cmdBindDescriptorSets(
|
||||
command_buffer,
|
||||
.graphics,
|
||||
piece_pipeline_context.pipeline_layout,
|
||||
0,
|
||||
&descriptor_sets,
|
||||
null,
|
||||
);
|
||||
|
||||
const piece_buffers = [_]vk.Buffer{piece_buffer.buffer};
|
||||
const piece_offsets = [_]vk.DeviceSize{0};
|
||||
|
||||
ldc.vkd.cmdBindVertexBuffers(
|
||||
command_buffer,
|
||||
0,
|
||||
&piece_buffers,
|
||||
&piece_offsets,
|
||||
);
|
||||
|
||||
ldc.vkd.cmdDraw(command_buffer, piece_buffer.vertex_count, 1, 0, 0);
|
||||
}
|
||||
|
||||
ldc.vkd.cmdEndRenderPass(command_buffer);
|
||||
|
||||
try ldc.vkd.endCommandBuffer(command_buffer);
|
||||
}
|
||||
|
||||
std.debug.print("recorded command buffers\n", .{});
|
||||
log.debug("recorded command buffers", .{});
|
||||
|
||||
return .{
|
||||
.command_pool = command_pool,
|
||||
.command_buffers = command_buffers,
|
||||
.allocator = allocator,
|
||||
return command_context;
|
||||
}
|
||||
|
||||
pub fn beginSingleTimeCommands(
|
||||
ldc: device.LogicalDeviceContext,
|
||||
command_context: CommandContext,
|
||||
) !vk.CommandBuffer {
|
||||
const command_buffer_allocate_info = vk.CommandBufferAllocateInfo{
|
||||
.command_pool = command_context.command_pool,
|
||||
.level = .primary,
|
||||
.command_buffer_count = 1,
|
||||
};
|
||||
|
||||
var command_buffer: vk.CommandBuffer = undefined;
|
||||
try ldc.vkd.allocateCommandBuffers(
|
||||
ldc.device,
|
||||
&command_buffer_allocate_info,
|
||||
@ptrCast(&command_buffer),
|
||||
);
|
||||
|
||||
const begin_info = vk.CommandBufferBeginInfo{
|
||||
.flags = .{
|
||||
.one_time_submit_bit = true,
|
||||
},
|
||||
};
|
||||
|
||||
try ldc.vkd.beginCommandBuffer(command_buffer, &begin_info);
|
||||
|
||||
return command_buffer;
|
||||
}
|
||||
|
||||
pub fn endSingleTimeCommands(
|
||||
ldc: device.LogicalDeviceContext,
|
||||
command_context: CommandContext,
|
||||
command_buffer: vk.CommandBuffer,
|
||||
) !void {
|
||||
try ldc.vkd.endCommandBuffer(command_buffer);
|
||||
|
||||
const command_buffers = [_]vk.CommandBuffer{command_buffer};
|
||||
|
||||
const submit_info = vk.SubmitInfo{
|
||||
.command_buffer_count = command_buffers.len,
|
||||
.p_command_buffers = &command_buffers,
|
||||
};
|
||||
|
||||
try ldc.vkd.queueSubmit(ldc.graphics_queue, &[_]vk.SubmitInfo{submit_info}, .null_handle);
|
||||
try ldc.vkd.queueWaitIdle(ldc.graphics_queue);
|
||||
ldc.vkd.freeCommandBuffers(ldc.device, command_context.command_pool, &command_buffers);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
const std = @import("std");
|
||||
const log = std.log.scoped(.graphics);
|
||||
const glfw = @import("zglfw");
|
||||
const vk = @import("vulkan");
|
||||
|
||||
@@ -16,9 +17,9 @@ pub fn initInstance(name: [:0]const u8) !VulkanContext {
|
||||
const base = vk.BaseWrapper.load(glfw.getInstanceProcAddress);
|
||||
const required_extensions = try glfw.getRequiredInstanceExtensions();
|
||||
|
||||
std.debug.print("Required instance extensions:\n", .{});
|
||||
log.debug("Required instance extensions:", .{});
|
||||
for (required_extensions) |extension| {
|
||||
std.debug.print(" {s}\n", .{extension});
|
||||
log.debug(" {s}", .{extension});
|
||||
}
|
||||
const app_info = vk.ApplicationInfo{
|
||||
.p_application_name = name,
|
||||
@@ -35,7 +36,7 @@ pub fn initInstance(name: [:0]const u8) !VulkanContext {
|
||||
};
|
||||
|
||||
const instance = try base.createInstance(&instance_create_info, null);
|
||||
std.debug.print("Created Vulkan Instance\n", .{});
|
||||
log.debug("Created Vulkan Instance", .{});
|
||||
|
||||
const vki = vk.InstanceWrapper.load(instance, base.dispatch.vkGetInstanceProcAddr.?);
|
||||
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
const vk = @import("vulkan");
|
||||
|
||||
const device = @import("device.zig");
|
||||
const pipeline = @import("pipeline.zig");
|
||||
const texture = @import("texture.zig");
|
||||
|
||||
pub const DescriptorContext = struct {
|
||||
descriptor_pool: vk.DescriptorPool,
|
||||
descriptor_set: vk.DescriptorSet,
|
||||
|
||||
pub fn destroy(self: *const DescriptorContext, ldc: *const device.LogicalDeviceContext) void {
|
||||
ldc.vkd.destroyDescriptorPool(ldc.device, self.descriptor_pool, null);
|
||||
}
|
||||
};
|
||||
|
||||
pub fn initTextureDescriptor(
|
||||
ldc: device.LogicalDeviceContext,
|
||||
pipeline_context: pipeline.PipelineContext,
|
||||
texture_context: texture.TextureContext,
|
||||
) !DescriptorContext {
|
||||
const pool_size = vk.DescriptorPoolSize{
|
||||
.type = .combined_image_sampler,
|
||||
.descriptor_count = 1,
|
||||
};
|
||||
|
||||
const pool_sizes = [_]vk.DescriptorPoolSize{pool_size};
|
||||
|
||||
const pool_info = vk.DescriptorPoolCreateInfo{
|
||||
.max_sets = 1,
|
||||
.pool_size_count = pool_sizes.len,
|
||||
.p_pool_sizes = &pool_sizes,
|
||||
};
|
||||
|
||||
const descriptor_pool = try ldc.vkd.createDescriptorPool(
|
||||
ldc.device,
|
||||
&pool_info,
|
||||
null,
|
||||
);
|
||||
errdefer ldc.vkd.destroyDescriptorPool(ldc.device, descriptor_pool, null);
|
||||
|
||||
const set_layouts = [_]vk.DescriptorSetLayout{
|
||||
pipeline_context.descriptor_set_layout,
|
||||
};
|
||||
|
||||
const alloc_info = vk.DescriptorSetAllocateInfo{
|
||||
.descriptor_pool = descriptor_pool,
|
||||
.descriptor_set_count = set_layouts.len,
|
||||
.p_set_layouts = &set_layouts,
|
||||
};
|
||||
|
||||
var descriptor_sets: [1]vk.DescriptorSet = undefined;
|
||||
try ldc.vkd.allocateDescriptorSets(
|
||||
ldc.device,
|
||||
&alloc_info,
|
||||
&descriptor_sets,
|
||||
);
|
||||
|
||||
const descriptor_set = descriptor_sets[0];
|
||||
|
||||
const image_info = vk.DescriptorImageInfo{
|
||||
.image_layout = .shader_read_only_optimal,
|
||||
.image_view = texture_context.image_view,
|
||||
.sampler = texture_context.sampler,
|
||||
};
|
||||
|
||||
const image_infos = [_]vk.DescriptorImageInfo{image_info};
|
||||
|
||||
const descriptor_write = vk.WriteDescriptorSet{
|
||||
.dst_set = descriptor_set,
|
||||
.dst_binding = 0,
|
||||
.dst_array_element = 0,
|
||||
.descriptor_count = 1,
|
||||
.descriptor_type = .combined_image_sampler,
|
||||
.p_image_info = &image_infos,
|
||||
.p_buffer_info = undefined,
|
||||
.p_texel_buffer_view = undefined,
|
||||
};
|
||||
|
||||
const descriptor_writes = [_]vk.WriteDescriptorSet{descriptor_write};
|
||||
|
||||
ldc.vkd.updateDescriptorSets(
|
||||
ldc.device,
|
||||
&descriptor_writes,
|
||||
null,
|
||||
);
|
||||
|
||||
return .{
|
||||
.descriptor_pool = descriptor_pool,
|
||||
.descriptor_set = descriptor_set,
|
||||
};
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
const std = @import("std");
|
||||
const log = std.log.scoped(.graphics);
|
||||
const vk = @import("vulkan");
|
||||
|
||||
const context = @import("context.zig");
|
||||
@@ -41,11 +42,11 @@ pub fn initLogicalDevice(
|
||||
|
||||
const device = try vc.vki.createDevice(physical_device, &device_create_info, null);
|
||||
errdefer vc.vki.destroyDevice(device, null);
|
||||
std.debug.print("created logical device\n", .{});
|
||||
log.debug("created logical device", .{});
|
||||
|
||||
const vkd = vk.DeviceWrapper.load(device, vc.vki.dispatch.vkGetDeviceProcAddr.?);
|
||||
const graphics_queue = vkd.getDeviceQueue(device, graphics_queue_family_index, 0);
|
||||
std.debug.print("retrieved graphics queue\n", .{});
|
||||
log.debug("retrieved graphics queue", .{});
|
||||
|
||||
return .{
|
||||
.physical_device = physical_device,
|
||||
@@ -61,11 +62,11 @@ pub fn debugPhysicalGPUs(
|
||||
physical_devices: []vk.PhysicalDevice,
|
||||
surface: vk.SurfaceKHR,
|
||||
) !void {
|
||||
std.debug.print("physical devices: {}\n", .{physical_devices.len});
|
||||
log.debug("physical devices: {}", .{physical_devices.len});
|
||||
|
||||
for (physical_devices, 0..) |physical_device, i| {
|
||||
const props = vc.vki.getPhysicalDeviceProperties(physical_device);
|
||||
std.debug.print("device {}: {s}\n", .{ i, std.mem.sliceTo(&props.device_name, 0) });
|
||||
log.debug("device {}: {s}", .{ i, std.mem.sliceTo(&props.device_name, 0) });
|
||||
const queue_families = try vc.vki.getPhysicalDeviceQueueFamilyPropertiesAlloc(
|
||||
physical_device,
|
||||
std.heap.page_allocator,
|
||||
@@ -83,8 +84,8 @@ pub fn debugPhysicalGPUs(
|
||||
surface,
|
||||
);
|
||||
|
||||
std.debug.print(
|
||||
" queue {}: count={}, graphics={}, compute={}, transfer={}, present={}\n",
|
||||
log.debug(
|
||||
" queue {}: count={}, graphics={}, compute={}, transfer={}, present={}",
|
||||
.{
|
||||
queue_index,
|
||||
queue_family.queue_count,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
const std = @import("std");
|
||||
const log = std.log.scoped(.graphics);
|
||||
const vk = @import("vulkan");
|
||||
|
||||
const commands = @import("commands.zig");
|
||||
@@ -33,7 +34,7 @@ pub fn drawFrame(
|
||||
|
||||
const image_index = image_result.image_index;
|
||||
const should_recreate_after_present = image_result.result == .suboptimal_khr;
|
||||
std.debug.print("Acquired swapchain image: {}\n", .{image_index});
|
||||
log.debug("Acquired swapchain image: {}", .{image_index});
|
||||
|
||||
try ldc.vkd.resetFences(ldc.device, &wait_fences);
|
||||
|
||||
@@ -76,7 +77,7 @@ pub fn drawFrame(
|
||||
error.OutOfDateKHR => return .Recreate,
|
||||
else => return err,
|
||||
};
|
||||
std.debug.print("Presented one frame\n", .{});
|
||||
log.debug("Presented one frame", .{});
|
||||
|
||||
if (should_recreate_after_present or present_result == .suboptimal_khr) {
|
||||
return FrameResult.Recreate;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
const std = @import("std");
|
||||
const log = std.log.scoped(.graphics);
|
||||
const vk = @import("vulkan");
|
||||
|
||||
const device = @import("device.zig");
|
||||
@@ -53,7 +54,7 @@ pub fn initFramebuffers(
|
||||
created_framebuffer_count += 1;
|
||||
}
|
||||
|
||||
std.debug.print("created framebuffers: {}\n", .{framebuffers.len});
|
||||
log.debug("created framebuffers: {}", .{framebuffers.len});
|
||||
|
||||
return .{
|
||||
.framebuffers = framebuffers,
|
||||
|
||||
+120
-23
@@ -7,10 +7,14 @@ const geometry = @import("../geometry.zig");
|
||||
pub const PipelineContext = struct {
|
||||
graphics_pipeline: vk.Pipeline,
|
||||
pipeline_layout: vk.PipelineLayout,
|
||||
descriptor_set_layout: vk.DescriptorSetLayout = .null_handle,
|
||||
|
||||
pub fn destroy(self: *const PipelineContext, ldc: *const device.LogicalDeviceContext) void {
|
||||
ldc.vkd.destroyPipeline(ldc.device, self.graphics_pipeline, null);
|
||||
ldc.vkd.destroyPipelineLayout(ldc.device, self.pipeline_layout, null);
|
||||
if (self.descriptor_set_layout != .null_handle) {
|
||||
ldc.vkd.destroyDescriptorSetLayout(ldc.device, self.descriptor_set_layout, null);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -31,8 +35,112 @@ pub fn createShaderModule(ldc: device.LogicalDeviceContext, allocator: std.mem.A
|
||||
return try ldc.vkd.createShaderModule(ldc.device, &create_info, null);
|
||||
}
|
||||
|
||||
pub fn initPipelineContext(ldc: device.LogicalDeviceContext, extent: vk.Extent2D, render_pass: vk.RenderPass, vert_spv: []const u8, frag_spv: []const u8, allocator: std.mem.Allocator) !PipelineContext {
|
||||
const pipeline_layout_create_info = vk.PipelineLayoutCreateInfo{};
|
||||
pub fn initBoardPipelineContext(ldc: device.LogicalDeviceContext, extent: vk.Extent2D, render_pass: vk.RenderPass, vert_spv: []const u8, frag_spv: []const u8, allocator: std.mem.Allocator) !PipelineContext {
|
||||
const attribute_descriptions = [_]vk.VertexInputAttributeDescription{
|
||||
.{
|
||||
.location = 0,
|
||||
.binding = 0,
|
||||
.format = .r32g32_sfloat,
|
||||
.offset = @offsetOf(geometry.Vertex, "position"),
|
||||
},
|
||||
.{
|
||||
.location = 1,
|
||||
.binding = 0,
|
||||
.format = .r32g32b32a32_sfloat,
|
||||
.offset = @offsetOf(geometry.Vertex, "color"),
|
||||
},
|
||||
};
|
||||
|
||||
return try initPipelineContext(
|
||||
ldc,
|
||||
extent,
|
||||
render_pass,
|
||||
vert_spv,
|
||||
frag_spv,
|
||||
allocator,
|
||||
null,
|
||||
&attribute_descriptions,
|
||||
);
|
||||
}
|
||||
|
||||
pub fn initPiecePipelineContext(ldc: device.LogicalDeviceContext, extent: vk.Extent2D, render_pass: vk.RenderPass, vert_spv: []const u8, frag_spv: []const u8, allocator: std.mem.Allocator) !PipelineContext {
|
||||
const sampler_layout_binding = vk.DescriptorSetLayoutBinding{
|
||||
.binding = 0,
|
||||
.descriptor_type = .combined_image_sampler,
|
||||
.descriptor_count = 1,
|
||||
.stage_flags = .{
|
||||
.fragment_bit = true,
|
||||
},
|
||||
.p_immutable_samplers = null,
|
||||
};
|
||||
|
||||
const descriptor_set_layout_bindings = [_]vk.DescriptorSetLayoutBinding{
|
||||
sampler_layout_binding,
|
||||
};
|
||||
|
||||
const descriptor_set_layout_create_info = vk.DescriptorSetLayoutCreateInfo{
|
||||
.binding_count = descriptor_set_layout_bindings.len,
|
||||
.p_bindings = &descriptor_set_layout_bindings,
|
||||
};
|
||||
|
||||
const descriptor_set_layout = try ldc.vkd.createDescriptorSetLayout(
|
||||
ldc.device,
|
||||
&descriptor_set_layout_create_info,
|
||||
null,
|
||||
);
|
||||
errdefer ldc.vkd.destroyDescriptorSetLayout(ldc.device, descriptor_set_layout, null);
|
||||
|
||||
const descriptor_set_layouts = [_]vk.DescriptorSetLayout{
|
||||
descriptor_set_layout,
|
||||
};
|
||||
|
||||
const attribute_descriptions = [_]vk.VertexInputAttributeDescription{
|
||||
.{
|
||||
.location = 0,
|
||||
.binding = 0,
|
||||
.format = .r32g32_sfloat,
|
||||
.offset = @offsetOf(geometry.Vertex, "position"),
|
||||
},
|
||||
.{
|
||||
.location = 1,
|
||||
.binding = 0,
|
||||
.format = .r32g32b32a32_sfloat,
|
||||
.offset = @offsetOf(geometry.Vertex, "color"),
|
||||
},
|
||||
.{
|
||||
.location = 2,
|
||||
.binding = 0,
|
||||
.format = .r32g32_sfloat,
|
||||
.offset = @offsetOf(geometry.Vertex, "uv"),
|
||||
},
|
||||
};
|
||||
|
||||
return try initPipelineContext(
|
||||
ldc,
|
||||
extent,
|
||||
render_pass,
|
||||
vert_spv,
|
||||
frag_spv,
|
||||
allocator,
|
||||
&descriptor_set_layouts,
|
||||
&attribute_descriptions,
|
||||
);
|
||||
}
|
||||
|
||||
fn initPipelineContext(
|
||||
ldc: device.LogicalDeviceContext,
|
||||
extent: vk.Extent2D,
|
||||
render_pass: vk.RenderPass,
|
||||
vert_spv: []const u8,
|
||||
frag_spv: []const u8,
|
||||
allocator: std.mem.Allocator,
|
||||
descriptor_set_layouts: ?[]const vk.DescriptorSetLayout,
|
||||
attribute_descriptions: []const vk.VertexInputAttributeDescription,
|
||||
) !PipelineContext {
|
||||
const pipeline_layout_create_info = vk.PipelineLayoutCreateInfo{
|
||||
.set_layout_count = if (descriptor_set_layouts) |layouts| @intCast(layouts.len) else 0,
|
||||
.p_set_layouts = if (descriptor_set_layouts) |layouts| layouts.ptr else null,
|
||||
};
|
||||
|
||||
const pipeline_layout = try ldc.vkd.createPipelineLayout(
|
||||
ldc.device,
|
||||
@@ -70,18 +178,11 @@ pub fn initPipelineContext(ldc: device.LogicalDeviceContext, extent: vk.Extent2D
|
||||
.input_rate = .vertex,
|
||||
};
|
||||
|
||||
const attribute_description = vk.VertexInputAttributeDescription{
|
||||
.location = 0,
|
||||
.binding = 0,
|
||||
.format = .r32g32_sfloat,
|
||||
.offset = @offsetOf(geometry.Vertex, "position"),
|
||||
};
|
||||
|
||||
const vertex_input_info = vk.PipelineVertexInputStateCreateInfo{
|
||||
.vertex_binding_description_count = 1,
|
||||
.p_vertex_binding_descriptions = @ptrCast(&binding_description),
|
||||
.vertex_attribute_description_count = 1,
|
||||
.p_vertex_attribute_descriptions = @ptrCast(&attribute_description),
|
||||
.vertex_attribute_description_count = @intCast(attribute_descriptions.len),
|
||||
.p_vertex_attribute_descriptions = attribute_descriptions.ptr,
|
||||
};
|
||||
|
||||
const input_assembly = vk.PipelineInputAssemblyStateCreateInfo{
|
||||
@@ -91,9 +192,9 @@ pub fn initPipelineContext(ldc: device.LogicalDeviceContext, extent: vk.Extent2D
|
||||
|
||||
const viewport = vk.Viewport{
|
||||
.x = 0.0,
|
||||
.y = 0.0,
|
||||
.y = @floatFromInt(extent.height),
|
||||
.width = @floatFromInt(extent.width),
|
||||
.height = @floatFromInt(extent.height),
|
||||
.height = -@as(f32, @floatFromInt(extent.height)),
|
||||
.min_depth = 0.0,
|
||||
.max_depth = 1.0,
|
||||
};
|
||||
@@ -115,9 +216,7 @@ pub fn initPipelineContext(ldc: device.LogicalDeviceContext, extent: vk.Extent2D
|
||||
.rasterizer_discard_enable = .false,
|
||||
.polygon_mode = .fill,
|
||||
.line_width = 1.0,
|
||||
.cull_mode = .{
|
||||
.back_bit = true,
|
||||
},
|
||||
.cull_mode = .{},
|
||||
.front_face = .clockwise,
|
||||
.depth_bias_enable = .false,
|
||||
.depth_bias_constant_factor = 0.0,
|
||||
@@ -141,9 +240,9 @@ pub fn initPipelineContext(ldc: device.LogicalDeviceContext, extent: vk.Extent2D
|
||||
.b_bit = true,
|
||||
.a_bit = true,
|
||||
},
|
||||
.blend_enable = .false,
|
||||
.src_color_blend_factor = .one,
|
||||
.dst_color_blend_factor = .zero,
|
||||
.blend_enable = .true,
|
||||
.src_color_blend_factor = .src_alpha,
|
||||
.dst_color_blend_factor = .one_minus_src_alpha,
|
||||
.color_blend_op = .add,
|
||||
.src_alpha_blend_factor = .one,
|
||||
.dst_alpha_blend_factor = .zero,
|
||||
@@ -176,10 +275,7 @@ pub fn initPipelineContext(ldc: device.LogicalDeviceContext, extent: vk.Extent2D
|
||||
.base_pipeline_index = -1,
|
||||
};
|
||||
|
||||
const pipeline_infos = [_]vk.GraphicsPipelineCreateInfo{
|
||||
pipeline_info,
|
||||
};
|
||||
|
||||
const pipeline_infos = [_]vk.GraphicsPipelineCreateInfo{pipeline_info};
|
||||
var pipelines: [1]vk.Pipeline = undefined;
|
||||
|
||||
_ = try ldc.vkd.createGraphicsPipelines(
|
||||
@@ -193,5 +289,6 @@ pub fn initPipelineContext(ldc: device.LogicalDeviceContext, extent: vk.Extent2D
|
||||
return .{
|
||||
.graphics_pipeline = pipelines[0],
|
||||
.pipeline_layout = pipeline_layout,
|
||||
.descriptor_set_layout = if (descriptor_set_layouts) |layouts| layouts[0] else .null_handle,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
const std = @import("std");
|
||||
const log = std.log.scoped(.graphics);
|
||||
const vk = @import("vulkan");
|
||||
|
||||
const device = @import("device.zig");
|
||||
@@ -59,7 +60,7 @@ pub fn initRenderPass(ldc: device.LogicalDeviceContext, format: vk.Format) !Rend
|
||||
};
|
||||
|
||||
const render_pass = try ldc.vkd.createRenderPass(ldc.device, &render_pass_create_info, null);
|
||||
std.debug.print("created render pass\n", .{});
|
||||
log.debug("created render pass", .{});
|
||||
|
||||
return .{ .render_pass = render_pass };
|
||||
}
|
||||
|
||||
+16
-13
@@ -1,4 +1,5 @@
|
||||
const std = @import("std");
|
||||
const log = std.log.scoped(.graphics);
|
||||
const glfw = @import("zglfw");
|
||||
const vk = @import("vulkan");
|
||||
|
||||
@@ -30,6 +31,7 @@ pub fn initSwapchain(
|
||||
ldc: device.LogicalDeviceContext,
|
||||
surface: vk.SurfaceKHR,
|
||||
window: *glfw.Window,
|
||||
old_swapchain: vk.SwapchainKHR,
|
||||
allocator: std.mem.Allocator,
|
||||
) !SwapchainContext {
|
||||
const surface_caps = try vc.vki.getPhysicalDeviceSurfaceCapabilitiesKHR(
|
||||
@@ -37,16 +39,16 @@ pub fn initSwapchain(
|
||||
surface,
|
||||
);
|
||||
|
||||
std.debug.print(
|
||||
"surface current extent: {}x{}\n",
|
||||
log.debug(
|
||||
"surface current extent: {}x{}",
|
||||
.{
|
||||
surface_caps.current_extent.width,
|
||||
surface_caps.current_extent.height,
|
||||
},
|
||||
);
|
||||
|
||||
std.debug.print(
|
||||
"surface min/max image count: {}/{}\n",
|
||||
log.debug(
|
||||
"surface min/max image count: {}/{}",
|
||||
.{
|
||||
surface_caps.min_image_count,
|
||||
surface_caps.max_image_count,
|
||||
@@ -100,16 +102,16 @@ pub fn initSwapchain(
|
||||
chosen_image_count = surface_caps.max_image_count;
|
||||
}
|
||||
|
||||
std.debug.print(
|
||||
"chosen swapchain format={any}, color_space={any}\n",
|
||||
log.debug(
|
||||
"chosen swapchain format={any}, color_space={any}",
|
||||
.{ chosen_surface_format.format, chosen_surface_format.color_space },
|
||||
);
|
||||
std.debug.print("chosen present mode={any}\n", .{chosen_present_mode});
|
||||
std.debug.print(
|
||||
"chosen extent={}x{}\n",
|
||||
log.debug("chosen present mode={any}", .{chosen_present_mode});
|
||||
log.debug(
|
||||
"chosen extent={}x{}",
|
||||
.{ chosen_extent.width, chosen_extent.height },
|
||||
);
|
||||
std.debug.print("chosen image count={}\n", .{chosen_image_count});
|
||||
log.debug("chosen image count={}", .{chosen_image_count});
|
||||
|
||||
const swapchain_create_info = vk.SwapchainCreateInfoKHR{
|
||||
.surface = surface,
|
||||
@@ -128,11 +130,12 @@ pub fn initSwapchain(
|
||||
},
|
||||
.present_mode = chosen_present_mode,
|
||||
.clipped = .true,
|
||||
.old_swapchain = old_swapchain,
|
||||
};
|
||||
|
||||
const swapchain = try ldc.vkd.createSwapchainKHR(ldc.device, &swapchain_create_info, null);
|
||||
errdefer ldc.vkd.destroySwapchainKHR(ldc.device, swapchain, null);
|
||||
std.debug.print("created swapchain\n", .{});
|
||||
log.debug("created swapchain", .{});
|
||||
|
||||
const swapchain_images = try ldc.vkd.getSwapchainImagesAllocKHR(
|
||||
ldc.device,
|
||||
@@ -140,7 +143,7 @@ pub fn initSwapchain(
|
||||
allocator,
|
||||
);
|
||||
errdefer allocator.free(swapchain_images);
|
||||
std.debug.print("swapchain images: {}\n", .{swapchain_images.len});
|
||||
log.debug("swapchain images: {}", .{swapchain_images.len});
|
||||
|
||||
const swapchain_image_views = try allocator.alloc(vk.ImageView, swapchain_images.len);
|
||||
errdefer allocator.free(swapchain_image_views);
|
||||
@@ -182,7 +185,7 @@ pub fn initSwapchain(
|
||||
created_image_view_count += 1;
|
||||
}
|
||||
|
||||
std.debug.print("created swapchain image views: {}\n", .{swapchain_image_views.len});
|
||||
log.debug("created swapchain image views: {}", .{swapchain_image_views.len});
|
||||
|
||||
return .{
|
||||
.swapchain = swapchain,
|
||||
|
||||
+2
-1
@@ -1,4 +1,5 @@
|
||||
const std = @import("std");
|
||||
const log = std.log.scoped(.graphics);
|
||||
const vk = @import("vulkan");
|
||||
|
||||
const device = @import("device.zig");
|
||||
@@ -44,7 +45,7 @@ pub fn initSyncObjects(ldc: device.LogicalDeviceContext) !SyncContext {
|
||||
null,
|
||||
);
|
||||
|
||||
std.debug.print("created synchronization objects\n", .{});
|
||||
log.debug("created synchronization objects", .{});
|
||||
|
||||
return .{
|
||||
.image_available_semaphore = image_available_semaphore,
|
||||
|
||||
@@ -0,0 +1,293 @@
|
||||
const vk = @import("vulkan");
|
||||
|
||||
const context = @import("context.zig");
|
||||
const device = @import("device.zig");
|
||||
const buffer = @import("buffer.zig");
|
||||
const commands = @import("commands.zig");
|
||||
const assets = @import("../assets.zig");
|
||||
|
||||
pub const TextureContext = struct {
|
||||
image: vk.Image,
|
||||
memory: vk.DeviceMemory,
|
||||
image_view: vk.ImageView,
|
||||
sampler: vk.Sampler,
|
||||
|
||||
pub fn destroy(self: *const TextureContext, ldc: *const device.LogicalDeviceContext) void {
|
||||
ldc.vkd.destroySampler(ldc.device, self.sampler, null);
|
||||
ldc.vkd.destroyImageView(ldc.device, self.image_view, null);
|
||||
ldc.vkd.destroyImage(ldc.device, self.image, null);
|
||||
ldc.vkd.freeMemory(ldc.device, self.memory, null);
|
||||
}
|
||||
};
|
||||
|
||||
pub fn createImage(
|
||||
vc: context.VulkanContext,
|
||||
ldc: device.LogicalDeviceContext,
|
||||
width: u32,
|
||||
height: u32,
|
||||
format: vk.Format,
|
||||
tiling: vk.ImageTiling,
|
||||
usage: vk.ImageUsageFlags,
|
||||
properties: vk.MemoryPropertyFlags,
|
||||
) !TextureContext {
|
||||
const image_create_info = vk.ImageCreateInfo{
|
||||
.image_type = .@"2d",
|
||||
.extent = .{
|
||||
.width = width,
|
||||
.height = height,
|
||||
.depth = 1,
|
||||
},
|
||||
.mip_levels = 1,
|
||||
.array_layers = 1,
|
||||
.format = format,
|
||||
.tiling = tiling,
|
||||
.initial_layout = .undefined,
|
||||
.usage = usage,
|
||||
.samples = .{ .@"1_bit" = true },
|
||||
.sharing_mode = .exclusive,
|
||||
};
|
||||
|
||||
const image = try ldc.vkd.createImage(ldc.device, &image_create_info, null);
|
||||
errdefer ldc.vkd.destroyImage(ldc.device, image, null);
|
||||
|
||||
const memory_requirements = ldc.vkd.getImageMemoryRequirements(ldc.device, image);
|
||||
const memory_type_index = try buffer.findMemoryType(
|
||||
vc,
|
||||
ldc,
|
||||
memory_requirements.memory_type_bits,
|
||||
properties,
|
||||
);
|
||||
|
||||
const alloc_info = vk.MemoryAllocateInfo{
|
||||
.allocation_size = memory_requirements.size,
|
||||
.memory_type_index = memory_type_index,
|
||||
};
|
||||
|
||||
const memory = try ldc.vkd.allocateMemory(ldc.device, &alloc_info, null);
|
||||
errdefer ldc.vkd.freeMemory(ldc.device, memory, null);
|
||||
|
||||
try ldc.vkd.bindImageMemory(ldc.device, image, memory, 0);
|
||||
|
||||
const image_view = try createImageView(ldc, image, format);
|
||||
errdefer ldc.vkd.destroyImageView(ldc.device, image_view, null);
|
||||
|
||||
const sampler = try createTextureSampler(ldc);
|
||||
errdefer ldc.vkd.destroySampler(ldc.device, sampler, null);
|
||||
|
||||
return .{
|
||||
.image = image,
|
||||
.memory = memory,
|
||||
.image_view = image_view,
|
||||
.sampler = sampler,
|
||||
};
|
||||
}
|
||||
|
||||
fn createImageView(
|
||||
ldc: device.LogicalDeviceContext,
|
||||
image: vk.Image,
|
||||
format: vk.Format,
|
||||
) !vk.ImageView {
|
||||
const view_create_info = vk.ImageViewCreateInfo{
|
||||
.image = image,
|
||||
.view_type = .@"2d",
|
||||
.format = format,
|
||||
.components = .{
|
||||
.r = .identity,
|
||||
.g = .identity,
|
||||
.b = .identity,
|
||||
.a = .identity,
|
||||
},
|
||||
.subresource_range = .{
|
||||
.aspect_mask = .{
|
||||
.color_bit = true,
|
||||
},
|
||||
.base_mip_level = 0,
|
||||
.level_count = 1,
|
||||
.base_array_layer = 0,
|
||||
.layer_count = 1,
|
||||
},
|
||||
};
|
||||
|
||||
return try ldc.vkd.createImageView(
|
||||
ldc.device,
|
||||
&view_create_info,
|
||||
null,
|
||||
);
|
||||
}
|
||||
|
||||
fn createTextureSampler(ldc: device.LogicalDeviceContext) !vk.Sampler {
|
||||
const sampler_create_info = vk.SamplerCreateInfo{
|
||||
.mag_filter = .linear,
|
||||
.min_filter = .linear,
|
||||
.mipmap_mode = .linear,
|
||||
.address_mode_u = .clamp_to_edge,
|
||||
.address_mode_v = .clamp_to_edge,
|
||||
.address_mode_w = .clamp_to_edge,
|
||||
.mip_lod_bias = 0.0,
|
||||
.anisotropy_enable = .false,
|
||||
.max_anisotropy = 1.0,
|
||||
.compare_enable = .false,
|
||||
.compare_op = .always,
|
||||
.min_lod = 0.0,
|
||||
.max_lod = 0.0,
|
||||
.border_color = .int_opaque_black,
|
||||
.unnormalized_coordinates = .false,
|
||||
};
|
||||
|
||||
return try ldc.vkd.createSampler(
|
||||
ldc.device,
|
||||
&sampler_create_info,
|
||||
null,
|
||||
);
|
||||
}
|
||||
|
||||
pub fn transitionImageLayout(
|
||||
ldc: device.LogicalDeviceContext,
|
||||
command_context: commands.CommandContext,
|
||||
image: vk.Image,
|
||||
old_layout: vk.ImageLayout,
|
||||
new_layout: vk.ImageLayout,
|
||||
) !void {
|
||||
const command_buffer = try commands.beginSingleTimeCommands(ldc, command_context);
|
||||
|
||||
var barrier = vk.ImageMemoryBarrier{
|
||||
.src_access_mask = .{},
|
||||
.dst_access_mask = .{},
|
||||
.old_layout = old_layout,
|
||||
.new_layout = new_layout,
|
||||
.src_queue_family_index = vk.QUEUE_FAMILY_IGNORED,
|
||||
.dst_queue_family_index = vk.QUEUE_FAMILY_IGNORED,
|
||||
.image = image,
|
||||
.subresource_range = .{
|
||||
.aspect_mask = .{ .color_bit = true },
|
||||
.base_mip_level = 0,
|
||||
.level_count = 1,
|
||||
.base_array_layer = 0,
|
||||
.layer_count = 1,
|
||||
},
|
||||
};
|
||||
|
||||
var source_stage: vk.PipelineStageFlags = undefined;
|
||||
var destination_stage: vk.PipelineStageFlags = undefined;
|
||||
|
||||
if (old_layout == .undefined and new_layout == .transfer_dst_optimal) {
|
||||
barrier.src_access_mask = .{};
|
||||
barrier.dst_access_mask = .{ .transfer_write_bit = true };
|
||||
|
||||
source_stage = .{ .top_of_pipe_bit = true };
|
||||
destination_stage = .{ .transfer_bit = true };
|
||||
} else if (old_layout == .transfer_dst_optimal and new_layout == .shader_read_only_optimal) {
|
||||
barrier.src_access_mask = .{ .transfer_write_bit = true };
|
||||
barrier.dst_access_mask = .{ .shader_read_bit = true };
|
||||
|
||||
source_stage = .{ .transfer_bit = true };
|
||||
destination_stage = .{ .fragment_shader_bit = true };
|
||||
} else {
|
||||
return error.UnsupportedLayoutTransition;
|
||||
}
|
||||
|
||||
const image_barriers = [_]vk.ImageMemoryBarrier{barrier};
|
||||
|
||||
ldc.vkd.cmdPipelineBarrier(
|
||||
command_buffer,
|
||||
source_stage,
|
||||
destination_stage,
|
||||
.{},
|
||||
null,
|
||||
null,
|
||||
&image_barriers,
|
||||
);
|
||||
|
||||
try commands.endSingleTimeCommands(ldc, command_context, command_buffer);
|
||||
}
|
||||
|
||||
pub fn copyBufferToImage(
|
||||
ldc: device.LogicalDeviceContext,
|
||||
command_context: commands.CommandContext,
|
||||
source_buffer: vk.Buffer,
|
||||
destination_image: vk.Image,
|
||||
width: u32,
|
||||
height: u32,
|
||||
) !void {
|
||||
const command_buffer = try commands.beginSingleTimeCommands(ldc, command_context);
|
||||
|
||||
const region = vk.BufferImageCopy{
|
||||
.buffer_offset = 0,
|
||||
.buffer_row_length = 0,
|
||||
.buffer_image_height = 0,
|
||||
.image_subresource = .{
|
||||
.aspect_mask = .{ .color_bit = true },
|
||||
.mip_level = 0,
|
||||
.base_array_layer = 0,
|
||||
.layer_count = 1,
|
||||
},
|
||||
.image_offset = .{ .x = 0, .y = 0, .z = 0 },
|
||||
.image_extent = .{
|
||||
.width = width,
|
||||
.height = height,
|
||||
.depth = 1,
|
||||
},
|
||||
};
|
||||
|
||||
const regions = [_]vk.BufferImageCopy{region};
|
||||
|
||||
ldc.vkd.cmdCopyBufferToImage(
|
||||
command_buffer,
|
||||
source_buffer,
|
||||
destination_image,
|
||||
.transfer_dst_optimal,
|
||||
®ions,
|
||||
);
|
||||
|
||||
try commands.endSingleTimeCommands(ldc, command_context, command_buffer);
|
||||
}
|
||||
|
||||
pub fn initTextureFromRgba(
|
||||
vc: context.VulkanContext,
|
||||
ldc: device.LogicalDeviceContext,
|
||||
command_context: commands.CommandContext,
|
||||
asset: []const u8,
|
||||
width: u32,
|
||||
height: u32,
|
||||
format: vk.Format,
|
||||
tiling: vk.ImageTiling,
|
||||
usage: vk.ImageUsageFlags,
|
||||
properties: vk.MemoryPropertyFlags,
|
||||
) !TextureContext {
|
||||
const staging = try buffer.initStagingBuffer(vc, ldc, asset);
|
||||
defer staging.destroy(&ldc);
|
||||
|
||||
const texture = try createImage(
|
||||
vc,
|
||||
ldc,
|
||||
width,
|
||||
height,
|
||||
format,
|
||||
tiling,
|
||||
usage,
|
||||
properties,
|
||||
);
|
||||
try transitionImageLayout(
|
||||
ldc,
|
||||
command_context,
|
||||
texture.image,
|
||||
.undefined,
|
||||
.transfer_dst_optimal,
|
||||
);
|
||||
try copyBufferToImage(
|
||||
ldc,
|
||||
command_context,
|
||||
staging.buffer,
|
||||
texture.image,
|
||||
width,
|
||||
height,
|
||||
);
|
||||
try transitionImageLayout(
|
||||
ldc,
|
||||
command_context,
|
||||
texture.image,
|
||||
.transfer_dst_optimal,
|
||||
.shader_read_only_optimal,
|
||||
);
|
||||
return texture;
|
||||
}
|
||||
Reference in New Issue
Block a user