Skip to content
Snippets Groups Projects
Unverified Commit 636a4938 authored by John Hunter's avatar John Hunter :minidisc:
Browse files

attempt to add mesh shading

parent 6b120a93
No related branches found
No related tags found
No related merge requests found
...@@ -671,8 +671,7 @@ dependencies = [ ...@@ -671,8 +671,7 @@ dependencies = [
[[package]] [[package]]
name = "egui_winit_vulkano" name = "egui_winit_vulkano"
version = "0.22.0" version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "git+https://github.com/Molive-0/egui_winit_vulkano#7136d8243a6803709b304bad965b22280351ebbf"
checksum = "c16b9a2bcbfc85f5a4e1d91d1126958451c881c69efcc98e5d6b1b0e5fbb7419"
dependencies = [ dependencies = [
"ahash", "ahash",
"bytemuck", "bytemuck",
...@@ -715,6 +714,7 @@ dependencies = [ ...@@ -715,6 +714,7 @@ dependencies = [
name = "erroccfisumreg" name = "erroccfisumreg"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"ash",
"bytemuck", "bytemuck",
"cgmath", "cgmath",
"egui", "egui",
...@@ -2235,9 +2235,7 @@ dependencies = [ ...@@ -2235,9 +2235,7 @@ dependencies = [
[[package]] [[package]]
name = "vulkano" name = "vulkano"
version = "0.32.3" version = "0.32.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f80b11c6c46ecb2c42155c8bcbc3ff04b783185181d4bbe19d9635a711ec747f"
dependencies = [ dependencies = [
"ahash", "ahash",
"ash", "ash",
...@@ -2247,9 +2245,9 @@ dependencies = [ ...@@ -2247,9 +2245,9 @@ dependencies = [
"half", "half",
"heck", "heck",
"indexmap", "indexmap",
"lazy_static",
"libloading", "libloading",
"objc", "objc",
"once_cell",
"parking_lot", "parking_lot",
"proc-macro2", "proc-macro2",
"quote", "quote",
...@@ -2259,13 +2257,12 @@ dependencies = [ ...@@ -2259,13 +2257,12 @@ dependencies = [
"smallvec", "smallvec",
"thread_local", "thread_local",
"vk-parse", "vk-parse",
"vulkano_macros",
] ]
[[package]] [[package]]
name = "vulkano-shaders" name = "vulkano-shaders"
version = "0.32.0" version = "0.32.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96bbe0784b21e32661fde8a883bb3f659a473693c9f23bab12c26d7884c15ed0"
dependencies = [ dependencies = [
"ahash", "ahash",
"heck", "heck",
...@@ -2279,8 +2276,6 @@ dependencies = [ ...@@ -2279,8 +2276,6 @@ dependencies = [
[[package]] [[package]]
name = "vulkano-util" name = "vulkano-util"
version = "0.32.0" version = "0.32.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df7d34bf37d622aa10d63a05396d91566d8298ca04ebc632f536946659a62f58"
dependencies = [ dependencies = [
"ahash", "ahash",
"vulkano", "vulkano",
...@@ -2291,8 +2286,6 @@ dependencies = [ ...@@ -2291,8 +2286,6 @@ dependencies = [
[[package]] [[package]]
name = "vulkano-win" name = "vulkano-win"
version = "0.32.0" version = "0.32.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac1056e3238fe9025628b3de0f401d8c60b7a6dc89e059534568f55fef4e29f7"
dependencies = [ dependencies = [
"core-graphics-types", "core-graphics-types",
"objc", "objc",
...@@ -2301,6 +2294,16 @@ dependencies = [ ...@@ -2301,6 +2294,16 @@ dependencies = [
"winit", "winit",
] ]
[[package]]
name = "vulkano_macros"
version = "0.32.0"
dependencies = [
"proc-macro-crate",
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "walkdir" name = "walkdir"
version = "2.3.2" version = "2.3.2"
......
...@@ -30,3 +30,14 @@ rodio = "0.16" ...@@ -30,3 +30,14 @@ rodio = "0.16"
egui = "0.20" egui = "0.20"
egui_winit_vulkano = "0.22" egui_winit_vulkano = "0.22"
ash = "*"
# using latest gits
[patch.crates-io]
vulkano = { path = "../vulkano/vulkano" }
vulkano-shaders = { path = "../vulkano/vulkano-shaders" }
vulkano-win = { path = "../vulkano/vulkano-win" }
vulkano-util = { path = "../vulkano/vulkano-util" }
egui_winit_vulkano = { git = "https://github.com/Molive-0/egui_winit_vulkano" }
/* 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);
}
\ No newline at end of file
...@@ -24,27 +24,36 @@ use obj::{LoadConfig, ObjData}; ...@@ -24,27 +24,36 @@ use obj::{LoadConfig, ObjData};
use rodio::{source::Source, Decoder, OutputStream}; use rodio::{source::Source, Decoder, OutputStream};
use std::io::Cursor; use std::io::Cursor;
use std::{sync::Arc, time::Instant}; use std::{sync::Arc, time::Instant};
use vulkano::buffer::CpuBufferPool; use vulkano::buffer::allocator::{SubbufferAllocator, SubbufferAllocatorCreateInfo};
use vulkano::command_buffer::allocator::StandardCommandBufferAllocator; 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::allocator::StandardDescriptorSetAllocator;
use vulkano::descriptor_set::{PersistentDescriptorSet, WriteDescriptorSet}; use vulkano::descriptor_set::{PersistentDescriptorSet, WriteDescriptorSet};
use vulkano::device::DeviceOwned; use vulkano::device::{DeviceOwned, QueueFlags};
use vulkano::format::Format; use vulkano::format::Format;
use vulkano::image::AttachmentImage; use vulkano::image::AttachmentImage;
use vulkano::memory::allocator::{MemoryUsage, StandardMemoryAllocator}; use vulkano::memory::allocator::{MemoryUsage, StandardMemoryAllocator};
use vulkano::pipeline::graphics::depth_stencil::DepthStencilState; use vulkano::pipeline::graphics::depth_stencil::DepthStencilState;
use vulkano::pipeline::graphics::rasterization::CullMode; use vulkano::pipeline::graphics::rasterization::CullMode;
use vulkano::pipeline::graphics::rasterization::FrontFace::Clockwise; use vulkano::pipeline::graphics::rasterization::FrontFace::Clockwise;
use vulkano::pipeline::graphics::vertex_input::Vertex;
use vulkano::pipeline::PipelineBindPoint; use vulkano::pipeline::PipelineBindPoint;
use vulkano::shader::ShaderModule; use vulkano::shader::ShaderModule;
use vulkano::swapchain::{PresentMode, SwapchainPresentInfo}; use vulkano::swapchain::{PresentMode, SwapchainPresentInfo};
use vulkano::VulkanLibrary; use vulkano::{NonExhaustive, VulkanLibrary, VulkanObject};
use winit::event::{DeviceEvent, DeviceId, ElementState, MouseButton, VirtualKeyCode}; use winit::event::{DeviceEvent, DeviceId, ElementState, MouseButton, VirtualKeyCode};
use ash::vk::CommandBuffer;
use egui_winit_vulkano::Gui; use egui_winit_vulkano::Gui;
use vulkano::pipeline::StateMode::Fixed; use vulkano::pipeline::StateMode::Fixed;
use vulkano::{ use vulkano::{
buffer::{BufferUsage, CpuAccessibleBuffer, TypedBufferAccess}, buffer::BufferUsage,
command_buffer::{ command_buffer::{
AutoCommandBufferBuilder, CommandBufferUsage, RenderPassBeginInfo, SubpassContents, AutoCommandBufferBuilder, CommandBufferUsage, RenderPassBeginInfo, SubpassContents,
}, },
...@@ -53,7 +62,7 @@ use vulkano::{ ...@@ -53,7 +62,7 @@ use vulkano::{
}, },
image::{view::ImageView, ImageAccess, ImageUsage, SwapchainImage}, image::{view::ImageView, ImageAccess, ImageUsage, SwapchainImage},
impl_vertex, impl_vertex,
instance::{Instance, InstanceCreateInfo}, instance::{Instance, InstanceCreateInfo, IntanceExtensions},
pipeline::{ pipeline::{
graphics::{ graphics::{
input_assembly::InputAssemblyState, input_assembly::InputAssemblyState,
...@@ -98,7 +107,10 @@ fn main() { ...@@ -98,7 +107,10 @@ fn main() {
let instance = Instance::new( let instance = Instance::new(
library, library,
InstanceCreateInfo { 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) // Enable enumerating devices that use non-conformant vulkan implementations. (ex. MoltenVK)
enumerate_portability: true, enumerate_portability: true,
..Default::default() ..Default::default()
...@@ -127,6 +139,9 @@ fn main() { ...@@ -127,6 +139,9 @@ fn main() {
// `khr_swapchain` extension. // `khr_swapchain` extension.
let device_extensions = DeviceExtensions { let device_extensions = DeviceExtensions {
khr_swapchain: true, khr_swapchain: true,
ext_mesh_shader: true,
khr_spirv_1_4: true,
khr_shader_float_controls: true,
..DeviceExtensions::empty() ..DeviceExtensions::empty()
}; };
...@@ -161,7 +176,8 @@ fn main() { ...@@ -161,7 +176,8 @@ fn main() {
// We select a queue family that supports graphics operations. When drawing to // 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 // 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. // 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 // 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 // found, `None` is returned to `filter_map`, which disqualifies this physical
...@@ -273,16 +289,13 @@ fn main() { ...@@ -273,16 +289,13 @@ fn main() {
// use that. // use that.
image_extent: window.inner_size().into(), image_extent: window.inner_size().into(),
image_usage: ImageUsage { image_usage: ImageUsage::COLOR_ATTACHMENT,
color_attachment: true,
..ImageUsage::empty()
},
// The alpha mode indicates how the alpha value of the final image will behave. For // 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. // example, you can choose whether the window will be opaque or transparent.
composite_alpha: surface_capabilities composite_alpha: surface_capabilities
.supported_composite_alpha .supported_composite_alpha
.iter() .into_iter()
.next() .next()
.unwrap(), .unwrap(),
...@@ -338,6 +351,8 @@ fn main() { ...@@ -338,6 +351,8 @@ fn main() {
#[derive(Clone, Copy, Zeroable, Pod, Debug)] #[derive(Clone, Copy, Zeroable, Pod, Debug)]
}, },
vulkan_version: "1.2",
spirv_version: "1.4"
} }
} }
...@@ -350,12 +365,30 @@ fn main() { ...@@ -350,12 +365,30 @@ fn main() {
#[derive(Clone, Copy, Zeroable, Pod, Debug)] #[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_vs = mesh_vs::load(device.clone()).unwrap();
let mesh_fs = mesh_fs::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 = /*let uniform_buffer =
CpuBufferPool::<vs::ty::PushConstantData>::uniform_buffer(memory_allocator);*/ CpuBufferPool::<vs::ty::PushConstantData>::uniform_buffer(memory_allocator);*/
...@@ -429,6 +462,7 @@ fn main() { ...@@ -429,6 +462,7 @@ fn main() {
&memory_allocator, &memory_allocator,
&mesh_vs, &mesh_vs,
&mesh_fs, &mesh_fs,
&implicit_ms,
&images, &images,
render_pass.clone(), render_pass.clone(),
&mut viewport, &mut viewport,
...@@ -476,13 +510,13 @@ fn main() { ...@@ -476,13 +510,13 @@ fn main() {
let descriptor_set_allocator = StandardDescriptorSetAllocator::new(device.clone()); 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(), memory_allocator.clone(),
BufferUsage { SubbufferAllocatorCreateInfo {
uniform_buffer: true, // We want to use the allocated subbuffers as vertex buffers.
..BufferUsage::empty() buffer_usage: BufferUsage::UNIFORM_BUFFER,
..Default::default()
}, },
MemoryUsage::Upload,
); );
// Create an egui GUI // Create an egui GUI
...@@ -638,6 +672,7 @@ fn main() { ...@@ -638,6 +672,7 @@ fn main() {
&memory_allocator, &memory_allocator,
&mesh_vs, &mesh_vs,
&mesh_fs, &mesh_fs,
&implicit_ms,
&new_images, &new_images,
render_pass.clone(), render_pass.clone(),
&mut viewport, &mut viewport,
...@@ -737,7 +772,9 @@ fn main() { ...@@ -737,7 +772,9 @@ fn main() {
light_count: gstate.lights.len() as u32, 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(); let layout = mesh_pipeline.layout().set_layouts().get(0).unwrap();
...@@ -843,6 +880,36 @@ fn main() { ...@@ -843,6 +880,36 @@ fn main() {
.unwrap(); .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 // We leave the render pass. Note that if we had multiple
// subpasses we could have called `next_subpass` to jump to the next subpass. // subpasses we could have called `next_subpass` to jump to the next subpass.
builder builder
...@@ -898,6 +965,7 @@ fn window_size_dependent_setup( ...@@ -898,6 +965,7 @@ fn window_size_dependent_setup(
allocator: &StandardMemoryAllocator, allocator: &StandardMemoryAllocator,
mesh_vs: &ShaderModule, mesh_vs: &ShaderModule,
mesh_fs: &ShaderModule, mesh_fs: &ShaderModule,
implicit_ms: &ShaderModule,
images: &[Arc<SwapchainImage>], images: &[Arc<SwapchainImage>],
render_pass: Arc<RenderPass>, render_pass: Arc<RenderPass>,
viewport: &mut Viewport, viewport: &mut Viewport,
...@@ -932,7 +1000,7 @@ fn window_size_dependent_setup( ...@@ -932,7 +1000,7 @@ fn window_size_dependent_setup(
// in. The pipeline will only be usable from this particular subpass. // in. The pipeline will only be usable from this particular subpass.
.render_pass(Subpass::from(render_pass.clone(), 0).unwrap()) .render_pass(Subpass::from(render_pass.clone(), 0).unwrap())
// We need to indicate the layout of the vertices. // 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. // The content of the vertex buffer describes a list of triangles.
.input_assembly_state(InputAssemblyState::new()) .input_assembly_state(InputAssemblyState::new())
// A Vulkan shader can in theory contain multiple entry points, so we have to specify // A Vulkan shader can in theory contain multiple entry points, so we have to specify
...@@ -947,6 +1015,7 @@ fn window_size_dependent_setup( ...@@ -947,6 +1015,7 @@ fn window_size_dependent_setup(
])) ]))
// See `vertex_shader`. // See `vertex_shader`.
.fragment_shader(mesh_fs.entry_point("main").unwrap(), ()) .fragment_shader(mesh_fs.entry_point("main").unwrap(), ())
.mesh_shader(implicit_ms.entry_point("main").unwrap(), ())
.depth_stencil_state(DepthStencilState::simple_depth_test()) .depth_stencil_state(DepthStencilState::simple_depth_test())
.rasterization_state(RasterizationState { .rasterization_state(RasterizationState {
front_face: Fixed(Clockwise), front_face: Fixed(Clockwise),
......
...@@ -4,8 +4,8 @@ use bytemuck::{Pod, Zeroable}; ...@@ -4,8 +4,8 @@ use bytemuck::{Pod, Zeroable};
use cgmath::{Deg, Euler, Matrix3, Point3, SquareMatrix, Vector3}; use cgmath::{Deg, Euler, Matrix3, Point3, SquareMatrix, Vector3};
use obj::{LoadConfig, ObjData}; use obj::{LoadConfig, ObjData};
use vulkano::{ use vulkano::{
buffer::{BufferUsage, CpuAccessibleBuffer}, buffer::{Buffer, BufferAllocateInfo, BufferUsage, Subbuffer},
impl_vertex, pipeline::graphics::vertex_input::Vertex,
}; };
use crate::MemoryAllocator; use crate::MemoryAllocator;
...@@ -16,18 +16,19 @@ pub const PLATONIC_SOLIDS: [(&str, &[u8]); 1] = [("Buny", include_bytes!("bunny. ...@@ -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 // 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. // particular example, it doesn't actually change the in-memory representation.
#[repr(C)] #[repr(C)]
#[derive(Clone, Copy, Debug, Default, Zeroable, Pod)] #[derive(Clone, Copy, Debug, Default, Zeroable, Pod, Vertex)]
pub struct Vertex { pub struct OVertex {
#[format(R32G32B32_SFLOAT)]
position: [f32; 3], position: [f32; 3],
#[format(R32G32B32_SFLOAT)]
normal: [f32; 3], normal: [f32; 3],
} }
impl_vertex!(Vertex, position, normal);
#[derive(Debug)] #[derive(Debug)]
pub struct Mesh { pub struct Mesh {
pub name: String, pub name: String,
pub vertices: Arc<CpuAccessibleBuffer<[Vertex]>>, pub vertices: Subbuffer<[OVertex]>,
pub indices: Arc<CpuAccessibleBuffer<[u32]>>, pub indices: Subbuffer<[u32]>,
pub pos: Point3<f32>, pub pos: Point3<f32>,
pub rot: Euler<Deg<f32>>, pub rot: Euler<Deg<f32>>,
pub scale: f32, pub scale: f32,
...@@ -55,7 +56,7 @@ pub fn load_obj(memory_allocator: &MemoryAllocator, input: &mut dyn Read, name: ...@@ -55,7 +56,7 @@ pub fn load_obj(memory_allocator: &MemoryAllocator, input: &mut dyn Read, name:
//println!("{:?}", exist); //println!("{:?}", exist);
indices.push(exist); indices.push(exist);
} else { } else {
vertices.push(Vertex { vertices.push(OVertex {
position: object.position[mapping.0 as usize], position: object.position[mapping.0 as usize],
normal: object.normal[mapping.1 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: ...@@ -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, memory_allocator,
BufferUsage { BufferAllocateInfo {
vertex_buffer: true, buffer_usage: BufferUsage::VERTEX_BUFFER,
..BufferUsage::empty() ..Default::default()
}, },
false,
vertices, vertices,
) )
.unwrap(); .unwrap();
let index_buffer = CpuAccessibleBuffer::from_iter( let index_buffer = Buffer::from_iter(
memory_allocator, memory_allocator,
BufferUsage { BufferAllocateInfo {
index_buffer: true, buffer_usage: BufferUsage::INDEX_BUFFER,
..BufferUsage::empty() ..Default::default()
}, },
false,
indices, indices,
) )
.unwrap(); .unwrap();
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment