shader: Initialize output parameters explicitly

This commit is contained in:
Hajime Hoshi 2020-09-07 00:13:46 +09:00
parent 404a662383
commit 2fb1033183
12 changed files with 77 additions and 4 deletions

View File

@ -724,6 +724,15 @@ func (cs *compileState) parseBlock(outer *block, fname string, stmts []ast.Stmt,
}
}()
if outer.outer == nil && len(outParams) > 0 && outParams[0].name != "" {
for i := range outParams {
block.ir.Stmts = append(block.ir.Stmts, shaderir.Stmt{
Type: shaderir.Init,
InitIndex: len(inParams) + i,
})
}
}
for _, stmt := range stmts {
ss, ok := cs.parseStmt(block, fname, stmt, inParams, outParams)
if !ok {

View File

@ -379,9 +379,11 @@ func (cs *compileState) parseStmt(block *block, fname string, stmt ast.Stmt, inP
case *ast.ReturnStmt:
if len(stmt.Results) != len(outParams) {
// TODO: Implenet multiple-value context.
cs.addError(stmt.Pos(), fmt.Sprintf("the number of returning variables must be %d but %d", len(outParams), len(stmt.Results)))
return nil, false
if !(len(stmt.Results) == 0 && len(outParams) > 0 && outParams[0].name != "") {
// TODO: Implenet multiple-value context.
cs.addError(stmt.Pos(), fmt.Sprintf("the number of returning variables must be %d but %d", len(outParams), len(stmt.Results)))
return nil, false
}
}
for i, r := range stmt.Results {

View File

@ -0,0 +1,8 @@
void F0(thread float& l0, thread array<float, 4>& l1, thread float4& l2);
void F0(thread float& l0, thread array<float, 4>& l1, thread float4& l2) {
l0 = float(0);
l1 = {};
l2 = float4(0);
return;
}

View File

@ -0,0 +1,11 @@
void F0(out float l0, out float l1[4], out vec4 l2);
void F0(out float l0, out float l1[4], out vec4 l2) {
l0 = float(0);
l1[0] = float(0);
l1[1] = float(0);
l1[2] = float(0);
l1[3] = float(0);
l2 = vec4(0);
return;
}

5
internal/shader/testdata/out.go vendored Normal file
View File

@ -0,0 +1,5 @@
package main
func Foo() (a float, b [4]float, c vec4) {
return
}

View File

@ -0,0 +1,8 @@
void F0(in vec2 l0, out vec3 l1, out vec4 l2);
void F0(in vec2 l0, out vec3 l1, out vec4 l2) {
l1 = vec3(0);
l2 = vec4(0);
l1 = vec3(1.0);
return;
}

6
internal/shader/testdata/return.go vendored Normal file
View File

@ -0,0 +1,6 @@
package main
func Foo(a vec2) (b vec3, c vec4) {
b = vec3(1)
return
}

View File

@ -7,6 +7,9 @@ varying vec4 V1;
void main(void) {
mat4 l0 = mat4(0);
gl_Position = vec4(0);
V0 = vec2(0);
V1 = vec4(0);
l0 = mat4((2.0) / ((U0).x), 0.0, 0.0, 0.0, 0.0, (2.0) / ((U0).y), 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, -1.0, -1.0, 0.0, 1.0);
gl_Position = (l0) * (vec4(A0, 0.0, 1.0));
V0 = A1;

View File

@ -7,6 +7,9 @@ varying vec4 V1;
void main(void) {
mat4 l0 = mat4(0);
gl_Position = vec4(0);
V0 = vec2(0);
V1 = vec4(0);
l0 = mat4((2.0) / ((U0).x), 0.0, 0.0, 0.0, 0.0, (2.0) / ((U0).y), 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, -1.0, -1.0, 0.0, 1.0);
gl_Position = (l0) * (vec4(A0, 0.0, 1.0));
V0 = A1;

View File

@ -414,6 +414,8 @@ func (c *compileContext) glslBlock(p *shaderir.Program, topBlock, block *shaderi
}
}
lines = append(lines, fmt.Sprintf("%s%s = %s;", idt, glslExpr(&lhs), glslExpr(&rhs)))
case shaderir.Init:
lines = append(lines, c.initVariable(p, topBlock, block, s.InitIndex, false, level)...)
case shaderir.If:
lines = append(lines, fmt.Sprintf("%sif (%s) {", idt, glslExpr(&s.Exprs[0])))
lines = append(lines, c.glslBlock(p, topBlock, s.Blocks[0], level+1)...)

View File

@ -313,10 +313,10 @@ func localVariableName(p *shaderir.Program, topBlock *shaderir.Block, idx int) s
func (c *compileContext) initVariable(p *shaderir.Program, topBlock, block *shaderir.Block, index int, decl bool, level int) []string {
idt := strings.Repeat("\t", level+1)
name := localVariableName(p, topBlock, index)
t := p.LocalVariableType(topBlock, block, index)
var lines []string
name := localVariableName(p, topBlock, index)
if decl {
lines = append(lines, fmt.Sprintf("%s%s = %s;", idt, c.metalVarDecl(p, &t, name, false, false), c.metalVarInit(p, &t)))
} else {
@ -412,6 +412,20 @@ func (c *compileContext) metalBlock(p *shaderir.Program, topBlock, block *shader
lines = append(lines, idt+"}")
case shaderir.Assign:
lines = append(lines, fmt.Sprintf("%s%s = %s;", idt, metalExpr(&s.Exprs[0]), metalExpr(&s.Exprs[1])))
case shaderir.Init:
init := true
if topBlock == p.VertexFunc.Block {
// In the vertex function, varying values are the output parameters.
// These values are represented as a struct and not needed to be initialized.
na := len(p.Attributes)
nv := len(p.Varyings)
if s.InitIndex < na+nv+1 {
init = false
}
}
if init {
lines = append(lines, c.initVariable(p, topBlock, block, s.InitIndex, false, level)...)
}
case shaderir.If:
lines = append(lines, fmt.Sprintf("%sif (%s) {", idt, metalExpr(&s.Exprs[0])))
lines = append(lines, c.metalBlock(p, topBlock, s.Blocks[0], level+1)...)

View File

@ -73,6 +73,7 @@ type Stmt struct {
ForEnd constant.Value
ForOp Op
ForDelta constant.Value
InitIndex int
}
type StmtType int
@ -81,6 +82,7 @@ const (
ExprStmt StmtType = iota
BlockStmt
Assign
Init
If
For
Continue