extract resources into renderer_resources
This commit is contained in:
parent
69039ba3c1
commit
a173cf18ff
|
|
@ -12,7 +12,7 @@ members = [
|
|||
"crates/window",
|
||||
"crates/game",
|
||||
"crates/text",
|
||||
"crates/bevy_vulkan_render", "crates/renderer_device",
|
||||
"crates/bevy_vulkan_render", "crates/renderer_device", "crates/renderer_resources",
|
||||
]
|
||||
|
||||
[dependencies]
|
||||
|
|
@ -57,6 +57,7 @@ ahash = "0.8"
|
|||
md-5 = "0.11.0"
|
||||
|
||||
parking_lot = "0.12.3"
|
||||
bytemuck = { version = "1.21.0", features = ["derive"] }
|
||||
|
||||
# tokio = "1.42"
|
||||
# futures = "0.3"
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ edition = "2024"
|
|||
|
||||
[dependencies]
|
||||
renderer_device = { path = "../renderer_device" }
|
||||
renderer_resources = { path = "../renderer_resources" }
|
||||
renderer_macros = { path = "renderer_macros" }
|
||||
arrayvec = { workspace = true }
|
||||
indexmap = { workspace = true }
|
||||
|
|
|
|||
|
|
@ -11,18 +11,17 @@ use raw_window_handle::{RawDisplayHandle, RawWindowHandle};
|
|||
|
||||
pub use ash;
|
||||
|
||||
mod buffers;
|
||||
pub mod commands;
|
||||
#[path = "egui.rs"]
|
||||
mod egui_pass;
|
||||
mod images;
|
||||
mod pipeline;
|
||||
pub mod render_graph;
|
||||
pub mod rendering;
|
||||
pub mod swapchain;
|
||||
mod text;
|
||||
pub mod util;
|
||||
|
||||
pub(crate) use renderer_resources::{buffers, images, pipeline};
|
||||
|
||||
pub use renderer_device::{device, instance, queue, sync};
|
||||
pub use renderer_device::{
|
||||
compatible_extension_properties, extension_intersection,
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ use std::sync::Arc;
|
|||
use ash::vk;
|
||||
use glam::{
|
||||
camera::rh::{proj, view},
|
||||
f32::Mat4,
|
||||
vec3,
|
||||
};
|
||||
use gpu_allocator::MemoryLocation;
|
||||
|
|
@ -165,11 +164,7 @@ impl Wireframe {
|
|||
);
|
||||
}
|
||||
|
||||
let future = cmd.submit_async(
|
||||
None,
|
||||
None,
|
||||
Arc::new(sync::Fence::from_pool(&dev, None)?),
|
||||
)?;
|
||||
let future = cmd.submit_async(None, None, Arc::new(sync::Fence::from_pool(&dev, None)?))?;
|
||||
|
||||
let pipeline = Self::create_pipeline(dev.clone())?;
|
||||
|
||||
|
|
|
|||
|
|
@ -562,7 +562,17 @@ impl Swapchain {
|
|||
|
||||
let idx = idx as usize;
|
||||
let image = self.images[idx];
|
||||
let image = Arc::new(images::Image::from_swapchain_image(image, &self));
|
||||
let image = Arc::new(images::Image::from_swapchain_raw(
|
||||
image,
|
||||
self.swapchain.device().clone(),
|
||||
self.config.format,
|
||||
vk::Extent3D {
|
||||
width: self.config.extent.width,
|
||||
height: self.config.extent.height,
|
||||
depth: 1,
|
||||
},
|
||||
self.config.usage,
|
||||
));
|
||||
let view = image.create_view(ImageViewDesc {
|
||||
name: Some(format!("swapchain-{:x}-image-view-{idx}", self.raw().as_raw()).into()),
|
||||
kind: vk::ImageViewType::TYPE_2D,
|
||||
|
|
|
|||
|
|
@ -6,75 +6,7 @@ use std::{
|
|||
use ash::vk;
|
||||
use bytemuck::{Pod, Zeroable};
|
||||
|
||||
pub(crate) mod weak_vec {
|
||||
#![allow(dead_code)]
|
||||
//! Module containing the [`WeakVec`] API.
|
||||
|
||||
use std::{sync::Weak, vec::Vec};
|
||||
|
||||
/// An optimized container for `Weak` references of `T` that minimizes reallocations by
|
||||
/// dropping older elements that no longer have strong references to them.
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct WeakVec<T> {
|
||||
inner: Vec<Weak<T>>,
|
||||
}
|
||||
|
||||
impl<T> Default for WeakVec<T> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
inner: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> WeakVec<T> {
|
||||
pub(crate) fn new() -> Self {
|
||||
Self { inner: Vec::new() }
|
||||
}
|
||||
|
||||
/// Pushes a new element to this collection.
|
||||
///
|
||||
/// If the inner Vec needs to be reallocated, we will first drop older elements that
|
||||
/// no longer have strong references to them.
|
||||
pub(crate) fn push(&mut self, value: Weak<T>) {
|
||||
if self.inner.len() == self.inner.capacity() {
|
||||
// Iterating backwards has the advantage that we don't do more work than we have to.
|
||||
for i in (0..self.inner.len()).rev() {
|
||||
if self.inner[i].strong_count() == 0 {
|
||||
self.inner.swap_remove(i);
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure our capacity is twice the number of live elements.
|
||||
// Leaving some spare capacity ensures that we won't re-scan immediately.
|
||||
self.inner.reserve_exact(self.inner.len());
|
||||
}
|
||||
|
||||
self.inner.push(value);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct WeakVecIter<T> {
|
||||
inner: std::vec::IntoIter<Weak<T>>,
|
||||
}
|
||||
|
||||
impl<T> Iterator for WeakVecIter<T> {
|
||||
type Item = Weak<T>;
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.inner.next()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> IntoIterator for WeakVec<T> {
|
||||
type Item = Weak<T>;
|
||||
type IntoIter = WeakVecIter<T>;
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
WeakVecIter {
|
||||
inner: self.inner.into_iter(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pub use renderer_resources::util::{F32, eq_f32, hash_f32, ord_f32};
|
||||
|
||||
#[derive(derive_more::Debug)]
|
||||
pub(crate) struct DropGuard(#[debug(skip)] ManuallyDrop<Box<dyn FnOnce()>>);
|
||||
|
|
@ -419,104 +351,6 @@ impl Rect2D {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn eq_f32(lhs: f32, rhs: f32) -> bool {
|
||||
use core::num::FpCategory::*;
|
||||
match (lhs.classify(), rhs.classify()) {
|
||||
(Zero, Zero) | (Nan, Nan) => true,
|
||||
(Infinite, Infinite) => lhs.signum() == rhs.signum(),
|
||||
_ => lhs == rhs,
|
||||
}
|
||||
}
|
||||
pub fn ord_f32(lhs: f32, rhs: f32) -> core::cmp::Ordering {
|
||||
use core::cmp::Ordering;
|
||||
use core::num::FpCategory::*;
|
||||
match (lhs.classify(), rhs.classify()) {
|
||||
(Zero, Zero) | (Nan, Nan) => Ordering::Equal,
|
||||
(Infinite, Infinite) => {
|
||||
core::cmp::PartialOrd::partial_cmp(&lhs.signum(), &rhs.signum()).unwrap()
|
||||
}
|
||||
_ => core::cmp::PartialOrd::partial_cmp(&lhs, &rhs).unwrap(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn hash_f32<H: std::hash::Hasher>(state: &mut H, f: f32) {
|
||||
use std::hash::Hash;
|
||||
let classify = f.classify();
|
||||
match classify {
|
||||
std::num::FpCategory::Nan => (classify as u8).hash(state),
|
||||
std::num::FpCategory::Infinite | std::num::FpCategory::Zero => {
|
||||
(classify as u8, f.signum() as i8).hash(state)
|
||||
}
|
||||
std::num::FpCategory::Subnormal | std::num::FpCategory::Normal => f.to_bits().hash(state),
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(transparent)]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct F32(f32);
|
||||
|
||||
impl F32 {
|
||||
#[inline]
|
||||
pub fn from_bits(bits: u32) -> Self {
|
||||
Self(f32::from_bits(bits))
|
||||
}
|
||||
#[inline]
|
||||
pub fn into_bits(self) -> u32 {
|
||||
self.0.to_bits()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<f32> for F32 {
|
||||
fn from(value: f32) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
impl From<F32> for f32 {
|
||||
fn from(value: F32) -> Self {
|
||||
value.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for F32 {
|
||||
type Target = f32;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for F32 {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for F32 {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
eq_f32(self.0, other.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for F32 {}
|
||||
|
||||
impl PartialOrd for F32 {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
||||
Some(ord_f32(self.0, other.0))
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for F32 {
|
||||
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
||||
ord_f32(self.0, other.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl core::hash::Hash for F32 {
|
||||
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
||||
hash_f32(state, self.0)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn timed<T, F: FnOnce() -> T>(label: &str, f: F) -> T {
|
||||
let now = std::time::Instant::now();
|
||||
let out = f();
|
||||
|
|
|
|||
13
crates/renderer_resources/Cargo.toml
Normal file
13
crates/renderer_resources/Cargo.toml
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
[package]
|
||||
name = "renderer_resources"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
renderer_device = { path = "../renderer_device" }
|
||||
ash = { workspace = true }
|
||||
gpu-allocator = { workspace = true }
|
||||
parking_lot = { workspace = true }
|
||||
bytemuck = { workspace = true }
|
||||
tracing = { workspace = true }
|
||||
ash-formats = { git = "https://github.com/janis-bhm/ash-formats", branch = "main" }
|
||||
|
|
@ -49,7 +49,6 @@ impl PartialEq for BufferDesc {
|
|||
fn eq(&self, other: &Self) -> bool {
|
||||
self.flags == other.flags
|
||||
// for hashmaps, `Eq` may be more strict than `Hash`
|
||||
&& self.name == other.name
|
||||
&& self.size == other.size
|
||||
&& self.usage == other.usage
|
||||
&& self.queue_families == other.queue_families
|
||||
|
|
@ -6,11 +6,8 @@ use std::{
|
|||
};
|
||||
|
||||
use crate::{
|
||||
device::{
|
||||
Allocation, AllocationStrategy, DeviceObject, QueueFlags,
|
||||
},
|
||||
swapchain::Swapchain,
|
||||
util::weak_vec::WeakVec,
|
||||
device::{Allocation, AllocationStrategy, DeviceObject, QueueFlags},
|
||||
util::WeakVec,
|
||||
};
|
||||
|
||||
use super::Device;
|
||||
|
|
@ -75,7 +72,6 @@ impl Eq for ImageDesc {}
|
|||
impl PartialEq for ImageDesc {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.flags == other.flags
|
||||
&& self.name == other.name
|
||||
&& self.format == other.format
|
||||
&& self.kind == other.kind
|
||||
&& self.mip_levels == other.mip_levels
|
||||
|
|
@ -90,7 +86,7 @@ impl PartialEq for ImageDesc {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> std::fmt::Debug for ImageDesc {
|
||||
impl std::fmt::Debug for ImageDesc {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("ImageDesc")
|
||||
.field("flags", &self.flags)
|
||||
|
|
@ -255,22 +251,24 @@ impl Image {
|
|||
Self::new_with_allocation_unchecked(device, image, allocation, desc)
|
||||
}
|
||||
|
||||
pub fn from_swapchain_image(image: vk::Image, swapchain: &Swapchain) -> Self {
|
||||
pub fn from_swapchain_raw(
|
||||
image: vk::Image,
|
||||
device: Device,
|
||||
format: vk::Format,
|
||||
extent: vk::Extent3D,
|
||||
usage: vk::ImageUsageFlags,
|
||||
) -> Self {
|
||||
Self {
|
||||
image: ImageInner::Swapchain(image, swapchain.swapchain.device().clone()),
|
||||
image: ImageInner::Swapchain(image, device),
|
||||
desc: ImageDesc {
|
||||
format: swapchain.config.format,
|
||||
format,
|
||||
kind: vk::ImageType::TYPE_2D,
|
||||
mip_levels: 1,
|
||||
array_layers: 1,
|
||||
samples: vk::SampleCountFlags::TYPE_1,
|
||||
extent: vk::Extent3D {
|
||||
width: swapchain.config.extent.width,
|
||||
height: swapchain.config.extent.height,
|
||||
depth: 1,
|
||||
},
|
||||
extent,
|
||||
tiling: vk::ImageTiling::OPTIMAL,
|
||||
usage: swapchain.config.usage,
|
||||
usage,
|
||||
queue_families: QueueFlags::PRESENT,
|
||||
layout: vk::ImageLayout::UNDEFINED,
|
||||
mem_location: gpu_allocator::MemoryLocation::GpuOnly,
|
||||
6
crates/renderer_resources/src/lib.rs
Normal file
6
crates/renderer_resources/src/lib.rs
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
pub use renderer_device::{Device, Error, Result, device, make_extension};
|
||||
|
||||
pub mod buffers;
|
||||
pub mod images;
|
||||
pub mod pipeline;
|
||||
pub mod util;
|
||||
170
crates/renderer_resources/src/util.rs
Normal file
170
crates/renderer_resources/src/util.rs
Normal file
|
|
@ -0,0 +1,170 @@
|
|||
pub(crate) mod weak_vec {
|
||||
#![allow(dead_code)]
|
||||
//! Module containing the [`WeakVec`] API.
|
||||
|
||||
use std::{sync::Weak, vec::Vec};
|
||||
|
||||
/// An optimized container for `Weak` references of `T` that minimizes reallocations by
|
||||
/// dropping older elements that no longer have strong references to them.
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct WeakVec<T> {
|
||||
inner: Vec<Weak<T>>,
|
||||
}
|
||||
|
||||
impl<T> Default for WeakVec<T> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
inner: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> WeakVec<T> {
|
||||
pub(crate) fn new() -> Self {
|
||||
Self { inner: Vec::new() }
|
||||
}
|
||||
|
||||
/// Pushes a new element to this collection.
|
||||
///
|
||||
/// If the inner Vec needs to be reallocated, we will first drop older elements that
|
||||
/// no longer have strong references to them.
|
||||
pub(crate) fn push(&mut self, value: Weak<T>) {
|
||||
if self.inner.len() == self.inner.capacity() {
|
||||
// Iterating backwards has the advantage that we don't do more work than we have to.
|
||||
for i in (0..self.inner.len()).rev() {
|
||||
if self.inner[i].strong_count() == 0 {
|
||||
self.inner.swap_remove(i);
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure our capacity is twice the number of live elements.
|
||||
// Leaving some spare capacity ensures that we won't re-scan immediately.
|
||||
self.inner.reserve_exact(self.inner.len());
|
||||
}
|
||||
|
||||
self.inner.push(value);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct WeakVecIter<T> {
|
||||
inner: std::vec::IntoIter<Weak<T>>,
|
||||
}
|
||||
|
||||
impl<T> Iterator for WeakVecIter<T> {
|
||||
type Item = Weak<T>;
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.inner.next()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> IntoIterator for WeakVec<T> {
|
||||
type Item = Weak<T>;
|
||||
type IntoIter = WeakVecIter<T>;
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
WeakVecIter {
|
||||
inner: self.inner.into_iter(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) use weak_vec::WeakVec;
|
||||
|
||||
pub fn eq_f32(lhs: f32, rhs: f32) -> bool {
|
||||
use core::num::FpCategory::*;
|
||||
match (lhs.classify(), rhs.classify()) {
|
||||
(Zero, Zero) | (Nan, Nan) => true,
|
||||
(Infinite, Infinite) => lhs.signum() == rhs.signum(),
|
||||
_ => lhs == rhs,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ord_f32(lhs: f32, rhs: f32) -> core::cmp::Ordering {
|
||||
use core::cmp::Ordering;
|
||||
use core::num::FpCategory::*;
|
||||
match (lhs.classify(), rhs.classify()) {
|
||||
(Zero, Zero) | (Nan, Nan) => Ordering::Equal,
|
||||
(Infinite, Infinite) => {
|
||||
core::cmp::PartialOrd::partial_cmp(&lhs.signum(), &rhs.signum()).unwrap()
|
||||
}
|
||||
_ => core::cmp::PartialOrd::partial_cmp(&lhs, &rhs).unwrap(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn hash_f32<H: std::hash::Hasher>(state: &mut H, f: f32) {
|
||||
use std::hash::Hash;
|
||||
let classify = f.classify();
|
||||
match classify {
|
||||
std::num::FpCategory::Nan => (classify as u8).hash(state),
|
||||
std::num::FpCategory::Infinite | std::num::FpCategory::Zero => {
|
||||
(classify as u8, f.signum() as i8).hash(state)
|
||||
}
|
||||
std::num::FpCategory::Subnormal | std::num::FpCategory::Normal => f.to_bits().hash(state),
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(transparent)]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct F32(f32);
|
||||
|
||||
impl F32 {
|
||||
#[inline]
|
||||
pub fn from_bits(bits: u32) -> Self {
|
||||
Self(f32::from_bits(bits))
|
||||
}
|
||||
#[inline]
|
||||
pub fn into_bits(self) -> u32 {
|
||||
self.0.to_bits()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<f32> for F32 {
|
||||
fn from(value: f32) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
impl From<F32> for f32 {
|
||||
fn from(value: F32) -> Self {
|
||||
value.0
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Deref for F32 {
|
||||
type Target = f32;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::DerefMut for F32 {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for F32 {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
eq_f32(self.0, other.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for F32 {}
|
||||
|
||||
impl PartialOrd for F32 {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
||||
Some(ord_f32(self.0, other.0))
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for F32 {
|
||||
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
||||
ord_f32(self.0, other.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl core::hash::Hash for F32 {
|
||||
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
||||
hash_f32(state, self.0)
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue