// //! Wrapper around the RAL code in celeritas-core // use std::ffi::c_void; // use celeritas_sys::{ // BufferHandle, GPU_CmdEncoder, GPU_CmdEncoder_BeginRender, GPU_CmdEncoder_EndRender, // GPU_EncodeBindShaderData, GPU_GetDefaultEncoder, GPU_GetDefaultRenderpass, // GPU_GraphicsPipeline_Create, GPU_Pipeline, GraphicsPipelineDesc, // ShaderBindingKind_BINDING_BYTES, ShaderBinding__bindgen_ty_1, // ShaderBinding__bindgen_ty_1__bindgen_ty_1, ShaderDesc, ShaderVisibility_VISIBILITY_COMPUTE, // ShaderVisibility_VISIBILITY_FRAGMENT, ShaderVisibility_VISIBILITY_VERTEX, Str8, TextureHandle, // VertexDescription, MAX_SHADER_DATA_LAYOUTS, // }; // use thiserror::Error; // use crate::IntoFFI; // /// Holds a pointer to the raw `GPU_CmdEncoder` // pub struct FrameRenderEncoder(*mut GPU_CmdEncoder); // /// Holds a pointer to the raw `GPU_Renderpass` // pub struct RenderPass(pub *mut celeritas_sys::GPU_Renderpass); // /// Holds a pointer to the raw `GPU_Pipeline` // pub struct Pipeline(*mut celeritas_sys::GPU_Pipeline); // impl FrameRenderEncoder { // pub fn new(renderpass: &RenderPass) -> Self { // let enc = unsafe { // let enc = GPU_GetDefaultEncoder(); // GPU_CmdEncoder_BeginRender(enc, renderpass.0); // enc // }; // FrameRenderEncoder(enc) // } // } // impl Drop for FrameRenderEncoder { // fn drop(&mut self) { // unsafe { // GPU_CmdEncoder_EndRender(self.0); // } // } // } // impl FrameRenderEncoder { // pub fn set_vertex_buffer(&self, buf: BufferHandle) { // // TODO: Get buffer ptr from handle // // TODO: assert that buffer type is vertex // todo!() // } // pub fn set_index_buffer(&self, buf: BufferHandle) { // // TODO: Get buffer ptr from handle // // TODO: assert that buffer type is index // todo!() // } // pub fn bind(&mut self, data: &S) { // // TODO: fill ShaderDataLayout with correct data // unsafe { GPU_EncodeBindShaderData(self.0, 0, todo!()) } // } // } // // Vertex Descriptions // pub enum VertexAttrKind { // Floatx1, // Floatx2, // Floatx3, // Floatx4, // U32x1, // U32x2, // U32x3, // U32x4, // I32x1, // I32x2, // I32x3, // I32x4, // } // pub struct VertexAttribute { // name: String, // kind: VertexAttrKind, // } // #[derive(Default)] // pub struct VertexDesc { // debug_label: String, // attributes: Vec, // } // impl VertexDesc { // pub fn new(name: String) -> Self { // Self { // debug_label: name, // attributes: vec![], // } // } // pub fn add_attr(mut self, attr_name: &str, kind: VertexAttrKind) -> Self { // self.attributes.push(VertexAttribute { // name: attr_name.to_owned(), // kind, // }); // self // } // } // impl IntoFFI for VertexDesc { // type FFIType = VertexDescription; // unsafe fn into_ffi(self) -> Self::FFIType { // VertexDescription { // debug_label: todo!(), // attr_names: todo!(), // attributes: todo!(), // attributes_count: todo!(), // use_full_vertex_size: todo!(), // } // } // } // pub struct PipelineBuilder { // name: String, // renderpass: Option, // vertex_description: VertexDesc, // data_layouts: Vec, // shader_paths: Option<(String, String)>, // } // #[derive(Debug, Error)] // pub enum RALError { // #[error("exceeded maximum of 8 layouts for a pipeline")] // TooManyShaderDataLayouts, // } // impl PipelineBuilder { // /// Create a new [PipelineBuilder] // pub fn new(name: String) -> Self { // let vertex_description = VertexDesc::new(format!("{} Vertex Description", name.clone())); // Self { // name, // renderpass: None, // vertex_description, // data_layouts: Vec::new(), // shader_paths: None, // } // } // pub fn build(self) -> Result { // let layouts = [celeritas_sys::ShaderDataLayout::default(); 8]; // if self.data_layouts.len() > MAX_SHADER_DATA_LAYOUTS as usize { // return Err(RALError::TooManyShaderDataLayouts); // } // for (i, layout) in self.data_layouts.iter().enumerate().take(8) { // // layouts[i] = celeritas_sys::ShaderDataLayout::from(layout); // } // let (vert_path, frag_path) = self.shader_paths.expect("Shader paths must be provided"); // let vert_code = std::fs::read_to_string(vert_path.clone()).expect("msg"); // let frag_code = std::fs::read_to_string(frag_path.clone()).expect("msg"); // // TODO: convert VertexDesc -> ffi::VertexDescription // // load shader // let vs = ShaderDesc { // debug_name: "".as_ptr() as *const i8, // filepath: Str8::from_str(&vert_path), // code: Str8::from_str(&vert_code), // is_spirv: false, // is_combined_vert_frag: false, // }; // let fs = ShaderDesc { // debug_name: "".as_ptr() as *const i8, // filepath: Str8::from_str(&frag_path), // code: Str8::from_str(&frag_code), // is_spirv: false, // is_combined_vert_frag: false, // }; // let desc = GraphicsPipelineDesc { // debug_name: "".as_ptr() as *const _, // vertex_desc: unsafe { self.vertex_description.into_ffi() }, // vs, // fs, // data_layouts: layouts, // data_layouts_count: layouts.len() as u32, // wireframe: false, // depth_test: true, // }; // let p = unsafe { // GPU_GraphicsPipeline_Create( // desc, // self.renderpass // .map(|r| r.0) // .unwrap_or(GPU_GetDefaultRenderpass()), // ) // }; // Ok(Pipeline(p)) // } // pub fn add_vertex_desc(mut self, vertex_desc: VertexDesc) -> Self { // self.vertex_description = vertex_desc; // self // } // pub fn add_shader_layout(mut self) -> Self { // let layout = S::layout(); // self.data_layouts.push(layout); // self // } // pub fn add_shader_src(mut self, vertex_path: &str, fragment_path: &str) -> Self { // self.shader_paths = Some((vertex_path.to_owned(), fragment_path.to_owned())); // self // } // } // impl Pipeline { // pub fn raw_ptr(&self) -> *mut GPU_Pipeline { // self.0 // } // } // /// // pub trait ShaderData { // /// // fn layout() -> ShaderDataLayout; // /// // fn bind(&self); // // fn bind_texture(&self, binding_name: &str, handle: TextureHandle); // // fn bind_buffer(&self, binding_name: &str, handle: BufferHandle); // } // #[derive(Clone)] // pub struct ShaderBinding { // pub label: String, // // pub label: *const ::std::os::raw::c_char, // pub kind: ShaderBindingKind, // pub vis: ShaderVisibility, // // pub data: ShaderBinding__bindgen_ty_1, // } // #[derive(Clone)] // pub enum ShaderBindingKind { // Bytes { size: usize, data: Option<*mut u8> }, // Buffer(Option), // Texture(Option), // } // bitflags::bitflags! { // #[derive(Debug, Clone, Copy, PartialEq, Eq)] // pub struct ShaderVisibility : u32 { // const VERTEX = 1 << ShaderVisibility_VISIBILITY_VERTEX; // const FRAGMENT = 1 << ShaderVisibility_VISIBILITY_FRAGMENT; // const COMPUTE = 1 << ShaderVisibility_VISIBILITY_COMPUTE; // } // } // impl Default for ShaderVisibility { // fn default() -> Self { // ShaderVisibility::all() // } // } // #[derive(Default)] // pub struct ShaderDataLayout { // pub bindings: heapless::Vec, // } // impl ShaderDataLayout { // pub fn from_slice(bindings: &[ShaderBinding]) -> Self { // todo!() // } // } // impl ShaderDataLayout { // pub fn into_ffi_type(self) -> celeritas_sys::ShaderDataLayout { // let mut bindings = [celeritas_sys::ShaderBinding::default(); 8]; // for (i, b) in self.bindings.iter().enumerate().take(8) { // bindings[i] = match b.kind { // ShaderBindingKind::Bytes { size, data } => celeritas_sys::ShaderBinding { // label: b.label.as_ptr() as *const i8, // kind: ShaderBindingKind_BINDING_BYTES, // vis: ShaderVisibility_VISIBILITY_VERTEX, // data: ShaderBinding__bindgen_ty_1 { // bytes: ShaderBinding__bindgen_ty_1__bindgen_ty_1 { // size: size as u32, // data: data.unwrap() as *mut c_void, // }, // }, // }, // ShaderBindingKind::Buffer(_) => todo!(), // ShaderBindingKind::Texture(_) => todo!(), // }; // } // celeritas_sys::ShaderDataLayout { // bindings, // binding_count: bindings.len(), // } // } // } // // impl<'a> From<&ShaderDataLayout<'a>> for celeritas_sys::ShaderDataLayout { // // fn from(value: &ShaderDataLayout) -> Self { // // todo!() // // } // // } // // --- types // #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] // pub enum PrimitiveTopology { // Point, // Line, // Triangle, // } // impl From for PrimitiveTopology { // fn from(value: celeritas_sys::PrimitiveTopology) -> Self { // match value { // celeritas_sys::PrimitiveTopology_CEL_POINT => PrimitiveTopology::Point, // celeritas_sys::PrimitiveTopology_CEL_LINE => PrimitiveTopology::Line, // celeritas_sys::PrimitiveTopology_CEL_TRI => { // PrimitiveTopology::Triangle // } // _ => unreachable!("enum conversion should be infallible"), // } // } // } // #[cfg(test)] // mod test { // use super::*; // struct TestData { // _a: [f32; 2], // _b: [f32; 4], // } // impl ShaderData for TestData { // fn layout() -> ShaderDataLayout { // todo!() // } // fn bind(&self) { // todo!() // } // } // #[test] // fn typecheck_pipeline_create() { // let vertex_desc = VertexDesc::new("Empty".into()) // .add_attr("position", VertexAttrKind::Floatx2) // .add_attr("color", VertexAttrKind::Floatx4); // let builder = PipelineBuilder::new("Test Pipeline".into()) // .add_shader_layout::() // .add_vertex_desc(vertex_desc); // let pipeline = builder.build().expect("Should be valid"); // } // }