#![cfg(target_os = "windows")]
use hotline_rs::*;
use os::{App, Window};
use gfx::{CmdBuf, Device, SwapChain, RenderPass};
#[repr(C)]
struct Vertex {
position: [f32; 3],
color: [f32; 4],
}
fn main() -> Result<(), hotline_rs::Error> {
let mut app = os_platform::App::create(os::AppInfo {
name: String::from("bindless"),
window: false,
num_buffers: 0,
dpi_aware: true,
});
let device = gfx_platform::Device::create(&gfx::DeviceInfo {
adapter_name: None,
shader_heap_size: 100,
render_target_heap_size: 100,
depth_stencil_heap_size: 100,
});
print!("{}", device.get_adapter_info());
let mut dev = device;
let mut win = app.create_window(os::WindowInfo {
title: String::from("bindless"),
rect: os::Rect {
x: 100,
y: 100,
width: 1280,
height: 720,
},
style: os::WindowStyleFlags::NONE,
parent_handle: None,
});
let swap_chain_info = gfx::SwapChainInfo {
num_buffers: 2,
format: gfx::Format::RGBA8n,
clear_colour: Some(gfx::ClearColour {
r: 0.45,
g: 0.55,
b: 0.60,
a: 1.00,
}),
};
let mut swap_chain = dev.create_swap_chain::<os_platform::App>(&swap_chain_info, &win)?;
let mut cmdbuffer = dev.create_cmd_buf(2);
let vertices = [
Vertex {
position: [-1.0, -1.0, 0.0],
color: [0.0, 0.0, 0.0, 1.0],
},
Vertex {
position: [-1.0, 1.0, 0.0],
color: [0.0, 1.0, 0.0, 1.0],
},
Vertex {
position: [1.0, 1.0, 0.0],
color: [1.0, 1.0, 0.0, 1.0],
},
Vertex {
position: [1.0, -1.0, 0.0],
color: [1.0, 0.0, 0.0, 1.0],
},
];
let info = gfx::BufferInfo {
usage: gfx::BufferUsage::VERTEX,
cpu_access: gfx::CpuAccessFlags::NONE,
format: gfx::Format::Unknown,
stride: std::mem::size_of::<Vertex>(),
num_elements: 4,
initial_state: gfx::ResourceState::VertexConstantBuffer
};
let vertex_buffer = dev.create_buffer(&info, Some(gfx::as_u8_slice(&vertices)))?;
let indices: [u16; 6] = [0, 1, 2, 0, 2, 3];
let info = gfx::BufferInfo {
usage: gfx::BufferUsage::INDEX,
cpu_access: gfx::CpuAccessFlags::NONE,
format: gfx::Format::R16u,
stride: std::mem::size_of::<u16>(),
num_elements: 6,
initial_state: gfx::ResourceState::IndexBuffer
};
let index_buffer = dev.create_buffer(&info, Some(gfx::as_u8_slice(&indices)))?;
let mut pmfx : pmfx::Pmfx<gfx_platform::Device> = pmfx::Pmfx::create(&mut dev, 0);
pmfx.load(&hotline_rs::get_data_path("shaders/bindless"))?;
pmfx.create_compute_pipeline(&dev, "compute_rw")?;
pmfx.create_render_pipeline(&dev, "bindless", swap_chain.get_backbuffer_pass())?;
let fmt = swap_chain.get_backbuffer_pass().get_format_hash();
let pso_pmfx = pmfx.get_render_pipeline_for_format("bindless", fmt)?;
let pso_compute = pmfx.get_compute_pipeline("compute_rw")?;
let mut textures: Vec<gfx_platform::Texture> = Vec::new();
let files = vec![
hotline_rs::get_src_data_path("textures/redchecker01.png"),
hotline_rs::get_src_data_path("textures/blend_test_fg.png"),
hotline_rs::get_src_data_path("textures/bear/bear_stomp_anim_001.png"),
hotline_rs::get_src_data_path("textures/bluechecker01.png"),
];
for file in files {
let image = image::load_from_file(&file)?;
let tex = dev.create_texture(&image.info, data![image.data.as_slice()])?;
textures.push(tex);
}
let constants: [f32; 4] = [1.0, 1.0, 0.0, 1.0];
let mut cbuffer: [f32; 64] = [0.0; 64];
cbuffer[0] = 1.0;
cbuffer[1] = 0.0;
cbuffer[2] = 1.0;
cbuffer[3] = 1.0;
let info = gfx::BufferInfo {
usage: gfx::BufferUsage::CONSTANT_BUFFER,
cpu_access: gfx::CpuAccessFlags::NONE,
format: gfx::Format::Unknown,
stride: cbuffer.len() * 4,
num_elements: 1,
initial_state: gfx::ResourceState::VertexConstantBuffer
};
let _constant_buffer = dev.create_buffer(&info, data![gfx::as_u8_slice(&cbuffer)]);
let rt_info = gfx::TextureInfo {
format: gfx::Format::RGBA8n,
tex_type: gfx::TextureType::Texture2D,
width: 512,
height: 512,
depth: 1,
array_layers: 1,
mip_levels: 1,
samples: 1,
usage: gfx::TextureUsage::SHADER_RESOURCE | gfx::TextureUsage::RENDER_TARGET,
initial_state: gfx::ResourceState::ShaderResource,
};
let render_target = dev.create_texture(&rt_info, data![]).unwrap();
let ds_info = gfx::TextureInfo {
format: gfx::Format::D24nS8u,
tex_type: gfx::TextureType::Texture2D,
width: 512,
height: 512,
depth: 1,
array_layers: 1,
mip_levels: 1,
samples: 1,
usage: gfx::TextureUsage::DEPTH_STENCIL,
initial_state: gfx::ResourceState::DepthStencil,
};
let depth_stencil = dev.create_texture::<u8>(&ds_info, None).unwrap();
let render_target_pass = dev
.create_render_pass(&gfx::RenderPassInfo {
render_targets: vec![&render_target],
rt_clear: Some(gfx::ClearColour {
r: 1.0,
g: 0.0,
b: 1.0,
a: 1.0,
}),
depth_stencil: Some(&depth_stencil),
ds_clear: Some(gfx::ClearDepthStencil {
depth: Some(1.0),
stencil: None,
}),
resolve: false,
discard: false,
array_slice: 0
})
.unwrap();
let rw_info = gfx::TextureInfo {
format: gfx::Format::RGBA8n,
tex_type: gfx::TextureType::Texture2D,
width: 512,
height: 512,
depth: 1,
array_layers: 1,
mip_levels: 1,
samples: 1,
usage: gfx::TextureUsage::SHADER_RESOURCE | gfx::TextureUsage::UNORDERED_ACCESS,
initial_state: gfx::ResourceState::ShaderResource,
};
let _rw_tex = dev.create_texture::<u8>(&rw_info, None).unwrap();
let mut ci = 0;
while app.run() {
win.update(&mut app);
swap_chain.update::<os_platform::App>(&mut dev, &win, &mut cmdbuffer);
cmdbuffer.reset(&swap_chain);
cmdbuffer.set_marker(0xff00ffff, "Frame Start");
cmdbuffer.begin_event(0xff0000ff, "Compute Pass");
cmdbuffer.set_compute_pipeline(pso_compute);
cmdbuffer.set_heap(pso_compute, dev.get_shader_heap());
cmdbuffer.dispatch(
gfx::Size3 {
x: 512 / 16,
y: 512 / 16,
z: 1,
},
gfx::Size3 {
x: 512,
y: 512,
z: 1,
},
);
cmdbuffer.end_event();
cmdbuffer.begin_event(0xff0000ff, "Render Target Pass");
cmdbuffer.transition_barrier(&gfx::TransitionBarrier {
texture: Some(&render_target),
buffer: None,
state_before: gfx::ResourceState::ShaderResource,
state_after: gfx::ResourceState::RenderTarget,
});
cmdbuffer.begin_render_pass(&render_target_pass);
cmdbuffer.end_render_pass();
cmdbuffer.transition_barrier(&gfx::TransitionBarrier {
texture: Some(&render_target),
buffer: None,
state_before: gfx::ResourceState::RenderTarget,
state_after: gfx::ResourceState::ShaderResource,
});
cmdbuffer.end_event();
cmdbuffer.begin_event(0xff0000ff, "Main Pass");
let vp_rect = win.get_viewport_rect();
let viewport = gfx::Viewport::from(vp_rect);
let scissor = gfx::ScissorRect::from(vp_rect);
cmdbuffer.transition_barrier(&gfx::TransitionBarrier {
texture: Some(swap_chain.get_backbuffer_texture()),
buffer: None,
state_before: gfx::ResourceState::Present,
state_after: gfx::ResourceState::RenderTarget,
});
let pass = swap_chain.get_backbuffer_pass_mut();
cmdbuffer.begin_render_pass(pass);
cmdbuffer.set_viewport(&viewport);
cmdbuffer.set_scissor_rect(&scissor);
cmdbuffer.set_render_pipeline(pso_pmfx);
cmdbuffer.set_heap(pso_pmfx, dev.get_shader_heap());
cmdbuffer.set_index_buffer(&index_buffer);
cmdbuffer.set_vertex_buffer(&vertex_buffer, 0);
cmdbuffer.push_render_constants(0, 4, 0, constants.as_slice());
cmdbuffer.draw_indexed_instanced(6, 1, 0, 0, 0);
cmdbuffer.end_render_pass();
cmdbuffer.transition_barrier(&gfx::TransitionBarrier {
texture: Some(swap_chain.get_backbuffer_texture()),
buffer: None,
state_before: gfx::ResourceState::RenderTarget,
state_after: gfx::ResourceState::Present,
});
cmdbuffer.end_event();
cmdbuffer.close()?;
dev.execute(&cmdbuffer);
swap_chain.swap(&dev);
ci = (ci + 1) % 4;
}
swap_chain.wait_for_last_frame();
dev.cleanup_dropped_resources(&swap_chain);
Ok(())
}