MTKView blend issues when re-using currentDrawable.texture in draw() loop

最后都变了- 提交于 2019-12-11 17:12:09

问题


I am working on a metal-backed painting application in which I divide the drawing of a stroke in two steps: the first step draws the leading edge of a stroke to screen and captures the entire to an MTLTexture via:

metalTextureComposite = self.currentDrawable!.texture

the second step draws an updated leading edge of the advancing stroke, and composites atop a polygon textured with the last saved metalTextureComposite.

This method allows me to draw infinitely long strokes without sacrificing performance, as these two steps get repeated for each frame of the drawing cycle.

The problem I'm having is that, using the desired source-over composite mode (see below code), I am only seeing the leading edge of the stroke being drawn to screen. This tells me that either I am not adequately capturing metalTextureComposite from the currentDrawable, or that I am making the wrong assumptions regarding the blending mode to use, which incidentally is as follows:

renderPipelineDescriptor.colorAttachments[0].sourceRGBBlendFactor = .sourceAlpha
renderPipelineDescriptor.colorAttachments[0].destinationRGBBlendFactor = .oneMinusSourceAlpha       
renderPipelineDescriptor.colorAttachments[0].sourceAlphaBlendFactor = .sourceAlpha                 
renderPipelineDescriptor.colorAttachments[0].destinationAlphaBlendFactor = .oneMinusSourceAlpha

If I use different blending modes, I do see the entirety of the stroke being drawn, but not necessarily the appearance I'm after. Below is the part of the code I'm including inside the MTKView's draw() method.

func metalRenderStampArray() {

    // first encode uber-stamp with previous loop's  metalTextureComposite in a background polygon
    // note metalTexture= metalTextureComposite contains previous loop's drawable contents
    metalCommandEncode(renderCommandEncoder: renderCommandEncoder, stampLayer: stampLayerMode.stampLayerBG, vertexArrayStamps: vertexArrayStampsBG, metalTexture: metalTextureComposite) // background uber-stamp

    // empty out uber-stamp in preparation for the next cycle
    initializeStampArrays(stampLayer: stampLayerMode.stampLayerBG) 

    // next, encode current subCurve chunk polygons in foreground
    // note metalTexture=brushTexture.texture is a round brush texture with alpha
    metalCommandEncode(renderCommandEncoder: renderCommandEncoder, stampLayer: stampLayerMode.stampLayerFG, vertexArrayStamps: vertexArrayStampsFG, metalTexture: brushTexture.texture) // foreground sub-curve chunk

    renderCommandEncoder?.endEncoding() // finalize renderEncoder set up

    // now present bg + fg composite which is where I see the problem
    commandBuffer?.present(self.currentDrawable!)

    // 7b. Render to pipeline
    commandBuffer?.commit() // commit and send task to gpu

    metalTextureComposite = nil // empty out before re-populating
    metalTextureComposite = self.currentDrawable!.texture // set up bg texture for next iteration 

    metalStampComputeComposite() // compute coordinates for the background composite stamp for the next iteration

 } // end of func metalRenderStampArray()

Should I be handling metalTextureComposite differently (since it is being written to at 1/fps) and if so, how should I handle it? The goal is to use a single blending mode for the background poly and the leading stroke polygons. Any help would be appreciated.


回答1:


You seem to be storing a reference to drawable's texture and then using it the next frame.

I can see 2 possible problems with this: - at the next frame draw cycle, the previous frame's texture might not yet be drawn to by the graphics processor - drawable's texture might be used by the system and app's code at the same time

I'd suggest try copy drawable's texture for your use in commandBuffer?.addCompletedHandler { }



来源:https://stackoverflow.com/questions/55272262/mtkview-blend-issues-when-re-using-currentdrawable-texture-in-draw-loop

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!