forked from cogentcore/core
-
Notifications
You must be signed in to change notification settings - Fork 0
/
pipeline.go
133 lines (118 loc) · 3.6 KB
/
pipeline.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
// Copyright (c) 2024, Cogent Core. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package gpu
import (
"log"
"log/slog"
"cogentcore.org/core/base/errors"
"github.com/cogentcore/webgpu/wgpu"
)
// Pipeline is the shared Base for Graphics and Compute Pipelines.
// It manages Shader program(s) that accomplish a specific
// type of rendering or compute function, using Vars / Values
// defined by the overall GraphicsSystem.
// In the graphics context, each pipeline could handle a different
// class of materials (textures, Phong lighting, etc).
type Pipeline struct {
// unique name of this pipeline
Name string
// System that we belong to and manages shared resources:
// Vars, Values, etc
System System
// Shaders contains actual shader code loaded for this pipeline.
// A single shader can have multiple entry points: see Entries.
Shaders map[string]*Shader
// Entries contains the entry points into shader code,
// which are what is actually called.
Entries map[string]*ShaderEntry
}
// Vars returns a pointer to the vars for this pipeline,
// which has Values within it.
func (pl *Pipeline) Vars() *Vars {
return pl.System.Vars()
}
// AddShader adds Shader with given name to the pipeline
func (pl *Pipeline) AddShader(name string) *Shader {
if pl.Shaders == nil {
pl.Shaders = make(map[string]*Shader)
}
if sh, has := pl.Shaders[name]; has {
log.Printf("gpu.Pipeline AddShader: Shader named: %s already exists in pipline: %s\n", name, pl.Name)
return sh
}
sh := NewShader(name, pl.System.Device())
pl.Shaders[name] = sh
return sh
}
// ShaderByName returns Shader by name.
// Returns nil if not found (error auto logged).
func (pl *Pipeline) ShaderByName(name string) *Shader {
sh, ok := pl.Shaders[name]
if !ok {
slog.Error("gpu.Pipeline ShaderByName", "Shader", name, "not found in pipeline", pl.Name)
return nil
}
return sh
}
// EntryByName returns ShaderEntry by name, which is Shader:Entry.
// Returns nil if not found (error auto logged).
func (pl *Pipeline) EntryByName(name string) *ShaderEntry {
sh, ok := pl.Entries[name]
if !ok {
slog.Error("gpu.Pipeline EntryByName", "Entry", name, "not found in pipeline", pl.Name)
return nil
}
return sh
}
// EntryByType returns ShaderEntry by ShaderType.
// Returns nil if not found.
func (pl *Pipeline) EntryByType(typ ShaderTypes) *ShaderEntry {
for _, sh := range pl.Entries {
if sh.Type == typ {
return sh
}
}
return nil
}
// AddEntry adds ShaderEntry for given shader, [ShaderTypes], and entry function name.
func (pl *Pipeline) AddEntry(sh *Shader, typ ShaderTypes, entry string) *ShaderEntry {
if pl.Entries == nil {
pl.Entries = make(map[string]*ShaderEntry)
}
name := sh.Name + ":" + entry
if se, has := pl.Entries[name]; has {
slog.Error("gpu.Pipeline AddEntry", "ShaderEntry named", name, "already exists in pipline", pl.Name)
return se
}
se := NewShaderEntry(sh, typ, entry)
pl.Entries[name] = se
return se
}
// releaseShaders releases the shaders
func (pl *Pipeline) releaseShaders() {
for _, sh := range pl.Shaders {
sh.Release()
}
pl.Shaders = nil
pl.Entries = nil
}
// bindLayout returns a PipeLineLayout based on Vars
func (pl *Pipeline) bindLayout() (*wgpu.PipelineLayout, error) {
lays := pl.Vars().bindLayout(pl.System.Device())
if lays != nil {
defer func() {
for _, bgl := range lays {
bgl.Release()
}
}()
}
rpl, err := pl.System.Device().Device.CreatePipelineLayout(&wgpu.PipelineLayoutDescriptor{
Label: pl.Name,
BindGroupLayouts: lays,
})
if errors.Log(err) != nil {
return nil, err
}
return rpl, nil
}