Compare commits
No commits in common. "dbc4294c0933aace36257bef62145fd097568b99" and "fdfc74c6681aa069ebd8642d5726a4483c81bf70" have entirely different histories.
dbc4294c09
...
fdfc74c668
|
@ -1,3 +0,0 @@
|
||||||
[target.x86_64-unknown-linux-gnu]
|
|
||||||
linker = "clang"
|
|
||||||
rustflags = ["-C", "link-arg=-fuse-ld=/usr/bin/mold"]
|
|
|
@ -7,11 +7,6 @@ members = [
|
||||||
"crates/game"
|
"crates/game"
|
||||||
]
|
]
|
||||||
|
|
||||||
[profile.debug-release]
|
|
||||||
inherits = "release"
|
|
||||||
opt-level = 2
|
|
||||||
debug = true
|
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
anyhow = "1.0.89"
|
anyhow = "1.0.89"
|
||||||
ash = "0.38.0"
|
ash = "0.38.0"
|
||||||
|
|
|
@ -26,17 +26,6 @@ pub struct BufferDesc {
|
||||||
pub alloc_flags: vk_mem::AllocationCreateFlags,
|
pub alloc_flags: vk_mem::AllocationCreateFlags,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::hash::Hash for BufferDesc {
|
|
||||||
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
|
||||||
self.flags.hash(state);
|
|
||||||
self.size.hash(state);
|
|
||||||
self.usage.hash(state);
|
|
||||||
self.queue_families.hash(state);
|
|
||||||
self.mem_usage.hash(state);
|
|
||||||
self.alloc_flags.bits().hash(state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::fmt::Debug for BufferDesc {
|
impl std::fmt::Debug for BufferDesc {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
f.debug_struct("BufferDesc")
|
f.debug_struct("BufferDesc")
|
||||||
|
@ -60,20 +49,6 @@ impl std::fmt::Debug for BufferDesc {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Eq for BufferDesc {}
|
|
||||||
impl PartialEq for BufferDesc {
|
|
||||||
fn eq(&self, other: &Self) -> bool {
|
|
||||||
self.flags == other.flags
|
|
||||||
// for hashmaps, `Eq` may be more strict than `Hash`
|
|
||||||
&& self.name == other.name
|
|
||||||
&& self.size == other.size
|
|
||||||
&& self.usage == other.usage
|
|
||||||
&& self.queue_families == other.queue_families
|
|
||||||
&& self.mem_usage == other.mem_usage
|
|
||||||
&& self.alloc_flags.bits() == other.alloc_flags.bits()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for BufferDesc {
|
impl Default for BufferDesc {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
|
|
@ -64,7 +64,6 @@ impl SingleUseCommandPool {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// get the underlying pool, bypassing the mutex
|
/// get the underlying pool, bypassing the mutex
|
||||||
#[allow(dead_code)]
|
|
||||||
pub unsafe fn pool(&self) -> vk::CommandPool {
|
pub unsafe fn pool(&self) -> vk::CommandPool {
|
||||||
self.pool.data_ptr().read()
|
self.pool.data_ptr().read()
|
||||||
}
|
}
|
||||||
|
@ -130,8 +129,6 @@ pub enum CommandBufferState {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
struct CommandBufferState2(AtomicU8);
|
struct CommandBufferState2(AtomicU8);
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
impl CommandBufferState2 {
|
impl CommandBufferState2 {
|
||||||
fn initial() -> Self {
|
fn initial() -> Self {
|
||||||
Self(AtomicU8::new(CommandBufferState::Initial as u8))
|
Self(AtomicU8::new(CommandBufferState::Initial as u8))
|
||||||
|
@ -191,13 +188,11 @@ impl !Sync for SingleUseCommand {}
|
||||||
impl SingleUseCommand {
|
impl SingleUseCommand {
|
||||||
pub fn new(device: Device, pool: Arc<SingleUseCommandPool>) -> VkResult<Self> {
|
pub fn new(device: Device, pool: Arc<SingleUseCommandPool>) -> VkResult<Self> {
|
||||||
let buffer = unsafe {
|
let buffer = unsafe {
|
||||||
let buffer = pool.pool.with_locked(|pool| {
|
let alloc_info = vk::CommandBufferAllocateInfo::default()
|
||||||
let alloc_info = vk::CommandBufferAllocateInfo::default()
|
.command_buffer_count(1)
|
||||||
.command_buffer_count(1)
|
.command_pool(pool.pool())
|
||||||
.command_pool(*pool)
|
.level(vk::CommandBufferLevel::PRIMARY);
|
||||||
.level(vk::CommandBufferLevel::PRIMARY);
|
let buffer = device.dev().allocate_command_buffers(&alloc_info)?[0];
|
||||||
Ok(device.dev().allocate_command_buffers(&alloc_info)?[0])
|
|
||||||
})?;
|
|
||||||
|
|
||||||
device.dev().begin_command_buffer(
|
device.dev().begin_command_buffer(
|
||||||
buffer,
|
buffer,
|
||||||
|
|
|
@ -184,7 +184,7 @@ pub fn egui_pre_pass(
|
||||||
rg.import_image(
|
rg.import_image(
|
||||||
img,
|
img,
|
||||||
Access {
|
Access {
|
||||||
layout: vk::ImageLayout::GENERAL,
|
layout: Some(vk::ImageLayout::GENERAL),
|
||||||
..Access::undefined()
|
..Access::undefined()
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -229,12 +229,12 @@ pub fn egui_pre_pass(
|
||||||
Access {
|
Access {
|
||||||
stage: vk::PipelineStageFlags2::NONE,
|
stage: vk::PipelineStageFlags2::NONE,
|
||||||
mask: vk::AccessFlags2::empty(),
|
mask: vk::AccessFlags2::empty(),
|
||||||
layout: vk::ImageLayout::UNDEFINED,
|
layout: Some(vk::ImageLayout::UNDEFINED),
|
||||||
},
|
},
|
||||||
Access {
|
Access {
|
||||||
stage: vk::PipelineStageFlags2::TRANSFER,
|
stage: vk::PipelineStageFlags2::TRANSFER,
|
||||||
mask: vk::AccessFlags2::TRANSFER_WRITE,
|
mask: vk::AccessFlags2::TRANSFER_WRITE,
|
||||||
layout: vk::ImageLayout::TRANSFER_DST_OPTIMAL,
|
layout: Some(vk::ImageLayout::TRANSFER_DST_OPTIMAL),
|
||||||
},
|
},
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
|
@ -270,12 +270,12 @@ pub fn egui_pre_pass(
|
||||||
Access {
|
Access {
|
||||||
stage: vk::PipelineStageFlags2::TRANSFER,
|
stage: vk::PipelineStageFlags2::TRANSFER,
|
||||||
mask: vk::AccessFlags2::TRANSFER_WRITE,
|
mask: vk::AccessFlags2::TRANSFER_WRITE,
|
||||||
layout: vk::ImageLayout::TRANSFER_DST_OPTIMAL,
|
layout: Some(vk::ImageLayout::TRANSFER_DST_OPTIMAL),
|
||||||
},
|
},
|
||||||
Access {
|
Access {
|
||||||
stage: vk::PipelineStageFlags2::TRANSFER,
|
stage: vk::PipelineStageFlags2::TRANSFER,
|
||||||
mask: vk::AccessFlags2::TRANSFER_READ,
|
mask: vk::AccessFlags2::TRANSFER_READ,
|
||||||
layout: vk::ImageLayout::TRANSFER_SRC_OPTIMAL,
|
layout: Some(vk::ImageLayout::TRANSFER_SRC_OPTIMAL),
|
||||||
},
|
},
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
|
@ -285,12 +285,12 @@ pub fn egui_pre_pass(
|
||||||
Access {
|
Access {
|
||||||
stage: vk::PipelineStageFlags2::NONE,
|
stage: vk::PipelineStageFlags2::NONE,
|
||||||
mask: vk::AccessFlags2::empty(),
|
mask: vk::AccessFlags2::empty(),
|
||||||
layout: vk::ImageLayout::GENERAL,
|
layout: Some(vk::ImageLayout::GENERAL),
|
||||||
},
|
},
|
||||||
Access {
|
Access {
|
||||||
stage: vk::PipelineStageFlags2::TRANSFER,
|
stage: vk::PipelineStageFlags2::TRANSFER,
|
||||||
mask: vk::AccessFlags2::TRANSFER_WRITE,
|
mask: vk::AccessFlags2::TRANSFER_WRITE,
|
||||||
layout: vk::ImageLayout::TRANSFER_DST_OPTIMAL,
|
layout: Some(vk::ImageLayout::TRANSFER_DST_OPTIMAL),
|
||||||
},
|
},
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
|
@ -334,12 +334,12 @@ pub fn egui_pre_pass(
|
||||||
Access {
|
Access {
|
||||||
stage: vk::PipelineStageFlags2::TRANSFER,
|
stage: vk::PipelineStageFlags2::TRANSFER,
|
||||||
mask: vk::AccessFlags2::TRANSFER_WRITE,
|
mask: vk::AccessFlags2::TRANSFER_WRITE,
|
||||||
layout: vk::ImageLayout::TRANSFER_DST_OPTIMAL,
|
layout: Some(vk::ImageLayout::TRANSFER_DST_OPTIMAL),
|
||||||
},
|
},
|
||||||
Access {
|
Access {
|
||||||
stage: vk::PipelineStageFlags2::ALL_COMMANDS,
|
stage: vk::PipelineStageFlags2::ALL_COMMANDS,
|
||||||
mask: vk::AccessFlags2::empty(),
|
mask: vk::AccessFlags2::empty(),
|
||||||
layout: vk::ImageLayout::GENERAL,
|
layout: Some(vk::ImageLayout::GENERAL),
|
||||||
},
|
},
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
|
@ -374,13 +374,13 @@ pub fn egui_pre_pass(
|
||||||
(
|
(
|
||||||
*id,
|
*id,
|
||||||
Access {
|
Access {
|
||||||
layout: vk::ImageLayout::GENERAL,
|
layout: Some(vk::ImageLayout::GENERAL),
|
||||||
..Access::undefined()
|
..Access::undefined()
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
record: Some(record),
|
record,
|
||||||
});
|
});
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -730,7 +730,7 @@ pub fn egui_pass(
|
||||||
rg.add_pass(PassDesc {
|
rg.add_pass(PassDesc {
|
||||||
reads,
|
reads,
|
||||||
writes,
|
writes,
|
||||||
record: Some(record),
|
record,
|
||||||
});
|
});
|
||||||
|
|
||||||
Ok(to_remove_tex_ids)
|
Ok(to_remove_tex_ids)
|
||||||
|
|
|
@ -1,8 +1,4 @@
|
||||||
use std::{
|
use std::{borrow::Cow, collections::HashMap, sync::Arc};
|
||||||
borrow::Cow,
|
|
||||||
collections::HashMap,
|
|
||||||
sync::{Arc, Weak},
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
define_device_owned_handle,
|
define_device_owned_handle,
|
||||||
|
@ -37,6 +33,7 @@ pub struct ImageDesc {
|
||||||
impl std::hash::Hash for ImageDesc {
|
impl std::hash::Hash for ImageDesc {
|
||||||
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
||||||
self.flags.hash(state);
|
self.flags.hash(state);
|
||||||
|
self.name.hash(state);
|
||||||
self.format.hash(state);
|
self.format.hash(state);
|
||||||
self.kind.hash(state);
|
self.kind.hash(state);
|
||||||
self.mip_levels.hash(state);
|
self.mip_levels.hash(state);
|
||||||
|
@ -131,8 +128,8 @@ define_device_owned_handle! {
|
||||||
format: vk::Format,
|
format: vk::Format,
|
||||||
views: Mutex<HashMap<ImageViewDesc, vk::ImageView>>,
|
views: Mutex<HashMap<ImageViewDesc, vk::ImageView>>,
|
||||||
aliases: Mutex<HashMap<ImageDesc, Arc<Image>>>,
|
aliases: Mutex<HashMap<ImageDesc, Arc<Image>>>,
|
||||||
parent: Option<Weak<Image>>,
|
parent: Option<Arc<Image>>,
|
||||||
is_swapchain_image: bool,
|
is_swapchain_image:bool,
|
||||||
} => |this| if !this.is_swapchain_image {
|
} => |this| if !this.is_swapchain_image {
|
||||||
unsafe {
|
unsafe {
|
||||||
for &view in this.views.lock().values() {
|
for &view in this.views.lock().values() {
|
||||||
|
@ -269,19 +266,20 @@ impl Image {
|
||||||
self.size.depth
|
self.size.depth
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_parent_or_self(self: &Arc<Self>) -> Arc<Image> {
|
fn get_parent(self: &Arc<Self>) -> Arc<Image> {
|
||||||
self.parent
|
self.parent.clone().unwrap_or_else(|| self.clone())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_alloc(&self) -> Option<&vk_mem::Allocation> {
|
||||||
|
self.alloc
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|weak| weak.upgrade().unwrap())
|
.or(self.parent.as_ref().and_then(|image| image.get_alloc()))
|
||||||
.unwrap_or_else(|| self.clone())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn get_alias(self: &Arc<Self>, desc: ImageDesc) -> VkResult<Arc<Self>> {
|
pub unsafe fn get_alias(self: &Arc<Self>, desc: ImageDesc) -> VkResult<Arc<Self>> {
|
||||||
self.get_parent_or_self().get_alias_inner(desc)
|
self.get_parent().get_alias_inner(desc)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// must only be called on the primogenitor of an image.
|
|
||||||
/// get the primogenitor with [`Self::get_parent_or_self()`]
|
|
||||||
unsafe fn get_alias_inner(self: Arc<Self>, desc: ImageDesc) -> VkResult<Arc<Image>> {
|
unsafe fn get_alias_inner(self: Arc<Self>, desc: ImageDesc) -> VkResult<Arc<Image>> {
|
||||||
use std::collections::hash_map::Entry::*;
|
use std::collections::hash_map::Entry::*;
|
||||||
match self.aliases.lock().entry(desc.clone()) {
|
match self.aliases.lock().entry(desc.clone()) {
|
||||||
|
@ -329,8 +327,7 @@ impl Image {
|
||||||
.mip_levels(mip_levels);
|
.mip_levels(mip_levels);
|
||||||
|
|
||||||
let alloc = self
|
let alloc = self
|
||||||
.alloc
|
.get_alloc()
|
||||||
.as_ref()
|
|
||||||
.expect("no alloc associated with image. is this the framebuffer?");
|
.expect("no alloc associated with image. is this the framebuffer?");
|
||||||
|
|
||||||
let image = unsafe {
|
let image = unsafe {
|
||||||
|
@ -345,6 +342,7 @@ impl Image {
|
||||||
image
|
image
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let parent = self.parent.clone().unwrap_or(self.clone());
|
||||||
let alias = Self::construct(
|
let alias = Self::construct(
|
||||||
self.device().clone(),
|
self.device().clone(),
|
||||||
image,
|
image,
|
||||||
|
@ -354,8 +352,8 @@ impl Image {
|
||||||
format,
|
format,
|
||||||
Mutex::new(HashMap::new()),
|
Mutex::new(HashMap::new()),
|
||||||
Mutex::new(HashMap::new()),
|
Mutex::new(HashMap::new()),
|
||||||
Some(Arc::downgrade(&self)),
|
Some(parent.clone()),
|
||||||
self.is_swapchain_image,
|
parent.is_swapchain_image,
|
||||||
)?;
|
)?;
|
||||||
Ok(vacant.insert(Arc::new(alias)).clone())
|
Ok(vacant.insert(Arc::new(alias)).clone())
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,6 @@ mod egui_pass;
|
||||||
mod images;
|
mod images;
|
||||||
mod pipeline;
|
mod pipeline;
|
||||||
mod render_graph;
|
mod render_graph;
|
||||||
mod rendering;
|
|
||||||
mod sync;
|
mod sync;
|
||||||
mod util;
|
mod util;
|
||||||
|
|
||||||
|
@ -442,7 +441,6 @@ impl PhysicalDeviceProperties {
|
||||||
pub struct PhysicalDevice {
|
pub struct PhysicalDevice {
|
||||||
pdev: vk::PhysicalDevice,
|
pdev: vk::PhysicalDevice,
|
||||||
queue_families: DeviceQueueFamilies,
|
queue_families: DeviceQueueFamilies,
|
||||||
#[allow(dead_code)]
|
|
||||||
properties: PhysicalDeviceProperties,
|
properties: PhysicalDeviceProperties,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -731,7 +729,7 @@ impl Swapchain {
|
||||||
format,
|
format,
|
||||||
)
|
)
|
||||||
.inspect(|img| {
|
.inspect(|img| {
|
||||||
_ = img.get_view(images::ImageViewDesc {
|
img.get_view(images::ImageViewDesc {
|
||||||
name: Some(format!("swapchain-{swapchain:?}-image-{i}-view").into()),
|
name: Some(format!("swapchain-{swapchain:?}-image-{i}-view").into()),
|
||||||
kind: vk::ImageViewType::TYPE_2D,
|
kind: vk::ImageViewType::TYPE_2D,
|
||||||
format,
|
format,
|
||||||
|
@ -2536,6 +2534,7 @@ impl<W> Renderer<W> {
|
||||||
let mut rg = render_graph::RenderGraph::new();
|
let mut rg = render_graph::RenderGraph::new();
|
||||||
let (textures_to_remove, cmds) = util::timed("record command buffer", || {
|
let (textures_to_remove, cmds) = util::timed("record command buffer", || {
|
||||||
let framebuffer = rg.import_image(frame.image.clone(), Access::undefined());
|
let framebuffer = rg.import_image(frame.image.clone(), Access::undefined());
|
||||||
|
rg.mark_as_output(framebuffer);
|
||||||
|
|
||||||
render_graph::clear_pass(&mut rg, clear_color, framebuffer);
|
render_graph::clear_pass(&mut rg, clear_color, framebuffer);
|
||||||
egui_pass::egui_pre_pass(
|
egui_pass::egui_pre_pass(
|
||||||
|
@ -2556,8 +2555,7 @@ impl<W> Renderer<W> {
|
||||||
output,
|
output,
|
||||||
framebuffer,
|
framebuffer,
|
||||||
)?;
|
)?;
|
||||||
|
render_graph::present_pass(&mut rg, framebuffer);
|
||||||
rg.mark_as_output(framebuffer, Access::present());
|
|
||||||
|
|
||||||
Result::Ok((textures_to_remove, rg.resolve(dev.clone())?))
|
Result::Ok((textures_to_remove, rg.resolve(dev.clone())?))
|
||||||
})?;
|
})?;
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1 +0,0 @@
|
||||||
|
|
|
@ -414,100 +414,3 @@ impl<'a, T: 'a> DerefMut for WithLifetime<'a, T> {
|
||||||
&mut self.0
|
&mut self.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bitflags::bitflags! {
|
|
||||||
pub struct PipelineAccess: u32 {
|
|
||||||
const TRANSFER = 1 << 0;
|
|
||||||
const VERTEX_ATTRIBUTE_INPUT = 1 << 1;
|
|
||||||
const DRAW_INDIRECT = 1 << 2;
|
|
||||||
const VERTEX_INPUT = 1 << 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct BitIter<'a> {
|
|
||||||
bits: &'a [u64],
|
|
||||||
num_bits: usize,
|
|
||||||
bit_offset: usize,
|
|
||||||
bit_index: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> std::fmt::Display for BitIter<'a> {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
f.debug_struct("BitIter")
|
|
||||||
.field_with("bits", |f| {
|
|
||||||
write!(f, "[")?;
|
|
||||||
for bit in self.clone() {
|
|
||||||
write!(f, "{bit}, ")?;
|
|
||||||
}
|
|
||||||
write!(f, " ]")
|
|
||||||
})
|
|
||||||
.finish()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> BitIter<'a> {
|
|
||||||
pub fn new(bits: &'a [u64], num_bits: usize) -> Self {
|
|
||||||
Self {
|
|
||||||
bits,
|
|
||||||
num_bits,
|
|
||||||
bit_index: 0,
|
|
||||||
bit_offset: 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn chunks(self, chunk_size: usize) -> ChunkedBitIter<'a> {
|
|
||||||
ChunkedBitIter {
|
|
||||||
inner: self,
|
|
||||||
chunk_size,
|
|
||||||
pos: 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl Iterator for BitIter<'_> {
|
|
||||||
type Item = usize;
|
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
|
||||||
loop {
|
|
||||||
if self.bit_index >= self.num_bits {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
let bit_index = self.bit_index + self.bit_offset;
|
|
||||||
let byte_idx = bit_index / 64;
|
|
||||||
let byte_offset = bit_index % 64;
|
|
||||||
self.bit_index += 1;
|
|
||||||
|
|
||||||
if (self.bits[byte_idx] >> byte_offset) & 1 == 1 {
|
|
||||||
return Some(self.bit_index - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct ChunkedBitIter<'a> {
|
|
||||||
inner: BitIter<'a>,
|
|
||||||
chunk_size: usize,
|
|
||||||
pos: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Iterator for ChunkedBitIter<'a> {
|
|
||||||
type Item = BitIter<'a>;
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
|
||||||
if self.pos >= self.inner.num_bits {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
let bits = (self.inner.num_bits - self.pos).min(self.chunk_size);
|
|
||||||
|
|
||||||
let iter = BitIter {
|
|
||||||
bits: &self.inner.bits[self.pos / 64..],
|
|
||||||
bit_offset: self.pos % 64,
|
|
||||||
bit_index: 0,
|
|
||||||
num_bits: bits,
|
|
||||||
};
|
|
||||||
self.pos += bits;
|
|
||||||
|
|
||||||
Some(iter)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in a new issue