mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-02 16:06:19 +00:00
8571433707
Signed-off-by: Egon Elbre <egonelbre@gmail.com>
139 lines
3.4 KiB
Go
139 lines
3.4 KiB
Go
// SPDX-License-Identifier: Unlicense OR MIT
|
|
|
|
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"io/ioutil"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"runtime"
|
|
"strings"
|
|
)
|
|
|
|
// FXC is hlsl compiler that targets ShaderModel 5.x and lower.
|
|
type FXC struct {
|
|
Bin string
|
|
WorkDir WorkDir
|
|
}
|
|
|
|
func NewFXC() *FXC { return &FXC{Bin: "fxc.exe"} }
|
|
|
|
// Compile compiles the input shader.
|
|
func (fxc *FXC) Compile(path, variant string, input []byte, entryPoint string, profileVersion string) ([]byte, error) {
|
|
base := fxc.WorkDir.Path(filepath.Base(path), variant, profileVersion)
|
|
pathin := base + ".in"
|
|
pathout := base + ".out"
|
|
result := pathout
|
|
|
|
if err := fxc.WorkDir.WriteFile(pathin, input); err != nil {
|
|
return nil, fmt.Errorf("unable to write shader to disk: %w", err)
|
|
}
|
|
|
|
cmd := exec.Command(fxc.Bin)
|
|
if runtime.GOOS != "windows" {
|
|
cmd = exec.Command("wine", fxc.Bin)
|
|
if err := winepath(&pathin, &pathout); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
var profile string
|
|
switch filepath.Ext(path) {
|
|
case ".frag":
|
|
profile = "ps_" + profileVersion
|
|
case ".vert":
|
|
profile = "vs_" + profileVersion
|
|
default:
|
|
return nil, fmt.Errorf("unrecognized shader type %s", path)
|
|
}
|
|
|
|
cmd.Args = append(cmd.Args,
|
|
"/Fo", pathout,
|
|
"/T", profile,
|
|
"/E", entryPoint,
|
|
pathin,
|
|
)
|
|
|
|
output, err := cmd.CombinedOutput()
|
|
if err != nil {
|
|
info := ""
|
|
if runtime.GOOS != "windows" {
|
|
info = "If the fxc tool cannot be found, set WINEPATH to the Windows path for the Windows SDK.\n"
|
|
}
|
|
return nil, fmt.Errorf("%s\n%sfailed to run %v: %w", output, info, cmd.Args, err)
|
|
}
|
|
|
|
compiled, err := ioutil.ReadFile(result)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("unable to read output %q: %w", pathout, err)
|
|
}
|
|
|
|
return compiled, nil
|
|
}
|
|
|
|
// DXC is hlsl compiler that targets ShaderModel 6.0 and newer.
|
|
type DXC struct {
|
|
Bin string
|
|
WorkDir WorkDir
|
|
}
|
|
|
|
func NewDXC() *DXC { return &DXC{Bin: "dxc.exe"} }
|
|
|
|
// Compile compiles the input shader.
|
|
func (dxc *DXC) Compile(path, variant string, input []byte, entryPoint string, profile string) ([]byte, error) {
|
|
base := dxc.WorkDir.Path(filepath.Base(path), variant, profile)
|
|
pathin := base + ".in"
|
|
pathout := base + ".out"
|
|
result := pathout
|
|
|
|
if err := dxc.WorkDir.WriteFile(pathin, input); err != nil {
|
|
return nil, fmt.Errorf("unable to write shader to disk: %w", err)
|
|
}
|
|
|
|
cmd := exec.Command(dxc.Bin)
|
|
if runtime.GOOS != "windows" {
|
|
cmd = exec.Command("wine", dxc.Bin)
|
|
if err := winepath(&pathin, &pathout); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
cmd.Args = append(cmd.Args,
|
|
"-Fo", pathout,
|
|
"-T", profile,
|
|
"-E", entryPoint,
|
|
"-Qstrip_reflect",
|
|
pathin,
|
|
)
|
|
|
|
output, err := cmd.CombinedOutput()
|
|
if err != nil {
|
|
info := ""
|
|
if runtime.GOOS != "windows" {
|
|
info = "If the dxc tool cannot be found, set WINEPATH to the Windows path for the Windows SDK.\n"
|
|
}
|
|
return nil, fmt.Errorf("%s\n%sfailed to run %v: %w", output, info, cmd.Args, err)
|
|
}
|
|
|
|
compiled, err := ioutil.ReadFile(result)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("unable to read output %q: %w", pathout, err)
|
|
}
|
|
|
|
return compiled, nil
|
|
}
|
|
|
|
// winepath uses the winepath tool to convert a paths to Windows format.
|
|
// The returned path can be used as arguments for Windows command line tools.
|
|
func winepath(paths ...*string) error {
|
|
for _, path := range paths {
|
|
out, err := exec.Command("winepath", "--windows", *path).Output()
|
|
if err != nil {
|
|
return fmt.Errorf("unable to run `winepath --windows %q`: %w", *path, err)
|
|
}
|
|
*path = strings.TrimSpace(string(out))
|
|
}
|
|
return nil
|
|
}
|