ci-platforms / darwin arm64 smoke (push) Skipped
ci / build (amd64, linux, ubuntu-24.04) (push) Failing after 12m19s
ci-platforms / darwin amd64 smoke (push) Skipped
ci-platforms / windows amd64 smoke (push) Skipped
github-native / gitea-pending (push) Skipped
github-native / darwin amd64 native (push) Skipped
github-native / linux amd64 native (push) Skipped
github-native / windows amd64 native (push) Skipped
github-native / darwin arm64 native (push) Skipped
github-native / gitea-result (push) Skipped
ci / checks (push) Failing after 23m57s
ci / release (push) Skipped
GitHub / windows amd64 native GitHub-hosted native CI: failure
GitHub / darwin arm64 native GitHub-hosted native CI: failure
GitHub / darwin amd64 native GitHub-hosted native CI: failure
GitHub / linux amd64 native GitHub-hosted native CI: success
170 lines
5.3 KiB
Go
170 lines
5.3 KiB
Go
package shader_test
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/hex"
|
|
"fmt"
|
|
"os/exec"
|
|
"strings"
|
|
"testing"
|
|
|
|
"aego/asset"
|
|
"aego/asset/importers/shader"
|
|
"aego/asset/pipeline"
|
|
"aego/core/ids"
|
|
"aego/core/log"
|
|
"aego/project"
|
|
rshader "aego/render/shader"
|
|
)
|
|
|
|
func TestCacheSaltSeesTransitiveEngineIncludes(t *testing.T) {
|
|
sources := map[string]string{
|
|
"engine://shaders/include/a.glsl": "#include \"engine/b.glsl\"\n",
|
|
"engine://shaders/include/b.glsl": "float helper(){return 1.;}\n",
|
|
}
|
|
ctx := &pipeline.ImportContext{ID: ids.AssetID{Lo: 1}, Path: "salt.aeshader", Source: []byte("#pragma aego abi 1\n#include \"engine/a.glsl\"\nvoid fragment(){aego_out=vec4(helper());}\n"), Read: func(path string) ([]byte, error) {
|
|
s, ok := sources[path]
|
|
if !ok {
|
|
return nil, fmt.Errorf("missing %s", path)
|
|
}
|
|
return []byte(s), nil
|
|
}}
|
|
i := shader.New()
|
|
i.Validator = "aego-test-no-validator"
|
|
i.Require = false
|
|
before, err := i.CacheSalt(ctx)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
sources["engine://shaders/include/b.glsl"] = "float helper(){return 2.;}\n"
|
|
after, err := i.CacheSalt(ctx)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if bytes.Equal(before, after) {
|
|
t.Fatal("engine include edit reused the prior cache key")
|
|
}
|
|
result, err := i.Import(ctx)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
a, err := asset.DecodeShader(result.Artifacts[0].Data)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if a.Validation != rshader.SchemaChecked {
|
|
t.Fatalf("missing validator falsely checked flags %b", a.Validation)
|
|
}
|
|
if len(a.Dependencies) != 3 || !strings.Contains(a.Variants[0].Sources[1], "return 2.") {
|
|
t.Fatal("prepared artifact omitted a transitive engine include")
|
|
}
|
|
i.Require = true
|
|
if _, err := i.CacheSalt(ctx); err == nil {
|
|
t.Fatal("require-validator reused an unchecked cache")
|
|
}
|
|
}
|
|
|
|
func TestDisabledExternalValidatorDoesNotClaimReferenceValidation(t *testing.T) {
|
|
ctx := &pipeline.ImportContext{ID: ids.AssetID{Lo: 2}, Path: "safe.aeshader", Source: []byte("#pragma aego abi 1\nvoid fragment(){aego_out=vec4(1.0);}\n")}
|
|
i := shader.New()
|
|
i.Require = false
|
|
i.Validator = "aego-test-no-validator"
|
|
ordinarySalt, err := i.CacheSalt(ctx)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
i.DisableExternal = true
|
|
disabledSalt, err := i.CacheSalt(ctx)
|
|
if err != nil || bytes.Equal(ordinarySalt, disabledSalt) {
|
|
t.Fatalf("restricted mode reused a different cache key: %v", err)
|
|
}
|
|
result, err := i.Import(ctx)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
a, err := asset.DecodeShader(result.Artifacts[0].Data)
|
|
if err != nil || a.Validation != rshader.SchemaChecked {
|
|
t.Fatalf("disabled validator marked shader reference-checked: %+v, %v", a, err)
|
|
}
|
|
i.Require = true
|
|
if _, err := i.CacheSalt(ctx); err == nil {
|
|
t.Fatal("required reference validation silently passed with external tools disabled")
|
|
}
|
|
if _, err := i.Import(ctx); err == nil {
|
|
t.Fatal("direct import bypassed required reference validation")
|
|
}
|
|
}
|
|
|
|
func TestReferenceDiagnosticsKeepTargetStageIncludeAndRawLog(t *testing.T) {
|
|
if _, err := exec.LookPath("glslangValidator"); err != nil {
|
|
t.Skip("glslangValidator unavailable")
|
|
}
|
|
ctx := &pipeline.ImportContext{ID: ids.AssetID{Lo: 7}, Path: "broken.aeshader", Source: []byte("#pragma aego abi 1\n#include \"broken.glsl\"\nvoid fragment(){aego_out=vec4(helper());}\n"), Read: func(string) ([]byte, error) { return []byte("float helper(){\n return missingName;\n}\n"), nil }}
|
|
i := shader.New()
|
|
i.Require = true
|
|
if _, err := i.Import(ctx); err == nil {
|
|
t.Fatal("invalid shader passed reference compilation")
|
|
}
|
|
ds, _ := i.Diagnostics()
|
|
found := map[string]bool{}
|
|
for _, d := range ds {
|
|
if d.File == "assets/shaders/include/broken.glsl" && d.Line == 2 && d.Stage == "fragment" && d.AssetID == ctx.ID.String() && strings.Contains(d.RawLog, "missingName") {
|
|
found[d.Backend] = true
|
|
}
|
|
}
|
|
if !found["GLSL330"] || !found["ESSL300"] {
|
|
t.Fatalf("incomplete diagnostic context: %+v", ds)
|
|
}
|
|
}
|
|
|
|
// Seed a live Pipeline with the salt produced by generator v7 for this exact
|
|
// input. The next lookup goes through the current generator on the same cache.
|
|
type upgradingPostShader struct {
|
|
*shader.Importer
|
|
useV7 bool
|
|
}
|
|
|
|
func (i *upgradingPostShader) CacheSalt(ctx *pipeline.ImportContext) ([]byte, error) {
|
|
if i.useV7 {
|
|
return hex.DecodeString("531d938d0d0a1b4d6cd6e9bd3fb18316ff0568b5ffb417a36ea11fa3d43338d7")
|
|
}
|
|
return i.Importer.CacheSalt(ctx)
|
|
}
|
|
|
|
func TestPostFXReimportsAfterGeneratorUpgrade(t *testing.T) {
|
|
p, err := project.Create(t.TempDir(), "Cached post effect", false)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
write(t, p.Root, "assets/cold.aeshader", "#pragma aego abi 1\n#pragma postfx\nvoid fragment(){ aego_out = aego_sample(aego_uv); }\n")
|
|
imp := &upgradingPostShader{Importer: shader.New(), useV7: true}
|
|
imp.Validator, imp.Require = "aego-no-reference-validator", false
|
|
reg := pipeline.NewImporterRegistry()
|
|
if err = reg.Register(imp); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
pl, err := pipeline.Open(p, reg, log.Nop())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer pl.Close()
|
|
if _, _, err = pl.Scan(); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
check := func(want int) {
|
|
t.Helper()
|
|
batch, err := pl.ImportAll()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(batch.Failed) != 0 || len(batch.Imported) != want {
|
|
t.Fatalf("want %d shader imports, got %d; failures %v", want, len(batch.Imported), batch.Failed)
|
|
}
|
|
}
|
|
check(1)
|
|
check(0)
|
|
imp.useV7 = false
|
|
check(1)
|
|
check(0)
|
|
}
|