| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132 |
- /*
- See LICENSE folder for this sample’s licensing information.
- Abstract:
- Implementation of a platform independent renderer class, which performs Metal setup and per frame rendering
- */
- @import simd;
- @import MetalKit;
- #import "AAPLRenderer.h"
- // Header shared between C code here, which executes Metal API commands, and .metal files, which
- // uses these types as inputs to the shaders.
- #import "AAPLShaderTypes.h"
- // Main class performing the rendering
- @implementation AAPLRenderer
- {
- id<MTLDevice> _device;
- // The render pipeline generated from the vertex and fragment shaders in the .metal shader file.
- id<MTLRenderPipelineState> _pipelineState;
- // The command queue used to pass commands to the device.
- id<MTLCommandQueue> _commandQueue;
- // The current size of the view, used as an input to the vertex shader.
- vector_uint2 _viewportSize;
- }
- - (nonnull instancetype)initWithMetalKitView:(nonnull MTKView *)mtkView
- {
- self = [super init];
- if(self)
- {
- NSError *error;
- _device = mtkView.device;
- // Load all the shader files with a .metal file extension in the project.
- id<MTLLibrary> defaultLibrary = [_device newDefaultLibrary];
- id<MTLFunction> vertexFunction = [defaultLibrary newFunctionWithName:@"vertexShader"];
- id<MTLFunction> fragmentFunction = [defaultLibrary newFunctionWithName:@"fragmentShader"];
- // Configure a pipeline descriptor that is used to create a pipeline state.
- MTLRenderPipelineDescriptor *pipelineStateDescriptor = [[MTLRenderPipelineDescriptor alloc] init];
- pipelineStateDescriptor.label = @"Simple Pipeline";
- pipelineStateDescriptor.vertexFunction = vertexFunction;
- pipelineStateDescriptor.fragmentFunction = fragmentFunction;
- pipelineStateDescriptor.colorAttachments[0].pixelFormat = mtkView.colorPixelFormat;
- _pipelineState = [_device newRenderPipelineStateWithDescriptor:pipelineStateDescriptor
- error:&error];
- // Pipeline State creation could fail if the pipeline descriptor isn't set up properly.
- // If the Metal API validation is enabled, you can find out more information about what
- // went wrong. (Metal API validation is enabled by default when a debug build is run
- // from Xcode.)
- NSAssert(_pipelineState, @"Failed to create pipeline state: %@", error);
- // Create the command queue
- _commandQueue = [_device newCommandQueue];
- }
- return self;
- }
- /// Called whenever view changes orientation or is resized
- - (void)mtkView:(nonnull MTKView *)view drawableSizeWillChange:(CGSize)size
- {
- // Save the size of the drawable to pass to the vertex shader.
- _viewportSize.x = size.width;
- _viewportSize.y = size.height;
- }
- /// Called whenever the view needs to render a frame.
- - (void)drawInMTKView:(nonnull MTKView *)view
- {
- static const AAPLVertex triangleVertices[] =
- {
- // 2D positions, RGBA colors
- { { 250, -250 }, { 1, 0, 0, 1 } },
- { { -250, -250 }, { 0, 1, 0, 1 } },
- { { 0, 250 }, { 0, 0, 1, 1 } },
- };
- // Create a new command buffer for each render pass to the current drawable.
- id<MTLCommandBuffer> commandBuffer = [_commandQueue commandBuffer];
- commandBuffer.label = @"MyCommand";
- // Obtain a renderPassDescriptor generated from the view's drawable textures.
- MTLRenderPassDescriptor *renderPassDescriptor = view.currentRenderPassDescriptor;
- if(renderPassDescriptor != nil)
- {
- // Create a render command encoder.
- id<MTLRenderCommandEncoder> renderEncoder =
- [commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor];
- renderEncoder.label = @"MyRenderEncoder";
- // Set the region of the drawable to draw into.
- [renderEncoder setViewport:(MTLViewport){0.0, 0.0, _viewportSize.x, _viewportSize.y, 0.0, 1.0 }];
- [renderEncoder setRenderPipelineState:_pipelineState];
- // Pass in the parameter data.
- [renderEncoder setVertexBytes:triangleVertices
- length:sizeof(triangleVertices)
- atIndex:AAPLVertexInputIndexVertices];
- [renderEncoder setVertexBytes:&_viewportSize
- length:sizeof(_viewportSize)
- atIndex:AAPLVertexInputIndexViewportSize];
- // Draw the triangle.
- [renderEncoder drawPrimitives:MTLPrimitiveTypeTriangle
- vertexStart:0
- vertexCount:3];
- [renderEncoder endEncoding];
- // Schedule a present once the framebuffer is complete using the current drawable.
- [commandBuffer presentDrawable:view.currentDrawable];
- }
- // Finalize rendering here & push the command buffer to the GPU.
- [commandBuffer commit];
- }
- @end
|