diff options
Diffstat (limited to 'src/gpu.rs')
| -rw-r--r-- | src/gpu.rs | 95 |
1 files changed, 95 insertions, 0 deletions
@@ -38,8 +38,17 @@ pub fn create_adapter( /// Requests a wgpu device + queue. pub fn create_device(adapter: &wgpu::Adapter) -> (wgpu::Device, wgpu::Queue) { + create_device_with_features(adapter, wgpu::Features::empty()) +} + +/// Requests a wgpu device + queue with additional features. +pub fn create_device_with_features( + adapter: &wgpu::Adapter, + features: wgpu::Features, +) -> (wgpu::Device, wgpu::Queue) { pollster::block_on(adapter.request_device(&wgpu::DeviceDescriptor { label: Some("device"), + required_features: features, ..Default::default() })) .expect("create device") @@ -116,6 +125,32 @@ pub fn create_tsv_client(device: &wgpu::Device) -> VkClient { pub const TSV_FORMAT: texture_share_vk_base::ipc::platform::img_data::ImgFormat = texture_share_vk_base::ipc::platform::img_data::ImgFormat::R8G8B8A8; +/// Re-export ImgFormat and ImgType for use in binaries. +pub use texture_share_vk_base::ipc::platform::img_data::{ImgFormat, ImgType}; + +/// Convert a TSV ImgFormat to a wgpu TextureFormat. +pub fn img_format_to_wgpu(fmt: ImgFormat) -> wgpu::TextureFormat { + match fmt { + ImgFormat::R8G8B8A8 => wgpu::TextureFormat::Rgba8UnormSrgb, + ImgFormat::R8G8B8 => wgpu::TextureFormat::Rgba8UnormSrgb, + ImgFormat::B8G8R8A8 => wgpu::TextureFormat::Bgra8UnormSrgb, + ImgFormat::B8G8R8 => wgpu::TextureFormat::Bgra8UnormSrgb, + ImgFormat::BC1_RGBA => wgpu::TextureFormat::Bc1RgbaUnorm, + ImgFormat::BC3_RGBA => wgpu::TextureFormat::Bc3RgbaUnorm, + ImgFormat::BC7_RGBA => wgpu::TextureFormat::Bc7RgbaUnorm, + ImgFormat::Undefined => wgpu::TextureFormat::Rgba8UnormSrgb, + } +} + +/// Returns the wgpu Features required for a TSV image format. +pub fn img_format_features(fmt: ImgFormat) -> wgpu::Features { + if fmt.is_compressed() { + wgpu::Features::TEXTURE_COMPRESSION_BC + } else { + wgpu::Features::empty() + } +} + /// Extracts the raw vk::Image handle from a wgpu Texture. /// /// # Safety @@ -139,3 +174,63 @@ pub fn destroy_fence(client: &VkClient, fence: vk::Fence) { let device = &client.get_vk_setup().device.device; unsafe { device.destroy_fence(fence, None) }; } + +/// Refresh all texture inputs from TSV shared images. +/// Handles format detection and texture recreation internally. +pub fn refresh_textures( + cache: &mut crate::uniform::UniformCache, + device: &wgpu::Device, + client: &mut VkClient, + fence: vk::Fence, +) { + let mut needs_rebind = false; + + for slot in cache.texture_slots_mut() { + let tsv_name = match slot.tsv_name() { + Some(n) => n.to_string(), + None => continue, + }; + + if !slot.tsv_registered() { + if let Err(e) = client.find_image(&tsv_name, true) { + log::debug!("tsv find '{tsv_name}': {e}"); + continue; + } + + match client.find_image_data(&tsv_name, true) { + Ok(Some((_lock, data))) => { + let format = img_format_to_wgpu(data.format); + if slot.resize( + device, + data.width, + data.height, + data.depth_or_array_layers, + format, + ) { + needs_rebind = true; + } + } + _ => continue, + } + + slot.set_tsv_registered(); + } + + let raw = unsafe { raw_image(slot.texture()) }; + match client.recv_image( + &tsv_name, + raw, + vk::ImageLayout::UNDEFINED, + vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL, + fence, + ) { + Ok(Some(())) => log::trace!("texture '{}' updated from '{tsv_name}'", slot.name()), + Ok(None) => {} + Err(e) => log::warn!("recv_image '{tsv_name}': {e}"), + } + } + + if needs_rebind { + cache.rebuild_bind_group(device); + } +} |
