Skip to content

Instantly share code, notes, and snippets.

@StarArawn
Created March 25, 2019 15:32
Show Gist options
  • Save StarArawn/8c08830877a3afd5d3a39f1fa6d5430a to your computer and use it in GitHub Desktop.
Save StarArawn/8c08830877a3afd5d3a39f1fa6d5430a to your computer and use it in GitHub Desktop.
impl<B> SimpleGraphicsPipelineDesc<B, Game<B>> for SpriteBatchPassDesc
where B: gfx_hal::Backend,
{
type Pipeline = SpriteBatchPass<B>;
fn depth_stencil(&self) -> Option<gfx_hal::pso::DepthStencilDesc> {
None
}
fn vertices(&self) -> Vec<(
Vec<gfx_hal::pso::Element<gfx_hal::format::Format>>,
gfx_hal::pso::ElemStride,
gfx_hal::pso::InstanceRate,
)> {
vec![SpriteVertex::VERTEX.gfx_vertex_input_desc(0)]
}
fn load_shader_set<'a>(
&self,
storage: &'a mut Vec<B::ShaderModule>,
factory: &mut Factory<B>,
aux: &Game<B>,
) -> gfx_hal::pso::GraphicsShaderSet<'a, B> {
let sprite_shader = aux.asset_manager.get_shader(&String::from("sprite.shader"));
storage.clear();
storage.push(sprite_shader.vertex.module(factory).unwrap());
storage.push(sprite_shader.fragment.module(factory).unwrap());
gfx_hal::pso::GraphicsShaderSet {
vertex: gfx_hal::pso::EntryPoint {
entry: "main",
module: &storage[0],
specialization: gfx_hal::pso::Specialization::default(),
},
fragment: Some(gfx_hal::pso::EntryPoint {
entry: "main",
module: &storage[1],
specialization: gfx_hal::pso::Specialization::default(),
}),
hull: None,
domain: None,
geometry: None,
}
}
fn layout(&self) -> Layout {
Layout {
sets: vec![SetLayout {
bindings: vec![
gfx_hal::pso::DescriptorSetLayoutBinding {
binding: 0,
ty: gfx_hal::pso::DescriptorType::SampledImage,
count: 128,
stage_flags: gfx_hal::pso::ShaderStageFlags::FRAGMENT,
immutable_samplers: false,
},
gfx_hal::pso::DescriptorSetLayoutBinding {
binding: 1,
ty: gfx_hal::pso::DescriptorType::Sampler,
count: 1,
stage_flags: gfx_hal::pso::ShaderStageFlags::FRAGMENT,
immutable_samplers: false,
},
gfx_hal::pso::DescriptorSetLayoutBinding {
binding: 2,
ty: gfx_hal::pso::DescriptorType::UniformBuffer,
count: 1,
stage_flags: gfx_hal::pso::ShaderStageFlags::VERTEX,
immutable_samplers: false,
}
]
}],
push_constants: Vec::new(),
}
}
fn build<'a>(
self,
_rendy_graph: &mut rendy::graph::GraphContext<B>,
factory: &mut Factory<B>,
_queue: QueueId,
_game: &Game<B>,
buffers: Vec<NodeBuffer>,
images: Vec<NodeImage>,
set_layouts: &[rendy::resource::set::DescriptorSetLayout<B>]
) -> Result<SpriteBatchPass<B>, failure::Error> {
assert!(buffers.is_empty());
assert!(images.is_empty());
assert!(!set_layouts.is_empty());
let vertex = factory.create_buffer(512, SpriteVertex::VERTEX.stride as u64 * MAX_VERTICES, (gfx_hal::buffer::Usage::VERTEX, MemoryUsageValue::Dynamic))
.unwrap();
Ok(SpriteBatchPass {
vertex,
sets: vec![None, None, None, None, None]
})
}
}
impl<B> SimpleGraphicsPipeline<B, Game<B>> for SpriteBatchPass<B>
where
B: gfx_hal::Backend
{
type Desc = SpriteBatchPassDesc;
fn prepare(
&mut self,
factory: &Factory<B>,
_queue: QueueId,
sets: &[rendy::resource::set::DescriptorSetLayout<B>],
index: usize,
game: &Game<B>
) -> PrepareResult {
let sprite_batch = &game.graphics.as_ref().unwrap().sprite_batch;
if sprite_batch.vertices.is_empty() {
return PrepareResult::DrawReuse;
}
let mut uniform_buffer = factory.create_buffer(0, std::mem::size_of::<UniformBuffer>() as u64, (gfx_hal::buffer::Usage::INDIRECT, MemoryUsageValue::Dynamic))
.unwrap();
unsafe {
let uniform = UniformBuffer {
proj: (game.current_scene.camera.view * game.current_scene.camera.projection).into()
};
factory.upload_visible_buffer(&mut uniform_buffer, 0, &[uniform]).unwrap();
}
unsafe {
factory.upload_visible_buffer(&mut self.vertex, 0, &sprite_batch.vertices).unwrap();
}
let sprite_batch: &SpriteBatch = &game.graphics.as_ref().unwrap().sprite_batch;
let texture: &crate::texture::Texture2D<B> = game.asset_manager.get_texture(&sprite_batch.textures.first().unwrap());
let textures = sprite_batch.textures.iter().map(|texture_name| {
let texture = game.asset_manager.get_texture(&texture_name);
gfx_hal::pso::Descriptor::Image(texture.internal.image_view.raw(), gfx_hal::image::Layout::ShaderReadOnlyOptimal)
}).collect();
if self.sets[index].is_none() {
let descriptor_set = factory.create_descriptor_set(&sets[0]).unwrap();
self.sets[index] = Some(descriptor_set);
println!("Addding new frame: {}", index);
}
let current_set = self.sets[index].as_ref().unwrap();
unsafe {
gfx_hal::Device::write_descriptor_sets(
factory.device(),
vec![
gfx_hal::pso::DescriptorSetWrite {
set: current_set.raw(),
binding: 0,
array_offset: 0,
descriptors: textures,
},
gfx_hal::pso::DescriptorSetWrite {
set: current_set.raw(),
binding: 1,
array_offset: 0,
descriptors: vec!(gfx_hal::pso::Descriptor::Sampler(texture.internal.sampler.raw())),
},
gfx_hal::pso::DescriptorSetWrite {
set: current_set.raw(),
binding: 2,
array_offset: 0,
descriptors: vec!(gfx_hal::pso::Descriptor::Buffer(uniform_buffer.raw(), None..None)),
}
],
);
}
PrepareResult::DrawRecord
}
fn draw(
&mut self,
layout: &B::PipelineLayout,
mut encoder: RenderPassEncoder<'_, B>,
index: usize,
game: &Game<B>,
) {
let current_set = self.sets[index].as_ref().unwrap();
let sprite_batch = &game.graphics.as_ref().unwrap().sprite_batch;
if sprite_batch.vertices.is_empty() {
return;
}
encoder.bind_graphics_descriptor_sets(
layout,
0,
std::iter::once(current_set.raw()),
std::iter::empty::<u32>(),
);
encoder.bind_vertex_buffers(0, Some((self.vertex.raw(), 0)));
encoder.draw(0..sprite_batch.vertices.len() as u32, 0..1);
}
fn dispose(self, _factory: &mut Factory<B>, _aux: &Game<B>) {
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment