Skip to content

Commit

Permalink
Added variants and parameters.
Browse files Browse the repository at this point in the history
  • Loading branch information
facundo-villa committed Oct 6, 2023
1 parent fd8a0e7 commit c32039b
Show file tree
Hide file tree
Showing 8 changed files with 333 additions and 122 deletions.
275 changes: 209 additions & 66 deletions src/render_domain.rs

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/rendering/render_system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ pub trait CommandBufferRecording {
fn dispatch(&mut self, x: u32, y: u32, z: u32);
fn indirect_dispatch(&mut self, buffer_descriptor: &BufferDescriptor);

fn clear_texture(&mut self, texture_handle: TextureHandle, clear_value: ClearValue);
fn clear_buffer(&mut self, buffer_handle: BufferHandle);

/// Copies texture data from a CPU accessible buffer to a GPU accessible texture.
Expand Down
25 changes: 23 additions & 2 deletions src/rendering/vulkan_render_system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ impl render_system::RenderSystem for VulkanRenderSystem {

fn create_pipeline_layout(&mut self, descriptor_set_layout_handles: &[render_system::DescriptorSetLayoutHandle], push_constant_ranges: &[render_system::PushConstantRange]) -> render_system::PipelineLayoutHandle {
// self.create_vulkan_pipeline_layout(&descriptor_set_layout_handles.iter().map(|descriptor_set_layout_handle| vk::DescriptorSetLayout::from_raw(descriptor_set_layout_handle.0)).collect::<Vec<_>>())
let push_constant_ranges = push_constant_ranges.iter().map(|push_constant_range| vk::PushConstantRange::default().size(push_constant_range.size).offset(push_constant_range.offset).stage_flags(vk::ShaderStageFlags::VERTEX | vk::ShaderStageFlags::COMPUTE)).collect::<Vec<_>>();
let push_constant_ranges = push_constant_ranges.iter().map(|push_constant_range| vk::PushConstantRange::default().size(push_constant_range.size).offset(push_constant_range.offset).stage_flags(vk::ShaderStageFlags::VERTEX | vk::ShaderStageFlags::FRAGMENT | vk::ShaderStageFlags::COMPUTE)).collect::<Vec<_>>();
let set_layouts = descriptor_set_layout_handles.iter().map(|set_layout| vk::DescriptorSetLayout::from_raw(set_layout.0)).collect::<Vec<_>>();

let pipeline_layout_create_info = vk::PipelineLayoutCreateInfo::default()
Expand Down Expand Up @@ -2224,7 +2224,7 @@ impl render_system::CommandBufferRecording for VulkanCommandBufferRecording<'_>
fn write_to_push_constant(&mut self, pipeline_layout_handle: &render_system::PipelineLayoutHandle, offset: u32, data: &[u8]) {
let command_buffer = self.get_command_buffer();
let pipeline_layout = vk::PipelineLayout::from_raw(pipeline_layout_handle.0);
unsafe { self.render_system.device.cmd_push_constants(command_buffer.command_buffer, pipeline_layout, vk::ShaderStageFlags::VERTEX | vk::ShaderStageFlags::COMPUTE, offset, data); }
unsafe { self.render_system.device.cmd_push_constants(command_buffer.command_buffer, pipeline_layout, vk::ShaderStageFlags::VERTEX | vk::ShaderStageFlags::FRAGMENT | vk::ShaderStageFlags::COMPUTE, offset, data); }
}

/// Draws a render system mesh.
Expand Down Expand Up @@ -2269,6 +2269,27 @@ impl render_system::CommandBufferRecording for VulkanCommandBufferRecording<'_>
}
}

fn clear_texture(&mut self, texture_handle: render_system::TextureHandle, clear_value: render_system::ClearValue) {
let (texture_handle, texture) = self.get_texture(texture_handle);

let clear_value = match clear_value {
render_system::ClearValue::None => vk::ClearColorValue{ float32: [0.0, 0.0, 0.0, 0.0] },
render_system::ClearValue::Color(color) => vk::ClearColorValue{ float32: [color.r, color.g, color.b, color.a] },
render_system::ClearValue::Depth(depth) => vk::ClearColorValue{ float32: [depth, 0.0, 0.0, 0.0] },
render_system::ClearValue::Integer(r, g, b, a) => vk::ClearColorValue{ uint32: [r, g, b, a] },
};

unsafe {
self.render_system.device.cmd_clear_color_image(self.get_command_buffer().command_buffer, texture.image, vk::ImageLayout::GENERAL, &clear_value, &[vk::ImageSubresourceRange {
aspect_mask: vk::ImageAspectFlags::COLOR,
base_mip_level: 0,
level_count: vk::REMAINING_MIP_LEVELS,
base_array_layer: 0,
layer_count: vk::REMAINING_ARRAY_LAYERS,
}]);
}
}

fn clear_buffer(&mut self, buffer_handle: render_system::BufferHandle) {
unsafe {
self.render_system.device.cmd_fill_buffer(self.get_command_buffer().command_buffer, self.render_system.buffers[buffer_handle.0 as usize].buffer, 0, vk::WHOLE_SIZE, 0);
Expand Down
2 changes: 1 addition & 1 deletion src/resource_manager/image_resource_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ impl ResourceHandler for ImageResourceHandler {
}
}

fn process(&self, asset_url: &str, bytes: &[u8]) -> Result<Vec<(Document, Vec<u8>)>, String> {
fn process(&self, _: &super::ResourceManager, asset_url: &str, bytes: &[u8]) -> Result<Vec<(Document, Vec<u8>)>, String> {
let mut decoder = png::Decoder::new(bytes);
decoder.set_transformations(png::Transformations::EXPAND);
let mut reader = decoder.read_info().unwrap();
Expand Down
134 changes: 90 additions & 44 deletions src/resource_manager/material_resource_handler.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
use std::{collections::hash_map::DefaultHasher, hash::Hasher, rc::Rc};

use log::{warn, debug, error};
use polodb_core::bson::Document;
use polodb_core::bson::{Document, Deserializer, Serializer};
use serde::{Serialize, Deserialize};

use crate::{rendering::{shader_generator::ShaderGenerator, render_system}, shader_generator, jspd::{self, lexer}};

use super::ResourceHandler;
use super::{ResourceHandler, ResourceManager};

pub struct MaterialResourcerHandler {

Expand All @@ -26,6 +26,19 @@ pub struct Material {
pub model: Model,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct VariantVariable {
pub name: String,
pub value: String,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Variant {
/// Parent material asset url.
pub parent: String,
pub variables: Vec<VariantVariable>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Shader {
pub stage: render_system::ShaderTypes,
Expand Down Expand Up @@ -55,56 +68,89 @@ impl ResourceHandler for MaterialResourcerHandler {
}
}

fn process(&self, asset_url: &str, bytes: &[u8]) -> Result<Vec<(Document, Vec<u8>)>, String> {
let material_json = json::parse(std::str::from_utf8(&bytes).unwrap()).unwrap();
fn process(&self, resource_manager: &ResourceManager, asset_url: &str, bytes: &[u8]) -> Result<Vec<(Document, Vec<u8>)>, String> {
let asset_json = json::parse(std::str::from_utf8(&bytes).unwrap()).unwrap();

let material_domain = match &material_json["domain"] {
json::JsonValue::Null => { "Common".to_string() }
json::JsonValue::Short(s) => { s.to_string() }
json::JsonValue::String(s) => { s.to_string() }
_ => { panic!("Invalid domain") }
};
let is_material = asset_json["parent"].is_null();

let material_type = match &material_json["type"] {
json::JsonValue::Null => { "Raw".to_string() }
json::JsonValue::Short(s) => { s.to_string() }
json::JsonValue::String(s) => { s.to_string() }
_ => { panic!("Invalid type") }
};

let mut shaders = material_json["shaders"].entries().filter_map(|(s_type, shader_json)| {
Self::produce_shader(&material_domain, &material_json, &shader_json, s_type)
}).collect::<Vec<_>>();

let required_resources = shaders.iter().map(|s| polodb_core::bson::doc! { "path": s.1.clone() }).collect::<Vec<_>>();

let material_resource_document = polodb_core::bson::doc!{
"class": "Material",
"required_resources": required_resources,
"resource": {}
};
if is_material {
let material_domain = match &asset_json["domain"] {
json::JsonValue::Null => { "Common".to_string() }
json::JsonValue::Short(s) => { s.to_string() }
json::JsonValue::String(s) => { s.to_string() }
_ => { panic!("Invalid domain") }
};

shaders.push(((material_resource_document.clone(), Vec::new()), "".to_string()));
let material_type = match &asset_json["type"] {
json::JsonValue::Null => { "Raw".to_string() }
json::JsonValue::Short(s) => { s.to_string() }
json::JsonValue::String(s) => { s.to_string() }
_ => { panic!("Invalid type") }
};

let mut shaders = asset_json["shaders"].entries().filter_map(|(s_type, shader_json)| {
Self::produce_shader(&material_domain, &asset_json, &shader_json, s_type)
}).collect::<Vec<_>>();

let required_resources = shaders.iter().map(|s| polodb_core::bson::doc! { "path": s.1.clone() }).collect::<Vec<_>>();

let material_resource_document = polodb_core::bson::doc!{
"class": "Material",
"required_resources": required_resources,
"resource": {}
};

shaders.push(((material_resource_document.clone(), Vec::new()), "".to_string()));

Ok(shaders.iter().map(|s| s.0.clone()).collect::<Vec<_>>())
} else {
let variant_json = asset_json;

let parent_material_url = variant_json["parent"].as_str().unwrap();

let (buffer, _) = resource_manager.read_asset_from_source(parent_material_url).unwrap();

Ok(shaders.iter().map(|s| s.0.clone()).collect::<Vec<_>>())
let parent_material_json = json::parse(std::str::from_utf8(&buffer).unwrap()).unwrap();

let material_resource_document = polodb_core::bson::doc!{
"class": "Variant",
"required_resources": [polodb_core::bson::doc! { "path": parent_material_url }],
"resource": {
"parent": parent_material_url,
"variables": variant_json["variables"].members().map(|v| {
polodb_core::bson::doc! {
"name": v["name"].as_str().unwrap(),
"value": v["value"].as_str().unwrap(),
}
}).collect::<Vec<_>>()
}
};

Ok(vec![(material_resource_document, Vec::new())])
}
}

fn get_deserializers(&self) -> Vec<(&'static str, Box<dyn Fn(&polodb_core::bson::Document) -> Box<dyn std::any::Any> + Send>)> {
vec![("Material",
Box::new(|_document| {
Box::new(Material {
model: Model {
name: Self::RENDER_MODEL.to_string(),
pass: "MaterialEvaluation".to_string(),
},
})
})),
("Shader",
Box::new(|_document| {
Box::new(Shader {
stage: render_system::ShaderTypes::Compute,
})
}))]
Box::new(|_document| {
Box::new(Material {
model: Model {
name: Self::RENDER_MODEL.to_string(),
pass: "MaterialEvaluation".to_string(),
},
})
})),
("Shader",
Box::new(|_document| {
Box::new(Shader {
stage: render_system::ShaderTypes::Compute,
})
})),
("Variant",
Box::new(|document| {
Box::new(Variant::deserialize(polodb_core::bson::Deserializer::new(document.into())).unwrap())
})),
]
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/resource_manager/mesh_resource_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ impl ResourceHandler for MeshResourceHandler {
}
}

fn process(&self, asset_url: &str, bytes: &[u8]) -> Result<Vec<(Document, Vec<u8>)>, String> {
fn process(&self, _: &super::ResourceManager, asset_url: &str, bytes: &[u8]) -> Result<Vec<(Document, Vec<u8>)>, String> {
let (gltf, buffers, _) = gltf::import_slice(bytes).unwrap();

let mut buf: Vec<u8> = Vec::with_capacity(4096 * 1024 * 3);
Expand Down
8 changes: 4 additions & 4 deletions src/resource_manager/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ trait ResourceHandler {
/// - **resource**: The resource data. Can look like anything.
/// - **hash**(optional): The resource hash. This is used to identify the resource data. If the resource handler wants to generate a hash for the resource it can do so else the resource manager will generate a hash for it. This is because some resources can generate hashes inteligently (EJ: code generators can output same hash for different looking code if the code is semantically identical).
/// - **required_resources**(optional): A list of resources that this resource depends on. This is used to load resources that depend on other resources.
fn process(&self, asset_url: &str, bytes: &[u8]) -> Result<Vec<(Document, Vec<u8>)>, String>;
fn process(&self, resource_manager: &ResourceManager, asset_url: &str, bytes: &[u8]) -> Result<Vec<(Document, Vec<u8>)>, String>;

fn get_deserializers(&self) -> Vec<(&'static str, Box<dyn Fn(&polodb_core::bson::Document) -> Box<dyn std::any::Any> + Send>)>;

Expand Down Expand Up @@ -295,13 +295,13 @@ impl ResourceManager {
let resource_descriptions = if let Some(a) = gather(&self.db, path) {
a
} else {
let r = Self::read_asset_from_source(path).unwrap();
let r = self.read_asset_from_source(path).unwrap();

let mut generated_resources = Vec::new();

for resource_handler in &self.resource_handlers {
if resource_handler.can_handle_type(r.1.as_str()) {
generated_resources.append(&mut resource_handler.process(path, &r.0).unwrap());
generated_resources.append(&mut resource_handler.process(self, path, &r.0).unwrap());
}
}

Expand Down Expand Up @@ -433,7 +433,7 @@ impl ResourceManager {
/// ```ignore
/// let (bytes, format) = ResourceManager::read_asset_from_source("textures/concrete").unwrap(); // Path relative to .../assets
/// ```
fn read_asset_from_source(path: &str) -> Result<(Vec<u8>, String), Option<Document>> {
pub(super) fn read_asset_from_source(&self, path: &str) -> Result<(Vec<u8>, String), Option<Document>> {
let resource_origin = if path.starts_with("http://") || path.starts_with("https://") { "network" } else { "local" };
let mut source_bytes;
let format;
Expand Down
8 changes: 4 additions & 4 deletions tests/gi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ fn gi() {
focus_distance: 0.0,
});

let _floor: EntityHandle<Mesh> = orchestrator.spawn(Mesh{ resource_id: "Box", material_id: "solid", transform: maths_rs::Mat4f::from_translation(Vec3f::new(0.0, -0.25, 0.0)), });
let _a: EntityHandle<Mesh> = orchestrator.spawn(Mesh{ resource_id: "Box", material_id: "solid", transform: maths_rs::Mat4f::from_translation(Vec3f::new(0.0, 0.25, 2.0)) * maths_rs::Mat4f::from_scale(Vec3f::new(0.5, 0.5, 0.5)), });
let _b: EntityHandle<Mesh> = orchestrator.spawn(Mesh{ resource_id: "Box", material_id: "solid", transform: maths_rs::Mat4f::from_translation(Vec3f::new(-0.8, 0.17, 1.7)) * maths_rs::Mat4f::from_scale(Vec3f::new(0.34, 0.34, 0.34)), });
let _c: EntityHandle<Mesh> = orchestrator.spawn(Mesh{ resource_id: "Box", material_id: "solid", transform: maths_rs::Mat4f::from_translation(Vec3f::new(0.7, 0.13, 1.8)) * maths_rs::Mat4f::from_scale(Vec3f::new(0.26, 0.26, 0.26)), });
let _floor: EntityHandle<Mesh> = orchestrator.spawn(Mesh{ resource_id: "Box", material_id: "white_solid", transform: maths_rs::Mat4f::from_translation(Vec3f::new(0.0, -0.25, 0.0)), });
let _a: EntityHandle<Mesh> = orchestrator.spawn(Mesh{ resource_id: "Box", material_id: "white_solid", transform: maths_rs::Mat4f::from_translation(Vec3f::new(0.0, 0.25, 2.0)) * maths_rs::Mat4f::from_scale(Vec3f::new(0.5, 0.5, 0.5)), });
let _b: EntityHandle<Mesh> = orchestrator.spawn(Mesh{ resource_id: "Box", material_id: "red_solid", transform: maths_rs::Mat4f::from_translation(Vec3f::new(-0.8, 0.17, 1.7)) * maths_rs::Mat4f::from_scale(Vec3f::new(0.34, 0.34, 0.34)), });
let _c: EntityHandle<Mesh> = orchestrator.spawn(Mesh{ resource_id: "Box", material_id: "green_solid", transform: maths_rs::Mat4f::from_translation(Vec3f::new(0.7, 0.13, 1.8)) * maths_rs::Mat4f::from_scale(Vec3f::new(0.26, 0.26, 0.26)), });

app.do_loop();

Expand Down

0 comments on commit c32039b

Please sign in to comment.