-
-
Notifications
You must be signed in to change notification settings - Fork 622
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
all: add a new package shaderprecomp
The current implementation is only for macOS so far. Updates #2861
- Loading branch information
1 parent
d7df5eb
commit c46f62e
Showing
17 changed files
with
599 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,3 +7,6 @@ | |
.vscode | ||
go.work | ||
go.work.sum | ||
|
||
*.metallib | ||
!dummy.metallib |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
// Copyright 2020 The Ebiten Authors | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
//go:build ignore | ||
|
||
//kage:unit pixels | ||
|
||
package main | ||
|
||
var Time float | ||
var Cursor vec2 | ||
|
||
func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 { | ||
pos := (dstPos.xy - imageDstOrigin()) / imageDstSize() | ||
pos += Cursor / imageDstSize() / 4 | ||
clr := 0.0 | ||
clr += sin(pos.x*cos(Time/15)*80) + cos(pos.y*cos(Time/15)*10) | ||
clr += sin(pos.y*sin(Time/10)*40) + cos(pos.x*sin(Time/25)*40) | ||
clr += sin(pos.x*sin(Time/5)*10) + sin(pos.y*sin(Time/35)*80) | ||
clr *= sin(Time/10) * 0.5 | ||
return vec4(clr, clr*0.5, sin(clr+Time/3)*0.75, 1) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
// Copyright 2024 The Ebitengine Authors | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package main | ||
|
||
import ( | ||
_ "embed" | ||
"log" | ||
|
||
"github.com/hajimehoshi/ebiten/v2" | ||
"github.com/hajimehoshi/ebiten/v2/ebitenutil" | ||
) | ||
|
||
//go:embed defaultshader.go | ||
var defaultShaderSourceBytes []byte | ||
|
||
type Game struct { | ||
defaultShader *ebiten.Shader | ||
counter int | ||
} | ||
|
||
func (g *Game) Update() error { | ||
g.counter++ | ||
|
||
if g.defaultShader == nil { | ||
s, err := ebiten.NewShader(defaultShaderSourceBytes) | ||
if err != nil { | ||
return err | ||
} | ||
g.defaultShader = s | ||
} | ||
return nil | ||
} | ||
|
||
func (g *Game) Draw(screen *ebiten.Image) { | ||
cx, cy := ebiten.CursorPosition() | ||
w, h := screen.Bounds().Dx(), screen.Bounds().Dy() | ||
op := &ebiten.DrawRectShaderOptions{} | ||
op.Uniforms = map[string]interface{}{ | ||
"Time": float32(g.counter) / float32(ebiten.TPS()), | ||
"Cursor": []float32{float32(cx), float32(cy)}, | ||
} | ||
screen.DrawRectShader(w, h, g.defaultShader, op) | ||
|
||
msg := `This is a test for shader precompilation. | ||
Precompilation works only on macOS so far. | ||
Note that this example still works even without shader precompilation.` | ||
ebitenutil.DebugPrint(screen, msg) | ||
} | ||
|
||
func (g *Game) Layout(outsideWidth, outsideHeight int) (screenWidth, screenHeight int) { | ||
return outsideWidth, outsideHeight | ||
} | ||
|
||
func main() { | ||
if err := registerPrecompiledShaders(); err != nil { | ||
log.Fatal(err) | ||
} | ||
if err := ebiten.RunGame(&Game{}); err != nil { | ||
log.Fatal(err) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
This is a dummy .metallib file to trick Go's embed package. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
// Copyright 2024 The Ebitengine Authors | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
//go:build ignore | ||
|
||
// This is a program to generate precompiled Metal libraries. | ||
// | ||
// See https://developer.apple.com/documentation/metal/shader_libraries/building_a_shader_library_by_precompiling_source_files. | ||
package main | ||
|
||
import ( | ||
"os" | ||
"os/exec" | ||
"path/filepath" | ||
|
||
"golang.org/x/sync/errgroup" | ||
|
||
"github.com/hajimehoshi/ebiten/v2/shaderprecomp" | ||
) | ||
|
||
func main() { | ||
if err := run(); err != nil { | ||
panic(err) | ||
} | ||
} | ||
|
||
func run() error { | ||
tmpdir, err := os.MkdirTemp("", "") | ||
if err != nil { | ||
return err | ||
} | ||
defer os.RemoveAll(tmpdir) | ||
|
||
srcs := shaderprecomp.AppendBuildinShaderSources(nil) | ||
|
||
defaultSrcBytes, err := os.ReadFile(filepath.Join("..", "defaultshader.go")) | ||
if err != nil { | ||
return err | ||
} | ||
defaultSrc, err := shaderprecomp.NewShaderSource(defaultSrcBytes) | ||
if err != nil { | ||
return err | ||
} | ||
srcs = append(srcs, defaultSrc) | ||
|
||
var wg errgroup.Group | ||
for _, src := range srcs { | ||
source := src | ||
wg.Go(func() error { | ||
return compile(source, tmpdir) | ||
}) | ||
} | ||
if err := wg.Wait(); err != nil { | ||
return err | ||
} | ||
return nil | ||
} | ||
|
||
func compile(source *shaderprecomp.ShaderSource, tmpdir string) error { | ||
id := source.ID().String() | ||
|
||
metalFilePath := filepath.Join(tmpdir, id+".metal") | ||
|
||
f, err := os.Create(metalFilePath) | ||
if err != nil { | ||
return err | ||
} | ||
defer f.Close() | ||
|
||
if err := shaderprecomp.CompileToMSL(f, source); err != nil { | ||
return err | ||
} | ||
if err := f.Sync(); err != nil { | ||
return err | ||
} | ||
|
||
irFilePath := filepath.Join(tmpdir, id+".ir") | ||
cmd := exec.Command("xcrun", "-sdk", "macosx", "metal", "-o", irFilePath, "-c", metalFilePath) | ||
cmd.Stderr = os.Stderr | ||
if err := cmd.Run(); err != nil { | ||
return err | ||
} | ||
|
||
metallibFilePath := id + ".metallib" | ||
cmd = exec.Command("xcrun", "-sdk", "macosx", "metallib", "-o", metallibFilePath, irFilePath) | ||
cmd.Stderr = os.Stderr | ||
if err := cmd.Run(); err != nil { | ||
return err | ||
} | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
// Copyright 2024 The Ebitengine Authors | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
//go:generate go run gen.go | ||
|
||
package metallib |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
// Copyright 2024 The Ebitengine Authors | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package main | ||
|
||
import ( | ||
"embed" | ||
"errors" | ||
"fmt" | ||
"io/fs" | ||
"os" | ||
|
||
"github.com/hajimehoshi/ebiten/v2/shaderprecomp" | ||
) | ||
|
||
//go:embed metallib/*.metallib | ||
var metallibs embed.FS | ||
|
||
func registerPrecompiledShaders() error { | ||
srcs := shaderprecomp.AppendBuildinShaderSources(nil) | ||
defaultShaderSource, err := shaderprecomp.NewShaderSource(defaultShaderSourceBytes) | ||
if err != nil { | ||
return err | ||
} | ||
srcs = append(srcs, defaultShaderSource) | ||
|
||
for _, src := range srcs { | ||
name := src.ID().String() + ".metallib" | ||
lib, err := metallibs.ReadFile("metallib/" + name) | ||
if err != nil { | ||
if errors.Is(err, fs.ErrNotExist) { | ||
fmt.Fprintf(os.Stderr, "precompiled Metal library %s was not found. Run 'go generate' for 'metallib' directory to generate them\n", name) | ||
continue | ||
} | ||
return err | ||
} | ||
shaderprecomp.RegisterMetalLibrary(src, lib) | ||
} | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
// Copyright 2024 The Ebitengine Authors | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
//go:build !darwin | ||
|
||
package main | ||
|
||
import ( | ||
"fmt" | ||
"os" | ||
) | ||
|
||
func registerPrecompiledShaders() error { | ||
fmt.Fprintf(os.Stderr, "precompiled shaders are not available in this environment.\n") | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.