summaryrefslogtreecommitdiffstats
path: root/src/gpu.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/gpu.rs')
-rw-r--r--src/gpu.rs95
1 files changed, 95 insertions, 0 deletions
diff --git a/src/gpu.rs b/src/gpu.rs
index e6529f9..993e524 100644
--- a/src/gpu.rs
+++ b/src/gpu.rs
@@ -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);
+ }
+}