mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-25 03:08:54 +01:00
internal/graphicsdriver/metal: Bug fix: Crashed with METAL_DEVICE_WRAPPER_TYPE=1
Closes #1697
This commit is contained in:
parent
315f87896b
commit
17d8cb5311
@ -296,12 +296,12 @@ FragmentShaderFunc(0, FILTER_SCREEN, ADDRESS_UNSAFE)
|
|||||||
`
|
`
|
||||||
|
|
||||||
type rpsKey struct {
|
type rpsKey struct {
|
||||||
useColorM bool
|
useColorM bool
|
||||||
filter driver.Filter
|
filter driver.Filter
|
||||||
address driver.Address
|
address driver.Address
|
||||||
compositeMode driver.CompositeMode
|
compositeMode driver.CompositeMode
|
||||||
colorWriteMask bool
|
stencilMode stencilMode
|
||||||
screen bool
|
screen bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type Graphics struct {
|
type Graphics struct {
|
||||||
@ -315,7 +315,8 @@ type Graphics struct {
|
|||||||
|
|
||||||
screenDrawable ca.MetalDrawable
|
screenDrawable ca.MetalDrawable
|
||||||
|
|
||||||
lastDstTexture mtl.Texture
|
lastDstTexture mtl.Texture
|
||||||
|
lastStencilMode stencilMode
|
||||||
|
|
||||||
vb mtl.Buffer
|
vb mtl.Buffer
|
||||||
ib mtl.Buffer
|
ib mtl.Buffer
|
||||||
@ -549,9 +550,8 @@ func (g *Graphics) Reset() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
rpld := mtl.RenderPipelineDescriptor{
|
rpld := mtl.RenderPipelineDescriptor{
|
||||||
VertexFunction: vs,
|
VertexFunction: vs,
|
||||||
FragmentFunction: fs,
|
FragmentFunction: fs,
|
||||||
StencilAttachmentPixelFormat: mtl.PixelFormatStencil8,
|
|
||||||
}
|
}
|
||||||
rpld.ColorAttachments[0].PixelFormat = g.view.colorPixelFormat()
|
rpld.ColorAttachments[0].PixelFormat = g.view.colorPixelFormat()
|
||||||
rpld.ColorAttachments[0].BlendingEnabled = true
|
rpld.ColorAttachments[0].BlendingEnabled = true
|
||||||
@ -578,7 +578,11 @@ func (g *Graphics) Reset() error {
|
|||||||
driver.FilterLinear,
|
driver.FilterLinear,
|
||||||
} {
|
} {
|
||||||
for c := driver.CompositeModeSourceOver; c <= driver.CompositeModeMax; c++ {
|
for c := driver.CompositeModeSourceOver; c <= driver.CompositeModeMax; c++ {
|
||||||
for _, cwm := range []bool{false, true} {
|
for _, stencil := range []stencilMode{
|
||||||
|
prepareStencil,
|
||||||
|
drawWithStencil,
|
||||||
|
noStencil,
|
||||||
|
} {
|
||||||
cmi := 0
|
cmi := 0
|
||||||
if cm {
|
if cm {
|
||||||
cmi = 1
|
cmi = 1
|
||||||
@ -588,9 +592,11 @@ func (g *Graphics) Reset() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
rpld := mtl.RenderPipelineDescriptor{
|
rpld := mtl.RenderPipelineDescriptor{
|
||||||
VertexFunction: vs,
|
VertexFunction: vs,
|
||||||
FragmentFunction: fs,
|
FragmentFunction: fs,
|
||||||
StencilAttachmentPixelFormat: mtl.PixelFormatStencil8,
|
}
|
||||||
|
if stencil != noStencil {
|
||||||
|
rpld.StencilAttachmentPixelFormat = mtl.PixelFormatStencil8
|
||||||
}
|
}
|
||||||
|
|
||||||
pix := mtl.PixelFormatRGBA8UNorm
|
pix := mtl.PixelFormatRGBA8UNorm
|
||||||
@ -605,22 +611,22 @@ func (g *Graphics) Reset() error {
|
|||||||
rpld.ColorAttachments[0].DestinationRGBBlendFactor = operationToBlendFactor(dst)
|
rpld.ColorAttachments[0].DestinationRGBBlendFactor = operationToBlendFactor(dst)
|
||||||
rpld.ColorAttachments[0].SourceAlphaBlendFactor = operationToBlendFactor(src)
|
rpld.ColorAttachments[0].SourceAlphaBlendFactor = operationToBlendFactor(src)
|
||||||
rpld.ColorAttachments[0].SourceRGBBlendFactor = operationToBlendFactor(src)
|
rpld.ColorAttachments[0].SourceRGBBlendFactor = operationToBlendFactor(src)
|
||||||
if cwm {
|
if stencil == prepareStencil {
|
||||||
rpld.ColorAttachments[0].WriteMask = mtl.ColorWriteMaskAll
|
|
||||||
} else {
|
|
||||||
rpld.ColorAttachments[0].WriteMask = mtl.ColorWriteMaskNone
|
rpld.ColorAttachments[0].WriteMask = mtl.ColorWriteMaskNone
|
||||||
|
} else {
|
||||||
|
rpld.ColorAttachments[0].WriteMask = mtl.ColorWriteMaskAll
|
||||||
}
|
}
|
||||||
rps, err := g.view.getMTLDevice().MakeRenderPipelineState(rpld)
|
rps, err := g.view.getMTLDevice().MakeRenderPipelineState(rpld)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
g.rpss[rpsKey{
|
g.rpss[rpsKey{
|
||||||
screen: screen,
|
screen: screen,
|
||||||
useColorM: cm,
|
useColorM: cm,
|
||||||
filter: f,
|
filter: f,
|
||||||
address: a,
|
address: a,
|
||||||
compositeMode: c,
|
compositeMode: c,
|
||||||
colorWriteMask: cwm,
|
stencilMode: stencil,
|
||||||
}] = rps
|
}] = rps
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -646,9 +652,10 @@ func (g *Graphics) draw(rps mtl.RenderPipelineState, dst *Image, dstRegion drive
|
|||||||
// 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?
|
||||||
if g.lastDstTexture != dst.mtlTexture() || stencilMode == prepareStencil {
|
if g.lastDstTexture != dst.mtlTexture() || (g.lastStencilMode == noStencil) != (stencilMode == noStencil) {
|
||||||
g.flushRenderCommandEncoderIfNeeded()
|
g.flushRenderCommandEncoderIfNeeded()
|
||||||
}
|
}
|
||||||
|
g.lastStencilMode = stencilMode
|
||||||
|
|
||||||
if g.rce == (mtl.RenderCommandEncoder{}) {
|
if g.rce == (mtl.RenderCommandEncoder{}) {
|
||||||
rpd := mtl.RenderPassDescriptor{}
|
rpd := mtl.RenderPassDescriptor{}
|
||||||
@ -755,7 +762,21 @@ func (g *Graphics) draw(rps mtl.RenderPipelineState, dst *Image, dstRegion drive
|
|||||||
}
|
}
|
||||||
g.rce.SetDepthStencilState(g.view.getMTLDevice().MakeDepthStencilState(desc))
|
g.rce.SetDepthStencilState(g.view.getMTLDevice().MakeDepthStencilState(desc))
|
||||||
case noStencil:
|
case noStencil:
|
||||||
g.rce.SetDepthStencilState(mtl.DepthStencilState{})
|
desc := mtl.DepthStencilDescriptor{
|
||||||
|
BackFaceStencil: mtl.StencilDescriptor{
|
||||||
|
StencilFailureOperation: mtl.StencilOperationKeep,
|
||||||
|
DepthFailureOperation: mtl.StencilOperationKeep,
|
||||||
|
DepthStencilPassOperation: mtl.StencilOperationKeep,
|
||||||
|
StencilCompareFunction: mtl.CompareFunctionAlways,
|
||||||
|
},
|
||||||
|
FrontFaceStencil: mtl.StencilDescriptor{
|
||||||
|
StencilFailureOperation: mtl.StencilOperationKeep,
|
||||||
|
DepthFailureOperation: mtl.StencilOperationKeep,
|
||||||
|
DepthStencilPassOperation: mtl.StencilOperationKeep,
|
||||||
|
StencilCompareFunction: mtl.CompareFunctionAlways,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
g.rce.SetDepthStencilState(g.view.getMTLDevice().MakeDepthStencilState(desc))
|
||||||
}
|
}
|
||||||
|
|
||||||
g.rce.DrawIndexedPrimitives(mtl.PrimitiveTypeTriangle, indexLen, mtl.IndexTypeUInt16, g.ib, indexOffset*2)
|
g.rce.DrawIndexedPrimitives(mtl.PrimitiveTypeTriangle, indexLen, mtl.IndexTypeUInt16, g.ib, indexOffset*2)
|
||||||
@ -775,29 +796,26 @@ func (g *Graphics) DrawTriangles(dstID driver.ImageID, srcIDs [graphics.ShaderIm
|
|||||||
srcs[i] = g.images[srcID]
|
srcs[i] = g.images[srcID]
|
||||||
}
|
}
|
||||||
|
|
||||||
var rpss [2]mtl.RenderPipelineState
|
rpss := map[stencilMode]mtl.RenderPipelineState{}
|
||||||
var uniformVars []interface{}
|
var uniformVars []interface{}
|
||||||
if shaderID == driver.InvalidShaderID {
|
if shaderID == driver.InvalidShaderID {
|
||||||
if dst.screen && filter == driver.FilterScreen {
|
if dst.screen && filter == driver.FilterScreen {
|
||||||
rpss[1] = g.screenRPS
|
rpss[noStencil] = g.screenRPS
|
||||||
} else {
|
} else {
|
||||||
useColorM := colorM != nil
|
for _, stencil := range []stencilMode{
|
||||||
rpss[0] = g.rpss[rpsKey{
|
prepareStencil,
|
||||||
screen: dst.screen,
|
drawWithStencil,
|
||||||
useColorM: useColorM,
|
noStencil,
|
||||||
filter: filter,
|
} {
|
||||||
address: address,
|
rpss[stencil] = g.rpss[rpsKey{
|
||||||
compositeMode: mode,
|
screen: dst.screen,
|
||||||
colorWriteMask: false,
|
useColorM: colorM != nil,
|
||||||
}]
|
filter: filter,
|
||||||
rpss[1] = g.rpss[rpsKey{
|
address: address,
|
||||||
screen: dst.screen,
|
compositeMode: mode,
|
||||||
useColorM: useColorM,
|
stencilMode: stencil,
|
||||||
filter: filter,
|
}]
|
||||||
address: address,
|
}
|
||||||
compositeMode: mode,
|
|
||||||
colorWriteMask: true,
|
|
||||||
}]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
w, h := dst.internalSize()
|
w, h := dst.internalSize()
|
||||||
@ -826,14 +844,16 @@ func (g *Graphics) DrawTriangles(dstID driver.ImageID, srcIDs [graphics.ShaderIm
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
var err error
|
for _, stencil := range []stencilMode{
|
||||||
rpss[0], err = g.shaders[shaderID].RenderPipelineState(g.view.getMTLDevice(), mode, false)
|
prepareStencil,
|
||||||
if err != nil {
|
drawWithStencil,
|
||||||
return err
|
noStencil,
|
||||||
}
|
} {
|
||||||
rpss[1], err = g.shaders[shaderID].RenderPipelineState(g.view.getMTLDevice(), mode, true)
|
var err error
|
||||||
if err != nil {
|
rpss[stencil], err = g.shaders[shaderID].RenderPipelineState(g.view.getMTLDevice(), mode, stencil)
|
||||||
return err
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uniformVars = make([]interface{}, graphics.PreservedUniformVariablesNum+len(uniforms))
|
uniformVars = make([]interface{}, graphics.PreservedUniformVariablesNum+len(uniforms))
|
||||||
@ -885,14 +905,14 @@ func (g *Graphics) DrawTriangles(dstID driver.ImageID, srcIDs [graphics.ShaderIm
|
|||||||
}
|
}
|
||||||
|
|
||||||
if evenOdd {
|
if evenOdd {
|
||||||
if err := g.draw(rpss[0], dst, dstRegion, srcs, indexLen, indexOffset, uniformVars, prepareStencil); err != nil {
|
if err := g.draw(rpss[prepareStencil], dst, dstRegion, srcs, indexLen, indexOffset, uniformVars, prepareStencil); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := g.draw(rpss[1], dst, dstRegion, srcs, indexLen, indexOffset, uniformVars, drawWithStencil); err != nil {
|
if err := g.draw(rpss[drawWithStencil], dst, dstRegion, srcs, indexLen, indexOffset, uniformVars, drawWithStencil); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if err := g.draw(rpss[1], dst, dstRegion, srcs, indexLen, indexOffset, uniformVars, noStencil); err != nil {
|
if err := g.draw(rpss[noStencil], dst, dstRegion, srcs, indexLen, indexOffset, uniformVars, noStencil); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,8 +27,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type shaderRpsKey struct {
|
type shaderRpsKey struct {
|
||||||
compositeMode driver.CompositeMode
|
compositeMode driver.CompositeMode
|
||||||
colorWriteMask bool
|
stencilMode stencilMode
|
||||||
}
|
}
|
||||||
|
|
||||||
type Shader struct {
|
type Shader struct {
|
||||||
@ -88,18 +88,20 @@ func (s *Shader) init(device mtl.Device) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Shader) RenderPipelineState(device mtl.Device, compositeMode driver.CompositeMode, colorWriteMask bool) (mtl.RenderPipelineState, error) {
|
func (s *Shader) RenderPipelineState(device mtl.Device, compositeMode driver.CompositeMode, stencilMode stencilMode) (mtl.RenderPipelineState, error) {
|
||||||
if rps, ok := s.rpss[shaderRpsKey{
|
if rps, ok := s.rpss[shaderRpsKey{
|
||||||
compositeMode: compositeMode,
|
compositeMode: compositeMode,
|
||||||
colorWriteMask: colorWriteMask,
|
stencilMode: stencilMode,
|
||||||
}]; ok {
|
}]; ok {
|
||||||
return rps, nil
|
return rps, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
rpld := mtl.RenderPipelineDescriptor{
|
rpld := mtl.RenderPipelineDescriptor{
|
||||||
VertexFunction: s.vs,
|
VertexFunction: s.vs,
|
||||||
FragmentFunction: s.fs,
|
FragmentFunction: s.fs,
|
||||||
StencilAttachmentPixelFormat: mtl.PixelFormatStencil8,
|
}
|
||||||
|
if stencilMode != noStencil {
|
||||||
|
rpld.StencilAttachmentPixelFormat = mtl.PixelFormatStencil8
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: For the precise pixel format, whether the render target is the screen or not must be considered.
|
// TODO: For the precise pixel format, whether the render target is the screen or not must be considered.
|
||||||
@ -111,10 +113,10 @@ func (s *Shader) RenderPipelineState(device mtl.Device, compositeMode driver.Com
|
|||||||
rpld.ColorAttachments[0].DestinationRGBBlendFactor = operationToBlendFactor(dst)
|
rpld.ColorAttachments[0].DestinationRGBBlendFactor = operationToBlendFactor(dst)
|
||||||
rpld.ColorAttachments[0].SourceAlphaBlendFactor = operationToBlendFactor(src)
|
rpld.ColorAttachments[0].SourceAlphaBlendFactor = operationToBlendFactor(src)
|
||||||
rpld.ColorAttachments[0].SourceRGBBlendFactor = operationToBlendFactor(src)
|
rpld.ColorAttachments[0].SourceRGBBlendFactor = operationToBlendFactor(src)
|
||||||
if colorWriteMask {
|
if stencilMode == prepareStencil {
|
||||||
rpld.ColorAttachments[0].WriteMask = mtl.ColorWriteMaskAll
|
|
||||||
} else {
|
|
||||||
rpld.ColorAttachments[0].WriteMask = mtl.ColorWriteMaskNone
|
rpld.ColorAttachments[0].WriteMask = mtl.ColorWriteMaskNone
|
||||||
|
} else {
|
||||||
|
rpld.ColorAttachments[0].WriteMask = mtl.ColorWriteMaskAll
|
||||||
}
|
}
|
||||||
|
|
||||||
rps, err := device.MakeRenderPipelineState(rpld)
|
rps, err := device.MakeRenderPipelineState(rpld)
|
||||||
@ -123,8 +125,8 @@ func (s *Shader) RenderPipelineState(device mtl.Device, compositeMode driver.Com
|
|||||||
}
|
}
|
||||||
|
|
||||||
s.rpss[shaderRpsKey{
|
s.rpss[shaderRpsKey{
|
||||||
compositeMode: compositeMode,
|
compositeMode: compositeMode,
|
||||||
colorWriteMask: colorWriteMask,
|
stencilMode: stencilMode,
|
||||||
}] = rps
|
}] = rps
|
||||||
return rps, nil
|
return rps, nil
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user