updated ebiten version from 2.7.9 to 2.9.9

This commit is contained in:
2026-06-15 19:06:55 +02:00
parent 21edbc41c4
commit db1b625069
405 changed files with 31913 additions and 12595 deletions
+87 -37
View File
@@ -18,6 +18,7 @@ import (
"fmt"
"image"
"math"
"slices"
"strings"
"github.com/hajimehoshi/ebiten/v2/internal/graphics"
@@ -61,32 +62,62 @@ func (p *drawTrianglesCommandPool) put(v *drawTrianglesCommand) {
// drawTrianglesCommand represents a drawing command to draw an image on another image.
type drawTrianglesCommand struct {
dst *Image
srcs [graphics.ShaderImageCount]*Image
vertices []float32
blend graphicsdriver.Blend
dstRegions []graphicsdriver.DstRegion
shader *Shader
uniforms []uint32
fillRule graphicsdriver.FillRule
dst *Image
srcs [graphics.ShaderSrcImageCount]*Image
vertices []float32
blend graphicsdriver.Blend
dstRegions []graphicsdriver.DstRegion
shader *Shader
uniforms []uint32
fillRule graphicsdriver.FillRule
firstCaller string
}
func (c *drawTrianglesCommand) String() string {
// TODO: Improve readability
blend := fmt.Sprintf("{src-color: %d, src-alpha: %d, dst-color: %d, dst-alpha: %d, op-color: %d, op-alpha: %d}",
c.blend.BlendFactorSourceRGB,
c.blend.BlendFactorSourceAlpha,
c.blend.BlendFactorDestinationRGB,
c.blend.BlendFactorDestinationAlpha,
c.blend.BlendOperationRGB,
c.blend.BlendOperationAlpha)
var blend string
switch c.blend {
case graphicsdriver.BlendSourceOver:
blend = "(source-over)"
case graphicsdriver.BlendClear:
blend = "(clear)"
case graphicsdriver.BlendCopy:
blend = "(copy)"
case graphicsdriver.BlendDestination:
blend = "(destination)"
case graphicsdriver.BlendSourceIn:
blend = "(source-in)"
case graphicsdriver.BlendDestinationIn:
blend = "(destination-in)"
case graphicsdriver.BlendSourceOut:
blend = "(source-out)"
case graphicsdriver.BlendDestinationOut:
blend = "(destination-out)"
case graphicsdriver.BlendSourceAtop:
blend = "(source-atop)"
case graphicsdriver.BlendDestinationAtop:
blend = "(destination-atop)"
case graphicsdriver.BlendXor:
blend = "(xor)"
case graphicsdriver.BlendLighter:
blend = "(lighter)"
default:
blend = fmt.Sprintf("{src-rgb: %d, src-alpha: %d, dst-rgb: %d, dst-alpha: %d, op-rgb: %d, op-alpha: %d}",
c.blend.BlendFactorSourceRGB,
c.blend.BlendFactorSourceAlpha,
c.blend.BlendFactorDestinationRGB,
c.blend.BlendFactorDestinationAlpha,
c.blend.BlendOperationRGB,
c.blend.BlendOperationAlpha)
}
dst := fmt.Sprintf("%d", c.dst.id)
if c.dst.screen {
dst += " (screen)"
} else if c.dst.attribute != "" {
dst += " (" + c.dst.attribute + ")"
}
var srcstrs [graphics.ShaderImageCount]string
var srcstrs [graphics.ShaderSrcImageCount]string
for i, src := range c.srcs {
if src == nil {
srcstrs[i] = "(nil)"
@@ -95,10 +126,21 @@ func (c *drawTrianglesCommand) String() string {
srcstrs[i] = fmt.Sprintf("%d", src.id)
if src.screen {
srcstrs[i] += " (screen)"
} else if src.attribute != "" {
srcstrs[i] += " (" + src.attribute + ")"
}
}
return fmt.Sprintf("draw-triangles: dst: %s <- src: [%s], num of dst regions: %d, num of indices: %d, blend: %s, fill rule: %s, shader id: %d", dst, strings.Join(srcstrs[:], ", "), len(c.dstRegions), c.numIndices(), blend, c.fillRule, c.shader.id)
shader := fmt.Sprintf("%d", c.shader.id)
if c.shader.name != "" {
shader += " (" + c.shader.name + ")"
}
str := fmt.Sprintf("draw-triangles: dst: %s <- src: [%s], num of dst regions: %d, num of indices: %d, blend: %s, fill rule: %s, shader: %s", dst, strings.Join(srcstrs[:], ", "), len(c.dstRegions), c.numIndices(), blend, c.fillRule, shader)
if c.firstCaller != "" {
str += "\n first-caller: " + c.firstCaller
}
return str
}
// Exec executes the drawTrianglesCommand.
@@ -108,7 +150,7 @@ func (c *drawTrianglesCommand) Exec(commandQueue *commandQueue, graphicsDriver g
return nil
}
var imgs [graphics.ShaderImageCount]graphicsdriver.ImageID
var imgs [graphics.ShaderSrcImageCount]graphicsdriver.ImageID
for i, src := range c.srcs {
if src == nil {
imgs[i] = graphicsdriver.InvalidImageID
@@ -142,18 +184,13 @@ func (c *drawTrianglesCommand) setVertices(vertices []float32) {
// CanMergeWithDrawTrianglesCommand returns a boolean value indicating whether the other drawTrianglesCommand can be merged
// with the drawTrianglesCommand c.
func (c *drawTrianglesCommand) CanMergeWithDrawTrianglesCommand(dst *Image, srcs [graphics.ShaderImageCount]*Image, vertices []float32, blend graphicsdriver.Blend, shader *Shader, uniforms []uint32, fillRule graphicsdriver.FillRule) bool {
func (c *drawTrianglesCommand) CanMergeWithDrawTrianglesCommand(dst *Image, srcs [graphics.ShaderSrcImageCount]*Image, vertices []float32, blend graphicsdriver.Blend, shader *Shader, uniforms []uint32, fillRule graphicsdriver.FillRule) bool {
if c.shader != shader {
return false
}
if len(c.uniforms) != len(uniforms) {
if !slices.Equal(c.uniforms, uniforms) {
return false
}
for i := range c.uniforms {
if c.uniforms[i] != uniforms[i] {
return false
}
}
if c.dst != dst {
return false
}
@@ -166,7 +203,7 @@ func (c *drawTrianglesCommand) CanMergeWithDrawTrianglesCommand(dst *Image, srcs
if c.fillRule != fillRule {
return false
}
if c.fillRule != graphicsdriver.FillAll && mightOverlapDstRegions(c.vertices, vertices) {
if c.fillRule != graphicsdriver.FillRuleFillAll && mightOverlapDstRegions(c.vertices, vertices) {
return false
}
return true
@@ -183,9 +220,9 @@ func dstRegionFromVertices(vertices []float32) (minX, minY, maxX, maxY float32)
maxX = negInf32
maxY = negInf32
for i := 0; i < len(vertices)/graphics.VertexFloatCount; i++ {
x := vertices[graphics.VertexFloatCount*i]
y := vertices[graphics.VertexFloatCount*i+1]
for i := 0; i < len(vertices); i += graphics.VertexFloatCount {
x := vertices[i]
y := vertices[i+1]
if x < minX {
minX = x
}
@@ -221,7 +258,11 @@ type writePixelsCommandArgs struct {
}
func (c *writePixelsCommand) String() string {
return fmt.Sprintf("write-pixels: dst: %d, len(args): %d", c.dst.id, len(c.args))
var args []string
for _, a := range c.args {
args = append(args, fmt.Sprintf("region: %s", a.region.String()))
}
return fmt.Sprintf("write-pixels: dst: %d, args: %s", c.dst.id, strings.Join(args, ", "))
}
// Exec executes the writePixelsCommand.
@@ -270,7 +311,11 @@ func (c *readPixelsCommand) NeedsSync() bool {
}
func (c *readPixelsCommand) String() string {
return fmt.Sprintf("read-pixels: image: %d", c.img.id)
var args []string
for _, a := range c.args {
args = append(args, fmt.Sprintf("region: %s", a.Region.String()))
}
return fmt.Sprintf("read-pixels: image: %d, args: %v", c.img.id, strings.Join(args, ", "))
}
// disposeImageCommand represents a command to dispose an image.
@@ -313,14 +358,19 @@ func (c *disposeShaderCommand) NeedsSync() bool {
// newImageCommand represents a command to create an empty image with given width and height.
type newImageCommand struct {
result *Image
width int
height int
screen bool
result *Image
width int
height int
screen bool
attribute string
}
func (c *newImageCommand) String() string {
return fmt.Sprintf("new-image: result: %d, width: %d, height: %d, screen: %t", c.result.id, c.width, c.height, c.screen)
str := fmt.Sprintf("new-image: result: %d, width: %d, height: %d, screen: %t", c.result.id, c.width, c.height, c.screen)
if c.attribute != "" {
str += ", attribute: " + c.attribute
}
return str
}
// Exec executes a newImageCommand.
@@ -18,6 +18,7 @@ import (
"fmt"
"image"
"math"
"strings"
"sync"
"sync/atomic"
@@ -43,14 +44,14 @@ const (
maxVertexFloatCount = MaxVertexCount * graphics.VertexFloatCount
)
var vsyncEnabled int32 = 1
var vsyncEnabled atomic.Bool
func init() {
vsyncEnabled.Store(true)
}
func SetVsyncEnabled(enabled bool, graphicsDriver graphicsdriver.Graphics) {
if enabled {
atomic.StoreInt32(&vsyncEnabled, 1)
} else {
atomic.StoreInt32(&vsyncEnabled, 0)
}
vsyncEnabled.Store(enabled)
runOnRenderThread(func() {
graphicsDriver.SetVsyncEnabled(enabled)
@@ -105,7 +106,7 @@ func mustUseDifferentVertexBuffer(nextNumVertexFloats int) bool {
}
// EnqueueDrawTrianglesCommand enqueues a drawing-image command.
func (q *commandQueue) EnqueueDrawTrianglesCommand(dst *Image, srcs [graphics.ShaderImageCount]*Image, vertices []float32, indices []uint32, blend graphicsdriver.Blend, dstRegion image.Rectangle, srcRegions [graphics.ShaderImageCount]image.Rectangle, shader *Shader, uniforms []uint32, fillRule graphicsdriver.FillRule) {
func (q *commandQueue) EnqueueDrawTrianglesCommand(dst *Image, srcs [graphics.ShaderSrcImageCount]*Image, vertices []float32, indices []uint32, blend graphicsdriver.Blend, dstRegion image.Rectangle, srcRegions [graphics.ShaderSrcImageCount]image.Rectangle, shader *Shader, uniforms []uint32, fillRule graphicsdriver.FillRule) {
if len(vertices) > maxVertexFloatCount {
panic(fmt.Sprintf("graphicscommand: len(vertices) must equal to or less than %d but was %d", maxVertexFloatCount, len(vertices)))
}
@@ -162,6 +163,16 @@ func (q *commandQueue) EnqueueDrawTrianglesCommand(dst *Image, srcs [graphics.Sh
c.shader = shader
c.uniforms = uniforms
c.fillRule = fillRule
c.firstCaller = ""
if debug.IsDebug {
file, line, typ := debug.FirstCaller()
switch typ {
case debug.CallerTypeRegular:
c.firstCaller = fmt.Sprintf("%s:%d", file, line)
case debug.CallerTypeInternal:
c.firstCaller = fmt.Sprintf("%s:%d (internal)", file, line)
}
}
q.commands = append(q.commands, c)
}
@@ -185,7 +196,7 @@ func (q *commandQueue) Flush(graphicsDriver graphicsdriver.Graphics, endFrame bo
var sync bool
// Disable asynchronous rendering when vsync is on, as this causes a rendering delay (#2822).
if endFrame && atomic.LoadInt32(&vsyncEnabled) != 0 {
if endFrame && vsyncEnabled.Load() {
sync = true
}
if !sync {
@@ -197,7 +208,7 @@ func (q *commandQueue) Flush(graphicsDriver graphicsdriver.Graphics, endFrame bo
}
}
logger := debug.SwitchLogger()
logger := debug.SwitchFrameLogger()
var flushErr error
runOnRenderThread(func() {
@@ -223,7 +234,7 @@ func (q *commandQueue) Flush(graphicsDriver graphicsdriver.Graphics, endFrame bo
}
// flush must be called the render thread.
func (q *commandQueue) flush(graphicsDriver graphicsdriver.Graphics, endFrame bool, logger debug.Logger) (err error) {
func (q *commandQueue) flush(graphicsDriver graphicsdriver.Graphics, endFrame bool, logger debug.FrameLogger) (err error) {
// If endFrame is true, Begin/End should be called to ensure the framebuffer is swapped.
if len(q.commands) == 0 && !endFrame {
return nil
@@ -231,7 +242,7 @@ func (q *commandQueue) flush(graphicsDriver graphicsdriver.Graphics, endFrame bo
es := q.indices
vs := q.vertices
logger.Logf("Graphics commands:\n")
logger.FrameLogf("Graphics commands:\n")
if err := graphicsDriver.Begin(); err != nil {
return err
@@ -294,7 +305,17 @@ func (q *commandQueue) flush(graphicsDriver graphicsdriver.Graphics, endFrame bo
if err := c.Exec(q, graphicsDriver, indexOffset); err != nil {
return err
}
logger.Logf(" %s\n", c)
if debug.IsDebug {
str := c.String()
for {
head, tail, ok := strings.Cut(str, "\n")
logger.FrameLogf(" %s\n", head)
if !ok {
break
}
str = tail
}
}
// TODO: indexOffset should be reset if the command type is different
// from the previous one. This fix is needed when another drawing command is
// introduced than drawTrianglesCommand.
@@ -324,29 +345,54 @@ func imageRectangleToRectangleF32(r image.Rectangle) rectangleF32 {
}
}
func (q *commandQueue) prependPreservedUniforms(uniforms []uint32, shader *Shader, dst *Image, srcs [graphics.ShaderImageCount]*Image, dstRegion image.Rectangle, srcRegions [graphics.ShaderImageCount]image.Rectangle) []uint32 {
func (q *commandQueue) prependPreservedUniforms(uniforms []uint32, shader *Shader, dst *Image, srcs [graphics.ShaderSrcImageCount]*Image, dstRegion image.Rectangle, srcRegions [graphics.ShaderSrcImageCount]image.Rectangle) []uint32 {
origUniforms := uniforms
uniforms = q.uint32sBuffer.alloc(len(origUniforms) + graphics.PreservedUniformUint32Count)
copy(uniforms[graphics.PreservedUniformUint32Count:], origUniforms)
uniforms = q.uint32sBuffer.alloc(len(origUniforms) + graphics.PreservedUniformDwordCount)
copy(uniforms[graphics.PreservedUniformDwordCount:], origUniforms)
return prependPreservedUniforms(uniforms, shader, dst, srcs, dstRegion, srcRegions)
}
func prependPreservedUniforms(uniforms []uint32, shader *Shader, dst *Image, srcs [graphics.ShaderSrcImageCount]*Image, dstRegion image.Rectangle, srcRegions [graphics.ShaderSrcImageCount]image.Rectangle) []uint32 {
// Set the destination texture size.
// Hard-code indices for BCE optimization.
_ = uniforms[graphics.PreservedUniformDwordCount-1]
dw, dh := dst.InternalSize()
uniforms[0] = math.Float32bits(float32(dw))
uniforms[1] = math.Float32bits(float32(dh))
uniformIndex := 2
for i := 0; i < graphics.ShaderImageCount; i++ {
var floatW, floatH uint32
if srcs[i] != nil {
w, h := srcs[i].InternalSize()
floatW = math.Float32bits(float32(w))
floatH = math.Float32bits(float32(h))
}
uniforms[uniformIndex+i*2] = floatW
uniforms[uniformIndex+1+i*2] = floatH
if srcs[0] != nil {
w, h := srcs[0].InternalSize()
uniforms[2] = math.Float32bits(float32(w))
uniforms[3] = math.Float32bits(float32(h))
} else {
uniforms[2] = 0
uniforms[3] = 0
}
if srcs[1] != nil {
w, h := srcs[1].InternalSize()
uniforms[4] = math.Float32bits(float32(w))
uniforms[5] = math.Float32bits(float32(h))
} else {
uniforms[4] = 0
uniforms[5] = 0
}
if srcs[2] != nil {
w, h := srcs[2].InternalSize()
uniforms[6] = math.Float32bits(float32(w))
uniforms[7] = math.Float32bits(float32(h))
} else {
uniforms[6] = 0
uniforms[7] = 0
}
if srcs[3] != nil {
w, h := srcs[3].InternalSize()
uniforms[8] = math.Float32bits(float32(w))
uniforms[9] = math.Float32bits(float32(h))
} else {
uniforms[8] = 0
uniforms[9] = 0
}
uniformIndex += graphics.ShaderImageCount * 2
dr := imageRectangleToRectangleF32(dstRegion)
if shader.unit() == shaderir.Texels {
@@ -357,16 +403,14 @@ func (q *commandQueue) prependPreservedUniforms(uniforms []uint32, shader *Shade
}
// Set the destination region origin.
uniforms[uniformIndex] = math.Float32bits(dr.x)
uniforms[uniformIndex+1] = math.Float32bits(dr.y)
uniformIndex += 2
uniforms[10] = math.Float32bits(dr.x)
uniforms[11] = math.Float32bits(dr.y)
// Set the destination region size.
uniforms[uniformIndex] = math.Float32bits(dr.width)
uniforms[uniformIndex+1] = math.Float32bits(dr.height)
uniformIndex += 2
uniforms[12] = math.Float32bits(dr.width)
uniforms[13] = math.Float32bits(dr.height)
var srs [graphics.ShaderImageCount]rectangleF32
var srs [graphics.ShaderSrcImageCount]rectangleF32
for i, r := range srcRegions {
srs[i] = imageRectangleToRectangleF32(r)
}
@@ -384,40 +428,49 @@ func (q *commandQueue) prependPreservedUniforms(uniforms []uint32, shader *Shade
}
// Set the source region origins.
for i := 0; i < graphics.ShaderImageCount; i++ {
uniforms[uniformIndex+i*2] = math.Float32bits(srs[i].x)
uniforms[uniformIndex+1+i*2] = math.Float32bits(srs[i].y)
}
uniformIndex += graphics.ShaderImageCount * 2
uniforms[14] = math.Float32bits(srs[0].x)
uniforms[15] = math.Float32bits(srs[0].y)
uniforms[16] = math.Float32bits(srs[1].x)
uniforms[17] = math.Float32bits(srs[1].y)
uniforms[18] = math.Float32bits(srs[2].x)
uniforms[19] = math.Float32bits(srs[2].y)
uniforms[20] = math.Float32bits(srs[3].x)
uniforms[21] = math.Float32bits(srs[3].y)
// Set the source region sizes.
for i := 0; i < graphics.ShaderImageCount; i++ {
uniforms[uniformIndex+i*2] = math.Float32bits(srs[i].width)
uniforms[uniformIndex+1+i*2] = math.Float32bits(srs[i].height)
}
uniformIndex += graphics.ShaderImageCount * 2
uniforms[22] = math.Float32bits(srs[0].width)
uniforms[23] = math.Float32bits(srs[0].height)
uniforms[24] = math.Float32bits(srs[1].width)
uniforms[25] = math.Float32bits(srs[1].height)
uniforms[26] = math.Float32bits(srs[2].width)
uniforms[27] = math.Float32bits(srs[2].height)
uniforms[28] = math.Float32bits(srs[3].width)
uniforms[29] = math.Float32bits(srs[3].height)
// Set the projection matrix.
uniforms[uniformIndex] = math.Float32bits(2 / float32(dw))
uniforms[uniformIndex+1] = 0
uniforms[uniformIndex+2] = 0
uniforms[uniformIndex+3] = 0
uniforms[uniformIndex+4] = 0
uniforms[uniformIndex+5] = math.Float32bits(2 / float32(dh))
uniforms[uniformIndex+6] = 0
uniforms[uniformIndex+7] = 0
uniforms[uniformIndex+8] = 0
uniforms[uniformIndex+9] = 0
uniforms[uniformIndex+10] = math.Float32bits(1)
uniforms[uniformIndex+11] = 0
uniforms[uniformIndex+12] = math.Float32bits(-1)
uniforms[uniformIndex+13] = math.Float32bits(-1)
uniforms[uniformIndex+14] = 0
uniforms[uniformIndex+15] = math.Float32bits(1)
uniforms[30] = math.Float32bits(2 / float32(dw))
uniforms[31] = 0
uniforms[32] = 0
uniforms[33] = 0
uniforms[34] = 0
uniforms[35] = math.Float32bits(2 / float32(dh))
uniforms[36] = 0
uniforms[37] = 0
uniforms[38] = 0
uniforms[39] = 0
uniforms[40] = math.Float32bits(1)
uniforms[41] = 0
uniforms[42] = math.Float32bits(-1)
uniforms[43] = math.Float32bits(-1)
uniforms[44] = 0
uniforms[45] = math.Float32bits(1)
return uniforms
}
// Confirm the concrete value of graphics.PreservedUniformDwordCount.
var _ [0]struct{} = [graphics.PreservedUniformDwordCount - 46]struct{}{}
type commandQueuePool struct {
cache []*commandQueue
m sync.Mutex
@@ -469,7 +522,7 @@ func (c *commandQueueManager) putCommandQueue(commandQueue *commandQueue) {
c.pool.put(commandQueue)
}
func (c *commandQueueManager) enqueueDrawTrianglesCommand(dst *Image, srcs [graphics.ShaderImageCount]*Image, vertices []float32, indices []uint32, blend graphicsdriver.Blend, dstRegion image.Rectangle, srcRegions [graphics.ShaderImageCount]image.Rectangle, shader *Shader, uniforms []uint32, fillRule graphicsdriver.FillRule) {
func (c *commandQueueManager) enqueueDrawTrianglesCommand(dst *Image, srcs [graphics.ShaderSrcImageCount]*Image, vertices []float32, indices []uint32, blend graphicsdriver.Blend, dstRegion image.Rectangle, srcRegions [graphics.ShaderSrcImageCount]image.Rectangle, shader *Shader, uniforms []uint32, fillRule graphicsdriver.FillRule) {
if c.current == nil {
c.current, _ = c.pool.get()
}
@@ -507,13 +560,6 @@ func roundUpPower2(x int) int {
return p2
}
func max(a, b int) int {
if a < b {
return b
}
return a
}
func (b *uint32sBuffer) alloc(n int) []uint32 {
buf := b.buf
if len(buf)+n > cap(buf) {
+22 -11
View File
@@ -37,6 +37,9 @@ type Image struct {
internalHeight int
screen bool
// attribute is used only for logs.
attribute string
// id is an identifier for the image. This is used only when dumping the information.
//
// This is duplicated with graphicsdriver.Image's ID, but this id is still necessary because this image might not
@@ -57,18 +60,20 @@ func genNextImageID() int {
// NewImage returns a new image.
//
// Note that the image is not initialized yet.
func NewImage(width, height int, screenFramebuffer bool) *Image {
func NewImage(width, height int, screenFramebuffer bool, attribute string) *Image {
i := &Image{
width: width,
height: height,
screen: screenFramebuffer,
id: genNextImageID(),
width: width,
height: height,
screen: screenFramebuffer,
id: genNextImageID(),
attribute: attribute,
}
c := &newImageCommand{
result: i,
width: width,
height: height,
screen: screenFramebuffer,
result: i,
width: width,
height: height,
screen: screenFramebuffer,
attribute: attribute,
}
theCommandQueueManager.enqueueCommand(c)
return i
@@ -130,7 +135,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
// elements for the source image are not used.
func (i *Image) DrawTriangles(srcs [graphics.ShaderImageCount]*Image, vertices []float32, indices []uint32, blend graphicsdriver.Blend, dstRegion image.Rectangle, srcRegions [graphics.ShaderImageCount]image.Rectangle, shader *Shader, uniforms []uint32, fillRule graphicsdriver.FillRule) {
func (i *Image) DrawTriangles(srcs [graphics.ShaderSrcImageCount]*Image, vertices []float32, indices []uint32, blend graphicsdriver.Blend, dstRegion image.Rectangle, srcRegions [graphics.ShaderSrcImageCount]image.Rectangle, shader *Shader, uniforms []uint32, fillRule graphicsdriver.FillRule) {
for _, src := range srcs {
if src == nil {
continue
@@ -230,6 +235,12 @@ func LogImagesInfo(images []*Image) {
})
for _, i := range images {
w, h := i.InternalSize()
debug.Logf(" %d: (%d, %d)\n", i.id, w, h)
var attr string
if i.attribute != "" {
attr = " (" + i.attribute + ")"
} else if i.screen {
attr = " (screen)"
}
debug.FrameLogf(" %d: (%d, %d)%s\n", i.id, w, h, attr)
}
}
@@ -31,12 +31,16 @@ type Shader struct {
shader graphicsdriver.Shader
ir *shaderir.Program
id int
// name is used only for logging.
name string
}
func NewShader(ir *shaderir.Program) *Shader {
func NewShader(ir *shaderir.Program, name string) *Shader {
s := &Shader{
ir: ir,
id: genNextShaderID(),
ir: ir,
id: genNextShaderID(),
name: name,
}
c := &newShaderCommand{
result: s,