diff options
| author | Irene Knapp <ireneista@irenes.space> | 2026-07-09 11:28:39 -0700 |
|---|---|---|
| committer | Irene Knapp <ireneista@irenes.space> | 2026-07-09 11:28:39 -0700 |
| commit | 399c1db1424f51d5897b839b2d11cbfa6f4a6205 (patch) | |
| tree | 06ef1b94d2fed30c168462691f417c2186179d7f | |
| parent | cd833e3d2dd46ba3d8b8e773b97ae8e850809d0a (diff) | |
only compute queue family indices once
as a now-removed comment said, doing this repeatedly was always sus Force-Push: yes Change-Id: I419683cc979147aff1790a75aa03509b23ae561e
| -rw-r--r-- | src/main.rs | 48 |
1 files changed, 27 insertions, 21 deletions
diff --git a/src/main.rs b/src/main.rs index e181e46..44e92bd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -45,6 +45,7 @@ impl<T> Acceptable<T> { if let Acceptable::Rejected(_) = self { true } else { false } } + #[allow(unused)] fn unwrap(self) -> T { if let Acceptable::Accepted(result) = self { result @@ -480,14 +481,8 @@ impl Surreality { -> Result<(vk::PhysicalDevice, Device, QueueFamilyIndices, vk::Queue, vk::Queue, EnableSwapchain)> { - let physical_device = Self::pick_vulkan_device(instance, surface)?; - - // We already did the check in score_vulkan_device(), so if it fails - // this second time, that's our own bug and we don't need to explain it - // to our users. - // TODO looks sus though - let indices = Self::find_device_queue_family_indices( - instance, surface, &physical_device)?.unwrap(); + let (physical_device, indices) + = Self::pick_vulkan_device(instance, surface)?; // We enumerate the device extensions here so they can inform // configuration. We already did this in score_vulkan_device(), but here @@ -1019,23 +1014,26 @@ impl Surreality { // device to connect it to. #[allow(unsafe_code)] fn pick_vulkan_device(instance: &Instance, surface: &vk::SurfaceKHR) - -> Result<vk::PhysicalDevice> + -> Result<(vk::PhysicalDevice, QueueFamilyIndices)> { let mut best_device = None; let mut best_score = None; + let mut best_indices = None; let mut rejected = BTreeMap::new(); for device in unsafe { instance.enumerate_physical_devices() }? { match Self::score_vulkan_device(instance, surface, &device)? { - Acceptable::Accepted(new_score) => { + Acceptable::Accepted((new_score, new_indices)) => { if let Some(old_score) = best_score { if new_score > old_score { best_device = Some(device); best_score = Some(new_score); + best_indices = Some(new_indices); } } else { best_device = Some(device); best_score = Some(new_score); + best_indices = Some(new_indices); } } Acceptable::Rejected(reason) => { @@ -1050,8 +1048,8 @@ impl Surreality { } } - if let Some(device) = best_device { - Ok(device) + if let (Some(device), Some(indices)) = (best_device, best_indices) { + Ok((device, indices)) } else if rejected.is_empty() { Err(Error { message: "The system has no GPUs of any kind.".to_string() @@ -1074,21 +1072,29 @@ impl Surreality { // will want to print explanations, but otherwise it'll want to be quiet. So // the outer Result is whether we successfully evaluated the device, and the // inner Acceptable is whether we approve of it. + // + // In the event that we find the device acceptable, we also return the + // queue family indices we'd be using if we ultimately go with it. While + // this is not strictly necessary, it's better to return them from here + // than to recompute them later on the assumption it'll work out the same. #[allow(unsafe_code)] fn score_vulkan_device(instance: &Instance, surface: &vk::SurfaceKHR, physical_device: &vk::PhysicalDevice) - -> Result<Acceptable<u64>> + -> Result<Acceptable<(u64, QueueFamilyIndices)>> { // Not all devices support graphics, and not all devices support // presenting to any given surface. We check whether this one is suitable - // by looking up the indices of the queue families we would use, though - // we ignore the actual values and recompute them later. - if let Acceptable::Rejected(rationale) - = Self::find_device_queue_family_indices( - instance, surface, physical_device)? + // by looking up the indices of the queue families we would use. If we + // ultimately use this device, we'll need these, so we make sure to return + // them. + let indices = match Self::find_device_queue_family_indices( + instance, surface, physical_device)? { - return Ok(Acceptable::Rejected(rationale)); - } + Acceptable::Rejected(rationale) => { + return Ok(Acceptable::Rejected(rationale)); + } + Acceptable::Accepted(indices) => indices + }; // At this point we know the device meets our high-level requirements, // so it's just a question of scoring. @@ -1145,7 +1151,7 @@ impl Surreality { // selected. } - Ok(Acceptable::Accepted(score)) + Ok(Acceptable::Accepted((score, indices))) } #[allow(unsafe_code)] |