From d11e008aa0a3633a771650c5ccfbc4192f6c0551 Mon Sep 17 00:00:00 2001 From: Michael Tang Date: Sun, 21 Apr 2019 19:41:14 -0700 Subject: [PATCH] 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