internal/shaderir: cache reachable uniform variables

Updates #2232
This commit is contained in:
Hajime Hoshi 2022-11-04 01:23:17 +09:00
parent 384dee7160
commit c4e4e55d75
4 changed files with 61 additions and 14 deletions

View File

@ -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) {

View File

@ -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)
}

View File

@ -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
}
}
}

View File

@ -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