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

[hlsl-out] Zero initialize variables. Write interpolation and sampling qualifier #1075

Merged
merged 1 commit into from
Jul 7, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 {
kvark marked this conversation as resolved.
Show resolved Hide resolved
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,
kvark marked this conversation as resolved.
Show resolved Hide resolved
),
("access", Targets::SPIRV | Targets::METAL | Targets::WGSL),
(
Expand Down