Start on implementing texture mapping (partially complete section 28 of the tutorial)
This commit is contained in:
parent
2d5a0420cd
commit
425577029d
283
src/app/data.rs
283
src/app/data.rs
@ -1,3 +1,4 @@
|
||||
#![allow(clippy::too_many_arguments)]
|
||||
use super::functions::*;
|
||||
use super::*;
|
||||
use crate::VALIDATION_ENABLED;
|
||||
@ -6,6 +7,7 @@ use ::anyhow::{anyhow, Result};
|
||||
use ::log::*;
|
||||
use ::std::collections::HashSet;
|
||||
use ::std::ffi::CStr;
|
||||
use ::std::fs::File;
|
||||
use ::std::os::raw::c_void;
|
||||
use ::std::ptr::copy_nonoverlapping as memcpy;
|
||||
use ::vulkanalia::prelude::v1_0::*;
|
||||
@ -61,6 +63,9 @@ pub(crate) struct AppData {
|
||||
framebuffers: Vec<vk::Framebuffer>,
|
||||
// Command Pool
|
||||
command_pool: vk::CommandPool,
|
||||
// Texture
|
||||
texture_image: vk::Image,
|
||||
texture_image_memory: vk::DeviceMemory,
|
||||
// Buffers
|
||||
vertex_buffer: vk::Buffer,
|
||||
vertex_buffer_memory: vk::DeviceMemory,
|
||||
@ -68,6 +73,7 @@ pub(crate) struct AppData {
|
||||
index_buffer_memory: vk::DeviceMemory,
|
||||
uniform_buffers: Vec<vk::Buffer>,
|
||||
pub(super) uniform_buffers_memory: Vec<vk::DeviceMemory>,
|
||||
// Descriptors
|
||||
descriptor_pool: vk::DescriptorPool,
|
||||
descriptor_sets: Vec<vk::DescriptorSet>,
|
||||
// Command Buffers
|
||||
@ -102,6 +108,7 @@ impl AppData {
|
||||
self.create_pipeline(&device)?;
|
||||
self.create_framebuffers(&device)?;
|
||||
self.create_command_pool(&instance, &device)?;
|
||||
self.create_texture_image(&instance, &device)?;
|
||||
self.create_vertex_buffer(&instance, &device)?;
|
||||
self.create_index_buffer(&instance, &device)?;
|
||||
self.create_uniform_buffers(&instance, &device)?;
|
||||
@ -474,21 +481,6 @@ impl AppData {
|
||||
// Pipeline
|
||||
//================================================
|
||||
|
||||
unsafe fn create_descriptor_set_layout(&mut self, device: &Device) -> Result<()> {
|
||||
let ubo_binding = vk::DescriptorSetLayoutBinding::builder()
|
||||
.binding(0)
|
||||
.descriptor_type(vk::DescriptorType::UNIFORM_BUFFER)
|
||||
.descriptor_count(1)
|
||||
.stage_flags(vk::ShaderStageFlags::VERTEX);
|
||||
|
||||
let bindings = &[ubo_binding];
|
||||
let info = vk::DescriptorSetLayoutCreateInfo::builder().bindings(bindings);
|
||||
|
||||
self.descriptor_set_layout = device.create_descriptor_set_layout(&info, None)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
unsafe fn create_render_pass(&mut self, _instance: &Instance, device: &Device) -> Result<()> {
|
||||
let color_attachment = vk::AttachmentDescription::builder()
|
||||
.format(self.swapchain_format)
|
||||
@ -529,6 +521,21 @@ impl AppData {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
unsafe fn create_descriptor_set_layout(&mut self, device: &Device) -> Result<()> {
|
||||
let ubo_binding = vk::DescriptorSetLayoutBinding::builder()
|
||||
.binding(0)
|
||||
.descriptor_type(vk::DescriptorType::UNIFORM_BUFFER)
|
||||
.descriptor_count(1)
|
||||
.stage_flags(vk::ShaderStageFlags::VERTEX);
|
||||
|
||||
let bindings = &[ubo_binding];
|
||||
let info = vk::DescriptorSetLayoutCreateInfo::builder().bindings(bindings);
|
||||
|
||||
self.descriptor_set_layout = device.create_descriptor_set_layout(&info, None)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
unsafe fn create_pipeline(&mut self, device: &Device) -> Result<()> {
|
||||
let vert = include_bytes!("../../shaders/vert.spv");
|
||||
let frag = include_bytes!("../../shaders/frag.spv");
|
||||
@ -632,6 +639,10 @@ impl AppData {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
//================================================
|
||||
// Framebuffers
|
||||
//================================================
|
||||
|
||||
unsafe fn create_framebuffers(&mut self, device: &Device) -> Result<()> {
|
||||
self.framebuffers = self
|
||||
.swapchain_image_views
|
||||
@ -669,74 +680,62 @@ impl AppData {
|
||||
}
|
||||
|
||||
//================================================
|
||||
// Buffers
|
||||
// Texture
|
||||
//================================================
|
||||
|
||||
unsafe fn create_buffer(
|
||||
&self,
|
||||
instance: &Instance,
|
||||
device: &Device,
|
||||
size: vk::DeviceSize,
|
||||
usage: vk::BufferUsageFlags,
|
||||
properties: vk::MemoryPropertyFlags,
|
||||
) -> Result<(vk::Buffer, vk::DeviceMemory)> {
|
||||
let buffer_info = vk::BufferCreateInfo::builder()
|
||||
.size(size)
|
||||
.usage(usage)
|
||||
.sharing_mode(vk::SharingMode::EXCLUSIVE);
|
||||
fn create_texture_image(&mut self, instance: &Instance, device: &Device) -> Result<()> {
|
||||
let image = File::open("resources/texture.png")?;
|
||||
|
||||
let buffer = device.create_buffer(&buffer_info, None)?;
|
||||
let decoder = png::Decoder::new(image);
|
||||
let mut reader = decoder.read_info()?;
|
||||
|
||||
let requirements = device.get_buffer_memory_requirements(buffer);
|
||||
let mut pixels = vec![0; reader.info().raw_bytes()];
|
||||
reader.next_frame(&mut pixels)?;
|
||||
|
||||
let memory_info = vk::MemoryAllocateInfo::builder()
|
||||
.allocation_size(requirements.size)
|
||||
.memory_type_index(self.get_memory_type_index(instance, properties, requirements)?);
|
||||
let size = reader.info().raw_bytes() as u64;
|
||||
let (width, height) = reader.info().size();
|
||||
|
||||
let buffer_memory = device.allocate_memory(&memory_info, None)?;
|
||||
let (_, staging_buffer_memory) = unsafe {
|
||||
self.create_buffer(
|
||||
instance,
|
||||
device,
|
||||
size,
|
||||
vk::BufferUsageFlags::TRANSFER_SRC,
|
||||
vk::MemoryPropertyFlags::HOST_COHERENT | vk::MemoryPropertyFlags::HOST_VISIBLE,
|
||||
)?
|
||||
};
|
||||
|
||||
device.bind_buffer_memory(buffer, buffer_memory, 0)?;
|
||||
let memory = unsafe {
|
||||
device.map_memory(staging_buffer_memory, 0, size, vk::MemoryMapFlags::empty())?
|
||||
};
|
||||
|
||||
Ok((buffer, buffer_memory))
|
||||
}
|
||||
unsafe {
|
||||
memcpy(pixels.as_ptr(), memory.cast(), pixels.len());
|
||||
|
||||
unsafe fn copy_buffer(
|
||||
&self,
|
||||
device: &Device,
|
||||
source: vk::Buffer,
|
||||
destination: vk::Buffer,
|
||||
size: vk::DeviceSize,
|
||||
) -> Result<()> {
|
||||
// Create the command buffer
|
||||
let info = vk::CommandBufferAllocateInfo::builder()
|
||||
.level(vk::CommandBufferLevel::PRIMARY)
|
||||
.command_pool(self.command_pool)
|
||||
.command_buffer_count(1);
|
||||
device.unmap_memory(staging_buffer_memory);
|
||||
|
||||
let command_buffer = device.allocate_command_buffers(&info)?[0];
|
||||
let (texture_image, texture_image_memory) = self.create_image(
|
||||
instance,
|
||||
device,
|
||||
width,
|
||||
height,
|
||||
vk::Format::R8G8B8A8_SRGB,
|
||||
vk::ImageTiling::OPTIMAL,
|
||||
vk::ImageUsageFlags::SAMPLED | vk::ImageUsageFlags::TRANSFER_DST,
|
||||
vk::MemoryPropertyFlags::DEVICE_LOCAL,
|
||||
)?;
|
||||
|
||||
let info = vk::CommandBufferBeginInfo::builder()
|
||||
.flags(vk::CommandBufferUsageFlags::ONE_TIME_SUBMIT);
|
||||
|
||||
device.begin_command_buffer(command_buffer, &info)?;
|
||||
|
||||
let regions = vk::BufferCopy::builder().size(size);
|
||||
device.cmd_copy_buffer(command_buffer, source, destination, &[regions]);
|
||||
|
||||
device.end_command_buffer(command_buffer)?;
|
||||
|
||||
// Execute command buffer
|
||||
let command_buffers = &[command_buffer];
|
||||
let info = vk::SubmitInfo::builder().command_buffers(command_buffers);
|
||||
|
||||
device.queue_submit(self.graphics_queue, &[info], vk::Fence::null())?;
|
||||
device.queue_wait_idle(self.graphics_queue)?;
|
||||
|
||||
device.free_command_buffers(self.command_pool, &[command_buffer]);
|
||||
self.texture_image = texture_image;
|
||||
self.texture_image_memory = texture_image_memory;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
//================================================
|
||||
// Buffers
|
||||
//================================================
|
||||
|
||||
unsafe fn create_vertex_buffer(&mut self, instance: &Instance, device: &Device) -> Result<()> {
|
||||
// Create staging buffer
|
||||
let size = (size_of::<Vertex>() * VERTICES.len()) as u64;
|
||||
@ -833,6 +832,10 @@ impl AppData {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
//================================================
|
||||
// Descriptors
|
||||
//================================================
|
||||
|
||||
unsafe fn create_descriptor_pool(&mut self, device: &Device) -> Result<()> {
|
||||
let ubo_size = vk::DescriptorPoolSize::builder()
|
||||
.type_(vk::DescriptorType::UNIFORM_BUFFER)
|
||||
@ -973,6 +976,116 @@ impl AppData {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
//================================================
|
||||
// Shared (Buffers)
|
||||
//================================================
|
||||
|
||||
unsafe fn create_buffer(
|
||||
&self,
|
||||
instance: &Instance,
|
||||
device: &Device,
|
||||
size: vk::DeviceSize,
|
||||
usage: vk::BufferUsageFlags,
|
||||
properties: vk::MemoryPropertyFlags,
|
||||
) -> Result<(vk::Buffer, vk::DeviceMemory)> {
|
||||
let buffer_info = vk::BufferCreateInfo::builder()
|
||||
.size(size)
|
||||
.usage(usage)
|
||||
.sharing_mode(vk::SharingMode::EXCLUSIVE);
|
||||
|
||||
let buffer = device.create_buffer(&buffer_info, None)?;
|
||||
|
||||
let requirements = device.get_buffer_memory_requirements(buffer);
|
||||
|
||||
let memory_info = vk::MemoryAllocateInfo::builder()
|
||||
.allocation_size(requirements.size)
|
||||
.memory_type_index(self.get_memory_type_index(instance, properties, requirements)?);
|
||||
|
||||
let buffer_memory = device.allocate_memory(&memory_info, None)?;
|
||||
|
||||
device.bind_buffer_memory(buffer, buffer_memory, 0)?;
|
||||
|
||||
Ok((buffer, buffer_memory))
|
||||
}
|
||||
|
||||
unsafe fn copy_buffer(
|
||||
&self,
|
||||
device: &Device,
|
||||
source: vk::Buffer,
|
||||
destination: vk::Buffer,
|
||||
size: vk::DeviceSize,
|
||||
) -> Result<()> {
|
||||
let command_buffer = self.begin_single_time_commands(device)?;
|
||||
|
||||
let regions = vk::BufferCopy::builder().size(size);
|
||||
device.cmd_copy_buffer(command_buffer, source, destination, &[regions]);
|
||||
|
||||
self.end_single_time_commands(device, command_buffer)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
//================================================
|
||||
// Shared (Images)
|
||||
//================================================
|
||||
|
||||
unsafe fn create_image(
|
||||
&self,
|
||||
instance: &Instance,
|
||||
device: &Device,
|
||||
width: u32,
|
||||
height: u32,
|
||||
format: vk::Format,
|
||||
tiling: vk::ImageTiling,
|
||||
usage: vk::ImageUsageFlags,
|
||||
properties: vk::MemoryPropertyFlags,
|
||||
) -> Result<(vk::Image, vk::DeviceMemory)> {
|
||||
let info = vk::ImageCreateInfo::builder()
|
||||
.image_type(vk::ImageType::_2D)
|
||||
.extent(vk::Extent3D {
|
||||
width,
|
||||
height,
|
||||
depth: 1,
|
||||
})
|
||||
.mip_levels(1)
|
||||
.array_layers(1)
|
||||
.format(format)
|
||||
.tiling(tiling)
|
||||
.initial_layout(vk::ImageLayout::UNDEFINED)
|
||||
.usage(usage)
|
||||
.samples(vk::SampleCountFlags::_1)
|
||||
.sharing_mode(vk::SharingMode::EXCLUSIVE);
|
||||
|
||||
let image = device.create_image(&info, None)?;
|
||||
|
||||
let requirements = device.get_image_memory_requirements(image);
|
||||
|
||||
let info = vk::MemoryAllocateInfo::builder()
|
||||
.allocation_size(requirements.size)
|
||||
.memory_type_index(self.get_memory_type_index(instance, properties, requirements)?);
|
||||
|
||||
let image_memory = device.allocate_memory(&info, None)?;
|
||||
|
||||
device.bind_image_memory(image, image_memory, 0)?;
|
||||
|
||||
Ok((image, image_memory))
|
||||
}
|
||||
|
||||
unsafe fn transition_image_layout(
|
||||
&self,
|
||||
device: &Device,
|
||||
image: vk::Image,
|
||||
format: vk::Format,
|
||||
old_layout: vk::ImageLayout,
|
||||
new_layout: vk::ImageLayout,
|
||||
) -> Result<()> {
|
||||
let command_buffer = self.begin_single_time_commands(device)?;
|
||||
|
||||
self.end_single_time_commands(device, command_buffer)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
//================================================
|
||||
// Shared (Other)
|
||||
//================================================
|
||||
@ -993,4 +1106,38 @@ impl AppData {
|
||||
})
|
||||
.ok_or_else(|| anyhow!("Failed to find suitable memory type."))
|
||||
}
|
||||
|
||||
unsafe fn begin_single_time_commands(&self, device: &Device) -> Result<vk::CommandBuffer> {
|
||||
let info = vk::CommandBufferAllocateInfo::builder()
|
||||
.level(vk::CommandBufferLevel::PRIMARY)
|
||||
.command_pool(self.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)
|
||||
}
|
||||
|
||||
unsafe fn end_single_time_commands(
|
||||
&self,
|
||||
device: &Device,
|
||||
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(self.graphics_queue, &[info], vk::Fence::null())?;
|
||||
device.queue_wait_idle(self.graphics_queue)?;
|
||||
|
||||
device.free_command_buffers(self.command_pool, command_buffers);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user