【Metal API 教程:第一讲】用XCode6.1创建并调试Metal工程

来源:互联网 发布:php post 编辑:程序博客网 时间:2024/05/01 21:27


Metal API


1.关于IOS 8 Metal


Metal API是apple 2014年在ios平台上推出的高效底层的3D图形API,它通过减少驱动层的API调用CPU的消耗提高渲染效率。

参考视频解说(百度云网盘链接)
1. Metal Framework Overview 
2. Metal Fundamentals
3. Metal Advanced 

2.创建Metal工程



首先要准备好苹果开发者的账号和一只iPhone 6/6s/iPad Air 2,Metal工程目前的编译和调试都需要真机进行调试。





如果没有连接真机并把目标设为真机的话,会出现Metal Compiler Error问题。


设为真机后,最后link上MetalFramework点播放键就能在iphone6上运行了。

3. 代码概览

a. 创建设备和指令队列

_device = MTLCreateSystemDefaultDevice();// create a new command queue_commandQueue = [_device newCommandQueue];_defaultLibrary = [_device newDefaultLibrary];</span>

b.加载资源(Metal Shader 和 ConstBuffer)

id <MTLFunction> fragmentProgram = [_defaultLibrary newFunctionWithName:@"lighting_fragment"];id <MTLFunction> vertexProgram = [_defaultLibrary newFunctionWithName:@"lighting_vertex"];

_vertexBuffer = [_device newBufferWithBytes:kCubeVertexData length:sizeof(kCubeVertexData) options:MTLResourceOptionCPUCacheModeDefault];_vertexBuffer.label = @"Vertices";

c.初始化渲染管线

MTLRenderPipelineDescriptor *pipelineStateDescriptor = [[MTLRenderPipelineDescriptor alloc] init];pipelineStateDescriptor.label                           = @"MyPipeline";pipelineStateDescriptor.sampleCount                     = _sampleCount;pipelineStateDescriptor.vertexFunction                  = vertexProgram;pipelineStateDescriptor.fragmentFunction                = fragmentProgram;pipelineStateDescriptor.colorAttachments[0].pixelFormat = MTLPixelFormatBGRA8Unorm;pipelineStateDescriptor.depthAttachmentPixelFormat      = _depthPixelFormat;    // create a compiled pipeline state object. Shader functions (from the render pipeline descriptor)// are compiled when this is created unlessed they are obtained from the device's cacheNSError *error = nil;_pipelineState = [_device newRenderPipelineStateWithDescriptor:pipelineStateDescriptor error:&error];if(!_pipelineState) {   NSLog(@">> ERROR: Couldnt create a pipeline: %@", error);      // assert here if pipeline coudnt be created for any reason   assert(0);}MTLDepthStencilDescriptor *depthStateDesc = [[MTLDepthStencilDescriptor alloc] init];depthStateDesc.depthCompareFunction = MTLCompareFunctionLess;depthStateDesc.depthWriteEnabled = YES;_depthState = [_device newDepthStencilStateWithDescriptor:depthStateDesc]; //renderEncoder需要用到


d.执行渲染


    // create a new command buffer for each renderpass to the current drawable    id <MTLCommandBuffer> commandBuffer = [_commandQueue commandBuffer];    // create a render command encoder so we can render into something    MTLRenderPassDescriptor *renderPassDescriptor = view.renderPassDescriptor;    if (renderPassDescriptor)    {        id <MTLRenderCommandEncoder> renderEncoder = [commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor];        [renderEncoder pushDebugGroup:@"Boxes"];        [renderEncoder setDepthStencilState:_depthState];        [renderEncoder setRenderPipelineState:_pipelineState];        [renderEncoder setVertexBuffer:_vertexBuffer offset:0 atIndex:0 ];                // NOTE: this could be alot faster if we render using instancing, but in this case we want to emit lots of draw calls        for (int i = 0; i < kNumberOfBoxes; i++) {            //  set constant buffer for each box            [renderEncoder setVertexBuffer:_dynamicConstantBuffer[_constantDataBufferIndex] offset:i*_sizeOfConstantT atIndex:1 ];                        // tell the render context we want to draw our primitives            [renderEncoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:36 instanceCount:1];        }                [renderEncoder endEncoding];        [renderEncoder popDebugGroup];        // call the view's completion handler which is required by the view since it will signal its semaphore and set up the next buffer        __block dispatch_semaphore_t block_sema = _inflight_semaphore;        [commandBuffer addCompletedHandler:^(id<MTLCommandBuffer> buffer) {            dispatch_semaphore_signal(block_sema);        }];                // schedule a present once rendering to the framebuffer is complete        [commandBuffer presentDrawable:view.currentDrawable];                // finalize rendering here. this will push the command buffer to the GPU        [commandBuffer commit];    }



4.Metal 调试


GPU Trace查看界面

本文版权DsoTsin所有,转载文章请注明出处!

下一讲【iOS8 Metal API 教程:第二讲】编写Metal Shader并渲染3D模型(上)

由于缺米,Metal教程等后续Mac到手之后再更新(虚拟机太慢了)

0 0
原创粉丝点击