mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-11-10 04:57:26 +01:00
graphicsdriver/metal: Rename Driver -> Graphics
This commit is contained in:
parent
6cbf37e855
commit
01d1afa25c
@ -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},
|
Loading…
Reference in New Issue
Block a user