vk: create raii buffer abstraction
This commit is contained in:
parent
53e3b5c2d1
commit
e428e02dfe
15
librashader-runtime-vk/src/draw_quad.rs
Normal file
15
librashader-runtime-vk/src/draw_quad.rs
Normal file
|
@ -0,0 +1,15 @@
|
|||
static VBO_OFFSCREEN_MVP: &[f32; 16] = &[
|
||||
// Offscreen
|
||||
-1.0, -1.0, 0.0, 0.0,
|
||||
-1.0, 1.0, 0.0, 1.0,
|
||||
1.0, -1.0, 1.0, 0.0,
|
||||
1.0, 1.0, 1.0, 1.0,
|
||||
];
|
||||
|
||||
static VBO_DEFAULT_FINAL_MVP: &[f32; 16] = &[
|
||||
// Final
|
||||
0.0, 0.0, 0.0, 0.0,
|
||||
0.0, 1.0, 0.0, 1.0,
|
||||
1.0, 0.0, 1.0, 0.0,
|
||||
1.0, 1.0, 1.0, 1.0,
|
||||
];
|
|
@ -1,8 +1,7 @@
|
|||
use std::error::Error;
|
||||
use std::ffi::CStr;
|
||||
use std::path::Path;
|
||||
use ash::vk;
|
||||
use ash::vk::{ColorComponentFlags, PFN_vkGetInstanceProcAddr, StaticFn};
|
||||
use ash::vk::{PFN_vkGetInstanceProcAddr, StaticFn};
|
||||
use rustc_hash::FxHashMap;
|
||||
use librashader_common::ImageFormat;
|
||||
use librashader_preprocess::ShaderSource;
|
||||
|
@ -15,8 +14,7 @@ use librashader_reflect::reflect::semantics::{Semantic, ShaderSemantics, Texture
|
|||
use librashader_runtime::uniforms::UniformStorage;
|
||||
use crate::error;
|
||||
use crate::filter_pass::FilterPass;
|
||||
use crate::framebuffer::{Framebuffer, VulkanRenderPass};
|
||||
use crate::vulkan_state::{PipelineLayoutObjects, VulkanGraphicsPipeline};
|
||||
use crate::vulkan_state::VulkanGraphicsPipeline;
|
||||
|
||||
pub struct Vulkan {
|
||||
physical_device: vk::PhysicalDevice,
|
||||
|
@ -59,7 +57,7 @@ impl From<VulkanInfo<'_>> for ash::Device {
|
|||
|
||||
pub struct FilterChainVulkan {
|
||||
pub(crate) common: FilterCommon,
|
||||
pub(crate) passes: Vec<FilterPass>,
|
||||
pub(crate) passes: Box<[FilterPass]>,
|
||||
// pub(crate) output_framebuffers: Box<[OwnedFramebuffer]>,
|
||||
// pub(crate) feedback_framebuffers: Box<[OwnedFramebuffer]>,
|
||||
// pub(crate) history_framebuffers: VecDeque<OwnedFramebuffer>,
|
||||
|
@ -100,7 +98,10 @@ impl FilterChainVulkan {
|
|||
// initialize passes
|
||||
let filters = Self::init_passes(&device, passes, &semantics, 3)?;
|
||||
eprintln!("filters initialized ok.");
|
||||
todo!();
|
||||
Ok(FilterChainVulkan {
|
||||
common: FilterCommon {},
|
||||
passes: filters
|
||||
})
|
||||
}
|
||||
|
||||
fn load_preset(
|
||||
|
@ -207,9 +208,7 @@ impl FilterChainVulkan {
|
|||
|
||||
let graphics_pipeline = VulkanGraphicsPipeline::new(device,
|
||||
&pipeline_cache,
|
||||
&spirv_words, &reflection, source.format, images)
|
||||
.unwrap();
|
||||
|
||||
&spirv_words, &reflection, source.format, images)?;
|
||||
// shader_vulkan: 2026
|
||||
filters.push(FilterPass {
|
||||
compiled: spirv_words,
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
use ash::vk;
|
||||
use ash::vk::{AttachmentLoadOp, AttachmentStoreOp, DeviceSize, Extent2D, Extent3D, ImageAspectFlags, ImageLayout, ImageTiling, ImageType, ImageUsageFlags, ImageViewType, PipelineBindPoint, SampleCountFlags, SharingMode};
|
||||
use glfw::Key::P;
|
||||
use librashader_common::{ImageFormat, Size};
|
||||
use ash::vk::{Extent3D, ImageAspectFlags, ImageLayout, ImageTiling, ImageType, ImageUsageFlags, ImageViewType, SampleCountFlags, SharingMode};
|
||||
use librashader_common::Size;
|
||||
use crate::error;
|
||||
use crate::renderpass::VulkanRenderPass;
|
||||
use crate::util::find_vulkan_memory_type;
|
||||
use crate::vulkan_primitives::VulkanImageMemory;
|
||||
|
||||
pub struct Framebuffer {
|
||||
device: ash::Device,
|
||||
|
@ -20,37 +21,7 @@ pub struct VulkanFramebuffer {
|
|||
pub image_view: vk::ImageView,
|
||||
pub fb_view: vk::ImageView,
|
||||
pub image: vk::Image,
|
||||
pub memory: VulkanMemory,
|
||||
}
|
||||
|
||||
pub struct VulkanMemory {
|
||||
pub handle: vk::DeviceMemory,
|
||||
device: ash::Device
|
||||
}
|
||||
|
||||
impl VulkanMemory {
|
||||
pub fn new(device: &ash::Device, alloc: &vk::MemoryAllocateInfo) -> error::Result<VulkanMemory> {
|
||||
unsafe {
|
||||
Ok(VulkanMemory {
|
||||
handle: device.allocate_memory(alloc, None)?,
|
||||
device: device.clone()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn bind(&self, image: &vk::Image) -> error::Result<()>{
|
||||
unsafe {
|
||||
Ok(self.device.bind_image_memory(image.clone(), self.handle.clone(), 0)?)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for VulkanMemory {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
self.device.free_memory(self.handle, None);
|
||||
}
|
||||
}
|
||||
pub memory: VulkanImageMemory,
|
||||
}
|
||||
|
||||
impl Drop for VulkanFramebuffer {
|
||||
|
@ -72,56 +43,6 @@ impl Drop for VulkanFramebuffer {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct VulkanRenderPass {
|
||||
pub render_pass: vk::RenderPass,
|
||||
format: ImageFormat
|
||||
}
|
||||
|
||||
impl VulkanRenderPass {
|
||||
pub fn create_render_pass(device: &ash::Device, mut format: ImageFormat) -> error::Result<Self> {
|
||||
// default to reasonable choice if unknown
|
||||
if format == ImageFormat::Unknown {
|
||||
format = ImageFormat::R8G8B8A8Unorm;
|
||||
}
|
||||
|
||||
let attachment = vk::AttachmentDescription::builder()
|
||||
.flags(vk::AttachmentDescriptionFlags::empty())
|
||||
.format(format.into())
|
||||
.samples(SampleCountFlags::TYPE_1)
|
||||
.load_op(AttachmentLoadOp::DONT_CARE)
|
||||
.store_op(AttachmentStoreOp::STORE)
|
||||
.stencil_load_op(AttachmentLoadOp::DONT_CARE)
|
||||
.stencil_store_op(AttachmentStoreOp::DONT_CARE)
|
||||
.initial_layout(ImageLayout::COLOR_ATTACHMENT_OPTIMAL)
|
||||
.final_layout(ImageLayout::COLOR_ATTACHMENT_OPTIMAL)
|
||||
.build();
|
||||
|
||||
let attachment_ref = vk::AttachmentReference::builder()
|
||||
.attachment(0)
|
||||
.layout(ImageLayout::COLOR_ATTACHMENT_OPTIMAL)
|
||||
.build();
|
||||
|
||||
let subpass = vk::SubpassDescription::builder()
|
||||
.pipeline_bind_point(PipelineBindPoint::GRAPHICS)
|
||||
.color_attachments(&[attachment_ref])
|
||||
.build();
|
||||
|
||||
let renderpass_info = vk::RenderPassCreateInfo::builder()
|
||||
.flags(vk::RenderPassCreateFlags::empty())
|
||||
.attachments(&[attachment])
|
||||
.subpasses(&[subpass])
|
||||
.build();
|
||||
|
||||
unsafe {
|
||||
let rp = device.create_render_pass(&renderpass_info, None)?;
|
||||
Ok(Self {
|
||||
render_pass: rp,
|
||||
format
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Framebuffer {
|
||||
pub fn new(device: &ash::Device, size: Size<u32>, render_pass: VulkanRenderPass, mip_levels: u32, mem_props: vk::PhysicalDeviceMemoryProperties) -> error::Result<Self> {
|
||||
let mut framebuffer = Framebuffer {
|
||||
|
@ -166,7 +87,7 @@ impl Framebuffer {
|
|||
.build();
|
||||
|
||||
// todo: optimize by reusing existing memory.
|
||||
let memory = VulkanMemory::new(&self.device, &alloc_info)?;
|
||||
let memory = VulkanImageMemory::new(&self.device, &alloc_info)?;
|
||||
memory.bind(&image)?;
|
||||
|
||||
let image_subresource = vk::ImageSubresourceRange::builder()
|
||||
|
|
|
@ -8,6 +8,9 @@ mod error;
|
|||
mod util;
|
||||
mod framebuffer;
|
||||
mod vulkan_state;
|
||||
mod draw_quad;
|
||||
mod renderpass;
|
||||
mod vulkan_primitives;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
|
54
librashader-runtime-vk/src/renderpass.rs
Normal file
54
librashader-runtime-vk/src/renderpass.rs
Normal file
|
@ -0,0 +1,54 @@
|
|||
use ash::vk;
|
||||
use ash::vk::{AttachmentLoadOp, AttachmentStoreOp, ImageLayout, PipelineBindPoint, SampleCountFlags};
|
||||
use librashader_common::ImageFormat;
|
||||
use crate::error;
|
||||
|
||||
pub struct VulkanRenderPass {
|
||||
pub render_pass: vk::RenderPass,
|
||||
pub format: ImageFormat
|
||||
}
|
||||
|
||||
impl VulkanRenderPass {
|
||||
pub fn create_render_pass(device: &ash::Device, mut format: ImageFormat) -> error::Result<Self> {
|
||||
// default to reasonable choice if unknown
|
||||
if format == ImageFormat::Unknown {
|
||||
format = ImageFormat::R8G8B8A8Unorm;
|
||||
}
|
||||
|
||||
let attachment = vk::AttachmentDescription::builder()
|
||||
.flags(vk::AttachmentDescriptionFlags::empty())
|
||||
.format(format.into())
|
||||
.samples(SampleCountFlags::TYPE_1)
|
||||
.load_op(AttachmentLoadOp::DONT_CARE)
|
||||
.store_op(AttachmentStoreOp::STORE)
|
||||
.stencil_load_op(AttachmentLoadOp::DONT_CARE)
|
||||
.stencil_store_op(AttachmentStoreOp::DONT_CARE)
|
||||
.initial_layout(ImageLayout::COLOR_ATTACHMENT_OPTIMAL)
|
||||
.final_layout(ImageLayout::COLOR_ATTACHMENT_OPTIMAL)
|
||||
.build();
|
||||
|
||||
let attachment_ref = vk::AttachmentReference::builder()
|
||||
.attachment(0)
|
||||
.layout(ImageLayout::COLOR_ATTACHMENT_OPTIMAL)
|
||||
.build();
|
||||
|
||||
let subpass = vk::SubpassDescription::builder()
|
||||
.pipeline_bind_point(PipelineBindPoint::GRAPHICS)
|
||||
.color_attachments(&[attachment_ref])
|
||||
.build();
|
||||
|
||||
let renderpass_info = vk::RenderPassCreateInfo::builder()
|
||||
.flags(vk::RenderPassCreateFlags::empty())
|
||||
.attachments(&[attachment])
|
||||
.subpasses(&[subpass])
|
||||
.build();
|
||||
|
||||
unsafe {
|
||||
let rp = device.create_render_pass(&renderpass_info, None)?;
|
||||
Ok(Self {
|
||||
render_pass: rp,
|
||||
format
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
124
librashader-runtime-vk/src/vulkan_primitives.rs
Normal file
124
librashader-runtime-vk/src/vulkan_primitives.rs
Normal file
|
@ -0,0 +1,124 @@
|
|||
use std::ffi::c_void;
|
||||
use ash::vk;
|
||||
use crate::{error, util};
|
||||
|
||||
pub struct VulkanImageMemory {
|
||||
pub handle: vk::DeviceMemory,
|
||||
device: ash::Device
|
||||
}
|
||||
|
||||
impl VulkanImageMemory {
|
||||
pub fn new(device: &ash::Device, alloc: &vk::MemoryAllocateInfo) -> error::Result<VulkanImageMemory> {
|
||||
unsafe {
|
||||
Ok(VulkanImageMemory {
|
||||
handle: device.allocate_memory(alloc, None)?,
|
||||
device: device.clone()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn bind(&self, image: &vk::Image) -> error::Result<()>{
|
||||
unsafe {
|
||||
Ok(self.device.bind_image_memory(image.clone(), self.handle.clone(), 0)?)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for VulkanImageMemory {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
self.device.free_memory(self.handle, None);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub struct VulkanBuffer {
|
||||
pub handle: vk::Buffer,
|
||||
device: ash::Device,
|
||||
pub memory: vk::DeviceMemory,
|
||||
pub size: vk::DeviceSize,
|
||||
}
|
||||
|
||||
pub struct VulkanBufferMapHandle<'a> {
|
||||
buffer: &'a mut VulkanBuffer,
|
||||
ptr: *mut c_void
|
||||
}
|
||||
|
||||
impl VulkanBuffer {
|
||||
pub fn new(device: &ash::Device, mem_props: &vk::PhysicalDeviceMemoryProperties, usage: vk::BufferUsageFlags,
|
||||
size: usize) -> error::Result<VulkanBuffer> {
|
||||
unsafe {
|
||||
let buffer_info = vk::BufferCreateInfo::builder()
|
||||
.size(size as vk::DeviceSize)
|
||||
.usage(usage)
|
||||
.sharing_mode(vk::SharingMode::EXCLUSIVE)
|
||||
.build();
|
||||
let buffer = device.create_buffer(&buffer_info, None)?;
|
||||
|
||||
let memory_reqs = device.get_buffer_memory_requirements(buffer);
|
||||
let alloc_info = vk::MemoryAllocateInfo::builder()
|
||||
.allocation_size(memory_reqs.size)
|
||||
.memory_type_index(util::find_vulkan_memory_type(mem_props, memory_reqs.memory_type_bits,
|
||||
vk::MemoryPropertyFlags::HOST_VISIBLE | vk::MemoryPropertyFlags::HOST_COHERENT))
|
||||
.build();
|
||||
|
||||
let alloc = device.allocate_memory(&alloc_info, None)?;
|
||||
device.bind_buffer_memory(buffer.clone(), alloc.clone(), 0)?;
|
||||
|
||||
Ok(VulkanBuffer {
|
||||
handle: buffer,
|
||||
memory: alloc,
|
||||
size: size as vk::DeviceSize,
|
||||
device: device.clone()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn copy_from(&mut self, buffer: &[u8]) -> error::Result<()> {
|
||||
let dst = self.device.map_memory(self.memory, 0, self.size, vk::MemoryMapFlags::empty())?;
|
||||
std::ptr::copy_nonoverlapping(buffer.as_ptr(), dst.cast(), buffer.len());
|
||||
self.device.unmap_memory(self.memory);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn map(&mut self) -> error::Result<VulkanBufferMapHandle> {
|
||||
let dst =
|
||||
unsafe {
|
||||
self.device.map_memory(self.memory, 0, self.size, vk::MemoryMapFlags::empty())?
|
||||
};
|
||||
|
||||
Ok(VulkanBufferMapHandle {
|
||||
buffer: self,
|
||||
ptr: dst,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for VulkanBuffer {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
if self.memory != vk::DeviceMemory::null() {
|
||||
self.device.free_memory(self.memory, None);
|
||||
}
|
||||
|
||||
if self.handle != vk::Buffer::null() {
|
||||
self.device.destroy_buffer(self.handle, None);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl <'a> VulkanBufferMapHandle<'a> {
|
||||
pub unsafe fn copy_from(&mut self, src: &[u8]) {
|
||||
std::ptr::copy_nonoverlapping(src.as_ptr(), self.ptr.cast(), src.len());
|
||||
}
|
||||
}
|
||||
|
||||
impl <'a> Drop for VulkanBufferMapHandle<'a> {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
self.buffer.device.unmap_memory(self.buffer.memory)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,7 +5,7 @@ use librashader_reflect::back::ShaderCompilerOutput;
|
|||
use librashader_reflect::reflect::semantics::{TextureBinding, UboReflection};
|
||||
use librashader_reflect::reflect::ShaderReflection;
|
||||
use crate::{error, util};
|
||||
use crate::framebuffer::VulkanRenderPass;
|
||||
use crate::renderpass::VulkanRenderPass;
|
||||
|
||||
pub struct PipelineDescriptors {
|
||||
pub replicas: u32,
|
||||
|
|
Loading…
Reference in a new issue