internal/shader: bug fix: bitwise operators with assignment didn't work

Closes #2752
Updates #2754
This commit is contained in:
Hajime Hoshi 2023-09-12 03:00:34 +09:00
parent c13980158f
commit 73e4423fe7
2 changed files with 67 additions and 1 deletions

View File

@ -60,7 +60,7 @@ func (cs *compileState) parseStmt(block *block, fname string, stmt ast.Stmt, inP
return nil, false
}
stmts = append(stmts, ss...)
case token.ADD_ASSIGN, token.SUB_ASSIGN, token.MUL_ASSIGN, token.QUO_ASSIGN, token.REM_ASSIGN:
case token.ADD_ASSIGN, token.SUB_ASSIGN, token.MUL_ASSIGN, token.QUO_ASSIGN, token.REM_ASSIGN, token.AND_ASSIGN, token.OR_ASSIGN, token.XOR_ASSIGN, token.AND_NOT_ASSIGN:
rhs, rts, ss, ok := cs.parseExpr(block, fname, stmt.Rhs[0], true)
if !ok {
return nil, false
@ -94,6 +94,15 @@ func (cs *compileState) parseStmt(block *block, fname string, stmt ast.Stmt, inP
op = shaderir.Div
case token.REM_ASSIGN:
op = shaderir.ModOp
case token.AND_ASSIGN:
op = shaderir.And
case token.OR_ASSIGN:
op = shaderir.Or
case token.XOR_ASSIGN:
op = shaderir.Xor
default:
cs.addError(stmt.Pos(), fmt.Sprintf("unexpected token: %s", stmt.Tok))
return nil, false
}
if lts[0].Main == rts[0].Main {

View File

@ -2242,3 +2242,60 @@ func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
})
}
}
// Issue #2752
func TestShaderBitwiseOperator(t *testing.T) {
const w, h = 16, 16
src := ebiten.NewImage(w, h)
src.Fill(color.RGBA{R: 0x24, G: 0x3f, B: 0x6a, A: 0xff})
for _, assign := range []bool{false, true} {
assign := assign
name := "op"
if assign {
name = "op+assign"
}
t.Run(name, func(t *testing.T) {
var code string
if assign {
code = ` v.rgb &= 0x5a
v.rgb |= 0x30
v.rgb ^= 0x8d`
} else {
code = ` v.rgb = v.rgb & 0x5a
v.rgb = v.rgb | 0x30
v.rgb = v.rgb ^ 0x8d`
}
s, err := ebiten.NewShader([]byte(fmt.Sprintf(`//kage:unit pixels
package main
func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
v := ivec4(imageSrc0At(texCoord) * 0xff)
%s
return vec4(v) / 0xff;
}
`, code)))
if err != nil {
t.Fatal(err)
}
dst := ebiten.NewImage(w, h)
op := &ebiten.DrawRectShaderOptions{}
op.Images[0] = src
dst.DrawRectShader(w, h, s, op)
for j := 0; j < h; j++ {
for i := 0; i < w; i++ {
got := dst.At(i, j).(color.RGBA)
want := color.RGBA{R: 0xbd, G: 0xb7, B: 0xf7, A: 0xff}
if !sameColors(got, want, 2) {
t.Errorf("dst.At(%d, %d): got: %v, want: %v", i, j, got, want)
}
}
}
})
}
}