339 lines
13 KiB
Rust
339 lines
13 KiB
Rust
use anyhow::Result;
|
|
|
|
use vulkanalia::prelude::v1_0::*;
|
|
|
|
|
|
use crate::app_data;
|
|
use crate::queue_family_indices;
|
|
use crate::scene;
|
|
|
|
pub unsafe fn create_command_pool(
|
|
instance: &Instance,
|
|
device: &Device,
|
|
data: &mut app_data::AppData,
|
|
) -> Result<()> {
|
|
let indices = queue_family_indices::QueueFamilyIndices::get(instance, data, data.physical_device)?;
|
|
|
|
let info = vk::CommandPoolCreateInfo::builder()
|
|
.flags(vk::CommandPoolCreateFlags::empty()) // Optional.
|
|
.queue_family_index(indices.graphics);
|
|
|
|
data.command_pool = device.create_command_pool(&info, None)?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
pub unsafe fn create_command_buffers(device: &Device, data: &mut app_data::AppData, scene_handler: &scene::Scene) -> Result<()> {
|
|
let allocate_info = vk::CommandBufferAllocateInfo::builder()
|
|
.command_pool(data.command_pool)
|
|
.level(vk::CommandBufferLevel::PRIMARY)
|
|
.command_buffer_count(data.framebuffers.len() as u32);
|
|
|
|
data.command_buffers = device.allocate_command_buffers(&allocate_info)?;
|
|
|
|
for (i, command_buffer) in data.command_buffers.iter().enumerate() {
|
|
let inheritance = vk::CommandBufferInheritanceInfo::builder();
|
|
|
|
let info = vk::CommandBufferBeginInfo::builder()
|
|
.flags(vk::CommandBufferUsageFlags::empty()) // Optional.
|
|
.inheritance_info(&inheritance); // Optional.
|
|
|
|
device.begin_command_buffer(*command_buffer, &info)?;
|
|
|
|
let render_area = vk::Rect2D::builder()
|
|
.offset(vk::Offset2D::default())
|
|
.extent(data.swapchain_extent);
|
|
|
|
let color_clear_value = vk::ClearValue {
|
|
color: vk::ClearColorValue {
|
|
float32: [0.0, 0.0, 0.0, 1.0],
|
|
},
|
|
};
|
|
|
|
let depth_clear_value = vk::ClearValue {
|
|
depth_stencil: vk::ClearDepthStencilValue {
|
|
depth: 1.0,
|
|
stencil: 0,
|
|
},
|
|
};
|
|
|
|
// define the compute load before going into the render pass
|
|
if scene_handler.volumetrics.len() != 0 {
|
|
device.cmd_bind_pipeline(
|
|
*command_buffer, vk::PipelineBindPoint::COMPUTE, data.pipeline_compute_rasterize); //todo build own pipeline
|
|
|
|
device.cmd_bind_descriptor_sets(
|
|
*command_buffer,
|
|
vk::PipelineBindPoint::COMPUTE,
|
|
data.pipeline_layout,
|
|
0,
|
|
&[data.descriptor_sets[i]],
|
|
&[]);
|
|
|
|
device.cmd_dispatch(*command_buffer, (data.compute_task_one_size as f64 / 16.0).ceil() as u32, 1, 1);
|
|
|
|
let buffer_memory_barrier_vertex = vk::BufferMemoryBarrier::builder()
|
|
.buffer(data.compute_out_cuboid_buffers[i])
|
|
.src_access_mask(vk::AccessFlags::SHADER_READ | vk::AccessFlags::SHADER_WRITE)
|
|
.dst_access_mask(vk::AccessFlags::VERTEX_ATTRIBUTE_READ)
|
|
.size(vk::WHOLE_SIZE as u64)
|
|
.build();
|
|
let buffer_memory_barrier_index = vk::BufferMemoryBarrier::builder()
|
|
.buffer(data.compute_out_cuboid_index_buffers[i])
|
|
.src_access_mask(vk::AccessFlags::SHADER_READ | vk::AccessFlags::SHADER_WRITE)
|
|
.dst_access_mask(vk::AccessFlags::INDEX_READ)
|
|
.size(vk::WHOLE_SIZE as u64)
|
|
.build();
|
|
|
|
device.cmd_pipeline_barrier(*command_buffer,
|
|
vk::PipelineStageFlags::COMPUTE_SHADER,
|
|
vk::PipelineStageFlags::VERTEX_INPUT,
|
|
vk::DependencyFlags::DEVICE_GROUP,
|
|
&[] as &[vk::MemoryBarrier],
|
|
&[buffer_memory_barrier_index, buffer_memory_barrier_vertex],
|
|
&[] as &[vk::ImageMemoryBarrier]);
|
|
|
|
// compute storage barrier
|
|
let buffer_memory_barrier_color = vk::BufferMemoryBarrier::builder()
|
|
.buffer(data.compute_out_storage_buffers_color[i])
|
|
.src_access_mask(vk::AccessFlags::SHADER_WRITE)
|
|
.dst_access_mask(vk::AccessFlags::SHADER_READ)
|
|
.size(vk::WHOLE_SIZE as u64)
|
|
.build();
|
|
|
|
let buffer_memory_barrier_transparent = vk::BufferMemoryBarrier::builder()
|
|
.buffer(data.compute_out_storage_buffers_transparent[i])
|
|
.src_access_mask(vk::AccessFlags::SHADER_WRITE)
|
|
.dst_access_mask(vk::AccessFlags::SHADER_READ)
|
|
.size(vk::WHOLE_SIZE as u64)
|
|
.build();
|
|
|
|
device.cmd_pipeline_barrier(*command_buffer,
|
|
vk::PipelineStageFlags::COMPUTE_SHADER,
|
|
vk::PipelineStageFlags::COMPUTE_SHADER,
|
|
vk::DependencyFlags::DEVICE_GROUP,
|
|
&[] as &[vk::MemoryBarrier],
|
|
&[buffer_memory_barrier_color, buffer_memory_barrier_transparent],
|
|
&[] as &[vk::ImageMemoryBarrier]);
|
|
// grow x axis
|
|
device.cmd_bind_pipeline(
|
|
*command_buffer, vk::PipelineBindPoint::COMPUTE, data.pipeline_compute_grow_one);
|
|
|
|
device.cmd_bind_descriptor_sets(
|
|
*command_buffer,
|
|
vk::PipelineBindPoint::COMPUTE,
|
|
data.pipeline_layout,
|
|
0,
|
|
&[data.descriptor_sets[i]],
|
|
&[]);
|
|
|
|
device.cmd_dispatch(*command_buffer, (data.compute_task_one_size as f64 / 16.0).ceil() as u32, 1, 1);
|
|
|
|
let buffer_memory_barrier_out = vk::BufferMemoryBarrier::builder()
|
|
.buffer(data.compute_out_storage_buffers_size_three[i])
|
|
.src_access_mask(vk::AccessFlags::SHADER_WRITE)
|
|
.dst_access_mask(vk::AccessFlags::SHADER_READ)
|
|
.size(vk::WHOLE_SIZE as u64)
|
|
.build();
|
|
|
|
device.cmd_pipeline_barrier(*command_buffer,
|
|
vk::PipelineStageFlags::COMPUTE_SHADER,
|
|
vk::PipelineStageFlags::COMPUTE_SHADER,
|
|
vk::DependencyFlags::DEVICE_GROUP,
|
|
&[] as &[vk::MemoryBarrier],
|
|
&[buffer_memory_barrier_out],
|
|
&[] as &[vk::ImageMemoryBarrier]);
|
|
// grow y axis
|
|
device.cmd_bind_pipeline(
|
|
*command_buffer, vk::PipelineBindPoint::COMPUTE, data.pipeline_compute_grow_two);
|
|
|
|
device.cmd_bind_descriptor_sets(
|
|
*command_buffer,
|
|
vk::PipelineBindPoint::COMPUTE,
|
|
data.pipeline_layout,
|
|
0,
|
|
&[data.descriptor_sets[i]],
|
|
&[]);
|
|
|
|
device.cmd_dispatch(*command_buffer, (data.compute_task_one_size as f64 / 16.0).ceil() as u32, 1, 1);
|
|
|
|
let buffer_memory_barrier_out = vk::BufferMemoryBarrier::builder()
|
|
.buffer(data.compute_out_storage_buffers_size_two[i])
|
|
.src_access_mask(vk::AccessFlags::SHADER_WRITE)
|
|
.dst_access_mask(vk::AccessFlags::SHADER_READ)
|
|
.size(vk::WHOLE_SIZE as u64)
|
|
.build();
|
|
|
|
device.cmd_pipeline_barrier(*command_buffer,
|
|
vk::PipelineStageFlags::COMPUTE_SHADER,
|
|
vk::PipelineStageFlags::COMPUTE_SHADER,
|
|
vk::DependencyFlags::DEVICE_GROUP,
|
|
&[] as &[vk::MemoryBarrier],
|
|
&[buffer_memory_barrier_out],
|
|
&[] as &[vk::ImageMemoryBarrier]);
|
|
|
|
// grow z axis
|
|
device.cmd_bind_pipeline(
|
|
*command_buffer, vk::PipelineBindPoint::COMPUTE, data.pipeline_compute_grow_three);
|
|
|
|
device.cmd_bind_descriptor_sets(
|
|
*command_buffer,
|
|
vk::PipelineBindPoint::COMPUTE,
|
|
data.pipeline_layout,
|
|
0,
|
|
&[data.descriptor_sets[i]],
|
|
&[]);
|
|
|
|
device.cmd_dispatch(*command_buffer, (data.compute_task_one_size as f64 / 16.0).ceil() as u32, 1, 1);
|
|
|
|
let buffer_memory_barrier_out = vk::BufferMemoryBarrier::builder()
|
|
.buffer(data.compute_out_storage_buffers_size_three[i])
|
|
.src_access_mask(vk::AccessFlags::SHADER_WRITE)
|
|
.dst_access_mask(vk::AccessFlags::SHADER_READ)
|
|
.size(vk::WHOLE_SIZE as u64)
|
|
.build();
|
|
|
|
device.cmd_pipeline_barrier(*command_buffer,
|
|
vk::PipelineStageFlags::COMPUTE_SHADER,
|
|
vk::PipelineStageFlags::COMPUTE_SHADER,
|
|
vk::DependencyFlags::DEVICE_GROUP,
|
|
&[] as &[vk::MemoryBarrier],
|
|
&[buffer_memory_barrier_out],
|
|
&[] as &[vk::ImageMemoryBarrier]);
|
|
}
|
|
// start render pass
|
|
let clear_values = &[color_clear_value, depth_clear_value];
|
|
let info = vk::RenderPassBeginInfo::builder()
|
|
.render_pass(data.render_pass)
|
|
.framebuffer(data.framebuffers[i])
|
|
.render_area(render_area)
|
|
.clear_values(clear_values);
|
|
|
|
device.cmd_begin_render_pass(
|
|
*command_buffer, &info, vk::SubpassContents::INLINE);
|
|
|
|
if scene_handler.vertices.len() != 0 {
|
|
device.cmd_bind_pipeline(
|
|
*command_buffer, vk::PipelineBindPoint::GRAPHICS, data.pipeline_cube);
|
|
|
|
device.cmd_bind_vertex_buffers(*command_buffer, 0, &[scene_handler.vertex_buffer_cube], &[0]);
|
|
device.cmd_bind_index_buffer(*command_buffer, scene_handler.index_buffer_cube, 0, vk::IndexType::UINT32);
|
|
|
|
|
|
device.cmd_bind_descriptor_sets(
|
|
*command_buffer,
|
|
vk::PipelineBindPoint::GRAPHICS,
|
|
data.pipeline_layout,
|
|
0,
|
|
&[data.descriptor_sets[i]],
|
|
&[],
|
|
);
|
|
|
|
device.cmd_draw_indexed(*command_buffer, scene_handler.indices_cube.len() as u32, 1, 0, 0, 0);
|
|
}
|
|
|
|
if scene_handler.sized_vertices.len() != 0 {
|
|
device.cmd_bind_pipeline(
|
|
*command_buffer, vk::PipelineBindPoint::GRAPHICS, data.pipeline_cuboid);
|
|
|
|
device.cmd_bind_vertex_buffers(*command_buffer, 0, &[scene_handler.vertex_buffer_cuboid], &[0]);
|
|
device.cmd_bind_index_buffer(*command_buffer, scene_handler.index_buffer_cuboid, 0, vk::IndexType::UINT32);
|
|
|
|
|
|
device.cmd_bind_descriptor_sets(
|
|
*command_buffer,
|
|
vk::PipelineBindPoint::GRAPHICS,
|
|
data.pipeline_layout,
|
|
0,
|
|
&[data.descriptor_sets[i]],
|
|
&[],
|
|
);
|
|
|
|
device.cmd_draw_indexed(*command_buffer, scene_handler.indices_cuboid.len() as u32, 1, 0, 0, 0);
|
|
}
|
|
// draw sized vertices from compute shader
|
|
if scene_handler.volumetrics.len() != 0 {
|
|
device.cmd_bind_pipeline(
|
|
*command_buffer, vk::PipelineBindPoint::GRAPHICS, data.pipeline_cuboid);
|
|
|
|
device.cmd_bind_vertex_buffers(*command_buffer, 0, &[data.compute_out_cuboid_buffers[i]], &[0]);
|
|
device.cmd_bind_index_buffer(*command_buffer, data.compute_out_cuboid_index_buffers[i], 0, vk::IndexType::UINT32);
|
|
|
|
|
|
device.cmd_bind_descriptor_sets(
|
|
*command_buffer,
|
|
vk::PipelineBindPoint::GRAPHICS,
|
|
data.pipeline_layout,
|
|
0,
|
|
&[data.descriptor_sets[i]],
|
|
&[],
|
|
);
|
|
|
|
device.cmd_draw_indexed(*command_buffer, (data.compute_task_one_out_size * 36) as u32, 1, 0, 0, 0);
|
|
}
|
|
|
|
if scene_handler.rt_vertices.len() != 0 {
|
|
device.cmd_bind_pipeline(
|
|
*command_buffer, vk::PipelineBindPoint::GRAPHICS, data.pipeline_quad); //todo build own pipeline
|
|
|
|
device.cmd_bind_vertex_buffers(*command_buffer, 0, &[scene_handler.vertex_buffer_quad], &[0]);
|
|
device.cmd_bind_index_buffer(*command_buffer, scene_handler.index_buffer_quad, 0, vk::IndexType::UINT32);
|
|
|
|
|
|
device.cmd_bind_descriptor_sets(
|
|
*command_buffer,
|
|
vk::PipelineBindPoint::GRAPHICS,
|
|
data.pipeline_layout,
|
|
0,
|
|
&[data.descriptor_sets[i]],
|
|
&[],
|
|
);
|
|
|
|
device.cmd_draw_indexed(*command_buffer, scene_handler.indices_rt.len() as u32, 1, 0, 0, 0);
|
|
}
|
|
|
|
device.cmd_end_render_pass(*command_buffer);
|
|
|
|
device.end_command_buffer(*command_buffer)?;
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
pub unsafe fn begin_single_time_commands(
|
|
device: &Device,
|
|
data: &app_data::AppData,
|
|
) -> Result<vk::CommandBuffer> {
|
|
let info = vk::CommandBufferAllocateInfo::builder()
|
|
.level(vk::CommandBufferLevel::PRIMARY)
|
|
.command_pool(data.command_pool)
|
|
.command_buffer_count(1);
|
|
|
|
let command_buffer = device.allocate_command_buffers(&info)?[0];
|
|
|
|
let info = vk::CommandBufferBeginInfo::builder()
|
|
.flags(vk::CommandBufferUsageFlags::ONE_TIME_SUBMIT);
|
|
|
|
device.begin_command_buffer(command_buffer, &info)?;
|
|
|
|
Ok(command_buffer)
|
|
}
|
|
|
|
pub unsafe fn end_single_time_commands(
|
|
device: &Device,
|
|
data: &app_data::AppData,
|
|
command_buffer: vk::CommandBuffer,
|
|
) -> Result<()> {
|
|
device.end_command_buffer(command_buffer)?;
|
|
|
|
let command_buffers = &[command_buffer];
|
|
let info = vk::SubmitInfo::builder()
|
|
.command_buffers(command_buffers);
|
|
|
|
device.queue_submit(data.graphics_queue, &[info], vk::Fence::null())?;
|
|
device.queue_wait_idle(data.graphics_queue)?;
|
|
|
|
device.free_command_buffers(data.command_pool, &[command_buffer]);
|
|
|
|
Ok(())
|
|
}
|