internal/graphicsdriver: refactoring: replace Uniform with []float32

Closes #2016
This commit is contained in:
Hajime Hoshi 2022-03-13 03:42:10 +09:00
parent 35a5c88901
commit 7d0f95e9be
11 changed files with 84 additions and 173 deletions

View File

@ -398,13 +398,13 @@ func (i *Image) processSrc(src *Image) {
// 5: Color G // 5: Color G
// 6: Color B // 6: Color B
// 7: Color Y // 7: Color Y
func (i *Image) DrawTriangles(srcs [graphics.ShaderImageNum]*Image, vertices []float32, indices []uint16, colorm affine.ColorM, mode graphicsdriver.CompositeMode, filter graphicsdriver.Filter, address graphicsdriver.Address, dstRegion, srcRegion graphicsdriver.Region, subimageOffsets [graphics.ShaderImageNum - 1][2]float32, shader *Shader, uniforms []graphicsdriver.Uniform, evenOdd bool) { func (i *Image) DrawTriangles(srcs [graphics.ShaderImageNum]*Image, vertices []float32, indices []uint16, colorm affine.ColorM, mode graphicsdriver.CompositeMode, filter graphicsdriver.Filter, address graphicsdriver.Address, dstRegion, srcRegion graphicsdriver.Region, subimageOffsets [graphics.ShaderImageNum - 1][2]float32, shader *Shader, uniforms [][]float32, evenOdd bool) {
backendsM.Lock() backendsM.Lock()
defer backendsM.Unlock() defer backendsM.Unlock()
i.drawTriangles(srcs, vertices, indices, colorm, mode, filter, address, dstRegion, srcRegion, subimageOffsets, shader, uniforms, evenOdd, false) i.drawTriangles(srcs, vertices, indices, colorm, mode, filter, address, dstRegion, srcRegion, subimageOffsets, shader, uniforms, evenOdd, false)
} }
func (i *Image) drawTriangles(srcs [graphics.ShaderImageNum]*Image, vertices []float32, indices []uint16, colorm affine.ColorM, mode graphicsdriver.CompositeMode, filter graphicsdriver.Filter, address graphicsdriver.Address, dstRegion, srcRegion graphicsdriver.Region, subimageOffsets [graphics.ShaderImageNum - 1][2]float32, shader *Shader, uniforms []graphicsdriver.Uniform, evenOdd bool, keepOnAtlas bool) { func (i *Image) drawTriangles(srcs [graphics.ShaderImageNum]*Image, vertices []float32, indices []uint16, colorm affine.ColorM, mode graphicsdriver.CompositeMode, filter graphicsdriver.Filter, address graphicsdriver.Address, dstRegion, srcRegion graphicsdriver.Region, subimageOffsets [graphics.ShaderImageNum - 1][2]float32, shader *Shader, uniforms [][]float32, evenOdd bool, keepOnAtlas bool) {
if i.disposed { if i.disposed {
panic("atlas: the drawing target image must not be disposed (DrawTriangles)") panic("atlas: the drawing target image must not be disposed (DrawTriangles)")
} }

View File

@ -214,7 +214,7 @@ func (i *Image) replacePendingPixels(pix []byte, x, y, width, height int) {
// DrawTriangles draws the src image with the given vertices. // DrawTriangles draws the src image with the given vertices.
// //
// Copying vertices and indices is the caller's responsibility. // Copying vertices and indices is the caller's responsibility.
func (i *Image) DrawTriangles(srcs [graphics.ShaderImageNum]*Image, vertices []float32, indices []uint16, colorm affine.ColorM, mode graphicsdriver.CompositeMode, filter graphicsdriver.Filter, address graphicsdriver.Address, dstRegion, srcRegion graphicsdriver.Region, subimageOffsets [graphics.ShaderImageNum - 1][2]float32, shader *Shader, uniforms []graphicsdriver.Uniform, evenOdd bool) { func (i *Image) DrawTriangles(srcs [graphics.ShaderImageNum]*Image, vertices []float32, indices []uint16, colorm affine.ColorM, mode graphicsdriver.CompositeMode, filter graphicsdriver.Filter, address graphicsdriver.Address, dstRegion, srcRegion graphicsdriver.Region, subimageOffsets [graphics.ShaderImageNum - 1][2]float32, shader *Shader, uniforms [][]float32, evenOdd bool) {
for _, src := range srcs { for _, src := range srcs {
if i == src { if i == src {
panic("buffered: Image.DrawTriangles: source images must be different from the receiver") panic("buffered: Image.DrawTriangles: source images must be different from the receiver")

View File

@ -140,7 +140,7 @@ func mustUseDifferentVertexBuffer(nextNumVertexFloats, nextNumIndices int) bool
} }
// EnqueueDrawTrianglesCommand enqueues a drawing-image command. // EnqueueDrawTrianglesCommand enqueues a drawing-image command.
func (q *commandQueue) EnqueueDrawTrianglesCommand(dst *Image, srcs [graphics.ShaderImageNum]*Image, offsets [graphics.ShaderImageNum - 1][2]float32, vertices []float32, indices []uint16, color affine.ColorM, mode graphicsdriver.CompositeMode, filter graphicsdriver.Filter, address graphicsdriver.Address, dstRegion, srcRegion graphicsdriver.Region, shader *Shader, uniforms []graphicsdriver.Uniform, evenOdd bool) { func (q *commandQueue) EnqueueDrawTrianglesCommand(dst *Image, srcs [graphics.ShaderImageNum]*Image, offsets [graphics.ShaderImageNum - 1][2]float32, vertices []float32, indices []uint16, color affine.ColorM, mode graphicsdriver.CompositeMode, filter graphicsdriver.Filter, address graphicsdriver.Address, dstRegion, srcRegion graphicsdriver.Region, shader *Shader, uniforms [][]float32, evenOdd bool) {
if len(indices) > graphics.IndicesNum { if len(indices) > graphics.IndicesNum {
panic(fmt.Sprintf("graphicscommand: len(indices) must be <= graphics.IndicesNum but not at EnqueueDrawTrianglesCommand: len(indices): %d, graphics.IndicesNum: %d", len(indices), graphics.IndicesNum)) panic(fmt.Sprintf("graphicscommand: len(indices) must be <= graphics.IndicesNum but not at EnqueueDrawTrianglesCommand: len(indices): %d, graphics.IndicesNum: %d", len(indices), graphics.IndicesNum))
} }
@ -363,7 +363,7 @@ type drawTrianglesCommand struct {
dstRegion graphicsdriver.Region dstRegion graphicsdriver.Region
srcRegion graphicsdriver.Region srcRegion graphicsdriver.Region
shader *Shader shader *Shader
uniforms []graphicsdriver.Uniform uniforms [][]float32
evenOdd bool evenOdd bool
} }

View File

@ -141,7 +141,7 @@ func (i *Image) InternalSize() (int, int) {
// //
// If the source image is not specified, i.e., src is nil and there is no image in the uniform variables, the // If the source image is not specified, i.e., src is nil and there is no image in the uniform variables, the
// elements for the source image are not used. // elements for the source image are not used.
func (i *Image) DrawTriangles(srcs [graphics.ShaderImageNum]*Image, offsets [graphics.ShaderImageNum - 1][2]float32, vertices []float32, indices []uint16, clr affine.ColorM, mode graphicsdriver.CompositeMode, filter graphicsdriver.Filter, address graphicsdriver.Address, dstRegion, srcRegion graphicsdriver.Region, shader *Shader, uniforms []graphicsdriver.Uniform, evenOdd bool) { func (i *Image) DrawTriangles(srcs [graphics.ShaderImageNum]*Image, offsets [graphics.ShaderImageNum - 1][2]float32, vertices []float32, indices []uint16, clr affine.ColorM, mode graphicsdriver.CompositeMode, filter graphicsdriver.Filter, address graphicsdriver.Address, dstRegion, srcRegion graphicsdriver.Region, shader *Shader, uniforms [][]float32, evenOdd bool) {
if shader == nil { if shader == nil {
// Fast path for rendering without a shader (#1355). // Fast path for rendering without a shader (#1355).
img := srcs[0] img := srcs[0]

View File

@ -39,11 +39,6 @@ type ColorM interface {
Elements(body *[16]float32, translate *[4]float32) Elements(body *[16]float32, translate *[4]float32)
} }
type Uniform struct {
Float32 float32
Float32s []float32
}
type Graphics interface { type Graphics interface {
Begin() Begin()
End(present bool) End(present bool)
@ -70,7 +65,7 @@ type Graphics interface {
// //
// * float32 // * float32
// * []float32 // * []float32
DrawTriangles(dst ImageID, srcs [graphics.ShaderImageNum]ImageID, offsets [graphics.ShaderImageNum - 1][2]float32, shader ShaderID, indexLen int, indexOffset int, mode CompositeMode, colorM ColorM, filter Filter, address Address, dstRegion, srcRegion Region, uniforms []Uniform, evenOdd bool) error DrawTriangles(dst ImageID, srcs [graphics.ShaderImageNum]ImageID, offsets [graphics.ShaderImageNum - 1][2]float32, shader ShaderID, indexLen int, indexOffset int, mode CompositeMode, colorM ColorM, filter Filter, address Address, dstRegion, srcRegion Region, uniforms [][]float32, evenOdd bool) error
} }
// GraphicsNotReady represents that the graphics driver is not ready for recovering from the context lost. // GraphicsNotReady represents that the graphics driver is not ready for recovering from the context lost.

View File

@ -784,7 +784,7 @@ func (g *Graphics) flushRenderCommandEncoderIfNeeded() {
g.lastDst = nil g.lastDst = nil
} }
func (g *Graphics) draw(rps mtl.RenderPipelineState, dst *Image, dstRegion graphicsdriver.Region, srcs [graphics.ShaderImageNum]*Image, indexLen int, indexOffset int, uniforms []graphicsdriver.Uniform, stencilMode stencilMode) error { func (g *Graphics) draw(rps mtl.RenderPipelineState, dst *Image, dstRegion graphicsdriver.Region, srcs [graphics.ShaderImageNum]*Image, indexLen int, indexOffset int, uniforms [][]float32, stencilMode stencilMode) error {
// When prepareing a stencil buffer, flush the current render command encoder // When prepareing a stencil buffer, flush the current render command encoder
// to make sure the stencil buffer is cleared when loading. // to make sure the stencil buffer is cleared when loading.
// TODO: What about clearing the stencil buffer by vertices? // TODO: What about clearing the stencil buffer by vertices?
@ -847,15 +847,8 @@ func (g *Graphics) draw(rps mtl.RenderPipelineState, dst *Image, dstRegion graph
g.rce.SetVertexBuffer(g.vb, 0, 0) g.rce.SetVertexBuffer(g.vb, 0, 0)
for i, u := range uniforms { for i, u := range uniforms {
if len(u.Float32s) == 0 { g.rce.SetVertexBytes(unsafe.Pointer(&u[0]), unsafe.Sizeof(u[0])*uintptr(len(u)), i+1)
v := u.Float32 g.rce.SetFragmentBytes(unsafe.Pointer(&u[0]), unsafe.Sizeof(u[0])*uintptr(len(u)), i+1)
g.rce.SetVertexBytes(unsafe.Pointer(&v), unsafe.Sizeof(v), i+1)
g.rce.SetFragmentBytes(unsafe.Pointer(&v), unsafe.Sizeof(v), i+1)
} else {
v := u.Float32s
g.rce.SetVertexBytes(unsafe.Pointer(&v[0]), unsafe.Sizeof(v[0])*uintptr(len(v)), i+1)
g.rce.SetFragmentBytes(unsafe.Pointer(&v[0]), unsafe.Sizeof(v[0])*uintptr(len(v)), i+1)
}
} }
for i, src := range srcs { for i, src := range srcs {
@ -873,7 +866,7 @@ func (g *Graphics) draw(rps mtl.RenderPipelineState, dst *Image, dstRegion graph
return nil return nil
} }
func (g *Graphics) DrawTriangles(dstID graphicsdriver.ImageID, srcIDs [graphics.ShaderImageNum]graphicsdriver.ImageID, offsets [graphics.ShaderImageNum - 1][2]float32, shaderID graphicsdriver.ShaderID, indexLen int, indexOffset int, mode graphicsdriver.CompositeMode, colorM graphicsdriver.ColorM, filter graphicsdriver.Filter, address graphicsdriver.Address, dstRegion, srcRegion graphicsdriver.Region, uniforms []graphicsdriver.Uniform, evenOdd bool) error { func (g *Graphics) DrawTriangles(dstID graphicsdriver.ImageID, srcIDs [graphics.ShaderImageNum]graphicsdriver.ImageID, offsets [graphics.ShaderImageNum - 1][2]float32, shaderID graphicsdriver.ShaderID, indexLen int, indexOffset int, mode graphicsdriver.CompositeMode, colorM graphicsdriver.ColorM, filter graphicsdriver.Filter, address graphicsdriver.Address, dstRegion, srcRegion graphicsdriver.Region, uniforms [][]float32, evenOdd bool) error {
dst := g.images[dstID] dst := g.images[dstID]
if dst.screen { if dst.screen {
@ -886,7 +879,7 @@ func (g *Graphics) DrawTriangles(dstID graphicsdriver.ImageID, srcIDs [graphics.
} }
rpss := map[stencilMode]mtl.RenderPipelineState{} rpss := map[stencilMode]mtl.RenderPipelineState{}
var uniformVars []graphicsdriver.Uniform var uniformVars [][]float32
if shaderID == graphicsdriver.InvalidShaderID { if shaderID == graphicsdriver.InvalidShaderID {
if dst.screen && filter == graphicsdriver.FilterScreen { if dst.screen && filter == graphicsdriver.FilterScreen {
rpss[noStencil] = g.screenRPS rpss[noStencil] = g.screenRPS
@ -921,30 +914,18 @@ func (g *Graphics) DrawTriangles(dstID graphicsdriver.ImageID, srcIDs [graphics.
if filter == graphicsdriver.FilterScreen { if filter == graphicsdriver.FilterScreen {
scale = float32(dst.width) / float32(srcs[0].width) scale = float32(dst.width) / float32(srcs[0].width)
} }
uniformVars = []graphicsdriver.Uniform{ uniformVars = [][]float32{
{float32(w), float32(h)},
sourceSize,
esBody[:],
esTranslate[:],
{ {
Float32s: []float32{float32(w), float32(h)}, srcRegion.X,
}, srcRegion.Y,
{ srcRegion.X + srcRegion.Width,
Float32s: sourceSize, srcRegion.Y + srcRegion.Height,
},
{
Float32s: esBody[:],
},
{
Float32s: esTranslate[:],
},
{
Float32s: []float32{
srcRegion.X,
srcRegion.Y,
srcRegion.X + srcRegion.Width,
srcRegion.Y + srcRegion.Height,
},
},
{
Float32: scale,
}, },
{scale},
} }
} else { } else {
for _, stencil := range []stencilMode{ for _, stencil := range []stencilMode{
@ -959,13 +940,11 @@ func (g *Graphics) DrawTriangles(dstID graphicsdriver.ImageID, srcIDs [graphics.
} }
} }
uniformVars = make([]graphicsdriver.Uniform, graphics.PreservedUniformVariablesNum+len(uniforms)) uniformVars = make([][]float32, graphics.PreservedUniformVariablesNum+len(uniforms))
// Set the destination texture size. // Set the destination texture size.
dw, dh := dst.internalSize() dw, dh := dst.internalSize()
uniformVars[graphics.TextureDestinationSizeUniformVariableIndex] = graphicsdriver.Uniform{ uniformVars[graphics.TextureDestinationSizeUniformVariableIndex] = []float32{float32(dw), float32(dh)}
Float32s: []float32{float32(dw), float32(dh)},
}
// Set the source texture sizes. // Set the source texture sizes.
usizes := make([]float32, 2*len(srcs)) usizes := make([]float32, 2*len(srcs))
@ -976,21 +955,15 @@ func (g *Graphics) DrawTriangles(dstID graphicsdriver.ImageID, srcIDs [graphics.
usizes[2*i+1] = float32(h) usizes[2*i+1] = float32(h)
} }
} }
uniformVars[graphics.TextureSourceSizesUniformVariableIndex] = graphicsdriver.Uniform{ uniformVars[graphics.TextureSourceSizesUniformVariableIndex] = usizes
Float32s: usizes,
}
// Set the destination region's origin. // Set the destination region's origin.
udorigin := []float32{float32(dstRegion.X) / float32(dw), float32(dstRegion.Y) / float32(dh)} udorigin := []float32{float32(dstRegion.X) / float32(dw), float32(dstRegion.Y) / float32(dh)}
uniformVars[graphics.TextureDestinationRegionOriginUniformVariableIndex] = graphicsdriver.Uniform{ uniformVars[graphics.TextureDestinationRegionOriginUniformVariableIndex] = udorigin
Float32s: udorigin,
}
// Set the destination region's size. // Set the destination region's size.
udsize := []float32{float32(dstRegion.Width) / float32(dw), float32(dstRegion.Height) / float32(dh)} udsize := []float32{float32(dstRegion.Width) / float32(dw), float32(dstRegion.Height) / float32(dh)}
uniformVars[graphics.TextureDestinationRegionSizeUniformVariableIndex] = graphicsdriver.Uniform{ uniformVars[graphics.TextureDestinationRegionSizeUniformVariableIndex] = udsize
Float32s: udsize,
}
// Set the source offsets. // Set the source offsets.
uoffsets := make([]float32, 2*len(offsets)) uoffsets := make([]float32, 2*len(offsets))
@ -998,21 +971,15 @@ func (g *Graphics) DrawTriangles(dstID graphicsdriver.ImageID, srcIDs [graphics.
uoffsets[2*i] = offset[0] uoffsets[2*i] = offset[0]
uoffsets[2*i+1] = offset[1] uoffsets[2*i+1] = offset[1]
} }
uniformVars[graphics.TextureSourceOffsetsUniformVariableIndex] = graphicsdriver.Uniform{ uniformVars[graphics.TextureSourceOffsetsUniformVariableIndex] = uoffsets
Float32s: uoffsets,
}
// Set the source region's origin of texture0. // Set the source region's origin of texture0.
usorigin := []float32{float32(srcRegion.X), float32(srcRegion.Y)} usorigin := []float32{float32(srcRegion.X), float32(srcRegion.Y)}
uniformVars[graphics.TextureSourceRegionOriginUniformVariableIndex] = graphicsdriver.Uniform{ uniformVars[graphics.TextureSourceRegionOriginUniformVariableIndex] = usorigin
Float32s: usorigin,
}
// Set the source region's size of texture0. // Set the source region's size of texture0.
ussize := []float32{float32(srcRegion.Width), float32(srcRegion.Height)} ussize := []float32{float32(srcRegion.Width), float32(srcRegion.Height)}
uniformVars[graphics.TextureSourceRegionSizeUniformVariableIndex] = graphicsdriver.Uniform{ uniformVars[graphics.TextureSourceRegionSizeUniformVariableIndex] = ussize
Float32s: ussize,
}
// Set the additional uniform variables. // Set the additional uniform variables.
for i, v := range uniforms { for i, v := range uniforms {

View File

@ -171,7 +171,7 @@ func (g *Graphics) uniformVariableName(idx int) string {
return name return name
} }
func (g *Graphics) DrawTriangles(dstID graphicsdriver.ImageID, srcIDs [graphics.ShaderImageNum]graphicsdriver.ImageID, offsets [graphics.ShaderImageNum - 1][2]float32, shaderID graphicsdriver.ShaderID, indexLen int, indexOffset int, mode graphicsdriver.CompositeMode, colorM graphicsdriver.ColorM, filter graphicsdriver.Filter, address graphicsdriver.Address, dstRegion, srcRegion graphicsdriver.Region, uniforms []graphicsdriver.Uniform, evenOdd bool) error { func (g *Graphics) DrawTriangles(dstID graphicsdriver.ImageID, srcIDs [graphics.ShaderImageNum]graphicsdriver.ImageID, offsets [graphics.ShaderImageNum - 1][2]float32, shaderID graphicsdriver.ShaderID, indexLen int, indexOffset int, mode graphicsdriver.CompositeMode, colorM graphicsdriver.ColorM, filter graphicsdriver.Filter, address graphicsdriver.Address, dstRegion, srcRegion graphicsdriver.Region, uniforms [][]float32, evenOdd bool) error {
destination := g.images[dstID] destination := g.images[dstID]
g.drawCalled = true g.drawCalled = true
@ -197,20 +197,16 @@ func (g *Graphics) DrawTriangles(dstID graphicsdriver.ImageID, srcIDs [graphics.
dw, dh := destination.framebufferSize() dw, dh := destination.framebufferSize()
g.uniformVars = append(g.uniformVars, uniformVariable{ g.uniformVars = append(g.uniformVars, uniformVariable{
name: "viewport_size", name: "viewport_size",
value: graphicsdriver.Uniform{ value: []float32{float32(dw), float32(dh)},
Float32s: []float32{float32(dw), float32(dh)}, typ: shaderir.Type{Main: shaderir.Vec2},
},
typ: shaderir.Type{Main: shaderir.Vec2},
}, uniformVariable{ }, uniformVariable{
name: "source_region", name: "source_region",
value: graphicsdriver.Uniform{ value: []float32{
Float32s: []float32{ srcRegion.X,
srcRegion.X, srcRegion.Y,
srcRegion.Y, srcRegion.X + srcRegion.Width,
srcRegion.X + srcRegion.Width, srcRegion.Y + srcRegion.Height,
srcRegion.Y + srcRegion.Height,
},
}, },
typ: shaderir.Type{Main: shaderir.Vec4}, typ: shaderir.Type{Main: shaderir.Vec4},
}) })
@ -221,39 +217,31 @@ func (g *Graphics) DrawTriangles(dstID graphicsdriver.ImageID, srcIDs [graphics.
var esTranslate [4]float32 var esTranslate [4]float32
colorM.Elements(&esBody, &esTranslate) colorM.Elements(&esBody, &esTranslate)
g.uniformVars = append(g.uniformVars, uniformVariable{ g.uniformVars = append(g.uniformVars, uniformVariable{
name: "color_matrix_body", name: "color_matrix_body",
value: graphicsdriver.Uniform{ value: esBody[:],
Float32s: esBody[:], typ: shaderir.Type{Main: shaderir.Mat4},
},
typ: shaderir.Type{Main: shaderir.Mat4},
}, uniformVariable{ }, uniformVariable{
name: "color_matrix_translation", name: "color_matrix_translation",
value: graphicsdriver.Uniform{ value: esTranslate[:],
Float32s: esTranslate[:], typ: shaderir.Type{Main: shaderir.Vec4},
},
typ: shaderir.Type{Main: shaderir.Vec4},
}) })
} }
if filter != graphicsdriver.FilterNearest { if filter != graphicsdriver.FilterNearest {
sw, sh := g.images[srcIDs[0]].framebufferSize() sw, sh := g.images[srcIDs[0]].framebufferSize()
g.uniformVars = append(g.uniformVars, uniformVariable{ g.uniformVars = append(g.uniformVars, uniformVariable{
name: "source_size", name: "source_size",
value: graphicsdriver.Uniform{ value: []float32{float32(sw), float32(sh)},
Float32s: []float32{float32(sw), float32(sh)}, typ: shaderir.Type{Main: shaderir.Vec2},
},
typ: shaderir.Type{Main: shaderir.Vec2},
}) })
} }
if filter == graphicsdriver.FilterScreen { if filter == graphicsdriver.FilterScreen {
scale := float32(destination.width) / float32(g.images[srcIDs[0]].width) scale := float32(destination.width) / float32(g.images[srcIDs[0]].width)
g.uniformVars = append(g.uniformVars, uniformVariable{ g.uniformVars = append(g.uniformVars, uniformVariable{
name: "scale", name: "scale",
value: graphicsdriver.Uniform{ value: []float32{scale},
Float32: scale, typ: shaderir.Type{Main: shaderir.Float},
},
typ: shaderir.Type{Main: shaderir.Float},
}) })
} }
} else { } else {
@ -271,7 +259,7 @@ func (g *Graphics) DrawTriangles(dstID graphicsdriver.ImageID, srcIDs [graphics.
const idx = graphics.TextureDestinationSizeUniformVariableIndex const idx = graphics.TextureDestinationSizeUniformVariableIndex
w, h := destination.framebufferSize() w, h := destination.framebufferSize()
g.uniformVars[idx].name = g.uniformVariableName(idx) g.uniformVars[idx].name = g.uniformVariableName(idx)
g.uniformVars[idx].value.Float32s = []float32{float32(w), float32(h)} g.uniformVars[idx].value = []float32{float32(w), float32(h)}
g.uniformVars[idx].typ = shader.ir.Uniforms[idx] g.uniformVars[idx].typ = shader.ir.Uniforms[idx]
} }
{ {
@ -286,7 +274,7 @@ func (g *Graphics) DrawTriangles(dstID graphicsdriver.ImageID, srcIDs [graphics.
} }
const idx = graphics.TextureSourceSizesUniformVariableIndex const idx = graphics.TextureSourceSizesUniformVariableIndex
g.uniformVars[idx].name = g.uniformVariableName(idx) g.uniformVars[idx].name = g.uniformVariableName(idx)
g.uniformVars[idx].value.Float32s = sizes g.uniformVars[idx].value = sizes
g.uniformVars[idx].typ = shader.ir.Uniforms[idx] g.uniformVars[idx].typ = shader.ir.Uniforms[idx]
} }
dw, dh := destination.framebufferSize() dw, dh := destination.framebufferSize()
@ -294,14 +282,14 @@ func (g *Graphics) DrawTriangles(dstID graphicsdriver.ImageID, srcIDs [graphics.
origin := []float32{float32(dstRegion.X) / float32(dw), float32(dstRegion.Y) / float32(dh)} origin := []float32{float32(dstRegion.X) / float32(dw), float32(dstRegion.Y) / float32(dh)}
const idx = graphics.TextureDestinationRegionOriginUniformVariableIndex const idx = graphics.TextureDestinationRegionOriginUniformVariableIndex
g.uniformVars[idx].name = g.uniformVariableName(idx) g.uniformVars[idx].name = g.uniformVariableName(idx)
g.uniformVars[idx].value.Float32s = origin g.uniformVars[idx].value = origin
g.uniformVars[idx].typ = shader.ir.Uniforms[idx] g.uniformVars[idx].typ = shader.ir.Uniforms[idx]
} }
{ {
size := []float32{float32(dstRegion.Width) / float32(dw), float32(dstRegion.Height) / float32(dh)} size := []float32{float32(dstRegion.Width) / float32(dw), float32(dstRegion.Height) / float32(dh)}
const idx = graphics.TextureDestinationRegionSizeUniformVariableIndex const idx = graphics.TextureDestinationRegionSizeUniformVariableIndex
g.uniformVars[idx].name = g.uniformVariableName(idx) g.uniformVars[idx].name = g.uniformVariableName(idx)
g.uniformVars[idx].value.Float32s = size g.uniformVars[idx].value = size
g.uniformVars[idx].typ = shader.ir.Uniforms[idx] g.uniformVars[idx].typ = shader.ir.Uniforms[idx]
} }
{ {
@ -312,21 +300,21 @@ func (g *Graphics) DrawTriangles(dstID graphicsdriver.ImageID, srcIDs [graphics.
} }
const idx = graphics.TextureSourceOffsetsUniformVariableIndex const idx = graphics.TextureSourceOffsetsUniformVariableIndex
g.uniformVars[idx].name = g.uniformVariableName(idx) g.uniformVars[idx].name = g.uniformVariableName(idx)
g.uniformVars[idx].value.Float32s = voffsets g.uniformVars[idx].value = voffsets
g.uniformVars[idx].typ = shader.ir.Uniforms[idx] g.uniformVars[idx].typ = shader.ir.Uniforms[idx]
} }
{ {
origin := []float32{float32(srcRegion.X), float32(srcRegion.Y)} origin := []float32{float32(srcRegion.X), float32(srcRegion.Y)}
const idx = graphics.TextureSourceRegionOriginUniformVariableIndex const idx = graphics.TextureSourceRegionOriginUniformVariableIndex
g.uniformVars[idx].name = g.uniformVariableName(idx) g.uniformVars[idx].name = g.uniformVariableName(idx)
g.uniformVars[idx].value.Float32s = origin g.uniformVars[idx].value = origin
g.uniformVars[idx].typ = shader.ir.Uniforms[idx] g.uniformVars[idx].typ = shader.ir.Uniforms[idx]
} }
{ {
size := []float32{float32(srcRegion.Width), float32(srcRegion.Height)} size := []float32{float32(srcRegion.Width), float32(srcRegion.Height)}
const idx = graphics.TextureSourceRegionSizeUniformVariableIndex const idx = graphics.TextureSourceRegionSizeUniformVariableIndex
g.uniformVars[idx].name = g.uniformVariableName(idx) g.uniformVars[idx].name = g.uniformVariableName(idx)
g.uniformVars[idx].value.Float32s = size g.uniformVars[idx].value = size
g.uniformVars[idx].typ = shader.ir.Uniforms[idx] g.uniformVars[idx].typ = shader.ir.Uniforms[idx]
} }

View File

@ -132,7 +132,7 @@ type openGLState struct {
programs map[programKey]program programs map[programKey]program
lastProgram program lastProgram program
lastUniforms map[string]graphicsdriver.Uniform lastUniforms map[string][]float32
lastActiveTexture int lastActiveTexture int
} }
@ -242,7 +242,7 @@ func areSameFloat32Array(a, b []float32) bool {
type uniformVariable struct { type uniformVariable struct {
name string name string
value graphicsdriver.Uniform value []float32
typ shaderir.Type typ shaderir.Type
} }
@ -282,41 +282,22 @@ func (g *Graphics) useProgram(program program, uniforms []uniformVariable, textu
} }
for _, u := range uniforms { for _, u := range uniforms {
if len(u.value.Float32s) == 0 { if got, expected := len(u.value), u.typ.FloatNum(); got != expected {
if u.typ.Main != shaderir.Float { // Copy a shaderir.Type value once. Do not pass u.typ directly to fmt.Errorf arguments, or
expected := &shaderir.Type{Main: shaderir.Float} // the value u would be allocated on heap.
got := u.typ typ := u.typ
return fmt.Errorf("opengl: uniform variable %s type doesn't match: expected %s but %s", u.name, expected.String(), got.String()) return fmt.Errorf("opengl: length of a uniform variables %s (%s) doesn't match: expected %d but %d", u.name, typ.String(), expected, got)
}
cached, ok := g.state.lastUniforms[u.name]
if ok && cached.Float32 == u.value.Float32 {
continue
}
// TODO: Remember whether the location is available or not.
g.context.uniformFloat(program, u.name, u.value.Float32)
if g.state.lastUniforms == nil {
g.state.lastUniforms = map[string]graphicsdriver.Uniform{}
}
g.state.lastUniforms[u.name] = u.value
} else {
if got, expected := len(u.value.Float32s), u.typ.FloatNum(); got != expected {
// Copy a shaderir.Type value once. Do not pass u.typ directly to fmt.Errorf arguments, or
// the value u would be allocated on heap.
typ := u.typ
return fmt.Errorf("opengl: length of a uniform variables %s (%s) doesn't match: expected %d but %d", u.name, typ.String(), expected, got)
}
cached, ok := g.state.lastUniforms[u.name]
if ok && areSameFloat32Array(cached.Float32s, u.value.Float32s) {
continue
}
g.context.uniformFloats(program, u.name, u.value.Float32s, u.typ)
if g.state.lastUniforms == nil {
g.state.lastUniforms = map[string]graphicsdriver.Uniform{}
}
g.state.lastUniforms[u.name] = u.value
} }
cached, ok := g.state.lastUniforms[u.name]
if ok && areSameFloat32Array(cached, u.value) {
continue
}
g.context.uniformFloats(program, u.name, u.value, u.typ)
if g.state.lastUniforms == nil {
g.state.lastUniforms = map[string][]float32{}
}
g.state.lastUniforms[u.name] = u.value
} }
var idx int var idx int

View File

@ -91,7 +91,7 @@ func (m *Mipmap) Pixels(x, y, width, height int) ([]byte, error) {
return m.orig.Pixels(x, y, width, height) return m.orig.Pixels(x, y, width, height)
} }
func (m *Mipmap) DrawTriangles(srcs [graphics.ShaderImageNum]*Mipmap, vertices []float32, indices []uint16, colorm affine.ColorM, mode graphicsdriver.CompositeMode, filter graphicsdriver.Filter, address graphicsdriver.Address, dstRegion, srcRegion graphicsdriver.Region, subimageOffsets [graphics.ShaderImageNum - 1][2]float32, shader *Shader, uniforms []graphicsdriver.Uniform, evenOdd bool, canSkipMipmap bool) { func (m *Mipmap) DrawTriangles(srcs [graphics.ShaderImageNum]*Mipmap, vertices []float32, indices []uint16, colorm affine.ColorM, mode graphicsdriver.CompositeMode, filter graphicsdriver.Filter, address graphicsdriver.Address, dstRegion, srcRegion graphicsdriver.Region, subimageOffsets [graphics.ShaderImageNum - 1][2]float32, shader *Shader, uniforms [][]float32, evenOdd bool, canSkipMipmap bool) {
if len(indices) == 0 { if len(indices) == 0 {
return return
} }

View File

@ -76,7 +76,7 @@ type drawTrianglesHistoryItem struct {
dstRegion graphicsdriver.Region dstRegion graphicsdriver.Region
srcRegion graphicsdriver.Region srcRegion graphicsdriver.Region
shader *Shader shader *Shader
uniforms []graphicsdriver.Uniform uniforms [][]float32
evenOdd bool evenOdd bool
} }
@ -365,7 +365,7 @@ func (i *Image) ReplacePixels(pixels []byte, x, y, width, height int) {
// 5: Color G // 5: Color G
// 6: Color B // 6: Color B
// 7: Color Y // 7: Color Y
func (i *Image) DrawTriangles(srcs [graphics.ShaderImageNum]*Image, offsets [graphics.ShaderImageNum - 1][2]float32, vertices []float32, indices []uint16, colorm affine.ColorM, mode graphicsdriver.CompositeMode, filter graphicsdriver.Filter, address graphicsdriver.Address, dstRegion, srcRegion graphicsdriver.Region, shader *Shader, uniforms []graphicsdriver.Uniform, evenOdd bool) { func (i *Image) DrawTriangles(srcs [graphics.ShaderImageNum]*Image, offsets [graphics.ShaderImageNum - 1][2]float32, vertices []float32, indices []uint16, colorm affine.ColorM, mode graphicsdriver.CompositeMode, filter graphicsdriver.Filter, address graphicsdriver.Address, dstRegion, srcRegion graphicsdriver.Region, shader *Shader, uniforms [][]float32, evenOdd bool) {
if i.priority { if i.priority {
panic("restorable: DrawTriangles cannot be called on a priority image") panic("restorable: DrawTriangles cannot be called on a priority image")
} }
@ -410,7 +410,7 @@ func (i *Image) DrawTriangles(srcs [graphics.ShaderImageNum]*Image, offsets [gra
} }
// appendDrawTrianglesHistory appends a draw-image history item to the image. // appendDrawTrianglesHistory appends a draw-image history item to the image.
func (i *Image) appendDrawTrianglesHistory(srcs [graphics.ShaderImageNum]*Image, offsets [graphics.ShaderImageNum - 1][2]float32, vertices []float32, indices []uint16, colorm affine.ColorM, mode graphicsdriver.CompositeMode, filter graphicsdriver.Filter, address graphicsdriver.Address, dstRegion, srcRegion graphicsdriver.Region, shader *Shader, uniforms []graphicsdriver.Uniform, evenOdd bool) { func (i *Image) appendDrawTrianglesHistory(srcs [graphics.ShaderImageNum]*Image, offsets [graphics.ShaderImageNum - 1][2]float32, vertices []float32, indices []uint16, colorm affine.ColorM, mode graphicsdriver.CompositeMode, filter graphicsdriver.Filter, address graphicsdriver.Address, dstRegion, srcRegion graphicsdriver.Region, shader *Shader, uniforms [][]float32, evenOdd bool) {
if i.stale || i.volatile || i.screen { if i.stale || i.volatile || i.screen {
return return
} }

View File

@ -23,7 +23,6 @@ import (
"github.com/hajimehoshi/ebiten/v2/internal/graphics" "github.com/hajimehoshi/ebiten/v2/internal/graphics"
"github.com/hajimehoshi/ebiten/v2/internal/graphicscommand" "github.com/hajimehoshi/ebiten/v2/internal/graphicscommand"
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver"
"github.com/hajimehoshi/ebiten/v2/internal/mipmap" "github.com/hajimehoshi/ebiten/v2/internal/mipmap"
"github.com/hajimehoshi/ebiten/v2/internal/shader" "github.com/hajimehoshi/ebiten/v2/internal/shader"
"github.com/hajimehoshi/ebiten/v2/internal/shaderir" "github.com/hajimehoshi/ebiten/v2/internal/shaderir"
@ -186,7 +185,7 @@ func (s *Shader) Dispose() {
s.shader = nil s.shader = nil
} }
func (s *Shader) convertUniforms(uniforms map[string]interface{}) []graphicsdriver.Uniform { func (s *Shader) convertUniforms(uniforms map[string]interface{}) [][]float32 {
type index struct { type index struct {
resultIndex int resultIndex int
shaderUniformIndex int shaderUniformIndex int
@ -205,18 +204,14 @@ func (s *Shader) convertUniforms(uniforms map[string]interface{}) []graphicsdriv
idx++ idx++
} }
us := make([]graphicsdriver.Uniform, len(names)) us := make([][]float32, len(names))
for name, idx := range names { for name, idx := range names {
if v, ok := uniforms[name]; ok { if v, ok := uniforms[name]; ok {
switch v := v.(type) { switch v := v.(type) {
case float32: case float32:
us[idx.resultIndex] = graphicsdriver.Uniform{ us[idx.resultIndex] = []float32{v}
Float32: v,
}
case []float32: case []float32:
us[idx.resultIndex] = graphicsdriver.Uniform{ us[idx.resultIndex] = v
Float32s: v,
}
default: default:
panic(fmt.Sprintf("ebiten: unexpected uniform value type: %s, %T", name, v)) panic(fmt.Sprintf("ebiten: unexpected uniform value type: %s, %T", name, v))
} }
@ -224,25 +219,10 @@ func (s *Shader) convertUniforms(uniforms map[string]interface{}) []graphicsdriv
} }
t := s.uniformTypes[idx.shaderUniformIndex] t := s.uniformTypes[idx.shaderUniformIndex]
us[idx.resultIndex] = zeroUniformValue(name, t) us[idx.resultIndex] = make([]float32, t.FloatNum())
} }
// TODO: Panic if uniforms include an invalid name // TODO: Panic if uniforms include an invalid name
return us return us
} }
func zeroUniformValue(name string, t shaderir.Type) graphicsdriver.Uniform {
switch t.Main {
case shaderir.Float:
return graphicsdriver.Uniform{
Float32: 0,
}
case shaderir.Array, shaderir.Vec2, shaderir.Vec3, shaderir.Vec4, shaderir.Mat2, shaderir.Mat3, shaderir.Mat4:
return graphicsdriver.Uniform{
Float32s: make([]float32, t.FloatNum()),
}
default:
panic(fmt.Sprintf("ebiten: unexpected uniform variable type: %s, %s", name, t.String()))
}
}