use std::{mem, sync::Arc}; use context::{prelude::*, ContextObject}; pub struct Fractal { context: Arc, descriptor_set: Arc, pipeline: Arc, render_target: RenderTarget, vertex_buffer: Arc>, } impl Fractal { pub fn new(context: &Arc) -> VerboseResult> { let render_core = context.render_core(); let render_target = RenderTarget::builder() .add_sub_pass( SubPass::builder(render_core.width(), render_core.height()) .set_prepared_targets( render_core.images()?.single()?, 0, [0.0, 0.0, 0.0, 0.0], true, ) .build(context.device(), context.queue())?, ) .build(context.device())?; let descriptor_layout = DescriptorSetLayout::builder() .add_layout_binding( 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT, 0, ) .build(context.device().clone())?; let pipeline_layout = PipelineLayout::builder() .add_descriptor_set_layout(&descriptor_layout) .build(context.device().clone())?; let pipeline = Pipeline::new_graphics() .default_rasterization(VK_CULL_MODE_FRONT_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE) .default_multisample(VK_SAMPLE_COUNT_1_BIT) .input_assembly(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, false) .default_color_blend(vec![VkPipelineColorBlendAttachmentState::default()]) .set_vertex_shader( ShaderModule::from_slice( context.device().clone(), include_bytes!("fractal.vert.spv"), ShaderType::Vertex, )?, vec![VkVertexInputBindingDescription { binding: 0, inputRate: VK_VERTEX_INPUT_RATE_VERTEX, stride: mem::size_of::<[f32; 2]>() as u32, }], vec![VkVertexInputAttributeDescription { location: 0, binding: 0, format: VK_FORMAT_R32G32_SFLOAT, offset: 0, }], ) .set_fragment_shader(ShaderModule::from_slice( context.device().clone(), include_bytes!("fractal.frag.spv"), ShaderType::Fragment, )?) .add_viewport(VkViewport { x: 0.0, y: 0.0, width: render_core.width() as f32, height: render_core.height() as f32, minDepth: 0.0, maxDepth: 1.0, }) .add_scissor(VkRect2D { offset: VkOffset2D { x: 0, y: 0 }, extent: VkExtent2D { width: render_core.width(), height: render_core.height(), }, }) .build( context.device().clone(), &pipeline_layout, render_target.render_pass(), 0, )?; let descriptor_set = DescriptorPool::builder() .set_layout(descriptor_layout) .build(context.device().clone())? .prepare_set() .allocate()?; let vertex_buffer = Buffer::builder() .set_data(&[ [-1.0, -1.0], [1.0, -1.0], [1.0, 1.0], [1.0, 1.0], [-1.0, 1.0], [-1.0, -1.0], ]) .set_memory_usage(MemoryUsage::CpuOnly) .set_usage(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT) .build(context.device().clone())?; Ok(Arc::new(Self { context: context.clone(), descriptor_set, pipeline, render_target, vertex_buffer, })) } } impl ContextObject for Fractal { fn name(&self) -> &str { "Fractal" } fn update(&self) -> VerboseResult<()> { Ok(()) } fn event(&self, event: Event) -> VerboseResult<()> { match event { Event::KeyDown(key) => match key { Keycode::Escape => self.context.close()?, _ => (), }, _ => (), } Ok(()) } } impl TScene for Fractal { fn update(&self) -> VerboseResult<()> { Ok(()) } fn process( &self, buffer_recorder: &mut CommandBufferRecorder<'_>, indices: &TargetMode, ) -> VerboseResult<()> { match indices { TargetMode::Single(index) => { self.render_target .begin(buffer_recorder, VK_SUBPASS_CONTENTS_INLINE, *index); buffer_recorder.bind_pipeline(&self.pipeline)?; buffer_recorder.bind_descriptor_sets_minimal(&[&self.descriptor_set])?; buffer_recorder.bind_vertex_buffer(&self.vertex_buffer); buffer_recorder.draw_complete_single_instance(self.vertex_buffer.size() as u32); self.render_target.end(buffer_recorder); } TargetMode::Stereo(_, _) => unimplemented!(), } Ok(()) } fn resize(&self) -> VerboseResult<()> { println!("resize of FB is still missing"); Ok(()) } }