attempt to add mesh shading
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
/* Copyright (c) 2021, Sascha Willems
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#version 450
|
||||
#extension GL_EXT_mesh_shader:require
|
||||
|
||||
layout(push_constant)uniform PushConstantData{
|
||||
mat4 world;
|
||||
mat4 view;
|
||||
mat4 proj;
|
||||
}pc;
|
||||
|
||||
layout(local_size_x=1,local_size_y=1,local_size_z=1)in;
|
||||
layout(triangles,max_vertices=3,max_primitives=1)out;
|
||||
|
||||
layout(location=0)out VertexOutput
|
||||
{
|
||||
vec4 color;
|
||||
}vertexOutput[];
|
||||
|
||||
const vec4[3]positions={
|
||||
vec4(0.,-1.,0.,1.),
|
||||
vec4(-1.,1.,0.,1.),
|
||||
vec4(1.,1.,0.,1.)
|
||||
};
|
||||
|
||||
const vec4[3]colors={
|
||||
vec4(0.,1.,0.,1.),
|
||||
vec4(0.,0.,1.,1.),
|
||||
vec4(1.,0.,0.,1.)
|
||||
};
|
||||
|
||||
void main()
|
||||
{
|
||||
uint iid=gl_LocalInvocationID.x;
|
||||
|
||||
vec4 offset=vec4(0.,0.,gl_GlobalInvocationID.x,0.);
|
||||
|
||||
SetMeshOutputsEXT(3,1);
|
||||
mat4 mvp=pc.proj*pc.view*pc.world;
|
||||
gl_MeshVerticesEXT[0].gl_Position=mvp*(positions[0]+offset);
|
||||
gl_MeshVerticesEXT[1].gl_Position=mvp*(positions[1]+offset);
|
||||
gl_MeshVerticesEXT[2].gl_Position=mvp*(positions[2]+offset);
|
||||
vertexOutput[0].color=colors[0];
|
||||
vertexOutput[1].color=colors[1];
|
||||
vertexOutput[2].color=colors[2];
|
||||
gl_PrimitiveTriangleIndicesEXT[gl_LocalInvocationIndex]=uvec3(0,1,2);
|
||||
}
|
||||
+89
-20
@@ -24,27 +24,36 @@ use obj::{LoadConfig, ObjData};
|
||||
use rodio::{source::Source, Decoder, OutputStream};
|
||||
use std::io::Cursor;
|
||||
use std::{sync::Arc, time::Instant};
|
||||
use vulkano::buffer::CpuBufferPool;
|
||||
use vulkano::command_buffer::allocator::StandardCommandBufferAllocator;
|
||||
use vulkano::buffer::allocator::{SubbufferAllocator, SubbufferAllocatorCreateInfo};
|
||||
use vulkano::buffer::sys::BufferCreateInfo;
|
||||
use vulkano::buffer::{Buffer, BufferAllocateInfo};
|
||||
use vulkano::command_buffer::allocator::{
|
||||
CommandBufferAllocator, CommandBufferBuilderAlloc, StandardCommandBufferAllocator,
|
||||
};
|
||||
use vulkano::command_buffer::synced::SyncCommandBufferBuilder;
|
||||
use vulkano::command_buffer::sys::{CommandBufferBeginInfo, UnsafeCommandBufferBuilder};
|
||||
use vulkano::command_buffer::CommandBufferInheritanceInfo;
|
||||
use vulkano::descriptor_set::allocator::StandardDescriptorSetAllocator;
|
||||
use vulkano::descriptor_set::{PersistentDescriptorSet, WriteDescriptorSet};
|
||||
use vulkano::device::DeviceOwned;
|
||||
use vulkano::device::{DeviceOwned, QueueFlags};
|
||||
use vulkano::format::Format;
|
||||
use vulkano::image::AttachmentImage;
|
||||
use vulkano::memory::allocator::{MemoryUsage, StandardMemoryAllocator};
|
||||
use vulkano::pipeline::graphics::depth_stencil::DepthStencilState;
|
||||
use vulkano::pipeline::graphics::rasterization::CullMode;
|
||||
use vulkano::pipeline::graphics::rasterization::FrontFace::Clockwise;
|
||||
use vulkano::pipeline::graphics::vertex_input::Vertex;
|
||||
use vulkano::pipeline::PipelineBindPoint;
|
||||
use vulkano::shader::ShaderModule;
|
||||
use vulkano::swapchain::{PresentMode, SwapchainPresentInfo};
|
||||
use vulkano::VulkanLibrary;
|
||||
use vulkano::{NonExhaustive, VulkanLibrary, VulkanObject};
|
||||
use winit::event::{DeviceEvent, DeviceId, ElementState, MouseButton, VirtualKeyCode};
|
||||
|
||||
use ash::vk::CommandBuffer;
|
||||
use egui_winit_vulkano::Gui;
|
||||
use vulkano::pipeline::StateMode::Fixed;
|
||||
use vulkano::{
|
||||
buffer::{BufferUsage, CpuAccessibleBuffer, TypedBufferAccess},
|
||||
buffer::BufferUsage,
|
||||
command_buffer::{
|
||||
AutoCommandBufferBuilder, CommandBufferUsage, RenderPassBeginInfo, SubpassContents,
|
||||
},
|
||||
@@ -53,7 +62,7 @@ use vulkano::{
|
||||
},
|
||||
image::{view::ImageView, ImageAccess, ImageUsage, SwapchainImage},
|
||||
impl_vertex,
|
||||
instance::{Instance, InstanceCreateInfo},
|
||||
instance::{Instance, InstanceCreateInfo, IntanceExtensions},
|
||||
pipeline::{
|
||||
graphics::{
|
||||
input_assembly::InputAssemblyState,
|
||||
@@ -98,7 +107,10 @@ fn main() {
|
||||
let instance = Instance::new(
|
||||
library,
|
||||
InstanceCreateInfo {
|
||||
enabled_extensions: required_extensions,
|
||||
enabled_extensions: IntanceExtensions {
|
||||
khr_get_physical_device_properties2,
|
||||
..required_extensions,
|
||||
},
|
||||
// Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
|
||||
enumerate_portability: true,
|
||||
..Default::default()
|
||||
@@ -127,6 +139,9 @@ fn main() {
|
||||
// `khr_swapchain` extension.
|
||||
let device_extensions = DeviceExtensions {
|
||||
khr_swapchain: true,
|
||||
ext_mesh_shader: true,
|
||||
khr_spirv_1_4: true,
|
||||
khr_shader_float_controls: true,
|
||||
..DeviceExtensions::empty()
|
||||
};
|
||||
|
||||
@@ -161,7 +176,8 @@ fn main() {
|
||||
// We select a queue family that supports graphics operations. When drawing to
|
||||
// a window surface, as we do in this example, we also need to check that queues
|
||||
// in this queue family are capable of presenting images to the surface.
|
||||
q.queue_flags.graphics && p.surface_support(i as u32, &surface).unwrap_or(false)
|
||||
q.queue_flags.intersects(QueueFlags::GRAPHICS)
|
||||
&& p.surface_support(i as u32, &surface).unwrap_or(false)
|
||||
})
|
||||
// The code here searches for the first queue family that is suitable. If none is
|
||||
// found, `None` is returned to `filter_map`, which disqualifies this physical
|
||||
@@ -273,16 +289,13 @@ fn main() {
|
||||
// use that.
|
||||
image_extent: window.inner_size().into(),
|
||||
|
||||
image_usage: ImageUsage {
|
||||
color_attachment: true,
|
||||
..ImageUsage::empty()
|
||||
},
|
||||
image_usage: ImageUsage::COLOR_ATTACHMENT,
|
||||
|
||||
// The alpha mode indicates how the alpha value of the final image will behave. For
|
||||
// example, you can choose whether the window will be opaque or transparent.
|
||||
composite_alpha: surface_capabilities
|
||||
.supported_composite_alpha
|
||||
.iter()
|
||||
.into_iter()
|
||||
.next()
|
||||
.unwrap(),
|
||||
|
||||
@@ -338,6 +351,8 @@ fn main() {
|
||||
|
||||
#[derive(Clone, Copy, Zeroable, Pod, Debug)]
|
||||
},
|
||||
vulkan_version: "1.2",
|
||||
spirv_version: "1.4"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -350,12 +365,30 @@ fn main() {
|
||||
|
||||
#[derive(Clone, Copy, Zeroable, Pod, Debug)]
|
||||
},
|
||||
vulkan_version: "1.2",
|
||||
spirv_version: "1.4"
|
||||
}
|
||||
}
|
||||
|
||||
let mesh_vs = mesh_vs::load(device.clone()).unwrap();
|
||||
let mesh_fs = mesh_fs::load(device.clone()).unwrap();
|
||||
|
||||
mod implicit_ms {
|
||||
vulkano_shaders::shader! {
|
||||
ty: "mesh",
|
||||
path: "src/cube.mesh.glsl",
|
||||
types_meta: {
|
||||
use bytemuck::{Pod, Zeroable};
|
||||
|
||||
#[derive(Clone, Copy, Zeroable, Pod, Debug)]
|
||||
},
|
||||
vulkan_version: "1.2",
|
||||
spirv_version: "1.4"
|
||||
}
|
||||
}
|
||||
|
||||
let implicit_ms = implicit_ms::load(device.clone()).unwrap();
|
||||
|
||||
/*let uniform_buffer =
|
||||
CpuBufferPool::<vs::ty::PushConstantData>::uniform_buffer(memory_allocator);*/
|
||||
|
||||
@@ -429,6 +462,7 @@ fn main() {
|
||||
&memory_allocator,
|
||||
&mesh_vs,
|
||||
&mesh_fs,
|
||||
&implicit_ms,
|
||||
&images,
|
||||
render_pass.clone(),
|
||||
&mut viewport,
|
||||
@@ -476,13 +510,13 @@ fn main() {
|
||||
|
||||
let descriptor_set_allocator = StandardDescriptorSetAllocator::new(device.clone());
|
||||
|
||||
let uniform_buffer = CpuBufferPool::<mesh_fs::ty::Data>::new(
|
||||
let uniform_buffer = SubbufferAllocator::new(
|
||||
memory_allocator.clone(),
|
||||
BufferUsage {
|
||||
uniform_buffer: true,
|
||||
..BufferUsage::empty()
|
||||
SubbufferAllocatorCreateInfo {
|
||||
// We want to use the allocated subbuffers as vertex buffers.
|
||||
buffer_usage: BufferUsage::UNIFORM_BUFFER,
|
||||
..Default::default()
|
||||
},
|
||||
MemoryUsage::Upload,
|
||||
);
|
||||
|
||||
// Create an egui GUI
|
||||
@@ -638,6 +672,7 @@ fn main() {
|
||||
&memory_allocator,
|
||||
&mesh_vs,
|
||||
&mesh_fs,
|
||||
&implicit_ms,
|
||||
&new_images,
|
||||
render_pass.clone(),
|
||||
&mut viewport,
|
||||
@@ -737,7 +772,9 @@ fn main() {
|
||||
light_count: gstate.lights.len() as u32,
|
||||
};
|
||||
|
||||
uniform_buffer.from_data(uniform_data).unwrap()
|
||||
let sub = uniform_buffer.allocate_sized().unwrap();
|
||||
*sub.write().unwrap() = uniform_data;
|
||||
sub
|
||||
};
|
||||
|
||||
let layout = mesh_pipeline.layout().set_layouts().get(0).unwrap();
|
||||
@@ -843,6 +880,36 @@ fn main() {
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
/*unsafe {
|
||||
let secondary_builder = AutoCommandBufferBuilder::secondary(
|
||||
&command_buffer_allocator,
|
||||
queue_family_index,
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
CommandBufferInheritanceInfo {
|
||||
render_pass: Some(
|
||||
Subpass::from(render_pass.clone(), 0).unwrap().into(),
|
||||
),
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let secondary_buffer = secondary_builder.build().unwrap();
|
||||
|
||||
(device.fns().ext_mesh_shader.cmd_draw_mesh_tasks_ext)(
|
||||
secondary_buffer.handle(),
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
);
|
||||
|
||||
/*builder
|
||||
.execute_commands(secondary_buffer)
|
||||
.expect("Failed to execute chicanery");*/
|
||||
}*/
|
||||
|
||||
builder.draw_mesh([1, 1, 1]).unwrap();
|
||||
|
||||
// We leave the render pass. Note that if we had multiple
|
||||
// subpasses we could have called `next_subpass` to jump to the next subpass.
|
||||
builder
|
||||
@@ -898,6 +965,7 @@ fn window_size_dependent_setup(
|
||||
allocator: &StandardMemoryAllocator,
|
||||
mesh_vs: &ShaderModule,
|
||||
mesh_fs: &ShaderModule,
|
||||
implicit_ms: &ShaderModule,
|
||||
images: &[Arc<SwapchainImage>],
|
||||
render_pass: Arc<RenderPass>,
|
||||
viewport: &mut Viewport,
|
||||
@@ -932,7 +1000,7 @@ fn window_size_dependent_setup(
|
||||
// in. The pipeline will only be usable from this particular subpass.
|
||||
.render_pass(Subpass::from(render_pass.clone(), 0).unwrap())
|
||||
// We need to indicate the layout of the vertices.
|
||||
.vertex_input_state(BuffersDefinition::new().vertex::<Vertex>())
|
||||
.vertex_input_state(OVertex::per_vertex())
|
||||
// The content of the vertex buffer describes a list of triangles.
|
||||
.input_assembly_state(InputAssemblyState::new())
|
||||
// A Vulkan shader can in theory contain multiple entry points, so we have to specify
|
||||
@@ -947,6 +1015,7 @@ fn window_size_dependent_setup(
|
||||
]))
|
||||
// See `vertex_shader`.
|
||||
.fragment_shader(mesh_fs.entry_point("main").unwrap(), ())
|
||||
.mesh_shader(implicit_ms.entry_point("main").unwrap(), ())
|
||||
.depth_stencil_state(DepthStencilState::simple_depth_test())
|
||||
.rasterization_state(RasterizationState {
|
||||
front_face: Fixed(Clockwise),
|
||||
|
||||
+17
-18
@@ -4,8 +4,8 @@ use bytemuck::{Pod, Zeroable};
|
||||
use cgmath::{Deg, Euler, Matrix3, Point3, SquareMatrix, Vector3};
|
||||
use obj::{LoadConfig, ObjData};
|
||||
use vulkano::{
|
||||
buffer::{BufferUsage, CpuAccessibleBuffer},
|
||||
impl_vertex,
|
||||
buffer::{Buffer, BufferAllocateInfo, BufferUsage, Subbuffer},
|
||||
pipeline::graphics::vertex_input::Vertex,
|
||||
};
|
||||
|
||||
use crate::MemoryAllocator;
|
||||
@@ -16,18 +16,19 @@ pub const PLATONIC_SOLIDS: [(&str, &[u8]); 1] = [("Buny", include_bytes!("bunny.
|
||||
// We use #[repr(C)] here to force rustc to not do anything funky with our data, although for this
|
||||
// particular example, it doesn't actually change the in-memory representation.
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Default, Zeroable, Pod)]
|
||||
pub struct Vertex {
|
||||
#[derive(Clone, Copy, Debug, Default, Zeroable, Pod, Vertex)]
|
||||
pub struct OVertex {
|
||||
#[format(R32G32B32_SFLOAT)]
|
||||
position: [f32; 3],
|
||||
#[format(R32G32B32_SFLOAT)]
|
||||
normal: [f32; 3],
|
||||
}
|
||||
impl_vertex!(Vertex, position, normal);
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Mesh {
|
||||
pub name: String,
|
||||
pub vertices: Arc<CpuAccessibleBuffer<[Vertex]>>,
|
||||
pub indices: Arc<CpuAccessibleBuffer<[u32]>>,
|
||||
pub vertices: Subbuffer<[OVertex]>,
|
||||
pub indices: Subbuffer<[u32]>,
|
||||
pub pos: Point3<f32>,
|
||||
pub rot: Euler<Deg<f32>>,
|
||||
pub scale: f32,
|
||||
@@ -55,7 +56,7 @@ pub fn load_obj(memory_allocator: &MemoryAllocator, input: &mut dyn Read, name:
|
||||
//println!("{:?}", exist);
|
||||
indices.push(exist);
|
||||
} else {
|
||||
vertices.push(Vertex {
|
||||
vertices.push(OVertex {
|
||||
position: object.position[mapping.0 as usize],
|
||||
normal: object.normal[mapping.1 as usize],
|
||||
});
|
||||
@@ -66,24 +67,22 @@ pub fn load_obj(memory_allocator: &MemoryAllocator, input: &mut dyn Read, name:
|
||||
}
|
||||
}
|
||||
|
||||
let vertex_buffer = CpuAccessibleBuffer::from_iter(
|
||||
let vertex_buffer = Buffer::from_iter(
|
||||
memory_allocator,
|
||||
BufferUsage {
|
||||
vertex_buffer: true,
|
||||
..BufferUsage::empty()
|
||||
BufferAllocateInfo {
|
||||
buffer_usage: BufferUsage::VERTEX_BUFFER,
|
||||
..Default::default()
|
||||
},
|
||||
false,
|
||||
vertices,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let index_buffer = CpuAccessibleBuffer::from_iter(
|
||||
let index_buffer = Buffer::from_iter(
|
||||
memory_allocator,
|
||||
BufferUsage {
|
||||
index_buffer: true,
|
||||
..BufferUsage::empty()
|
||||
BufferAllocateInfo {
|
||||
buffer_usage: BufferUsage::INDEX_BUFFER,
|
||||
..Default::default()
|
||||
},
|
||||
false,
|
||||
indices,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
Reference in New Issue
Block a user