aboutsummaryrefslogtreecommitdiff
path: root/stockton-render/src/draw/draw_passes/level.rs
diff options
context:
space:
mode:
Diffstat (limited to 'stockton-render/src/draw/draw_passes/level.rs')
-rw-r--r--stockton-render/src/draw/draw_passes/level.rs478
1 files changed, 0 insertions, 478 deletions
diff --git a/stockton-render/src/draw/draw_passes/level.rs b/stockton-render/src/draw/draw_passes/level.rs
deleted file mode 100644
index 682c775..0000000
--- a/stockton-render/src/draw/draw_passes/level.rs
+++ /dev/null
@@ -1,478 +0,0 @@
-//! Minimal code for drawing any level, based on traits from stockton-levels
-
-use super::{util::TargetSpecificResources, DrawPass, IntoDrawPass};
-use crate::{
- draw::{
- buffers::{
- draw_buffers::{DrawBuffers, INITIAL_INDEX_SIZE, INITIAL_VERT_SIZE},
- DedicatedLoadedImage, ModifiableBuffer,
- },
- builders::{
- pipeline::{
- CompletePipeline, PipelineSpecBuilder, VertexBufferSpec,
- VertexPrimitiveAssemblerSpec,
- },
- renderpass::RenderpassSpec,
- shader::ShaderDesc,
- },
- queue_negotiator::QueueNegotiator,
- target::SwapchainProperties,
- texture::{resolver::TextureResolver, TexLoadQueue, TextureLoadConfig, TextureRepo},
- },
- error::{EnvironmentError, LevelError, LockPoisoned},
- types::*,
-};
-use hal::{
- buffer::SubRange,
- command::{ClearColor, ClearDepthStencil, ClearValue, RenderAttachmentInfo, SubpassContents},
- format::{Aspects, Format},
- image::{
- Filter, FramebufferAttachment, Layout, SubresourceRange, Usage, ViewCapabilities, WrapMode,
- },
- pass::{Attachment, AttachmentLoadOp, AttachmentOps, AttachmentStoreOp},
- pso::{
- BlendDesc, BlendOp, BlendState, ColorBlendDesc, ColorMask, Comparison, DepthStencilDesc,
- DepthTest, Face, Factor, FrontFace, InputAssemblerDesc, LogicOp, PolygonMode, Primitive,
- Rasterizer, ShaderStageFlags, State, VertexInputRate,
- },
-};
-use legion::{Entity, IntoQuery};
-use shaderc::ShaderKind;
-use stockton_levels::{
- features::MinRenderFeatures,
- parts::{data::Geometry, IsFace},
-};
-use stockton_types::{
- components::{CameraSettings, CameraVPMatrix, Transform},
- *,
-};
-
-use std::{
- array::IntoIter,
- convert::TryInto,
- iter::{empty, once},
- marker::PhantomData,
- sync::{Arc, RwLock},
-};
-
-use anyhow::{Context, Result};
-
-/// The Vertexes that go to the shader
-#[derive(Debug, Clone, Copy)]
-struct UvPoint(pub Vector3, pub i32, pub Vector2);
-
-/// Draw a level
-pub struct LevelDrawPass<'a, M> {
- pipeline: CompletePipeline,
- repo: TextureRepo,
- active_camera: Entity,
- draw_buffers: DrawBuffers<'a, UvPoint>,
-
- framebuffers: TargetSpecificResources<FramebufferT>,
- depth_buffers: TargetSpecificResources<DedicatedLoadedImage>,
-
- _d: PhantomData<M>,
-}
-
-impl<'a, M> DrawPass for LevelDrawPass<'a, M>
-where
- M: for<'b> MinRenderFeatures<'b> + 'static,
-{
- fn queue_draw(
- &mut self,
- session: &Session,
- img_view: &ImageViewT,
- cmd_buffer: &mut crate::types::CommandBufferT,
- ) -> anyhow::Result<()> {
- // We might have loaded more textures
- self.repo.process_responses();
-
- // Make sure we update the vertex buffers after they're written to, but before they're read from.
- self.draw_buffers
- .vertex_buffer
- .record_commit_cmds(cmd_buffer)?;
- self.draw_buffers
- .index_buffer
- .record_commit_cmds(cmd_buffer)?;
-
- // Get level & camera
- let mut query = <(&Transform, &CameraSettings, &CameraVPMatrix)>::query();
- let (camera_transform, camera_settings, camera_vp) = query
- .get(&session.world, self.active_camera)
- .context("Couldn't find camera components")?;
- let map_lock: Arc<RwLock<M>> = session.resources.get::<Arc<RwLock<M>>>().unwrap().clone();
- let map = map_lock.read().map_err(|_| LockPoisoned::Map)?;
-
- // Get framebuffer and depth buffer
- let fb = self.framebuffers.get_next();
- let db = self.depth_buffers.get_next();
-
- unsafe {
- cmd_buffer.begin_render_pass(
- &self.pipeline.renderpass,
- fb,
- self.pipeline.render_area,
- vec![
- RenderAttachmentInfo {
- image_view: img_view,
- clear_value: ClearValue {
- color: ClearColor {
- float32: [0.0, 0.0, 0.0, 1.0],
- },
- },
- },
- RenderAttachmentInfo {
- image_view: &*db.image_view,
- clear_value: ClearValue {
- depth_stencil: ClearDepthStencil {
- depth: 1.0,
- stencil: 0,
- },
- },
- },
- ]
- .into_iter(),
- SubpassContents::Inline,
- );
- cmd_buffer.bind_graphics_pipeline(&self.pipeline.pipeline);
-
- // VP Matrix
- let vp = &*(camera_vp.vp_matrix.data.as_slice() as *const [f32] as *const [u32]);
-
- cmd_buffer.push_graphics_constants(
- &self.pipeline.pipeline_layout,
- ShaderStageFlags::VERTEX,
- 0,
- vp,
- );
-
- // Bind buffers
- cmd_buffer.bind_vertex_buffers(
- 0,
- once((
- self.draw_buffers.vertex_buffer.get_buffer(),
- SubRange {
- offset: 0,
- size: None,
- },
- )),
- );
- cmd_buffer.bind_index_buffer(
- self.draw_buffers.index_buffer.get_buffer(),
- SubRange {
- offset: 0,
- size: None,
- },
- hal::IndexType::U16,
- );
- }
-
- // Get visible faces
- let mut faces = map.get_visible(camera_transform, camera_settings);
-
- // Iterate over faces, copying them in and drawing groups that use the same texture chunk all at once.
- let face = faces.next();
- if let Some(face) = face {
- let mut face = map.get_face(face).ok_or(LevelError::BadReference)?;
- let mut current_chunk = face.texture_idx(&map) as usize / 8;
- let mut chunk_start = 0;
-
- let mut curr_vert_idx: usize = 0;
- let mut curr_idx_idx: usize = 0;
- loop {
- if current_chunk != face.texture_idx(&map) as usize / 8 {
- // Last index was last of group, so draw it all if textures are loaded.
- draw_or_queue(
- current_chunk,
- &mut self.repo,
- cmd_buffer,
- &*self.pipeline.pipeline_layout,
- chunk_start as u32,
- curr_idx_idx as u32,
- )?;
-
- // Next group of same-chunked faces starts here.
- chunk_start = curr_idx_idx;
- current_chunk = face.texture_idx(&map) as usize / 8;
- }
-
- match face.geometry(&map) {
- Geometry::Vertices(v1, v2, v3) => {
- for v in &[v1, v2, v3] {
- let uvp =
- UvPoint(v.position, face.texture_idx(&map).try_into()?, v.tex);
-
- self.draw_buffers.vertex_buffer[curr_vert_idx] = uvp;
- curr_vert_idx += 1;
- }
- self.draw_buffers.index_buffer[curr_idx_idx] = (
- curr_vert_idx as u16 - 3,
- curr_vert_idx as u16 - 2,
- curr_vert_idx as u16 - 1,
- );
- curr_idx_idx += 1;
- }
- }
-
- if curr_vert_idx >= INITIAL_VERT_SIZE.try_into()?
- || curr_idx_idx >= INITIAL_INDEX_SIZE.try_into()?
- {
- println!("out of vertex buffer space!");
- break;
- }
-
- match faces.next() {
- Some(x) => face = map.get_face(x).ok_or(LevelError::BadReference)?,
- None => break,
- };
- }
-
- // Draw the final group of chunks
- draw_or_queue(
- current_chunk,
- &mut self.repo,
- cmd_buffer,
- &*self.pipeline.pipeline_layout,
- chunk_start as u32,
- curr_idx_idx as u32,
- )?;
- }
-
- unsafe {
- cmd_buffer.end_render_pass();
- }
-
- Ok(())
- }
-
- fn deactivate(self, device_lock: &mut Arc<RwLock<DeviceT>>) -> Result<()> {
- unsafe {
- let mut device = device_lock.write().map_err(|_| LockPoisoned::Device)?;
- self.pipeline.deactivate(&mut device);
- self.draw_buffers.deactivate(&mut device);
- for fb in self.framebuffers.dissolve() {
- device.destroy_framebuffer(fb);
- }
- for db in self.depth_buffers.dissolve() {
- db.deactivate(&mut device);
- }
- }
- self.repo.deactivate(device_lock);
-
- Ok(())
- }
-}
-
-pub struct LevelDrawPassConfig<R> {
- pub active_camera: Entity,
- pub tex_resolver: R,
-}
-
-impl<'a, M, R> IntoDrawPass<LevelDrawPass<'a, M>> for LevelDrawPassConfig<R>
-where
- M: for<'b> MinRenderFeatures<'b> + 'static,
- R: TextureResolver + Send + Sync + 'static,
-{
- fn init(
- self,
- _session: &Session,
- adapter: &Adapter,
- device_lock: Arc<RwLock<DeviceT>>,
- queue_negotiator: &mut QueueNegotiator,
- swapchain_properties: &SwapchainProperties,
- ) -> Result<LevelDrawPass<'a, M>> {
- let spec = PipelineSpecBuilder::default()
- .rasterizer(Rasterizer {
- polygon_mode: PolygonMode::Fill,
- cull_face: Face::BACK,
- front_face: FrontFace::CounterClockwise,
- depth_clamping: false,
- depth_bias: None,
- conservative: true,
- line_width: State::Static(1.0),
- })
- .depth_stencil(DepthStencilDesc {
- depth: Some(DepthTest {
- fun: Comparison::Less,
- write: true,
- }),
- depth_bounds: false,
- stencil: None,
- })
- .blender(BlendDesc {
- logic_op: Some(LogicOp::Copy),
- targets: vec![ColorBlendDesc {
- mask: ColorMask::ALL,
- blend: Some(BlendState {
- color: BlendOp::Add {
- src: Factor::One,
- dst: Factor::Zero,
- },
- alpha: BlendOp::Add {
- src: Factor::One,
- dst: Factor::Zero,
- },
- }),
- }],
- })
- .primitive_assembler(VertexPrimitiveAssemblerSpec::with_buffers(
- InputAssemblerDesc::new(Primitive::TriangleList),
- vec![VertexBufferSpec {
- attributes: vec![Format::Rgb32Sfloat, Format::R32Sint, Format::Rg32Sfloat],
- rate: VertexInputRate::Vertex,
- }],
- ))
- .shader_vertex(ShaderDesc {
- source: include_str!("../data/stockton.vert").to_string(),
- entry: "main".to_string(),
- kind: ShaderKind::Vertex,
- })
- .shader_fragment(ShaderDesc {
- source: include_str!("../data/stockton.frag").to_string(),
- entry: "main".to_string(),
- kind: ShaderKind::Fragment,
- })
- .push_constants(vec![(ShaderStageFlags::VERTEX, 0..64)])
- .renderpass(RenderpassSpec {
- colors: vec![Attachment {
- format: Some(swapchain_properties.format),
- samples: 1,
- ops: AttachmentOps::new(AttachmentLoadOp::Clear, AttachmentStoreOp::Store),
- stencil_ops: AttachmentOps::new(
- AttachmentLoadOp::Clear,
- AttachmentStoreOp::DontCare,
- ),
- layouts: Layout::ColorAttachmentOptimal..Layout::ColorAttachmentOptimal,
- }],
- depth: Some(Attachment {
- format: Some(swapchain_properties.depth_format),
- samples: 1,
- ops: AttachmentOps::new(AttachmentLoadOp::Clear, AttachmentStoreOp::DontCare),
- stencil_ops: AttachmentOps::new(
- AttachmentLoadOp::DontCare,
- AttachmentStoreOp::DontCare,
- ),
- layouts: Layout::Undefined..Layout::DepthStencilAttachmentOptimal,
- }),
- inputs: vec![],
- resolves: vec![],
- preserves: vec![],
- })
- .build()
- .context("Error building pipeline")?;
-
- let repo = TextureRepo::new(
- device_lock.clone(),
- queue_negotiator
- .family::<TexLoadQueue>()
- .ok_or(EnvironmentError::NoSuitableFamilies)
- .context("Error finding texture queue")?,
- queue_negotiator
- .get_queue::<TexLoadQueue>()
- .ok_or(EnvironmentError::NoQueues)
- .context("Error finding texture queue")?,
- adapter,
- TextureLoadConfig {
- resolver: self.tex_resolver,
- filter: Filter::Linear,
- wrap_mode: WrapMode::Tile,
- },
- )
- .context("Error creating texture repo")?;
-
- let (draw_buffers, pipeline, framebuffers, depth_buffers) = {
- let mut device = device_lock.write().map_err(|_| LockPoisoned::Device)?;
- let draw_buffers =
- DrawBuffers::new(&mut device, adapter).context("Error creating draw buffers")?;
- let pipeline = spec
- .build(
- &mut device,
- swapchain_properties.extent,
- swapchain_properties,
- once(&*repo.get_ds_layout()?),
- )
- .context("Error building pipeline")?;
-
- let fat = swapchain_properties.framebuffer_attachment();
- let dat = FramebufferAttachment {
- usage: Usage::DEPTH_STENCIL_ATTACHMENT,
- format: swapchain_properties.depth_format,
- view_caps: ViewCapabilities::empty(),
- };
- let framebuffers = TargetSpecificResources::new(
- || unsafe {
- Ok(device.create_framebuffer(
- &pipeline.renderpass,
- IntoIter::new([fat.clone(), dat.clone()]),
- swapchain_properties.extent,
- )?)
- },
- swapchain_properties.image_count as usize,
- )?;
- let depth_buffers = TargetSpecificResources::new(
- || {
- DedicatedLoadedImage::new(
- &mut device,
- adapter,
- swapchain_properties.depth_format,
- Usage::DEPTH_STENCIL_ATTACHMENT,
- SubresourceRange {
- aspects: Aspects::DEPTH,
- level_start: 0,
- level_count: Some(1),
- layer_start: 0,
- layer_count: Some(1),
- },
- swapchain_properties.extent.width as usize,
- swapchain_properties.extent.height as usize,
- )
- .context("Error creating depth buffer")
- },
- swapchain_properties.image_count as usize,
- )?;
-
- (draw_buffers, pipeline, framebuffers, depth_buffers)
- };
-
- Ok(LevelDrawPass {
- pipeline,
- repo,
- draw_buffers,
- active_camera: self.active_camera,
- _d: PhantomData,
- framebuffers,
- depth_buffers,
- })
- }
-
- fn find_aux_queues<'c>(
- adapter: &'c Adapter,
- queue_negotiator: &mut QueueNegotiator,
- ) -> Result<Vec<(&'c QueueFamilyT, Vec<f32>)>> {
- queue_negotiator.find(adapter, &TexLoadQueue)?;
-
- Ok(vec![queue_negotiator
- .family_spec::<TexLoadQueue>(&adapter.queue_families, 1)
- .ok_or(EnvironmentError::NoSuitableFamilies)?])
- }
-}
-
-fn draw_or_queue(
- current_chunk: usize,
- tex_repo: &mut TextureRepo,
- cmd_buffer: &mut CommandBufferT,
- pipeline_layout: &PipelineLayoutT,
- chunk_start: u32,
- curr_idx_idx: u32,
-) -> Result<()> {
- if let Some(ds) = tex_repo.attempt_get_descriptor_set(current_chunk) {
- unsafe {
- cmd_buffer.bind_graphics_descriptor_sets(pipeline_layout, 0, once(ds), empty());
- cmd_buffer.draw_indexed(chunk_start * 3..(curr_idx_idx * 3) + 1, 0, 0..1);
- }
- } else {
- tex_repo.queue_load(current_chunk)?
- }
-
- Ok(())
-}