vulkan runs! but might need optimisation lmao

This commit is contained in:
Alex Janka 2023-10-02 10:42:30 +11:00
parent adfc1f4b3e
commit bbff0d9929
5 changed files with 781 additions and 24 deletions

View file

@ -5,7 +5,7 @@ edition = "2021"
[features] [features]
default = ["vulkan"] default = ["vulkan"]
pixels = ["dep:pixels", "dep:bytemuck"] pixels = ["dep:pixels"]
vulkan = ["dep:ash", "dep:ash-window", "dep:raw-window-handle", "dep:naga"] vulkan = ["dep:ash", "dep:ash-window", "dep:raw-window-handle", "dep:naga"]
camera = ["dep:nokhwa", "dep:send_wrapper"] camera = ["dep:nokhwa", "dep:send_wrapper"]
@ -22,7 +22,7 @@ nokhwa = { version = "0.10.3", features = [
send_wrapper = { version = "0.6.0", optional = true } send_wrapper = { version = "0.6.0", optional = true }
winit = "0.28" winit = "0.28"
winit_input_helper = "0.14" winit_input_helper = "0.14"
bytemuck = { version = "1.13", optional = true } bytemuck = "1.13"
pixels = { version = "0.12", optional = true } pixels = { version = "0.12", optional = true }
ash = { git = "https://github.com/ash-rs/ash", features = [ ash = { git = "https://github.com/ash-rs/ash", features = [
"linked", "linked",

View file

@ -1,4 +1,4 @@
#![feature(let_chains, if_let_guard)] #![feature(let_chains, if_let_guard, iter_array_chunks)]
#[cfg(feature = "camera")] #[cfg(feature = "camera")]
use camera::Webcam; use camera::Webcam;

View file

@ -3,9 +3,6 @@ struct VsOutput {
@builtin(position) position: vec4<f32>, @builtin(position) position: vec4<f32>,
} }
struct Locals {
transform: mat4x4<f32>,
}
@vertex @vertex
fn vs_main( fn vs_main(

View file

@ -1,5 +1,8 @@
use std::mem;
use ash::{ use ash::{
extensions::khr::{Surface, Swapchain}, extensions::khr::{Surface, Swapchain},
util::Align,
vk, Device, Entry, Instance, vk, Device, Entry, Instance,
}; };
use ash_window::enumerate_required_extensions; use ash_window::enumerate_required_extensions;
@ -15,21 +18,21 @@ const SHADER: &[u8] = include_bytes!(concat!(env!("CARGO_MANIFEST_DIR"), "/shade
pub struct WindowData { pub struct WindowData {
scale_factor: u32, scale_factor: u32,
entry: Entry, // entry: Entry,
instance: Instance, instance: Instance,
device: Device, device: Device,
surface_loader: Surface, surface_loader: Surface,
swapchain_loader: Swapchain, swapchain_loader: Swapchain,
pdevice: vk::PhysicalDevice, // pdevice: vk::PhysicalDevice,
device_memory_properties: vk::PhysicalDeviceMemoryProperties, // device_memory_properties: vk::PhysicalDeviceMemoryProperties,
queue_family_index: u32, // queue_family_index: u32,
present_queue: vk::Queue, present_queue: vk::Queue,
surface: vk::SurfaceKHR, surface: vk::SurfaceKHR,
surface_format: vk::SurfaceFormatKHR, // surface_format: vk::SurfaceFormatKHR,
surface_resolution: vk::Extent2D, surface_resolution: vk::Extent2D,
swapchain: vk::SwapchainKHR, swapchain: vk::SwapchainKHR,
present_images: Vec<vk::Image>, // present_images: Vec<vk::Image>,
present_image_views: Vec<vk::ImageView>, present_image_views: Vec<vk::ImageView>,
pool: vk::CommandPool, pool: vk::CommandPool,
@ -45,10 +48,27 @@ pub struct WindowData {
draw_commands_reuse_fence: vk::Fence, draw_commands_reuse_fence: vk::Fence,
setup_commands_reuse_fence: vk::Fence, setup_commands_reuse_fence: vk::Fence,
vertex_input_buffer: vk::Buffer,
renderpass: vk::RenderPass,
framebuffers: Vec<vk::Framebuffer>,
pipeline_layout: vk::PipelineLayout,
descriptor_sets: Vec<vk::DescriptorSet>,
graphic_pipeline: vk::Pipeline,
viewports: [vk::Viewport; 1],
scissors: [vk::Rect2D; 1],
index_buffer: vk::Buffer,
index_buffer_data: [u32; 6],
image_buffer: vk::Buffer,
image_buffer_memory: vk::DeviceMemory,
image_buffer_memory_req: vk::MemoryRequirements,
image_extent: vk::Extent2D,
texture_image: vk::Image,
} }
impl WindowData { impl WindowData {
pub fn new(factor: u32, window: &Window) -> Self { pub unsafe fn new(factor: u32, window: &Window) -> Self {
let entry = Entry::linked(); let entry = Entry::linked();
let name = std::ffi::CString::new("gameboy").unwrap(); let name = std::ffi::CString::new("gameboy").unwrap();
@ -344,22 +364,537 @@ impl WindowData {
let rendering_complete_semaphore = let rendering_complete_semaphore =
unsafe { device.create_semaphore(&semaphore_create_info, None) }.unwrap(); unsafe { device.create_semaphore(&semaphore_create_info, None) }.unwrap();
let renderpass_attachments = [
vk::AttachmentDescription {
format: surface_format.format,
samples: vk::SampleCountFlags::TYPE_1,
load_op: vk::AttachmentLoadOp::CLEAR,
store_op: vk::AttachmentStoreOp::STORE,
final_layout: vk::ImageLayout::PRESENT_SRC_KHR,
..Default::default()
},
vk::AttachmentDescription {
format: vk::Format::D16_UNORM,
samples: vk::SampleCountFlags::TYPE_1,
load_op: vk::AttachmentLoadOp::CLEAR,
initial_layout: vk::ImageLayout::DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
final_layout: vk::ImageLayout::DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
..Default::default()
},
];
let color_attachment_refs = [vk::AttachmentReference {
attachment: 0,
layout: vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL,
}];
let depth_attachment_ref = vk::AttachmentReference {
attachment: 1,
layout: vk::ImageLayout::DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
};
let dependencies = [vk::SubpassDependency {
src_subpass: vk::SUBPASS_EXTERNAL,
src_stage_mask: vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT,
dst_access_mask: vk::AccessFlags::COLOR_ATTACHMENT_READ
| vk::AccessFlags::COLOR_ATTACHMENT_WRITE,
dst_stage_mask: vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT,
..Default::default()
}];
let subpass = vk::SubpassDescription::default()
.color_attachments(&color_attachment_refs)
.depth_stencil_attachment(&depth_attachment_ref)
.pipeline_bind_point(vk::PipelineBindPoint::GRAPHICS);
let renderpass_create_info = vk::RenderPassCreateInfo::default()
.attachments(&renderpass_attachments)
.subpasses(std::slice::from_ref(&subpass))
.dependencies(&dependencies);
let renderpass =
unsafe { device.create_render_pass(&renderpass_create_info, None) }.unwrap();
let framebuffers: Vec<vk::Framebuffer> = present_image_views
.iter()
.map(|&present_image_view| {
let framebuffer_attachments = [present_image_view, depth_image_view];
let frame_buffer_create_info = vk::FramebufferCreateInfo::default()
.render_pass(renderpass)
.attachments(&framebuffer_attachments)
.width(surface_resolution.width)
.height(surface_resolution.height)
.layers(1);
unsafe { device.create_framebuffer(&frame_buffer_create_info, None) }.unwrap()
})
.collect();
let index_buffer_data = [0u32, 1, 2, 2, 3, 0];
let index_buffer_info = vk::BufferCreateInfo {
size: std::mem::size_of_val(&index_buffer_data) as u64,
usage: vk::BufferUsageFlags::INDEX_BUFFER,
sharing_mode: vk::SharingMode::EXCLUSIVE,
..Default::default()
};
let index_buffer = device.create_buffer(&index_buffer_info, None).unwrap();
let index_buffer_memory_req = device.get_buffer_memory_requirements(index_buffer);
let index_buffer_memory_index = find_memorytype_index(
&index_buffer_memory_req,
&device_memory_properties,
vk::MemoryPropertyFlags::HOST_VISIBLE | vk::MemoryPropertyFlags::HOST_COHERENT,
)
.expect("Unable to find suitable memorytype for the index buffer.");
let index_allocate_info = vk::MemoryAllocateInfo {
allocation_size: index_buffer_memory_req.size,
memory_type_index: index_buffer_memory_index,
..Default::default()
};
let index_buffer_memory = device.allocate_memory(&index_allocate_info, None).unwrap();
let index_ptr: *mut std::ffi::c_void = device
.map_memory(
index_buffer_memory,
0,
index_buffer_memory_req.size,
vk::MemoryMapFlags::empty(),
)
.unwrap();
let mut index_slice = Align::new(
index_ptr,
std::mem::align_of::<u32>() as u64,
index_buffer_memory_req.size,
);
index_slice.copy_from_slice(&index_buffer_data);
device.unmap_memory(index_buffer_memory);
device
.bind_buffer_memory(index_buffer, index_buffer_memory, 0)
.unwrap();
let vertices: [Vertex; 3] = [Vertex(-1.0, -1.0), Vertex(3.0, -1.0), Vertex(-1.0, 3.0)];
let vertex_input_buffer_info = vk::BufferCreateInfo {
size: std::mem::size_of_val(&vertices) as u64,
usage: vk::BufferUsageFlags::VERTEX_BUFFER,
sharing_mode: vk::SharingMode::EXCLUSIVE,
..Default::default()
};
let vertex_input_buffer = device
.create_buffer(&vertex_input_buffer_info, None)
.unwrap();
let vertex_input_buffer_memory_req =
device.get_buffer_memory_requirements(vertex_input_buffer);
let vertex_input_buffer_memory_index = find_memorytype_index(
&vertex_input_buffer_memory_req,
&device_memory_properties,
vk::MemoryPropertyFlags::HOST_VISIBLE | vk::MemoryPropertyFlags::HOST_COHERENT,
)
.expect("Unable to find suitable memorytype for the vertex buffer.");
let vertex_buffer_allocate_info = vk::MemoryAllocateInfo {
allocation_size: vertex_input_buffer_memory_req.size,
memory_type_index: vertex_input_buffer_memory_index,
..Default::default()
};
let vertex_input_buffer_memory = device
.allocate_memory(&vertex_buffer_allocate_info, None)
.unwrap();
let vert_ptr = device
.map_memory(
vertex_input_buffer_memory,
0,
vertex_input_buffer_memory_req.size,
vk::MemoryMapFlags::empty(),
)
.unwrap();
let mut slice = Align::new(
vert_ptr,
std::mem::align_of::<Vertex>() as u64,
vertex_input_buffer_memory_req.size,
);
slice.copy_from_slice(&vertices);
device.unmap_memory(vertex_input_buffer_memory);
device
.bind_buffer_memory(vertex_input_buffer, vertex_input_buffer_memory, 0)
.unwrap();
let window_size = window.inner_size();
let window_width = window_size.width;
let window_height = window_size.height;
let inner_width = window_width / factor;
let inner_height = window_height / factor;
let image_extent = vk::Extent2D {
width: inner_width,
height: inner_height,
};
let image_buffer_info = vk::BufferCreateInfo {
size: (std::mem::size_of::<u8>() * (inner_width * inner_height * 4) as usize) as u64,
usage: vk::BufferUsageFlags::TRANSFER_SRC,
sharing_mode: vk::SharingMode::EXCLUSIVE,
..Default::default()
};
let image_buffer = device.create_buffer(&image_buffer_info, None).unwrap();
let image_buffer_memory_req = device.get_buffer_memory_requirements(image_buffer);
let image_buffer_memory_index = find_memorytype_index(
&image_buffer_memory_req,
&device_memory_properties,
vk::MemoryPropertyFlags::HOST_VISIBLE | vk::MemoryPropertyFlags::HOST_COHERENT,
)
.expect("Unable to find suitable memorytype for the image buffer.");
let image_buffer_allocate_info = vk::MemoryAllocateInfo {
allocation_size: image_buffer_memory_req.size,
memory_type_index: image_buffer_memory_index,
..Default::default()
};
let image_buffer_memory = device
.allocate_memory(&image_buffer_allocate_info, None)
.unwrap();
device
.bind_buffer_memory(image_buffer, image_buffer_memory, 0)
.unwrap();
let texture_create_info = vk::ImageCreateInfo {
image_type: vk::ImageType::TYPE_2D,
format: vk::Format::R8G8B8A8_UNORM,
extent: image_extent.into(),
mip_levels: 1,
array_layers: 1,
samples: vk::SampleCountFlags::TYPE_1,
tiling: vk::ImageTiling::OPTIMAL,
usage: vk::ImageUsageFlags::TRANSFER_DST | vk::ImageUsageFlags::SAMPLED,
sharing_mode: vk::SharingMode::EXCLUSIVE,
..Default::default()
};
let texture_image = device.create_image(&texture_create_info, None).unwrap();
let texture_memory_req = device.get_image_memory_requirements(texture_image);
let texture_memory_index = find_memorytype_index(
&texture_memory_req,
&device_memory_properties,
vk::MemoryPropertyFlags::DEVICE_LOCAL,
)
.expect("Unable to find suitable memory index for depth image.");
let texture_allocate_info = vk::MemoryAllocateInfo {
allocation_size: texture_memory_req.size,
memory_type_index: texture_memory_index,
..Default::default()
};
let texture_memory = device
.allocate_memory(&texture_allocate_info, None)
.unwrap();
device
.bind_image_memory(texture_image, texture_memory, 0)
.expect("Unable to bind depth image memory");
record_submit_commandbuffer(
&device,
setup_command_buffer,
setup_commands_reuse_fence,
present_queue,
&[],
&[],
&[],
|device, texture_command_buffer| {
let texture_barrier = vk::ImageMemoryBarrier {
dst_access_mask: vk::AccessFlags::TRANSFER_WRITE,
new_layout: vk::ImageLayout::TRANSFER_DST_OPTIMAL,
image: texture_image,
subresource_range: vk::ImageSubresourceRange {
aspect_mask: vk::ImageAspectFlags::COLOR,
level_count: 1,
layer_count: 1,
..Default::default()
},
..Default::default()
};
device.cmd_pipeline_barrier(
texture_command_buffer,
vk::PipelineStageFlags::BOTTOM_OF_PIPE,
vk::PipelineStageFlags::TRANSFER,
vk::DependencyFlags::empty(),
&[],
&[],
&[texture_barrier],
);
let buffer_copy_regions = vk::BufferImageCopy::default()
.image_subresource(
vk::ImageSubresourceLayers::default()
.aspect_mask(vk::ImageAspectFlags::COLOR)
.layer_count(1),
)
.image_extent(image_extent.into());
device.cmd_copy_buffer_to_image(
texture_command_buffer,
image_buffer,
texture_image,
vk::ImageLayout::TRANSFER_DST_OPTIMAL,
&[buffer_copy_regions],
);
let texture_barrier_end = vk::ImageMemoryBarrier {
src_access_mask: vk::AccessFlags::TRANSFER_WRITE,
dst_access_mask: vk::AccessFlags::SHADER_READ,
old_layout: vk::ImageLayout::TRANSFER_DST_OPTIMAL,
new_layout: vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL,
image: texture_image,
subresource_range: vk::ImageSubresourceRange {
aspect_mask: vk::ImageAspectFlags::COLOR,
level_count: 1,
layer_count: 1,
..Default::default()
},
..Default::default()
};
device.cmd_pipeline_barrier(
texture_command_buffer,
vk::PipelineStageFlags::TRANSFER,
vk::PipelineStageFlags::FRAGMENT_SHADER,
vk::DependencyFlags::empty(),
&[],
&[],
&[texture_barrier_end],
);
},
);
let sampler_info = vk::SamplerCreateInfo {
mag_filter: vk::Filter::NEAREST,
min_filter: vk::Filter::NEAREST,
mipmap_mode: vk::SamplerMipmapMode::NEAREST,
address_mode_u: vk::SamplerAddressMode::MIRRORED_REPEAT,
address_mode_v: vk::SamplerAddressMode::MIRRORED_REPEAT,
address_mode_w: vk::SamplerAddressMode::MIRRORED_REPEAT,
max_anisotropy: 1.0,
border_color: vk::BorderColor::FLOAT_OPAQUE_WHITE,
compare_op: vk::CompareOp::NEVER,
..Default::default()
};
let sampler = device.create_sampler(&sampler_info, None).unwrap();
let tex_image_view_info = vk::ImageViewCreateInfo {
view_type: vk::ImageViewType::TYPE_2D,
format: texture_create_info.format,
components: vk::ComponentMapping {
r: vk::ComponentSwizzle::R,
g: vk::ComponentSwizzle::G,
b: vk::ComponentSwizzle::B,
a: vk::ComponentSwizzle::A,
},
subresource_range: vk::ImageSubresourceRange {
aspect_mask: vk::ImageAspectFlags::COLOR,
level_count: 1,
layer_count: 1,
..Default::default()
},
image: texture_image,
..Default::default()
};
let tex_image_view = device
.create_image_view(&tex_image_view_info, None)
.unwrap();
let descriptor_sizes = [
vk::DescriptorPoolSize {
ty: vk::DescriptorType::UNIFORM_BUFFER,
descriptor_count: 1,
},
vk::DescriptorPoolSize {
ty: vk::DescriptorType::COMBINED_IMAGE_SAMPLER,
descriptor_count: 1,
},
];
let descriptor_pool_info = vk::DescriptorPoolCreateInfo::default()
.pool_sizes(&descriptor_sizes)
.max_sets(1);
let descriptor_pool = device
.create_descriptor_pool(&descriptor_pool_info, None)
.unwrap();
let desc_layout_bindings = [
vk::DescriptorSetLayoutBinding {
descriptor_type: vk::DescriptorType::UNIFORM_BUFFER,
descriptor_count: 1,
stage_flags: vk::ShaderStageFlags::FRAGMENT,
..Default::default()
},
vk::DescriptorSetLayoutBinding {
binding: 1,
descriptor_type: vk::DescriptorType::COMBINED_IMAGE_SAMPLER,
descriptor_count: 1,
stage_flags: vk::ShaderStageFlags::FRAGMENT,
..Default::default()
},
];
let descriptor_info =
vk::DescriptorSetLayoutCreateInfo::default().bindings(&desc_layout_bindings);
let desc_set_layouts = [device
.create_descriptor_set_layout(&descriptor_info, None)
.unwrap()];
let desc_alloc_info = vk::DescriptorSetAllocateInfo::default()
.descriptor_pool(descriptor_pool)
.set_layouts(&desc_set_layouts);
let descriptor_sets = device.allocate_descriptor_sets(&desc_alloc_info).unwrap();
let tex_descriptor = vk::DescriptorImageInfo {
image_layout: vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL,
image_view: tex_image_view,
sampler,
};
let write_desc_sets = [vk::WriteDescriptorSet {
dst_set: descriptor_sets[0],
dst_binding: 1,
descriptor_count: 1,
descriptor_type: vk::DescriptorType::COMBINED_IMAGE_SAMPLER,
p_image_info: &tex_descriptor,
..Default::default()
}];
device.update_descriptor_sets(&write_desc_sets, &[]);
let shader = ash::util::read_spv(&mut std::io::Cursor::new(SHADER)).unwrap();
let shader_info = vk::ShaderModuleCreateInfo::default().code(&shader);
println!("shader info: {:#?}", shader_info);
let shader_module = unsafe { device.create_shader_module(&shader_info, None) }
.expect("Error creating shader module");
let layout_create_info =
vk::PipelineLayoutCreateInfo::default().set_layouts(&desc_set_layouts);
let pipeline_layout =
unsafe { device.create_pipeline_layout(&layout_create_info, None) }.unwrap();
let vertex_shader_entry_name = std::ffi::CStr::from_bytes_with_nul_unchecked(b"vs_main\0");
let fragment_shader_entry_name =
std::ffi::CStr::from_bytes_with_nul_unchecked(b"fs_main\0");
let shader_stage_create_infos = [
vk::PipelineShaderStageCreateInfo {
module: shader_module,
p_name: vertex_shader_entry_name.as_ptr(),
stage: vk::ShaderStageFlags::VERTEX,
..Default::default()
},
vk::PipelineShaderStageCreateInfo {
module: shader_module,
p_name: fragment_shader_entry_name.as_ptr(),
stage: vk::ShaderStageFlags::FRAGMENT,
..Default::default()
},
];
let vertex_input_binding_descriptions = [vk::VertexInputBindingDescription {
binding: 0,
stride: mem::size_of::<Vertex>() as u32,
input_rate: vk::VertexInputRate::VERTEX,
}];
let vertex_input_attribute_descriptions = [vk::VertexInputAttributeDescription {
location: 0,
binding: 0,
format: vk::Format::R32G32B32A32_SFLOAT,
offset: 0,
}];
let vertex_input_state_info = vk::PipelineVertexInputStateCreateInfo::default()
.vertex_attribute_descriptions(&vertex_input_attribute_descriptions)
.vertex_binding_descriptions(&vertex_input_binding_descriptions);
let vertex_input_assembly_state_info = vk::PipelineInputAssemblyStateCreateInfo {
topology: vk::PrimitiveTopology::TRIANGLE_LIST,
..Default::default()
};
let viewports = [vk::Viewport {
x: 0.0,
y: 0.0,
width: surface_resolution.width as f32,
height: surface_resolution.height as f32,
min_depth: 0.0,
max_depth: 1.0,
}];
let scissors = [surface_resolution.into()];
let viewport_state_info = vk::PipelineViewportStateCreateInfo::default()
.scissors(&scissors)
.viewports(&viewports);
let rasterization_info = vk::PipelineRasterizationStateCreateInfo {
front_face: vk::FrontFace::COUNTER_CLOCKWISE,
line_width: 1.0,
polygon_mode: vk::PolygonMode::FILL,
..Default::default()
};
let multisample_state_info = vk::PipelineMultisampleStateCreateInfo::default()
.rasterization_samples(vk::SampleCountFlags::TYPE_1);
let noop_stencil_state = vk::StencilOpState {
fail_op: vk::StencilOp::KEEP,
pass_op: vk::StencilOp::KEEP,
depth_fail_op: vk::StencilOp::KEEP,
compare_op: vk::CompareOp::ALWAYS,
..Default::default()
};
let depth_state_info = vk::PipelineDepthStencilStateCreateInfo {
depth_test_enable: 1,
depth_write_enable: 1,
depth_compare_op: vk::CompareOp::LESS_OR_EQUAL,
front: noop_stencil_state,
back: noop_stencil_state,
max_depth_bounds: 1.0,
..Default::default()
};
let color_blend_attachment_states = [vk::PipelineColorBlendAttachmentState {
blend_enable: 0,
src_color_blend_factor: vk::BlendFactor::SRC_COLOR,
dst_color_blend_factor: vk::BlendFactor::ONE_MINUS_DST_COLOR,
color_blend_op: vk::BlendOp::ADD,
src_alpha_blend_factor: vk::BlendFactor::ZERO,
dst_alpha_blend_factor: vk::BlendFactor::ZERO,
alpha_blend_op: vk::BlendOp::ADD,
color_write_mask: vk::ColorComponentFlags::RGBA,
}];
let color_blend_state = vk::PipelineColorBlendStateCreateInfo::default()
.logic_op(vk::LogicOp::CLEAR)
.attachments(&color_blend_attachment_states);
let dynamic_state = [vk::DynamicState::VIEWPORT, vk::DynamicState::SCISSOR];
let dynamic_state_info =
vk::PipelineDynamicStateCreateInfo::default().dynamic_states(&dynamic_state);
let graphic_pipeline_infos = vk::GraphicsPipelineCreateInfo::default()
.stages(&shader_stage_create_infos)
.vertex_input_state(&vertex_input_state_info)
.input_assembly_state(&vertex_input_assembly_state_info)
.viewport_state(&viewport_state_info)
.rasterization_state(&rasterization_info)
.multisample_state(&multisample_state_info)
.depth_stencil_state(&depth_state_info)
.color_blend_state(&color_blend_state)
.dynamic_state(&dynamic_state_info)
.layout(pipeline_layout)
.render_pass(renderpass);
let graphics_pipelines = device
.create_graphics_pipelines(vk::PipelineCache::null(), &[graphic_pipeline_infos], None)
.unwrap();
let graphic_pipeline = graphics_pipelines[0];
Self { Self {
scale_factor: factor, scale_factor: factor,
entry, // entry,
instance, instance,
device, device,
surface_loader, surface_loader,
swapchain_loader, swapchain_loader,
pdevice, // pdevice,
device_memory_properties, // device_memory_properties,
queue_family_index, // queue_family_index,
present_queue, present_queue,
surface, surface,
surface_format, // surface_format,
surface_resolution, surface_resolution,
swapchain, swapchain,
present_images, // present_images,
present_image_views, present_image_views,
pool, pool,
draw_command_buffer, draw_command_buffer,
@ -371,16 +906,221 @@ impl WindowData {
rendering_complete_semaphore, rendering_complete_semaphore,
draw_commands_reuse_fence, draw_commands_reuse_fence,
setup_commands_reuse_fence, setup_commands_reuse_fence,
vertex_input_buffer,
renderpass,
framebuffers,
pipeline_layout,
descriptor_sets,
graphic_pipeline,
viewports,
scissors,
index_buffer,
index_buffer_data,
image_buffer,
image_buffer_memory,
image_buffer_memory_req,
image_extent,
texture_image,
} }
} }
pub fn resize(&mut self, _width: u32, _height: u32, factor: u32, window: &Window) { pub fn resize(&mut self, _width: u32, _height: u32, factor: u32, window: &Window) {
*self = Self::new(factor, window); *self = unsafe { Self::new(factor, window) };
} }
pub fn new_frame(&mut self, buffer: &[[u8; 4]]) {} pub fn new_frame(&mut self, buffer: &[[u8; 4]]) {
unsafe {
let image_ptr = self
.device
.map_memory(
self.image_buffer_memory,
0,
self.image_buffer_memory_req.size,
vk::MemoryMapFlags::empty(),
)
.unwrap();
let mut image_slice: Align<u8> = Align::new(
image_ptr,
std::mem::align_of::<u8>() as u64,
self.image_buffer_memory_req.size,
);
pub fn render(&mut self) {} image_slice.copy_from_slice(bytemuck::cast_slice(buffer));
self.device.unmap_memory(self.image_buffer_memory);
self.device
.bind_buffer_memory(self.image_buffer, self.image_buffer_memory, 0)
.unwrap();
record_submit_commandbuffer(
&self.device,
self.setup_command_buffer,
self.setup_commands_reuse_fence,
self.present_queue,
&[],
&[],
&[],
|device, texture_command_buffer| {
let texture_barrier = vk::ImageMemoryBarrier {
dst_access_mask: vk::AccessFlags::TRANSFER_WRITE,
new_layout: vk::ImageLayout::TRANSFER_DST_OPTIMAL,
image: self.texture_image,
subresource_range: vk::ImageSubresourceRange {
aspect_mask: vk::ImageAspectFlags::COLOR,
level_count: 1,
layer_count: 1,
..Default::default()
},
..Default::default()
};
device.cmd_pipeline_barrier(
texture_command_buffer,
vk::PipelineStageFlags::BOTTOM_OF_PIPE,
vk::PipelineStageFlags::TRANSFER,
vk::DependencyFlags::empty(),
&[],
&[],
&[texture_barrier],
);
let buffer_copy_regions = vk::BufferImageCopy::default()
.image_subresource(
vk::ImageSubresourceLayers::default()
.aspect_mask(vk::ImageAspectFlags::COLOR)
.layer_count(1),
)
.image_extent(self.image_extent.into());
device.cmd_copy_buffer_to_image(
texture_command_buffer,
self.image_buffer,
self.texture_image,
vk::ImageLayout::TRANSFER_DST_OPTIMAL,
&[buffer_copy_regions],
);
let texture_barrier_end = vk::ImageMemoryBarrier {
src_access_mask: vk::AccessFlags::TRANSFER_WRITE,
dst_access_mask: vk::AccessFlags::SHADER_READ,
old_layout: vk::ImageLayout::TRANSFER_DST_OPTIMAL,
new_layout: vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL,
image: self.texture_image,
subresource_range: vk::ImageSubresourceRange {
aspect_mask: vk::ImageAspectFlags::COLOR,
level_count: 1,
layer_count: 1,
..Default::default()
},
..Default::default()
};
device.cmd_pipeline_barrier(
texture_command_buffer,
vk::PipelineStageFlags::TRANSFER,
vk::PipelineStageFlags::FRAGMENT_SHADER,
vk::DependencyFlags::empty(),
&[],
&[],
&[texture_barrier_end],
);
},
);
}
}
pub fn render(&mut self) {
unsafe {
let (present_index, _) = self
.swapchain_loader
.acquire_next_image(
self.swapchain,
std::u64::MAX,
self.present_complete_semaphore,
vk::Fence::null(),
)
.unwrap();
let clear_values = [
vk::ClearValue {
color: vk::ClearColorValue {
float32: [0.0, 0.0, 0.0, 0.0],
},
},
vk::ClearValue {
depth_stencil: vk::ClearDepthStencilValue {
depth: 1.0,
stencil: 0,
},
},
];
let render_pass_begin_info = vk::RenderPassBeginInfo::default()
.render_pass(self.renderpass)
.framebuffer(self.framebuffers[present_index as usize])
.render_area(self.surface_resolution.into())
.clear_values(&clear_values);
record_submit_commandbuffer(
&self.device,
self.draw_command_buffer,
self.draw_commands_reuse_fence,
self.present_queue,
&[vk::PipelineStageFlags::BOTTOM_OF_PIPE],
&[self.present_complete_semaphore],
&[self.rendering_complete_semaphore],
|device, draw_command_buffer| {
device.cmd_begin_render_pass(
draw_command_buffer,
&render_pass_begin_info,
vk::SubpassContents::INLINE,
);
device.cmd_bind_descriptor_sets(
draw_command_buffer,
vk::PipelineBindPoint::GRAPHICS,
self.pipeline_layout,
0,
&self.descriptor_sets[..],
&[],
);
device.cmd_bind_pipeline(
draw_command_buffer,
vk::PipelineBindPoint::GRAPHICS,
self.graphic_pipeline,
);
device.cmd_set_viewport(draw_command_buffer, 0, &self.viewports);
device.cmd_set_scissor(draw_command_buffer, 0, &self.scissors);
device.cmd_bind_vertex_buffers(
draw_command_buffer,
0,
&[self.vertex_input_buffer],
&[0],
);
device.cmd_bind_index_buffer(
draw_command_buffer,
self.index_buffer,
0,
vk::IndexType::UINT32,
);
device.cmd_draw_indexed(
draw_command_buffer,
self.index_buffer_data.len() as u32,
1,
0,
0,
1,
);
device.cmd_end_render_pass(draw_command_buffer);
},
);
let present_info = vk::PresentInfoKHR {
wait_semaphore_count: 1,
p_wait_semaphores: &self.rendering_complete_semaphore,
swapchain_count: 1,
p_swapchains: &self.swapchain,
p_image_indices: &present_index,
..Default::default()
};
self.swapchain_loader
.queue_present(self.present_queue, &present_info)
.unwrap();
}
}
} }
impl Drop for WindowData { impl Drop for WindowData {
@ -412,7 +1152,7 @@ impl Drop for WindowData {
} }
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
pub fn record_submit_commandbuffer<F: FnOnce(&Device, vk::CommandBuffer)>( fn record_submit_commandbuffer<F: FnOnce(&Device, vk::CommandBuffer)>(
device: &Device, device: &Device,
command_buffer: vk::CommandBuffer, command_buffer: vk::CommandBuffer,
command_buffer_reuse_fence: vk::Fence, command_buffer_reuse_fence: vk::Fence,
@ -462,3 +1202,21 @@ pub fn record_submit_commandbuffer<F: FnOnce(&Device, vk::CommandBuffer)>(
.expect("queue submit failed."); .expect("queue submit failed.");
} }
} }
fn find_memorytype_index(
memory_req: &vk::MemoryRequirements,
memory_prop: &vk::PhysicalDeviceMemoryProperties,
flags: vk::MemoryPropertyFlags,
) -> Option<u32> {
memory_prop.memory_types[..memory_prop.memory_type_count as _]
.iter()
.enumerate()
.find(|(index, memory_type)| {
(1 << index) & memory_req.memory_type_bits != 0
&& memory_type.property_flags & flags == flags
})
.map(|(index, _memory_type)| index as _)
}
#[derive(Clone, Debug, Copy)]
struct Vertex(f32, f32);

View file

@ -114,7 +114,9 @@ impl WindowRenderer {
let real_factor = (window.scale_factor() * factor as f64) as usize; let real_factor = (window.scale_factor() * factor as f64) as usize;
let data = Arc::new(Mutex::new(WindowData::new(real_factor as u32, &window))); let data = Arc::new(Mutex::new(unsafe {
WindowData::new(real_factor as u32, &window)
}));
let info = WindowInfo { let info = WindowInfo {
id: window.id(), id: window.id(),
data: data.clone(), data: data.clone(),