Skip to content

Commit

Permalink
Dx9 backend
Browse files Browse the repository at this point in the history
  • Loading branch information
veeenu committed Feb 28, 2024
1 parent 59b9426 commit 7bbbe06
Show file tree
Hide file tree
Showing 8 changed files with 461 additions and 174 deletions.
74 changes: 24 additions & 50 deletions src/hooks/dx9.rs
Original file line number Diff line number Diff line change
@@ -1,25 +1,23 @@
use std::ffi::c_void;
use std::mem;
use std::sync::atomic::Ordering;
use std::sync::{Arc, OnceLock};
use std::sync::OnceLock;

use imgui::Context;
use once_cell::sync::OnceCell;
use parking_lot::Mutex;
use tracing::{error, trace};
use windows::core::{Error, Interface, Result, HRESULT};
use windows::Win32::Foundation::{BOOL, HWND, LPARAM, LRESULT, RECT, WPARAM};
use windows::Win32::Foundation::{BOOL, HWND, RECT};
use windows::Win32::Graphics::Direct3D9::{
Direct3DCreate9, IDirect3DDevice9, D3DADAPTER_DEFAULT, D3DCREATE_SOFTWARE_VERTEXPROCESSING,
D3DDEVTYPE_NULLREF, D3DDISPLAYMODE, D3DFORMAT, D3DPRESENT_PARAMETERS, D3DSWAPEFFECT_DISCARD,
D3D_SDK_VERSION,
Direct3DCreate9, IDirect3DDevice9, D3DADAPTER_DEFAULT, D3DBACKBUFFER_TYPE_MONO,
D3DCREATE_SOFTWARE_VERTEXPROCESSING, D3DDEVTYPE_NULLREF, D3DDISPLAYMODE, D3DFORMAT,
D3DPRESENT_PARAMETERS, D3DSWAPEFFECT_DISCARD, D3D_SDK_VERSION,
};
use windows::Win32::Graphics::Gdi::RGNDATA;
use windows::Win32::UI::WindowsAndMessaging::{CallWindowProcW, DefWindowProcW};

use super::DummyHwnd;
use crate::compositor::dx9::Compositor;
use crate::mh::MhHook;
use crate::pipeline::{Pipeline, PipelineMessage, PipelineSharedState};
use crate::renderer::{D3D9RenderEngine, Pipeline};
use crate::{util, Hooks, ImguiRenderLoop};

type Dx9PresentType = unsafe extern "system" fn(
Expand All @@ -35,67 +33,44 @@ struct Trampolines {
}

static mut TRAMPOLINES: OnceLock<Trampolines> = OnceLock::new();
static mut PIPELINE: OnceCell<(Mutex<Pipeline<Compositor>>, Arc<PipelineSharedState>)> =
OnceCell::new();
static mut PIPELINE: OnceCell<Mutex<Pipeline<D3D9RenderEngine>>> = OnceCell::new();
static mut RENDER_LOOP: OnceCell<Box<dyn ImguiRenderLoop + Send + Sync>> = OnceCell::new();

unsafe fn init_pipeline(
device: &IDirect3DDevice9,
) -> Result<(Mutex<Pipeline<Compositor>>, Arc<PipelineSharedState>)> {
unsafe fn init_pipeline(device: &IDirect3DDevice9) -> Result<Mutex<Pipeline<D3D9RenderEngine>>> {
let mut creation_parameters = Default::default();
let _ = device.GetCreationParameters(&mut creation_parameters);
let hwnd = creation_parameters.hFocusWindow;

let compositor = Compositor::new(device, hwnd)?;
let mut ctx = Context::create();
let engine = D3D9RenderEngine::new(device, &mut ctx)?;

let Some(render_loop) = RENDER_LOOP.take() else {
return Err(Error::new(HRESULT(-1), "Render loop not yet initialized".into()));
};

let (pipeline, shared_state) = Pipeline::new(hwnd, imgui_wnd_proc, compositor, render_loop)
.map_err(|(e, render_loop)| {
RENDER_LOOP.get_or_init(move || render_loop);
e
})?;

Ok((Mutex::new(pipeline), shared_state))
let pipeline = Pipeline::new(hwnd, ctx, engine, render_loop).map_err(|(e, render_loop)| {
RENDER_LOOP.get_or_init(move || render_loop);
e
})?;
Ok(Mutex::new(pipeline))
}

fn render(device: &IDirect3DDevice9) -> Result<()> {
let (pipeline, _) = unsafe { PIPELINE.get_or_try_init(|| init_pipeline(device)) }?;
let pipeline = unsafe { PIPELINE.get_or_try_init(|| init_pipeline(device)) }?;

let Some(mut pipeline) = pipeline.try_lock() else {
return Err(Error::new(HRESULT(-1), "Could not lock pipeline".into()));
};

let source = pipeline.render()?;
pipeline.prepare_render()?;

pipeline.compositor().composite(pipeline.engine(), source)?;
let surface = unsafe { device.GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO).unwrap() };

Ok(())
}

unsafe extern "system" fn imgui_wnd_proc(
hwnd: HWND,
msg: u32,
wparam: WPARAM,
lparam: LPARAM,
) -> LRESULT {
let Some(shared_state) = PIPELINE.get().map(|(_, shared_state)| shared_state) else {
return DefWindowProcW(hwnd, msg, wparam, lparam);
};
unsafe { device.BeginScene() }?;
pipeline.render(surface)?;
unsafe { device.EndScene() }?;

let _ = shared_state.tx.send(PipelineMessage(hwnd, msg, wparam, lparam));

// CONCURRENCY: as the message interpretation now happens out of band, this
// expresses the intent as of *before* the current message was received.
let should_block_messages = shared_state.should_block_events.load(Ordering::SeqCst);

if should_block_messages {
LRESULT(1)
} else {
CallWindowProcW(Some(shared_state.wnd_proc), hwnd, msg, wparam, lparam)
}
Ok(())
}

unsafe extern "system" fn dx9_present_impl(
Expand All @@ -106,10 +81,9 @@ unsafe extern "system" fn dx9_present_impl(
pdirtyregion: *const RGNDATA,
) -> HRESULT {
let Trampolines { dx9_present } =
TRAMPOLINES.get().expect("DirectX 12 trampolines uninitialized");
TRAMPOLINES.get().expect("DirectX 9 trampolines uninitialized");

if let Err(e) = render(&device) {
util::print_dxgi_debug_messages();
error!("Render error: {e:?}");
}

Expand Down
4 changes: 2 additions & 2 deletions src/hooks/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ use windows::Win32::UI::WindowsAndMessaging::{
pub mod dx11;
#[cfg(feature = "dx12")]
pub mod dx12;
// #[cfg(feature = "dx9")]
// pub mod dx9;
#[cfg(feature = "dx9")]
pub mod dx9;
// #[cfg(feature = "opengl3")]
// pub mod opengl3;

Expand Down
12 changes: 2 additions & 10 deletions src/renderer/backend/dx11.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ use std::{mem, ptr, slice};
use imgui::internal::RawWrapper;
use imgui::{BackendFlags, Context, DrawCmd, DrawData, DrawIdx, DrawVert, TextureId};
use memoffset::offset_of;
use tracing::debug;
use windows::core::{s, Interface, Result};
use windows::Win32::Foundation::RECT;
use windows::Win32::Graphics::Direct3D::Fxc::D3DCompile;
Expand Down Expand Up @@ -41,7 +40,7 @@ impl D3D11RenderEngine {

ctx.set_ini_filename(None);
ctx.io_mut().backend_flags |= BackendFlags::RENDERER_HAS_VTX_OFFSET;
ctx.set_renderer_name(String::from(concat!("imgui-dx12@", env!("CARGO_PKG_VERSION"))));
ctx.set_renderer_name(String::from(concat!("hudhook-dx11@", env!("CARGO_PKG_VERSION"))));
let fonts = ctx.fonts();
let fonts_texture = fonts.build_rgba32_texture();
fonts.tex_id = unsafe {
Expand Down Expand Up @@ -99,14 +98,6 @@ impl RenderEngine for D3D11RenderEngine {

impl D3D11RenderEngine {
unsafe fn render_draw_data(&mut self, draw_data: &DrawData) -> Result<()> {
if draw_data.display_size[0] <= 0f32 || draw_data.display_size[1] <= 0f32 {
debug!(
"Insufficent display size {}x{}, skip rendering",
draw_data.display_size[0], draw_data.display_size[1]
);
return Ok(());
}

self.vertex_buffer.clear();
self.index_buffer.clear();
self.projection_buffer.clear();
Expand Down Expand Up @@ -654,6 +645,7 @@ impl<T> Buffer<T> {
&mut self.resource,
Self::create_resource(device, capacity, self.bind_flag)?,
));
self.resource_capacity = capacity;
}

unsafe {
Expand Down
42 changes: 14 additions & 28 deletions src/renderer/backend/dx12.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use std::{mem, ptr, slice};
use imgui::internal::RawWrapper;
use imgui::{BackendFlags, Context, DrawCmd, DrawData, DrawIdx, DrawVert, TextureId};
use memoffset::offset_of;
use tracing::{debug, trace};
use tracing::debug;
use windows::core::{s, w, ComInterface, Result};
use windows::Win32::Foundation::*;
use windows::Win32::Graphics::Direct3D::Fxc::*;
Expand Down Expand Up @@ -57,7 +57,7 @@ impl D3D12RenderEngine {

ctx.set_ini_filename(None);
ctx.io_mut().backend_flags |= BackendFlags::RENDERER_HAS_VTX_OFFSET;
ctx.set_renderer_name(String::from(concat!("imgui-dx12@", env!("CARGO_PKG_VERSION"))));
ctx.set_renderer_name(String::from(concat!("hudhook-dx12@", env!("CARGO_PKG_VERSION"))));
let fonts = ctx.fonts();
let fonts_texture = fonts.build_rgba32_texture();
fonts.tex_id = unsafe {
Expand Down Expand Up @@ -135,14 +135,6 @@ impl RenderEngine for D3D12RenderEngine {

impl D3D12RenderEngine {
unsafe fn render_draw_data(&mut self, draw_data: &DrawData) -> Result<()> {
if draw_data.display_size[0] <= 0f32 || draw_data.display_size[1] <= 0f32 {
debug!(
"Insufficent display size {}x{}, skip rendering",
draw_data.display_size[0], draw_data.display_size[1]
);
return Ok(());
}

self.vertex_buffer.clear();
self.index_buffer.clear();

Expand All @@ -158,6 +150,7 @@ impl D3D12RenderEngine {

self.vertex_buffer.upload(&self.device)?;
self.index_buffer.upload(&self.device)?;

self.projection_buffer = {
let [l, t, r, b] = [
draw_data.display_pos[0],
Expand Down Expand Up @@ -196,17 +189,15 @@ impl D3D12RenderEngine {
let tex_handle = D3D12_GPU_DESCRIPTOR_HANDLE {
ptr: cmd_params.texture_id.id() as u64,
};
unsafe {
self.command_list.SetGraphicsRootDescriptorTable(1, tex_handle);
self.command_list.RSSetScissorRects(&[r]);
self.command_list.DrawIndexedInstanced(
count as _,
1,
(cmd_params.idx_offset + idx_offset) as _,
(cmd_params.vtx_offset + vtx_offset) as _,
0,
);
}
self.command_list.SetGraphicsRootDescriptorTable(1, tex_handle);
self.command_list.RSSetScissorRects(&[r]);
self.command_list.DrawIndexedInstanced(
count as _,
1,
(cmd_params.idx_offset + idx_offset) as _,
(cmd_params.vtx_offset + vtx_offset) as _,
0,
);
}
},
DrawCmd::ResetRenderState => {
Expand All @@ -215,9 +206,7 @@ impl D3D12RenderEngine {
// whatsoever. What am I doing wrong?
self.setup_render_state(draw_data);
},
DrawCmd::RawCallback { callback, raw_cmd } => unsafe {
callback(cl.raw(), raw_cmd)
},
DrawCmd::RawCallback { callback, raw_cmd } => callback(cl.raw(), raw_cmd),
}
}
idx_offset += cl.idx_buffer().len();
Expand Down Expand Up @@ -266,10 +255,6 @@ impl D3D12RenderEngine {
);
self.command_list.OMSetBlendFactor(Some(&[0f32; 4]));
}

pub fn resize(&mut self, _width: u32, _height: u32) -> Result<()> {
Ok(())
}
}

unsafe fn create_command_objects(
Expand Down Expand Up @@ -627,6 +612,7 @@ impl<T> Buffer<T> {
let capacity = self.data.capacity();
if capacity > self.resource_capacity {
drop(mem::replace(&mut self.resource, Self::create_resource(device, capacity)?));
self.resource_capacity = capacity;
}

unsafe {
Expand Down
Loading

0 comments on commit 7bbbe06

Please sign in to comment.