use crate::gfx::backend::{ChunkMesh, FrameParams, RenderBackend};
use crate::gfx::input::RenderInput;
use crate::gfx::mesh_payload::{SkinnedVertex, Vertex};
use crate::gfx::profile::RenderStats;
use crate::gfx::render_types::SkinnedDrawObject;
use super::context::{DxContext, debug_assert_main_thread};
macro_rules! forward {
() => {};
(fn $name:ident(&self $(, $arg:ident: $ty:ty)* $(,)?) -> $ret:ty; $($rest:tt)*) => {
fn $name(&self $(, $arg: $ty)*) -> $ret { self.$name($($arg),*) }
forward!($($rest)*);
};
(fn $name:ident(&self $(, $arg:ident: $ty:ty)* $(,)?); $($rest:tt)*) => {
fn $name(&self $(, $arg: $ty)*) { self.$name($($arg),*) }
forward!($($rest)*);
};
(fn $name:ident(&mut self $(, $arg:ident: $ty:ty)* $(,)?) -> $ret:ty; $($rest:tt)*) => {
fn $name(&mut self $(, $arg: $ty)*) -> $ret {
debug_assert_main_thread(stringify!($name));
self.$name($($arg),*)
}
forward!($($rest)*);
};
(fn $name:ident(&mut self $(, $arg:ident: $ty:ty)* $(,)?); $($rest:tt)*) => {
fn $name(&mut self $(, $arg: $ty)*) {
debug_assert_main_thread(stringify!($name));
self.$name($($arg),*)
}
forward!($($rest)*);
};
}
impl RenderBackend for DxContext {
forward! {
fn window_closed(&mut self) -> bool;
fn capture_cursor(&mut self);
fn set_ui_cursor_hidden(&mut self, hidden: bool);
fn cursor_outside_window(&self) -> bool;
fn set_menu_mode(&mut self, on: bool);
fn set_camera_capture(&mut self, capture: bool);
fn set_reflection_probes(&mut self, probes: &[crate::gfx::reflection_probe::ProbePlacement]);
fn set_vsync(&mut self, on: bool);
fn set_window_mode(&mut self, mode: crate::components::WindowMode);
fn set_window_size(&mut self, width: u32, height: u32);
fn display_modes(&self) -> Vec<crate::gfx::display_mode::DisplayMode>;
fn current_display_mode(&self) -> Option<crate::gfx::display_mode::DisplayMode>;
fn set_display_mode(&mut self, mode: crate::gfx::display_mode::DisplayMode);
fn update_post_process(
&mut self,
tunables: crate::gfx::render_types::PostProcessTunables,
);
fn set_ambient_intensity(&mut self, value: f32);
fn update_directional_lights(&mut self, lights: &[crate::components::DirectionalLight]);
fn set_keymap(&mut self, keymap: &crate::gfx::keymap::KeyMap);
fn apply_quality_settings(&mut self, settings: crate::gfx::backend::QualitySettings);
fn set_shadow_update(&mut self, update: crate::components::ShadowUpdate);
fn set_shadow_distance(&mut self, distance: u32);
fn set_shadow_cascades(&mut self, count: u32);
fn update_quality_params(&mut self, settings: crate::gfx::backend::QualitySettings);
fn take_input(&mut self) -> RenderInput;
fn wait_idle(&self);
fn draw_frame(&mut self, params: FrameParams<'_>) -> crate::gfx::error::RenderResult<()>;
fn update_view(&mut self, matrix: [[f32; 4]; 4]);
fn update_models(&mut self, updates: &[(u32, [[f32; 4]; 4])]);
fn retire_draw_object(&mut self, draw_idx: usize);
fn update_skinned_pose(&mut self, skinned_index: usize, matrices: &[[[f32; 4]; 4]]);
fn update_morph_weights(&mut self, skinned_index: usize, weights: &[f32]);
fn reveal_skinned_instance(&mut self, instance_index: usize, model: [[f32; 4]; 4]);
fn retire_skinned_draw_object(&mut self, skinned_index: usize);
fn update_skinned_models(&mut self, updates: &[(u32, [[f32; 4]; 4])]);
fn evict_texture_slot(&mut self, slot: usize) -> Result<(), String>;
fn evict_mesh(&mut self, draw_idx: usize, retire_frame: u64) -> Result<(), String>;
fn seed_mesh_streaming(&mut self, vtx_offset: u64, vtx_bytes: u64, idx_offset: u64, idx_bytes: u64);
fn remove_chunk_mesh(&mut self, draw_idx: usize, retire_frame: u64) -> Result<(), String>;
fn set_chunk_model(&mut self, draw_idx: usize, model: [[f32; 4]; 4]) -> Result<(), String>;
fn add_decal(&mut self, record: crate::gfx::decal::DecalRecord) -> Result<usize, String>;
fn remove_decal(&mut self, decal_id: usize) -> Result<(), String>;
fn add_emitter(&mut self, record: crate::gfx::particles::ParticleEmitterRecord) -> Result<usize, String>;
fn remove_emitter(&mut self, emitter_id: usize) -> Result<(), String>;
fn render_stats(&self) -> RenderStats;
fn capabilities(&self) -> crate::gfx::backend::DeviceCapabilities;
fn gpu_profile(&self) -> crate::gfx::backend::GpuProfile;
fn logical_size(&self) -> (f32, f32);
fn update_color_lut(&mut self, size: u32, data: &[u8]) -> Result<(), String>;
fn update_fog_settings(&mut self, settings: Option<crate::gfx::volumetric_fog::FogSettings>);
fn update_mesh_geometry(&mut self, draw_idx: usize, verts: &[crate::gfx::mesh_payload::Vertex], idxs: &[u16], lod_alternates: &[(f32, Vec<u16>)]) -> Result<(), String>;
fn update_world_shader_pipelines(&mut self, vert_bytes: Option<&[u8]>, frag_bytes: Option<&[u8]>, shadow_bytes: Option<&[u8]>, vert_instanced_bytes: Option<&[u8]>) -> Result<(), String>;
fn update_skinned_mesh_geometry(&mut self, skinned_index: usize, vertex_base: u32, verts: &[crate::gfx::mesh_payload::SkinnedVertex], idxs: &[u16]) -> Result<(), String>;
fn update_skinned_skeleton(&mut self, skinned_index: usize, new_joint_count: usize) -> Result<(), String>;
fn rebuild_skinned_geometry(&mut self, changes: Vec<crate::gfx::backend::SkinnedDrawGeometryUpdate>) -> Result<Vec<crate::gfx::backend::SkinnedSlotLayout>, String>;
fn clone_static_draw_object(&mut self, src_draw_idx: usize, model: [[f32; 4]; 4], dst: crate::gfx::draw_slot::SlotAlloc) -> Result<(), String>;
fn evict_world_shader(&mut self, bucket: u32);
}
fn hot_swap_config(&self) -> Option<crate::gfx::backend_init::SwapchainConfig> {
Some(self.swapchain_config)
}
fn reload_world(
&mut self,
init: crate::gfx::backend_init::BackendInit<'_>,
) -> crate::gfx::error::RenderResult<()> {
Ok(self.apply_world_reload(init)?)
}
fn update_texture_slot(
&mut self,
slot: usize,
image: &crate::bake::texture::TextureImage,
) -> crate::gfx::error::RenderResult<()> {
debug_assert_main_thread("update_texture_slot");
Ok(DxContext::update_texture_slot(self, slot, image)?)
}
fn upload_mesh(
&mut self,
draw_idx: usize,
verts: &[Vertex],
idxs: &[u16],
frame: u64,
) -> crate::gfx::error::RenderResult<()> {
debug_assert_main_thread("upload_mesh");
Ok(DxContext::upload_mesh(self, draw_idx, verts, idxs, frame)?)
}
fn setup_chunk_streaming(
&mut self,
chunk_vtx_bytes: usize,
chunk_idx_bytes: usize,
texture_slot: usize,
normal_map_slot: usize,
) -> crate::gfx::error::RenderResult<()> {
debug_assert_main_thread("setup_chunk_streaming");
Ok(DxContext::setup_chunk_streaming(
self,
chunk_vtx_bytes,
chunk_idx_bytes,
texture_slot,
normal_map_slot,
)?)
}
fn add_chunk_mesh(
&mut self,
mesh: ChunkMesh<'_>,
dst: crate::gfx::draw_slot::SlotAlloc,
) -> crate::gfx::error::RenderResult<()> {
debug_assert_main_thread("add_chunk_mesh");
DxContext::add_chunk_mesh(self, mesh, dst)
}
fn update_environment_map(&mut self, payload: &[u8]) -> crate::gfx::error::RenderResult<()> {
debug_assert_main_thread("update_environment_map");
Ok(DxContext::update_environment_map(self, payload)?)
}
fn rebuild_static_geometry(
&mut self,
changes: Vec<crate::gfx::backend::DrawGeometryUpdate>,
) -> crate::gfx::error::RenderResult<()> {
debug_assert_main_thread("rebuild_static_geometry");
Ok(DxContext::rebuild_static_geometry(self, changes)?)
}
fn install_world_shader(
&mut self,
bucket: u32,
shader: crate::gfx::backend_init::ShaderBytes<'_>,
) -> crate::gfx::error::RenderResult<()> {
debug_assert_main_thread("install_world_shader");
DxContext::install_world_shader(self, bucket, shader)
.map_err(crate::gfx::error::RenderError::ShaderCompile)
}
fn upload_skinned(
&mut self,
vertices: &[SkinnedVertex],
indices: &[u32],
draw_objects: Vec<SkinnedDrawObject>,
_vert_bytes: &[u8],
frag_bytes: &[u8],
_shadow_bytes: &[u8],
) -> crate::gfx::error::RenderResult<()> {
debug_assert_main_thread("upload_skinned");
Ok(self.upload_skinned(vertices, indices, draw_objects, frag_bytes)?)
}
fn upload_skinned_morphs(
&mut self,
morphs: Vec<Option<std::sync::Arc<crate::gfx::mesh_payload::PayloadMorphs>>>,
) {
debug_assert_main_thread("upload_skinned_morphs");
if let Err(e) = DxContext::upload_skinned_morphs(self, morphs) {
tracing::error!("DirectX: morph target upload failed: {}", e);
}
}
fn draw_geometry_size(&self, draw_idx: usize) -> Option<(usize, usize)> {
self.draw
.objects
.get(draw_idx)
.map(|o| (o.vertex_count, o.index_count))
}
fn draw_lod_index_counts(&self, draw_idx: usize) -> Option<Vec<usize>> {
self.draw
.objects
.get(draw_idx)
.map(|o| o.lod_alternates.iter().map(|s| s.index_count).collect())
}
fn shader_reload_flag(&self) -> Option<std::sync::Arc<std::sync::atomic::AtomicBool>> {
self.shader_reload_pending()
}
fn screenshot(&mut self, path: &str) -> Result<String, String> {
debug_assert_main_thread("screenshot");
self.capture_screenshot(path)
}
}