018: Data for the vertex shader
This commit is contained in:
parent
84019305a9
commit
7be29cb3a9
9 changed files with 292 additions and 52 deletions
96
Cargo.lock
generated
96
Cargo.lock
generated
|
|
@ -505,6 +505,19 @@ dependencies = [
|
|||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gpu-allocator"
|
||||
version = "0.27.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c151a2a5ef800297b4e79efa4f4bec035c5f51d5ae587287c9b952bdf734cacd"
|
||||
dependencies = [
|
||||
"ash",
|
||||
"log",
|
||||
"presser",
|
||||
"thiserror",
|
||||
"windows",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.14.5"
|
||||
|
|
@ -792,6 +805,12 @@ dependencies = [
|
|||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "presser"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e8cf8e6a8aa66ce33f63993ffc4ea4271eb5b0530a9002db8455ea6050c77bfa"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-crate"
|
||||
version = "1.3.1"
|
||||
|
|
@ -1159,17 +1178,6 @@ version = "0.9.4"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||
|
||||
[[package]]
|
||||
name = "vk-mem"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0cb12b79bcec57a3334d0284f1364c1846f378bb47df9779c6dbfcfc245c9404"
|
||||
dependencies = [
|
||||
"ash",
|
||||
"bitflags 2.6.0",
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "vk-shader-macros"
|
||||
version = "0.2.10"
|
||||
|
|
@ -1190,9 +1198,9 @@ dependencies = [
|
|||
"ash-window",
|
||||
"dotenvy",
|
||||
"env_logger",
|
||||
"gpu-allocator",
|
||||
"log",
|
||||
"thiserror",
|
||||
"vk-mem",
|
||||
"vk-shader-macros",
|
||||
"winit",
|
||||
]
|
||||
|
|
@ -1417,6 +1425,70 @@ dependencies = [
|
|||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows"
|
||||
version = "0.58.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6"
|
||||
dependencies = [
|
||||
"windows-core",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.58.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99"
|
||||
dependencies = [
|
||||
"windows-implement",
|
||||
"windows-interface",
|
||||
"windows-result",
|
||||
"windows-strings",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-implement"
|
||||
version = "0.58.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-interface"
|
||||
version = "0.58.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-result"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e"
|
||||
dependencies = [
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-strings"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10"
|
||||
dependencies = [
|
||||
"windows-result",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.45.0"
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@ ash = "0.38.0"
|
|||
ash-window = "0.13.0"
|
||||
dotenvy = "0.15.7"
|
||||
env_logger = "0.11.3"
|
||||
gpu-allocator = "0.27.0"
|
||||
log = "0.4.22"
|
||||
thiserror = "1.0.62"
|
||||
vk-mem = "0.4.0"
|
||||
vk-shader-macros = "0.2.10"
|
||||
winit = { version = "0.29", features = ["rwh_06"] }
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
layout(location = 0) out vec4 theColour;
|
||||
|
||||
layout(location = 1) in vec4 colourdata_from_the_vertexshader;
|
||||
layout(location = 0) in vec4 data_from_the_vertexshader;
|
||||
|
||||
void main() {
|
||||
theColour = colourdata_from_the_vertexshader;
|
||||
theColour = data_from_the_vertexshader;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,13 @@
|
|||
#version 450
|
||||
|
||||
layout(location = 1) out vec4 colourdata_from_the_vertexshader;
|
||||
layout(location = 0) in vec4 position;
|
||||
layout(location = 1) in float size;
|
||||
layout(location = 2) in vec4 colour;
|
||||
|
||||
layout(location = 0) out vec4 colourdata_for_the_fragmentshader;
|
||||
|
||||
void main() {
|
||||
gl_PointSize = 10.0;
|
||||
gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
colourdata_from_the_vertexshader = vec4(0.0, 0.6, 1.0, 1.0);
|
||||
gl_PointSize = size;
|
||||
gl_Position = position;
|
||||
colourdata_for_the_fragmentshader = vec4(0.4, 1.0, 0.5, 1.0);
|
||||
}
|
||||
|
|
|
|||
89
src/instance/buffer.rs
Normal file
89
src/instance/buffer.rs
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
use ash::vk;
|
||||
use gpu_allocator::vulkan::Allocation as GpuAllocation;
|
||||
use gpu_allocator::vulkan::AllocationCreateDesc;
|
||||
use gpu_allocator::vulkan::AllocationScheme;
|
||||
use gpu_allocator::vulkan::Allocator as GpuAllocator;
|
||||
use gpu_allocator::vulkan::AllocatorCreateDesc;
|
||||
use gpu_allocator::MemoryLocation;
|
||||
|
||||
use super::EngineError;
|
||||
|
||||
pub struct BufferAllocator {
|
||||
pub allocator: GpuAllocator,
|
||||
}
|
||||
|
||||
pub struct Buffer {
|
||||
pub allocation: Option<GpuAllocation>,
|
||||
pub buffer: vk::Buffer,
|
||||
}
|
||||
|
||||
impl BufferAllocator {
|
||||
pub fn init(
|
||||
ash_instance: &ash::Instance,
|
||||
physical_device: vk::PhysicalDevice,
|
||||
device: &ash::Device,
|
||||
) -> Result<Self, EngineError> {
|
||||
let allocator = GpuAllocator::new(&AllocatorCreateDesc {
|
||||
instance: ash_instance.clone(),
|
||||
device: device.clone(),
|
||||
physical_device,
|
||||
debug_settings: Default::default(),
|
||||
buffer_device_address: true, // Ideally, check the BufferDeviceAddressFeatures struct.
|
||||
allocation_sizes: Default::default(),
|
||||
})?;
|
||||
Ok(Self { allocator })
|
||||
}
|
||||
|
||||
pub fn create_buffer(
|
||||
&mut self,
|
||||
device: &ash::Device,
|
||||
size: u64,
|
||||
) -> Result<Buffer, EngineError> {
|
||||
let vk_info = vk::BufferCreateInfo::default()
|
||||
.size(size)
|
||||
.usage(vk::BufferUsageFlags::STORAGE_BUFFER);
|
||||
|
||||
let buffer = unsafe { device.create_buffer(&vk_info, None) }.unwrap();
|
||||
let requirements = unsafe { device.get_buffer_memory_requirements(buffer) };
|
||||
let allocation = self.allocator.allocate(&AllocationCreateDesc {
|
||||
name: "Example allocation",
|
||||
requirements,
|
||||
location: MemoryLocation::CpuToGpu,
|
||||
linear: true, // Buffers are always linear
|
||||
allocation_scheme: AllocationScheme::GpuAllocatorManaged,
|
||||
})?;
|
||||
|
||||
// Bind memory to the buffer
|
||||
unsafe {
|
||||
device
|
||||
.bind_buffer_memory(buffer, allocation.memory(), allocation.offset())
|
||||
.unwrap()
|
||||
};
|
||||
|
||||
Ok(Buffer {
|
||||
allocation: Some(allocation),
|
||||
buffer,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn free_buffer_allocation(&mut self, device: &ash::Device, buffer: &mut Buffer) {
|
||||
let allocation = buffer.allocation.take();
|
||||
self.allocator.free(allocation.unwrap()).unwrap();
|
||||
unsafe { device.destroy_buffer(buffer.buffer, None) };
|
||||
}
|
||||
}
|
||||
|
||||
impl Buffer {
|
||||
pub fn mapped_slice_mut(&mut self) -> Option<&mut [u8]> {
|
||||
if let Some(v) = &mut self.allocation {
|
||||
v.mapped_slice_mut()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn fill(&mut self, data: &[u8]) {
|
||||
let inner_buffer = self.mapped_slice_mut().unwrap();
|
||||
inner_buffer.copy_from_slice(data);
|
||||
}
|
||||
}
|
||||
17
src/instance/error.rs
Normal file
17
src/instance/error.rs
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
use ash::vk;
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum EngineError {
|
||||
#[error(transparent)]
|
||||
VkError(#[from] vk::Result),
|
||||
#[error(transparent)]
|
||||
AshLoadingError(#[from] ash::LoadingError),
|
||||
#[error(transparent)]
|
||||
WinitOsError(#[from] winit::error::OsError),
|
||||
#[error(transparent)]
|
||||
WinitEventLoopError(#[from] winit::error::EventLoopError),
|
||||
#[error(transparent)]
|
||||
RWHError(#[from] winit::raw_window_handle::HandleError),
|
||||
#[error(transparent)]
|
||||
AllocationError(#[from] gpu_allocator::AllocationError),
|
||||
}
|
||||
|
|
@ -1,8 +1,11 @@
|
|||
use std::ffi::{c_char, CString};
|
||||
|
||||
use ash::vk;
|
||||
use buffer::{Buffer, BufferAllocator};
|
||||
|
||||
pub mod buffer;
|
||||
pub mod debug;
|
||||
pub mod error;
|
||||
pub mod pipeline;
|
||||
pub mod pools;
|
||||
pub mod queue;
|
||||
|
|
@ -10,6 +13,8 @@ pub mod surface;
|
|||
pub mod swapchain;
|
||||
pub mod window;
|
||||
|
||||
pub use error::EngineError;
|
||||
|
||||
pub use debug::DebugInstance;
|
||||
pub use pipeline::Pipeline;
|
||||
use pools::Pools;
|
||||
|
|
@ -23,20 +28,6 @@ use crate::frame_counter::FrameCounter;
|
|||
const ENGINE_NAME: &core::ffi::CStr = c"UnknownGameEngine";
|
||||
const APP_NAME: &core::ffi::CStr = c"Vulkan Tutorial";
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum EngineError {
|
||||
#[error(transparent)]
|
||||
VkError(#[from] vk::Result),
|
||||
#[error(transparent)]
|
||||
AshLoadingError(#[from] ash::LoadingError),
|
||||
#[error(transparent)]
|
||||
WinitOsError(#[from] winit::error::OsError),
|
||||
#[error(transparent)]
|
||||
WinitEventLoopError(#[from] winit::error::EventLoopError),
|
||||
#[error(transparent)]
|
||||
RWHError(#[from] winit::raw_window_handle::HandleError),
|
||||
}
|
||||
|
||||
pub struct EngineInstance {
|
||||
pub entry: ash::Entry,
|
||||
pub ash_instance: ash::Instance,
|
||||
|
|
@ -53,6 +44,9 @@ pub struct EngineInstance {
|
|||
pub pipeline: Pipeline,
|
||||
pub pools: Pools,
|
||||
pub commandbuffers: Vec<vk::CommandBuffer>,
|
||||
pub allocator: std::mem::ManuallyDrop<BufferAllocator>,
|
||||
pub buffer1: Buffer,
|
||||
pub buffer2: Buffer,
|
||||
pub framecount: FrameCounter,
|
||||
}
|
||||
|
||||
|
|
@ -118,8 +112,62 @@ impl EngineInstance {
|
|||
let renderpass = Self::init_renderpass(&device, surface_format.format)?;
|
||||
swapchain.create_framebuffers(&device, renderpass)?;
|
||||
|
||||
log::debug!("Create allocator");
|
||||
let mut allocator = BufferAllocator::init(&ash_instance, physical_device, &device)?;
|
||||
let mut buffer1 = allocator.create_buffer(&device, 16)?;
|
||||
|
||||
unsafe {
|
||||
let data: [u8; 16] = std::mem::transmute([-0.5f32, 0.0f32, 0.0f32, 1.0f32]);
|
||||
buffer1.fill(&data);
|
||||
}
|
||||
|
||||
let mut buffer2 = allocator.create_buffer(&device, 20)?;
|
||||
unsafe {
|
||||
let data: [u8; 20] = std::mem::transmute([5.0f32, 1.0f32, 1.0f32, 0.0f32, 1.0f32]);
|
||||
buffer2.fill(&data);
|
||||
}
|
||||
|
||||
let vertex_attrib_descs = [
|
||||
vk::VertexInputAttributeDescription {
|
||||
binding: 0,
|
||||
location: 0,
|
||||
offset: 0,
|
||||
format: vk::Format::R32G32B32A32_SFLOAT,
|
||||
},
|
||||
vk::VertexInputAttributeDescription {
|
||||
binding: 1,
|
||||
location: 1,
|
||||
offset: 0,
|
||||
format: vk::Format::R32_SFLOAT,
|
||||
},
|
||||
vk::VertexInputAttributeDescription {
|
||||
binding: 1,
|
||||
location: 2,
|
||||
offset: 4,
|
||||
format: vk::Format::R32G32B32A32_SFLOAT,
|
||||
},
|
||||
];
|
||||
let vertex_binding_descs = [
|
||||
vk::VertexInputBindingDescription {
|
||||
binding: 0,
|
||||
stride: 16,
|
||||
input_rate: vk::VertexInputRate::VERTEX,
|
||||
},
|
||||
vk::VertexInputBindingDescription {
|
||||
binding: 1,
|
||||
stride: 20,
|
||||
input_rate: vk::VertexInputRate::VERTEX,
|
||||
},
|
||||
];
|
||||
|
||||
log::debug!("Init pipeline");
|
||||
let pipeline = Pipeline::init(&device, &swapchain, &renderpass)?;
|
||||
let pipeline = Pipeline::init(
|
||||
&device,
|
||||
&swapchain,
|
||||
&renderpass,
|
||||
&vertex_attrib_descs,
|
||||
&vertex_binding_descs,
|
||||
)?;
|
||||
|
||||
log::debug!("Init pools");
|
||||
let pools = Pools::init(&device, &queue_families)?;
|
||||
|
|
@ -127,7 +175,16 @@ impl EngineInstance {
|
|||
log::debug!("Create command buffers");
|
||||
let commandbuffers = pools.create_commandbuffers(&device, swapchain.framebuffers.len())?;
|
||||
for (i, &commandbuffer) in commandbuffers.iter().enumerate() {
|
||||
Self::fill_commandbuffer(&device, commandbuffer, renderpass, &swapchain, i, &pipeline)?;
|
||||
Self::fill_commandbuffer(
|
||||
&device,
|
||||
commandbuffer,
|
||||
renderpass,
|
||||
&swapchain,
|
||||
i,
|
||||
&pipeline,
|
||||
buffer1.buffer,
|
||||
buffer2.buffer,
|
||||
)?;
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
|
|
@ -146,6 +203,9 @@ impl EngineInstance {
|
|||
pipeline,
|
||||
pools,
|
||||
commandbuffers,
|
||||
allocator: std::mem::ManuallyDrop::new(allocator),
|
||||
buffer1,
|
||||
buffer2,
|
||||
framecount: FrameCounter::new(),
|
||||
})
|
||||
}
|
||||
|
|
@ -156,8 +216,14 @@ impl EngineInstance {
|
|||
.device_wait_idle()
|
||||
.expect("something wrong while waiting");
|
||||
self.pools.cleanup(&self.device);
|
||||
// self.queues.cleanup();
|
||||
self.pipeline.cleanup(&self.device);
|
||||
|
||||
self.allocator
|
||||
.free_buffer_allocation(&self.device, &mut self.buffer1);
|
||||
self.allocator
|
||||
.free_buffer_allocation(&self.device, &mut self.buffer2);
|
||||
std::mem::ManuallyDrop::drop(&mut self.allocator);
|
||||
|
||||
self.device.destroy_render_pass(self.renderpass, None);
|
||||
self.swapchain.cleanup(&self.device);
|
||||
std::mem::ManuallyDrop::drop(&mut self.surface);
|
||||
|
|
@ -325,6 +391,9 @@ impl EngineInstance {
|
|||
swapchain: &Swapchain,
|
||||
framebuffer_index: usize,
|
||||
pipeline: &Pipeline,
|
||||
// buffers: &[vk::Buffer],
|
||||
buffer1: vk::Buffer,
|
||||
buffer2: vk::Buffer,
|
||||
) -> Result<(), vk::Result> {
|
||||
let commandbuffer_begininfo = vk::CommandBufferBeginInfo::default();
|
||||
unsafe {
|
||||
|
|
@ -356,6 +425,8 @@ impl EngineInstance {
|
|||
vk::PipelineBindPoint::GRAPHICS,
|
||||
pipeline.pipeline,
|
||||
);
|
||||
device.cmd_bind_vertex_buffers(commandbuffer, 0, &[buffer1], &[0]);
|
||||
device.cmd_bind_vertex_buffers(commandbuffer, 1, &[buffer2], &[0]);
|
||||
device.cmd_draw(commandbuffer, 1, 1, 0, 0);
|
||||
device.cmd_end_render_pass(commandbuffer);
|
||||
device.end_command_buffer(commandbuffer)?;
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@ impl Pipeline {
|
|||
logical_device: &ash::Device,
|
||||
swapchain: &Swapchain,
|
||||
renderpass: &vk::RenderPass,
|
||||
vertex_attrib_descs: &[vk::VertexInputAttributeDescription],
|
||||
vertex_binding_descs: &[vk::VertexInputBindingDescription],
|
||||
) -> Result<Pipeline, vk::Result> {
|
||||
let vertexshader_createinfo = vk::ShaderModuleCreateInfo::default()
|
||||
.code(vk_shader_macros::include_glsl!("./shaders/shader.vert", kind: vert));
|
||||
|
|
@ -42,18 +44,6 @@ impl Pipeline {
|
|||
.name(&mainfunctionname);
|
||||
let shader_stages = vec![vertexshader_stage, fragmentshader_stage];
|
||||
|
||||
let vertex_attrib_descs = [vk::VertexInputAttributeDescription {
|
||||
binding: 0,
|
||||
location: 0,
|
||||
offset: 0,
|
||||
format: vk::Format::R32G32B32A32_SFLOAT,
|
||||
}];
|
||||
let vertex_binding_descs = [vk::VertexInputBindingDescription {
|
||||
binding: 0,
|
||||
stride: 16,
|
||||
input_rate: vk::VertexInputRate::VERTEX,
|
||||
}];
|
||||
|
||||
let vertex_input_info = vk::PipelineVertexInputStateCreateInfo::default()
|
||||
.vertex_attribute_descriptions(&vertex_attrib_descs)
|
||||
.vertex_binding_descriptions(&vertex_binding_descs);
|
||||
|
|
|
|||
|
|
@ -54,10 +54,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
|
||||
let semaphores_available = [e.swapchain.image_available[e.swapchain.current_image]];
|
||||
let waiting_stages = [vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT];
|
||||
let semaphores_finished = [
|
||||
e.swapchain.rendering_finished[e.swapchain.current_image],
|
||||
// e.swapchain.next_frame[next_image],
|
||||
];
|
||||
let semaphores_finished = [e.swapchain.rendering_finished[e.swapchain.current_image]];
|
||||
let commandbuffers = [e.commandbuffers[image_index as usize]];
|
||||
let submit_info = [vk::SubmitInfo::default()
|
||||
.wait_semaphores(&semaphores_available)
|
||||
|
|
|
|||
Loading…
Reference in a new issue