From 01d1afa25c727059e44f0be42ae82da7cd606435 Mon Sep 17 00:00:00 2001 From: Hajime Hoshi Date: Sat, 4 Apr 2020 17:12:24 +0900 Subject: [PATCH] graphicsdriver/metal: Rename Driver -> Graphics --- .../metal/{driver.go => graphics.go} | 304 +++++++++--------- 1 file changed, 152 insertions(+), 152 deletions(-) rename internal/graphicsdriver/metal/{driver.go => graphics.go} (76%) diff --git a/internal/graphicsdriver/metal/driver.go b/internal/graphicsdriver/metal/graphics.go similarity index 76% rename from internal/graphicsdriver/metal/driver.go rename to internal/graphicsdriver/metal/graphics.go index 850eab600..ea2ffdc50 100644 --- a/internal/graphicsdriver/metal/driver.go +++ b/internal/graphicsdriver/metal/graphics.go @@ -283,7 +283,7 @@ type rpsKey struct { screen bool } -type Driver struct { +type Graphics struct { view view screenRPS mtl.RenderPipelineState @@ -307,91 +307,91 @@ type Driver struct { pool unsafe.Pointer } -var theDriver Driver +var theGraphics Graphics -func Get() *Driver { - return &theDriver +func Get() *Graphics { + return &theGraphics } -func (d *Driver) SetThread(thread *thread.Thread) { - d.t = thread +func (g *Graphics) SetThread(thread *thread.Thread) { + g.t = thread } -func (d *Driver) Begin() { - d.t.Call(func() error { +func (g *Graphics) Begin() { + g.t.Call(func() error { // NSAutoreleasePool is required to release drawable correctly (#847). // https://developer.apple.com/library/archive/documentation/3DDrawing/Conceptual/MTLBestPracticesGuide/Drawables.html - d.pool = C.allocAutoreleasePool() + g.pool = C.allocAutoreleasePool() return nil }) } -func (d *Driver) End() { - d.flush(false, true) - d.t.Call(func() error { - d.screenDrawable = ca.MetalDrawable{} - C.releaseAutoreleasePool(d.pool) - d.pool = nil +func (g *Graphics) End() { + g.flush(false, true) + g.t.Call(func() error { + g.screenDrawable = ca.MetalDrawable{} + C.releaseAutoreleasePool(g.pool) + g.pool = nil return nil }) } -func (d *Driver) SetWindow(window unsafe.Pointer) { - d.t.Call(func() error { +func (g *Graphics) SetWindow(window unsafe.Pointer) { + g.t.Call(func() error { // Note that [NSApp mainWindow] returns nil when the window is borderless. // Then the window is needed to be given explicitly. - d.view.setWindow(window) + g.view.setWindow(window) return nil }) } -func (d *Driver) SetUIView(uiview uintptr) { +func (g *Graphics) SetUIView(uiview uintptr) { // TODO: Should this be called on the main thread? - d.view.setUIView(uiview) + g.view.setUIView(uiview) } -func (d *Driver) SetVertices(vertices []float32, indices []uint16) { - d.t.Call(func() error { - if d.vb != (mtl.Buffer{}) { - d.vb.Release() +func (g *Graphics) SetVertices(vertices []float32, indices []uint16) { + g.t.Call(func() error { + if g.vb != (mtl.Buffer{}) { + g.vb.Release() } - if d.ib != (mtl.Buffer{}) { - d.ib.Release() + if g.ib != (mtl.Buffer{}) { + g.ib.Release() } - d.vb = d.view.getMTLDevice().MakeBufferWithBytes(unsafe.Pointer(&vertices[0]), unsafe.Sizeof(vertices[0])*uintptr(len(vertices)), resourceStorageMode) - d.ib = d.view.getMTLDevice().MakeBufferWithBytes(unsafe.Pointer(&indices[0]), unsafe.Sizeof(indices[0])*uintptr(len(indices)), resourceStorageMode) + g.vb = g.view.getMTLDevice().MakeBufferWithBytes(unsafe.Pointer(&vertices[0]), unsafe.Sizeof(vertices[0])*uintptr(len(vertices)), resourceStorageMode) + g.ib = g.view.getMTLDevice().MakeBufferWithBytes(unsafe.Pointer(&indices[0]), unsafe.Sizeof(indices[0])*uintptr(len(indices)), resourceStorageMode) return nil }) } -func (d *Driver) flush(wait bool, present bool) { - d.t.Call(func() error { - if d.cb == (mtl.CommandBuffer{}) { +func (g *Graphics) flush(wait bool, present bool) { + g.t.Call(func() error { + if g.cb == (mtl.CommandBuffer{}) { return nil } - if present && d.screenDrawable != (ca.MetalDrawable{}) { - d.cb.PresentDrawable(d.screenDrawable) + if present && g.screenDrawable != (ca.MetalDrawable{}) { + g.cb.PresentDrawable(g.screenDrawable) } - d.cb.Commit() + g.cb.Commit() if wait { - d.cb.WaitUntilCompleted() + g.cb.WaitUntilCompleted() } - d.cb = mtl.CommandBuffer{} + g.cb = mtl.CommandBuffer{} return nil }) } -func (d *Driver) checkSize(width, height int) { +func (g *Graphics) checkSize(width, height int) { if width < 1 { panic(fmt.Sprintf("metal: width (%d) must be equal or more than %d", width, 1)) } if height < 1 { panic(fmt.Sprintf("metal: height (%d) must be equal or more than %d", height, 1)) } - m := d.MaxImageSize() + m := g.MaxImageSize() if width > m { panic(fmt.Sprintf("metal: width (%d) must be less than or equal to %d", width, m)) } @@ -400,8 +400,8 @@ func (d *Driver) checkSize(width, height int) { } } -func (d *Driver) NewImage(width, height int) (driver.Image, error) { - d.checkSize(width, height) +func (g *Graphics) NewImage(width, height int) (driver.Image, error) { + g.checkSize(width, height) td := mtl.TextureDescriptor{ PixelFormat: mtl.PixelFormatRGBA8UNorm, Width: graphics.InternalImageSize(width), @@ -410,52 +410,52 @@ func (d *Driver) NewImage(width, height int) (driver.Image, error) { Usage: textureUsage, } var t mtl.Texture - d.t.Call(func() error { - t = d.view.getMTLDevice().MakeTexture(td) + g.t.Call(func() error { + t = g.view.getMTLDevice().MakeTexture(td) return nil }) return &Image{ - driver: d, - width: width, - height: height, - texture: t, + graphics: g, + width: width, + height: height, + texture: t, }, nil } -func (d *Driver) NewScreenFramebufferImage(width, height int) (driver.Image, error) { - d.t.Call(func() error { - d.view.setDrawableSize(width, height) +func (g *Graphics) NewScreenFramebufferImage(width, height int) (driver.Image, error) { + g.t.Call(func() error { + g.view.setDrawableSize(width, height) return nil }) return &Image{ - driver: d, - width: width, - height: height, - screen: true, + graphics: g, + width: width, + height: height, + screen: true, }, nil } -func (d *Driver) SetTransparent(transparent bool) { - d.transparent = transparent +func (g *Graphics) SetTransparent(transparent bool) { + g.transparent = transparent } -func (d *Driver) Reset() error { - if err := d.t.Call(func() error { - if d.cq != (mtl.CommandQueue{}) { - d.cq.Release() - d.cq = mtl.CommandQueue{} +func (g *Graphics) Reset() error { + if err := g.t.Call(func() error { + if g.cq != (mtl.CommandQueue{}) { + g.cq.Release() + g.cq = mtl.CommandQueue{} } // TODO: Release existing rpss - if d.rpss == nil { - d.rpss = map[rpsKey]mtl.RenderPipelineState{} + if g.rpss == nil { + g.rpss = map[rpsKey]mtl.RenderPipelineState{} } - if err := d.view.reset(); err != nil { + if err := g.view.reset(); err != nil { return err } - if d.transparent { - d.view.ml.SetOpaque(false) + if g.transparent { + g.view.ml.SetOpaque(false) } replaces := map[string]string{ @@ -470,7 +470,7 @@ func (d *Driver) Reset() error { src = strings.Replace(src, k, v, -1) } - lib, err := d.view.getMTLDevice().MakeLibrary(src, mtl.CompileOptions{}) + lib, err := g.view.getMTLDevice().MakeLibrary(src, mtl.CompileOptions{}) if err != nil { return err } @@ -487,17 +487,17 @@ func (d *Driver) Reset() error { VertexFunction: vs, FragmentFunction: fs, } - rpld.ColorAttachments[0].PixelFormat = d.view.colorPixelFormat() + rpld.ColorAttachments[0].PixelFormat = g.view.colorPixelFormat() rpld.ColorAttachments[0].BlendingEnabled = true rpld.ColorAttachments[0].DestinationAlphaBlendFactor = mtl.BlendFactorZero rpld.ColorAttachments[0].DestinationRGBBlendFactor = mtl.BlendFactorZero rpld.ColorAttachments[0].SourceAlphaBlendFactor = mtl.BlendFactorOne rpld.ColorAttachments[0].SourceRGBBlendFactor = mtl.BlendFactorOne - rps, err := d.view.getMTLDevice().MakeRenderPipelineState(rpld) + rps, err := g.view.getMTLDevice().MakeRenderPipelineState(rpld) if err != nil { return err } - d.screenRPS = rps + g.screenRPS = rps conv := func(c driver.Operation) mtl.BlendFactor { switch c { @@ -544,7 +544,7 @@ func (d *Driver) Reset() error { pix := mtl.PixelFormatRGBA8UNorm if screen { - pix = d.view.colorPixelFormat() + pix = g.view.colorPixelFormat() } rpld.ColorAttachments[0].PixelFormat = pix rpld.ColorAttachments[0].BlendingEnabled = true @@ -554,11 +554,11 @@ func (d *Driver) Reset() error { rpld.ColorAttachments[0].DestinationRGBBlendFactor = conv(dst) rpld.ColorAttachments[0].SourceAlphaBlendFactor = conv(src) rpld.ColorAttachments[0].SourceRGBBlendFactor = conv(src) - rps, err := d.view.getMTLDevice().MakeRenderPipelineState(rpld) + rps, err := g.view.getMTLDevice().MakeRenderPipelineState(rpld) if err != nil { return err } - d.rpss[rpsKey{ + g.rpss[rpsKey{ screen: screen, useColorM: cm, filter: f, @@ -571,7 +571,7 @@ func (d *Driver) Reset() error { } } - d.cq = d.view.getMTLDevice().MakeCommandQueue() + g.cq = g.view.getMTLDevice().MakeCommandQueue() return nil }); err != nil { return err @@ -580,11 +580,11 @@ func (d *Driver) Reset() error { return nil } -func (d *Driver) Draw(indexLen int, indexOffset int, mode driver.CompositeMode, colorM *affine.ColorM, filter driver.Filter, address driver.Address) error { - d.drawCalled = true +func (g *Graphics) Draw(indexLen int, indexOffset int, mode driver.CompositeMode, colorM *affine.ColorM, filter driver.Filter, address driver.Address) error { + g.drawCalled = true - if err := d.t.Call(func() error { - d.view.update() + if err := g.t.Call(func() error { + g.view.update() rpd := mtl.RenderPassDescriptor{} // Even though the destination pixels are not used, mtl.LoadActionDontCare might cause glitches @@ -593,33 +593,33 @@ func (d *Driver) Draw(indexLen int, indexOffset int, mode driver.CompositeMode, rpd.ColorAttachments[0].StoreAction = mtl.StoreActionStore var t mtl.Texture - if d.dst.screen { - if d.screenDrawable == (ca.MetalDrawable{}) { - drawable := d.view.drawable() + if g.dst.screen { + if g.screenDrawable == (ca.MetalDrawable{}) { + drawable := g.view.drawable() if drawable == (ca.MetalDrawable{}) { return nil } - d.screenDrawable = drawable + g.screenDrawable = drawable } - t = d.screenDrawable.Texture() + t = g.screenDrawable.Texture() } else { - t = d.dst.texture + t = g.dst.texture } rpd.ColorAttachments[0].Texture = t rpd.ColorAttachments[0].ClearColor = mtl.ClearColor{} - w, h := d.dst.viewportSize() + w, h := g.dst.viewportSize() - if d.cb == (mtl.CommandBuffer{}) { - d.cb = d.cq.MakeCommandBuffer() + if g.cb == (mtl.CommandBuffer{}) { + g.cb = g.cq.MakeCommandBuffer() } - rce := d.cb.MakeRenderCommandEncoder(rpd) + rce := g.cb.MakeRenderCommandEncoder(rpd) - if d.dst.screen && filter == driver.FilterScreen { - rce.SetRenderPipelineState(d.screenRPS) + if g.dst.screen && filter == driver.FilterScreen { + rce.SetRenderPipelineState(g.screenRPS) } else { - rce.SetRenderPipelineState(d.rpss[rpsKey{ - screen: d.dst.screen, + rce.SetRenderPipelineState(g.rpss[rpsKey{ + screen: g.dst.screen, useColorM: colorM != nil, filter: filter, address: address, @@ -634,14 +634,14 @@ func (d *Driver) Draw(indexLen int, indexOffset int, mode driver.CompositeMode, ZNear: -1, ZFar: 1, }) - rce.SetVertexBuffer(d.vb, 0, 0) + rce.SetVertexBuffer(g.vb, 0, 0) viewportSize := [...]float32{float32(w), float32(h)} rce.SetVertexBytes(unsafe.Pointer(&viewportSize[0]), unsafe.Sizeof(viewportSize), 1) sourceSize := [...]float32{ - float32(graphics.InternalImageSize(d.src.width)), - float32(graphics.InternalImageSize(d.src.height)), + float32(graphics.InternalImageSize(g.src.width)), + float32(graphics.InternalImageSize(g.src.height)), } rce.SetFragmentBytes(unsafe.Pointer(&sourceSize[0]), unsafe.Sizeof(sourceSize), 2) @@ -649,15 +649,15 @@ func (d *Driver) Draw(indexLen int, indexOffset int, mode driver.CompositeMode, rce.SetFragmentBytes(unsafe.Pointer(&esBody[0]), unsafe.Sizeof(esBody[0])*uintptr(len(esBody)), 3) rce.SetFragmentBytes(unsafe.Pointer(&esTranslate[0]), unsafe.Sizeof(esTranslate[0])*uintptr(len(esTranslate)), 4) - scale := float32(d.dst.width) / float32(d.src.width) + scale := float32(g.dst.width) / float32(g.src.width) rce.SetFragmentBytes(unsafe.Pointer(&scale), unsafe.Sizeof(scale), 5) - if d.src != nil { - rce.SetFragmentTexture(d.src.texture, 0) + if g.src != nil { + rce.SetFragmentTexture(g.src.texture, 0) } else { rce.SetFragmentTexture(mtl.Texture{}, 0) } - rce.DrawIndexedPrimitives(mtl.PrimitiveTypeTriangle, indexLen, mtl.IndexTypeUInt16, d.ib, indexOffset*2) + rce.DrawIndexedPrimitives(mtl.PrimitiveTypeTriangle, indexLen, mtl.IndexTypeUInt16, g.ib, indexOffset*2) rce.EndEncoding() return nil @@ -668,76 +668,76 @@ func (d *Driver) Draw(indexLen int, indexOffset int, mode driver.CompositeMode, return nil } -func (d *Driver) ResetSource() { - d.t.Call(func() error { - d.src = nil +func (g *Graphics) ResetSource() { + g.t.Call(func() error { + g.src = nil return nil }) } -func (d *Driver) SetVsyncEnabled(enabled bool) { - d.view.setDisplaySyncEnabled(enabled) +func (g *Graphics) SetVsyncEnabled(enabled bool) { + g.view.setDisplaySyncEnabled(enabled) } -func (d *Driver) VDirection() driver.VDirection { +func (g *Graphics) VDirection() driver.VDirection { return driver.VUpward } -func (d *Driver) NeedsRestoring() bool { +func (g *Graphics) NeedsRestoring() bool { return false } -func (d *Driver) IsGL() bool { +func (g *Graphics) IsGL() bool { return false } -func (d *Driver) HasHighPrecisionFloat() bool { +func (g *Graphics) HasHighPrecisionFloat() bool { return true } -func (d *Driver) MaxImageSize() int { +func (g *Graphics) MaxImageSize() int { m := 0 - d.t.Call(func() error { - if d.maxImageSize == 0 { - d.maxImageSize = 4096 + g.t.Call(func() error { + if g.maxImageSize == 0 { + g.maxImageSize = 4096 // https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf switch { - case d.view.getMTLDevice().SupportsFeatureSet(mtl.FeatureSet_iOS_GPUFamily5_v1): - d.maxImageSize = 16384 - case d.view.getMTLDevice().SupportsFeatureSet(mtl.FeatureSet_iOS_GPUFamily4_v1): - d.maxImageSize = 16384 - case d.view.getMTLDevice().SupportsFeatureSet(mtl.FeatureSet_iOS_GPUFamily3_v1): - d.maxImageSize = 16384 - case d.view.getMTLDevice().SupportsFeatureSet(mtl.FeatureSet_iOS_GPUFamily2_v2): - d.maxImageSize = 8192 - case d.view.getMTLDevice().SupportsFeatureSet(mtl.FeatureSet_iOS_GPUFamily2_v1): - d.maxImageSize = 4096 - case d.view.getMTLDevice().SupportsFeatureSet(mtl.FeatureSet_iOS_GPUFamily1_v2): - d.maxImageSize = 8192 - case d.view.getMTLDevice().SupportsFeatureSet(mtl.FeatureSet_iOS_GPUFamily1_v1): - d.maxImageSize = 4096 - case d.view.getMTLDevice().SupportsFeatureSet(mtl.FeatureSet_tvOS_GPUFamily2_v1): - d.maxImageSize = 16384 - case d.view.getMTLDevice().SupportsFeatureSet(mtl.FeatureSet_tvOS_GPUFamily1_v1): - d.maxImageSize = 8192 - case d.view.getMTLDevice().SupportsFeatureSet(mtl.FeatureSet_macOS_GPUFamily1_v1): - d.maxImageSize = 16384 + case g.view.getMTLDevice().SupportsFeatureSet(mtl.FeatureSet_iOS_GPUFamily5_v1): + g.maxImageSize = 16384 + case g.view.getMTLDevice().SupportsFeatureSet(mtl.FeatureSet_iOS_GPUFamily4_v1): + g.maxImageSize = 16384 + case g.view.getMTLDevice().SupportsFeatureSet(mtl.FeatureSet_iOS_GPUFamily3_v1): + g.maxImageSize = 16384 + case g.view.getMTLDevice().SupportsFeatureSet(mtl.FeatureSet_iOS_GPUFamily2_v2): + g.maxImageSize = 8192 + case g.view.getMTLDevice().SupportsFeatureSet(mtl.FeatureSet_iOS_GPUFamily2_v1): + g.maxImageSize = 4096 + case g.view.getMTLDevice().SupportsFeatureSet(mtl.FeatureSet_iOS_GPUFamily1_v2): + g.maxImageSize = 8192 + case g.view.getMTLDevice().SupportsFeatureSet(mtl.FeatureSet_iOS_GPUFamily1_v1): + g.maxImageSize = 4096 + case g.view.getMTLDevice().SupportsFeatureSet(mtl.FeatureSet_tvOS_GPUFamily2_v1): + g.maxImageSize = 16384 + case g.view.getMTLDevice().SupportsFeatureSet(mtl.FeatureSet_tvOS_GPUFamily1_v1): + g.maxImageSize = 8192 + case g.view.getMTLDevice().SupportsFeatureSet(mtl.FeatureSet_macOS_GPUFamily1_v1): + g.maxImageSize = 16384 default: panic("metal: there is no supported feature set") } } - m = d.maxImageSize + m = g.maxImageSize return nil }) return m } type Image struct { - driver *Driver - width int - height int - screen bool - texture mtl.Texture + graphics *Graphics + width int + height int + screen bool + texture mtl.Texture } // viewportSize must be called from the main thread. @@ -749,7 +749,7 @@ func (i *Image) viewportSize() (int, int) { } func (i *Image) Dispose() { - i.driver.t.Call(func() error { + i.graphics.t.Call(func() error { if i.texture != (mtl.Texture{}) { i.texture.Release() i.texture = mtl.Texture{} @@ -766,12 +766,12 @@ func (i *Image) IsInvalidated() bool { } func (i *Image) syncTexture() { - i.driver.t.Call(func() error { - if i.driver.cb != (mtl.CommandBuffer{}) { + i.graphics.t.Call(func() error { + if i.graphics.cb != (mtl.CommandBuffer{}) { panic("metal: command buffer must be empty at syncTexture: flush is not called yet?") } - cb := i.driver.cq.MakeCommandBuffer() + cb := i.graphics.cq.MakeCommandBuffer() bce := cb.MakeBlitCommandEncoder() bce.SynchronizeTexture(i.texture, 0, 0) bce.EndEncoding() @@ -782,11 +782,11 @@ func (i *Image) syncTexture() { } func (i *Image) Pixels() ([]byte, error) { - i.driver.flush(true, false) + i.graphics.flush(true, false) i.syncTexture() b := make([]byte, 4*i.width*i.height) - i.driver.t.Call(func() error { + i.graphics.t.Call(func() error { i.texture.GetBytes(&b[0], uintptr(4*i.width), mtl.Region{ Size: mtl.Size{Width: i.width, Height: i.height, Depth: 1}, }, 0) @@ -796,27 +796,27 @@ func (i *Image) Pixels() ([]byte, error) { } func (i *Image) SetAsDestination() { - i.driver.t.Call(func() error { - i.driver.dst = i + i.graphics.t.Call(func() error { + i.graphics.dst = i return nil }) } func (i *Image) SetAsSource() { - i.driver.t.Call(func() error { - i.driver.src = i + i.graphics.t.Call(func() error { + i.graphics.src = i return nil }) } func (i *Image) ReplacePixels(args []*driver.ReplacePixelsArgs) { - d := i.driver - if d.drawCalled { - d.flush(true, false) - d.drawCalled = false + g := i.graphics + if g.drawCalled { + g.flush(true, false) + g.drawCalled = false } - d.t.Call(func() error { + g.t.Call(func() error { for _, a := range args { i.texture.ReplaceRegion(mtl.Region{ Origin: mtl.Origin{X: a.X, Y: a.Y, Z: 0},