Compare commits
3 commits
0ea1243ddc
...
d9b1f1dbe8
Author | SHA1 | Date | |
---|---|---|---|
d9b1f1dbe8 | |||
9651b338f3 | |||
fa9c52ac10 |
1 changed files with 220 additions and 8 deletions
228
src/main.rs
228
src/main.rs
|
@ -173,6 +173,10 @@ struct VulkanApp {
|
||||||
swap_chain_image_views: Vec<ffi::VkImageView>,
|
swap_chain_image_views: Vec<ffi::VkImageView>,
|
||||||
render_pass: ffi::VkRenderPass,
|
render_pass: ffi::VkRenderPass,
|
||||||
pipeline_layout: ffi::VkPipelineLayout,
|
pipeline_layout: ffi::VkPipelineLayout,
|
||||||
|
graphics_pipeline: ffi::VkPipeline,
|
||||||
|
swap_chain_framebuffers: Vec<ffi::VkFramebuffer>,
|
||||||
|
command_pool: ffi::VkCommandPool,
|
||||||
|
command_buffer: ffi::VkCommandBuffer,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VulkanApp {
|
impl VulkanApp {
|
||||||
|
@ -193,6 +197,10 @@ impl VulkanApp {
|
||||||
swap_chain_image_views: Vec::new(),
|
swap_chain_image_views: Vec::new(),
|
||||||
render_pass: std::ptr::null_mut(),
|
render_pass: std::ptr::null_mut(),
|
||||||
pipeline_layout: std::ptr::null_mut(),
|
pipeline_layout: std::ptr::null_mut(),
|
||||||
|
graphics_pipeline: std::ptr::null_mut(),
|
||||||
|
swap_chain_framebuffers: Vec::new(),
|
||||||
|
command_pool: std::ptr::null_mut(),
|
||||||
|
command_buffer: std::ptr::null_mut(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -231,6 +239,9 @@ impl VulkanApp {
|
||||||
self.create_render_pass().unwrap();
|
self.create_render_pass().unwrap();
|
||||||
self.create_graphics_pipeline()
|
self.create_graphics_pipeline()
|
||||||
.expect("Should be able to set up graphics pipeline");
|
.expect("Should be able to set up graphics pipeline");
|
||||||
|
self.create_framebuffers().unwrap();
|
||||||
|
self.create_command_pool().unwrap();
|
||||||
|
self.create_command_buffer().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_instance(&mut self) -> Result<(), String> {
|
fn create_instance(&mut self) -> Result<(), String> {
|
||||||
|
@ -898,13 +909,6 @@ impl VulkanApp {
|
||||||
input_assembly.topology = ffi::VkPrimitiveTopology_VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
|
input_assembly.topology = ffi::VkPrimitiveTopology_VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
|
||||||
input_assembly.primitiveRestartEnable = ffi::VK_FALSE;
|
input_assembly.primitiveRestartEnable = ffi::VK_FALSE;
|
||||||
|
|
||||||
let viewport = self.create_viewport();
|
|
||||||
|
|
||||||
let mut scissor: ffi::VkRect2D = unsafe { std::mem::zeroed() };
|
|
||||||
scissor.offset.x = 0;
|
|
||||||
scissor.offset.y = 0;
|
|
||||||
scissor.extent = self.swap_chain_extent;
|
|
||||||
|
|
||||||
let dynamic_state_info_struct = Self::create_dynamic_state_info_struct();
|
let dynamic_state_info_struct = Self::create_dynamic_state_info_struct();
|
||||||
|
|
||||||
let viewport_state = Self::create_viewport_state_info_struct();
|
let viewport_state = Self::create_viewport_state_info_struct();
|
||||||
|
@ -939,6 +943,42 @@ impl VulkanApp {
|
||||||
return Err(String::from("Failed to create pipeline layout!"));
|
return Err(String::from("Failed to create pipeline layout!"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut pipeline_info: ffi::VkGraphicsPipelineCreateInfo = unsafe { std::mem::zeroed() };
|
||||||
|
pipeline_info.sType = ffi::VkStructureType_VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
|
||||||
|
pipeline_info.stageCount = 2;
|
||||||
|
pipeline_info.pStages = shader_stages.as_ptr();
|
||||||
|
|
||||||
|
pipeline_info.pVertexInputState = std::ptr::addr_of!(vertex_input_info);
|
||||||
|
pipeline_info.pInputAssemblyState = std::ptr::addr_of!(input_assembly);
|
||||||
|
pipeline_info.pViewportState = std::ptr::addr_of!(viewport_state);
|
||||||
|
pipeline_info.pRasterizationState = std::ptr::addr_of!(rasterizer_info);
|
||||||
|
pipeline_info.pMultisampleState = std::ptr::addr_of!(multisampling_info);
|
||||||
|
pipeline_info.pDepthStencilState = std::ptr::null();
|
||||||
|
pipeline_info.pColorBlendState = std::ptr::addr_of!(color_blend_info_struct);
|
||||||
|
pipeline_info.pDynamicState = std::ptr::addr_of!(dynamic_state_info_struct);
|
||||||
|
|
||||||
|
pipeline_info.layout = self.pipeline_layout;
|
||||||
|
|
||||||
|
pipeline_info.renderPass = self.render_pass;
|
||||||
|
pipeline_info.subpass = 0;
|
||||||
|
|
||||||
|
pipeline_info.basePipelineHandle = std::ptr::null_mut();
|
||||||
|
pipeline_info.basePipelineIndex = -1;
|
||||||
|
|
||||||
|
let result = unsafe {
|
||||||
|
ffi::vkCreateGraphicsPipelines(
|
||||||
|
self.device,
|
||||||
|
std::ptr::null_mut(),
|
||||||
|
1,
|
||||||
|
std::ptr::addr_of!(pipeline_info),
|
||||||
|
std::ptr::null(),
|
||||||
|
std::ptr::addr_of_mut!(self.graphics_pipeline),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
if result != ffi::VkResult_VK_SUCCESS {
|
||||||
|
return Err(String::from("Failed to create a graphics pipeline!"));
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Use the *_shader_stage_info structs before vert/frag_shader_module is cleaned up.
|
// TODO: Use the *_shader_stage_info structs before vert/frag_shader_module is cleaned up.
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -1021,7 +1061,7 @@ impl VulkanApp {
|
||||||
vertex_input_info
|
vertex_input_info
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_viewport(&mut self) -> ffi::VkViewport {
|
fn create_viewport(&self) -> ffi::VkViewport {
|
||||||
let mut viewport: ffi::VkViewport = unsafe { std::mem::zeroed() };
|
let mut viewport: ffi::VkViewport = unsafe { std::mem::zeroed() };
|
||||||
viewport.x = 0.0;
|
viewport.x = 0.0;
|
||||||
viewport.y = 0.0;
|
viewport.y = 0.0;
|
||||||
|
@ -1033,6 +1073,13 @@ impl VulkanApp {
|
||||||
viewport
|
viewport
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn create_scissor(&self) -> ffi::VkRect2D {
|
||||||
|
ffi::VkRect2D {
|
||||||
|
offset: ffi::VkOffset2D { x: 0, y: 0 },
|
||||||
|
extent: self.swap_chain_extent,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn create_viewport_state_info_struct() -> ffi::VkPipelineViewportStateCreateInfo {
|
fn create_viewport_state_info_struct() -> ffi::VkPipelineViewportStateCreateInfo {
|
||||||
let mut viewport_state: ffi::VkPipelineViewportStateCreateInfo =
|
let mut viewport_state: ffi::VkPipelineViewportStateCreateInfo =
|
||||||
unsafe { std::mem::zeroed() };
|
unsafe { std::mem::zeroed() };
|
||||||
|
@ -1162,10 +1209,175 @@ impl VulkanApp {
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn create_framebuffers(&mut self) -> Result<(), String> {
|
||||||
|
self.swap_chain_framebuffers
|
||||||
|
.resize(self.swap_chain_image_views.len(), std::ptr::null_mut());
|
||||||
|
|
||||||
|
for (idx, image_view) in self.swap_chain_image_views.iter().enumerate() {
|
||||||
|
let mut framebuffer_info: ffi::VkFramebufferCreateInfo = unsafe { std::mem::zeroed() };
|
||||||
|
framebuffer_info.sType = ffi::VkStructureType_VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
|
||||||
|
framebuffer_info.renderPass = self.render_pass;
|
||||||
|
framebuffer_info.attachmentCount = 1;
|
||||||
|
framebuffer_info.pAttachments = image_view as *const ffi::VkImageView;
|
||||||
|
framebuffer_info.width = self.swap_chain_extent.width;
|
||||||
|
framebuffer_info.height = self.swap_chain_extent.height;
|
||||||
|
framebuffer_info.layers = 1;
|
||||||
|
|
||||||
|
let result = unsafe {
|
||||||
|
ffi::vkCreateFramebuffer(
|
||||||
|
self.device,
|
||||||
|
std::ptr::addr_of!(framebuffer_info),
|
||||||
|
std::ptr::null(),
|
||||||
|
std::ptr::addr_of_mut!(self.swap_chain_framebuffers[idx]),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
if result != ffi::VkResult_VK_SUCCESS {
|
||||||
|
return Err(String::from("Failed to create framebuffer!"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_command_pool(&mut self) -> Result<(), String> {
|
||||||
|
let indices = self.find_queue_families(self.physical_device);
|
||||||
|
|
||||||
|
let mut pool_info: ffi::VkCommandPoolCreateInfo = unsafe { std::mem::zeroed() };
|
||||||
|
pool_info.sType = ffi::VkStructureType_VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
|
||||||
|
pool_info.flags =
|
||||||
|
ffi::VkCommandPoolCreateFlagBits_VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
|
||||||
|
pool_info.queueFamilyIndex = indices
|
||||||
|
.graphics_family
|
||||||
|
.expect("indices should have graphics family idx");
|
||||||
|
|
||||||
|
let result = unsafe {
|
||||||
|
ffi::vkCreateCommandPool(
|
||||||
|
self.device,
|
||||||
|
std::ptr::addr_of!(pool_info),
|
||||||
|
std::ptr::null(),
|
||||||
|
std::ptr::addr_of_mut!(self.command_pool),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
if result != ffi::VkResult_VK_SUCCESS {
|
||||||
|
return Err(String::from("Failed to create command pool!"));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_command_buffer(&mut self) -> Result<(), String> {
|
||||||
|
let mut alloc_info: ffi::VkCommandBufferAllocateInfo = unsafe { std::mem::zeroed() };
|
||||||
|
alloc_info.sType = ffi::VkStructureType_VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
|
||||||
|
alloc_info.commandPool = self.command_pool;
|
||||||
|
alloc_info.level = ffi::VkCommandBufferLevel_VK_COMMAND_BUFFER_LEVEL_PRIMARY;
|
||||||
|
alloc_info.commandBufferCount = 1;
|
||||||
|
|
||||||
|
let result = unsafe {
|
||||||
|
ffi::vkAllocateCommandBuffers(
|
||||||
|
self.device,
|
||||||
|
std::ptr::addr_of!(alloc_info),
|
||||||
|
std::ptr::addr_of_mut!(self.command_buffer),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
if result != ffi::VkResult_VK_SUCCESS {
|
||||||
|
return Err(String::from("Failed to allocate command buffers!"));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn record_command_buffer(
|
||||||
|
&mut self,
|
||||||
|
command_buffer: ffi::VkCommandBuffer,
|
||||||
|
image_index: usize,
|
||||||
|
) -> Result<(), String> {
|
||||||
|
let mut begin_info: ffi::VkCommandBufferBeginInfo = unsafe { std::mem::zeroed() };
|
||||||
|
begin_info.sType = ffi::VkStructureType_VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
||||||
|
begin_info.flags = 0;
|
||||||
|
begin_info.pInheritanceInfo = std::ptr::null();
|
||||||
|
|
||||||
|
let result =
|
||||||
|
unsafe { ffi::vkBeginCommandBuffer(command_buffer, std::ptr::addr_of!(begin_info)) };
|
||||||
|
if result != ffi::VkResult_VK_SUCCESS {
|
||||||
|
return Err(String::from("Failed to begin recording command buffer!"));
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut render_pass_info: ffi::VkRenderPassBeginInfo = unsafe { std::mem::zeroed() };
|
||||||
|
render_pass_info.sType = ffi::VkStructureType_VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
||||||
|
render_pass_info.renderPass = self.render_pass;
|
||||||
|
render_pass_info.framebuffer = self.swap_chain_framebuffers[image_index];
|
||||||
|
|
||||||
|
render_pass_info.renderArea.offset.x = 0;
|
||||||
|
render_pass_info.renderArea.offset.y = 0;
|
||||||
|
render_pass_info.renderArea.extent = self.swap_chain_extent;
|
||||||
|
|
||||||
|
let mut clear_color: ffi::VkClearValue = unsafe { std::mem::zeroed() };
|
||||||
|
unsafe {
|
||||||
|
clear_color.color.float32[0] = 0.0;
|
||||||
|
clear_color.color.float32[1] = 0.0;
|
||||||
|
clear_color.color.float32[2] = 0.0;
|
||||||
|
clear_color.color.float32[3] = 1.0;
|
||||||
|
}
|
||||||
|
render_pass_info.clearValueCount = 1;
|
||||||
|
render_pass_info.pClearValues = std::ptr::addr_of!(clear_color);
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
ffi::vkCmdBeginRenderPass(
|
||||||
|
command_buffer,
|
||||||
|
std::ptr::addr_of!(render_pass_info),
|
||||||
|
ffi::VkSubpassContents_VK_SUBPASS_CONTENTS_INLINE,
|
||||||
|
);
|
||||||
|
ffi::vkCmdBindPipeline(
|
||||||
|
command_buffer,
|
||||||
|
ffi::VkPipelineBindPoint_VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||||
|
self.graphics_pipeline,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let viewport = self.create_viewport();
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
ffi::vkCmdSetViewport(command_buffer, 0, 1, std::ptr::addr_of!(viewport));
|
||||||
|
}
|
||||||
|
|
||||||
|
let scissor = self.create_scissor();
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
ffi::vkCmdSetScissor(command_buffer, 0, 1, std::ptr::addr_of!(scissor));
|
||||||
|
ffi::vkCmdDraw(command_buffer, 3, 1, 0, 0);
|
||||||
|
ffi::vkCmdEndRenderPass(command_buffer);
|
||||||
|
|
||||||
|
if ffi::vkEndCommandBuffer(command_buffer) != ffi::VkResult_VK_SUCCESS {
|
||||||
|
return Err(String::from("Failed to record command buffer!"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for VulkanApp {
|
impl Drop for VulkanApp {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
|
if !self.command_pool.is_null() {
|
||||||
|
unsafe {
|
||||||
|
ffi::vkDestroyCommandPool(self.device, self.command_pool, std::ptr::null());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for framebuffer in &self.swap_chain_framebuffers {
|
||||||
|
unsafe {
|
||||||
|
ffi::vkDestroyFramebuffer(self.device, *framebuffer, std::ptr::null());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !self.graphics_pipeline.is_null() {
|
||||||
|
unsafe {
|
||||||
|
ffi::vkDestroyPipeline(self.device, self.graphics_pipeline, std::ptr::null());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if !self.pipeline_layout.is_null() {
|
if !self.pipeline_layout.is_null() {
|
||||||
unsafe {
|
unsafe {
|
||||||
ffi::vkDestroyPipelineLayout(self.device, self.pipeline_layout, std::ptr::null());
|
ffi::vkDestroyPipelineLayout(self.device, self.pipeline_layout, std::ptr::null());
|
||||||
|
|
Loading…
Reference in a new issue