Skip to content

Commit

Permalink
[naga hlsl-out] Handle array types for function return values and cal…
Browse files Browse the repository at this point in the history
…ls (gfx-rs#6971)
  • Loading branch information
jamienicol authored Jan 23, 2025
1 parent 5e2bcc9 commit 0282d61
Show file tree
Hide file tree
Showing 9 changed files with 165 additions and 57 deletions.
60 changes: 40 additions & 20 deletions naga/src/back/hlsl/writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1336,25 +1336,37 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {

self.update_expressions_to_bake(module, func, info);

// Write modifier
if let Some(crate::FunctionResult {
binding:
Some(
ref binding @ crate::Binding::BuiltIn(crate::BuiltIn::Position {
invariant: true,
}),
),
..
}) = func.result
{
self.write_modifier(binding)?;
}

// Write return type
if let Some(ref result) = func.result {
// Write typedef if return type is an array
let array_return_type = match module.types[result.ty].inner {
TypeInner::Array { base, size, .. } => {
let array_return_type = self.namer.call(&format!("ret_{name}"));
write!(self.out, "typedef ")?;
self.write_type(module, result.ty)?;
write!(self.out, " {}", array_return_type)?;
self.write_array_size(module, base, size)?;
writeln!(self.out, ";")?;
Some(array_return_type)
}
_ => None,
};

// Write modifier
if let Some(
ref binding @ crate::Binding::BuiltIn(crate::BuiltIn::Position { invariant: true }),
) = result.binding
{
self.write_modifier(binding)?;
}

// Write return type
match func_ctx.ty {
back::FunctionType::Function(_) => {
self.write_type(module, result.ty)?;
if let Some(array_return_type) = array_return_type {
write!(self.out, "{array_return_type}")?;
} else {
self.write_type(module, result.ty)?;
}
}
back::FunctionType::EntryPoint(index) => {
if let Some(ref ep_output) = self.entry_point_io[index as usize].output {
Expand Down Expand Up @@ -2212,13 +2224,21 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
write!(self.out, "const ")?;
let name = Baked(expr).to_string();
let expr_ty = &func_ctx.info[expr].ty;
match *expr_ty {
proc::TypeResolution::Handle(handle) => self.write_type(module, handle)?,
let ty_inner = match *expr_ty {
proc::TypeResolution::Handle(handle) => {
self.write_type(module, handle)?;
&module.types[handle].inner
}
proc::TypeResolution::Value(ref value) => {
self.write_value_type(module, value)?
self.write_value_type(module, value)?;
value
}
};
write!(self.out, " {name} = ")?;
write!(self.out, " {name}")?;
if let TypeInner::Array { base, size, .. } = *ty_inner {
self.write_array_size(module, base, size)?;
}
write!(self.out, " = ")?;
self.named_expressions.insert(expr, name);
}
let func_name = &self.names[&NameKey::Function(function)];
Expand Down
8 changes: 6 additions & 2 deletions naga/tests/in/array-in-function-return-type.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@ fn ret_array() -> array<f32, 2> {
return array<f32, 2>(1.0, 2.0);
}

fn ret_array_array() -> array<array<f32, 2>, 3> {
return array<array<f32, 2>, 3>(ret_array(), ret_array(), ret_array());
}

@fragment
fn main() -> @location(0) vec4<f32> {
let a = ret_array();
return vec4<f32>(a[0], a[1], 0.0, 1.0);
let a = ret_array_array();
return vec4<f32>(a[0][0], a[0][1], 0.0, 1.0);
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,16 @@ float[2] ret_array() {
return float[2](1.0, 2.0);
}

void main() {
float[3][2] ret_array_array() {
float _e0[2] = ret_array();
_fs2p_location0 = vec4(_e0[0], _e0[1], 0.0, 1.0);
float _e1[2] = ret_array();
float _e2[2] = ret_array();
return float[3][2](_e0, _e1, _e2);
}

void main() {
float _e0[3][2] = ret_array_array();
_fs2p_location0 = vec4(_e0[0][0], _e0[0][1], 0.0, 1.0);
return;
}

32 changes: 32 additions & 0 deletions naga/tests/out/hlsl/array-in-function-return-type.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
typedef float ret_Constructarray2_float_[2];
ret_Constructarray2_float_ Constructarray2_float_(float arg0, float arg1) {
float ret[2] = { arg0, arg1 };
return ret;
}

typedef float ret_ret_array[2];
ret_ret_array ret_array()
{
return Constructarray2_float_(1.0, 2.0);
}

typedef float ret_Constructarray3_array2_float__[3][2];
ret_Constructarray3_array2_float__ Constructarray3_array2_float__(float arg0[2], float arg1[2], float arg2[2]) {
float ret[3][2] = { arg0, arg1, arg2 };
return ret;
}

typedef float ret_ret_array_array[3][2];
ret_ret_array_array ret_array_array()
{
const float _e0[2] = ret_array();
const float _e1[2] = ret_array();
const float _e2[2] = ret_array();
return Constructarray3_array2_float__(_e0, _e1, _e2);
}

float4 main() : SV_Target0
{
const float _e0[3][2] = ret_array_array();
return float4(_e0[0][0], _e0[0][1], 0.0, 1.0);
}
12 changes: 12 additions & 0 deletions naga/tests/out/hlsl/array-in-function-return-type.ron
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
(
vertex:[
],
fragment:[
(
entry_point:"main",
target_profile:"ps_5_1",
),
],
compute:[
],
)
15 changes: 13 additions & 2 deletions naga/tests/out/msl/array-in-function-return-type.msl
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,28 @@ using metal::uint;
struct type_1 {
float inner[2];
};
struct type_2 {
type_1 inner[3];
};

type_1 ret_array(
) {
return type_1 {1.0, 2.0};
}

type_2 ret_array_array(
) {
type_1 _e0 = ret_array();
type_1 _e1 = ret_array();
type_1 _e2 = ret_array();
return type_2 {_e0, _e1, _e2};
}

struct main_Output {
metal::float4 member [[color(0)]];
};
fragment main_Output main_(
) {
type_1 _e0 = ret_array();
return main_Output { metal::float4(_e0.inner[0], _e0.inner[1], 0.0, 1.0) };
type_2 _e0 = ret_array_array();
return main_Output { metal::float4(_e0.inner[0].inner[0], _e0.inner[0].inner[1], 0.0, 1.0) };
}
70 changes: 43 additions & 27 deletions naga/tests/out/spv/array-in-function-return-type.spvasm
Original file line number Diff line number Diff line change
@@ -1,42 +1,58 @@
; SPIR-V
; Version: 1.1
; Generator: rspirv
; Bound: 26
; Bound: 38
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %18 "main" %16
OpExecutionMode %18 OriginUpperLeft
OpEntryPoint Fragment %28 "main" %26
OpExecutionMode %28 OriginUpperLeft
OpDecorate %4 ArrayStride 4
OpDecorate %16 Location 0
OpDecorate %7 ArrayStride 8
OpDecorate %26 Location 0
%2 = OpTypeVoid
%3 = OpTypeFloat 32
%6 = OpTypeInt 32 0
%5 = OpConstant %6 2
%4 = OpTypeArray %3 %5
%7 = OpTypeVector %3 4
%10 = OpTypeFunction %4
%11 = OpConstant %3 1.0
%12 = OpConstant %3 2.0
%13 = OpConstantComposite %4 %11 %12
%17 = OpTypePointer Output %7
%16 = OpVariable %17 Output
%19 = OpTypeFunction %2
%20 = OpConstant %3 0.0
%9 = OpFunction %4 None %10
%8 = OpLabel
OpBranch %14
%14 = OpLabel
OpReturnValue %13
%8 = OpConstant %6 3
%7 = OpTypeArray %4 %8
%9 = OpTypeVector %3 4
%12 = OpTypeFunction %4
%13 = OpConstant %3 1.0
%14 = OpConstant %3 2.0
%15 = OpConstantComposite %4 %13 %14
%19 = OpTypeFunction %7
%27 = OpTypePointer Output %9
%26 = OpVariable %27 Output
%29 = OpTypeFunction %2
%30 = OpConstant %3 0.0
%11 = OpFunction %4 None %12
%10 = OpLabel
OpBranch %16
%16 = OpLabel
OpReturnValue %15
OpFunctionEnd
%18 = OpFunction %2 None %19
%15 = OpLabel
OpBranch %21
%21 = OpLabel
%22 = OpFunctionCall %4 %9
%23 = OpCompositeExtract %3 %22 0
%24 = OpCompositeExtract %3 %22 1
%25 = OpCompositeConstruct %7 %23 %24 %20 %11
OpStore %16 %25
%18 = OpFunction %7 None %19
%17 = OpLabel
OpBranch %20
%20 = OpLabel
%21 = OpFunctionCall %4 %11
%22 = OpFunctionCall %4 %11
%23 = OpFunctionCall %4 %11
%24 = OpCompositeConstruct %7 %21 %22 %23
OpReturnValue %24
OpFunctionEnd
%28 = OpFunction %2 None %29
%25 = OpLabel
OpBranch %31
%31 = OpLabel
%32 = OpFunctionCall %7 %18
%33 = OpCompositeExtract %4 %32 0
%34 = OpCompositeExtract %3 %33 0
%35 = OpCompositeExtract %4 %32 0
%36 = OpCompositeExtract %3 %35 1
%37 = OpCompositeConstruct %9 %34 %36 %30 %13
OpStore %26 %37
OpReturn
OpFunctionEnd
11 changes: 9 additions & 2 deletions naga/tests/out/wgsl/array-in-function-return-type.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,15 @@ fn ret_array() -> array<f32, 2> {
return array<f32, 2>(1f, 2f);
}

fn ret_array_array() -> array<array<f32, 2>, 3> {
let _e0 = ret_array();
let _e1 = ret_array();
let _e2 = ret_array();
return array<array<f32, 2>, 3>(_e0, _e1, _e2);
}

@fragment
fn main() -> @location(0) vec4<f32> {
let _e0 = ret_array();
return vec4<f32>(_e0[0], _e0[1], 0f, 1f);
let _e0 = ret_array_array();
return vec4<f32>(_e0[0][0], _e0[0][1], 0f, 1f);
}
3 changes: 1 addition & 2 deletions naga/tests/snapshots.rs
Original file line number Diff line number Diff line change
Expand Up @@ -676,14 +676,13 @@ fn convert_wgsl() {
let _ = env_logger::try_init();

let inputs = [
// TODO: merge array-in-ctor and array-in-function-return-type tests after fix HLSL issue https://github.com/gfx-rs/naga/issues/1930
(
"array-in-ctor",
Targets::SPIRV | Targets::METAL | Targets::GLSL | Targets::HLSL | Targets::WGSL,
),
(
"array-in-function-return-type",
Targets::SPIRV | Targets::METAL | Targets::GLSL | Targets::WGSL,
Targets::SPIRV | Targets::METAL | Targets::GLSL | Targets::HLSL | Targets::WGSL,
),
(
"empty",
Expand Down

0 comments on commit 0282d61

Please sign in to comment.