zworld/engine/renderapi/shader/shader.go
2024-01-14 22:56:06 +08:00

102 lines
2.2 KiB
Go

package shader
import (
"fmt"
"zworld/engine/renderapi/device"
"zworld/engine/renderapi/texture"
"zworld/engine/renderapi/types"
)
type Input struct {
Index int
Type types.Type
}
type Inputs map[string]Input
// Input returns the index and type of a shader input by name, and a bool indicating wheter its valid.
func (i Inputs) Input(name string) (int, types.Type, bool) {
input, exists := i[name]
return input.Index, input.Type, exists
}
type Bindings map[string]int
// Descriptor returns the index of a descriptor by name, and a bool indicating wheter its valid.
func (d Bindings) Descriptor(name string) (int, bool) {
index, exists := d[name]
return index, exists
}
type T interface {
Name() string
Modules() []Module
Destroy()
Input(name string) (int, types.Type, bool)
Descriptor(name string) (int, bool)
Textures() []texture.Slot
}
type shader struct {
name string
modules []Module
inputs Inputs
bindings Bindings
textures []texture.Slot
}
func New(device device.T, path string) T {
// todo: inputs & descriptors should be obtained from SPIR-V reflection
details, err := ReadDetails(fmt.Sprintf("shaders/%s.json", path))
if err != nil {
panic(fmt.Sprintf("failed to load shader details: %s", err))
}
inputs, err := details.ParseInputs()
if err != nil {
panic(fmt.Sprintf("failed to parse shader inputs: %s", err))
}
modules := []Module{
NewModule(device, fmt.Sprintf("shaders/%s.vs.glsl", path), StageVertex),
NewModule(device, fmt.Sprintf("shaders/%s.fs.glsl", path), StageFragment),
}
return &shader{
name: path,
modules: modules,
inputs: inputs,
bindings: details.Bindings,
textures: details.Textures,
}
}
// Name returns the file name of the shader
func (s *shader) Name() string {
return s.name
}
func (s *shader) Modules() []Module {
return s.modules
}
// Destroy the shader and its modules.
func (s *shader) Destroy() {
for _, module := range s.modules {
module.Destroy()
}
}
func (s *shader) Input(name string) (int, types.Type, bool) {
return s.inputs.Input(name)
}
func (s *shader) Textures() []texture.Slot {
return s.textures
}
func (s *shader) Descriptor(name string) (int, bool) {
return s.bindings.Descriptor(name)
}