diff --git a/internal/graphicscommand/command.go b/internal/graphicscommand/command.go index aac2ed4c6..496444fbd 100644 --- a/internal/graphicscommand/command.go +++ b/internal/graphicscommand/command.go @@ -111,18 +111,7 @@ func (q *commandQueue) EnqueueDrawTrianglesCommand(dst *Image, srcs [graphics.Sh uniforms = prependPreservedUniforms(uniforms, dst, srcs, offsets, dstRegion, srcRegion) // Remove unused uniform variables so that more commands can be merged. - uvs := map[int]struct{}{} - for _, i := range shader.ir.ReachableUniformVariablesFromBlock(shader.ir.VertexFunc.Block) { - uvs[i] = struct{}{} - } - for _, i := range shader.ir.ReachableUniformVariablesFromBlock(shader.ir.FragmentFunc.Block) { - uvs[i] = struct{}{} - } - for i := range uniforms { - if _, ok := uvs[i]; !ok { - uniforms[i] = nil - } - } + shader.ir.FilterUniformVariables(uniforms) // TODO: If dst is the screen, reorder the command to be the last. if !split && 0 < len(q.commands) { diff --git a/internal/shaderir/export_test.go b/internal/shaderir/export_test.go new file mode 100644 index 000000000..349041473 --- /dev/null +++ b/internal/shaderir/export_test.go @@ -0,0 +1,19 @@ +// Copyright 2022 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 shaderir + +func (p *Program) ReachableUniformVariablesFromBlock(block *Block) []int { + return p.reachableUniformVariablesFromBlock(block) +} diff --git a/internal/shaderir/program.go b/internal/shaderir/program.go index 283803c51..371107325 100644 --- a/internal/shaderir/program.go +++ b/internal/shaderir/program.go @@ -31,6 +31,8 @@ type Program struct { Funcs []Func VertexFunc VertexFunc FragmentFunc FragmentFunc + + reachableUniforms map[int]struct{} } type Func struct { @@ -420,7 +422,7 @@ func walkExprsInExpr(f func(expr *Expr), expr *Expr) { } } -func (p *Program) ReachableUniformVariablesFromBlock(block *Block) []int { +func (p *Program) reachableUniformVariablesFromBlock(block *Block) []int { indexToFunc := map[int]*Func{} for _, f := range p.Funcs { f := f @@ -451,3 +453,20 @@ func (p *Program) ReachableUniformVariablesFromBlock(block *Block) []int { sort.Ints(is) return is } + +func (p *Program) FilterUniformVariables(uniforms [][]float32) { + if p.reachableUniforms == nil { + p.reachableUniforms = map[int]struct{}{} + for _, i := range p.reachableUniformVariablesFromBlock(p.VertexFunc.Block) { + p.reachableUniforms[i] = struct{}{} + } + for _, i := range p.reachableUniformVariablesFromBlock(p.FragmentFunc.Block) { + p.reachableUniforms[i] = struct{}{} + } + } + for i := range uniforms { + if _, ok := p.reachableUniforms[i]; !ok { + uniforms[i] = nil + } + } +} diff --git a/internal/shader/reachable_test.go b/internal/shaderir/reachable_test.go similarity index 79% rename from internal/shader/reachable_test.go rename to internal/shaderir/reachable_test.go index 544934d9c..5a4aec2ed 100644 --- a/internal/shader/reachable_test.go +++ b/internal/shaderir/reachable_test.go @@ -12,12 +12,32 @@ // See the License for the specific language governing permissions and // limitations under the License. -package shader_test +package shaderir_test import ( + "go/parser" + "go/token" "testing" + + "github.com/hajimehoshi/ebiten/v2/internal/shader" + "github.com/hajimehoshi/ebiten/v2/internal/shaderir" ) +func compileToIR(src []byte) (*shaderir.Program, error) { + fset := token.NewFileSet() + f, err := parser.ParseFile(fset, "", src, parser.AllErrors) + if err != nil { + return nil, err + } + + ir, err := shader.Compile(fset, f, "Vertex", "Fragment", 0) + if err != nil { + return nil, err + } + + return ir, nil +} + func areIntSlicesEqual(a, b []int) bool { if len(a) != len(b) { return false