Add DirectX support behind feature flag

This commit is contained in:
Michael Tang 2019-04-21 19:41:14 -07:00
parent 616d61767f
commit d11e008aa0
8 changed files with 79 additions and 28 deletions

View File

@ -9,6 +9,11 @@ repository = "https://github.com/Gekkio/imgui-rs"
license = "MIT/Apache-2.0" license = "MIT/Apache-2.0"
publish = false publish = false
[features]
opengl = ["imgui-gfx-renderer/opengl"]
directx = ["imgui-gfx-renderer/directx"]
default = ["opengl"]
[dev-dependencies] [dev-dependencies]
gfx = "0.17" gfx = "0.17"
gfx_window_glutin = "0.28" gfx_window_glutin = "0.28"

4
imgui-examples/README.md Normal file
View File

@ -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`

View File

@ -5,11 +5,17 @@ mod support_gfx;
const CLEAR_COLOR: [f32; 4] = [1.0, 1.0, 1.0, 1.0]; const CLEAR_COLOR: [f32; 4] = [1.0, 1.0, 1.0, 1.0];
fn main() { 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 { 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) .size((300.0, 100.0), ImGuiCond::FirstUseEver)
.build(|| { .build(|| {
ui.text(im_str!("Hello world!")); ui.text(im_str!("Hello world!"));

View File

@ -3,6 +3,7 @@ use imgui_gfx_renderer::{Renderer, Shaders};
use imgui_winit_support; use imgui_winit_support;
use std::time::Instant; use std::time::Instant;
#[cfg(feature = "opengl")]
pub fn run<F: FnMut(&Ui) -> bool>(title: String, clear_color: [f32; 4], mut run_ui: F) { pub fn run<F: FnMut(&Ui) -> bool>(title: String, clear_color: [f32; 4], mut run_ui: F) {
use gfx::{self, Device}; use gfx::{self, Device};
use gfx_window_glutin; use gfx_window_glutin;
@ -146,8 +147,8 @@ pub fn run<F: FnMut(&Ui) -> bool>(title: String, clear_color: [f32; 4], mut run_
} }
} }
// #[cfg(windows)] #[cfg(feature = "directx")]
pub fn run_dx11<F: FnMut(&Ui) -> bool>(title: String, clear_color: [f32; 4], mut run_ui: F) { pub fn run<F: FnMut(&Ui) -> bool>(title: String, clear_color: [f32; 4], mut run_ui: F) {
use gfx::{self, Device}; use gfx::{self, Device};
use gfx_window_dxgi; use gfx_window_dxgi;
use glutin; use glutin;

View File

@ -9,6 +9,11 @@ repository = "https://github.com/Gekkio/imgui-rs"
license = "MIT/Apache-2.0" license = "MIT/Apache-2.0"
categories = ["gui", "rendering"] categories = ["gui", "rendering"]
[features]
opengl = []
directx = []
default = ["opengl"]
[badges] [badges]
travis-ci = { repository = "Gekkio/imgui-rs" } travis-ci = { repository = "Gekkio/imgui-rs" }

View File

@ -21,6 +21,8 @@ mod hlsl_build {
.join("shader") .join("shader")
.join("sm_40.hlsl"); .join("sm_40.hlsl");
println!("cargo:rerun-if-changed={}", source_path.display());
let src_data = fs::read_to_string(&source_path).unwrap(); let src_data = fs::read_to_string(&source_path).unwrap();
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());

View File

@ -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! { extended_defines! {
pipeline pipe { pipeline pipe {
vertex_buffer: gfx::VertexBuffer<ImDrawVert> = (), vertex_buffer: gfx::VertexBuffer<ImDrawVert> = (),
@ -91,12 +105,12 @@ extended_defines! {
} }
} }
// TODO need constant buffer support // This version of `pipe` uses a constant buffer containing `matrix`, used in the HLSL shader
#[cfg(windows)] #[cfg(feature = "directx")]
extended_defines! { extended_defines! {
pipeline pipe { pipeline pipe {
vertex_buffer: gfx::VertexBuffer<ImDrawVert> = (), vertex_buffer: gfx::VertexBuffer<ImDrawVert> = (),
matrix: gfx::Global<[[f32; 4]; 4]> = "transform", constants: gfx::ConstantBuffer<constants::Constants> = "Constants",
tex: gfx::TextureSampler<[f32; 4]> = "tex", tex: gfx::TextureSampler<[f32; 4]> = "tex",
out: gfx::BlendTarget<gfx::format::Rgba8> = ( out: gfx::BlendTarget<gfx::format::Rgba8> = (
"Target0", "Target0",
@ -109,13 +123,20 @@ extended_defines! {
#[derive(Copy, Clone, Debug, PartialEq, Eq)] #[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Shaders { pub enum Shaders {
GlSl400, // OpenGL 4.0+ /// OpenGL 4.0+
GlSl150, // OpenGL 3.2+ GlSl400,
GlSl130, // OpenGL 3.0+ /// OpenGL 3.2+
GlSl110, // OpenGL 2.0+ GlSl150,
GlSlEs300, // OpenGL ES 3.0+ /// OpenGL 3.0+
GlSlEs100, // OpenGL ES 2.0+ GlSl130,
HlslSm40, // HLSL Shader Model 4.0+ /// OpenGL 2.0+
GlSl110,
/// OpenGL ES 3.0+
GlSlEs300,
/// OpenGL ES 2.0+
GlSlEs100,
/// HLSL Shader Model 4.0+
HlslSm40,
} }
impl Shaders { impl Shaders {
@ -147,13 +168,13 @@ impl Shaders {
include_bytes!("shader/glsles_100.frag"), include_bytes!("shader/glsles_100.frag"),
), ),
HlslSm40 => { HlslSm40 => {
#[cfg(not(windows))] #[cfg(not(feature = "directx"))]
{ {
// panic instead? // panic instead?
(&[0], &[0]) (&[0], &[0])
} }
#[cfg(windows)] #[cfg(feature = "directx")]
{ {
( (
include_bytes!(concat!(env!("OUT_DIR"), "/hlsl_vertex_shader_bytecode")), include_bytes!(concat!(env!("OUT_DIR"), "/hlsl_vertex_shader_bytecode")),
@ -174,6 +195,8 @@ pub struct Renderer<R: Resources> {
bundle: Bundle<R, pipe::Data<R>>, bundle: Bundle<R, pipe::Data<R>>,
index_buffer: Buffer<R, u16>, index_buffer: Buffer<R, u16>,
textures: Textures<Texture<R>>, textures: Textures<Texture<R>>,
#[cfg(feature = "directx")]
constants: Buffer<R, constants::Constants>,
} }
impl<R: Resources> Renderer<R> { impl<R: Resources> Renderer<R> {
@ -230,6 +253,8 @@ impl<R: Resources> Renderer<R> {
}, },
index_buffer, index_buffer,
textures, textures,
#[cfg(feature = "directx")]
constants: factory.create_constant_buffer(1),
}) })
} }
@ -309,9 +334,19 @@ impl<R: Resources> Renderer<R> {
.min(fb_height) .min(fb_height)
.round() as u16, .round() as u16,
}; };
#[cfg(feature = "directx")]
{
let constants = constants::Constants { matrix: *matrix };
encoder.update_constant_buffer(&self.constants, &constants);
}
let data = pipe::BorrowedData { let data = pipe::BorrowedData {
vertex_buffer: &self.bundle.vertex_buffer, vertex_buffer: &self.bundle.vertex_buffer,
#[cfg(not(feature = "directx"))]
matrix, matrix,
#[cfg(feature = "directx")]
constants: &self.constants,
tex, tex,
out: &self.bundle.out, out: &self.bundle.out,
scissor: &scissor, scissor: &scissor,

View File

@ -1,16 +1,9 @@
cbuffer Constants : register(b0) { cbuffer Constants : register(b0) {
float4x4 transform; float4x4 matrix_;
} }
Texture2D tex; Texture2D tex;
SamplerState tex_;
// Should be trilinear clamp
SamplerState linear_clamp_sampler
{
Filter = MIN_MAG_MIP_LINEAR;
AddressU = Clamp;
AddressV = Clamp;
};
struct VIn { struct VIn {
float2 position : pos; float2 position : pos;
@ -28,7 +21,7 @@ struct VOut
VOut VertexMain(VIn vertex) VOut VertexMain(VIn vertex)
{ {
VOut output; 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.uv = vertex.uv;
output.color = vertex.color; output.color = vertex.color;
@ -37,5 +30,5 @@ VOut VertexMain(VIn vertex)
float4 PixelMain(VOut vout) : SV_TARGET float4 PixelMain(VOut vout) : SV_TARGET
{ {
return vout.color * tex.Sample(linear_clamp_sampler, vout.uv); return vout.color * tex.Sample(tex_, vout.uv);
} }