[hlsl-out] Return entry points name to users

This commit is contained in:
Gordon-F 2021-06-24 13:59:35 +03:00 committed by Dzmitry Malyshau
parent 391983459a
commit e28344edbb
11 changed files with 92 additions and 62 deletions

View File

@ -304,9 +304,12 @@ fn main() {
}
"hlsl" => {
use naga::back::hlsl;
let hlsl = hlsl::write_string(&module, info.as_ref().unwrap(), &params.hlsl)
let mut buffer = String::new();
let mut writer = hlsl::Writer::new(&mut buffer, &params.hlsl);
writer
.write(&module, info.as_ref().unwrap())
.unwrap_pretty();
fs::write(output_path, hlsl).unwrap();
fs::write(output_path, buffer).unwrap();
}
"wgsl" => {
use naga::back::wgsl;

View File

@ -15,30 +15,45 @@ pub enum ShaderModel {
V6_0,
}
impl ShaderModel {
pub fn to_profile_string(self, stage: crate::ShaderStage) -> String {
let stage_prefix = match stage {
crate::ShaderStage::Vertex => "vs_",
crate::ShaderStage::Fragment => "ps_",
crate::ShaderStage::Compute => "cs_",
};
let version = match self {
Self::V5_0 => "5_0",
Self::V5_1 => "5_1",
Self::V6_0 => "6_0",
};
format!("{}{}", stage_prefix, version)
}
}
/// Structure that contains the configuration used in the [`Writer`](Writer)
#[derive(Debug, Clone)]
pub struct Options {
/// The hlsl shader model to be used
pub shader_model: ShaderModel,
/// The vertex entry point name in generated shader
pub vertex_entry_point_name: String,
/// The fragment entry point name in generated shader
pub fragment_entry_point_name: String,
/// The comput entry point name in generated shader
pub compute_entry_point_name: String,
}
impl Default for Options {
fn default() -> Self {
Options {
shader_model: ShaderModel::V5_0,
vertex_entry_point_name: String::from("vert_main"),
fragment_entry_point_name: String::from("frag_main"),
compute_entry_point_name: String::from("comp_main"),
}
}
}
pub struct ReflectionInfo {
/// Information about all entry points (stage, name).
pub entry_points: Vec<(crate::ShaderStage, String)>,
// TODO: locations
}
#[derive(Error, Debug)]
pub enum Error {
#[error(transparent)]
@ -50,14 +65,3 @@ pub enum Error {
#[error("{0}")]
Custom(String),
}
pub fn write_string(
module: &crate::Module,
info: &crate::valid::ModuleInfo,
options: &Options,
) -> Result<String, Error> {
let mut w = Writer::new(String::new(), options);
w.write(module, info)?;
let output = w.finish();
Ok(output)
}

View File

@ -13,9 +13,14 @@ const LOCATION_SEMANTIC: &str = "LOC";
/// Shorthand result used internally by the backend
type BackendResult = Result<(), Error>;
/// Structure contains information required for generating
/// wrapped structure of all entry points arguments
struct EntryPointBinding {
/// Associated shader stage
stage: ShaderStage,
/// Generated structure name
name: String,
/// Members of generated structure
members: Vec<EpStructMember>,
}
@ -29,8 +34,11 @@ pub struct Writer<'a, W> {
out: W,
names: crate::FastHashMap<NameKey, String>,
namer: proc::Namer,
/// HLSL backend options
options: &'a Options,
/// Information about entry point arguments wrapped into structure
ep_inputs: Vec<Option<EntryPointBinding>>,
/// Set of expressions that have associated temporary variables
named_expressions: crate::NamedExpressions,
}
@ -54,7 +62,11 @@ impl<'a, W: Write> Writer<'a, W> {
self.ep_inputs.clear();
}
pub fn write(&mut self, module: &Module, info: &valid::ModuleInfo) -> BackendResult {
pub fn write(
&mut self,
module: &Module,
info: &valid::ModuleInfo,
) -> Result<super::ReflectionInfo, Error> {
self.reset(module);
// Write all constants
@ -102,7 +114,7 @@ impl<'a, W: Write> Writer<'a, W> {
// Write all entry points wrapped structs
for (index, ep) in module.entry_points.iter().enumerate() {
self.write_ep_input_struct(module, &ep.function, ep.stage, index)?;
self.write_ep_input_struct(module, &ep.function, ep.stage, &ep.name, index)?;
}
// Write all regular functions
@ -121,6 +133,8 @@ impl<'a, W: Write> Writer<'a, W> {
writeln!(self.out)?;
}
let mut entry_points_info = Vec::with_capacity(module.entry_points.len());
// Write all entry points
for (index, ep) in module.entry_points.iter().enumerate() {
let ctx = back::FunctionCtx {
@ -140,20 +154,20 @@ impl<'a, W: Write> Writer<'a, W> {
)?;
}
let name = match ep.stage {
ShaderStage::Vertex => &self.options.vertex_entry_point_name,
ShaderStage::Fragment => &self.options.fragment_entry_point_name,
ShaderStage::Compute => &self.options.compute_entry_point_name,
};
let name = self.names[&NameKey::EntryPoint(index as u16)].clone();
self.write_function(module, name, &ep.function, &ctx)?;
self.write_function(module, &name, &ep.function, &ctx)?;
if index < module.entry_points.len() - 1 {
writeln!(self.out)?;
}
entry_points_info.push((ep.stage, name))
}
Ok(())
Ok(super::ReflectionInfo {
entry_points: entry_points_info,
})
}
fn write_binding(&mut self, binding: &crate::Binding) -> BackendResult {
@ -174,14 +188,16 @@ impl<'a, W: Write> Writer<'a, W> {
module: &Module,
func: &crate::Function,
stage: ShaderStage,
entry_point_name: &str,
index: usize,
) -> BackendResult {
if !func.arguments.is_empty() {
let struct_name = self.namer.call_unique(match stage {
let struct_name_prefix = match stage {
ShaderStage::Vertex => "VertexInput",
ShaderStage::Fragment => "FragmentInput",
ShaderStage::Compute => "ComputeInput",
});
};
let struct_name = format!("{}_{}", struct_name_prefix, entry_point_name);
let mut members = Vec::with_capacity(func.arguments.len());
@ -1058,10 +1074,6 @@ impl<'a, W: Write> Writer<'a, W> {
Ok(())
}
pub fn finish(self) -> W {
self.out
}
}
fn image_dimension_str(dim: crate::ImageDimension) -> &'static str {

View File

@ -29,3 +29,10 @@ fn main([[location(0)]] uv : vec2<f32>) -> [[location(0)]] vec4<f32> {
let premultiplied = color.a * color;
return premultiplied;
}
// We need to make sure that backends are successfully handling multiple entry points for the same shader stage.
//[[stage(fragment)]]
//fn fs_extra() -> [[location(0)]] vec4<f32> {
// return vec4<f32>(0.0, 0.5, 0.0, 0.5);
//}

View File

@ -1,5 +1,5 @@
[numthreads(1, 1, 1)]
void comp_main()
void main()
{
return;
}

View File

@ -1,2 +1,2 @@
compute=cs_5_0
compute_name=comp_main
compute_name=main

View File

@ -18,7 +18,7 @@ static float2 a_uv1;
static gl_PerVertex perVertexStruct = { float4(0.0, 0.0, 0.0, 1.0), 1.0, float(0.0), float(0.0) };
static float2 a_pos1;
struct VertexInput {
struct VertexInput_main {
float2 a_uv2 : LOC1;
float2 a_pos2 : LOC0;
};
@ -32,10 +32,10 @@ void main1()
return;
}
type10 vert_main(VertexInput vertexinput)
type10 main(VertexInput_main vertexinput_main)
{
a_uv1 = vertexinput.a_uv2;
a_pos1 = vertexinput.a_pos2;
a_uv1 = vertexinput_main.a_uv2;
a_pos1 = vertexinput_main.a_pos2;
main1();
float2 _expr10 = v_uv;
float4 _expr11 = perVertexStruct.gl_Position;

View File

@ -1,2 +1,2 @@
vertex=vs_5_0
vertex_name=vert_main
vertex_name=main

View File

@ -8,24 +8,24 @@ struct VertexOutput {
Texture2D<float4> u_texture : register(t0);
SamplerState u_sampler : register(s1);
struct VertexInput {
struct VertexInput_main {
float2 pos1 : LOC0;
float2 uv2 : LOC1;
};
struct FragmentInput {
struct FragmentInput_main {
float2 uv3 : LOC0;
};
VertexOutput vert_main(VertexInput vertexinput)
VertexOutput main(VertexInput_main vertexinput_main)
{
const VertexOutput vertexoutput1 = { vertexinput.uv2, float4((c_scale * vertexinput.pos1), 0.0, 1.0) };
const VertexOutput vertexoutput1 = { vertexinput_main.uv2, float4((c_scale * vertexinput_main.pos1), 0.0, 1.0) };
return vertexoutput1;
}
float4 frag_main(FragmentInput fragmentinput) : SV_Target0
float4 main1(FragmentInput_main fragmentinput_main) : SV_Target0
{
float4 color = u_texture.Sample(u_sampler, fragmentinput.uv3);
float4 color = u_texture.Sample(u_sampler, fragmentinput_main.uv3);
if ((color.w == 0.0)) {
discard;
}

View File

@ -1,4 +1,4 @@
vertex=vs_5_0
vertex_name=vert_main
vertex_name=main
fragment=ps_5_0
fragment_name=frag_main
fragment_name=main1

View File

@ -261,26 +261,30 @@ fn write_output_hlsl(
file_name: &str,
) {
use naga::back::hlsl;
let mut buffer = String::new();
let options = hlsl::Options::default();
let string = hlsl::write_string(module, info, &options).unwrap();
let mut writer = hlsl::Writer::new(&mut buffer, &options);
let reflection_info = writer.write(module, info).unwrap();
fs::write(destination.join(format!("hlsl/{}.hlsl", file_name)), string).unwrap();
fs::write(destination.join(format!("hlsl/{}.hlsl", file_name)), buffer).unwrap();
// We need a config file for validation script
// This file contains an info about profiles (shader stages) contains inside generated shader
// This info will be passed to dxc
let mut config_str = String::from("");
for ep in module.entry_points.iter() {
let (stage_str, profile, ep_name) = match ep.stage {
naga::ShaderStage::Vertex => ("vertex", "vs_5_0", &options.vertex_entry_point_name),
naga::ShaderStage::Fragment => {
("fragment", "ps_5_0", &options.fragment_entry_point_name)
}
naga::ShaderStage::Compute => ("compute", "cs_5_0", &options.compute_entry_point_name),
for (stage, name) in reflection_info.entry_points.iter() {
let stage_str = match stage {
naga::ShaderStage::Vertex => "vertex",
naga::ShaderStage::Fragment => "fragment",
naga::ShaderStage::Compute => "compute",
};
config_str = format!(
"{}{}={}\n{}_name={}\n",
config_str, stage_str, profile, stage_str, ep_name
config_str,
stage_str,
options.shader_model.to_profile_string(*stage),
stage_str,
name
);
}
fs::write(