Compare commits
No commits in common. "cb02051cf3536538dd9ad2435082e4b418cc9fee" and "7b6da19a77c9f289115865913cee8c18867bcf54" have entirely different histories.
cb02051cf3
...
7b6da19a77
51
Cargo.toml
51
Cargo.toml
|
|
@ -28,28 +28,27 @@ debug = true
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
anyhow = "1.0.89"
|
anyhow = "1.0.89"
|
||||||
thiserror = "2.0"
|
thiserror = "2.0"
|
||||||
derive_more = { version = "2", features = ["deref", "debug", "deref_mut"] }
|
derive_more = { version = "1.0.0", features = ["deref", "debug", "deref_mut"] }
|
||||||
|
|
||||||
tracing = "0.1"
|
tracing = "0.1"
|
||||||
tracing-subscriber = {version ="0.3", features = ["env-filter"]}
|
tracing-subscriber = {version ="0.3", features = ["env-filter"]}
|
||||||
|
|
||||||
glam = { version = "0.33", features = ["bytemuck"] }
|
glam = {version = "0.29.0", features = ["bytemuck"]}
|
||||||
rand = "0.10"
|
rand = "0.9"
|
||||||
bitflags = "2.6"
|
bitflags = "2.6"
|
||||||
thread_local = "1.1.8"
|
thread_local = "1.1.8"
|
||||||
|
|
||||||
ash = "0.38.0"
|
ash = "0.38.0"
|
||||||
ash-formats = { git = "https://github.com/janis-bhm/ash-formats.git", version = "0.1.0" }
|
|
||||||
ash-window = "0.13.0"
|
ash-window = "0.13.0"
|
||||||
# vk-mem = "0.5.0"
|
vk-mem = "0.5.0"
|
||||||
gpu-allocator = { git = "https://github.com/janis-bhm/gpu-allocator", branch = "main" }
|
gpu-allocator = { git = "https://github.com/janis-bhm/gpu-allocator", branch = "main" }
|
||||||
rectangle-pack = "0.4.2"
|
rectangle-pack = "0.4.2"
|
||||||
# vk-sync = "0.1.6"
|
vk-sync = "0.1.6"
|
||||||
|
|
||||||
arrayvec = "0.7.6"
|
arrayvec = "0.7.6"
|
||||||
tinyvec = "1.8"
|
tinyvec = "1.8"
|
||||||
indexmap = "2"
|
indexmap = "2"
|
||||||
petgraph = "0.8"
|
petgraph = "0.7"
|
||||||
itertools = "0.14.0"
|
itertools = "0.14.0"
|
||||||
ahash = "0.8"
|
ahash = "0.8"
|
||||||
|
|
||||||
|
|
@ -58,10 +57,10 @@ md-5 = "0.11.0"
|
||||||
|
|
||||||
parking_lot = "0.12.3"
|
parking_lot = "0.12.3"
|
||||||
|
|
||||||
# tokio = "1.42"
|
tokio = "1.42"
|
||||||
# futures = "0.3"
|
futures = "0.3"
|
||||||
smol = "2.0"
|
smol = "2.0"
|
||||||
# rayon = "1.10"
|
rayon = "1.10"
|
||||||
|
|
||||||
winit = {version = "0.30.5", features = ["rwh_06"]}
|
winit = {version = "0.30.5", features = ["rwh_06"]}
|
||||||
raw-window-handle = "0.6"
|
raw-window-handle = "0.6"
|
||||||
|
|
@ -69,22 +68,22 @@ raw-window-handle = "0.6"
|
||||||
egui = "0.32"
|
egui = "0.32"
|
||||||
egui_winit_platform = "0.27"
|
egui_winit_platform = "0.27"
|
||||||
|
|
||||||
bevy = { path = "/var/code/bevy-engine/bevy" }
|
bevy = { version = "0.19.0-dev", git = "https://github.com/bevyengine/bevy" }
|
||||||
bevy_app = { path = "/var/code/bevy-engine/bevy/crates/bevy_app" }
|
bevy_app = { version = "0.19.0-dev", git = "https://github.com/bevyengine/bevy" }
|
||||||
bevy_asset = { path = "/var/code/bevy-engine/bevy/crates/bevy_asset" }
|
bevy_asset = { version = "0.19.0-dev", git = "https://github.com/bevyengine/bevy" }
|
||||||
bevy_derive = { path = "/var/code/bevy-engine/bevy/crates/bevy_derive" }
|
bevy_derive = { version = "0.19.0-dev", git = "https://github.com/bevyengine/bevy" }
|
||||||
bevy_ecs = { path = "/var/code/bevy-engine/bevy/crates/bevy_ecs", features = ["multi_threaded", "trace"]}
|
bevy_ecs = { version = "0.19.0-dev", git = "https://github.com/bevyengine/bevy", features = ["multi_threaded", "trace"]}
|
||||||
# bevy_hierarchy = { path = "/var/code/bevy-engine/bevy/crates/bevy_hierarchy" }
|
bevy_hierarchy = { version = "0.19.0-dev", git = "https://github.com/bevyengine/bevy" }
|
||||||
bevy_log = { path = "/var/code/bevy-engine/bevy/crates/bevy_log" }
|
bevy_log = { version = "0.19.0-dev", git = "https://github.com/bevyengine/bevy" }
|
||||||
# bevy_math = { path = "/var/code/bevy-engine/bevy/crates/bevy_math" }
|
bevy_math = { version = "0.19.0-dev", git = "https://github.com/bevyengine/bevy" }
|
||||||
bevy_platform = { path = "/var/code/bevy-engine/bevy/crates/bevy_platform" }
|
bevy_platform = { version = "0.19.0-dev", git = "https://github.com/bevyengine/bevy" }
|
||||||
bevy_reflect = { path = "/var/code/bevy-engine/bevy/crates/bevy_reflect" }
|
bevy_reflect = { version = "0.19.0-dev", git = "https://github.com/bevyengine/bevy" }
|
||||||
bevy_tasks = { path = "/var/code/bevy-engine/bevy/crates/bevy_tasks" }
|
bevy_tasks = { version = "0.19.0-dev", git = "https://github.com/bevyengine/bevy" }
|
||||||
bevy_time = { path = "/var/code/bevy-engine/bevy/crates/bevy_time" }
|
bevy_time = { version = "0.19.0-dev", git = "https://github.com/bevyengine/bevy" }
|
||||||
# bevy_transform = { path = "/var/code/bevy-engine/bevy/crates/bevy_transform" }
|
bevy_transform = { version = "0.19.0-dev", git = "https://github.com/bevyengine/bevy" }
|
||||||
bevy_utils = { path = "/var/code/bevy-engine/bevy/crates/bevy_utils" }
|
bevy_utils = { version = "0.19.0-dev", git = "https://github.com/bevyengine/bevy" }
|
||||||
bevy_window = { path = "/var/code/bevy-engine/bevy/crates/bevy_window" }
|
bevy_window = { version = "0.19.0-dev", git = "https://github.com/bevyengine/bevy" }
|
||||||
# bevy_winit = { path = "/var/code/bevy-engine/bevy/crates/bevy_winit" }
|
bevy_winit = { version = "0.19.0-dev", git = "https://github.com/bevyengine/bevy" }
|
||||||
|
|
||||||
[[example]]
|
[[example]]
|
||||||
name = "bevy_integration"
|
name = "bevy_integration"
|
||||||
|
|
|
||||||
2
assets/fonts/.gitignore
vendored
2
assets/fonts/.gitignore
vendored
|
|
@ -1,3 +1 @@
|
||||||
*.ttf
|
*.ttf
|
||||||
!Roboto/Roboto-VariableFont_wdth,wght.ttf
|
|
||||||
!Noto_Sans_SC/NotoSansSC-VariableFont_wght.ttf
|
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,3 @@ for filename in "${!FONTS[@]}"; do
|
||||||
echo "Fetching $filename from $url"
|
echo "Fetching $filename from $url"
|
||||||
curl -L "$url" -o "$filename"
|
curl -L "$url" -o "$filename"
|
||||||
done
|
done
|
||||||
|
|
||||||
mkdir -p Roboto Noto_Sans_SC
|
|
||||||
cp Roboto.ttf Roboto/Roboto-VariableFont_wdth,wght.ttf
|
|
||||||
cp NotoSansSC.ttf Noto_Sans_SC/NotoSansSC-VariableFont_wght.ttf
|
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,10 @@ use crate::extract_plugin::MainWorld;
|
||||||
use bevy_ecs::{
|
use bevy_ecs::{
|
||||||
change_detection::Tick,
|
change_detection::Tick,
|
||||||
prelude::*,
|
prelude::*,
|
||||||
|
query::FilteredAccessSet,
|
||||||
system::{
|
system::{
|
||||||
ReadOnlySystemParam, SystemAccess, SystemMeta, SystemParam, SystemParamAccessConflict,
|
ReadOnlySystemParam, SystemMeta, SystemParam, SystemParamItem, SystemParamValidationError,
|
||||||
SystemParamItem, SystemParamValidationError, SystemState,
|
SystemState,
|
||||||
},
|
},
|
||||||
world::unsafe_world_cell::UnsafeWorldCell,
|
world::unsafe_world_cell::UnsafeWorldCell,
|
||||||
};
|
};
|
||||||
|
|
@ -82,9 +83,15 @@ where
|
||||||
fn init_access(
|
fn init_access(
|
||||||
state: &Self::State,
|
state: &Self::State,
|
||||||
system_meta: &mut SystemMeta,
|
system_meta: &mut SystemMeta,
|
||||||
system_access: &mut SystemAccess,
|
component_access_set: &mut FilteredAccessSet,
|
||||||
) -> Result<(), SystemParamAccessConflict> {
|
world: &mut World,
|
||||||
Res::<MainWorld>::init_access(&state.main_world_state, system_meta, system_access)
|
) {
|
||||||
|
Res::<MainWorld>::init_access(
|
||||||
|
&state.main_world_state,
|
||||||
|
system_meta,
|
||||||
|
component_access_set,
|
||||||
|
world,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
||||||
|
|
@ -101,50 +101,7 @@ impl Plugin for RenderPlugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init_vulkan(app: &mut App) -> Option<()> {
|
fn init_vulkan(app: &mut App) -> Option<()> {
|
||||||
let instance_desc = renderer::instance::InstanceDesc {
|
let device = renderer::device::Device::new_from_default_desc(None, &[]).ok()?;
|
||||||
app_name: Some("Vidya"),
|
|
||||||
layers: &[],
|
|
||||||
layer_settings: &[],
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
let instance = renderer::instance::Instance::new(&instance_desc).ok()?;
|
|
||||||
|
|
||||||
let required_extensions = [
|
|
||||||
renderer::make_extension!(renderer::ash::ext::mesh_shader),
|
|
||||||
renderer::make_extension!(renderer::ash::ext::index_type_uint8),
|
|
||||||
renderer::make_extension!(renderer::ash::khr::spirv_1_4),
|
|
||||||
];
|
|
||||||
let features = renderer::PhysicalDeviceFeatures {
|
|
||||||
core: renderer::ash::vk::PhysicalDeviceFeatures::default()
|
|
||||||
.sampler_anisotropy(true)
|
|
||||||
.fill_mode_non_solid(true)
|
|
||||||
.multi_draw_indirect(true),
|
|
||||||
core11: renderer::ash::vk::PhysicalDeviceVulkan11Features::default()
|
|
||||||
.shader_draw_parameters(true),
|
|
||||||
core12: renderer::ash::vk::PhysicalDeviceVulkan12Features::default()
|
|
||||||
.shader_int8(true)
|
|
||||||
.runtime_descriptor_array(true)
|
|
||||||
.descriptor_binding_partially_bound(true)
|
|
||||||
.shader_sampled_image_array_non_uniform_indexing(true)
|
|
||||||
.descriptor_binding_sampled_image_update_after_bind(true)
|
|
||||||
.storage_buffer8_bit_access(true),
|
|
||||||
core13: renderer::ash::vk::PhysicalDeviceVulkan13Features::default()
|
|
||||||
.synchronization2(true)
|
|
||||||
.dynamic_rendering(true)
|
|
||||||
.maintenance4(true),
|
|
||||||
mesh_shader: Some(
|
|
||||||
renderer::ash::vk::PhysicalDeviceMeshShaderFeaturesEXT::default()
|
|
||||||
.mesh_shader(true)
|
|
||||||
.task_shader(true),
|
|
||||||
),
|
|
||||||
};
|
|
||||||
|
|
||||||
let adapter = instance
|
|
||||||
.choose_adapter_default(None, &required_extensions, Some(&features))
|
|
||||||
.ok()?;
|
|
||||||
let device = adapter
|
|
||||||
.create_logical_device(&instance, &required_extensions, features, None)
|
|
||||||
.ok()?;
|
|
||||||
|
|
||||||
let device = RenderDevice { device };
|
let device = RenderDevice { device };
|
||||||
app.insert_resource(device.clone());
|
app.insert_resource(device.clone());
|
||||||
|
|
|
||||||
|
|
@ -93,12 +93,12 @@ impl Plugin for SyncWorldPlugin {
|
||||||
fn build(&self, app: &mut bevy_app::App) {
|
fn build(&self, app: &mut bevy_app::App) {
|
||||||
app.init_resource::<PendingSyncEntity>();
|
app.init_resource::<PendingSyncEntity>();
|
||||||
app.add_observer(
|
app.add_observer(
|
||||||
|add: On<Add<SyncToRenderWorld>>, mut pending: ResMut<PendingSyncEntity>| {
|
|add: On<Add, SyncToRenderWorld>, mut pending: ResMut<PendingSyncEntity>| {
|
||||||
pending.push(EntityRecord::Added(add.entity));
|
pending.push(EntityRecord::Added(add.entity));
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
app.add_observer(
|
app.add_observer(
|
||||||
|remove: On<Remove<SyncToRenderWorld>>,
|
|remove: On<Remove, SyncToRenderWorld>,
|
||||||
mut pending: ResMut<PendingSyncEntity>,
|
mut pending: ResMut<PendingSyncEntity>,
|
||||||
query: Query<&RenderEntity>| {
|
query: Query<&RenderEntity>| {
|
||||||
if let Ok(e) = query.get(remove.entity) {
|
if let Ok(e) = query.get(remove.entity) {
|
||||||
|
|
@ -278,15 +278,15 @@ mod render_entities_world_query_impls {
|
||||||
use super::{MainEntity, RenderEntity};
|
use super::{MainEntity, RenderEntity};
|
||||||
|
|
||||||
use bevy_ecs::{
|
use bevy_ecs::{
|
||||||
archetype::{Archetype, ArchetypeId},
|
archetype::Archetype,
|
||||||
change_detection::Tick,
|
change_detection::Tick,
|
||||||
component::{ComponentId, Components},
|
component::{ComponentId, Components},
|
||||||
entity::Entity,
|
entity::Entity,
|
||||||
query::{
|
query::{
|
||||||
ArchetypeQueryData, FilteredAccess, FilteredAccessSet, IterQueryData, QueryData,
|
ArchetypeQueryData, FilteredAccess, IterQueryData, QueryData, ReadOnlyQueryData,
|
||||||
ReadOnlyQueryData, ReleaseStateQueryData, SingleEntityQueryData, WorldQuery,
|
ReleaseStateQueryData, SingleEntityQueryData, WorldQuery,
|
||||||
},
|
},
|
||||||
storage::{Table, TableId, TableRow},
|
storage::{Table, TableRow},
|
||||||
world::{World, unsafe_world_cell::UnsafeWorldCell},
|
world::{World, unsafe_world_cell::UnsafeWorldCell},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -305,12 +305,14 @@ mod render_entities_world_query_impls {
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn init_fetch<'w, 's>(
|
unsafe fn init_fetch<'w, 's>(
|
||||||
world: UnsafeWorldCell<'w>,
|
world: UnsafeWorldCell<'w>,
|
||||||
state: &'s Self::State,
|
component_id: &'s ComponentId,
|
||||||
last_run: Tick,
|
last_run: Tick,
|
||||||
this_run: Tick,
|
this_run: Tick,
|
||||||
) -> Self::Fetch<'w> {
|
) -> Self::Fetch<'w> {
|
||||||
// SAFETY: defers to the `&T` implementation, with T set to `RenderEntity`.
|
// SAFETY: defers to the `&T` implementation, with T set to `RenderEntity`.
|
||||||
unsafe { <&RenderEntity as WorldQuery>::init_fetch(world, state, last_run, this_run) }
|
unsafe {
|
||||||
|
<&RenderEntity as WorldQuery>::init_fetch(world, component_id, last_run, this_run)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const IS_DENSE: bool = <&'static RenderEntity as WorldQuery>::IS_DENSE;
|
const IS_DENSE: bool = <&'static RenderEntity as WorldQuery>::IS_DENSE;
|
||||||
|
|
@ -318,45 +320,28 @@ mod render_entities_world_query_impls {
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn set_archetype<'w, 's>(
|
unsafe fn set_archetype<'w, 's>(
|
||||||
fetch: &mut Self::Fetch<'w>,
|
fetch: &mut Self::Fetch<'w>,
|
||||||
state: &'s Self::State,
|
component_id: &'s ComponentId,
|
||||||
archetype_id: ArchetypeId,
|
|
||||||
archetype: &'w Archetype,
|
archetype: &'w Archetype,
|
||||||
table_id: TableId,
|
|
||||||
table: &'w Table,
|
table: &'w Table,
|
||||||
) {
|
) {
|
||||||
// SAFETY: defers to the `&T` implementation, with T set to `RenderEntity`.
|
// SAFETY: defers to the `&T` implementation, with T set to `RenderEntity`.
|
||||||
unsafe {
|
unsafe {
|
||||||
<&RenderEntity as WorldQuery>::set_archetype(
|
<&RenderEntity as WorldQuery>::set_archetype(fetch, component_id, archetype, table);
|
||||||
fetch,
|
|
||||||
state,
|
|
||||||
archetype_id,
|
|
||||||
archetype,
|
|
||||||
table_id,
|
|
||||||
table,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn set_table<'w, 's>(
|
unsafe fn set_table<'w, 's>(
|
||||||
fetch: &mut Self::Fetch<'w>,
|
fetch: &mut Self::Fetch<'w>,
|
||||||
state: &'s Self::State,
|
&component_id: &'s ComponentId,
|
||||||
table_id: TableId,
|
|
||||||
table: &'w Table,
|
table: &'w Table,
|
||||||
) {
|
) {
|
||||||
// SAFETY: defers to the `&T` implementation, with T set to `RenderEntity`.
|
// SAFETY: defers to the `&T` implementation, with T set to `RenderEntity`.
|
||||||
unsafe { <&RenderEntity as WorldQuery>::set_table(fetch, state, table_id, table) }
|
unsafe { <&RenderEntity as WorldQuery>::set_table(fetch, &component_id, table) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_component_access(state: &Self::State, access: &mut FilteredAccess) {
|
fn update_component_access(&component_id: &ComponentId, access: &mut FilteredAccess) {
|
||||||
<&RenderEntity as WorldQuery>::update_component_access(state, access);
|
<&RenderEntity as WorldQuery>::update_component_access(&component_id, access);
|
||||||
}
|
|
||||||
|
|
||||||
fn init_nested_access(
|
|
||||||
_state: &Self::State,
|
|
||||||
_component_access_set: &mut FilteredAccessSet,
|
|
||||||
) -> Result<(), FilteredAccessSet> {
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init_state(world: &mut World) -> ComponentId {
|
fn init_state(world: &mut World) -> ComponentId {
|
||||||
|
|
@ -368,13 +353,11 @@ mod render_entities_world_query_impls {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn matches_component_set(
|
fn matches_component_set(
|
||||||
state: &Self::State,
|
&state: &ComponentId,
|
||||||
set_contains_id: &impl Fn(ComponentId) -> bool,
|
set_contains_id: &impl Fn(ComponentId) -> bool,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
<&RenderEntity as WorldQuery>::matches_component_set(state, set_contains_id)
|
<&RenderEntity as WorldQuery>::matches_component_set(&state, set_contains_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_archetypes(_state: &mut Self::State, _world: UnsafeWorldCell) {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SAFETY: Component access of Self::ReadOnly is a subset of Self.
|
// SAFETY: Component access of Self::ReadOnly is a subset of Self.
|
||||||
|
|
@ -442,12 +425,14 @@ mod render_entities_world_query_impls {
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn init_fetch<'w, 's>(
|
unsafe fn init_fetch<'w, 's>(
|
||||||
world: UnsafeWorldCell<'w>,
|
world: UnsafeWorldCell<'w>,
|
||||||
state: &'s Self::State,
|
component_id: &'s ComponentId,
|
||||||
last_run: Tick,
|
last_run: Tick,
|
||||||
this_run: Tick,
|
this_run: Tick,
|
||||||
) -> Self::Fetch<'w> {
|
) -> Self::Fetch<'w> {
|
||||||
// SAFETY: defers to the `&T` implementation, with T set to `MainEntity`.
|
// SAFETY: defers to the `&T` implementation, with T set to `MainEntity`.
|
||||||
unsafe { <&MainEntity as WorldQuery>::init_fetch(world, state, last_run, this_run) }
|
unsafe {
|
||||||
|
<&MainEntity as WorldQuery>::init_fetch(world, component_id, last_run, this_run)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const IS_DENSE: bool = <&'static MainEntity as WorldQuery>::IS_DENSE;
|
const IS_DENSE: bool = <&'static MainEntity as WorldQuery>::IS_DENSE;
|
||||||
|
|
@ -455,45 +440,28 @@ mod render_entities_world_query_impls {
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn set_archetype<'w, 's>(
|
unsafe fn set_archetype<'w, 's>(
|
||||||
fetch: &mut Self::Fetch<'w>,
|
fetch: &mut Self::Fetch<'w>,
|
||||||
state: &'s Self::State,
|
component_id: &ComponentId,
|
||||||
archetype_id: ArchetypeId,
|
|
||||||
archetype: &'w Archetype,
|
archetype: &'w Archetype,
|
||||||
table_id: TableId,
|
|
||||||
table: &'w Table,
|
table: &'w Table,
|
||||||
) {
|
) {
|
||||||
// SAFETY: defers to the `&T` implementation, with T set to `MainEntity`.
|
// SAFETY: defers to the `&T` implementation, with T set to `MainEntity`.
|
||||||
unsafe {
|
unsafe {
|
||||||
<&MainEntity as WorldQuery>::set_archetype(
|
<&MainEntity as WorldQuery>::set_archetype(fetch, component_id, archetype, table);
|
||||||
fetch,
|
|
||||||
state,
|
|
||||||
archetype_id,
|
|
||||||
archetype,
|
|
||||||
table_id,
|
|
||||||
table,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn set_table<'w, 's>(
|
unsafe fn set_table<'w, 's>(
|
||||||
fetch: &mut Self::Fetch<'w>,
|
fetch: &mut Self::Fetch<'w>,
|
||||||
state: &'s Self::State,
|
&component_id: &'s ComponentId,
|
||||||
table_id: TableId,
|
|
||||||
table: &'w Table,
|
table: &'w Table,
|
||||||
) {
|
) {
|
||||||
// SAFETY: defers to the `&T` implementation, with T set to `MainEntity`.
|
// SAFETY: defers to the `&T` implementation, with T set to `MainEntity`.
|
||||||
unsafe { <&MainEntity as WorldQuery>::set_table(fetch, state, table_id, table) }
|
unsafe { <&MainEntity as WorldQuery>::set_table(fetch, &component_id, table) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_component_access(state: &Self::State, access: &mut FilteredAccess) {
|
fn update_component_access(&component_id: &ComponentId, access: &mut FilteredAccess) {
|
||||||
<&MainEntity as WorldQuery>::update_component_access(state, access);
|
<&MainEntity as WorldQuery>::update_component_access(&component_id, access);
|
||||||
}
|
|
||||||
|
|
||||||
fn init_nested_access(
|
|
||||||
_state: &Self::State,
|
|
||||||
_component_access_set: &mut FilteredAccessSet,
|
|
||||||
) -> Result<(), FilteredAccessSet> {
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init_state(world: &mut World) -> ComponentId {
|
fn init_state(world: &mut World) -> ComponentId {
|
||||||
|
|
@ -505,13 +473,11 @@ mod render_entities_world_query_impls {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn matches_component_set(
|
fn matches_component_set(
|
||||||
state: &Self::State,
|
&state: &ComponentId,
|
||||||
set_contains_id: &impl Fn(ComponentId) -> bool,
|
set_contains_id: &impl Fn(ComponentId) -> bool,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
<&MainEntity as WorldQuery>::matches_component_set(state, set_contains_id)
|
<&MainEntity as WorldQuery>::matches_component_set(&state, set_contains_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_archetypes(_state: &mut Self::State, _world: UnsafeWorldCell) {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SAFETY: Component access of Self::ReadOnly is a subset of Self.
|
// SAFETY: Component access of Self::ReadOnly is a subset of Self.
|
||||||
|
|
@ -592,12 +558,12 @@ mod tests {
|
||||||
main_world.init_resource::<PendingSyncEntity>();
|
main_world.init_resource::<PendingSyncEntity>();
|
||||||
|
|
||||||
main_world.add_observer(
|
main_world.add_observer(
|
||||||
|add: On<Add<SyncToRenderWorld>>, mut pending: ResMut<PendingSyncEntity>| {
|
|add: On<Add, SyncToRenderWorld>, mut pending: ResMut<PendingSyncEntity>| {
|
||||||
pending.push(EntityRecord::Added(add.entity));
|
pending.push(EntityRecord::Added(add.entity));
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
main_world.add_observer(
|
main_world.add_observer(
|
||||||
|remove: On<Remove<SyncToRenderWorld>>,
|
|remove: On<Remove, SyncToRenderWorld>,
|
||||||
mut pending: ResMut<PendingSyncEntity>,
|
mut pending: ResMut<PendingSyncEntity>,
|
||||||
query: Query<&RenderEntity>| {
|
query: Query<&RenderEntity>| {
|
||||||
if let Ok(e) = query.get(remove.entity) {
|
if let Ok(e) = query.get(remove.entity) {
|
||||||
|
|
|
||||||
|
|
@ -5,10 +5,7 @@ use std::{
|
||||||
|
|
||||||
use bevy_ecs::{entity::EntityHashMap, prelude::*};
|
use bevy_ecs::{entity::EntityHashMap, prelude::*};
|
||||||
use bevy_window::{PrimaryWindow, RawHandleWrapper, Window, WindowClosing};
|
use bevy_window::{PrimaryWindow, RawHandleWrapper, Window, WindowClosing};
|
||||||
use renderer::{
|
use renderer::{ash::vk, swapchain::WindowSurface};
|
||||||
ash::vk,
|
|
||||||
swapchain::{Surface, SwapchainConfiguration},
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::{RenderDevice, extract_param::Extract};
|
use crate::{RenderDevice, extract_param::Extract};
|
||||||
|
|
||||||
|
|
@ -42,7 +39,7 @@ impl DerefMut for ExtractedWindows {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default, Resource)]
|
||||||
pub struct Surfaces {
|
pub struct Surfaces {
|
||||||
surfaces: EntityHashMap<SurfaceData>,
|
surfaces: EntityHashMap<SurfaceData>,
|
||||||
configured: HashSet<Entity>,
|
configured: HashSet<Entity>,
|
||||||
|
|
@ -60,11 +57,11 @@ impl Surfaces {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct SurfaceData {
|
pub struct SurfaceData {
|
||||||
pub surface: Surface,
|
pub surface: WindowSurface,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Deref for SurfaceData {
|
impl Deref for SurfaceData {
|
||||||
type Target = Surface;
|
type Target = WindowSurface;
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
&self.surface
|
&self.surface
|
||||||
|
|
@ -77,7 +74,7 @@ pub(crate) fn extract_windows(
|
||||||
mut closing: Extract<MessageReader<WindowClosing>>,
|
mut closing: Extract<MessageReader<WindowClosing>>,
|
||||||
windows: Extract<Query<(Entity, &RawHandleWrapper, &Window, Option<&PrimaryWindow>)>>,
|
windows: Extract<Query<(Entity, &RawHandleWrapper, &Window, Option<&PrimaryWindow>)>>,
|
||||||
mut removed: Extract<RemovedComponents<RawHandleWrapper>>,
|
mut removed: Extract<RemovedComponents<RawHandleWrapper>>,
|
||||||
mut surfaces: NonSendMut<Surfaces>,
|
mut surfaces: ResMut<Surfaces>,
|
||||||
) {
|
) {
|
||||||
for (entity, handle, window, primary) in windows.iter() {
|
for (entity, handle, window, primary) in windows.iter() {
|
||||||
if primary.is_some() {
|
if primary.is_some() {
|
||||||
|
|
@ -119,7 +116,7 @@ pub(crate) fn extract_windows(
|
||||||
|
|
||||||
pub(crate) fn need_surface_configuration(
|
pub(crate) fn need_surface_configuration(
|
||||||
windows: Res<ExtractedWindows>,
|
windows: Res<ExtractedWindows>,
|
||||||
surfaces: NonSend<Surfaces>,
|
surfaces: Res<Surfaces>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
windows
|
windows
|
||||||
.windows
|
.windows
|
||||||
|
|
@ -129,7 +126,7 @@ pub(crate) fn need_surface_configuration(
|
||||||
|
|
||||||
pub(crate) fn configure_surfaces(
|
pub(crate) fn configure_surfaces(
|
||||||
windows: Res<ExtractedWindows>,
|
windows: Res<ExtractedWindows>,
|
||||||
mut surfaces: NonSendMut<Surfaces>,
|
mut surfaces: ResMut<Surfaces>,
|
||||||
device: Res<RenderDevice>,
|
device: Res<RenderDevice>,
|
||||||
) {
|
) {
|
||||||
for window in windows.windows.values() {
|
for window in windows.windows.values() {
|
||||||
|
|
@ -139,49 +136,27 @@ pub(crate) fn configure_surfaces(
|
||||||
window.handle.get_window_handle(),
|
window.handle.get_window_handle(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let surface = unsafe {
|
let surface = WindowSurface::new(
|
||||||
Surface::new_from_raw_window_handle(
|
(**device).clone(),
|
||||||
device.instance(),
|
vk::Extent2D {
|
||||||
display_handle,
|
|
||||||
window_handle,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
.expect("Failed to create window surface");
|
|
||||||
surface
|
|
||||||
.configure(
|
|
||||||
&**device,
|
|
||||||
SwapchainConfiguration {
|
|
||||||
extent: vk::Extent2D {
|
|
||||||
width: window.physical_width,
|
width: window.physical_width,
|
||||||
height: window.physical_height,
|
height: window.physical_height,
|
||||||
},
|
},
|
||||||
..Default::default()
|
window_handle,
|
||||||
},
|
display_handle,
|
||||||
)
|
)
|
||||||
.expect("Failed to configure window surface");
|
.expect("Failed to create window surface");
|
||||||
|
|
||||||
SurfaceData { surface }
|
SurfaceData { surface }
|
||||||
});
|
});
|
||||||
|
|
||||||
if window.size_changed {
|
if window.size_changed {
|
||||||
let config = surface
|
|
||||||
.surface
|
|
||||||
.swapchain()
|
|
||||||
.as_ref()
|
|
||||||
.map(|swapchain| swapchain.config().clone())
|
|
||||||
.unwrap_or_default();
|
|
||||||
surface
|
surface
|
||||||
.surface
|
.surface
|
||||||
.configure(
|
.recreate_with(Some(vk::Extent2D {
|
||||||
&**device,
|
|
||||||
SwapchainConfiguration {
|
|
||||||
extent: vk::Extent2D {
|
|
||||||
width: window.physical_width,
|
width: window.physical_width,
|
||||||
height: window.physical_height,
|
height: window.physical_height,
|
||||||
},
|
}))
|
||||||
..config
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.expect("Failed to recreate surface");
|
.expect("Failed to recreate surface");
|
||||||
}
|
}
|
||||||
surfaces.configured.insert(window.entity);
|
surfaces.configured.insert(window.entity);
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
use rand::{RngExt, SeedableRng};
|
use rand::{Rng, SeedableRng};
|
||||||
use renderer::{
|
use renderer::{
|
||||||
Renderer2, render_graph,
|
Renderer2, render_graph,
|
||||||
swapchain::{Surface, SwapchainConfiguration},
|
swapchain::{Surface, SwapchainConfiguration},
|
||||||
|
|
@ -106,8 +106,7 @@ impl WinitState {
|
||||||
|
|
||||||
use renderer::ash::vk::Handle;
|
use renderer::ash::vk::Handle;
|
||||||
let [r, g, b]: [f32; 3] =
|
let [r, g, b]: [f32; 3] =
|
||||||
rand::prelude::StdRng::seed_from_u64(window.surface.raw().as_raw())
|
rand::prelude::StdRng::seed_from_u64(window.surface.raw().as_raw()).random();
|
||||||
.random::<[f32; 3]>();
|
|
||||||
render_graph::clear_pass(rg, renderer::util::Rgba([r, g, b, 1.0]), framebuffer);
|
render_graph::clear_pass(rg, renderer::util::Rgba([r, g, b, 1.0]), framebuffer);
|
||||||
egui_pre_pass(
|
egui_pre_pass(
|
||||||
&dev,
|
&dev,
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ indexmap = { workspace = true }
|
||||||
petgraph = { workspace = true }
|
petgraph = { workspace = true }
|
||||||
itertools = { workspace = true }
|
itertools = { workspace = true }
|
||||||
ahash = { workspace = true }
|
ahash = { workspace = true }
|
||||||
# rand = { workspace = true }
|
rand = { workspace = true }
|
||||||
parking_lot = { workspace = true }
|
parking_lot = { workspace = true }
|
||||||
glam = { workspace = true }
|
glam = { workspace = true }
|
||||||
bitflags = { workspace = true }
|
bitflags = { workspace = true }
|
||||||
|
|
@ -21,9 +21,8 @@ anyhow = { workspace = true }
|
||||||
tracing = { workspace = true }
|
tracing = { workspace = true }
|
||||||
|
|
||||||
ash = { workspace = true }
|
ash = { workspace = true }
|
||||||
ash-formats = { workspace = true }
|
|
||||||
ash-window = { workspace = true }
|
ash-window = { workspace = true }
|
||||||
# vk-mem = { workspace = true }
|
vk-mem = { workspace = true }
|
||||||
gpu-allocator = { workspace = true }
|
gpu-allocator = { workspace = true }
|
||||||
rectangle-pack = { workspace = true }
|
rectangle-pack = { workspace = true }
|
||||||
|
|
||||||
|
|
@ -31,13 +30,13 @@ md-5 = { workspace = true }
|
||||||
|
|
||||||
raw-window-handle = { workspace = true }
|
raw-window-handle = { workspace = true }
|
||||||
egui = { workspace = true , features = ["bytemuck"]}
|
egui = { workspace = true , features = ["bytemuck"]}
|
||||||
# egui_winit_platform = { workspace = true }
|
egui_winit_platform = { workspace = true }
|
||||||
|
|
||||||
#futures = { workspace = true }
|
futures = { workspace = true }
|
||||||
smol = { workspace = true }
|
smol = { workspace = true }
|
||||||
# tokio = {workspace = true, features = ["rt", "sync"]}
|
# tokio = {workspace = true, features = ["rt", "sync"]}
|
||||||
|
|
||||||
# bevy_tasks = { workspace = true }
|
bevy_tasks = { workspace = true }
|
||||||
|
|
||||||
derive_more = { workspace = true , features = ["debug"] }
|
derive_more = { workspace = true , features = ["debug"] }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,12 +6,11 @@ use crate::{
|
||||||
images::{Image, QueueOwnership},
|
images::{Image, QueueOwnership},
|
||||||
pipeline::{Pipeline, PipelineLayout},
|
pipeline::{Pipeline, PipelineLayout},
|
||||||
sync::{self, FenceFuture},
|
sync::{self, FenceFuture},
|
||||||
util::{self, MutexExt},
|
util::{self, FormatExt, MutexExt},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{Device, queue::Queue};
|
use super::{Device, queue::Queue};
|
||||||
use ash::{prelude::*, vk};
|
use ash::{prelude::*, vk};
|
||||||
use ash_formats::FormatHelpers as _;
|
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
@ -476,7 +475,17 @@ pub mod traits {
|
||||||
subresources: &[vk::ImageSubresourceRange],
|
subresources: &[vk::ImageSubresourceRange],
|
||||||
) {
|
) {
|
||||||
// assert_eq!(self.state(), CommandBufferState::Recording);
|
// assert_eq!(self.state(), CommandBufferState::Recording);
|
||||||
let clear_colors = format.clear_value(color.into_f32());
|
let clear_colors = match format.get_component_kind() {
|
||||||
|
crate::util::FormatComponentKind::Float => vk::ClearColorValue {
|
||||||
|
float32: color.into_f32(),
|
||||||
|
},
|
||||||
|
crate::util::FormatComponentKind::UInt => vk::ClearColorValue {
|
||||||
|
uint32: color.into_u32(),
|
||||||
|
},
|
||||||
|
crate::util::FormatComponentKind::SInt => vk::ClearColorValue {
|
||||||
|
int32: color.into_i32(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
self.device().dev().cmd_clear_color_image(
|
self.device().dev().cmd_clear_color_image(
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ use std::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use ash::vk;
|
use ash::vk;
|
||||||
use ash_formats::FormatHelpers as _;
|
|
||||||
use gpu_allocator::MemoryLocation;
|
use gpu_allocator::MemoryLocation;
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
|
|
||||||
|
|
@ -134,7 +133,7 @@ pub fn egui_pre_pass(
|
||||||
dev.clone(),
|
dev.clone(),
|
||||||
BufferDesc {
|
BufferDesc {
|
||||||
name: Some("egui-prepass-staging-buffer".into()),
|
name: Some("egui-prepass-staging-buffer".into()),
|
||||||
size: vk::Format::R8G8B8A8_UNORM.layer_size([extent.0, extent.1, 1]),
|
size: (extent.0 * extent.1 * 4) as u64, // RGBA8
|
||||||
usage: vk::BufferUsageFlags::TRANSFER_SRC,
|
usage: vk::BufferUsageFlags::TRANSFER_SRC,
|
||||||
queue_families: device::QueueFlags::empty(),
|
queue_families: device::QueueFlags::empty(),
|
||||||
mem_location: MemoryLocation::CpuToGpu,
|
mem_location: MemoryLocation::CpuToGpu,
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,6 @@ use crate::{
|
||||||
|
|
||||||
use super::Device;
|
use super::Device;
|
||||||
use ash::vk::{self, Handle};
|
use ash::vk::{self, Handle};
|
||||||
use ash_formats::FormatExt;
|
|
||||||
use gpu_allocator::vulkan::{AllocationCreateDesc, AllocationScheme};
|
use gpu_allocator::vulkan::{AllocationCreateDesc, AllocationScheme};
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
|
|
||||||
|
|
@ -511,7 +510,8 @@ fn validate_image_view_format(image: &ImageDesc, view_format: vk::Format) -> boo
|
||||||
let mutable = image.flags.contains(vk::ImageCreateFlags::MUTABLE_FORMAT);
|
let mutable = image.flags.contains(vk::ImageCreateFlags::MUTABLE_FORMAT);
|
||||||
|
|
||||||
if mutable {
|
if mutable {
|
||||||
image.format == view_format || image.format.format_class() == view_format.format_class()
|
image.format == view_format
|
||||||
|
|| FormatClass::from(image.format) == FormatClass::from(view_format)
|
||||||
} else {
|
} else {
|
||||||
image.format == view_format
|
image.format == view_format
|
||||||
}
|
}
|
||||||
|
|
@ -957,3 +957,500 @@ pub const SUBRESOURCERANGE_COLOR_ALL: vk::ImageSubresourceRange = vk::ImageSubre
|
||||||
base_array_layer: 0,
|
base_array_layer: 0,
|
||||||
layer_count: vk::REMAINING_ARRAY_LAYERS,
|
layer_count: vk::REMAINING_ARRAY_LAYERS,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// copilot generated from spec:
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
|
pub enum FormatClass {
|
||||||
|
Bits8,
|
||||||
|
Bits16,
|
||||||
|
Alpha8,
|
||||||
|
Bits24,
|
||||||
|
Bits32,
|
||||||
|
Bits48,
|
||||||
|
Bits64,
|
||||||
|
Bits96,
|
||||||
|
Bits128,
|
||||||
|
Bits192,
|
||||||
|
Bits256,
|
||||||
|
|
||||||
|
D16,
|
||||||
|
D24,
|
||||||
|
D32,
|
||||||
|
S8,
|
||||||
|
D16S8,
|
||||||
|
D24S8,
|
||||||
|
D32S8,
|
||||||
|
|
||||||
|
Bc1Rgb,
|
||||||
|
Bc1Rgba,
|
||||||
|
Bc2,
|
||||||
|
Bc3,
|
||||||
|
Bc4,
|
||||||
|
Bc5,
|
||||||
|
Bc6h,
|
||||||
|
Bc7,
|
||||||
|
|
||||||
|
Etc2Rgb,
|
||||||
|
Etc2Rgba,
|
||||||
|
Etc2EacRgba,
|
||||||
|
EacR,
|
||||||
|
EacRg,
|
||||||
|
|
||||||
|
Astc4x4,
|
||||||
|
Astc5x4,
|
||||||
|
Astc5x5,
|
||||||
|
Astc6x5,
|
||||||
|
Astc6x6,
|
||||||
|
Astc8x5,
|
||||||
|
Astc8x6,
|
||||||
|
Astc8x8,
|
||||||
|
Astc10x5,
|
||||||
|
Astc10x6,
|
||||||
|
Astc10x8,
|
||||||
|
Astc10x10,
|
||||||
|
Astc12x10,
|
||||||
|
Astc12x12,
|
||||||
|
|
||||||
|
YuvG8B8G8R8_422,
|
||||||
|
YuvB8G8R8G8_422,
|
||||||
|
|
||||||
|
YuvG8B8R8Triplane420,
|
||||||
|
YuvG8B8R8Biplane420,
|
||||||
|
YuvG8B8R8Triplane422,
|
||||||
|
YuvG8B8R8Biplane422,
|
||||||
|
YuvG8B8R8Triplane444,
|
||||||
|
YuvG10X6B10X6R10X6Triplane420,
|
||||||
|
YuvG10X6B10X6R10X6Biplane420,
|
||||||
|
YuvG10X6B10X6R10X6Triplane422,
|
||||||
|
YuvG10X6B10X6R10X6Biplane422,
|
||||||
|
YuvG10X6B10X6R10X6Triplane444,
|
||||||
|
YuvG12X4B12X4R12X4Triplane420,
|
||||||
|
YuvG12X4B12X4R12X4Biplane420,
|
||||||
|
YuvG12X4B12X4R12X4Triplane422,
|
||||||
|
YuvG12X4B12X4R12X4Biplane422,
|
||||||
|
YuvG12X4B12X4R12X4Triplane444,
|
||||||
|
YuvG16B16R16Triplane420,
|
||||||
|
YuvG16B16R16Biplane420,
|
||||||
|
YuvG16B16R16Triplane422,
|
||||||
|
YuvG16B16R16Biplane422,
|
||||||
|
YuvG16B16R16Triplane444,
|
||||||
|
|
||||||
|
YuvG8B8R8Biplane444,
|
||||||
|
YuvG10X6B10X6R10X6Biplane444,
|
||||||
|
YuvG12X4B12X4R12X4Biplane444,
|
||||||
|
YuvG16B16R16Biplane444,
|
||||||
|
|
||||||
|
Bits64R10G10B10A10,
|
||||||
|
Bits64G10B10G10R10_422,
|
||||||
|
Bits64B10G10R10G10_422,
|
||||||
|
Bits64R12G12B12A12,
|
||||||
|
Bits64G12B12G12R12_422,
|
||||||
|
Bits64B12G12R12G12_422,
|
||||||
|
Bits64G16B16G16R16_422,
|
||||||
|
Bits64B16G16R16G16_422,
|
||||||
|
Bits64R14G14B14A14,
|
||||||
|
|
||||||
|
Pvrtc1_2bpp,
|
||||||
|
Pvrtc1_4bpp,
|
||||||
|
Pvrtc2_2bpp,
|
||||||
|
Pvrtc2_4bpp,
|
||||||
|
|
||||||
|
Astc3x3x3,
|
||||||
|
Astc4x3x3,
|
||||||
|
Astc4x4x3,
|
||||||
|
Astc4x4x4,
|
||||||
|
Astc5x4x4,
|
||||||
|
Astc5x5x4,
|
||||||
|
Astc5x5x5,
|
||||||
|
Astc6x5x5,
|
||||||
|
Astc6x6x5,
|
||||||
|
Astc6x6x6,
|
||||||
|
|
||||||
|
YuvG14X2B14X2R14X2Biplane420,
|
||||||
|
YuvG14X2B14X2R14X2Biplane422,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<vk::Format> for FormatClass {
|
||||||
|
fn from(format: vk::Format) -> Self {
|
||||||
|
use vk::Format as F;
|
||||||
|
match format {
|
||||||
|
// 8-bit
|
||||||
|
F::R4G4_UNORM_PACK8
|
||||||
|
| F::R8_UNORM
|
||||||
|
| F::R8_SNORM
|
||||||
|
| F::R8_USCALED
|
||||||
|
| F::R8_SSCALED
|
||||||
|
// | F::R8_BOOL_ARM
|
||||||
|
// | F::R8_SFLOAT_FPENCODING_FLOAT8E4M3_ARM
|
||||||
|
// | F::R8_SFLOAT_FPENCODING_FLOAT8E5M2_ARM
|
||||||
|
| F::R8_UINT
|
||||||
|
| F::R8_SINT
|
||||||
|
| F::R8_SRGB => FormatClass::Bits8,
|
||||||
|
|
||||||
|
// 16-bit
|
||||||
|
F::A1B5G5R5_UNORM_PACK16_KHR
|
||||||
|
| F::R10X6_UNORM_PACK16
|
||||||
|
| F::R12X4_UNORM_PACK16
|
||||||
|
| F::A4R4G4B4_UNORM_PACK16
|
||||||
|
| F::A4B4G4R4_UNORM_PACK16
|
||||||
|
// | F::R10X6_UINT_PACK16_ARM
|
||||||
|
// | F::R12X4_UINT_PACK16_ARM
|
||||||
|
// | F::R14X2_UINT_PACK16_ARM
|
||||||
|
// | F::R14X2_UNORM_PACK16_ARM
|
||||||
|
// | F::R16_SFLOAT_FPENCODING_BFLOAT16_ARM
|
||||||
|
| F::R4G4B4A4_UNORM_PACK16
|
||||||
|
| F::B4G4R4A4_UNORM_PACK16
|
||||||
|
| F::R5G6B5_UNORM_PACK16
|
||||||
|
| F::B5G6R5_UNORM_PACK16
|
||||||
|
| F::R5G5B5A1_UNORM_PACK16
|
||||||
|
| F::B5G5R5A1_UNORM_PACK16
|
||||||
|
| F::A1R5G5B5_UNORM_PACK16
|
||||||
|
| F::R8G8_UNORM
|
||||||
|
| F::R8G8_SNORM
|
||||||
|
| F::R8G8_USCALED
|
||||||
|
| F::R8G8_SSCALED
|
||||||
|
| F::R8G8_UINT
|
||||||
|
| F::R8G8_SINT
|
||||||
|
| F::R8G8_SRGB
|
||||||
|
| F::R16_UNORM
|
||||||
|
| F::R16_SNORM
|
||||||
|
| F::R16_USCALED
|
||||||
|
| F::R16_SSCALED
|
||||||
|
| F::R16_UINT
|
||||||
|
| F::R16_SINT
|
||||||
|
| F::R16_SFLOAT => FormatClass::Bits16,
|
||||||
|
|
||||||
|
// 8-bit alpha
|
||||||
|
F::A8_UNORM_KHR => FormatClass::Alpha8,
|
||||||
|
|
||||||
|
// 24-bit
|
||||||
|
F::R8G8B8_UNORM
|
||||||
|
| F::R8G8B8_SNORM
|
||||||
|
| F::R8G8B8_USCALED
|
||||||
|
| F::R8G8B8_SSCALED
|
||||||
|
| F::R8G8B8_UINT
|
||||||
|
| F::R8G8B8_SINT
|
||||||
|
| F::R8G8B8_SRGB
|
||||||
|
| F::B8G8R8_UNORM
|
||||||
|
| F::B8G8R8_SNORM
|
||||||
|
| F::B8G8R8_USCALED
|
||||||
|
| F::B8G8R8_SSCALED
|
||||||
|
| F::B8G8R8_UINT
|
||||||
|
| F::B8G8R8_SINT
|
||||||
|
| F::B8G8R8_SRGB => FormatClass::Bits24,
|
||||||
|
|
||||||
|
// 32-bit
|
||||||
|
F::R10X6G10X6_UNORM_2PACK16
|
||||||
|
| F::R12X4G12X4_UNORM_2PACK16
|
||||||
|
// | F::R16G16_SFIXED5_NV
|
||||||
|
// | F::R10X6G10X6_UINT_2PACK16_ARM
|
||||||
|
// | F::R12X4G12X4_UINT_2PACK16_ARM
|
||||||
|
// | F::R14X2G14X2_UINT_2PACK16_ARM
|
||||||
|
// | F::R14X2G14X2_UNORM_2PACK16_ARM
|
||||||
|
| F::R8G8B8A8_UNORM
|
||||||
|
| F::R8G8B8A8_SNORM
|
||||||
|
| F::R8G8B8A8_USCALED
|
||||||
|
| F::R8G8B8A8_SSCALED
|
||||||
|
| F::R8G8B8A8_UINT
|
||||||
|
| F::R8G8B8A8_SINT
|
||||||
|
| F::R8G8B8A8_SRGB
|
||||||
|
| F::B8G8R8A8_UNORM
|
||||||
|
| F::B8G8R8A8_SNORM
|
||||||
|
| F::B8G8R8A8_USCALED
|
||||||
|
| F::B8G8R8A8_SSCALED
|
||||||
|
| F::B8G8R8A8_UINT
|
||||||
|
| F::B8G8R8A8_SINT
|
||||||
|
| F::B8G8R8A8_SRGB
|
||||||
|
| F::A8B8G8R8_UNORM_PACK32
|
||||||
|
| F::A8B8G8R8_SNORM_PACK32
|
||||||
|
| F::A8B8G8R8_USCALED_PACK32
|
||||||
|
| F::A8B8G8R8_SSCALED_PACK32
|
||||||
|
| F::A8B8G8R8_UINT_PACK32
|
||||||
|
| F::A8B8G8R8_SINT_PACK32
|
||||||
|
| F::A8B8G8R8_SRGB_PACK32
|
||||||
|
| F::A2R10G10B10_UNORM_PACK32
|
||||||
|
| F::A2R10G10B10_SNORM_PACK32
|
||||||
|
| F::A2R10G10B10_USCALED_PACK32
|
||||||
|
| F::A2R10G10B10_SSCALED_PACK32
|
||||||
|
| F::A2R10G10B10_UINT_PACK32
|
||||||
|
| F::A2R10G10B10_SINT_PACK32
|
||||||
|
| F::A2B10G10R10_UNORM_PACK32
|
||||||
|
| F::A2B10G10R10_SNORM_PACK32
|
||||||
|
| F::A2B10G10R10_USCALED_PACK32
|
||||||
|
| F::A2B10G10R10_SSCALED_PACK32
|
||||||
|
| F::A2B10G10R10_UINT_PACK32
|
||||||
|
| F::A2B10G10R10_SINT_PACK32
|
||||||
|
| F::R16G16_UNORM
|
||||||
|
| F::R16G16_SNORM
|
||||||
|
| F::R16G16_USCALED
|
||||||
|
| F::R16G16_SSCALED
|
||||||
|
| F::R16G16_UINT
|
||||||
|
| F::R16G16_SINT
|
||||||
|
| F::R16G16_SFLOAT
|
||||||
|
| F::R32_UINT
|
||||||
|
| F::R32_SINT
|
||||||
|
| F::R32_SFLOAT
|
||||||
|
| F::B10G11R11_UFLOAT_PACK32
|
||||||
|
| F::E5B9G9R9_UFLOAT_PACK32 => FormatClass::Bits32,
|
||||||
|
|
||||||
|
// 48-bit
|
||||||
|
F::R16G16B16_UNORM
|
||||||
|
| F::R16G16B16_SNORM
|
||||||
|
| F::R16G16B16_USCALED
|
||||||
|
| F::R16G16B16_SSCALED
|
||||||
|
| F::R16G16B16_UINT
|
||||||
|
| F::R16G16B16_SINT
|
||||||
|
| F::R16G16B16_SFLOAT => FormatClass::Bits48,
|
||||||
|
|
||||||
|
// 64-bit
|
||||||
|
F::R16G16B16A16_UNORM
|
||||||
|
| F::R16G16B16A16_SNORM
|
||||||
|
| F::R16G16B16A16_USCALED
|
||||||
|
| F::R16G16B16A16_SSCALED
|
||||||
|
| F::R16G16B16A16_UINT
|
||||||
|
| F::R16G16B16A16_SINT
|
||||||
|
| F::R16G16B16A16_SFLOAT
|
||||||
|
| F::R32G32_UINT
|
||||||
|
| F::R32G32_SINT
|
||||||
|
| F::R32G32_SFLOAT
|
||||||
|
| F::R64_UINT
|
||||||
|
| F::R64_SINT
|
||||||
|
| F::R64_SFLOAT => FormatClass::Bits64,
|
||||||
|
|
||||||
|
// 96-bit
|
||||||
|
F::R32G32B32_UINT | F::R32G32B32_SINT | F::R32G32B32_SFLOAT => FormatClass::Bits96,
|
||||||
|
|
||||||
|
// 128-bit
|
||||||
|
F::R32G32B32A32_UINT
|
||||||
|
| F::R32G32B32A32_SINT
|
||||||
|
| F::R32G32B32A32_SFLOAT
|
||||||
|
| F::R64G64_UINT
|
||||||
|
| F::R64G64_SINT
|
||||||
|
| F::R64G64_SFLOAT => FormatClass::Bits128,
|
||||||
|
|
||||||
|
// 192-bit
|
||||||
|
F::R64G64B64_UINT | F::R64G64B64_SINT | F::R64G64B64_SFLOAT => FormatClass::Bits192,
|
||||||
|
|
||||||
|
// 256-bit
|
||||||
|
F::R64G64B64A64_UINT | F::R64G64B64A64_SINT | F::R64G64B64A64_SFLOAT => {
|
||||||
|
FormatClass::Bits256
|
||||||
|
}
|
||||||
|
|
||||||
|
// Depth / Stencil
|
||||||
|
F::D16_UNORM => FormatClass::D16,
|
||||||
|
F::X8_D24_UNORM_PACK32 => FormatClass::D24,
|
||||||
|
F::D32_SFLOAT => FormatClass::D32,
|
||||||
|
F::S8_UINT => FormatClass::S8,
|
||||||
|
F::D16_UNORM_S8_UINT => FormatClass::D16S8,
|
||||||
|
F::D24_UNORM_S8_UINT => FormatClass::D24S8,
|
||||||
|
F::D32_SFLOAT_S8_UINT => FormatClass::D32S8,
|
||||||
|
|
||||||
|
// BCn
|
||||||
|
F::BC1_RGB_UNORM_BLOCK | F::BC1_RGB_SRGB_BLOCK => FormatClass::Bc1Rgb,
|
||||||
|
F::BC1_RGBA_UNORM_BLOCK | F::BC1_RGBA_SRGB_BLOCK => FormatClass::Bc1Rgba,
|
||||||
|
F::BC2_UNORM_BLOCK | F::BC2_SRGB_BLOCK => FormatClass::Bc2,
|
||||||
|
F::BC3_UNORM_BLOCK | F::BC3_SRGB_BLOCK => FormatClass::Bc3,
|
||||||
|
F::BC4_UNORM_BLOCK | F::BC4_SNORM_BLOCK => FormatClass::Bc4,
|
||||||
|
F::BC5_UNORM_BLOCK | F::BC5_SNORM_BLOCK => FormatClass::Bc5,
|
||||||
|
F::BC6H_UFLOAT_BLOCK | F::BC6H_SFLOAT_BLOCK => FormatClass::Bc6h,
|
||||||
|
F::BC7_UNORM_BLOCK | F::BC7_SRGB_BLOCK => FormatClass::Bc7,
|
||||||
|
|
||||||
|
// ETC2 / EAC
|
||||||
|
F::ETC2_R8G8B8_UNORM_BLOCK | F::ETC2_R8G8B8_SRGB_BLOCK => FormatClass::Etc2Rgb,
|
||||||
|
F::ETC2_R8G8B8A1_UNORM_BLOCK | F::ETC2_R8G8B8A1_SRGB_BLOCK => FormatClass::Etc2Rgba,
|
||||||
|
F::ETC2_R8G8B8A8_UNORM_BLOCK | F::ETC2_R8G8B8A8_SRGB_BLOCK => FormatClass::Etc2EacRgba,
|
||||||
|
F::EAC_R11_UNORM_BLOCK | F::EAC_R11_SNORM_BLOCK => FormatClass::EacR,
|
||||||
|
F::EAC_R11G11_UNORM_BLOCK | F::EAC_R11G11_SNORM_BLOCK => FormatClass::EacRg,
|
||||||
|
|
||||||
|
// ASTC 2D
|
||||||
|
F::ASTC_4X4_SFLOAT_BLOCK | F::ASTC_4X4_UNORM_BLOCK | F::ASTC_4X4_SRGB_BLOCK => {
|
||||||
|
FormatClass::Astc4x4
|
||||||
|
}
|
||||||
|
F::ASTC_5X4_SFLOAT_BLOCK | F::ASTC_5X4_UNORM_BLOCK | F::ASTC_5X4_SRGB_BLOCK => {
|
||||||
|
FormatClass::Astc5x4
|
||||||
|
}
|
||||||
|
F::ASTC_5X5_SFLOAT_BLOCK | F::ASTC_5X5_UNORM_BLOCK | F::ASTC_5X5_SRGB_BLOCK => {
|
||||||
|
FormatClass::Astc5x5
|
||||||
|
}
|
||||||
|
F::ASTC_6X5_SFLOAT_BLOCK | F::ASTC_6X5_UNORM_BLOCK | F::ASTC_6X5_SRGB_BLOCK => {
|
||||||
|
FormatClass::Astc6x5
|
||||||
|
}
|
||||||
|
F::ASTC_6X6_SFLOAT_BLOCK | F::ASTC_6X6_UNORM_BLOCK | F::ASTC_6X6_SRGB_BLOCK => {
|
||||||
|
FormatClass::Astc6x6
|
||||||
|
}
|
||||||
|
F::ASTC_8X5_SFLOAT_BLOCK | F::ASTC_8X5_UNORM_BLOCK | F::ASTC_8X5_SRGB_BLOCK => {
|
||||||
|
FormatClass::Astc8x5
|
||||||
|
}
|
||||||
|
F::ASTC_8X6_SFLOAT_BLOCK | F::ASTC_8X6_UNORM_BLOCK | F::ASTC_8X6_SRGB_BLOCK => {
|
||||||
|
FormatClass::Astc8x6
|
||||||
|
}
|
||||||
|
F::ASTC_8X8_SFLOAT_BLOCK | F::ASTC_8X8_UNORM_BLOCK | F::ASTC_8X8_SRGB_BLOCK => {
|
||||||
|
FormatClass::Astc8x8
|
||||||
|
}
|
||||||
|
F::ASTC_10X5_SFLOAT_BLOCK | F::ASTC_10X5_UNORM_BLOCK | F::ASTC_10X5_SRGB_BLOCK => {
|
||||||
|
FormatClass::Astc10x5
|
||||||
|
}
|
||||||
|
F::ASTC_10X6_SFLOAT_BLOCK | F::ASTC_10X6_UNORM_BLOCK | F::ASTC_10X6_SRGB_BLOCK => {
|
||||||
|
FormatClass::Astc10x6
|
||||||
|
}
|
||||||
|
F::ASTC_10X8_SFLOAT_BLOCK | F::ASTC_10X8_UNORM_BLOCK | F::ASTC_10X8_SRGB_BLOCK => {
|
||||||
|
FormatClass::Astc10x8
|
||||||
|
}
|
||||||
|
F::ASTC_10X10_SFLOAT_BLOCK | F::ASTC_10X10_UNORM_BLOCK | F::ASTC_10X10_SRGB_BLOCK => {
|
||||||
|
FormatClass::Astc10x10
|
||||||
|
}
|
||||||
|
F::ASTC_12X10_SFLOAT_BLOCK | F::ASTC_12X10_UNORM_BLOCK | F::ASTC_12X10_SRGB_BLOCK => {
|
||||||
|
FormatClass::Astc12x10
|
||||||
|
}
|
||||||
|
F::ASTC_12X12_SFLOAT_BLOCK | F::ASTC_12X12_UNORM_BLOCK | F::ASTC_12X12_SRGB_BLOCK => {
|
||||||
|
FormatClass::Astc12x12
|
||||||
|
}
|
||||||
|
|
||||||
|
// Packed/YCbCr-ish (as listed)
|
||||||
|
F::G8B8G8R8_422_UNORM => FormatClass::YuvG8B8G8R8_422,
|
||||||
|
F::B8G8R8G8_422_UNORM => FormatClass::YuvB8G8R8G8_422,
|
||||||
|
|
||||||
|
F::G8_B8_R8_3PLANE_420_UNORM => FormatClass::YuvG8B8R8Triplane420,
|
||||||
|
F::G8_B8R8_2PLANE_420_UNORM => FormatClass::YuvG8B8R8Biplane420,
|
||||||
|
F::G8_B8_R8_3PLANE_422_UNORM => FormatClass::YuvG8B8R8Triplane422,
|
||||||
|
F::G8_B8R8_2PLANE_422_UNORM => FormatClass::YuvG8B8R8Biplane422,
|
||||||
|
F::G8_B8_R8_3PLANE_444_UNORM => FormatClass::YuvG8B8R8Triplane444,
|
||||||
|
|
||||||
|
F::G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16 => {
|
||||||
|
FormatClass::YuvG10X6B10X6R10X6Triplane420
|
||||||
|
}
|
||||||
|
F::G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16 => {
|
||||||
|
FormatClass::YuvG10X6B10X6R10X6Biplane420
|
||||||
|
}
|
||||||
|
F::G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16 => {
|
||||||
|
FormatClass::YuvG10X6B10X6R10X6Triplane422
|
||||||
|
}
|
||||||
|
F::G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16 => {
|
||||||
|
FormatClass::YuvG10X6B10X6R10X6Biplane422
|
||||||
|
}
|
||||||
|
F::G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16 => {
|
||||||
|
FormatClass::YuvG10X6B10X6R10X6Triplane444
|
||||||
|
}
|
||||||
|
|
||||||
|
F::G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16 => {
|
||||||
|
FormatClass::YuvG12X4B12X4R12X4Triplane420
|
||||||
|
}
|
||||||
|
F::G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16 => {
|
||||||
|
FormatClass::YuvG12X4B12X4R12X4Biplane420
|
||||||
|
}
|
||||||
|
F::G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16 => {
|
||||||
|
FormatClass::YuvG12X4B12X4R12X4Triplane422
|
||||||
|
}
|
||||||
|
F::G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16 => {
|
||||||
|
FormatClass::YuvG12X4B12X4R12X4Biplane422
|
||||||
|
}
|
||||||
|
F::G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16 => {
|
||||||
|
FormatClass::YuvG12X4B12X4R12X4Triplane444
|
||||||
|
}
|
||||||
|
|
||||||
|
F::G16_B16_R16_3PLANE_420_UNORM => FormatClass::YuvG16B16R16Triplane420,
|
||||||
|
F::G16_B16R16_2PLANE_420_UNORM => FormatClass::YuvG16B16R16Biplane420,
|
||||||
|
F::G16_B16_R16_3PLANE_422_UNORM => FormatClass::YuvG16B16R16Triplane422,
|
||||||
|
F::G16_B16R16_2PLANE_422_UNORM => FormatClass::YuvG16B16R16Biplane422,
|
||||||
|
F::G16_B16_R16_3PLANE_444_UNORM => FormatClass::YuvG16B16R16Triplane444,
|
||||||
|
|
||||||
|
// 2-plane 444 (additional section)
|
||||||
|
F::G8_B8R8_2PLANE_444_UNORM => FormatClass::YuvG8B8R8Biplane444,
|
||||||
|
F::G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16 => {
|
||||||
|
FormatClass::YuvG10X6B10X6R10X6Biplane444
|
||||||
|
}
|
||||||
|
F::G12X4_B12X4R12X4_2PLANE_444_UNORM_3PACK16 => {
|
||||||
|
FormatClass::YuvG12X4B12X4R12X4Biplane444
|
||||||
|
}
|
||||||
|
F::G16_B16R16_2PLANE_444_UNORM => FormatClass::YuvG16B16R16Biplane444,
|
||||||
|
|
||||||
|
// 64-bit special grouped headings from the markdown
|
||||||
|
F::R10X6G10X6B10X6A10X6_UNORM_4PACK16 /* | F::R10X6G10X6B10X6A10X6_UINT_4PACK16_ARM */
|
||||||
|
=> {
|
||||||
|
FormatClass::Bits64R10G10B10A10
|
||||||
|
}
|
||||||
|
F::G10X6B10X6G10X6R10X6_422_UNORM_4PACK16 => FormatClass::Bits64G10B10G10R10_422,
|
||||||
|
F::B10X6G10X6R10X6G10X6_422_UNORM_4PACK16 => FormatClass::Bits64B10G10R10G10_422,
|
||||||
|
F::R12X4G12X4B12X4A12X4_UNORM_4PACK16 /*| F::R12X4G12X4B12X4A12X4_UINT_4PACK16_ARM */
|
||||||
|
=> {
|
||||||
|
FormatClass::Bits64R12G12B12A12
|
||||||
|
}
|
||||||
|
F::G12X4B12X4G12X4R12X4_422_UNORM_4PACK16 => FormatClass::Bits64G12B12G12R12_422,
|
||||||
|
F::B12X4G12X4R12X4G12X4_422_UNORM_4PACK16 => FormatClass::Bits64B12G12R12G12_422,
|
||||||
|
F::G16B16G16R16_422_UNORM => FormatClass::Bits64G16B16G16R16_422,
|
||||||
|
F::B16G16R16G16_422_UNORM => FormatClass::Bits64B16G16R16G16_422,
|
||||||
|
|
||||||
|
// F::R14X2G14X2B14X2A14X2_UINT_4PACK16_ARM
|
||||||
|
// | F::R14X2G14X2B14X2A14X2_UNORM_4PACK16_ARM => FormatClass::Bits64_R14G14B14A14,
|
||||||
|
|
||||||
|
// PVRTC
|
||||||
|
F::PVRTC1_2BPP_UNORM_BLOCK_IMG | F::PVRTC1_2BPP_SRGB_BLOCK_IMG => {
|
||||||
|
FormatClass::Pvrtc1_2bpp
|
||||||
|
}
|
||||||
|
F::PVRTC1_4BPP_UNORM_BLOCK_IMG | F::PVRTC1_4BPP_SRGB_BLOCK_IMG => {
|
||||||
|
FormatClass::Pvrtc1_4bpp
|
||||||
|
}
|
||||||
|
F::PVRTC2_2BPP_UNORM_BLOCK_IMG | F::PVRTC2_2BPP_SRGB_BLOCK_IMG => {
|
||||||
|
FormatClass::Pvrtc2_2bpp
|
||||||
|
}
|
||||||
|
F::PVRTC2_4BPP_UNORM_BLOCK_IMG | F::PVRTC2_4BPP_SRGB_BLOCK_IMG => {
|
||||||
|
FormatClass::Pvrtc2_4bpp
|
||||||
|
}
|
||||||
|
|
||||||
|
// ASTC 3D (EXT)
|
||||||
|
// F::ASTC_3X3X3_UNORM_BLOCK_EXT
|
||||||
|
// | F::ASTC_3X3X3_SRGB_BLOCK_EXT
|
||||||
|
// | F::ASTC_3X3X3_SFLOAT_BLOCK_EXT => FormatClass::Astc3x3x3,
|
||||||
|
// F::ASTC_4X3X3_UNORM_BLOCK_EXT
|
||||||
|
// | F::ASTC_4X3X3_SRGB_BLOCK_EXT
|
||||||
|
// | F::ASTC_4X3X3_SFLOAT_BLOCK_EXT => FormatClass::Astc4x3x3,
|
||||||
|
// F::ASTC_4X4X3_UNORM_BLOCK_EXT
|
||||||
|
// | F::ASTC_4X4X3_SRGB_BLOCK_EXT
|
||||||
|
// | F::ASTC_4X4X3_SFLOAT_BLOCK_EXT => FormatClass::Astc4x4x3,
|
||||||
|
// F::ASTC_4X4X4_UNORM_BLOCK_EXT
|
||||||
|
// | F::ASTC_4X4X4_SRGB_BLOCK_EXT
|
||||||
|
// | F::ASTC_4X4X4_SFLOAT_BLOCK_EXT => FormatClass::Astc4x4x4,
|
||||||
|
// F::ASTC_5X4X4_UNORM_BLOCK_EXT
|
||||||
|
// | F::ASTC_5X4X4_SRGB_BLOCK_EXT
|
||||||
|
// | F::ASTC_5X4X4_SFLOAT_BLOCK_EXT => FormatClass::Astc5x4x4,
|
||||||
|
// F::ASTC_5X5X4_UNORM_BLOCK_EXT
|
||||||
|
// | F::ASTC_5X5X4_SRGB_BLOCK_EXT
|
||||||
|
// | F::ASTC_5X5X4_SFLOAT_BLOCK_EXT => FormatClass::Astc5x5x4,
|
||||||
|
// F::ASTC_5X5X5_UNORM_BLOCK_EXT
|
||||||
|
// | F::ASTC_5X5X5_SRGB_BLOCK_EXT
|
||||||
|
// | F::ASTC_5X5X5_SFLOAT_BLOCK_EXT => FormatClass::Astc5x5x5,
|
||||||
|
// F::ASTC_6X5X5_UNORM_BLOCK_EXT
|
||||||
|
// | F::ASTC_6X5X5_SRGB_BLOCK_EXT
|
||||||
|
// | F::ASTC_6X5X5_SFLOAT_BLOCK_EXT => FormatClass::Astc6x5x5,
|
||||||
|
// F::ASTC_6X6X5_UNORM_BLOCK_EXT
|
||||||
|
// | F::ASTC_6X6X5_SRGB_BLOCK_EXT
|
||||||
|
// | F::ASTC_6X6X5_SFLOAT_BLOCK_EXT => FormatClass::Astc6x6x5,
|
||||||
|
// F::ASTC_6X6X6_UNORM_BLOCK_EXT
|
||||||
|
// | F::ASTC_6X6X6_SRGB_BLOCK_EXT
|
||||||
|
// | F::ASTC_6X6X6_SFLOAT_BLOCK_EXT => FormatClass::Astc6x6x6,
|
||||||
|
|
||||||
|
// // 14-bit 2-plane
|
||||||
|
// F::G14X2_B14X2R14X2_2PLANE_420_UNORM_3PACK16_ARM => {
|
||||||
|
// FormatClass::YuvG14X2_B14X2R14X2_2Plane_420
|
||||||
|
// }
|
||||||
|
// F::G14X2_B14X2R14X2_2PLANE_422_UNORM_3PACK16_ARM => {
|
||||||
|
// FormatClass::YuvG14X2_B14X2R14X2_2Plane_422
|
||||||
|
// }
|
||||||
|
|
||||||
|
_ => todo!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn format_to_aspect_mask(format: vk::Format) -> vk::ImageAspectFlags {
|
||||||
|
use vk::Format as F;
|
||||||
|
match format {
|
||||||
|
F::D16_UNORM | F::X8_D24_UNORM_PACK32 | F::D32_SFLOAT => vk::ImageAspectFlags::DEPTH,
|
||||||
|
F::D16_UNORM_S8_UINT | F::D24_UNORM_S8_UINT | F::D32_SFLOAT_S8_UINT => {
|
||||||
|
vk::ImageAspectFlags::DEPTH | vk::ImageAspectFlags::STENCIL
|
||||||
|
}
|
||||||
|
F::S8_UINT => vk::ImageAspectFlags::STENCIL,
|
||||||
|
_ => vk::ImageAspectFlags::COLOR,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -338,7 +338,7 @@ impl Instance {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn choose_adapter_default(
|
pub(crate) fn choose_adapter_default(
|
||||||
&self,
|
&self,
|
||||||
surface: Option<&Surface>,
|
surface: Option<&Surface>,
|
||||||
required_extensions: &[Extension],
|
required_extensions: &[Extension],
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,8 @@
|
||||||
#![feature(
|
#![feature(
|
||||||
negative_impls,
|
negative_impls,
|
||||||
map_try_insert,
|
map_try_insert,
|
||||||
core_io,
|
|
||||||
core_io_borrowed_buf,
|
|
||||||
debug_closure_helpers,
|
debug_closure_helpers,
|
||||||
|
core_io_borrowed_buf,
|
||||||
slice_partition_dedup
|
slice_partition_dedup
|
||||||
)]
|
)]
|
||||||
|
|
||||||
|
|
@ -36,7 +35,7 @@ pub mod sync;
|
||||||
mod text;
|
mod text;
|
||||||
pub mod util;
|
pub mod util;
|
||||||
|
|
||||||
use device::Device;
|
use device::{Device, DeviceOwned};
|
||||||
|
|
||||||
mod texture {
|
mod texture {
|
||||||
use std::{collections::BTreeMap, sync::Arc};
|
use std::{collections::BTreeMap, sync::Arc};
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,6 @@ use crate::{
|
||||||
util::{self, Rgba, WithLifetime},
|
util::{self, Rgba, WithLifetime},
|
||||||
};
|
};
|
||||||
use ash::vk;
|
use ash::vk;
|
||||||
use ash_formats::FormatExt;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
|
|
@ -1268,7 +1267,7 @@ pub fn image_barrier(
|
||||||
.old_layout(before_access.layout)
|
.old_layout(before_access.layout)
|
||||||
.new_layout(after_access.layout)
|
.new_layout(after_access.layout)
|
||||||
.subresource_range(vk::ImageSubresourceRange {
|
.subresource_range(vk::ImageSubresourceRange {
|
||||||
aspect_mask: format.aspect_flags(),
|
aspect_mask: util::image_aspect_from_format(format),
|
||||||
..images::SUBRESOURCERANGE_ALL
|
..images::SUBRESOURCERANGE_ALL
|
||||||
})
|
})
|
||||||
.src_queue_family_index(
|
.src_queue_family_index(
|
||||||
|
|
|
||||||
|
|
@ -337,7 +337,7 @@ impl<'cmd> CommandList<'cmd> {
|
||||||
|
|
||||||
// construct barriers
|
// construct barriers
|
||||||
// TODO: need to know each images aspects at this point
|
// TODO: need to know each images aspects at this point
|
||||||
for _barrier in barriers {
|
for barrier in barriers {
|
||||||
// stuff
|
// stuff
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,7 @@
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use ash::vk;
|
use ash::vk;
|
||||||
use glam::{
|
use glam::{f32::Mat4, vec3};
|
||||||
camera::rh::{proj, view},
|
|
||||||
vec3,
|
|
||||||
};
|
|
||||||
use gpu_allocator::MemoryLocation;
|
use gpu_allocator::MemoryLocation;
|
||||||
|
|
||||||
pub use crate::egui_pass::{egui_pass, egui_pre_pass};
|
pub use crate::egui_pass::{egui_pass, egui_pre_pass};
|
||||||
|
|
@ -322,14 +319,14 @@ impl Wireframe {
|
||||||
let cmd = &ctx.cmd;
|
let cmd = &ctx.cmd;
|
||||||
|
|
||||||
//let model = Mat4::from_scale(vec3(0.01, 0.01, 0.01));
|
//let model = Mat4::from_scale(vec3(0.01, 0.01, 0.01));
|
||||||
let proj = proj::vulkan::perspective(
|
let proj = Mat4::perspective_lh(
|
||||||
core::f32::consts::FRAC_PI_4,
|
core::f32::consts::FRAC_PI_4,
|
||||||
target.width() as f32 / target.height() as f32,
|
target.width() as f32 / target.height() as f32,
|
||||||
0.1,
|
0.1,
|
||||||
100.0,
|
100.0,
|
||||||
);
|
);
|
||||||
let pos = vec3(0.0, 0.0, -5.0);
|
let pos = vec3(0.0, 0.0, -5.0);
|
||||||
let view = view::look_at_mat4(pos, pos + vec3(0.0, 0.0, 1.0), vec3(0.0, 1.0, 0.0));
|
let view = Mat4::look_at_rh(pos, pos + vec3(0.0, 0.0, 1.0), vec3(0.0, 1.0, 0.0));
|
||||||
let to_clip = proj * view; // * model;
|
let to_clip = proj * view; // * model;
|
||||||
|
|
||||||
let color_attachment = &vk::RenderingAttachmentInfo::default()
|
let color_attachment = &vk::RenderingAttachmentInfo::default()
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,7 @@ impl SyncThreadpool {
|
||||||
use std::sync::atomic::Ordering;
|
use std::sync::atomic::Ordering;
|
||||||
match self
|
match self
|
||||||
.num_threads
|
.num_threads
|
||||||
.try_update(Ordering::Release, Ordering::Acquire, |i| {
|
.fetch_update(Ordering::Release, Ordering::Acquire, |i| {
|
||||||
if i < self.max_threads {
|
if i < self.max_threads {
|
||||||
Some(i + 1)
|
Some(i + 1)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,7 @@ use std::{
|
||||||
sync::{Arc, Weak},
|
sync::{Arc, Weak},
|
||||||
};
|
};
|
||||||
|
|
||||||
use ash::vk::{self, Extent2D};
|
use ash::vk::Extent2D;
|
||||||
use ash_formats::FormatHelpers as _;
|
|
||||||
use cosmic_text::{CacheKey, FontSystem, PhysicalGlyph, SwashCache};
|
use cosmic_text::{CacheKey, FontSystem, PhysicalGlyph, SwashCache};
|
||||||
use glam::IVec2;
|
use glam::IVec2;
|
||||||
use guillotiere::size2;
|
use guillotiere::size2;
|
||||||
|
|
@ -190,7 +189,7 @@ impl std::fmt::Debug for FontAtlas {
|
||||||
|
|
||||||
impl FontAtlas {
|
impl FontAtlas {
|
||||||
fn new(size: u32) -> Self {
|
fn new(size: u32) -> Self {
|
||||||
let num_bytes = vk::Format::R8G8B8A8_UNORM.layer_size([size, size, 1]);
|
let num_bytes = size * size * 4;
|
||||||
Self {
|
Self {
|
||||||
image: Arc::new(Image(parking_lot::RwLock::new(ImageInner {
|
image: Arc::new(Image(parking_lot::RwLock::new(ImageInner {
|
||||||
image: vec![0; num_bytes as usize],
|
image: vec![0; num_bytes as usize],
|
||||||
|
|
@ -235,7 +234,7 @@ impl FontAtlas {
|
||||||
let y = y + line_y;
|
let y = y + line_y;
|
||||||
let image_offset = 4 * y as u32 * image.width() + 4 * x as u32;
|
let image_offset = 4 * y as u32 * image.width() + 4 * x as u32;
|
||||||
let glyph_offset = 4 * line_y * width;
|
let glyph_offset = 4 * line_y * width;
|
||||||
let len = vk::Format::R8G8B8A8_UNORM.row_pitch(width as u32) as usize;
|
let len = 4 * width as usize;
|
||||||
let dst = &mut image.bytes_mut()[image_offset as usize..][..len];
|
let dst = &mut image.bytes_mut()[image_offset as usize..][..len];
|
||||||
let src = &data[glyph_offset as usize..][..len];
|
let src = &data[glyph_offset as usize..][..len];
|
||||||
dst.copy_from_slice(src);
|
dst.copy_from_slice(src);
|
||||||
|
|
|
||||||
|
|
@ -199,6 +199,229 @@ impl<'a, T: 'a> MutexExt<'a, T> for parking_lot::Mutex<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub trait FormatExt {
|
||||||
|
fn get_component_kind(&self) -> FormatComponentKind;
|
||||||
|
fn is_f32(&self) -> bool;
|
||||||
|
fn is_u32(&self) -> bool;
|
||||||
|
fn is_i32(&self) -> bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
|
pub enum FormatComponentKind {
|
||||||
|
Float,
|
||||||
|
UInt,
|
||||||
|
SInt,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn format_to_primitive(format: vk::Format) -> FormatComponentKind {
|
||||||
|
use FormatComponentKind::*;
|
||||||
|
match format {
|
||||||
|
vk::Format::BC6H_SFLOAT_BLOCK => Float,
|
||||||
|
vk::Format::D32_SFLOAT => Float,
|
||||||
|
vk::Format::R16G16B16A16_SFLOAT => Float,
|
||||||
|
vk::Format::R16G16B16_SFLOAT => Float,
|
||||||
|
vk::Format::R16G16_SFLOAT => Float,
|
||||||
|
vk::Format::R16_SFLOAT => Float,
|
||||||
|
vk::Format::R32G32B32A32_SFLOAT => Float,
|
||||||
|
vk::Format::R32G32B32_SFLOAT => Float,
|
||||||
|
vk::Format::R32G32_SFLOAT => Float,
|
||||||
|
vk::Format::R32_SFLOAT => Float,
|
||||||
|
vk::Format::R64G64B64A64_SFLOAT => Float,
|
||||||
|
vk::Format::R64G64B64_SFLOAT => Float,
|
||||||
|
vk::Format::R64G64_SFLOAT => Float,
|
||||||
|
vk::Format::R64_SFLOAT => Float,
|
||||||
|
vk::Format::D32_SFLOAT_S8_UINT => Float,
|
||||||
|
vk::Format::A2B10G10R10_SINT_PACK32 => SInt,
|
||||||
|
vk::Format::A2R10G10B10_SINT_PACK32 => SInt,
|
||||||
|
vk::Format::A8B8G8R8_SINT_PACK32 => SInt,
|
||||||
|
vk::Format::B8G8R8A8_SINT => SInt,
|
||||||
|
vk::Format::B8G8R8_SINT => SInt,
|
||||||
|
vk::Format::R16G16B16A16_SINT => SInt,
|
||||||
|
vk::Format::R16G16B16_SINT => SInt,
|
||||||
|
vk::Format::R16G16_SINT => SInt,
|
||||||
|
vk::Format::R16_SINT => SInt,
|
||||||
|
vk::Format::R32G32B32A32_SINT => SInt,
|
||||||
|
vk::Format::R32G32B32_SINT => SInt,
|
||||||
|
vk::Format::R32G32_SINT => SInt,
|
||||||
|
vk::Format::R32_SINT => SInt,
|
||||||
|
vk::Format::R64G64B64A64_SINT => SInt,
|
||||||
|
vk::Format::R64G64B64_SINT => SInt,
|
||||||
|
vk::Format::R64G64_SINT => SInt,
|
||||||
|
vk::Format::R64_SINT => SInt,
|
||||||
|
vk::Format::R8G8B8A8_SINT => SInt,
|
||||||
|
vk::Format::R8G8B8_SINT => SInt,
|
||||||
|
vk::Format::R8G8_SINT => SInt,
|
||||||
|
vk::Format::R8_SINT => SInt,
|
||||||
|
vk::Format::A2B10G10R10_SNORM_PACK32 => Float,
|
||||||
|
vk::Format::A2R10G10B10_SNORM_PACK32 => Float,
|
||||||
|
vk::Format::A8B8G8R8_SNORM_PACK32 => Float,
|
||||||
|
vk::Format::B8G8R8A8_SNORM => Float,
|
||||||
|
vk::Format::B8G8R8_SNORM => Float,
|
||||||
|
vk::Format::BC4_SNORM_BLOCK => Float,
|
||||||
|
vk::Format::BC5_SNORM_BLOCK => Float,
|
||||||
|
vk::Format::EAC_R11G11_SNORM_BLOCK => Float,
|
||||||
|
vk::Format::EAC_R11_SNORM_BLOCK => Float,
|
||||||
|
vk::Format::R16G16B16A16_SNORM => Float,
|
||||||
|
vk::Format::R16G16B16_SNORM => Float,
|
||||||
|
vk::Format::R16G16_SNORM => Float,
|
||||||
|
vk::Format::R16_SNORM => Float,
|
||||||
|
vk::Format::R8G8B8A8_SNORM => Float,
|
||||||
|
vk::Format::R8G8B8_SNORM => Float,
|
||||||
|
vk::Format::R8G8_SNORM => Float,
|
||||||
|
vk::Format::R8_SNORM => Float,
|
||||||
|
vk::Format::A8B8G8R8_SRGB_PACK32 => Float,
|
||||||
|
vk::Format::ASTC_10X10_SRGB_BLOCK => Float,
|
||||||
|
vk::Format::ASTC_10X5_SRGB_BLOCK => Float,
|
||||||
|
vk::Format::ASTC_10X6_SRGB_BLOCK => Float,
|
||||||
|
vk::Format::ASTC_10X8_SRGB_BLOCK => Float,
|
||||||
|
vk::Format::ASTC_12X10_SRGB_BLOCK => Float,
|
||||||
|
vk::Format::ASTC_12X12_SRGB_BLOCK => Float,
|
||||||
|
vk::Format::ASTC_4X4_SRGB_BLOCK => Float,
|
||||||
|
vk::Format::ASTC_5X4_SRGB_BLOCK => Float,
|
||||||
|
vk::Format::ASTC_5X5_SRGB_BLOCK => Float,
|
||||||
|
vk::Format::ASTC_6X5_SRGB_BLOCK => Float,
|
||||||
|
vk::Format::ASTC_6X6_SRGB_BLOCK => Float,
|
||||||
|
vk::Format::ASTC_8X5_SRGB_BLOCK => Float,
|
||||||
|
vk::Format::ASTC_8X6_SRGB_BLOCK => Float,
|
||||||
|
vk::Format::ASTC_8X8_SRGB_BLOCK => Float,
|
||||||
|
vk::Format::B8G8R8A8_SRGB => Float,
|
||||||
|
vk::Format::B8G8R8_SRGB => Float,
|
||||||
|
vk::Format::BC1_RGBA_SRGB_BLOCK => Float,
|
||||||
|
vk::Format::BC1_RGB_SRGB_BLOCK => Float,
|
||||||
|
vk::Format::BC2_SRGB_BLOCK => Float,
|
||||||
|
vk::Format::BC3_SRGB_BLOCK => Float,
|
||||||
|
vk::Format::BC7_SRGB_BLOCK => Float,
|
||||||
|
vk::Format::ETC2_R8G8B8A1_SRGB_BLOCK => Float,
|
||||||
|
vk::Format::ETC2_R8G8B8A8_SRGB_BLOCK => Float,
|
||||||
|
vk::Format::ETC2_R8G8B8_SRGB_BLOCK => Float,
|
||||||
|
vk::Format::R8G8B8A8_SRGB => Float,
|
||||||
|
vk::Format::R8G8B8_SRGB => Float,
|
||||||
|
vk::Format::R8G8_SRGB => Float,
|
||||||
|
vk::Format::R8_SRGB => Float,
|
||||||
|
vk::Format::A2B10G10R10_SSCALED_PACK32 => Float,
|
||||||
|
vk::Format::A2R10G10B10_SSCALED_PACK32 => Float,
|
||||||
|
vk::Format::A8B8G8R8_SSCALED_PACK32 => Float,
|
||||||
|
vk::Format::B8G8R8A8_SSCALED => Float,
|
||||||
|
vk::Format::B8G8R8_SSCALED => Float,
|
||||||
|
vk::Format::R16G16B16A16_SSCALED => Float,
|
||||||
|
vk::Format::R16G16B16_SSCALED => Float,
|
||||||
|
vk::Format::R16G16_SSCALED => Float,
|
||||||
|
vk::Format::R16_SSCALED => Float,
|
||||||
|
vk::Format::R8G8B8A8_SSCALED => Float,
|
||||||
|
vk::Format::R8G8B8_SSCALED => Float,
|
||||||
|
vk::Format::R8G8_SSCALED => Float,
|
||||||
|
vk::Format::R8_SSCALED => Float,
|
||||||
|
vk::Format::B10G11R11_UFLOAT_PACK32 => Float,
|
||||||
|
vk::Format::BC6H_UFLOAT_BLOCK => Float,
|
||||||
|
vk::Format::E5B9G9R9_UFLOAT_PACK32 => Float,
|
||||||
|
vk::Format::A2B10G10R10_UINT_PACK32 => UInt,
|
||||||
|
vk::Format::A2R10G10B10_UINT_PACK32 => UInt,
|
||||||
|
vk::Format::A8B8G8R8_UINT_PACK32 => UInt,
|
||||||
|
vk::Format::B8G8R8A8_UINT => UInt,
|
||||||
|
vk::Format::B8G8R8_UINT => UInt,
|
||||||
|
vk::Format::R16G16B16A16_UINT => UInt,
|
||||||
|
vk::Format::R16G16B16_UINT => UInt,
|
||||||
|
vk::Format::R16G16_UINT => UInt,
|
||||||
|
vk::Format::R16_UINT => UInt,
|
||||||
|
vk::Format::R32G32B32A32_UINT => UInt,
|
||||||
|
vk::Format::R32G32B32_UINT => UInt,
|
||||||
|
vk::Format::R32G32_UINT => UInt,
|
||||||
|
vk::Format::R32_UINT => UInt,
|
||||||
|
vk::Format::R64G64B64A64_UINT => UInt,
|
||||||
|
vk::Format::R64G64B64_UINT => UInt,
|
||||||
|
vk::Format::R64G64_UINT => UInt,
|
||||||
|
vk::Format::R64_UINT => UInt,
|
||||||
|
vk::Format::R8G8B8A8_UINT => UInt,
|
||||||
|
vk::Format::R8G8B8_UINT => UInt,
|
||||||
|
vk::Format::R8G8_UINT => UInt,
|
||||||
|
vk::Format::R8_UINT => UInt,
|
||||||
|
vk::Format::S8_UINT => UInt,
|
||||||
|
vk::Format::A1R5G5B5_UNORM_PACK16 => Float,
|
||||||
|
vk::Format::A2B10G10R10_UNORM_PACK32 => Float,
|
||||||
|
vk::Format::A2R10G10B10_UNORM_PACK32 => Float,
|
||||||
|
vk::Format::A8B8G8R8_UNORM_PACK32 => Float,
|
||||||
|
vk::Format::ASTC_10X10_UNORM_BLOCK => Float,
|
||||||
|
vk::Format::ASTC_10X5_UNORM_BLOCK => Float,
|
||||||
|
vk::Format::ASTC_10X6_UNORM_BLOCK => Float,
|
||||||
|
vk::Format::ASTC_10X8_UNORM_BLOCK => Float,
|
||||||
|
vk::Format::ASTC_12X10_UNORM_BLOCK => Float,
|
||||||
|
vk::Format::ASTC_12X12_UNORM_BLOCK => Float,
|
||||||
|
vk::Format::ASTC_4X4_UNORM_BLOCK => Float,
|
||||||
|
vk::Format::ASTC_5X4_UNORM_BLOCK => Float,
|
||||||
|
vk::Format::ASTC_5X5_UNORM_BLOCK => Float,
|
||||||
|
vk::Format::ASTC_6X5_UNORM_BLOCK => Float,
|
||||||
|
vk::Format::ASTC_6X6_UNORM_BLOCK => Float,
|
||||||
|
vk::Format::ASTC_8X5_UNORM_BLOCK => Float,
|
||||||
|
vk::Format::ASTC_8X6_UNORM_BLOCK => Float,
|
||||||
|
vk::Format::ASTC_8X8_UNORM_BLOCK => Float,
|
||||||
|
vk::Format::B4G4R4A4_UNORM_PACK16 => Float,
|
||||||
|
vk::Format::B5G5R5A1_UNORM_PACK16 => Float,
|
||||||
|
vk::Format::B5G6R5_UNORM_PACK16 => Float,
|
||||||
|
vk::Format::B8G8R8A8_UNORM => Float,
|
||||||
|
vk::Format::B8G8R8_UNORM => Float,
|
||||||
|
vk::Format::BC1_RGBA_UNORM_BLOCK => Float,
|
||||||
|
vk::Format::BC1_RGB_UNORM_BLOCK => Float,
|
||||||
|
vk::Format::BC2_UNORM_BLOCK => Float,
|
||||||
|
vk::Format::BC3_UNORM_BLOCK => Float,
|
||||||
|
vk::Format::BC4_UNORM_BLOCK => Float,
|
||||||
|
vk::Format::BC5_UNORM_BLOCK => Float,
|
||||||
|
vk::Format::BC7_UNORM_BLOCK => Float,
|
||||||
|
vk::Format::D16_UNORM => Float,
|
||||||
|
vk::Format::D16_UNORM_S8_UINT => Float,
|
||||||
|
vk::Format::D24_UNORM_S8_UINT => Float,
|
||||||
|
vk::Format::EAC_R11G11_UNORM_BLOCK => Float,
|
||||||
|
vk::Format::EAC_R11_UNORM_BLOCK => Float,
|
||||||
|
vk::Format::ETC2_R8G8B8A1_UNORM_BLOCK => Float,
|
||||||
|
vk::Format::ETC2_R8G8B8A8_UNORM_BLOCK => Float,
|
||||||
|
vk::Format::ETC2_R8G8B8_UNORM_BLOCK => Float,
|
||||||
|
vk::Format::R16G16B16A16_UNORM => Float,
|
||||||
|
vk::Format::R16G16B16_UNORM => Float,
|
||||||
|
vk::Format::R16G16_UNORM => Float,
|
||||||
|
vk::Format::R16_UNORM => Float,
|
||||||
|
vk::Format::R4G4B4A4_UNORM_PACK16 => Float,
|
||||||
|
vk::Format::R4G4_UNORM_PACK8 => Float,
|
||||||
|
vk::Format::R5G5B5A1_UNORM_PACK16 => Float,
|
||||||
|
vk::Format::R5G6B5_UNORM_PACK16 => Float,
|
||||||
|
vk::Format::R8G8B8A8_UNORM => Float,
|
||||||
|
vk::Format::R8G8B8_UNORM => Float,
|
||||||
|
vk::Format::R8G8_UNORM => Float,
|
||||||
|
vk::Format::R8_UNORM => Float,
|
||||||
|
vk::Format::X8_D24_UNORM_PACK32 => Float,
|
||||||
|
vk::Format::A2B10G10R10_USCALED_PACK32 => Float,
|
||||||
|
vk::Format::A2R10G10B10_USCALED_PACK32 => Float,
|
||||||
|
vk::Format::A8B8G8R8_USCALED_PACK32 => Float,
|
||||||
|
vk::Format::B8G8R8A8_USCALED => Float,
|
||||||
|
vk::Format::B8G8R8_USCALED => Float,
|
||||||
|
vk::Format::R16G16B16A16_USCALED => Float,
|
||||||
|
vk::Format::R16G16B16_USCALED => Float,
|
||||||
|
vk::Format::R16G16_USCALED => Float,
|
||||||
|
vk::Format::R16_USCALED => Float,
|
||||||
|
vk::Format::R8G8B8A8_USCALED => Float,
|
||||||
|
vk::Format::R8G8B8_USCALED => Float,
|
||||||
|
vk::Format::R8G8_USCALED => Float,
|
||||||
|
vk::Format::R8_USCALED => Float,
|
||||||
|
_ => unimplemented!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FormatExt for vk::Format {
|
||||||
|
fn get_component_kind(&self) -> FormatComponentKind {
|
||||||
|
format_to_primitive(*self)
|
||||||
|
}
|
||||||
|
fn is_f32(&self) -> bool {
|
||||||
|
format_to_primitive(*self) == FormatComponentKind::Float
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_u32(&self) -> bool {
|
||||||
|
format_to_primitive(*self) == FormatComponentKind::UInt
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_i32(&self) -> bool {
|
||||||
|
format_to_primitive(*self) == FormatComponentKind::SInt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, PartialEq, Eq, Hash, Clone, Copy)]
|
#[derive(Debug, Default, PartialEq, Eq, Hash, Clone, Copy)]
|
||||||
pub struct Rect2D {
|
pub struct Rect2D {
|
||||||
top_left: glam::IVec2,
|
top_left: glam::IVec2,
|
||||||
|
|
@ -395,6 +618,21 @@ impl Rgba {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub fn image_aspect_from_format(format: vk::Format) -> vk::ImageAspectFlags {
|
||||||
|
use vk::{Format, ImageAspectFlags};
|
||||||
|
match format {
|
||||||
|
Format::D32_SFLOAT | Format::X8_D24_UNORM_PACK32 | Format::D16_UNORM => {
|
||||||
|
ImageAspectFlags::DEPTH
|
||||||
|
}
|
||||||
|
Format::S8_UINT => ImageAspectFlags::STENCIL,
|
||||||
|
Format::D32_SFLOAT_S8_UINT | Format::D16_UNORM_S8_UINT | Format::D24_UNORM_S8_UINT => {
|
||||||
|
ImageAspectFlags::DEPTH | ImageAspectFlags::STENCIL
|
||||||
|
}
|
||||||
|
_ => ImageAspectFlags::COLOR,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
pub struct WithLifetime<'a, T>(T, std::marker::PhantomData<&'a ()>);
|
pub struct WithLifetime<'a, T>(T, std::marker::PhantomData<&'a ()>);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ version = "0.1.0"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
ash-formats = { workspace = true }
|
|
||||||
thiserror = { workspace = true }
|
thiserror = { workspace = true }
|
||||||
anyhow = { workspace = true }
|
anyhow = { workspace = true }
|
||||||
tracing = { workspace = true }
|
tracing = { workspace = true }
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
#![feature(debug_closure_helpers)]
|
#![feature(debug_closure_helpers)]
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
use ash_formats::FormatHelpers as _;
|
|
||||||
use bevy_asset::{Asset, AssetLoader};
|
use bevy_asset::{Asset, AssetLoader};
|
||||||
use bevy_ecs::prelude::*;
|
use bevy_ecs::prelude::*;
|
||||||
use bevy_reflect::TypePath;
|
use bevy_reflect::TypePath;
|
||||||
|
|
@ -43,7 +42,7 @@ impl std::fmt::Debug for FontData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, TypePath)]
|
#[derive(Debug, Default)]
|
||||||
struct FontLoader;
|
struct FontLoader;
|
||||||
|
|
||||||
#[derive(thiserror::Error, Debug)]
|
#[derive(thiserror::Error, Debug)]
|
||||||
|
|
@ -242,7 +241,7 @@ impl std::fmt::Debug for FontAtlas {
|
||||||
|
|
||||||
impl FontAtlas {
|
impl FontAtlas {
|
||||||
fn new(size: u32) -> Self {
|
fn new(size: u32) -> Self {
|
||||||
let num_bytes = renderer::ash::vk::Format::R8G8B8A8_UNORM.layer_size([size, size, 1]);
|
let num_bytes = size * size * 4;
|
||||||
Self {
|
Self {
|
||||||
image: Arc::new(Image(parking_lot::RwLock::new(ImageInner {
|
image: Arc::new(Image(parking_lot::RwLock::new(ImageInner {
|
||||||
image: vec![0; num_bytes as usize],
|
image: vec![0; num_bytes as usize],
|
||||||
|
|
@ -290,7 +289,7 @@ impl FontAtlas {
|
||||||
let y = y + line_y;
|
let y = y + line_y;
|
||||||
let image_offset = 4 * y as u32 * image.width() + 4 * x as u32;
|
let image_offset = 4 * y as u32 * image.width() + 4 * x as u32;
|
||||||
let glyph_offset = 4 * line_y * width;
|
let glyph_offset = 4 * line_y * width;
|
||||||
let len = renderer::ash::vk::Format::R8G8B8A8_UNORM.row_pitch(width as u32) as usize;
|
let len = 4 * width as usize;
|
||||||
let dst = &mut image.bytes_mut()[image_offset as usize..][..len];
|
let dst = &mut image.bytes_mut()[image_offset as usize..][..len];
|
||||||
let src = &data[glyph_offset as usize..][..len];
|
let src = &data[glyph_offset as usize..][..len];
|
||||||
dst.copy_from_slice(src);
|
dst.copy_from_slice(src);
|
||||||
|
|
|
||||||
168
docs/renderer.md
168
docs/renderer.md
|
|
@ -1,168 +0,0 @@
|
||||||
# Renderer and repository guide
|
|
||||||
|
|
||||||
## Repository overview
|
|
||||||
|
|
||||||
Vidya is a Rust 2024 workspace containing a low-level Vulkan renderer, a Bevy-facing integration crate, small game/window crates, and a separate Bevy text crate. The root package is named `vidya`; the current runnable entry point is the `bevy_integration` example. The renderer is primarily an `ash`-based Vulkan layer, while `bevy_vulkan_render` sets up Bevy render-world infrastructure and currently contains a mock render system rather than a finished Bevy rendering backend.
|
|
||||||
|
|
||||||
Line counts below are `wc -l` counts over Rust source files in each package (not generated/dependency code); for the renderer the 22 files total 14,100 lines. This source inventory differs from the supplied starting estimate of about 24,600 lines across 23 files: the current `crates/renderer/src` glob has 22 `.rs` files and their measured total is 14,100 lines.
|
|
||||||
|
|
||||||
| Workspace member | Approx. Rust LOC | Purpose |
|
|
||||||
|---|---:|---|
|
|
||||||
| `crates/renderer` | 14,100 | Vulkan instance/device/resources, command recording, swapchains, render graph, egui and glyph-atlas code. |
|
|
||||||
| `crates/bevy_vulkan_render` | 1,518 | Bevy render sub-app, world synchronization/extraction, threaded scheduling, and window surfaces. |
|
|
||||||
| `crates/game` | 315 | Standalone winit/egui demo using `renderer::Renderer2`. |
|
|
||||||
| `crates/text` | 484 | Bevy asset/ECS-oriented text and font-atlas implementation built on `cosmic-text`. |
|
|
||||||
| `crates/window` | 1 | Minimal winit dependency crate; its `src/lib.rs` is empty. |
|
|
||||||
| root `vidya` package | 45 | Example host and dependency on `bevy_vulkan_render`; three lines of `src/lib.rs` plus the 42-line example. |
|
|
||||||
|
|
||||||
The code has two overlapping integration paths: `crates/game` directly creates the renderer and surfaces; the root example constructs a Bevy `App` with Bevy's standard plugins plus `bevy_vulkan_render::RenderPlugin`.
|
|
||||||
|
|
||||||
## Dependencies and toolchain
|
|
||||||
|
|
||||||
| Area | Repository configuration |
|
|
||||||
|---|---|
|
|
||||||
| Rust | `rust-toolchain` pins `nightly`; packages use edition 2024. |
|
|
||||||
| Local Bevy | Workspace dependencies point to `/var/code/bevy-engine/bevy` and its crate directories, not crates.io: `bevy`, `bevy_app`, `bevy_asset`, `bevy_derive`, `bevy_ecs`, `bevy_hierarchy`, `bevy_log`, `bevy_math`, `bevy_platform`, `bevy_reflect`, `bevy_tasks`, `bevy_time`, `bevy_transform`, `bevy_utils`, `bevy_window`, and `bevy_winit`. This checkout is Bevy `0.20.0-dev` as recorded in the project setup. `bevy_ecs` enables `multi_threaded` and `trace`. |
|
|
||||||
| Vulkan/window | `ash 0.38.0`, `ash-formats` for Vulkan format metadata/helpers, including the adopted `FormatHelpers` sizing and clear-value helpers, `ash-window 0.13.0`, `vk-mem 0.5.0`, `gpu-allocator` from the `janis-bhm/gpu-allocator` GitHub `main` branch, `winit 0.30.5`, and `raw-window-handle 0.6`. Renderer allocation code specifically uses `gpu-allocator`; `vk-mem` is declared but is not the allocation path in `device.rs`, `buffers.rs`, or `images.rs`. |
|
|
||||||
| Shared crates | `glam 0.33` with `bytemuck`, `rand 0.10`, `derive_more 2`, `petgraph 0.8`, `egui 0.32`, `tracing`, `parking_lot`, among others. See root `[workspace.dependencies]` for the complete list. |
|
|
||||||
| Text | `cosmic-text 0.12.1`, `guillotiere 0.6.2`, and `sys-locale 0.3.2` are used in the renderer and/or text crate. |
|
|
||||||
|
|
||||||
`crates/renderer/src/lib.rs` enables these nightly features (the `text` crate separately opts in to `debug_closure_helpers`):
|
|
||||||
|
|
||||||
| Feature gate | Use visible in the code |
|
|
||||||
|---|---|
|
|
||||||
| `negative_impls` | Explicitly marks command pools/buffers and single-use command objects as `!Send`/`!Sync` where Vulkan command-pool thread ownership is constrained (`commands.rs`). |
|
|
||||||
| `map_try_insert` | Uses `BTreeMap::try_insert`/`HashMap::try_insert` in graph and resource bookkeeping. |
|
|
||||||
| `core_io` | Imports `core::io::BorrowedBuf` in the graph-builder egui demo. |
|
|
||||||
| `core_io_borrowed_buf` | Enables the borrowed-buffer fill APIs used alongside `BorrowedBuf` in that demo. |
|
|
||||||
| `slice_partition_dedup` | Deduplicates selected queue family indices in-place (`queue.rs`). |
|
|
||||||
|
|
||||||
## Renderer crate
|
|
||||||
|
|
||||||
### Public surface and code map
|
|
||||||
|
|
||||||
`renderer/src/lib.rs` owns core device/feature types and exports `ash`, `instance`, `device`, `queue`, `commands`, `render_graph`, `rendering`, `swapchain`, `sync`, and `util`. `buffers`, `images`, `pipeline`, `text`, `debug`, and the egui implementation are declared as private modules. `egui.rs` is loaded as the private `egui_pass` module; `rendering` re-exports its two egui pass functions. The `render_graph` submodules are also private; `render_graph/mod.rs` currently re-exports the legacy graph API only.
|
|
||||||
|
|
||||||
| Source | Responsibilities and key types | Relationship / visibility |
|
|
||||||
|---|---|---|
|
|
||||||
| [`lib.rs`](../crates/renderer/src/lib.rs) | Crate root, feature/property representations (`PhysicalDeviceFeatures`, `PhysicalDeviceProperties`, `PhysicalDeviceInfo`), `Error`/`Result`, `SamplerCache`, `EguiState`, `Renderer2`, and the internal texture manager. `Renderer2::new`, `create_surface`, and async `draw_graph` are the higher-level convenience flow. | Public exports and renderer assembly; creates the instance, adapter, device, graph, and submission/presentation flow. |
|
|
||||||
| [`instance.rs`](../crates/renderer/src/instance.rs) | Vulkan loader/instance setup (`Instance`, `InstanceDesc`, `DebugUtilsCreateInfo`), layer and extension selection, physical-device enumeration, adapter ranking via `choose_adapter_default`, and surface capability queries. | `Instance` is re-exported from crate root and hands `PhysicalDeviceInfo` to `device.rs`. |
|
|
||||||
| [`device.rs`](../crates/renderer/src/device.rs) | Logical `Device`/`DeviceInner`, required extensions and feature chain, GPU allocator, device object lifetime helpers (`DeviceOwned`, `DeviceObject` family), resource allocation types (`Allocation`, `AllocationStrategy`), and reusable device pools. | Adapter creation calls into `queue.rs`, sets up queues and `gpu_allocator`, and is held by buffers, images, commands, and sync objects. |
|
|
||||||
| [`queue.rs`](../crates/renderer/src/queue.rs) | `Queue`, `QueueFamily`, `DeviceQueues`, `DeviceQueueInfos`, queue capability flags and family selection. | Called by logical device initialization; supplies graphics/main, compute and transfer queues to the device. |
|
|
||||||
| [`buffers.rs`](../crates/renderer/src/buffers.rs) | `BufferDesc` and `Buffer`: Vulkan buffer creation, queue-sharing mode, memory allocation/binding, optional mapped `map`/`map_mut`, raw handle and length. | Private module; used by commands, renderer helpers, graph implementations and egui uploads. |
|
|
||||||
| [`images.rs`](../crates/renderer/src/images.rs) | `ImageDesc`, `Image`, `ImageViewDesc`, `ImageView`, `Extent`, `Offset`, `MipRange`, `QueueOwnership`. Uses `ash-formats` format metadata. Handles owned and swapchain images, memory, views, extents and subresources. | Private module; swapchains wrap their external images here. Used by render graph and egui. |
|
|
||||||
| [`memory.rs`](../crates/renderer/src/memory.rs) | Empty placeholder (one blank line). | Not an allocation implementation; allocation is in `device.rs` and resource constructors. |
|
|
||||||
| [`pipeline.rs`](../crates/renderer/src/pipeline.rs) | Descriptor/pipeline descriptions and objects: `DescriptorPool`, `DescriptorSetLayout`, `PipelineLayout`, `Sampler`, `ShaderModule`, `Pipeline`, `PipelineCache`; supports compute and graphics pipeline construction. `ShaderModule::new_from_path` reads SPIR-V words and `new_from_memory` accepts words directly. | Private module; `commands.rs` binds pipelines/descriptors; `EguiState` and rendering helpers build concrete pipelines. No shader compiler/build pipeline is defined here. |
|
|
||||||
| [`commands.rs`](../crates/renderer/src/commands.rs) | Low-level command-pool and command-buffer abstractions (`SingleUseCommandPool`, `CommandList`, command-buffer types/state, `CommandBufferExt`), recording/copy/barrier operations and queue submission/futures. | The legacy graph and one-off uploads use these command buffers; synchronization objects come from `sync.rs`. |
|
|
||||||
| [`swapchain.rs`](../crates/renderer/src/swapchain.rs) | `Surface`, `Swapchain`, `SwapchainConfiguration`, `SwapchainImage`, `SwapchainFrame`; creates/configures surfaces and swapchains, acquires images, and presents them. | Surface owns a replaceable optional swapchain. Swapchain images are represented by `images::Image`/`ImageView`; uses `Fence` and semaphores. |
|
|
||||||
| [`sync.rs`](../crates/renderer/src/sync.rs) | `Fence`, binary/timeline `Semaphore`, `SyncThreadpool`, `FenceFuture`, and pooled synchronization objects. | The swapchain and command submission code use fences/semaphores; `DeviceInner` owns a sync waiter pool and device pools. |
|
|
||||||
| [`render_graph/mod.rs`](../crates/renderer/src/render_graph/mod.rs) | Declares `legacy`, `commands`, `graph_builder`, `recorder`, and `resources`; re-exports `legacy::*`. | Despite the internal new graph files, the externally reachable `RenderGraph` is the `legacy.rs` implementation. `#![allow(dead_code)]` covers the module tree. |
|
|
||||||
| [`render_graph/legacy.rs`](../crates/renderer/src/render_graph/legacy.rs) | Current reachable graph API: `RenderGraph`, `GraphResourceId`, `GraphResourceDesc`, `GraphResource`, `PassDesc`, `RenderContext`, `Access`, load/store ops and helpers such as `clear_pass`/`present_pass`. Stores imported/created resources, pass access declarations and output resources; `resolve` orders passes and records a `CommandList` for its caller to submit. | Re-exported by `render_graph/mod.rs`; used by `Renderer2::draw_graph`, `rendering/mod.rs` and `egui.rs`. Although named legacy, this is the path called by the current rendering code. |
|
|
||||||
| [`render_graph/resources.rs`](../crates/renderer/src/render_graph/resources.rs) | Newer command-graph resource abstraction: `Resource`, `ResourceId`, ranges/access records, `Buffer`/`Texture` handles and slices/regions, `Read`/`Write`/`ReadWrite` wrappers. | Internal to newer `commands.rs`/`recorder.rs`; not re-exported from `render_graph/mod.rs`. |
|
|
||||||
| [`render_graph/commands.rs`](../crates/renderer/src/render_graph/commands.rs) | New command API (`Command`, `ImportResource`, `Copy`, `ClearTexture`, `UpdateBuffer`, rendering/pipeline/buffer/descriptor/draw commands, `PipelineBarrier`); each command declares resource side effects and implements recording. | Uses newer resource wrappers and `CommandRecorder`, separate from the currently re-exported legacy `PassDesc` graph. Several commands remain incomplete; see current state. |
|
|
||||||
| [`render_graph/recorder.rs`](../crates/renderer/src/render_graph/recorder.rs) | New `CommandRecorder`, `CommandList`, `RenderPass`, side-effect maps, command metadata and access/barrier collection. | Intended to translate new graph commands to Vulkan command buffers; recorder resource lookups and barrier application contain explicit unimplemented code. |
|
|
||||||
| [`render_graph/graph_builder.rs`](../crates/renderer/src/render_graph/graph_builder.rs) | New `GraphResourceRegistry` and `GraphBuilder`, wrappers for buffer and staging resources, plus an `api_demo::egui_graph` sample that packs vertices/indices/draw data with `BorrowedBuf`. | Not a wired-up implementation of the current legacy graph: the resource-creation methods are `todo!()` and part of the sample is `unimplemented!()`. |
|
|
||||||
| [`rendering/mod.rs`](../crates/renderer/src/rendering/mod.rs) | `Wireframe` GPU data/pipeline example and `Wireframe::pass`; exports `egui_pre_pass` and `egui_pass` from the egui module. | Builds passes on the legacy `RenderGraph`; uses `Buffer`, `Pipeline`, graph access declarations, and commands. |
|
|
||||||
| [`egui.rs`](../crates/renderer/src/egui.rs) | `egui_pre_pass` uploads egui texture deltas (including staging/atlas packing) and `egui_pass` adds drawing work; uses `EguiState`, texture IDs, buffers, images, samplers, pipeline, and graph commands. | Private module imported by `rendering/mod.rs`; current code exercises the legacy graph, not the in-progress typed graph API. |
|
|
||||||
| [`text.rs`](../crates/renderer/src/text.rs) | Private glyph rasterization and atlas data structures (`FontId`, font stores/atlas sets, `get_outlined_glyph_texture`) based on `cosmic-text` and `guillotiere`. Embeds `assets/fonts/Roboto.ttf` and `NotoSansSC.ttf`. | Renderer-local/private text implementation; not the same module as the public Bevy-oriented `crates/text` crate. Contains an unfinished subpixel-mask case. |
|
|
||||||
| [`util.rs`](../crates/renderer/src/util.rs) | Shared Vulkan helpers and data types (`DebugName`, `Rect2D`, `F32`, `Rgba`, `Rgba8`, bit iterators, `CStringList`, drop/lifetime helpers and internal `WeakVec`). | Used across resource, debug, image and graph code. |
|
|
||||||
| [`debug.rs`](../crates/renderer/src/debug.rs) | Vulkan debug messenger callback, translating validation severities into `tracing` levels. | Used by instance setup; intentionally private. |
|
|
||||||
|
|
||||||
### Initialization, resources, and commands
|
|
||||||
|
|
||||||
The normal setup path begins with `Instance::new(&InstanceDesc)` (`instance.rs`), which loads Vulkan through `ash`, enables supported requested/WSI extensions and creates debug-utils state. The default description requests surface support and the Khronos validation layer/settings (unsupported layers are logged and filtered). Adapter enumeration exposes device properties/features as `PhysicalDeviceInfo`.
|
|
||||||
|
|
||||||
`Instance::choose_adapter_default(surface, required_extensions, required_features)` ranks adapters. Its comparator attempts to prefer swapchain/required-extension support and requested `PhysicalDeviceFeatures`, requires preference for Vulkan 1.3 `synchronization2`, `dynamic_rendering`, and `maintenance4`, then prefers discrete GPUs, newer API versions, more device-local memory, and larger 2D image limits. It is ranking logic, not a robust suitability filter: required extension checks return `Less` for the left-hand candidate rather than first excluding every unsuitable device, and `create_logical_device` warns and omits unsupported requested extensions. An important limitation visible in code: the `surface` argument is currently ignored at the `// TODO` surface-compatibility check; choosing an adapter does not actually validate that it can present to that surface. `PhysicalDeviceFeatures` is a chain of core and version/extension feature structs; `create_logical_device` pushes those into `vk::DeviceCreateInfo`.
|
|
||||||
|
|
||||||
`PhysicalDeviceInfo::create_logical_device` asks `DeviceQueueInfos::select_queue_families` for queue families, creates the logical device, retrieves queues, creates extension loaders, then creates `gpu_allocator::vulkan::Allocator` and resource pools. Queue selection chooses the first family containing both `GRAPHICS` and `COMPUTE`, decrements its available queue count, and asserts that this selected family has `PRESENT`. It then takes another available compute family and transfer family if found; missing compute/transfer queues alias the graphics queue. Therefore a display handle that did not produce presentation support can reach the explicit `Selected graphics queue family does not support presentation` assertion. The presentation flags are derived from a display handle, and the queue-selection path is not a general strategy for selecting a distinct present-only family.
|
|
||||||
|
|
||||||
The allocator is stored behind a mutex on `DeviceInner`. Both `Buffer::new` and `Image::new` create the Vulkan object, query memory requirements, allocate using `AllocationStrategy::{AllocatorManaged,Dedicated}`, bind the returned allocation, and retain it for destruction. `BufferDesc`/`ImageDesc` include memory location, usage, queue family flags and allocation strategy. Buffers may expose mapped bytes when the allocator returns a mapped allocation. Images also support externally owned swapchain images and cached weak image-view references. `memory.rs` itself has no implementation.
|
|
||||||
|
|
||||||
There is no universal upload subsystem in `buffers.rs`/`images.rs`; upload paths are explicit at call sites. For example, `Wireframe::from_triangles_indexed` writes positions/indices/colors to a `CpuToGpu` staging buffer, copies into `GpuOnly` vertex/index buffers via a one-off command buffer, and adds transfer-to-vertex/index barriers. The egui pre-pass similarly writes texture data to mapped staging storage and records graph copy work. Shader modules load SPIR-V from a path or word slice; pipeline creation consumes `GraphicsPipelineDesc` or `ComputePipelineDesc`, descriptor layouts/pools, and optional `PipelineCache`. Shader source compilation is outside this crate's code.
|
|
||||||
|
|
||||||
### Surfaces, frames, and synchronization
|
|
||||||
|
|
||||||
`Surface::new_from_raw_window_handle` creates a Vulkan surface from raw handles; `Surface::headless` is also defined. `Surface::configure` avoids recreation for an equal config on the same device, otherwise creates a replacement swapchain using the old swapchain handle. `SwapchainConfiguration` includes extent/format/present mode/usage and image-count options, while capability validation chooses compatible settings. Acquiring a frame asynchronously reserves a per-frame acquire semaphore, performs `acquire_next_image` through `smol::unblock` under the swapchain lock, creates an `Image` and view for the acquired swapchain image, and waits on a fence. `SwapchainImage` and `SwapchainFrame` are `must_use` and expose `present`.
|
|
||||||
|
|
||||||
Swapchain synchronization is not just a generic frame fence ring: the implementation creates acquire semaphores based on the number of in-flight frames and a release semaphore for every swapchain image. Submission waits on the acquire semaphore and signals the release semaphore; presentation waits on the release semaphore. `Swapchain::max_in_flight_images` is image count minus the surface minimum image count. The general `sync.rs` API also supports dedicated/pooled fences, binary/timeline semaphores, and fence futures serviced by a bounded waiter thread pool. `Renderer2::draw_graph` demonstrates acquire → import framebuffer → graph resolve → submit using acquire/release semaphores → await → present.
|
|
||||||
|
|
||||||
### Render graph: current path and in-progress path
|
|
||||||
|
|
||||||
The currently wired graph is `render_graph::legacy::RenderGraph`, re-exported by `render_graph/mod.rs`. It owns resources and `PassDesc`s with declared read/write `Access` values and optional one-shot `RecordFn`s. Imported framebuffer/images/buffers and created resource descriptions receive graph IDs. Outputs are marked explicitly; resolution determines which passes feed outputs and prepares resources/barriers before executing recorded passes. `Renderer2::draw_graph` constructs this graph and calls `resolve`; the wireframe and egui rendering functions add passes to it. In `legacy.rs`, comments discuss future resource aliasing, but should not be read as proof that aliasing is fully implemented.
|
|
||||||
|
|
||||||
The sibling `resources.rs`, `commands.rs`, `recorder.rs`, and `graph_builder.rs` form a newer typed command/resource design, but are private submodules and are not re-exported or connected to the root `RenderGraph` API. `resources.rs` tracks buffer/image ranges and stage/access/layout side effects; `commands.rs` describes copies, clears, updates, rendering scopes, binding, draws and barriers; `recorder.rs` is intended to lower command lists and insert transitions; `graph_builder.rs` contains the graph-resource registry and a sample upload/build path. That path uses staging buffers and `core::io::BorrowedBuf` for writing several egui draw-data arrays into one mapped region. However, the builder methods that create command lists and make/import buffers are `todo!()`, and the recorder still has unimplemented handle accessors/barrier code. Treat this as an experimental/incomplete path, not as the graph used by `draw_graph`.
|
|
||||||
|
|
||||||
### Text, egui, and orchestration
|
|
||||||
|
|
||||||
The renderer's private `text.rs` embeds two font files and manages per-font/per-size glyph atlases; `get_outlined_glyph_texture` rasterizes glyphs through `cosmic-text`/Swash and packs masks/color glyphs. It is separate from `crates/text/src/lib.rs`, which defines a Bevy `FontData` asset, font loader, ECS text component and its own atlas machinery. Both source trees embed font paths from `assets/fonts`.
|
|
||||||
|
|
||||||
The renderer egui path in `egui.rs` consumes `egui::FullOutput`: texture deltas are converted to image/atlas staging uploads, and tessellated primitives are emitted as rendering passes using the egui pipeline and descriptor state. `rendering/mod.rs` re-exports `egui_pre_pass` and `egui_pass` alongside the `Wireframe` graph pass. `Renderer2` is a direct-use convenience owner for instance/device/samplers/textures/egui state and surfaces; its `draw_graph` orchestrates one frame. Bevy has a separate plugin/schedule integration and currently does not call this orchestration as an active render backend.
|
|
||||||
|
|
||||||
## Bevy integration crate
|
|
||||||
|
|
||||||
`crates/bevy_vulkan_render/src/lib.rs` declares `RenderPlugin`, the `RenderApp` sub-app label, `Render` and `RenderStartup` schedules, and ordered `RenderSystems` sets (`ExtractCommands`, `Prepare`, `Render`, `Cleanup`, `PostCleanup`). `RenderPlugin::build` adds `ExtractPlugin`, initializes render schedules on the sub-app and installs `mock_render_system`. `RenderDevice` is a Bevy resource wrapper around `renderer::device::Device`. An `init_vulkan` function exists and requests sampler anisotropy, non-solid fill, multi-draw-indirect, Vulkan 1.1/1.2/1.3 features and mesh shaders, but it is unused according to both source and compiler dead-code warnings.
|
|
||||||
|
|
||||||
`extract_plugin.rs` creates the `RenderApp` `SubApp`, installs `ExtractSchedule`, and arranges sync/extract each frame. It moves the main `World` into a temporary `MainWorld` resource for extraction, restores it afterward, and delays `ExtractSchedule` deferred-command application into the render schedule's `ExtractCommands` set. This leaves the main thread free earlier for pipelining.
|
|
||||||
|
|
||||||
`extract_param.rs` defines `Extract<'w, 's, P>`, a `SystemParam` wrapper for applying a read-only system parameter to `MainWorld` during `ExtractSchedule`. It registers read-only main-world access and intentionally disallows contained mutating system params.
|
|
||||||
|
|
||||||
`sync_world.rs` implements `SyncWorldPlugin` and the `SyncToRenderWorld` marker. Observer records are processed by `entity_sync_system` to maintain the main/render entity link: `RenderEntity` on the main side points to the render entity; `MainEntity` points back. Custom `QueryData` implementations let `Query<RenderEntity>` and `Query<MainEntity>` return the wrapped `Entity` directly. Temporary render entities are despawned in post-cleanup. A TODO calls out batching pending sync records.
|
|
||||||
|
|
||||||
`window/mod.rs` holds extracted physical window metadata in `ExtractedWindows`, keyed by entity, and stores a `Surfaces` map keyed per window entity. `extract_windows` tracks primary window, dimensions, closing/removal, and initial presentation state. `need_surface_configuration` detects new/unconfigured or resized windows; `configure_surfaces` creates a `Surface` from the raw handles and configures/reconfigures its swapchain. These functions and resources are currently reported unused by the compiler, so their source structure is present but not yet integrated into active plugin systems.
|
|
||||||
|
|
||||||
`rendering.rs` defines `RenderingPlugin` and `RenderExtractApp`. When installed after `RenderPlugin`, it transfers the `RenderApp` between the main app and a spawned render thread using bounded async channels, executes render-app updates there, and extracts/sends it back each frame. The root example installs `RenderPlugin`, but does not install `RenderingPlugin`; the current `RenderPlugin` only installs a mock render function.
|
|
||||||
|
|
||||||
## Current state and known unfinished work
|
|
||||||
|
|
||||||
### Build and warnings
|
|
||||||
|
|
||||||
On the checked-out tree, `cargo check --workspace --all-targets` completes successfully. It emits warnings, including deprecated `glam::Mat4::perspective_lh` and `Mat4::look_at_rh` calls in `rendering/mod.rs`, a deprecated standard-library atomic `fetch_update` use, unused imports/variables, and dead code. Specifically, compiler warnings expose that `init_vulkan`, the window extraction/configuration functions, `render_start`/`render_startup`, and parts of sync tracking are unused. This is a compile check, not evidence that a Vulkan device/surface runs successfully on a target machine.
|
|
||||||
|
|
||||||
### Marker inventory (source scan)
|
|
||||||
|
|
||||||
Across `crates/renderer/src`, `crates/bevy_vulkan_render/src`, `crates/game/src`, and `crates/text/src`, a literal scan finds **21 `TODO`/`FIXME` occurrences** and **19 `todo!`/`unimplemented!` occurrences**. The latter includes test-only code; it does not imply 19 active runtime paths. The locations and notable behaviors are:
|
|
||||||
|
|
||||||
| File / lines | Finding |
|
|
||||||
|---|---|
|
|
||||||
| `renderer/src/instance.rs:368` | Surface compatibility in default adapter ranking is a TODO; `:474` XCB presentation support is `todo!("xcb")`. |
|
|
||||||
| `renderer/src/queue.rs:326-329` | Explicit assertion requires selected graphics+compute family to present. |
|
|
||||||
| `renderer/src/render_graph/graph_builder.rs:41,44,53,59` | New builder methods are `todo!()`; `:266` has an `unimplemented!()` factory in the demo path. |
|
|
||||||
| `renderer/src/render_graph/recorder.rs:23,27,31,35,39,43,344` | `CommandRecorder` accessors and image barrier recording are unimplemented/todo. `:339` also notes missing image aspect information. |
|
|
||||||
| `renderer/src/render_graph/commands.rs:316,592` | Render load/store operations are noted as TODO; `PipelineBarrier::apply` is `todo!()`. |
|
|
||||||
| `renderer/src/render_graph/resources.rs:46,250` | TODOs flag buffer-row range units and possible write-order conflict handling. |
|
|
||||||
| `renderer/src/render_graph/legacy.rs:799,809` | TODOs in graph hazard/dependency handling for first-pass checks. |
|
|
||||||
| `renderer/src/text.rs:71,162,281-282` | Atlas naming, host-visible/coherent image considerations, and `SubpixelMask` glyph content remain TODO/todo. |
|
|
||||||
| `renderer/src/sync.rs:361,373` | `vk::Handle::from_raw` for binary and timeline semaphore wrappers is unimplemented. |
|
|
||||||
| `renderer/src/device.rs:1107-1113` | A `#[cfg(test)]` helper contains a `summon` stub with `unimplemented!()`; test-only. |
|
|
||||||
| `renderer/src/lib.rs:610`; `swapchain.rs:593`; `commands.rs:749`; `egui.rs:320` | Additional behavior/design TODO comments; swapchain present-id/wait support is noted as optional work. |
|
|
||||||
| `bevy_vulkan_render/src/sync_world.rs:217` | TODO to batch pending sync records. |
|
|
||||||
| `game/src/main.rs:49,58,85` | TODOs call out error handling, resize handling and unfinished draw-request logging/path. |
|
|
||||||
| `text/src/lib.rs:123,214,336-337` | Separate Bevy text implementation has similar atlas/image TODOs and an unfinished subpixel-mask case. |
|
|
||||||
|
|
||||||
The largest architectural caveat is that the typed `render_graph` command/recorder/builder files are not active wiring: the legacy graph is still the sole graph re-export, and the new recorder contains explicit stubs. The Bevy crate likewise has substantial extraction/window/thread infrastructure, but its current installed render schedule uses a mock system and its Vulkan initializer/surface functions are unused. Bevy-facing rendering should therefore be described as scaffolding/integration work in progress rather than a complete rendered-frame backend.
|
|
||||||
|
|
||||||
## Build and run
|
|
||||||
|
|
||||||
1. Use the repository's nightly toolchain (`rustup` will honor `rust-toolchain`). The renderer has compile-time `include_bytes!` references to font files; the repository currently contains the generated flat and directory layouts. To regenerate the expected layouts, run the fetch script from the font directory:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
cd assets/fonts
|
|
||||||
./fetch.sh
|
|
||||||
cd ../..
|
|
||||||
```
|
|
||||||
|
|
||||||
`fetch.sh` downloads the upstream Google Fonts files; network access is needed only for this prerequisite. It creates `Roboto/Roboto-VariableFont_wdth,wght.ttf` and `Noto_Sans_SC/NotoSansSC-VariableFont_wght.ttf` from flat files. Renderer-local text also includes flat `Roboto.ttf` and `NotoSansSC.ttf`.
|
|
||||||
|
|
||||||
2. Check the workspace and all targets:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
cargo check --workspace --all-targets
|
|
||||||
```
|
|
||||||
|
|
||||||
3. Run the Bevy example:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
cargo run --example bevy_integration
|
|
||||||
```
|
|
||||||
|
|
||||||
The example creates a Bevy app with minimal, asset, window/winit, camera/mesh/text and `VulkanRenderPlugin` plugins. It currently prints `Hello, world!` before running; the installed Vulkan render plugin uses a mock render system. For direct renderer/egui experimentation, `crates/game/src/main.rs` is the standalone winit entry point, though it too has TODO-marked draw/resize work and requires a Vulkan-capable system/display.
|
|
||||||
Loading…
Reference in a new issue