mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-06 09:55:40 +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:
@@ -10,5 +10,5 @@ require (
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
gioui.org/cpu v0.0.0-20210817075930-8d6a761490d2
|
gioui.org/cpu v0.0.0-20210817075930-8d6a761490d2
|
||||||
gioui.org/shader v1.0.2
|
gioui.org/shader v1.0.3
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ dmitri.shuralyov.com/gpu/mtl v0.0.0-20201218220906-28db891af037/go.mod h1:H6x//7
|
|||||||
gioui.org/cpu v0.0.0-20210808092351-bfe733dd3334/go.mod h1:A8M0Cn5o+vY5LTMlnRoK3O5kG+rH0kWfJjeKd9QpBmQ=
|
gioui.org/cpu v0.0.0-20210808092351-bfe733dd3334/go.mod h1:A8M0Cn5o+vY5LTMlnRoK3O5kG+rH0kWfJjeKd9QpBmQ=
|
||||||
gioui.org/cpu v0.0.0-20210817075930-8d6a761490d2 h1:AGDDxsJE1RpcXTAxPG2B4jrwVUJGFDjINIPi1jtO6pc=
|
gioui.org/cpu v0.0.0-20210817075930-8d6a761490d2 h1:AGDDxsJE1RpcXTAxPG2B4jrwVUJGFDjINIPi1jtO6pc=
|
||||||
gioui.org/cpu v0.0.0-20210817075930-8d6a761490d2/go.mod h1:A8M0Cn5o+vY5LTMlnRoK3O5kG+rH0kWfJjeKd9QpBmQ=
|
gioui.org/cpu v0.0.0-20210817075930-8d6a761490d2/go.mod h1:A8M0Cn5o+vY5LTMlnRoK3O5kG+rH0kWfJjeKd9QpBmQ=
|
||||||
gioui.org/shader v1.0.2 h1:5JrtNdOqmY+tQzBKKVFqf0YIziUK38OEw8mxxEbXdc8=
|
gioui.org/shader v1.0.3 h1:xllhh4w2XWej9lfkHMtOtI3ES05T8xZzxrSSWbMZgTw=
|
||||||
gioui.org/shader v1.0.2/go.mod h1:mWdiME581d/kV7/iEhLmUgUK5iZ09XR5XpduXzbePVM=
|
gioui.org/shader v1.0.3/go.mod h1:mWdiME581d/kV7/iEhLmUgUK5iZ09XR5XpduXzbePVM=
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||||
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
|
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
|
||||||
|
|||||||
+20
-34
@@ -88,11 +88,8 @@ type compute struct {
|
|||||||
pipeline driver.Pipeline
|
pipeline driver.Pipeline
|
||||||
buffer sizedBuffer
|
buffer sizedBuffer
|
||||||
quads []materialVertex
|
quads []materialVertex
|
||||||
vert struct {
|
uniforms struct {
|
||||||
uniforms *materialVertUniforms
|
u *materialUniforms
|
||||||
buf driver.Buffer
|
|
||||||
}
|
|
||||||
frag struct {
|
|
||||||
buf driver.Buffer
|
buf driver.Buffer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -172,13 +169,10 @@ type copyUniforms struct {
|
|||||||
_ [8]byte // Pad to 16 bytes.
|
_ [8]byte // Pad to 16 bytes.
|
||||||
}
|
}
|
||||||
|
|
||||||
type materialVertUniforms struct {
|
type materialUniforms struct {
|
||||||
scale [2]float32
|
scale [2]float32
|
||||||
pos [2]float32
|
pos [2]float32
|
||||||
}
|
emulatesRGB float32
|
||||||
|
|
||||||
type materialFragUniforms struct {
|
|
||||||
emulateSRGB float32
|
|
||||||
_ [12]byte // Pad to 16 bytes
|
_ [12]byte // Pad to 16 bytes
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -504,25 +498,14 @@ func newCompute(ctx driver.Device) (*compute, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
g.materials.pipeline = pipe
|
g.materials.pipeline = pipe
|
||||||
g.materials.vert.uniforms = new(materialVertUniforms)
|
g.materials.uniforms.u = new(materialUniforms)
|
||||||
|
|
||||||
buf, err = ctx.NewBuffer(driver.BufferBindingUniforms, int(unsafe.Sizeof(*g.materials.vert.uniforms)))
|
buf, err = ctx.NewBuffer(driver.BufferBindingUniforms, int(unsafe.Sizeof(*g.materials.uniforms.u)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
g.Release()
|
g.Release()
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
g.materials.vert.buf = buf
|
g.materials.uniforms.buf = buf
|
||||||
var emulateSRGB materialFragUniforms
|
|
||||||
if !g.srgb {
|
|
||||||
emulateSRGB.emulateSRGB = 1.0
|
|
||||||
}
|
|
||||||
buf, err = ctx.NewBuffer(driver.BufferBindingUniforms, int(unsafe.Sizeof(emulateSRGB)))
|
|
||||||
if err != nil {
|
|
||||||
g.Release()
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
buf.Upload(byteslice.Struct(&emulateSRGB))
|
|
||||||
g.materials.frag.buf = buf
|
|
||||||
|
|
||||||
for _, shader := range shaders {
|
for _, shader := range shaders {
|
||||||
if !g.useCPU {
|
if !g.useCPU {
|
||||||
@@ -874,7 +857,6 @@ func (g *compute) blitLayers(viewport image.Point) {
|
|||||||
layers := g.collector.frame.layers
|
layers := g.collector.frame.layers
|
||||||
g.ctx.Viewport(0, 0, viewport.X, viewport.Y)
|
g.ctx.Viewport(0, 0, viewport.X, viewport.Y)
|
||||||
g.ctx.BindPipeline(g.output.blitPipeline)
|
g.ctx.BindPipeline(g.output.blitPipeline)
|
||||||
g.ctx.BindVertexUniforms(g.output.uniBuf)
|
|
||||||
for len(layers) > 0 {
|
for len(layers) > 0 {
|
||||||
g.output.layerVertices = g.output.layerVertices[:0]
|
g.output.layerVertices = g.output.layerVertices[:0]
|
||||||
atlas := layers[0].alloc.atlas
|
atlas := layers[0].alloc.atlas
|
||||||
@@ -906,6 +888,7 @@ func (g *compute) blitLayers(viewport image.Point) {
|
|||||||
g.output.uniforms.pos = [2]float32{ox, oy}
|
g.output.uniforms.pos = [2]float32{ox, oy}
|
||||||
g.output.uniforms.uvScale = [2]float32{1 / float32(atlas.size.X), 1 / float32(atlas.size.Y)}
|
g.output.uniforms.uvScale = [2]float32{1 / float32(atlas.size.X), 1 / float32(atlas.size.Y)}
|
||||||
g.output.uniBuf.Upload(byteslice.Struct(g.output.uniforms))
|
g.output.uniBuf.Upload(byteslice.Struct(g.output.uniforms))
|
||||||
|
g.ctx.BindUniforms(g.output.uniBuf)
|
||||||
vertexData := byteslice.Slice(g.output.layerVertices)
|
vertexData := byteslice.Slice(g.output.layerVertices)
|
||||||
g.output.buffer.ensureCapacity(false, g.ctx, driver.BufferBindingVertices, len(vertexData))
|
g.output.buffer.ensureCapacity(false, g.ctx, driver.BufferBindingVertices, len(vertexData))
|
||||||
g.output.buffer.buffer.Upload(vertexData)
|
g.output.buffer.buffer.Upload(vertexData)
|
||||||
@@ -1001,9 +984,14 @@ func (g *compute) renderMaterials() error {
|
|||||||
}
|
}
|
||||||
// Transform to clip space: [-1, -1] - [1, 1] and flip Y-axis to cancel the implied transformation
|
// Transform to clip space: [-1, -1] - [1, 1] and flip Y-axis to cancel the implied transformation
|
||||||
// between framebuffer and texture space.
|
// between framebuffer and texture space.
|
||||||
m.vert.uniforms.scale = [2]float32{2, -2}
|
*m.uniforms.u = materialUniforms{
|
||||||
m.vert.uniforms.pos = [2]float32{-1, +1}
|
scale: [2]float32{2, -2},
|
||||||
m.vert.buf.Upload(byteslice.Struct(m.vert.uniforms))
|
pos: [2]float32{-1, +1},
|
||||||
|
}
|
||||||
|
if !g.srgb {
|
||||||
|
m.uniforms.u.emulatesRGB = 1.0
|
||||||
|
}
|
||||||
|
m.uniforms.buf.Upload(byteslice.Struct(m.uniforms.u))
|
||||||
vertexData := byteslice.Slice(m.quads)
|
vertexData := byteslice.Slice(m.quads)
|
||||||
n := pow2Ceil(len(vertexData))
|
n := pow2Ceil(len(vertexData))
|
||||||
m.buffer.ensureCapacity(false, g.ctx, driver.BufferBindingVertices, n)
|
m.buffer.ensureCapacity(false, g.ctx, driver.BufferBindingVertices, n)
|
||||||
@@ -1013,10 +1001,9 @@ func (g *compute) renderMaterials() error {
|
|||||||
d.Action = driver.LoadActionClear
|
d.Action = driver.LoadActionClear
|
||||||
}
|
}
|
||||||
g.ctx.BeginRenderPass(atlas.fbo, d)
|
g.ctx.BeginRenderPass(atlas.fbo, d)
|
||||||
g.ctx.BindVertexUniforms(m.vert.buf)
|
|
||||||
g.ctx.BindFragmentUniforms(m.frag.buf)
|
|
||||||
g.ctx.BindTexture(0, imgAtlas.image)
|
g.ctx.BindTexture(0, imgAtlas.image)
|
||||||
g.ctx.BindPipeline(m.pipeline)
|
g.ctx.BindPipeline(m.pipeline)
|
||||||
|
g.ctx.BindUniforms(m.uniforms.buf)
|
||||||
g.ctx.BindVertexBuffer(m.buffer.buffer, 0)
|
g.ctx.BindVertexBuffer(m.buffer.buffer, 0)
|
||||||
newAllocs := atlas.allocs[allocStart:]
|
newAllocs := atlas.allocs[allocStart:]
|
||||||
for i, a := range newAllocs {
|
for i, a := range newAllocs {
|
||||||
@@ -1507,8 +1494,7 @@ func (g *compute) Release() {
|
|||||||
&g.buffers.config,
|
&g.buffers.config,
|
||||||
g.materials.pipeline,
|
g.materials.pipeline,
|
||||||
&g.materials.buffer,
|
&g.materials.buffer,
|
||||||
g.materials.vert.buf,
|
g.materials.uniforms.buf,
|
||||||
g.materials.frag.buf,
|
|
||||||
g.timers.t,
|
g.timers.t,
|
||||||
}
|
}
|
||||||
for _, r := range res {
|
for _, r := range res {
|
||||||
|
|||||||
+36
-64
@@ -282,30 +282,20 @@ type blitter struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type blitColUniforms struct {
|
type blitColUniforms struct {
|
||||||
vert struct {
|
blitUniforms
|
||||||
blitUniforms
|
_ [128 - unsafe.Sizeof(blitUniforms{}) - unsafe.Sizeof(colorUniforms{})]byte // Padding to 128 bytes.
|
||||||
_ [12]byte // Padding to a multiple of 16.
|
colorUniforms
|
||||||
}
|
|
||||||
frag struct {
|
|
||||||
colorUniforms
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type blitTexUniforms struct {
|
type blitTexUniforms struct {
|
||||||
vert struct {
|
blitUniforms
|
||||||
blitUniforms
|
_ [12]byte // Padding to 16 bytes.
|
||||||
_ [12]byte // Padding to a multiple of 16.
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type blitLinearGradientUniforms struct {
|
type blitLinearGradientUniforms struct {
|
||||||
vert struct {
|
blitUniforms
|
||||||
blitUniforms
|
_ [128 - unsafe.Sizeof(blitUniforms{}) - unsafe.Sizeof(gradientUniforms{})]byte // Padding to 128 bytes.
|
||||||
_ [12]byte // Padding to a multiple of 16.
|
gradientUniforms
|
||||||
}
|
|
||||||
frag struct {
|
|
||||||
gradientUniforms
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type uniformBuffer struct {
|
type uniformBuffer struct {
|
||||||
@@ -314,9 +304,8 @@ type uniformBuffer struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type pipeline struct {
|
type pipeline struct {
|
||||||
pipeline driver.Pipeline
|
pipeline driver.Pipeline
|
||||||
vertUniforms *uniformBuffer
|
uniforms *uniformBuffer
|
||||||
fragUniforms *uniformBuffer
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type blitUniforms struct {
|
type blitUniforms struct {
|
||||||
@@ -536,8 +525,7 @@ func newBlitter(ctx driver.Device) *blitter {
|
|||||||
b.texUniforms = new(blitTexUniforms)
|
b.texUniforms = new(blitTexUniforms)
|
||||||
b.linearGradientUniforms = new(blitLinearGradientUniforms)
|
b.linearGradientUniforms = new(blitLinearGradientUniforms)
|
||||||
pipelines, err := createColorPrograms(ctx, gio.Shader_blit_vert, gio.Shader_blit_frag,
|
pipelines, err := createColorPrograms(ctx, gio.Shader_blit_vert, gio.Shader_blit_frag,
|
||||||
[3]interface{}{&b.colUniforms.vert, &b.linearGradientUniforms.vert, &b.texUniforms.vert},
|
[3]interface{}{b.colUniforms, b.linearGradientUniforms, b.texUniforms},
|
||||||
[3]interface{}{&b.colUniforms.frag, &b.linearGradientUniforms.frag, nil},
|
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@@ -553,7 +541,7 @@ func (b *blitter) release() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func createColorPrograms(b driver.Device, vsSrc shader.Sources, fsSrc [3]shader.Sources, vertUniforms, fragUniforms [3]interface{}) ([3]*pipeline, error) {
|
func createColorPrograms(b driver.Device, vsSrc shader.Sources, fsSrc [3]shader.Sources, uniforms [3]interface{}) ([3]*pipeline, error) {
|
||||||
var pipelines [3]*pipeline
|
var pipelines [3]*pipeline
|
||||||
blend := driver.BlendDesc{
|
blend := driver.BlendDesc{
|
||||||
Enable: true,
|
Enable: true,
|
||||||
@@ -589,17 +577,14 @@ func createColorPrograms(b driver.Device, vsSrc shader.Sources, fsSrc [3]shader.
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return pipelines, err
|
return pipelines, err
|
||||||
}
|
}
|
||||||
var vertBuffer, fragBuffer *uniformBuffer
|
var vertBuffer *uniformBuffer
|
||||||
if u := vertUniforms[materialTexture]; u != nil {
|
if u := uniforms[materialTexture]; u != nil {
|
||||||
vertBuffer = newUniformBuffer(b, u)
|
vertBuffer = newUniformBuffer(b, u)
|
||||||
}
|
}
|
||||||
if u := fragUniforms[materialTexture]; u != nil {
|
pipelines[materialTexture] = &pipeline{pipe, vertBuffer}
|
||||||
fragBuffer = newUniformBuffer(b, u)
|
|
||||||
}
|
|
||||||
pipelines[materialTexture] = &pipeline{pipe, vertBuffer, fragBuffer}
|
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
var vertBuffer, fragBuffer *uniformBuffer
|
var vertBuffer *uniformBuffer
|
||||||
fsh, err := b.NewFragmentShader(fsSrc[materialColor])
|
fsh, err := b.NewFragmentShader(fsSrc[materialColor])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
pipelines[materialTexture].Release()
|
pipelines[materialTexture].Release()
|
||||||
@@ -618,16 +603,13 @@ func createColorPrograms(b driver.Device, vsSrc shader.Sources, fsSrc [3]shader.
|
|||||||
pipelines[materialTexture].Release()
|
pipelines[materialTexture].Release()
|
||||||
return pipelines, err
|
return pipelines, err
|
||||||
}
|
}
|
||||||
if u := vertUniforms[materialColor]; u != nil {
|
if u := uniforms[materialColor]; u != nil {
|
||||||
vertBuffer = newUniformBuffer(b, u)
|
vertBuffer = newUniformBuffer(b, u)
|
||||||
}
|
}
|
||||||
if u := fragUniforms[materialColor]; u != nil {
|
pipelines[materialColor] = &pipeline{pipe, vertBuffer}
|
||||||
fragBuffer = newUniformBuffer(b, u)
|
|
||||||
}
|
|
||||||
pipelines[materialColor] = &pipeline{pipe, vertBuffer, fragBuffer}
|
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
var vertBuffer, fragBuffer *uniformBuffer
|
var vertBuffer *uniformBuffer
|
||||||
fsh, err := b.NewFragmentShader(fsSrc[materialLinearGradient])
|
fsh, err := b.NewFragmentShader(fsSrc[materialLinearGradient])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
pipelines[materialTexture].Release()
|
pipelines[materialTexture].Release()
|
||||||
@@ -648,13 +630,10 @@ func createColorPrograms(b driver.Device, vsSrc shader.Sources, fsSrc [3]shader.
|
|||||||
pipelines[materialColor].Release()
|
pipelines[materialColor].Release()
|
||||||
return pipelines, err
|
return pipelines, err
|
||||||
}
|
}
|
||||||
if u := vertUniforms[materialLinearGradient]; u != nil {
|
if u := uniforms[materialLinearGradient]; u != nil {
|
||||||
vertBuffer = newUniformBuffer(b, u)
|
vertBuffer = newUniformBuffer(b, u)
|
||||||
}
|
}
|
||||||
if u := fragUniforms[materialLinearGradient]; u != nil {
|
pipelines[materialLinearGradient] = &pipeline{pipe, vertBuffer}
|
||||||
fragBuffer = newUniformBuffer(b, u)
|
|
||||||
}
|
|
||||||
pipelines[materialLinearGradient] = &pipeline{pipe, vertBuffer, fragBuffer}
|
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
for _, p := range pipelines {
|
for _, p := range pipelines {
|
||||||
@@ -1151,21 +1130,21 @@ func (b *blitter) blit(mat materialType, col f32color.RGBA, col1, col2 f32color.
|
|||||||
var uniforms *blitUniforms
|
var uniforms *blitUniforms
|
||||||
switch mat {
|
switch mat {
|
||||||
case materialColor:
|
case materialColor:
|
||||||
b.colUniforms.frag.color = col
|
b.colUniforms.color = col
|
||||||
uniforms = &b.colUniforms.vert.blitUniforms
|
uniforms = &b.colUniforms.blitUniforms
|
||||||
case materialTexture:
|
case materialTexture:
|
||||||
t1, t2, t3, t4, t5, t6 := uvTrans.Elems()
|
t1, t2, t3, t4, t5, t6 := uvTrans.Elems()
|
||||||
b.texUniforms.vert.blitUniforms.uvTransformR1 = [4]float32{t1, t2, t3, 0}
|
b.texUniforms.blitUniforms.uvTransformR1 = [4]float32{t1, t2, t3, 0}
|
||||||
b.texUniforms.vert.blitUniforms.uvTransformR2 = [4]float32{t4, t5, t6, 0}
|
b.texUniforms.blitUniforms.uvTransformR2 = [4]float32{t4, t5, t6, 0}
|
||||||
uniforms = &b.texUniforms.vert.blitUniforms
|
uniforms = &b.texUniforms.blitUniforms
|
||||||
case materialLinearGradient:
|
case materialLinearGradient:
|
||||||
b.linearGradientUniforms.frag.color1 = col1
|
b.linearGradientUniforms.color1 = col1
|
||||||
b.linearGradientUniforms.frag.color2 = col2
|
b.linearGradientUniforms.color2 = col2
|
||||||
|
|
||||||
t1, t2, t3, t4, t5, t6 := uvTrans.Elems()
|
t1, t2, t3, t4, t5, t6 := uvTrans.Elems()
|
||||||
b.linearGradientUniforms.vert.blitUniforms.uvTransformR1 = [4]float32{t1, t2, t3, 0}
|
b.linearGradientUniforms.blitUniforms.uvTransformR1 = [4]float32{t1, t2, t3, 0}
|
||||||
b.linearGradientUniforms.vert.blitUniforms.uvTransformR2 = [4]float32{t4, t5, t6, 0}
|
b.linearGradientUniforms.blitUniforms.uvTransformR2 = [4]float32{t4, t5, t6, 0}
|
||||||
uniforms = &b.linearGradientUniforms.vert.blitUniforms
|
uniforms = &b.linearGradientUniforms.blitUniforms
|
||||||
}
|
}
|
||||||
uniforms.transform = [4]float32{scale.X, scale.Y, off.X, off.Y}
|
uniforms.transform = [4]float32{scale.X, scale.Y, off.X, off.Y}
|
||||||
p.UploadUniforms(b.ctx)
|
p.UploadUniforms(b.ctx)
|
||||||
@@ -1197,23 +1176,16 @@ func (u *uniformBuffer) Release() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *pipeline) UploadUniforms(ctx driver.Device) {
|
func (p *pipeline) UploadUniforms(ctx driver.Device) {
|
||||||
if p.vertUniforms != nil {
|
if p.uniforms != nil {
|
||||||
p.vertUniforms.Upload()
|
p.uniforms.Upload()
|
||||||
ctx.BindVertexUniforms(p.vertUniforms.buf)
|
ctx.BindUniforms(p.uniforms.buf)
|
||||||
}
|
|
||||||
if p.fragUniforms != nil {
|
|
||||||
p.fragUniforms.Upload()
|
|
||||||
ctx.BindFragmentUniforms(p.fragUniforms.buf)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *pipeline) Release() {
|
func (p *pipeline) Release() {
|
||||||
p.pipeline.Release()
|
p.pipeline.Release()
|
||||||
if p.vertUniforms != nil {
|
if p.uniforms != nil {
|
||||||
p.vertUniforms.Release()
|
p.uniforms.Release()
|
||||||
}
|
|
||||||
if p.fragUniforms != nil {
|
|
||||||
p.fragUniforms.Release()
|
|
||||||
}
|
}
|
||||||
*p = pipeline{}
|
*p = pipeline{}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
buf := buffer.(*Buffer)
|
||||||
b.ctx.VSSetConstantBuffers(buf.buf)
|
b.ctx.VSSetConstantBuffers(buf.buf)
|
||||||
}
|
|
||||||
|
|
||||||
func (b *Backend) BindFragmentUniforms(buffer driver.Buffer) {
|
|
||||||
buf := buffer.(*Buffer)
|
|
||||||
b.ctx.PSSetConstantBuffers(buf.buf)
|
b.ctx.PSSetConstantBuffers(buf.buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -43,8 +43,7 @@ type Device interface {
|
|||||||
BindVertexBuffer(b Buffer, offset int)
|
BindVertexBuffer(b Buffer, offset int)
|
||||||
BindIndexBuffer(b Buffer)
|
BindIndexBuffer(b Buffer)
|
||||||
BindImageTexture(unit int, texture Texture, access AccessBits, format TextureFormat)
|
BindImageTexture(unit int, texture Texture, access AccessBits, format TextureFormat)
|
||||||
BindVertexUniforms(buf Buffer)
|
BindUniforms(buf Buffer)
|
||||||
BindFragmentUniforms(buf Buffer)
|
|
||||||
BindStorageBuffer(binding int, buf Buffer)
|
BindStorageBuffer(binding int, buf Buffer)
|
||||||
|
|
||||||
BeginCompute()
|
BeginCompute()
|
||||||
|
|||||||
@@ -1005,20 +1005,9 @@ func (b *Backend) BindVertexUniforms(buf driver.Buffer) {
|
|||||||
}
|
}
|
||||||
if bf.buffer != 0 {
|
if bf.buffer != 0 {
|
||||||
C.renderEncSetVertexBuffer(enc, bf.buffer, uniformBufferIndex, 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)
|
C.renderEncSetFragmentBuffer(enc, bf.buffer, uniformBufferIndex, 0)
|
||||||
} else if bf.size > 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)
|
C.renderEncSetFragmentBytes(enc, unsafe.Pointer(&bf.store[0]), C.NSUInteger(bf.size), uniformBufferIndex)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,17 +26,14 @@ type Backend struct {
|
|||||||
|
|
||||||
glver [2]int
|
glver [2]int
|
||||||
gles bool
|
gles bool
|
||||||
ubo bool
|
|
||||||
feats driver.Caps
|
feats driver.Caps
|
||||||
// floatTriple holds the settings for floating point
|
// floatTriple holds the settings for floating point
|
||||||
// textures.
|
// textures.
|
||||||
floatTriple textureTriple
|
floatTriple textureTriple
|
||||||
// Single channel alpha textures.
|
// Single channel alpha textures.
|
||||||
alphaTriple textureTriple
|
alphaTriple textureTriple
|
||||||
srgbaTriple textureTriple
|
srgbaTriple textureTriple
|
||||||
vertUniforms *buffer
|
storage [storageBindings]*buffer
|
||||||
fragUniforms *buffer
|
|
||||||
storage [storageBindings]*buffer
|
|
||||||
|
|
||||||
sRGBFBO *SRGBFBO
|
sRGBFBO *SRGBFBO
|
||||||
|
|
||||||
@@ -190,13 +187,10 @@ func newOpenGLDevice(api driver.OpenGL) (driver.Device, error) {
|
|||||||
}
|
}
|
||||||
floatTriple, ffboErr := floatTripleFor(f, ver, exts)
|
floatTriple, ffboErr := floatTripleFor(f, ver, exts)
|
||||||
srgbaTriple, srgbErr := srgbaTripleFor(ver, exts)
|
srgbaTriple, srgbErr := srgbaTripleFor(ver, exts)
|
||||||
gles30 := gles && ver[0] >= 3
|
|
||||||
gles31 := gles && (ver[0] > 3 || (ver[0] == 3 && ver[1] >= 1))
|
gles31 := gles && (ver[0] > 3 || (ver[0] == 3 && ver[1] >= 1))
|
||||||
gl40 := !gles && ver[0] >= 4
|
|
||||||
b := &Backend{
|
b := &Backend{
|
||||||
glver: ver,
|
glver: ver,
|
||||||
gles: gles,
|
gles: gles,
|
||||||
ubo: gles30 || gl40,
|
|
||||||
funcs: f,
|
funcs: f,
|
||||||
floatTriple: floatTriple,
|
floatTriple: floatTriple,
|
||||||
alphaTriple: alphaTripleFor(ver),
|
alphaTriple: alphaTripleFor(ver),
|
||||||
@@ -712,12 +706,9 @@ func (b *Backend) NewBuffer(typ driver.BufferBinding, size int) (driver.Buffer,
|
|||||||
if typ != driver.BufferBindingUniforms {
|
if typ != driver.BufferBindingUniforms {
|
||||||
return nil, errors.New("uniforms buffers cannot be bound as anything else")
|
return nil, errors.New("uniforms buffers cannot be bound as anything else")
|
||||||
}
|
}
|
||||||
if !b.ubo {
|
buf.data = make([]byte, size)
|
||||||
// GLES 2 doesn't support uniform buffers.
|
|
||||||
buf.data = make([]byte, size)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if typ&^driver.BufferBindingUniforms != 0 || b.ubo {
|
if typ&^driver.BufferBindingUniforms != 0 {
|
||||||
buf.hasBuffer = true
|
buf.hasBuffer = true
|
||||||
buf.obj = b.funcs.CreateBuffer()
|
buf.obj = b.funcs.CreateBuffer()
|
||||||
if err := glErr(b.funcs); err != nil {
|
if err := glErr(b.funcs); err != nil {
|
||||||
@@ -841,7 +832,6 @@ func (b *Backend) prepareDraw() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
b.setupVertexArrays()
|
b.setupVertexArrays()
|
||||||
p.prog.updateUniforms()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func toGLDrawMode(mode driver.Topology) gl.Enum {
|
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)
|
b.funcs.Uniform1i(u, tex.Binding)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if b.ubo {
|
prog.vertUniforms.setup(b.funcs, p, vsh.src.Uniforms.Size, vsh.src.Uniforms.Locations)
|
||||||
for _, block := range vsh.src.Uniforms.Blocks {
|
prog.fragUniforms.setup(b.funcs, p, fsh.src.Uniforms.Size, fsh.src.Uniforms.Locations)
|
||||||
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)
|
|
||||||
}
|
|
||||||
return prog, nil
|
return prog, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -994,38 +965,13 @@ func (b *Backend) BindStorageBuffer(binding int, buf driver.Buffer) {
|
|||||||
b.storage[binding] = bf
|
b.storage[binding] = bf
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Backend) BindVertexUniforms(buf driver.Buffer) {
|
func (b *Backend) BindUniforms(buf driver.Buffer) {
|
||||||
bf := buf.(*buffer)
|
bf := buf.(*buffer)
|
||||||
if bf.typ&driver.BufferBindingUniforms == 0 {
|
if bf.typ&driver.BufferBindingUniforms == 0 {
|
||||||
panic("not a uniform buffer")
|
panic("not a uniform buffer")
|
||||||
}
|
}
|
||||||
b.vertUniforms = bf
|
b.state.pipeline.prog.vertUniforms.update(b.funcs, bf)
|
||||||
}
|
b.state.pipeline.prog.fragUniforms.update(b.funcs, 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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Backend) BindProgram(prog driver.Program) {
|
func (b *Backend) BindProgram(prog driver.Program) {
|
||||||
|
|||||||
+27
-40
@@ -37,30 +37,20 @@ type coverer struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type coverTexUniforms struct {
|
type coverTexUniforms struct {
|
||||||
vert struct {
|
coverUniforms
|
||||||
coverUniforms
|
_ [12]byte // Padding to multiple of 16.
|
||||||
_ [12]byte // Padding to multiple of 16.
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type coverColUniforms struct {
|
type coverColUniforms struct {
|
||||||
vert struct {
|
coverUniforms
|
||||||
coverUniforms
|
_ [128 - unsafe.Sizeof(coverUniforms{}) - unsafe.Sizeof(colorUniforms{})]byte // Padding to 128 bytes.
|
||||||
_ [12]byte // Padding to multiple of 16.
|
colorUniforms
|
||||||
}
|
|
||||||
frag struct {
|
|
||||||
colorUniforms
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type coverLinearGradientUniforms struct {
|
type coverLinearGradientUniforms struct {
|
||||||
vert struct {
|
coverUniforms
|
||||||
coverUniforms
|
_ [128 - unsafe.Sizeof(coverUniforms{}) - unsafe.Sizeof(gradientUniforms{})]byte // Padding to 128.
|
||||||
_ [12]byte // Padding to multiple of 16.
|
gradientUniforms
|
||||||
}
|
|
||||||
frag struct {
|
|
||||||
gradientUniforms
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type coverUniforms struct {
|
type coverUniforms struct {
|
||||||
@@ -87,11 +77,9 @@ type stenciler struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type stencilUniforms struct {
|
type stencilUniforms struct {
|
||||||
vert struct {
|
transform [4]float32
|
||||||
transform [4]float32
|
pathOffset [2]float32
|
||||||
pathOffset [2]float32
|
_ [8]byte // Padding to multiple of 16.
|
||||||
_ [8]byte // Padding to multiple of 16.
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type intersectUniforms struct {
|
type intersectUniforms struct {
|
||||||
@@ -161,8 +149,7 @@ func newCoverer(ctx driver.Device) *coverer {
|
|||||||
c.texUniforms = new(coverTexUniforms)
|
c.texUniforms = new(coverTexUniforms)
|
||||||
c.linearGradientUniforms = new(coverLinearGradientUniforms)
|
c.linearGradientUniforms = new(coverLinearGradientUniforms)
|
||||||
pipelines, err := createColorPrograms(ctx, gio.Shader_cover_vert, gio.Shader_cover_frag,
|
pipelines, err := createColorPrograms(ctx, gio.Shader_cover_vert, gio.Shader_cover_frag,
|
||||||
[3]interface{}{&c.colUniforms.vert, &c.linearGradientUniforms.vert, &c.texUniforms.vert},
|
[3]interface{}{c.colUniforms, c.linearGradientUniforms, c.texUniforms},
|
||||||
[3]interface{}{&c.colUniforms.frag, &c.linearGradientUniforms.frag, nil},
|
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@@ -215,7 +202,7 @@ func newStenciler(ctx driver.Device) *stenciler {
|
|||||||
defer vsh.Release()
|
defer vsh.Release()
|
||||||
defer fsh.Release()
|
defer fsh.Release()
|
||||||
st.pipeline.uniforms = new(stencilUniforms)
|
st.pipeline.uniforms = new(stencilUniforms)
|
||||||
vertUniforms := newUniformBuffer(ctx, &st.pipeline.uniforms.vert)
|
vertUniforms := newUniformBuffer(ctx, st.pipeline.uniforms)
|
||||||
pipe, err := st.ctx.NewPipeline(driver.PipelineDesc{
|
pipe, err := st.ctx.NewPipeline(driver.PipelineDesc{
|
||||||
VertexShader: vsh,
|
VertexShader: vsh,
|
||||||
FragmentShader: fsh,
|
FragmentShader: fsh,
|
||||||
@@ -228,7 +215,7 @@ func newStenciler(ctx driver.Device) *stenciler {
|
|||||||
PixelFormat: driver.TextureFormatFloat,
|
PixelFormat: driver.TextureFormatFloat,
|
||||||
Topology: driver.TopologyTriangles,
|
Topology: driver.TopologyTriangles,
|
||||||
})
|
})
|
||||||
st.pipeline.pipeline = &pipeline{pipe, vertUniforms, nil}
|
st.pipeline.pipeline = &pipeline{pipe, vertUniforms}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@@ -252,7 +239,7 @@ func newStenciler(ctx driver.Device) *stenciler {
|
|||||||
PixelFormat: driver.TextureFormatFloat,
|
PixelFormat: driver.TextureFormatFloat,
|
||||||
Topology: driver.TopologyTriangleStrip,
|
Topology: driver.TopologyTriangleStrip,
|
||||||
})
|
})
|
||||||
st.ipipeline.pipeline = &pipeline{ipipe, vertUniforms, nil}
|
st.ipipeline.pipeline = &pipeline{ipipe, vertUniforms}
|
||||||
return st
|
return st
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -364,8 +351,8 @@ func (s *stenciler) stencilPath(bounds image.Rectangle, offset f32.Point, uv ima
|
|||||||
texSize := f32.Point{X: float32(bounds.Dx()), Y: float32(bounds.Dy())}
|
texSize := f32.Point{X: float32(bounds.Dx()), Y: float32(bounds.Dy())}
|
||||||
scale := f32.Point{X: 2 / texSize.X, Y: 2 / texSize.Y}
|
scale := f32.Point{X: 2 / texSize.X, Y: 2 / texSize.Y}
|
||||||
orig := f32.Point{X: -1 - float32(bounds.Min.X)*2/texSize.X, Y: -1 - float32(bounds.Min.Y)*2/texSize.Y}
|
orig := f32.Point{X: -1 - float32(bounds.Min.X)*2/texSize.X, Y: -1 - float32(bounds.Min.Y)*2/texSize.Y}
|
||||||
s.pipeline.uniforms.vert.transform = [4]float32{scale.X, scale.Y, orig.X, orig.Y}
|
s.pipeline.uniforms.transform = [4]float32{scale.X, scale.Y, orig.X, orig.Y}
|
||||||
s.pipeline.uniforms.vert.pathOffset = [2]float32{offset.X, offset.Y}
|
s.pipeline.uniforms.pathOffset = [2]float32{offset.X, offset.Y}
|
||||||
s.pipeline.pipeline.UploadUniforms(s.ctx)
|
s.pipeline.pipeline.UploadUniforms(s.ctx)
|
||||||
// Draw in batches that fit in uint16 indices.
|
// Draw in batches that fit in uint16 indices.
|
||||||
start := 0
|
start := 0
|
||||||
@@ -390,21 +377,21 @@ func (c *coverer) cover(mat materialType, col f32color.RGBA, col1, col2 f32color
|
|||||||
var uniforms *coverUniforms
|
var uniforms *coverUniforms
|
||||||
switch mat {
|
switch mat {
|
||||||
case materialColor:
|
case materialColor:
|
||||||
c.colUniforms.frag.color = col
|
c.colUniforms.color = col
|
||||||
uniforms = &c.colUniforms.vert.coverUniforms
|
uniforms = &c.colUniforms.coverUniforms
|
||||||
case materialLinearGradient:
|
case materialLinearGradient:
|
||||||
c.linearGradientUniforms.frag.color1 = col1
|
c.linearGradientUniforms.color1 = col1
|
||||||
c.linearGradientUniforms.frag.color2 = col2
|
c.linearGradientUniforms.color2 = col2
|
||||||
|
|
||||||
t1, t2, t3, t4, t5, t6 := uvTrans.Elems()
|
t1, t2, t3, t4, t5, t6 := uvTrans.Elems()
|
||||||
c.linearGradientUniforms.vert.uvTransformR1 = [4]float32{t1, t2, t3, 0}
|
c.linearGradientUniforms.uvTransformR1 = [4]float32{t1, t2, t3, 0}
|
||||||
c.linearGradientUniforms.vert.uvTransformR2 = [4]float32{t4, t5, t6, 0}
|
c.linearGradientUniforms.uvTransformR2 = [4]float32{t4, t5, t6, 0}
|
||||||
uniforms = &c.linearGradientUniforms.vert.coverUniforms
|
uniforms = &c.linearGradientUniforms.coverUniforms
|
||||||
case materialTexture:
|
case materialTexture:
|
||||||
t1, t2, t3, t4, t5, t6 := uvTrans.Elems()
|
t1, t2, t3, t4, t5, t6 := uvTrans.Elems()
|
||||||
c.texUniforms.vert.uvTransformR1 = [4]float32{t1, t2, t3, 0}
|
c.texUniforms.uvTransformR1 = [4]float32{t1, t2, t3, 0}
|
||||||
c.texUniforms.vert.uvTransformR2 = [4]float32{t4, t5, t6, 0}
|
c.texUniforms.uvTransformR2 = [4]float32{t4, t5, t6, 0}
|
||||||
uniforms = &c.texUniforms.vert.coverUniforms
|
uniforms = &c.texUniforms.coverUniforms
|
||||||
}
|
}
|
||||||
uniforms.transform = [4]float32{scale.X, scale.Y, off.X, off.Y}
|
uniforms.transform = [4]float32{scale.X, scale.Y, off.X, off.Y}
|
||||||
uniforms.uvCoverTransform = [4]float32{coverScale.X, coverScale.Y, coverOff.X, coverOff.Y}
|
uniforms.uvCoverTransform = [4]float32{coverScale.X, coverScale.Y, coverOff.X, coverOff.Y}
|
||||||
|
|||||||
Reference in New Issue
Block a user