mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-11-10 04:57:26 +01:00
Compare commits
4 Commits
ecc3f29af1
...
4818768965
Author | SHA1 | Date | |
---|---|---|---|
|
4818768965 | ||
|
83ae577c80 | ||
|
8be3bb41d5 | ||
|
3279688dd6 |
@ -61,33 +61,27 @@ func run() error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defaultSrc, err := shaderprecomp.NewShaderSource(defaultSrcBytes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
srcs = append(srcs, defaultSrc)
|
||||
srcs = append(srcs, shaderprecomp.NewShaderSource(defaultSrcBytes))
|
||||
|
||||
for _, src := range srcs {
|
||||
for i, src := range srcs {
|
||||
// Avoid using errgroup.Group.
|
||||
// Compiling sources in parallel causes a mixed error message on the console.
|
||||
if err := compile(src, tmpdir); err != nil {
|
||||
if err := compile(src, i, tmpdir); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func generateHSLSFiles(source *shaderprecomp.ShaderSource, tmpdir string) (vs, ps string, err error) {
|
||||
id := source.ID().String()
|
||||
|
||||
vsHLSLFilePath := filepath.Join(tmpdir, id+"_vs.hlsl")
|
||||
func generateHSLSFiles(source *shaderprecomp.ShaderSource, index int, tmpdir string) (vs, ps string, err error) {
|
||||
vsHLSLFilePath := filepath.Join(tmpdir, fmt.Sprintf("%d_vs.hlsl", index))
|
||||
vsf, err := os.Create(vsHLSLFilePath)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
defer vsf.Close()
|
||||
|
||||
psHLSLFilePath := filepath.Join(tmpdir, id+"_ps.hlsl")
|
||||
psHLSLFilePath := filepath.Join(tmpdir, fmt.Sprintf("%d_ps.hlsl", index))
|
||||
psf, err := os.Create(psHLSLFilePath)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
@ -101,17 +95,15 @@ func generateHSLSFiles(source *shaderprecomp.ShaderSource, tmpdir string) (vs, p
|
||||
return vsHLSLFilePath, psHLSLFilePath, nil
|
||||
}
|
||||
|
||||
func compile(source *shaderprecomp.ShaderSource, tmpdir string) error {
|
||||
func compile(source *shaderprecomp.ShaderSource, index int, tmpdir string) error {
|
||||
// Generate HLSL files. Make sure this process doesn't have any handlers of the files.
|
||||
// Without closing the files, fxc.exe cannot access the files.
|
||||
vsHLSLFilePath, psHLSLFilePath, err := generateHSLSFiles(source, tmpdir)
|
||||
vsHLSLFilePath, psHLSLFilePath, err := generateHSLSFiles(source, index, tmpdir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
id := source.ID().String()
|
||||
|
||||
vsFXCFilePath := id + "_vs.fxc"
|
||||
vsFXCFilePath := fmt.Sprintf("%d_vs.fxc", index)
|
||||
cmd := exec.Command("fxc.exe", "/nologo", "/O3", "/T", shaderprecomp.HLSLVertexShaderProfile, "/E", shaderprecomp.HLSLVertexShaderEntryPoint, "/Fo", vsFXCFilePath, vsHLSLFilePath)
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
@ -119,7 +111,7 @@ func compile(source *shaderprecomp.ShaderSource, tmpdir string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
psFXCFilePath := id + "_ps.fxc"
|
||||
psFXCFilePath := fmt.Sprintf("%d_ps.fxc", index)
|
||||
cmd = exec.Command("fxc.exe", "/nologo", "/O3", "/T", shaderprecomp.HLSLPixelShaderProfile, "/E", shaderprecomp.HLSLPixelShaderEntryPoint, "/Fo", psFXCFilePath, psHLSLFilePath)
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
|
@ -20,6 +20,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
@ -46,26 +47,20 @@ func run() error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defaultSrc, err := shaderprecomp.NewShaderSource(defaultSrcBytes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
srcs = append(srcs, defaultSrc)
|
||||
srcs = append(srcs, shaderprecomp.NewShaderSource(defaultSrcBytes))
|
||||
|
||||
for _, src := range srcs {
|
||||
for i, src := range srcs {
|
||||
// Avoid using errgroup.Group.
|
||||
// Compiling sources in parallel causes a mixed error message on the console.
|
||||
if err := compile(src, tmpdir); err != nil {
|
||||
if err := compile(src, i, tmpdir); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func compile(source *shaderprecomp.ShaderSource, tmpdir string) error {
|
||||
id := source.ID().String()
|
||||
|
||||
metalFilePath := filepath.Join(tmpdir, id+".metal")
|
||||
func compile(source *shaderprecomp.ShaderSource, index int, tmpdir string) error {
|
||||
metalFilePath := filepath.Join(tmpdir, fmt.Sprintf("%d.metal", index))
|
||||
|
||||
f, err := os.Create(metalFilePath)
|
||||
if err != nil {
|
||||
@ -80,14 +75,14 @@ func compile(source *shaderprecomp.ShaderSource, tmpdir string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
irFilePath := filepath.Join(tmpdir, id+".ir")
|
||||
irFilePath := filepath.Join(tmpdir, fmt.Sprintf("%d.ir", index))
|
||||
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"
|
||||
metallibFilePath := fmt.Sprintf("%d.metallib", index)
|
||||
cmd = exec.Command("xcrun", "-sdk", "macosx", "metallib", "-o", metallibFilePath, irFilePath)
|
||||
cmd.Stderr = os.Stderr
|
||||
if err := cmd.Run(); err != nil {
|
||||
|
@ -16,9 +16,10 @@ package main
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/hajimehoshi/ebiten/v2/shaderprecomp"
|
||||
)
|
||||
@ -27,40 +28,20 @@ import (
|
||||
var metallibs embed.FS
|
||||
|
||||
func registerPrecompiledShaders() error {
|
||||
ents, err := metallibs.ReadDir("metallib")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var registered bool
|
||||
for _, ent := range ents {
|
||||
if ent.IsDir() {
|
||||
continue
|
||||
}
|
||||
|
||||
const suffix = ".metallib"
|
||||
name := ent.Name()
|
||||
if !strings.HasSuffix(name, suffix) {
|
||||
continue
|
||||
}
|
||||
|
||||
id := name[:len(name)-len(suffix)]
|
||||
srcID, err := shaderprecomp.ParseSourceID(id)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
srcs := shaderprecomp.AppendBuildinShaderSources(nil)
|
||||
srcs = append(srcs, shaderprecomp.NewShaderSource(defaultShaderSourceBytes))
|
||||
|
||||
for i, src := range srcs {
|
||||
name := fmt.Sprintf("%d.metallib", i)
|
||||
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(srcID, lib)
|
||||
registered = true
|
||||
}
|
||||
|
||||
if !registered {
|
||||
fmt.Fprintln(os.Stderr, "precompiled Metal libraries were not found. Run 'go generate' for 'metallib' directory to generate them.")
|
||||
shaderprecomp.RegisterMetalLibrary(src, lib)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -16,9 +16,10 @@ package main
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/hajimehoshi/ebiten/v2/shaderprecomp"
|
||||
)
|
||||
@ -29,44 +30,31 @@ import (
|
||||
var fxcs embed.FS
|
||||
|
||||
func registerPrecompiledShaders() error {
|
||||
ents, err := fxcs.ReadDir("fxc")
|
||||
srcs := shaderprecomp.AppendBuildinShaderSources(nil)
|
||||
srcs = append(srcs, shaderprecomp.NewShaderSource(defaultShaderSourceBytes))
|
||||
|
||||
for i, src := range srcs {
|
||||
vsname := fmt.Sprintf("%d_vs.fxc", i)
|
||||
vs, err := fxcs.ReadFile("fxc/" + vsname)
|
||||
if err != nil {
|
||||
if errors.Is(err, fs.ErrNotExist) {
|
||||
fmt.Fprintf(os.Stderr, "precompiled HLSL library %s was not found. Run 'go generate' for 'fxc' directory to generate them.\n", vsname)
|
||||
continue
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
var registered bool
|
||||
for _, ent := range ents {
|
||||
if ent.IsDir() {
|
||||
psname := fmt.Sprintf("%d_ps.fxc", i)
|
||||
ps, err := fxcs.ReadFile("fxc/" + psname)
|
||||
if err != nil {
|
||||
if errors.Is(err, fs.ErrNotExist) {
|
||||
fmt.Fprintf(os.Stderr, "precompiled HLSL library %s was not found. Run 'go generate' for 'fxc' directory to generate them.\n", psname)
|
||||
continue
|
||||
}
|
||||
|
||||
const suffix = "_vs.fxc"
|
||||
name := ent.Name()
|
||||
if !strings.HasSuffix(name, suffix) {
|
||||
continue
|
||||
}
|
||||
|
||||
id := name[:len(name)-len(suffix)]
|
||||
srcID, err := shaderprecomp.ParseSourceID(id)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
vs, err := fxcs.ReadFile("fxc/" + id + "_vs.fxc")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ps, err := fxcs.ReadFile("fxc/" + id + "_ps.fxc")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
shaderprecomp.RegisterFXCs(srcID, vs, ps)
|
||||
registered = true
|
||||
}
|
||||
|
||||
if !registered {
|
||||
fmt.Fprintln(os.Stderr, "precompiled HLSL libraries were not found. Run 'go generate' for 'fxc' directory to generate them.")
|
||||
shaderprecomp.RegisterFXCs(src, vs, ps)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -70,8 +70,8 @@ func (c *precompiledFXCs) get(hash shaderir.SourceHash) ([]byte, []byte) {
|
||||
|
||||
var thePrecompiledFXCs precompiledFXCs
|
||||
|
||||
func RegisterPrecompiledFXCs(hash shaderir.SourceHash, vertex, pixel []byte) {
|
||||
thePrecompiledFXCs.put(hash, vertex, pixel)
|
||||
func RegisterPrecompiledFXCs(source []byte, vertex, pixel []byte) {
|
||||
thePrecompiledFXCs.put(shaderir.CalcSourceHash(source), vertex, pixel)
|
||||
}
|
||||
|
||||
var vertexShaderCache = map[string]*_ID3DBlob{}
|
||||
|
@ -51,8 +51,8 @@ func (c *precompiledLibraries) get(hash shaderir.SourceHash) []byte {
|
||||
|
||||
var thePrecompiledLibraries precompiledLibraries
|
||||
|
||||
func RegisterPrecompiledLibrary(hash shaderir.SourceHash, bin []byte) {
|
||||
thePrecompiledLibraries.put(hash, bin)
|
||||
func RegisterPrecompiledLibrary(source []byte, bin []byte) {
|
||||
thePrecompiledLibraries.put(shaderir.CalcSourceHash(source), bin)
|
||||
}
|
||||
|
||||
type shaderRpsKey struct {
|
||||
|
@ -18,10 +18,6 @@
|
||||
|
||||
package playstation5
|
||||
|
||||
import (
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/shaderir"
|
||||
)
|
||||
|
||||
func RegisterPrecompiledShaders(hash shaderir.SourceHash, vertex, pixel []byte) {
|
||||
func RegisterPrecompiledShaders(source []byte, vertex, pixel []byte) {
|
||||
// TODO: Implement this.
|
||||
}
|
||||
|
@ -17,7 +17,6 @@ package shaderir
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"go/constant"
|
||||
"go/token"
|
||||
"hash/fnv"
|
||||
@ -43,19 +42,6 @@ func CalcSourceHash(source []byte) SourceHash {
|
||||
return hash
|
||||
}
|
||||
|
||||
func ParseSourceHash(s string) (SourceHash, error) {
|
||||
bs, err := hex.DecodeString(s)
|
||||
if err != nil {
|
||||
return SourceHash{}, err
|
||||
}
|
||||
var hash SourceHash
|
||||
if len(bs) != len(hash) {
|
||||
return SourceHash{}, fmt.Errorf("shaderir: invalid size hash: %s", s)
|
||||
}
|
||||
copy(hash[:], bs)
|
||||
return hash, nil
|
||||
}
|
||||
|
||||
func (s SourceHash) String() string {
|
||||
return hex.EncodeToString(s[:])
|
||||
}
|
||||
|
@ -16,8 +16,6 @@ package shaderprecomp
|
||||
|
||||
import (
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/builtinshader"
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/graphics"
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/shaderir"
|
||||
)
|
||||
|
||||
// AppendBuildinShaderSources appends all the built-in shader sources to the given slice.
|
||||
@ -27,11 +25,7 @@ import (
|
||||
// AppendBuildinShaderSources is concurrent-safe.
|
||||
func AppendBuildinShaderSources(sources []*ShaderSource) []*ShaderSource {
|
||||
for _, s := range builtinshader.AppendShaderSources(nil) {
|
||||
src, err := NewShaderSource(s)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
sources = append(sources, src)
|
||||
sources = append(sources, NewShaderSource(s))
|
||||
}
|
||||
return sources
|
||||
}
|
||||
@ -39,41 +33,11 @@ func AppendBuildinShaderSources(sources []*ShaderSource) []*ShaderSource {
|
||||
// ShaderSource is an object encapsulating a shader source code.
|
||||
type ShaderSource struct {
|
||||
source []byte
|
||||
id ShaderSourceID
|
||||
}
|
||||
|
||||
// NewShaderSource creates a new ShaderSource object from the given source code.
|
||||
func NewShaderSource(source []byte) (*ShaderSource, error) {
|
||||
hash, err := graphics.CalcSourceHash(source)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
func NewShaderSource(source []byte) *ShaderSource {
|
||||
return &ShaderSource{
|
||||
source: source,
|
||||
id: ShaderSourceID(hash),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ID returns a unique identifier for the shader source.
|
||||
// The ShaderSourceID value must be the same for the same shader source and the same Ebitengine version.
|
||||
// There is no guarantee that the ShaderSourceID value is the same between different Ebitengine versions.
|
||||
func (s *ShaderSource) ID() ShaderSourceID {
|
||||
return s.id
|
||||
}
|
||||
|
||||
// ShaderSourceID is a uniuqe identifier for a shader source.
|
||||
type ShaderSourceID [16]byte
|
||||
|
||||
// ParseSourceID parses a string representation of the shader source ID.
|
||||
func ParseSourceID(s string) (ShaderSourceID, error) {
|
||||
h, err := shaderir.ParseSourceHash(s)
|
||||
if err != nil {
|
||||
return ShaderSourceID{}, err
|
||||
}
|
||||
return ShaderSourceID(h), nil
|
||||
}
|
||||
|
||||
// String returns a string representation of the shader source ID.
|
||||
func (s ShaderSourceID) String() string {
|
||||
return shaderir.SourceHash(s).String()
|
||||
}
|
||||
|
@ -21,7 +21,6 @@ import (
|
||||
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/graphics"
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver/metal"
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/shaderir"
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/shaderir/msl"
|
||||
)
|
||||
|
||||
@ -39,11 +38,11 @@ func CompileToMSL(w io.Writer, source *ShaderSource) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// RegisterMetalLibrary registers a precompiled Metal library for a shader source ID.
|
||||
// RegisterMetalLibrary registers a precompiled Metal library for a shader source.
|
||||
// library must be the content of a .metallib file.
|
||||
// For more details, see https://developer.apple.com/documentation/metal/shader_libraries/building_a_shader_library_by_precompiling_source_files.
|
||||
//
|
||||
// RegisterMetalLibrary is concurrent-safe.
|
||||
func RegisterMetalLibrary(id ShaderSourceID, library []byte) {
|
||||
metal.RegisterPrecompiledLibrary(shaderir.SourceHash(id), library)
|
||||
func RegisterMetalLibrary(source *ShaderSource, library []byte) {
|
||||
metal.RegisterPrecompiledLibrary(source.source, library)
|
||||
}
|
||||
|
@ -21,7 +21,6 @@ import (
|
||||
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/graphics"
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver/playstation5"
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/shaderir"
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/shaderir/pssl"
|
||||
)
|
||||
|
||||
@ -47,5 +46,5 @@ func CompileToPSSL(vertexWriter, pixelWriter io.Writer, source *ShaderSource) er
|
||||
//
|
||||
// RegisterPlayStationShaders is concurrent-safe.
|
||||
func RegisterPlayStationShaders(source *ShaderSource, vertexShader, pixelShader []byte) {
|
||||
playstation5.RegisterPrecompiledShaders(shaderir.SourceHash(source.ID()), vertexShader, pixelShader)
|
||||
playstation5.RegisterPrecompiledShaders(source.source, vertexShader, pixelShader)
|
||||
}
|
||||
|
@ -21,7 +21,6 @@ import (
|
||||
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/graphics"
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver/directx"
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/shaderir"
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/shaderir/hlsl"
|
||||
)
|
||||
|
||||
@ -57,11 +56,11 @@ func CompileToHLSL(vertexWriter, pixelWriter io.Writer, source *ShaderSource) er
|
||||
return nil
|
||||
}
|
||||
|
||||
// RegisterFXCs registers a precompiled HLSL (FXC) for a shader source ID.
|
||||
// RegisterFXCs registers a precompiled HLSL (FXC) for a shader source.
|
||||
// vertexFXC and pixelFXC must be the content of .fxc files generated by `fxc` command.
|
||||
// For more details, see https://learn.microsoft.com/en-us/windows/win32/direct3dtools/dx-graphics-tools-fxc-using.
|
||||
//
|
||||
// RegisterFXCs is concurrent-safe.
|
||||
func RegisterFXCs(id ShaderSourceID, vertexFXC, pixelFXC []byte) {
|
||||
directx.RegisterPrecompiledFXCs(shaderir.SourceHash(id), vertexFXC, pixelFXC)
|
||||
func RegisterFXCs(source *ShaderSource, vertexFXC, pixelFXC []byte) {
|
||||
directx.RegisterPrecompiledFXCs(source.source, vertexFXC, pixelFXC)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user