Ios 优化渲染MTLTexture以显示的性能?
我用以下代码向显示器演示MTLTexture。这是一个大的(~12k)纹理,大约需要10毫秒来绘制。因为我需要渲染至少30FPS(33ms/帧),所以仅仅显示纹理就要花费将近三分之一的计算时间 有什么技巧可以提高性能并更快地绘制纹理吗?在GPU帧捕获中,它显示了大量的消隐时间。我尝试启用/禁用剔除,但我仍然看到用于剔除的时间相同Ios 优化渲染MTLTexture以显示的性能?,ios,performance,metal,mtkview,Ios,Performance,Metal,Mtkview,我用以下代码向显示器演示MTLTexture。这是一个大的(~12k)纹理,大约需要10毫秒来绘制。因为我需要渲染至少30FPS(33ms/帧),所以仅仅显示纹理就要花费将近三分之一的计算时间 有什么技巧可以提高性能并更快地绘制纹理吗?在GPU帧捕获中,它显示了大量的消隐时间。我尝试启用/禁用剔除,但我仍然看到用于剔除的时间相同 vertex TextureMappingVertex mapTexture(unsigned int vertex_id [[ vertex_id ]], const
vertex TextureMappingVertex mapTexture(unsigned int vertex_id [[ vertex_id ]], constant Uniforms& uniforms [[ buffer(0) ]]) {
float4x4 renderedCoordinates = float4x4(float4( -1.f, -1.f, 0.f, 1.f ),
float4( 1.f, -1.f, 0.f, 1.f ),
float4( -1.f, 1.f, 0.f, 1.f ),
float4( 1.f, 1.f, 0.f, 1.f ));
float4x2 textureCoordinates = float4x2(float2( 0.f, 1.f ),
float2( 1.f, 1.f ),
float2( 0.f, 0.f ),
float2( 1.f, 0.f ));
TextureMappingVertex outVertex;
outVertex.renderedCoordinate = uniforms.mvp_matrix * renderedCoordinates[vertex_id];
outVertex.textureCoordinate = textureCoordinates[vertex_id];
return outVertex;
}
fragment half4 displayTexture(TextureMappingVertex mappingVertex [[ stage_in ]],
texture2d<half, access::sample> texture [[ texture(0) ]]) {
constexpr sampler s(address::clamp_to_edge, filter::nearest);
return half4(texture.sample(s, mappingVertex.textureCoordinate));
}
func draw(in view: MTKView) {
guard let commandBuffer = commandQueue.makeCommandBuffer() else { return }
guard let descriptor = view.currentRenderPassDescriptor else {return}
let render = commandBuffer.makeRenderCommandEncoder(descriptor: descriptor)
render?.pushDebugGroup("Render to Screen")
render?.setRenderPipelineState(renderCanvasPipelineState)
render?.setFragmentTexture(canvasTexture, index: 0)
render?.setVertexBuffer(uniformBuffer, offset: 0, index: 0)
render?.setCullMode(.none)
render?.drawPrimitives(type: .triangleStrip, vertexStart: 0, vertexCount: 4, instanceCount: 1)
render?.popDebugGroup()
render?.endEncoding()
guard let drawable = view.currentDrawable else { return }
commandBuffer.present(drawable)
commandBuffer.commit()
}
func initializeCanvasRenderPipelineState() {
let library = Renderer.device.makeDefaultLibrary()
let pipelineDescriptor = MTLRenderPipelineDescriptor()
pipelineDescriptor.sampleCount = 1
pipelineDescriptor.rasterSampleCount = 1
pipelineDescriptor.colorAttachments[0].pixelFormat = .rgba8Unorm
pipelineDescriptor.depthAttachmentPixelFormat = .invalid
pipelineDescriptor.vertexFunction = library?.makeFunction(name: "mapTexture")
pipelineDescriptor.fragmentFunction = library?.makeFunction(name: "displayTexture")
pipelineDescriptor.colorAttachments[0].isBlendingEnabled = false
do {
try renderCanvasPipelineState = Renderer.device.makeRenderPipelineState(descriptor: pipelineDescriptor)
}
catch {
assertionFailure("Failed creating a render state pipeline. Can't render the texture without one.")
return
}
}
vertex TextureMappingVertex贴图纹理(无符号整数顶点id[[vertex_id]],常量制服和制服[[buffer(0)]){
float4x4 renderedCoordinates=float4x4(float4(-1.f,-1.f,0.f,1.f),
浮动4(1.f,-1.f,0.f,1.f),
浮动4(-1.f,1.f,0.f,1.f),
浮动4(1.f,1.f,0.f,1.f));
float4x2纹理坐标=float4x2(float2(0.f,1.f),
浮动2(1.f,1.f),
浮动2(0.f,0.f),
浮动2(1.f,0.f));
TextureMappingVertex outVertex;
outVertex.renderedCoordinate=uniforms.mvp_矩阵*renderedCoordinates[vertex_id];
outVertex.TextureCoordination=纹理坐标[顶点id];
返回顶点;
}
fragment half4 displayTexture(TextureMappingVertex贴图顶点[[stage_in]],
纹理2D纹理[[纹理(0)]){
constexpr采样器s(地址:钳制到边缘,过滤器:最近);
返回half4(纹理.sample(s,mappingVertex.textureCoordinate));
}
func绘图(视图中:MTKView){
guard let commandBuffer=commandQueue.makeCommandBuffer()else{return}
guard let descriptor=view.currentRenderPassDescriptor else{return}
让render=commandBuffer.makeRenderCommandEncoder(描述符:描述符)
渲染?.pushDebugGroup(“渲染到屏幕”)
render?.setRenderPipelineState(renderCanvasPipelineState)
render?.setFragmentTexture(CanvaTexture,索引:0)
render?.setVertexBuffer(uniformBuffer,偏移量:0,索引:0)
渲染?.setCullMode(.none)
render?.drawPrimitives(类型:.triangleStrip,vertexStart:0,vertexCount:4,instanceCount:1)
render?.popDebugGroup()
渲染?.endEncoding()
guard let drawable=view.currentDrawable else{return}
commandBuffer.present(可提取)
commandBuffer.commit()
}
func initializeCanvasRenderPipelineState(){
let library=Renderer.device.makeDefaultLibrary()
让pipelineDescriptor=MTLRenderPipelineDescriptor()
pipelineDescriptor.sampleCount=1
pipelineDescriptor.rasterSampleCount=1
pipelineDescriptor.colorAttachments[0]。pixelFormat=.rgba8Unorm
pipelineDescriptor.DepthatAttachmentPixelFormat=。无效
pipelineDescriptor.vertexFunction=library?.makeFunction(名称:“mapTexture”)
pipelineDescriptor.fragmentFunction=library?.makeFunction(名称:“displayTexture”)
pipelineDescriptor.colorAttachments[0]。isBlendingEnabled=false
做{
尝试renderCanvasPipelineState=Renderer.device.makeRenderPipelineState(描述符:pipelineDescriptor)
}
抓住{
assertionFailure(“创建渲染状态管道失败。没有管道无法渲染纹理。”)
返回
}
}
制服.mvp\U矩阵是如何设置的?您是否总是正面绘制四边形,只是缩放和平移x和y(并围绕z旋转?),以获得所需的零件?或者,您是否有可能绕其他轴旋转?我想你可以通过画一个没有延伸到窗口外的四边形来避免剔除,而是调整纹理坐标来选择你想要采样的纹理部分;我只是缩放和平移,没有旋转。如果有帮助,我可以添加代码。有趣。所以保持四边形静止,但平移/缩放纹理坐标?所以我现在只是做了一些实验,硬连接纹理坐标,如果显示完整的纹理,性能实际上没有任何提高。但当我将纹理放大到2倍时,速度大约是2倍。我不确定它是否值得实现,因为我认为大多数情况下都会显示完整的纹理。还有什么我可以试试的吗?你的用例真的需要3D吗?或者你“仅仅”需要在屏幕上显示一个纹理(变换)吗?严格来说,它本质上只是显示一个图像。