mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-24 10:48:53 +01:00
graphicsdriver/metal: Move MTLDevice and CAMetalLayer to the other struct
On iOS, they are given or included in a MTKView and we don't have to (or should not) make them. Let's move them to a different struct.
This commit is contained in:
parent
57d493a549
commit
c7ab66e0e1
@ -283,10 +283,8 @@ type rpsKey struct {
|
||||
}
|
||||
|
||||
type Driver struct {
|
||||
window uintptr
|
||||
view view
|
||||
|
||||
device mtl.Device
|
||||
ml ca.MetalLayer
|
||||
screenRPS mtl.RenderPipelineState
|
||||
rpss map[rpsKey]mtl.RenderPipelineState
|
||||
cq mtl.CommandQueue
|
||||
@ -339,8 +337,8 @@ func (d *Driver) End() {
|
||||
func (d *Driver) SetWindow(window uintptr) {
|
||||
d.t.Call(func() error {
|
||||
// Note that [NSApp mainWindow] returns nil when the window is borderless.
|
||||
// Then the window is needed to be given.
|
||||
d.window = window
|
||||
// Then the window is needed to be given explicitly.
|
||||
d.view.setWindow(window)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
@ -353,8 +351,8 @@ func (d *Driver) SetVertices(vertices []float32, indices []uint16) {
|
||||
if d.ib != (mtl.Buffer{}) {
|
||||
d.ib.Release()
|
||||
}
|
||||
d.vb = d.device.MakeBufferWithBytes(unsafe.Pointer(&vertices[0]), unsafe.Sizeof(vertices[0])*uintptr(len(vertices)), mtl.ResourceStorageModeManaged)
|
||||
d.ib = d.device.MakeBufferWithBytes(unsafe.Pointer(&indices[0]), unsafe.Sizeof(indices[0])*uintptr(len(indices)), mtl.ResourceStorageModeManaged)
|
||||
d.vb = d.view.getMTLDevice().MakeBufferWithBytes(unsafe.Pointer(&vertices[0]), unsafe.Sizeof(vertices[0])*uintptr(len(vertices)), mtl.ResourceStorageModeManaged)
|
||||
d.ib = d.view.getMTLDevice().MakeBufferWithBytes(unsafe.Pointer(&indices[0]), unsafe.Sizeof(indices[0])*uintptr(len(indices)), mtl.ResourceStorageModeManaged)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
@ -390,25 +388,25 @@ func (d *Driver) checkSize(width, height int) {
|
||||
d.maxImageSize = 4096
|
||||
// https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf
|
||||
switch {
|
||||
case d.device.SupportsFeatureSet(mtl.FeatureSet_iOS_GPUFamily5_v1):
|
||||
case d.view.getMTLDevice().SupportsFeatureSet(mtl.FeatureSet_iOS_GPUFamily5_v1):
|
||||
d.maxImageSize = 16384
|
||||
case d.device.SupportsFeatureSet(mtl.FeatureSet_iOS_GPUFamily4_v1):
|
||||
case d.view.getMTLDevice().SupportsFeatureSet(mtl.FeatureSet_iOS_GPUFamily4_v1):
|
||||
d.maxImageSize = 16384
|
||||
case d.device.SupportsFeatureSet(mtl.FeatureSet_iOS_GPUFamily3_v1):
|
||||
case d.view.getMTLDevice().SupportsFeatureSet(mtl.FeatureSet_iOS_GPUFamily3_v1):
|
||||
d.maxImageSize = 16384
|
||||
case d.device.SupportsFeatureSet(mtl.FeatureSet_iOS_GPUFamily2_v2):
|
||||
case d.view.getMTLDevice().SupportsFeatureSet(mtl.FeatureSet_iOS_GPUFamily2_v2):
|
||||
d.maxImageSize = 8192
|
||||
case d.device.SupportsFeatureSet(mtl.FeatureSet_iOS_GPUFamily2_v1):
|
||||
case d.view.getMTLDevice().SupportsFeatureSet(mtl.FeatureSet_iOS_GPUFamily2_v1):
|
||||
d.maxImageSize = 4096
|
||||
case d.device.SupportsFeatureSet(mtl.FeatureSet_iOS_GPUFamily1_v2):
|
||||
case d.view.getMTLDevice().SupportsFeatureSet(mtl.FeatureSet_iOS_GPUFamily1_v2):
|
||||
d.maxImageSize = 8192
|
||||
case d.device.SupportsFeatureSet(mtl.FeatureSet_iOS_GPUFamily1_v1):
|
||||
case d.view.getMTLDevice().SupportsFeatureSet(mtl.FeatureSet_iOS_GPUFamily1_v1):
|
||||
d.maxImageSize = 4096
|
||||
case d.device.SupportsFeatureSet(mtl.FeatureSet_tvOS_GPUFamily2_v1):
|
||||
case d.view.getMTLDevice().SupportsFeatureSet(mtl.FeatureSet_tvOS_GPUFamily2_v1):
|
||||
d.maxImageSize = 16384
|
||||
case d.device.SupportsFeatureSet(mtl.FeatureSet_tvOS_GPUFamily1_v1):
|
||||
case d.view.getMTLDevice().SupportsFeatureSet(mtl.FeatureSet_tvOS_GPUFamily1_v1):
|
||||
d.maxImageSize = 8192
|
||||
case d.device.SupportsFeatureSet(mtl.FeatureSet_macOS_GPUFamily1_v1):
|
||||
case d.view.getMTLDevice().SupportsFeatureSet(mtl.FeatureSet_macOS_GPUFamily1_v1):
|
||||
d.maxImageSize = 16384
|
||||
default:
|
||||
panic("metal: there is no supported feature set")
|
||||
@ -446,7 +444,7 @@ func (d *Driver) NewImage(width, height int) (driver.Image, error) {
|
||||
}
|
||||
var t mtl.Texture
|
||||
d.t.Call(func() error {
|
||||
t = d.device.MakeTexture(td)
|
||||
t = d.view.getMTLDevice().MakeTexture(td)
|
||||
return nil
|
||||
})
|
||||
return &Image{
|
||||
@ -459,7 +457,7 @@ func (d *Driver) NewImage(width, height int) (driver.Image, error) {
|
||||
|
||||
func (d *Driver) NewScreenFramebufferImage(width, height int) (driver.Image, error) {
|
||||
d.t.Call(func() error {
|
||||
d.ml.SetDrawableSize(width, height)
|
||||
d.view.setDrawableSize(width, height)
|
||||
return nil
|
||||
})
|
||||
return &Image{
|
||||
@ -482,22 +480,10 @@ func (d *Driver) Reset() error {
|
||||
d.rpss = map[rpsKey]mtl.RenderPipelineState{}
|
||||
}
|
||||
|
||||
var err error
|
||||
d.device, err = mtl.CreateSystemDefaultDevice()
|
||||
if err != nil {
|
||||
if err := d.view.reset(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
d.ml = ca.MakeMetalLayer()
|
||||
d.ml.SetDevice(d.device)
|
||||
// https://developer.apple.com/documentation/quartzcore/cametallayer/1478155-pixelformat
|
||||
//
|
||||
// The pixel format for a Metal layer must be MTLPixelFormatBGRA8Unorm,
|
||||
// MTLPixelFormatBGRA8Unorm_sRGB, MTLPixelFormatRGBA16Float, MTLPixelFormatBGRA10_XR, or
|
||||
// MTLPixelFormatBGRA10_XR_sRGB.
|
||||
d.ml.SetPixelFormat(mtl.PixelFormatBGRA8UNorm)
|
||||
d.ml.SetMaximumDrawableCount(3)
|
||||
|
||||
replaces := map[string]string{
|
||||
"{{.FilterNearest}}": fmt.Sprintf("%d", graphics.FilterNearest),
|
||||
"{{.FilterLinear}}": fmt.Sprintf("%d", graphics.FilterLinear),
|
||||
@ -510,7 +496,7 @@ func (d *Driver) Reset() error {
|
||||
src = strings.Replace(src, k, v, -1)
|
||||
}
|
||||
|
||||
lib, err := d.device.MakeLibrary(src, mtl.CompileOptions{})
|
||||
lib, err := d.view.getMTLDevice().MakeLibrary(src, mtl.CompileOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -527,13 +513,13 @@ func (d *Driver) Reset() error {
|
||||
VertexFunction: vs,
|
||||
FragmentFunction: fs,
|
||||
}
|
||||
rpld.ColorAttachments[0].PixelFormat = d.ml.PixelFormat()
|
||||
rpld.ColorAttachments[0].PixelFormat = d.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.device.MakeRenderPipelineState(rpld)
|
||||
rps, err := d.view.getMTLDevice().MakeRenderPipelineState(rpld)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -588,7 +574,7 @@ 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.device.MakeRenderPipelineState(rpld)
|
||||
rps, err := d.view.getMTLDevice().MakeRenderPipelineState(rpld)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -603,7 +589,7 @@ func (d *Driver) Reset() error {
|
||||
}
|
||||
}
|
||||
|
||||
d.cq = d.device.MakeCommandQueue()
|
||||
d.cq = d.view.getMTLDevice().MakeCommandQueue()
|
||||
return nil
|
||||
}); err != nil {
|
||||
return err
|
||||
@ -614,8 +600,7 @@ func (d *Driver) Reset() error {
|
||||
|
||||
func (d *Driver) Draw(indexLen int, indexOffset int, mode graphics.CompositeMode, colorM *affine.ColorM, filter graphics.Filter, address graphics.Address) error {
|
||||
if err := d.t.Call(func() error {
|
||||
// NSView can be changed anytime (probably). Set this everyframe.
|
||||
setView(d.window, d.ml)
|
||||
d.view.update()
|
||||
|
||||
rpd := mtl.RenderPassDescriptor{}
|
||||
if d.dst.screen {
|
||||
@ -628,9 +613,8 @@ func (d *Driver) Draw(indexLen int, indexOffset int, mode graphics.CompositeMode
|
||||
var t mtl.Texture
|
||||
if d.dst.screen {
|
||||
if d.screenDrawable == (ca.MetalDrawable{}) {
|
||||
drawable, err := d.ml.NextDrawable()
|
||||
if err != nil {
|
||||
// Drawable is nil. This can happen at the initial state. Let's wait and see.
|
||||
drawable := d.view.drawable()
|
||||
if drawable == (ca.MetalDrawable{}) {
|
||||
return nil
|
||||
}
|
||||
d.screenDrawable = drawable
|
||||
@ -704,10 +688,7 @@ func (d *Driver) ResetSource() {
|
||||
}
|
||||
|
||||
func (d *Driver) SetVsyncEnabled(enabled bool) {
|
||||
// TODO: Now SetVsyncEnabled is called only from the main thread, and d.t.Run is not available since
|
||||
// recursive function call via Run is forbidden.
|
||||
// Fix this to use d.t.Run to avoid confusion.
|
||||
d.ml.SetDisplaySyncEnabled(enabled)
|
||||
d.view.setDisplaySyncEnabled(enabled)
|
||||
}
|
||||
|
||||
func (d *Driver) VDirection() driver.VDirection {
|
||||
|
@ -19,8 +19,44 @@ package metal
|
||||
|
||||
import (
|
||||
"github.com/hajimehoshi/ebiten/internal/graphicsdriver/metal/ca"
|
||||
"github.com/hajimehoshi/ebiten/internal/graphicsdriver/metal/mtl"
|
||||
)
|
||||
|
||||
func setView(window uintptr, layer ca.MetalLayer) {
|
||||
// TODO: Implement this
|
||||
type view struct {
|
||||
}
|
||||
|
||||
func (v *view) setWindow(window uintptr) {
|
||||
panic("metal: setWindow cannot be called on iOS")
|
||||
}
|
||||
|
||||
func (v *view) setDrawableSize(width, height int) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
func (v *view) getMTLDevice() mtl.Device {
|
||||
// TODO: Implement this
|
||||
return mtl.Device{}
|
||||
}
|
||||
|
||||
func (v *view) setDisplaySyncEnabled(enabled bool) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
func (v *view) colorPixelFormat() mtl.PixelFormat {
|
||||
// TODO: Implement this
|
||||
return 0
|
||||
}
|
||||
|
||||
func (v *view) reset() error {
|
||||
// Do nothing
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *view) update() {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
func (v *view) drawable() ca.MetalDrawable {
|
||||
// TODO: Implemnt this
|
||||
return ca.MetalDrawable{}
|
||||
}
|
||||
|
91
internal/graphicsdriver/metal/view_macos.go
Normal file
91
internal/graphicsdriver/metal/view_macos.go
Normal file
@ -0,0 +1,91 @@
|
||||
// Copyright 2019 The Ebiten Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// +build darwin
|
||||
// +build !ios
|
||||
|
||||
package metal
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
"github.com/hajimehoshi/ebiten/internal/graphicsdriver/metal/ca"
|
||||
"github.com/hajimehoshi/ebiten/internal/graphicsdriver/metal/mtl"
|
||||
"github.com/hajimehoshi/ebiten/internal/graphicsdriver/metal/ns"
|
||||
)
|
||||
|
||||
type view struct {
|
||||
window uintptr
|
||||
|
||||
device mtl.Device
|
||||
ml ca.MetalLayer
|
||||
}
|
||||
|
||||
func (v *view) setWindow(window uintptr) {
|
||||
v.window = window
|
||||
}
|
||||
|
||||
func (v *view) setDrawableSize(width, height int) {
|
||||
v.ml.SetDrawableSize(width, height)
|
||||
}
|
||||
|
||||
func (v *view) getMTLDevice() mtl.Device {
|
||||
return v.device
|
||||
}
|
||||
|
||||
func (v *view) setDisplaySyncEnabled(enabled bool) {
|
||||
// TODO: Now SetVsyncEnabled is called only from the main thread, and d.t.Run is not available since
|
||||
// recursive function call via Run is forbidden.
|
||||
// Fix this to use d.t.Run to avoid confusion.
|
||||
v.ml.SetDisplaySyncEnabled(enabled)
|
||||
}
|
||||
|
||||
func (v *view) colorPixelFormat() mtl.PixelFormat {
|
||||
return v.ml.PixelFormat()
|
||||
}
|
||||
|
||||
func (v *view) reset() error {
|
||||
var err error
|
||||
v.device, err = mtl.CreateSystemDefaultDevice()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
v.ml = ca.MakeMetalLayer()
|
||||
v.ml.SetDevice(v.device)
|
||||
// https://developer.apple.com/documentation/quartzcore/cametallayer/1478155-pixelformat
|
||||
//
|
||||
// The pixel format for a Metal layer must be MTLPixelFormatBGRA8Unorm,
|
||||
// MTLPixelFormatBGRA8Unorm_sRGB, MTLPixelFormatRGBA16Float, MTLPixelFormatBGRA10_XR, or
|
||||
// MTLPixelFormatBGRA10_XR_sRGB.
|
||||
v.ml.SetPixelFormat(mtl.PixelFormatBGRA8UNorm)
|
||||
v.ml.SetMaximumDrawableCount(3)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *view) update() {
|
||||
// NSView can be changed anytime (probably). Set this everyframe.
|
||||
cocoaWindow := ns.NewWindow(unsafe.Pointer(v.window))
|
||||
cocoaWindow.ContentView().SetLayer(v.ml)
|
||||
cocoaWindow.ContentView().SetWantsLayer(true)
|
||||
}
|
||||
|
||||
func (v *view) drawable() ca.MetalDrawable {
|
||||
d, err := v.ml.NextDrawable()
|
||||
if err != nil {
|
||||
// Drawable is nil. This can happen at the initial state. Let's wait and see.
|
||||
return ca.MetalDrawable{}
|
||||
}
|
||||
return d
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
// Copyright 2019 The Ebiten Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// +build darwin
|
||||
// +build !ios
|
||||
|
||||
package metal
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
"github.com/hajimehoshi/ebiten/internal/graphicsdriver/metal/ca"
|
||||
"github.com/hajimehoshi/ebiten/internal/graphicsdriver/metal/ns"
|
||||
)
|
||||
|
||||
func setView(window uintptr, layer ca.MetalLayer) {
|
||||
cocoaWindow := ns.NewWindow(unsafe.Pointer(window))
|
||||
cocoaWindow.ContentView().SetLayer(layer)
|
||||
cocoaWindow.ContentView().SetWantsLayer(true)
|
||||
}
|
Loading…
Reference in New Issue
Block a user