Skip to content

TSL: Variables without a stack node generated in unexpected stacks #32009

@shotamatsuda

Description

@shotamatsuda

Description

Related: #31929, #30954

Code for variables created without a stack node is generated in the stack where they first appear, which is understandable given the current implementation, but it can generate codes in unexpected stacks.

I suppose this is a known limitation of TSL, but I'd like to have an open issue for this. The closest issue would be #30954, whose root cause is the same, but this issue is not limited to Loop node.

Reproduction steps

The simplest example I can come up with is as follows:

output = select(bool(false), normalView, normalView.negate())

which produces the following code, similar to the one we saw in #31929, because some built-in nodes are declared as variables without a stack:

var nodeVar0 : vec3<f32>;
var normalViewGeometry : vec3<f32>;
var NORMAL_normalView : vec3<f32>;
var normalView : vec3<f32>;

if ( false ) {
  normalViewGeometry = normalize( v_normalViewGeometry );
  NORMAL_normalView = normalViewGeometry;
  normalView = NORMAL_normalView;
  nodeVar0 = normalView;
} else {
  normalView = NORMAL_normalView; // "NORMAL_normalView" isn't initialized
  nodeVar0 = ( - normalView );
}

A similar issue exists with Loop as follows:

output = Fn(() => {
  const a = vec3().toVar('a')
  Loop({ start: 0, end: 10 }, () => {
    a.addAssign(normalView)
  })
  return a
})()

which produces the following code:

var a : vec3<f32>;
var normalViewGeometry : vec3<f32>;
var NORMAL_normalView : vec3<f32>;
var normalView : vec3<f32>;

a = vec3<f32>( 0.0, 0.0, 0.0 );
for ( var i : i32 = 0; i < 10; i ++ ) {
  // "normalView" is computed in every loop step, which is not incorrect but is inefficient.
  normalViewGeometry = normalize( v_normalViewGeometry );
  NORMAL_normalView = normalViewGeometry;
  normalView = NORMAL_normalView;
  a = ( a + normalView );
}

The current workaround for this issue is manually storing them in temporary variables so that they are generated in the correct stack, but it would be better if TSL could handle this at the language level.

output = Fn(() => {
  const normalViewVar = normalView.toVar()
  return select(bool(false), normalViewVar, normalViewVar.negate())
})()

output = Fn(() => {
  const a = vec3().toVar('a')
  const normalViewVar = normalView.toVar()
  Loop({ start: 0, end: 10 }, () => {
    a.addAssign(normalViewVar)
  })
  return a
})()

Code

Please refer to the codes above and below.

Live example

https://jsfiddle.net/shotamatsuda/xp5z3nwo/

Screenshots

No response

Version

r180

Device

No response

Browser

No response

OS

No response

Metadata

Metadata

Assignees

Labels

BugTSLThree.js Shading Language

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions