vk: use gpu-allocator for memory allocations
This commit is contained in:
parent
336094cad9
commit
009e740610
59
Cargo.lock
generated
59
Cargo.lock
generated
|
@ -2,6 +2,15 @@
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 3
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "addr2line"
|
||||||
|
version = "0.19.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97"
|
||||||
|
dependencies = [
|
||||||
|
"gimli",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "adler"
|
name = "adler"
|
||||||
version = "1.0.2"
|
version = "1.0.2"
|
||||||
|
@ -64,6 +73,21 @@ version = "1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "backtrace"
|
||||||
|
version = "0.3.67"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca"
|
||||||
|
dependencies = [
|
||||||
|
"addr2line",
|
||||||
|
"cc",
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"miniz_oxide",
|
||||||
|
"object",
|
||||||
|
"rustc-demangle",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bit-set"
|
name = "bit-set"
|
||||||
version = "0.5.3"
|
version = "0.5.3"
|
||||||
|
@ -564,6 +588,12 @@ dependencies = [
|
||||||
"weezl",
|
"weezl",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gimli"
|
||||||
|
version = "0.27.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "221996f774192f0f718773def8201c4ae31f02616a54ccfc2d358bb0e5cefdec"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gl"
|
name = "gl"
|
||||||
version = "0.14.0"
|
version = "0.14.0"
|
||||||
|
@ -625,6 +655,18 @@ version = "0.3.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
|
checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gpu-allocator"
|
||||||
|
version = "0.22.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ce95f9e2e11c2c6fadfce42b5af60005db06576f231f5c92550fdded43c423e8"
|
||||||
|
dependencies = [
|
||||||
|
"ash",
|
||||||
|
"backtrace",
|
||||||
|
"log",
|
||||||
|
"thiserror",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hashbrown"
|
name = "hashbrown"
|
||||||
version = "0.12.3"
|
version = "0.12.3"
|
||||||
|
@ -930,6 +972,7 @@ dependencies = [
|
||||||
"ash-window",
|
"ash-window",
|
||||||
"bytemuck",
|
"bytemuck",
|
||||||
"glfw 0.49.1",
|
"glfw 0.49.1",
|
||||||
|
"gpu-allocator",
|
||||||
"librashader-common 0.1.0-rc.2",
|
"librashader-common 0.1.0-rc.2",
|
||||||
"librashader-preprocess",
|
"librashader-preprocess",
|
||||||
"librashader-presets 0.1.0-rc.2",
|
"librashader-presets 0.1.0-rc.2",
|
||||||
|
@ -937,6 +980,7 @@ dependencies = [
|
||||||
"librashader-runtime",
|
"librashader-runtime",
|
||||||
"librashader-spirv-cross",
|
"librashader-spirv-cross",
|
||||||
"num",
|
"num",
|
||||||
|
"parking_lot",
|
||||||
"raw-window-handle 0.5.0",
|
"raw-window-handle 0.5.0",
|
||||||
"rayon",
|
"rayon",
|
||||||
"rustc-hash",
|
"rustc-hash",
|
||||||
|
@ -1290,6 +1334,15 @@ dependencies = [
|
||||||
"malloc_buf",
|
"malloc_buf",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "object"
|
||||||
|
version = "0.30.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "once_cell"
|
name = "once_cell"
|
||||||
version = "1.17.0"
|
version = "1.17.0"
|
||||||
|
@ -1483,6 +1536,12 @@ dependencies = [
|
||||||
"spirv",
|
"spirv",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustc-demangle"
|
||||||
|
version = "0.1.21"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc-hash"
|
name = "rustc-hash"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
|
|
|
@ -121,7 +121,7 @@ Please report an issue if you run into a shader that works in RetroArch, but not
|
||||||
* The Vulkan runtime uses [`VK_KHR_dynamic_rendering`](https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VK_KHR_dynamic_rendering.html) by default.
|
* The Vulkan runtime uses [`VK_KHR_dynamic_rendering`](https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VK_KHR_dynamic_rendering.html) by default.
|
||||||
This extension must be enabled at device creation. Explicit render passes can be used by configuring filter chain options, but may have reduced performance
|
This extension must be enabled at device creation. Explicit render passes can be used by configuring filter chain options, but may have reduced performance
|
||||||
compared to dynamic rendering.
|
compared to dynamic rendering.
|
||||||
* UBOs use multiple discontiguous buffers. This may be improved in the future by switching to VMA rather than manually handling allocations.
|
* Allocations within the runtime are done through [gpu-allocator](https://github.com/Traverse-Research/gpu-allocator) rather than handled manually.
|
||||||
* Direct3D 11
|
* Direct3D 11
|
||||||
* Framebuffer copies are done via `ID3D11DeviceContext::CopySubresourceRegion` rather than a CPU conversion + copy.
|
* Framebuffer copies are done via `ID3D11DeviceContext::CopySubresourceRegion` rather than a CPU conversion + copy.
|
||||||
* Direct3D 12
|
* Direct3D 12
|
||||||
|
|
|
@ -24,7 +24,8 @@ rustc-hash = "1.1.0"
|
||||||
bytemuck = "1.12.3"
|
bytemuck = "1.12.3"
|
||||||
thiserror = "1.0.37"
|
thiserror = "1.0.37"
|
||||||
ash = { version = "0.37.1+1.3.235", features = ["linked", "debug"] }
|
ash = { version = "0.37.1+1.3.235", features = ["linked", "debug"] }
|
||||||
|
gpu-allocator = { version = "0.22.0", default-features = false, features = ["vulkan"] }
|
||||||
|
parking_lot = "0.12.1"
|
||||||
rayon = "1.6.1"
|
rayon = "1.6.1"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
use crate::error;
|
use crate::error;
|
||||||
use crate::vulkan_primitives::VulkanBuffer;
|
use crate::memory::VulkanBuffer;
|
||||||
use ash::vk;
|
use ash::vk;
|
||||||
|
use gpu_allocator::vulkan::Allocator;
|
||||||
use librashader_runtime::quad::QuadType;
|
use librashader_runtime::quad::QuadType;
|
||||||
|
use parking_lot::RwLock;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
|
@ -30,25 +32,23 @@ pub struct DrawQuad {
|
||||||
impl DrawQuad {
|
impl DrawQuad {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
device: &Arc<ash::Device>,
|
device: &Arc<ash::Device>,
|
||||||
mem_props: &vk::PhysicalDeviceMemoryProperties,
|
allocator: &Arc<RwLock<Allocator>>,
|
||||||
) -> error::Result<DrawQuad> {
|
) -> error::Result<DrawQuad> {
|
||||||
let mut buffer = VulkanBuffer::new(
|
let mut buffer = VulkanBuffer::new(
|
||||||
device,
|
device,
|
||||||
mem_props,
|
allocator,
|
||||||
vk::BufferUsageFlags::VERTEX_BUFFER,
|
vk::BufferUsageFlags::VERTEX_BUFFER,
|
||||||
2 * std::mem::size_of::<[f32; 16]>(),
|
2 * std::mem::size_of::<[f32; 16]>(),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut map = buffer.map()?;
|
let slice = buffer.as_mut_slice()?;
|
||||||
unsafe {
|
slice[0..std::mem::size_of::<[f32; 16]>()]
|
||||||
map.copy_from(0, bytemuck::cast_slice(VBO_OFFSCREEN));
|
.copy_from_slice(bytemuck::cast_slice(VBO_OFFSCREEN));
|
||||||
map.copy_from(
|
slice[std::mem::size_of::<[f32; 16]>()..]
|
||||||
std::mem::size_of::<[f32; 16]>(),
|
.copy_from_slice(bytemuck::cast_slice(VBO_DEFAULT_FINAL));
|
||||||
bytemuck::cast_slice(VBO_DEFAULT_FINAL),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(DrawQuad {
|
Ok(DrawQuad {
|
||||||
buffer,
|
buffer,
|
||||||
device: device.clone(),
|
device: device.clone(),
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
//! Vulkan shader runtime errors.
|
//! Vulkan shader runtime errors.
|
||||||
|
use gpu_allocator::AllocationError;
|
||||||
use librashader_preprocess::PreprocessError;
|
use librashader_preprocess::PreprocessError;
|
||||||
use librashader_presets::ParsePresetError;
|
use librashader_presets::ParsePresetError;
|
||||||
use librashader_reflect::error::{ShaderCompileError, ShaderReflectError};
|
use librashader_reflect::error::{ShaderCompileError, ShaderReflectError};
|
||||||
|
@ -24,6 +25,10 @@ pub enum FilterChainError {
|
||||||
VulkanResult(#[from] ash::vk::Result),
|
VulkanResult(#[from] ash::vk::Result),
|
||||||
#[error("could not find a valid vulkan memory type")]
|
#[error("could not find a valid vulkan memory type")]
|
||||||
VulkanMemoryError(u32),
|
VulkanMemoryError(u32),
|
||||||
|
#[error("could not allocate gpu memory")]
|
||||||
|
AllocationError(#[from] AllocationError),
|
||||||
|
#[error("allocation is already freed")]
|
||||||
|
AllocationDoesNotExist,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Result type for Vulkan filter chains.
|
/// Result type for Vulkan filter chains.
|
||||||
|
|
|
@ -4,15 +4,16 @@ use crate::filter_pass::FilterPass;
|
||||||
use crate::framebuffer::OutputImage;
|
use crate::framebuffer::OutputImage;
|
||||||
use crate::graphics_pipeline::VulkanGraphicsPipeline;
|
use crate::graphics_pipeline::VulkanGraphicsPipeline;
|
||||||
use crate::luts::LutTexture;
|
use crate::luts::LutTexture;
|
||||||
|
use crate::memory::RawVulkanBuffer;
|
||||||
use crate::options::{FilterChainOptionsVulkan, FrameOptionsVulkan};
|
use crate::options::{FilterChainOptionsVulkan, FrameOptionsVulkan};
|
||||||
use crate::queue_selection::get_graphics_queue;
|
use crate::queue_selection::get_graphics_queue;
|
||||||
use crate::samplers::SamplerSet;
|
use crate::samplers::SamplerSet;
|
||||||
use crate::texture::{InputImage, OwnedImage, OwnedImageLayout, VulkanImage};
|
use crate::texture::{InputImage, OwnedImage, OwnedImageLayout, VulkanImage};
|
||||||
use crate::vulkan_primitives::RawVulkanBuffer;
|
|
||||||
use crate::{error, util};
|
use crate::{error, util};
|
||||||
use ash::vk;
|
use ash::vk;
|
||||||
use librashader_common::{ImageFormat, Size, Viewport};
|
use librashader_common::{ImageFormat, Size, Viewport};
|
||||||
|
|
||||||
|
use gpu_allocator::vulkan::Allocator;
|
||||||
use librashader_presets::{ShaderPreset, TextureConfig};
|
use librashader_presets::{ShaderPreset, TextureConfig};
|
||||||
use librashader_reflect::back::targets::SPIRV;
|
use librashader_reflect::back::targets::SPIRV;
|
||||||
use librashader_reflect::back::{CompileReflectShader, CompileShader};
|
use librashader_reflect::back::{CompileReflectShader, CompileShader};
|
||||||
|
@ -24,6 +25,7 @@ use librashader_runtime::binding::BindingUtil;
|
||||||
use librashader_runtime::image::{Image, UVDirection};
|
use librashader_runtime::image::{Image, UVDirection};
|
||||||
use librashader_runtime::quad::QuadType;
|
use librashader_runtime::quad::QuadType;
|
||||||
use librashader_runtime::uniforms::UniformStorage;
|
use librashader_runtime::uniforms::UniformStorage;
|
||||||
|
use parking_lot::RwLock;
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
@ -36,9 +38,10 @@ use rayon::prelude::*;
|
||||||
/// A Vulkan device and metadata that is required by the shader runtime.
|
/// A Vulkan device and metadata that is required by the shader runtime.
|
||||||
pub struct VulkanObjects {
|
pub struct VulkanObjects {
|
||||||
pub(crate) device: Arc<ash::Device>,
|
pub(crate) device: Arc<ash::Device>,
|
||||||
pub(crate) memory_properties: vk::PhysicalDeviceMemoryProperties,
|
pub(crate) alloc: Arc<RwLock<Allocator>>,
|
||||||
queue: vk::Queue,
|
queue: vk::Queue,
|
||||||
pipeline_cache: vk::PipelineCache,
|
pipeline_cache: vk::PipelineCache,
|
||||||
|
// pub(crate) memory_properties: vk::PhysicalDeviceMemoryProperties,
|
||||||
}
|
}
|
||||||
|
|
||||||
type ShaderPassMeta =
|
type ShaderPassMeta =
|
||||||
|
@ -75,26 +78,28 @@ impl TryFrom<VulkanInstance> for VulkanObjects {
|
||||||
device.create_pipeline_cache(&vk::PipelineCacheCreateInfo::default(), None)?;
|
device.create_pipeline_cache(&vk::PipelineCacheCreateInfo::default(), None)?;
|
||||||
|
|
||||||
let queue = get_graphics_queue(&instance, &device, vulkan.physical_device);
|
let queue = get_graphics_queue(&instance, &device, vulkan.physical_device);
|
||||||
let memory_properties =
|
|
||||||
instance.get_physical_device_memory_properties(vulkan.physical_device);
|
// let memory_properties =
|
||||||
|
// instance.get_physical_device_memory_properties(vulkan.physical_device);
|
||||||
|
|
||||||
|
let alloc = util::create_allocator(device.clone(), instance, vulkan.physical_device)?;
|
||||||
|
|
||||||
Ok(VulkanObjects {
|
Ok(VulkanObjects {
|
||||||
device: Arc::new(device),
|
device: Arc::new(device),
|
||||||
|
alloc,
|
||||||
queue,
|
queue,
|
||||||
pipeline_cache,
|
pipeline_cache,
|
||||||
memory_properties,
|
// memory_properties,
|
||||||
// debug,
|
// debug,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<(vk::PhysicalDevice, ash::Instance, Arc<ash::Device>)> for VulkanObjects {
|
impl TryFrom<(vk::PhysicalDevice, ash::Instance, ash::Device)> for VulkanObjects {
|
||||||
type Error = FilterChainError;
|
type Error = FilterChainError;
|
||||||
|
|
||||||
fn try_from(
|
fn try_from(value: (vk::PhysicalDevice, ash::Instance, ash::Device)) -> error::Result<Self> {
|
||||||
value: (vk::PhysicalDevice, ash::Instance, Arc<ash::Device>),
|
|
||||||
) -> error::Result<Self> {
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let device = value.2;
|
let device = value.2;
|
||||||
|
|
||||||
|
@ -103,13 +108,16 @@ impl TryFrom<(vk::PhysicalDevice, ash::Instance, Arc<ash::Device>)> for VulkanOb
|
||||||
|
|
||||||
let queue = get_graphics_queue(&value.1, &device, value.0);
|
let queue = get_graphics_queue(&value.1, &device, value.0);
|
||||||
|
|
||||||
let memory_properties = value.1.get_physical_device_memory_properties(value.0);
|
// let memory_properties = value.1.get_physical_device_memory_properties(value.0);
|
||||||
|
|
||||||
|
let alloc = util::create_allocator(device.clone(), value.1, value.0)?;
|
||||||
|
|
||||||
Ok(VulkanObjects {
|
Ok(VulkanObjects {
|
||||||
device,
|
alloc,
|
||||||
|
device: Arc::new(device),
|
||||||
queue,
|
queue,
|
||||||
pipeline_cache,
|
pipeline_cache,
|
||||||
memory_properties,
|
// memory_properties,
|
||||||
// debug: value.3,
|
// debug: value.3,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -288,7 +296,7 @@ impl FilterChainVulkan {
|
||||||
.map(|param| (param.name, param.value))
|
.map(|param| (param.name, param.value))
|
||||||
.collect(),
|
.collect(),
|
||||||
},
|
},
|
||||||
draw_quad: DrawQuad::new(&device.device, &device.memory_properties)?,
|
draw_quad: DrawQuad::new(&device.device, &device.alloc)?,
|
||||||
device: device.device.clone(),
|
device: device.device.clone(),
|
||||||
output_inputs: output_textures.into_boxed_slice(),
|
output_inputs: output_textures.into_boxed_slice(),
|
||||||
feedback_inputs: feedback_textures.into_boxed_slice(),
|
feedback_inputs: feedback_textures.into_boxed_slice(),
|
||||||
|
@ -324,7 +332,7 @@ impl FilterChainVulkan {
|
||||||
let uniform_storage = UniformStorage::new_with_ubo_storage(
|
let uniform_storage = UniformStorage::new_with_ubo_storage(
|
||||||
RawVulkanBuffer::new(
|
RawVulkanBuffer::new(
|
||||||
&vulkan.device,
|
&vulkan.device,
|
||||||
&vulkan.memory_properties,
|
&vulkan.alloc,
|
||||||
vk::BufferUsageFlags::UNIFORM_BUFFER,
|
vk::BufferUsageFlags::UNIFORM_BUFFER,
|
||||||
ubo_size,
|
ubo_size,
|
||||||
)?,
|
)?,
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
use crate::filter_chain::FilterCommon;
|
use crate::filter_chain::FilterCommon;
|
||||||
use crate::framebuffer::OutputImage;
|
use crate::framebuffer::OutputImage;
|
||||||
use crate::graphics_pipeline::VulkanGraphicsPipeline;
|
use crate::graphics_pipeline::VulkanGraphicsPipeline;
|
||||||
|
use crate::memory::RawVulkanBuffer;
|
||||||
use crate::samplers::SamplerSet;
|
use crate::samplers::SamplerSet;
|
||||||
use crate::texture::InputImage;
|
use crate::texture::InputImage;
|
||||||
use crate::vulkan_primitives::RawVulkanBuffer;
|
|
||||||
use crate::{error, VulkanImage};
|
use crate::{error, VulkanImage};
|
||||||
use ash::vk;
|
use ash::vk;
|
||||||
use librashader_common::{ImageFormat, Size, Viewport};
|
use librashader_common::{ImageFormat, Size, Viewport};
|
||||||
|
|
|
@ -22,6 +22,7 @@ use ash::vk;
|
||||||
|
|
||||||
use librashader_common::Viewport;
|
use librashader_common::Viewport;
|
||||||
|
|
||||||
|
use crate::options::FrameOptionsVulkan;
|
||||||
use winit::event::{ElementState, Event, KeyboardInput, VirtualKeyCode, WindowEvent};
|
use winit::event::{ElementState, Event, KeyboardInput, VirtualKeyCode, WindowEvent};
|
||||||
use winit::event_loop::{ControlFlow, EventLoop, EventLoopBuilder};
|
use winit::event_loop::{ControlFlow, EventLoop, EventLoopBuilder};
|
||||||
use winit::platform::windows::EventLoopBuilderExtWindows;
|
use winit::platform::windows::EventLoopBuilderExtWindows;
|
||||||
|
@ -256,7 +257,10 @@ impl VulkanWindow {
|
||||||
},
|
},
|
||||||
cmd,
|
cmd,
|
||||||
frame,
|
frame,
|
||||||
None,
|
Some(&FrameOptionsVulkan {
|
||||||
|
clear_history: frame == 0,
|
||||||
|
frame_direction: 0,
|
||||||
|
}),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
use crate::hello_triangle::surface::VulkanSurface;
|
use crate::hello_triangle::surface::VulkanSurface;
|
||||||
use crate::hello_triangle::vulkan_base::VulkanBase;
|
use crate::hello_triangle::vulkan_base::VulkanBase;
|
||||||
use crate::util::find_vulkan_memory_type;
|
use crate::memory::VulkanImageMemory;
|
||||||
use crate::vulkan_primitives::VulkanImageMemory;
|
|
||||||
use ash::prelude::VkResult;
|
use ash::prelude::VkResult;
|
||||||
use ash::vk;
|
use ash::vk;
|
||||||
use ash::vk::Extent3D;
|
use ash::vk::Extent3D;
|
||||||
|
@ -95,33 +94,9 @@ impl VulkanSwapchain {
|
||||||
let image = base.device.create_image(&create_info, None)?;
|
let image = base.device.create_image(&create_info, None)?;
|
||||||
let mem_reqs = unsafe { base.device.get_image_memory_requirements(image) };
|
let mem_reqs = unsafe { base.device.get_image_memory_requirements(image) };
|
||||||
|
|
||||||
// base.debug
|
let memory =
|
||||||
// .loader
|
VulkanImageMemory::new(&base.device, &base.allocator, mem_reqs, &image)
|
||||||
// .set_debug_utils_object_name(
|
.unwrap();
|
||||||
// base.device.handle(),
|
|
||||||
// &vk::DebugUtilsObjectNameInfoEXT::builder()
|
|
||||||
// .object_handle(image.as_raw())
|
|
||||||
// .object_name(CStr::from_bytes_with_nul_unchecked(b"RenderImage\0"))
|
|
||||||
// .object_type(vk::ObjectType::IMAGE)
|
|
||||||
// .build(),
|
|
||||||
// )
|
|
||||||
// .expect("could not set object name");
|
|
||||||
|
|
||||||
let alloc_info = vk::MemoryAllocateInfo::builder()
|
|
||||||
.allocation_size(mem_reqs.size)
|
|
||||||
.memory_type_index(
|
|
||||||
find_vulkan_memory_type(
|
|
||||||
&base.mem_props,
|
|
||||||
mem_reqs.memory_type_bits,
|
|
||||||
vk::MemoryPropertyFlags::DEVICE_LOCAL,
|
|
||||||
)
|
|
||||||
.unwrap(),
|
|
||||||
)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
// todo: optimize by reusing existing memory.
|
|
||||||
let memory = VulkanImageMemory::new(&base.device, &alloc_info).unwrap();
|
|
||||||
memory.bind(&image).unwrap();
|
|
||||||
|
|
||||||
render_images.push((image, memory))
|
render_images.push((image, memory))
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,10 @@ use crate::filter_chain::VulkanObjects;
|
||||||
|
|
||||||
use crate::hello_triangle::physicaldevice::{find_queue_family, pick_physical_device};
|
use crate::hello_triangle::physicaldevice::{find_queue_family, pick_physical_device};
|
||||||
|
|
||||||
|
use crate::util;
|
||||||
use ash::prelude::VkResult;
|
use ash::prelude::VkResult;
|
||||||
|
use gpu_allocator::vulkan::{Allocator, AllocatorCreateDesc};
|
||||||
|
use parking_lot::RwLock;
|
||||||
use std::ffi::CStr;
|
use std::ffi::CStr;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
@ -20,6 +23,7 @@ pub struct VulkanBase {
|
||||||
// pub debug: VulkanDebug,
|
// pub debug: VulkanDebug,
|
||||||
pub physical_device: vk::PhysicalDevice,
|
pub physical_device: vk::PhysicalDevice,
|
||||||
pub mem_props: vk::PhysicalDeviceMemoryProperties,
|
pub mem_props: vk::PhysicalDeviceMemoryProperties,
|
||||||
|
pub allocator: Arc<RwLock<Allocator>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VulkanBase {
|
impl VulkanBase {
|
||||||
|
@ -61,6 +65,10 @@ impl VulkanBase {
|
||||||
let mem_props = unsafe { instance.get_physical_device_memory_properties(physical_device) };
|
let mem_props = unsafe { instance.get_physical_device_memory_properties(physical_device) };
|
||||||
dbg!("got memprops");
|
dbg!("got memprops");
|
||||||
|
|
||||||
|
let alloc =
|
||||||
|
util::create_allocator(device.clone(), instance.clone(), physical_device.clone())
|
||||||
|
.expect("could not create allocator");
|
||||||
|
|
||||||
Ok(VulkanBase {
|
Ok(VulkanBase {
|
||||||
entry,
|
entry,
|
||||||
instance,
|
instance,
|
||||||
|
@ -69,6 +77,7 @@ impl VulkanBase {
|
||||||
physical_device,
|
physical_device,
|
||||||
mem_props,
|
mem_props,
|
||||||
// debug,
|
// debug,
|
||||||
|
allocator: alloc,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,10 +170,8 @@ impl TryFrom<&VulkanBase> for VulkanObjects {
|
||||||
type Error = FilterChainError;
|
type Error = FilterChainError;
|
||||||
|
|
||||||
fn try_from(value: &VulkanBase) -> Result<Self, Self::Error> {
|
fn try_from(value: &VulkanBase) -> Result<Self, Self::Error> {
|
||||||
VulkanObjects::try_from((
|
let device = (*value.device).clone();
|
||||||
value.physical_device,
|
|
||||||
value.instance.clone(),
|
VulkanObjects::try_from((value.physical_device, value.instance.clone(), device))
|
||||||
value.device.clone(),
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,12 +15,12 @@ mod graphics_pipeline;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod hello_triangle;
|
mod hello_triangle;
|
||||||
mod luts;
|
mod luts;
|
||||||
|
mod memory;
|
||||||
mod parameters;
|
mod parameters;
|
||||||
mod queue_selection;
|
mod queue_selection;
|
||||||
mod samplers;
|
mod samplers;
|
||||||
mod texture;
|
mod texture;
|
||||||
mod util;
|
mod util;
|
||||||
mod vulkan_primitives;
|
|
||||||
|
|
||||||
pub use filter_chain::FilterChainVulkan;
|
pub use filter_chain::FilterChainVulkan;
|
||||||
pub use filter_chain::VulkanInstance;
|
pub use filter_chain::VulkanInstance;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::filter_chain::VulkanObjects;
|
use crate::filter_chain::VulkanObjects;
|
||||||
|
use crate::memory::{VulkanBuffer, VulkanImageMemory};
|
||||||
use crate::texture::{InputImage, VulkanImage};
|
use crate::texture::{InputImage, VulkanImage};
|
||||||
use crate::vulkan_primitives::{VulkanBuffer, VulkanImageMemory};
|
|
||||||
use crate::{error, util};
|
use crate::{error, util};
|
||||||
use ash::vk;
|
use ash::vk;
|
||||||
use librashader_presets::TextureConfig;
|
use librashader_presets::TextureConfig;
|
||||||
|
@ -46,21 +46,14 @@ impl LutTexture {
|
||||||
|
|
||||||
let memory = unsafe {
|
let memory = unsafe {
|
||||||
let mem_reqs = vulkan.device.get_image_memory_requirements(texture);
|
let mem_reqs = vulkan.device.get_image_memory_requirements(texture);
|
||||||
let mem_type = util::find_vulkan_memory_type(
|
// let mem_type = util::find_vulkan_memory_type(
|
||||||
&vulkan.memory_properties,
|
// &vulkan.memory_properties,
|
||||||
mem_reqs.memory_type_bits,
|
// mem_reqs.memory_type_bits,
|
||||||
vk::MemoryPropertyFlags::DEVICE_LOCAL,
|
// vk::MemoryPropertyFlags::DEVICE_LOCAL,
|
||||||
)?;
|
// )?;
|
||||||
VulkanImageMemory::new(
|
VulkanImageMemory::new(&vulkan.device, &vulkan.alloc, mem_reqs, &texture)?
|
||||||
&vulkan.device,
|
|
||||||
&vk::MemoryAllocateInfo::builder()
|
|
||||||
.memory_type_index(mem_type)
|
|
||||||
.allocation_size(mem_reqs.size),
|
|
||||||
)?
|
|
||||||
};
|
};
|
||||||
|
|
||||||
memory.bind(&texture)?;
|
|
||||||
|
|
||||||
let image_subresource = vk::ImageSubresourceRange::builder()
|
let image_subresource = vk::ImageSubresourceRange::builder()
|
||||||
.level_count(image_info.mip_levels)
|
.level_count(image_info.mip_levels)
|
||||||
.layer_count(1)
|
.layer_count(1)
|
||||||
|
@ -86,14 +79,12 @@ impl LutTexture {
|
||||||
|
|
||||||
let mut staging = VulkanBuffer::new(
|
let mut staging = VulkanBuffer::new(
|
||||||
&vulkan.device,
|
&vulkan.device,
|
||||||
&vulkan.memory_properties,
|
&vulkan.alloc,
|
||||||
vk::BufferUsageFlags::TRANSFER_SRC,
|
vk::BufferUsageFlags::TRANSFER_SRC,
|
||||||
image.bytes.len(),
|
image.bytes.len(),
|
||||||
)?;
|
)?;
|
||||||
unsafe {
|
|
||||||
let mut handle = staging.map()?;
|
staging.as_mut_slice()?.copy_from_slice(&image.bytes);
|
||||||
handle.copy_from(0, &image.bytes)
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
util::vulkan_image_layout_transition_levels(
|
util::vulkan_image_layout_transition_levels(
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
use crate::{error, util};
|
use crate::error;
|
||||||
|
use crate::error::FilterChainError;
|
||||||
use ash::vk;
|
use ash::vk;
|
||||||
|
use gpu_allocator::vulkan::{Allocation, AllocationCreateDesc, AllocationScheme, Allocator};
|
||||||
|
use gpu_allocator::MemoryLocation;
|
||||||
use librashader_runtime::uniforms::UniformStorageAccess;
|
use librashader_runtime::uniforms::UniformStorageAccess;
|
||||||
|
use parking_lot::RwLock;
|
||||||
|
|
||||||
use std::ffi::c_void;
|
use std::ffi::c_void;
|
||||||
use std::mem::ManuallyDrop;
|
use std::mem::ManuallyDrop;
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
|
@ -8,32 +13,46 @@ use std::ptr::NonNull;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
pub struct VulkanImageMemory {
|
pub struct VulkanImageMemory {
|
||||||
pub handle: vk::DeviceMemory,
|
allocation: Option<Allocation>,
|
||||||
|
allocator: Arc<RwLock<Allocator>>,
|
||||||
device: Arc<ash::Device>,
|
device: Arc<ash::Device>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VulkanImageMemory {
|
impl VulkanImageMemory {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
device: &Arc<ash::Device>,
|
device: &Arc<ash::Device>,
|
||||||
alloc: &vk::MemoryAllocateInfo,
|
allocator: &Arc<RwLock<Allocator>>,
|
||||||
|
requirements: vk::MemoryRequirements,
|
||||||
|
image: &vk::Image,
|
||||||
) -> error::Result<VulkanImageMemory> {
|
) -> error::Result<VulkanImageMemory> {
|
||||||
|
let allocation = allocator.write().allocate(&AllocationCreateDesc {
|
||||||
|
name: "imagemem",
|
||||||
|
requirements,
|
||||||
|
location: MemoryLocation::GpuOnly,
|
||||||
|
linear: false,
|
||||||
|
allocation_scheme: AllocationScheme::DedicatedImage(*image),
|
||||||
|
})?;
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
|
device.bind_image_memory(*image, allocation.memory(), 0)?;
|
||||||
Ok(VulkanImageMemory {
|
Ok(VulkanImageMemory {
|
||||||
handle: device.allocate_memory(alloc, None)?,
|
allocation: Some(allocation),
|
||||||
device: device.clone(),
|
allocator: Arc::clone(allocator),
|
||||||
|
device: Arc::clone(device),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn bind(&self, image: &vk::Image) -> error::Result<()> {
|
|
||||||
unsafe { Ok(self.device.bind_image_memory(*image, self.handle, 0)?) }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for VulkanImageMemory {
|
impl Drop for VulkanImageMemory {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
unsafe {
|
unsafe {
|
||||||
self.device.free_memory(self.handle, None);
|
let allocation = self.allocation.take();
|
||||||
|
if let Some(allocation) = allocation {
|
||||||
|
if let Err(e) = self.allocator.write().free(allocation) {
|
||||||
|
println!("librashader-runtime-vk: [warn] failed to deallocate image buffer {e}")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,19 +60,15 @@ impl Drop for VulkanImageMemory {
|
||||||
pub struct VulkanBuffer {
|
pub struct VulkanBuffer {
|
||||||
pub handle: vk::Buffer,
|
pub handle: vk::Buffer,
|
||||||
device: Arc<ash::Device>,
|
device: Arc<ash::Device>,
|
||||||
memory: vk::DeviceMemory,
|
memory: Option<Allocation>,
|
||||||
|
allocator: Arc<RwLock<Allocator>>,
|
||||||
size: vk::DeviceSize,
|
size: vk::DeviceSize,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct VulkanBufferMapHandle<'a> {
|
|
||||||
buffer: &'a mut VulkanBuffer,
|
|
||||||
ptr: *mut c_void,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl VulkanBuffer {
|
impl VulkanBuffer {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
device: &Arc<ash::Device>,
|
device: &Arc<ash::Device>,
|
||||||
mem_props: &vk::PhysicalDeviceMemoryProperties,
|
allocator: &Arc<RwLock<Allocator>>,
|
||||||
usage: vk::BufferUsageFlags,
|
usage: vk::BufferUsageFlags,
|
||||||
size: usize,
|
size: usize,
|
||||||
) -> error::Result<VulkanBuffer> {
|
) -> error::Result<VulkanBuffer> {
|
||||||
|
@ -66,45 +81,48 @@ impl VulkanBuffer {
|
||||||
let buffer = device.create_buffer(&buffer_info, None)?;
|
let buffer = device.create_buffer(&buffer_info, None)?;
|
||||||
|
|
||||||
let memory_reqs = device.get_buffer_memory_requirements(buffer);
|
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)?;
|
let alloc = allocator.write().allocate(&AllocationCreateDesc {
|
||||||
device.bind_buffer_memory(buffer, alloc, 0)?;
|
name: "buffer",
|
||||||
|
requirements: memory_reqs,
|
||||||
|
location: MemoryLocation::CpuToGpu,
|
||||||
|
linear: true,
|
||||||
|
allocation_scheme: AllocationScheme::DedicatedBuffer(buffer),
|
||||||
|
})?;
|
||||||
|
|
||||||
|
// let alloc = device.allocate_memory(&alloc_info, None)?;
|
||||||
|
device.bind_buffer_memory(buffer, alloc.memory(), 0)?;
|
||||||
|
|
||||||
Ok(VulkanBuffer {
|
Ok(VulkanBuffer {
|
||||||
handle: buffer,
|
handle: buffer,
|
||||||
memory: alloc,
|
memory: Some(alloc),
|
||||||
|
allocator: Arc::clone(allocator),
|
||||||
size: size as vk::DeviceSize,
|
size: size as vk::DeviceSize,
|
||||||
device: device.clone(),
|
device: device.clone(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn map(&mut self) -> error::Result<VulkanBufferMapHandle> {
|
pub fn as_mut_slice(&mut self) -> error::Result<&mut [u8]> {
|
||||||
let dst = unsafe {
|
let Some(allocation) = self.memory.as_mut() else {
|
||||||
self.device
|
return Err(FilterChainError::AllocationDoesNotExist)
|
||||||
.map_memory(self.memory, 0, self.size, vk::MemoryMapFlags::empty())?
|
|
||||||
};
|
};
|
||||||
|
let Some(allocation) = allocation.mapped_slice_mut() else {
|
||||||
Ok(VulkanBufferMapHandle {
|
return Err(FilterChainError::AllocationDoesNotExist)
|
||||||
buffer: self,
|
};
|
||||||
ptr: dst,
|
Ok(allocation)
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for VulkanBuffer {
|
impl Drop for VulkanBuffer {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
unsafe {
|
unsafe {
|
||||||
if self.memory != vk::DeviceMemory::null() {
|
if let Some(allocation) = self.memory.take() {
|
||||||
self.device.free_memory(self.memory, None);
|
if let Err(e) = self.allocator.write().free(allocation) {
|
||||||
|
println!(
|
||||||
|
"librashader-runtime-vk: [warn] failed to deallocate buffer memory {e}"
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.handle != vk::Buffer::null() {
|
if self.handle != vk::Buffer::null() {
|
||||||
|
@ -114,26 +132,6 @@ impl Drop for VulkanBuffer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> VulkanBufferMapHandle<'a> {
|
|
||||||
pub unsafe fn copy_from(&mut self, offset: usize, src: &[u8]) {
|
|
||||||
let mut align = ash::util::Align::new(
|
|
||||||
self.ptr
|
|
||||||
.map_addr(|original| original.wrapping_add(offset))
|
|
||||||
.cast(),
|
|
||||||
std::mem::align_of::<u8>() as u64,
|
|
||||||
self.buffer.size,
|
|
||||||
);
|
|
||||||
|
|
||||||
align.copy_from_slice(src);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Drop for VulkanBufferMapHandle<'a> {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
unsafe { self.buffer.device.unmap_memory(self.buffer.memory) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// SAFETY: Creating the pointer should be safe in multithreaded contexts.
|
/// SAFETY: Creating the pointer should be safe in multithreaded contexts.
|
||||||
///
|
///
|
||||||
/// Mutation is guarded by DerefMut<Target=[u8]>
|
/// Mutation is guarded by DerefMut<Target=[u8]>
|
||||||
|
@ -146,18 +144,17 @@ pub struct RawVulkanBuffer {
|
||||||
impl RawVulkanBuffer {
|
impl RawVulkanBuffer {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
device: &Arc<ash::Device>,
|
device: &Arc<ash::Device>,
|
||||||
mem_props: &vk::PhysicalDeviceMemoryProperties,
|
allocator: &Arc<RwLock<Allocator>>,
|
||||||
usage: vk::BufferUsageFlags,
|
usage: vk::BufferUsageFlags,
|
||||||
size: usize,
|
size: usize,
|
||||||
) -> error::Result<Self> {
|
) -> error::Result<Self> {
|
||||||
let buffer = ManuallyDrop::new(VulkanBuffer::new(device, mem_props, usage, size)?);
|
let buffer = ManuallyDrop::new(VulkanBuffer::new(device, allocator, usage, size)?);
|
||||||
let ptr = unsafe {
|
|
||||||
NonNull::new_unchecked(device.map_memory(
|
let Some(ptr) = buffer.memory
|
||||||
buffer.memory,
|
.as_ref()
|
||||||
0,
|
.map(|m| m.mapped_ptr())
|
||||||
buffer.size,
|
.flatten() else {
|
||||||
vk::MemoryMapFlags::empty(),
|
return Err(FilterChainError::AllocationDoesNotExist)
|
||||||
)?)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(RawVulkanBuffer { buffer, ptr })
|
Ok(RawVulkanBuffer { buffer, ptr })
|
||||||
|
@ -193,12 +190,7 @@ impl RawVulkanBuffer {
|
||||||
impl Drop for RawVulkanBuffer {
|
impl Drop for RawVulkanBuffer {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
unsafe {
|
unsafe {
|
||||||
self.buffer.device.unmap_memory(self.buffer.memory);
|
ManuallyDrop::drop(&mut self.buffer);
|
||||||
self.ptr = NonNull::dangling();
|
|
||||||
if self.buffer.memory != vk::DeviceMemory::null() {
|
|
||||||
self.buffer.device.free_memory(self.buffer.memory, None);
|
|
||||||
}
|
|
||||||
|
|
||||||
if self.buffer.handle != vk::Buffer::null() {
|
if self.buffer.handle != vk::Buffer::null() {
|
||||||
self.buffer.device.destroy_buffer(self.buffer.handle, None);
|
self.buffer.device.destroy_buffer(self.buffer.handle, None);
|
||||||
}
|
}
|
|
@ -1,8 +1,9 @@
|
||||||
use crate::filter_chain::VulkanObjects;
|
use crate::filter_chain::VulkanObjects;
|
||||||
use crate::util::find_vulkan_memory_type;
|
use crate::memory::VulkanImageMemory;
|
||||||
use crate::vulkan_primitives::VulkanImageMemory;
|
|
||||||
use crate::{error, util};
|
use crate::{error, util};
|
||||||
use ash::vk;
|
use ash::vk;
|
||||||
|
use gpu_allocator::vulkan::Allocator;
|
||||||
|
use parking_lot::RwLock;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use crate::error::FilterChainError;
|
use crate::error::FilterChainError;
|
||||||
|
@ -12,7 +13,7 @@ use librashader_runtime::scaling::{MipmapSize, ScaleFramebuffer, ViewportSize};
|
||||||
|
|
||||||
pub struct OwnedImage {
|
pub struct OwnedImage {
|
||||||
pub device: Arc<ash::Device>,
|
pub device: Arc<ash::Device>,
|
||||||
pub mem_props: vk::PhysicalDeviceMemoryProperties,
|
pub allocator: Arc<RwLock<Allocator>>,
|
||||||
pub image_view: vk::ImageView,
|
pub image_view: vk::ImageView,
|
||||||
pub image: VulkanImage,
|
pub image: VulkanImage,
|
||||||
pub memory: VulkanImageMemory,
|
pub memory: VulkanImageMemory,
|
||||||
|
@ -32,7 +33,7 @@ pub struct OwnedImageLayout {
|
||||||
impl OwnedImage {
|
impl OwnedImage {
|
||||||
fn new_internal(
|
fn new_internal(
|
||||||
device: Arc<ash::Device>,
|
device: Arc<ash::Device>,
|
||||||
mem_props: vk::PhysicalDeviceMemoryProperties,
|
alloc: &Arc<RwLock<Allocator>>,
|
||||||
size: Size<u32>,
|
size: Size<u32>,
|
||||||
mut format: ImageFormat,
|
mut format: ImageFormat,
|
||||||
max_miplevels: u32,
|
max_miplevels: u32,
|
||||||
|
@ -63,19 +64,7 @@ impl OwnedImage {
|
||||||
let image = unsafe { device.create_image(&image_create_info, None)? };
|
let image = unsafe { device.create_image(&image_create_info, None)? };
|
||||||
let mem_reqs = unsafe { device.get_image_memory_requirements(image) };
|
let mem_reqs = unsafe { device.get_image_memory_requirements(image) };
|
||||||
|
|
||||||
let alloc_info = vk::MemoryAllocateInfo::builder()
|
let memory = VulkanImageMemory::new(&device, alloc, mem_reqs, &image)?;
|
||||||
.allocation_size(mem_reqs.size)
|
|
||||||
.memory_type_index(find_vulkan_memory_type(
|
|
||||||
&mem_props,
|
|
||||||
mem_reqs.memory_type_bits,
|
|
||||||
vk::MemoryPropertyFlags::DEVICE_LOCAL,
|
|
||||||
)?)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
// todo: optimize by reusing existing memory.
|
|
||||||
let memory = VulkanImageMemory::new(&device, &alloc_info)?;
|
|
||||||
memory.bind(&image)?;
|
|
||||||
|
|
||||||
let image_subresource = vk::ImageSubresourceRange::builder()
|
let image_subresource = vk::ImageSubresourceRange::builder()
|
||||||
.base_mip_level(0)
|
.base_mip_level(0)
|
||||||
.base_array_layer(0)
|
.base_array_layer(0)
|
||||||
|
@ -103,7 +92,7 @@ impl OwnedImage {
|
||||||
|
|
||||||
Ok(OwnedImage {
|
Ok(OwnedImage {
|
||||||
device,
|
device,
|
||||||
mem_props,
|
allocator: Arc::clone(alloc),
|
||||||
image_view,
|
image_view,
|
||||||
image: VulkanImage {
|
image: VulkanImage {
|
||||||
image,
|
image,
|
||||||
|
@ -124,7 +113,7 @@ impl OwnedImage {
|
||||||
) -> error::Result<OwnedImage> {
|
) -> error::Result<OwnedImage> {
|
||||||
Self::new_internal(
|
Self::new_internal(
|
||||||
vulkan.device.clone(),
|
vulkan.device.clone(),
|
||||||
vulkan.memory_properties,
|
&vulkan.alloc,
|
||||||
size,
|
size,
|
||||||
format,
|
format,
|
||||||
max_miplevels,
|
max_miplevels,
|
||||||
|
@ -150,7 +139,7 @@ impl OwnedImage {
|
||||||
|
|
||||||
let new = OwnedImage::new_internal(
|
let new = OwnedImage::new_internal(
|
||||||
self.device.clone(),
|
self.device.clone(),
|
||||||
self.mem_props,
|
&self.allocator,
|
||||||
size,
|
size,
|
||||||
if format == ImageFormat::Unknown {
|
if format == ImageFormat::Unknown {
|
||||||
ImageFormat::R8G8B8A8Unorm
|
ImageFormat::R8G8B8A8Unorm
|
||||||
|
|
|
@ -1,70 +0,0 @@
|
||||||
use crate::error;
|
|
||||||
use crate::vulkan_primitives::VulkanBuffer;
|
|
||||||
use ash::vk;
|
|
||||||
use librashader_runtime::ringbuffer::{BoxRingBuffer, RingBuffer};
|
|
||||||
use librashader_runtime::uniforms::UniformStorageAccess;
|
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
pub struct VkUboRing {
|
|
||||||
ring: BoxRingBuffer<VulkanBuffer>,
|
|
||||||
device: Arc<ash::Device>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl VkUboRing {
|
|
||||||
pub fn new(
|
|
||||||
device: &Arc<ash::Device>,
|
|
||||||
mem_props: &vk::PhysicalDeviceMemoryProperties,
|
|
||||||
ring_size: usize,
|
|
||||||
buffer_size: usize,
|
|
||||||
) -> error::Result<Self> {
|
|
||||||
let mut ring = Vec::new();
|
|
||||||
for _ in 0..ring_size {
|
|
||||||
ring.push(VulkanBuffer::new(
|
|
||||||
device,
|
|
||||||
mem_props,
|
|
||||||
vk::BufferUsageFlags::UNIFORM_BUFFER,
|
|
||||||
buffer_size,
|
|
||||||
)?);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(VkUboRing {
|
|
||||||
ring: BoxRingBuffer::from_vec(ring),
|
|
||||||
device: device.clone(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn bind_to_descriptor_set(
|
|
||||||
&mut self,
|
|
||||||
descriptor_set: vk::DescriptorSet,
|
|
||||||
binding: u32,
|
|
||||||
storage: &impl UniformStorageAccess,
|
|
||||||
) -> error::Result<()> {
|
|
||||||
// todo: write directly to allocated buffer.
|
|
||||||
unsafe {
|
|
||||||
let buffer = self.ring.current_mut();
|
|
||||||
let mut map = buffer.map()?;
|
|
||||||
map.copy_from(0, storage.ubo_slice())
|
|
||||||
}
|
|
||||||
|
|
||||||
let buffer = self.ring.current();
|
|
||||||
unsafe {
|
|
||||||
let buffer_info = [vk::DescriptorBufferInfo::builder()
|
|
||||||
.buffer(buffer.handle)
|
|
||||||
.offset(0)
|
|
||||||
.range(storage.ubo_slice().len() as vk::DeviceSize)
|
|
||||||
.build()];
|
|
||||||
|
|
||||||
let write_info = [vk::WriteDescriptorSet::builder()
|
|
||||||
.descriptor_type(vk::DescriptorType::UNIFORM_BUFFER)
|
|
||||||
.dst_set(descriptor_set)
|
|
||||||
.dst_binding(binding)
|
|
||||||
.dst_array_element(0)
|
|
||||||
.buffer_info(&buffer_info)
|
|
||||||
.build()];
|
|
||||||
|
|
||||||
self.device.update_descriptor_sets(&write_info, &[])
|
|
||||||
}
|
|
||||||
self.ring.next();
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,4 +1,8 @@
|
||||||
use ash::vk;
|
use ash::vk;
|
||||||
|
use gpu_allocator::vulkan::{Allocator, AllocatorCreateDesc};
|
||||||
|
use gpu_allocator::AllocatorDebugSettings;
|
||||||
|
use parking_lot::RwLock;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
use crate::error;
|
use crate::error;
|
||||||
use crate::error::FilterChainError;
|
use crate::error::FilterChainError;
|
||||||
|
@ -17,6 +21,7 @@ pub fn binding_stage_to_vulkan_stage(stage_mask: BindingStage) -> vk::ShaderStag
|
||||||
mask
|
mask
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
pub fn find_vulkan_memory_type(
|
pub fn find_vulkan_memory_type(
|
||||||
props: &vk::PhysicalDeviceMemoryProperties,
|
props: &vk::PhysicalDeviceMemoryProperties,
|
||||||
device_reqs: u32,
|
device_reqs: u32,
|
||||||
|
@ -81,3 +86,18 @@ pub unsafe fn vulkan_image_layout_transition_levels(
|
||||||
&[barrier],
|
&[barrier],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn create_allocator(
|
||||||
|
device: ash::Device,
|
||||||
|
instance: ash::Instance,
|
||||||
|
physical_device: vk::PhysicalDevice,
|
||||||
|
) -> error::Result<Arc<RwLock<Allocator>>> {
|
||||||
|
let alloc = Allocator::new(&AllocatorCreateDesc {
|
||||||
|
instance,
|
||||||
|
device,
|
||||||
|
physical_device,
|
||||||
|
debug_settings: Default::default(),
|
||||||
|
buffer_device_address: false,
|
||||||
|
})?;
|
||||||
|
Ok(Arc::new(RwLock::new(alloc)))
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue