From 616d61767f207bcc313c79fff480e2bd15a9e065 Mon Sep 17 00:00:00 2001 From: Michael Tang Date: Sat, 13 Apr 2019 20:44:03 -0700 Subject: [PATCH 1/5] WIP hlsl support --- imgui-examples/Cargo.lock | 52 +++++++-- imgui-examples/Cargo.toml | 3 + imgui-examples/examples/hello_gfx.rs | 2 +- imgui-examples/examples/support_gfx/mod.rs | 128 +++++++++++++++++++++ imgui-gfx-renderer/Cargo.toml | 3 + imgui-gfx-renderer/build.rs | 109 ++++++++++++++++++ imgui-gfx-renderer/src/lib.rs | 33 ++++++ imgui-gfx-renderer/src/shader/sm_40.hlsl | 41 +++++++ 8 files changed, 358 insertions(+), 13 deletions(-) create mode 100644 imgui-gfx-renderer/build.rs create mode 100644 imgui-gfx-renderer/src/shader/sm_40.hlsl diff --git a/imgui-examples/Cargo.lock b/imgui-examples/Cargo.lock index fd5b1d6..83d6189 100644 --- a/imgui-examples/Cargo.lock +++ b/imgui-examples/Cargo.lock @@ -1,3 +1,5 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. [[package]] name = "andrew" version = "0.1.4" @@ -193,6 +195,16 @@ dependencies = [ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "gfx_device_dx11" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "gfx_core 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "gfx_device_gl" version = "0.15.4" @@ -211,6 +223,18 @@ dependencies = [ "gl_generator 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "gfx_window_dxgi" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "gfx_core 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", + "gfx_device_dx11 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winit 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "gfx_window_glutin" version = "0.28.0" @@ -273,35 +297,37 @@ dependencies = [ [[package]] name = "imgui" -version = "0.0.22-pre" +version = "0.0.23-pre" dependencies = [ - "imgui-sys 0.0.22-pre", + "imgui-sys 0.0.23-pre", ] [[package]] name = "imgui-examples" -version = "0.0.22-pre" +version = "0.0.23-pre" dependencies = [ "gfx 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)", + "gfx_window_dxgi 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)", "gfx_window_glutin 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)", "glutin 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)", - "imgui 0.0.22-pre", - "imgui-gfx-renderer 0.0.22-pre", - "imgui-winit-support 0.0.22-pre", + "imgui 0.0.23-pre", + "imgui-gfx-renderer 0.0.23-pre", + "imgui-winit-support 0.0.23-pre", ] [[package]] name = "imgui-gfx-renderer" -version = "0.0.22-pre" +version = "0.0.23-pre" dependencies = [ "gfx 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)", - "imgui 0.0.22-pre", - "imgui-sys 0.0.22-pre", + "imgui 0.0.23-pre", + "imgui-sys 0.0.23-pre", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "imgui-sys" -version = "0.0.22-pre" +version = "0.0.23-pre" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", @@ -311,9 +337,9 @@ dependencies = [ [[package]] name = "imgui-winit-support" -version = "0.0.22-pre" +version = "0.0.23-pre" dependencies = [ - "imgui 0.0.22-pre", + "imgui 0.0.23-pre", "winit 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -870,8 +896,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" "checksum gfx 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7d7ce0c1f747245342a73453fdb098ea0764c430421fbc4d98cdc8ef8ede4834" "checksum gfx_core 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c74932837e61f20956c3da1a47471513707dde300274812bba94373ab51830ae" +"checksum gfx_device_dx11 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b918e22cc5747deaba469c5e04bc7f2bb63a4a0b6baaf93427d1f794236383ff" "checksum gfx_device_gl 0.15.4 (registry+https://github.com/rust-lang/crates.io-index)" = "eb0cf0ff6a14427022856f608c167cd93ef01ead97ff2eff4ff0287130e80d0f" "checksum gfx_gl 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e8a920f8f6c1025a7ddf9dd25502bf059506fd3cd765dfbe8dba0b56b7eeecb" +"checksum gfx_window_dxgi 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8365e2133ea9cd77c4a2ef600977e28596da6098d5a36c541a0f8310ad4c675c" "checksum gfx_window_glutin 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9762740a3aa4d2c0dc61fca23a4271e4c26586d90d7e904c00e2dd97d775db7f" "checksum gl_generator 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a0ffaf173cf76c73a73e080366bf556b4776ece104b06961766ff11449f38604" "checksum gl_generator 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a795170cbd85b5a7baa58d6d7525cae6a03e486859860c220f7ebbbdd379d0a" diff --git a/imgui-examples/Cargo.toml b/imgui-examples/Cargo.toml index d6cbd5b..62aed38 100644 --- a/imgui-examples/Cargo.toml +++ b/imgui-examples/Cargo.toml @@ -16,3 +16,6 @@ glutin = "0.19" imgui = { version = "0.0.23-pre", path = "../" } imgui-gfx-renderer = { version = "0.0.23-pre", path = "../imgui-gfx-renderer" } imgui-winit-support = { version = "0.0.23-pre", path = "../imgui-winit-support" } + +[target.'cfg(windows)'.dev-dependencies] +gfx_window_dxgi = "0.17" \ No newline at end of file diff --git a/imgui-examples/examples/hello_gfx.rs b/imgui-examples/examples/hello_gfx.rs index 162f32d..449856b 100644 --- a/imgui-examples/examples/hello_gfx.rs +++ b/imgui-examples/examples/hello_gfx.rs @@ -5,7 +5,7 @@ mod support_gfx; const CLEAR_COLOR: [f32; 4] = [1.0, 1.0, 1.0, 1.0]; fn main() { - support_gfx::run("hello_gfx.rs".to_owned(), CLEAR_COLOR, hello_world); + support_gfx::run_dx11("hello_gfx.rs".to_owned(), CLEAR_COLOR, hello_world); } fn hello_world<'a>(ui: &Ui<'a>) -> bool { diff --git a/imgui-examples/examples/support_gfx/mod.rs b/imgui-examples/examples/support_gfx/mod.rs index d59cec6..960ada9 100644 --- a/imgui-examples/examples/support_gfx/mod.rs +++ b/imgui-examples/examples/support_gfx/mod.rs @@ -145,3 +145,131 @@ pub fn run bool>(title: String, clear_color: [f32; 4], mut run_ device.cleanup(); } } + +// #[cfg(windows)] +pub fn run_dx11 bool>(title: String, clear_color: [f32; 4], mut run_ui: F) { + use gfx::{self, Device}; + use gfx_window_dxgi; + use glutin; + + type ColorFormat = gfx::format::Rgba8; + type DepthFormat = gfx::format::DepthStencil; + + let mut events_loop = glutin::EventsLoop::new(); + let window = glutin::WindowBuilder::new() + .with_title(title) + .with_dimensions(glutin::dpi::LogicalSize::new(1024f64, 768f64)); + let (window, mut device, mut factory, mut main_color) = + gfx_window_dxgi::init::(window, &events_loop) + .expect("Failed to initalize graphics"); + let mut encoder: gfx::Encoder<_, _> = factory.create_command_buffer().into(); + + let mut imgui = ImGui::init(); + { + // Fix incorrect colors with sRGB framebuffer + fn imgui_gamma_to_linear(col: ImVec4) -> ImVec4 { + let x = col.x.powf(2.2); + let y = col.y.powf(2.2); + let z = col.z.powf(2.2); + let w = 1.0 - (1.0 - col.w).powf(2.2); + ImVec4::new(x, y, z, w) + } + + let style = imgui.style_mut(); + for col in 0..style.colors.len() { + style.colors[col] = imgui_gamma_to_linear(style.colors[col]); + } + } + imgui.set_ini_filename(None); + + // In the examples we only use integer DPI factors, because the UI can get very blurry + // otherwise. This might or might not be what you want in a real application. + let hidpi_factor = window.inner.get_hidpi_factor().round(); + + let font_size = (13.0 * hidpi_factor) as f32; + + imgui.fonts().add_default_font_with_config( + ImFontConfig::new() + .oversample_h(1) + .pixel_snap_h(true) + .size_pixels(font_size), + ); + + imgui.fonts().add_font_with_config( + include_bytes!("../../../resources/mplus-1p-regular.ttf"), + ImFontConfig::new() + .merge_mode(true) + .oversample_h(1) + .pixel_snap_h(true) + .size_pixels(font_size) + .rasterizer_multiply(1.75), + &FontGlyphRange::japanese(), + ); + + imgui.set_font_global_scale((1.0 / hidpi_factor) as f32); + + let mut renderer = Renderer::init( + &mut imgui, + &mut factory, + Shaders::HlslSm40, + main_color.clone(), + ) + .expect("Failed to initialize renderer"); + + imgui_winit_support::configure_keys(&mut imgui); + + let mut last_frame = Instant::now(); + let mut quit = false; + + loop { + events_loop.poll_events(|event| { + use glutin::{ + Event, + WindowEvent::{CloseRequested, Resized}, + }; + + imgui_winit_support::handle_event( + &mut imgui, + &event, + window.inner.get_hidpi_factor(), + hidpi_factor, + ); + + if let Event::WindowEvent { event, .. } = event { + match event { + Resized(size) => { + // gfx_window_dxgi::update_views(&window, &mut factory, &mut device, ); + renderer.update_render_target(main_color.clone()); + } + CloseRequested => quit = true, + _ => (), + } + } + }); + if quit { + break; + } + + let now = Instant::now(); + let delta = now - last_frame; + let delta_s = delta.as_secs() as f32 + delta.subsec_nanos() as f32 / 1_000_000_000.0; + last_frame = now; + + imgui_winit_support::update_mouse_cursor(&imgui, &window.inner); + + let frame_size = imgui_winit_support::get_frame_size(&window.inner, hidpi_factor).unwrap(); + + let ui = imgui.frame(frame_size, delta_s); + if !run_ui(&ui) { + break; + } + + encoder.clear(&main_color, clear_color); + renderer + .render(ui, &mut factory, &mut encoder) + .expect("Rendering failed"); + encoder.flush(&mut device); + window.swap_buffers(1); + device.cleanup(); + } +} diff --git a/imgui-gfx-renderer/Cargo.toml b/imgui-gfx-renderer/Cargo.toml index 08812a7..27bfd94 100644 --- a/imgui-gfx-renderer/Cargo.toml +++ b/imgui-gfx-renderer/Cargo.toml @@ -16,3 +16,6 @@ travis-ci = { repository = "Gekkio/imgui-rs" } gfx = "0.17" imgui = { version = "0.0.23-pre", path = "../" } imgui-sys = { version = "0.0.23-pre", path = "../imgui-sys", features = ["gfx"] } + +[target.'cfg(windows)'.build-dependencies] +winapi = { version = "0.3", features = ["d3dcompiler"] } \ No newline at end of file diff --git a/imgui-gfx-renderer/build.rs b/imgui-gfx-renderer/build.rs new file mode 100644 index 0000000..128dc27 --- /dev/null +++ b/imgui-gfx-renderer/build.rs @@ -0,0 +1,109 @@ +fn main() { + #[cfg(windows)] + hlsl_build::compile_hlsl_shaders(); +} + +#[cfg(windows)] +mod hlsl_build { + use std::env; + use std::ffi::CStr; + use std::ffi::CString; + use std::fs; + use std::path::Path; + use std::path::PathBuf; + use std::ptr; + use std::slice; + use std::str; + + pub fn compile_hlsl_shaders() { + let source_path = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()) + .join("src") + .join("shader") + .join("sm_40.hlsl"); + + let src_data = fs::read_to_string(&source_path).unwrap(); + + let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); + + fs::write( + out_dir.join("hlsl_vertex_shader_bytecode"), + compile_shader(&src_data, &source_path, "VertexMain", "vs_4_0").unwrap_or_else( + |error_message| { + eprintln!("{}", error_message); + panic!("Vertex shader failed to compile"); + }, + ), + ) + .unwrap(); + + fs::write( + out_dir.join("hlsl_pixel_shader_bytecode"), + compile_shader(&src_data, &source_path, "PixelMain", "ps_4_0").unwrap_or_else( + |error_message| { + eprintln!("{}", error_message); + panic!("Pixel shader failed to compile"); + }, + ), + ) + .unwrap(); + } + + fn compile_shader( + src_data: &str, + source_path: &Path, + entry_point: &str, + target: &str, + ) -> Result, String> { + use winapi::shared::minwindef::LPCVOID; + use winapi::um::d3dcommon::ID3DBlob; + use winapi::um::d3dcompiler; + + unsafe { + let mut code: *mut ID3DBlob = ptr::null_mut(); + let mut error_msgs: *mut ID3DBlob = ptr::null_mut(); + + let hr = d3dcompiler::D3DCompile( + src_data.as_bytes().as_ptr() as LPCVOID, + src_data.as_bytes().len(), + CString::new(source_path.to_string_lossy().to_string()) + .unwrap() + .as_ptr(), + ptr::null(), + ptr::null_mut(), + CString::new(entry_point).unwrap().as_ptr(), + CString::new(target).unwrap().as_ptr(), + 0, + 0, + &mut code, + &mut error_msgs, + ); + + if hr < 0 { + if !error_msgs.is_null() { + let error_msgs = error_msgs.as_ref().unwrap(); + + let error_msgs = str::from_utf8(slice::from_raw_parts( + error_msgs.GetBufferPointer() as *const u8, + error_msgs.GetBufferSize(), + )) + .expect("error messages from D3DCompile not valid UTF-8"); + + Err(error_msgs.to_string()) + } else { + Err(format!("hresult: {}", hr)) + } + } else { + let code = code + .as_ref() + .expect("null code blob returned from D3DCompile"); + + Ok(slice::from_raw_parts( + code.GetBufferPointer() as *const u8, + code.GetBufferSize(), + ) + .to_vec()) + } + } + } + +} diff --git a/imgui-gfx-renderer/src/lib.rs b/imgui-gfx-renderer/src/lib.rs index bbfb794..0049e85 100644 --- a/imgui-gfx-renderer/src/lib.rs +++ b/imgui-gfx-renderer/src/lib.rs @@ -76,6 +76,7 @@ macro_rules! extended_defines { } } +#[cfg(not(windows))] extended_defines! { pipeline pipe { vertex_buffer: gfx::VertexBuffer = (), @@ -90,6 +91,22 @@ extended_defines! { } } +// TODO need constant buffer support +#[cfg(windows)] +extended_defines! { + pipeline pipe { + vertex_buffer: gfx::VertexBuffer = (), + matrix: gfx::Global<[[f32; 4]; 4]> = "transform", + tex: gfx::TextureSampler<[f32; 4]> = "tex", + out: gfx::BlendTarget = ( + "Target0", + gfx::state::ColorMask::all(), + gfx::preset::blend::ALPHA, + ), + scissor: gfx::Scissor = (), + } +} + #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum Shaders { GlSl400, // OpenGL 4.0+ @@ -98,6 +115,7 @@ pub enum Shaders { GlSl110, // OpenGL 2.0+ GlSlEs300, // OpenGL ES 3.0+ GlSlEs100, // OpenGL ES 2.0+ + HlslSm40, // HLSL Shader Model 4.0+ } impl Shaders { @@ -128,6 +146,21 @@ impl Shaders { include_bytes!("shader/glsles_100.vert"), include_bytes!("shader/glsles_100.frag"), ), + HlslSm40 => { + #[cfg(not(windows))] + { + // panic instead? + (&[0], &[0]) + } + + #[cfg(windows)] + { + ( + include_bytes!(concat!(env!("OUT_DIR"), "/hlsl_vertex_shader_bytecode")), + include_bytes!(concat!(env!("OUT_DIR"), "/hlsl_pixel_shader_bytecode")), + ) + } + } } } } diff --git a/imgui-gfx-renderer/src/shader/sm_40.hlsl b/imgui-gfx-renderer/src/shader/sm_40.hlsl new file mode 100644 index 0000000..d18d01f --- /dev/null +++ b/imgui-gfx-renderer/src/shader/sm_40.hlsl @@ -0,0 +1,41 @@ +cbuffer Constants : register(b0) { + float4x4 transform; +} + +Texture2D tex; + +// Should be trilinear clamp +SamplerState linear_clamp_sampler +{ + Filter = MIN_MAG_MIP_LINEAR; + AddressU = Clamp; + AddressV = Clamp; +}; + +struct VIn { + float2 position : pos; + float2 uv : uv; + float4 color : col; +}; + +struct VOut +{ + float4 position : SV_POSITION; + float2 uv : TEXCOORD0; + float4 color : COLOR; +}; + +VOut VertexMain(VIn vertex) +{ + VOut output; + output.position = mul(transform, float4(vertex.position, 0.0, 1.0)); + output.uv = vertex.uv; + output.color = vertex.color; + + return output; +} + +float4 PixelMain(VOut vout) : SV_TARGET +{ + return vout.color * tex.Sample(linear_clamp_sampler, vout.uv); +} \ No newline at end of file From d11e008aa0a3633a771650c5ccfbc4192f6c0551 Mon Sep 17 00:00:00 2001 From: Michael Tang Date: Sun, 21 Apr 2019 19:41:14 -0700 Subject: [PATCH 2/5] Add DirectX support behind feature flag --- imgui-examples/Cargo.toml | 5 ++ imgui-examples/README.md | 4 ++ imgui-examples/examples/hello_gfx.rs | 10 +++- imgui-examples/examples/support_gfx/mod.rs | 5 +- imgui-gfx-renderer/Cargo.toml | 5 ++ imgui-gfx-renderer/build.rs | 2 + imgui-gfx-renderer/src/lib.rs | 61 +++++++++++++++++----- imgui-gfx-renderer/src/shader/sm_40.hlsl | 15 ++---- 8 files changed, 79 insertions(+), 28 deletions(-) create mode 100644 imgui-examples/README.md diff --git a/imgui-examples/Cargo.toml b/imgui-examples/Cargo.toml index 62aed38..5ce5691 100644 --- a/imgui-examples/Cargo.toml +++ b/imgui-examples/Cargo.toml @@ -9,6 +9,11 @@ repository = "https://github.com/Gekkio/imgui-rs" license = "MIT/Apache-2.0" publish = false +[features] +opengl = ["imgui-gfx-renderer/opengl"] +directx = ["imgui-gfx-renderer/directx"] +default = ["opengl"] + [dev-dependencies] gfx = "0.17" gfx_window_glutin = "0.28" diff --git a/imgui-examples/README.md b/imgui-examples/README.md new file mode 100644 index 0000000..d53f497 --- /dev/null +++ b/imgui-examples/README.md @@ -0,0 +1,4 @@ +# `imgui-examples` + +- Run with OpenGL backend: `cargo run --example hello_gfx` +- Run with DirectX backend: `cargo run --example hello_gfx --features directx --no-default-features` \ No newline at end of file diff --git a/imgui-examples/examples/hello_gfx.rs b/imgui-examples/examples/hello_gfx.rs index 449856b..e425e17 100644 --- a/imgui-examples/examples/hello_gfx.rs +++ b/imgui-examples/examples/hello_gfx.rs @@ -5,11 +5,17 @@ mod support_gfx; const CLEAR_COLOR: [f32; 4] = [1.0, 1.0, 1.0, 1.0]; fn main() { - support_gfx::run_dx11("hello_gfx.rs".to_owned(), CLEAR_COLOR, hello_world); + support_gfx::run("hello_gfx.rs".to_owned(), CLEAR_COLOR, hello_world); } fn hello_world<'a>(ui: &Ui<'a>) -> bool { - ui.window(im_str!("Hello world")) + #[cfg(feature = "opengl")] + let window_title = im_str!("Hello world (OpenGL)"); + + #[cfg(feature = "directx")] + let window_title = im_str!("Hello world (DirectX)"); + + ui.window(window_title) .size((300.0, 100.0), ImGuiCond::FirstUseEver) .build(|| { ui.text(im_str!("Hello world!")); diff --git a/imgui-examples/examples/support_gfx/mod.rs b/imgui-examples/examples/support_gfx/mod.rs index 960ada9..ba7d9d0 100644 --- a/imgui-examples/examples/support_gfx/mod.rs +++ b/imgui-examples/examples/support_gfx/mod.rs @@ -3,6 +3,7 @@ use imgui_gfx_renderer::{Renderer, Shaders}; use imgui_winit_support; use std::time::Instant; +#[cfg(feature = "opengl")] pub fn run bool>(title: String, clear_color: [f32; 4], mut run_ui: F) { use gfx::{self, Device}; use gfx_window_glutin; @@ -146,8 +147,8 @@ pub fn run bool>(title: String, clear_color: [f32; 4], mut run_ } } -// #[cfg(windows)] -pub fn run_dx11 bool>(title: String, clear_color: [f32; 4], mut run_ui: F) { +#[cfg(feature = "directx")] +pub fn run bool>(title: String, clear_color: [f32; 4], mut run_ui: F) { use gfx::{self, Device}; use gfx_window_dxgi; use glutin; diff --git a/imgui-gfx-renderer/Cargo.toml b/imgui-gfx-renderer/Cargo.toml index 27bfd94..881de91 100644 --- a/imgui-gfx-renderer/Cargo.toml +++ b/imgui-gfx-renderer/Cargo.toml @@ -9,6 +9,11 @@ repository = "https://github.com/Gekkio/imgui-rs" license = "MIT/Apache-2.0" categories = ["gui", "rendering"] +[features] +opengl = [] +directx = [] +default = ["opengl"] + [badges] travis-ci = { repository = "Gekkio/imgui-rs" } diff --git a/imgui-gfx-renderer/build.rs b/imgui-gfx-renderer/build.rs index 128dc27..0cef94b 100644 --- a/imgui-gfx-renderer/build.rs +++ b/imgui-gfx-renderer/build.rs @@ -21,6 +21,8 @@ mod hlsl_build { .join("shader") .join("sm_40.hlsl"); + println!("cargo:rerun-if-changed={}", source_path.display()); + let src_data = fs::read_to_string(&source_path).unwrap(); let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); diff --git a/imgui-gfx-renderer/src/lib.rs b/imgui-gfx-renderer/src/lib.rs index 0049e85..5c3d636 100644 --- a/imgui-gfx-renderer/src/lib.rs +++ b/imgui-gfx-renderer/src/lib.rs @@ -76,7 +76,21 @@ macro_rules! extended_defines { } } -#[cfg(not(windows))] +#[cfg(feature = "directx")] +mod constants { + use gfx::gfx_constant_struct_meta; + use gfx::gfx_impl_struct_meta; + + gfx::gfx_constant_struct! { + Constants { + // `matrix` is a reserved keyword in HLSL + matrix: [[f32; 4]; 4] = "matrix_", + } + } +} + +// This version of `pipe` uses a single uniform for `matrix`, used in GLSL shaders +#[cfg(not(feature = "directx"))] extended_defines! { pipeline pipe { vertex_buffer: gfx::VertexBuffer = (), @@ -91,12 +105,12 @@ extended_defines! { } } -// TODO need constant buffer support -#[cfg(windows)] +// This version of `pipe` uses a constant buffer containing `matrix`, used in the HLSL shader +#[cfg(feature = "directx")] extended_defines! { pipeline pipe { vertex_buffer: gfx::VertexBuffer = (), - matrix: gfx::Global<[[f32; 4]; 4]> = "transform", + constants: gfx::ConstantBuffer = "Constants", tex: gfx::TextureSampler<[f32; 4]> = "tex", out: gfx::BlendTarget = ( "Target0", @@ -109,13 +123,20 @@ extended_defines! { #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum Shaders { - GlSl400, // OpenGL 4.0+ - GlSl150, // OpenGL 3.2+ - GlSl130, // OpenGL 3.0+ - GlSl110, // OpenGL 2.0+ - GlSlEs300, // OpenGL ES 3.0+ - GlSlEs100, // OpenGL ES 2.0+ - HlslSm40, // HLSL Shader Model 4.0+ + /// OpenGL 4.0+ + GlSl400, + /// OpenGL 3.2+ + GlSl150, + /// OpenGL 3.0+ + GlSl130, + /// OpenGL 2.0+ + GlSl110, + /// OpenGL ES 3.0+ + GlSlEs300, + /// OpenGL ES 2.0+ + GlSlEs100, + /// HLSL Shader Model 4.0+ + HlslSm40, } impl Shaders { @@ -147,13 +168,13 @@ impl Shaders { include_bytes!("shader/glsles_100.frag"), ), HlslSm40 => { - #[cfg(not(windows))] + #[cfg(not(feature = "directx"))] { // panic instead? (&[0], &[0]) } - #[cfg(windows)] + #[cfg(feature = "directx")] { ( include_bytes!(concat!(env!("OUT_DIR"), "/hlsl_vertex_shader_bytecode")), @@ -174,6 +195,8 @@ pub struct Renderer { bundle: Bundle>, index_buffer: Buffer, textures: Textures>, + #[cfg(feature = "directx")] + constants: Buffer, } impl Renderer { @@ -230,6 +253,8 @@ impl Renderer { }, index_buffer, textures, + #[cfg(feature = "directx")] + constants: factory.create_constant_buffer(1), }) } @@ -309,9 +334,19 @@ impl Renderer { .min(fb_height) .round() as u16, }; + + #[cfg(feature = "directx")] + { + let constants = constants::Constants { matrix: *matrix }; + encoder.update_constant_buffer(&self.constants, &constants); + } + let data = pipe::BorrowedData { vertex_buffer: &self.bundle.vertex_buffer, + #[cfg(not(feature = "directx"))] matrix, + #[cfg(feature = "directx")] + constants: &self.constants, tex, out: &self.bundle.out, scissor: &scissor, diff --git a/imgui-gfx-renderer/src/shader/sm_40.hlsl b/imgui-gfx-renderer/src/shader/sm_40.hlsl index d18d01f..5063e04 100644 --- a/imgui-gfx-renderer/src/shader/sm_40.hlsl +++ b/imgui-gfx-renderer/src/shader/sm_40.hlsl @@ -1,16 +1,9 @@ cbuffer Constants : register(b0) { - float4x4 transform; + float4x4 matrix_; } Texture2D tex; - -// Should be trilinear clamp -SamplerState linear_clamp_sampler -{ - Filter = MIN_MAG_MIP_LINEAR; - AddressU = Clamp; - AddressV = Clamp; -}; +SamplerState tex_; struct VIn { float2 position : pos; @@ -28,7 +21,7 @@ struct VOut VOut VertexMain(VIn vertex) { VOut output; - output.position = mul(transform, float4(vertex.position, 0.0, 1.0)); + output.position = mul(matrix_, float4(vertex.position, 0.0, 1.0)); output.uv = vertex.uv; output.color = vertex.color; @@ -37,5 +30,5 @@ VOut VertexMain(VIn vertex) float4 PixelMain(VOut vout) : SV_TARGET { - return vout.color * tex.Sample(linear_clamp_sampler, vout.uv); + return vout.color * tex.Sample(tex_, vout.uv); } \ No newline at end of file From b97bb58a5621f34661a59d4a81763233ac93ac7c Mon Sep 17 00:00:00 2001 From: Michael Tang Date: Tue, 23 Apr 2019 17:37:46 -0700 Subject: [PATCH 3/5] Make imgui build successfully with `directx` even when not on windows --- imgui-gfx-renderer/Cargo.toml | 1 + imgui-gfx-renderer/src/lib.rs | 22 +++++++++++----------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/imgui-gfx-renderer/Cargo.toml b/imgui-gfx-renderer/Cargo.toml index 495036b..e93979a 100644 --- a/imgui-gfx-renderer/Cargo.toml +++ b/imgui-gfx-renderer/Cargo.toml @@ -21,6 +21,7 @@ travis-ci = { repository = "Gekkio/imgui-rs" } gfx = "0.18" imgui = { version = "0.0.24-pre", path = "../" } imgui-sys = { version = "0.0.24-pre", path = "../imgui-sys", features = ["gfx"] } +cfg-if = "0.1" [target.'cfg(windows)'.build-dependencies] winapi = { version = "0.3", features = ["d3dcompiler"] } diff --git a/imgui-gfx-renderer/src/lib.rs b/imgui-gfx-renderer/src/lib.rs index 5c3d636..dbe1bec 100644 --- a/imgui-gfx-renderer/src/lib.rs +++ b/imgui-gfx-renderer/src/lib.rs @@ -168,19 +168,19 @@ impl Shaders { include_bytes!("shader/glsles_100.frag"), ), HlslSm40 => { - #[cfg(not(feature = "directx"))] - { - // panic instead? - (&[0], &[0]) + cfg_if::cfg_if! { + if #[cfg(all(feature = "directx", windows))] { + const HLSL_BYTECODE: (&[u8], &[u8]) = ( + include_bytes!(concat!(env!("OUT_DIR"), "/hlsl_vertex_shader_bytecode")), + include_bytes!(concat!(env!("OUT_DIR"), "/hlsl_pixel_shader_bytecode")), + ); + } else { + // panic instead? + const HLSL_BYTECODE: (&[u8], &[u8]) = (&[0], &[0]); + } } - #[cfg(feature = "directx")] - { - ( - include_bytes!(concat!(env!("OUT_DIR"), "/hlsl_vertex_shader_bytecode")), - include_bytes!(concat!(env!("OUT_DIR"), "/hlsl_pixel_shader_bytecode")), - ) - } + HLSL_BYTECODE } } } From fdc8a6a4e20af32a6481c943611b13fb2c4620ec Mon Sep 17 00:00:00 2001 From: Michael Tang Date: Tue, 23 Apr 2019 17:49:32 -0700 Subject: [PATCH 4/5] Commit shaders so they don't need to be missing on non-Windows platforms --- imgui-gfx-renderer/Cargo.toml | 1 - imgui-gfx-renderer/build.rs | 35 ++++++++++++++--------- imgui-gfx-renderer/src/data/pixel.fx | Bin 0 -> 652 bytes imgui-gfx-renderer/src/data/vertex.fx | Bin 0 -> 848 bytes imgui-gfx-renderer/src/lib.rs | 19 +++--------- imgui-gfx-renderer/src/shader/sm_40.hlsl | 10 +++---- 6 files changed, 30 insertions(+), 35 deletions(-) create mode 100644 imgui-gfx-renderer/src/data/pixel.fx create mode 100644 imgui-gfx-renderer/src/data/vertex.fx diff --git a/imgui-gfx-renderer/Cargo.toml b/imgui-gfx-renderer/Cargo.toml index e93979a..495036b 100644 --- a/imgui-gfx-renderer/Cargo.toml +++ b/imgui-gfx-renderer/Cargo.toml @@ -21,7 +21,6 @@ travis-ci = { repository = "Gekkio/imgui-rs" } gfx = "0.18" imgui = { version = "0.0.24-pre", path = "../" } imgui-sys = { version = "0.0.24-pre", path = "../imgui-sys", features = ["gfx"] } -cfg-if = "0.1" [target.'cfg(windows)'.build-dependencies] winapi = { version = "0.3", features = ["d3dcompiler"] } diff --git a/imgui-gfx-renderer/build.rs b/imgui-gfx-renderer/build.rs index 0cef94b..6625d4a 100644 --- a/imgui-gfx-renderer/build.rs +++ b/imgui-gfx-renderer/build.rs @@ -1,34 +1,41 @@ fn main() { #[cfg(windows)] - hlsl_build::compile_hlsl_shaders(); + { + // Note: When building on Windows, this build script will automatically recompile the HLSL shaders. + + use std::env; + use std::path::PathBuf; + + let src_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()).join("src"); + + hlsl_build::update_hlsl_shaders( + &src_dir.join("shader").join("sm_40.hlsl"), + &src_dir.join("data").join("vertex.fx"), + &src_dir.join("data").join("pixel.fx"), + ); + } } #[cfg(windows)] mod hlsl_build { - use std::env; - use std::ffi::CStr; use std::ffi::CString; use std::fs; use std::path::Path; - use std::path::PathBuf; use std::ptr; use std::slice; use std::str; - pub fn compile_hlsl_shaders() { - let source_path = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()) - .join("src") - .join("shader") - .join("sm_40.hlsl"); - + pub fn update_hlsl_shaders( + source_path: &Path, + vertex_destination: &Path, + pixel_destination: &Path, + ) { println!("cargo:rerun-if-changed={}", source_path.display()); let src_data = fs::read_to_string(&source_path).unwrap(); - let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); - fs::write( - out_dir.join("hlsl_vertex_shader_bytecode"), + vertex_destination, compile_shader(&src_data, &source_path, "VertexMain", "vs_4_0").unwrap_or_else( |error_message| { eprintln!("{}", error_message); @@ -39,7 +46,7 @@ mod hlsl_build { .unwrap(); fs::write( - out_dir.join("hlsl_pixel_shader_bytecode"), + pixel_destination, compile_shader(&src_data, &source_path, "PixelMain", "ps_4_0").unwrap_or_else( |error_message| { eprintln!("{}", error_message); diff --git a/imgui-gfx-renderer/src/data/pixel.fx b/imgui-gfx-renderer/src/data/pixel.fx new file mode 100644 index 0000000000000000000000000000000000000000..697cba0add874e0018f875a3bf6aff7e0fad6bff GIT binary patch literal 652 zcmaJ-y-LGS82vOAe-N8Ra1hBNR1j&4gCIz2e%eCqExD-_5o*;)3zd|bK@i;B96I;_ z-Ls1?;O5}ugY*UB`I=r(p&mHNx#xaAC$XBx=F|J=ZDo`hetzW-U$g5Eb42t!Pqcvd zKKKC^V1}R$-?eOK2u}ePZSo-%$AlUm@*LFI`vacMXoK9xJ5pc_;Kl8<3WolDiyw5- zy&42}!A)pn+#RD_l~qG_+SmTTFoWBEw+E5S?&T`$;JbPAU}LG&KJK-*~B zvR(8N(mFfGnF}F7-Qmo=-?``hd^+jkjyYFZoceek+3dU*;lbm-8S4ogb=k;I!^^-|hvXx|4W557))1zD-3ZFpK|@+CYRR1dDL}0m1u1xp zm3x48RSxRaW=Udr2JoouRV#JB;hzV_yt80r^KRa7FUzNAb;Ib!a3H1k)q1TzrCq+gzuRLfO ziuSO^!x~V-I#)T>^Zsl29CZ&1wd_q!_pxTey|(ZZy56=Ia0WmfjWPSEDX-_hJn#G; F`vw)JPpkj{ literal 0 HcmV?d00001 diff --git a/imgui-gfx-renderer/src/lib.rs b/imgui-gfx-renderer/src/lib.rs index dbe1bec..bfaf85a 100644 --- a/imgui-gfx-renderer/src/lib.rs +++ b/imgui-gfx-renderer/src/lib.rs @@ -167,21 +167,10 @@ impl Shaders { include_bytes!("shader/glsles_100.vert"), include_bytes!("shader/glsles_100.frag"), ), - HlslSm40 => { - cfg_if::cfg_if! { - if #[cfg(all(feature = "directx", windows))] { - const HLSL_BYTECODE: (&[u8], &[u8]) = ( - include_bytes!(concat!(env!("OUT_DIR"), "/hlsl_vertex_shader_bytecode")), - include_bytes!(concat!(env!("OUT_DIR"), "/hlsl_pixel_shader_bytecode")), - ); - } else { - // panic instead? - const HLSL_BYTECODE: (&[u8], &[u8]) = (&[0], &[0]); - } - } - - HLSL_BYTECODE - } + HlslSm40 => ( + include_bytes!("data/pixel.fx"), + include_bytes!("data/vertex.fx"), + ), } } } diff --git a/imgui-gfx-renderer/src/shader/sm_40.hlsl b/imgui-gfx-renderer/src/shader/sm_40.hlsl index 5063e04..b40ba25 100644 --- a/imgui-gfx-renderer/src/shader/sm_40.hlsl +++ b/imgui-gfx-renderer/src/shader/sm_40.hlsl @@ -1,14 +1,14 @@ cbuffer Constants : register(b0) { - float4x4 matrix_; + float4x4 matrix_; } Texture2D tex; SamplerState tex_; struct VIn { - float2 position : pos; - float2 uv : uv; - float4 color : col; + float2 position : pos; + float2 uv : uv; + float4 color : col; }; struct VOut @@ -30,5 +30,5 @@ VOut VertexMain(VIn vertex) float4 PixelMain(VOut vout) : SV_TARGET { - return vout.color * tex.Sample(tex_, vout.uv); + return vout.color * tex.Sample(tex_, vout.uv); } \ No newline at end of file From e89375b39a4bc278fa514f6b20a7510e9342fa38 Mon Sep 17 00:00:00 2001 From: Michael Tang Date: Tue, 23 Apr 2019 18:26:20 -0700 Subject: [PATCH 5/5] Cleanup --- imgui-gfx-renderer/build.rs | 6 ++++++ imgui-gfx-renderer/src/lib.rs | 2 +- imgui-gfx-renderer/src/shader/sm_40.hlsl | 26 ++++++++++++------------ 3 files changed, 20 insertions(+), 14 deletions(-) diff --git a/imgui-gfx-renderer/build.rs b/imgui-gfx-renderer/build.rs index 6625d4a..8730d98 100644 --- a/imgui-gfx-renderer/build.rs +++ b/imgui-gfx-renderer/build.rs @@ -34,6 +34,9 @@ mod hlsl_build { let src_data = fs::read_to_string(&source_path).unwrap(); + if vertex_destination.exists() { + fs::remove_file(vertex_destination).unwrap(); + } fs::write( vertex_destination, compile_shader(&src_data, &source_path, "VertexMain", "vs_4_0").unwrap_or_else( @@ -45,6 +48,9 @@ mod hlsl_build { ) .unwrap(); + if pixel_destination.exists() { + fs::remove_file(pixel_destination).unwrap(); + } fs::write( pixel_destination, compile_shader(&src_data, &source_path, "PixelMain", "ps_4_0").unwrap_or_else( diff --git a/imgui-gfx-renderer/src/lib.rs b/imgui-gfx-renderer/src/lib.rs index bfaf85a..2cd5b33 100644 --- a/imgui-gfx-renderer/src/lib.rs +++ b/imgui-gfx-renderer/src/lib.rs @@ -168,8 +168,8 @@ impl Shaders { include_bytes!("shader/glsles_100.frag"), ), HlslSm40 => ( - include_bytes!("data/pixel.fx"), include_bytes!("data/vertex.fx"), + include_bytes!("data/pixel.fx"), ), } } diff --git a/imgui-gfx-renderer/src/shader/sm_40.hlsl b/imgui-gfx-renderer/src/shader/sm_40.hlsl index b40ba25..bdfb4ca 100644 --- a/imgui-gfx-renderer/src/shader/sm_40.hlsl +++ b/imgui-gfx-renderer/src/shader/sm_40.hlsl @@ -1,34 +1,34 @@ cbuffer Constants : register(b0) { - float4x4 matrix_; + float4x4 matrix_; } Texture2D tex; SamplerState tex_; struct VIn { - float2 position : pos; - float2 uv : uv; - float4 color : col; + float2 position : pos; + float2 uv : uv; + float4 color : col; }; struct VOut { - float4 position : SV_POSITION; - float2 uv : TEXCOORD0; - float4 color : COLOR; + float4 position : SV_POSITION; + float2 uv : TEXCOORD0; + float4 color : COLOR; }; VOut VertexMain(VIn vertex) { - VOut output; - output.position = mul(matrix_, float4(vertex.position, 0.0, 1.0)); - output.uv = vertex.uv; - output.color = vertex.color; + VOut output; + output.position = mul(matrix_, float4(vertex.position, 0.0, 1.0)); + output.uv = vertex.uv; + output.color = vertex.color; - return output; + return output; } float4 PixelMain(VOut vout) : SV_TARGET { - return vout.color * tex.Sample(tex_, vout.uv); + return vout.color * tex.Sample(tex_, vout.uv); } \ No newline at end of file