render: add SpecializedPipeline and SpecializedShader types
This commit is contained in:
parent
e57fdca1bc
commit
e89c693c4d
@ -22,15 +22,21 @@ pub struct ShaderSpecialization {
|
|||||||
pub shader_defs: HashSet<String>,
|
pub shader_defs: HashSet<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct SpecializedShader {
|
||||||
|
shader: Handle<Shader>,
|
||||||
|
specialization: ShaderSpecialization,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SpecializedPipeline {
|
||||||
|
pipeline: Handle<PipelineDescriptor>,
|
||||||
|
specialization: PipelineSpecialization,
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: consider using (Typeid, fieldinfo.index) in place of string for hashes
|
// TODO: consider using (Typeid, fieldinfo.index) in place of string for hashes
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct PipelineCompiler {
|
pub struct PipelineCompiler {
|
||||||
pub shader_source_to_compiled:
|
specialized_shaders: HashMap<Handle<Shader>, Vec<SpecializedShader>>,
|
||||||
HashMap<Handle<Shader>, Vec<(ShaderSpecialization, Handle<Shader>)>>,
|
specialized_pipelines: HashMap<Handle<PipelineDescriptor>, Vec<SpecializedPipeline>>,
|
||||||
pub specialized_pipelines: HashMap<
|
|
||||||
Handle<PipelineDescriptor>,
|
|
||||||
Vec<(PipelineSpecialization, Handle<PipelineDescriptor>)>,
|
|
||||||
>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PipelineCompiler {
|
impl PipelineCompiler {
|
||||||
@ -40,8 +46,8 @@ impl PipelineCompiler {
|
|||||||
shader_handle: &Handle<Shader>,
|
shader_handle: &Handle<Shader>,
|
||||||
shader_specialization: &ShaderSpecialization,
|
shader_specialization: &ShaderSpecialization,
|
||||||
) -> Handle<Shader> {
|
) -> Handle<Shader> {
|
||||||
let compiled_shaders = self
|
let specialized_shaders = self
|
||||||
.shader_source_to_compiled
|
.specialized_shaders
|
||||||
.entry(*shader_handle)
|
.entry(*shader_handle)
|
||||||
.or_insert_with(|| Vec::new());
|
.or_insert_with(|| Vec::new());
|
||||||
|
|
||||||
@ -52,15 +58,15 @@ impl PipelineCompiler {
|
|||||||
return *shader_handle;
|
return *shader_handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some((_shader_specialization, compiled_shader)) =
|
if let Some(specialized_shader) =
|
||||||
compiled_shaders
|
specialized_shaders
|
||||||
.iter()
|
.iter()
|
||||||
.find(|(current_shader_specialization, _compiled_shader)| {
|
.find(|current_specialized_shader| {
|
||||||
*current_shader_specialization == *shader_specialization
|
current_specialized_shader.specialization == *shader_specialization
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
// if shader has already been compiled with current configuration, use existing shader
|
// if shader has already been compiled with current configuration, use existing shader
|
||||||
*compiled_shader
|
specialized_shader.shader
|
||||||
} else {
|
} else {
|
||||||
// if no shader exists with the current configuration, create new shader and compile
|
// if no shader exists with the current configuration, create new shader and compile
|
||||||
let shader_def_vec = shader_specialization
|
let shader_def_vec = shader_specialization
|
||||||
@ -69,9 +75,12 @@ impl PipelineCompiler {
|
|||||||
.cloned()
|
.cloned()
|
||||||
.collect::<Vec<String>>();
|
.collect::<Vec<String>>();
|
||||||
let compiled_shader = shader.get_spirv_shader(Some(&shader_def_vec));
|
let compiled_shader = shader.get_spirv_shader(Some(&shader_def_vec));
|
||||||
let compiled_handle = shaders.add(compiled_shader);
|
let specialized_handle = shaders.add(compiled_shader);
|
||||||
compiled_shaders.push((shader_specialization.clone(), compiled_handle));
|
specialized_shaders.push(SpecializedShader {
|
||||||
compiled_handle
|
shader: specialized_handle,
|
||||||
|
specialization: shader_specialization.clone(),
|
||||||
|
});
|
||||||
|
specialized_handle
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,13 +95,13 @@ impl PipelineCompiler {
|
|||||||
render_resource_bindings: &RenderResourceBindings,
|
render_resource_bindings: &RenderResourceBindings,
|
||||||
) -> Handle<PipelineDescriptor> {
|
) -> Handle<PipelineDescriptor> {
|
||||||
let source_descriptor = pipelines.get(&source_pipeline).unwrap();
|
let source_descriptor = pipelines.get(&source_pipeline).unwrap();
|
||||||
let mut compiled_descriptor = source_descriptor.clone();
|
let mut specialized_descriptor = source_descriptor.clone();
|
||||||
compiled_descriptor.shader_stages.vertex = self.compile_shader(
|
specialized_descriptor.shader_stages.vertex = self.compile_shader(
|
||||||
shaders,
|
shaders,
|
||||||
&compiled_descriptor.shader_stages.vertex,
|
&specialized_descriptor.shader_stages.vertex,
|
||||||
&pipeline_specialization.shader_specialization,
|
&pipeline_specialization.shader_specialization,
|
||||||
);
|
);
|
||||||
compiled_descriptor.shader_stages.fragment = compiled_descriptor
|
specialized_descriptor.shader_stages.fragment = specialized_descriptor
|
||||||
.shader_stages
|
.shader_stages
|
||||||
.fragment
|
.fragment
|
||||||
.as_ref()
|
.as_ref()
|
||||||
@ -104,35 +113,38 @@ impl PipelineCompiler {
|
|||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
compiled_descriptor.reflect_layout(
|
specialized_descriptor.reflect_layout(
|
||||||
shaders,
|
shaders,
|
||||||
true,
|
true,
|
||||||
Some(vertex_buffer_descriptors),
|
Some(vertex_buffer_descriptors),
|
||||||
Some(render_resource_bindings),
|
Some(render_resource_bindings),
|
||||||
);
|
);
|
||||||
|
|
||||||
compiled_descriptor.primitive_topology = pipeline_specialization.primitive_topology;
|
specialized_descriptor.primitive_topology = pipeline_specialization.primitive_topology;
|
||||||
let compiled_pipeline_handle =
|
let specialized_pipeline_handle =
|
||||||
if *pipeline_specialization == PipelineSpecialization::default() {
|
if *pipeline_specialization == PipelineSpecialization::default() {
|
||||||
pipelines.set(source_pipeline, compiled_descriptor);
|
pipelines.set(source_pipeline, specialized_descriptor);
|
||||||
source_pipeline
|
source_pipeline
|
||||||
} else {
|
} else {
|
||||||
pipelines.add(compiled_descriptor)
|
pipelines.add(specialized_descriptor)
|
||||||
};
|
};
|
||||||
|
|
||||||
render_resource_context.create_render_pipeline(
|
render_resource_context.create_render_pipeline(
|
||||||
compiled_pipeline_handle,
|
specialized_pipeline_handle,
|
||||||
pipelines.get(&compiled_pipeline_handle).unwrap(),
|
pipelines.get(&specialized_pipeline_handle).unwrap(),
|
||||||
&shaders,
|
&shaders,
|
||||||
);
|
);
|
||||||
|
|
||||||
let compiled_pipelines = self
|
let specialized_pipelines = self
|
||||||
.specialized_pipelines
|
.specialized_pipelines
|
||||||
.entry(source_pipeline)
|
.entry(source_pipeline)
|
||||||
.or_insert_with(|| Vec::new());
|
.or_insert_with(|| Vec::new());
|
||||||
compiled_pipelines.push((pipeline_specialization.clone(), compiled_pipeline_handle));
|
specialized_pipelines.push(SpecializedPipeline {
|
||||||
|
pipeline: specialized_pipeline_handle,
|
||||||
|
specialization: pipeline_specialization.clone(),
|
||||||
|
});
|
||||||
|
|
||||||
compiled_pipeline_handle
|
specialized_pipeline_handle
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compile_render_pipelines(
|
fn compile_render_pipelines(
|
||||||
@ -145,17 +157,17 @@ impl PipelineCompiler {
|
|||||||
) {
|
) {
|
||||||
for render_pipeline in render_pipelines.pipelines.iter_mut() {
|
for render_pipeline in render_pipelines.pipelines.iter_mut() {
|
||||||
let source_pipeline = render_pipeline.pipeline;
|
let source_pipeline = render_pipeline.pipeline;
|
||||||
let compiled_pipeline_handle = if let Some((_shader_defs, compiled_pipeline_handle)) =
|
let compiled_pipeline_handle = if let Some(specialized_pipeline) =
|
||||||
self.specialized_pipelines
|
self.specialized_pipelines
|
||||||
.get_mut(&source_pipeline)
|
.get_mut(&source_pipeline)
|
||||||
.and_then(|specialized_pipelines| {
|
.and_then(|specialized_pipelines| {
|
||||||
specialized_pipelines.iter().find(
|
specialized_pipelines.iter().find(
|
||||||
|(pipeline_specialization, _compiled_pipeline_handle)| {
|
|current_specialized_pipeline| {
|
||||||
*pipeline_specialization == render_pipeline.specialization
|
current_specialized_pipeline.specialization == render_pipeline.specialization
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}) {
|
}) {
|
||||||
*compiled_pipeline_handle
|
specialized_pipeline.pipeline
|
||||||
} else {
|
} else {
|
||||||
self.compile_pipeline(
|
self.compile_pipeline(
|
||||||
render_resource_context,
|
render_resource_context,
|
||||||
@ -177,7 +189,7 @@ impl PipelineCompiler {
|
|||||||
pipeline_handle: Handle<PipelineDescriptor>,
|
pipeline_handle: Handle<PipelineDescriptor>,
|
||||||
) -> Option<impl Iterator<Item = &Handle<PipelineDescriptor>>> {
|
) -> Option<impl Iterator<Item = &Handle<PipelineDescriptor>>> {
|
||||||
if let Some(compiled_pipelines) = self.specialized_pipelines.get(&pipeline_handle) {
|
if let Some(compiled_pipelines) = self.specialized_pipelines.get(&pipeline_handle) {
|
||||||
Some(compiled_pipelines.iter().map(|(_, handle)| handle))
|
Some(compiled_pipelines.iter().map(|specialized_pipeline| &specialized_pipeline.pipeline))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@ -189,7 +201,7 @@ impl PipelineCompiler {
|
|||||||
.map(|compiled_pipelines| {
|
.map(|compiled_pipelines| {
|
||||||
compiled_pipelines
|
compiled_pipelines
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(_, pipeline_handle)| pipeline_handle)
|
.map(|specialized_pipeline| &specialized_pipeline.pipeline)
|
||||||
})
|
})
|
||||||
.flatten()
|
.flatten()
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ fn main() {
|
|||||||
.add_default_plugins()
|
.add_default_plugins()
|
||||||
.add_plugin(FrameTimeDiagnosticsPlugin::default())
|
.add_plugin(FrameTimeDiagnosticsPlugin::default())
|
||||||
.add_startup_system(setup.system())
|
.add_startup_system(setup.system())
|
||||||
// .add_system(text_update_system.system())
|
.add_system(text_update_system.system())
|
||||||
.run();
|
.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user