mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-01 07:35:40 +00:00
gpu: setup OpenGL ES texture uniforms automatically from shader metadata
Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
+6
-4
@@ -46,6 +46,12 @@ type ShaderSources struct {
|
||||
Uniforms []UniformLocation
|
||||
UniformSize int
|
||||
Inputs []InputLocation
|
||||
Textures []TextureBinding
|
||||
}
|
||||
|
||||
type TextureBinding struct {
|
||||
Name string
|
||||
Binding int
|
||||
}
|
||||
|
||||
type UniformLocation struct {
|
||||
@@ -109,12 +115,8 @@ type Program interface {
|
||||
Release()
|
||||
SetVertexUniforms(buf Buffer)
|
||||
SetFragmentUniforms(buf Buffer)
|
||||
UniformFor(uniform string) Uniform
|
||||
Uniform1i(u Uniform, v int)
|
||||
}
|
||||
|
||||
type Uniform interface{}
|
||||
|
||||
type Buffer interface {
|
||||
BindVertex(stride, offset int)
|
||||
BindIndex()
|
||||
|
||||
+43
-6
@@ -27,6 +27,12 @@ type shaderArgs struct {
|
||||
Header string
|
||||
}
|
||||
|
||||
// TextureBinding matches gpu.TextureBinding.
|
||||
type TextureBinding struct {
|
||||
Name string
|
||||
Binding int
|
||||
}
|
||||
|
||||
// InputLocation matches gpu.InputLocation.
|
||||
type InputLocation struct {
|
||||
Name string
|
||||
@@ -90,6 +96,7 @@ func generate() error {
|
||||
hlsl []byte
|
||||
inputs []InputLocation
|
||||
uniforms []UniformLocation
|
||||
textures []TextureBinding
|
||||
uniformSize int
|
||||
}
|
||||
args := [nvariants]shaderArgs{
|
||||
@@ -109,7 +116,7 @@ func generate() error {
|
||||
}
|
||||
// Make the GL ES 2 source compatible with desktop GL 3.
|
||||
gles2 = "#version 100\n" + gles2
|
||||
inputs, uniforms, uniformSize, err := parseReflection(reflect)
|
||||
inputs, uniforms, textures, uniformSize, err := parseReflection(reflect)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -138,6 +145,7 @@ func generate() error {
|
||||
variants[i].hlsl = hlslc
|
||||
variants[i].inputs = inputs
|
||||
variants[i].uniforms = uniforms
|
||||
variants[i].textures = textures
|
||||
variants[i].uniformSize = uniformSize
|
||||
}
|
||||
name := filepath.Base(shader)
|
||||
@@ -165,8 +173,17 @@ func generate() error {
|
||||
fmt.Fprintf(&out, "{Name: %q, Type: %d, Size: %d, Offset: %d},\n", u.Name, u.Type, u.Size, u.Offset)
|
||||
}
|
||||
fmt.Fprintf(&out, "},\n")
|
||||
}
|
||||
if src.uniformSize != 0 {
|
||||
fmt.Fprintf(&out, "UniformSize: %d,\n", src.uniformSize)
|
||||
}
|
||||
if len(src.textures) > 0 {
|
||||
fmt.Fprintf(&out, "Textures: []TextureBinding{\n")
|
||||
for _, t := range src.textures {
|
||||
fmt.Fprintf(&out, "{Name: %q, Binding: %d},\n", t.Name, t.Binding)
|
||||
}
|
||||
fmt.Fprintf(&out, "},\n")
|
||||
}
|
||||
fmt.Fprintf(&out, "GLES2: %#v,\n", src.gles2)
|
||||
fmt.Fprintf(&out, "/*\n%s\n*/\n", src.hlslSrc)
|
||||
fmt.Fprintf(&out, "HLSL: %#v,\n", src.hlsl)
|
||||
@@ -191,7 +208,7 @@ func generate() error {
|
||||
return ioutil.WriteFile("shaders.go", gosrc, 0644)
|
||||
}
|
||||
|
||||
func parseReflection(jsonData []byte) ([]InputLocation, []UniformLocation, int, error) {
|
||||
func parseReflection(jsonData []byte) ([]InputLocation, []UniformLocation, []TextureBinding, int, error) {
|
||||
type InputReflection struct {
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
@@ -214,9 +231,18 @@ func parseReflection(jsonData []byte) ([]InputLocation, []UniformLocation, int,
|
||||
Size int `json:"block_size"`
|
||||
Members []UniformMemberReflection `json:"members"`
|
||||
}
|
||||
type TextureReflection struct {
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Set int `json:"set"`
|
||||
Binding int `json:"binding"`
|
||||
Dimension string `json:"dimension"`
|
||||
Format string `json:"format"`
|
||||
}
|
||||
type shaderReflection struct {
|
||||
Inputs []InputReflection `json:"inputs"`
|
||||
UniformBuffers []UniformBufferReflection `json:"uniform_buffers"`
|
||||
Textures []TextureReflection `json:"textures"`
|
||||
}
|
||||
type shaderMetadata struct {
|
||||
VS shaderReflection `json:"vs"`
|
||||
@@ -224,14 +250,14 @@ func parseReflection(jsonData []byte) ([]InputLocation, []UniformLocation, int,
|
||||
}
|
||||
var reflect shaderMetadata
|
||||
if err := json.Unmarshal(jsonData, &reflect); err != nil {
|
||||
return nil, nil, 0, fmt.Errorf("parseReflection: %v", err)
|
||||
return nil, nil, nil, 0, fmt.Errorf("parseReflection: %v", err)
|
||||
}
|
||||
var inputs []InputLocation
|
||||
inputRef := reflect.VS.Inputs
|
||||
for _, input := range inputRef {
|
||||
dataType, dataSize, err := parseDataType(input.Type)
|
||||
if err != nil {
|
||||
return nil, nil, 0, fmt.Errorf("parseReflection: %v", err)
|
||||
return nil, nil, nil, 0, fmt.Errorf("parseReflection: %v", err)
|
||||
}
|
||||
inputs = append(inputs, InputLocation{
|
||||
Name: input.Name,
|
||||
@@ -255,7 +281,7 @@ func parseReflection(jsonData []byte) ([]InputLocation, []UniformLocation, int,
|
||||
for _, member := range block.Members {
|
||||
dataType, size, err := parseDataType(member.Type)
|
||||
if err != nil {
|
||||
return nil, nil, 0, fmt.Errorf("parseReflection: %v", err)
|
||||
return nil, nil, nil, 0, fmt.Errorf("parseReflection: %v", err)
|
||||
}
|
||||
ublocks = append(ublocks, UniformLocation{
|
||||
// Synthetic name generated by glslcc.
|
||||
@@ -267,7 +293,18 @@ func parseReflection(jsonData []byte) ([]InputLocation, []UniformLocation, int,
|
||||
}
|
||||
blockOffset += block.Size
|
||||
}
|
||||
return inputs, ublocks, blockOffset, nil
|
||||
textures := reflect.VS.Textures
|
||||
if len(textures) == 0 {
|
||||
textures = reflect.FS.Textures
|
||||
}
|
||||
var texBinds []TextureBinding
|
||||
for _, texture := range textures {
|
||||
texBinds = append(texBinds, TextureBinding{
|
||||
Name: texture.Name,
|
||||
Binding: texture.Binding,
|
||||
})
|
||||
}
|
||||
return inputs, ublocks, texBinds, blockOffset, nil
|
||||
}
|
||||
|
||||
func parseDataType(t string) (DataType, int, error) {
|
||||
|
||||
+14
-10
@@ -366,6 +366,20 @@ func (b *Backend) NewProgram(vssrc, fssrc gpu.ShaderSources) (gpu.Program, error
|
||||
obj: p,
|
||||
nattr: len(attr),
|
||||
}
|
||||
gpuProg.Bind()
|
||||
// Bind texture uniforms.
|
||||
for _, tex := range vssrc.Textures {
|
||||
u := b.funcs.GetUniformLocation(p, tex.Name)
|
||||
if u.valid() {
|
||||
b.funcs.Uniform1i(u, tex.Binding)
|
||||
}
|
||||
}
|
||||
for _, tex := range fssrc.Textures {
|
||||
u := b.funcs.GetUniformLocation(p, tex.Name)
|
||||
if u.valid() {
|
||||
b.funcs.Uniform1i(u, tex.Binding)
|
||||
}
|
||||
}
|
||||
gpuProg.vertUniforms.setup(b.funcs, p, vssrc.UniformSize, vssrc.Uniforms)
|
||||
gpuProg.fragUniforms.setup(b.funcs, p, fssrc.UniformSize, fssrc.Uniforms)
|
||||
return gpuProg, nil
|
||||
@@ -389,21 +403,11 @@ func (p *gpuProgram) updateUniforms() {
|
||||
p.fragUniforms.update(p.backend.funcs)
|
||||
}
|
||||
|
||||
func (p *gpuProgram) Uniform1i(u gpu.Uniform, v int) {
|
||||
p.Bind()
|
||||
p.backend.funcs.Uniform1i(u.(Uniform), v)
|
||||
}
|
||||
|
||||
func (p *gpuProgram) Bind() {
|
||||
p.backend.useProgram(p)
|
||||
p.backend.enableVertexArrays(p.nattr)
|
||||
}
|
||||
|
||||
func (p *gpuProgram) UniformFor(uniform string) gpu.Uniform {
|
||||
f := p.backend.funcs
|
||||
return GetUniformLocation(f, p.obj, uniform)
|
||||
}
|
||||
|
||||
func (p *gpuProgram) Release() {
|
||||
p.backend.funcs.DeleteProgram(p.obj)
|
||||
}
|
||||
|
||||
@@ -425,8 +425,6 @@ func newBlitter(ctx Backend) *blitter {
|
||||
}
|
||||
b.prog = prog
|
||||
b.layout = layout
|
||||
texProg := b.prog[materialTexture].prog
|
||||
texProg.Uniform1i(texProg.UniformFor("tex"), 0)
|
||||
return b
|
||||
}
|
||||
|
||||
|
||||
@@ -134,11 +134,6 @@ func newCoverer(ctx Backend) *coverer {
|
||||
}
|
||||
c.prog = prog
|
||||
c.layout = layout
|
||||
texProg := prog[materialTexture].prog
|
||||
texProg.Uniform1i(texProg.UniformFor("tex"), 0)
|
||||
for _, p := range prog {
|
||||
p.prog.Uniform1i(p.prog.UniformFor("cover"), 1)
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
@@ -190,8 +185,6 @@ func newStenciler(ctx Backend) *stenciler {
|
||||
panic(err)
|
||||
}
|
||||
vertUniforms = newUniformBuffer(ctx, &st.iprog.uniforms.vert)
|
||||
coverLoc := iprog.UniformFor("cover")
|
||||
iprog.Uniform1i(coverLoc, 0)
|
||||
st.iprog.prog = newProgram(iprog, vertUniforms, nil)
|
||||
st.iprog.layout = iprogLayout
|
||||
return st
|
||||
|
||||
+14
-1
@@ -48,6 +48,9 @@ var (
|
||||
HLSL: []byte(nil),
|
||||
},
|
||||
ShaderSources{
|
||||
Textures: []TextureBinding{
|
||||
{Name: "tex", Binding: 0},
|
||||
},
|
||||
GLES2: "#version 100\nprecision mediump float;\nprecision highp int;\n\nuniform mediump sampler2D tex;\n\nvarying vec2 vUV;\n\nvoid main()\n{\n gl_FragData[0] = texture2D(tex, vUV);\n}\n\n",
|
||||
/*
|
||||
Texture2D<float4> tex : register(t0);
|
||||
@@ -155,7 +158,10 @@ var (
|
||||
{Name: "_12._color", Type: 0, Size: 4, Offset: 0},
|
||||
},
|
||||
UniformSize: 16,
|
||||
GLES2: "#version 100\nprecision mediump float;\nprecision highp int;\n\nstruct Color\n{\n vec4 _color;\n};\n\nuniform Color _12;\n\nuniform mediump sampler2D cover;\n\nvarying highp vec2 vCoverUV;\nvarying vec2 vUV;\n\nvoid main()\n{\n gl_FragData[0] = _12._color;\n float cover_1 = abs(texture2D(cover, vCoverUV).x);\n gl_FragData[0] *= cover_1;\n}\n\n",
|
||||
Textures: []TextureBinding{
|
||||
{Name: "cover", Binding: 1},
|
||||
},
|
||||
GLES2: "#version 100\nprecision mediump float;\nprecision highp int;\n\nstruct Color\n{\n vec4 _color;\n};\n\nuniform Color _12;\n\nuniform mediump sampler2D cover;\n\nvarying highp vec2 vCoverUV;\nvarying vec2 vUV;\n\nvoid main()\n{\n gl_FragData[0] = _12._color;\n float cover_1 = abs(texture2D(cover, vCoverUV).x);\n gl_FragData[0] *= cover_1;\n}\n\n",
|
||||
/*
|
||||
cbuffer Color : register(b0)
|
||||
{
|
||||
@@ -201,6 +207,10 @@ var (
|
||||
HLSL: []byte(nil),
|
||||
},
|
||||
ShaderSources{
|
||||
Textures: []TextureBinding{
|
||||
{Name: "tex", Binding: 0},
|
||||
{Name: "cover", Binding: 1},
|
||||
},
|
||||
GLES2: "#version 100\nprecision mediump float;\nprecision highp int;\n\nuniform mediump sampler2D tex;\nuniform mediump sampler2D cover;\n\nvarying vec2 vUV;\nvarying highp vec2 vCoverUV;\n\nvoid main()\n{\n gl_FragData[0] = texture2D(tex, vUV);\n float cover_1 = abs(texture2D(cover, vCoverUV).x);\n gl_FragData[0] *= cover_1;\n}\n\n",
|
||||
/*
|
||||
Texture2D<float4> tex : register(t0);
|
||||
@@ -315,6 +325,9 @@ var (
|
||||
HLSL: []byte(nil),
|
||||
}
|
||||
shader_intersect_frag = ShaderSources{
|
||||
Textures: []TextureBinding{
|
||||
{Name: "cover", Binding: 0},
|
||||
},
|
||||
GLES2: "#version 100\nprecision mediump float;\nprecision highp int;\n\nuniform mediump sampler2D cover;\n\nvarying highp vec2 vUV;\n\nvoid main()\n{\n float cover_1 = abs(texture2D(cover, vUV).x);\n gl_FragData[0].x = cover_1;\n}\n\n",
|
||||
/*
|
||||
Texture2D<float4> cover : register(t0);
|
||||
|
||||
Reference in New Issue
Block a user