Skip to content
This repository has been archived by the owner on Jan 29, 2025. It is now read-only.

Commit

Permalink
[hlsl-out] Zero initialize variables. Write interpolation and samplin…
Browse files Browse the repository at this point in the history
…g qualifier
  • Loading branch information
Gordon-F committed Jul 7, 2021
1 parent 2b475ec commit c50537c
Show file tree
Hide file tree
Showing 7 changed files with 138 additions and 30 deletions.
114 changes: 91 additions & 23 deletions src/back/hlsl/writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ impl<'a, W: Write> Writer<'a, W> {
names: crate::FastHashMap::default(),
namer: proc::Namer::default(),
options,
ep_inputs: Vec::with_capacity(3),
ep_inputs: Vec::new(),
named_expressions: crate::NamedExpressions::default(),
}
}
Expand Down Expand Up @@ -139,8 +139,8 @@ 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, &ep.name, index)?;
for ep in module.entry_points.iter() {
self.write_ep_input_struct(module, &ep.function, ep.stage, &ep.name)?;
}

// Write all regular functions
Expand Down Expand Up @@ -196,7 +196,7 @@ impl<'a, W: Write> Writer<'a, W> {
})
}

fn write_binding(
fn write_semantic(
&mut self,
binding: &crate::Binding,
stage: Option<ShaderStage>,
Expand Down Expand Up @@ -224,7 +224,6 @@ impl<'a, W: Write> Writer<'a, W> {
func: &crate::Function,
stage: ShaderStage,
entry_point_name: &str,
index: usize,
) -> BackendResult {
if !func.arguments.is_empty() {
let struct_name_prefix = match stage {
Expand Down Expand Up @@ -255,7 +254,7 @@ impl<'a, W: Write> Writer<'a, W> {
self.write_type(module, member.ty)?;
write!(self.out, " {}", &member.name)?;
if let Some(ref binding) = member.binding {
self.write_binding(binding, Some(stage), Some(false))?;
self.write_semantic(binding, Some(stage), Some(false))?;
}
write!(self.out, ";")?;
writeln!(self.out)?;
Expand All @@ -272,7 +271,9 @@ impl<'a, W: Write> Writer<'a, W> {
members,
};

self.ep_inputs.insert(index, Some(ep_input));
self.ep_inputs.push(Some(ep_input));
} else {
self.ep_inputs.push(None);
}

Ok(())
Expand All @@ -289,6 +290,10 @@ impl<'a, W: Write> Writer<'a, W> {
let global = &module.global_variables[handle];
let inner = &module.types[global.ty].inner;

if let Some(storage_access) = storage_access(global.storage_access) {
write!(self.out, "{} ", storage_access)?;
}

let (storage_class, register_ty) = match *inner {
TypeInner::Image { .. } => ("", "t"),
TypeInner::Sampler { .. } => ("", "s"),
Expand All @@ -311,9 +316,11 @@ impl<'a, W: Write> Writer<'a, W> {
if let Some(ref binding) = global.binding {
writeln!(self.out, " : register({}{});", register_ty, binding.binding)?;
} else {
write!(self.out, " = ")?;
if let Some(init) = global.init {
write!(self.out, " = ")?;
self.write_constant(module, init)?;
} else {
self.write_default_init(module, global.ty)?;
}
writeln!(self.out, ";")?;
}
Expand Down Expand Up @@ -441,6 +448,24 @@ impl<'a, W: Write> Writer<'a, W> {
self.write_array_size(module, size)?;
}
_ => {
// Write interpolation modifier before type
if let Some(crate::Binding::Location {
interpolation,
sampling,
..
}) = member.binding
{
if let Some(interpolation) = interpolation {
write!(self.out, "{} ", interpolation_str(interpolation))?
}

if let Some(sampling) = sampling {
if let Some(str) = sampling_str(sampling) {
write!(self.out, "{} ", str)?
}
}
}

// Write the member type and name
self.write_type(module, member.ty)?;
write!(
Expand All @@ -452,7 +477,7 @@ impl<'a, W: Write> Writer<'a, W> {
}

if let Some(ref binding) = member.binding {
self.write_binding(binding, shader_stage, out)?;
self.write_semantic(binding, shader_stage, out)?;
};
write!(self.out, ";")?;
writeln!(self.out)?;
Expand Down Expand Up @@ -623,16 +648,8 @@ impl<'a, W: Write> Writer<'a, W> {
};
if let Some(ref result) = func.result {
if let Some(ref binding) = result.binding {
match *binding {
crate::Binding::BuiltIn(builtin) => {
write!(self.out, " : {}", builtin_str(builtin))?;
}
crate::Binding::Location { location, .. } => {
if stage == Some(ShaderStage::Fragment) {
write!(self.out, " : SV_Target{}", location)?;
}
}
}
let output = stage.is_some();
self.write_semantic(binding, stage, Some(output))?;
}
}

Expand All @@ -649,15 +666,18 @@ impl<'a, W: Write> Writer<'a, W> {
self.write_type(module, local.ty)?;
write!(self.out, " {}", self.names[&func_ctx.name_key(handle)])?;

write!(self.out, " = ")?;
// Write the local initializer if needed
if let Some(init) = local.init {
// Put the equal signal only if there's a initializer
// The leading and trailing spaces aren't needed but help with readability
write!(self.out, " = ")?;

// Write the constant
// `write_constant` adds no trailing or leading space/newline
self.write_constant(module, init)?;
} else {
// Zero initialize local variables
self.write_default_init(module, local.ty)?;
}

// Finish the local with `;` and add a newline (only for readability)
Expand Down Expand Up @@ -783,7 +803,7 @@ impl<'a, W: Write> Writer<'a, W> {
variable_name
)?;
self.write_expr(module, expr, func_ctx)?;
writeln!(self.out)?;
writeln!(self.out, ";")?;
writeln!(
self.out,
"{}return {};",
Expand Down Expand Up @@ -904,7 +924,7 @@ impl<'a, W: Write> Writer<'a, W> {
}
}
if is_struct {
write!(self.out, " }};")?
write!(self.out, " }}")?
} else {
write!(self.out, ")")?
}
Expand Down Expand Up @@ -993,7 +1013,6 @@ impl<'a, W: Write> Writer<'a, W> {
level: _, // TODO:
depth_ref: _, // TODO:
} => {
// TODO: others
self.write_expr(module, image, func_ctx)?;
write!(self.out, ".Sample(")?;
self.write_expr(module, sampler, func_ctx)?;
Expand Down Expand Up @@ -1331,6 +1350,15 @@ impl<'a, W: Write> Writer<'a, W> {

Ok(())
}

/// Helper function that write default zero initialization
fn write_default_init(&mut self, module: &Module, ty: Handle<crate::Type>) -> BackendResult {
write!(self.out, "(")?;
self.write_type(module, ty)?;
write!(self.out, ")0")?;

Ok(())
}
}

fn image_dimension_str(dim: crate::ImageDimension) -> &'static str {
Expand Down Expand Up @@ -1388,3 +1416,43 @@ fn scalar_kind_str(kind: crate::ScalarKind, width: crate::Bytes) -> Result<&'sta
Sk::Bool => Ok("bool"),
}
}

fn storage_access(storage_access: crate::StorageAccess) -> Option<&'static str> {
if storage_access == crate::StorageAccess::LOAD {
Some("ByteAddressBuffer")
} else if storage_access.is_all() {
Some("RWByteAddressBuffer")
} else {
None
}
}

fn number_of_components(vector_size: crate::VectorSize) -> usize {
match vector_size {
crate::VectorSize::Bi => 2,
crate::VectorSize::Tri => 3,
crate::VectorSize::Quad => 4,
}
}

/// Helper function that returns the string corresponding to the HLSL interpolation qualifier
fn interpolation_str(interpolation: crate::Interpolation) -> &'static str {
use crate::Interpolation as I;

match interpolation {
I::Perspective => "linear",
I::Linear => "noperspective",
I::Flat => "nointerpolation",
}
}

/// Return the HLSL auxiliary qualifier for the given sampling value.
fn sampling_str(sampling: crate::Sampling) -> Option<&'static str> {
use crate::Sampling as S;

match sampling {
S::Center => None,
S::Centroid => Some("centroid"),
S::Sample => Some("sample"),
}
}
2 changes: 1 addition & 1 deletion tests/out/hlsl/interface.hlsl
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
struct VertexOutput {
float4 position : SV_Position;
float varying : LOC1;
linear float varying : LOC1;
};

struct FragmentOutput {
Expand Down
36 changes: 36 additions & 0 deletions tests/out/hlsl/interpolate.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
struct FragmentInput {
float4 position : SV_Position;
nointerpolation uint flat : LOC0;
noperspective float linear1 : LOC1;
noperspective centroid float2 linear_centroid : LOC2;
noperspective sample float3 linear_sample : LOC3;
linear float4 perspective : LOC4;
linear centroid float perspective_centroid : LOC5;
linear sample float perspective_sample : LOC6;
};

struct FragmentInput_main {
FragmentInput val1;
};

FragmentInput main()
{
FragmentInput out1 = (FragmentInput)0;

out1.position = float4(2.0, 4.0, 5.0, 6.0);
out1.flat = 8u;
out1.linear1 = 27.0;
out1.linear_centroid = float2(64.0, 125.0);
out1.linear_sample = float3(216.0, 343.0, 512.0);
out1.perspective = float4(729.0, 1000.0, 1331.0, 1728.0);
out1.perspective_centroid = 2197.0;
out1.perspective_sample = 2744.0;
FragmentInput _expr30 = out1;
const FragmentInput fragmentinput1 = _expr30;
return fragmentinput1;
}

void main1(FragmentInput_main fragmentinput_main)
{
return;
}
4 changes: 4 additions & 0 deletions tests/out/hlsl/interpolate.hlsl.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
vertex=vs_5_0
vertex_name=main
fragment=ps_5_0
fragment_name=main1
8 changes: 4 additions & 4 deletions tests/out/hlsl/quad-vert.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,17 @@ struct gl_PerVertex {
};

struct type10 {
float2 member : LOC0;
linear float2 member : LOC0;
float4 gl_Position : SV_Position;
float gl_PointSize : PSIZE;
float gl_ClipDistance[1] : SV_ClipDistance;
float gl_CullDistance[1] : SV_CullDistance;
};

static float2 v_uv;
static float2 a_uv1;
static float2 v_uv = (float2)0;
static float2 a_uv1 = (float2)0;
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;
static float2 a_pos1 = (float2)0;

struct VertexInput_main {
float2 a_uv2 : LOC1;
Expand Down
2 changes: 1 addition & 1 deletion tests/out/hlsl/quad.hlsl
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
static const float c_scale = 1.2;

struct VertexOutput {
float2 uv : LOC0;
linear float2 uv : LOC0;
float4 position : SV_Position;
};

Expand Down
2 changes: 1 addition & 1 deletion tests/snapshots.rs
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,7 @@ fn convert_wgsl() {
),
(
"interpolate",
Targets::SPIRV | Targets::METAL | Targets::GLSL | Targets::WGSL,
Targets::SPIRV | Targets::METAL | Targets::GLSL | Targets::HLSL | Targets::WGSL,
),
("access", Targets::SPIRV | Targets::METAL | Targets::WGSL),
(
Expand Down

0 comments on commit c50537c

Please sign in to comment.