mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-04 00:45:35 +00:00
gpu: switch from uniform buffers to combined push buffers
Vulkan doesn't support changing uniforms during a render pass. However, push constants *can* be changed. The gio-shader repository was changed to use push constants instead of uniforms, this change implements the corresponding driver and renderer change. Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
@@ -681,13 +681,9 @@ func (b *Backend) BindStorageBuffer(binding int, buffer driver.Buffer) {
|
||||
}
|
||||
}
|
||||
|
||||
func (b *Backend) BindVertexUniforms(buffer driver.Buffer) {
|
||||
func (b *Backend) BindUniforms(buffer driver.Buffer) {
|
||||
buf := buffer.(*Buffer)
|
||||
b.ctx.VSSetConstantBuffers(buf.buf)
|
||||
}
|
||||
|
||||
func (b *Backend) BindFragmentUniforms(buffer driver.Buffer) {
|
||||
buf := buffer.(*Buffer)
|
||||
b.ctx.PSSetConstantBuffers(buf.buf)
|
||||
}
|
||||
|
||||
|
||||
@@ -43,8 +43,7 @@ type Device interface {
|
||||
BindVertexBuffer(b Buffer, offset int)
|
||||
BindIndexBuffer(b Buffer)
|
||||
BindImageTexture(unit int, texture Texture, access AccessBits, format TextureFormat)
|
||||
BindVertexUniforms(buf Buffer)
|
||||
BindFragmentUniforms(buf Buffer)
|
||||
BindUniforms(buf Buffer)
|
||||
BindStorageBuffer(binding int, buf Buffer)
|
||||
|
||||
BeginCompute()
|
||||
|
||||
@@ -1005,20 +1005,9 @@ func (b *Backend) BindVertexUniforms(buf driver.Buffer) {
|
||||
}
|
||||
if bf.buffer != 0 {
|
||||
C.renderEncSetVertexBuffer(enc, bf.buffer, uniformBufferIndex, 0)
|
||||
} else if bf.size > 0 {
|
||||
C.renderEncSetVertexBytes(enc, unsafe.Pointer(&bf.store[0]), C.NSUInteger(bf.size), uniformBufferIndex)
|
||||
}
|
||||
}
|
||||
|
||||
func (b *Backend) BindFragmentUniforms(buf driver.Buffer) {
|
||||
bf := buf.(*Buffer)
|
||||
enc := b.renderEnc
|
||||
if enc == 0 {
|
||||
panic("no active render pass")
|
||||
}
|
||||
if bf.buffer != 0 {
|
||||
C.renderEncSetFragmentBuffer(enc, bf.buffer, uniformBufferIndex, 0)
|
||||
} else if bf.size > 0 {
|
||||
C.renderEncSetVertexBytes(enc, unsafe.Pointer(&bf.store[0]), C.NSUInteger(bf.size), uniformBufferIndex)
|
||||
C.renderEncSetFragmentBytes(enc, unsafe.Pointer(&bf.store[0]), C.NSUInteger(bf.size), uniformBufferIndex)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,17 +26,14 @@ type Backend struct {
|
||||
|
||||
glver [2]int
|
||||
gles bool
|
||||
ubo bool
|
||||
feats driver.Caps
|
||||
// floatTriple holds the settings for floating point
|
||||
// textures.
|
||||
floatTriple textureTriple
|
||||
// Single channel alpha textures.
|
||||
alphaTriple textureTriple
|
||||
srgbaTriple textureTriple
|
||||
vertUniforms *buffer
|
||||
fragUniforms *buffer
|
||||
storage [storageBindings]*buffer
|
||||
alphaTriple textureTriple
|
||||
srgbaTriple textureTriple
|
||||
storage [storageBindings]*buffer
|
||||
|
||||
sRGBFBO *SRGBFBO
|
||||
|
||||
@@ -190,13 +187,10 @@ func newOpenGLDevice(api driver.OpenGL) (driver.Device, error) {
|
||||
}
|
||||
floatTriple, ffboErr := floatTripleFor(f, ver, exts)
|
||||
srgbaTriple, srgbErr := srgbaTripleFor(ver, exts)
|
||||
gles30 := gles && ver[0] >= 3
|
||||
gles31 := gles && (ver[0] > 3 || (ver[0] == 3 && ver[1] >= 1))
|
||||
gl40 := !gles && ver[0] >= 4
|
||||
b := &Backend{
|
||||
glver: ver,
|
||||
gles: gles,
|
||||
ubo: gles30 || gl40,
|
||||
funcs: f,
|
||||
floatTriple: floatTriple,
|
||||
alphaTriple: alphaTripleFor(ver),
|
||||
@@ -712,12 +706,9 @@ func (b *Backend) NewBuffer(typ driver.BufferBinding, size int) (driver.Buffer,
|
||||
if typ != driver.BufferBindingUniforms {
|
||||
return nil, errors.New("uniforms buffers cannot be bound as anything else")
|
||||
}
|
||||
if !b.ubo {
|
||||
// GLES 2 doesn't support uniform buffers.
|
||||
buf.data = make([]byte, size)
|
||||
}
|
||||
buf.data = make([]byte, size)
|
||||
}
|
||||
if typ&^driver.BufferBindingUniforms != 0 || b.ubo {
|
||||
if typ&^driver.BufferBindingUniforms != 0 {
|
||||
buf.hasBuffer = true
|
||||
buf.obj = b.funcs.CreateBuffer()
|
||||
if err := glErr(b.funcs); err != nil {
|
||||
@@ -841,7 +832,6 @@ func (b *Backend) prepareDraw() {
|
||||
return
|
||||
}
|
||||
b.setupVertexArrays()
|
||||
p.prog.updateUniforms()
|
||||
}
|
||||
|
||||
func toGLDrawMode(mode driver.Topology) gl.Enum {
|
||||
@@ -954,27 +944,8 @@ func (b *Backend) newProgram(desc driver.PipelineDesc) (*program, error) {
|
||||
b.funcs.Uniform1i(u, tex.Binding)
|
||||
}
|
||||
}
|
||||
if b.ubo {
|
||||
for _, block := range vsh.src.Uniforms.Blocks {
|
||||
blockIdx := b.funcs.GetUniformBlockIndex(p, block.Name)
|
||||
if blockIdx != gl.INVALID_INDEX {
|
||||
b.funcs.UniformBlockBinding(p, blockIdx, uint(block.Binding))
|
||||
}
|
||||
}
|
||||
// To match Direct3D 11 with separate vertex and fragment
|
||||
// shader uniform buffers, offset all fragment blocks to be
|
||||
// located after the vertex blocks.
|
||||
off := len(vsh.src.Uniforms.Blocks)
|
||||
for _, block := range fsh.src.Uniforms.Blocks {
|
||||
blockIdx := b.funcs.GetUniformBlockIndex(p, block.Name)
|
||||
if blockIdx != gl.INVALID_INDEX {
|
||||
b.funcs.UniformBlockBinding(p, blockIdx, uint(block.Binding+off))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
prog.vertUniforms.setup(b.funcs, p, vsh.src.Uniforms.Size, vsh.src.Uniforms.Locations)
|
||||
prog.fragUniforms.setup(b.funcs, p, fsh.src.Uniforms.Size, fsh.src.Uniforms.Locations)
|
||||
}
|
||||
prog.vertUniforms.setup(b.funcs, p, vsh.src.Uniforms.Size, vsh.src.Uniforms.Locations)
|
||||
prog.fragUniforms.setup(b.funcs, p, fsh.src.Uniforms.Size, fsh.src.Uniforms.Locations)
|
||||
return prog, nil
|
||||
}
|
||||
|
||||
@@ -994,38 +965,13 @@ func (b *Backend) BindStorageBuffer(binding int, buf driver.Buffer) {
|
||||
b.storage[binding] = bf
|
||||
}
|
||||
|
||||
func (b *Backend) BindVertexUniforms(buf driver.Buffer) {
|
||||
func (b *Backend) BindUniforms(buf driver.Buffer) {
|
||||
bf := buf.(*buffer)
|
||||
if bf.typ&driver.BufferBindingUniforms == 0 {
|
||||
panic("not a uniform buffer")
|
||||
}
|
||||
b.vertUniforms = bf
|
||||
}
|
||||
|
||||
func (b *Backend) BindFragmentUniforms(buf driver.Buffer) {
|
||||
bf := buf.(*buffer)
|
||||
if bf.typ&driver.BufferBindingUniforms == 0 {
|
||||
panic("not a uniform buffer")
|
||||
}
|
||||
b.fragUniforms = bf
|
||||
}
|
||||
|
||||
func (p *program) updateUniforms() {
|
||||
f := p.backend.funcs
|
||||
if b := p.backend.vertUniforms; b != nil {
|
||||
if p.backend.ubo {
|
||||
p.backend.glstate.bindBufferBase(f, gl.UNIFORM_BUFFER, 0, b.obj)
|
||||
} else {
|
||||
p.vertUniforms.update(f, b)
|
||||
}
|
||||
}
|
||||
if b := p.backend.fragUniforms; b != nil {
|
||||
if p.backend.ubo {
|
||||
p.backend.glstate.bindBufferBase(f, gl.UNIFORM_BUFFER, 1, b.obj)
|
||||
} else {
|
||||
p.fragUniforms.update(f, b)
|
||||
}
|
||||
}
|
||||
b.state.pipeline.prog.vertUniforms.update(b.funcs, bf)
|
||||
b.state.pipeline.prog.fragUniforms.update(b.funcs, bf)
|
||||
}
|
||||
|
||||
func (b *Backend) BindProgram(prog driver.Program) {
|
||||
|
||||
Reference in New Issue
Block a user